通过jQuery.support看javascript中的兼容性问题

  我们知道,jQuery.support是jQuery中检测兼容性问题的最重要方法。注意,这里仅仅是检测,其具体的解决兼容性方法是利用其“钩子机制”实现。

  首先来看源码,一窥究竟。

  引用源码:jQuery.1.10.2

jQuery.support = (function( support ) {

    var all, a, input, select, fragment, opt, eventName, isSupported, i,
        div = document.createElement("div");

    // Setup
    div.setAttribute( "className", "t" );
    div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";

    // Finish early in limited (non-browser) environments
    all = div.getElementsByTagName("*") || [];
    a = div.getElementsByTagName("a")[ 0 ];
    if ( !a || !a.style || !all.length ) {
        return support;
    }

    // First batch of tests
    select = document.createElement("select");
    opt = select.appendChild( document.createElement("option") );
    input = div.getElementsByTagName("input")[ 0 ];

    a.style.cssText = "top:1px;float:left;opacity:.5";

    // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
    support.getSetAttribute = div.className !== "t";

    // IE strips leading whitespace when .innerHTML is used
    support.leadingWhitespace = div.firstChild.nodeType === 3;

    // Make sure that tbody elements aren't automatically inserted
    // IE will insert them into empty tables
    support.tbody = !div.getElementsByTagName("tbody").length;

    // Make sure that link elements get serialized correctly by innerHTML
    // This requires a wrapper element in IE
    support.htmlSerialize = !!div.getElementsByTagName("link").length;

    // Get the style information from getAttribute
    // (IE uses .cssText instead)
    support.style = /top/.test( a.getAttribute("style") );

    // Make sure that URLs aren't manipulated
    // (IE normalizes it by default)
    support.hrefNormalized = a.getAttribute("href") === "/a";

    // Make sure that element opacity exists
    // (IE uses filter instead)
    // Use a regex to work around a WebKit issue. See #5145
    support.opacity = /^0.5/.test( a.style.opacity );

    // Verify style float existence
    // (IE uses styleFloat instead of cssFloat)
    support.cssFloat = !!a.style.cssFloat;

    // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
    support.checkOn = !!input.value;

    // Make sure that a selected-by-default option has a working selected property.
    // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
    support.optSelected = opt.selected;

    // Tests for enctype support on a form (#6743)
    support.enctype = !!document.createElement("form").enctype;

    // Makes sure cloning an html5 element does not cause problems
    // Where outerHTML is undefined, this still works
    support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>";

    // Will be defined later
    support.inlineBlockNeedsLayout = false;
    support.shrinkWrapBlocks = false;
    support.pixelPosition = false;
    support.deleteExpando = true;
    support.noCloneEvent = true;
    support.reliableMarginRight = true;
    support.boxSizingReliable = true;

    // Make sure checked status is properly cloned
    input.checked = true;
    support.noCloneChecked = input.cloneNode( true ).checked;

    // Make sure that the options inside disabled selects aren't marked as disabled
    // (WebKit marks them as disabled)
    select.disabled = true;
    support.optDisabled = !opt.disabled;

    // Support: IE<9
    try {
        delete div.test;
    } catch( e ) {
        support.deleteExpando = false;
    }

    // Check if we can trust getAttribute("value")
    input = document.createElement("input");
    input.setAttribute( "value", "" );
    support.input = input.getAttribute( "value" ) === "";

    // Check if an input maintains its value after becoming a radio
    input.value = "t";
    input.setAttribute( "type", "radio" );
    support.radioValue = input.value === "t";

    // #11217 - WebKit loses check when the name is after the checked attribute
    input.setAttribute( "checked", "t" );
    input.setAttribute( "name", "t" );

    fragment = document.createDocumentFragment();
    fragment.appendChild( input );

    // Check if a disconnected checkbox will retain its checked
    // value of true after appended to the DOM (IE6/7)
    support.appendChecked = input.checked;

    // WebKit doesn't clone checked state correctly in fragments
    support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;

    // Support: IE<9
    // Opera does not clone events (and typeof div.attachEvent === undefined).
    // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
    if ( div.attachEvent ) {
        div.attachEvent( "onclick", function() {
            support.noCloneEvent = false;
        });

        div.cloneNode( true ).click();
    }

    // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
    // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
    for ( i in { submit: true, change: true, focusin: true }) {
        div.setAttribute( eventName = "on" + i, "t" );

        support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
    }

    div.style.backgroundClip = "content-box";
    div.cloneNode( true ).style.backgroundClip = "";
    support.clearCloneStyle = div.style.backgroundClip === "content-box";

    // Support: IE<9
    // Iteration over object's inherited properties before its own.
    for ( i in jQuery( support ) ) {
        break;
    }
    support.ownLast = i !== "0";

    // Run tests that need a body at doc ready
    jQuery(function() {
        var container, marginDiv, tds,
            divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
            body = document.getElementsByTagName("body")[0];

        if ( !body ) {
            // Return for frameset docs that don't have a body
            return;
        }

        container = document.createElement("div");
        container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";

        body.appendChild( container ).appendChild( div );

        // Support: IE8
        // Check if table cells still have offsetWidth/Height when they are set
        // to display:none and there are still other visible table cells in a
        // table row; if so, offsetWidth/Height are not reliable for use when
        // determining if an element has been hidden directly using
        // display:none (it is still safe to use offsets if a parent element is
        // hidden; don safety goggles and see bug #4512 for more information).
        div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
        tds = div.getElementsByTagName("td");
        tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
        isSupported = ( tds[ 0 ].offsetHeight === 0 );

        tds[ 0 ].style.display = "";
        tds[ 1 ].style.display = "none";

        // Support: IE8
        // Check if empty table cells still have offsetWidth/Height
        support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );

        // Check box-sizing and margin behavior.
        div.innerHTML = "";
        div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";

        // Workaround failing boxSizing test due to offsetWidth returning wrong value
        // with some non-1 values of body zoom, ticket #13543
        jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {
            support.boxSizing = div.offsetWidth === 4;
        });

        // Use window.getComputedStyle because jsdom on node.js will break without it.
        if ( window.getComputedStyle ) {
            support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
            support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";

            // Check if div with explicit width and no margin-right incorrectly
            // gets computed margin-right based on width of container. (#3333)
            // Fails in WebKit before Feb 2011 nightlies
            // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
            marginDiv = div.appendChild( document.createElement("div") );
            marginDiv.style.cssText = div.style.cssText = divReset;
            marginDiv.style.marginRight = marginDiv.style.width = "0";
            div.style.width = "1px";

            support.reliableMarginRight =
                !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
        }

        if ( typeof div.style.zoom !== core_strundefined ) {
            // Support: IE<8
            // Check if natively block-level elements act like inline-block
            // elements when setting their display to 'inline' and giving
            // them layout
            div.innerHTML = "";
            div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
            support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );

            // Support: IE6
            // Check if elements with layout shrink-wrap their children
            div.style.display = "block";
            div.innerHTML = "<div></div>";
            div.firstChild.style.width = "5px";
            support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );

            if ( support.inlineBlockNeedsLayout ) {
                // Prevent IE 6 from affecting layout for positioned elements #11048
                // Prevent IE from shrinking the body in IE 7 mode #12869
                // Support: IE<8
                body.style.zoom = 1;
            }
        }

        body.removeChild( container );

        // Null elements to avoid leaks in IE
        container = div = tds = marginDiv = null;
    });

    // Null elements to avoid leaks in IE
    all = select = fragment = opt = a = input = null;

    return support;
})({});

