• Non ci sono risultati.

Guida introduttiva al Document Object Model (© I.D. Falconi ~ 27.02.13)

N/A
N/A
Protected

Academic year: 2021

Condividi "Guida introduttiva al Document Object Model (© I.D. Falconi ~ 27.02.13)"

Copied!
14
0
0

Testo completo

(1)

Guida introduttiva al Document Object Model

(© I.D. Falconi ~ 27.02.13)

Il DOM (Document Object Model) è un modello che descrive come i diversi oggetti di una pagina web sono collegati tra loro.

 Tecnicamente è un’ API (Application Programming Interface), ovvero,

un'interfaccia per la programmazione di applicazioni; in pratica è un insieme di funzioni, metodi e proprietà, che i programmi possono richiamare per interagire, in modo trasparente, col sistema sottostante.

Il DOM è un'API definita dal W3C, indipendente dalla piattaforma, che

descrive la struttura di un documento HTML (e XML), tramite il quale i costruttori di pagine web possono accedere a tutti gli elementi della pagina stessa.

Questo, ovviamente, non significa che i produttori di browser lo rispettino. Da qui nascono i problemi relativi alla diversa interpretazione dei browser.

Il DOM non è una parte di JavaScript. JavaScript è solo un modo per accedere al DOM, e non è l'unico.

Cerchiamo ora di capire nel dettaglio come il DOM struttura una pagina attraverso un semplice esempio:

<html>

<head>

<title>IL DOM</title>

<head>

<body>

<p id="paragrafo1">Pagina di <span id=”evidenzia”>PROVA</span> Document Object Model</p>

</body>

</html>

Il DOM rappresenta una generica pagina web (il documento) tramite un albero,

secondo le relazioni che legano e collegano i vari elementi presenti nel documento

stesso, evidenziandone le parentele e le caratteristiche: in sostanza ogni elemento

presente nella pagina, ogni tag (come <title>), ogni testo (come "Pagina di") è un nodo.

(2)

I nodi possono anche avere attributi e proprietà. Inoltre un nodo può contenere altri nodi, in questo caso si parla più propriamente di nodo elemento.

Nell’esempio, il nodo elemento html ha due figli, head e body. L’elemento body ha un figlio, p, che a sua volta ha tre figli, due nodi di testo (“Pagina di “ e “ Document Object Model”), e un nodo elemento, span. Quest’ultimo ha come figlio un nodo di testo (“PROVA”). Il nodo elemento head ha invece un solo figlio, title, avente a sua volta come figlio il nodo di testo “IL DOM”.

Tramite il DOM sarà possibile accedere e manipolare ogni nodo, aggiungerne di nuovi dinamicamente, ed eliminarne altri già presenti (queste possibilità,

ovviamente, sono offerte da tutti i browser che supportano il DOM W3C).

Prima di entrare nella descrizione dei principali metodi e proprietà del DOM, definiamo più esattamente la differenza tra elemento e nodo.

Un nodo elemento (element) è contraddistinto da un tag. Esso può quindi contenere al suo interno altri elementi ( si pensi al tag TABLE, che può contenere le righe e le celle della tabella stessa, e a loro volta questi possono contenere altri elementi).

Il nodo (node) ha un significato più ampio: oltre ad includere nella sua definizione tutti gli elementi, un nodo può essere anche un testo o un attributo. I nodi di testo, a differenza di tutti gli altri nodi, non possono avere attributi e non possono

contenere altri nodi.

(3)

TAB 1 - Principali tipi di nodo relativi ad HTML

NodeType NodeName NodeValue DESCRIZIONE

1 (elemento) nome TAG null Qualsiasi TAG

2 (attributo) nome attributo valore attributo attributo di un elemento

3 (testo) #text testo contenuto frammento di testo di un elemento

8 (commento) #comment testo di commento commento html

9 (documento) #document null oggetto radice

10 (DocumentType) DOCTYPE null specifica DTD

11 (frammento) #document-fragment null Uno o più nodi esterni al documento

TAB 2 - Proprietà degli oggetti nodo

Proprietà tipo DESCRIZIONE

nodeName stringa varia a seconda del tipo di nodo (TAB 1) nodeValue stringa varia a seconda del tipo di nodo (TAB 1) nodeType intero Costante che rappresenta ciascun tipo

parentNode oggetto Riferimento al contenitore immediatamente più esterno

childNodes collection tutti i nodi figli in ordine di codice sorgente

