Pregunta ¿Cómo encontrar detectores de eventos en un nodo DOM al depurar o desde el código JavaScript?


Tengo una página donde algunos oyentes de eventos están conectados a cuadros de entrada y cuadros de selección. ¿Hay alguna manera de averiguar qué eventos oyentes están observando un nodo DOM específico y para qué evento?

Los eventos se adjuntan utilizando:

  1. Prototipo  Event.observe;
  2. DOM addEventListener;
  3. Como atributo de elemento element.onclick.

706
2018-01-15 14:19


origen


Respuestas:


Si solo necesita inspeccionar lo que sucede en una página, puede intentar Evento visual bookmarklet.

Actualizar: Evento visual 2 disponible;


469
2017-08-06 17:48



Depende de cómo se adjunten los eventos. Para la ilustración supongo que tenemos el siguiente controlador de clics:

var handler = function() { alert('clicked!') };

Vamos a adjuntarlo a nuestro elemento utilizando diferentes métodos, algunos que permiten la inspección y otros que no.

Método A) manejador de evento único

element.onclick = handler;
// inspect
alert(element.onclick); // alerts "function() { alert('clicked!') }"

Método B) controladores de eventos múltiples

if(element.addEventListener) { // DOM standard
    element.addEventListener('click', handler, false)
} else if(element.attachEvent) { // IE
    element.attachEvent('onclick', handler)
}
// cannot inspect element to find handlers

Método C): jQuery

$(element).click(handler);
  • 1.3.x

    // inspect
    var clickEvents = $(element).data("events").click;
    jQuery.each(clickEvents, function(key, value) {
        alert(value) // alerts "function() { alert('clicked!') }"
    })
    
  • 1.4.x (almacena el controlador dentro de un objeto)

    // inspect
    var clickEvents = $(element).data("events").click;
    jQuery.each(clickEvents, function(key, handlerObj) {
        alert(handlerObj.handler) // alerts "function() { alert('clicked!') }"
        // also available: handlerObj.type, handlerObj.namespace
    })
    

(Ver jQuery.fn.data y jQuery.data)

Método D): Prototipo (desordenado)

$(element).observe('click', handler);
  • 1.5.x

    // inspect
    Event.observers.each(function(item) {
        if(item[0] == element) {
            alert(item[2]) // alerts "function() { alert('clicked!') }"
        }
    })
    
  • 1.6 a 1.6.0.3, inclusive (se puso muy difícil aquí)

    // inspect. "_eventId" is for < 1.6.0.3 while 
    // "_prototypeEventID" was introduced in 1.6.0.3
    var clickEvents = Event.cache[element._eventId || (element._prototypeEventID || [])[0]].click;
    clickEvents.each(function(wrapper){
        alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
    })
    
  • 1.6.1 (poco mejor)

    // inspect
    var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
    clickEvents.each(function(wrapper){
        alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
    })
    

346
2018-01-15 15:13



Compatibilidad con Chrome, Firefox, Vivaldi y Safari getEventListeners(domElement) en su consola de Developer Tools.

Para la mayoría de los propósitos de depuración, esto podría ser utilizado.

A continuación hay una muy buena referencia para usarlo: https://developers.google.com/chrome-developer-tools/docs/commandline-api#geteventlistenersobject


203
2018-05-14 13:40



WebKit Inspector en los navegadores Chrome o Safari ahora lo hace. Mostrará los detectores de eventos para un elemento DOM cuando lo seleccione en el panel Elementos.


81
2018-01-17 07:39



Es posible enumerar todos los oyentes del evento en JavaScript: no es tan difícil; solo tienes que hackear el prototypemétodo de los elementos HTML (antes de agregando los oyentes).

function reportIn(e){
    var a = this.lastListenerInfo[this.lastListenerInfo.length-1];
    console.log(a)
}


HTMLAnchorElement.prototype.realAddEventListener = HTMLAnchorElement.prototype.addEventListener;

