获得所有DOM事件的数组

时间:2012-02-20 21:17:28

标签: javascript dom javascript-events event-handling

我创建了一个多用途工厂事件发射器工厂功能。有了它,我可以将对象转换为事件发射器。如果有人想要查看或使用它,事件发射器工厂的代码如下。

我的问题是如何从DOM中获取事件列表。 请注意我不是要获取绑定事件列表。我想要一个可能的所有事件的列表。我想向发射器添加“管道”方法。此方法将获取DOM对象并绑定到所有可能的事件,然后当任何这些事件触发时,将触发发射器中具有相同名称的事件。

我认为没有办法做到这一点。我准备制作一个硬编码的事件名称数组,但是如果我可以获得更好的DOM数组,那么如果W3C标准化了更多的事件类型,它仍然可以工作。

P.S。如果你为W3C工作,这就是让每个人都讨厌DOM的垃圾。请停止像玩具语言一样对待JavaScript。它不是玩具语言,需要的不仅仅是玩具DOM。

/**
 * Creates a event emitter
 */
function EventEmitter() {
    var api, callbacks;

    //vars
    api = {
        "on": on,
        "trigger": trigger
    };
    callbacks = {};

    //return the api
    return api;

    /**
     * Binds functions to events
     * @param event
     * @param callback
     */
    function on(event, callback) {
        var api;

        if(typeof event !== 'string') { throw new Error('Cannot bind to event emitter. The passed event is not a string.'); }
        if(typeof callback !== 'function') { throw new Error('Cannot bind to event emitter. The passed callback is not a function.'); }

        //return the api
        api = {
            "clear": clear
        };

        //create the event namespace if it doesn't exist
        if(!callbacks[event]) { callbacks[event] = []; }

        //save the callback
        callbacks[event].push(callback);

        //return the api
        return api;

        function clear() {
            var i;
            if(callbacks[event]) {
                i = callbacks[event].indexOf(callback);
                callbacks[event].splice(i, 1);

                if(callbacks[event].length < 1) {
                    delete callbacks[event];
                }

                return true;
            }
            return false;
        }
    }

    /**
     * Triggers a given event and optionally passes its handlers all additional parameters
     * @param event
     */
    function trigger(event    ) {
        var args;

        if(typeof event !== 'string' && !Array.isArray(event)) { throw new Error('Cannot bind to event emitter. The passed event is not a string or an array.'); }

        //get the arguments
        args = Array.prototype.slice.apply(arguments).splice(1);

        //handle event arrays
        if(Array.isArray(event)) {

            //for each event in the event array self invoke passing the arguments array
            event.forEach(function(event) {

                //add the event name to the begining of the arguments array
                args.unshift(event);

                //trigger the event
                trigger.apply(this, args);

                //shift off the event name
                args.shift();

            });

            return;
        }

        //if the event has callbacks then execute them
        if(callbacks[event]) {

            //fire the callbacks
            callbacks[event].forEach(function(callback) { callback.apply(this, args); });
        }
    }
}

5 个答案:

答案 0 :(得分:6)

以下版本适用于Chrome,Safari和FF。

Object.getOwnPropertyNames(document).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)))).filter(function(i){return !i.indexOf('on')&&(document[i]==null||typeof document[i]=='function');})

UPD

这是适用于IE9 +,Chrome,Safari和FF的版本。

Object.getOwnPropertyNames(document).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)))).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(window))).filter(function(i){return !i.indexOf('on')&&(document[i]==null||typeof document[i]=='function');}).filter(function(elem, pos, self){return self.indexOf(elem) == pos;})

PS:结果是一系列事件名称,如["onwebkitpointerlockerror", "onwebkitpointerlockchange", "onwebkitfullscreenerror", "onwebkitfullscreenchange", "onselectionchange", "onselectstart", "onsearch", "onreset", "onpaste", "onbeforepaste", "oncopy"] ...等。

答案 1 :(得分:5)

所有DOM事件均以on开头。您可以遍历任何Element实例,并列出以on开头的所有属性。

实施例。在控制台中复制粘贴以下代码(Firefox,使用Array comprehensions;)):

[i for(i in document)].filter(function(i){return i.substring(0,2)=='on'&&(document[i]==null||typeof document[i]=='function');})

