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

jQuery.support 的实现方式

jquery.support
jquery.support 用于检查浏览器对各项特性的支持。检查项多达 27 个。
     首先,让我们用一段代码测试一下 support 中包含的检查项:
<script src='jquery.js'></script> <script> support = $.support; for (key in support) { document.write('support.' + key + ' = ' + support[key] + '<br />'); } </script>
ie 下的输出结果为:
support.leadingwhitespace = false support.tbody = false support.htmlserialize = false support.style = false support.hrefnormalized = false support.opacity = false support.cssfloat = false support.checkon = true support.optselected = false support.getsetattribute = false support.submitbubbles = false support.changebubbles = false support.focusinbubbles = true support.deleteexpando = false support.nocloneevent = false support.inlineblockneedslayout = false support.shrinkwrapblocks = true support.reliablemarginright = true support.noclonechecked = false support.optdisabled = true support.radiovalue = false support.checkclone = undefined support.appendchecked = false support.boxmodel = false support.reliablehiddenoffsets = false support.ajax = true support.cors = false
firefox 中的显示结果为:
support.leadingwhitespace = true support.tbody = true support.htmlserialize = true support.style = true support.hrefnormalized = true support.opacity = true support.cssfloat = true support.checkon = true support.optselected = true support.getsetattribute = true support.submitbubbles = true support.changebubbles = true support.focusinbubbles = false support.deleteexpando = true support.nocloneevent = true support.inlineblockneedslayout = false support.shrinkwrapblocks = false support.reliablemarginright = true support.noclonechecked = true support.optdisabled = true support.radiovalue = true support.checkclone = undefined support.appendchecked = true support.boxmodel = true support.reliablehiddenoffsets = true support.ajax = true support.cors = true
需要注意的是,源代码中 checkclone 的检查是有问题的。这将在后面提到。
接下来,我们就对这些检查项进行逐一的分析。
leadingwhitespace
检查用 innerhtml 赋值时,是否会保留前面的空白符。
ie中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ var p = document.createelement( "p" ); p.innerhtml = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; var support = { leadingwhitespace: (p.firstchild.nodetype === 3) } return { support : support } }();
这段代码中,先创建了一个 p ,之后就用 innerhtml 为 p 赋值,
然后检查 p 的第一个子元素的 nodetype 是否为 3 (表示文本),
是的话则空白字符被保留,否则未被保留。
tbody
检查是否会自动为 table 插入 tbody ,会的话为 false ,不会则为 true 。
ie中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... var support = { leadingwhitespace: (p.firstchild.nodetype === 3), tbody: !p.getelementsbytagname("tbody").length } // other codes ... }();
这段代码在原有基础上为 support 增加了 tbody 属性, 并检查是否能够获取 tbody 标签。
由于 innerhtml 中已经包含了 table 标签,能获取 tbody 标签的话则表示会自动为 table 插入 tbody,否则表示不会自动插入 tbody 。
htmlserialize
检查link标签能否被正确地序列化。
ie中为 false , firefox 中为true 。
实现方式如下:
$ = function(){ // other codes ... var a = p.getelementsbytagname("a")[0]; var support = { // other codes ... tbody: !p.getelementsbytagname( "tbody" ).length, htmlserialize: !!p.getelementsbytagname("link").length } return { support : support } }();
这段代码在原有基础上为 support 增加了 htmlserialize 属性,并检查能否获取 link 标签。
由于 innerhtml 中已经包含了 link 标签,能通过getelementsbytagname 获取 link 标签的话,表示 link 可以被正确地序列化,否则表示 link 标签不能被正确地序列化。
style
检查是否能通过 “style” 属性获取 dom element 的样式。
ie中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... var a = p.getelementsbytagname("a")[0]; var support = { // other codes ... htmlserialize: !!p.getelementsbytagname("link").length, style: /top/.test(a.getattribute("style")) } return { support : support } }();
这段代码先是通过 getelementsbytagname("a") 获取表示链接的 dom element,
然后在原有基础上为 support 增加了 style 属性,并检查能否通过 getattribute("style") 获取样式。
hrefnormalized
检查链接的 “href” 属性能否被正常地序列化。
ie中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... style: /top/.test(a.getattribute("style")), hrefnormalized: (a.getattribute("href") === "/a") } return { support : support } }();
这段代码通过 getattribute("href") 来获取 “href” 属性的值,
能正确获取则表示链接的 “href”属性能够被正确地序列化。
opacity
检查 css 样式中的透明度设置能够被有效支持。
ie 中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... hrefnormalized: (a.getattribute("href") === "/a"), opacity: /^0.55$/.test(a.style.opacity) } return { support : support } }();
这段代码通过 a.style.opacity 来获取透明度设置,并用正则表达式 /^0.55$/ 进行检查,通过检查表示 css 样式中的透明度能够被有效地支持,否则表示不能。
cssfloat
检查 css 样式中的 float 属性能够被有效支持。
ie 中为 false , firefox中为 true 。
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... opacity: /^0.55$/.test(a.style.opacity), cssfloat: !!a.style.cssfloat } return { support : support } }();
这段代码通过 a.style.cssfloat 来获取 float 属性,并通过 !! 将属性转为 boolean 值(undefined 将被转为 false ,而其他值将被转为 true)。
checkon
检查 chebox 的 value 是否为 “on”。
ie 和 firefox 中都为true,而 chrome 中则为 false 。
实现方式如下:
$ = function(){ // other codes ... var a = p.getelementsbytagname("a")[0], input = p.getelementsbytagname("input")[0]; var support = { // other codes ... cssfloat: !!a.style.cssfloat, checkon: (input.value === "on") } return { support : support } }();
这段代码先通过 getelementsbytagname("input") 获取 checkbox,然后检查 checkbox 的 value 是否为 “on”。
optselected
检查 select 中的第一个 option 能否被默认选中。
ie 中为 false , firefox 中为 true 。
$ = function(){ // other codes ... var select = document.createelement("select"); var opt = select.appendchild(document.createelement("option")); var support = { // other codes ... checkon: (input.value === "on"), optselected: opt.selected } return { support : support } }();
这段代码先通过 createelement("select") 创建了一个 select,
然后将一个 “option” 添加到了 select 中。
接着在 support 中增加了属性 optselected,检查 opt.selected 是否为true 。
getsetattribute
检查能够功过 getattribute("calssname") 和 setattribute("classname", "...") 来获取和设置 p 的 css class。
实际上只检查 setattribute("classname", "...")。
ie 中为 false , firefox 中为 true 。
$ = function(){ // other codes ... p.setattribute("classname", "t"); var support = { // other codes ... optselected: opt.selected, getsetattribute: p.classname !== "t" } return { support : support } }();
这段代码通过 p.setattribute("classsname", "t") 将 p 的 css class 设置为 “t”,然后在 support 中增加 getsetattribute 属性, 检查 p 的 classname 是否为 “t”。
submitbubbles, changebubbles, focusinbubbles
检查 submit、change、focus 事件是否在“冒泡阶段”触发。实际上只针对 ie 进行检查。因为大多数浏览器(及ie9)使用 addeventlistener 附加事件,函数的第三个参数 usecapture (是否在“捕捉阶段”触发事件)既可以为 false ,也可以为 true 。
而 ie (ie9之前)使用 attachevent 函数附加事件,该函数无法指定在哪个阶段触发事件,一律都为“冒泡阶段”触发。
关于 bubble event 的更多内容,可以参考 iteye 里其他相关的文章:
http://www.iteye.com/search?query=bubble+event&type=blog
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... getsetattribute: p.classname !== "t", submitbubbles: true, changebubbles: true, focusinbubbles: false } if (p.attachevent) { for(var i in { submit: 1, change: 1, focusin: 1 }) { var eventname = "on" + i; var issupported = (eventname in p); if (!issupported) { p.setattribute(eventname, "return;"); issupported = ( typeof p[eventname] === "function" ); } support[i + "bubbles"] = issupported; } } return { support : support } }();
首先,在 support 中增加 submitbubbles, changebubbles, focusinbubbles,默认值分别为 true, true, false ,这是针对大多数浏览器的。
然后,针对ie (也就是存在 domelement.attachevent 函数的情况),检查 "onxxx" 事件是否存在,以及能否通过 setattribute(eventname, xxx)进行设置,可以的话就判断为“冒泡阶段”触发(即只要支持该事件,就判断为“冒泡阶段”触发)。
事实上,jquery 中的 focusin 事件是在 focus 的基础上进行模拟的,浏览器并不支持该事件,所以 focusinbubbles 总是为 false。
从源代码中的注释来看,似乎还考虑到了跨站脚本攻击:
short-circuiting here helps us to avoid an eval call (in setattribute) which can cause csp to go haywire.
大意是说在这里进行简短的检查(typeof p[eventname] === "function"),而不是直接用 eval 执行事件,可以避免不可控的跨站脚本攻击。(我不确定有没有翻译错)
deleteexpando
检查是否允许删除附加在 dom element 上的数据。
ie 中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... focusinbubbles: false, deleteexpando: true } // other codes ... try { delete p.test; } catch(e) { support.deleteexpando = false; } return { support : support } }();
首先在 support 中增加属性 deleteexpando ,默认值为 true 。
然后尝试删除 p.test ,发生错误则将 deleteexpando 设为 false 。
nocloneevent
检查复制 dom element 时是否会连同 event 一起复制,会则为 false , 不会则为true 。
ie 中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... deleteexpando: true, nocloneevent: true } // other codes ... if (!p.addeventlistener && p.attachevent && p.fireevent) { p.attachevent( "onclick", function click() { support.nocloneevent = false; p.detachevent( "onclick", click ); }); p.clonenode(true).fireevent("onclick"); } return { support : support } }();
首先在 support 中增加属性 nocloneevent , 默认值为 true 。
然后复制 p, 并触发其 “onclick” 事件,触发成功则为将 nocloneevent 设为 false。
从判断条件来看,依旧是针对 ie 的事件体系的检查。
inlineblockneedslayout, shrinkwrapblocks
都是针对 offsetwidth 的检查。
inlineblockneedslayout 表示将原本 display 为 block 的 dom element 设置为 disylay: inline 时,是否与 inline 形式的 dom elemnt 一致( offsetwidth 为 2 )。
ie 8 及之前的浏览器中为 true , firefox 中为 false 。
shrinkwrapblocks 表示内部 dom element 的样式是否会影响外部 dom element 的样式。
ie 6 中为 true , 多数浏览器中为 false 。
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... nocloneevent: true, inlineblockneedslayout: false, shrinkwrapblocks: false } // other codes ... if ( "zoom" in p.style ) { p.style.display = "inline"; p.style.zoom = 1; support.inlineblockneedslayout = ( p.offsetwidth === 2 ); p.style.display = ""; p.innerhtml = "<p style='width:4px;'></p>"; support.shrinkwrapblocks = ( p.offsetwidth !== 2 ); } return { support : support } }();
首先在 support 中增加这两个属性,然后将 p 的 css 样式中的 display 设为 inline ,并检查 offsetwidth ,以确定 inlineblockneedslayout 的值。
接着在 p 内部增加一个 p, 并将其宽度设为 4px ,并检查 offsetwith 的值,以确定外部的 p 是否会受到影响而收缩。
reliablemarginright
检查 margin right 的计算是否可靠。 各浏览器中都为 true 。
原注释中提到某些老版本的 webkit 内核的浏览器中为 false 。
实现方式如下:
$ = function(){ // other codes ... var support = { // other codes ... shrinkwrapblocks: false, reliablemarginright: true } // other codes ... if ( document.defaultview && document.defaultview.getcomputedstyle ) { var marginp = document.createelement( "p" ); marginp.style.width = "0"; marginp.style.marginright = "0"; p.appendchild( marginp ); support.reliablemarginright = ( parseint( document.defaultview.getcomputedstyle( marginp, null ).marginright, 10 ) || 0 ) === 0; } return { support : support } }();
简单地说,就是将 width 和 marginright 设为 0 时,获取的 marginrignt 应为 0 。
noclonechecked
检查复制 checkbox 时是否连选中状态也一同复制,若复制则为 false ,否则为 true 。
实现方式如下:
$ = function(){ // other codes ... input.checked = true; support.noclonechecked = input.clonenode(true).checked; return { support : support } }();
这段代码将 input 的选中状态设为 true ,然后复制 input ,并检查 checked 是否为 true 。
optdisabled
已经被设为 disable 的 select ,其内部的 option 的 disable 不应为 true 。
这个名称有一定的误导性,可能称为 “optnotdisabled” 更合适一些。
在各浏览器上的值都为 true 。
根据原注释,某些老版本的 webkit 内核的浏览器上,该值为 false 。
实现如下:
$ = function(){ // other codes ... select.disabled = true; support.optdisabled = !opt.disabled; return { support : support } }();
这段代码先将 select 的状态设为 disable , 然后检查其中的 option 的 disable 的值。
radiovalue
检查 input 元素被设为 radio 类型后是否仍然保持原来的值。
ie 中为 false , firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... input = document.createelement("input"); input.value = "t"; input.setattribute("type", "radio"); support.radiovalue = input.value === "t"; return { support : support } }();
这段代码先创建了 input 元素,将 value 设为 “t” ,然后将其类型设置为 “radio”,最后检查器 input 原来的值是否仍然保留。
checkclone
检查 fragment 中的 checkbox 的选中状态是否能被复制,ie 中为 false ,firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... p.innerhtml = ""; input.setattribute("checked", "checked"); p.appendchild( input ); fragment = document.createdocumentfragment(); fragment.appendchild( p.firstchild ); support.checkclone = fragment.clonenode(true).clonenode(true).lastchild.checked; return { support : support } }();
这段代码创建了一个 fragment ,并将一个处于选中状态的 checkbox 加入,连续复制两遍后检查 checkbox 是否为选中状态。(这里源代码中的实现似乎有问题,没有将 p 的 innerhtml 清空,导致 p 的 firstchild 并非 checkbox,使得 checkclone 在各浏览器中的值均为 undefined 。)
appendchecked
检查被添加到 dom 中的 checkbox 是否仍然保留原来的选中状态。
ie 中为 false ,firefox 中为 true 。
实现方式如下:
$ = function(){ // other codes ... support.appendchecked = input.checked; return { support : support } }();
实际上只是简单地检查之前添加到 fragment 中的 checkbox 的选中状态。
boxmodel
检查页面渲染是否符合 w3c box model 。
在 ie 中没有 doctype 声明时为 false ,其余情况为 true 。
实现方式如下:
$ = function(){ // other codes ... p.innerhtml = ""; p.style.width = p.style.paddingleft = "1px"; body = document.createelement( "body" ); bodystyle = { visibility: "hidden", width: 0, height: 0, border: 0, margin: 0, background: "none" }; for (var i in bodystyle ) { body.style[i] = bodystyle[i]; } body.appendchild(p); document.documentelement.appendchild(body); support.boxmodel = p.offsetwidth === 2; body.innerhtml = ""; document.documentelement.removechild( body ); return { support : support } }();
将 p 的 width 和 paddingleft 设为 1px ,然后将它添加到 body 中,检查 p 的 offsetwidth 是否为 2 。
reliablehiddenoffsets
检查 hidden 状态下的 offsetwidth 和 offsetheight 是否正确。
ie 中为 false , firefox 中为 true 。
实现方式如下(插入到清空 body.innerhtml 之前):
$ = function(){ // other codes ... p.innerhtml = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>"; var tds = p.getelementsbytagname("td"); var issupported = (tds[0].offsetheight === 0); tds[0].style.display = ""; tds[1].style.display = "none"; support.reliablehiddenoffsets = issupported && (tds[0].offsetheight === 0); body.innerhtml = ""; document.documentelement.removechild( body ); return { support : support } }();
检查将一个 td 隐藏时, 相邻的 td 的 offsetheight 是否为 0 。
ajax, cors
检查是否支持 ajax 请求,以及是否支持跨域 ajax。
ie 与 firefox 中 ajax 均为 true ,ie 中 cors 为 false , firefox 中 cros 为 false 。
实现方式如下:
$ = function(){ // other codes ... var xhr = window.activexobject ? !this.islocal && createstandardxhr() || createactivexhr() : createstandardxhr(); support.ajax = !!xhr; support.cors = !!xhr && ( "withcredentials" in xhr ) function createstandardxhr() { try { return new window.xmlhttprequest(); } catch( e ) {} } function createactivexhr() { try { return new window.activexobject("microsoft.xmlhttp"); } catch( e ) {} } return { support : support } }();
尝试创建 ajax 对象,创建成功,则 ajax 为 true ;如果 ajax 对象中包含了 withcredentials 属性,则表示支持跨域 ajax。
以上就是jquery.support 的实现方式的详细内容。
其它类似信息

推荐信息