Obtenga oyentes de eventos adjuntos al nodo mediante addEventListener

106

Ya he mirado estas preguntas:

sin embargo, ninguno de ellos responde cómo obtener una lista de oyentes de eventos adjuntos a un nodo utilizando addEventListener, sin modificar el addEventListenerprototipo antes de que se creen los oyentes de eventos.

VisualEvent no muestra todos los oyentes de eventos (los específicos de iPhone) y quiero hacer esto (algo) programáticamente.

Tyilo
fuente
"algo programáticamente" y el hecho de que la respuesta aceptada para esta pregunta sea una característica de devtools hace que esto sea un duplicado de la pregunta enumerada. Para aquellos que buscan una solución JS, la respuesta es "no hay una"
Nickolay

Respuestas:

135

Chrome DevTools, Safari Inspector y Firebug son compatibles con getEventListeners (nodo) .

getEventListeners (documento)

NVI
fuente
6
Quiero señalar que el método getEventListeners no es compatible con la versión Firefox 35.
MURATSPLAT
Puede que no funcione en Firefox, pero, de nuevo, los desarrolladores se desarrollan en varios navegadores / Esto seguro AYUDA si uno necesita modificar un sitio existente ... ¡MUCHO!
JasonXA
1
No es Firefox 69.
Vitaly Zdanevich
65

No puedes.

La única forma de obtener una lista de todos los detectores de eventos adjuntos a un nodo es interceptar la llamada del adjunto del detector.

DOM4 addEventListener

Dice

Agregue un detector de eventos a la lista asociada de detectores de eventos con tipo establecido en tipo, detector establecido en detector y captura establecida en captura, a menos que ya haya un detector de eventos en esa lista con el mismo tipo, detector y captura.

Lo que significa que se agrega un detector de eventos a la "lista de detectores de eventos". Eso es todo. No hay noción de qué debería ser esta lista ni cómo debería acceder a ella.

Raynos
fuente
12
¿Alguna posibilidad de proporcionar alguna justificación o razonamiento de por qué debe funcionar de esta manera? Claramente, el navegador sabe cuáles son todos los oyentes.
Darth Egregious
3
@ user973810: ¿Cómo quieres que justifique esto? La API DOM no proporciona ninguna forma de hacerlo y no hay formas no estándar de hacerlo en los navegadores actuales. En cuanto a por qué este es el caso, realmente no lo sé. Parece razonable querer hacer.
Tim Down
He visto algunos hilos sobre cómo agregar una API al DOM para esto.
Raynos
@TimDown la edición ayuda. Ver que no hay una especificación para algo como "getEventListeners" justifica por qué no existe tal cosa.
Darth Egregious
24

Dado que no hay una forma nativa de hacer esto, aquí hay una solución menos intrusiva que encontré (no agregue ningún método de prototipo 'antiguo'):

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
fuente
También debe hacer que intercepte los oyentes de eventos de ventana. Aparte de eso, ¡esto funciona muy bien!
2

Puede obtener todos los eventos de jQuery usando $ ._ data ($ ('[selector]') [0], 'events'); cambie [selector] a lo que necesite.

Hay un complemento que recopila todos los eventos adjuntos por jQuery llamado eventsReport.

También escribo mi propio complemento que hace esto con un mejor formato.

Pero de todos modos, parece que no podemos recopilar eventos agregados por el método addEventListener. Puede ser que podamos envolver la llamada addEventListener para almacenar eventos agregados después de nuestra llamada de cierre.

Parece la mejor manera de ver eventos agregados a un elemento con herramientas de desarrollo.

Pero no verá eventos delegados allí. Entonces, necesitamos jQuery eventsReport.

ACTUALIZACIÓN: AHORA PODEMOS ver eventos agregados por el método addEventListener VER RESPUESTA CORRECTA A ESTA PREGUNTA.

Rantiev
fuente
Esta es una interfaz privada y obsoleta y puede desaparecer pronto, así que no confíe en eso.
mgol
1
Sí, pero cuando respondí, no existía tal capacidad en las herramientas de desarrollo. Entonces, no había nada para elegir.
Rantiev
Está en desuso @Rantiev, ¿puedes eliminar esa respuesta?
Julio Marins
2

No puedo encontrar una manera de hacer esto con el código, pero en Firefox 64, los eventos se enumeran junto a cada entidad HTML en el Inspector de herramientas para desarrolladores, como se indica en la página Examinar oyentes de eventos de MDN y como se muestra en esta imagen:

captura de pantalla de FF Inspector

Adam Katz
fuente