back to top

L’oggetto document di Javascript e l’interazione col DOM

Il Document Object Model (o, più brevemente, DOM) è uno standard ufficiale del W3C attraverso il quale la struttura di un documento (come ad esempio una pagina HTML) è rappresentata sotto forma di un modello orientato agli oggetti.

In pratica ogni elemento della struttura del documento è rappresentato sotto forma di nodo di un elemento padre creando una sorta di "albero" in cui si creano una serie di ramificazioni. facciamo un esempio partendo da una semplicissima struttura HTML:

<html>
  <head>
    <title>titolo del documento</title>
  </head>
  <body>
    <h1>titolo H1</h1>
    <p>testo testo testo</p>
  </body>
</html>

La rappresentazione del DOM di questa pagina sarebbe:

  • documento
    • head
      • title
        • titolo del documento (text node)
    • body
      • h1
        • titolo H1 (text node)
      • p
        • testo testo testo (text node)

Il DOM e javascript

Attraverso Javascript è possibile manipolare il DOM della pagina; ogni elemento della pagina viene rappresentato come un oggetto il quale può essere manipolato attraverso metodi e proprietà.

L’oggetto di base per la manipolazione del DOM è document il quale rappresenta la radice del documento nel suo complesso (cioè la pagina web). L’oggetto document è il genitore di tutti gli altri elementi della pagina web.

Selezionare gli elementi della pagina

Attraverso l’oggetto document è possibile accedere a tutti gli elementi della pagina. Per identificare il o gli elementi sui quali agire è necessario fare ricorso ad uno di questi metodi:

  • getElementByID() – identifica un solo elemento della pagina attraverso l’attributo ID (univoco);
  • getElementByTagName() – identifica un set di elementi della pagina attraverso l’indicazione dello specifico tag (ad esempio tutti i paragrafi o tutti i link);
  • getElementByClassName() – identifica un set di elementi della pagina attraverso l’indicazione di una specifica classe;

Vediamo qualche esempio:

// identifico uno specifico elemento della pagina
var testo = document.getElementById('articolo');

// all'interno di questo elemento posso selezionare, ad esempio, tutti i link
var links = testo.getElementByTagName('a');

Come potete vedere ho applicato il metodo getElementById all’oggetto document creando, a mia volta, un nuovo oggetto (che ho chiamato "testo"). In seguito ho applicato il metodo getElementByTagName al nuovo oggetto "testo" per identificare tutti i link presenti in quello specifico elemento della pagina.

Modificare l’HTML del documento

Attraverso la proprietà innerHTML posso "scrivere" codice HTML all’interno di un qualsiasi nodo della pagina. Poco sopra, infatti, abbiamo visto come effettuare la selezione degli elementi e come, una volta selezionati, anche questi si trasformino in oggetti.

A questo punto non resta che applicare la proprietà innerHTML all’oggetto corrispondente al nodo il cui contenuto vogliamo modificare.

var testo = document.getElementById('articolo');
testo.innerHTML = 'Scrivo codice <b>HTML</b>...';

Così facendo l’eventuale contenuto dell’elemento selezionato verrà sostituito da quello specificato col metodo innerHTML.

Modificare il valore di un attributo

Nella lezione dedicata agli oggetti di javascript abbiamo accennato al fatto che ogni attributo si "trasforma" in una proprietà dello specifico oggetto element a cui ri riferisce. Ne consegue che abbiamo la possibilità di manipolare gli attributi a nostro piacimento.

Si supponga, ad esempio, di voler cambiare l’immagine sorgente (attributo src) di un tag <img>:

document.getElementById('miafoto').src = 'nuovafoto.jpg';

Modificare lo stile CSS di un elemento

L’attributo style di un oggetto element può diventare a sua volta un oggetto ed essere manipolato attraverso una serie di proprietà corrispondenti alle proprietà dei fogli di stile. vediamo un esempio:

// imposto il colore rosso per il testo
document.getElementById('articolo').style.color = '#FF0000';

