// 跨浏览器事件处理程序封装
var EventUtil = {
// 添加事件句柄
addHandler: function(element, type, handler){
// DOM 2 级事件处理程序
if (element.addEventListener){
element.addEventListener(type, handler, false);
}
// IE事件处理程序
else if (element.attachEvent){
element.attachEvent("on" + type, handler);
}
// DOM 0 级事件处理程序
else{
element["on" + type] = handler;
}
},
// 获取鼠标事件button属性 ,
// 0:主鼠标按钮
// 1:中间按钮
// 2:次鼠标按钮
getButton: function(event){
// DOM Button属性
if(document.implementation.hasFeature("MouseEvents", "2.0")){
return event.button;
}
// IE 模式下的button属性
else{
switch(event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4: return 1;
}
}
},
// 获取键盘事件keypress事件的charCode属性
// 该值表示按下的键所表明的ASCII码
getCharCode: function(event){
// IE9 FireFox Chrome Safari
if(typeof event.getCharCode == "number"){
return event.charCode;
}
// IE8 Opera
else{
return event.keyCode;
}
},
// 获取剪切板内容
getClipboardText: function(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
// 获取事件对象
getEvent: function(event){
return event ? event : window.event;
},
// 获取relatedTarget属性
// 在mouseover事件触发时,IE的fromElement属性中保存了相关元素;
// 在mouseout事件触发时,IE的toElement属性中保存了相关元素
getRelatedTarget: function(event){
// DOM属性,IE8不支持
if (event.relatedTarget){
return event.relatedTarget;
}
// IE mouseout
else if (event.toElement){
return event.toElement;
}
// IE mouseover
else if (event.fromElement){
return event.fromElement;
}
else {
return null;
}
},
// 获取target事件对象
getTarget: function(event){
// DOM || IE
return event.target || event.srcElement;
},
// 获取鼠标滚轮滚动时的属性值
getWheelDelta: function(event){
// IE6.0 Chrome Opera Safari wheelData属性值
// 向前滚动是120的倍数
// 向后滚动是-120的倍数
if (event.wheelDelta){
return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
}
// Firefox detail属性值
// 向前滚动是-3的倍数
// 向后滚动是3的倍数
else {
return -event.detail * 40;
}
},
// 取消事件的默认行为
preventDefault: function(event){
// DOM
if (event.preventDefault){
event.preventDefault();
}
// IE
else {
event.returnValue = false;
}
},
// 移除事件句柄
removeHandler: function(element, type, handler){
// DOM 2
if (element.removeEventListener){
element.removeEventListener(type, handler, false);
}
// IE
else if (element.detachEvent){
element.detachEvent("on" + type, handler);
}
// DOM 0
else {
element["on" + type] = null;
}
},
// 设置剪切板内容
setClipboardText: function(event, value){
// Chrome
if (event.clipboardData){
event.clipboardData.setData("text/plain", value);
}
// IE
else if (window.clipboardData){
window.clipboardData.setData("text", value);
}
},
// 取消事件冒泡
stopPropagation: function(event){
// DOM
if (event.stopPropagation){
event.stopPropagation();
}
// IE
else {
event.cancelBubble = true;
}
}
};
这是EventUtil中最经常使用的方法,它的做用是为对象添加事件并保证兼容性javascript
在DOM0级事件处理程序(下文均简称“DOM0级”)中java
每一个元素(包括windows和document)都有本身的事件处理程序属性(一般所有小写)windows
如常见的onload、onclick等浏览器
以Click事件为例(下同),DOM0级一般以下指定事件处理程序函数
1 var btn=document.getElementById("myBtn");
2 btn.onclick=function(){ //指定事件处理程序
3 alert(this.id); //"myBtn"
4 };
在DOM2级事件处理程序(下文均简称“DOM2级”)中this
指定事件处理程序的方法为addEventListener( )编码
它接受3个参数:要处理的事件名、做为事件处理程序的函数和一个布尔值(大多数状况下是false)spa
(布尔值表示是在捕获阶段(true)仍是冒泡阶段(false)调用事件处理程序)设计
DOM2级一般以下指定事件处理程序指针
1 var btn=document.getElementById("myBtn");
2 //在外部定义好函数再传给addEventListener(),这样才能够经过removeEventListener()移除
3 var handler=function(){
4 alert(this.id);
5 };
6 btn.addEventListener("click",handler,false);
在旧版本IE(表明IE8-,下文均简称“IE”)中
指定事件处理程序的方法为attachEvent( )
它接受两个参数:事件处理程序名称与事件处理程序函数
IE中一般以下指定事件处理程序
1 var btn=document.getElementById("myBtn");
2 var handler=function(){
3 alert("Clicked");
4 };
5 //注意:第一个参数是"onclick",而非DOM0的addEventListener()方法中的"click"
6 btn.attachEvent("onclick",handler);
由上可见,DOM0级、DOM2级和IE中指定事件方法有很大不一样
EventUtil对象中的addHandler方法正是为了处理这些差别而存在
在添加了EventUtil(指上文“EventUtil对象全见”中的代码,下同)后,能够以下所示为对象指定事件处理程序
1 var btn=document.getElementById("myBtn"); 2 var handler=function(){ 3 alert("Clicked!"); 4 }; 5 EventUtil.addHandler(btn,"click",handler); //调用已定义的EventUtil对象
就像这样,使用addHandler方法指定事件处理程序
便可兼容支持DOM0级、DOM2级的浏览器或IE浏览器
一样的,在DOM0级、DOM2级与IE中,移除事件的方法是不一样的
在DOM0级中,在再也不须要某对象的事件处理程序时(如页面销毁前),能够像下面这样简单的移除事件处理程序
btn.onclick=null;
在DOM2级中,删除事件处理程序须要使用removeEventListener( )方法,以下所示
1 //这里的handler应与使用addEventListener指定事件处理函数时所用的外部函数相同
2 btn.removeEventListener("click",handler,fals
而在IE中,删除事件则需使用detachEvent( )方法
btn.detachEvent("onclick",handler);
由于这些差别的存在,才令EventUtil中有了removeHandler方法
在添加了EventUtil后,能够以下所示使用removeHandler方法方便地删除对象事件处理程序
1 //一样的,这里的handler应与使用addHandler指定事件处理函数时所用的外部函数相同
2 EventUtil.removeHandler(btn,"click",hanlder);
你可能已经发现了,在EventUtil中,不少方法的参数都是event
这个event实际上是事件对象
兼容DOM(不管是DOM0级仍是DOM2级)的浏览器会将一个event对象传入到事件处理程序中
这个event对象支持许多方法,下表列出了一些经常使用的方法以供参考
属性/方法 | 类型 | 读/写 | 说明 |
---|---|---|---|
currentTarget | Element | 只读 | 其事件处理程序当前正在处理事件的那个元素 |
preventDefault( ) | Function | 只读 | 取消事件的默认行为 |
stopPropagation( ) | Function | 只读 | 取消事件的进一步捕获或冒泡 |
target | Element | 只读 | 事件的实际(真正)目标 |
type | String | 只读 | 被触发的事件的类型 |
在兼容DOM的浏览器中,event对象能够以下面这个例子这样使用
1 var btn=document.getElementById("myBtn"); 2 var handler=function(event){ 3 switch(event.type){ //使用event.type检测事件类型 4 case "click": //如果Click事件 5 alert("Clicked"); 6 break; 7 case: "mouseover": //如果Mouseover事件 8 //使用event.target获取事件目标,并更改目标样式背景颜色 9 event.target.style.backgroundColor="red"; 10 break; 11 case: "mouseout": //如果Mouseout事件 12 event.target.style.backgroundColor=""; 13 break; 14 } 15 }; 16 btn.onclick=handler; //使用DOM0级为对象添加事件处理函数 17 btn.onmouseover=handler; 18 btn.onmouseout=handler;
须要强调的是,以上使用event事件的方法仅适用于兼容DOM的浏览器
在IE中则有所不一样
在IE中,使用DOM0级添加事件处理程序时,event对象做为window对象的一个属性存在,以下例子所示
1 btn.onclick=function(){ 2 var event=window.event; 3 alert(event.type); //"click" 4 };
神奇的是,若是事件处理程序是使用attachEvent( )添加的,则又能够像在支持DOM的浏览器中同样
event对象又可做为参数传入事件处理程序函数中,以下例子所示
1 btn.attachEvent("onclick",function(event){ 2 alert(event.type); //"click" 3 });
并且,更神奇的是,在IE中,event对象的一些属性/方法还跟其它支持DOM的浏览器中不一样,以下表
属性/方法 | 类型 | 读/写 | 说明 |
---|---|---|---|
cancelBubble | Boolean | 读/写 | 默认值为false,将其设置为true就能够取消事件冒泡 (与DOM中的stopPropagation( )方法的做用相同) |
returnValue | Boolean | 读/写 | 默认值为true,将其设置为false就能够取消事件的默认行为 (与DOM中的preventDefault( )方法的做用相同) |
srcElement | Element | 只读 | 事件的目标(与DOM中的target属性相同) |
type | String | 只读 | 被触发的事件类型 |
正是由于这些差别的存在,使得EventUtil中的getEvent方法应运而生
在添加了EventUtil后,能够以下“重点语句”所示获取event对象而无需担忧上述差别致使的兼容问题
1 var btn=document.getElementById("myBtn"); 2 var handler=function(event){ 3 event=EventUtil.getEvent(event); //重点语句 4 }; 5 EventUtil.addHandler(btn,"click",handler);
这样,就解决了event对象获取方式不一样的问题
至于event对象的属性/方法差别,下文还会介绍其它方法进行处理
在上一部分(“event对象与getEvent方法”)的介绍中,经过表格你可能已经发现
在IE中和其它兼容DOM的浏览器中,获取事件目标(target)的方法不一样
在IE中,获取事件目标对象的方法为event.srcElement
而在其它兼容DOM的浏览器中,获取事件目标对象的方法却为event.target
getTarget方法正是为了处理这个差别而存在
在添加了EventUtil后,能够以下“重点语句”所示获取事件的目标(target)对象而无需担忧上述差别致使的兼容问题
1 var btn=document.getElementById("myBtn"); 2 var handler=function(event){ 3 event=EventUtil.getEvent(event); 4 var target=EventUtil.getTarget(event); //重点语句 5 }; 6 EventUtil.addHandler(btn,"click",handler);
在其它兼容DOM的浏览器中,阻止特定事件的默认行为只需使用event对象自带的preventDefault( )方法,以下所示
1 var link=document.getElementById("myLink"); 2 link.onclick=function(event){ 3 event.preventDefault(); //DOM0级或DOM2级阻止事件默认行为的方法 4 }
而在IE中,则需赋予event.returnValue的值为false才能阻止特定事件的默认行为
1 link.attachEvent("onclick",function(event){ 2 event.returnValue=false; //IE中阻止事件默认行为的方法 3 });
故在EventUtil中,存在一个preventDefault方法,用于统一上述差别
在添加了EventUtil后,能够以下“重点语句”所示阻止特定事件的默认行为而无需担忧上述差别致使的兼容问题
1 var link=document.getElementById("myLink"); 2 var handler=function(event){ 3 event=EventUtil.getEvent(event); 4 EventUtil.preventDefault(event); //重点语句 5 }; 6 EventUtil.addHandler(link,"click",handler);
有时候,咱们须要取消事件的进一步捕获或冒泡,即中止事件在DOM层次中传播
兼容DOM的浏览器能够经过使用event对象自带的stopPropagation( )方法作到这一点
1 var link=document.getElementById("myLink"); 2 link.onclick=function(event){ 3 event.stopPropagation(); //DOM0级或DOM2级取消事件的进一步捕获或冒泡的方法 4 };
而在IE中,则需赋予event.cancelBubble的值为true
1 link.attachEvent("onclick",function(event){ 2 event.cancelBubble=true; //IE中取消事件的进一步冒泡的方法 3 });
EventUtil中的stopPropagation( )方法能够统一上述差别
在添加了EventUtil后,能够以下“重点语句”所示取消事件的进一步捕获或冒泡而无需担忧差别致使的兼容问题
1 var link=document.getElementById("myLink"); 2 var handler=function(event){ 3 event=EventUtil.getEvent(event); 4 EventUtil.stopPropagation(event); //重点语句 5 }; 6 EventUtil.addHandler(link,"click",handler);
mouseover与mouseout有“主目标(主元素)”与“相关元素”的概念
由于在发生mouseover或mouseout事件时,还会涉及到其它元素
这两个事件都会涉及把鼠指针从一个元素(相关元素)移到另外一个元素(主目标)内
具体点说
对mouseover事件而言,事件的主目标是得到光标的元素,而相关元素是那个失去光标的元素
对mouseout事件而言,事件的主目标是失去光标的元素,而相关元素是那个得到光标的元素
DOM经过event对象的relatedTarget属性提供了相关元素的信息
但IE8及以前的版本不支持relatedTarget属性,不过提供了其它相似属性支持
在mouseover事件触发时,IE的formElement属性中保存了相关元素
在mouseout事件触发时,IE的toElement属性中保存了相关元素
EventUtil中的getRelatedTarget方法正是为了平衡这些差别而存在
在添加了EventUtil后,能够像下面示例“重点语句”同样使用getRelatedTarget方法
1 var div=document.getElementById("myDiv"); 2 EventUtil.addHandler(div,"mouseout",function(event){ 3 event=EventUtil.getEvent(event); 4 var target=EventUtil.getTarget(event); 5 var relatedTarget=EventUtil.getRelatedTarget(event); //重点语句 6 alert("鼠标离开了"+target.tagName+"元素而进入了"+relatedTarget.tagName+"元素"); 7 });
咱们知道,只有在鼠标主按钮被单击(或键盘回车键被按下、触摸屏被单点击中)时才会触发click事件
但对于mousedown和mouseup事件来讲,鼠标上的任意按钮均可以触发它
有时,咱们可能须要知道用户按下了哪一个鼠标按钮
DOM的event.button属性能够作到这一点,这个属性可能有3个值
0表示主鼠标按钮(一般是左键)、1表示鼠标滚轮按钮、2表示鼠标右键
虽然IE的event对象也提供了button属性
但遗憾的是,IE的button属性与DOM的button属性有很大差别
并且不被其它浏览器支持,实用性很低,在此不予赘述
getButton方法的做用是,让全部浏览器的event.button表现与DOM相同
在添加了EventUtil后,能够像下面示例“重点语句”同样使用getButton方法而无需考虑IE中的差别
1 var div=document.getElementById("myDiv"); 2 EventUtil.addHandler(div,"mousedown",function(event){ //监控按下div的是哪一个按钮 3 event=EventUtil.getEvent(event); 4 alert(EventUtil.getButton(event)); //重点语句,弹出框显示按下哪一个鼠标键的代号(0、1或2) 5 }); 6 //同理,若事件是mouseup,则botton值表示释放的是哪一个按钮
有时,为了让页面达到某些特殊效果,咱们须要监视用户的鼠标滚轮操做
这一次,“不同凡响”的是Firefox,而不是旧版本的IE
全部浏览器(包括IE6,除了Firefox)均支持鼠标滚轮事件mousewheel
而Firefox倒是经过DOMMouseScroll事件实现相似功能
事件名的差别没法经过EventUtil改变
但关键是,这个事件表示鼠标滚轮滚动方向的方法,Firefox与其它浏览器也有差别
差别的自己已不是重点,重点是EventUtil的getWheelDelta方法能够很好的解决它们的差别
在添加了EventUtil后,能够像下面示例“重点语句”同样使用getWheelDelta方法而无需考虑FIrefox中的差别
1 function handleMouseWheel(event){ 2 event=EventUtil.getEvent(event); 3 var delta=EventUtil.getWheelDelta(event); //重点语句,delta是表示鼠标滚轮滚动方向的数值 4 alert(delta); 5 } 6 EventUtil.addHandler(document,"mousewheel",handleMouseWheel); //非Firefox 7 EventUtil.addHandler(document,"DOMMouseScroll",handleMouseWheel); //Firefox
多数状况下,咱们只需关心如上例中经过getWheelDelta方法得到的delta数值的正负
当用户向前滚动鼠标滚轮时,delta的数值为正,反之为负
滚轮滚动越多,delta数值的绝对值越大,且均是120的倍数
在全部浏览器中,按下可以插入或删除的字符的按键都会触发keypress事件
但IE8-及Opera取得字符编码(ASCII码)的方式与其它浏览器是不一样的
为了解决这一差别,在EventUtil中存在getCharCode方法
在添加了EventUtil后,能够像下面示例“重点语句”同样使用getCharCode方法来获取统一的字符编码
1 var textbox=document.getElementById("myText"); 2 EventUtil.addHandler(textbox,"keypress",function(event){ 3 event=EventUtil.getEvent(event); 4 alert(EventUtil.getCharCode(event)); //重点语句,弹出窗口中显示按下按键表明字符的ASCII码 5 });