事件嗅探技术

给浏览器绑定事件的兼容性很麻烦.因为不同的浏览器提供了不同的事件支持.比如IE系列的支持mouseenter/mouseleave事件.而opera不支持contextmenu以及input相关的onbeforepaste, onbeforecut等.

比如我们要绑定鼠标滚轮事件.那么通过浏览器嗅觉的方法.会是以下的伪代码:

 

?
1
2
3
4
5
if (co.browser.ie) {
     Event.on(document, 'mousewheel' , callback);
} else  {
     Event.on(document, 'DOMMouseScroll' , callback);
}

 

但如果有一天IE支持了DOMMouseScroll事件的话.那么这段代码就又需要改变了.这样是很危险的.

那么有没有一种方法能够直接嗅探一个元素是否支持一个事件呢?

其实在DOM2事件标志是可以通过in来检测一个事件是否存在于一个元素

 

?
1
2
alert( 'onclick'  in  document.documentElement); // true
alert( 'onclick2'  in  document.documentElement); // false

 

而且要保证事件对应的元素可以是事件的起源地

 

?
1
2
alert( 'onreset'  in  document.documentElement); // false
alert( 'onreset'  in  document.createElement( 'input' )); // true

 

可以看出通过in很容易就做到了事件支持检测.但不幸的是.firefox根本就不支持.但好的方法又被挖掘出来了.那就是将一个事件属性设置给要检测的元素.如果元素可以识别这个事件.那么这个事件会有一个事件句柄

 

?
1
2
3
4
5
var  el = document.createElement( 'div' );
el.setAttribute( 'onclick' , 'return;' );
typeof  el.onclick; // "function"
el.setAttribute( 'onclick2' , 'return;' );
typeof  el.onclick2; // "undefined"

 

通过上面的两个分支的分析.就可以写下这个检测函数: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var  isEventSupported = ( function () {
     var  TAGNAMES = {
         'select' : 'input' , 'change' : 'input' ,
         'submit' : 'form' , 'reset' : 'form' ,
         'error' : 'img' , 'load' : 'img' , 'abort' : 'img'
     }, cache = {};
     function  isEventSupported(eventName) {
         eventName = 'on'  + eventName;
         if  (eventName in  cache) {
             return  cache[eventName];
         }
         var  el = document.createElement(TAGNAMES[eventName] || 'div' )
         var  isSupported = (eventName in  el),
             proto = el.__proto__ || {},
             temp;
         if  (isSupported && (temp = proto[eventName]) && delete  proto[eventName]) { // 防止DOM的__proto__被改写
             isSupported = eventName in  el;
             proto[name] = temp;
         }
         if  (!isSupported ) {
             el.setAttribute(eventName, 'return;' );
             isSupported = typeof  el[eventName] == 'function' ;
             el.removeAttribute(eventName);
         }
         el = null ;
         cache[eventName] = isSupported;
         return  isSupported;
         
     }
     return  isEventSupported;
})();

到此.如果坚持opera浏览器是否支持contextmenu函数的话.就可以使用

 

?
alert(isEventSupported( 'contextmenu' )); // opera -- false

 

不用使用浏览器探测.也不需要担心那些因素了.

因为Div可以作为所有鼠标事件的载体.那么如果单纯检测MouseEvent的支持.可以用下面的简化函数(JQ1.4也使用了)

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
var  eventSupported = function ( eventName ) {
     var  el = document.createElement( "div" );
     eventName = "on"  + eventName;
 
     var  isSupported = (eventName in  el);
     if  ( !isSupported ) {
         el.setAttribute(eventName, "return;" );
         isSupported = typeof  el[eventName] === "function" ;
     }
     el = null ;
 
     return  isSupported;
};

 

这样IE就可以用eventSupported('mouseenter')来检测了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值