检测浏览器对事件的支持程度
来源: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;
};


猜你喜欢
- 来自 Nine Javascript Gotchas , 以下是JavaScript容易犯错的九个陷阱。虽然不是什么很高深的技术问题,但注意
- 一、HandlerSocket是什么?HandlerSocket是akira higuchi写的一个MySQL的插件。以MySQL Daem
- 问题tensor详细数值 不能直接print打印:import tensorflow as tfx = tf.constant(1)prin
- fsockopen函数能够运用,首先要开启php.ini中的allow_url_open=on;fsockopen是对socket客户端代码
- 想要一个这玩意,可是找了网上许多着色器,要么是兼容性成问题,要么是匹配不精确,比如说:1、注释里包含字符串、关键词,类似于:/* xxxx&
- 一、在访客的内心深处做导航我讨厌迷失,不管是在道路上或是在线网络上。猜想一下?您的访客也是这样的。就像我们期望看到的道路上的路标一样,来帮助
- ASP是Web上的客户机/服务器结构的中间层,虽然它使用脚本语言(Java Script,VB Script等)编写,程序代码在服务器上运行
- 一,概要需求: 实现一个GUI界面下的 6+1体育彩票选号器.(1) 要求界面可以加载系统时间及开奖时间(2)功能区完成人选及机选的功能 人
- Python虚拟机注:本篇是根据教程学习记录的笔记,部分内容与教程是相同的,因为转载需要填链接,但是没有,所以填的原创,如果侵权会直接删除。
- '$.browser.msie' 为空或不是对象,这个是jQuery错误出现这个错误,是因为升级了jQuery版本,从1.9
- 前言题目如下:给定一个仅包含大小写字母和空格 ’ ’ 的字符串 s,返回其最后一个单词的长度。如果字
- 1.下载egit插件打开Eclipse,git需要eclipse授权,通过网页是无法下载egit的安装包的。在菜单栏依次打开eclipse→
- 本文介绍了PyTorch上搭建简单神经网络实现回归和分类的示例,分享给大家,具体如下:一、PyTorch入门1. 安装方法登录PyTorch
- 本文实例为大家分享了python版百度语音识别功能的具体代码,供大家参考,具体内容如下环境:使用的IDE是Pycharm1.新建工程2.配置
- 近期线上出现一个bug,研发的小伙伴把测试环境的地址写死到代码中,在上线前忘记修改,导致线上发布的代码中使用了测试环境地址。开发过程中虽然有
- 常用的转换函数是 cast 和 convert,用于把表达式得出的值的类型转换成另一个数据类型,如果转换失败,该函数抛出错误,导致整个事务回
- 方法1:import sysprint(sys.argv)得到文件当前绝对路径字符串的一个列表['D:/pycharm/Practi
- 前言单例模式(Singleton Pattern),是一种软件设计模式,是类只能实例化一个对象,目的是便于外界的访问,节约系统资源,如果希望
- 前言: 时间戳字段在MySQL中经常使用到,比如需要记录一行数据创建的时间或修改的时间时,我们通常会使用时间戳即timestamp字段。本篇
- setup语法糖 最大好处就是所有声明部分皆可直接使用,无需return出去注意:部分功能还不完善,如:name、render还需