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

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

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属性会自动设置。下面,我们就通过一个例子来了解如何模拟对按钮的单击事件。


1

2

3

4

5

6

7

8

var btn = document.getElementById("myBtn");

//创建事件对象

var event = document.createEvent("MouseEvents");

//初始化事件对象

event.initMouseEvent("click"truetrue, document.defaultView, 0, 0, 0, 0, 0,

falsefalsefalsefalse, 0, null);

//触发事件

btn.dispatchEvent(event);

运行一下
在兼容DOM的浏览器中,也可以通过相同的方式来模拟其他鼠标事件(例如dblclick)。

2. 模拟键盘事件

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

  • 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 事件。


1

2

3

4

5

6

7

8

9

10

var textbox = document.getElementById("myTextbox"),

event;

//以DOM3 级方式创建事件对象

if (document.implementation.hasFeature("KeyboardEvents""3.0")) {

    event = document.createEvent("KeyboardEvent");

    //初始化事件对象

    event.initKeyboardEvent("keydown"truetrue, 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()方法就可以触发键盘事件,如下面的例子所示。


1

2

3

4

5

6

7

8

9

//只适用于Firefox

var textbox = document.getElementById("myTextbox")

//创建事件对象

var event = document.createEvent("KeyEvents");

//初始化事件对象

event.initKeyEvent("keypress"truetrue, document.defaultView, falsefalse,

falsefalse, 65, 65);

//触发事件

textbox.dispatchEvent(event);

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

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。下面来看一个模拟变动事件的例子。


1

2

3

var event = document.createEvent("MutationEvents");

event.initMutationEvent("DOMNodeInserted"truefalse, someNode, "","","",0);

targ et.dispatchEvent(event);

以上代码模拟了DOMNodeInserted 事件。其他变动事件也都可以照这个样子来模拟,只要改一改参数就可以了。
要模拟HTML 事件,同样需要先创建一个event 对象——通过createEvent("HTMLEvents"),然后再使用这个对象的initEvent()方法来初始化它即可,如下面的例子所示。


1

2

3

var event = document.createEvent("HTMLEvents");

event.initEvent("focus"truefalse);

targ et.dispatchEvent(event);

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

浏览器中很少使用变动事件和HTML 事件,因为使用它们会受到一些限制。

4. 自定义DOM 事件

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

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

可以像分派其他事件一样在DOM 中分派创建的自定义事件对象。例如:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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"truefalse"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 事件过程。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

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


1

2

3

4

5

6

7

8

9

10

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而在文本框中看到任何字符,即使触发了事件处理程序也没有用。

时间: 2024-10-03 14:34:43

模拟事件【JavaScript高级程序设计第三版】的相关文章

《JavaScript高级程序设计 第三版》 前2章 Javascript简介与HTML 读书笔记

第一章:Javascript简介 1.JavaScript诞生于1995年,当时,它的主要目的是处理以前由服务器端语言(如Perl)负责的一些输入验证操作.现在,JavaScript是一种专为与网页交互而设计的脚本语言. 注:Netscape(网景)公司研发,Java是sun公司研发,原名为LiveScript,为了搭上媒体热炒的Java的顺风车,更名为JavaScript 2.微软推出JSript的和网景的JavaScript相竞争,最后微软胜利.ECMA指定了规定并重新命名为ECMAScri

21.1 XMLHttpRequest 对象【JavaScript高级程序设计第三版】

IE5 是第一款引入XHR 对象的浏览器.在IE5 中,XHR 对象是通过MSXML 库中的一个ActiveX对象实现的.因此,在IE 中可能会遇到三种不同版本的XHR 对象,即MSXML2.XMLHttp.MSXML2.XMLHttp.3.0 和MXSML2.XMLHttp.6.0.要使用MSXML 库中的XHR 对象,需要像第18章讨论创建XML 文档时一样,编写一个函数,例如: //适用于IE7 之前的版本 function createXHR() { if (typeof argumen

2.1 &lt;script&gt;元素【JavaScript高级程序设计第三版】

向 HTML 页面中插入 JavaScript 的主要方法,就是使用<script>元素.这个元素由 Netscape 创造并在 Netscape Navigator 2 中首先实现.后来,这个元素被加入到正式的 HTML 规范中. HTML 4.01 为<script>定义了下列 6 个属性. async:可选.表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本.只对外部脚本文件有效. charset:可选.表示通过 src 属性指定的代码的字符

javascript高级程序设计第三版 读书笔记

第三章   基本概念 1.在JavaScript中是区分大小写的,第一个字符是字母 _ 或者$,其他字符可以试数字 字母 _ 或者$,命名格式要求是驼峰式书写(第一个字母小写,剩下的每个有意义的单词开头大写  比如fontSize) 2.单行注释//  块级注释为/*多行 内容*/ 不得使用关键字和保留字 3.在JavaScript中变量是松散型的   可以为任何一种类型 4.用var操作符定义的变量成为定义该变量的作用域中的局部变量. function test(){ var i = 'hi'

20.2 解析与序列化【JavaScript高级程序设计第三版】

JSON 之所以流行,拥有与JavaScript 类似的语法并不是全部原因.更重要的一个原因是,可以把JSON 数据结构解析为有用的JavaScript 对象.与XML 数据结构要解析成DOM 文档而且从中提取数据极为麻烦相比,JSON 可以解析为JavaScript 对象的优势极其明显.就以上一节中包含一组图书的JSON数据结构为例,在解析为JavaScript 对象后,只需要下面一行简单的代码就可以取得第三本书的书名: books[2].title 当然,这里是假设把解析JSON 数据结构后

4.1 基本类型和引用类型的值【JavaScript高级程序设计第三版】

ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象. 在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值.第3 章讨论了5 种基本数据类型:Undefined.Null.Boolean.Number 和String.这5 种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值. 引用类型的值是保存在内存中的对象.与其他语言不同,JavaScript 不允许直接访问内存中的

javascript高级程序设计第三版dom元素大小笔记

是滚动大小(scroll dimension),指的是包含滚动内容的元素的大小.有些元素(例如 <html>元素),即使没有执行任何代码也能自动地添加滚动条:但另外一些元素,则需要通过 CSS 的 overflow 属性进行设置才能滚动.以下是 4 个与滚动大小相关的属性. 在IE8以下scrollHeight=元素内容本身的高度. 1.增加边框,不同浏览器有不同解释. 谷歌火狐IE>=8会忽略边框的大小. 2,增加内边距,最终值是width||height+padding ie8以下是

10.1.5 Comment类型【JavaScript高级程序设计第三版】

注释在DOM中是通过Comment 类型来表示的.Comment 节点具有下列特征: nodeType 的值为8: nodeName 的值为"#comment": nodeValue 的值是注释的内容: parentNode 可能是Document 或Element: 不支持(没有)子节点. Comment 类型与Text 类型继承自相同的基类,因此它拥有除splitText()之外的所有字符串操作方法.与Text 类型相似,也可以通过nodeValue 或data 属性来取得注释的内

读Javascript高级程序设计第三版第六章面向对象设计--创建对象

虽然Object构造函数或者对象字面量都可以用来创建单个对象,但是缺点非常明显:使用同一接口创建很多对象,会产生大量重复代码. 工厂模式  1 function CreatePerson(name,age,job){ 2         var o=new Object(); 3         o.name=name; 4         o.age=age; 5         o.job=job; 6         o.sayName=function(){ 7