2012-02-20 14 views
6

Ho creato una funzione factory emettitore eventi multiuso. Con esso posso trasformare gli oggetti in emettitori di eventi. Il codice per la fabbrica di emettitori di eventi è sotto se qualcuno vorrebbe dare un'occhiata o usarlo.Come ottenere una matrice di tutti gli eventi DOM possibili

La mia domanda è come ottenere un elenco di eventi dal DOM. Nota. Non sto cercando di ottenere un elenco di eventi associati. Voglio una lista di tutti gli eventi possibili. Voglio aggiungere un metodo "pipe" agli emettitori. Questo metodo prenderebbe un oggetto DOM e si collegherebbe a tutti gli eventi possibili, quindi quando uno di quegli eventi sparasse ognuno avrebbe attivato un evento con lo stesso nome nell'emettitore.

Non immagino ci sia un modo per farlo. Sono pronto a creare un array di nomi di eventi, ma se riesco a ottenere l'array per il DOM, sarebbe molto meglio e funzionerebbe ancora se il W3C standardizzasse più tipi di eventi.

P.S. Se lavori per il W3C questo è il tipo di schifezza che fa odiare tutti il ​​DOM. Si prega di smettere di trattare JavaScript come un linguaggio giocattolo. Non è un linguaggio giocattolo e ha bisogno di più del tuo DOM giocattolo.

/** 
* Creates a event emitter 
*/ 
function EventEmitter() { 
    var api, callbacks; 

    //vars 
    api = { 
     "on": on, 
     "trigger": trigger 
    }; 
    callbacks = {}; 

    //return the api 
    return api; 

    /** 
    * Binds functions to events 
    * @param event 
    * @param callback 
    */ 
    function on(event, callback) { 
     var api; 

     if(typeof event !== 'string') { throw new Error('Cannot bind to event emitter. The passed event is not a string.'); } 
     if(typeof callback !== 'function') { throw new Error('Cannot bind to event emitter. The passed callback is not a function.'); } 

     //return the api 
     api = { 
      "clear": clear 
     }; 

     //create the event namespace if it doesn't exist 
     if(!callbacks[event]) { callbacks[event] = []; } 

     //save the callback 
     callbacks[event].push(callback); 

     //return the api 
     return api; 

     function clear() { 
      var i; 
      if(callbacks[event]) { 
       i = callbacks[event].indexOf(callback); 
       callbacks[event].splice(i, 1); 

       if(callbacks[event].length < 1) { 
        delete callbacks[event]; 
       } 

       return true; 
      } 
      return false; 
     } 
    } 

    /** 
    * Triggers a given event and optionally passes its handlers all additional parameters 
    * @param event 
    */ 
    function trigger(event ) { 
     var args; 

     if(typeof event !== 'string' && !Array.isArray(event)) { throw new Error('Cannot bind to event emitter. The passed event is not a string or an array.'); } 

     //get the arguments 
     args = Array.prototype.slice.apply(arguments).splice(1); 

     //handle event arrays 
     if(Array.isArray(event)) { 

      //for each event in the event array self invoke passing the arguments array 
      event.forEach(function(event) { 

       //add the event name to the begining of the arguments array 
       args.unshift(event); 

       //trigger the event 
       trigger.apply(this, args); 

       //shift off the event name 
       args.shift(); 

      }); 

      return; 
     } 

     //if the event has callbacks then execute them 
     if(callbacks[event]) { 

      //fire the callbacks 
      callbacks[event].forEach(function(callback) { callback.apply(this, args); }); 
     } 
    } 
} 
+0

Ho fatto una domanda simile: [È possibile registrare tutti gli eventi sulla pagina nel browser?] (Http://stackoverflow.com/questions/5107232/is-it-possibile-per-programmaticamente -Catch-all-eventi-on-the-page-in-the-browser). –

risposta

5

Ecco una versione che funziona in Chrome, Safari e FF.

Object.getOwnPropertyNames(document).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)))).filter(function(i){return !i.indexOf('on')&&(document[i]==null||typeof document[i]=='function');}) 

UPD:

Ed ecco la versione che funziona in IE9 +, Chrome, Safari e FF.

Object.getOwnPropertyNames(document).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)))).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(window))).filter(function(i){return !i.indexOf('on')&&(document[i]==null||typeof document[i]=='function');}).filter(function(elem, pos, self){return self.indexOf(elem) == pos;}) 

PS: il risultato è una serie di eventi nome come ["onwebkitpointerlockerror", "onwebkitpointerlockchange", "onwebkitfullscreenerror", "onwebkitfullscreenchange", "onselectionchange", "onselectstart", "onsearch", "onreset", "onpaste", "onbeforepaste", "oncopy"] ... ect.

5

Tutti gli eventi DOM iniziano con on. È possibile eseguire il ciclo di qualsiasi istanza Element ed elencare tutte le proprietà che iniziano con on.

Esempio. Copiare e incollare il seguente codice nella console (Firefox, utilizzando comprehensions Array;)):

[i for(i in document)].filter(function(i){return i.substring(0,2)=='on'&&(document[i]==null||typeof document[i]=='function');}) 

Un altro metodo per ottenere gli eventi è, cercando in the specification, che rivela:

