How to debug JavaScript / jQuery event bindings with Firebug or similar tools?
Asked Answered
A

15

618

I need to debug a web application that uses jQuery to do some fairly complex and messy DOM manipulation. At one point, some of the events that were bound to particular elements, are not fired and simply stop working.

If I had a capability to edit the application source, I would drill down and add a bunch of Firebug console.log() statements and comment/uncomment pieces of code to try to pinpoint the problem. But let's assume I cannot edit the application code and need to work entirely in Firefox using Firebug or similar tools.

Firebug is very good at letting me navigate and manipulate the DOM. So far, though, I have not been able to figure out how to do event debugging with Firebug. Specifically, I just want to see a list of event handlers bound to a particular element at a given time (using Firebug JavaScript breakpoints to trace the changes). But either Firebug does not have the capability to see bound events, or I'm too dumb to find it. :-)

Any recommendations or ideas? Ideally, I would just like to see and edit events bound to elements, similarly to how I can edit DOM today.

Arrio answered 20/2, 2009 at 19:42 Comment(0)
D
356

See How to find event listeners on a DOM node.

In a nutshell, assuming at some point an event handler is attached to your element (eg): $('#foo').click(function() { console.log('clicked!') });

You inspect it like so:

  • jQuery 1.3.x

    var clickEvents = $('#foo').data("events").click;
    jQuery.each(clickEvents, function(key, value) {
      console.log(value) // prints "function() { console.log('clicked!') }"
    })
    
  • jQuery 1.4.x

    var clickEvents = $('#foo').data("events").click;
    jQuery.each(clickEvents, function(key, handlerObj) {
      console.log(handlerObj.handler) // prints "function() { console.log('clicked!') }"
    })
    

See jQuery.fn.data (where jQuery stores your handler internally).

  • jQuery 1.8.x

    var clickEvents = $._data($('#foo')[0], "events").click;
    jQuery.each(clickEvents, function(key, handlerObj) {
      console.log(handlerObj.handler) // prints "function() { console.log('clicked!') }"
    })
    
