Is it possible to programmatically catch all events on the page in the browser?

前端 未结 7 486
心在旅途
心在旅途 2020-12-02 08:18

First of all, here is a list of event types that are defined by the W3C standards. (This list is based on the onevent attributes defined in the HTML5 standard. I assume that

相关标签:
7条回答
  • 2020-12-02 08:19

    There doesn't seem to be any 'easy-way' to do that.

    My idea: You know which are all the events, so you can handle all events for every DOM element:

    var events =
    [   
        "onabort",
        "onafterprint",
        "onbeforeprint",
        "onbeforeunload",
        ...
    
    ];
    
    var root = document.body;
    var elms = root.childNodes;
    
    for(var i = 0; i < elms.length; i++)
    {
        for(var j = 0; j < events.length; j++)
        {
            elms[i][events[j]] = globalHandler;
        }
    }
    
    function globalHandler()
    {
        alert("Global handler called");
    }
    

    That's the 'intuitive idea' but doesn't seem to be very efficient. However, it should work.

    Good luck.

    0 讨论(0)
  • 2020-12-02 08:23

    For the last version of the MDN website:

    (function getAllEventTypes(){
      if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;
    
      var types = {};
      $('.standard-table').map(function(){
        if($(this).find('caption').length > 0){
            var type = $(this).find('caption')[0].innerHTML || 'OtherEvent';
        types[type] = types[type] || [];     
        $(this).find('tbody tr td code a').each(function(el){
            if(this.innerText) types[type].push(this.innerText);
        });
        }
      });
      for(var t in types) types[t] = types[t].join(' ');
      return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
    })();
    
    0 讨论(0)
  • My solution to this problem. I loop through all datatypes on the global context (window, in this case), check if the type extends EventTarget, and then extracts them via checking for the "on" prefix.

    const getEventNames = (root) => {
      let events = [ ];
    
      const objectHasSubPrototype = (object, comp) => {
        let proto = Object.getPrototypeOf(object);
    
        while(proto !== null && proto !== EventTarget) {
          proto = Object.getPrototypeOf(proto);
        }
    
        return (proto !== null);
      };
    
      const addEventNames = (propNames) => {
        propNames.filter(x => x.match(/^on\w+$/)).forEach((propName) => {
          propName = propName.substr(2);
          if(events.indexOf(propName) === -1) {
            events.push(propName);
          }
        });
      };
    
      Object.getOwnPropertyNames(root).forEach((name) => {
        let value = root[name];
    
        if(value) {
          if(objectHasSubPrototype(value, EventTarget)) {
            let propNames = Object.getOwnPropertyNames(Object.getPrototypeOf(value).prototype);
            addEventNames(propNames);
    
            propNames = Object.getOwnPropertyNames(window);
            addEventNames(propNames);
          }
        }
      });
    
      return events;
    };
    
    // Attach all events to the window
    getEventNames(window).forEach((eventName) => {
      window.addEventListener(eventName, (event) => console.log(eventName, event));
    });
    
    0 讨论(0)
  • 2020-12-02 08:26

    I highly doubt there's a way to do this in Firefox. Looking at Firebug's source code (particularly the attachAllListeners method), turns out that iterating through a list of event names is obviously the way to go, but this doesn't solve the bubbling issues.

    0 讨论(0)
  • 2020-12-02 08:32
    /*
    
    function getAllEventTypes(){
    
      if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;
    
      var types = {};
      $('.standard-table:eq(0) tr').find('td:eq(1)').map(function(){
        var type = $.trim(this.innerText) || 'OtherEvent';
        types[type] = types[type] || [];     
        var event = $.trim(this.previousElementSibling.innerText);
        if(event) types[type].push(event);
      });
      for(var t in types) types[t] = types[t].join(' ');
      return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
    }
    
    */
    
    var DOMEvents = {
    UIEvent: "abort DOMActivate error load resize scroll select unload",
    ProgressEvent: "abort error load loadend loadstart progress progress timeout",
    Event: "abort afterprint beforeprint cached canplay canplaythrough change chargingchange chargingtimechange checking close dischargingtimechange DOMContentLoaded downloading durationchange emptied ended ended error error error error fullscreenchange fullscreenerror input invalid languagechange levelchange loadeddata loadedmetadata noupdate obsolete offline online open open orientationchange pause pointerlockchange pointerlockerror play playing ratechange readystatechange reset seeked seeking stalled submit success suspend timeupdate updateready visibilitychange volumechange waiting",
    AnimationEvent: "animationend animationiteration animationstart",
    AudioProcessingEvent: "audioprocess",
    BeforeUnloadEvent: "beforeunload",
    TimeEvent: "beginEvent endEvent repeatEvent",
    OtherEvent: "blocked complete upgradeneeded versionchange",
    FocusEvent: "blur DOMFocusIn  Unimplemented DOMFocusOut  Unimplemented focus focusin focusout",
    MouseEvent: "click contextmenu dblclick mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup show",
    SensorEvent: "compassneedscalibration Unimplemented userproximity",
    OfflineAudioCompletionEvent: "complete",
    CompositionEvent: "compositionend compositionstart compositionupdate",
    ClipboardEvent: "copy cut paste",
    DeviceLightEvent: "devicelight",
    DeviceMotionEvent: "devicemotion",
    DeviceOrientationEvent: "deviceorientation",
    DeviceProximityEvent: "deviceproximity",
    MutationNameEvent: "DOMAttributeNameChanged DOMElementNameChanged",
    MutationEvent: "DOMAttrModified DOMCharacterDataModified DOMNodeInserted DOMNodeInsertedIntoDocument DOMNodeRemoved DOMNodeRemovedFromDocument DOMSubtreeModified",
    DragEvent: "drag dragend dragenter dragleave dragover dragstart drop",
    GamepadEvent: "gamepadconnected gamepaddisconnected",
    HashChangeEvent: "hashchange",
    KeyboardEvent: "keydown keypress keyup",
    MessageEvent: "message message message message",
    PageTransitionEvent: "pagehide pageshow",
    PopStateEvent: "popstate",
    StorageEvent: "storage",
    SVGEvent: "SVGAbort SVGError SVGLoad SVGResize SVGScroll SVGUnload",
    SVGZoomEvent: "SVGZoom",
    TouchEvent: "touchcancel touchend touchenter touchleave touchmove touchstart",
    TransitionEvent: "transitionend",
    WheelEvent: "wheel"
    }
    
    var RecentlyLoggedDOMEventTypes = {};
    
    for(DOMEvent in DOMEvents){
    
      var DOMEventTypes = DOMEvents[DOMEvent].split(' ');
    
      DOMEventTypes.filter(function(DOMEventType){
        var DOMEventCategory = DOMEvent + ' '+DOMEventType;  
        document.addEventListener(DOMEventType, function(e){
          if(RecentlyLoggedDOMEventTypes[DOMEventCategory]) return;
          RecentlyLoggedDOMEventTypes[DOMEventCategory] = true;
          setTimeout(function(){ RecentlyLoggedDOMEventTypes[DOMEventCategory] = false }, 5000);
          var isActive = e.target==document.activeElement;
          if(isActive) {
            console.info(DOMEventCategory, 
              ' target=', e.target, 
              ' active=', document.activeElement, 
              ' isActive=', true );
          } else {
            console.log(DOMEventCategory, 
              ' target=', e.target,
              ' active=', document.activeElement, 
              ' isActive=', false );
          }
    
        }, true);
      });
    
    }
    
    0 讨论(0)
  • 2020-12-02 08:40

    A bit late to the party but I did create something that might be useful for others here.

    https://codepen.io/phreaknation/pen/QmJjEa

    This is an ES6 Class that captures all events from an element that is known to that element. This demo allows you to change the element time in the page, as well as read out the events with clickable links to their MDN page as well as interact with the element and see how the events are triggered with time stamps.

    I hope this helps

    Class code

    class EventSystem {
      constructor(element) {
        this._ = {
          element: null
        }
    
        return this;
      }
    
      getAllEventTypes({blacklist = [], whitelist = []} = {}) {
        const events = [];
        for (let property in this._.element) {
          const match = property.match(/^on(.*)/);
          if (match) {
            if ((whitelist.length > 0 ? whitelist.indexOf(match) !== -1 : true) &&
                (blacklist.length > 0 ? blacklist.indexOf(match) === -1 : true)) {
              events.push(match[1]);
            }          
          }
        }
        return events;
      }
    
      getElementType() {
        return this._.element.tagName.toLowerCase();
      }
    
      setElement(element) {
        this._.element = element;
        return this;
      }
    
      applyEvents(events, callback) {
        events.forEach((event) => {
          this._.element.addEventListener(event, (ev) => {
            if (typeof callback === 'function') {
              callback(event, ev);
            }
          })
        })
      }
    }
    
    0 讨论(0)
提交回复
热议问题