2012-04-20 17 views
5

¿Alguien puede decir cómo "desvincular" una función anónima? JQUERY es capaz de hacer eso, pero ¿cómo puedo implementar esta funcionalidad en mi propio script?Desvincular una función anónima

Este es el escenario:

El siguiente código adjuntar un evento 'onclick' a la Div que tienen 'someDivId' como identificación, ahora wen, hace clic en el DIV, es espectáculo 'clic'.

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

Eso es todo muy bien, el problema es la forma de "no-adjuntar" la función de la DIV si la función es anónima o la forma de "no-ATTACH" todos los eventos adjuntos al elemento 'a'?

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

Este es el código para bindEvent Método:

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

¿De dónde sacaste 'bindEvent()'? ¿Qué hace? – jfriend00

+0

¿Está solicitando una respuesta que no esté basada en jQuery (por ejemplo, javascript simple)? – jfriend00

+0

@ jfriend00: quiere implementarlo solo, por ej. no está usando jQuery, pero pregunta cómo lo hace jQuery. – prodigitalson

Respuesta

4

Finalmente, y después de horas de prueba & errores que he encontrado una solución, tal vez no es la mejor o más eficiente, pero ... TI ¡TRABAJOS! (Probado en IE9, Firefox 12, Chrome 18)

En primer lugar, creo dos métodos cross-browser y auxiliary addEvent() y removeEvent(). (Idea tomada del código fuente de 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]); 

    } 
} 

También necesitamos una especie de 'contenedor' para almacenar los eventos asociado a los elementos, así:

HELPERS.EVTS = {}; 

Y por último los dos exigible y expuesto a los métodos de los usuarios: El siguiente uno para agregar un evento (evento) y asociar este evento a un método (controlador) para un elemento específico (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; 

    } 

Por último, el método que ONU-adjuntar todos los eventos pre-adjunta (eventos) para un elemento específico (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; 

    } 

Por cierto, para llamar a estos métodos que usted debe hacer lo siguiente: Capture un DOM nodo

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

Call el método 'bindEvent()' con los parámetros correspondientes.

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

Y para de-adjuntarlo:

removeAllEvent('click',a); 

Eso es todo, esperamos que sea útil para alguien un día.

+1

No estoy seguro de que la línea 'HELPERS.EVT [el]', donde 'el' es una referencia a un elemento DOM, esté haciendo lo que crees que está haciendo. Los nombres de propiedad de JavaScript [deben ser cadenas] (https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators#Property_names), y no estoy seguro de que exista un método estándar 'toString' para los elementos DOM. En Firefox 11 e IE9, obtengo '" [object HTMLDivElement] "' ​​cuando llamo a 'toString' en un elemento' div'. –

+0

@CheranShunmugavel: Es exactamente correcto. Usando este sistema, dos elementos 'div' diferentes aparecerán como la misma propiedad en la tabla' HELPERS.EVT'. –

2

Personalmente (y sé que este no es el "mejor", como lo hace conmigo requerir que pensar en lo que estoy haciendo), Me gusta usar las propiedades de evento on* del elemento con el que estoy trabajando.

Esto tiene la conveniente ventaja de poder separar los eventos de forma rápida y sencilla.

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

Sin embargo, usted tiene que tener cuidado con esto porque si intenta agregar un segundo controlador de eventos que se sobreponen a la primera. Tenlo en cuenta y deberías estar bien.

+0

a.onclick = null no funciona, eso es porque la función bindEvent() funciona de forma diferente, por favor, verifique la pregunta original: voy a editarla y publicar el código del bindEvent() –

+0

gracias a una idea de jlaceda encontré una solución para resolver el problema. –

-1

Esto es de jQuery de 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

Esto es solo una pequeña parte del sistema de eventos de jQuery. ¿Cómo responderá la pregunta? –

+0

@jlaceda Estoy revisando ahora el código fuente completo. ¡Gracias! –

+0

@amnotiam Me imaginé que esta es la parte de "metal más puro" del procedimiento de eliminación de eventos en jquery y será una referencia útil para crear una función personalizada UnBind. Pero tienes razón en que no es una respuesta completa. Editaré en una función independiente que se basará en este fragmento. – jlaceda

1

No estoy seguro de si se puede desvincular una función anónima unido a través de JavaScript. Si es posible, puede eliminar el elemento del DOM y volver a crearlo. Esto eliminará cualquier controlador de eventos adjunto anteriormente.

+0

pero JQuery puede hacerlo! ¡Así que no es imposible! –

+1

@JoshGuzman: jQuery enlaza exactamente * un * manejador por elemento, y nunca es el manejador que lo pasó. Sus manejadores se almacenan en 'jQuery.cache'. Vincula un manejador genérico que, cuando se invoca, mira el objeto de evento, ve qué tipo de evento es, busca un número de serie en el elemento, busca si ese número de serie existe en 'jQuery.cache', y si es así, comprueba si se han proporcionado controladores para el tipo de evento actual, y lo invoca si es así. –

+0

... el manejador genérico vinculado a jQuery también se menciona en 'jQuery.cache', por lo que cuando llega el momento de desvincularlo, realiza una búsqueda similar y lo pasa a los métodos nativos que desvinculan los manejadores. Por supuesto, cuando haces '.unbind ('click')', simplemente está borrando los manejadores 'click' en' jQuery.cache'. –

1

JavaScript no proporciona una lista de detectores de eventos adjuntos a un nodo.

Puede eliminar todos los detectores de eventos de un nodo, pero utilizando el método Node.cloneNode, ve aquí: https://developer.mozilla.org/En/DOM/Node.cloneNode

Este clona el nodo (obviamente) pero no clona los detectores de eventos asociados a la misma.

También puedes, simplemente enlazar funciones vacíos como los detectores de eventos:

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

Pero la función que unir a un elemento es anónima, lo que significa que no tengo ninguna referencia de nombre, por lo que no puedo anularlos ni conocerlos. –

+0

Ah sí, olvidé que puede tener múltiples oyentes de eventos para el mismo evento. No puede obtener una referencia a su función anónima. Si puede cambiar su código para que no sea anónimo, esa sería la mejor solución. De lo contrario, tendrá que matar a todos los oyentes del evento y agregar los que desee, de nuevo. – Griffin

+0

problema resuelto, gracias de cualquier manera. –

Cuestiones relacionadas