DOM元素都有一些標準事件,一般使用時只要使用οnclick=function的方式就可以了,但是當需要爲DOM元素添加多個事件,刪除事件,或在用Javascript封裝控件的時候,爲封裝的控件添加自定義事件的時候,οnclick=function的方式就不夠用了,但是瀏覽器有addEventListener和attachEvent方法可供調用,從而模擬出類似於C#中的事件委託的事件觸發機制!
/* * 功能:事件處理 * Author:LQB * 時間:2009-1-4 * #include JCore.js */ var JEvents = function(){ this.events={}; this.addEvent = function(o){//添加事件 if(typeof o == 'string'){/*strArg1,strArg2……的方式傳遞參數*/ for(var i = 0, a = arguments, v; v = a[i]; i++){ v = v.toString().toLowerCase(); var enFX = v.indexOf("on")==0 ? v.substr(2) : v; if(!this.events[enFX]){ this.events[enFX] = true; } } }else{ JCore.apply(this.events, o,false); } }; this.addListener = function(eventName,fn,scope/*,Args……*/){//爲事件添加處理方法 if(typeof(eventName)!="string"|| eventName.lenght==0)return; if(typeof(fn)!="function")return; eventName = eventName.toString().toLowerCase(); var enFX = eventName.indexOf("on")==0 ? eventName.substr(2) : eventName; if(!this.events[enFX]){ throw "Error! Event /"" + eName + "/" doesnt exist." } var sp = scope||window; var callArgs = Array.prototype.slice.call(arguments, 3);//從第4個參數開始 callArgs = typeof(callArgs)!="undefined"?callArgs:[]; var delegate = fn.createDelegate(callArgs,sp);//JCore支持 //爲fn方法創建標記,在刪除事件時使用 if(!fn.uid) { var time = new Date(); fn.uid= ""+time.getMinutes()+time.getSeconds()+time.getMilliseconds(); } //標記委託,在刪除事件綁定時使用 delegate.uid = getCacheAttName(enFX,fn.uid); if(typeof(this.events[enFX])!="object") this.events[enFX]=[]; this.events[enFX].push(delegate);//把方法添加到事件列表中 }; this.removeListener = function(eventName,fn){//移除事件綁定 if(eventName && fn){ eventName = eventName.toString().toLowerCase(); var enFX = eventName.indexOf("on")==0?eventName.substr(2):eventName; var AttName = getCacheAttName(enFX,fn.uid); if(typeof(this.events[enFX])=="object"){//存在這個事件 var functions = this.events[enFX]; for(i=0;i<functions.length;i++){//依次查找每個方法 if(functions[i].uid===AttName){//找到,刪除 this.events[enFX].remove(functions[i]); break; } } } } } this.fireEvent = function(eName,eventArg){//觸發事件 eName = eName.toString().toLowerCase(); var enFX = eName.indexOf("on")==0 ? eName.substr(2) : eName; var Arg = new Array(); if(typeof(eventArg)!="undefined"){ if(typeof(eventArg)=="array") Arg=eventArg; else Arg.push(eventArg); } if(typeof(this.events[enFX])=="object"){//存在此事件,同時添加了事件處理方法 var functions = this.events[enFX]; for(i=0;i<functions.length;i++){//依次觸發所有方法 functions[i].apply(window,Arg); } } } /*---------------------------------------私有方法--------------------------------------*/ var getCacheAttName = function(eventName,fnuid){ return "handle-"+eventName+"-"+fnuid; } } /*------------------------------------------------------以下是靜態方法,用於處理DOM element的事件-----------------------------------------*/ var JEventsExtendMethod = { cache : {//時間處理緩存,用於標記各個事件處理方法,在刪除事件時使用 eventCache : {}, setCache : function(el,Name,value){ if(typeof(this.eventCache[el])!="object"){ this.eventCache[el]={length :1}; } this.eventCache[el][Name]=value; this.eventCache[el].length++; }, getCache : function(el,Name){ if(typeof(this.eventCache[el]) =="object") return this.eventCache[el][Name]; else return null; }, removeCache : function(el,Name){ if(typeof(this.eventCache[el]) =="object"){ delete this.eventCache[el][Name];//刪除屬性 this.eventCache[el].length--; } if(this.eventCache[el] && this.eventCache[el].length ==1)//清除 delete this.eventCache[el]; } }, getCacheAttName : function(eventName,fnuid){ return "handle-"+eventName+"-"+fnuid; }, bind : function(el,eventName,fn,scope/*,Args……*/){//爲elment添加事件處理方法 if(typeof(el)=="undefined"||el==null)return; if(typeof(eventName)!="string"|| eventName.lenght==0)return; if(typeof(fn)!="function")return; var indexOfon = eventName.toString().toLowerCase().indexOf("on"); var enIE = indexOfon==0?eventName:"on"+eventName; var enFX = indexOfon==0?eventName.substr(2):eventName; var sp = scope||window; var callArgs = Array.prototype.slice.call(arguments, 4);//從第5個參數開始 callArgs = typeof(callArgs)!="undefined"?callArgs:[]; var delegate = fn.createDelegate(callArgs,sp);//JCore支持 if (el.addEventListener){//Mozilla系列,按隊列順序執行 el.addEventListener(enFX, delegate, false);//第三個參數與觸發方式相關 } else if (el.attachEvent){//非Mozilla系列,按堆棧順序執行(後加的事件先執行) el.attachEvent(enIE, delegate); } //爲fn方法創建標記,在刪除事件時使用 if(!fn.uid) { var time = new Date(); fn.uid= ""+time.getMinutes()+time.getSeconds()+time.getMilliseconds(); } if(!el.id){ el.id = JCore.id(el,null); } //標記委託,在刪除事件綁定時使用 var AttName = this.getCacheAttName(enFX,fn.uid); this.cache.setCache(el.id,AttName,delegate); }, unbind : function(el,eventName,fn){//爲elment解除事件綁定 if(typeof(el)=="undefined"||el==null)return; var indexOfon = eventName.toString().toLowerCase().indexOf("on"); var enIE = indexOfon==0?eventName:"on"+eventName; var enFX = indexOfon==0?eventName.substr(2):eventName; var AttName = this.getCacheAttName(enFX,fn.uid); var delegate = this.cache.getCache(el.id,AttName); if(delegate){ if (el.removeEventListener){//Mozilla系列 el.removeEventListener(enFX, delegate, false); } else if (el.detachEvent){//非Mozilla系列 el.detachEvent(enIE, delegate); } } //刪除事件緩存 this.cache.removeCache(el.id,AttName); } } JCore.apply(JEvents,JEventsExtendMethod); /*--------------------------------對event的參數包裝---------------------------------*/ var JEventWrap = function(event){ this.xtype="EventWrap"; this.data=null; this.srcElement = null; //發生事件的文檔元素 this.button = null; //[FX:0-左鍵,1-中間鍵,2-右鍵][IE:1-左鍵,2-右鍵,4-中鍵](僅對onmousedown, onmouseup,onmousemove有效) this.type = null; this.clientX = 0; //鼠標指針相對客戶區或瀏覽器窗口的X座標(標準屬性) this.clientY = 0; //鼠標指針相對客戶區或瀏覽器窗口的Y座標(標準屬性) this.offsetX = 0; //鼠標指針相對於源元素的X座標(兼容屬性)(IE) this.offsetY = 0; //鼠標指針相對於源元素的Y座標(兼容屬性)(IE) this.screenX = 0; //鼠標指針相對於用戶顯示器的左上角X座標(兼容屬性)(FX) this.screenY = 0; //鼠標指針相對於用戶顯示器的左上角Y座標(兼容屬性)(FX) this.altKey = false; //是否Alt鍵 this.ctrlKey = false; //是否Ctrl鍵, this.shitfKey = false; //是否Shift鍵 this.keyCode = 0; this.originaEvent = null; //未包裝的原始事件對象 /*----構造-----*/ if(event){ if(event.srcElement){//IE this.srcElement = event.srcElement; this.offsetX = event.offsetX; this.offsetY = event.offsetY; this.button = event.button; } else{ this.srcElement = event.target; this.offsetX = event.clientX - event.target.offsetLeft; this.offsetY = event.clientY - event.target.offsetTop; } this.type = event.type; this.altKey = event.altKey; this.ctrlKey = event.ctrlKey; this.shitfKey = event.shitfKey; this.clientX = event.clientX; this.clientY = event.clientY; this.screenX = event.screenX; this.screenY = event.screenY; this.keyCode = event.keyCode; this.originaEvent = event; } }
其中JCore.js文件見上一篇日誌“Javascript實現import動態導入文件方法”!