By ages04


2010-03-25 18:47:08 8 Comments

I need to find which event handlers are registered over an object.

For example:

$("#el").click(function() {...});
$("#el").mouseover(function() {...});

$("#el") has click and mouseover registered.

Is there a function to find out that, and possibly iterate over the event handlers?

If it is not possible on a jQuery object through proper methods, is it possible on a plain DOM object?

14 comments

@Nick Craver 2010-03-25 20:21:13

You can do it by crawling the events (as of jQuery 1.8+), like this:

$.each($._data($("#id")[0], "events"), function(i, event) {
  // i is the event type, like "click"
  $.each(event, function(j, h) {
    // h.handler is the function being called
  });
});

Here's an example you can play with:

$(function() {
  $("#el").click(function(){ alert("click"); });
  $("#el").mouseover(function(){ alert("mouseover"); });

  $.each($._data($("#el")[0], "events"), function(i, event) {
    output(i);
    $.each(event, function(j, h) {
        output("- " + h.handler);
    });
  });
});

function output(text) {
    $("#output").html(function(i, h) {
        return h + text + "<br />";
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="el">Test</div>
<code>
    <span id="output"></span>
</code>

@Andrew Ensley 2010-12-29 19:58:19

This is the correct answer. The crucial bit is the second half. This helped me find an issue in under a minute that would have taken over an hour if I had to search through all the code. Thank you!

@Timo Kähkönen 2012-12-21 21:15:00

Works with 1.4, but not in jQuery 1.8.2.

@gnarf 2013-01-10 17:13:58

For jQuery 1.8+, you must use the 'private data' method: jQuery._data( jQuery("#el")[0], "events" ); instead of the 'public data' method: jQuery("#el").data("events"). The events object hasn't actually been stored in .data() for a long time, we trimmed a few bytes of code out by removing this "proxy" from the "public API"

@algorhythm 2014-11-12 16:48:08

I've combined both solutions from @jps to one function:

jQuery.fn.getEvents = function() {
    if (typeof(jQuery._data) == 'function') {
        return jQuery._data(this.get(0), 'events') || {};
    } else if (typeof(this.data) == 'function') { // jQuery version < 1.7.?
        return this.data('events') || {};
    }
    return {};
};

But beware, this function can only return events that were set using jQuery itself.

@Tom G 2018-08-30 15:39:11

To check for events on an element:

var events = $._data(element, "events")

Note that this will only work with direct event handlers, if you are using $(document).on("event-name", "jq-selector", function() { //logic }), you will want to see the getEvents function at the bottom of this answer

For example:

 var events = $._data(document.getElementById("myElemId"), "events")

or

 var events = $._data($("#myElemId")[0], "events")

Full Example:

<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
        <script>
            $(function() {
                $("#textDiv").click(function() {
                    //Event Handling
                });
                var events = $._data(document.getElementById('textDiv'), "events");
                var hasEvents = (events != null);
            });
        </script>
    </head>
    <body>
        <div id="textDiv">Text</div>
    </body>
</html>

A more complete way to check, that includes dynamic listeners, installed with $(document).on

function getEvents(element) {
    var elemEvents = $._data(element, "events");
    var allDocEvnts = $._data(document, "events");
    for(var evntType in allDocEvnts) {
        if(allDocEvnts.hasOwnProperty(evntType)) {
            var evts = allDocEvnts[evntType];
            for(var i = 0; i < evts.length; i++) {
                if($(element).is(evts[i].selector)) {
                    if(elemEvents == null) {
                        elemEvents = {};
                    }
                    if(!elemEvents.hasOwnProperty(evntType)) {
                        elemEvents[evntType] = [];
                    }
                    elemEvents[evntType].push(evts[i]);
                }
            }
        }
    }
    return elemEvents;
}

Example usage:

getEvents($('#myElemId')[0])

@Erutan409 2017-11-07 19:34:42

I created a custom jQuery selector that checks against both jQuery's cache of assigned event handlers as well as elements that use the native method for adding them:

(function($){

    $.find.selectors[":"].event = function(el, pos, match) {

        var search = (function(str){
            if (str.substring(0,2) === "on") {str = str.substring(2);}
            return str;
        })(String(match[3]).trim().toLowerCase());

        if (search) {
            var events = $._data(el, "events");
            return ((events && events.hasOwnProperty(search)) || el["on"+search]);
        }

        return false;

    };

})(jQuery);

Example:

$(":event(click)")

This will return elements that have a click handler attached to them.

@Marquinho Peli 2016-08-15 15:32:47

@tempranova 2016-04-06 09:32:48

Another way to do it is to just use jQuery to grab the element, then go through actual Javascript to get and set and play with the event handlers. For instance:

var oldEventHandler = $('#element')[0].onclick;
// Remove event handler
$('#element')[0].onclick = null;
// Switch it back
$('#element')[0].onclick = oldEventHandler;

@Emile Bergeron 2016-04-07 18:44:46

I think that jQuery does event handling optimization which I think is circumvented by your code here.

@tempranova 2016-04-07 23:44:18

Thanks, yeah I had a feeling this was hacky - any good link to learn more about that optimization?

@Emile Bergeron 2016-04-08 15:03:24

I don't remember where I read that and I can't find it right now...

@Rui 2014-01-21 15:05:29

Shameless plug, but you can use findHandlerJS

To use it you just have to include findHandlersJS (or just copy&paste the raw javascript code to chrome's console window) and specify the event type and a jquery selector for the elements you are interested in.

For your example you could quickly find the event handlers you mentioned by doing

findEventHandlers("click", "#el")
findEventHandlers("mouseover", "#el")

This is what gets returned:

  • element
    The actual element where the event handler was registered in
  • events
    Array with information about the jquery event handlers for the event type that we are interested in (e.g. click, change, etc)
    • handler
      Actual event handler method that you can see by right clicking it and selecting Show function definition
    • selector
      The selector provided for delegated events. It will be empty for direct events.
    • targets
      List with the elements that this event handler targets. For example, for a delegated event handler that is registered in the document object and targets all buttons in a page, this property will list all buttons in the page. You can hover them and see them highlighted in chrome.

You can try it here

@Marquinho Peli 2016-08-19 23:09:26

I think that should be the accepted answer. That's the only one that works for me too. It's very thorough since goes through all elements searching for events.

@R. Oosterholt 2012-07-26 06:04:10

Events can be retrieved using:

jQuery(elem).data('events');

or jQuery 1.8+:

jQuery._data(elem, 'events');

Note: Events bounded using $('selector').live('event', handler) can be retrieved using:

jQuery(document).data('events')

@Mike W 2017-03-17 20:28:18

jQuery(document).data('events') gives me undefined

@Jesan Fafon 2014-05-06 22:55:24

In a modern browser with ECMAScript 5.1 / Array.prototype.map, you can also use

jQuery._data(DOCUMENTELEMENT,'events')["EVENT_NAME"].map(function(elem){return elem.handler;});

in your browser console, which will print the source of the handlers, comma delimited. Useful for glancing at what all is running on a particular event.

@Mike W 2017-03-17 20:30:18

jQuery._data('ct100_ContentPlaceHolder1_lcsSection','events'‌​)["EVENT_NAME"].map(‌​function(elem){retur‌​n elem.handler;}); Uncaught TypeError: Cannot read property 'EVENT_NAME' of undefined at <anonymous>:1:62

@Jesan Fafon 2017-03-17 21:45:54

'ct100_ContentPlaceHolder1_lcsSection' is a string, not a DOM Element.

@pid 2014-10-14 14:44:01

I have to say many of the answers are interesting, but recently I had a similar problem and the solution was extremely simple by going the DOM way. It is different because you don't iterate but aim directly at the event you need, but below I'll give a more general answer.

I had an image in a row:

<table>
  <td><tr><img class="folder" /></tr><tr>...</tr></td>
</table>

And that image had a click event handler attached to it:

imageNode.click(function () { ... });

My intention was to expand the clickable area to the whole row, so I first got all images and relative rows:

tableNode.find("img.folder").each(function () {
  var tr;

  tr = $(this).closest("tr");
  // <-- actual answer
});

Now in the actual anwer line I just did as follows, giving an answer to the original question:

tr.click(this.onclick);

So I fetched the event handler directly from the DOM element and put it into the jQuery click event handler. Works like a charm.

Now, to the general case. In the old pre-jQuery days you could get all events attached to an object with two simple yet powerful functions gifted to us mortals by Douglas Crockford:

function walkTheDOM(node, func)
{
  func(node);
  node = node.firstChild;
  while (node)
  {
    walkTheDOM(node, func);
    node = node.nextSibling;
  }
}

function purgeEventHandlers(node)
{
  walkTheDOM(node, function (n) {
    var f;

    for (f in n)
    {
      if (typeof n[f] === "function")
      {
        n[f] = null;
      }
    }
  });
}

@oligofren 2013-04-03 08:32:31

As of 1.9 there is no documented way to retrieve the events, other than to use the Migrate plugin to restore the old behavior. You could use the _.data() method as jps mentions, but that is an internal method. So just do the right thing and use the Migrate plugin if you need this functionality.

From the jQuery documentation on .data("events")

Prior to 1.9, .data("events") could be used to retrieve jQuery's undocumented internal event data structure for an element if no other code had defined a data element with the name "events". This special case has been removed in 1.9. There is no public interface to retrieve this internal data structure, and it remains undocumented. However, the jQuery Migrate plugin restores this behavior for code that depends upon it.

@Ian 2013-05-23 21:21:28

The accepted answer also clearly shows the new, correct way to get it for recent versions: jQuery._data( elem, "events" );...

@oligofren 2013-05-27 09:49:16

A private, undocumented way will never be a correct way. The correct way - meaning documented, public, and intended - is to use the Migrate plugin.

@Ian 2013-05-28 15:17:09

You seem to misunderstand the point of the Migrate plugin. jQuery removed deprecated features, and the Migrate plugin is to help migrate developer's code to the newer versions so that they can immediately take advantage of new features and improvements, but not lose functionality. It's meant to help the coder see what they need to do in order to start properly using new versions of jQuery. You shouldn't use it in production to restore features. Also, many things aren't documented and up to date in jQuery documentation - they've pointed it out before, so that's not a reason

@Ian 2013-05-28 15:17:56

Also, if it's included as a suggestion in the jQuery blog, I'd use it: blog.jquery.com/2012/08/09/jquery-1-8-released

@oligofren 2013-05-28 15:41:22

Your reasoning on the Migrate plugin seems reasonable. OK if I delete my answer?

@Ian 2013-05-28 15:55:12

I wasn't trying to just shoot you down, I just like being open to options. I'll remove my downvote as these comments now add information. But it's up to you if you want to delete. The plugin is still an option because it clearly restores the .data("events") functionality, but it has its limitations and will more in the future.

@jps 2010-03-25 18:50:43

As of jQuery 1.8, the event data is no longer available from the "public API" for data. Read this jQuery blog post. You should now use this instead:

jQuery._data( elem, "events" );

elem should be an HTML Element, not a jQuery object, or selector.

Please note, that this is an internal, 'private' structure, and shouldn't be modified. Use this for debugging purposes only.

In older versions of jQuery, you might have to use the old method which is:

jQuery( elem ).data( "events" );

@Tarsis Azevedo 2011-10-05 20:59:22

great! It works for me

@Skylar Saveland 2012-08-17 18:21:37

@bullgare 2012-08-18 11:01:37

but you can still use $._data($(elem).get(0), "events")

@Sam Greenhalgh 2012-08-20 03:41:28

blog.jquery.com/2011/11/08/building-a-slimmer-jquery .data(“events”): jQuery stores its event-related data in a data object named (wait for it) events on each element. This is an internal data structure so in 1.8 this will be removed from the user data name space so it won’t conflict with items of the same name. jQuery’s event data can still be accessed via jQuery._data(element, "events") but be aware that this is an internal data structure that is undocumented and should not be modified.

@gnarf 2013-01-10 17:07:07

@SamGreenhalgh I edited the answer to include your information, that old way was forever removed in 1.8 (finally!), so it's worth updating the answer.

@oligofren 2013-04-03 08:33:02

This is no longer valid. As of 1.9 this has been removed.

@podperson 2013-07-24 19:40:31

Really? It's working for me with 1.10/2.0 for me.

@Andy Gee 2013-08-22 13:28:23

A new jsfiddle for post jquery 1.8 releases is here jsfiddle.net/9n6gh

@Jim 2015-02-09 10:34:38

I've been using this method to try and find out the click event of a button. In the Chrome console it showed handler: function () { inside the click property. I had to double click on the function part for it to expand and show the full contents of the function.

@Adib Aroui 2015-05-18 22:38:30

@jim yeaaah, the double click is the answer

@oriadam 2015-12-31 06:05:27

Seamlessly support both options: var events = (jQuery._data || jQuery.data)(elem, 'events');

@user4584267 2016-06-02 01:20:22

function events(e) { $(e).each(function(){console.log(this);console.log($._data( this, "events" ));console.log("\n")}) } A quick function yet useful

@mzalazar 2016-07-05 20:49:31

JQuery 1.8+ jQuery._data( document.getElementById('myElement'), 'events' );

@ScottyG 2017-08-02 19:21:19

Worked great for me! Thanks! I used this to help write a testHandler function to test if a specific handler is attached to an objects event. stackoverflow.com/a/45448636/2512022

@themis 2017-12-07 16:07:17

can you get all the events of an element save them on a variable unbind the element and the rebind it? I need to disable a a href element and then rebind it after an event is complete

@CrazyMerlin 2018-03-21 17:19:59

No! You should not be referencing method that start with an underscore. This is a hack. Those methods are private class methods, it's just that JS doesn't have proper classes so everything is exposed. This is just a bad development hack

@enorl76 2018-04-09 18:44:55

@CrazyMerlin ok, thanks for that. Now maybe you have a better answer?

@PhistucK 2012-07-05 11:38:18

For jQuery 1.8+, this will no longer work because the internal data is placed in a different object.

The latest unofficial (but works in previous versions as well, at least in 1.7.2) way of doing it now is - $._data(element, "events")

The underscore ("_") is what makes the difference here. Internally, it is calling $.data(element, name, null, true), the last (fourth) parameter is an internal one ("pvt").

@Mars Robertson 2012-09-12 12:02:19

$._data("body", "events") undefined $().jquery; "1.7.1" (tried 1.7.2 and 1.8.1 all the time "undefined")

@PhistucK 2012-09-12 15:08:35

@Michal - api.jquery.com/jQuery.data says it accepts an element, not a selector.

@Mars Robertson 2012-09-13 11:12:17

Now works fine: $._data($("body").get(0), "events") Or even better: $("body").data("events") !

@gnarf 2013-01-10 17:11:09

FWIW - Pointing out that it 'internally' calls the other data function with a parameter we specifically don't document probably isn't needed. But yes, jQuery._data( element, "events" ) is the 'correct' way to get this information now.

@Anton 2012-07-26 06:10:30

I use eventbug plugin to firebug for this purpose.

@Gruber 2013-02-26 08:17:35

Thanks, great tip. The extension adds a tab to Firebug ("Events") that shows the events of the page, so you can expore them easily.

@clayzermk1 2013-02-27 18:49:27

Also, Chrome Developer Tools has "Event Listeners" under the "Elements" tab and "Event Listener Breakpoints" under the "Sources" tab.

Related Questions

Sponsored Content

55 Answered Questions

[SOLVED] How do I check if an element is hidden in jQuery?

61 Answered Questions

[SOLVED] How to check whether a checkbox is checked in jQuery?

40 Answered Questions

[SOLVED] Is there an "exists" function for jQuery?

  • 2008-08-27 19:49:41
  • Jake McGraw
  • 715270 View
  • 2591 Score
  • 40 Answer
  • Tags:   javascript jquery

8 Answered Questions

[SOLVED] Why does jQuery or a DOM method such as getElementById not find the element?

13 Answered Questions

23 Answered Questions

[SOLVED] Event binding on dynamically created elements?

40 Answered Questions

[SOLVED] Setting "checked" for a checkbox with jQuery?

15 Answered Questions

[SOLVED] "Thinking in AngularJS" if I have a jQuery background?

16 Answered Questions

[SOLVED] How do I find out which DOM element has the focus?

  • 2009-01-30 20:21:31
  • Tony Peterson
  • 596825 View
  • 1190 Score
  • 16 Answer
  • Tags:   javascript dom

15 Answered Questions

Sponsored Content