2012-04-20 21 views
5

Qualcuno può dire come "dissipare" una funzione anonima? JQUERY è in grado di farlo, ma come posso implementare questa funzionalità nel mio script.Non associare una funzione anonima

questo è lo scenario:

Il seguente codice allegare un 'onclick' evento al div che hanno 'someDivId' come ID, ora wen si fa clic sul DIV, è show 'cliccato!'.

var a = document.getElementById('someDivId'); 
bindEvent(a,'click',function(){alert('clicked!');}); 

Questo è tutto grande, il problema è come "un-attach" la funzione al DIV se la funzione è anonimo o come "non-attach" tutti gli eventi collegati alla 'un' elemento?

unBind(a,'click'); //Not necessarily the given params, it's just an example. 

Questo è il codice per il metodo bindEvent:

function bindEvent (el,evtType,fn){ 
    if (el.attachEvent) { 
     el['e'+evtType+fn] = fn; 
     el[evtType+fn] = function(){ 
      fn.call(el,window.event); 
     } 
     el.attachEvent('on'+evtType, el[evtType+fn]); 
    } else { 
     el.addEventListener(evtType, fn, false); 
    } 
} 
+1

Dove hai ottenuto 'bindEvent()'? Che cosa fa? – jfriend00

+0

Stai chiedendo una risposta non basata su jQuery (ad esempio, plain javascript)? – jfriend00

+0

@ jfriend00: vuole implementarlo da solo - es. hes non usa jQuery, ma chiede come fa jQuery. – prodigitalson

risposta

4

Infine, e dopo ore di test & errori che ho trovato una soluzione, forse non è il migliore o più efficiente, ma ... IT LAVORI! (Testato su IE9, Firefox 12, Chrome 18)

Prima di tutto ho creato due metodi addEvent() e removeEvent() tra browser e ausiliari. (Idea tratta dal codice sorgente di Jquery!)

HELPERS.removeEvent = document.removeEventListener ? 
function(type, handle,el) { 
    if (el.removeEventListener) { 
    //W3C Standard  
    el.removeEventListener(type, handle, true); 
    } 
} : 
function(type, handle,el) { 
    if (el.detachEvent) { 
     //The IE way 
     el.detachEvent('on'+type, el[type+handle]); 
     el[type+handle] = null; 
    } 
}; 

HELPERS.addEvent = document.addEventListener ? 
function(type, handle,el) { 
    if (el.addEventListener) { 
     //W3C Standard 
     el.addEventListener(type, handle, true); 
    } 
} : 
function(type, handle,el) { 
    if (el.attachEvent) { 
     //The IE way 
     el['e'+type+handle] = handle; 
     el[type+handle] = function(){ 
      handle.call(el,window.event); 
     }; 
     el.attachEvent('on'+type, el[type+handle]); 

    } 
} 

Inoltre abbiamo bisogno di un qualche tipo di 'contenitore' per memorizzare gli eventi collegati agli elementi, in questo modo:

HELPERS.EVTS = {}; 

E infine i due callable ed esposto ai metodi degli utenti: La prossima uno per aggiungere un evento (evento) e associare questo evento a un metodo (gestore) per un elemento specifico (el).

function bindEvent(event, handler,el) { 

      if(!(el in HELPERS.EVT)) { 
       // HELPERS.EVT stores references to nodes 
       HELPERS.EVT[el] = {}; 
      } 

      if(!(event in HELPERS.EVT[el])) { 
       // each entry contains another entry for each event type 
       HELPERS.EVT[el][event] = []; 
      } 
      // capture reference 
      HELPERS.EVT[el][event].push([handler, true]); 
      //Finally call the aux. Method 
      HELPERS.addEvent(event,handler,el); 

     return; 

    } 

Infine il metodo che non-allegare tutti gli eventi pre-attached (evento) per un elemento specifico (el)

function removeAllEvent(event,el) { 

      if(el in HELPERS.EVT) { 
       var handlers = HELPERS.EVT[el]; 
       if(event in handlers) { 
        var eventHandlers = handlers[event]; 
        for(var i = eventHandlers.length; i--;) { 
         var handler = eventHandlers[i]; 
         HELPERS.removeEvent(event,handler[0],el); 

        } 
       } 
      } 

    return; 

    } 

Tra l'altro, di chiamare questa modalità è necessario effettuare le seguenti operazioni: Capture un DOM Node

var a = document.getElementById('some_id'); 

chiamate il metodo 'bindEvent()' con i parametri corrispondenti.

bindEvent('click',function(){alert('say hi');},a); 

e di de-attaccarlo:

removeAllEvent('click',a); 

Questo è tutto, spero possa essere utile per qualcuno un giorno.

+1

