您好,欢迎访问一九零五行业门户网

jQuery 源码分析笔记(5) jQuery.support_jquery

其中jquery.browser已经提供了根据useragent检测的浏览器信息。而jquery.support 使用特性检测来检查浏览器的功能以及bug。
和文档一样,首先说明一下,这个模块是很底层的代码,基本不需要在日常开发中使用,但是插件的开发者更需要。因为插件需要兼容各个浏览器。首先看一下 support模块提供了哪些浏览器特性的检测,以下结果是在chrome 13 dev下看到的结果。根据浏览器的不同,这里的成员可能会有变化。(ps:再次吐槽ie,大部分属性都是ie比较特别)
ajax: true。是否支持xmlhttprequest对象。老版本的ie不支持,必须用activex。 * appendchecked: true。 * boxmodel: true。是否根据w3c css盒模式渲染。ie6和7的quirks模式为false。 * changebubbles: true。change事件是否沿着dom树冒泡。这是w3c dom事件模型的要求,但是ie目前为止是false。jquery模拟了这个冒泡特性。 * checkclone: undefined。在克隆radio button或者checkbox时是否保留选中状态。以前说createfragment缓存的时候提到过,webkit内核是不保留的。 * checkon: false。checkbox在没有指定时是否默认为on。 * cors: true。xmlhttprequest对象是否带有withcredentials属性。可以执行跨域请求。或者没有这个属性,但是有其他途径可以实现跨域xhr请求的,也是true(比如通过windows gadget)。 * cssfloat: true。支持cssfloat的css属性。ie是false,它使用了stylefloat。 * deleteexpando: true。 * focusinbubbles: false。 * getsetattribute: true。 * hrefnormalized: true。对一个a元素调用getattribute(href)时,是否返回原始指定的url。ie会返回完整路径。比如对于href=1.html的链接,ie会得到http://..../1.html。 * htmlserialize: true。是否可以用innerhtml插入link元素。ie为false。 * inlineblockneedslayout: false。为了让block元素表现inline-block,是否需要为inline并且haslayout(ie下的概念,大部分布局问题的根源)。ie8以下有问题。 * leadingwhitespace: true。innerhtml属性是否严格按照代码渲染。ie6-8中会去掉前置的空白。(所以使用markdown写的这篇文章在ie下有格式问题,因为换行不见了) * noclonechecked: true。1.5.1新属性。检测浏览器是否克隆checked扩展属性。ie为false。 * nocloneevent: true。拷贝的元素是否会带有事件处理函数(即event handler是否被拷贝过去)。ie为false。 * opacity: true。是否支持opacity css属性(透明度)。ie为false,它使用alpha filter。 * optdisabled: true。已经disabled的select元素中的option元素是否默认为disabled。 * optselected: true。一个默认被选中的option元素的selected属性是否正常。 * radiovalue: true。 * reliablehiddenoffsets: true。在table的cells被设置为display:none的时候,仍然有offsetwidth/height。即hidden靠不住。只有ie8有这个问题。参见4512号bug * reliablemarginright: true。div有显式的宽度,但是没有margin-right。此时基于容器计算margin-right不正确。旧版本webkit有问题。参见3333号bug * scripteval(): 1.5.1版本前,这是一个属性,而现在变成函数了。检测一个inline的脚本在使用标准的dom操作函数被添加时是否会自动执行。比如appendchild和createtextnode。ie是false,它使用text来插入脚本。 * shrinkwrapblocks: false。元素在haslayout的情况下是否会撑大父节点。只有ie6是true。 * style: true。一个元素的inline的style属性是否可以用dom属性访问。比如getattribute(style)。ie是false,它使用csstext属性。 * submitbubbles: true。submit事件是否沿着dom树冒泡。ie为false,jquery模拟了这个冒泡过程。 * tbody: true。一个空的table元素是否可以没有tbody元素。根据html规范,子元素是可选的。但是ie是false,所以会自动插入一个tbody元素。
jquery创建了几个元素用来判断浏览器特性。如下:
复制代码 代码如下:
var div = document.createelement(div);
div.setattribute(classname, t);
div.innerhtml =
a;
all = div.getelementsbytagname(*);
a = div.getelementsbytagname(a)[0];
var select = document.createelement(select);
opt = select.appendchild(document.createelement(option));
input = div.getelementsbytagname(input)[0];
其中div元素相当有内涵。包括了空白开头,空table元素,inline style,opacity等等。除了一行行看代码和注释也没啥其他笔记了:
复制代码 代码如下:
support = {
// ie会把开头的空格去掉,所以nodetype不是3(文本)
leadingwhitespace: (div.firstchild.nodetype === 3),
// ie会自动插入tbody,所以length不同
tbody: !div.getelementsbyname(tbody).length,
// ie不允许用这种方式插入link元素
htmlserialize: !!div.getelementsbytagname(link).length,
// 如果正常获得style的话,这个正则表达式应该会正常通过
style: /top/.test(a.getattribute(style)),
// href属性应该是原始指定的字符串,ie会修改为http开头的绝对url
hrefnormalized: (a.getattribute(href) === /a),
// 能得到opacity属性。这里使用了正则表达式,是为了绕过webkit[5145号bug](http://dev.jquery.com/ticket/5145)
// 但是这应该是一个早期版本的问题。起码在chrome 13中,不用正则也是对的。
opacity: /^0.55$/.test(a.style.opacity),
// ie使用stylefloat
cssfloat: !!a.style.cssfloat,
// div中的checkbox没有指定值,看默认值是否是on。webkit是。所以我的结果是false
checkon: (input.value === on),
// 这个select只有一个option元素,所以渲染时,这个option是默认选中的。此时selected应该是true。
optselected: opt.selected,
submitbubbles: true,
changebubbles: true,
focusinbubbles: false,
deleteexpando: true,
nocloneevent: true,
inlineblockneedslayout: false,
shrinkwrapblocks: false,
reliablemarginright: true
};
下面的大部分都是按部就班的测试。其中boxmodel的测试比较有趣:
复制代码 代码如下:
div.innerhtml = ; // 从头来
div.style.width = div.style.paddingleft = 1px;
body = document.createelement(body);
body.style.width = 0;
body.style.height = 0;
body.style.border = 0;
body.style.margin = 0; // 全部设置为0
body.appendchild(div);
document.documentelement.insertbefore(body, document.documentelement.firstchild);
support.boxmodel = div.offsetwidth === 2;
// 这个时候div嵌套在body下。而body长宽高,边框和margin都是0。所以div的偏移应该就是它自己的paddingleft+width。如果不对,就说明盒模式不对。
然后值得注意的是事件的冒泡,注释中提到的技术参考文章链接已经失效。请自己搜索detecting event support without browser sniffing
复制代码 代码如下:
// attachevent是ie的,所以这里实际上只检查了ie,其他浏览器都是前面设置的默认值。
if(div.attachevent) {
for(i = {
submit: 1,
change: 1
focusin: 1
}) {
eventname = on + i;
issupported = (eventname in div);
if(!issupported) {
div.setattribute(eventname, return;);
issupported = (typeof div[eventname] === function);
}
support[i + bubbles] = issupported;
}
}
ps: 浏览器检测是一个很纠结,很细节的任务。这个笔记慢慢完善中……
18:30补充:经过ie9的测试,以上大部分ie相关问题都已经不存在。以下是ie9+win7的测试结果:
复制代码 代码如下:
$.support
{
boxmodel: true,
changebubbles: true,
checkclone: true,
checkon: true,
cssfloat: true,
deleteexpando: true,
hrefnormalized: true,
htmlserialize: true,
leadingwhitespace: true,
nocloneevent: false,
opacity: true,
optselected: false,
parentnode: true,
scripteval: true,
style: true,
submitbubbles: true,
tbody: true
}
其它类似信息

推荐信息