Comment trouver des écouteurs d'événements sur un noeud DOM lors du débogage ou à partir du code JavaScript?

j'ai une page où certains écouteurs d'événements sont attachés à des boîtes de saisie et à des boîtes de sélection. Y a-t-il un moyen de savoir quels écouteurs d'événements observent un noeud DOM particulier et pour quel événement?

Les événements

sont attachés en utilisant:

  1. Prototype Event.observe ;
  2. DOM addEventListener ;
  3. comme attribut d'élément element.onclick .
714
demandé sur Peter Mortensen 2009-01-15 17:19:44

17 réponses

si vous avez juste besoin d'inspecter ce qui se passe sur une page, vous pouvez essayer le événement visuel bookmarklet.

mise à Jour : Visual Event 2 "151920920 disponible";

469
répondu Andrew Hedges 2012-08-10 08:52:35

Cela dépend de la façon dont les événements sont attachés. Pour l'illustration présumons que nous avons le gestionnaire de clic suivant:

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

nous allons l'attacher à notre élément en utilisant différentes méthodes, certaines qui permettent l'inspection et d'autres pas.

la Méthode A) seul gestionnaire d'événement

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

Méthode B) manipulateurs d'événements multiples

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éthode 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 (stocke le gestionnaire à l'intérieur d'un objet)

    // 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
    })
    

(voir jQuery.fn.data et jQuery.data )

méthode D): Prototype (messy)

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

    // inspect
    Event.observers.each(function(item) {
        if(item[0] == element) {
            alert(item[2]) // alerts "function() { alert('clicked!') }"
        }
    })
    
  • de 1,6 à 1.6.0.3, inclusive (a été très difficile ici)

    // 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 (peu mieux)

    // inspect
    var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
    clickEvents.each(function(wrapper){
        alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
    })
    
346
répondu Crescent Fresh 2010-03-04 15:50:45

Chrome, Firefox, Vivaldi et Safari prennent en charge getEventListeners(domElement) dans leur console D'outils de développement.

pour la plupart des fins de débogage, ceci pourrait être utilisé.

ci-Dessous est une très bonne référence de l'utiliser: https://developers.google.com/chrome-developer-tools/docs/commandline-api#geteventlistenersobject

214
répondu Raghav 2017-02-05 19:33:41

WebKit Inspector dans les navigateurs Chrome ou Safari fait maintenant cela. Il affichera les écouteurs d'événements pour un élément DOM lorsque vous le sélectionnez dans le volet Elements.

82
répondu Ishan 2011-01-17 07:39:55

il est possible de lister tous les écouteurs d'événements en JavaScript: ce n'est pas si difficile; il suffit de hacker la méthode prototype des éléments HTML ( avant ajout des écouteurs).

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});
};

maintenant chaque élément d'ancrage ( a ) aura une propriété lastListenerInfo qui contient tous ses auditeurs. Et il fonctionne même pour enlever les écouteurs avec des fonctions anonymes.

62
répondu Ivan Castellanos 2012-07-30 00:11:42

(Réécriture de la réponse de cette question puisque c'est d'actualité ici.)

lors du débogage, si vous voulez simplement voir les événements, je vous recommande l'un ou l'autre...

  1. Événement Visuel
  2. la section Elements des outils de développement de Chrome: sélectionnez un élément et recherchez "event Listeners" en bas à droite (similaire à Firefox)

si vous voulez utiliser les événements dans votre code, et vous utilisez jQuery avant la version 1.8 , vous pouvez utiliser:

$(selector).data("events")

pour avoir les évènements. depuis la version 1.8, en utilisant .les données ("événements") sont discontinuées (voir ce ticket de bug ). Vous pouvez utiliser:

$._data(element, "events")

un autre exemple: écrire tous les événements de clic sur un certain lien vers la console:

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

(voir http://jsfiddle.net/HmsQC/ pour un exemple)

malheureusement, utilisant $._data ceci n'est pas recommandé sauf pour le débogage car il s'agit d'une structure jQuery interne, et pourrait changer dans les versions futures. Malheureusement, je ne connais pas d'autre moyen facile d'accéder aux événements.

38
répondu Luke 2017-05-23 11:47:29

utiliser getEventListeners dans Google Chrome 151930920":

getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));
29
répondu Pranay Soni 2018-04-03 23:32:26

1: Prototype.observe utilise un élément.addEventListener (voir le code source )

2: Vous pouvez remplacer Element.addEventListener par Element.addEventListener pour vous souvenir des écouteurs ajoutés (la propriété EventListenerList de handy a été retirée de la proposition de DOM3 spec). Exécutez ce code avant que n'importe quel événement est attaché:

(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);
  };
})();

lire tous les événements par:

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

Et n'oubliez pas de remplacer Element.removeEventListener pour supprimer l'événement la coutume Element.eventListenerList .

3: la Element.onclick propriété nécessite une attention particulière ici:

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

