How to find event listeners on a DOM node in JavaScript or in debugging?
Asked Answered
F

22

1123

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.
Faction answered 15/1, 2009 at 14:19 Comment(5)
How are the events attached in the first place? Are you using a library (eg Prototype, jQuery, etc)?Voltammeter
It's important to note that multiple callback functions can be attached for the same type of event via element.addEventListener(type, callback, [bubble]), while element.onclick = function will overwrite every time you assign.Matrass
Gets all events alongside their respective element: Array.from(document.querySelectorAll("*")).forEach(e => { const ev = getEventListeners(e); if (Object.keys(ev).length !== 0) {console.log(e, ev)} })Mindszenty
You can hijack the addEventListener and capture a list of all listeners in the DOM element. Here is sample code https://mcmap.net/q/46899/-javascript-dom-how-to-remove-all-event-listeners-of-a-dom-objectWieche
Note that getEventListeners() only exists in the Chrome dev console, not in ordinary JavaScript.Murtha
M
543

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

Update: Visual Event 2 available.

Mcclung answered 6/8, 2010 at 17:48 Comment(14)
Perfect! Beats Firebug's EventBug plugin.Outdoors
This adds a jillion elements to the page, many of which are images. Its usefulness is reduced greatly on a page with many event handlers (mine has 17k and Visual Event took about 3 minutes to load).Soutane
I believe the Chrome extension @ssharma mentioned is the one available hereHazlitt
Visial Event does not work if the page refers a third party js library. It raises an error: XMLHttpRequest cannot load A.com/js/jquery-ui-1.10.3.custom.js?_=1384831682813. Origin B.com is not allowed by Access-Control-Allow-Origin.Fiscus
It's obvious from the source, but the bookmarklet injects a 3rd-party script into your site. This may be fine for most uses, but if you're dealing with PCI, HIPAA, etc. data then you should probably steer clear.Blount
Chrome and FF internal Developer Tools (F12) has a built-in event viewer! Chrome: on the "Elements" tab, select and element and see to the right there are: Style, Computed, Event ListenersGabble
It seems that Visual Event doesn't support the DOM 2 way of adding EventListeners. This is extremely odd and incomprehensible for me, since it does support half a dozen non-core libraries.Dacca
@Gabble Awesome! Any way to determine which one I want to look at more quickly than opening them one by one?Kuehn
@Kuehn Firefox has this small "ev" icon near the elements that has event listeners. I couldn't find a similar icon on Chrome, sorry. doABarrelRoll721 If you find a way to detect them, it's very easy to add an event parser to the Visual Event library. Come on in, the code is great :)Gabble
You also have a problem if the script is minified, everything will be on one line. A copy button would be nice. Also the VE popup gets into my way when I hover over elements... But nevertheless a very helpful extension!Fraze
@TonyR you came looking for an event visualizer and complain because it's taking 3 mins to load on 17k events? I mean I can create an AI VisualEvent which will look at your events and only catch the ones that you would need at that particular time only if you like...Atal
What is the difference between Visual Event and Visual Event 2?Earmuff
This was life saver.. it is shame that now-a-days this doens't work for exploring github site as the browser doesn't allow dinamyc inclusion of a javascript file from another domain (kind of a CORS Problem that doesn't exist before..) i guess i should send a ticket to the owner of Visual Event.Midget
It stops working and displays the error events.hasOwnProperty is not a function. I fixed it: github.com/DataTables/VisualEvent/pull/69Saraann
H
655

Chrome, 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:
getEventListeners function


Highly voted tip from Clifford Fajardo from the comments:

getEventListeners($0) will get the event listeners for the element you have focused on in the Chrome dev tools.

Hypostasize answered 14/5, 2013 at 13:40 Comment(13)
+1. Browser-specific code isn't a problem for me, because I'm trying to get a page I don't control to work properly.Chrome
nice, but only works in the command line of the Chrome console :(Underquote
In which chrome versions is this available, because 40 does not seem to have it ...Coral
@Coral The current one that I use is 41.0.2272.89. The feature still exists.Hypostasize
@Hypostasize ah thanks, the usage is getEventListeners(object) NOT: obj getEventListeners() as I first thought :)Coral
You could've saved me 3 hours if you'd have explained how to get the source code of an eventlistener. That "reference" didn't explain anything. In case anyone else was on a loss here's how: var list = getEventListeners(document.getElementById("YOURIDHERE")); console.log(list["focus"][0]["listener"].toString()). Change "focus" to the event you want to inspect and the number if there are multiple listeners on the same event.Dacca
TIP: getEventListeners($0) will get the event listeners for the element you have focused on in the Chrome dev tools. I use this all the time. Love not having to use querySelector or get__By_ functionsRieger
@CliffordFajardo Sounds like a nice hidden feature there. <3Postprandial
As oriadam mentioned in his comment, Chrome and Firefox internal Developer Tools (F12) has a built-in event viewer.Sisley
Unfortunately, although getEventListeners() was supported by Firebug, it's not supported by Firefox Developer Tools. (Bug 1164285)Gail
Pro tip: click the "eye" icon in the Console below the Elements tab and add Expression with value getEventListeners($0) and you'll get instant knowledge of any attached event listeners whenever you focus an element in the Elements view. An alternative method to this is to open view "Event Listeners" and clear the checkbox "Ancestors".Insatiable
List all events except some DOM elements var all = document.querySelectorAll( ':not( link, svg *,svg, script, meta ) '), allEvents = {}; for (var i=0, max=all.length; i < all.length; i++) { let events = getEventListeners(all[i]); if(Object.keys(events).length !== 0) { for (const property in events) { allEvents[property] = true; } } } console.log(allEvents);Hubble
To remove all listeners from an element you selected in DevTools: getEventListeners($0).click.forEach(listenerObj => $0.removeEventListener('click', listenerObj.listener)) — this is similar to @doABarrellRoll721 's answer, but with a correctionCerotype
M
543

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

Update: Visual Event 2 available.

Mcclung answered 6/8, 2010 at 17:48 Comment(14)
Perfect! Beats Firebug's EventBug plugin.Outdoors
This adds a jillion elements to the page, many of which are images. Its usefulness is reduced greatly on a page with many event handlers (mine has 17k and Visual Event took about 3 minutes to load).Soutane
I believe the Chrome extension @ssharma mentioned is the one available hereHazlitt
Visial Event does not work if the page refers a third party js library. It raises an error: XMLHttpRequest cannot load A.com/js/jquery-ui-1.10.3.custom.js?_=1384831682813. Origin B.com is not allowed by Access-Control-Allow-Origin.Fiscus
It's obvious from the source, but the bookmarklet injects a 3rd-party script into your site. This may be fine for most uses, but if you're dealing with PCI, HIPAA, etc. data then you should probably steer clear.Blount
Chrome and FF internal Developer Tools (F12) has a built-in event viewer! Chrome: on the "Elements" tab, select and element and see to the right there are: Style, Computed, Event ListenersGabble
It seems that Visual Event doesn't support the DOM 2 way of adding EventListeners. This is extremely odd and incomprehensible for me, since it does support half a dozen non-core libraries.Dacca
@Gabble Awesome! Any way to determine which one I want to look at more quickly than opening them one by one?Kuehn
@Kuehn Firefox has this small "ev" icon near the elements that has event listeners. I couldn't find a similar icon on Chrome, sorry. doABarrelRoll721 If you find a way to detect them, it's very easy to add an event parser to the Visual Event library. Come on in, the code is great :)Gabble
You also have a problem if the script is minified, everything will be on one line. A copy button would be nice. Also the VE popup gets into my way when I hover over elements... But nevertheless a very helpful extension!Fraze
@TonyR you came looking for an event visualizer and complain because it's taking 3 mins to load on 17k events? I mean I can create an AI VisualEvent which will look at your events and only catch the ones that you would need at that particular time only if you like...Atal
What is the difference between Visual Event and Visual Event 2?Earmuff
This was life saver.. it is shame that now-a-days this doens't work for exploring github site as the browser doesn't allow dinamyc inclusion of a javascript file from another domain (kind of a CORS Problem that doesn't exist before..) i guess i should send a ticket to the owner of Visual Event.Midget
It stops working and displays the error events.hasOwnProperty is not a function. I fixed it: github.com/DataTables/VisualEvent/pull/69Saraann
V
399

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.

Voltammeter answered 15/1, 2009 at 15:13 Comment(9)
Thx for updating this. It's unfortunate that you have to iterate thru each type of handler.Diarthrosis
On "Method B" (addEventListener) here's an answer regarding the status of the enumeration facilities for handlers registered with pure DOM Events API: #7811034Dissociable
@John: thanks for the comment. You have an example of "real JavaScript" to fetch listeners previously added via addEventListener?Voltammeter
If someone is sloppy they can create a monitoring service. If they have good practices they simply won't need to create one. Same listeners overwrite the old versions of themselves.Heartache
@Jan, this does not seem to work for jQuery 1.7.2, is there a different approach for that version ?Glabrescent
What about event listeners that aren't on the actual element like the following: $(parentElement).on(event, 'myElement', handler);?Cartwell
Why are there so many ways of attaching events and so many places they can be saved? It's not really helping us programmers, is it?Branchiopod
@Glabrescent In jQuery, events are now stored in an internal data array rather than being accessible via .data('events') like they were before. To access the internal event data, use $._data(elem, 'events'). Note that this function is marked "for internal use only" in the jQuery source, so no promises that it will always work in the future, but I believe it's worked ever since jQuery 1.7 and still works.Zebada
@MattBrowne Very nice. I added it to the answer as a complete solution.Eudosia
M
98

WebKit Inspector in Chrome or Safari browsers now does this. It will display the event listeners for a DOM element when you select it in the Elements pane.

Meristic answered 17/1, 2011 at 7:39 Comment(4)
I'm not sure it shows all the event handlers; just the single HTML event handler.Constructivism
I should mention EventBug plugin for Firebug for completeness <softwareishard.com/blog/category/eventbug>Dissociable
This just made my day, some legacy prototype code had multiple functions bound to the same event on the same element and I was dying trying to track them down. Thank you so much Ishan.Ketonuria
It's a busy interface. Could you show us where these appear in the pane?Haynie
P
92

It is possible to list all event listeners in JavaScript: It's not that hard; you just have to hack the prototype's method of the HTML elements (before adding the listeners).

function reportIn(e){
    var a = this.lastListenerInfo[this.lastListenerInfo.length-1];
    console.log(a)
}


HTMLAnchorElement.prototype.realAddEventListener = HTMLAnchorElement.prototype.addEventListener;

HTMLAnchorElement.prototype.addEventListener = function(a,b,c){
    this.realAddEventListener(a,reportIn,c); 
    this.realAddEventListener(a,b,c); 
    if(!this.lastListenerInfo){  this.lastListenerInfo = new Array()};
    this.lastListenerInfo.push({a : a, b : b , c : c});
};

Now every anchor element (a) will have a lastListenerInfo property wich contains all of its listeners. And it even works for removing listeners with anonymous functions.

Promote answered 22/6, 2011 at 4:32 Comment(8)
This method won't work if you're writing a user script or content script. Not only are likely to be sandboxed these days but how can you guarantee the order of execution?Constructivism
this method works with chrome/19 and FF/12. order of execution can be guaranteed if you hook this before other scriptsTube
Couldn't you just modify Node.prototype instead? That's where HTMLAnchorElement inherits .addEventListener from anyways.'Cordage
You're assuming that the user agent implements prototype inheritance for DOM host objects and allows you to modify them. Neither of those are good ideas: don't modify objects you don't own.Peritoneum
This is pretty useless - it shows what eventListeners were added, which can be good in some cases, but not what was removed. So if you are trying to debug what was removed and what wasn't, there is simply no way.Femur
@Femur is right. This doesn't show you the eventlisteners that you have at the moment. I wonder if the upvoters even read the question.Dacca
@Dacca And I wonder if you have common sense. You see, JavaScript executes in the side of the browser, so you can execute it at any moment you need, e.g. with a little help of tamper-monkey you can execute on all websites you open.Promote
@IvanCastellanos What I meant was that your lastListenerInfo array contains only the listeners that were added. OP asked for which event listeners are observing a particular DOM node, which includes the ones that were removed. If you'd have overwritten removeEventListener the same you did with addEventListener your lastListenerInfo array would have exactly what OP asked for (although he was talking about input and select elements, not anchors, but whatever).Dacca
S
63

Use getEventListeners in Google Chrome:

getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));
Stamps answered 19/3, 2014 at 9:30 Comment(2)
Uncaught ReferenceError: getEventListeners is not definedLeahy
getEventListeners works only in Chrome's devtools console. And this is a duplicate of this more elaborate answer: https://mcmap.net/q/45637/-how-to-find-event-listeners-on-a-dom-node-in-javascript-or-in-debuggingDissociable
W
46

