2010-03-25 24 views
476

Necesito encontrar qué controladores de eventos están registrados sobre un objeto.jQuery encontrar controladores de eventos registrados con un objeto

Por ejemplo:

$("#el").click(function() {...}); 
$("#el").mouseover(function() {...}); 

$("#el") tiene clic y encima del ratón registrado.

¿Existe alguna función para averiguarlo y, posiblemente, iterar sobre los controladores de eventos?

Si no es posible en un objeto jQuery con los métodos adecuados, ¿es posible en un objeto DOM simple?

+5

lamentablemente, ahora: http://bugs.jquery.com/ticket/10589 –

+2

admiten jQuery pre y post 1.8: 'var events = (jQuery._data || jQuery.data) (elem, 'events') ; ' – oriadam

+2

Tenga en cuenta que puede usar las herramientas de desarrollo FF y Chrome (F12) para ver estos detectores de eventos. Consulte https://developers.google.com/web/tools/chrome-devtools/debug/command-line/events#view-event-listeners-registered-on-doms-elements y https://developer.mozilla.org/es-ES/docs/Herramientas/Page_Inspector/How_to/Examine_event_listeners – oriadam

Respuesta

596

A partir de jQuery 1.8, los datos del evento ya no están disponibles en la "API pública" para los datos. Lee this jQuery blog post. Ahora debe utilizar en su lugar:

jQuery._data(elem, "events"); 

elem debería ser un elemento HTML, no un objeto jQuery, o el selector.

Tenga en cuenta que esta es una estructura interna 'privada' y no debe modificarse. Úselo para propósitos de depuración solamente.

En las versiones anteriores de jQuery, puede que tenga que utilizar el método antiguo, que es:

jQuery(elem).data("events"); 
+0

¡excelente! Funciona para mí –

+18

ya no está: http://bugs.jquery.com/ticket/10589 –

+189

pero aún puede usar '$ ._ data ($ (elem) .get (0)," events ")' – bullgare

71

Usted puede hacerlo de esta manera:

$("#el").click(function(){ alert("click");}); 
$("#el").mouseover(function(){ alert("mouseover"); }); 

$.each($("#el").data("events"), function(i, e) { 
    alert(i); 
}); 
//alerts 'click' then 'mouseover' 

Si estás en jQuery 1.4 + , esto alertará al evento y funciones con destino a la misma:

$.each($("#el").data("events"), function(i, event) { 
    alert(i); 
    $.each(event, function(j, h) { 
     alert(h.handler); 
    }); 
}); 
//alerts: 
//'click' 
//'function(){ alert("click"); }' 
//'mouseover' 
//'function(){ alert("mouseover"); }' 

​You can play with it on jsFiddle here

+2

Esta es la respuesta correcta. El bit crucial es la segunda mitad. Esto me ayudó a encontrar un problema en menos de un minuto que hubiera tomado más de una hora si tuviera que buscar todo el código. ¡Gracias! –

+2

Funciona con 1.4, pero no con jQuery 1.8.2. –

+15

Para jQuery 1.8+, ** debes ** utilizar el método de 'datos privados': 'jQuery._data (jQuery (" # el ") [0]," eventos ");' en lugar del método de 'datos públicos' : 'jQuery (" # el "). data (" eventos ")'. El objeto 'events' no se ha almacenado en' .data() 'durante mucho tiempo, recortamos algunos bytes de código eliminando este" proxy "de la" API pública " – gnarf

35

Para jQuery 1.8+, esto ya no funcionará porque los datos internos se colocan en un objeto diferente.

La última no oficial (pero funciona en las versiones anteriores, así, al menos en 1.7.2) forma de hacerlo es ahora - $._data(element, "events")

El guión bajo ("_") es lo que hace la diferencia aquí. Internamente, está llamando al $.data(element, name, null, true), el último (cuarto) parámetro es uno interno ("pvt").

+0

$ ._ data (" body "," eventos ") undefined $(). jquery; "1.7.1" (intentado 1.7.2 y 1.8.1 todo el tiempo "indefinido") –

+2

@Michal - http://api.jquery.com/jQuery.data/ dice que acepta un elemento, no un selector. – PhistucK

+1

Ahora funciona bien: $ ._ data ($ ("body"). Get (0), "events") O incluso mejor: $ ("body"). Data ("events")! –

2

