跨瀏覽器事件對象及其封裝本身的函數

JavaScript中,DOM0級、DOM2級與舊版本IE(8-)爲對象添加事件的方法不一樣windows

爲了以跨瀏覽器的方式處理事件,須要編寫一段「通用代碼」,即跨瀏覽器的事件處理程序瀏覽器

習慣上,這個方法屬於一個名爲EventUtil的對象函數

編寫並使用該對象後,可保證處理事件的代碼能在大多數瀏覽器下一致的運行this

 1 var EventUtil={
 2      
 3    addHandler:function(element,type,handler){ //添加事件
 4       if(element.addEventListener){
 5          element.addEventListener(type,handler,false);  //使用DOM2級方法添加事件
 6       }else if(element.attachEvent){                    //使用IE方法添加事件
 7          element.attachEvent("on"+type,handler);
 8       }else{
 9          element["on"+type]=handler;          //使用DOM0級方法添加事件
10       }
11    }, 
12  
13    removeHandler:function(element,type,handler){  //取消事件
14       if(element.removeEventListener){
15          element.removeEventListener(type,handler,false);
16       }else if(element.detachEvent){
17          element.detachEvent("on"+type,handler);
18       }else{
19          element["on"+type]=null;
20       }
21    },
22  
23    getEvent:function(event){  //使用這個方法跨瀏覽器取得event對象
24       return event?event:window.event;
25    },
26      
27    getTarget:function(event){  //返回事件的實際目標
28       return event.target||event.srcElement;
29    },
30      
31    preventDefault:function(event){   //阻止事件的默認行爲
32       if(event.preventDefault){
33          event.preventDefault();
34       }else{
35          event.returnValue=false;
36       }
37    },
38  
39    stopPropagation:function(event){  //當即中止事件在DOM中的傳播
40                                      //避免觸發註冊在document.body上面的事件處理程序
41       if(event.stopPropagation){
42          event.stopPropagation();
43       }else{
44          event.cancelBubble=true;
45       }
46    },
47          
48    getRelatedTarget:function(event){  //獲取mouseover和mouseout相關元素
49       if(event.relatedTarget){
50          return event.relatedTarget;
51       }else if(event.toElement){      //兼容IE8-
52          return event.toElement;
53       }else if(event.formElement){
54          return event.formElement;
55       }else{
56          return null;
57       }
58    },
59          
60    getButton:function(event){    //獲取mousedown或mouseup按下或釋放的按鈕是鼠標中的哪個
61       if(document.implementation.hasFeature("MouseEvents","2.0")){
62          return event.button;
63       }else{
64          switch(event.button){   //將IE模型下的button屬性映射爲DOM模型下的button屬性
65             case 0:
66             case 1:
67             case 3:
68             case 5:
69             case 7:
70                return 0;  //按下的是鼠標主按鈕(通常是左鍵)
71             case 2:
72             case 6:
73                return 2;  //按下的是中間的鼠標按鈕
74             case 4:
75                return 1;  //鼠標次按鈕(通常是右鍵)
76          }
77       }
78    },
79          
80    getWheelDelta:function(event){ //獲取表示鼠標滾輪滾動方向的數值
81       if(event.wheelDelta){
82          return event.wheelDelta;
83       }else{
84          return -event.detail*40;
85       }
86    },
87          
88    getCharCode:function(event){   //以跨瀏覽器取得相同的字符編碼,需在keypress事件中使用
89       if(typeof event.charCode=="number"){
90          return event.charCode;
91       }else{
92          return event.keyCode;
93       }
94    }
95          
96 };

addHandler方法

這是EventUtil中最經常使用的方法,它的做用是爲對象添加事件並保證兼容性編碼

DOM0級事件處理程序(下文均簡稱「DOM0級」)中spa

每一個元素(包括windows和document)都有本身的事件處理程序屬性(一般所有小寫)指針

如常見的onload、onclick等code

Click事件爲例(下同),DOM0級一般以下指定事件處理程序orm

1 var btn=document.getElementById("myBtn");
2 btn.onclick=function(){ //指定事件處理程序
3    alert(this.id);      //"myBtn"
4 };

DOM2級事件處理程序(下文均簡稱「DOM2級」)中對象

指定事件處理程序的方法爲addEventListener( )

它接受3個參數:要處理的事件名、做爲事件處理程序的函數和一個布爾值(大多數狀況下是false)

(布爾值表示是在捕獲階段(true)仍是冒泡階段(false)調用事件處理程序)

DOM2級一般以下指定事件處理程序