firstChild oggetto riferimento al primo nodo figlio

lastChild oggetto riferimento all’ultimo nodo figlio

previousSibling oggetto riferimento al precedente nodo fratello

nextSibling oggetto riferimento al successivo nodo fratello

attributes NodeMap collection di nodi attributo

(4)

L'OGGETTO DOCUMENT

document è l'oggetto che contiene tutti gli elementi della pagina.

In prima approssimazione, possiamo far corrispondere "document" al tag <html>. Più propriamente, corrisponde a tutto il codice della pagina, anche esterno al tag <html>, come ad esempio la definizione del DOCTYPE.

Fatta questa premessa, esaminiamo i principali metodi di document, che si possono dividere tra:

metodi per l’accesso agli elementi della pagina

metodi per la creazione di nuovi elementi Accesso agli elementi della pagina

A supporto di questa necessità il DOM fornisce 2 metodi:

 getElementById()

 getElementsByTagName()

getElementById() - permette di recuperare l'elemento caratterizzato univocamente dal valore del proprio attributo ID. In particolare restituisce un riferimento

all'elemento in questione.

elemento=document.getElementById(idElemento)

- idElemento è il valore (unico nella pagina) dell'attributo ID dell'elemento che si vuole recuperare.

getElementsByTagName() - permette di recuperare l'insieme degli elementi

caratterizzati dallo stesso tag, organizzati in array, nell'ordine in cui compaiono nel codice della pagina.

listaElementi=document.getElementsByTagName(nomeTAG) - nomeTAG è il nome del tag di cui si vuole recuperare la lista.

L'array può, ovviamente, essere scandito con la consueta sintassi, ovvero usando le parentesi quadre: listaElementi[indice]. Il W3C fornisce un metodo alternativo per scorrere le liste dei nodi: listaElementi.item(indice).

Questa stessa sintassi si può applicare a tutti gli array di nodi che incontreremo.

Si utilizzerà uno o l’altro dei due metodi getElementById e getElementsByTagName

a seconda che si voglia recuperare un elemento particolare oppure una famiglia di

elementi con le stesse caratteristiche.

(5)

Creazione di nuovi elementi

Passiamo ora ai metodi di document che si occupano di creare nuovi elementi della pagina:

 createElement()

 createTextNode()

createElement() - permette di creare un nuovo elemento di qualunque tipo. Ritorna un riferimento al nuovo elemento creato.

nuovoElemento = document.createElement(nomeTAG)

- nuovoElemento è la variabile che conterrà il riferimento al nuovo elemento creato

- nomeTAG è il nome del Tag di cui si vuole creare un nuovo elemento

createTextNode() - permette di creare un nuovo nodo di testo. Questi sono nodi particolari, che non possono contenere altri nodi, né possono avere attributi, sono quindi nodi terminali (foglie). In particolare, questo metodo, restituisce un

riferimento al nuovo nodo di testo creato.

nodoTesto = document.createTextNode(testo)

- nodoTesto è la variabile che conterrà il riferimento al nuovo nodo di testo - testo è la stringa di testo da inserire nel nuovo nodo

In realtà il nodo non viene visualizzato: resterà nella memoria del browser fino alla chiamata di un opportuno metodo di inserimento nella pagina.

Gestione dei nodi elemento

I metodi per element, consentono per lo più di gestire e manipolare le caratteristiche di ogni singolo elemento, come recuperare, impostare e rimuovere gli attributi

dell'elemento stesso.

getElementsByTagName() - stesso metodo visto per document, con identica sintassi e semantica. In questo caso naturalmente ritorna la lista degli elementi contenuti all'interno di un certo elemento. Possiamo pensare all’elemento come una sottoradice e riapplicare il modello visto finora.

setAttribute() - permette di creare un nuovo attributo per l'elemento specificato.

Qualora l'attributo sia già presente, il metodo ne sovrascrive il valore.

element.setAttribute(nomeAttributo,valoreAttributo)

- nomeAttributo è la stringa col nome dell'attributo che deve essere inserito o modificato

- valoreAttributo è la stringa col valore da assegnare all'attributo specificato

(6)

getAttribute() - recupera il valore di un attributo dell'elemento.

element.getAttribute(nomeAttributo)

- nomeAttributo è la stringa col nome dell'attributo di cui si vuole recuperare il valore

removeAttribute() - rimuove l'attributo passato come parametro. Qualora l'attributo abbia un valore di default, sarà questo il nuovo valore assunto dall'attributo.

