// 跨瀏覽器事件處理程序封裝
var EventUtil = {
// 添加事件句柄
addHandler: function(element, type, handler){
// DOM 2 級事件處理程序
if (element.addEventListener){
element.addEventListener(type, handler, false);
}
// IE事件處理程序
else if (element.attachEvent){
element.attachEvent("on" + type, handler);
}
// DOM 0 級事件處理程序
else{
element["on" + type] = handler;
}
},
// 獲取鼠標事件button屬性 ,
// 0:主鼠標按鈕
// 1:中間按鈕
// 2:次鼠標按鈕
getButton: function(event){
// DOM Button屬性
if(document.implementation.hasFeature("MouseEvents", "2.0")){
return event.button;
}
// IE 模式下的button屬性
else{
switch(event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4: return 1;
}
}
},
// 獲取鍵盤事件keypress事件的charCode屬性
// 該值表示按下的鍵所表明的ASCII碼
getCharCode: function(event){
// IE9 FireFox Chrome Safari
if(typeof event.getCharCode == "number"){
return event.charCode;
}
// IE8 Opera
else{
return event.keyCode;
}
},
// 獲取剪切板內容
getClipboardText: function(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
// 獲取事件對象
getEvent: function(event){
return event ? event : window.event;
},
// 獲取relatedTarget屬性
// 在mouseover事件觸發時,IE的fromElement屬性中保存了相關元素;
// 在mouseout事件觸發時,IE的toElement屬性中保存了相關元素
getRelatedTarget: function(event){
// DOM屬性,IE8不支持
if (event.relatedTarget){
return event.relatedTarget;
}
// IE mouseout
else if (event.toElement){
return event.toElement;
}
// IE mouseover
else if (event.fromElement){
return event.fromElement;
}
else {
return null;
}
},
// 獲取target事件對象
getTarget: function(event){
// DOM || IE
return event.target || event.srcElement;
},
// 獲取鼠標滾輪滾動時的屬性值
getWheelDelta: function(event){
// IE6.0 Chrome Opera Safari wheelData屬性值
// 向前滾動是120的倍數
// 向後滾動是-120的倍數
if (event.wheelDelta){
return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
}
// Firefox detail屬性值
// 向前滾動是-3的倍數
// 向後滾動是3的倍數
else {
return -event.detail * 40;
}
},
// 取消事件的默認行爲
preventDefault: function(event){
// DOM
if (event.preventDefault){
event.preventDefault();
}
// IE
else {
event.returnValue = false;
}
},
// 移除事件句柄
removeHandler: function(element, type, handler){
// DOM 2
if (element.removeEventListener){
element.removeEventListener(type, handler, false);
}
// IE
else if (element.detachEvent){
element.detachEvent("on" + type, handler);
}
// DOM 0
else {
element["on" + type] = null;
}
},
// 設置剪切板內容
setClipboardText: function(event, value){
// Chrome
if (event.clipboardData){
event.clipboardData.setData("text/plain", value);
}
// IE
else if (window.clipboardData){
window.clipboardData.setData("text", value);
}
},
// 取消事件冒泡
stopPropagation: function(event){
// DOM
if (event.stopPropagation){
event.stopPropagation();
}
// IE
else {
event.cancelBubble = true;
}
}
};
這是EventUtil中最經常使用的方法,它的做用是爲對象添加事件並保證兼容性javascript
在DOM0級事件處理程序(下文均簡稱「DOM0級」)中java
每一個元素(包括windows和document)都有本身的事件處理程序屬性(一般所有小寫)windows
如常見的onload、onclick等瀏覽器
以Click事件爲例(下同),DOM0級一般以下指定事件處理程序函數
1 var btn=document.getElementById("myBtn");
2 btn.onclick=function(){ //指定事件處理程序
3 alert(this.id); //"myBtn"
4 };
在DOM2級事件處理程序(下文均簡稱「DOM2級」)中this
指定事件處理程序的方法爲addEventListener( )編碼
它接受3個參數:要處理的事件名、做爲事件處理程序的函數和一個布爾值(大多數狀況下是false)spa
(布爾值表示是在捕獲階段(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,fals
而在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 });