17.2. DOM2中的高級事件處理(Advanced Event Handling with DOM Level 2)
??????? 迄今為止,在本章中出現(xiàn)的事件處理技術(shù)都是DOM0級的一部分,所有支持JavaScript的瀏覽器都支持DOM0的API.DOM2定義了高級的事件處理API,和DOM0的API相比,有著令人矚目的不同(而且功能更強(qiáng)大).雖然DOM2標(biāo)準(zhǔn)并沒有把已有的API收入其中,但是DOM0級API也沒有被去除.對于基本的事件處理任務(wù),你會覺得使用這些簡單的API更自由一些.
??????? DOM2事件模型被除了IE以外的所有瀏覽器支持.
17.2.1. 事件傳播(Event Propagation)
??????? 在DOM0級事件模型中,瀏覽器分派事件給發(fā)生事件的文檔元素.如果那個對象有相應(yīng)的事件處理程序,那么就運(yùn)行該程序.再沒有更多的事情發(fā)生了.情況在DOM2中就是復(fù)雜得多.在DOM2高級事件模型中,當(dāng)一個文檔元素(被叫做事件的目標(biāo)(target)對象)觸發(fā)了一個事件,這個目標(biāo)對象的事件處理程序被觸發(fā),除此之外,該目標(biāo)對象的每一個祖輩元素都有一個或者兩個機(jī)會去處理該事件.事件傳播的過程包括三個階段.
??????? 首先,在捕獲階段(capturing phase),事件是從文檔對象(Document object)開始,沿著文檔樹向下一直到目標(biāo)對象傳播的.如果任何目標(biāo)對象的祖輩(不包括目標(biāo)對象本身)也有一些指定注冊的捕獲事件的處理程序,在事件傳播的這個階段(捕獲階段)將運(yùn)行它們.(一會兒你就會看到如何注冊正常事件處理程序和捕獲事件處理程序.)
??????? 事件傳播的下一個階段發(fā)生在目標(biāo)對象自身:所有注冊到目標(biāo)對象的對應(yīng)事件處理程序都被運(yùn)行.這和DOM0提供的事件模型是相似的.
??????? 事件傳播的第三階段是冒泡階段,或者說按文檔層次倒序的,從目標(biāo)元素到文檔對象(Document object).盡管所有的事件都受事件傳播的捕獲階段(capturing phase)的影響,但是,并不是所有類型的事件都冒泡:例如,除了被定義了提交事件(submit)的form以外,把這個事件向上傳播到文檔元素是沒有任何意義的.另一方面,像mousedown這樣的一般事件對文檔中的其它元素是有意義的,所以這些事件才沿著文檔層次向上冒泡,并且觸發(fā)目標(biāo)元素的祖輩元素的相應(yīng)事件的處理程序.通常情況下,原始的輸入事件冒泡,而高級的語義事件不會.(稍候在本章中出現(xiàn)的表17-3是一個權(quán)威的列表,它指出哪些事件是冒泡的,哪些不是.)
??????? 在事件傳播期間,每個事件的處理程序都可以阻止事件的進(jìn)一步傳播,只需通過調(diào)用表現(xiàn)這個事件的事件對象的stopPropagation( )方法就可以.事件對象和stopPropagation( )方法一會兒再進(jìn)一步討論.
??????? 一些事件會使瀏覽器執(zhí)行一個與事件相關(guān)聯(lián)的默認(rèn)行為.例如,當(dāng)點(diǎn)擊一個鏈接(<a> tag)的時(shí)候,瀏覽器的默認(rèn)行為是轉(zhuǎn)向超鏈接.像這樣的默認(rèn)行為,只有事件傳播的三個階段都完成了才會執(zhí)行,在事件傳播過程中調(diào)用的任何處理程序都能阻止默認(rèn)行為的發(fā)生,調(diào)用事件對象的preventDefault( )方法就可以了.
??????? 盡管這種事件傳播機(jī)制似乎讓人難以理解,但是它有助于你集中你的事件處理代碼.DOM1指出了所有的文檔元素,還指出了在那些元素上允許發(fā)生的事件(如mouseover事件).這就意味著,與舊的DOM0事件模型相比,DOM1是在很多很多的地方注冊事件處理程序.假設(shè)你想在鼠標(biāo)經(jīng)過每一個文檔中的段落元素(<P>)時(shí)觸發(fā)一個事件處理程序.除了在所有的段落標(biāo)簽(<p>tag)注冊一個onmouseover事件處理程序之外,取而代之的辦法是為文檔對象(Document object)注冊一個單獨(dú)的事件處理程序,然后,或者在捕獲階段,或者在冒泡階段,處理這些事件.
??????? 事件傳播還有一個很重要的細(xì)節(jié).在DOM0模型中,你只能為一個特定的對象的一個特定類型的事件注冊一個處理程序.而在DOM2模型中,你可以為一個特定對象的一個特定類型事件注冊任意數(shù)量的事件處理程序.這也適用于事件傳播時(shí),在捕獲階段或者冒泡階段,事件對象的祖輩的處理函數(shù)被調(diào)用的情況.
17.2.2. 事件處理程序的注冊(Event Handler Registration)
??????? 在DOM0的API中,你通過在HTML中設(shè)置屬性(attribute)或者在JavaScript中設(shè)置一個對象的屬性(property)的方法注冊事件.而在DOM2模型中,你通過調(diào)用那個對象的addEventListener( )方法注冊事件處理程序.(DOM標(biāo)準(zhǔn)在這個API里使用了術(shù)語listener,但是在本文中,我將繼續(xù)使用這個術(shù)語的同義詞:handler.)這個方法有三個參數(shù).第一個是被注冊的事件類型.事件類型是一個字符串,包含小寫的,去掉開頭的"on"的HTML中的事件屬性名.如果你在DOM0里使用HTML屬性onmousedown,你在DOM2中就是使用字符串"mousedown".
??????? 第二個參數(shù)是指定類型的事件觸發(fā)的時(shí)候應(yīng)該調(diào)用的監(jiān)聽函數(shù).在你的函數(shù)被調(diào)用的時(shí)候,傳入了唯一的一個參數(shù):Event對象.這個對象包含了事件的細(xì)節(jié)信息(如:哪個鼠標(biāo)鍵被按下)和一些方法,如:stopPropagation( ).在本章后面將深入討論事件接口和它的子接口.
??????? addEventListener( )函數(shù)的最后一個參數(shù)是一個布爾值.如果為true,指定的事件處理程序在事件傳播的捕獲階段將捕獲事件.如果是false,事件處理程序就是一個正常的事件處理程序了,只有在事件直接發(fā)生在該對象上或者發(fā)生在子代對象上向上冒泡到達(dá)這個元素時(shí),處理程序才被調(diào)用.
舉個例子,你可以像下面這樣使用addEventListener( )方法給一個form元素注冊一個提交事件(submit):
document.myform.addEventListener("submit",
???????????????????????????????? function(e) {return validate(e.target); }
???????????????????????????????? false);
如果你想捕獲發(fā)生在一個特定名字的div中的鼠標(biāo)按下(mousedown)事件,你可以這樣使用addEventListener( ):
var mydiv = document.getElementById("mydiv");
mydiv.addEventListener("mousedown", handleMouseDown, true);
注意,這些例子假設(shè)你已經(jīng)在你的JavaScript代碼中定義了函數(shù)名為validate( )和handleMouseDown( )的函數(shù).
用addEventListener( )函數(shù)注冊的事件監(jiān)聽程序運(yùn)行在它們被定義的作用域.它們并不是在參數(shù)的作用域鏈中被調(diào)用的.
??????? 因?yàn)樵贒OM2中通過調(diào)用一個方法來給對象添加事件監(jiān)聽器,而不是通過設(shè)置HTML屬性或者JavaScript屬性的方法,所以,你可以給一個指定對象的一個特定事件注冊多于一個的事件監(jiān)聽程序.如果你通過調(diào)用addEventListener( )函數(shù)為同一對象的同一事件注冊多個監(jiān)聽程序,當(dāng)那個對象上那個類型的事件發(fā)生的時(shí)候(或者是向上冒泡,或者是捕獲的),所有的處理程序都被調(diào)用.重點(diǎn)理解一下:DOM標(biāo)準(zhǔn)并沒有保證一個對象的所有監(jiān)聽函數(shù)被調(diào)用的順序,因此,你不應(yīng)該依賴于函數(shù)按照被注冊的順序被執(zhí)行(事實(shí)上是根本不按順序執(zhí)行).還要注意的是,如果你多次注冊相同的監(jiān)聽程序給同一個元素,只有第一次注冊的有效,其余的被忽略.
??????? 為什么你想要在同一個對象的同一個事件上注冊多個事件監(jiān)聽程序呢?因?yàn)檫@有助于將你的軟件模塊化.假設(shè),你寫了一個可重用的JavaScript代碼模塊,它使用圖像上的mouseover事件執(zhí)行圖片輪換.現(xiàn)在再假設(shè)你有另一個模塊也想使用mouseover事件來顯示一些在HTML彈出窗體或者工具提示(Tool tip)上的附加信息.在DOM0的API中,你不得不把這兩段代碼合并成一個,這樣才能共用一個圖片對象的onmouseover屬性.另一方面,在DOM2的API中,每一個模塊都可以注冊它需要的事件監(jiān)聽程序,而不必管其它的模塊.
??????? removeEventListener( )和addEventListener( )是一對方法,它需要與addEventListener( )同樣的三個參數(shù),但它的功能是從一個對象刪除一個事件監(jiān)聽函數(shù),而不是添加.它常用于臨時(shí)注冊一個事件監(jiān)聽函數(shù),然后很快就刪除這個函數(shù).例如,你得到一個mousedown事件的時(shí)候,想為mousemove和mouseup事件注冊臨時(shí)的捕獲事件監(jiān)聽函數(shù),這樣就可以知道,是否用戶拖拽了鼠標(biāo).然后在mouseup事件發(fā)生的時(shí)候,解除這個注冊的監(jiān)聽程序.在這種情況下,事件監(jiān)聽器的刪除代碼如下:
document.removeEventListener("mousemove", handleMouseMove, true);
document.removeEventListener("mouseup", handleMouseUp, true);
??????? addEventListener( )方法和removeEventListener( )方法都被定義在事件目標(biāo)接口中(the EventTarget interface),在支持DOM2事件模型的Web瀏覽器中,元素和文檔節(jié)點(diǎn)實(shí)現(xiàn)了這個接口,并且提供了這些事件注冊方法.
??????? [*] 從技術(shù)上來講,DOM指出在文檔(document)中的所有節(jié)點(diǎn)(包括文本節(jié)點(diǎn):Text nodes)都實(shí)現(xiàn)了這個事件對象接口.然后事實(shí)上,web瀏覽器僅在元素(Element)和文檔節(jié)點(diǎn)(Document nodes)上支持事件監(jiān)聽器的注冊,還有窗口(Window)對象,盡管這已經(jīng)超出了DOM的范圍.
17.2.3. addEventListener( )和this關(guān)鍵字(addEventListener( ) and the this Keyword)
??????? 在原來的DOM0級事件模型中,當(dāng)一個函數(shù)被注冊給一個文檔元素的某個事件監(jiān)聽程序時(shí),它變成了那個文檔元素的一個方法.當(dāng)這個事件監(jiān)聽程序被調(diào)用時(shí),它作為這個元素的一個方法被調(diào)用,在函數(shù)的內(nèi)部,this關(guān)鍵字引用當(dāng)前發(fā)生事件的元素.
??????? DOM2是用一種與語言無關(guān)的方法寫的,它指出監(jiān)聽器(listeners)是對象,而不是簡單的函數(shù).綁定了DOM的JavaScript用Javascript函數(shù)事件監(jiān)聽器取代對JavaScript對象使用的需求.( The JavaScript binding of the DOM makes JavaScript functions event handlers instead of requiring the use of a JavaScript object.)不幸的是,這個綁定關(guān)系并沒有實(shí)際的指出監(jiān)聽函數(shù)如何被調(diào)用,也沒有指出this關(guān)鍵字的值.
??????? 且不去考慮標(biāo)準(zhǔn)的不足,所有已知的實(shí)現(xiàn)都調(diào)用用addEventListener( )方法注冊的處理程序,就像這些處理程序是目標(biāo)對象的方法一樣.也就是說,當(dāng)監(jiān)聽程序被調(diào)用的時(shí)候,this關(guān)鍵字引用這個監(jiān)聽程序被注冊的那個對象.如果你寧愿不依賴這種未指定的行為,你可以使用傳入監(jiān)聽程序的事件對象(Event object)的currentTarget屬性.在本章稍候的討論中你會看到,currentTarget屬性引用事件監(jiān)聽程序被注冊的對象.
17.2.4. 把對象(Objects)注冊為事件監(jiān)聽器(Registering Objects as Event Handlers)
??????? addEventListener( )允許你注冊一個事件監(jiān)聽函數(shù).對于面向?qū)ο缶幊?你可能更喜歡定義一個客戶端對象的方法作為事件監(jiān)聽程序,然后把它們作為那個對象的方法進(jìn)行調(diào)用.對于Java程序員,DOM標(biāo)準(zhǔn)允許這樣做:事件監(jiān)聽程序可以是實(shí)現(xiàn)了EvnentListener接口并且有一個名為handleEvent()的方法的對象.在Java中,當(dāng)你注冊一個事件監(jiān)聽程序時(shí),你給addEventListener( )傳入一個對象,而不是一個函數(shù).簡單的說,綁定了DOM API的JavaScript不需要你去實(shí)現(xiàn)EventListener接口,相反的,允許你直接給addEventListener( )傳遞一個函數(shù)引用.
然而,如果你在寫一個面向?qū)ο蟮腏avaScript程序,并且更喜歡用對象作為事件監(jiān)聽程序,你可以用一個像下邊這樣的函數(shù)來注冊:
function registerObjectEventHandler(element, eventtype, listener, captures) {
??? element.addEventListener(eventtype,
???????????????????????????? function(event) { listener.handleEvent(event); }
???????????????????????????? captures);
}
??????? 只要一個對象定義了handleEvent( )方法,就可以用這個函數(shù)把該對象注冊為一個事件監(jiān)聽程序.那個方法作為監(jiān)聽對象的方法被調(diào)用,this關(guān)鍵字引用這個監(jiān)聽對象,而不是產(chǎn)生事件的文檔元素.
??????? 盡管這不是DOM標(biāo)準(zhǔn)的一部分,Firefox(和其它基于Mozilla codebase的瀏覽器)允許把定義了handleEvent()方法的事件監(jiān)聽對象直接傳遞給addEventListener()方法,來代替函數(shù).對于這些瀏覽器,就沒有必要定義一個像剛才展示的注冊函數(shù)了.
17.2.5. 事件模型和事件類型(Event Modules and Event Types)
??????? 如我前面所說,DOM2是模塊化的,所以,一個實(shí)現(xiàn)可以支持其中的一部分而忽略其它對其它部分的支持.事件API(Events API)就是這樣一個模塊.你可以像這樣來測試一個瀏覽器是否支持這個模塊:
document.implementation.hasFeature("Events", "2.0")
??????? 然而,事件模塊只包含用于基本事件監(jiān)聽結(jié)構(gòu)的API.子模塊提供對特定類型事件的支持.每個子模塊都提供對一類相關(guān)事件類型的支持,并且定義了傳入事件監(jiān)聽程序的事件類型.例如,名為MouseEvents的子模塊提供了mousedown, mouseup, click等相關(guān)事件的類型.它也定義了MouseEvent接口.實(shí)現(xiàn)了那個接口的對象,為任何一個被這個模塊支持的事件類型,被傳入事件監(jiān)聽程序.
??????? 表17-2列出了每一個事件模塊,它定義的接口,和被它支持的事件類型.注意,DOM2并沒有把任何鍵盤事件標(biāo)準(zhǔn)化,因此這里沒有列出鍵盤事件模塊.然而,當(dāng)前的瀏覽器都支持鍵盤事件,在本章的后面,你會了解的更多一些.(此處省略幾句和MutationEvents模塊相關(guān)的描述)
Table 17-2. Event modules, interfaces, and types
Module name
|
Event interface
|
Event types
|
HTMLEvents
|
Event
|
abort, blur, change, error, focus, load, reset, resize, scroll, select, submit, unload
|
MouseEvents
|
MouseEvent
|
click, mousedown, mousemove, mouseout, mouseover, mouseup
|
UIEvents
|
UIEvent
|
DOMActivate, DOMFocusIn, DOMFocusOut
|
??????? 如你在表17-2中所見,HTMLEvents和MouseEvents模塊定義的事件類型和DOM0的事件模塊是非常相似的.UIEvents模塊定義了事件類型,這和被HTML表單元素支持的focus,blur和click事件很相似,但更通用的,所以,他們能被任何可以接受焦點(diǎn)或者被激活的文檔元素產(chǎn)生.
??????? 如前所述,當(dāng)一個事件發(fā)生的時(shí)候,它的監(jiān)聽程序被傳入一個實(shí)現(xiàn)了那個類型事件的事件接口對象.這個對象的屬性提供了對事件監(jiān)聽程序可能有用的細(xì)節(jié)信息.表17-3再一次列出標(biāo)準(zhǔn)的事件,但這次是按事件類型組織的,而不是事件模型.對于每個事件類型,該表都指出傳入它的監(jiān)聽程序的事件對象的種類,是否這個事件有一個可以用preventDefault()方法阻止發(fā)生的默認(rèn)行為.對于HTMLEvents模塊中的事件,表格中的第五列指出哪些HTML元素可以產(chǎn)生該事件.對于所有其它的事件類型,第五列指出事件對象的哪些屬性包含了有意義的事件細(xì)節(jié)信息.注意,在這一列中列出的屬性,不包括被基本事件接口定義的對所有事件類型都有意義的屬性.
Table 17-3. Event types
Event type
|
Interface
|
B
|
C
|
Supported by/detail properties
|
abort
|
Event
|
yes
|
no
|
<img>, <object>
|
blur
|
Event
|
no
|
no
|
<a>, <area>, <button>, <input>, <label>, <select>, <textarea>
|
change
|
Event
|
yes
|
no
|
<input>, <select>, <textarea>
|
click
|
MouseEvent
|
yes
|
yes
|
screenX, screenY, clientX, clientY, altKey, ctrlKey, shiftKey, metaKey, button, detail
|
error
|
Event
|
yes
|
no
|
<body>, <frameset>, <img>, <object>
|
focus
|
Event
|
no
|
no
|
<a>, <area>, <button>, <input>, <label>, <select>, <textarea>
|
load
|
Event
|
no
|
no
|
<body>, <frameset>, <iframe>, <img>, <object>
|
mousedown
|
MouseEvent
|
yes
|
yes
|
screenX, screenY, clientX, clientY, altKey, ctrlKey, shiftKey, metaKey, button, detail
|
mousemove
|
MouseEvent
|
yes
|
no
|
screenX, screenY, clientX, clientY, altKey, ctrlKey, shiftKey, metaKey
|
mouseout
|
MouseEvent
|
yes
|
yes
|
screenX, screenY, clientX, clientY, altKey, ctrlKey, shiftKey, metaKey, relatedTarget
|
mouseover
|
MouseEvent
|
yes
|
yes
|
screenX, screenY, clientX, clientY, altKey, ctrlKey, shiftKey, metaKey, relatedTarget
|
mouseup
|
MouseEvent
|
yes
|
yes
|
screenX, screenY, clientX, clientY, altKey, ctrlKey, shiftKey, metaKey, button, detail
|
reset
|
Event
|
yes
|
no
|
<form>
|
resize
|
Event
|
yes
|
no
|
<body>, <frameset>, <iframe>
|
scroll
|
Event
|
yes
|
no
|
<body>
|
select
|
Event
|
yes
|
no
|
<input>, <textarea>
|
submit
|
Event
|
yes
|
yes
|
<form>
|
unload
|
Event
|
no
|
no
|
<body>, <frameset>
|
DOMActivate
|
UIEvent
|
yes
|
yes
|
detail
|
DOMFocusIn
|
UIEvent
|
yes
|
no
|
none
|
DOMFocusOut
|
UIEvent
|
yes
|
no
|
none
|
??????? 被DOM0和DOM2支持的事件類型大體相同(UIEvents除外).DOM2標(biāo)準(zhǔn)添加了對abort,error,resize和scroll事件類型的支持,這些不是HTML 4的標(biāo)準(zhǔn),但它不支持HTML 4標(biāo)準(zhǔn)中的鍵盤事件和雙擊事件.(取而代之的是,傳入click事件處理程序的對象的細(xì)節(jié)屬性指出了發(fā)生的連續(xù)點(diǎn)擊的次數(shù).)
17.2.6. 事件接口和事件細(xì)節(jié)(Event Interfaces and Event Details)
??????? 一個事件發(fā)生的時(shí)候,DOM2提供了關(guān)于這個事件的其它細(xì)節(jié)(例如何時(shí)何地發(fā)生的),這些信息作為傳入到事件監(jiān)聽程序的對象的屬性出現(xiàn).每一個事件模塊都有一個相關(guān)聯(lián)的事件接口,該接口指出和那個類型事件相關(guān)的細(xì)節(jié).表17-2列出了三種不同的事件模塊和三種不同的事件接口.
??????? 事實(shí)上這三個接口是互相關(guān)聯(lián)的,并且形成了一個層次關(guān)系.事件接口是這個層次的根層;所有的事件對象都實(shí)現(xiàn)了它大部分基本的事件接口.UIEvent是事件接口的子接口:任何實(shí)現(xiàn)了UIEvent接口的事件對象都實(shí)現(xiàn)了Event接口的屬性和方法.MouseEvent接口又是UIEvent的子接口.舉個例子,這就是說,傳給點(diǎn)擊事件處理程序的事件對象實(shí)現(xiàn)了在MouseEvent, UIEvent, 和Event接口中定義的所有屬性和方法.
接下來的部分介紹的是事件接口,并且著重講最重要的屬性和方法.
17.2.6.1. 事件(Event)
??????? 在HTMLEvents模塊中定義的事件類型使用Event接口.所有其它的事件類型都使用Event的子接口,子接口被所有的事件對象實(shí)現(xiàn),并且提供了應(yīng)用于那個事件類型的細(xì)節(jié)信息.事件接口定義了如下屬性(注意,這些屬性和所有事件子接口的屬性都是只讀的):
type
??????? 發(fā)生的事件類型.這個屬性的值是事件類型的名字,它和用于注冊事件處理程序時(shí)使用的字符串是一樣的(如: click 或者 mouseover).
target
??????? 事件發(fā)生的節(jié)點(diǎn),可能與currentTarget不同.
currentTarget
??????? 正在處理事件的節(jié)點(diǎn)(也就是正在運(yùn)行的事件處理程序所屬的節(jié)點(diǎn)).如果在事件被捕獲或者冒泡階段被處理,這個屬性的值和target屬性的值是不同的.如前所述,你可以在你的事件處理程序中用這個屬性代替this關(guān)鍵字
eventPhase
??????? 指出正在理的是事件傳播的哪一個階段的數(shù)值.該值為三個常中之一:Event.CAPTURING_PHASE, Event.AT_TARGET, 或者 Event.BUBBLING_PHASE.
timeStamp
??????? 指出該事件何時(shí)發(fā)生的日期對象
bubbles
??????? 指出該事件是否沿文檔樹向中冒泡的布爾值.
cancelable
??????? 指出該事件是否有一個可以用prevertDefault()阻止的和事件相關(guān)聯(lián)的默認(rèn)行為的布爾值.
??????? 除了這七個屬性以外,事件接口定義了兩個方法,也都被事件對象實(shí)現(xiàn)了,它們是:stopPropagation( ) 和 preventDefault( ).任何事件處理程序都可以調(diào)用stopPropagation( )來阻止正在被傳播的事件越過正在被處理的節(jié)點(diǎn).任何事件處理程序都可以調(diào)用preventDefault( )來阻止瀏覽器執(zhí)行與該事件關(guān)聯(lián)的默認(rèn)行為.在DOM2中調(diào)用preventDefault( ),就像在DOM0中返回false.
17.2.6.2. 用戶信息事件(UIEvent)
??????? 用戶信息事件接口是Event的子接口.它定義了被傳遞到DOMFocusIn, DOMFocusOut和DOMActivate的事件對象的類型.這些事件類型通常是用不到的;但對于UIEvent接口來講,比較重要的是它是MouseEvent的父接口.除了在Event中定義的屬性外,UIEvent還定義了兩個屬性:
view
??????? 發(fā)生的事件所在的窗口對象(Window Object:known as a view in DOM terminology).
detail
??????? 可以提供附加信息的數(shù)值.對于click,mousedown和mouseup事件,這個字段代表點(diǎn)擊計(jì)數(shù):1代表單擊,2代表雙擊,3代表三擊.(注意,每次點(diǎn)擊都產(chǎn)生一個事件,但是如果多次點(diǎn)擊間隔足夠短,detail屬性就會指示出來.也就是說,detail為2的鼠標(biāo)事件要優(yōu)先于detail為1的鼠標(biāo)事件.)對于DOMActivate事件,這個字段值為1代表正常激活,2代表極度活躍(hyperactivation),比如雙擊或者Shift-Enter組合鍵.
17.2.6.3. MouseEvent
MouseEvent接口繼承了Event和UIEvent的屬性和方法,還定義了如下附加屬性:
附加屬性:
button
??????? 數(shù)值類型,指出在mousedown, mouseup或者click事件期間哪一個鼠標(biāo)鍵改變了狀態(tài).0代表左鍵,1代表中鍵,2代表右鍵.只有當(dāng)一個按鍵改變狀態(tài)時(shí),才使用這個屬性;例如:不能用于報(bào)告mousemove事件發(fā)生時(shí)哪個鍵是被按下的.注意Netscape 6得到的值為1,2,3,而不是0,1,2.這個問題在Netscape 6.1中已經(jīng)修正了.
altKey , ctrlKey, metaKey, shiftKey
??????? 這四個布爾值代表,當(dāng)一個鼠標(biāo)事件發(fā)生時(shí),是否 Alt, Ctrl, Meta或者Shift鍵被按下.與button屬性不同,這些按鍵屬性對于任何鼠標(biāo)事件都是有效的.
clientX, clientY
??????? 這兩個屬性指出鼠標(biāo)指針的X和Y坐標(biāo),相對于瀏覽器窗口的客戶區(qū).注意這個坐標(biāo)并沒有計(jì)算文檔的滾動高度或者寬度在內(nèi):如果事件發(fā)生在窗口的最上邊,不管這個文檔已經(jīng)向下滾動了多遠(yuǎn),clientY就是0.不幸的是,DOM2并沒有提供一個標(biāo)準(zhǔn)的方法去轉(zhuǎn)換這個窗口坐標(biāo)為文檔坐標(biāo).在除了IE以外的瀏覽器中,你可以加上window.pageXOffset和window.pageYOffset.
screenX, screenY
??????? 這兩個屬性指出鼠標(biāo)指針相對于用戶顯示器的左上角的坐標(biāo).如果你打算在鼠標(biāo)事件發(fā)生的地點(diǎn)或者附近打開一個窗口,這兩個屬性就有用了.
relatedTarget
??????? 這個屬性引用一個相對于事件的target節(jié)點(diǎn)的節(jié)點(diǎn).對于mouseover事件,它引用當(dāng)鼠標(biāo)經(jīng)過target節(jié)點(diǎn)時(shí)鼠標(biāo)離開的那個節(jié)點(diǎn).對于mouseout事件,它引用當(dāng)鼠標(biāo)離開目標(biāo)節(jié)點(diǎn)時(shí),鼠標(biāo)進(jìn)入的節(jié)點(diǎn).對于其它事件,這兩個屬性是無用的.
17.2.7. 混合事件模型(Mixing Event Models)
??????? 到現(xiàn)在為止,我們討論了傳統(tǒng)的DOM0級事件模型,和新的標(biāo)準(zhǔn)的DOM2模型.為了向后兼容,支持DOM2模型的瀏覽器將繼續(xù)支持DOM0級事件模型.這就意味著,你可以在一個文檔里混合使用這兩種事件模型.
??????? 支持DOM2級事件模型的web瀏覽器總是傳遞一個事件對象給事件監(jiān)聽程序,這和用DOM0級事件模型的HTML屬性或者JavaScript屬性注冊事件處理程序是一致的,理解這一點(diǎn)很重要.當(dāng)事件監(jiān)聽程序作為一個HTML屬性被定義的時(shí)候,它被暗中轉(zhuǎn)換成一個函數(shù),這個函數(shù)有一個名為event的參數(shù).這就意味著,像這樣的一個事件監(jiān)聽程序可以用標(biāo)識符event來引用事件對象.
??????? DOM標(biāo)準(zhǔn)承認(rèn)DOM0級事件模型繼續(xù)保留使用,并指出,對待DOM0事件模型的監(jiān)聽程序的注冊方法就像用addEventListener( )注冊的一樣.也就是說,如果你給一個文檔元素e的onclick屬性賦值為函數(shù)f(或者說設(shè)置對應(yīng)的HTML中的onclick屬性),它和下面這種注冊方法是一樣的:
e.addEventListener("click", f, false);
當(dāng)函數(shù)f被調(diào)用的時(shí)候,傳入一個事件對象作為參數(shù),盡管這個函數(shù)是用DOM0模型注冊的.
???
posted on 2006-11-16 21:19
梅雪香 閱讀(3673)
評論(7) 編輯 收藏