Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

L'oggetto Event: metodi crossbrowser ed esempi

Tutto sull'oggetto Event: i principali metodi e le proprietà del mouse e l'uso di codice crossbrowser
Tutto sull'oggetto Event: i principali metodi e le proprietà del mouse e l'uso di codice crossbrowser
Link copiato negli appunti

L'Oggetto Event è un'interfaccia che consente di accedere ad informazioni riguardanti gli eventi attivati nel corso della navigazione. Con l'oggetto Event possiamo gestire in tutta comodità alcuni eventi associati alle azioni dell'utente, tipo il click del mouse.

Poiché, come abbiamo visto nell'

[!] Ci sono problemi con l'autore. Controllare il mapping sull'Author Manager

, esistono delle differenze tra il modello proposto dal W3C (e seguito da Netscape e Mozilla), e quello adottato da Explorer. Le diversità si rifletteranno anche sulle informazioni che l'oggetto Event può fornire nei diversi browser.

In questa pagina dapprima mostreremo le proprietà e i metodi più importanti dell'oggetto event definiti dal W3C, poi mostreremo quelli che definisce Explorer e infine cercheremo, quando sia possibile, di fornire una versione crossbrowser della proprietà o dei metodi trattati.

Per quanto riguarda Opera, occorre fare un discorso a parte. Infatti "il browser più veloce nel mondo" rimane molto vago sulla gestione degli eventi, tanto che nelle specifiche si limita a dire: "la variabile event passata agli event handlers non rispetta gli standard javascript". Il modello utilizzato da Opera, sembra infatti essere un'ibrido tra quello standard e quello di Explorer: pur definendo una sola fase di bubbling del flusso d'evento, supporta molte delle proprietà definite sia dal W3C sia da Explorer. Questo mix rende la gestione degli eventi tutt'altro che limpida ed offre il fianco anche alla presenza di alcuni bug.

Cercherò di dare qualche delucidazione in più, mostrando quali proprietà supporta e mostrando qualche bug in cui mi sono imbattuto. Fortunatamente nella versione 6 del browser le cose sembrano andare molto meglio e nella futura versione di Opera 7

Cominciamo col considerare le specifiche del W3C.

L'Oggetto Event del W3C

Ogni volta che un event handler viene "acceso", il W3C specifica che il primo parametro passato alla funzione da eseguire sia un'oggetto che implementi l'interfaccia Event. Quindi ad esempio, per definere una generica funzione (listener) che debba manipolare l'oggetto event, scriveremo:

e
  // e
  // e può essere usato per gestire l'evento stesso
}

Nota event

<DIV ID="livello" onclick="gestoreEvento(event

o

document.getElementById("livello").onclick = gestoreEvento

L'Oggetto Event

  • bubbles

    (true|false) Valore booleanno che indica se l'evento può avere una fase di bubbling (true) oppure no (false). Non tutti gli eventi infatti possono risalire la struttura gerarchica del documento, si pensi, ad esempio, all'evento onload

    event.bubbles

  • cancelable

    (true|false) Valore booleano che indica se l'azione di default di un evento possa essere cancellata. Per azioni di default si intendono tutte quelle azioni che vengono eseguite dal flusso d'evento senza l'uso di un event handler, come ad esempio può essere il caricamento di un URL in seguito alla pressione su un tag A con il proprio attributo href

    event.cancelable

  • currentTarget

    La proprietà restituisce un riferimento al nodo per il quale il flusso d'evento sta passando. Questa proprietà, quindi, nel corso dell'Event Flow

    event.currentTarget

  • eventPhase

    La proprietà restituisce un valore intero che descrive in quale fase si trovi attualmente il flusso d'evento; i valori possono essere: 1 (fase di CAPTURING), 2 (raggiunto il TARGET), 3 (fase di BUBBLING). La sintassi è:

    event.eventPhase

  • target

    Restituisce un riferimento al nodo dal quale è originato il flusso d'evento. Nel dettaglio, si riferisce, al nodo obiettivo del flusso d'evento nella sua fase di capturing, che coincide con il punto di partenza della successiva fase di bubbling. La sintassi è:

    event.target

  • type

    Restituisce una stringa che descrive il tipo di evento, come ad esempio: "click","mouseover", ecc. La sintassi è:

    event.type

Passiamo a considerare i principali metodi:

  • preventDefault

    Questo metodo consente di cancellare l'azione di default per quegli eventi per cui la proprietà cancelable

    event.preventDefault()

  • stopPropagation

    Questo metodo permette di interrompere la propagazione dell'evento, arrestando l'Event Flow

    event.stopPropagation()

