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

相關文章
相關標籤/搜索