Non sono sicuro che la riga 'HELPERS.EVT [el]', dove 'el' è un riferimento a un elemento DOM, sta facendo ciò che pensi che stia facendo. Nomi di proprietà JavaScript [devono essere stringhe] (https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators#Property_names) e non sono sicuro che esista un metodo standard 'toString' per elementi DOM. In Firefox 11 e IE9, ottengo '" [object HTMLDivElement] "' ​​quando si chiama 'toString' su un elemento' div'. –

+0

@CheranShunmugavel: ha esattamente ragione. Usando questo sistema, due diversi elementi 'div' appariranno come la stessa proprietà nella tabella' HELPERS.EVT'. –

2

Personalmente (e so che questo non è il modo "migliore", come fa mi richiede di pensare a quello che sto facendo), Mi piace usare solo le proprietà dell'evento on* dell'elemento con cui sto lavorando.

Questo ha il vantaggio pratico di essere in grado di staccare rapidamente e facilmente gli eventi.

var a = document.getElementById('someDivId'); 
a.onclick = function() {alert("Clicked!");}; 
// later... 
a.onclick = null; 

Tuttavia, c'è bisogno di essere attenti a questo perché se si tenta di aggiungere un secondo gestore di eventi che sovrascrive il primo. Tienilo a mente e dovresti stare tutto bene.

+0

a.onclick = null non funziona, questo perché la funzione bindEvent() funziona in un modo diverso, per favore, controlla la domanda originale: ho intenzione di modificarlo un post il codice di bindEvent() –

+0

grazie a un'idea di jlaceda ho trovato una soluzione per risolvere il problema. –

-1

Questo è da jQuery di source:

jQuery.removeEvent = document.removeEventListener ? 
    function(elem, type, handle) { 
     if (elem.removeEventListener) { 
      elem.removeEventListener(type, handle, false); 
     } 
    } : 
    function(elem, type, handle) { 
     if (elem.detachEvent) { 
      elem.detachEvent("on" + type, handle); 
     } 
    }; 
+2

Questa è solo una piccola parte del sistema di eventi di jQuery. Come risponderà alla domanda? –

+0

@jlaceda Sto controllando adesso il codice sorgente completo. grazie! –

+0

@amnotiam Ho pensato che questa è la parte "più bare metal" della procedura di rimozione degli eventi in jquery e sarà utile riferimento nella creazione di una funzione unBind personalizzata. Ma hai ragione che non è una risposta completa. Verrà modificato in una funzione autonoma basata su questo frammento di codice. – jlaceda

1

io non sono sicuro se si può associare una funzione anonima collegata tramite JavaScript. Se possibile, puoi semplicemente rimuovere l'elemento dal DOM e ricrearlo. Questo eliminerà qualsiasi gestore di eventi precedentemente collegato.

+0

ma JQuery può farlo! quindi non è impossibile! –

+1

@JoshGuzman: jQuery lega esattamente * un * gestore per elemento, e non è mai il gestore che lo ha passato. I tuoi gestori sono memorizzati in 'jQuery.cache' Lega un gestore generico che, quando viene richiamato, guarda l'oggetto evento, vede quale tipo di evento è, cerca un numero seriale sull'elemento, guarda se quel numero di serie esiste in 'jQuery.cache', e se è così, controlla se sono stati dati eventuali gestori per il tipo di evento corrente e se lo richiama. –

+0

... il gestore generico a cui jQuery è associato fa anche riferimento in 'jQuery.cache', quindi quando arriva il momento di smistarlo, fa una ricerca simile e lo passa ai metodi nativi che non tengono i gestori. Ovviamente, quando si esegue '.unbind ('click')', si cancellano i gestori di 'click' in' jQuery.cache'. –

1

JavaScript non fornisce alcun elenco di listener di eventi collegati a un nodo.

È possibile rimuovere tutti gli ascoltatori di eventi di un nodo, ma utilizzando il metodo Node.cloneNode, vedi qui: https://developer.mozilla.org/En/DOM/Node.cloneNode

Questa cloni il nodo (ovviamente), ma non clonare i listener di eventi ad essa collegati.

Si potrebbe anche solo legare funzioni vuote come ascoltatori di eventi:

function noop() {} 
bindEvent(myElement, "click", noop); 
+0

Ma la funzione che leghiamo a un elemento è anonima, il che significa che non ho alcun riferimento al nome, quindi non posso ignorarli o conoscerli. –

+0

Ah sì, ho dimenticato che puoi avere più ascoltatori di eventi per lo stesso evento. Non puoi ottenere un riferimento alla tua funzione anonima. Se puoi cambiare il tuo codice in modo che non sia anonimo, quella sarebbe la soluzione migliore. Altrimenti dovrai solo uccidere tutti gli ascoltatori di eventi e aggiungere quelli che vuoi, di nuovo. – Griffin

+0

problema risolto, grazie in ogni modo. –

Problemi correlati