13.6 模拟事件【JavaScript高级程序设计第三版】

事件,就是网页中某个特别值得关注的瞬间。事件常常由用户操做或经过其余浏览器功能来触发。
但不多有人知道,也可使用JavaScript 在任意时刻来触发特定的事件,而此时的事件就如同浏览器建立的事件同样。也就是说,这些事件该冒泡还会冒泡,并且照样可以致使浏览器执行已经指定的处理它们的事件处理程序。在测试Web 应用程序,模拟触发事件是一种极其有用的技术。DOM2 级规范为此规定了模拟特定事件的方式,IE九、Opera、Firefox、Chrome 和Safari 都支持这种方式。IE 有它本身模拟事件的方式。api

13.6.1 DOM中的事件模拟

能够在document 对象上使用createEvent()方法建立event 对象。这个方法接收一个参数,即表示要建立的事件类型的字符串。在DOM2 级中,全部这些字符串都使用英文复数形式,而在DOM3级中都变成了单数。这个字符串能够是下列几字符串之一。浏览器

  • UIEvents:通常化的UI 事件。鼠标事件和键盘事件都继承自UI 事件。DOM3 级中是UIEvent。
  • MouseEvents:通常化的鼠标事件。DOM3 级中是MouseEvent。
  • MutationEvents:通常化的DOM 变更事件。DOM3 级中是MutationEvent。
  • HTMLEvents:通常化的HTML 事件。没有对应的DOM3 级事件(HTML 事件被分散到其余类别中)。

要注意的是,“DOM2 级事件”并无专门规定键盘事件,后来的“DOM3 级事件”中才正式将其做为一种事件给出规定。IE9 是目前惟一支持DOM3 级键盘事件的浏览器。不过,在其余浏览器中,在现有方法的基础上,能够经过几种方式来模拟键盘事件。
在建立了event 对象以后,还须要使用与事件有关的信息对其进行初始化。每种类型的event 对象都有一个特殊的方法,为它传入适当的数据就能够初始化该event 对象。不一样类型的这个方法的名字也不相同,具体要取决于createEvent()中使用的参数。
模拟事件的最后一步就是触发事件。这一步须要使用dispatchEvent()方法,全部支持事件的DOM 节点都支持这个方法。调用dispatchEvent()方法时,须要传入一个参数,即表示要触发事件的event 对象。触发事件以后,该事件就跻身“官方事件”之列了,于是可以照样冒泡并引起相应事件处理程序的执行。测试

1. 模拟鼠标事件

建立新的鼠标事件对象并为其指定必要的信息,就能够模拟鼠标事件。建立鼠标事件对象的方法是为createEvent()传入字符串"MouseEvents"。返回的对象有一个名为initMouseEvent()方法,用于指定与该鼠标事件有关的信息。这个方法接收15 个参数,分别与鼠标事件中每一个典型的属性一一对应;这些参数的含义以下。编码

  • type(字符串):表示要触发的事件类型,例如"click"。
  • bubbles(布尔值):表示事件是否应该冒泡。为精确地模拟鼠标事件,应该把这个参数设置为true。
  • cancelable(布尔值):表示事件是否能够取消。为精确地模拟鼠标事件,应该把这个参数设置为true。
  • view(AbstractView):与事件关联的视图。这个参数几乎老是要设置为document.defaultView。
  • detail(整数):与事件有关的详细信息。这个值通常只有事件处理程序使用,但一般都设置为0。
  • screenX(整数):事件相对于屏幕的X 坐标。
  • screenY(整数):事件相对于屏幕的Y 坐标。
  • clientX(整数):事件相对于视口的X 坐标。
  • clientY(整数):事件想对于视口的Y 坐标。
  • ctrlKey(布尔值):表示是否按下了Ctrl 键。默认值为false。
  • altKey(布尔值):表示是否按下了Alt 键。默认值为false。
  • shiftKey(布尔值):表示是否按下了Shift 键。默认值为false。
  • metaKey(布尔值):表示是否按下了Meta 键。默认值为false。
  • button(整数):表示按下了哪个鼠标键。默认值为0。
  • relatedTarget(对象):表示与事件相关的对象。这个参数只在模拟mouseover 或mouseout时使用。