element.removeAttribute(nomeAttributo)

- nomeAttributo è la stringa col nome dell'attributo che si vuole eliminare

tagName - restituisce il nome del tag dell'elemento associato.

nomeTag = element.tagName I nodi

Come già anticipato, nella definizione di node ricadono non solo gli elementi, che possono a loro volta avere elementi figli o attributi, ma anche particolari componenti di una pagina, come il testo o i commenti. Questi ultimi, non potendo avere attributi né includere altri elementi, non sarebbero raggiungibili con i metodi visti finora.

In questa sezione verranno mostrati metodi e proprietà proprie di ogni node, con i

quali è possibile scorrere la struttura della pagina per recuperare e manipolare ogni

nodo.

(7)

Proprietà

childNodes

collection contenente l’insieme dei nodi figli. Un nodo figlio (child) è un nodo contenuto in quello considerato ed è quindi nel livello gerarchico

immediatamente sottostante. Qualora il nodo non possegga figli, la proprietà restituisce un array vuoto.

arrayFigli = node.childNodes

firstChild

primo figlio del nodo al quale è applicata. Corrisponde all'elemento di indice 0 di childNodes. Se il nodo non ha sottonodi restituisce null.

nodoFiglio = node.firstChild // equivalente node.childNodes[0]

lastChild

ultimo figlio del nodo al quale è applicata. Corrisponde all' ultimo elemento di childNodes. Se il nodo non ha sottonodi restituisce null.

nodoFiglio = node.lastChild

// equivalente node.childNodes[node.childNodes.length-1]

nextSibling

nodo adiacente successivo a quello al quale è applicato. Se il nodo non ha

"fratelli minori", la proprietà restituisce null.

nodoSuccessivo = node.nextSibling

previousSibling

nodo adiacente precedente a quello al quale è applicato. Se il nodo non ha

"fratelli maggiori", la proprietà restituisce null.

nodoPrecedente = node.previousSibling

parentNode

nodo padre di quello al quale è applicato. Il nodo document è il solo all’interno della pagina a non avere padre e, per esso, la proprietà restituisce null.

nodoPadre = node.parentNode

Esistono però altri casi in cui il parentNode è nullo. Si pensi ad esempio al nodo di

testo creato in precedenza. In generale, qualsiasi nodo, finché non sarà inserito nella

struttura gerarchica della pagina, non avrà alcun nodo padre.

(8)

nodeValue

valore del nodo. Il valore di ritorno dipende dal tipo di nodo in questione. In particolare, per i tag il valore ritornato è null, mentre per i nodi di testo è il testo. In quest'ultimo caso la proprietà è read/write, cioè consente non solo di leggere il testo, ma anche di modificarlo.

valore = node.nodeValue Metodi

hasChildNodes

permette di verificare se un nodo possegga figli oppure no. Restituisce un valore booleano relativo al risultato della verifica: se il nodo contiene altri nodi restituisce true altrimenti false.

node.hasChildNodes()

I prossimi metodi sono finalizzati ad inserire o eliminare in maniera mirata gli elementi dalla struttura gerarchica della pagina.

appendChild

inserisce un nuovo nodo alla fine della lista dei figli del nodo al quale è applicato.

node.appendChild(nodo) nodo è il nodo che si vuole inserire

insertBefore

insersce un nuovo nodo nella lista dei figli del nodo al quale è applicato il metodo, appena prima di un nodo specificato.

node.insertBefore(nodoDaInserire,nodoDiRiferimento)

nodoDaInserire è il nodo che si vuole inserire nella lista dei figli di "node"

nodoDiRiferimento è il nodo della lista dei figli di "node" prima del quale si vuole inserire il nuovo nodo.

replaceChild

inserisce un nuovo nodo al posto di un altro nella struttura della pagina.

node.replaceChild(nuovoNodo,vecchioNodo)

nuovoNodo è il nuovo nodo che si vuole inserire al posto del vecchio

vecchioNodo è il nodo che si vuole rimpiazzare con il nuovo

(9)

removeChild

elimina e restituisce il nodo specificato dalla lista dei figli del nodo al quale è applicato.

node.removeChild(nodoDaRimuovere)

nodoDaRimuovere è il nuovo nodo che viene rimosso e restituito dal metodo Spesso può essere utile poter duplicare un nodo, con tutti i suoi attributi, e tutti i suoi figli senza dover ripercorrere tutti i passi che sono serviti per la sua creazione. A questo scopo si utilizza il seguente metodo:

