模拟事件【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
|
//只适用于Firefoxvar 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 的目的是 ...
随机推荐
- SpringBoot实用技巧札记
目录 如何手工设置SpringBoot内嵌的Tomcat启动端口号(port) 如何解决Eclipse.Properties中文乱码的问题 如何手工设置SpringBoot内嵌的Tomcat启动端口号 ...
- Scrapy 框架(二)数据的持久化
scrapy数据的持久化(将数据保存到数据库) 一.建立项目 1.scrapy startproject dushu 2.进入项目 cd dushu 执行:scrapy genspider -t cr ...
- jmeter.bat配置(主要关于OOM)
jmeter.bat是jmeter在windows系统下的启动文件.在使用jmeter压测,线程数设置过多时可能会报内存溢出(Out Of Memory Error),这时候可以去尝试调整一下jmet ...
- (二)Lua脚本语言入门(关于函数)
上一篇文章忘了插入代码了,方便粘贴复制...... 函数 对于c语言就是 void aa()//c语言是用void { print("这是一个函数") } Lua就变成了 func ...
- 【转】PHP 类与对象
原文:http://blog.csdn.net/e421083458/article/details/8217650 1.类与对象 对象:实际存在该类事物中每个实物的个体.$a =new User() ...
- TortoiseSVN 只取下或更新部分文件的方法(Sparse Update/Sparse Checkout)
Sparse Update/Sparse Checkout To easily select only the items you want for the checkout and force ...
- 20155220 Exp9 Web安全基础实践
Exp9 Web安全基础实践 实验过程 开启webgoat 输入java -jar webgoat-container-7.1-exec.jar,来运行webgoat 在浏览器输入localhost: ...
- Luogu P1972 [SDOI2009]HH的项链
很清新自然凶猛的数据结构题,都是套路啊 我们可以考虑离线做,先把区间按右端点从小到大排序 首先注意到一种贝壳如果在一段中出现超过1次,那么它在前面或后面就无关紧要了 举一个例子: 对于数列1 2 3 ...
- LOJ.#6468. 魔法[差分+树状数组]
题意 题目链接 分析 将询问差分并不断加入颜色. 每种颜色,一个位置 \(p\) 都只会走到与之左右相邻的两个位置之一,分类讨论 \(\rm |A-B|\) 的符号. 实现可以使用树状数组. 总时间复 ...
- Grid布局20行代码快速生成瀑布流
网格布局 Grid 布局,好用又简单,至少比 Flex 要人性化一点,美中不足就是浏览器支持度差点. DOM结构 中间夹层为了后续拓展. CSS .grid { display: grid; grid ...