jQuery瀏覽器相容模組support詳解

NONO發表於2016-07-30

jQuery的屬性support是判斷瀏覽器之間是否相容模組 ,該模組包含了leadingWhitespace,tbody,htmlSerialize,style,hrefNormalized,opacity,cssFloat,checkOn,optSelected,getSetAttribute….等相容問題,所有的這些屬性也只是jQuery內部會用到,因為jQ內部一些模組需要對這些東西進行判斷, 就直接寫成了一個support模組, 可以供我們, 但是我們寫程式碼的時基本都沒用到啊, 今天再把這些玩意兒過一下, 測試的瀏覽器為FF,CHROME,IE11, IE6-IE10是用IE11模擬的:

$.support.leadingWhitespace  ———— IE中自動去空格

$.support.checkOn   —-chrome中radio預設值為checkOn

$.support.tbody  —-IE通過innerHTML自動生成tbody

$.support.htmlSerialize —–  標準瀏覽器會自動生成link標籤

$.support.style  —-IE67中getAttriute會獲取各種型別的資料….

$.support.opacity  —- IE678不支援opacity

$.support.cssFloat   —-cssFloat標準瀏覽器支援的,IE要用styleFloat

$.support.optSelected  —–瀏覽器並不會設定預設的option

$.support.getSetAttribute  —-getSetAttribute在瀏覽器之間的相容

$.support.html5Clone   —- 複製標籤的問題

$.support.boxModel  —- 是否支援盒模型

$.support.submitBubbles  —-冒泡

$.support.changeBubbles  —-冒泡

$.support.focusinBubbles  —-冒泡

$.support.deleteExpando   —–IE的DOM元素是COM元件, 不能delete元件的屬性

$.support.noCloneEvent   —-複製元素的事件

$.support.reliableHiddenOffsets   —-table元素中tr內td的問題;

$.support.boxSizing  —是否支援boxSizing

$.support.doesNotIncludeMarginInBodyOffset  —-body不會包含margin的問題(算不算問題呢?)

$.support.pixelPosition   —-獲取樣式返回的是否是畫素值

$.support.boxSizingReliable  —-boxSizing是否可用

$.support.reliableMarginRight    —-chrome中margin的bug

$.support.inlineBlockNeedsLayout    —-IE中layout的問題

$.support.shrinkWrapBlocks    —-IE6中自動擴大寬高的問題

$.support.leadingWhitespace屬性

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>
        IE678中自動過濾了元素前後的空格,
        而且空格不包含在childNodes裡面,
        <script type="text/javascript">
            var el = document.createElement("div");
            el.innerHTML = "  <div id=\"null\"> </div> ";
            l(el.childNodes.length);
        </script>
    </body>
</html>
標準瀏覽器中是遵守使用者輸入, el應該包含三個節點 :["", "<div id=\"null\"> </div>", ""]節點;

IE678中卻只有1個節點, 這個節點就是那個DIV:

$.support.checkOn屬性

標準瀏覽器中的checkbox預設value為”on”,IE5678也都是”on”, 但是在某些webkit中checkbox的值預設為”"字串,現在的瀏覽器版本都很高了, 基本沒有這個問題, 如果你有chrome低版本的話可以用下面這個demo測試看看有沒有問題:

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>
        <input id="ck" type='checkbox'/>
        <script type="text/javascript">
            var el = document.getElementById("ck");
            //標準瀏覽器有change事件;
            el.onchange = function() {
                l(el.value);
                l(ck.checked)
            }
            //IE中的萬能事件propertychange;
            el.onpropertychange = function() {
                l(el.value);
                l(ck.checked)
            }
            l(el.value);
        </script>
    </body>
</html>

$.support.tbody屬性

在IE6和IE7中新建table會自動建立tbody元素;

如果我們為建立的table新增tr或者新增td, 那麼所有的瀏覽器都會自動建立tbody;