cloneNode

duplica un nodo già esistente, offrendo la possibilità di scegliere se duplicare il singolo nodo, o anche tutti i suoi figli. Dopodiché il metodo ritorna il nodo clone.

node.cloneNode(figli)

figli (true|false) è un valore booleano che determina se clonare tutti i figli

insieme al nodo al quale è applicato il metodo (true), oppure

se clonare il solo nodo (false)

(10)

Gestione degli spazi (CR LF TAB) nel DOM

Alcuni browser considerano gli spazi come nodi di testo. Si consideri l’esempio che segue:

<h2>Lista bevande</h2>

<ul>

<li>birra</li>

<li>vino</li>

</ul>

Firefox, rappresenta il codice con la seguente struttura:

H2

o #text (Lista bevande)

 #text (line-break)

UL

o #text (line-break and tab) o LI

 #text (birra) o #text (line-break and tab) o LI

 #text (vino) o #text (line-break)

 Internet Explorer, invece, ignora gli spazi:

H2

o #text (Lista bevande)

UL o LI

 #text (birra) o LI

 #text (vino)

Possono insorgere complicazioni quando si utilizzano metodi che ricorrono alla relazione diretta fra i nodi, come firstChild o nextSibling.

Per esempio, il primo figlio di <ul>, in IE è il primo <li>, mentre in FF è un nodo di testo contenente uno spazio.

Le principali tecniche per evitare riferimenti errati sono:

fare ricorso a riferimenti basati su collection:

getElementsByTagName('li').item(0) invece che firstChild

Saltare i nodi di testo contenenti spazi var item = list.firstChild;

while(item.nodeName == '#text')

{ item = item.nextSibling; }

(11)

Gestione eventi

All’interno di un browser si verificano diversi tipi di eventi, ovvero, in generale, le azioni dell'utente sul documento. Alcuni di quelli più comuni riguardano il

comportamento del mouse, della tastiera e degli elementi dei form.

evento descrizione

click

dblclick click e doppio-click del mouse

mouseover puntatore entra nell’area di un elemento

mouseout puntatore esce dall’area di un elemento Keydown

keypress keyup

puntatore fasi successive della pressione di un tasto:

mentre si preme, premuto, rilascio

load immediatamente dopo il caricamento dell’elemento

unload immediatamente prima della fase di scaricamento dell’elemento

resize nella fase di ridimensionamento

scroll nella fase scorrimento del contenuto di un elemento

alcuni eventi sono trattati in maniera diversa dai vari browser.

L’esecuzione di una determinata serie di azioni al verificarsi di un evento si ottiene progettando delle apposite funzioni dette tecnicamente event handlers e

associandole all’evento.

Tale operazione può essere compiuta in vari modi:

modalità tradizionale

ricavata l’id dell’elemento e definita la funzione, si associa la funzione all’evento (registrazione dell’evento) tramite dot notation

elemento.onclick=event_handler

esempio:

<input type=”button” id=”test” name=”test” value=”TEST”>

<script type=”text/javascript”>

function avvisa() {alert(‘test OK’);} //event handler document.getElementById(‘test’).onclick=avvisa;

</script>

Occorre notare che l’evento click viene identificato tramite il parametro onclick .

Questo semplice modo di gestire gli eventi è sufficiente per la maggior parte delle

(12)

esigenze, ma esiste un metodo più complesso in grado di associare ad un evento più di una funzione.

Modalità DOM W3C

ricavata l’id dell’elemento e progettata la funzione, si associa la funzione all’evento (registrazione) tramite il metodo addEventListener dell’elemento.

elemento. addEventListener(‘evento’,event_handler,cattura)

esempio:

<input type=”button” id=”test” name=”test” value=”TEST”>

<script type=”text/javascript”>

function avvisa() {alert(‘test OK’);} //event handler

document.getElementById(‘test’). addEventListener('click', avvisa, false);

</script>

Il terzo parametro, booleano, specifica se l’evento deve essere catturato o se deve essere passato agli elementi contenitori.

NOTA: tale metodo non è supportato dalle versioni di IE precedenti alla 9, per le quali Microsoft ha implementato il metodo attachEvent.

elemento.attachEvent('onevento', event_handler);