Da notare che in Javascript i nomi di alcune proprietà CSS variano leggermente quando vengono utilizzati sotto forma di proprietà. La proprietà background-image, ad esempio, corrisponde alla proprietà Javascript backgroundImage. In linea di massima possiamo dire che il nome delle proprietà CSS composto da più parole separate dal trattino (come ad esempio "border-color") viene trasformato in una stringa unica in cui la parola che segue al trattino (che viene omesso) ha la prima lettera maiuscola (ad esempio "borderColor").

Gestire gli eventi utilizzando il DOM

Attraverso l’utilizzo del DOM è anche possibile assegnare un evento ad un dato elemento della pagina. Ad esempio:

document.getElementById('miafoto').onclick = function(){ ... };

In questo caso l’evento Javascript si trasforma in una proprietà dell’oggetto element e, come tale, può essere settato a piacimento.

Sempre attraverso il DOM è possibile creare degli event listener cioè dei "rilevatori di eventi" associati a specifici elementi della pagina. Facciamo un esempio:

// assegno una funzione esterna
foto.addEventListener('click', miafunzione);

// definisco internamente al metodo le istruzioni da eseguire
document.getElementById('miafoto').addEventListener('click', function() { alert('...'); });

E’ possibile associare una molteplicita di event handler (anche dello stesso tipo) a ciascun oggetto. Ad esempio, quindi, possiamo associare diverse funzioni al medesimo evento "click" sul medesimo oggetto con ID "miafoto".

var foto = document.getElementById('miafoto');
foto.addEventListener('click', miafunzione);
foto.addEventListener('click', suafunzione);
foto.addEventListener('click', tuafunzione);

Volendo è anche possibile compiere l’operazione inversa, cioè disassociare una funzione da un dato evento su un oggetto. Per farlo si utilizza il metodo removeEventListener in questo modo:

foto.removeEventListener('click', tuafunzione);

Creare un nuovo elemento della pagina

Per aggiungere un nuovo elemento nell’albero della pagina sarà necessario prima crearlo e poi appenderlo al nodo nel quale o si desidera inserire. Per creare un nuovo elemento nel DOM si utilizza il metodo createElement() specificando, come attributo, che tipo di elemento si desidera creare. Una volta creato l’elemento sarà, ovviamente, vuoto.

Nell’esempio che segue, dopo aver creato un nuovo paragrafo, andremo a riempirlo creando un text-node al suo interno.

// creo il nuovo elemento (un paragrafo)
var nuovo = document.createElement('p');

// creo un nuovo nodo di testo per "riempire" il nuovo elemento
var testo = nuovo.createTextNode('Nuovo testo da inserire');

// appendo il nodo di testo al nuovo elemento
nuovo.appendChild(testo);

// seleziono il nodo nel quale voglio aggiungere il nuovo elemento
var articolo = document.getElementById('articolo');

// ora aggiungo il nuovo elemento al nodo selezionato all'inizio
articolo.appendChild(nuovo);

Utilizzando il metodo appendChild(), il nuovo elemento viene posizionato in fondo all’elemento selezionato. Se non vogliamo che ciò accada ma vogliamo inserire il nuovo elemento in un punto ben preciso abbiamo a disposizione il metodo insertBefore(). Questo metodo richiede due parametri: il primo corrisponde al nuovo elemento da inserire, il secondo corrisponde all’oggetto che identifica il l’elemento prima del quale effettuare l’inserzione.

Si supponga, ad esempio, che il nostro articolo sia così strutturato:

<div id="articolo">
  <p id="frase1">...</p>
  <p id="frase2">...</p>
  <p id="frase3">...</p>
</div>

e si supponga di voler inserire il nuovo paragrafo subito dopo il primo. Questo il codice del nostro esempio:

// creo il nuovo elemento (un paragrafo)
var nuovo = document.createElement('p');

// creo un nuovo nodo di testo per "riempire" il nuovo elemento
var testo = nuovo.createTextNode('Nuovo testo da inserire');

// appendo il nodo di testo al nuovo elemento
nuovo.appendChild(testo);

// seleziono il nodo nel quale voglio aggiungere il nuovo elemento
var articolo = document.getElementById('articolo');

// seleziono il sotto-elemento prima del quale voglio inserire quello nuovo 
var frase = articolo.getElementById('frase1');