如果是動態建立的table和tr,把tr新增到tbody中,那麼tbod根本不會出來, 所有瀏覽器都遵循開發者的操作(瀏覽器的心思真的不好猜測啊)

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>
        <div id="tb"></div>
        <div id="tb2"></div>
        <div id="tb3"></div>
        <script type="text/javascript">
            var el = document.getElementById("tb");
            el.innerHTML = "<table></table>"
            //IE67中會輸出1, 標準瀏覽器遵循使用者輸入,不會是自動生成tbody,所以tobdy的length是0
            l(el.getElementsByTagName("tbody").length);
        </script>
        <script>
            var el = document.getElementById("tb2");
            el.innerHTML="<table><tr>111</tr></table>";
            //無論是標準還是IE67都會自動生成tbody標籤
            l(el.getElementsByTagName("tbody").length);
        </script>
        <script>
            var el = document.getElementById("tb3");
            el.innerHTML="<table><td>111</td></table>";
            //無論是標準還是IE67都會自動生成tbody標籤
            l(el.getElementsByTagName("tbody").length);
        </script>
        <script>
            var tb = document.createElement("table");
            var tr = document.createElement("tr");
            tr.innerHTML = "trtrtr";
            tb.appendChild(tr);
            document.getElementsByTagName("body")[0].appendChild(tb);
        </script>
    </body>
</html>

程式碼執行完畢以後你會看到, 當table裡沒有元素的時候, chrome沒有自動產生tbody, 如果你不按照正常的寫法寫table, 而是這樣

"<table><tr>111</tr></table>";

產生的HTML變成這樣”111<table><tr></tr></table>“,  在jQ中你這樣寫$(“<table><tr>111</tr></table>”), 生成的HTML也是這樣的["111","<table><tr></tr></table>"],所以再三強調寫html標籤的巢狀要符合標準….

IE中又是例外一回事,通過innerHTML的方式會自動新增tbody, 而且你標籤巢狀錯了他也不管你,通過appendChild的方式跟其他瀏覽器一樣不會主動生成tbody;

$.support.htmlSerialize

IE678瀏覽器中不能夠通過innerHTML動態生成link標籤, 要通過新建標籤的形式建立:

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>
        <div class="bounce animated infinite">
            bounce
        </div>
        <div id="link"></div>
        <script type="text/javascript">
            var eLink = document.getElementById("link");
            eLink.innerHTML = '<link href="http://cdn.bootcss.com/animate.css/3.3.0/animate.css" rel="stylesheet">';
        </script>
    </body>
</html>

雖然link標籤多數都可以通過innerHTML生成, 但是我們要通過innerHTML生成script標籤是不可行的:

//這樣的寫法在瀏覽器中根本不生效;
document.body.innerHTML = "<script src='1.js'></script>"

//但是我們可以通過jQuery的方式生成並插入到DOM數種
$("<script src='1.js'></script>").appendTo(document.body)

$.support.style

標準瀏覽器通過getAttribute獲取都應該是字串的,IE67你getAttriute是各種奇葩,你獲取的style是一整個樣式物件, IE67要獲取行內樣式要用  eDiv.style.cssText  才行哦

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>
        <div id="div" style="background:#f00;" onclick="fn">
            divide
        </div>
        <div id="link"></div>
        <script type="text/javascript">
            var fn = function() {
                alert(1);
            };
            var eDiv = document.getElementById("div");
            //標準瀏覽器要麼返回的是background:#f00,要麼返回background: rgb(255, 0, 0);
            //IE6,IE7返回了所有的style屬性
            l(eDiv.getAttribute("style"));
            l(typeof eDiv.getAttribute("onclick"));
        </script>
    </body>
</html>

IE67中獲取style返回的是下面圖片, 這個應該是eDiv的元素屬性才對, 意思就是說IE67中DOM屬性節點屬性傻傻分不清楚, 比如onclick返回的是function….(等等,我想靜靜….):

獲取一個html頁面的相對路徑可以通過動態建立一個錨連結,然後獲取這個錨連線的href就可以獲取到絕對的路徑, 瀏覽器獲取script標籤的src方式要根據瀏覽器的特性,一般來說是這樣的:

document.querySelector ? node.src : node.getAttribute(“src”,4);

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>
        <a id="a" href="./xx.html"></a>
        <script id="js" src="xx.js"></script>
        <div id="link"></div>
        <script type="text/javascript">
            var fn = function() {
                alert(1);
            };
            //反正你通過屬性的方式獲取a錨連線的href都是絕對路徑,getAttribute都是開發者輸入的字串,
            var eA = document.getElementById("a");
            l(eA.getAttribute("href",3));
            l(eA.href);

            var js = document.getElementById("js");
            //IE8以後和標準瀏覽器獲取絕對的src直接通過src,IE67通過src獲取絕對路徑, 這個技巧在獲取script標籤的src時候會用到;
            l(js.getAttribute("src",4));
            l(js.src);
        </script>
    </body>