获取事件的另一种方法是查看the specification,其中显示:

  // event handler IDL attributes
  [TreatNonCallableAsNull] attribute Function? onabort;
  [TreatNonCallableAsNull] attribute Function? onblur;
  [TreatNonCallableAsNull] attribute Function? oncanplay;
  [TreatNonCallableAsNull] attribute Function? oncanplaythrough;
  [TreatNonCallableAsNull] attribute Function? onchange;
  [TreatNonCallableAsNull] attribute Function? onclick;
  [TreatNonCallableAsNull] attribute Function? oncontextmenu;
  [TreatNonCallableAsNull] attribute Function? oncuechange;
  [TreatNonCallableAsNull] attribute Function? ondblclick;
  [TreatNonCallableAsNull] attribute Function? ondrag;
  [TreatNonCallableAsNull] attribute Function? ondragend;
  [TreatNonCallableAsNull] attribute Function? ondragenter;
  [TreatNonCallableAsNull] attribute Function? ondragleave;
  [TreatNonCallableAsNull] attribute Function? ondragover;
  [TreatNonCallableAsNull] attribute Function? ondragstart;
  [TreatNonCallableAsNull] attribute Function? ondrop;
  [TreatNonCallableAsNull] attribute Function? ondurationchange;
  [TreatNonCallableAsNull] attribute Function? onemptied;
  [TreatNonCallableAsNull] attribute Function? onended;
  [TreatNonCallableAsNull] attribute Function? onerror;
  [TreatNonCallableAsNull] attribute Function? onfocus;
  [TreatNonCallableAsNull] attribute Function? oninput;
  [TreatNonCallableAsNull] attribute Function? oninvalid;
  [TreatNonCallableAsNull] attribute Function? onkeydown;
  [TreatNonCallableAsNull] attribute Function? onkeypress;
  [TreatNonCallableAsNull] attribute Function? onkeyup;
  [TreatNonCallableAsNull] attribute Function? onload;
  [TreatNonCallableAsNull] attribute Function? onloadeddata;
  [TreatNonCallableAsNull] attribute Function? onloadedmetadata;
  [TreatNonCallableAsNull] attribute Function? onloadstart;
  [TreatNonCallableAsNull] attribute Function? onmousedown;
  [TreatNonCallableAsNull] attribute Function? onmousemove;
  [TreatNonCallableAsNull] attribute Function? onmouseout;
  [TreatNonCallableAsNull] attribute Function? onmouseover;
  [TreatNonCallableAsNull] attribute Function? onmouseup;
  [TreatNonCallableAsNull] attribute Function? onmousewheel;
  [TreatNonCallableAsNull] attribute Function? onpause;
  [TreatNonCallableAsNull] attribute Function? onplay;
  [TreatNonCallableAsNull] attribute Function? onplaying;
  [TreatNonCallableAsNull] attribute Function? onprogress;
  [TreatNonCallableAsNull] attribute Function? onratechange;
  [TreatNonCallableAsNull] attribute Function? onreset;
  [TreatNonCallableAsNull] attribute Function? onscroll;
  [TreatNonCallableAsNull] attribute Function? onseeked;
  [TreatNonCallableAsNull] attribute Function? onseeking;
  [TreatNonCallableAsNull] attribute Function? onselect;
  [TreatNonCallableAsNull] attribute Function? onshow;
  [TreatNonCallableAsNull] attribute Function? onstalled;
  [TreatNonCallableAsNull] attribute Function? onsubmit;
  [TreatNonCallableAsNull] attribute Function? onsuspend;
  [TreatNonCallableAsNull] attribute Function? ontimeupdate;
  [TreatNonCallableAsNull] attribute Function? onvolumechange;
  [TreatNonCallableAsNull] attribute Function? onwaiting;

  // special event handler IDL attributes that only apply to Document objects
  [TreatNonCallableAsNull,LenientThis] attribute Function? onreadystatechange;

答案 2 :(得分:0)

我已经阅读了规范,并且我已经确认目前无法进行此操作。感谢W3C没有为我们提供最基本的环境!

我设法绕过这个问题而不牺牲任何东西。正如我之前所说,管道将来自另一个发射器(例如DOM节点)的任何事件传输到当前发射器。但是,在有人试图听一个事件之前,我不需要做任何事情。在内部我所做的是绑定到管道发射器,因为人们绑定到当前发射器。

如果你好奇我能做什么,我released the library。管道代码采用pipe()方法和on()方法。

答案 3 :(得分:0)

在过去的一个世纪,当我为IE进行构建相当于在全世界87%到92%的范围内构建建筑时,这就是我用来获得动态eventList的方式。这是一个像::: eventList = []; for( var x in this )if( x.match(/\bon/) )eventList.push(x); 这样的单行代码,我刚刚在赢7的最新Opera,IE11,相当老的Chrome和大约2年的Firefox上进行了测试...和该死的(!)-就像是一种魅力。

var eventList = [];

for( var x in this )if( /\bon/.test(x) )eventList.push(x),
console.info( x );

console.info( eventList.length );

答案 4 :(得分:0)

您可能没有一个详尽的清单,因为我们可以触发任何名称的综合事件。

例如:

// Since we can even make it bubble
// overriding dispatchEvent wouldn't do either.
// Here we listen on document
document.addEventListener("foo", evt => console.log("foo fired"));
const event = new Event("foo", { bubbles: true });
// And we fire on <body>
document.body.dispatchEvent( event );

几乎没有所有“内置”事件的列表。这些事件中有许多没有在任何地方公开的.onevent IDL属性,例如Document或Window的DOMContentLoaded,也没有输入元素compositionXXX或隐藏在各种规范中的许多其他元素。

// won't fire
window.onDOMContentLoaded = evt => console.log('caught through onDOMContentLoaded');
// will fire
window.addEventListener('DOMContentLoaded', evt => console.log('caught through addEventListener'));

即使捕获所有这些onevent的IDL属性,也需要遍历所有Constructor的原型,因为window仅暴露了其中的一些。

console.log("onaddtrack available in window?", "onaddtrack" in window);
console.log("onaddtrack available in MediaStream's proto?", "onaddtrack" in MediaStream.prototype);

虽然我们可以在线找到quite big lists个此类事件,但由于规格不断变化,并且浏览器不支持规格中的所有内容,或者相反,它们不支持规格中未包含的功能,列表将全部捕获

(例如,最后一点,dragexit event当前仅在Firefox支持的情况下才从规范中删除。)