IE9算是微軟大幅向其他瀏覽器靠攏的改版,在網頁呈現上已做到幾乎與Chrome, Firefox, Safari一致,不過,這也意味著IE9跟IE8的行為有明顯差異。(補充)

前幾天處理了一個IE8檢視正常網頁在IE9爆炸的案例,在此筆記:

以下範例可重現問題。程式在網頁新增一個<table>,而在<td>間故意夾雜換行或空白,接著透過<tr> .childNodes找出第二個<td>並取出其中HTML內容的第一個字元。(理論可用jQuery處理,不推此種寫法,但原程式如此)

$("<table id='x'><tr><td>a01</td>\n<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>\n<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>

  1. TD:a01
  2. TD:b01
  3. TD:c01

但在IE9,<td>間的換行以及空白也被算成子節點之一,故共有五個子節點:

  1. TD:a01
  2. #text:%0A
  3. TD:b01
  4. #text:%20
  5. TD:c01

參考W3CSchool關於Node Types的說明,除了<TD>Element Node外,Text甚至CDATASection也都算Node的一種,而在Firefox、Chrome中亦是依此邏輯運作。以此而論,先前程式碼可行,反而是因為IE8不合群所致。

回到案例解決上,用$(this).find(“td:eq(1)”).html()取代原來寫法便能輕鬆解決此一跨瀏覽器問題,而在程式修正前,只能請使用者啟動相容檢視模式先避開此一相容議題。


Comments

Be the first to post a comment

Post a comment