Javascript处理DOM元素事件实现代码


Posted in Javascript onMay 23, 2012

DOM元素都有一些标准事件,一般使用时只要使用onclick=function的方式就可以了,但是当需要为DOM元素添加多个事件,删除事件,或在用Javascript封装控件的时候,为封装的控件添加自定义事件的时候,onclick=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核心支持代码
Javascript 相关文章推荐
关于火狐(firefox)及ie下event获取的两种方法
Dec 27 Javascript
jQuery DOM删除节点操作指南
Mar 03 Javascript
Js实现自定义右键行为
Mar 26 Javascript
JQuery实现级联下拉框效果实例讲解
Sep 17 Javascript
JS实现鼠标移上去显示图片或微信二维码
Dec 14 Javascript
微信小程序 详解下拉加载与上拉刷新实现方法
Jan 13 Javascript
移动端手指放大缩小插件与js源码
May 22 Javascript
在Vue中使用echarts的实例代码(3种图)
Jul 10 Javascript
使用angularjs.foreach时return的问题解决
Sep 30 Javascript
详解如何使用koa实现socket.io官网的例子
Nov 04 Javascript
快速对接payjq的个人微信支付接口过程解析
Aug 15 Javascript
JS正则表达式常见函数与用法小结
Apr 13 Javascript
面向对象Javascript核心支持代码分享
May 23 #Javascript
Package.js  现代化的JavaScript项目make工具
May 23 #Javascript
检测input每次的输入是否合法遇到汉字输入就有问题
May 23 #Javascript
JavaScript可否多线程? 深入理解JavaScript定时机制
May 23 #Javascript
setTimeout的延时为0时多个浏览器的区别
May 23 #Javascript
jQuery 瀑布流 绝对定位布局(二)(延迟AJAX加载图片)
May 23 #Javascript
jQuery 瀑布流 浮动布局(一)(延迟AJAX加载图片)
May 23 #Javascript
You might like
php中explode与split的区别介绍
2012/10/03 PHP
php验证邮箱和ip地址最简单方法汇总
2015/10/30 PHP
javascript 树形导航菜单实例代码
2013/08/13 Javascript
浅谈JavaScript字符集
2014/05/22 Javascript
Mac OS X 系统下安装和部署Egret引擎开发环境
2014/09/03 Javascript
使用javascript获取页面名称
2014/12/23 Javascript
改变checkbox默认选中状态及取值的实现代码
2016/05/26 Javascript
分享JavaScript监听全部Ajax请求事件的方法
2016/08/28 Javascript
浅谈jQuery hover(over, out)事件函数
2016/12/03 Javascript
浅谈JavaScript的闭包函数
2016/12/08 Javascript
React Native 截屏组件的示例代码
2017/12/06 Javascript
Vue实现PopupWindow组件详解
2018/04/28 Javascript
JavaScript中创建原子的方法总结
2018/08/26 Javascript
详解Vue2 添加对scss的支持
2019/01/02 Javascript
javascript实现前端成语点击验证优化
2020/06/24 Javascript
nuxt 自定义 auth 中间件实现令牌的持久化操作
2020/11/05 Javascript
python文件和目录操作函数小结
2014/07/11 Python
python shell根据ip获取主机名代码示例
2017/11/25 Python
Python编程中NotImplementedError的使用方法
2018/04/21 Python
python得到windows自启动列表的方法
2018/10/14 Python
利用Pytorch实现简单的线性回归算法
2020/01/15 Python
Python select及selectors模块概念用法详解
2020/06/22 Python
Python Opencv实现单目标检测的示例代码
2020/09/08 Python
关于Python 解决Python3.9 pandas.read_excel(‘xxx.xlsx‘)报错的问题
2020/11/28 Python
美国现代家具和家居商店:Apt2B
2016/08/29 全球购物
Saks Fifth Avenue澳洲/亚太地区:萨克斯第五大道精品百货店
2019/06/09 全球购物
澳大利亚在线床零售商:Bedworks
2020/09/01 全球购物
生物学学生自我评价
2014/01/17 职场文书
《海底世界》教学反思
2014/04/16 职场文书
班级学习计划书
2014/04/27 职场文书
群众路线查摆问题整改措施思想汇报
2014/10/10 职场文书
干部作风建设个人剖析材料
2014/10/11 职场文书
2014学生会工作总结报告
2014/12/02 职场文书
公司经营目标责任书
2015/01/29 职场文书
2015年宣传工作总结
2015/04/08 职场文书
学校教师培训工作总结
2015/10/14 职场文书