显而易见,initMouseEvent()方法的这些参数是与鼠标事件的event 对象所包含的属性一一对应的。其中,前4 个参数对正确地激发事件相当重要,由于浏览器要用到这些参数;而剩下的全部参数只有在事件处理程序中才会用到。当把event 对象传给dispatchEvent()方法时,这个对象的target属性会自动设置。下面,咱们就经过一个例子来了解如何模拟对按钮的单击事件。spa

var btn = document.getElementById("myBtn");
//建立事件对象
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);

运行一下
在兼容DOM的浏览器中,也能够经过相同的方式来模拟其余鼠标事件(例如dblclick)。对象

2. 模拟键盘事件

前面曾经提到过,“DOM2 级事件”中没有就键盘事件做出规定,所以模拟键盘事件并无现成的思路可循。“DOM2 级事件”的草案中原本包含了键盘事件,但在定稿以前又被删除了;Firefox 根据其草案实现了键盘事件。须要提请你们注意的是,“DOM3 级事件”中的键盘事件与曾包含在“DOM2 级事件”草案中的键盘事件有很大区别。
DOM3 级规定,调用createEvent()并传入"KeyboardEvent"就能够建立一个键盘事件。返回的事件对象会包含一个initKeyEvent()方法,这个方法接收下列参数。blog

  • type(字符串):表示要触发的事件类型,如"keydown"。
  • bubbles(布尔值):表示事件是否应该冒泡。为精确模拟鼠标事件,应该设置为true。
  • cancelable(布尔值):表示事件是否能够取消。为精确模拟鼠标事件,应该设置为true。
  • view (AbstractView ):与事件关联的视图。这个参数几乎老是要设置为document.defaultView。
  • key(布尔值):表示按下的键的键码。
  • location(整数):表示按下了哪里的键。0 表示默认的主键盘,1 表示左,2 表示右,3 表示数字键盘,4 表示移动设备(即虚拟键盘),5 表示手柄。
  • modifiers(字符串):空格分隔的修改键列表,如"Shift"。
  • repeat(整数):在一行中按了这个键多少次。

因为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 个参数。教程

  • type(字符串):表示要触发的事件类型,如"keydown"。
  • bubbles(布尔值):表示事件是否应该冒泡。为精确模拟鼠标事件,应该设置为true。
  • cancelable(布尔值):表示事件是否能够取消。为精确模拟鼠标事件,应该设置为true。
  • view(AbstractView):与事件关联的视图。这个参数几乎老是要设置为document.default-View。
  • ctrlKey(布尔值):表示是否按下了Ctrl 键。默认值为false。
  • altKey(布尔值):表示是否按下了Alt 键。默认值为false。
  • shiftKey(布尔值):表示是否按下了Shift 键。默认值为false。
  • metaKey(布尔值):表示是否按下了Meta 键。默认值为false。
  • keyCode(整数):被按下或释放的键的键码。这个参数对keydown 和keyup 事件有用,默认值为0。
  • charCode(整数):经过按键生成的字符的ASCII 编码。这个参数对keypress 事件有用,默认值为0。

将建立的event 对象传入到dispatchEvent()方法就能够触发键盘事件,以下面的例子所示。seo

//只适用于Firefox
var textbox = document.getElementById("myTextbox")
//建立事件对象
var event = document.createEvent("KeyEvents");
//初始化事件对象
event.initKeyEvent("keypress", true, true, document.defaultView, false, false,
false, false, 65, 65);
//触发事件
textbox.dispatchEvent(event);

运行一下
在Firefox 中运行上面的代码,会在指定的文本框中输入字母A。一样,也能够依此模拟keyup 和keydown 事件。
在其余浏览器中,则须要建立一个通用的事件,而后再向事件对象中添加键盘事件特有的信息。
例如:

var textbox = document.getElementById("myTextbox");
//建立事件对象
var event = document.createEvent("Events");
//初始化事件对象
event.initEvent(type, bubbles, cancelable);
event.view = document.defaultView;
event.altKey = false;
event.ctrlKey = false;
event.shiftKey = false;
event.metaKey = false;
event.keyCode = 65;
event.charCode = 65;
//触发事件
textbox.dispatchEvent(event);

