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('
', h, ' ', p, ' handler', h > 1 ? 's' : '');
if(r.delegateCount) {
for(var q = 0; q < r.length; q++)
if(r[q].selector) s.push('
', p, ' for ', r[q].selector);
}
}
s.push('
');
});
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('
', h, ' ', p, ' handler', h > 1 ? 's' : '');
if(r.delegateCount) {
for(var q = 0; q < r.length; q++)
if(r[q].selector) s.push('
', p, ' for ', r[q].selector);
}
}
s.push('
');
});
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.