How to find event listeners on a DOM node when debugging or from the JavaScript code?

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

Update: Visual Event 2 available.


Chrome, Firefox, Vivaldi and Safari support getEventListeners(domElement) in their Developer Tools console.

For majority of the debugging purposes, this could be used.

Below is a very good reference to use it: https://developers.google.com/web/tools/chrome-devtools/console/utilities#geteventlisteners


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
console.log(element.onclick); // "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) {
         console.log(value) // "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) {
         console.log(handlerObj.handler) // "function() { alert('clicked!') }"
         // also available: handlerObj.type, handlerObj.namespace
     })
    
  • 1.7+ (very nice)

    Made using knowledge from this comment.

     events = $._data(this, 'events');
     for (type in events) {
       events[type].forEach(function (event) {
         console.log(event['handler']);
       });
     }
    

(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) {
             console.log(item[2]) // "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){
         console.log(wrapper.handler) // "function() { alert('clicked!') }"
     })
    
  • 1.6.1 (little better)

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

When clicking the resulting output in the console (which shows the text of the function), the console will navigate directly to the line of the function's declaration in the relevant JS file.