HTMLAnchorElement.prototype.addEventListener = function(a,b,c){
    this.realAddEventListener(a,reportIn,c); 
    this.realAddEventListener(a,b,c); 
    if(!this.lastListenerInfo){  this.lastListenerInfo = new Array()};
    this.lastListenerInfo.push({a : a, b : b , c : c});
};

Ahora cada elemento de anclaje (a) tendrá un lastListenerInfo propiedad que contiene a todos sus oyentes. E incluso funciona para eliminar oyentes con funciones anónimas.


61
2018-06-22 04:32



(Reescribiendo la respuesta de esta pregunta ya que es relevante aquí).

Al depurar, si solo quieres ver los eventos, te recomiendo ...

  1. Evento visual
  2. los Elementos sección de Herramientas para desarrolladores de Chrome: seleccione un elemento y busque "Escuchadores de eventos" en la esquina inferior derecha (similar en Firefox)

Si desea usar los eventos en su código, y está usando jQuery antes de la versión 1.8, puedes usar:

$(selector).data("events")

para obtener los eventos. A partir de la versión 1.8, el uso de .data ("eventos") se suspende (ver este boleto error) Puedes usar:

$._data(element, "events")

Otro ejemplo: escriba todos los eventos de clic en un cierto enlace a la consola:

var $myLink = $('a.myClass');
console.log($._data($myLink[0], "events").click);

(ver http://jsfiddle.net/HmsQC/ para un ejemplo de trabajo)

Desafortunadamente, usando datos $ ._ esto no es recomendable a excepción de la depuración, ya que es una estructura jQuery interna, y podría cambiar en versiones futuras. Lamentablemente, no conozco ningún otro medio fácil de acceder a los eventos.


38
2017-10-22 19:04



Use getEventListeners en Google Chrome:

getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));

26
2018-03-19 09:30



1: Prototype.observe usa Element.addEventListener (ver el código fuente)

2: puede anular Element.addEventListener recordar los oyentes añadidos (propiedad útil) EventListenerList fue eliminado de la propuesta de especificación DOM3). Ejecute este código antes de adjuntar cualquier evento:

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    this._addEventListener(a,b,c);
    if(!this.eventListenerList) this.eventListenerList = {};
    if(!this.eventListenerList[a]) this.eventListenerList[a] = [];
    this.eventListenerList[a].push(b);
  };
})();

Lea todos los eventos por:

var clicks = someElement.eventListenerList.click;
if(clicks) clicks.forEach(function(f) {
  alert("I listen to this function: "+f.toString());
});

Y no te olvides de anular Element.removeEventListener para eliminar el evento de la costumbre Element.eventListenerList.

3: el Element.onclick la propiedad necesita cuidados especiales aquí:

if(someElement.onclick)
  alert("I also listen tho this: "+someElement.onclick.toString());

4: no olvides el Element.onclick atributo de contenido: estas son dos cosas diferentes:

someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute

Entonces debes manejarlo también:

var click = someElement.getAttribute("onclick");
if(click) alert("I even listen to this: "+click);

El marcador de evento visual (mencionado en la respuesta más popular) solo roba el caché de controlador de biblioteca personalizado:

Resulta que no hay un método estándar proporcionado por el W3C   interfaz de DOM recomendada para descubrir qué eventos son los oyentes   unido a un elemento particular. Si bien esto puede parecer un   supervisión, hubo una propuesta para incluir una propiedad llamada   eventListenerList a la especificación DOM nivel 3, pero fue   lamentablemente se eliminó en los borradores posteriores. Como tal, nos vemos obligados a   miró las bibliotecas individuales de Javascript, que típicamente   mantener un caché de eventos adjuntos (para que luego puedan eliminarse y   realizar otras abstracciones útiles).

Como tal, para que Evento Visual muestre eventos, debe ser capaz de   analizar la información del evento de una biblioteca Javascript.

La anulación de elementos puede ser cuestionable (es decir, porque hay algunas características específicas de DOM como colecciones en vivo, que no se pueden codificar en JS), pero da soporte de forma nativa a eventListenerList y funciona en Chrome, Firefox y Opera (no funciona en IE7 )


22
2018-04-03 15:08