Quickly finding and debugging jQuery event handlers with findHandlersJS

I moved my blog to www.blinkingcaret.com. It has a new design an lots of great new blog posts.

Click here to read this post there.

tl;dr: Finding event handlers registered using jQuery can be tricky. findHandlersJS makes finding them easy, all you need is the event type and a jQuery selector for the elements where the events might originate. Examples can be found here. A working page with findHandlersJS loaded and ready to try can be found here.


Events and event handling are an important part of client-side development. Frequently we are tasked with changing their behavior and part of that process involves locating which methods handle which events. Unfortunately sometimes they can be difficult to locate, especially when we are dealing with a code base that we are not familiar with.

In this blog post I’ll describe an alternative that hopefully makes finding event handlers easier, in particular, event handlers registered using jQuery.

But first let’s look at how we can register an event handler using javascript.

Registering events and event bubbling with plain javascript

You can add event handlers in javascript using the addEventListnerMethod:

Html

<input type="button" id="myButton" value="Click me"/>
<span id="myLabel"></span>

Javascript

document.getElementById('myButton').addEventListener("click", function(event){ 
    //this is the event handler for the click event in myButton
    document.getElementById('myLabel').innerText=event.target.id + " was clicked"; 
});

Check it out here

One important thing to be aware about events is that they bubble. What this means is that every element in the hierarchy until the root element of the html will have a chance to handle the event.

Imagine this is describes your html page:

document 
    div
        p
          button

You can register an event handler on the button, in the paragraph that contains the button, the div that contains the paragraph or the document itself. They will all “see” the event. This is the reason why it is sometimes difficult to find where the particular event we are interested in is being handled. For example, the next example exhibits the same behavior as the previous one:

Html

<input type="button" id="myButton" value="Click me"/>
<span id="myLabel"></span>

Javascript

document.addEventListener("click", function(event){
    //this is the event handler for the click event that will be used if you click any element in the page
    document.getElementById('myLabel').innerText=event.target.id + " was clicked";
});

Try it here

Although this seems to produce the same end result, if you would go look for the event handler in the button itself, you would not find it.

Why would you use this technique then? This technique is popular when parts of the web page are injected via ajax calls. The document object is part of the page’s header object so you can always rely on document being available (which is handy if part of the webpage is going to be fetched sometime in the future), and register your event handlers there.

Registering direct and delegated events using jQuery

With jQuery, event handlers are registered using the .on keyword.

jQuery makes the distinction between event handlers that only handle events triggered in the element they were registered on (direct events handlers) and event handlers that handle events that were triggered in a subset of the children of the element they were registered in (delegate event handlers). The subset of the children is specified through a jQuery selector.

Here’s an example of a direct event handler that handles clicks in a button:

Html

<input type="button" id="myButton" value="Click me"/>
<span id="myLabel"></span>

Javascript

$(function(){
    $('#myButton').on("click", function(event){
        $('#myLabel').text(event.target.id + " was clicked");
    });
});

Try it here

Here’s an example of a delegate event handler that handles clicks in all buttons that exist now or that might be added in the future in the whole page:

Delegated events

Html

<input type="button" id="myButton" value="Click me"/>
<span id="myLabel"></span>

Javascript

$(function(){
    $(document).on("click", ":button", function(event){
        $('#myLabel').text(event.target.id + " was clicked");
    });
});

Try it here

The best place to find out more about delegate and direct events is the .on documentation page.

Finding event handlers using Chrome dev tools

Browser dev tools help you find event handlers, for example in Chrome you can right click anywhere in the page, for example on a button, and select “Inspect Element”. The event handlers will be shown in the Event Listeners tab (right side of the elements tab).

Event Listeners tab on chrome

A very handy feature of the tooling is that you can right click the “handler” and select show function definition:

Show Function Definition on Chrome

You can then add breakpoints and debug the event handlers. However if you use events registered with jQuery, you will see jQuery’s event handler. This is because jQuery adds additional functionality to the normal event handlers. This is one of the complicating factors that makes finding the actual event handlers we are interested in more difficult.

If you use findHandlersJS instead you’ll get directly to the actual event handlers.

findHandlersJS (works best in chrome)

The idea is that by specifying an event type (e.g. “click”), and which elements you are interested in, using a jQuery selector, you get all the event handlers that are triggered when you click one of the elements that are covered by the selector you specified.

Here’s an example

Imagine you are working on this web page:

simple form with save and cancel buttons

And you want to debug the event handler for the Save button. After you include findHandlersJS you could write in chrome’s console:

findEventHandlers("click", ":button:contains('Save')")

That would provide you with the following information

save button information from findHandlersJS

  • 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 then hoover over the element property and chrome will highlight the element where the event handler was registered:

highlight of element where the save event handler was registered

You can also hover over function on the handler property and select Show function definition. That will show you the source code for that event handler. You can add breakpoints and debug the event handler method.

click show function definition source code for save

More examples:

findEventHandlers(“click”, “div#itemList :button”) would return information about all the jquery event handlers (direct or delegated) that handle a click in the buttons inside a div with id “itemList”.

findEventHandlers(“click”, “*”) returns all click event handlers, including those registered on the document object

findEventHandlers(“change”, document) returns the change event handlers registered on the document object

findEventHandlers(“addNewItem”, “div#items :button:nth(3)”) all event handlers that handle the custom event addNewItem for the the fourth button inside the div with id=”items”

Try these examples here.

You can get findHandlersJS in github here. You can just copy and paste the raw javascript code to chrome’s console window and just start using it, or if you want to use it in your project just make sure you add it after jQuery (I’ve tested it in versions >= 1.7.1. Might also work with older versions).

Any comments/suggestions are welcomed.


Was this post helful to you? Do you use Windows 8.1 or Windows Phone 8.1? If so check out my game, Memory Ace, it’s an educational game that teaches memorization techniques. With a little bit of training I’ve used it to memorize a full deck of cards without much effort. It’s great for keeping those neurons healthy!

Get the Windows 8.1 store version here.

Get the Windows Phone 8.1 version here.

Also for Windows Phone check out Lectito, it’s a speed reader that you can launch from the browser.

Lectito speed reader for windows phone

Get it here.


8 Comments on “Quickly finding and debugging jQuery event handlers with findHandlersJS”

  1. […] Mais informação sobre findHandlersJS aqui(esta em inglês). […]

  2. J says:

    You’re a fucking genius!!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s