</html>

$.support.opacity

opacity這個玩意兒到了IE9才支援, IE678只能用濾鏡:filter:opacity(alpha=10);

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>
        <div style="position: absolute;">
            1111
        </div>

        <div style="opacity:0.2;float:left">
            對對對
        </div>
        <script type="text/javascript">
            l("haha");
        </script>
    </body>
</html>

$.support.cssFloat

這個玩意兒標準瀏覽器是cssFloat, IE中要用styleFloat,比如:

element.style.cssFloat;
element.style.styleFloat;

$.support.optSelected

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>

        <script type="text/javascript">
        select = document.createElement("select");
        var opt;
        //建立optino元素的方法1:
        //opt = document.createElement("option");
        //opt.setAttribute("value","value");
        //opt.setAttribute("name","name");
        //(opt.textContent  = "text")|| (opt.innerText = "text");

        //建立optino元素的方法2:
        //這樣也可以;
        //opt = document.createElement("option");
        //opt.value = "value";
        //opt.text = "text";
        //這樣也行;

        //建立optino元素的方法3:
        opt = new Option("text","value");

        select.appendChild( opt );
        document.getElementsByTagName("body")[0].appendChild(select);
        l( opt.selected );
        </script>
    </body>
</html>

$.support.getSetAttribute

IE67可以用setAttribute設定className的class, 出了IE67以外的瀏覽器可以用setAttribute(class,”")設定class;

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script type="text/javascript">

            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

        </script>

        <script type="text/javascript">
        div = document.createElement("div");
        div.setAttribute( "className", "t" );
        l(div.className !== "t");
        /*
        div.setAttribute( "class", "t" );
        l(div.className == "t");
        */
        </script>
    </body>
</html>

$.support.html5Clone

IE6新建一些無法識別的標籤時候會出現問題,比如

<script type="text/javascript">
l(document.createElement("nav").cloneNode( true ).outerHTML);
</script>

在IE6中執行會變成這樣:, 而且這個特性在IE11模擬IE5,IE6一點效果都沒有;

小技巧為了讓IE6支援HTML5的標籤可以自己建立html5標籤,而且你可以給這些標籤自定義樣式:

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script>
        (function(){
            var element=['header','footer','article','aside','section','nav','menu','hgroup','details','dialog','figure','figcaption'],
                len=element.length;
            while(len--){
                document.createElement(element[len])
            };
         })();
         </script>

        <style>
        nav{
            width:100px;
            height:100px;
            background:#f00;
            display:block;
        }
        </style>
        <nav>nav</nav>
        <footer>footer</footer>
        <script type="text/javascript">
            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();
        </script>

        <script type="text/javascript">
        l(document.createElement("nav").cloneNode( true ).outerHTML);
        </script>
    </body>
</html>

$.support.boxModel

這個玩意兒 document.compatMode === “‘BackCompat’”  是為了讓我們知道當前的文件模式是否是標準的文件模式,還是有用的;

$.support.submitBubbles, $.support.changeBubbles, $.support.focusinBubbles

除了火狐以外所有的瀏覽器都支援focusin和focusout, 這兩個事件和focus和blur的區別是, focus和blur並不會發生冒泡,focusin和focusout會冒泡, 我們可以通過focusin和focusout實現事件代理, 例子:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta charset="utf-8" />
  <title>focus(in|out) not implemented</title>
  <script type="text/javascript">//<![CDATA[

   document.addEventListener('focusin',function(e){if(e.target.tagName=='INPUT')e.target.style.backgroundColor='green'},0)
   document.addEventListener('focusout',function(e){if(e.target.tagName=='INPUT')e.target.style.backgroundColor='white'},0)

  //]]></script>
 </head>
 <body>
  <div><input type="text" style="background:red" /></div>
  <div>Please click on input above to change element color.</div>
  <div><a href="http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#event-type-focusIn">http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#event-type-focusIn</a></div>
  <div style="color:red">Firefox: not implemented yet!</div>
  <div style="color:green">IE 9: focused in - green</div>
  <div style="color:green">Opera 11.5: focused in - green</div>
  <div style="color:green">Chrome 14: focused in - green</div>
  <div style="color:green">Safari 5.1: focused in - green</div>
  <div>Konqueror 4.7: only DOMFocus</div>
 </body>
</html>

雖然就只有firefox不支援focusin, 但是support.focusinBubblesff,chrome,以及IE11中的值都為false, 也就是說jQuery把他們都統一起來,通過focus和blur的的自定義代理模擬focusin和focusout;

因為ie6-ie10中都支援attachEvent方法,所以focusinBubble都為true, IE11不支援attachEvent,所以focusinBubble為false了;

submitBubbles和changeBubbles在IE8以下的瀏覽器中都是false;

結果的確有點亂, 在後面的事件系統中不支援事件冒泡是要做特殊處理的,下面這個程式碼從jQ中切出來( ̄_, ̄ )的程式碼;

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <script>
            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;word-break:break-all";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();
        //寫了一個小小的JSON方法,哈哈o(^▽^)o,666666666666666
            if(!window.JSON) {
                window.JSON = {
                    stringify : function(json) {
                        var str = "{";
                        for(var p in json) {
                            if( typeof json[p] === "object") {
                                str += (p+":"+ window.JSON.stringify(json[p]) +",");
                            }else {
                                str += (p+":"+String(json[p])+",")
                            };
                        };
                        return str.slice(0,-1)+"}";
                    }
                }
            };
            //testing;
            l( JSON.stringify({1:{2:3,4:{5:"six"}}}) );
        </script>

        <script type="text/javascript">
        var support = {
            submitBubbles: true,
            changeBubbles: true,
            focusinBubbles: false
        };

        var div = document.createElement("div");
        if ( div.attachEvent ) {
            for ( i in {
                submit: true,
                change: true,
                focusin: true
            }) {
                eventName = "on" + i;
                isSupported = ( eventName in div );
                if ( !isSupported ) {
                    div.setAttribute( eventName, "return;" );
                    isSupported = ( typeof div[ eventName ] === "function" );
                };
                support[ i + "Bubbles" ] = isSupported;
            };
        };
        l( JSON.stringify(support) );

        </script>
    </body>
</html>

$.support.deleteExpando

因為IE6和IE7下的DOM元素是COM元件,delete刪除COM元件的屬性會報錯,所以有了deleteExpando這個玩意兒,DEMO

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
        <div id="id"></div>
        <script>
            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;word-break:break-all";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();

            var id = document.getElementById("id");
            id.test = "1111";
            try {
                delete id.test;
            } catch( e ) {
                l( "delete錯誤" );
            };
        </script>

    </body>
</html>

$.support.noCloneEvent

又是IE, 複製元素會把事件複製過去,support.noCloneEvent就是檢測IE是否會複製元素的事件的屬性, 因為jQuery中元素的事件是和資料快取系統($.data,$.cahce)緊密耦合的, 要複製一個元素的事件直接複製元素的expanDo就可以, 事件並不是直接繫結到元素上的, 相關的JS程式碼:

        if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
            div.attachEvent( "onclick", clickFn = function() {
                // Cloning a node shouldn't copy over any
                // bound event handlers (IE does this)
                support.noCloneEvent = false;
            });
            div.cloneNode( true ).fireEvent("onclick");
            div.detachEvent( "onclick", clickFn );
        }

