sfandler
sfandler

Reputation: 640

Find elements which are bound to a specific event

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

Answers (3)

Matt Styles
Matt Styles

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

Nizar
Nizar

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

Makaze
Makaze

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

Related Questions