一、模拟事件(模拟一个事件的触发)
- 事件,就是网页中某个特别值得关注的瞬间。事件经常由用户操作或通过其他浏览器功能来触发。 但很少有人知道,也可以使用 JavaScript 在任意时刻来触发特定的事件,而此时的事件就如同浏览器创建的事件一样。也就是说,这些事件该冒泡还会冒泡,而且照样能够导致浏览器执行已经指定的处理它们的事件处理程序。
- 在
测试 Web 应用程序
,模拟触发事件是一种极其有用的技术。DOM2 级规范为此 规定了模拟特定事件的方式,IE9、Opera、Firefox、Chrome 和 Safari 都支持这种方式。IE 有它自己模拟事件的方式。
二、DOM中的事件模拟
-
使用
createEvent()方法创建 event 对象
:可以在 document 对象上使用 createEvent()方法创建 event 对象。 -
这个方法接收一个参数,即表示要创建的事件类型的字符串。在 DOM2 级中,所有这些字符串都使用英文复数形式,而在 DOM3级中都变成了单数。这个字符串可以是下列几字符串之一。
要注意的是,“DOM2 级事件”并没有专门规定键盘事件,后来的“DOM3 级事件”中才正式将其作为一种事件给出规定。IE9 是目前唯一支持 DOM3 级键盘事件的浏览器。不过,在其他浏览器中,在现有方法的基础上,可以通过几种方式来模拟键盘事件。 -
在创建了 event 对象之后,还需要使用与事件有关的信息对其进行初始化。每种类型的 event 对象都有一个特殊的方法,为它传入适当的数据就可以初始化该 event 对象。不同类型的这个方法的名字也不相同,具体要取决于 createEvent()中使用的参数。
-
模拟事件的最后一步就是触发事件。这一步需要使用
dispatchEvent()
方法,所有支持事件的 DOM 节点都支持这个方法。调用 dispatchEvent()方法时,需要传入一个参数,即表示要触发事件的 event 对象。触发事件之后,该事件就跻身“官方事件”之列了,因而能够照样冒泡并引发相应事件处理程序的执行。
1、模拟鼠标事件
- 创建新的鼠标事件对象并为其指定必要的信息,就可以模拟鼠标事件。
- 创建鼠标事件对象的方法:为
createEvent()传入字符串"MouseEvents"
。返回的对象有一个名为initMouseEvent()方法
, 用于指定与该鼠标事件有关的信息【用于初始化】。这个方法接收 15 个参数,分别与鼠标事件中每个典型的属性一一 对应;这些参数的含义如下。
显而易见,initMouseEvent()方法的这些参数是与鼠标事件的 event 对象所包含的属性一一对应的。其中,前 4 个参数对正确地激发事件至关重要,因为浏览器要用到这些参数;而剩下的所有参数只有在事件处理程序中才会用到。
- 当把
event 对象传给 dispatchEvent()方法
时,这个对象的 target 属性会自动设置。下面,我们就通过一个例子来了解如何模拟对按钮的单击事件。
在兼容 DOM 的浏览器中,也可以通过相同的方式来模拟其他鼠标事件(例如 dblclick)。
-
以下模拟的鼠标事件,会自动弹出alert(1);
var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert(1); } var event = document.createEvent("MouseEvents"); event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0,false, false, false, false, 0, null); btn.dispatchEvent(event);
2、模拟键盘事件( 已废弃)
前面曾经提到过,“DOM2 级事件”中没有就键盘事件作出规定,因此模拟键盘事件并没有现成的思路可循。“DOM2 级事件”的草案中本来包含了键盘事件,但在定稿之前又被删除了;Firefox 根据其草案实现了键盘事件。需要提请大家注意的是,“DOM3 级事件”中的键盘事件与曾包含在“DOM2 级 事件”草案中的键盘事件有很大区别。
- DOM3 级规定,调用 createEvent()并传入
"KeyboardEvent"
就可以创建一个键盘事件。返回的事件对象会包含一个 initKeyEvent()方法
,这个方法接收下列参数。
由于 DOM3 级不提倡使用 keypress 事件,因此只能利用这种技术来模拟keydown 和 keyup 事件
。
var textbox = document.getElementById("myTextbox"),
event;
//以 DOM3 级方式创建事件对象
if (document.implementation.hasFeature("KeyboardEvents", "3.0")){
event = document.createEvent("KeyboardEvent");
//初始化事件对象
event.initKeyboardEvent("keydown", true, true, document.defaultView, "a",0, "Shift", 0);
}
//触发事件
textbox.dispatchEvent(event);
这个例子模拟的是按住 Shift 的同时又按下 A 键。在使用 document.createEvent (“KeyboardEvent”)之前,应该先检测浏览器是否支持 DOM3 级事件;其他浏览器返回一个非标准的 KeyboardEvent 对象。
- 在 Firefox 中,调用 createEvent()并传入
"KeyEvents"
就可以创建一个键盘事件。返回的事件对象会包含一个initKeyEvent()方法
,这个方法接受下列 10 个参数。
- 将创建的 event 对象传入到 dispatchEvent()方法就可以触发键盘事件,如下面的例子所示。
在 Firefox 中运行上面的代码,会在指定的文本框中输入字母 A。同样,也可以依此模拟 keyup 和 keydown 事件。 - 在其他浏览器中,则需要创建一个通用的事件,然后再向事件对象中添加键盘事件特有的信息。 例如:
以上代码首先创建了一个通用事件,然后调用initEvent()
对其进行初始化,最后又为其添加了键盘事件的具体信息。在此必须要使用通用事件
,而不能使用 UI 事件,因为 UI 事件不允许向 event 对象中再添加新属性(Safari 除外)。像这样模拟事件虽然会触发键盘事件,但却不会向文本框中写入文本,这是由于无法精确模拟键盘事件所造成的。
3、模拟其他事件
虽然鼠标事件和键盘事件是在浏览器中最经常模拟的事件,但有时候同样需要模拟变动事件和 HTML 事件。
- 要模拟变动事件,可以使用
createEvent("MutationEvents")
创建一个包含initMutationEvent()方法
的变动事件对象。
- 这个方法接受的参数包括:type、bubbles、 cancelable、relatedNode、preValue、newValue、attrName 和 attrChange。下面来看一个模拟变动事件的例子。
以上代码模拟了DOMNodeInserted事件。其他变动事件也都可以照这个样子来模拟,只要改一改参数就可以了。
- 要模拟 HTML 事件,同样需要先创建一个 event 对象——通过
createEvent("HTMLEvents")
, 然后再使用这个对象的initEvent()方法
来初始化
它即可,如下面的例子所示。
这个例子展示了如何在给定目标上模拟 focus 事件。模拟其他 HTML 事件的方法也是这样。
浏览器中很少使用变动事件和 HTML 事件,因为使用它们会受到一些限制。
4、自定义 DOM 事件
-
DOM3 级还定义了“自定义事件”。自定义事件不是由 DOM 原生触发的,它的目的是让开发人员创建自己的事件。
-
要创建新的自定义事件,可以
调用 createEvent("CustomEvent")
。返回的对象有一个名为initCustomEvent()的方法
,接收如下 4 个参数。
-
可以像分派其他事件一样在 DOM 中分派创建的自定义事件对象。例如:
这个例子创建了
一个冒泡事件"myevent"
。而 event.detail 的值被设置成了一个简单的字符串, 然后在<div>
元素和 document 上侦听这个事件。因为 initCustomEvent()方法已经指定这个事件应该冒泡,所以浏览器会负责将事件向上冒泡到 document。
支持自定义 DOM 事件的浏览器有 IE9+和 Firefox 6+。
三、IE中的事件模拟
在 IE8 及之前版本中模拟事件与在 DOM 中模拟事件的思路相似:先创建 event 对象,然后为其指定相应的信息,然后再使用该对象来触发事件。当然,IE 在实现每个步骤时都采用了不一样的方式。
- 调用
document.createEventObject()方法
可以在 IE 中创建 event 对象
。但与 DOM 方式不同 的是,这个方法不接受参数,结果会返回一个通用的 event 对象。 - 然后,你必须手工为这个对象添加所有必要的信息(没有方法来辅助完成这一步骤)。
- 最后一步就是
在目标上调用 fireEvent()方法
,这 个方法接受两个参数:事件处理程序的名称和 event 对象。在调用 fireEvent()方法时,会自动为 event 对象添加 srcElement 和 type 属性;其他属性则都是必须通过手工添加的。换句话说,模拟任何 IE 支持的事件都采用相同的模式。例如,下面的代码模拟了在一个按钮上触发 click 事件过程。
var btn = document.getElementById("myBtn");
//创建事件对象
var event = document.createEventObject();
//初始化事件对象
event.screenX = 100;
event.screenY = 0;
event.clientX = 0;
event.clientY = 0;
event.ctrlKey = false;
event.altKey = false;
event.shiftKey = false;
event.button = 0;
//触发事件
btn.fireEvent("onclick", event);
- 这个例子先创建了一个 event 对象,然后又用一些信息对其进行了初始化。注意,这里可以为对象随意添加属性,不会有任何限制——即使添加的属性 IE8 及更早版本并不支持也无所谓。在此添加的属性对事件没有什么影响,因为只有事件处理程序才会用到它们。
- 采用相同的模式也可以模拟触发 keypress 事件,如下面的例子所示。
由于鼠标事件、键盘事件以及其他事件的 event 对象并没有什么不同,所以可以使用通用对象来 触发任何类型的事件。不过,正如在 DOM 中模拟键盘事件一样,运行这个例子也不会因模拟了 keypress 而在文本框中看到任何字符,即使触发了事件处理程序也没有用【只在火狐中会嘛?
】。