I due metodi hanno una sintassi diversa, ad esempio quello del W3C si riferisce all’evento con il suo nome e non con la sua proprietà (quindi senza il prefisso on), e prevede il terzo parametro.

 Per le versionisuccessive alla 9, il documento deve comunque riportare la specifica

<!DOCTYPE html>

Rimozione event handler

Oltre ad aggiungere event handler ad un evento, possiamo toglierle:

elemento.removeEventListener(‘evento’,event_handler,cattura)

NOTA: tale metodo non è supportato dalle versioni di IE precedenti alla 9, per le quali Microsoft ha implementato il metodo detachEvent.

elemento.detachEvent('onevento', event_handler);

Un esempio di applicazione potrebbe essere l’attivazione “one-shot” di un event

handler.

(13)

Esempi applicativi DOM

Aggiunta dinamica di un nuovo paragrafo in fondo alla pagina //crea in memoria un nuovo elemento <p>

var nuovoPar=document.createElement("p");

// assegnazione id

nuovoPar.setAttribute("id","newP"); // oppure: nuovoPar.id="newP";

// per aggiungere il testo, bisogna creare un nuovo nodo di testo e // appenderlo, come figlio, al paragrafo

var nuovoTxt=document.createTextNode(“paragrafo creato dinamicamente”);

nuovoPar.appendChild(nuovoTxt);

// Il nuovo elemento paragrafo è pronto per essere inserito nel documento.

// scegliamo di aggiungerlo in fondo alla pagina, come ultimo figlio del <body>

var pagina=document.getElementsByTagName("body");

pagina[0].appendChild(nuovoPar); // oppure: document.body.appendChild(nuovoPar);

Aggiunta dinamica di una nuova tabella (2 righe, 4 colonne) // riferimento a body

var body = document.getElementsByTagName("body")[0];

// crea un elemento <table> e un elemento <tbody>

var tbl = document.createElement("table");

var tblBody = document.createElement("tbody");

// crea le righe

for (var r = 0; r < 2; r++) { // crea l’elemento <tr>

var row = document.createElement("tr");

for (var c = 0; c < 4; c++) {

// crea un elemento <td> e un nodo di testo, appende il nodo di testo // alla cella e appende la cella in fondo alla riga

var cell = document.createElement("td");

var cellText = document.createTextNode("cella riga "+r+", colonna "+c);

cell.appendChild(cellText);

row.appendChild(cell);

}

// appende la riga in fondo a tbody tblBody.appendChild(row);

}

// appende tbody alla tabella tbl.appendChild(tblBody);

// appende la tabella al body body.appendChild(tbl);

// imposta id a “tab1”

tbl.setAttribute("id", "tab1");

(14)

Aggiunta dinamica di una nuova riga in fondo ad una tabella esistente var tab= document.getElementById("tab1");

var tbody=tab.firstChild;

var lastRow=tbody.lastChild;

var nuovaRiga=lastRow.cloneNode(true);

for (var i=0;i<nuovaRiga.childNodes.length;i++) nuovaRiga.childNodes[i].firstChild.nodeValue=’X’;

tbody.appendChild(nuovaRiga);

Riferimenti

Documenti correlati

Direzione Provinciale di Salerno – Ufficio Provinciale - Territorio Via dei Principati, 75 – 84122 Salerno tel. In virtù di tale accordo, quest’Ufficio redige il presente

a presentare un’offerta per la redazione del certificato di Attestazione di Prestazione Energetica, redatto secondo le modalità indicate nei decreti del Ministero dello

Nella definizione della rete test sono stati accettati alcuni compromessi rispetto alle linee guida sopra menzionate: in particolare sono state incluse stazioni i

Con riferimento al quesito in oggetto si rappresenta che il requisito al capitolo 6.3 comma b - fatturato specifico minimo annuo – può essere soddisfatto anche in presenza

ST 11690 2018 INIT IT 24/08/2018 Proposta di DECISIONE DEL CONSIGLIO relativa alla posizione che dovrà essere assunta a nome dell'Unione europea nel comitato APE

La ricezione della Circolare da parte delle componenti in indirizzo è condizione necessaria e sufficiente a esonerare la scuola da qualsiasi responsabilità

1. esame dei titoli posseduti, delle esperienze e delle abilità professionali maturate, in relazione al profilo considerato, sulla base dei criteri di valutazione di cui

Se si desidera connettersi a più server, senza dover ricordare o immettere la password per ogni sistema, è necessario anche utilizzare Autenticazione della passphrase tramite Pageant