How to find event listeners on a DOM node when deb

2018-12-31 00:54发布

I have a page where some event listeners are attached to input boxes and select boxes. Is there a way to find out which event listeners are observing a particular DOM node and for what event?

Events are attached using:

  1. Prototype's Event.observe;
  2. DOM's addEventListener;
  3. As element attribute element.onclick.

17条回答
余生请多指教
2楼-- · 2018-12-31 01:36

The Firefox developer tools now does this. Events are shown by clicking the "ev" button on the right of each element's display, including jQuery and DOM events.

Screenshot of Firefox developer tools' event listener button in the inspector tab

查看更多
旧时光的记忆
3楼-- · 2018-12-31 01:37

If you just need to inspect what's happening on a page, you might try the Visual Event bookmarklet.

Update: Visual Event 2 available;

查看更多
骚的不知所云
4楼-- · 2018-12-31 01:38

Prototype 1.7.1 way

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];
}
查看更多
看淡一切
5楼-- · 2018-12-31 01:40

1: Prototype.observe uses Element.addEventListener (see the source code)

2: You can override Element.addEventListener to remember the added listeners (handy property EventListenerList was removed from DOM3 spec proposal). Run this code before any event is attached:

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

Read all the events by:

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

And don't forget to override Element.removeEventListener to remove the event from the custom Element.eventListenerList.

3: the Element.onclick property needs special care here:

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

4: don't forget the Element.onclick content attribute: these are two different things:

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

So you need to handle it, too:

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

The Visual Event bookmarklet (mentioned in the most popular answer) only steals the custom library handler cache:

It turns out that there is no standard method provided by the W3C recommended DOM interface to find out what event listeners are attached to a particular element. While this may appear to be an oversight, there was a proposal to include a property called eventListenerList to the level 3 DOM specification, but was unfortunately been removed in later drafts. As such we are forced to looked at the individual Javascript libraries, which typically maintain a cache of attached events (so they can later be removed and perform other useful abstractions).

As such, in order for Visual Event to show events, it must be able to parse the event information out of a Javascript library.

Element overriding may be questionable (i.e. because there are some DOM specific features like live collections, which can not be coded in JS), but it gives the eventListenerList support natively and it works in Chrome, Firefox and Opera (doesn't work in IE7).

查看更多
姐姐魅力值爆表
6楼-- · 2018-12-31 01:40

There exists nice jQuery Events extension :

enter image description here (topic source)

查看更多
看淡一切
7楼-- · 2018-12-31 01:42

It depends on how the events are attached. For illustration presume we have the following click handler:

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

We're going to attach it to our element using different methods, some which allow inspection and some that don't.

Method A) single event handler

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

Method B) multiple event handlers

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

Method 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 (stores the handler inside an object)

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

(See jQuery.fn.data and jQuery.data)

Method D): Prototype (messy)

$(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 to 1.6.0.3, inclusive (got very difficult here)

    // 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 (little better)

    // inspect
    var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
    clickEvents.each(function(wrapper){
        alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
    })
    
查看更多
登录 后发表回答