获取所有可能的 DOM 事件的数组
我创建了一个多用途工厂事件发射器工厂函数。有了它我可以将对象变成事件发射器。如果有人想查看或使用它,事件发射器工厂的代码如下。
我的问题是如何从 DOM 获取事件列表。 请注意,我并不是想获取绑定事件的列表。我想要所有可能事件的列表。我想向发射器添加“管道”方法。此方法将采用 DOM 对象并绑定到所有可能的事件,然后当其中任何一个事件触发时,每个事件都会在发射器中触发同名的事件。
我不认为有办法做到这一点。我准备制作一个硬编码的事件名称数组,但如果我可以获取 DOM 的数组,效果会更好,并且在 W3C 标准化更多事件类型的情况下仍然可以工作。
PS 如果你为 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); });
}
}
}
I've created a multi purpose factory event emitter factory function. With it I can turn objects into event emitters. The code for the event emitter factory is below if anyone would like to have a look or use it.
My question is how can I get a list of events from the DOM. Please note I'm not trying to get a list of bound events. I want a list of all events possible. I want to add a "pipe" method to emitters. This method would take a DOM object and bind to all possible events, then when any of those events fire each would trigger an event of the same name in the emitter.
I don't imagine there is a way to do this. I'm prepared to make a hard coded array of event names, but if I can get the array for the DOM instead that would be much better and would still work if the W3C standardizes more event types.
P.S. If you work for the W3C this is the kind of crap that makes everyone hate the DOM. Please stop treating JavaScript like a toy language. It is not a toy language and needs more than your toy 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); });
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是一个适用于 Chrome、Safari 和 FF 的版本。
UPD 1:
这是适用于 IE9+、Chrome、Safari 和 FF 的版本。
UPD 2:
这是一个使用较新 JavaScript 功能的版本(
[...new Set(...)]
用于过滤掉重复,替换filter
方法)。PS:结果是一个事件名称数组,例如
["onwebkitpointerlockerror", "onwebkitpointerlockchange", "onwebkitfullscreenerror", "onwebkitfullscreenchange", "onselectionchange", "onselectstart", "onsearch", "onreset", "onpaste" 、“onbeforepaste”、“oncopy”]
...等。Here is a version that works in Chrome, Safari and FF.
UPD 1:
And here is the version that works in IE9+, Chrome, Safari and FF.
UPD 2:
And here's a version using newer JavaScript features (the
[...new Set(...)]
is to filter out duplicates, replacing thefilter
approach).PS: the result is an array of events name like
["onwebkitpointerlockerror", "onwebkitpointerlockchange", "onwebkitfullscreenerror", "onwebkitfullscreenchange", "onselectionchange", "onselectstart", "onsearch", "onreset", "onpaste", "onbeforepaste", "oncopy"]
... ect.所有 DOM 事件均以
on
开头。您可以循环遍历任何Element
实例,并列出以on
开头的所有属性。例子。将以下代码复制粘贴到控制台中(Firefox,使用数组推导式;)):
获取事件的另一种方法是查看 规范,其中揭示了:
All DOM events start with
on
. You can loop through anyElement
instance, and list all properties which start withon
.Example. Copy-paste the following code in the console (Firefox, using Array comprehensions ;)):
Another method to get the events is by looking at the specification, which reveals:
这就是我在上个世纪获取动态
eventList
的方式,当时为 IE 构建相当于为世界上 87% 到 92% 的人构建。这是一个单行代码,例如 ::eventList = []; for( var x in this )if( x.match(/\bon/) )eventList.push(x);
我刚刚在我的 win 7 最新 Opera、IE11 上测试了它,一个相当旧的 Chrome 浏览器,还有大约 2 年历史的 Firefox……该死的(!)——工作得非常有魅力。This is how I used to get the dynamic
eventList
in the past century when building for IE was the equivalent of building for 87% to 92% of the world. It was a oneliner such as ::eventList = []; for( var x in this )if( x.match(/\bon/) )eventList.push(x);
and I just tested it on my win 7 up to date Opera, IE11, a pretty old Chrome, and about 2 years old Firefox... and damn (!) - worked like a charm.您不可能有一份详尽的列表,因为我们可以用任何名称触发合成事件。
例如:
即使拥有所有“内置”事件的列表也几乎是不可能的。其中许多事件没有在任何地方公开
.onevent
IDL 属性,例如文档或窗口的DOMContentLoaded
,或输入元素compositionXXX
或许多其他隐藏的各种规格。即使捕获所有这些
oneevent
IDL 属性也需要遍历所有构造函数的原型,因为window
仅公开其中的一些属性。虽然我们可以在网上找到此类事件的相当大的列表,因为规范在不断变化,浏览器并不支持规范中的所有功能,或者相反,支持规范中没有的功能,没有这样的列表可以涵盖所有功能。
(例如,对于最后一点,dragexit 事件目前已从规范中删除,只有 Firefox 支持。)
You can't have an exhaustive list, for one because we can fire synthetic events with any name.
For instance:
Even having a list of all "built-in" events is near impossible. Many of these events don't have an
.onevent
IDL attribute exposed anywhere, like Document's or Window'sDOMContentLoaded
, or inputs ElementscompositionXXX
or many others hidden in various specs.Even catching all these
onevent
IDL attributes would require to walk through all the Constructor's prototypes sincewindow
only exposes some of these.And while we can find quite big lists of such events online, since the specs are changing continuously and the browsers do not support everything from the specs, or at the contrary supporting features that are not in the specs, no such list will catch them all.
(For instance on this last point, the dragexit event is currently being removed from the specs, when only Firefox does support it.)