jQuery find events handlers registered with an object

460,680

Solution 1

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" );

Solution 2

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>

Solution 3

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

Solution 4

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

Solution 5

I use eventbug plugin to firebug for this purpose.

Share:
460,680
ages04
Author by

ages04

Updated on March 27, 2020

Comments

  • ages04
    ages04 about 4 years

    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?

  • bullgare
    bullgare over 11 years
    but you can still use $._data($(elem).get(0), "events")
  • Sam Greenhalgh
    Sam Greenhalgh over 11 years
    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.
  • Michal Stefanow
    Michal Stefanow over 11 years
    $._data("body", "events") undefined $().jquery; "1.7.1" (tried 1.7.2 and 1.8.1 all the time "undefined")
  • PhistucK
    PhistucK over 11 years
    @Michal - api.jquery.com/jQuery.data says it accepts an element, not a selector.
  • Michal Stefanow
    Michal Stefanow over 11 years
    Now works fine: $._data($("body").get(0), "events") Or even better: $("body").data("events") !
  • Timo Kähkönen
    Timo Kähkönen over 11 years
    Works with 1.4, but not in jQuery 1.8.2.
  • gnarf
    gnarf over 11 years
    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.
  • gnarf
    gnarf over 11 years
    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"
  • Gruber
    Gruber about 11 years
    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
    clayzermk1 about 11 years
    Also, Chrome Developer Tools has "Event Listeners" under the "Elements" tab and "Event Listener Breakpoints" under the "Sources" tab.
  • Ian
    Ian almost 11 years
    The accepted answer also clearly shows the new, correct way to get it for recent versions: jQuery._data( elem, "events" );...
  • oligofren
    oligofren almost 11 years
    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
    Ian almost 11 years
    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
    Ian almost 11 years
    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
    oligofren almost 11 years
    Your reasoning on the Migrate plugin seems reasonable. OK if I delete my answer?
  • Jim
    Jim about 9 years
    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
    Adib Aroui almost 9 years
    @jim yeaaah, the double click is the answer
  • oriadam
    oriadam over 8 years
    Seamlessly support both options: var events = (jQuery._data || jQuery.data)(elem, 'events');
  • Emile Bergeron
    Emile Bergeron about 8 years
    I think that jQuery does event handling optimization which I think is circumvented by your code here.
  • tempranova
    tempranova about 8 years
    Thanks, yeah I had a feeling this was hacky - any good link to learn more about that optimization?
  • Admin
    Admin almost 8 years
    function events(e) { $(e).each(function(){console.log(this);console.log($._data( this, "events" ));console.log("\n")}) } A quick function yet useful
  • Mike W
    Mike W about 7 years
    jQuery(document).data('events') gives me undefined
  • Mike W
    Mike W about 7 years
    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
    Jesan Fafon about 7 years
    'ct100_ContentPlaceHolder1_lcsSection' is a string, not a DOM Element.
  • ScottyG
    ScottyG almost 7 years
    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
  • themhz
    themhz over 6 years
    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
  • Paul Allsopp
    Paul Allsopp about 6 years
    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
    enorl76 about 6 years
    @CrazyMerlin ok, thanks for that. Now maybe you have a better answer?
  • Dominik Szymański
    Dominik Szymański about 4 years
    This getEvents method is overally great, but the thing is, it gives duplicate entries in IE11 (I know, IE again, but corporate needs it...). EDIT: $._data contains duplicate events for element, even though on FF it doesn't contain any... Weird IE world. But it's important to watch out for this possibility of having duplicate events.
  • Dominik Szymański
    Dominik Szymański about 4 years
    Oh, Tom, it's actually your code that's multiplying events with each execution of this method. Not good.
  • Rajat
    Rajat over 3 years
    it's returning undefined.