1 var btn=document.getElementById("myBtn");
2 //在外部定義好函數再傳給addEventListener(),這樣才能夠經過removeEventListener()移除
3 var handler=function(){ 
4    alert(this.id);
5 };
6 btn.addEventListener("click",handler,false);

在舊版本IE(表明IE8-,下文均簡稱「IE」)中

指定事件處理程序的方法爲attachEvent( )

它接受兩個參數:事件處理程序名稱與事件處理程序函數

IE中一般以下指定事件處理程序

1 var btn=document.getElementById("myBtn");
2 var handler=function(){
3    alert("Clicked");
4 };
5 //注意:第一個參數是"onclick",而非DOM0的addEventListener()方法中的"click"
6 btn.attachEvent("onclick",handler);

由上可見,DOM0級、DOM2級和IE中指定事件方法有很大不一樣

EventUtil對象中的addHandler方法正是爲了處理這些差別而存在

在添加了EventUtil(指上文「EventUtil對象全見」中的代碼,下同)後,能夠以下所示爲對象指定事件處理程序

1 var btn=document.getElementById("myBtn");
2 var handler=function(){
3    alert("Clicked!");
4 };
5 EventUtil.addHandler(btn,"click",handler);  //調用已定義的EventUtil對象

就像這樣,使用addHandler方法指定事件處理程序

便可兼容支持DOM0級、DOM2級的瀏覽器或IE瀏覽器

removeHandler方法

一樣的,在DOM0級、DOM2級與IE中,移除事件的方法是不一樣的

DOM0級中,在再也不須要某對象的事件處理程序時(如頁面銷燬前),能夠像下面這樣簡單的移除事件處理程序

btn.onclick=null;

DOM2級中,刪除事件處理程序須要使用removeEventListener( )方法,以下所示

 1 //這裏的handler應與使用addEventListener指定事件處理函數時所用的外部函數相同

2 btn.removeEventListener("click",handler,false); 

而在IE中,刪除事件則需使用detachEvent( )方法

btn.detachEvent("onclick",handler); 

由於這些差別的存在,才令EventUtil中有了removeHandler方法

在添加了EventUtil後,能夠以下所示使用removeHandler方法方便地刪除對象事件處理程序

 1 //一樣的,這裏的handler應與使用addHandler指定事件處理函數時所用的外部函數相同

2 EventUtil.removeHandler(btn,"click",hanlder); 

event對象與getEvent方法

你可能已經發現了,在EventUtil中,不少方法的參數都是event

這個event實際上是事件對象

兼容DOM(不管是DOM0級仍是DOM2級)的瀏覽器會將一個event對象傳入到事件處理程序中

這個event對象支持許多方法,下表列出了一些經常使用的方法以供參考

屬性/方法 類型 讀/寫 說明
currentTarget Element 只讀 其事件處理程序當前正在處理事件的那個元素
preventDefault( ) Function 只讀 取消事件的默認行爲
stopPropagation( ) Function 只讀 取消事件的進一步捕獲或冒泡
target Element 只讀 事件的實際(真正)目標
type String 只讀 被觸發的事件的類型

在兼容DOM的瀏覽器中,event對象能夠以下面這個例子這樣使用

 1 var btn=document.getElementById("myBtn");
 2 var handler=function(event){
 3    switch(event.type){      //使用event.type檢測事件類型
 4       case "click":         //如果Click事件
 5          alert("Clicked");
 6          break;
 7       case: "mouseover":    //如果Mouseover事件
 8          //使用event.target獲取事件目標,並更改目標樣式背景顏色
 9          event.target.style.backgroundColor="red";
10          break;
11       case: "mouseout":     //如果Mouseout事件
12          event.target.style.backgroundColor="";
13          break;
14    }
15 };
16 btn.onclick=handler;  //使用DOM0級爲對象添加事件處理函數
17 btn.onmouseover=handler;
18 btn.onmouseout=handler;

須要強調的是,以上使用event事件的方法僅適用於兼容DOM的瀏覽器

在IE中則有所不一樣

在IE中,使用DOM0級添加事件處理程序時,event對象做爲window對象的一個屬性存在,以下例子所示

1 btn.onclick=function(){
2    var event=window.event;
3    alert(event.type);  //"click"
4 };

神奇的是,若是事件處理程序是使用attachEvent( )添加的,則又能夠像在支持DOM的瀏覽器中同樣

