Obtenir des écouteurs d'événements attachés au nœud à l'aide de addEventListener

106

J'ai déjà examiné ces questions:

cependant aucun d'entre eux ne répond comment obtenir une liste d'écouteurs d'événements attachés à un nœud en utilisant addEventListener, sans modifier le addEventListenerprototype avant la création des écouteurs d'événements.

VisualEvent n'affiche pas tous les écouteurs d'événements (spécifiques à l'iphone) et je veux le faire (un peu) par programme.

Tyilo
la source
"quelque peu par programme" et le fait que la réponse acceptée pour cette question soit une fonctionnalité de devtools en fait un double de la question listée. Pour ceux qui recherchent une solution JS, la réponse est «il n'y en a pas»
Nickolay

Réponses:

135

Chrome DevTools, Safari Inspector et Firebug prennent en charge getEventListeners (nœud) .

getEventListeners (document)

NVI
la source
6
Je tiens à noter que la méthode getEventListeners ne prend pas en charge la version Firefox 35.
MURATSPLAT
Cela peut ne pas fonctionner sur Firefox, mais là encore les développeurs se développent sur plusieurs navigateurs / Cela AIDE bien sûr si l'on a besoin de modifier un site existant ... BEAUCOUP!
JasonXA
1
Not it Firefox 69.
Vitaly Zdanevich
65

Vous ne pouvez pas.

La seule façon d'obtenir une liste de tous les écouteurs d'événements attachés à un nœud est d'intercepter l'appel de pièce jointe d'écouteur.

DOM4 addEventListener

Dit

Ajoutez un écouteur d'événement à la liste associée d'écouteurs d'événements avec le type défini sur type, l'écouteur défini sur écouteur et la capture définie sur capture, sauf s'il existe déjà un écouteur d'événement dans cette liste avec le même type, écouteur et capture.

Cela signifie qu'un écouteur d'événements est ajouté à la "liste des écouteurs d'événements". C'est tout. Il n'y a aucune notion de ce que devrait être cette liste ni de la façon dont vous devriez y accéder.

Raynos
la source
12
Une chance de fournir une justification ou un raisonnement pour expliquer pourquoi cela doit fonctionner de cette façon? Il est clair que le navigateur sait ce que sont tous les auditeurs.
Darth Egregious
3
@ user973810: Comment voulez-vous qu'il justifie cela? L'API DOM ne fournit aucun moyen de le faire et il n'y a pas de moyens non standard de le faire dans les navigateurs actuels. Quant à savoir pourquoi c'est le cas, je ne sais pas vraiment. Il semble raisonnable de vouloir faire.
Tim Down
J'ai vu quelques threads traîner sur l'ajout d'une API au DOM pour cela.
Raynos
@TimDown, la modification aide. Voir qu'il n'y a pas de spécification pour quelque chose comme "getEventListeners" justifie pourquoi il n'y a pas une telle chose.
Darth Egregious
24

Puisqu'il n'y a pas de moyen natif de le faire, voici la solution moins intrusive que j'ai trouvée (n'ajoutez aucune méthode de prototype `` ancienne ''):

var ListenerTracker=new function(){
    var is_active=false;
    // listener tracking datas
    var _elements_  =[];
    var _listeners_ =[];
    this.init=function(){
        if(!is_active){//avoid duplicate call
            intercep_events_listeners();
        }
        is_active=true;
    };
    // register individual element an returns its corresponding listeners
    var register_element=function(element){
        if(_elements_.indexOf(element)==-1){
            // NB : split by useCapture to make listener easier to find when removing
            var elt_listeners=[{/*useCapture=false*/},{/*useCapture=true*/}];
            _elements_.push(element);
            _listeners_.push(elt_listeners);
        }
        return _listeners_[_elements_.indexOf(element)];
    };
    var intercep_events_listeners = function(){
        // backup overrided methods
        var _super_={
            "addEventListener"      : HTMLElement.prototype.addEventListener,
            "removeEventListener"   : HTMLElement.prototype.removeEventListener
        };

        Element.prototype["addEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["addEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            useCapture=useCapture?1:0;

            if(!listeners[useCapture][type])listeners[useCapture][type]=[];
            listeners[useCapture][type].push(listener);
        };
        Element.prototype["removeEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["removeEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            useCapture=useCapture?1:0;
            if(!listeners[useCapture][type])return;
            var lid = listeners[useCapture][type].indexOf(listener);
            if(lid>-1)listeners[useCapture][type].splice(lid,1);
        };
        Element.prototype["getEventListeners"]=function(type){
            var listeners=register_element(this);
            // convert to listener datas list
            var result=[];
            for(var useCapture=0,list;list=listeners[useCapture];useCapture++){
                if(typeof(type)=="string"){// filtered by type
                    if(list[type]){
                        for(var id in list[type]){
                            result.push({"type":type,"listener":list[type][id],"useCapture":!!useCapture});
                        }
                    }
                }else{// all
                    for(var _type in list){
                        for(var id in list[_type]){
                            result.push({"type":_type,"listener":list[_type][id],"useCapture":!!useCapture});
                        }
                    }
                }
            }
            return result;
        };
    };
}();
ListenerTracker.init();
Yorg
la source
Vous devriez également le faire intercepter les écouteurs d'événements de fenêtre. A part ça, cela fonctionne très bien!
2

Vous pouvez obtenir tous les événements jQuery en utilisant $ ._ data ($ ('[selector]') [0], 'events'); changez le [sélecteur] en fonction de vos besoins.

Il existe un plugin qui rassemble tous les événements attachés par jQuery appelé eventsReport.

J'écris également mon propre plugin qui le fait avec un meilleur formatage.

Mais de toute façon, il semble que nous ne pouvons pas rassembler les événements ajoutés par la méthode addEventListener. Peut-être pouvons-nous encapsuler l'appel addEventListener pour stocker les événements ajoutés après notre appel wrap.

Cela semble être le meilleur moyen de voir les événements ajoutés à un élément avec des outils de développement.

Mais vous n'y verrez pas d'événements délégués. Nous avons donc besoin de jQuery eventsReport.

MISE À JOUR: NOW Nous POUVONS voir les événements ajoutés par la méthode addEventListener VOIR LA BONNE RÉPONSE À CETTE QUESTION.

Rantiev
la source
Il s'agit d'une interface privée et obsolète et elle pourrait bientôt disparaître, alors ne vous fiez pas à cela.
mgol
1
Oui, mais au moment où j'ai répondu, il n'y avait pas une telle capacité dans les outils de développement. Donc, il n'y avait rien à choisir.
Rantiev
Elle est obsolète @Rantiev, pouvez-vous supprimer cette réponse?
Julio Marins
2

Je ne trouve pas de moyen de le faire avec du code, mais dans Firefox 64, les événements sont répertoriés à côté de chaque entité HTML dans l'inspecteur des outils de développement, comme indiqué sur la page Examiner les écouteurs d'événements de MDN et comme illustré dans cette image:

capture d'écran de FF Inspector

Adam Katz
la source