moomoo
moomoo

Reputation:

List all javascript events wired up on a page using jquery

Using jQuery, is it possible to get a list of all the events and to which element the event is bound to?

Upvotes: 46

Views: 31385

Answers (5)

Can Guney Aksakalli
Can Guney Aksakalli

Reputation: 1330

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

Upvotes: 3

Rodolpho Brock
Rodolpho Brock

Reputation: 8165

To use console.table() I did some modifications...

(function($) {
    $.eventReport = function(selector, root) {
        var s = [];
        $(selector || '*', root).addBack().each(function() {
            var e = $._data(this, 'events');
            if(!e) return;
            var tagGroup = this.tagName || "document";
            if(this.id) tagGroup += '#' + this.id;
            if(this.className) tagGroup += '.' + this.className.replace(/ +/g, '.');

            var delegates = [];
            for(var p in e) {
                var r = e[p];
                var h = r.length - r.delegateCount;

                if(h)
                    s.push([tagGroup, p + ' handler' + (h > 1 ? 's' : '')]);

                if(r.delegateCount) {
                    for(var q = 0; q < r.length; q++)
                        if(r[q].selector) s.push([tagGroup + ' delegates', p + ' for ' + r[q].selector]);
                }
            }
        });
        return s;
    }
    $.fn.eventReport = function(selector) {
        return $.eventReport(selector, this);
    }
})(jQuery);

So now I can do things like this:

console.table($.eventReport())

See what happens at chrome: Console in chrome

Upvotes: 0

Prestaul
Prestaul

Reputation: 85184

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.

Upvotes: 95

Misha Moroshko
Misha Moroshko

Reputation: 171419

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

Upvotes: 5

Tom Ritter
Tom Ritter

Reputation: 101400

I bet you could traverse the DOM and inspect the event attribute on each element building up a list... but I've never tried it.

Upvotes: 0

Related Questions