在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 };
這是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瀏覽器
一樣的,在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);
你可能已經發現了,在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對象的屬性/方法差別,下文還會介紹其它方法進行處理
在上一部分(「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);
在其它兼容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);
有時候,咱們須要取消事件的進一步捕獲或冒泡,即中止事件在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);
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 });
咱們知道,只有在鼠標主按鈕被單擊(或鍵盤迴車鍵被按下、觸摸屏被單點擊中)時纔會觸發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值表示釋放的是哪一個按鈕
有時,爲了讓頁面達到某些特殊效果,咱們須要監視用戶的鼠標滾輪操做
這一次,「不同凡響」的是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的倍數
在全部瀏覽器中,按下可以插入或刪除的字符的按鍵都會觸發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 });