Home » Jquery » jQuery find events handlers registered with an object

jQuery find events handlers registered with an object

Posted by: admin November 2, 2017 Leave a comment

Questions:

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?

Answers:

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

Questions:
Answers:

You can do it like this:

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

$.each($("#el").data("events"), function(i, e) {
    alert(i);
});
//alerts 'click' then 'mouseover'

If you’re on jQuery 1.4+, this will alert the event and functions bound to it:

$.each($("#el").data("events"), function(i, event) {
    alert(i);
    $.each(event, function(j, h) {
        alert(h.handler);
    });
});
//alerts: 
//'click'
//'function (){ alert("click"); }'
//'mouseover'
//'function(){ alert("mouseover"); }'

​You can play with it on jsFiddle here

Questions:
Answers:

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

Questions:
Answers:

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

Questions:
Answers:

I use eventbug plugin to firebug for this purpose.

Questions:
Answers:

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 that events that was setted with jQuery itself.

Questions:
Answers:

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.

Questions:
Answers:

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.

Questions:
Answers:

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

Questions:
Answers:

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

Questions:
Answers:

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;

Questions:
Answers:

Try jquery debugger plugin if you’re using chrome: https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi?hl=en