consideriamo poi le principali proprietà relative agli eventi di mouse:

  • button

    Questa proprietà restituisce un valore intero che indica quale pulsante del mouse ha cambiato il proprio stato, ovvero sia stato premuto o rilasciato.
    I valori restituiti possono essere:

    0
    1
    2

    Nel caso in cui il mouse possega solo due pulsanti, la proprietà può restituire o 0 (pulsante sinistro) o 2 (pulsante destro). La sua sintassi è:

    event.button

  • relatedTarget

    Questa è una proprietà molto importante che permette di gestire con facilità gli eventi di onmouseover onmouseout onmouseover

    Nel caso dell'onmouseout relatedTarget

    event.relatedTarget

  • screenX

    La proprietà restituisce la coordinata X del puntatore del mouse relativa allo schermo. L'origine dell'asse è nell'angolo in alto a sinistra dello schermo. La sintassi è:

    event.screenX

  • screenY

    La proprietà restituisce la coordinata Y del puntatore del mouse relativa allo schermo. La sintassi è:

    event.screenY

  • clientX *

    La proprietà restituisce la coordinata X del puntatore del mouse relativa all'area client client

    event.clientX

    *

  • clientY *

    La proprietà restituisce la coordinata Y del puntatore del mouse relativa all'area client

    event.clientY

    *

  • L'Oggetto Event di Explorer

    Explorer possiede un diverso modello d'evento rispetto a quello definito dal W3C. Questo si ripercuote anche sull'oggetto event di Explorer e sulle sue proprietà. Fortunatamente, gran parte delle informazioni definite nell'oggetto event del W3C, sono definite anche nel browser della Microsoft, anche se sono spesso recuperabili attraverso proprietà con nomi differenti rispetto a quelle appena viste. La prima differenza consiste nel fatto che, a differenza dell'oggetto standard, in Explorer l'oggetto event non è passato come parametro negli event handler, ma è un'oggetto contenuto in window accessibile globalmente attraverso la sintassi:

    o semplicemente

    event

    Vediamo le proprietà dell'oggetto event

    • cancelBubble

      (true|false) Valore booleanno che se settato a true

      event.cancelBubble

    • returnValue

      (true|false) Valore booleano che se settato a true permette di cancellare l'azione di default dell'evento. La sintassi è:

    • srcElement

      La proprietà restituisce un riferimento al nodo (source Element

      event.srcElement

    • type

      Restituisce una stringa che descrive il tipo di evento, come ad esempio: "click","mouseover", ecc. La sua sintassi è:

      event.type

    le principali proprietà relative agli eventi di mouse sono:

    • button

      Questa proprietà, come l'omonima definita dal W3C, restituisce un valore intero che indica quale pulsante del mouse è stato premuto. Le differenze rispetto agli standard risiedono sui possibili valori restituiti:

      0
      1
      2
      3
      4
      5
      6
      7

      La sua sintassi è:

      event.button

    • fromElement

      Questa è una proprietà legata agli eventi di onmouseover onmouseout
      La sintassi è:

      event.fromElement

    • toElement

      Anche questa è una proprietà legata agli eventi di onmouseover onmouseout
      La sintassi è:

      event.toElement

    • screenX

      La proprietà restituisce la coordinata X del puntatore del mouse relativa allo schermo. La sintassi è:

      event.screenX

    • screenY

      La proprietà restituisce la coordinata Y del puntatore del mouse relativa allo schermo. La sintassi è:

      event.screenY

    • clientX

      La proprietà restituisce la coordinata X del puntatore del mouse relativa all'area client

      event.clientX

    • clientY

      La proprietà restituisce la coordinata Y del puntatore del mouse relativa all'area client

      event.clientY

    • offsetX

      La proprietà restituisce la coordinata X del puntatore del mouse relativa all'elemento che ha acceso l'evento. La sintassi è:

      event.offsetX

    • offsetY

      La proprietà restituisce la coordinata Y del puntatore del mouse relativa all'elemento che ha acceso l'evento. La sintassi è:

      event.offsetY

    Queste due ultime proprietà, messe a disposizione da Explorer, non hanno un corrispettivo standard. Netscape/Mozilla

    • layerX

      La proprietà restituisce la coordinata X del puntatore del mouse relativa all'elemento che ha acceso l'evento. La sintassi è:

      event.layerX

    • layerY

      La proprietà restituisce la coordinata Y del puntatore del mouse relativa all'elemento che ha acceso l'evento. La sintassi è:

      event.layerY

    • Una versione Crossbrowser dell'Oggetto Event

      Abbiamo avuto modo di evidenziare le differenze fra il metodo di gestione del W3C e il metodo di Internet Explorer, non resta che mettere insieme le informazioni appena acquisite per creare del codice crossbrowser, che ci permetta di sfruttare il flusso degli eventi e le proprietà dell'oggetto event.

      Accedere all'Oggetto Event

      Verifichiamo se il primo parametro di una funzione listener sia un'istanza dell'oggetto event (come descritto dal W3C) oppure no; in quest'ultimo caso significa che il browser è Explorer, perciò recuperemo l'oggetto event accessibile globalmente. Il codice sarà quindi:


        if(!e) e = window.event;
        // a questo punto e contiene un riferimento crossbrower
        // all'oggetto event

      Accedere alle principali proprietà dell'Oggetto Event

      Non tutte le proprietà possono essere tradotte (come bubbles o eventPhase), a causa proprio del differente modello d'evento, e per alcune non occorre creare codici crossbrower (come per type). Per tutte le altre possiamo procedere facendo una rilevazione d'oggetto per verificare se le proprietà o i metodi standard siano supportati o meno. Nel codice sottostante riprenderò il riferimento crossbrowser e dell'oggetto event appena recuperato:


      // sorgente contiene un riferimento crossbrowser
      // all'oggetto dal quale il flusso di bubbling si è generato

      if(e.stopPropagation) e.stopPropagation()
      else e.cancelBubble=true
      // con queste due righe viene interrotto il flusso d'evento

      if(e.preventDefault) e.preventDefault()
      else e.returnValue=true
      // con queste due righe si cancella l'azione di default dell'evento

      Per quanto riguarda le proprietà legate agli eventi di mouse, bisogna ricordare che la proprietà standard relatedTarget onmouseover onmouseout onmouseover onmouseout

      daElemento = (mw3) ? ((e.type=="mouseover") ? e.relatedTarget :e.target) : e.fromElement;
      aElemento = (mw3) ? ((e.type=="mouseout") ? e.relatedTarget :e.target) : e.toElement;

      Seguendo la stessa filosofia il codice crossbrowser riguardante la posizione del mouse, relativa all'elemento che ha attivato l'evento, sarà:

      ricordando però, che in quest'ultimo caso, nessuna delle proprietà è definita dagli standard. Passiamo ora a considerare qualche esempio.

      Esempi

      In quest'ultima sezione persenteremo dapprima un piccolo esempio didattico, che ha lo scopo di far prendere confidenza con l'oggetto event, con le sue proprietà e il suo modello, dopodichè mostreremo una applicazione che si basa proprio sul concetto del flusso d'evento e sulle capacità che il JavaScript offre per gestirlo e manipolarlo.

      Un Esempio didattico

      Per meglio comprendere il ruolo delle proprietà riguardanti gli eventi onmouseover, onmouseout e onmousemove e l'event bubbling, vi propongo questo esempio nel quale visualizzo in una textarea gli elementi a cui si riferiscono di volta in volta le varie proprietà riguardanti gli eventi di mouse. Per facilitare la lettura dei risulati potete cancellare il contenuto della prima textarea cliccando sopra i vari layer.

      In una seconda textarea visualizzo le coordinate del puntatore del mouse relative a diversi punti di riferimento.

      Nota: in questo esempio Opera 5, manifesta un bug, dovuto al fatto che, pur ammettendo l'event bubbling, di volta in volta l'ultimo evento accaduto, invece di concludere il proprio flusso ed uscire dalla struttura del documento, sembra perdurare. Questo porta a gravi conflitti nella gestione dell'oggetto event. Nell'esempio proposto, solo in Opera 5, per cancellare la textarea occorre cliccare sull'area relativa al SOLO livello "box", per evitare il crash del browser.

      Questo bug è stato corretto nella versione 6.

      box

      esterno

      interno


      tabella

      Nel mostrare il codice dell'esempio metto in evidenza gli event handler:


      <table class="tabella" width="100%" onmousemove="coordinate(event)"
      onclick="alert('hai premuto fuori dal livello 'box'')"

      <tr>
        <td>
          <div id="box" onclick="pulisci(event);"
            <div id="esterno" onmouseover="mostra_su_video(event)" onmouseout="mostra_su_video(event)"
            <b id="bold_esterno">esterno</b>
              <div id="interno"><b id="bold_interno">interno</b></div>
            </div>
          </div>
        </td>
        <td>
          <textarea rows=9 cols=40 name="video"></textarea>
          <textarea rows=3 cols=40 name="coord"></textarea>
        </td>
      </tr>
      <tr><td colspan="2" height="50px"><b>tabella</b></td>
      </tr>
      </table>
      </form>

      le funzioni richiamate sono:

      /*-----------------------
        Funzioni principali
      -----------------------*/

      stringa = "";

      function mostra_su_video(e)
        if(!e) e = window.event;
        sorgente = (e.target) ? e.target : e.srcElement;

        mw3 = (e.relatedTarget && e.target) ? 1 : 0;
        daElemento = (mw3) ? ((e.type=="mouseover") ? e.relatedTarget :e.target) : e.fromElement;
        aElemento = (mw3) ? ((e.type=="mouseout") ? e.relatedTarget :e.target) : e.toElement;

        stringa += "evento : "+e.type;
        stringa += "ngenarato in : "+con_id(sorgente).id;
        stringa += "nesce da : "+((daElemento)? con_id(daElemento).id : "proprietà non definita")
        stringa += "ndiretto in : "+((aElemento)? con_id(aElemento).id : "proprietà non definita")
        stringa += "nn";
        document.forms["f1"].video.value=stringa

        if(e.stopPropagation) e.stopPropagation()
        else e.cancelBubble=true
      }

      // La seguente funzione ha lo scopo di visualizzare
      // nella seconda textarea (chiamata "coord")
      // le coordinate del mouse rispetto ai diversi
      // punti di riferimento.

      function coordinate(e)
        stringaxy = "";
        if(!e) window.event
        oggsrc = (e.target) ? e.target : e.srcElement;
        sx = e.screenX
        sy = e.screenY
        cx = e.clientX
        cy = e.clientY
        ox = (e.offsetX) ? e.offsetX : e.layerX
        oy = (e.offsetY) ? e.offsetY : e.layerY
        stringaxy = "screenX = "+sx+", screenY = "+sy
        stringaxy += "nclientX = "+cx+", clientY = "+cy
        stringaxy += "n"+con_id(oggsrc).id+": X = "+ox+", Y = "+oy
        document.forms["f1"].coord.value = stringaxy
      }

      // Questa è la funzione che ripulisce
      // la textArea per semplificare il
      // controllo degli eventi.
      // notate il codice crossbrowser per
      // interrompere il flusso d'evento.

      function pulisci(e)

      /*-----------------------
        Funzioni secondarie
      -----------------------*/

      // utilizzo la seguente funzione per intercettare il tag bold
      // quando si fa un rollover sui testi.
      // Ricordatevi infatti che anche i testi sono dei nodi.

      function con_id(ogg){
        while(ogg && !ogg.id)
      // Introduco la proprietà parentElement, che è l'equivalente
      // di parentNode per Explorer 4.
          ogg = (ogg.parentNode) ? ogg.parentNode : ogg.parentElement;
        if(!ogg) {ogg=new Object(); ogg.id="elemento senza ID"}
        return(ogg)
      }

      Se l'esempio vi è chiaro in tutti i suoi aspetti potete passare ad esaminare il codice della prossima applicazione.

      Un'Applicazione: Rollover su Tabelle

      Questo è un ottimo esempio per descrivere le proprietà dell'oggetto event e l'utilità del saper sfruttare il modello d'evento per scrivere codici intelligenti e dinamici.

      L'esempio permette di creare un'effetto rollover e di permanenza alla pressione sulle celle di una tabella, il tutto si basa sulla conoscenza dell'event flow e in particolare della fase di bubbling, grazie alla quale gli eventi generati in un qualsiasi elemento risalgono, di volta in volta,gli elementi di ordine gerarchico superiore.

      Nel dettaglio, si sfrutta il fatto che gli eventi generati nelle celle e nelle righe di una tabella, risalgono la struttura della pagina e tutti passano per l'elemento TABLE.

      Per cui è possibile usare gli event handler solo su questo elemento, senza il bisogno di metterli in tutte le celle della tabella in cui si voglia intervenire...e potrebbero essere molte.

      Lo script originale (indicatomi dai ragazzi del

      [!] Ci sono problemi con l'autore. Controllare il mapping sull'Author Manager

      ) lo potete trovare a questo

      [!] Ci sono problemi con l'autore. Controllare il mapping sull'Author Manager

      . La mia versione "italianizza" il codice oltre ad aggiungere qualche altra funzionalità allo script.
      Questo codice gira su:

      • Explorer 4+
      • Netscape 6+
      • Opera 6
      • Mozilla 1, e tutti i browser W3C compatibili

      Per quanto riguarda Opera 5, è sempre presente il bug descritto nella pagina precedente. Ecco un'esempio dell'applicazione:

      Titolo 1 Titolo 2
      cella 1 cella 2
      cella 3 cella 4
      cella 5 cella 6
      cella 7 cella 8

      Nel codice HTML metto ancora una volta in evidenza gli event handlers:

      <table border=1 cellpadding=0 cellspacing=0
      onmouseover="cambiaSuOver(event)"
      onmouseout="cambiaSuOut(event)"
      onclick="clicca()"

      width="40%">
      <TR><TD id="ignora">Titolo 1</TD><TD id="ignora1">Titolo 2</TD></TR>
      <TR><TD>cella 1</TD><TD>cella 2</TD></TR>
      <TR><TD>cella 3</TD><TD>cella 4</TD></TR>
      <TR><TD>cella 5</TD><TD>cella 6</TD></TR>
      <TR><TD>cella 7</TD><TD>cella 8</TD></TR>
      </TABLE>

      Come potete vedere, gli event handler sono solo al livello del tag TABLE e gestiscono gli eventi di mouse accesi nelle varie celle della tabella. Il codice JavaScript invece è:

      /*-----------------------
        Funzioni principali
      -----------------------*/

      // I seguenti array contengono gli stili che devono essere settati
      // alle celle della tabella nei rispettivi eventi di mouse

      stiliOver = new Array("backgroundColor=#FFCC00","color=black","fontStyle=italic")
      stiliOut = new Array("backgroundColor=white","color=black","fontStyle=normal")
      stiliClick = new Array("backgroundColor=#FF9900","color=#FFFF66")

      // "acceso" è la variabile che di volta in volta contiene
      // un riferimento alla cella cliccata

      acceso = null

      function cambiaSuOver(e)
        if(!e) e = event
        sorgente = (e.target) ? e.target : e.srcElement
        if (sorgente.tagName=="TR" || sorgente.tagName=="TABLE")
          return
        while(sorgente.tagName!="TD" && sorgente.tagName!="HTML")
          sorgente = (sorgente.parentNode) ? sorgente.parentNode : sorgente.parentElement
        if (sorgente.id!="ignora" && sorgente!=acceso) {
          for(a in stiliOver) {
            stile=stiliOver[a].split("=");
            sorgente.style[stile[0]]=stile[1];
          }
        }
      }

      function cambiaSuOut(e)
        if(!e) e = event
        if
      (e.fromElement&&(e.fromElement.contains(e.toElement)||sorgente.contains(e.toElement)||sorgente.id=="ignora")
      ||sorgente==acceso||sorgente.tagName=="TR"||sorgente.tagName=="TABLE")
          return
        else if (e.relatedTarget&&(contains_ns6(sorgente, e.relatedTarget)||sorgente.id=="ignora"||sorgente==acceso))
          return
        if (e.toElement&&e.toElement!=sorgente||e.relatedTarget&&e.relatedTarget!=sorgente)
          for(a in stiliOut) {
            stile=stiliOut[a].split("=");
            sorgente.style[stile[0]]=stile[1];
          }
      }

      function clicca()
        if (sorgente!=acceso&&sorgente.id!="ignora") {
          if(acceso) {
            for(a in stiliOut) {
              stile=stiliOut[a].split("=");

              acceso.style[stile[0]]=stile[1];
            }
          }
          for(a in stiliClick) {
            stile=stiliClick[a].split("=");
            sorgente.style[stile[0]]=stile[1];
          }
          acceso = sorgente
        }
      }

      /*-----------------------
        Funzioni secondarie
      -----------------------*/

      // contains è un metodo introdotto da Explorer fin dalla
      // versione 4. Il metodo verifica se l'elemento passato come parametro è
      // contenuto dall'elemento al quale il metodo è applicato.
      // La seguente funzione mira ad estendere il metodo anche nei browser
      // (come Netscape 6, Opera 5) che originariamente non lo supportano

      function contains_ns6(master, slave) {
        while (slave.parentNode)
          if ((slave = slave.parentNode) == master)
            return true;
        return false;
      }

      Nota

      stiliOver = new Array("backgroundColor=#FFCC00","color=black","fontStyle=italic")
      stiliOut = new Array("backgroundColor=white","color=black","fontStyle=normal")
      stiliClick = new Array("backgroundColor=#FF9900","color=#FFFF66")

      Riempendoli con elementi che settino le varie proprietà dell'oggetto style

      Se volete, potete scaricare il codice:

      [!] Ci sono problemi con l'autore. Controllare il mapping sull'Author Manager

      .

      Questo articolo contiene link di affiliazione: acquisti o ordini effettuati tramite tali link permetteranno al nostro sito di ricevere una commissione nel rispetto del codice etico

Ti consigliamo anche