一、DOM 级别 2 的事件模拟
利用 DOM2 的标准我们可以模拟这些类型的事件:HTMLEvents,MutationEvents,UIEvents 和 MouseEvents。而事件的模拟基本是三步:createEvent,initEvent 和 dispatchEvent。例如我们可以用下面的方式模拟 HTML 事件:
var event = document.createEvent("HTMLEvents"); event.initEvent("focus", true, false); element.dispatchEvent(event);
其中 HTML 事件包括这些:load,unload,abort,error,select,change,submit,reset,focus,blur,resize,scroll。
而变动事件的模拟的例子如下:
var event = document.createEvent("MutationEvents"); event.initMutationEvent("DOMNodeInserted", true, false, someNode, "","","",0); element.dispatchEvent(event);
其中变动事件包括这些:DOMSubtreeModified,DOMNodeInserted,DOMNodeRemoved,DOMNodeRemovedFromDocument,DOMNodeInsertedIntoDocument,DOMAttrModified,DOMCharacterDataModified。
上面这两类事件用得不多的,我们经常需要模拟的是鼠标事件。例如:
var event = document.createEvent("MouseEvents"); event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); element.dispatchEvent(event);
initMouseEvent 的 15 个参数中,第一个指该事件的名称,第二个指该事件是否冒泡,而第三个指该事件是否可取消。其它的参数的意义可以参考 DOM2 文档。如果我们只需要模拟该事件而不关心该事件出现的坐标等,可以偷懒用 initUIEvent(这是由于 MouseEvent 对象继承自 UIEvent 对象),如下:
var event = document.createEvent("MouseEvents"); event.initUIEvent("click", true, true, document.defaultView, 0); element.dispatchEvent(event);
或者更加偷懒地使用 initEvent(因为 UIEvent 对象也是继承自最基本的 Event 对象):
var event = document.createEvent("MouseEvents"); event.initEvent("click", true, true); element.dispatchEvent(event);
二、DOM 级别 3 的事件模拟
在 DOM3 中,增加了 KeyboardEvent,WheelEvent,CustomEvent 等类型事件的模拟。注意对于事件类型名称 DOM2 中使用复数形式,而 DOM3 中使用单数形式。同时,对于 DOM2 中的 MutationEvents,UIEvents 和 MouseEvents,在 DOM3 中同样可以用单数形式的 MutationEvent,UIEvent 和 MouseEvent(DOM3 中没有 HTMLEvent,只涉及到 FocusEvent)。列个表对比并总结如下:
下面的例子模拟了键盘的 keydown 事件(按下 Shift+a):
event = document.createEvent("KeyboardEvent"); event.initKeyboardEvent("keydown", true, true, document.defaultView, "a", 0, "Shift", 0); element.dispatchEvent(event);
类似地也可以模拟 keyup 和 keypress 事件。DOM3 标准中的 initKeyboardEvent 函数参数有过改动,这导致各个浏览器的兼容性出现问题。我们可以参考这里的 gist 代码:Cross-browser initKeyboardEvent。
三、事件模拟的浏览器支持
Firefox,Chrome,Safari,Opera 支持 DOM2 的事件模拟,但是基本不支持 DOM3 新的事件模拟。而 IE9 支持 DOM2 和 DOM3 的事件模拟,但是 IE8 及其之前的版本完全不支持 DOM2 和 DOM3 的事件模拟。在旧版本的 IE 中可以使用 createEventObject 和 fireEvent 方法实现事件模拟。
我们可以用 document.implementation.hasFeature 方法检测浏览器对这些事件模拟的支持情况。例如:
var hasDOM2HTMLEvents = document.implementation.hasFeature("HTMLEvents", "2.0"); var hasDOM3KeyboardEvent = document.implementation.hasFeature("KeyboadEvent", "3.0");
但实际上,这种方法还是不够可靠,最后还是用特性检测比较好。
参考资料:
[1] DOM Level 2 Events - 1. Document Object Model Events
[2] DOM Level 2 Events - Appendix A: IDL Definitions
[3] DOM Level 3 Events - #events-DocumentEvent-createEvent
[4] DOM Level 3 Events - #event-types
[5] DOM Level 3 Events - #event-interfaces
[6] document.createEvent - Document Object Model (DOM) | MDN
[7] DOM Level 3 Events support in IE9 - IEBlog - Site Home - MSDN Blogs
[8] Internet Explorer: Testing Center #domevents