Javascript 尽可能获取所有DOM事件的数组
我已经创建了一个多用途的工厂事件发射器工厂函数。使用它,我可以将对象转化为事件发射器。如果有人想查看或使用它,下面是事件发射器工厂的代码 我的问题是如何从DOM中获取事件列表请注意,我并没有试图获取绑定事件的列表。我想要一个所有可能事件的列表。我想要为发射器添加一个“管道”方法。此方法将获取一个DOM对象并绑定到所有可能的事件,然后当这些事件中的任何一个触发时,每个事件都将触发发射器中同名的事件 我想没有办法做到这一点。我准备制作一个事件名称的硬编码数组,但是如果我可以得到DOM的数组,那会更好,而且如果W3C标准化更多的事件类型,它仍然可以工作 另外,如果你为W3C工作,这就是那种让每个人都讨厌DOM的垃圾。请停止将JavaScript视为玩具语言。它不是一种玩具语言,需要的不仅仅是玩具DOMJavascript 尽可能获取所有DOM事件的数组,javascript,dom,event-handling,dom-events,Javascript,Dom,Event Handling,Dom Events,我已经创建了一个多用途的工厂事件发射器工厂函数。使用它,我可以将对象转化为事件发射器。如果有人想查看或使用它,下面是事件发射器工厂的代码 我的问题是如何从DOM中获取事件列表请注意,我并没有试图获取绑定事件的列表。我想要一个所有可能事件的列表。我想要为发射器添加一个“管道”方法。此方法将获取一个DOM对象并绑定到所有可能的事件,然后当这些事件中的任何一个触发时,每个事件都将触发发射器中同名的事件 我想没有办法做到这一点。我准备制作一个事件名称的硬编码数组,但是如果我可以得到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上测试了它。。。还有该死的(!)-工作起来很有魅力
<