jQuery buscar controladores de eventos registrados con un objeto


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

Por ejemplo:

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

$("#el") tiene pulse y mouseover registrado.

¿Hay una función para averiguar eso, y posiblemente iterar sobre los controladores de eventos?

Si no es posible en un objeto jQuery a través de métodos adecuados, ¿es posible en un objeto DOM sencillo?

Author: Ian, 2010-03-25

14 answers

A partir de jQuery 1.8, los datos de eventos ya no están disponibles desde la "API pública" para datos. Leer esta entrada de blog de jQuery. Ahora deberías usar esto en su lugar:

jQuery._data( elem, "events" );

elem debe ser un elemento HTML, no un objeto jQuery, o selector.

Tenga en cuenta que esta es una estructura interna, 'privada', y no debe modificarse. Utilice esto solo para fines de depuración.

En versiones anteriores de jQuery, es posible que tenga que usar el método antiguo que es:

jQuery( elem ).data( "events" );
 627
Author: jps,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-10 17:15:09

Puedes hacerlo así:

$("#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á en jQuery 1.4+, esto alertará al evento y las funciones vinculadas a él:

$.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"); }'

Puedes jugar con él en jsFiddle aquí

 75
Author: Nick Craver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-25 20:34:04

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

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

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

 36
Author: PhistucK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-12 15:09:08

Shameless plug, pero se puede utilizar findHandlerJS

Para usarlo solo tienes que incluir findHandlersJS (o simplemente copiar y pegar el código javascript raw en la ventana de la consola de chrome) y especificar el tipo de evento y un selector jquery para los elementos que te interesan.

Para su ejemplo, puede encontrar rápidamente los controladores de eventos que mencionó haciendo

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

Esto es lo que se devuelve:

  • elemento
    Real elemento donde se registró el controlador de eventos en
  • eventos
    Array con información sobre los controladores de eventos de jquery para el tipo de evento que nos interesa (por ejemplo, clic, cambio, etc)
    • controlador
      Método de controlador de eventos real que puede ver haciendo clic derecho en él y seleccionando Mostrar definición de función
    • selector
      El selector proporcionado para eventos delegados. Estará vacío para eventos directos.
    • objetivos
      Lista con los elementos que este controlador de eventos se dirige. Por ejemplo, para un controlador de eventos delegado registrado en el objeto document y dirigido a todos los botones de una página, esta propiedad mostrará una lista de todos los botones de la página. Puede pasar el ratón sobre ellos y verlos resaltados en Chrome.

Puedes probarlo aquí

 29
Author: Rui,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-13 16:44:04

Utilizo eventbug plugin para firebug para este propósito.

 13
Author: Anton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-26 06:10:30

He combinado ambas soluciones de @jps a una 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 cuidado, esta función solo puede devolver los eventos que se configuraron con jQuery.

 8
Author: algorhythm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-14 23:20:10

A partir de la versión 1.9 no hay ninguna forma documentada de recuperar los eventos, aparte de utilizar el plugin Migrate para restaurar el comportamiento anterior. Podrías usar el _.método data () como menciona jps, pero es un método interno. Así que haz lo correcto y usa el plugin Migrate si necesitas esta funcionalidad.

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

Antes de 1.9, .datos ("eventos") podrían ser utilizados para recuperar jQuery estructura interna de datos de eventos no documentada para elemento si no hay otro code había definido un elemento de datos con el nombre "events". Este especial se ha eliminado el caso en 1.9. No hay interfaz pública para recuperar esta estructura de datos internos, y sigue siendo indocumentada. Obstante, el complemento jQuery Migrate restaura este comportamiento para el código que depende sobre ello.

 6
Author: oligofren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-27 10:06:45

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

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

En la consola de su navegador, que imprimirá el origen de los controladores, delimitado por comas. Útil para echar un vistazo a lo que todo se está ejecutando en un evento en particular.

 3
Author: Jesan Fafon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-10 16:04:01

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

Tenía una imagen en fila:

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

Y esa imagen tenía un controlador de eventos de clic adjunto:

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

Mi intención era expandir el área clicable a toda la fila, así que primero obtuve todas las imágenes y filas relativas:

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

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

Ahora en la línea actual anwer acabo de hacer lo siguiente, dando una respuesta a la pregunta original:

tr.click(this.onclick);

Así que busqué el controlador de eventos directamente desde el elemento DOM y lo puse en el controlador de eventos jQuery click. Funciona como un encanto.

Ahora, al caso general. En los viejos días previos a jQuery, se podían asociar todos los eventos a un objeto con dos funciones simples pero poderosas que nos regaló 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;
      }
    }
  });
}
 2
Author: pid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-14 14:49:50

Los eventos se pueden recuperar usando:

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

O jQuery 1.8+:

jQuery._data(elem, 'events');

Nota: Eventos acotados usando $('selector').live('event', handler) puede ser recuperado usando:

jQuery(document).data('events')
 2
Author: R. Oosterholt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-03 15:03:26

He creado un selector de jQuery personalizado que comprueba tanto la caché de jQuery de controladores de eventos asignados como los elementos que utilizan el método nativo para agregarlos:

(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 tienen un controlador de clics adjunto a ellos.

 2
Author: Erutan409,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-07 19:40:09

Otra forma de hacerlo es simplemente usar jQuery para agarrar el elemento, luego pasar por Javascript real para obtener y establecer 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;
 1
Author: tempranova,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-06 09:32:48
 0
Author: Marquinho Peli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-15 15:32:47

Para comprobar si hay eventos en un elemento:

var events = $._data(element, "events")

Tenga en cuenta que esto solo funcionará con controladores de eventos directos, si está utilizando $(document).on ("event-name", "jq-selector", function() { //logic}), querrá ver la función GetEvents en la parte inferior de esta respuesta

Por ejemplo:

 var events = $._data(document.getElementById("myElemId"), "events")

O

 var events = $._data($("#myElemId")[0], "events")

Ejemplo Completo:

<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
        <script>
            $(function() {
                $("#textDiv").click(function() {
                    //Event Handling
                });
                var events = $._data(document.getElementById('textDiv'), "events");
                var hasEvents = (events != null);
            });
        </script>
    </head>
    <body>
        <div id="textDiv">Text</div>
    </body>
</html>

Una forma más completa de comprobar, que incluye oyentes dinámicos, instalado con $(document).el

function getEvents(element) {
    var elemEvents = $._data(element, "events");
    var allDocEvnts = $._data(document, "events");
    for(var evntType in allDocEvnts) {
        if(allDocEvnts.hasOwnProperty(evntType)) {
            var evts = allDocEvnts[evntType];
            for(var i = 0; i < evts.length; i++) {
                if($(element).is(evts[i].selector)) {
                    if(elemEvents == null) {
                        elemEvents = {};
                    }
                    if(!elemEvents.hasOwnProperty(evntType)) {
                        elemEvents[evntType] = [];
                    }
                    elemEvents[evntType].push(evts[i]);
                }
            }
        }
    }
    return elemEvents;
}

Ejemplo de uso:

getEvents($('#myElemId')[0])
 0
Author: Tom G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-30 15:39:11