$.support.reliableHiddenOffsets

reliableHiddenOffsets這個是很少見的一個問題, 在IE7和IE6中出現bug, 如果一個table中有一個有內容的td的display為none, 這個table其他的td沒有內容但是是顯示著的話,那麼這些td的高度為1, 這個1不知道是從哪裡來的,很怪的一個bug(然道是空格?), 不管了, 反正用的少

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
    </body>
        <script>
            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;word-break:break-all";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();
        </script>

        <script type="text/javascript">
            var container = document.createElement("div");
            var div = document.createElement("div");
            var isSupported;
            var body = document.getElementsByTagName("body")[0];
            body.insertBefore( container, body.firstChild );

            container.appendChild( div );
            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";
            isSupported = isSupported && ( tds[ 0 ].offsetHeight === 0 );
            l( isSupported );
        </script>
</html>

$.support.boxSizing,$.support.doesNotIncludeMarginInBodyOffset

IE8中是支援box-sizing的,IE6,IE7通過開啟怪異模式也是支援boxSizing的;doesNotIncludeMarginInBodyOffset很不常用, 一般的offsetLeft或者offsetTop是從邊框外開始計算的,也就是包含了margin, 但是因為body這個元素的特殊性質,body的offsetTop和offsetLeft並不包含margin,而且body一般有一個預設8px的marign, 導致計算位置的時候會產生混亂, so, jQ把他們統一起來了,doesNotIncludeMarginInBodyOffset這個在任何瀏覽器中都未true,(哎,放心了,我的小心肝都快碎了);

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
    </body>
        <script>
            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;word-break:break-all";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();
        </script>

        <script type="text/javascript">

            var div = document.createElement("div");
            var body = document.getElementsByTagName("body")[0];
            var support = {};
            body.insertBefore( div, body.firstChild );

            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%;";
            support.boxSizing = ( div.offsetWidth === 4 );
            support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );

            l( support.boxSizing );
            l( support.doesNotIncludeMarginInBodyOffset );
        </script>
