Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get event listeners attached to node using addEventListener

People also ask

How do you find attached event listeners?

Right-click on the search icon button and choose “inspect” to open the Chrome developer tools. Once the dev tools are open, switch to the “Event Listeners” tab and you will see all the event listeners bound to the element. You can expand any event listener by clicking the right-pointing arrowhead.

Does addEventListener bind this?

addEventListener cannot bind this again. You can call bind multiple times. Even if you call it on a bound function, you can perform partial application.

How do I check if an event listener exists?

To check whether dynamically attached event listener exists or not with JavaScript, we can get and set the element's listener attribute. export const attachEvent = ( element: Element, eventName: string, callback: () => void ) => { if (element && eventName && element. getAttribute("listener") !== "true") { element.


Chrome DevTools, Safari Inspector and Firebug support getEventListeners(node).

getEventListeners(document)


You can't.

The only way to get a list of all event listeners attached to a node is to intercept the listener attachment call.

DOM4 addEventListener

Says

Append an event listener to the associated list of event listeners with type set to type, listener set to listener, and capture set to capture, unless there already is an event listener in that list with the same type, listener, and capture.

Meaning that an event listener is added to the "list of event listeners". That's all. There is no notion of what this list should be nor how you should access it.


Since there is no native way to do this ,Here is the less intrusive solution i found (dont add any 'old' prototype methods):

var ListenerTracker=new function(){
    var targets=[];
    // listener tracking datas
    var _elements_  =[];
    var _listeners_ =[];
    this.init=function(){
        this.listen(Element,window);
    };
    this.listen=function(){
        for(var i=0;i<arguments.length;i++){
            if(targets.indexOf(arguments[i])===-1){
                targets.push(arguments[i]);//avoid duplicate call
                intercep_events_listeners(arguments[i]);
            }
        }
    };
    // register individual element an returns its corresponding listeners
    var register_element=function(element){
        if(_elements_.indexOf(element)==-1){
            // NB : split by useCapture to make listener easier to find when removing
            var elt_listeners=[{/*useCapture=false*/},{/*useCapture=true*/}];
            _elements_.push(element);
            _listeners_.push(elt_listeners);
        }
        return _listeners_[_elements_.indexOf(element)];
    };
    var intercep_events_listeners = function(target){
        var _target=target;
        if(target.prototype)_target=target.prototype;
        if(_target.getEventListeners)return;
        if(typeof(_target.addEventListener)!=='function'||typeof(_target.removeEventListener)!=='function'){
            console.log('target=',target);
            throw('\nListenerTracker Error:\nUnwrappable target.');
        }
        // backup overrided methods
        var _super_={
            "addEventListener"      : _target.addEventListener,
            "removeEventListener"   : _target.removeEventListener
        };

        _target["addEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["addEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            var uc=(typeof(useCapture)==='object'?useCapture.useCapture:useCapture)?1:0;
            if(!listeners[uc][type])listeners[uc][type]=[];
            listeners[uc][type].push({cb:listener,args:arguments});
        };
        _target["removeEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["removeEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            useCapture=(typeof(useCapture)==='object'?useCapture.useCapture:useCapture)?1:0;
            if(!listeners[useCapture][type])return;
            var lid = listeners[useCapture][type].findIndex(obj=>obj.cb===listener);
            if(lid>-1)listeners[useCapture][type].splice(lid,1);
        };
        _target["getEventListeners"]=function(type){
            var listeners=register_element(this);
            // convert to listener datas list
            var result=[];
            for(var useCapture=0,list;list=listeners[useCapture];useCapture++){
                if(typeof(type)=="string"){// filtered by type
                    if(list[type]){
                        for(var id in list[type]){
                            result.push({
                                "type":type,
                                "listener":list[type][id].cb,
                                "args":list[type][id].args,
                                "useCapture":!!useCapture
                            });
                        }
                    }
                }else{// all
                    for(var _type in list){
                        for(var id in list[_type]){
                            result.push({
                                "type":_type,
                                "listener":list[_type][id].cb,
                                "args":list[_type][id].args,
                                "useCapture":!!useCapture
                            });
                        }
                    }
                }
            }
            return result;
        };
    };

}();


ListenerTracker.init();

EDIT

Suggestion from @mplungjan: modified to listen to wrappable targets (singleton|constructor). 'init' tracks Element and window .

exemple with other wrappable target:

ListenerTracker.listen(XMLHttpRequest);

Suggestion from @kodfire : You may get optionals arguments with the args property.


I can't find a way to do this with code, but in stock Firefox 64, events are listed next to each HTML entity in the Developer Tools Inspector as noted on MDN's Examine Event Listeners page and as demonstrated in this image:

screen shot of FF Inspector


You can obtain all jQuery events using $._data($('[selector]')[0],'events'); change [selector] to what you need.

There is a plugin that gather all events attached by jQuery called eventsReport.

Also i write my own plugin that do this with better formatting.

But anyway it seems we can't gather events added by addEventListener method. May be we can wrap addEventListener call to store events added after our wrap call.

It seems the best way to see events added to an element with dev tools.

But you will not see delegated events there. So there we need jQuery eventsReport.

UPDATE: NOW We CAN see events added by addEventListener method SEE RIGHT ANSWER TO THIS QUESTION.