Los eventos pueden ser recuperados usando:

jQuery(elem).data('events'); 

o jQuery 1.8+:

jQuery._data(elem, 'events'); 

Nota: Eventos acotado utilizando $('selector').live('event', handler) se pueden recuperar usando:

jQuery(document).data('events') 
+1

jQuery (documento) .data ('eventos') me da indefinido –

13

Utilizo el plugin eventbug para el firebug para este propósito.

+0

Gracias, gran consejo. La extensión agrega una pestaña a Firebug ("Eventos") que muestra los eventos de la página, para que pueda exporearlos fácilmente. – Gruber

+10

Además, Chrome Developer Tools tiene "Escuchadores de eventos" en la pestaña "Elementos" y "Puntos de interrupción del escuchador de eventos" en la pestaña "Fuentes". – clayzermk1

6

A partir de 1.9, no existe una forma documentada de recuperar los eventos, salvo el uso del complemento Migrate para restaurar el comportamiento anterior. Puede usar el método _.data() como menciona jps, pero ese es un método interno. Así que haga lo correcto y use el complemento Migrate si necesita esta funcionalidad.

De la documentación de jQuery en .data("events")

Prior to 1.9, .data("events") could be used to retrieve jQuery's undocumented internal event data structure for an element if no other code had defined a data element with the name "events". This special case has been removed in 1.9. There is no public interface to retrieve this internal data structure, and it remains undocumented. However, the jQuery Migrate plugin restores this behavior for code that depends upon it.

+0

La respuesta aceptada también muestra claramente la nueva forma ** correcta ** de obtenerla para versiones recientes: 'jQuery._data (elem," events ");' ... – Ian

+1

Una forma privada, no documentada, nunca será * correcto * manera. La forma correcta, es decir, documentada, pública y prevista, es utilizar el complemento Migrate. – oligofren

+3

Parece que no entiende bien el punto del complemento Migrate. jQuery eliminó las características en desuso, y el complemento Migrate es para ayudar ** a migrar ** el código del desarrollador a las versiones más nuevas para que puedan aprovechar de inmediato las nuevas características y mejoras, pero no perder la funcionalidad. Está destinado a ayudar al codificador a ver lo que deben hacer para comenzar a utilizar adecuadamente las nuevas versiones de jQuery. No debe usarlo en producción para ** restaurar ** funciones.Además, muchas cosas no están documentadas y actualizadas en la documentación de jQuery, ya lo señalaron antes, así que no es un motivo – Ian

26

Enchufe desvergonzado, pero se puede usar findHandlerJS

Para usarlo sólo hay que incluir findHandlersJS (o simplemente copiar & pegar el raw javascript code a la ventana de la consola de cromo) y especifique el tipo de evento y un selector de jquery para los elementos que le interesan.

Para su ejemplo usted podría qui ckly encontrar los controladores de eventos que usted ha mencionado haciendo

findEventHandlers("click", "#el") 
findEventHandlers("mouseover", "#el") 

Esto es lo que se volvió:

  • elemento
    El elemento real en el que el controlador de eventos se registró en
  • eventos
    matriz con la información sobre los manejadores de eventos jquery para el tipo de evento que nos interesa (ej. clic, cambio, etc.)
    • manejador
      método actual controlador de eventos que se puede ver haciendo clic derecho y seleccionando Mostrar definición de función
    • selector de
      El selector previsto eventos delegadas. Estará vacío para eventos directos.
    • objetivos
      Lista con los elementos a los que apunta este controlador de eventos. Por ejemplo, para un controlador de eventos delegado que está registrado en el objeto del documento y se dirige a todos los botones en una página, esta propiedad mostrará una lista de todos los botones en la página. Puede colocarlos sobre ellos y verlos resaltados en cromo.

Puede probarlo here

+5

Muchas gracias. Ninguna de las otras soluciones funcionó para mí, ¡pero funcionó! – AlcubierreDrive

+0

Creo que esa debería ser la respuesta aceptada. Ese es el único que también funciona para mí. Es muy completo ya que pasa por todos los elementos en busca de eventos. –

+0

¡Excelente! esto funciona realmente bien! – EmilianoPe

3

En un navegador moderno con ECMAScript 5.1/Array.prototype.map, también se puede utilizar

jQuery._data(DOCUMENTELEMENT,'events')["EVENT_NAME"].map(function(elem){return elem.handler;}); 