(Rewriting the answer from this question since it's relevant here.)

When debugging, if you just want to see the events, I recommend either...

  1. Visual Event
  2. The Elements section of Chrome's Developer Tools: select an element and look for "Event Listeners" on the bottom right (similar in Firefox)

If you want to use the events in your code, and you are using jQuery before version 1.8, you can use:

$(selector).data("events")

to get the events. As of version 1.8, using .data("events") is discontinued (see this bug ticket). You can use:

$._data(element, "events")

Another example: Write all click events on a certain link to the console:

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

(see http://jsfiddle.net/HmsQC/ for a working example)

Unfortunately, using $._data this is not recommended except for debugging since it is an internal jQuery structure, and could change in future releases. Unfortunately I know of no other easy means of accessing the events.

Wroth answered 22/10, 2012 at 19:4 Comment(2)
$._data(elem, "events") doesn't appear to work with jQuery 1.10, at least for events registered using $(elem).on('event', ...). Does anyone know how to debug those?Aplenty
I'm not positive, but I think the first param of $._data may need to be an element and not a jQuery object. So I need to fix my example above to be console.log($._data($myLink[0], "events").click);Wroth
E
37

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).

Elene answered 3/4, 2014 at 15:8 Comment(1)
Very nice answer style! I wish you have more upvotes! 👍Tornado
M
26

Paste in console to get all eventListeners printed beside their HTML element

Array.from(document.querySelectorAll("*")).forEach(element => {
    const events = getEventListeners(element)
    if (Object.keys(events).length !== 0) {
         console.log(element, events)
    }
})
Mindszenty answered 22/7, 2020 at 14:22 Comment(3)
also const ev = getEventListeners(document) if (Object.keys(ev).length !== 0) console.log(ev)Bade
If I try using getEventListeners in my JS file, I get Uncaught ReferenceError: getEventListeners is not defined.Koy
@Koy becuase your JS does not know that you will run the code in the Chrome context. Never use this in production either way, only for debugging purposesMindszenty
H
25

You could wrap the native DOM methods for managing event listeners by putting this at the top of your <head>:

<script>
    (function(w){
        var originalAdd = w.addEventListener;
        w.addEventListener = function(){
            // add your own stuff here to debug
            return originalAdd.apply(this, arguments);
        };

        var originalRemove = w.removeEventListener;
        w.removeEventListener = function(){
            // add your own stuff here to debug
            return originalRemove.apply(this, arguments);
        };
    })(window);
</script>

H/T @les2

Hinshaw answered 6/11, 2015 at 17:49 Comment(2)
Please correct me if I'm wrong, but isn't it only for event listeners attached to the window?Nefen
@MaciejKrawczyk yep, and those that bubbleHinshaw
D
19

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

Dragonhead answered 14/1, 2015 at 15:33 Comment(2)
I did look at one of the dom elements on the page that the Visual Event 2 bookmarklet is showing an event wired to, and I did see the little "ev" button to the right, like you show.Bayreuth
Firefox's event listener could find out jQuery delegated events while Chrome needs plugin to do it.Gamb
H
14

Update 2022:

In the Chrome Developer Tools, in the Elements panel, there is the Event Listeners tab, where you can see listeners for the element.

You can also unselect "Ancestors" so it only shows the listeners for that element

Developer Tools

Hinterland answered 5/9, 2022 at 5:28 Comment(0)
N
13

If you have Firebug, you can use console.dir(object or array) to print a nice tree in the console log of any JavaScript scalar, array, or object.

Try:

console.dir(clickEvents);

or

console.dir(window);
Neurovascular answered 7/1, 2010 at 22:52 Comment(1)
New feature in firebug 1.12 getfirebug.com/wiki/index.php/GetEventListenersNadene
M
13

Fully working solution based on answer by Jan Turon - behaves like getEventListeners() from console:

(There is a little bug with duplicates. It doesn't break much anyway.)

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._addEventListener(a,b,c);
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(!this.eventListenerList[a])
      this.eventListenerList[a] = [];
    //this.removeEventListener(a,b,c); // TODO - handle duplicates..
    this.eventListenerList[a].push({listener:b,useCapture:c});
  };

  Element.prototype.getEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined)
      return this.eventListenerList;
    return this.eventListenerList[a];
  };
  Element.prototype.clearEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined){
      for(var x in (this.getEventListeners())) this.clearEventListeners(x);
        return;
    }
    var el = this.getEventListeners(a);
    if(el==undefined)
      return;
    for(var i = el.length - 1; i >= 0; --i) {
      var ev = el[i];
      this.removeEventListener(a, ev.listener, ev.useCapture);
    }
  };

  Element.prototype._removeEventListener = Element.prototype.removeEventListener;
  Element.prototype.removeEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._removeEventListener(a,b,c);
      if(!this.eventListenerList)
        this.eventListenerList = {};
      if(!this.eventListenerList[a])
        this.eventListenerList[a] = [];

      // Find the event in the list
      for(var i=0;i<this.eventListenerList[a].length;i++){
          if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
              this.eventListenerList[a].splice(i, 1);
              break;
          }
      }
    if(this.eventListenerList[a].length==0)
      delete this.eventListenerList[a];
  };
})();

