IE9相容問題-childNodes行為改變
IE9算是微軟大幅向其他瀏覽器靠攏的改版,在網頁呈現上已做到幾乎與Chrome, Firefox, Safari一致,不過,這也意味著IE9跟IE8的行為有明顯差異。(補充)
前幾天處理了一個IE8檢視正常網頁在IE9爆炸的案例,在此筆記:
以下範例可重現問題。程式在網頁新增一個<table>,而在<td>間故意夾雜換行或空白,接著透過<tr> .childNodes找出第二個<td>並取出其中HTML內容的第一個字元。(理論可用jQuery處理,不推此種寫法,但原程式如此)
排版顯示純文字
$("<table id='x'><tr><td>a01</td>
<td>b01</td> <td>c01</td></tr></table>")
.appendTo("body");
$('#x tr').each(function() {
try {
alert(this.childNodes[1].innerHTML.substr(0, 1));
} catch (er) {
alert("Error: " + er);
}
});
在IE8執行時,可以如預期取得”b”;但是到了IE9,卻會因為childNodes[1].innerHTML == undefined而發生以下錯誤: Error: TypeError: Unable to get value of the property 'substr': object is null or undefined
經檢測發現這是IE9對childNodes定義不同造成,用以下範例突顯二者差異:
排版顯示純文字
$("<table id='x'><tr><td>a01</td>
<td>b01</td> <td>c01</td></tr></table>")
.appendTo("body");
$("#x tr").each(function() {
var nodes = this.childNodes;
var h = ["<ol>"];
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
h.push("<li>" + node.nodeName + ":" +
(node.innerHTML || escape(node.data)) + "</li>");
}
h.push("</ol>");
$("body").append(h.join(""));
});
試著列舉<tr>的childNodes,在IE8只有三個<td>
- TD:a01
- TD:b01
- TD:c01
但在IE9,<td>間的換行以及空白也被算成子節點之一,故共有五個子節點:
- TD:a01
- #text:%0A
- TD:b01
- #text:%20
- TD:c01
參考W3CSchool關於Node Types的說明,除了<TD>Element Node外,Text甚至CDATASection也都算Node的一種,而在Firefox、Chrome中亦是依此邏輯運作。以此而論,先前程式碼可行,反而是因為IE8不合群所致。
回到案例解決上,用$(this).find(“td:eq(1)”).html()取代原來寫法便能輕鬆解決此一跨瀏覽器問題,而在程式修正前,只能請使用者啟動相容檢視模式先避開此一相容議題。