[jquery] jQuery find events handlers registered with an object

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?

This question is related to jquery events dom

The answer is


jQuery is not letting you just simply access the events for a given element. You can access them using undocumented internal method

$._data(element, "events")

But it still won't give you all the events, to be precise won't show you events assigned with

$([selector|element]).on()

These events are stored inside document, so you can fetch them by browsing through

$._data(document, "events")

but that is hard work, as there are events for whole webpage.

Tom G above created function that filters document for only events of given element and merges output of both methods, but it had a flaw of duplicating events in the output (and effectively on the element's jQuery internal event list messing with your application). I fixed that flaw and you can find the code below. Just paste it into your dev console or into your app code and execute it when needed to get nice list of all events for given element.

What is important to notice, element is actually HTMLElement, not jQuery object.

function getEvents(element) {
    var elemEvents = $._data(element, "events");
    var allDocEvnts = $._data(document, "events");
    function equalEvents(evt1, evt2)
    {
        return evt1.guid === evt2.guid;
    }

    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] = [];
                    }
                    if(!elemEvents[evntType].some(function(evt) { return equalEvents(evt, evts[i]); })) {
                        elemEvents[evntType].push(evts[i]);
                    }
                }
            }
        }
    }
    return elemEvents;
}


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:

_x000D_
_x000D_
$(function() {_x000D_
  $("#el").click(function(){ alert("click"); });_x000D_
  $("#el").mouseover(function(){ alert("mouseover"); });_x000D_
_x000D_
  $.each($._data($("#el")[0], "events"), function(i, event) {_x000D_
    output(i);_x000D_
    $.each(event, function(j, h) {_x000D_
        output("- " + h.handler);_x000D_
    });_x000D_
  });_x000D_
});_x000D_
_x000D_
function output(text) {_x000D_
    $("#output").html(function(i, h) {_x000D_
        return h + text + "<br />";_x000D_
    });_x000D_
}
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>_x000D_
<div id="el">Test</div>_x000D_
<code>_x000D_
    <span id="output"></span>_x000D_
</code>
_x000D_
_x000D_
_x000D_


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

    // jQuery version < 1.7.?
    if (typeof(this.data) === 'function') {
        return this.data('events') || {};
    }

    return {};
};

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


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;

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.


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.


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


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

I combined some of the answers above and created this crazy looking but functional script that lists hopefully most of the event listeners on the given element. Feel free to optimize it here.

_x000D_
_x000D_
var element = $("#some-element");_x000D_
_x000D_
// sample event handlers_x000D_
element.on("mouseover", function () {_x000D_
  alert("foo");_x000D_
});_x000D_
_x000D_
$(".parent-element").on("mousedown", "span", function () {_x000D_
  alert("bar");_x000D_
});_x000D_
_x000D_
$(document).on("click", "span", function () {_x000D_
  alert("xyz");_x000D_
});_x000D_
_x000D_
var collection = element.parents()_x000D_
  .add(element)_x000D_
  .add($(document));_x000D_
collection.each(function() {_x000D_
  var currentEl = $(this) ? $(this) : $(document);_x000D_
  var tagName = $(this)[0].tagName ? $(this)[0].tagName : "DOCUMENT";_x000D_
  var events = $._data($(this)[0], "events");_x000D_
  var isItself = $(this)[0] === element[0]_x000D_
  if (!events) return;_x000D_
  $.each(events, function(i, event) {_x000D_
    if (!event) return;_x000D_
    $.each(event, function(j, h) {_x000D_
      var found = false;        _x000D_
      if (h.selector && h.selector.length > 0) {_x000D_
        currentEl.find(h.selector).each(function () {_x000D_
          if ($(this)[0] === element[0]) {_x000D_
            found = true;_x000D_
          }_x000D_
        });_x000D_
      } else if (!h.selector && isItself) {_x000D_
        found = true;_x000D_
      }_x000D_
_x000D_
      if (found) {_x000D_
        console.log("################ " + tagName);_x000D_
        console.log("event: " + i);_x000D_
        console.log("selector: '" + h.selector + "'");_x000D_
        console.log(h.handler);_x000D_
      }_x000D_
    });_x000D_
  });_x000D_
});
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>_x000D_
_x000D_
<div class="parent-element">_x000D_
  <span id="some-element"></span>_x000D_
</div>
_x000D_
_x000D_
_x000D_


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

I use eventbug plugin to firebug for this purpose.


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

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.


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


Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to events

onKeyDown event not working on divs in React Detect click outside Angular component Angular 2 Hover event Global Events in Angular How to fire an event when v-model changes? Passing string parameter in JavaScript function Capture close event on Bootstrap Modal AngularJs event to call after content is loaded Remove All Event Listeners of Specific Type Jquery .on('scroll') not firing the event while scrolling

Examples related to dom

How do you set the document title in React? How to find if element with specific id exists or not Cannot read property 'style' of undefined -- Uncaught Type Error adding text to an existing text element in javascript via DOM Violation Long running JavaScript task took xx ms How to get `DOM Element` in Angular 2? Angular2, what is the correct way to disable an anchor element? React.js: How to append a component on click? Detect click outside React component DOM element to corresponding vue.js component