Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List all javascript events wired up on a page using jquery

jQuery makes this relatively easy because it stores the event handlers in the element data. You should be able to use something like this:

(function($) {
    $.eventReport = function(selector, root) {
        var s = [];
        $(selector || '*', root).andSelf().each(function() {
            // the following line is the only change
            var e = $.data(this, 'events');
            if(!e) return;
            s.push(this.tagName);
            if(this.id) s.push('#', this.id);
            if(this.className) s.push('.', this.className.replace(/ +/g, '.'));
            for(var p in e) {
                var r = e[p],
                    h = r.length - r.delegateCount;
                if(h)
                    s.push('\n', h, ' ', p, ' handler', h > 1 ? 's' : '');
                if(r.delegateCount) {
                    for(var q = 0; q < r.length; q++)
                        if(r[q].selector) s.push('\n', p, ' for ', r[q].selector);
                }
            }
            s.push('\n\n');
        });
        return s.join('');
    }
    $.fn.eventReport = function(selector) {
        return $.eventReport(selector, this);
    }
})(jQuery);

and you can call it:

// all events
alert($.eventReport());

// just events on inputs
alert($.eventReport('input')); 

// just events assigned to this element
alert($.eventReport('#myelement')); 

// events assigned to inputs in this element
alert($.eventReport('input', '#myelement')); 
alert($('#myelement').eventReport('input')); // same result

// just events assigned to this element's children
alert($('#myelement').eventReport()); 
alert($.eventReport('*', '#myelement'); // same result

UPDATE: I added a count of handlers and some information about delegated events to the output of the above function.

UPDATE (8/24/2012): While the function above still works in jQuery 1.7.2 and lower, jQuery no longer stores the event object in jQuery.data(elem, 'events') and if you are using jQuery 1.8 or later you will no longer be able to use the function above!

In exchange for jQuery.data(elem, 'events') you can now use jQuery._data(elem, 'events'). An update to the function above would look like this:

(function($) {
    $.eventReport = function(selector, root) {
        var s = [];
        $(selector || '*', root).addBack().each(function() {
            // the following line is the only change
            var e = $._data(this, 'events');
            if(!e) return;
            s.push(this.tagName);
            if(this.id) s.push('#', this.id);
            if(this.className) s.push('.', this.className.replace(/ +/g, '.'));
            for(var p in e) {
                var r = e[p],
                    h = r.length - r.delegateCount;
                if(h)
                    s.push('\n', h, ' ', p, ' handler', h > 1 ? 's' : '');
                if(r.delegateCount) {
                    for(var q = 0; q < r.length; q++)
                        if(r[q].selector) s.push('\n', p, ' for ', r[q].selector);
                }
            }
            s.push('\n\n');
        });
        return s.join('');
    }
    $.fn.eventReport = function(selector) {
        return $.eventReport(selector, this);
    }
})(jQuery);

UPDATE (4/25/2013): andSelf() is deprecated from 1.8.x http://bugs.jquery.com/ticket/9800 , I replaced with addBack() instead.


// List bound events
console.log($('#elem').data('events'));

// Log ALL handlers for ALL events
$.each($('#elem').data('events'), function(i, event) {
  $.each(event, function(i, handler){
    console.log(handler.toString());
  });
});

I use this one to list all elements that has a bounded event.

$('*').each(function(){
    var events = $(this).data('events');
    if(events != null)
    {
        console.log(this);
        console.log(events);
    }
});

It is also possible to collect elements as a list for each event by writing some additional codes like this:

var eventArrays = {};

$('*').each(function(){
    var events = $(this).data('events');
    for(var anEvent in events){
        if(!eventArrays[anEvent])
            eventArrays[anEvent] = [];
        eventArrays[anEvent].push(this);
    }
});

console.log(eventArrays);