Usage:

someElement.getEventListeners([name]) - return list of event listeners, if name is set return array of listeners for that event

someElement.clearEventListeners([name]) - remove all event listeners, if name is set only remove listeners for that event

Multiflorous answered 27/6, 2015 at 10:47 Comment(4)
This is a nice answer, but I can't get it to work on the body and document elements.Ornithic
@David Bradshaw: because body, document and window have their own prototype and not the Element prototype...Semilunar
@n00b: There's a bug. That's why hmmm. You use the comma-operator in the if statement for listener and useCaption... The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand. So you remove the first eventListener that matches in useCapture, irrespective of the type of the event... That should be && instead of comma.Semilunar
Just to be clear, this redefines Element.prototype.addEventListener and therefore must be run before any such calls are made. That means userscripts can't use it to interact with website's listeners.Weatherman
T
10

Opera 12 (not the latest Chrome Webkit engine based) Dragonfly has had this for a while and is obviously displayed in the DOM structure. In my opinion it is a superior debugger and is the only reason remaining why I still use the Opera 12 based version (there is no v13, v14 version and the v15 Webkit based lacks Dragonfly still)

enter image description here

Turtledove answered 28/11, 2013 at 16:30 Comment(0)
B
5

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];
}
Butt answered 17/1, 2013 at 17:28 Comment(0)
N
5