en la consola del navegador, que imprimirá la fuente de los manejadores, delimitados por comas. Útil para echar un vistazo a todo lo que se está ejecutando en un evento en particular.

+0

'jQuery._data ('ct100_ContentPlaceHolder1_lcsSection', 'events') [" EVENT_NAME "]. Map (función (elem) {return elem.handler;});' UnEught TypeError: no se puede leer la propiedad 'EVENT_NAME' de undefined en : 1: 62 –

+0

''ct100_ContentPlaceHolder1_lcsSection'' es una cadena, no un elemento DOM. –

2

Debo decir que muchas de las respuestas son interesantes, pero recientemente tuve un problema similar y la solución fue extremadamente simple yendo por el camino DOM. Es diferente porque no iteras, sino que apuntas directamente al evento que necesitas, pero a continuación daré una respuesta más general.

que tenían una imagen en una fila:

<table> 
    <td><tr><img class="folder" /></tr><tr>...</tr></td> 
</table> 

Y esa imagen tenía un controlador de eventos click que se le atribuye:

imageNode.click(function() { ... }); 

Mi intención era ampliar el área seleccionable a toda la fila , así que me dieron todas las imágenes primera y filas relativos:

tableNode.find("img.folder").each(function() { 
    var tr; 

    tr = $(this).closest("tr"); 
    // <-- actual answer 
}); 

Ahora en el real de la línea anwer acabo de hacer de la siguiente manera, de dar una respuesta a la pregunta original:

tr.click(this.onclick); 

Así que fue a buscar el controlador de eventos directamente desde el elemento DOM y ponerlo en el jQuery clic controlador de eventos. Funciona de maravilla.

Ahora, para el caso general. En los viejos tiempos pre-jQuery usted podría conseguir todos los eventos asociados a un objeto con dos funciones simples pero poderosas dotados a los mortales por Douglas Crockford:

function walkTheDOM(node, func) 
{ 
    func(node); 
    node = node.firstChild; 
    while (node) 
    { 
    walkTheDOM(node, func); 
    node = node.nextSibling; 
    } 
} 

function purgeEventHandlers(node) 
{ 
    walkTheDOM(node, function (n) { 
    var f; 

    for (f in n) 
    { 
     if (typeof n[f] === "function") 
     { 
     n[f] = null; 
     } 
    } 
    }); 
} 
8

He combinado de ambas soluciones @jps a uno función:

jQuery.fn.getEvents = function() { 
    if (typeof(jQuery._data) == 'function') { 
     return jQuery._data(this.get(0), 'events') || {}; 
    } else if (typeof(this.data) == 'function') { // jQuery version < 1.7.? 
     return this.data('events') || {}; 
    } 
    return {}; 
}; 

Pero tenga en cuenta que esta función solo puede devolver los eventos que se establecieron con jQuery.

1

Otra forma de hacerlo es simplemente utilizar jQuery para tomar el elemento, luego pasar por el Javascript real para obtener y configurar y jugar con los controladores de eventos. Por ejemplo:

var oldEventHandler = $('#element')[0].onclick; 
// Remove event handler 
$('#element')[0].onclick = null; 
// Switch it back 
$('#element')[0].onclick = oldEventHandler; 
+0

Creo que jQuery optimiza el manejo de eventos, lo que creo que está eludido por su código aquí. –

+0

Gracias, sí. Tenía la sensación de que esto era raro. ¿Algún buen enlace para obtener más información sobre esa optimización? – tempranova

+0

No recuerdo dónde lo leí y no puedo encontrarlo ahora ... –

1

creé un selector personalizado jQuery que comprueba contra el caché de controladores de eventos asignados de tanto jQuery, así como los elementos que utilizan el nativo método para la adición de ellos:

(function($){ 

    $.find.selectors[":"].event = function(el, pos, match) { 

     var search = (function(str){ 
      if (str.substring(0,2) === "on") {str = str.substring(2);} 
      return str; 
     })(String(match[3]).trim().toLowerCase()); 

     if (search) { 
      var events = $._data(el, "events"); 
      return ((events && events.hasOwnProperty(search)) || el["on"+search]); 
     } 

     return false; 

    }; 

})(jQuery); 

Ejemplo:

$(":event(click)") 

Esto devolverá los elementos que tengan un manejador de clics asociado.

Cuestiones relacionadas