检测浏览器对事件的支持程度

来源:Ruby's Louvre 时间:2009-12-23 19:40:00 

自从jQuery搞出特性侦探这东东,西方从来没有如此狂热研究浏览器。在以前javascript与DOM遍地是bug,美工主宰前端的年代,人们只有两种极端方式,用户禁止脚本运行,浏览器商狂升级(IE6之前也很积极的)。

这年头,也就Base2与Prototype2做得最好,当然dojo与YUI也不错。不过最近五年,Opera与Safari都建立了对DOM完整的支持后,世界分两半,一半是IE统治的混乱世界,它是拥有如此丰富的私有特征,CSS表达式,HTC,CSS滤镜,VML,userData,XML数据岛,最早的AJAX支持,以及DHTML最好的支持API(innerHTML,innerText,outerHTML,outerText,insertAdjactentXXX,offsetXXX,clientXXX,scrollXXX,Range,designMode,sertRow和insertCell等动态操作表格API……),难怪IE会赢的!不过IE也埋下了许多地雷,加之IE不会其他游览器升级那么快,许多Bug都要我们亲手修正。这么多浏览器,这么多版本,特性侦探是很有必要。现在我们看到那一套关于事件的API,基本上是微软从桌面搬过来,后来W3C又加一大堆与DOM开头的事件,不过除了DOMMouseScroll基本没什么人用。N多事件,与逐个嗅探浏览器那样成了个头痛的问题。

John Resig说过类库就是用来屏蔽浏览器的差异的。在国外这篇文章中,就有对事件支持的详尽分析(注,那个博客是John Resig经常去的,你可以把它当成的jQuery核心小组的酒吧,他们与其他高手经常在那里讨论浏览器的天方夜谭,研究javascript的炼金术)。在事件系统中,很明显的几个,IE支持mouseenter与mouseleave,Opera支持右键菜单但不允许你用contextmenu类似的API操作它,还有onbeforepaste, onbeforecut这些与input元素相关的事件,IE与WebKit支持,但FF不支持……非常混乱。一般我们可以用for...in循环把它遍历一下,或者像以下简单地检测:

'onclick' in document.documentElement; // true 
'onclick2' in document.documentElement; // false

很不幸,这不准确,因为我们可以添加一些同名的自定义属性。有人说,赶在用户添加之前检测它们,但也行不通,因此有些事件是只有特定元素才有的。

'onreset' in document.documentElement; // false 
'onreset' in document.createElement('input'); // true

在标准浏览器我们可以用setAttrubute为元素赋以已知事件名一个值,这个值会自动包装成一个函数,如果非事件名,则不会改变其类型。那么我检测它是否为函数就是!

var el = document.createElement('div'); 
el.setAttribute('onclick', 'return;'); 
alert(typeof el.onclick); // "function" 
el.setAttribute('onclick2', 'return;'); 
alert(typeof el.onclick2); // "undefined"

同样很不幸,基于众所周知的原因,IE的setAttribute与W3C是有很大的差别,IE会原样输出,加之,IE不存在所谓的泛化函数(原生对象的方法),它的API没有name,call,apply与toString,因此也无法判定它们是否为函数。综合以上两种方式,看看外国人搞出什么怪物来……

var isEventSupported = (function(){//使用模块模式 
var TAGNAMES = {//特定元素上的特定事件 
'select':'input','change':'input', 
 'submit':'form','reset':'form', 
'error':'img','load':'img','abort':'img'

function isEventSupported(eventName, element) { 
element = element || document.createElement(TAGNAMES[eventName] || 'div'); 
eventName = 'on' + eventName; 
// When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those 

var isSupported = (eventName in element);//DOM0 
if (!isSupported) { 
// if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element 
if (!element.setAttribute) { 
element = document.createElement('div'); 

if (element.setAttribute && element.removeAttribute) { 
element.setAttribute(eventName, ''); 
isSupported = typeof element[eventName] == 'function'; 
// if property was created, "remove it" (by setting value to `undefined`) 
if (typeof element[eventName] != 'undefined') { 
element[eventName] = void 0; 

element.removeAttribute(eventName); 


element = null; 
return isSupported; 

return isEventSupported; 
})();


连HTML5与iPhone touch的一些专有事件也能检测到。

在jQuery1.4α2中也支持这种特性侦探了,不过用的是早期版本,不如上面写出来的那个!

//jQuery1.4α2 
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;  
};

标签:浏览器,事件,支持
0
投稿

猜你喜欢

  • Python使用django获取用户IP地址的方法

    2021-07-22 04:01:05
  • PHP children()函数讲解

    2023-06-13 04:38:38
  • python如何基于redis实现ip代理池

    2022-11-05 20:49:08
  • 使用python获取csv文本的某行或某列数据的实例

    2021-06-13 14:11:20
  • Windows11使用Cpython 编译文件报错 error: Unable to find vcvarsall.bat 完美解决方法

    2021-03-14 19:03:19
  • Python使用内置函数setattr设置对象的属性值

    2021-10-09 20:32:44
  • Oracle 数据库连接查询SQL语句

    2009-08-05 20:56:00
  • 浅谈Python中用datetime包进行对时间的一些操作

    2022-09-27 09:32:14
  • JavaScript+Canvas实现带跳动效果的粒子动画

    2024-04-23 09:08:06
  • Python实现计算圆周率π的值到任意位的方法示例

    2021-09-08 16:47:09
  • PHP控制反转(IOC)和依赖注入(DI)

    2024-05-11 10:09:31
  • Python实战之实现获取动态图表

    2023-10-31 14:03:34
  • python实现发送邮件功能代码

    2023-08-25 16:05:10
  • MySQL索引知识的一些小妙招总结

    2024-01-13 18:16:39
  • python中强大的format函数实例详解

    2022-02-19 18:47:10
  • ASP使用连接MYSQL数据库全攻略

    2007-09-23 09:06:00
  • asp伪静态情况下实现的utf-8文件缓存实现代码

    2011-02-24 10:49:00
  • Python eval()与exec()函数使用介绍

    2022-03-13 19:24:31
  • python opencv 找出图像中的最大轮廓并填充(生成mask)

    2021-01-14 23:42:10
  • python利用beautifulSoup实现爬虫

    2022-05-17 21:10:34
  • asp之家 网络编程 m.aspxhome.com