I am trying to do that in jQuery 2.1, and with the "$().click() -> $(element).data("events").click;" method it doesn't work.

I realized that only the $._data() functions works in my case :

	$(document).ready(function(){

		var node = $('body');
		
        // Bind 3 events to body click
		node.click(function(e) { alert('hello');  })
			.click(function(e) { alert('bye');  })
			.click(fun_1);

        // Inspect the events of body
		var events = $._data(node[0], "events").click;
		var ev1 = events[0].handler // -> function(e) { alert('hello')
		var ev2 = events[1].handler // -> function(e) { alert('bye')
		var ev3 = events[2].handler // -> function fun_1()
        
		$('body')
			.append('<p> Event1 = ' + eval(ev1).toString() + '</p>')
			.append('<p> Event2 = ' + eval(ev2).toString() + '</p>')
			.append('<p> Event3 = ' + eval(ev3).toString() + '</p>');        
	
	});

	function fun_1() {
		var txt = 'text del missatge';	 
		alert(txt);
	}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
</body>
Nicker answered 19/5, 2015 at 8:33 Comment(1)
This worked for me! But TypeScript complains saying "Property '_data' does not exist on type 'JQueryStatic'. Did you mean 'data'?" ... what's going on here?Galileo
S
5

I was recently working with events and wanted to view/control all events in a page. Having looked at possible solutions, I've decided to go my own way and create a custom system to monitor events. So, I did three things.

