How to find event listeners on a DOM node when debugging or from the JavaScript code?

前端 未结 19 2540
臣服心动
臣服心动 2020-11-21 05:34

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 a

相关标签:
19条回答
  • 2020-11-21 06:22

    changing these functions will allow you to log the listeners added:

    EventTarget.prototype.addEventListener
    EventTarget.prototype.attachEvent
    EventTarget.prototype.removeEventListener
    EventTarget.prototype.detachEvent
    

    read the rest of the listeners with

    console.log(someElement.onclick);
    console.log(someElement.getAttribute("onclick"));
    
    0 讨论(0)
  • 2020-11-21 06:23

    If you just need to inspect what's happening on a page, you might try the Visual Event bookmarklet.

    Update: Visual Event 2 available.

    0 讨论(0)
  • 2020-11-21 06:23

    Use getEventListeners in Google Chrome:

    getEventListeners(document.getElementByID('btnlogin'));
    getEventListeners($('#btnlogin'));
    
    0 讨论(0)
  • 2020-11-21 06:25

    Chrome, Firefox, Vivaldi and Safari support getEventListeners(domElement) in their Developer Tools console.

    For majority of the debugging purposes, this could be used.

    Below is a very good reference to use it: https://developers.google.com/web/tools/chrome-devtools/console/utilities#geteventlisteners

    0 讨论(0)
  • 2020-11-21 06:25

    It depends on how the events are attached. For illustration presume we have the following click handler:

    var 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!') }"
       })
      
    • 1.7+ (very nice)

      Made using knowledge from this comment.

       events = $._data(this, 'events');
       for (type in events) {
         events[type].forEach(function (event) {
           console.log(event['handler']);
         });
       }
      

      When clicking the resulting output in the console (which shows the text of the function), the console will navigate directly to the line of the function's declaration in the relevant JS file.

    0 讨论(0)
  • 2020-11-21 06:27

    Fully working solution based on answer by Jan Turon - behaves like getEventListeners() from console:

    (There is a little bug with duplicates. It doesn't break much anyway.)

    (function() {
      Element.prototype._addEventListener = Element.prototype.addEventListener;
      Element.prototype.addEventListener = function(a,b,c) {
        if(c==undefined)
          c=false;
        this._addEventListener(a,b,c);
        if(!this.eventListenerList)
          this.eventListenerList = {};
        if(!this.eventListenerList[a])
          this.eventListenerList[a] = [];
        //this.removeEventListener(a,b,c); // TODO - handle duplicates..
        this.eventListenerList[a].push({listener:b,useCapture:c});
      };
    
      Element.prototype.getEventListeners = function(a){
        if(!this.eventListenerList)
          this.eventListenerList = {};
        if(a==undefined)
          return this.eventListenerList;
        return this.eventListenerList[a];
      };
      Element.prototype.clearEventListeners = function(a){
        if(!this.eventListenerList)
          this.eventListenerList = {};
        if(a==undefined){
          for(var x in (this.getEventListeners())) this.clearEventListeners(x);
            return;
        }
        var el = this.getEventListeners(a);
        if(el==undefined)
          return;
        for(var i = el.length - 1; i >= 0; --i) {
          var ev = el[i];
          this.removeEventListener(a, ev.listener, ev.useCapture);
        }
      };
    
      Element.prototype._removeEventListener = Element.prototype.removeEventListener;
      Element.prototype.removeEventListener = function(a,b,c) {
        if(c==undefined)
          c=false;
        this._removeEventListener(a,b,c);
          if(!this.eventListenerList)
            this.eventListenerList = {};
          if(!this.eventListenerList[a])
            this.eventListenerList[a] = [];
    
          // Find the event in the list
          for(var i=0;i<this.eventListenerList[a].length;i++){
              if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
                  this.eventListenerList[a].splice(i, 1);
                  break;
              }
          }
        if(this.eventListenerList[a].length==0)
          delete this.eventListenerList[a];
      };
    })();
    

    Usage:

    someElement.getEventListeners([name]) - return list of event listeners, if name is set return array of listeners for that event

    someElement.clearEventListeners([name]) - remove all event listeners, if name is set only remove listeners for that event

    0 讨论(0)
提交回复
热议问题