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下通过getList函数实现分页效果的代码
Sep 17 Javascript
jquer之ajaxQueue简单实现代码
Sep 15 Javascript
JavaScript/jQuery 表单美化插件小结
Feb 14 Javascript
再谈javascript面向对象编程
Mar 18 Javascript
解决jQuery上传插件Uploadify出现Http Error 302错误的方法
Dec 18 Javascript
微信小程序  简单实例(阅读器)的实例开发
Sep 29 Javascript
Angularjs 设置全局变量的方法总结
Oct 20 Javascript
JS FormData上传文件的设置方法
Jul 05 Javascript
在ABP框架中使用BootstrapTable组件的方法
Jul 31 Javascript
详解利用Angular实现多团队模块化SPA开发框架
Nov 27 Javascript
vue 实现模糊检索并根据其他字符的首字母顺序排列
Sep 19 Javascript
JavaScript使用百度ECharts插件绘制饼图操作示例
Nov 26 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
自制短波长线天线频率预选器 - 成功消除B2K之流的镜像
2021/03/02 无线电
php 中文处理函数集合
2008/08/27 PHP
用PHP为SHOPEX增加日志功能代码
2010/07/02 PHP
php excel reader读取excel内容存入数据库实现代码
2012/12/06 PHP
php如何解决无法上传大于8M的文件问题
2014/03/10 PHP
php支付宝在线支付接口开发教程
2016/09/19 PHP
PHP抓取远程图片(含不带后缀的)教程详解
2016/10/21 PHP
Python中使用django form表单验证的方法
2017/01/16 PHP
PHP实现的数据对象映射模式详解
2019/03/20 PHP
js GridView 实现自动计算操作代码
2009/03/25 Javascript
js 获取Listbox选择的值的代码
2010/04/15 Javascript
javascript中的delete使用详解
2013/04/11 Javascript
Redis基本知识、安装、部署、配置笔记
2015/03/05 Javascript
JavaScript数据类型学习笔记
2016/01/25 Javascript
JS弹出层遮罩,隐藏背景页面滚动条细节优化分析
2016/04/29 Javascript
浅析Bootstrap表格的使用
2016/06/23 Javascript
bootstrap table插件的分页与checkbox使用详解
2017/07/23 Javascript
微信小程序使用image组件显示图片的方法【附源码下载】
2017/12/08 Javascript
Webpack之tree-starking 解析
2018/09/11 Javascript
解决Layui数据表格显示无数据提示的问题
2019/11/14 Javascript
Python中条件选择和循环语句使用方法介绍
2013/03/13 Python
python对字典进行排序实例
2014/09/25 Python
使用Python的Scrapy框架编写web爬虫的简单示例
2015/04/17 Python
python爬虫_微信公众号推送信息爬取的实例
2017/10/23 Python
Python button选取本地图片并显示的实例
2019/06/13 Python
Python 余弦相似度与皮尔逊相关系数 计算实例
2019/12/23 Python
CSS3教程:边框属性border的极致应用
2009/04/02 HTML / CSS
复古斯堪的纳维亚儿童服装:Baby go Retro
2017/09/09 全球购物
路由表示做什么用的?在linux环境中怎么来配置一条默认路由?
2013/06/07 面试题
金融系毕业生自荐书
2014/07/08 职场文书
安全目标管理责任书
2014/07/25 职场文书
新闻专业毕业生求职信
2014/08/08 职场文书
市委常委会班子党的群众路线教育实践活动整改方案
2014/10/25 职场文书
2016元旦主持人经典开场白台词
2015/12/03 职场文书
2019让人心动的商业计划书
2019/06/27 职场文书
sql查询语句之平均分、最高最低分及排序语句
2022/05/30 MySQL