How to find what code is run by a button/element in Chrome using Developer Tools

How to find what code is run by a button/element in Chrome using Developer Tools

I’m using Chrome and my own website.
What I know from the inside:
1) I have a form where people sign up by clicking this orange image-button:

2) I inspect it, and this is all it is:

3) At the top of the source code, there are tons of script sources. Of
course, I know which one the button calls, I coded it:
4) Within that file, you could find: $(“.formSend”).click(function() { … }); which is what is triggered by the button (to do a fairly complex form validation and submit) and what I want is to be able to find that using chrome dev tools on any website.
How can we find out where does the element call?

Listeners tab didn’t work for me
So then I tried looking the click event listeners, which seemed like a safe bet to me but… there’s no jquery2.js in there (and I wouldn’t really know which file the code is so I’d waste time checking all these…):

My $(“.formSend”).click(function() { … }); function within jquery2.js file is not there.
Jesse explains why down in his answer:

“Finally, the reason why your function is not directly bound to the click event handler is because jQuery returns a function that gets bound. jQuery’s function in turn goes through some abstraction layers and checks, and somewhere in there, it executes your function.”

EDIT: I’ve collected all the methods this question arose in one answer down below as suggested by some of you.


Solution 1:

Alexander Pavlov’s answer gets the closest to what you want.

Due to the extensiveness of jQuery’s abstraction and functionality, a lot of hoops have to be jumped in order to get to the meat of the event. I have set up this jsFiddle to demonstrate the work.

1. Setting up the Event Listener Breakpoint

You were close on this one.

  1. Open the Chrome Dev Tools (F12), and go to the Sources tab.
  2. Drill down to Mouse -> Click
    Chrome Dev Tools -> Sources tab -> Mouse -> Click
    (click to zoom)

2. Click the button!

Chrome Dev Tools will pause script execution, and present you with this beautiful entanglement of minified code:

Chrome Dev Tools paused script execution
(click to zoom)

3. Find the glorious code!

Now, the trick here is to not get carried away pressing the key, and keep an eye out on the screen.

  1. Press the F11 key (Step In) until desired source code appears
  2. Source code finally reached
    • In the jsFiddle sample provided above, I had to press F11 108 times before reaching the desired event handler/function
    • Your mileage may vary, depending on the version of jQuery (or framework library) used to bind the events
    • With enough dedication and time, you can find any event handler/function

Desired event handler/function

4. Explanation

I don’t have the exact answer, or explanation as to why jQuery goes through the many layers of abstractions it does – all I can suggest is that it is because of the job it does to abstract away its usage from the browser executing the code.

Here is a jsFiddle with a debug version of jQuery (i.e., not minified). When you look at the code on the first (non-minified) breakpoint, you can see that the code is handling many things:

    // ...snip...

    if ( !(eventHandle = elemData.handle) ) {
        eventHandle = elemData.handle = function( e ) {
            // Discard the second event of a jQuery.event.trigger() and
            // when an event is called after a page has unloaded
            return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
                jQuery.event.dispatch.apply( elem, arguments ) : undefined;

    // ...snip...

The reason I think you missed it on your attempt when the “execution pauses and I jump line by line“, is because you may have used the “Step Over” function, instead of Step In. Here is a StackOverflow answer explaining the differences.

Finally, the reason why your function is not directly bound to the click event handler is because jQuery returns a function that gets bound. jQuery’s function in turn goes through some abstraction layers and checks, and somewhere in there, it executes your function.

Solution 2:

Solution 1: Framework blackboxing

Works great, just a bit of set up but no third parties.

Edit: Since writing this solution, Chrome (and other browsers too I’m sure) has made it easier to blackbox scripts.

According to Chrome’s documentation:

What happens when you blackbox a script?

Exceptions thrown from library code will not pause (if Pause on
exceptions is enabled), Stepping into/out/over bypasses the library
code, Event listener breakpoints don’t break in library code, The
debugger will not pause on any breakpoints set in library code. The
end result is you are debugging your application code instead of third
party resources.

Here’s the updated workflow:

  1. Pop open Chrome Developer Tools (F12 or ++i), go to settings (upper right, or F1). Find a tab on the left called “Blackboxing

enter image description here

  1. And this is where you put the RegEx pattern of the files you want to avoid passing through. For example: jquery\..*\.js (human translation: jquery.*.js)
  2. If you want to skip files with multiple patterns you can add them using the pipe character like so: jquery\..*\.js|include\.postload\.js. Or just keep adding them with the “Add” button.
  3. Now apply Solution 3 described down bellow.

Bonus tip: I use Regex101 (but there are many others) to quickly test my rusty regex patterns and find out where I’m wrong with the regex step-by-step debugger.

You can also use the context menu when working in the Sources panel. When viewing a file you can right-click in the editor. And you can right-click on a file in the file navigator. From there choose Blackbox Script. This will add the file to the list in the Settings panel:

enter image description here

Solution 2: Visual Event

enter image description here

It’s a good tool to have.

Solution 3: Going through code

This kind of painful but easy (blackboxing will prove very hepful here).

  1. Opening Dev Tools -> Sources tab, and on the right find Event
    Listener Breakpoints

    enter image description here

  2. Expand Mouse and click on… well, click.

  3. Now click the element (execution should pause) and here starts the game: just start pressing F11 (which is Step in) to go through all code. Sit tight, there can be a ton of jumps.

Solution 4: Survival mode

I’m always left with ++F or:

enter image description here

and searching #envio or whatever the tag/class/id you think starts the party, reading all findings to try figure out what code could be running, feeling a loser and feeling that there’s got to be a safe way of really knowing WHAT is triggered by the button.

But be aware sometimes there’s not only an img but tons of divs overlapping, and you can’t even know what triggers the code. You probably shouldn’t have to use this method.

Solution 3:

Sounds like the “…and I jump line by line…” part is wrong. Do you StepOver or StepIn and are you sure you don’t accidentally miss the relevant call?

That said, debugging frameworks can be tedious for exactly this reason. To alleviate the problem, you can enable the “Enable frameworks debugging support” experiment. Happy debugging! 🙂

Solution 4:

You can use findHandlersJS

Solution 5:

This solution needs the jQuery’s data method.

  1. Open Chrome’s console (although any browser with jQuery loaded will work)
  2. Run $._data($(".example").get(0), "events")
  3. Drill down the output to find the desired event handler.
  4. Right-click on “handler” and select “Show function definition”
  5. The code will be shown in the Sources tab

$._data() is just accessing jQuery’s data method. A more readable alternative could be jQuery._data().

Interesting point by this SO answer:

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

A version agnostic jQuery would be: (jQuery._data ||, 'events');