模拟事件【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" , 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()方法,这个方法接收下列参数。
- 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" , 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()方法就可以触发键盘事件,如下面的例子所示。
1
2
3
4
5
6
7
8
9
|
//只适用于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 事件。
在其他浏览器中,则需要创建一个通用的事件,然后再向事件对象中添加键盘事件特有的信息。
例如:
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" , true , false , someNode, "" , "" , "" ,0); targ et.dispatchEvent( event ); |
以上代码模拟了DOMNodeInserted 事件。其他变动事件也都可以照这个样子来模拟,只要改一改参数就可以了。
要模拟HTML 事件,同样需要先创建一个event 对象——通过createEvent("HTMLEvents"),然后再使用这个对象的initEvent()方法来初始化它即可,如下面的例子所示。
1
2
3
|
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 中分派创建的自定义事件对象。例如:
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" , 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 事件过程。
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而在文本框中看到任何字符,即使触发了事件处理程序也没有用。
模拟事件【JavaScript高级程序设计第三版】的更多相关文章
- JavaScript高级程序设计第三版.CHM【带实例】
从驱动全球商业.贸易及管理领域不计其数的复杂应用程序的角度来看,说 JavaScript 已经成为当今世界上最流行的编程语言一点儿都不为过. JavaScript 是一种非常松散的面向对象语言,也是 ...
- 13.6 模拟事件【JavaScript高级程序设计第三版】
事件,就是网页中某个特别值得关注的瞬间.事件经常由用户操作或通过其他浏览器功能来触发. 但很少有人知道,也可以使用JavaScript 在任意时刻来触发特定的事件,而此时的事件就如同浏览器创建的事件一 ...
- javascript高级程序设计第三版书摘
在HTML 中使用JavaScript <script>元素 在使用<script>元素嵌入 JavaScript 代码时,只须为<script>指定 type 属 ...
- 13.4.3 鼠标与滚轮事件【JavaScript高级程序设计第三版】
鼠标事件是Web 开发中最常用的一类事件,毕竟鼠标还是最主要的定位设备.DOM3 级事件中定义了9 个鼠标事件,简介如下. click:在用户单击主鼠标按钮(一般是左边的按钮)或者按下回车键时触发.这 ...
- 22.1 高级函数【JavaScript高级程序设计第三版】
函数是JavaScript 中最有趣的部分之一.它们本质上是十分简单和过程化的,但也可以是非常复杂和动态的.一些额外的功能可以通过使用闭包来实现.此外,由于所有的函数都是对象,所以使用函数指针非常简单 ...
- 21.1 XMLHttpRequest 对象【JavaScript高级程序设计第三版】
IE5 是第一款引入XHR 对象的浏览器.在IE5 中,XHR 对象是通过MSXML 库中的一个ActiveX对象实现的.因此,在IE 中可能会遇到三种不同版本的XHR 对象,即MSXML2.XMLH ...
- 14.5 富文本编辑【JavaScript高级程序设计第三版】
富文本编辑,又称为WYSIWYG(What You See Is What You Get,所见即所得).在网页中编辑富文本内容,是人们对Web 应用程序最大的期待之一.虽然也没有规范,但在IE 最早 ...
- DOM 操作技术【JavaScript高级程序设计第三版】
很多时候,DOM 操作都比较简明,因此用JavaScript 生成那些通常原本是用HTML 代码生成的内容并不麻烦.不过,也有一些时候,操作DOM 并不像表面上看起来那么简单.由于浏览器中充斥着隐藏的 ...
- 23.3.3 Web存储机制【JavaScript高级程序设计第三版】
Web Storage 最早是在Web 超文本应用技术工作组(WHAT-WG)的Web 应用1.0 规范中描述的. 这个规范的最初的工作最终成为了HTML5 的一部分.Web Storage 的目的是 ...
随机推荐
- Python2.7-netrc
netrc 模块,用于解析和封装 netrc 类型的文件,这种类型的文件用于 unix 的 ftp 程序和其他 ftp 客户端.----------------不知道到底是个什么东西 1.模块对象 1 ...
- easyui combotree combobox 使用例子
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...
- Vim2.1-Vim简明教程【CoolShell】【非原创】
vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的.下面的文章翻译自<Learn Vim Progress ...
- MFC Edit控件的使用~~
EditBox,一般用于显示数字文本,或者与用户沟通获取数字文本. 这里介绍一种将EditBox与一个变量关联起来的方法: 快捷键:Shift + Ctrl + X,进入类导向,选择成员变量属性页: ...
- 【中间件】Redis 实战之主从复制、高可用、分布式
目录 简介 持久化 主从复制 高可用 Redis-Sentinel .NET Core开发 分布式 Redis-Cluster 配置说明 常见问题 简介 本节内容基于 CentOS 7.4.1708, ...
- numpy 初识(三)
基本运算 exp: e sqrt:开放 floor:向下取整 ravel:矩阵拉成一个向 T:转置(行和列变换) 改变形状: resize: 更改其形状(返回值为None)a.resize(6,2) ...
- 绕WAF&安全狗新姿势
俗话说只要思路宽,绕狗绕的欢.前段时间我有尝试着用以下的方法绕狗,效果还不错.不过这方法呢也许这段时间可以绕过,过段时间可能就失效了,大家还是要多去尝试找到更多的方法. 举例-->整型注入 绕过 ...
- unity2D限制位置的背景移动补偿效果
有时候我们想要背景可以跟随相机移动补偿,但是又不想该背景物体离原来的位置太远,比如我们想要一棵树在一个房子的后面,然后使用相机补偿使其跟随移动,达到3D错觉效果,但是我们又不想该物体偏离房屋太远.假设 ...
- 172. Remove Element【LintCode by java】
Description Given an array and a value, remove all occurrences of that value in place and return the ...
- 原生js实现table的排序
原生js实现table的排序 今天遇到了一个问题就是使用原生js对table标签进行排序 一开始的时候陷入了一个误区就是首先获取table,然后每次比较完大小都会交换children的值,准备到最后吧 ...