javascript框架設(shè)計(jì)之瀏覽器的嗅探和特征偵測
瀏覽器的嗅探現(xiàn)在已經(jīng)不推薦了,但在某些場合還是需要的。比如一些統(tǒng)計(jì)腳本。在標(biāo)準(zhǔn)瀏覽器里,提供了document.implementation.hasfeature,可惜有bug,不準(zhǔn)確,目前,w3c又推出了CSS.supports方法,顯示出大家對這塊的關(guān)注。
1.判定瀏覽器。
主流的瀏覽器有ie firefox opera chorme safari 早期這些框架都是通過navigator.userAgent進(jìn)行判定,目前國外的瀏覽器幾乎都是可以判定的。
關(guān)于瀏覽器的判斷腳本,jQuery已經(jīng)移出本體,形成一個插件。更多的方式不多介紹,
移動設(shè)備的相關(guān)判定,這個建議看jQuery mobile與zepto的源代碼。
isIPone = /isIPone/i.test(navigator.userAgent);
isIPone4 = window.devicePixelRatio >= 2 //在網(wǎng)頁中,pixel與point比值稱為device-pixel-ratio,普通設(shè)備都是1,iPhone4是2,有些 安卓機(jī)型是1.5
isIpad = /ipad/i.test(navigator.userAgent)
isAndroid = /android/i.test(navigator.userAgent)
isIOS = isIPone || isIpad
國內(nèi)的瀏覽器判定可以看Tangrame或qwrap,它們基本是IE,webkit,blink內(nèi)核。
2.事件的支持偵測
prototype的核心成員kangax寫了一篇文章,來判斷瀏覽器對某種事件的支持。里面給出的實(shí)現(xiàn)如下:
var isEventSupported = (function() { var TAGNAMES = { 'select':'input','change':'input', 'submit':'form','reset':'form', 'error':'img','load':'img','abort':'img' } function isEventSupported(eventName){ var el = document.createElement(TAGNAMES[eventName] || 'div'); eventName = 'on' + eventName; var isSupported = (eventName in el); if (!isSupported) { el.setAttribute(eventName, 'return;'); isSupported = typeof el[eventName] == 'function'; } el = null; return isSupported; } return isEventSupported; })();
現(xiàn)在jQuery等框架都是使用腳本的簡化版
不過哪一個也好,這種檢測只對DOM0奏效,像DOMMouseScroll DOMContentLoaded DOMFocusIn DOMFocusOut DOMSubtreeModified DOMNodeInserted DOMNodeRemoved DOMNodeRemovedFromDocument DOMNodeInsertedIntoDocument DOMAttrModified DOMCharactorDataModified這些以DOM開頭的就無能為力了。
這些事件中,有的非常有用,如DOMMouseScroll,firefox一直不支持mousesheel,只能用它做替代品。
DOMContentLoaded是實(shí)現(xiàn)domReady的重要事件;DOMNodeRemoved是判定元素是否從其父節(jié)點(diǎn)移除,父節(jié)點(diǎn)可能是其它元素節(jié)點(diǎn)或文檔碎片;DOMNodeRemovedFromDocument 是移離DOM樹,DOMAttrModified 以前經(jīng)常用于模擬IE的onpropertyChange
css3添加兩種動畫,一種是transition動畫,另外一種是keyframe補(bǔ)間動畫。它們在事件結(jié)束時(shí)都用事件回調(diào)。但在標(biāo)準(zhǔn)化過程中,瀏覽器給它們起的名字相當(dāng)于沒規(guī)則。這個也需要預(yù)先偵測出來。
下面是bootstrap的實(shí)現(xiàn)。聽說來源于modernizr,比較粗糙。比如你使用的Oprera已經(jīng)支持不帶事件標(biāo)準(zhǔn)事件名。它還是返回oTransitionEnd.
$.supports.transition = (function(){ var transitionEnd = (function(){ var el = document.createElement('bootstarp'), transEndEventNames = { 'WebkitTransition':'webkitTransitionEnd', 'MozTransition':'transitionend', 'OTransition':'OTransitionEnd otransitionend', 'transition':'transitionend' }; for (var name in transEndEventNames){ if (el.style[name] !== undefined){ return transEndEventNames[name] } } }()); return transitionEnd && { end: transitionEnd } })();
keyframe補(bǔ)間動畫來自mass的fx_neo模塊
var eventName = { AnimationEvent:'animationend', WebKirAnimationEvent: 'WebKirAnimationEnd' },animationend; for(var name in eventName) { if (/object|function/.test(typeof window[name])){ animationend = eventName[name] break } }
3.樣式的支持偵探
css3帶來許多好用的樣式,但是麻煩的是每個瀏覽器都有自己的私有前綴,massFramework提供了一個cssName方法來處理它們,有就返回可用的駝峰樣式名,沒有就null
var prefixes = ['','-webkit-','-o-','-moz-','-ms-']; var cssMap = { "float" : $.support.cssFloat ? 'cssFloat' : 'styleFloat',background:'backgroundColor' }; function cssName(name, host, camelCase){ if(cssMap[name]) { return cssMap[name]; } host = host || document.documentElement for (var i = 0 || n = prefixes.length; i < n; i++) { camelCase = $.String.camelize(prefixes[i] + name); if (camelCase in host) { return (cssMap[name] = camelCase) } } return null }
一個樣式對于N種樣式值,比如display有n種取值,如果要偵測瀏覽器是否支持某一種,會很麻煩。為此,瀏覽器做了一個善舉,給出一個css.supports的API,如果不支持,則嘗試下一個開源項(xiàng)目。顯然,不是很完美。
https://github.com/termi/CSS.supports
4.jQuery的一些常用的特征的含義
jQuery在support模塊例舉了一些常用的DOM特征支持情況,不過名字起的很怪,不同版本差別也很大,本章以jQuery1.8為準(zhǔn)。
leadingWhitespace:判定瀏覽器在進(jìn)行innerHTML賦值時(shí),是否存在trimLeft操作,這個功能原本是IE發(fā)明的,結(jié)果其他瀏覽器認(rèn)為要忠于以后的原始值,最前面的空白不能神略掉,要變成一個文本節(jié)點(diǎn),最終IE678返回false,其他瀏覽器返回true
tobody:指在用innerHTML動態(tài)創(chuàng)建元素時(shí),瀏覽器是否會在table內(nèi)自動補(bǔ)上tobody,jQuery希望瀏覽器別處理,讓jQuery來補(bǔ)全。判斷瀏覽器是否只能插入tobody。在表格布局的年代,這個特性十分受用。如果沒有tbody,table會在瀏覽器解析到閉合標(biāo)簽時(shí)才顯示出來。如果起始標(biāo)簽和閉合標(biāo)簽相隔很遠(yuǎn),換言之,這個表格很長,用戶會什么都看不到,但有了tbody分段顯示和識別,避免了長時(shí)間空白后一下子顯示出來的情況。
var div = document.createElement("div");
div.innerHTML = '<table></table>'
alert(div.innerHTML) //=>ie678返回<table><tbody></tbody></table>,其它返回<table></table>
html.Serialize:判斷瀏覽器是否完好支持用innerHTML轉(zhuǎn)換一個符合html標(biāo)簽規(guī)則的字符串為一個元素節(jié)點(diǎn),此過程jQuery稱為序列化,但I(xiàn)E支持不夠完好。包括scirpt link style mata在內(nèi)的no-scope元素都轉(zhuǎn)換失敗。
style:這個命名很難看懂,不看代碼不知道什么意思,真像是判定getAttribute是否返回style的用戶預(yù)設(shè)值。IE678沒有返回區(qū)分特性的特征,返回一個CSSStyleDeclaration對象。
hrefNormalized:判定getAttribute能否返回href的用戶預(yù)設(shè)值。IE會補(bǔ)充給你完整的路徑給你
opacity:判定瀏覽器是否支持opacity屬性,ie678要使用濾鏡
cssFloat: 判定float的樣式在DOM的名字是那個,W3c為cssFloat,IE678為styleFloat
CheckOn: 在大多數(shù)瀏覽器中checkBox的value為on,chorme返回空字符串
optSelected: 判定是否正確取得動態(tài)添加option元素的seleted,ie6-10與老版的safari對動態(tài)添加option沒有設(shè)置為true。解決辦法,在訪問selected屬性前,先訪問父節(jié)點(diǎn)的selectedIndex屬性,再強(qiáng)制計(jì)算option的seleted.
<select id='optSelected'></select> <script type="text/javascript"> var select = document.getElementById('optSelected'); var option = document.createElement('option'); select.appendChild(option); alert(option.selected); select.selectedIndex; alert(option.selected) </script>
optDisabled : 判定select元素的disable屬性是否影響到子元素的disabled取值.在safari中,一旦select元素被disabled,它的子元素也disabled,導(dǎo)致一個值也取不到
checkClone:是指一個checkbox元素,如果設(shè)置了checked=true,且在多次克隆后,它的復(fù)制品能否保持為true。這個方法只有在safari4中返回false,其它的都true
inlineBlockNeedsLayout:判定是否使用hasLayout方法讓dispaly:inline-block生效。這個方法只有ie678為true
getSetAttribute:判定是否區(qū)分特性屬性,只有ie678為false
noCloneEvent:判定在克隆元素時(shí)是否克隆attachEvent綁定事件。只有舊版本的ie及其兼容模式返回false
enctype:判定瀏覽器是否支持encoding屬性,ie67使用encoding屬性來代替
boxModel:判定瀏覽器是否在content-box盒子渲染模式下
submitBubbles, changeBubbles, focusinBubble:判定瀏覽器是否支持這些事件,一直冒泡到document
shrinkWrapBlocks:判定元素是否會被子元素?fù)伍_。在IE678中,非替換元素在設(shè)置了大小與hasLayout的情況下,將將其父級元素?fù)未蟆?/p>
html5Clone:判定能否使用cloneNode克隆HTML5新標(biāo)簽 ,舊版本的IE不支持。需要用到outerHTML
deleteExpando:判定能否刪除元素節(jié)點(diǎn)上的自定義元素,這用于jQuery緩存系統(tǒng)。舊版本的IE不支持,直接undefined
pixelPosition:判定getComputedStyle能否轉(zhuǎn)換元素的top left bottom right元素的百分比值。這個在webkit系統(tǒng)會出現(xiàn)問題,需要用到 Dean Edwards神的hack
reliableMarginRight:判定getComputedStyle能否正確的取得元素的marginRiht.
clearCloneStyle :ie9 10 會出現(xiàn)奇怪的bug,當(dāng)復(fù)制了一個元素的background-*樣式的元素,對復(fù)制的元素進(jìn)行清空時(shí),會清空原來的樣式。
隨著瀏覽器瘋狂更新版本,標(biāo)準(zhǔn)瀏覽器引發(fā)的各種bug已經(jīng)超越IE,特征偵測不退反進(jìn),越來越重要了。
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
- 十大熱門的JavaScript框架和庫
- 深入解析JavaScript框架Backbone.js中的事件機(jī)制
- JavaScript框架是什么?怎樣才能叫做框架?
- 超贊的動手創(chuàng)建JavaScript框架的詳細(xì)教程
- javascript框架設(shè)計(jì)之類工廠
- javascript框架設(shè)計(jì)之種子模塊
- javascript框架設(shè)計(jì)之框架分類及主要功能
- 2014 年最熱門的21款JavaScript框架推薦
- javascript框架設(shè)計(jì)讀書筆記之?dāng)?shù)組的擴(kuò)展與修復(fù)
- javascript框架設(shè)計(jì)讀書筆記之字符串的擴(kuò)展和修復(fù)
- javascript框架設(shè)計(jì)讀書筆記之模塊加載系統(tǒng)
- javascript框架設(shè)計(jì)讀書筆記之種子模塊
- JavaScript框架(iframe)操作總結(jié)
- 怎么選擇Javascript框架(Javascript Framework)
- 詳細(xì)介紹8款超實(shí)用JavaScript框架
- brook javascript框架介紹
- 16個最流行的JavaScript框架[推薦]
- 如何選擇適合你的JavaScript框架
相關(guān)文章
JavaScript將字符串轉(zhuǎn)換成字符編碼列表的方法
這篇文章主要介紹了JavaScript將字符串轉(zhuǎn)換成字符編碼列表的方法,實(shí)例分析了javascript中charCodeAt函數(shù)的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03js實(shí)現(xiàn)網(wǎng)頁隨機(jī)驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)網(wǎng)頁隨機(jī)驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10總結(jié)JavaScript中布爾操作符||與&&的使用技巧
這篇文章主要介紹了總結(jié)JavaScript中布爾操作符||與&&的使用技巧,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-11-11獲取當(dāng)前網(wǎng)頁document.url location.href區(qū)別總結(jié)
請教:document.URL和window.location.href區(qū)別2008-05-05Bootstrap CSS組件之按鈕組(btn-group)
這篇文章主要為大家詳細(xì)介紹了Bootstrap CSS組件之按鈕組(btn-group),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12