Как найти прослушиватели событий на узле DOM при отладке или из кода JavaScript?



Answers

Это зависит от того, как события привязаны. Для иллюстрации предположим, что у нас есть следующий обработчик кликов:

var handler = function() { alert('clicked!') };

Мы собираемся прикрепить его к нашему элементу, используя различные методы, некоторые из которых позволяют проводить инспекцию, а некоторые - нет.

Метод A) обработчик одного события

element.onclick = handler;
// inspect
alert(element.onclick); // alerts "function() { alert('clicked!') }"

Метод B) несколько обработчиков событий

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

Метод 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 (хранит обработчик внутри объекта)

    // 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
    })
    

(См. jQuery.fn.data и jQuery.data )

Метод D): Прототип (грязный)

$(element).observe('click', handler);
  • 1.5.x

    // inspect
    Event.observers.each(function(item) {
        if(item[0] == element) {
            alert(item[2]) // alerts "function() { alert('clicked!') }"
        }
    })
    
  • 1.6 до 1.6.0.3, включительно (здесь очень сложно)

    // 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 (немного лучше)

    // inspect
    var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
    clickEvents.each(function(wrapper){
        alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
    })
    
Question

У меня есть страница, где некоторые слушатели событий прикреплены к полям ввода и выберите поля. Есть ли способ узнать, какие слушатели событий наблюдают за конкретным узлом DOM и каким событием?

События прилагаются с использованием:

  1. Prototype's Event.observe ;
  2. DOM addEventListener ;
  3. В качестве элемента element element.onclick .






Opera 12 (не последний движок Chrome Webkit) Dragonfly имеет это некоторое время и явно отображается в структуре DOM. По-моему, это превосходный отладчик, и это единственная причина, по которой я все еще использую версию на основе Opera 12 (нет версии v13, v14 и v15 Webkit на основе отсутствия Dragonfly)




Теперь инструменты разработчика Firefox делают это. События отображаются нажатием кнопки «ev» справа от отображения каждого элемента, включая события jQuery и DOM .




(Переписывая ответ из этого вопроса, так как он имеет значение здесь.)

При отладке, если вы просто хотите увидеть события, я рекомендую либо ...

  1. Визуальное событие
  2. Раздел « Элементы » инструментов разработчика Chrome: выберите элемент и найдите «Слушатели событий» в правом нижнем углу (аналогично Firefox)

Если вы хотите использовать события в своем коде и используете jQuery до версии 1.8 , вы можете использовать:

$(selector).data("events")

чтобы получить события. Начиная с версии 1.8, использование .data («events») прекращается (см. Этот биг-код ). Вы можете использовать:

$._data(element, "events")

Другой пример: записать все события кликов по определенной ссылке на консоль:

var $myLink = $('a.myClass');
console.log($._data($myLink[0], "events").click);

(см. http://jsfiddle.net/HmsQC/ для рабочего примера)

К сожалению, использование $ ._ данных не рекомендуется, кроме отладки, поскольку это внутренняя структура jQuery и может быть изменена в будущих выпусках. К сожалению, я не знаю других простых способов доступа к событиям.




Прототип 1.7.1

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];
}



1: Prototype.observe использует Element.addEventListener (см. Исходный код )

2: Вы можете переопределить Element.addEventListener чтобы запомнить добавленные слушатели (удобное свойство EventListenerList было удалено из предложения спецификации DOM3). Запустите этот код до присоединения любого события:

(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);
  };
})();

Прочтите все события:

var clicks = someElement.eventListenerList.click;
if(clicks) clicks.forEach(function(f) {
  alert("I listen to this function: "+f.toString());
});

И не забудьте переопределить Element.removeEventListener чтобы удалить событие из пользовательского Element.eventListenerList .

3: свойство Element.onclick нуждается в особом уходе:

if(someElement.onclick)
  alert("I also listen tho this: "+someElement.onclick.toString());

4: не забывайте атрибут контента Element.onclick : это две разные вещи:

someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute

Так что вам тоже нужно справиться:

var click = someElement.getAttribute("onclick");
if(click) alert("I even listen to this: "+click);

Виджет закладок Visual Event (упомянутый в наиболее популярном ответе) только крадет кеш обработчика пользовательской библиотеки:

Оказывается, нет стандартного метода, предоставляемого рекомендованным W3C интерфейсом DOM, чтобы узнать, какие прослушиватели событий привязаны к определенному элементу. Хотя это может показаться надзором, было предложение включить свойство, называемое eventListenerList, в спецификацию DOM уровня 3, но, к сожалению, было удалено в последующих черновиках. Таким образом, мы вынуждены смотреть на отдельные библиотеки Javascript, которые обычно поддерживают кэш присоединенных событий (поэтому впоследствии их можно удалить и выполнить другие полезные абстракции).

Таким образом, чтобы Visual Event отображал события, он должен иметь возможность анализировать информацию о событиях из библиотеки Javascript.

Переопределение элементов может быть сомнительным (т. Е. Потому что есть некоторые DOM-специфические функции, такие как живые коллекции, которые нельзя кодировать в JS), но он обеспечивает поддержку eventListenerList изначально и работает в Chrome, Firefox и Opera (не работает в IE7 ).




WebKit Inspector в браузерах Chrome или Safari теперь делает это. Он отобразит прослушиватели событий для элемента DOM, когда вы выберете его в панели «Элементы».




Links