Holen Sie sich Ereignis-Listener mit addEventListener an den Knoten

106

Ich habe mir diese Fragen bereits angesehen:

Keiner von ihnen antwortet jedoch, wie eine Liste von Ereignis-Listenern abgerufen werden kann, die mit einem Knoten verbunden sind addEventListener, ohne den addEventListenerPrototyp zu ändern, bevor die Ereignis-Listener erstellt werden.

VisualEvent zeigt nicht alle Ereignis-Listener (iPhone-spezifische) an, und ich möchte dies (etwas) programmgesteuert tun.

Tyilo
quelle
"etwas programmatisch" und die Tatsache, dass die akzeptierte Antwort auf diese Frage eine devtools-Funktion ist, macht dies zu einem Duplikat der aufgelisteten Frage. Für diejenigen, die nach einer JS-Lösung suchen, lautet die Antwort "Es gibt keine"
Nickolay,

Antworten:

135

Chrome DevTools, Safari Inspector und Firebug unterstützen getEventListeners (Knoten) .

getEventListeners (Dokument)

NVI
quelle
6
Ich möchte darauf hinweisen, dass die Methode getEventListeners die Firefox 35-Version nicht unterstützt.
MURATSPLAT
Es funktioniert möglicherweise nicht unter Firefox, aber dann entwickeln sich Entwickler auf mehreren Browsern. Dies hilft sicher, wenn eine vorhandene Site geändert werden muss ... VIEL!
JasonXA
1
Nicht es Firefox 69.
Vitaly Zdanevich
65

Das kannst du nicht.

Die einzige Möglichkeit, eine Liste aller an einen Knoten angehängten Ereignis-Listener abzurufen, besteht darin, den Aufruf des Listener-Anhangs abzufangen.

DOM4 addEventListener

Sagt

Hängen Sie einen Ereignis-Listener an die zugehörige Liste von Ereignis-Listenern an, deren Typ auf Typ, Listener auf Listener und Capture auf Capture festgelegt ist, es sei denn, in dieser Liste befindet sich bereits ein Event-Listener mit demselben Typ, Listener und Capture.

Dies bedeutet, dass ein Ereignis-Listener zur "Liste der Ereignis-Listener" hinzugefügt wird. Das ist alles. Es gibt keine Vorstellung davon, wie diese Liste aussehen soll und wie Sie darauf zugreifen sollen.

Raynos
quelle
12
Gibt es eine Möglichkeit, eine Begründung oder Begründung dafür zu liefern, warum dies so funktionieren muss? Der Browser weiß eindeutig, was alle Hörer sind.
Darth Egregious
3
@ user973810: Wie soll er das rechtfertigen? Die DOM-API bietet keine Möglichkeit, dies zu tun, und es gibt keine nicht standardmäßigen Möglichkeiten, dies in aktuellen Browsern zu tun. Warum dies der Fall ist, weiß ich nicht genau. Es scheint eine vernünftige Sache zu sein, dies tun zu wollen.
Tim Down
Ich habe ein paar Threads gesehen, in denen es darum ging, dem DOM eine API hinzuzufügen.
Raynos
@ TimDown hilft die Bearbeitung. Zu sehen, dass es keine Spezifikation für so etwas wie "getEventListeners" gibt, rechtfertigt, warum es so etwas nicht gibt.
Darth Egregious
24

Da es keinen nativen Weg gibt, dies zu tun, habe ich hier eine weniger aufdringliche Lösung gefunden (keine 'alten' Prototypmethoden hinzufügen):

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
quelle
Sie sollten auch festlegen, dass Fensterereignis-Listener abgefangen werden. Davon abgesehen funktioniert das großartig!
2

Sie können alle jQuery-Ereignisse mit $ ._ data ($ ('[Selektor]') [0], 'Ereignisse') abrufen. Ändern Sie [Selektor] auf das, was Sie brauchen.

Es gibt ein Plugin, das alle von jQuery angehängten Ereignisse mit dem Namen eventsReport sammelt.

Außerdem schreibe ich mein eigenes Plugin, das dies mit besserer Formatierung tut.

Es scheint jedoch, dass wir keine Ereignisse erfassen können, die mit der Methode addEventListener hinzugefügt wurden. Möglicherweise können wir den Aufruf von addEventListener umbrechen, um Ereignisse zu speichern, die nach unserem Aufruf von wrap hinzugefügt wurden.

Es scheint der beste Weg zu sein, Ereignisse zu sehen, die einem Element mit Entwicklungswerkzeugen hinzugefügt wurden.

Sie werden dort jedoch keine delegierten Ereignisse sehen. Da brauchen wir also jQuery eventsReport.

UPDATE: JETZT KÖNNEN Ereignisse angezeigt werden, die mit der Methode addEventListener hinzugefügt wurden. SIEHE RICHTIGE ANTWORT AUF DIESE FRAGE.

Rantiev
quelle
Dies ist eine private und veraltete Schnittstelle, die möglicherweise bald verschwindet. Verlassen Sie sich also nicht darauf.
mgol
1
Ja, aber als ich antwortete, gab es in Dev-Tools keine solche Fähigkeit. Es gab also nichts zur Auswahl.
Rantiev
Es ist veraltet @Rantiev, können Sie diese Antwort entfernen?
Julio Marins
2

Ich kann keine Möglichkeit finden, dies mit Code zu tun, aber in Firefox 64 werden Ereignisse neben jeder HTML-Entität im Developer Tools Inspector aufgelistet, wie auf der MDN- Seite " Ereignis-Listener untersuchen " angegeben und in diesem Bild gezeigt:

Screenshot von FF Inspector

Adam Katz
quelle