57 il DOM e i suoi nodi
Analizziamo questa struttura HTML
<div id="container"> <section> <article> <header> <h1>This is a head article</h1> <p> I'm a paragraph inside a header<br> </p> </header> </article> </section> </div>
abbiamo annidati diversi elementi uno dentro all’altro, Tutti questi nodi sono legati parentalmente, il <div> è padre di <selector>, il quale è padre di <articale> e così via e ognuno di. questi elementi è figlio di un altro ( anche il div ne avrà poi altri sopra ). Vediamo come poter navigare questo albero padre/figlio con js.
Intanto metto il controllo di pagina caricata e abbrevio document memorizzandolo in una variabile
<script> document.addEventListener('DOMContentLoaded', function () { var doc = document; }); </script>
se selezioniamo con querySelector l’ID container del <div> e lo mandiamo in console, possiamo vedere quella parte di nodo selezionata ispezionando la console del browser.
var container = doc.querySelector('#container'); console.log(container);
Se invece di fare il console.log, eseguiamo il console.dir , possiamo vedere invece tutta l’alberatura dei nodi di quell’elemento div#container, andando su childNodes avremo tutti i nodi presenti, nel nostro caso in posizione 0 un nodo di tipo text, in posizione 1 un nodo section, in posizione 2 un altro di tipo text. Il primo e l’ultimo nodo di childNodes di tipo text sono dovuti agli spazi che vengono considerati testo. Se noi attaccassimo gli elementi, il nodo text verrebbe eliminato
<div id="container"><section>
Nel nodo children, in posizione 0 troviamo section, il quale a sua volta nel suo children avrà in posizione 0 article e così via.
Un altro rapporto interessante da consultare è il parentNode che mostra l’elemento genitore che nel nostro esempio è body.
Posso accedere a tutti questi nodi con js, per esempio per accedere al parentNode del div che è il body:
container.parentNode
a questo punto posso applicare degli stili sui nodi parenti
container.parentNode.style.background='#c0c0c0';
posso anche rimuovere un elemento del parentNode con il metodo removeChild()
container.parentNode.removeChild(container);
cancellando tutti gli elementi figli, nel nostro caso rimane il body vuoto.
Posso per esempio vedere quanti figli ha il <div> container
alert(container.children.length);
posso accedere hai figli dei children
alert(container.children[0].children.length);
sto accedendo ad <article> e via via posso scendere nell’alberatura del DOM.
Posso anche accedere il primo figlio di un elemento con firstChild,
console.log(container.firstChild);
nel nostro esempio il primo figlio di container è <section>, perchè la nostra ultima struttura HTML era
<div id="container"><section>
ma se noi mandiamo a capo <section> nel codice
<div id="container"> <section>
il primo figlio restituito sarà text perchè lo spazio viene considerato come elemento figlio di tipo text.
Per accedere al primo figlio che non sia testo si utilizza il nodo firstElementChild
console.log(container.firstElementChild);
in questo caso mi viene restituito il primo elemento figlio di tipo HTML. Da qui possiamo modificare tale elemento agendo sul suo stile come sappiamo.
oltre a rimuovere un figlio con removeChild(), possiamo anche aggiungere un nuovo elemento con il metodo appendChild().
var section = container.firstElementChild; container.appendChild(section)
In questo caso però non sto aggiungendo nulla perchè in container c’è memorizzato un riferimento all’elemento <section> che già esiste, quindi non ho apportato modifiche all’HTML, volendo duplicarlo posso utilizzare il metodo cloneNode()
var section = container.firstElementChild; var section2 = section.cloneNode() container.appendChild(section2)
In questo caso ho clonato il tag <section> che però non avrà tutta la struttura HTML del primo, per clonarlo insieme a tutti i suoi elementi discendenti, devo aggiungere il parametro TRUE cloneNode(true)
var section = container.firstElementChild; var section2 = section.cloneNode(true) container.appendChild(section2)
Ora avrò 2 elementi uguali <section> inseriti dentro al container