【前端】跨瀏覽器事件處理程序EventUtil.js我的註釋及詳解

《javascript高級程序設計》跨瀏覽器事件處理程序EventUtil.js我的註釋

EventUtil.js

// 跨瀏覽器事件處理程序封裝
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;
        }
    }

};

  

詳細說明:

 

addHandler方法

這是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瀏覽器

 

removeHandler方法

一樣的,在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);

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 });
相關文章
相關標籤/搜索