Javascript 尽可能获取所有DOM事件的数组

Javascript 尽可能获取所有DOM事件的数组,javascript,dom,event-handling,dom-events,Javascript,Dom,Event Handling,Dom Events,我已经创建了一个多用途的工厂事件发射器工厂函数。使用它,我可以将对象转化为事件发射器。如果有人想查看或使用它,下面是事件发射器工厂的代码 我的问题是如何从DOM中获取事件列表请注意,我并没有试图获取绑定事件的列表。我想要一个所有可能事件的列表。我想要为发射器添加一个“管道”方法。此方法将获取一个DOM对象并绑定到所有可能的事件,然后当这些事件中的任何一个触发时,每个事件都将触发发射器中同名的事件 我想没有办法做到这一点。我准备制作一个事件名称的硬编码数组,但是如果我可以得到DOM的数组,那会更好

我已经创建了一个多用途的工厂事件发射器工厂函数。使用它,我可以将对象转化为事件发射器。如果有人想查看或使用它,下面是事件发射器工厂的代码

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

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

另外,如果你为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); });
        }
    }
}
/**
*创建事件发射器
*/
函数EventEmitter(){
var-api,回调;
//瓦尔斯
api={
“on”:on,
“触发器”:触发器
};
回调={};
//返回api
返回api;
/**
*将函数绑定到事件
*@param事件
*@param回调
*/
函数打开(事件、回调){
var-api;
if(typeof event!=='string'){throw new Error('无法绑定到事件发射器。传递的事件不是字符串。');}
if(typeof callback!=“function”){throw new Error('无法绑定到事件发射器。传递的回调不是函数。');}
//返回api
api={
“清除”:清除
};
//如果事件命名空间不存在,请创建它
如果(!callbacks[event]){callbacks[event]=[];}
//保存回调
回调[事件]。推送(回调);
//返回api
返回api;
函数clear(){
var i;
if(回调[事件]){
i=回调[事件].indexOf(回调);
回调[event].splice(i,1);
if(回调[event].length<1){
删除回调[事件];
}
返回true;
}
返回false;
}
}
/**
*触发给定事件,并可选地向其处理程序传递所有附加参数
*@param事件
*/
函数触发器(事件){
var-args;
if(typeof event!='string'&&&!Array.isArray(event)){throw new Error('无法绑定到事件发射器。传递的事件不是字符串或数组');}
//获取参数
args=Array.prototype.slice.apply(参数).splice(1);
//句柄事件数组
if(Array.isArray(事件)){
//对于事件数组中的每个事件,通过参数数组进行自调用
event.forEach(函数(事件){
//将事件名称添加到arguments数组的开头
参数取消移位(事件);
//触发事件
触发器。应用(此参数为args);
//关闭事件名称
args.shift();
});
返回;
}
//如果事件有回调,则执行回调
if(回调[事件]){
//启动回调
回调[event].forEach(函数(回调){callback.apply(this,args);});
}
}
}

所有DOM事件都以上的
开始。您可以循环任何
元素
实例,并列出所有以
开头的属性

例如。在控制台中复制粘贴以下代码(Firefox,使用数组理解;):

获取事件的另一种方法是查看,它显示:

  // 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;

我已经阅读了规范,我已经确认这在目前是不可能的。感谢W3C没有为我们提供最基本的环境保护

不过,我还是设法避开了这个问题,没有牺牲任何东西。正如我前面所说,管道将来自另一个发射器(如DOM节点)的任何事件传输到当前发射器。然而,我不需要做任何事情,直到有人试图听一个事件。在内部,我所做的是绑定到管道发射器,就像人们绑定到当前发射器一样


我想知道你是否好奇我做了什么。管道的代码位于
pipe()
方法和
on()
方法中。

这是一个适用于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');})
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;})
UPD 1

这是在IE9+、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');})
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;})
UPD 2

这里有一个版本使用了更新的JavaScript特性(新的设置(…)]
是用来过滤重复的内容,取代了
过滤方法)

[…新设置([
…Object.getOwnPropertyNames(文档),
…Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)),
…Object.getOwnPropertyNames(Object.getPrototypeOf(窗口)),
].filter(k=>k.startsWith(“on”)&&(文档[k]==null | | |文档类型[k]==function”));

PS:结果是一个事件名称数组,如
[“onwebkitpointerlockerror”、“onwebkitpointerlockchange”、“onwebkitfullscreenerror”、“onwebkitfullscreenchange”、“onselectionchange”、“onselectstart”、“onsearch”、“onreset”、“onpaste”、“onbeforepaste”、“oncopy”]
。。。等等。

在过去的一个世纪里,我就是这样得到动态的
事件列表的,当时IE的建设相当于世界87%到92%的地区的建设。它是一个单行程序,例如::
eventList=[];如果(x.match(/\bon/))eventList.push(x),则为(本例中的变量x)我刚刚在我的Win7最新Opera、IE11、一款相当老的Chrome浏览器和大约2年前的Firefox上测试了它。。。还有该死的(!)-工作起来很有魅力

<