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énementssont attachés en utilisant:
- Prototype
Event.observe
; - DOM
addEventListener
; - comme attribut d'élément
element.onclick
.
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";
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!') }" })
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
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.
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.
(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...
- Événement Visuel
- 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.
utiliser getEventListeners dans Google Chrome 151930920":
getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));
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).
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
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);
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)
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
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];
}
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>
Il existe de nice jQuery Événements extension :
(topic source )
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.
Le Codepeut ê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");
});
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.