// ora aggiungo il nuovo elemento al nodo selezionato subito prima dell'elemento "frase"
articolo.insertBefore(nuovo,frase);

Se al posto di insertBefore() avessimo utilizzato replaceChild() avremmo sostituito la frase con ID "frase1" con quella generata dinamicamente.

Eliminare un elemento dal DOM

Per eliminare un elemento dall’albero del DOM si utilizza il metodo removeChild(). Come lascia intuire il nome, viene utilizzato per rimuovere un elemento figlio dell’oggetto selezionato.

Volendo tornare all’esempio visto sopra e supponendo di voler eliminare la frase con id "frase1" avremmo utilizzato il seguente codice:

// seleziono il nodo nel quale voglio lavorare
var articolo = document.getElementById('articolo');

// seleziono il sotto-elemento che desidero cancellare
var frase = articolo.getElementById('frase1');

// ora procedo all'eliminazione
articolo.removeChild(frase);

Una particolarità del DOM è che per rimuovere un elemento dalla pagina è sempre necessario conoscere l’elemento genitore. Un "trucchetto" per ovviare a questa procedura è offerto da questo codice:

var elimina = document.getElementById('frase1');
elimina.parentNode.removeChild(elimina);

Muoversi tra gli elementi del DOM

Come abbiamo detto il DOM è come un albero rappresentato da diversi rami, ogni punto di origine di uno o più rami è detto nodo. Javascript disponde di diverse proprietà per muoversi all’interno dei vari nodi di un documento HTML. Questa sono:

  • parentNode
  • childNodes[indice]
  • firstChild
  • lastChild
  • nextSibling
  • previousSibling

E’ importante sottolineare che nel modello del DOM ogni blocco di testo corrisponde a un noto (Text Node) quindi per accedere, ad esempio, al testo contenuto all’interno di una tag <p> sarà necessario far riferimento ad un ulteriore nodo (il nodo di testo, appunto) e poi applicare la proprietà nodeValue:

var testo = document.getElementById('frase1').firstChild.nodeValue;

In realtà, per raggiungere il nostro scopo, avremmo potuto scrivere più semplicemente:

var testo = document.getElementById('frase1').innerHTML;

Tuttavia era necessario sottolineare come, nel DOM, i blocchi di testo siano qualificati come nodi a se stanti.

parentNode

la proprietà parentNode consente di accedere al nodo genitore dell’oggetto element corrente.

Abbiamo già visto questa proprietà all’opera poco sopra, nell’ultimo esempio relativo all’eliminazione di un elemento dal DOM (cui vi invito a fare riferimento).

firstChild e lastChild

Queste tre proprietà consentono di accedere, rispettivamente, al primo nodo e all’ultimo elemento figlio dell’oggetto element corrente.

childNodes

la proprietà childNodes consente di accedere ad un determinato nodo figlio specificandone l’indice numerico (ricordiamoci che la numerazione degli indici parte da 0 e NON da 1!).

In sostanza possiamo dire che childNodes[0] è l’equivalente di firstChild.

nextSibling e previousSibling

Queste due proprietà consentono di muoversi tra i nodi "fratelli" e più precisamente consento di accedere a quello precedente e quello successivo.

La radice del documento

Per accedere alla radice della nostra pagina HTML possiamo utilizzare la proprietà documentElement dell’oggetto document.

Se desideriamo selezionare solo il corpo del documento, invece, possiamo utilizzare semplicemente la proprietà body.

var radice = document.documentElement;
var corpo = document.body;
Pubblicitร 
Massimiliano Bossi
Massimiliano Bossi
Stregato dalla rete sin dai tempi delle BBS e dei modem a 2.400 baud, ho avuto la fortuna di poter trasformare la mia passione in un lavoro (nonostante una Laurea in Giurisprudenza). Adoro scrivere codice e mi occupo quotidianamente di comunicazione, design e nuovi media digitali. Orgogliosamente "nerd" sono il fondatore di MRW.it (per il quale ho scritto centinaia di articoli) e di una nota Web-Agency (dove seguo in prima persona progetti digitali per numerosi clienti sia in Italia che all'estero).