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 相关文章推荐
Js之软键盘实现(js源码)
Jan 30 Javascript
仅IE6/7/8中innerHTML返回值忽略英文空格的问题
Apr 07 Javascript
JavaScript 放大镜 移动镜片效果代码
May 09 Javascript
关于jQuery判断元素是否存在的问题示例探讨
Jul 21 Javascript
JavaScript数组迭代器实例分析
Jun 09 Javascript
AngularJS 最常用的功能汇总
Feb 17 Javascript
js一维数组、多维数组和对象的混合使用方法
Apr 03 Javascript
利用JQuery直接调用asp.net后台的简单方法
Oct 27 Javascript
js获取指定字符前/后的字符串简单实例
Oct 27 Javascript
微信小程序简单实现form表单获取输入数据功能示例
Nov 30 Javascript
Egg Vue SSR 服务端渲染数据请求与asyncData
Nov 24 Javascript
vue Element左侧无限级菜单实现
Jun 10 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+js实现图片的上传、裁剪、预览、提交示例
2013/08/27 PHP
destoon实现VIP排名一直在前面排序的方法
2014/08/21 PHP
PHP递归统计系统中代码行数
2019/09/19 PHP
jquery实现checkbox 全选/全不选的通用写法
2014/02/22 Javascript
Jquery实现兼容各大浏览器的Enter回车切换输入焦点的方法
2014/09/01 Javascript
javascript 面向对象封装与继承
2014/11/27 Javascript
JS实现Select的option上下移动的方法
2016/03/01 Javascript
使用jQuery Rotare实现微信大转盘抽奖功能
2016/06/20 Javascript
AngularJS实现自定义指令及指令配置项的方法
2017/11/20 Javascript
js时间戳与日期格式之间相互转换
2017/12/11 Javascript
jQuery实现上下滚动公告栏详细代码
2018/11/21 jQuery
js设置默认时间跨度过程详解
2019/07/17 Javascript
关于layui的动态图标不显示的解决方法
2019/09/04 Javascript
微信小程序日历插件代码实例
2019/12/04 Javascript
Vue中 axios delete请求参数操作
2020/08/25 Javascript
python实现上传样本到virustotal并查询扫描信息的方法
2014/10/05 Python
python根据出生日期获得年龄的方法
2015/03/31 Python
python中map、any、all函数用法分析
2015/04/21 Python
pandas DataFrame索引行列的实现
2019/06/04 Python
Python学习笔记之迭代器和生成器用法实例详解
2019/08/08 Python
Python3使用xml.dom.minidom和xml.etree模块儿解析xml文件封装函数的方法
2019/09/23 Python
Python进程池Pool应用实例分析
2019/11/27 Python
日本无添加化妆品:HABA
2016/08/18 全球购物
攀岩、滑雪、徒步旅行装备:Black Diamond Equipment
2019/08/16 全球购物
什么是Web Service?
2012/07/25 面试题
业务经理的岗位职责
2013/11/16 职场文书
简历的自我评价
2014/02/03 职场文书
校园摄影活动策划方案
2014/02/05 职场文书
平面设计专业大学生职业规划书
2014/03/12 职场文书
文秘专业应届生求职信
2014/05/26 职场文书
2015年乡镇卫生院工作总结
2015/04/22 职场文书
芙蓉镇观后感
2015/06/10 职场文书
《鸡兔同笼》教学反思
2016/02/19 职场文书
导游词之苏州盘门景区
2019/11/12 职场文书
go结构体嵌套的切片数组操作
2021/04/28 Golang
vue使用watch监听属性变化
2022/04/30 Vue.js