源碼解讀jQ中瀏覽器兼容模塊support
//這樣的寫法在瀏覽器中根本不生效;document.body.innerHTML = "<script src='1.js'></script>"http://但是我們可以通過jQuery的方式生成并插入到DOM數(shù)種$("<script src='1.js'></script>").appendTo(document.body)
$.support.style
標(biāo)準(zhǔn)瀏覽器通過getAttribute獲取都應(yīng)該是字符串的,IE67你getAttriute是各種奇葩,你獲取的style是一整個樣式對象, IE67要獲取行內(nèi)樣式要用 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創(chuàng)建的元素有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"); //標(biāo)準(zhǔn)瀏覽器要么返回的是background:#f00,要么返回background: rgb(255, 0, 0); //IE6,IE7返回了所有的style屬性 l(eDiv.getAttribute("style")); l(typeof eDiv.getAttribute("onclick")); </script> </body></html>
IE67中獲取style返回的是下面圖片, 這個應(yīng)該是eDiv的元素屬性才對, 意思就是說IE67中DOM屬性和節(jié)點屬性傻傻分不清楚, 比如onclick返回的是function….(等等,我想靜靜….):
獲取一個html頁面的相對路徑可以通過動態(tài)創(chuàng)建一個錨鏈接,然后獲取這個錨連接的href就可以獲取到絕對的路徑, 瀏覽器獲取script標(biāo)簽的src方式要根據(jù)瀏覽器的特性,一般來說是這樣的:
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創(chuàng)建的元素有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都是開發(fā)者輸入的字符串, var eA = document.getElementById("a"); l(eA.getAttribute("href",3)); l(eA.href); var js = document.getElementById("js"); //IE8以后和標(biāo)準(zhǔn)瀏覽器獲取絕對的src直接通過src,IE67通過src獲取絕對路徑, 這個技巧在獲取script標(biāo)簽的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創(chuàng)建的元素有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
這個玩意兒標(biāo)準(zhǔn)瀏覽器是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創(chuàng)建的元素有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; //創(chuàng)建optino元素的方法1: //opt = document.createElement("option"); //opt.setAttribute("value","value"); //opt.setAttribute("name","name"); //(opt.textContent = "text")|| (opt.innerText = "text"); //創(chuàng)建optino元素的方法2: //這樣也可以; //opt = document.createElement("option"); //opt.value = "value"; //opt.text = "text"; //這樣也行; //創(chuàng)建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設(shè)置className的class, 出了IE67以外的瀏覽器可以用setAttribute(class,”")設(shè)置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創(chuàng)建的元素有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新建一些無法識別的標(biāo)簽時候會出現(xiàn)問題,比如
<script type="text/javascript">l(document.createElement("nav").cloneNode( true ).outerHTML);</script>
在IE6中執(zhí)行會變成這樣:
, 而且這個特性在IE11模擬IE5,IE6一點效果都沒有;
小技巧為了讓IE6支持HTML5的標(biāo)簽可以自己創(chuàng)建html5標(biāo)簽,而且你可以給這些標(biāo)簽自定義樣式:
<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創(chuàng)建的元素有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'”
是為了讓我們知道當(dāng)前的文檔模式是否是標(biāo)準(zhǔn)的文檔模式,還是有用的;
$.support.submitBubbles, $.support.changeBubbles, $.support.focusinBubbles
除了火狐以外所有的瀏覽器都支持focusin和focusout, 這兩個事件和focus和blur的區(qū)別是, focus和blur并不會發(fā)生冒泡,focusin和focusout會冒泡, 我們可以通過focusin和focusout實現(xiàn)事件代理, 例子:
<!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 >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.focusinBubbles
在ff,chrome,以及IE11中的值都為false, 也就是說jQuery把他們都統(tǒng)一起來,通過focus和blur的的自定義代理模擬focusin和focusout;
因為ie6-ie10中都支持attachEvent方法,所以focusinBubble都為true, IE11不支持attachEvent,所以focusinBubble為false了;
submitBubbles和changeBubbles在IE8以下的瀏覽器中都是false;
結(jié)果的確有點亂, 在后面的事件系統(tǒng)中不支持事件冒泡是要做特殊處理的,下面這個代碼從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創(chuàng)建的元素有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創(chuàng)建的元素有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, 復(fù)制元素會把事件復(fù)制過去,support.noCloneEvent
就是檢測IE是否會復(fù)制元素的事件的屬性, 因為jQuery中元素的事件是和數(shù)據(jù)緩存系統(tǒng)($.data,$.cahce)緊密耦合的, 要復(fù)制一個元素的事件直接復(fù)制元素的expanDo就可以, 事件并不是直接綁定到元素上的, 相關(guān)的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中出現(xiàn)bug, 如果一個table中有一個有內(nèi)容的td的display為none, 這個table其他的td沒有內(nèi)容但是是顯示著的話,那么這些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創(chuàng)建的元素有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這個元素的特殊性質(zhì),body的offsetTop和offsetLeft并不包含margin,而且body一般有一個默認(rèn)8px的marign, 導(dǎo)致計算位置的時候會產(chǎn)生混亂, so, jQ把他們統(tǒng)一起來了,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創(chuàng)建的元素有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是指當(dāng)你給一個元素設(shè)置百分比的寬度或者高度的時候, 通過getComputedStye標(biāo)準(zhǔn)瀏覽器都要返回像素的寬高, 有些瀏覽器返回的還是百分比的寬高, 這個bug應(yīng)該是低版本的chrome或者ff才有的bug, IE(<=IE10)通過currentStyle獲取的寬高返回的還是百分比的寬高, 要獲取像素寬高需要hack…..,我想靜靜….;
boxSizingReliable這個也是再次驗證盒模型是否支持, 不知道有什么用;
reliableMarginRight是指低版本chrome獲取不到marginRight的問題,jQuery真是操碎了心;
<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創(chuàng)建的元素有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;進(jìn)行模擬, 所以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創(chuàng)建的元素有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>
通過直接調(diào)用jQuery.support來檢測某些功能,通過查看其源代碼我們可以更深入的了解各個瀏覽器之間的區(qū)別。特別是針對IE,還有webkit的bug,都能讓我們受益匪淺。本文內(nèi)容到此就結(jié)束了,希望對大家學(xué)習(xí)jQuery有所幫助。
- jQuery 1.9移除了$.browser可以使用$.support來替代
- jQuery 1.9使用$.support替代$.browser的使用方法
- jQuery 源碼分析筆記(5) jQuery.support
- jQuery ajax BUG:object doesn''t support this property or method
- jQuery下通過$.browser來判斷瀏覽器.
- js/jquery獲取瀏覽器窗口可視區(qū)域高度和寬度以及滾動條高度實現(xiàn)代碼
- jquery判斷瀏覽器類型的代碼
- 兩種方法基于jQuery實現(xiàn)IE瀏覽器兼容placeholder效果
- js/jquery判斷瀏覽器的方法小結(jié)
- jQuery一步一步實現(xiàn)跨瀏覽器的可編輯表格,支持IE、Firefox、Safari、Chrome、Opera
相關(guān)文章
基于Jquery的動態(tài)創(chuàng)建DOM元素的代碼
jquery動態(tài)創(chuàng)建頁面元素,mark一下,以備以后查詢時使用。以創(chuàng)建div和input為例。2010-12-12jQuery實現(xiàn)表單動態(tài)添加與刪除數(shù)據(jù)操作示例
這篇文章主要介紹了jQuery實現(xiàn)表單動態(tài)添加與刪除數(shù)據(jù)操作,涉及jQuery事件響應(yīng)及頁面元素動態(tài)操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2018-07-07基于jQuery實現(xiàn)的設(shè)置文本區(qū)域的光標(biāo)位置
之前做一個代碼提示的功能涉及到在文本框中插入文本的操作,需要獲得當(dāng)前光標(biāo)位置插入文本,本文章向大家介紹jQuery如何設(shè)置文本區(qū)域的光標(biāo)位置,需要的朋友可以參考一下2018-06-06調(diào)用HttpHanlder的幾種返回方式小結(jié)
本篇文章主要是對調(diào)用HttpHanlder的幾種返回方式進(jìn)行了總結(jié)介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12