event對象又可做爲參數傳入事件處理程序函數中,以下例子所示

 1 btn.attachEvent("onclick",function(event){ 2 alert(event.type); //"click" 3 }); 

並且,更神奇的是,在IE中,event對象的一些屬性/方法還跟其它支持DOM的瀏覽器中不一樣,以下表

屬性/方法 類型 讀/寫 說明
cancelBubble Boolean 讀/寫 默認值爲false,將其設置爲true就能夠取消事件冒泡
(與DOM中的stopPropagation( )方法的做用相同)
returnValue Boolean 讀/寫 默認值爲true,將其設置爲false就能夠取消事件的默認行爲
(與DOM中的preventDefault( )方法的做用相同)
srcElement Element 只讀 事件的目標(與DOM中的target屬性相同)
type String 只讀 被觸發的事件類型

正是由於這些差別的存在,使得EventUtil中的getEvent方法應運而生

在添加了EventUtil後,能夠以下「重點語句」所示獲取event對象而無需擔憂上述差別致使的兼容問題

1 var btn=document.getElementById("myBtn");
2 var handler=function(event){
3    event=EventUtil.getEvent(event); //重點語句
4 };
5 EventUtil.addHandler(btn,"click",handler); 

這樣,就解決了event對象獲取方式不一樣的問題

至於event對象的屬性/方法差別,下文還會介紹其它方法進行處理

target對象與getTarget方法

在上一部分(「event對象與getEvent方法」)的介紹中,經過表格你可能已經發現

IE中和其它兼容DOM的瀏覽器中,獲取事件目標(target)的方法不一樣

IE中,獲取事件目標對象的方法爲event.srcElement

而在其它兼容DOM的瀏覽器中,獲取事件目標對象的方法卻爲event.target

getTarget方法正是爲了處理這個差別而存在

在添加了EventUtil後,能夠以下「重點語句」所示獲取事件的目標(target)對象而無需擔憂上述差別致使的兼容問題

1 var btn=document.getElementById("myBtn");
2 var handler=function(event){
3    event=EventUtil.getEvent(event); 
4    var target=EventUtil.getTarget(event); //重點語句
5 };
6 EventUtil.addHandler(btn,"click",handler); 

preventDefault方法

在其它兼容DOM的瀏覽器中,阻止特定事件的默認行爲只需使用event對象自帶preventDefault( )方法,以下所示

1 var link=document.getElementById("myLink");
2 link.onclick=function(event){
3    event.preventDefault(); //DOM0級或DOM2級阻止事件默認行爲的方法
4 }

而在IE中,則需賦予event.returnValue的值爲false才能阻止特定事件的默認行爲

 1 link.attachEvent("onclick",function(event){ 2 event.returnValue=false; //IE中阻止事件默認行爲的方法 3 }); 

故在EventUtil中,存在一個preventDefault方法,用於統一上述差別

在添加了EventUtil後,能夠以下「重點語句」所示阻止特定事件的默認行爲而無需擔憂上述差別致使的兼容問題

1 var link=document.getElementById("myLink");
2 var handler=function(event){
3    event=EventUtil.getEvent(event);
4    EventUtil.preventDefault(event); //重點語句
5 };
6 EventUtil.addHandler(link,"click",handler);

stopPropagation方法

有時候,咱們須要取消事件的進一步捕獲或冒泡,即中止事件在DOM層次中傳播

兼容DOM的瀏覽器能夠經過使用event對象自帶的stopPropagation( )方法作到這一點

1 var link=document.getElementById("myLink");
2 link.onclick=function(event){
3    event.stopPropagation(); //DOM0級或DOM2級取消事件的進一步捕獲或冒泡的方法
4 };

而在IE中,則需賦予event.cancelBubble的值爲true

 1 link.attachEvent("onclick",function(event){ 2 event.cancelBubble=true; //IE中取消事件的進一步冒泡的方法 3 }); 

EventUtil中的stopPropagation( )方法能夠統一上述差別

在添加了EventUtil後,能夠以下「重點語句」所示取消事件的進一步捕獲或冒泡而無需擔憂差別致使的兼容問題

1 var link=document.getElementById("myLink");
2 var handler=function(event){
3    event=EventUtil.getEvent(event);
4    EventUtil.stopPropagation(event); //重點語句
5 };
6 EventUtil.addHandler(link,"click",handler);

相關元素與getRelatedTarget方法

mouseover與mouseout有「主目標(主元素)」與「相關元素」的概念

由於在發生mouseover或mouseout事件時,還會涉及到其它元素

這兩個事件都會涉及把鼠指針從一個元素(相關元素)移到另外一個元素(主目標)內

具體點說

mouseover事件而言,事件的主目標是得到光標的元素,而相關元素是那個失去光標的元素

mouseout事件而言,事件的主目標是失去光標的元素,而相關元素是那個得到光標的元素

DOM經過event對象的relatedTarget屬性提供了相關元素的信息

IE8及以前的版本不支持relatedTarget屬性,不過提供了其它相似屬性支持

mouseover事件觸發時,IE的formElement屬性中保存了相關元素

mouseout事件觸發時,IE的toElement屬性中保存了相關元素

EventUtil中的getRelatedTarget方法正是爲了平衡這些差別而存在

在添加了EventUtil後,能夠像下面示例「重點語句」同樣使用getRelatedTarget方法

1 var div=document.getElementById("myDiv");
2 EventUtil.addHandler(div,"mouseout",function(event){
3    event=EventUtil.getEvent(event);
4    var target=EventUtil.getTarget(event);
5    var relatedTarget=EventUtil.getRelatedTarget(event); //重點語句
6    alert("鼠標離開了"+target.tagName+"元素而進入了"+relatedTarget.tagName+"元素");
7 });

getButton方法

咱們知道,只有在鼠標主按鈕被單擊(或鍵盤迴車鍵被按下、觸摸屏被單點擊中)時纔會觸發click事件

但對於mousedown和mouseup事件來講,鼠標上的任意按鈕均可以觸發它

有時,咱們可能須要知道用戶按下了哪一個鼠標按鈕

DOM的event.button屬性能夠作到這一點,這個屬性可能有3個值

0表示主鼠標按鈕(一般是左鍵)、1表示鼠標滾輪按鈕、2表示鼠標右鍵

雖然IE的event對象也提供了button屬性

但遺憾的是,IE的button屬性與DOM的button屬性有很大差別

並且不被其它瀏覽器支持,實用性很低,在此不予贅述

getButton方法的做用是,讓全部瀏覽器的event.button表現與DOM相同

在添加了EventUtil後,能夠像下面示例「重點語句」同樣使用getButton方法而無需考慮IE中的差別

1 var div=document.getElementById("myDiv");
2 EventUtil.addHandler(div,"mousedown",function(event){ //監控按下div的是哪一個按鈕
3    event=EventUtil.getEvent(event);
4    alert(EventUtil.getButton(event));  //重點語句,彈出框顯示按下哪一個鼠標鍵的代號(0、1或2)
5 });
6 //同理,若事件是mouseup,則botton值表示釋放的是哪一個按鈕

getWheelDelta方法

有時,爲了讓頁面達到某些特殊效果,咱們須要監視用戶的鼠標滾輪操做

這一次,「不同凡響」的是Firefox,而不是舊版本的IE

全部瀏覽器(包括IE6,除了Firefox)均支持鼠標滾輪事件mousewheel

Firefox倒是經過DOMMouseScroll事件實現相似功能

事件名的差別沒法經過EventUtil改變

但關鍵是,這個事件表示鼠標滾輪滾動方向的方法,Firefox與其它瀏覽器也有差別

差別的自己已不是重點,重點是EventUtil的getWheelDelta方法能夠很好的解決它們的差別

在添加了EventUtil後,能夠像下面示例「重點語句」同樣使用getWheelDelta方法而無需考慮FIrefox中的差別

1 function handleMouseWheel(event){
2    event=EventUtil.getEvent(event);
3    var delta=EventUtil.getWheelDelta(event);  //重點語句,delta是表示鼠標滾輪滾動方向的數值
4    alert(delta);
5 }
6 EventUtil.addHandler(document,"mousewheel",handleMouseWheel);      //非Firefox
7 EventUtil.addHandler(document,"DOMMouseScroll",handleMouseWheel);  //Firefox

多數狀況下,咱們只需關心如上例中經過getWheelDelta方法得到的delta數值的正負

當用戶向前滾動鼠標滾輪時,delta的數值爲正,反之爲負

滾輪滾動越多,delta數值的絕對值越大,且均是120的倍數

getCharCode方法

在全部瀏覽器中,按下可以插入或刪除的字符的按鍵都會觸發keypress事件

IE8-及Opera取得字符編碼(ASCII碼)的方式與其它瀏覽器是不一樣的

爲了解決這一差別,在EventUtil中存在getCharCode方法

在添加了EventUtil後,能夠像下面示例「重點語句」同樣使用getCharCode方法來獲取統一的字符編碼

1 var textbox=document.getElementById("myText");
2 EventUtil.addHandler(textbox,"keypress",function(event){
3    event=EventUtil.getEvent(event);
4    alert(EventUtil.getCharCode(event)); //重點語句,彈出窗口中顯示按下按鍵表明字符的ASCII碼
5 });
相關文章
相關標籤/搜索