这是一个闭包自治性函数,返回的是一个support函数。我们把其中的兼容性问题一一列出来。

通过console.log把support打印出来

1,ajax,判断浏览器是否支持XMLHttpRequest对象

这个代码可不是在suppport闭包里。

8648行:xhrSupported = jQuery.ajaxSettings.xhr();

8650行:xhrSupported = jQuery.support.ajax = !!xhrSupported;

2,appendChecked, 检查被添加到 DOM 中的 checkbox 是否仍然保留原来的选中状态。 ie6/7为false

3,boxSizing,检测是否支持box-sizing

4,boxSizingReliable,检测盒子模型是否可靠

5,changeBubbles,检测是否支持changeBubbles事件

6,checkClone,检测选中的元素状态能否被赋值

7,checkOn,检测checkbox值是否为on

8,clearCloneStyle,检测元素的backgroundClip是否被清除

9,cors,检测是否是跨域

7768行:jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );

10,cssFloat,检查 css 样式中的 float 属性是否存在

11,deleteExpando,检查是否允许删除附加在 DOM Element 上的数据。 

12,enctype,检查创建form的enctype属性是否存在

13,focusinBubbles,检测是否支持focusinBubbles事件

14,getSetAttribute,检查是否可以设置 div 的 css class

15,hrefNormalized,检查链接的 “href” 属性能否被正常地序列化。 

16,html5Clone,验证是否支持html5节点复制

17,htmlSerialize,验证innerHTML插入链接元素是否可被序列化
18,inlineBlockNeedsLayout, 检测块元素在display:inline并拥有layout属性,是否会按inline-block显示
19,input,验证input元素value值
20,leadingWhitespace,检查用 innerHTML 赋值时,是否会保留前面的空白符
21,noCloneChecked, 检查复制 checkbox 时是否连选中状态也一同复制
22,noCloneEvent,检查复制 DOM Element 时是否会连同 event 一起复制
23,opacity, 检查 css 样式中的透明度设置能够被有效支持。
24,optDisabled,获取下拉列表子元素的disabled是否为true
25,optSelected,验证创建的select元素的第一个option元素是否会默认选中
26,ownLast,
27,pixelPosition,检测图层定位(像素位置)是否有误
28,radioValue,检查 input 元素被设为 radio 类型后是否仍然保持原来的值。 
29,reliableHiddenOffsets, 检查 hidden 状态下的  offsetWidth 和 offsetHeight 是否正确。 
30,reliableMarginRight,检查 Margin Right 的计算是否可靠
31,shrinkWrapBlocks,表示内部 DOM Element 的样式是否会影响外部 DOM Element 的样式。    IE 6 中为 true , 多数浏览器中为 false 。
32,style,检查是否能通过 “style” 属性获取 DOM Element 的样式。 
33,submitBubbles,检查是否支持submitBubbles事件
34,tbody ,检查是否会自动为 table 插入 tbody 
 
以上把jQuery中所有的support属性全部列出来了,具体的使用要针对具体的工作。
posted @ 2015-05-05 15:35  sinbad121  阅读(1831)  评论(1编辑  收藏  举报