Salta el contingut

DOM: Model de Document

Qué és el DOM?

El DOM (Document Object Model) és una representació en forma d'arbre de tots els elements d'un document HTML. JavaScript pot accedir a qualsevol node d'aquest arbre i llegir, crear, modificar o eliminar elements dinàmicament.

document
└── html
    ├── head
    │   ├── meta
    │   └── title
    └── body
        ├── header
        │   └── h1
        ├── main
        │   ├── article
        │   │   ├── h2
        │   │   └── p
        │   └── aside
        └── footer

Selecció d'elements

// Per ID (retorna un element o null)
const titol = document.getElementById('titol-principal');

// Per classe (retorna HTMLCollection)
const targetes = document.getElementsByClassName('targeta');

// Per etiqueta (retorna HTMLCollection)
const paràgrafs = document.getElementsByTagName('p');

// querySelector — primer element que coincideix (CSS selector)
const primer = document.querySelector('.targeta');
const nav = document.querySelector('nav > a:first-child');

// querySelectorAll — tots els elements que coincideixen (NodeList)
const totes = document.querySelectorAll('.targeta');
const inputs = document.querySelectorAll('input[type="text"]');

// Iterar NodeList
totes.forEach(targeta => {
    console.log(targeta.textContent);
});

Llegir i modificar contingut

const elem = document.querySelector('#missatge');

// Llegir contingut
console.log(elem.textContent);  // text pla (sense HTML)
console.log(elem.innerHTML);    // HTML intern (permet HTML)
console.log(elem.outerHTML);    // HTML de l'element i els seus fills

// Modificar contingut
elem.textContent = "Nou text";                    // text pla (segur)
elem.innerHTML = "<strong>Text en negreta</strong>"; // HTML (cuidado XSS)

// Atributs
const img = document.querySelector('img');
console.log(img.getAttribute('alt'));      // llegir atribut
img.setAttribute('alt', 'Nova descripció'); // modificar atribut
img.removeAttribute('title');              // eliminar atribut

// Propietats directes (recomanat per a atributs comuns)
const input = document.querySelector('input');
console.log(input.value);   // valor actual
console.log(input.checked); // per a checkboxes
input.disabled = true;       // desactivar

// Dataset (atributs data-*)
// HTML: <div data-id="42" data-nom="Joan">
const div = document.querySelector('[data-id]');
console.log(div.dataset.id);    // "42"
console.log(div.dataset.nom);   // "Joan"
div.dataset.edat = 22;          // afegir data-edat="22"

Modificar estils

const elem = document.querySelector('.targeta');

// Estils en línia (inline)
elem.style.color = '#00695c';
elem.style.fontSize = '1.2rem';
elem.style.display = 'none';         // amagar
elem.style.display = 'block';        // mostrar

// Classes CSS (recomanat — separa JS del CSS)
elem.classList.add('actiu');          // afegir classe
elem.classList.remove('actiu');       // eliminar classe
elem.classList.toggle('actiu');       // alternar (add si no existeix, remove si existeix)
elem.classList.contains('actiu');     // comprova si té la classe (retorna boolean)
elem.classList.replace('vell', 'nou'); // reemplaça una classe

// Llegir estils computats (estils aplicats per CSS)
const estils = window.getComputedStyle(elem);
console.log(estils.color);
console.log(estils.fontSize);

Crear i inserir elements

// Crear un element
const nouParagraf = document.createElement('p');
nouParagraf.textContent = 'Un nou paràgraf';
nouParagraf.classList.add('intro');

// Inserir al DOM
const contenidor = document.querySelector('#contingut');
contenidor.appendChild(nouParagraf);       // al final
contenidor.prepend(nouParagraf);           // al principi
contenidor.insertBefore(nouParagraf, ref); // davant d'un element de referència

// Mètodes moderns (ES2017+)
contenidor.append(nouParagraf);     // al final (accepta strings)
contenidor.prepend(nouParagraf);    // al principi
ref.before(nouParagraf);            // davant de ref
ref.after(nouParagraf);             // darrere de ref

// Clonar elements
const copia = elem.cloneNode(true);   // true = clonar fills també
contenidor.appendChild(copia);

// Crear elements complexos amb template literal
const html = `
    <article class="targeta" data-id="${id}">
        <h3>${titol}</h3>
        <p>${descripcio}</p>
    </article>
`;
contenidor.insertAdjacentHTML('beforeend', html);

Eliminar elements

// Mètode modern (recomanat)
const elem = document.querySelector('.temp');
elem.remove();

// Mètode antic (via pare)
elem.parentNode.removeChild(elem);

// Buidar el contingut d'un element
const llista = document.querySelector('#llista');
llista.innerHTML = '';         // ràpid però destrueix els event listeners fills
while (llista.firstChild) {   // net i segur
    llista.removeChild(llista.firstChild);
}

Events

// addEventListener (recomanat)
const botó = document.querySelector('#enviar');

botó.addEventListener('click', function(event) {
    console.log('S\'ha fet clic!');
    event.preventDefault();  // evita el comportament per defecte (enviar form, seguir link)
    event.stopPropagation(); // evita que l'event es propagui cap amunt (bubbling)
});

// Arrow function
botó.addEventListener('click', (e) => {
    console.log(e.target);      // l'element que ha generat l'event
    console.log(e.currentTarget); // l'element al qual s'ha afegit el listener
});

// Events de formulari
const form = document.querySelector('#el-meu-form');
form.addEventListener('submit', (e) => {
    e.preventDefault();
    const nom = document.querySelector('#nom').value;
    if (!nom) {
        alert('El nom és obligatori!');
        return;
    }
    console.log('Formulari enviat amb nom:', nom);
});

// Event de canvi d'input
document.querySelector('#nota').addEventListener('input', (e) => {
    const valor = parseFloat(e.target.value);
    const resultat = document.querySelector('#resultat');
    resultat.textContent = valor >= 5 ? 'Aprovat' : 'Suspens';
});

// Events de teclat
document.addEventListener('keydown', (e) => {
    console.log(e.key, e.code, e.ctrlKey, e.shiftKey);
    if (e.key === 'Enter') { /* ... */ }
    if (e.ctrlKey && e.key === 's') {
        e.preventDefault();
        console.log('Ctrl+S atrapat!');
    }
});

// Event delegation (per a elements dinàmics)
document.querySelector('#llista').addEventListener('click', (e) => {
    const item = e.target.closest('li');
    if (item) {
        item.classList.toggle('completat');
    }
});

Miniactivitat AC03737

Crea una pàgina HTML amb: 1. Una llista de tasques (<ul>) buida 2. Un camp de text i un botó "Afegir" 3. Quan es clica el botó, afegeix un <li> a la llista amb el text del camp 4. Cada <li> ha de tenir un botó "Eliminar" que l'elimini 5. En fer clic a un <li> (però no al seu botó), es marca/desmarca com a completada (class completada)