</html>

$.support.pixelPosition ,$.support.boxSizingReliable,$.support.reliableMarginRight

piexelPosition是指當你給一個元素設定百分比的寬度或者高度的時候, 通過getComputedStye標準瀏覽器都要返回畫素的寬高, 有些瀏覽器返回的還是百分比的寬高, 這個bug應該是低版本的chrome或者ff才有的bug, IE(<=IE10)通過currentStyle獲取的寬高返回的還是百分比的寬高, 要獲取畫素寬高需要hack…..,我想靜靜….;

boxSizingReliable這個也是再次驗證盒模型是否支援, 不知道有什麼用;

reliableMarginRight是指低版本chrome獲取不到marginRight的問題,jQuery真是操碎了心, bugs連結

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
    </body>
        <script>
            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;word-break:break-all";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();
        </script>

        <script type="text/javascript">

            var div = document.createElement("div");
            var body = document.getElementsByTagName("body")[0];
            var support = {};
            body.insertBefore( div, body.firstChild );

            div.innerHTML = "";
            div.style.cssText = "width:50%";
            if(window.getComputedStyle)
                l( window.getComputedStyle(div,null)["width"] );
            if(div.currentStyle) {
                l( div.currentStyle["width"] );
            }
        </script>
</html>

$.support.inlineBlockNeedsLayout, $.support.shrinkWrapBlocks

IE67瀏覽器,如果元素的display樣式值為inline-block,並不會生效,要用display:inline;zoom:1;進行模擬, 所以inlineBlockNeedsLayout也是對於IE做的特殊處理;

shrinkWrapBlocks是因為在IE6中,子元素的寬度超過的父級元素,父元素的寬度也會被撐開,老問題。

<html>
    <head>
        <meta charset="utf-8" />
        <title>相容</title>
    </head>
    <body>
    </body>
        <script>
            window.l = (function() {
                var el = document.createElement("div"), index = 0;
                el.style.cssText = "padding:10px;position:fixed;top:0;right:0;width:10%;border:1px solid #f00;word-break:break-all";
                return function(message) {
                    message = message.toString();
                    if( message ) {
                        var span = document.createElement("span");
                        span.innerHTML = (++index) + "資訊:<br>"+ message+"<br>";
                        el.appendChild( span );
                    };
                    //IE低版本直接通過createElement建立的元素有parentNode;
                    if( !el.parentNode || (el.parentNode.toString() === "[object]") ) {
                        document.body.appendChild(el);
                    };
                    return l;
                };
            })();
        </script>

        <div id="shrinkWrapBlocks" style="width: 1px; zoom: 1;"> 
            <div style="width: 4px;"> 
            </div> 
        </div> 

        <script type="text/javascript"> 
            var div = document.getElementById('shrinkWrapBlocks'), 
            inner = div.getElementsByTagName('div')[0]; 
            l(div.offsetWidth); 
        </script>
</html>

參考這裡:

學習jQuery.support

focusin和focusout相關

MDN的focusin和focusout

jQuery support 原始碼解讀

相關文章