jQuery.support
jQuery.support는 브라우저의 다양한 기능 지원을 확인하는 데 사용됩니다. 체크항목은 최대 27개 입니다.
먼저 코드를 사용하여 지원에 포함된 확인 항목을 테스트해 보겠습니다.
<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
tbody가 테이블에 자동으로 삽입되는지 확인하세요. 그렇지 않으면 false입니다.
IE에서는 false이고 FireFox에서는 true입니다.
구현 방법은 다음과 같습니다.
$ = function(){ // Other codes ... var support = { leadingWhitespace: (p.firstChild.nodeType === 3), tbody: !p.getElementsByTagName("tbody").length } // Other codes ... }();
이 코드는 기본적으로 지원하기 위해 tbody 속성을 추가하고, tbody 태그를 얻을 수 있는지 확인하는 코드입니다.
innerHTML에는 이미 테이블 태그가 포함되어 있으므로 tbody 태그를 얻을 수 있으면 tbody가 테이블에 자동으로 삽입된다는 의미이고, 그렇지 않으면 tbody가 자동으로 삽입되지 않는다는 의미입니다.
htmlSerialize
링크 태그가 올바르게 직렬화될 수 있는지 확인하세요.
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 } }();
이 코드는 기본적으로 지원하기 위해 htmlSerialize 속성을 추가하고, 링크 태그를 얻을 수 있는지 확인하는 코드입니다.
innerHTML에는 이미 링크 태그가 포함되어 있으므로 getElementsByTagName을 통해 링크 태그를 얻을 수 있으면 링크가 올바르게 직렬화될 수 있다는 의미이고, 그렇지 않으면 링크 태그가 올바르게 직렬화될 수 없다는 의미입니다.
style
"style" 속성을 통해 DOM 요소의 스타일을 얻을 수 있는지 확인하세요.
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를 획득하고,
원본 기반으로 지원할 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 } }();
이 코드는 "href" 속성 값을 얻기 위해 getAttribute("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 구현 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!