// event handler IDL attributes 
    [TreatNonCallableAsNull] attribute Function? onabort; 
    [TreatNonCallableAsNull] attribute Function? onblur; 
    [TreatNonCallableAsNull] attribute Function? oncanplay; 
    [TreatNonCallableAsNull] attribute Function? oncanplaythrough; 
    [TreatNonCallableAsNull] attribute Function? onchange; 
    [TreatNonCallableAsNull] attribute Function? onclick; 
    [TreatNonCallableAsNull] attribute Function? oncontextmenu; 
    [TreatNonCallableAsNull] attribute Function? oncuechange; 
    [TreatNonCallableAsNull] attribute Function? ondblclick; 
    [TreatNonCallableAsNull] attribute Function? ondrag; 
    [TreatNonCallableAsNull] attribute Function? ondragend; 
    [TreatNonCallableAsNull] attribute Function? ondragenter; 
    [TreatNonCallableAsNull] attribute Function? ondragleave; 
    [TreatNonCallableAsNull] attribute Function? ondragover; 
    [TreatNonCallableAsNull] attribute Function? ondragstart; 
    [TreatNonCallableAsNull] attribute Function? ondrop; 
    [TreatNonCallableAsNull] attribute Function? ondurationchange; 
    [TreatNonCallableAsNull] attribute Function? onemptied; 
    [TreatNonCallableAsNull] attribute Function? onended; 
    [TreatNonCallableAsNull] attribute Function? onerror; 
    [TreatNonCallableAsNull] attribute Function? onfocus; 
    [TreatNonCallableAsNull] attribute Function? oninput; 
    [TreatNonCallableAsNull] attribute Function? oninvalid; 
    [TreatNonCallableAsNull] attribute Function? onkeydown; 
    [TreatNonCallableAsNull] attribute Function? onkeypress; 
    [TreatNonCallableAsNull] attribute Function? onkeyup; 
    [TreatNonCallableAsNull] attribute Function? onload; 
    [TreatNonCallableAsNull] attribute Function? onloadeddata; 
    [TreatNonCallableAsNull] attribute Function? onloadedmetadata; 
    [TreatNonCallableAsNull] attribute Function? onloadstart; 
    [TreatNonCallableAsNull] attribute Function? onmousedown; 
    [TreatNonCallableAsNull] attribute Function? onmousemove; 
    [TreatNonCallableAsNull] attribute Function? onmouseout; 
    [TreatNonCallableAsNull] attribute Function? onmouseover; 
    [TreatNonCallableAsNull] attribute Function? onmouseup; 
    [TreatNonCallableAsNull] attribute Function? onmousewheel; 
    [TreatNonCallableAsNull] attribute Function? onpause; 
    [TreatNonCallableAsNull] attribute Function? onplay; 
    [TreatNonCallableAsNull] attribute Function? onplaying; 
    [TreatNonCallableAsNull] attribute Function? onprogress; 
    [TreatNonCallableAsNull] attribute Function? onratechange; 
    [TreatNonCallableAsNull] attribute Function? onreset; 
    [TreatNonCallableAsNull] attribute Function? onscroll; 
    [TreatNonCallableAsNull] attribute Function? onseeked; 
    [TreatNonCallableAsNull] attribute Function? onseeking; 
    [TreatNonCallableAsNull] attribute Function? onselect; 
    [TreatNonCallableAsNull] attribute Function? onshow; 
    [TreatNonCallableAsNull] attribute Function? onstalled; 
    [TreatNonCallableAsNull] attribute Function? onsubmit; 
    [TreatNonCallableAsNull] attribute Function? onsuspend; 
    [TreatNonCallableAsNull] attribute Function? ontimeupdate; 
    [TreatNonCallableAsNull] attribute Function? onvolumechange; 
    [TreatNonCallableAsNull] attribute Function? onwaiting; 

    // special event handler IDL attributes that only apply to Document objects 
    [TreatNonCallableAsNull,LenientThis] attribute Function? onreadystatechange; 
+0

Nota.L'elenco precedente di eventi è ** non completo **. Ad esempio, l'elemento ['] (http://dev.w3.org/html5/spec/Overview.html#the-body-element) definisce anche un insieme di eventi. Basta cercare la funzione di attributo '[TreatNonCallableAsNull]? on' nella specifica per trovare tutti gli eventi (HTML5). –

+0

Ho già provato ad eseguire il ciclo attraverso gli eventi di livello DOM 0 e non si visualizzano in un ciclo for in perché i metodi * non sono enumerabili quando vengono lasciati come null. Si prega di notare che non sto cercando di catturare i binding esistenti. Sto cercando di ottenere una lista dinamica di possibili associazioni. –

+0

@RobertHurst Nei browser conformi (moderni), tutti gli eventi sono enumerabili. Quando non sono ancora definiti, devono essere "null", per definizione. Poiché gli eventi sono ** conosciuti in anticipo **, consiglio di creare un elenco di eventi e di implementarlo. È molto più efficiente rispetto al ciclo delle proprietà di molti elementi e al filtraggio dei nomi delle proprietà. –

0

I' Ho letto le specifiche e ho confermato che non è attualmente possibile. Grazie W3C per non averci fornito l'ambiente più basilare!

Sono riuscito a risolvere il problema senza sacrificare nulla. Come ho detto prima, pipe trasporta qualsiasi evento da un altro emettitore (come un nodo DOM) nell'emettitore corrente. Tuttavia non ho bisogno di fare nulla finché qualcuno non cerca di ascoltare un evento. Internamente ciò che faccio è legarsi agli emettitori tubolari mentre le persone si legano all'emettitore corrente.

Ho il released the library se siete curiosi di vedere cosa ho fatto. Il codice per pipe è nel metodo pipe() e nel metodo on().

Problemi correlati