Получить прослушиватели событий, подключенные к узлу, с помощью addEventListener

107

Я уже смотрел на эти вопросы:

однако ни один из них не отвечает, как получить список прослушивателей событий, прикрепленных к узлу, используя addEventListenerбез изменения addEventListenerпрототипа до создания прослушивателей событий.

VisualEvent не отображает всех прослушивателей событий (только для iphone), и я хочу сделать это (отчасти) программно.

Tyilo
источник
"несколько программно", и тот факт, что принятый ответ на этот вопрос является функцией инструментов разработчика, делает его дубликатом указанного вопроса. Для тех, кто ищет JS-решение, ответ - «его нет»
Николай

Ответы:

137

Chrome DevTools, Safari Inspector и Firebug поддерживают getEventListeners (узел) .

getEventListeners (документ)

NVI
источник
6
Хочу отметить, что метод getEventListeners не поддерживает версию Firefox 35.
MURATSPLAT 06
Это может не работать в Firefox, но, опять же, разработчики разрабатывают несколько браузеров. Это ПОМОГАЕТ, если нужно изменить существующий сайт ... ОЧЕНЬ!
JasonXA
1
Только не Firefox 69.
Виталий Зданевич
65

Вы не можете.

Единственный способ получить список всех прослушивателей событий, прикрепленных к узлу, - это перехватить вызов присоединения слушателя.

DOM4 addEventListener

Говорит

Добавьте прослушиватель событий в связанный список прослушивателей событий с типом, для которого задано значение type, для прослушивателя, настроенного для прослушивателя, и для захвата, для которого задано захват, если в этом списке еще нет прослушивателя событий с тем же типом, прослушивателем и захватом.

Это означает, что слушатель событий добавляется в «список слушателей событий». Вот и все. Нет никакого представления о том, каким должен быть этот список и как к нему обращаться.

Райнос
источник
12
Есть ли шанс предоставить какое-то оправдание или аргумент, почему это должно работать именно так? Очевидно, что браузер знает, кто все слушатели.
Дарт Эгрегиус
3
@ user973810: Как вы хотите, чтобы он это оправдал? DOM API не предоставляет возможности сделать это, и в текущих браузерах нет нестандартных способов сделать это. Что касается того, почему это так, я действительно не знаю. Кажется, это разумное желание сделать.
Тим Даун
Я видел несколько тусовок о добавлении API в DOM для этого.
Raynos 05
@TimDown редактирование помогает. То, что нет спецификации для чего-то вроде "getEventListeners", оправдывает, почему этого нет.
Darth Egregious 05
24

Поскольку для этого нет собственного способа, вот менее навязчивое решение, которое я нашел (не добавляйте никаких «старых» методов прототипа):

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();
йорг
источник
Вы также должны заставить его перехватывать прослушиватели оконных событий. В остальном это отлично работает!
2

Вы можете получить все события jQuery, используя $ ._ data ($ ('[selector]') [0], 'events'); измените [селектор] на то, что вам нужно.

Существует плагин, который собирает все события, прикрепленные jQuery, под названием eventsReport.

Также я пишу свой собственный плагин, который делает это с лучшим форматированием.

Но в любом случае, похоже, мы не можем собрать события, добавленные методом addEventListener. Возможно, мы можем обернуть вызов addEventListener для хранения событий, добавленных после нашего вызова обертывания.

Кажется, лучший способ увидеть события, добавленные к элементу, с помощью инструментов разработчика.

Но вы не увидите там делегированных событий. Итак, нам нужен jQuery eventsReport.

ОБНОВЛЕНИЕ: ТЕПЕРЬ мы МОЖЕМ видеть события, добавленные методом addEventListener. СМОТРИТЕ ВЕРНЫЙ ОТВЕТ НА ЭТОТ ВОПРОС.

Рантьев
источник
Это частный и устаревший интерфейс, и он может скоро исчезнуть, поэтому не полагайтесь на него.
mgol
1
Да, но когда я ответил, в инструментах Dev не было такой возможности. Так что выбирать было не из чего.
Рантиев
@Rantiev устарел, вы можете удалить этот ответ?
Хулио Маринс,
2

Я не могу найти способ сделать это с помощью кода, но в стандартном Firefox 64 события перечислены рядом с каждым HTML-объектом в Инспекторе инструментов разработчика, как указано на странице MDN Examine Event Listeners и как показано на этом изображении:

снимок экрана FF Inspector

Адам Кац
источник