Reputation: 640
I have an element $button
on which I defined the following event:
$button.on('draghover', function(event) { ... });
Somewhere else in my code, I would like to find all elements who have a listener attached to the 'draghover' event. I am expecting a function like jQuery.getElementsForEvent('draghover')
which would returns a list containing the button: [ $button ]
.
Any help would be appreciated.
Upvotes: 2
Views: 67
Reputation: 2452
Given that there are (probably) more DOM nodes than there are event listeners it would make sense to keep track of elements connected with certain events.
// Events is a key:value pair, where key is your event name and
// the values are an array full of elements associated with that event.
// An ES2015 Map would be better here.
var events = {}
function attach( element, event, listener ) {
// Create new array with the element or append it to the list
events.event = events.event && events.event.length
? events.event.concat( [ element ] )
: [ element ]
element.addEventListener( event, listener )
}
events
then contains all of the elements associated with a particular event and does not require traversing the entire DOM looking for data
.
In the example each array is of elements but you might want to change the structure so that the array holds an object referencing element:listener
, that way you could more easily do the inverse and remove listeners from elements but maintain your hot list of events.
Upvotes: 1
Reputation: 481
No, there's no direct way to do this in Jquery.
Event binding happens in the object level, namely, when you bind an event to an object with a specific handler, the event handler is stored in the object itself, and when you trigger the event, jquery will lookup in the object for handlers of the specific event and fire them.
The primitive solution is to the iterate over all elements and check if it has the specific event.
A more advanced(and complicated) solution is to define a global dictionary when the key is event name and the value is an array of elements bound to it, override jquery functions ($.bind, $.unbind and others).
Upvotes: 1
Reputation: 1086
The only solution I can think of is to iterate over every element in a collection and see if it has the event, then return the filtered list. Here is an example (run it in the console to test):
jQuery('a:last').on('test', function() { alert('hello'); });
jQuery.fn.extend({
getElementsWithEvent: function(eventName) {
return this.filter(function(i, element) {
var flagged = false;
if ($(element).data('events')) {
jQuery.each($(element).data('events'), function(i, event) {
if (event[0].type == eventName) {
flagged = true;
return false;
}
});
}
return flagged;
});
}
});
jQuery('a').getElementsWithEvent('test');
Upvotes: 1