给浏览器绑定事件的兼容性很麻烦.因为不同的浏览器提供了不同的事件支持.比如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')来检测了.