4: n'oubliez pas l'attribut Element.onclick content: ce sont deux choses différentes:

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

donc vous devez le manipuler, aussi:

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

L'Événement Visuel bookmarklet (mentionné dans la réponse la plus populaire) seulement s'empare de la bibliothèque personnalisés du gestionnaire de cache:

il s'avère qu'il n'y a pas de méthode standard fournie par le W3C interface DOM recommandée pour connaître les écouteurs d'événements attaché à un élément particulier. C'est peut-être un surveillance, il a été proposé d'inclure un bien appelé eventListenerList à la spécification DOM de niveau 3, mais était malheureusement a été supprimé dans les versions ultérieures. En tant que tel, nous sommes forcés de a examiné les bibliothèques Javascript individuelles, qui typiquement maintenir un cache d'événements attachés (de sorte qu'ils puissent plus tard être enlevés et effectuer d'autres abstractions).

en tant que tel, pour Qu'un événement visuel puisse montrer des événements, il doit pouvoir analysez les informations sur l'événement à partir D'une bibliothèque Javascript.

élément dominant peut être discutable (i.e. parce qu'il ya certaines caractéristiques spécifiques DOM comme les collections en direct, qui ne peut pas être codé dans JS), mais il donne l'eventListenerList soutenez nativement et cela fonctionne dans Chrome, Firefox et Opera (ne fonctionne pas dans IE7).

23
répondu Jan Turoň 2015-06-27 10:05:40

vous pourriez envelopper les méthodes DOM natives pour la gestion des écouteurs d'événements en mettant ceci au sommet de votre <head> :

<script>
    (function(w){
        var originalAdd = w.addEventListener;
        w.addEventListener = function(){
            // add your own stuff here to debug
            return originalAdd.apply(this, arguments);
        };

        var originalRemove = w.removeEventListener;
        w.removeEventListener = function(){
            // add your own stuff here to debug
            return originalRemove.apply(this, arguments);
        };
    })(window);
</script>

h / t @les2

21
répondu Jon z 2015-11-06 17:49:11

Firefox developer tools. Les événements sont affichés en cliquant sur le bouton" ev "à droite de l'écran de chaque élément, y compris les événements jQuery et DOM .

Screenshot of Firefox developer tools' event listener button in the inspector tab

17
répondu simonzack 2016-09-29 17:43:30

si vous avez coupe-feu , vous pouvez utiliser console.dir(object or array) pour imprimer un bel arbre dans le journal de la console de n'importe quel scalaire, tableau ou objet JavaScript.

, Essayez:

console.dir(clickEvents);

ou

console.dir(window);
12
répondu Michael Butler 2016-09-29 17:41:42

Opera 12 (pas le dernier moteur de Webkit Chrome) Dragonfly a eu cela pendant un certain temps et est évidemment affiché dans la structure DOM. À mon avis, c'est un débogueur supérieur et c'est la seule raison pour laquelle j'utilise toujours la version basée sur Opera 12 (Il n'y a pas de version v13, V14 et la version basée sur le Webkit v15 n'a pas de Dragonfly still)

enter image description here

7
répondu Daniel Sokolowski 2013-11-28 16:30:26

solution entièrement fonctionnelle basée sur réponse de Jan Turon - se comporte comme getEventListeners() de la console:

(il y a un petit bug avec des doublons. Il ne casse pas beaucoup de toute façon.)

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._addEventListener(a,b,c);
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(!this.eventListenerList[a])
      this.eventListenerList[a] = [];
    //this.removeEventListener(a,b,c); // TODO - handle duplicates..
    this.eventListenerList[a].push({listener:b,useCapture:c});
  };

  Element.prototype.getEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined)
      return this.eventListenerList;
    return this.eventListenerList[a];
  };
  Element.prototype.clearEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined){
      for(var x in (this.getEventListeners())) this.clearEventListeners(x);
        return;
    }
    var el = this.getEventListeners(a);
    if(el==undefined)
      return;
    for(var i = el.length - 1; i >= 0; --i) {
      var ev = el[i];
      this.removeEventListener(a, ev.listener, ev.useCapture);
    }
  };

  Element.prototype._removeEventListener = Element.prototype.removeEventListener;
  Element.prototype.removeEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._removeEventListener(a,b,c);
      if(!this.eventListenerList)
        this.eventListenerList = {};
      if(!this.eventListenerList[a])
        this.eventListenerList[a] = [];

      // Find the event in the list
      for(var i=0;i<this.eventListenerList[a].length;i++){
          if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
              this.eventListenerList[a].splice(i, 1);
              break;
          }
      }
    if(this.eventListenerList[a].length==0)
      delete this.eventListenerList[a];
  };
})();

Utilisation:

someElement.getEventListeners([name]) - retour à la liste des écouteurs d'événement, si le nom est de retour tableau des auditeurs pour l'événement

someElement.clearEventListeners([name]) - supprimer tous les écouteurs d'événements, si le nom est défini uniquement supprimer les écouteurs pour cet événement

