Utilizzo degli eventi in JavaScript

Se ritieni utile questo articolo, considera la possibilità di effettuare una donazione (il cui importo è a tua completa discrezione) tramite PayPal. Grazie.

Come tutti i principali modelli ad oggetti, anche l'Object Model di Dynamic HTML (DHTML) è essenzialmente caratterizzato da:

  • Costanti, come tabella colori, HTTP Response Headers, tabella codici di una specifica lingua, ecc.

  • Collezioni, come ad esempio childNodes (collection di elementi HTML e TextNode che discendono da uno specifico oggetto), attributes (l'elenco degli attributi di un oggetto), images (la collezioni di immagini contenute in un document), ecc.

  • Oggetti, ovvero i singoli "mattoncini" che costituiscono il DOM di un documento, tipicamente inseriti tramite markup come body, img, form, ecc.

  • Metodi, come alert per la visualizzazione di una finestra di dialogo applicativa, appendChild che consente di estendere la collection dei childNodes di un oggetto, createElement per istanziare un nuovo elemento per uno specifico tag, ecc.

  • Proprietà, che consentono di specificare - tipicamente come attributi nel markup - caratteristiche specifiche di un oggetto come background, border, font, title, width, height, ecc.

  • Eventi, ovvero la modalità con cui un oggetto notifica all'esterno che "è successo qualcosa", come un cambiamento dello stato (come ad esempio load, error, ecc.) o l'azione di un utente o di un altro elemento del DOM (come ad esempio click, , focus, blur, ecc.)

In questo articolo ci soffermeremo in particolare sull'utilizzo degli eventi, analizzando i diversi metodi disponibili per intercettare gli eventi ed associarvi il codice JavaScript necessario al funzionamento di un'applicazione web-based.

Event handling

Esistono diverse modalità per intercettare un evento (event handling). Di seguito vengono proposte le principali soluzioni disponibili:

Gestione degli eventi tramite markup

L'handling di un evento tramite markup è probabilmente la modalità più diffusa:

<input type="button" value="Hello" onclick="alert('Hello World!');" />

Che produce il seguente elemento:

Gestione degli eventi tramite codice JavaScript

Tramite JavaScript è possibile associare ad un evento di uno specifico oggetto l'esecuzione di un particolare codice:

<input type="button" value="Hello" id="btnHello1" />

<script type="text/javascript">

document.getElementById("btnHello1").onclick = function()
{
    alert("Hello World!");
}

</script>

Che produce:

In modo analogo possiamo associare ad un evento l'esecuzione di specifica funzione:

<input type="button" value="Hello" id="btnHello2" />

<script type="text/javascript">

document.getElementById("btnHello2").onclick = HelloWorld;

function HelloWorld()
{
    alert("Hello World!");
}

</script>

Si noti l'assenza delle parentesi tonde nell'associazione della funzione all'evento (function pointer)

Che produce:

Gestione degli eventi tramite Object Model: addEventListener / attachEvent

Quest'ultima è decisamente la modalità migliore per registrare un evento in quanto:

  • può essere utilizzato con qualsiasi elemento del DOM e non solo con gli elementi HTML

  • fornisce una gestione migliore del codice eseguito in corrispondenza dello scatenarsi di un evento (capturing vs. bubbling)

  • consente di gestire più handler per lo stesso evento; ciò è particolarmente utile nello sviluppo di librerie generiche (o di Web User Control), dove una gestione degli eventi tramite markup o puntatori a funzione potrebbe creare problemi di sovrascrittura di handler impostati direttamente dalla pagina o da altri controlli/librerie (immaginiamo ad esempio il tipico caso di inizializzazione di un componente che richiede il load completo del DOM: associarlo sovrascrivendo l'evento onload del body potrebbe compromettere l'esecuzione del resto della pagina!)

Lo standard W3C prevede l'uso di:

target.addEventListener(type, listener, useCapture);

Dove:

  • target: l'oggetto di cui si desidera intercettare l'evento

  • type: la stringa che rappresenta il tipo di evento da intercettare

  • listener: l'oggetto che riceve la notifica quando l'evento viene scatenato; deve implementare l'interfaccia EventListener oppure, più semplicemente, essere un punatore ad una funzione JavaScript.

  • useCapture: se "true" tutti gli eventi del tipo specificato saranno gestiti dal listener indicato prima di venir iniviati agli elementi nella gerarchia del DOM; per maggiori dettagli si rimanda a DOM Level 3 Events

In Microsoft Internet Explorer anziché addEventListener si utilizza:

bSuccess = object.attachEvent(sEvent, fpNotify);

Dove:

  • object: l'oggetto di cui si desidera intercettare l'evento

  • sEvent: la stringa che rappresenta il tipo di evento da intercettare

  • fpNotify: il punatore alla funzione JavaScript che si desidera invoca allo scatenarsi dell'evento.

  • bSuccess: (ritorno) un valore booleano che indica se l'evento è stato correttamente associato alla funzione specificata

È dunque importante notare come l'Object Model di DHTML dipenda fortemente dalla piattaforma utilizzata (tipicamente dal browser in cui viene caricato il documento); per la realizzazione di applicazioni indipendenti dalla piattaforma è dunque necessario utilizzare solo gli elementi (oggetti, collezioni, metodi, proprietà ed eventi) pienamente supportati da tutti i browser di riferimento.

Per implementare correttamente la gestione degli eventi utilizzando il DOM è dunque necessario affidarsi ad un controllo basato sulle browser-capabilities:

<input type="button" value="Hello" id="btnHello3" />

<script type="text/javascript">

var btn = document.getElementById("btnHello3");

if (btn.addEventListener)
    btn.addEventListener("click", HelloWorld, false);
else if (btn.attachEvent)
    btn.attachEvent("onclick", HelloWorld);

function HelloWorld()
{
    alert("Hello World!");
}

</script>

Che produce:

In modo analogo è possibile rimuovere un event handler utilizzando removeEventListener (W3C Standard) oppure detachEvent (Internet Explorer).

Come già accennato in precedenza, uno dei vantaggi maggiori derivanti dall'uso di addEventListener (o attachEvent nel caso di IE) è che permette di associare handler ad eventi già intercettati senza comprometterne il funzionamento:

<input type="button" value="Hello" id="btnHello4" onclick="alert('onclick da markup');" />

<script type="text/javascript">

var btn = document.getElementById("btnHello4");

if (btn.addEventListener)
    btn.addEventListener("click", function(){alert("onclick da addEventListener");}, false);
else if (btn.attachEvent)
    btn.attachEvent("onclick", function(){alert("onclick da attachEvent");});

</script>

In questo modo il pulsante:

esegue correttamente sia il codice associato all'evento "onclick" da markup, sia quello associato tramite DOM