First, I needed a container for all the event listeners in the page: that's theEventListeners object. It has three useful methods: add(), remove(), and get().

Next, I created an EventListener object to hold the necessary information for the event, i.e.: target, type, callback, options, useCapture, wantsUntrusted, and added a method remove() to remove the listener.

Lastly, I extended the native addEventListener() and removeEventListener() methods to make them work with the objects I've created (EventListener and EventListeners).

Usage:

var bodyClickEvent = document.body.addEventListener("click", function () {
    console.log("body click");
});

// bodyClickEvent.remove();

addEventListener() creates an EventListener object, adds it to EventListeners and returns the EventListener object, so it can be removed later.

EventListeners.get() can be used to view the listeners in the page. It accepts an EventTarget or a string (event type).

// EventListeners.get(document.body);
// EventListeners.get("click");

Demo

Let's say we want to know every event listener in this current page. We can do that (assuming you're using a script manager extension, Tampermonkey in this case). Following script does this:

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include      https://stackoverflow.com/*
// @grant        none
// ==/UserScript==

(function() {
    fetch("https://raw.githubusercontent.com/akinuri/js-lib/master/event/event-listeners/event-listeners.js")
        .then(function (response) {
            return response.text();
        })
        .then(function (text) {
            eval(text);
            window.EventListeners = EventListeners;
        });
})(window);