以上代码首先建立了一个通用事件,而后调用initEvent()对其进行初始化,最后又为其添加了键盘事件的具体信息。在此必需要使用通用事件,而不能使用UI 事件,由于UI 事件不容许向event对象中再添加新属性(Safari 除外)。像这样模拟事件虽然会触发键盘事件,但却不会向文本框中写入文本,这是因为没法精确模拟键盘事件所形成的。

3. 模拟其余事件

虽然鼠标事件和键盘事件是在浏览器中最常常模拟的事件,但有时候一样须要模拟变更事件和HTML 事件。要模拟变更事件, 可使用createEvent("MutationEvents") 建立一个包含initMutationEvent() 方法的变更事件对象。这个方法接受的参数包括: type 、bubbles 、cancelable、relatedNode、preValue、newValue、attrName 和attrChange。下面来看一个模拟变更事件的例子。

var event = document.createEvent("MutationEvents");
event.initMutationEvent("DOMNodeInserted", true, false, someNode, "","","",0);
targ et.dispatchEvent(event);

以上代码模拟了DOMNodeInserted 事件。其余变更事件也均可以照这个样子来模拟,只要改一改参数就能够了。
要模拟HTML 事件,一样须要先建立一个event 对象——经过createEvent("HTMLEvents"),而后再使用这个对象的initEvent()方法来初始化它便可,以下面的例子所示。

var event = document.createEvent("HTMLEvents");
event.initEvent("focus", true, false);
targ et.dispatchEvent(event);

这个例子展现了如何在给定目标上模拟focus 事件。模拟其余HTML 事件的方法也是这样。

浏览器中不多使用变更事件和HTML 事件,由于使用它们会受到一些限制。

4. 自定义DOM 事件

DOM3 级还定义了“自定义事件”。自定义事件不是由DOM 原生触发的,它的目的是让开发人员建立本身的事件。要建立新的自定义事件,能够调用createEvent("CustomEvent")。返回的对象有一个名为initCustomEvent()的方法,接收以下4 个参数。

  • type(字符串):触发的事件类型,例如"keydown"。
  • bubbles(布尔值):表示事件是否应该冒泡。
  • cancelable(布尔值):表示事件是否能够取消。
  • detail(对象):任意值,保存在event 对象的detail 属性中。

能够像分派其余事件同样在DOM 中分派建立的自定义事件对象。例如:

var div = document.getElementById("myDiv"),
event;
EventUtil.addHandler(div, "myevent",
function(event) {
	alert("DIV: " + event.detail);
});
EventUtil.addHandler(document, "myevent",
function(event) {
	alert("DOCUMENT: " + event.detail);
});
if (document.implementation.hasFeature("CustomEvents", "3.0")) {
	event = document.createEvent("CustomEvent");
	event.initCustomEvent("myevent", true, false, "Hello world!");
	div.dispatchEvent(event);
}

运行一下
这个例子建立了一个冒泡事件"myevent"。而event.detail 的值被设置成了一个简单的字符串,而后在<div>元素和document 上侦听这个事件。由于initCustomEvent()方法已经指定这个事件应该冒泡,因此浏览器会负责将事件向上冒泡到document。
支持自定义DOM事件的浏览器有IE9+和Firefox 6+。

13.6.2 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 事件,以下面的例子所示。

var textbox = document.getElementById("myTextbox");
//建立事件对象
var event = document.createEventObject();
//初始化事件对象
event.altKey = false;
event.ctrlKey = false;
event.shiftKey = false;
event.keyCode = 65;
//触发事件
textbox.fireEvent("onkeypress", event);

运行一下
因为鼠标事件、键盘事件以及其余事件的event 对象并无什么不一样,因此可使用通用对象来触发任何类型的事件。不过,正如在DOM中模拟键盘事件同样,运行这个例子也不会因模拟了keypress而在文本框中看到任何字符,即便触发了事件处理程序也没有用。

下载离线版教程:http://www.shouce.ren/api/view/a/15218

相关文章
相关标签/搜索