和文檔一樣,首先說明一下,這個模塊是很底層的代碼,基本不需要在日常開發中使用,但是插件的開發者更需要。因為插件需要兼容各個浏覽器。首先看一下 support模塊提供了哪些浏覽器特性的檢測,以下結果是在Chrome 13 Dev下看到的結果。根據浏覽器的不同,這裡的成員可能會有變化。(PS:再次吐槽IE,大部分屬性都是IE比較特別)
jQuery創建了幾個元素用來判斷浏覽器特性。如下:
代碼如下:
var div = document.createElement("div");
div.setAttribute("className", "t");
div.innerHTML = " <LINK><TABLE><TBODY></TBODY></TABLE><A style="FLOAT: left; TOP: 1px; opacity: .55" href="http://www.poluoluo.com/a">a</A><INPUT type=checkbox>";
all = div.getElementsByTagName("*");
a = div.getElementsByTagName("a")[0];
var select = document.createElement("select");
opt = select.appendChild(document.createElement("option"));
input = div.getElementsByTagName("input")[0];
其中div元素相當有內涵。包括了空白開頭,空Table元素,inline style,opacity等等。除了一行行看代碼和注釋也沒啥其他筆記了:
代碼如下:
support = {
// IE會把開頭的空格去掉,所以nodeType不是3(文本)
leadingWhitespace: (div.firstChild.nodeType === 3),
// IE會自動插入tbody,所以length不同
tbody: !div.getElementsByName("tbody").length,
// IE不允許用這種方式插入link元素
htmlSerialize: !!div.getElementsByTagName("link").length,
// 如果正常獲得style的話,這個正則表達式應該會正常通過
style: /top/.test(a.getAttribute("style")),
// href屬性應該是原始指定的字符串,IE會修改為http開頭的絕對URL
hrefNormalized: (a.getAttribute("href") === "/a"),
// 能得到opacity屬性。這裡使用了正則表達式,是為了繞過WebKit[5145號bug](http://dev.jquery.com/ticket/5145)
// 但是這應該是一個早期版本的問題。起碼在Chrome 13中,不用正則也是對的。
opacity: /^0.55$/.test(a.style.opacity),
// IE使用styleFloat
cssFloat: !!a.style.cssFloat,
// div中的checkbox沒有指定值,看默認值是否是on。WebKit是""。所以我的結果是false
checkOn: (input.value === "on"),
// 這個select只有一個option元素,所以渲染時,這個option是默認選中的。此時selected應該是true。
optSelected: opt.selected,
submitBubbles: true,
changeBubbles: true,
focusinBubbles: false,
deleteExpando: true,
noCloneEvent: true,
inlineBlockNeedsLayout: false,
shrinkWrapBlocks: false,
reliableMarginRight: true
};
下面的大部分都是按部就班的測試。其中BoxModel的測試比較有趣:
代碼如下:
div.innerHTML = ""; // 從頭來
div.style.width = div.style.paddingLeft = "1px";
body = document.createElement("body");
body.style.width = 0;
body.style.height = 0;
body.style.border = 0;
body.style.margin = 0; // 全部設置為0
body.appendChild(div);
document.documentElement.insertBefore(body, document.documentElement.firstChild);
support.boxModel = div.offsetWidth === 2;
// 這個時候div嵌套在body下。而body長寬高,邊框和margin都是0。所以div的偏移應該就是它自己的paddingLeft+width。如果不對,就說明盒模式不對。
然後值得注意的是事件的冒泡,注釋中提到的技術參考文章鏈接已經失效。請自己搜索"Detecting event support without browser sniffing"
代碼如下:
// attachEvent是IE的,所以這裡實際上只檢查了IE,其他浏覽器都是前面設置的默認值。
if(div.attachEvent) {
for(i = {
submit: 1,
change: 1
focusin: 1
}) {
eventName = "on" + i;
isSupported = (eventName in div);
if(!isSupported) {
div.setAttribute(eventName, "return;");
isSupported = (typeof div[eventName] === "function");
}
support[i + "Bubbles"] = isSupported;
}
}
PS: 浏覽器檢測是一個很糾結,很細節的任務。這個筆記慢慢完善中……
18:30補充:經過IE9的測試,以上大部分IE相關問題都已經不存在。以下是IE9+Win7的測試結果:
代碼如下:
$.support
{
boxModel: true,
changeBubbles: true,
checkClone: true,
checkOn: true,
cssFloat: true,
deleteExpando: true,
hrefNormalized: true,
htmlSerialize: true,
leadingWhitespace: true,
noCloneEvent: false,
opacity: true,
optSelected: false,
parentNode: true,
scriptEval: true,
style: true,
submitBubbles: true,
tbody: true
}