前文提到眼前的棘手任務是在HTML5網站整合活化石等級的ASP(是的,就是ASP!不是ASPX),其中一大挑戰是ASP網頁裡大量使用XML Data Island與VBScript,能不能與HTML5並存是未知數,心中最理想結果是以IFrame內嵌ASP,大草原上羚羊跟迅猛龍一起快樂奔跑,世界真美好~當然,最後證明這只是不切實際的幻想,真實上演的是迅猛龍趕羚羊咬羚羊的慘烈場景 orz

試著在HTML5 IFrame內嵌實際的ASP,陸續發生詭異錯誤,為讓測試單純化,我簡化成用一個parent.html加一個embedded.html重現問題:

parent.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
</head>
<body>
    <iframe src="http://portal.lab.com/Blah/embedded.html"></iframe>
</body>
</html>

embedded.html (裡面加進測試實際ASP時出錯的VBScript及XML Data Island寫法)

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=7">
    <title>Embedded</title>
    <meta charset="utf-8" />
</head>
<body>
    <script type="text/javascript">
        alert("JavaScript");
    </script>
    <script type="text/vbscript">
        MsgBox "VBScript"
        Sub ButtonClick(strText)
            MsgBox strText + " Clicked"
        End Sub
    </script>
    <button onclick="vbscript : call ButtonClick(Me.InnerText)">Test1</button>
    <button onclick="vbscript : ButtonClick(Me.InnerText)">Test2</button>
    <xml>
        This parses as <b>HTML</b> in Internet Explorer 10 and other browsers.
        In older versions of Internet Explorer it parses as XML.
    </xml>
</body>
</html>

用IE11獨立瀏覽embedded.html完全正常,靠著X-UA-Compatible IE=7啟用IE7標準模式,XML Data Island、VBScript都活得好好。

當embedded.html被以IFrame內嵌進parent.html時,一切變了樣,VBScript跟XML Data Island都失效了。

查文件確定兩件事:

  1. IE10起不再支援XML Data Island
    https://msdn.microsoft.com/en-us/library/hh801224(v=vs.85).aspx
  2. IE11起不支援VBScript
    https://msdn.microsoft.com/en-us/library/dn384057(v=vs.85).aspx

不支援是指IE11/IE10標準模式不支援,切到IE7/IE8/IE9相容模式,老東西還可以再戰十年。問題出在parent.html用了X-UA-Compatible IE=Edge(代表使用IE最新標準模式),必須改成IE=9以確保XML Data Island跟VBScript可以運作。關掉並重啟IE(註:發現這個修改要重開IE才生效),XML Data Island OK了,VBScript的MsgBox也能執行,但部分VBScript出現錯誤:

  1. onclick="vbscript : call ButtonClick()"的call必須移除
  2. IE認不得ButtonClick(Me.InnerText)中的Me(相當於JavaScript的this)

單獨執行embedded.html不會發生這些錯誤,由此推論embedded.html被內嵌在parent.html時與獨立執行時的IE模式不完全相同。在stackoverflow找到一段透過navigator.userAgent偵測IE模式的範例:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=7">
    <title>Embedded</title>
    <meta charset="utf-8" />
</head>
<body>
<script>
//ref: http://stackoverflow.com/a/34928891
function IeVersion() {
    var value = {
        IsIE: false, TrueVersion: 0, ActingVersion: 0, CompatibilityMode: false
    };
 
    //Try to find the Trident version number
    var trident = navigator.userAgent.match(/Trident\/(\d+)/);
    if (trident) {
        value.IsIE = true;
        //Convert from the Trident version number to the IE version number
        value.TrueVersion = parseInt(trident[1], 10) + 4;
    }
 
    //Try to find the MSIE number
    var msie = navigator.userAgent.match(/MSIE (\d+)/);
    if (msie) {
        value.IsIE = true;
        //Find the IE version number from the user agent string
        value.ActingVersion = parseInt(msie[1]);
    } else {
        //Must be IE 11 in "edge" mode
        value.ActingVersion = value.TrueVersion;
    }
 
    //If we have both a Trident and MSIE version number, see if they're different
    if (value.IsIE && value.TrueVersion > 0 && value.ActingVersion > 0) {
        //In compatibility mode if the trident number doesn't match up with the MSIE number
        value.CompatibilityMode = value.TrueVersion != value.ActingVersion;
    }
    return value;
}
var ie = IeVersion();
document.write("UserAgent: " + navigator.userAgent + "<br />");
document.write("IsIE: " + ie.IsIE + "</br>");
document.write("TrueVersion: " + ie.TrueVersion + "</br>");
document.write("ActingVersion: " + ie.ActingVersion + "</br>");
document.write("CompatibilityMode: " + ie.CompatibilityMode + "</br>");
</script>    
</body>
</html>

實測發現,embedded.html明確宣告X-UA-Compatible IE=7,獨立開啟時為IE7模式:

被內嵌於X-UA-Compatible IE=9的parent.html時,embedded.html也處於IE9模式:

這就是MSDN文件所說:

As of IE9 mode, webpages cannot display multiple document modes. For example, consider a standards-based webpage that contains a frame element that displays content in quirks mode. IE9 mode displays the child frame in standards mode (because the parent document is in standards mode). Starting with Internet Explorer 10, however, child frames can emulate quirks mode. For more info, see IEBlog: HTML5 Quirks mode in IE10. For best results, however, use document modes consistently.

IE9起,檢視網頁只允許存在一種文件模式,故IFrame網頁必須沿用父網頁的IE標準模式。IE10做了點改善,允許IFrame網頁啟用Quirks相容,但Quirks相容僅能涵蓋一些舊版樣式、HTML語法,對於XML Data Island、VBScript語法支援問題無能為力。

由實驗印證IE同一時間只能使用一種標準模式,父網頁與IFrame要嘛一起用IE9,要嘛一起用IE7,而IE9與IE7對於VBScript支援有些許差異,除非修改VBScript程式,不然就得降級到IE7。

歸納結論如下:

  1. 如要使用VBScript,IE必須指定IE10以下的IE相容模式
  2. 如要使用XML Data Isaland,則必須使用IE9以下相容模式
  3. 當父網頁為 IE11、IE10、IE9 模式,透過IFrame內嵌網頁會沿用父網頁的文件模式,透過X-UA-Compatible亦無法改變。 當父網頁為 IE8、IE7、IE5 模式,IFrame 內嵌的網頁可透過 X-UA-Compatible 切換與父網頁不同的 IE 模式,但 Edge、IE10、IE9 會降為 IE8。詳細說明
  4. IE7與IE9都支援VBScript,但在語法與部分細節上有所差異,必須修改後才能使用

評估之後,修改老程式無可避免,一些網頁只能認命重寫~順勢消滅一些IE Only老網頁,就當做功德吧!orz


Comments

# by Alex Lee

阿彌陀佛

# by 路人

XML Data Isaland 剛出來時候,配合 xmlhttp 用得很開心啊!但後來 json 當道,現在做專案已經不考慮 IE 了......

Post a comment