7
répondu n00b 2017-05-23 12:26:38

Prototype 1.7.1 façon

function get_element_registry(element) {
    var cache = Event.cache;
    if(element === window) return 0;
    if(typeof element._prototypeUID === 'undefined') {
        element._prototypeUID = Element.Storage.UID++;
    }
    var uid =  element._prototypeUID;           
    if(!cache[uid]) cache[uid] = {element: element};
    return cache[uid];
}
4
répondu Ronald 2013-01-17 17:28:55

j'essaie de le faire dans jQuery 2.1, et avec la méthode $().click() -> $(element).data("events").click; " ça ne marche pas.

j'ai réalisé que seuls les $._data() fonctionne dans mon cas :

	$(document).ready(function(){

		var node = $('body');
		
        // Bind 3 events to body click
		node.click(function(e) { alert('hello');  })
			.click(function(e) { alert('bye');  })
			.click(fun_1);

        // Inspect the events of body
		var events = $._data(node[0], "events").click;
		var ev1 = events[0].handler // -> function(e) { alert('hello')
		var ev2 = events[1].handler // -> function(e) { alert('bye')
		var ev3 = events[2].handler // -> function fun_1()
        
		$('body')
			.append('<p> Event1 = ' + eval(ev1).toString() + '</p>')
			.append('<p> Event2 = ' + eval(ev2).toString() + '</p>')
			.append('<p> Event3 = ' + eval(ev3).toString() + '</p>');        
	
	});

	function fun_1() {
		var txt = 'text del missatge';	 
		alert(txt);
	}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
</body>
2
répondu Joel Barba 2015-05-19 09:00:35

Il existe de nice jQuery Événements extension :

enter image description here (topic source )

1
répondu T.Todua 2017-05-23 12:34:45

je travaillais récemment avec des événements et je voulais voir/contrôler tous les événements dans une page. Après avoir examiné les solutions possibles, j'ai décidé d'avoir mon propre chemin et de créer un système personnalisé pour surveiller les événements. Donc, j'ai fait trois choses.

tout d'abord, j'avais besoin d'un conteneur pour tous les écouteurs d'événements de la page: c'est l'objet EventListeners . Il a trois méthodes utiles: add() , remove() , et get() .

ensuite, j'ai créé un EventListener objet pour contenir les informations nécessaires pour l'événement, c'est à dire: target , type , callback , options , useCapture , wantsUntrusted , et ajouté une méthode remove() pour supprimer l'auditeur.

enfin, j'ai étendu les méthodes natives addEventListener() et removeEventListener() pour les faire fonctionner avec les objets que j'ai créés ( EventListener et EventListeners ).

Utilisation:

var bodyClickEvent = document.body.addEventListener("click", function () {
    console.log("body click");
});

// bodyClickEvent.remove();

addEventListener() crée un objet EventListener , l'ajoute à EventListeners et renvoie l'objet EventListener , de sorte qu'il peut être supprimé plus tard.

EventListeners.get() peut être utilisé pour voir les auditeurs dans la page. Il accepte une EventTarget ou une chaîne de caractères (type d'événement).

// EventListeners.get(document.body);
// EventListeners.get("click");

Démo

disons que nous voulons savoir tous les écouteurs d'événements dans cette page actuelle. Nous pouvons le faire cela (en supposant que vous utilisez une extension script manager, Tampermonkey dans ce cas). Le script suivant fait ceci:

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include      https://stackoverflow.com/*
// @grant        none
// ==/UserScript==

(function() {
    fetch("https://raw.githubusercontent.com/akinuri/js-lib/master/EventListener.js")
        .then(function (response) {
            return response.text();
        })
        .then(function (text) {
            eval(text);
            window.EventListeners = EventListeners;
        });
})(window);

et quand nous lisons tous les auditeurs, il est dit qu'il y a 299 auditeurs d'événements. Il semble y avoir des doubles, mais je ne sais pas si ce sont vraiment des doubles. Tous les types d'événements ne sont pas dupliqués, donc tous ces "dupliqués" pourraient être un auditeur individuel.

screenshot of console listing all event listeners in this page

Le Code

peut être trouvé dans mon dépôt . Je ne voulais pas le poster ici parce qu'il est assez long.


mise à jour: cela ne semble pas fonctionner avec jQuery. Quand j'examine L'Eventilistener, je vois que le rappel est

function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}

je crois que ceci appartient à jQuery, et n'est pas le vrai rappel. jQuery stocke le rappel réel dans le propriétés de L'EventTarget:

$(document.body).click(function () {
    console.log("jquery click");
});

enter image description here

pour supprimer un écouteur d'événement, le rappel réel doit être passé à la méthode removeEventListener() . Donc, pour que cela fonctionne avec jQuery, il faut le modifier davantage. Je pourrais corriger cela dans l'avenir.

0
répondu akinuri 2018-06-28 10:33:33