I have a page where some event listeners are attached to input boxes and select boxes. Is there a way to find out which event listeners are observing a particular DOM node and for what event?
Events are attached using 1) prototype's Event.observe 2) DOM's addEventListener 3) as element attribute element.onclick
Source: Tips4all
If you just need to inspect what's happening on a page, you might try the Visual Event bookmarklet.
ReplyDeleteIt depends on how the events are attached. For illustration presume we have the following click handler:
ReplyDeletevar handler = function() { alert('clicked!') };
We're going to attach it to our element using different methods, some which allow inspection and some that don't.
Method A) single event handler
element.onclick = handler;
// inspect
alert(element.onclick); // alerts "function() { alert('clicked!') }"
Method B) multiple event handlers
if(element.addEventListener) { // DOM standard
element.addEventListener('click', handler, false)
} else if(element.attachEvent) { // IE
element.attachEvent('onclick', handler)
}
// cannot inspect element to find handlers
Method C): jQuery
$(element).click(handler);
1.3.x
// inspect
var clickEvents = $(element).data("events").click;
jQuery.each(clickEvents, function(key, value) {
alert(value) // alerts "function() { alert('clicked!') }"
})
1.4.x (stores the handler inside an object)
// inspect
var clickEvents = $(element).data("events").click;
jQuery.each(clickEvents, function(key, handlerObj) {
alert(handlerObj.handler) // alerts "function() { alert('clicked!') }"
// also available: handlerObj.type, handlerObj.namespace
})
(See jQuery.fn.data and jQuery.data)
Method D): Prototype (messy)
$(element).observe('click', handler);
1.5.x
// inspect
Event.observers.each(function(item) {
if(item[0] == element) {
alert(item[2]) // alerts "function() { alert('clicked!') }"
}
})
1.6 to 1.6.0.3, inclusive (got very difficult here)
// inspect. "_eventId" is for < 1.6.0.3 while
// "_prototypeEventID" was introduced in 1.6.0.3
var clickEvents = Event.cache[element._eventId || (element._prototypeEventID || [])[0]].click;
clickEvents.each(function(wrapper){
alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
})
1.6.1 (little better)
// inspect
var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
clickEvents.each(function(wrapper){
alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
})
WebKit Inspector in Chrome or Safari browsers now does this. It will display the event listeners for a DOM element when you select it in the Elements pane.
ReplyDeleteIt is possible to list all event listeners in javascript: Is not that hard; you just have to hack the prototype method of the HTML elements (before adding the listeners)
ReplyDeletefunction reportIn(e){
var a = this.lastListenerInfo[this.lastListenerInfo.length-1];
console.log(a)
}
HTMLAnchorElement.prototype.realAddEventListener = HTMLAnchorElement.prototype.addEventListener;
HTMLAnchorElement.prototype.addEventListener = function(a,b,c){
this.realAddEventListener(a,reportIn,c);
this.realAddEventListener(a,b,c);
if(!this.lastListenerInfo){ this.lastListenerInfo = new Array()};
this.lastListenerInfo.push({a : a, b : b , c : c});
};
Now every anchor element ( < a > ) will have a 'lastListenerInfo' propierty wich contains all of its listeneres. And it even works for removing listeners with anonymous functions.
If you have Firebug, you can use console.dir(object or array) to print a nice tree in the console log of any javascript scalar, array, or object.
ReplyDeleteTry:
console.dir(clickEvents);
or
console.dir(window);