事件嗅探技术
2010-04-29 23:05 BlueDream 阅读(606) 评论(0) 收藏 举报给浏览器绑定事件的兼容性很麻烦.因为不同的浏览器提供了不同的事件支持.比如IE系列的支持mouseenter/mouseleave事件.而opera不支持contextmenu以及input相关的onbeforepaste, onbeforecut等.
比如我们要绑定鼠标滚轮事件.那么通过浏览器嗅觉的方法.会是以下的伪代码:
if(co.browser.ie) {
Event.on(document, 'mousewheel', callback);
} else {
Event.on(document, 'DOMMouseScroll', callback);
}
但如果有一天IE支持了DOMMouseScroll事件的话.那么这段代码就又需要改变了.这样是很危险的.
那么有没有一种方法能够直接嗅探一个元素是否支持一个事件呢?
其实在DOM2事件标志是可以通过in来检测一个事件是否存在于一个元素
alert('onclick' in document.documentElement); // true
alert('onclick2' in document.documentElement); // false
而且要保证事件对应的元素可以是事件的起源地
alert('onreset' in document.documentElement); // false
alert('onreset' in document.createElement('input')); // true
可以看出通过in很容易就做到了事件支持检测.但不幸的是.firefox根本就不支持.但好的方法又被挖掘出来了.那就是将一个事件属性设置给要检测的元素.如果元素可以识别这个事件.那么这个事件会有一个事件句柄
var el = document.createElement('div');
el.setAttribute('onclick', 'return;');
typeof el.onclick; // "function"
el.setAttribute('onclick2', 'return;');
typeof el.onclick2; // "undefined"
通过上面的两个分支的分析.就可以写下这个检测函数:
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也使用了)
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')来检测了.
参考链接:
http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
浙公网安备 33010602011771号