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 相关文章推荐
DEFER怎么用?
Jul 01 Javascript
初窥JQuery(二)事件机制(2)
Dec 06 Javascript
js中arguments的用法(实例讲解)
Nov 30 Javascript
jquery操作复选框checkbox的方法汇总
Feb 05 Javascript
js实现完全自定义可带多级目录的网页鼠标右键菜单方法
Feb 28 Javascript
Jquery Easyui进度条组件Progress使用详解(8)
Mar 26 Javascript
Chrome浏览器的alert弹窗禁止再次弹出后恢复的方法
Dec 30 Javascript
详解Angular中的自定义服务Service、Provider以及Factory
Apr 22 Javascript
jQury Ajax使用Token验证身份实例代码
Sep 22 Javascript
深入浅析JS中的严格模式
Jun 04 Javascript
vue+elementui 对话框取消 表单验证重置示例
Oct 29 Javascript
react中useState使用:如何实现在当前表格直接更改数据
Aug 05 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 MVC
2014/09/10 PHP
php使用Jpgraph绘制3D饼状图的方法
2015/06/10 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
在你的网页中嵌入外部网页的方法
2007/04/02 Javascript
AngularJS入门知识之MVW类框架的编程思想探讨
2014/12/08 Javascript
javascript里使用php代码实例
2014/12/13 Javascript
JavaScript jQuery 中定义数组与操作及jquery数组操作
2015/12/18 Javascript
jquery ztree实现树的搜索功能
2016/02/25 Javascript
jQuery实时显示鼠标指针位置和键盘ASCII码
2016/03/28 Javascript
Bootstrap 粘页脚效果
2016/03/28 Javascript
基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)
2016/08/29 Javascript
Angular实现可删除并计算总金额的购物车功能示例
2017/12/26 Javascript
Vue开发中常见的套路和技巧总结
2020/11/24 Vue.js
Python IDLE 错误:IDLE''s subprocess didn''t make connection 的解决方案
2017/02/13 Python
Python 中pandas.read_excel详细介绍
2017/06/23 Python
Python2.7 实现引入自己写的类方法
2018/04/29 Python
python之文件读取一行一行的方法
2018/07/12 Python
python绘制散点图并标记序号的方法
2018/12/11 Python
PYTHON实现SIGN签名的过程解析
2019/10/28 Python
Python log模块logging记录打印用法解析
2020/01/20 Python
python 实现简易的记事本
2020/11/30 Python
idealfit英国:世界领先的女性健身用品和运动衣物品牌
2017/11/25 全球购物
YSL圣罗兰美妆官方旗舰店:购买YSL口红
2018/04/16 全球购物
临床护理求职信
2014/04/26 职场文书
安康杯竞赛活动总结
2014/05/05 职场文书
电工技术比武方案
2014/05/11 职场文书
租房协议书样本
2014/08/20 职场文书
离职报告格式
2014/11/04 职场文书
2016年寒假社会实践活动心得体会
2015/10/09 职场文书
小学数学教学反思范文
2016/02/16 职场文书
职业生涯规划书之大学四年
2019/08/07 职场文书
pytorch 中nn.Dropout的使用说明
2021/05/20 Python
Python获取江苏疫情实时数据及爬虫分析
2021/08/02 Python
JavaScript实现栈结构详细过程
2021/12/06 Javascript
springboot入门 之profile设置方式
2022/04/04 Java/Android
Win11安全功能升级:内置防网络钓鱼功能
2022/04/08 数码科技