And when we list all the listeners, it says there are 299 event listeners. There "seems" to be some duplicates, but I don't know if they're really duplicates. Not every event type is duplicated, so all those "duplicates" might be an individual listener.

screenshot of console listing all event listeners in this page

Code can be found at my repository. I didn't want to post it here because it's rather long.


Update: This doesn't seem to work with jQuery. When I examine the EventListener, I see that the callback is

function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}

I believe this belongs to jQuery, and is not the actual callback. jQuery stores the actual callback in the properties of the EventTarget:

$(document.body).click(function () {
    console.log("jquery click");
});

enter image description here

To remove an event listener, the actual callback needs to be passed to the removeEventListener() method. So in order to make this work with jQuery, it needs further modification. I might fix that in the future.

Stratocumulus answered 28/6, 2018 at 9:21 Comment(0)
H
3

There exists nice jQuery Events extension :

enter image description here (topic source)

Historical answered 28/2, 2017 at 15:13 Comment(0)
L
3

Currently, Sep. 2023 in Firefox Browser 117.0.1, you can see this by clicking on the appropriate "event" button in the "Inspector" in the "Developer Tools" as shown below:

enter image description here

Lala answered 28/9, 2023 at 18:6 Comment(0)
P
2

changing these functions will allow you to log the listeners added:

EventTarget.prototype.addEventListener
EventTarget.prototype.attachEvent
EventTarget.prototype.removeEventListener
EventTarget.prototype.detachEvent

read the rest of the listeners with

console.log(someElement.onclick);
console.log(someElement.getAttribute("onclick"));
Pretentious answered 18/4, 2019 at 14:57 Comment(0)
G
1

For quickly listing and/or removing all event handlers on document or any element:

(only works in Chrome console because it uses getEventListeners(), see:
https://developer.chrome.com/docs/devtools/console/utilities/#getEventListeners-function
)

let list = [];
let targets = Array.from(document.querySelectorAll('*'));
targets.push(document);
targets.forEach((obj) => {
    let listeners = getEventListeners(obj);
    for (p in listeners) {
        listeners[p].forEach((l) => {
            removeEventListener(l.type, l.listener, l.useCapture);
            list.push([obj, l.type, l.listener, '' + l.listener, l.useCapture]);
        });
    }
});
console.table(list);


Or type in console (or code):

debugger;

to step through code to find what exactly happens when e.g. hovering over element.

debugger; also works great to halt halt any runaway loops.


Slightly related, to stop most loops (hacky, but works):

for (i = 0; i < 10000; i++) {
  clearTimeout(i);
  clearInterval(i);
  cancelAnimationFrame(i);
}
Gujarati answered 2/10, 2023 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.