Dowling answered 20/2, 2009 at 20:21 Comment(8)
FYI: This will not display events that weren't attached with jQueryCounterespionage
Totally agree about console.log(), however it should be hedged with something like if (window.console) in case it gets left in the code (much easier to do than with alert()) and breaks IE.Seasonseasonable
@Seasonseasonable Personally I prefer to do a check for the console at the start of the file, and if it doesn't exist create a dummy object.Ideo
Below is a similar snippet for debugging all events (please excuse the lack of formatting): $('#foo').click(function(event) { var events = $(this).data('events'); $.each(events, function(event, handlers) { $.each(handlers, function(key, handlerObj) { console.log("--------------------------------------"); console.log(event+"["+key+"] | "+handlerObj.handler) ; }); });Pyxis
So how do you do it with events that weren't attached with jQuery?Kingwood
@BrainSlugs83: see the linked answer in this answer. (tl;dr: you can't).Dowling
console.debug() will write in the debug consoleAmitosis
@CrescentFresh How if I want to know where was attached $('#foo').click(function() { console.log('clicked!') });Pesthole
M
162

There's a nice bookmarklet called Visual Event that can show you all the events attached to an element. It has color-coded highlights for different types of events (mouse, keyboard, etc.). When you hover over them, it shows the body of the event handler, how it was attached, and the file/line number (on WebKit and Opera). You can also trigger the event manually.

It can't find every event because there's no standard way to look up what event handlers are attached to an element, but it works with popular libraries like jQuery, Prototype, MooTools, YUI, etc.

Marika answered 20/2, 2009 at 19:52 Comment(1)
Note that since this runs in content JavaScript, it gets its data by querying JavaScript libraries. So it will only show events added with a supported library (which includes jQuery).Corkhill
S
41

You could use FireQuery. It shows any events attached to DOM elements in the Firebug's HTML tab. It also shows any data attached to the elements through $.data.

Stefan answered 7/10, 2009 at 3:26 Comment(2)
That plugin has 1 really big downside: When you are debugging, and you want to inspect the value of a variable which contains a jquery collection you are not able to inspect the value when your code is paused. This is not the cause with firebug. The reason for me to uninstall it. aloneDrawbar
FireQuery doesn't seem to show attached events anymore :(Justification
B
25

Here's a plugin which can list all event handlers for any given element/event:

$.fn.listHandlers = function(events, outputFunction) {
    return this.each(function(i){
        var elem = this,
            dEvents = $(this).data('events');
        if (!dEvents) {return;}
        $.each(dEvents, function(name, handler){
            if((new RegExp('^(' + (events === '*' ? '.+' : events.replace(',','|').replace(/^on/i,'')) + ')$' ,'i')).test(name)) {
               $.each(handler, function(i,handler){
                   outputFunction(elem, '\n' + i + ': [' + name + '] : ' + handler );
               });
           }
        });
    });
};

Use it like this:

// List all onclick handlers of all anchor elements:
$('a').listHandlers('onclick', console.info);

// List all handlers for all events of all elements:
$('*').listHandlers('*', console.info);

// Write a custom output function:
$('#whatever').listHandlers('click',function(element,data){
    $('body').prepend('<br />' + element.nodeName + ': <br /><pre>' + data + '<\/pre>');
});

Src: (my blog) -> http://james.padolsey.com/javascript/debug-jquery-events-with-listhandlers/

Brownlee answered 20/2, 2009 at 21:4 Comment(0)
C
23

The WebKit Developer Console (found in Chrome, Safari, etc.) lets you view attached events for elements.

More detail in this Stack Overflow question

Costly answered 21/8, 2010 at 18:21 Comment(1)
And for Firefox, instructions are on MDNBambibambie
G
11

Use $._data(htmlElement, "events") in jquery 1.7+;

ex:

$._data(document, "events") or $._data($('.class_name').get(0), "events")

Garret answered 20/8, 2012 at 15:12 Comment(0)
A
8

As a colleague suggested, console.log > alert:

var clickEvents = $('#foo').data("events").click;
jQuery.each(clickEvents, function(key, value) {
    console.log(value);
})
Argumentum answered 18/11, 2009 at 16:31 Comment(0)
B
6

jQuery stores events in the following:

$("a#somefoo").data("events")

Doing a console.log($("a#somefoo").data("events")) should list the events attached to that element.

Biannulate answered 20/2, 2009 at 20:12 Comment(0)
D
5

Using DevTools in the latest Chrome (v29) I find these two tips very helpful for debugging events:

  1. Listing jQuery events of the last selected DOM element

    • Inspect an element on the page
    • type the following in the console:

      $._data($0, "events") //assuming jQuery 1.7+

    • It will list all jQuery event objects associated with it, expand the interested event, right-click on the function of the "handler" property and choose "Show function definition". It will open the file containing the specified function.
  2. Utilizing the monitorEvents() command

Devoice answered 3/9, 2013 at 22:49 Comment(0)
D
5

ev icon next to elements

Within the Firefox Developer Tools' Inspector panel lists all events bound to an element.

First select an element with Ctrl + Shift + C, e.g. Stack Overflow's upvote arrow.

Click on the ev icon to the right of the element, and a dialogue opens:

events tooltip

Click on the pause sign || symbol for the event you want, and this opens the debugger on the line of the handler.

You can now place a breakpoint there as usual in the debugger, by clicking on the left margin of the line.

This is mentioned at: https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_event_listeners

Unfortunately, I couldn't find a way for this to play nicely with prettyfication, it just seems to open at the minified line: How to beautify Javascript and CSS in Firefox / Firebug?

Tested on Firefox 42.

Diaphragm answered 17/11, 2015 at 10:40 Comment(1)
Unfortunately this doesnt work well for locating inherited listeners.Majuscule
S
4

Looks like FireBug crew is working on an EventBug extension. It will add another panel to FireBug - Events.

"The events panel will list all of the event handlers on the page grouped by event type. For each event type you can open up to see the elements the listeners are bound to and summary of the function source." EventBug Rising

Although they cannot say right now when it will be released.

Stairway answered 28/10, 2009 at 13:35 Comment(1)
This feature was released and included into FireBug 2.0.1. Now when you inspect a HTML element on a page, there is a new "Events" panel where you can see attached events and their handlers.Zelikow
A
4

I also found jQuery Debugger in the chrome store. You can click on a dom item and it will show all events bound to it along with the callback function. I was debugging an application where events weren't being removed properly and this helped me track it down in minutes. Obviously this is for chrome though, not firefox.

Arctic answered 27/4, 2012 at 16:15 Comment(0)
M
3

According to this thread, there is no way in Firebug to view what events are attached to listeners on a DOM element.

It looks like the best you can do is either what tj111 suggests, or you could right-click the element in the HTML viewer, and click "Log Events" so you can see which events are firing for a particular DOM element. I suppose one could do that to see what events could be firing off particular functions.

Manolo answered 20/2, 2009 at 20:3 Comment(0)
D
2

With version 2.0 Firebug introduced an Events panel, which lists all events for the element currently selected within the HTML panel.

*Events* side panel in Firebug

It can also display event listeners wrapped into jQuery event bindings in case the option Show Wrapped Listeners is checked, which you can reach via the Events panel's options menu.

With that panel the workflow to debug an event handler is as follows:

  1. Select the element with the event listener you want to debug
  2. Inside the Events side panel right-click the function under the related event and choose Set Breakpoint
  3. Trigger the event

=> The script execution will stop at the first line of the event handler function and you can step debug it.

Dove answered 15/1, 2015 at 22:33 Comment(0)
L
0

Firebug 2 does now incorporate DOM events debugging / inspection.

Lou answered 11/6, 2014 at 14:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.