轉換網頁程式:從 IE 到 Mozilla

  • 版本網址代稱: 轉換網頁程式:從_IE_到_Mozilla
  • 版本標題: 轉換網頁程式:從 IE 到 Mozilla
  • 版本 ID: 307297
  • 建立日期:
  • 建立者: sailplaneTW
  • Is current revision?
  • 回應

版本內容

{{ template.Translation("http://developer.mozilla.org/en/docs/Migrate_apps_from_Internet_Explorer_to_Mozilla") }}

這篇文章描述 IE 與 Mozilla 瀏覽器之間在程式上的差異,協助您將 IE-only 網頁改寫為 Mozilla 通用網頁。

簡介

Netscape 當初決定要製作 Mozilla 瀏覽器時刻意決定要支援 W3C 標準,因此 Mozilla 並不能完全回溯相容 Netscape Navigator 4.x 及 Microsoft Internet Explorer 的自有程式。舉例來說,Mozilla 不支援稍候會討論的 <layer> 標籤。此外,有些在 W3C 標準觀念尚未普及前製作的瀏覽器(如 Internet Explorer 4)內含各式怪異的花招,我們稱為怪癖(Quirk),而為了相容這些舊瀏覽器的模式便稱為 Quirks 模式。本文稍後也會討論 Mozilla 的 Quirks 模式。

我也會闡述其他 Mozilla 支援、但還沒有 W3C 相關規格的非標準技術,如 XMLHttpRequest 及 Rich-text 編輯功能。此處指的 W3C 規格包括:

跨瀏覽器程式小技巧

雖然這世上有所謂的 Web 標準,但不同的瀏覽器作法依然大不相同(即使是同一個瀏覽器,也可能因為作業系統差別而相異)。許多瀏覽器(如 Internet Explorer)在 W3C 規格形成前便提供某些功能,卻在標準制訂後忘了修改既有支援程式以符合標準。

在我闡述 Mozilla 與 Internet Explorer 相異之處前,我會先講點小技巧,讓你的 Web 應用程式容易擴充、在未來略事修改便能相容新瀏覽器。

不同瀏覽器下的某相同功能,往往也有不同的 API,所以在某些程式中你會發現不少 if() else() 程式區段,以便區分不同的瀏覽器。以下程式是寫給 Internet Explorer 用的:

. . . 

var elm; 

if (ns4) 
  elm = document.layers["myID"]; 
else if (ie4) 
  elm = document.all["myID"]

上面這段程式稱不上容易擴充,如果你要多相容一種瀏覽器就得改寫一次。

要排除遇到新的瀏覽器就要重寫網頁碼的情形,最容易的方法,就是把功能「抽」出來。與其使用一堆 if() else(),不如將常用的程式片段獨立為一個函式以提高效率。如此一來不但程式易讀,要支援更多瀏覽器也方便些:

var elm = getElmById("myID"); 

function getElmById(aID){ 
  var element = null; 

  if (isMozilla || isIE5) 
    element = document.getElementById(aID) 
  else if (isNetscape4) 
   element = document.layers[aID] 
  else if (isIE4) 
    element = document.all[aID]; 

  return element; 
} 

以上的程式仍得處理瀏覽器偵測的問題,通常這要靠 useragent 字串來解決,例如:

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016 

雖然 useragent 字串提供瀏覽器的詳細資訊,但處理這段字串的程式碰上新瀏覽器時還是有可能出錯,此時便需修改程式。

如果瀏覽器種類無關緊要(好比你已經把不支援的瀏覽器全都擋在門外了),那麼依據瀏覽器的能力來判別會比較好一點。通常可以用 JavaScript 來測試必備的功能,舉例來說,與其使用這樣的程式碼:

if (isMozilla || isIE5) 

還不如換條路走:

if (document.getElementById) 

這樣也可以讓其他支援此方法的瀏覽器(如 Opera 或 Safari)正常使用,無須更動程式。

而依據 useragent 字串辨識瀏覽器也並非一無是處,例如在檢查瀏覽器是否符合最低需求或除錯時都有其用途。

JavaScript也允許順序條件語言(inline conditional statements)以助於代碼的可讀性:

JavaScript 也支援判斷句簡寫法,協助你將程式寫得更易讀:

var foo = (condition) ? conditionIsTrue : conditionIsFalse; 

舉例而言,要取用某元素,可以寫為:

 
function getElement(aID){ 
  return (document.getElementById) ? document.getElementById(aID)
                                   : document.all[aID];
} 

Mozilla 與 Internet Explorer 的差別

首先,我要討論Mozilla和IE在表現HTML行為上的差別。

工具提示(tooltips)

老牌的瀏覽器透過在超連結和利用 alt 屬性值的 HTML 中導入工具提示來作為工具提示的內容。 最新的 W3C HTML specification 建立了 title 這個屬性,它包含超連結的詳細說明。 現代的瀏覽器會使用 title 的屬性來顯示工具提示,而且 mozilla 只支援 title 屬性,並不支援 alt 屬性。

HTML 特殊字元(entities)

HTML 標籤可以是一些在 W3 standards body 中已定義的字元。 您可以利用它們的數值或字符來代替字元。 舉例來說,您可以利用 &#160; 或等同的字符參考資料 &nbsp; 來代替空白鍵。

有一些很老很老的瀏覽器,像是 Internet Explorer ,它們允許在特殊字元後面拿走;(分號(:

&nbsp Foo 
&nbsp&nbsp Foo 

Mozilla 依然會把 &nbsp 當作空白鍵,既使這樣違反了 W3C 標準(W3C specification)。 但如果 &nbsp 後面直接跟上一些其他的字元,瀏覽器就不會轉換它。 範例:

&nbsp12345 

這行程式碼在 Mozilla 中就不會被執行,因為它違反了 W3 標準(W3 standard)。請使用正確的格式(&nbsp;)來避免瀏覽器與瀏覽器之間的差異性。

DOM 差異

文件物件模型(The Document Object Model,簡稱DOM)是一個裝載著文件元素的樹狀結構。你可以熟練地透過已成為 W3C 標準的 JavaScript API 來操作 DOM。然而在 W3C 標準建立以前, Netscape 4 和 IE 4 實作了一些類似的 API。 Mozilla 僅在使用 W3C 標準無法達成這些 API 的效果時才予以實作。

存取元素

如果你想以跨瀏覽器的方式來取得某個元素的參考,請使用document.getelementById(aID) 方法,這個方法不僅可以在 IE 5.0+ 和 Mozilla 上正常運作,它還是 DOM Level 1 的規範。

Mozilla 不能夠以 document.elementName 或是元素名稱來存取元素,而 IE 可以(名為全域名稱污染)。 Mozilla 也不支援 Netscape 4 的 document.layers 和 IE 的 document.all。 而 document.getElementById 可以讓你取得某個元素,你還可以使用 document.layersdocument.all 指定一個 tag 名稱來取得一串文件元素,像是全部的 <div> 元素。

在 W3C DOM Level 1 的規範中,JavaScript 應透過 getElementsByTagName() 取得相同標籤(tag)下的元素。這個方法會傳回一個陣列,同時這個方法也可以呼叫 document 或其他節點下的元素。如果你想取得,你可以透過 getElementsByTagName("*") 來取得整個 DOM 下的元素陣列。

就如下面表格一,DOM Level 1 經常被用來移動或者隱藏元素。當一個 HTML 元素可以隨意移動時,Netscape 4 所使用的 <layer> 標籤就不被 Mozilla 支援,你可以使用如同 Internet Explorer 的 <div>。根據 HTML 規範,這個標籤可以在 Mozilla 正常運行的。

 

表格一 - 用於存取元素的方法

方法 描述
document.getElementById( aId ) 回傳文件中 ID 值為 aId 元素的。
document.getElementsByTagName( aTagName ) 回傳文件中標籤名稱為 aTagName 的元素

縱橫 DOM

Mozilla 支援透過 JavaScript 存取 DOM 樹狀圖的 W3C DOM APIs (詳見表格二)。透過他可以讀取文件中的任何一個節點。Internet Explorer 也支援這個 APIs,同時也支援一些過時的方法,像是 children

 

表格二 - 縱橫 DOM 的方法

屬性/方法 描述
childNodes 回傳一個該元素下所有子節點的陣列。
firstChild 回傳該元素下的第一個子節點。
getAttribute( aAttributeName ) 回傳 aAttributeName 的值。
hasAttribute( aAttributeName ) 回傳一個關於節點 aAttributeName 是否有屬性的布林值。
hasChildNodes() 回傳一個關於該節點下是否仍含有子節點的布林值。
lastChild 回傳該元素下的最後一個子節點。
nextSibling 回傳當下節點後的下一個節點。
nodeName 回傳一個當下節點名稱的字串。
nodeType 回傳該節點的類型。
數值 描述
1 元素節點(Element Node)
2 屬性節點(Attribute Node)
3 文字節點(Text Node)
4 CDATA 段落節點(CDATA Section Node)
5 實體參引節點(Entity Reference Node)
6 實體節點(Entity Node)
7 處理指令(Processing Instruction Node)
8 註解節點(Comment Node)
9 文件節點(Document Node)
10 文件型別(Document Type Node)
11 文件片段(Document Fragment Node)
12 記法節點(Notation Node)
     *譯注:目前參照 中央研究院計算中心曾士熊先生提供 SGML 名詞部份的翻譯內容,其中並不包含「文件片段(Document Fragment Node)」
nodeValue 回傳當下節點的值。當節點中存在文字或文段,如文字和註解節點時,此方法會回傳他們的字串值。當節點為屬性節點(attribute node)時,此方法將會回傳屬性值。除此之外,其餘的節點類型都會回傳 null。 
ownerDocument 回傳存在於當下節點的 document 物件。
parentNode 回傳當前節點的父節點。
previousSibling 回傳在該節點之前的節點。
removeAttribute( aName ) 從當前的節點中移除 aName 屬性。
setAttribute( aName, aValue ) 將 aName 屬性的值更改為 aValue。

在 Internet Explorer 中有個不正常的怪癖(quirk),上表中有許多方法會略過自動產生的空白文字節點。請注意,在 Mozilla 中這些並不會略過,所以有時候你必須區別開這些節點。每一個節點都有它的 nodeType 屬性。舉例來說,元素節點的類型是 1;而文字節點是 3、註解節點是 8(詳見表格二 - nodeType)。最好區別開這些空白文字節點的辦法就是指處裡節點類型為 1 的子節點:

HTML部分: 
  <div id="foo">
    <span>Test</span>
  </div>

JavaScript部分: 
  var myDiv = document.getElementById("foo"); 
  var myChildren = myXMLDoc.childNodes; 
  for (var i = 0; i < myChildren.length; i++) { 
    if (myChildren[i].nodeType == 1){ 
      // 元素節點
    }
  }

內容建立及處理

Mozilla 支援一些比較舊的動態增加 DOM 內容的方法,像是

document.writedocument.open 和 document.close。 

Mozilla 也支援 Internet Explorer 的 innerHTML 方法,這個方法可以用來處理所有的節點。即使這個方法無效,Mozilla 還支援 outerHTML (這個方法包含該元素,它與 innerHTML 有一定的差異) 和 innerText (用於存取或修改節點的文字,功能與 Mozilla 裡的 textContent 差不多)。

Internet Explorer 中存在著許多不規範也不被 Mozilla 的內容處理方法,包括回傳參數、插入數值和插入元素到節點中。像是 getAdjacentElementinsertAdjacentHTML 等。表格三中敘述了 W3C 定義的內容處理方法,它們適用於所有的 DOM 節點。

 

表格三 - Mozilla 使用的內容處理方法

方法 描述
appendChild( aNode ) 建立一個新的子節點,並回傳新子節點的參照值。
cloneNode( aDeep ) 複製該節點並且傳回複製後的節點。如果 aDeep 的值「成立」,那個這個方法會把該節點下所有的子節點複製到新的節點。
createElement( aTagName ) 建立並回傳一個沒有母節點(即上層沒有節點)的節點。該節點的名稱為 aTagName 。
createTextNode( aTextValue ) 建立並回傳一個沒有母節點的文字節點,該節點值為 aTextValue。
insertBefore( aNewNode, aChildNode ) 把 aNewNode 插入到 aChildNode 之前。(兩者都必須在當前的節點下)
removeChild( aChildNode ) 移除 aChildNode 並回傳一個參照值。
replaceChild( aNewNode, aChildNode ) 用 aChildNode 替代 aNewNode,並且回傳一個移除節點的參照值。

文件片段

因為效能的緣故,你可以在記憶體中創建 document 而非在現存的 DOM 上做動作。 DOM Level 1 Core 引入了 document fragments,這是一個輕量化的 document 且支援了部份既有可用的 document interface。舉例來說,他雖不支援 getElementById 但卻支援 appendChild 。你可以很容易的按照現存的的 document 來創建  document fragments 。

在 Mozilla 中,要創造新的 document fragments 只需要使用 document.createDocumentFragment(),之後你便可取得一個空的 document fragment。

Internet Explorer 在實做 document fragment 上並未按照標準的 W3C standard 。倘若你在 IE 中調用此功能,只能拿回一個 regular document 而非 document fragment。

JavaScript 差異

Mozilla 與 Internet Explorer 之間最大的差別就是 JavaScript。 這些問題通常存在於瀏覽器所公佈的 JavaScript APIs,像是 DOM hooks。 這兩種瀏覽器各自佔有一部份 JavaScript 核心的差異性;這些遇到的問題通常也和時間有關。

JavaScript 日期差異

getYear 這個函數是唯一 Date 中的不同點。根據 ECMAScript specification(JavaScript 也遵循這個 specification),這個函式不是 Y2k-compliant 。假設在 2004 年時執行 new Date().getYear(),它會回傳 "104" 。根據 ECMAScript specification , getYear 會回傳年份減去 1900,原意是回傳 "98" 來表示 1998。getYear 在 ECMAScript Version 3 時被 getFullYear() 所代替。 當 mozilla 繼續遵循規範時,Internet Explorer 已經把 getYear() 修改成像 getFullYear() 的工作方式,使它成為Y2k-compliant。

JavaScript 執行差異

不同的瀏覽器使用不同的方法執行 JavaScript。舉例來說,下面的程式碼假設當 script 執行的時候 div 節點已經存在於 DOM:

...
<div id="foo">Loading...</div>

<script> 
  document.getElementById("foo").innerHTML = "Done."; 
</script> 

無論如何,這都不能夠確定元素(elements)是否存在。要確認所有的元素都存在,您應該將 onload 事件擺在 <body> 標籤:

<body onload="doFinish()"> 

<div id="foo">Loading...</div> 

<script> 
  function doFinish() { 
    var element = document.getElementById("foo");
	  element.innerHTML = "Done."; 
  }
</script> 
... 

像這樣與時間相關的問題也和硬體有關-較慢的系統可以顯示出較快的系統中隱藏的臭蟲(bugs)。 window.open 是一個具體的例子:  

<script> 
  function doOpenWindow(){ 
    var myWindow = window.open("about:blank"); 
    myWindow.location.href = "http://www.ibm.com"; 
  }
</script> 

這段程式碼的問題是: window.open 的時程是非同步的-它不會阻擋 JavaScript 的執行,直到所有的新視窗載入完畢。 因此,您應該在在載入新視窗完畢後才執行 window.open 。 您可以透過 在新視窗中利用 onload 執行 window.opener 來回到原本開啟新視窗的視窗(母體)。

JavaScript 產生之 HTML 差異

  在 JavaScript 中,我們可以透過 document.write 來從字串產生 HTML 程式碼。但這有個值得注意的地方在於,要是你的內嵌碼中中含有 <script> tag 會發生什麼事?當你的目標頁面處於 <a href="#html_modes">strict rendering mode</a> 下時,它將會解析位於  <script> 和  </script>  中的內容。讓我們看個例子:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
... 
<script> 
  document.write("<script>alert("Hello")</script>") 
</script> 

  因為目前處於 strict mode 下,Mozilla 的解析器 (parser) 將會查看介於 <script> 和 </script>中的內容。這是因為在 strict mode 下解析器並不認得任何語言。但假如處在 quirks mode 下,解析器卻識得 JavaScript 語法。而事實上,Internet Explorer 總是處於 quirks mode 下 - 它並不真正之支援 XHTML。一個比較兩全其美的作法是將該內容分割成兩個部份:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
... 
<script> 
  document.write("<script>alert("Hello")</" + "script>") 
</script> 

JavaScript 除錯

Mozilla provides several ways to debug JavaScript-related issues found in applications created for Internet Explorer. The first tool is the built-in JavaScript console, shown in Figure 1, where errors and warnings are logged. You can access it in Mozilla by going to Tools -> Web Development -> JavaScript Console, or in Firefox (the standalone browser product from Mozilla) at Tools -> JavaScript Console.

 

Figure 1. JavaScript console

Javascript Console

The JavaScript console can show the full log list or just errors, warnings, and messages. The error message in Figure 1 says that at aol.com, line 95 tries to access an undefined variable called is_ns70. Clicking on the link will open Mozilla's internal view source window with the offending line highlighted.

The console also allows you to evaluate JavaScript. To evaluate the entered JavaScript syntax, type in 1+1 into the input field and press Evaluate, as Figure 2 shows.

 

Figure 2. JavaScript console evaluating

JavaScript Console evaluating

Mozilla's JavaScript engine has built-in support for debugging, and thus can provide powerful tools for JavaScript developers. Venkman, shown in Figure 3, is a powerful, cross-platform JavaScript debugger that integrates with Mozilla. It is usually bundled with Mozilla releases; you can find it at Tools -> Web Development -> JavaScript Debugger. For Firefox, the debugger isn't bundled; instead, you can download and install it from the Venkman Project Page. You can also find tutorials at the development page, located at the Venkman Development Page.

 

Figure 3. Mozilla's JavaScript debugger

Mozilla's JavaScript debugger

The JavaScript debugger can debug JavaScript running in the Mozilla browser window. It supports such standard debugging features as breakpoint management, call stack inspection, and variable/object inspection. All features are accessible through the user interface or through the debugger's interactive console. With the console, you al can execute arbitrary JavaScript in the same scope as the JavaScript currently being debugged.

CSS 差異

與 Internet Explorer 和其他的瀏覽器比較之下, Mozilla 擁有最強大的 Cascading Style Sheets 4(即 CSS) 支援, 包含大部份的 CSS1、CSS2 和部份的 CSS3 。

對於下列敘述的問題, Mozilla 會在 JavaScript 控制台中發出警告。 如果您遇到了 CSS 的相關問題,請確認 JavaScript 控制台。

CSS 檔無法套用:MIME Type 問題

CSS 定義的相關檔沒有被讀取是 CSS 的相關問題中最常見的。 這通常是伺服器將 CSS 檔案送出了錯誤的 MIME Type 。 CSS 說明書 ( CSS specification ) 中提到:「 CSS 檔案應該被作為 text/css mimetype 。」 當網頁處於嚴格的規範模式 ( strict standards mode )時, Mozilla 將遵循並只載入以 text/css 作為 mimetype 的 CSS 檔案。 在 Internet Explorer 中,無論 mimetype 是甚麼, CSS 檔案都會被載入。 當網頁的 doctype ( document type,檔案類型 ) 在網頁的開頭被指定時,他們會進入嚴格的標準模式。 要解決這個問題,您可以修改正確的 mimetype 或移除 doctype。 我們會在下個章節中討論更多關於 doctype。

CSS 單位

有很多網路應用程式都不在他們的 CSS 中加上單位,尤其是利用 JavaScript 設定 CSS 的時候。 當網頁不執行在標準模式時,Mozilla 不會回報錯誤。 因為 Internet Explorer 並非真正的支援 XHTML ,它不在乎有沒有具體的單位描述。 如果網頁處於嚴格的標準描述下,並且沒有使用單位,那麼 Mozilla 將忽略以下的 style :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html> 
  <body> 
    // works in strict mode 
    <div style="width:40px; border:1px solid black;">
      Text
    </div>

    // will fail in strict mode 
    <div style="width:40; border:1px solid black;">
      Text
    </div>
  </body> 
</html> 

因為上述的範例中有一個規範的 doctype (檔案類型),所以網頁將執行在嚴格的標準模式下。 第一個 div 標籤會套用 40 像素的寬度,因為它有單位,但是第二個 div 標籤將不會套用指定的寬度,因此會套用預設的 100% 寬度。 透過 JavaScript 設定寬度將會得到一樣的結果。

JavaScript 及 CSS

既然 Mozilla 支援 CSS 標準,它同時也支援透過 JavaScript 設定 CSS 的 CSS DOM。 您可以透過 style 標籤讀取、移除和修改 CSS 的屬性規則:

<div id="myDiv" border:1px solid black;">
  Text
</div>

<script> 
  var myElm = document.getElementById("myDiv"); 
  myElm.style.width = "40px"; 
</script> 

您可以利用這種方式來延伸 css 的屬性。再次強調,如果網頁處於標準模式,您必須加上單位,否則 Mozilla 將忽略指令。 當您要查詢變數時,透過 .style.width 來達成,在 Mozilla 和 Internet Explorer 中,傳回的值中會包含單位,也就是傳回了一串字串。 您可以利用 parseFloat("40px") 將字串轉換成數值。

CSS 溢出部分(overflow)差異

CSS 增加了溢出(overflow)的概念,它允許您定義如何處理溢出部份;舉例來說,當 div 內容指定的高度高於 div 的高度時, CSS 規範(CSS standard)中定義了如果程式中沒有定義溢出的相關設定, div 的內容將會溢出。 但是 Internet Explorer 仍然不會遵循相關規範,並且會為了留住內容而擴張 div 的高度。 下面的例子表現了這個差異性:

<div style="height:100px; border: 1px solid black;"> 
  <div style="height:150px; border: 1px solid red; margin:10px;">
    a
  </div> 
</div> 

就像你在圖片四看到的,Mozilla 依照了 CSS 規範做出了判斷。 規範中提到了在這個情況下,因為 div 的內部高過它的母體,所以它溢出到了按鈕的地方。 如果您這麼愛 Internet Explorer 的行為,就不要在母體(即 div )加上 height 這個屬性。

 

圖片四:div溢出部份

DIVdiv溢出部份

hover(滑鼠移上某元素)效果差異

在一些網站上存在著 Internet Explorer 的非標準 CSS hover。 在 Mozilla 中,通常當滑鼠滑入的時候,利用改變 Text Style 來顯示它自己。 這是因為 a:hover ,在 Internet Explorer 中的 CSS 解析器對應 HTML 中錨點(anchor)的是 <a href="" />,而不是 <a name="" /> 由於作者將錨點設定標記(anchor-setting markup)套用進了區塊,所以造成了文字的顏色變化:

CSS: 
  a:hover {color:green;} 

HTML: 
  <a href="foo.com">This text should turn green when you hover over it.</a>

  <a name="anchor-name"> 
    This text should change color when hovered over, but doesn't in Internet Explorer. 
  </a> 

Mozilla 遵循 CSS 說明書 ( CSS specification )並且在這個例子中會把顏色變成綠色。 您可以使用這兩種方法來讓 Mozilla 擁有像 Internet Explorer 的效果,並且當滑鼠滑入時不會改變文字的顏色:

  • 其一,您可以把 CSS 的規則改成 a:link:hover {color:green;},這樣只會當該元素是超連結(有 href 屬性),才會改變顏色。
  • 其二,您可以修改標記,並在文字的開頭之前關閉已打開的 <a /> -採用這個方法的話,錨點(anchor)會是有效的。

Quirks 模式、標準模式

  在舊的瀏覽器上 (如 Internet Explorer 4),網頁可能會被以一種被不完全正確的方式渲染網頁。當 Mozilla 企圖成為一個和標準相容的瀏覽器的情況下,它採取三種不同方式來處理在這些不太合標準的渲染方式下開發的既有網頁。你可以在  Mozilla 瀏覽器中的  View -> Page Info (或 Ctrl-i) 下查看目前處於哪種模式。而該採取怎樣的模式則取決於該頁面的 doctype。

  Doctypes (document type declarations) 看起來是:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  藍色部份稱為 public identifier,而綠色部份是為 system identifier (以 URI 方式描述)。

Standards Mode (標準模式)

  Standards mode 是最嚴謹的渲染模式。它將完全按照 W3C HTML 以及 CSS specification 來處理,並且不支援任何除此之外的寫法。 Mozilla 會在以下情形中使用此模式:

  • 當頁面是以 text/xml mimetype 或任何其他 XML 及 XHTML mimetype 發送時
  • 採用除了 IBM doctype 之外的任何 "DOCTYPE HTML SYSTEM" doctype (例如 <!DOCTYPE HTML SYSTEM "http://www.w3.org/TR/REC-html40/strict.dtd">)
  • 不知名的 doctypes 或沒有提供 DTDs 的 doctypes 

Almost Standards mode (近乎標準模式)

Mozilla introduced almost standards mode for one reason: a section in the CSS 2 specification breaks designs based on a precise layout of small images in table cells. Instead of forming one image to the user, each small image ends up with a gap next to it. The old IBM homepage shown in Figure 5 offers an example.

 

Figure 5. Image gap

Image Gap

Almost standards mode behaves almost exactly as standards mode, except when it comes to an image gap issue. The issue occurs often on standards-compliant pages and causes them to display incorrectly.

Mozilla uses almost standards mode for the following conditions:

  • For any "loose" doctype (for example, <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">, <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">)
  • For the IBM doctype (<!DOCTYPE html SYSTEM "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd">)

You can read more about the image gap issue.

Quirks Mode (怪癖模式)

  以目前情況來說,網路上充斥著許多不完全符合標準規範的網頁。這些不合標準的網頁,卻和有著 bug 的瀏覽器配合的很好。舉例來說,在以前Netscape 居市場領導地位時,便有著 bug。而 IE 誕生石,為了能和那些網頁相容,「繼承」了這些 bug 們。對於在之後才來到市場上的新一代瀏覽器們來說,這些 bug 們便被稱為 quirks (但他們大都能向下相容於這些網頁)。值得注意的是,因為這些既有網頁並非按照規格設計,所以新瀏覽器在渲染時得花上更多時間。不幸的是,絕大多數的網頁都有賴新瀏覽器們以此模式渲染。

Mozilla 會在以下情況使用此模式:

  • 當網頁不指明 doctype 時
  • 當 doctypes 沒有 system identifier 時(例如 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">)

For further reading, check out: List of Quirks and List of Doctypes and What Modes They Cause.

 

事件差異

Mozilla and Internet Explorer are almost completely different in the area of events. The Mozilla event model follows the W3C and Netscape model. In Internet Explorer, if a function is called from an event, it can access the event object through window.event. Mozilla passes an event object to event handlers. They must specifically pass the object on to the function called through an argument. A cross-browser event handling example follows:

<div onclick="handleEvent(event)">Click me!</div> 

<script> 
  function handleEvent(aEvent) { 
    // if aEvent is null, means the Internet Explorer event model, 
    // so get window.event. 
    var myEvent = aEvent ? aEvent : window.event; 
  }
</script> 

The properties and functions that the event object exposes are also often named differently between Mozilla and Internet Explorer, as Table 4 shows.

 

Table 4. Event properties differences between Mozilla and Internet Explorer

Internet Explorer Name Mozilla Name Description
altKey altKey Boolean property that returns whether the alt key was pressed during the event.
cancelBubble stopPropagation() Used to stop the event from bubbling farther up the tree.
clientX clientX The X coordinate of the event, in relation to the client.
clientY clientY The Y coordinate of the event, in relation to the client.
ctrlKey ctrlKey Boolean property that returns whether the Ctrl key was pressed during the event.
fromElement relatedTarget For mouse events, this is the element from which the mouse moved away.
keyCode keyCode For keyboard events, this is a number representing the key that was pressed. It is 0 for mouse events.
returnValue preventDefault() Used to prevent the event's default action from occurring.
screenX screenX The X coordinate of the event, in relation to the screen.
screenX screenY The Y coordinate of the event, in relation to the screen.
shiftKey shiftKey Boolean property that returns whether the Shift key was pressed during the event.
srcElement target The element to which the event was originally dispatched.
toElement currentTarget For mouse events, this is the element to which the mouse moved.
type type Returns the name of the event.

加上事件控制式

Mozilla supports two ways to attach events through JavaScript. The first, supported by all browsers, sets event properties directly on objects. To set a click event handler, a function reference is passed to the object's onclick property:

<div id="myDiv">Click me!</div>

<script>
  function handleEvent(aEvent) {
    // if aEvent is null, means the Internet Explorer event model,
    // so get window.event.
    var myEvent = aEvent ? aEvent : window.event;
  }

  function onPageLoad(){
    document.getElementById("myDiv").onclick = handleEvent;
  } 
</script>

Mozilla fully supports the W3C standard way of attaching listeners to DOM nodes. You use the addEventListener() and removeEventListener() methods, and have the benefit of being able to set multiple listeners for the same event type. Both methods require three parameters: the event type, a function reference, and a boolean denoting whether the listener should catch events in their capture phase. If the boolean is set to false, it will only catch bubbling events. W3C events have three phases: capturing, at target, and bubbling. Every event object has an eventPhase attribute indicating the phase numerically (0 indexed). Every time you trigger an event, the event starts at the DOM's outermost element, the element at the top of the DOM tree. It then walks the DOM using the most direct route toward the target, which is the capturing phase. When the event reaches the target, the event is in the target phase.  After arriving at the target, it walks up the DOM tree back to the outermost node; this is bubbling. Internet Explorer's event model only has the bubbling phase; therefore, setting the third parameter to false results in Internet Explorer-like behavior:

<div id="myDiv">Click me!</div> 

<script> 

  function handleEvent(aEvent) {
    // if aEvent is null, it is the Internet Explorer event model,
    // so get window.event.
    var myEvent = aEvent ? aEvent : window.event;
  }

  function onPageLoad() {
    var element = document.getElementById("myDiv");
    element.addEventListener("click", handleEvent, false);
  }
</script>

One advantage of addEventListener() and removeEventListener() over setting properties is that you can have multiple event listeners for the same event, each calling another function. Thus, to remove an event listener requires all three parameters be the same as the ones you use when adding the listener.

Mozilla does not support Internet Explorer's method of converting <script> tags into event handlers, which extends <script> with for and event attributes (see Table 5). It also does not support the attachEvent and detachEvent methods. Instead, you should use the addEventListener and removeEventListener methods. Internet Explorer does not support the W3C events specification.

 

Table 5. Event method differences between Mozilla and Internet Explorer

Internet Explorer Method Mozilla Method Description
attachEvent(aEventType, aFunctionReference) addEventListener(aEventType, aFunctionReference, aUseCapture) Adds an event listener to a DOM element.
detachEvent(aEventType, aFunctionReference) removeEventListener(aEventType, aFunctionReference, aUseCapture) Removes an event listener to a DOM element.

Rich-text 編輯

While Mozilla prides itself with being the most W3C standards-compliant browser, it does support nonstandard functionality, such as innerHTML and rich text editing, if no W3C equivalent exists.

Mozilla 1.3 introduced an implementation of Internet Explorer's designMode feature, which turns an HTML document into a rich text editor field. Once turned into the editor, commands can run on the document through the execCommand command. Mozilla does not support Internet Explorer's contentEditable attribute for making any widget editable. You can use an iframe to add a rich text editor.

Rich-text 差異

Mozilla supports the W3C standard of accessing iframe's document object through IFrameElm.contentDocument, while Internet Explorer requires you to access it through document.frames{{ mediawiki.external('\"name\"') }} and then access the resulting document:

function getIFrameDocument(aID) {
  var rv = null; 

  // if contentDocument exists, W3C compliant (Mozilla)
  if (document.getElementById(aID).contentDocument){
    rv = document.getElementById(aID).contentDocument;
  } else {
    // IE
    rv = document.frames[aID].document;
  }
  return rv;
}

Another difference between Mozilla and Internet Explorer is the HTML that the rich text editor creates. Mozilla defaults to using CSS for the generated markup. However, Mozilla allows you to toggle between HTML and CSS mode using the useCSS execCommand and toggling it between true and false. Internet Explorer always uses HTML markup.

Mozilla (CSS): 
  <span style="color: blue;">Big Blue</span> 

Mozilla (HTML): 
  <font color="blue">Big Blue</font> 

Internet Explorer: 
  <FONT color="blue">Big Blue</FONT> 

Below is a list of commands that execCommand in Mozilla supports:

 

Table 6. Rich text editing commands

Command Name Description Argument
bold Toggles the selection's bold attribute. ---
createlink Generates an HTML link from the selected text. The URL to use for the link
delete Deletes the selection. ---
fontname Changes the font used in the selected text. The font name to use (Arial, for example)
fontsize Changes the font size used in the selected text. The font size to use
fontcolor Changes the font color used in the selected text. The color to use
indent Indents the block where the caret is. ---
inserthorizontalrule Inserts an <hr> element at the cursor's position. ---
insertimage Inserts an image at the cursor's position. URL of the image to use
insertorderedlist Inserts an ordered list (<ol>) element at the cursor's position. ---
insertunorderedlist Inserts an unordered list (<ul>) element at the cursor's position. ---
italic Toggles the selection's italicize attribute. ---
justifycenter Centers the content at the current line. ---
justifyleft Justifies the content at the current line to the left. ---
justifyright Justifies the content at the current line to the right. ---
outdent Outdents the block where the caret is. ---
redo Redoes the previous undo command. ---
removeformat Removes all formatting from the selection. ---
selectall Selects everything in the rich text editor. ---
strikethrough Toggles the strikethrough of the selected text. ---
subscript Converts the current selection into subscript. ---
superscript Converts the current selection into superscript. ---
underline Toggles the underline of the selected text. ---
undo Undoes the last executed command. ---
unlink Removes all link information from the selection. ---
useCSS Toggles the usage of CSS in the generated markup. Boolean value

For more information, visit Rich-Text Editing in Mozilla.

 

XML 差異

Mozilla 對 XML 與相關的技術有很完整的支援,如對 XSLT 與 Web services 等。它也支援一些 Internet Explorer 非標準的延伸,例如 XMLHttpRequest。

Mozilla has strong support for XML and XML-related technologies, such as XSLT and Web services. It also supports some nonstandard Internet Explorer extensions, such as XMLHttpRequest.

掌控 XML

如同對於標準 HTML,對於可各方面控制 XML 檔的 DOM 的支援,Mozilla 也是依 W3C 所定的 XML DOM 規格。Mozilla 與 Internet Explorer 在 XML DOM 上的不同處大多在於 Internet Explorer 非標準的處理方式。一個常見的差異是對空白字元節點的處理。 通常在建立 XML 時,XML 節點間會有空白。 Internet Explorer 用 XMLNode.childNodes[] 時不會包括這些空白節點,但在 Mozilla 上這些節點會在 array 裡。

As with standard HTML, Mozilla supports the W3C XML DOM specification, which allows you to manipulate almost any aspect of an XML document. Differences between Internet Explorer's XML DOM and Mozilla are usually caused by Internet Explorer's nonstandard behaviors. Probably the most common difference is how they handle white space text nodes. Often when XML generates, it contains white spaces between XML nodes. Internet Explorer, when using XMLNode.childNodes[], will not contain these white space nodes. In Mozilla, those nodes will be in the array.

XML: 
  <?xml version="1.0"?> 
  <myXMLdoc xmlns:myns="http://myfoo.com"> 
    <myns:foo>bar</myns:foo> 
  </myXMLdoc>

JavaScript:
  var myXMLDoc = getXMLDocument().documentElement; 
  alert(myXMLDoc.childNodes.length); 

The first line of JavaScript 的第一行載入 XML 檔並用 documentElement 來存取它的 root 元素 (myXMLDoc)。第二行顯示子節點的數目。根據 W3C 規格,接在一起的空白與換行字符組成一個文字節點。在 Mozilla 上 myXMLdoc 節點有三個子:一個有換行字符與兩個空白的文字節點、myns:foo 節點、與另一個有換行字符的文字節點。Internet Explorer 並不遵循這個,因此上面的程式碼會顯示 "1",表示只有 myns:foo 節點。所以,如要迴走子節點並掠過文字節點,要分辨這些節點。

The first line of JavaScript loads the XML document and accesses the root element (myXMLDoc) by retrieving the documentElement. The second line simply alerts the number of child nodes. Per the W3C specification, the white spaces and new lines merge into one text node if they follow each other. For Mozilla, the myXMLdoc node has three children: a text node containing a new line and two spaces; the myns:foo node; and another text node with a new line. Internet Explorer, however, does not abide by this and will return "1" for the above code, namely only the myns:foo node. Therefore, to walk the child nodes and disregard text nodes, you must distinguish such nodes.

As mentioned earlier, every node has a nodeType attribute representing the node type. For example, an element node has type 1, while a document node has type 9. To disregard text nodes, you must check for types 3 (text node) and 8 (comment node).

XML:
  <?xml version="1.0"?>   
  <myXMLdoc xmlns:myns="http://myfoo.com"> 
    <myns:foo>bar</myns:foo> 
  </myXMLdoc>

JavaScript: 
  var myXMLDoc = getXMLDocument().documentElement; 
  var myChildren = myXMLDoc.childNodes; 

  for (var run = 0; run < myChildren.length; run++){ 
    if ( (myChildren[run].nodeType != 3) &&
          myChildren[run].nodeType != 8) ){ 
      // not a text or comment node 
    }
  }

XML data islands

Internet Explorer has a nonstandard feature called XML data islands, which allow you to embed XML inside an HTML document using the nonstandard HTML tag <xml>. Mozilla does not support XML data islands and handles them as unknown HTML tags. You can achieve the same functionality using XHTML; however, because Internet Explorer's support for XHTML is weak, this is usually not an option.

One cross-browser solution is to use DOM parsers, which parse a string that contains a serialized XML document and generates the document for the parsed XML. Mozilla uses the DOMParser class, which takes the serialized string and creates an XML document out of it. In Internet Explorer, you can achieve the same functionality using ActiveX. A new Microsoft.XMLDOM generates and has a loadXML method that can take in a string and generate a document from it. The following code shows you how:

IE XML data island: 
  .. 
  <xml id="xmldataisland"> 
    <foo>bar</foo> 
  </xml>

Cross-browser solution: 
  var xmlString = "<xml id=\"xmldataisland\"><foo>bar</foo></xml>"; 

  var myDocument; 

  if (document.implementation.createDocument){ 
    // Mozilla, create a new DOMParser 
    var parser = new DOMParser(); 
    myDocument = parser.parseFromString(xmlString, "text/xml"); 
  } else if (window.ActiveXObject){ 
    // Internet Explorer, create a new XML document using ActiveX 
    // and use loadXML as a DOM parser. 
    myDocument = new ActiveXObject("Microsoft.XMLDOM") 
    myDocument.async="false"; 

    myDocument.loadXML(xmlString);   
  }

XML HTTP request

Internet Explorer allows you to send and retrieve XML files using MSXML's XMLHTTP class, which is instantiated through ActiveX using new ActiveXObject("Msxml2.XMLHTTP") or new ActiveXObject("Microsoft.XMLHTTP"). Since there is no standard method of doing this, Mozilla provides the same functionality in the global JavaScript XMLHttpRequest object. The object generates asynchronous requests by default.

After instantiating the object using new XMLHttpRequest(), you can use the open method to specify what type of request (GET or POST) you use, which file you load, and if it is asynchronous or not. If the call is asynchronous, then give the onload member a function reference, which is called once the request has completed.

Synchronous request:

  var myXMLHTTPRequest = new XMLHttpRequest(); 
  myXMLHTTPRequest.open("GET", "data.xml", false); 

  myXMLHTTPRequest.send(null); 

  var myXMLDocument = myXMLHTTPRequest.responseXML; 

Asynchronous request:

  var myXMLHTTPRequest; 

  function xmlLoaded() { 
    var myXMLDocument = myXMLHTTPRequest.responseXML; 
  }

  function loadXML(){ 
    myXMLHTTPRequest = new XMLHttpRequest();

    myXMLHTTPRequest.open("GET", "data.xml", true);

    myXMLHTTPRequest.onload = xmlLoaded; 

    myXMLHTTPRequest.send(null); 
  }

Table 7 features a list of available methods and properties for Mozilla's XMLHttpRequest.

 

Table 7. XMLHttpRequest methods and properties

Name Description
void abort() Stops the request if it is still running.
string getAllResponseHeaders() Returns all response headers as one string.
string getResponseHeader(string headerName) Returns the value of the specified header.
functionRef onerror If set, the references function will be called whenever an error occurs during the request.
functionRef onload If set, the references function will be called when the request completes successfully and the response has been received. Use when an asynchronous request is used.
void open (string HTTP_Method, string URL)

void open (string HTTP_Method, string URL, boolean async, string userName, string password)
Initializes the request for the specified URL, using either GET or POST as the HTTP method. To send the request, call the send() method after initialization. If async is false, the request is synchronous, else it defaults to asynchronous. Optionally, you can specify a username and password for the given URL needed.
int readyState State of the request. Possible values:
Value Description
0 UNINITIALIZED - open() has not been called yet.
1 LOADING - send() has not been called yet.
2 LOADED - send() has been called, headers and status are available.
3 INTERACTIVE - Downloading, responseText holds the partial data.
4 COMPLETED - Finished with all operations.
string responseText String containing the response.
DOMDocument responseXML DOM Document containing the response.
void send(variant body) Initiates the request. If body is defined, it issent as the body of the POST request. body can be an XML document or a string serialized XML document.
void setRequestHeader (string headerName, string headerValue) Sets an HTTP request header for use in the HTTP request. Has to be called after open() is called.
string status The status code of the HTTP response.

XSLT 差異

Mozilla supports XSL Transformations (XSLT) 1.0. It also allows JavaScript to perform XSLT transformations and allows running XPATH on a document.

Mozilla requires that you send the XML and XSLT file holding the stylesheet with an XML mimetype (text/xml or application/xml). This is the most common reason why XSLT won't run in Mozilla but will in Internet Explorer. Mozilla is strict in that way.

Internet Explorer 5.0 and 5.5 supported XSLT's working draft, which is substantially different than the final 1.0 recommendation. The easiest way to distinguish what version an XSLT file was written against is to look at the namespace. The namespace for the 1.0 recommendation is http://www.w3.org/1999/XSL/Transform, while the working draft's namespace is http://www.w3.org/TR/WD-xsl. Internet Explorer 6 supports the working draft for backwards compatibility, but Mozilla does not support the working draft, only the final recommendation.

If XSLT requires you to distinguish the browser, you can query the "xsl:vendor" system property. Mozilla's XSLT engine will report itself as "Transformiix" and Internet Explorer will return "Microsoft."

<xsl:if test="system-property('xsl:vendor') = 'Transformiix'"> 
  <!-- Mozilla specific markup --> 
</xsl:if> 
<xsl:if test="system-property('xsl:vendor') = 'Microsoft'"> 
  <!-- Internet Explorer specific markup --> 
</xsl:if> 

Mozilla also provides JavaScript interfaces for XSLT, allowing a Web site to complete XSLT transformations in memory. You can do this using the global XSLTProcessor JavaScript object. XSLTProcessor requires you to load the XML and XSLT files, because it needs their DOM documents. The XSLT document, imported by the XSLTProcessor, allows you to manipulate XSLT parameters. XSLTProcessor can generate a standalone document using transformToDocument(), or it can create a document fragment using transformToFragment(), which you can easily append into another DOM document. Below is an example:

 

var xslStylesheet; 
var xsltProcessor = new XSLTProcessor(); 

// load the xslt file, example1.xsl 
var myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xsl", false); 
myXMLHTTPRequest.send(null); 

// get the XML document and import it 
xslStylesheet = myXMLHTTPRequest.responseXML; 

xsltProcessor.importStylesheet(xslStylesheet); 

// load the xml file, example1.xml 
myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xml", false); 
myXMLHTTPRequest.send(null); 

var xmlSource = myXMLHTTPRequest.responseXML; 

var resultDocument = xsltProcessor.transformToDocument(xmlSource); 

After creating an XSLTProcessor, you load the XSLT file using XMLHttpRequest. The XMLHttpRequest's responseXML member contains the XML document of the XSLT file, which is passed to importStylesheet. You then use the XMLHttpRequest again to load the source XML document that must be transformed; that document is then passed to the transformToDocument method of XSLTProcessor. Table 8 features a list of XSLTProcessor methods.

 

Table 8. XSLTProcessor methods

Method Description
void importStylesheet(Node styleSheet) Imports the XSLT stylesheet. The styleSheet argument is the root node of an XSLT stylesheet's DOM document.
DocumentFragment transformToFragment(Node source, Document owner) Transforms the Node source by applying the stylesheet imported using the importStylesheet method and generates a DocumentFragment. owner specifies what DOM document the DocumentFragment should belong to, making it appendable to that DOM document.
Document transformToDocument(Node source) Transforms the Node source by applying the stylesheet imported using the importStylesheet method and returns a standalone DOM document.
void setParameter(String namespaceURI, String localName, Variant value) Sets a parameter in the imported XSLT stylesheet.
Variant getParameter(String namespaceURI, String localName) Gets the value of a parameter in the imported XSLT stylesheet.
void removeParameter(String namespaceURI, String localName) Removes all set parameters from the imported XSLT stylesheet and makes them default to the XSLT-defined defaults.
void clearParameters() Removes all set parameters and sets them to defaults specified in the XSLT stylesheet.
void reset() Removes all parameters and stylesheets.

原文資訊

{{ languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla", "es": "es/Migrar_aplicaciones_desde_Internet_Explorer_a_Mozilla", "fr": "fr/Migration_d\'applications_d\'Internet_Explorer_vers_Mozilla", "ko": "ko/Migrate_apps_from_Internet_Explorer_to_Mozilla", "zh-cn": "cn/\u4eceInternet_Explorer\u8fc1\u79fb\u5230Mozilla" } ) }}

版本來源

<p>{{ template.Translation("http://developer.mozilla.org/en/docs/Migrate_apps_from_Internet_Explorer_to_Mozilla") }}</p>
<p>這篇文章描述 IE 與 Mozilla 瀏覽器之間在程式上的差異,協助您將 IE-only 網頁改寫為 Mozilla 通用網頁。</p>
<h3 id=".E7.B0.A1.E4.BB.8B" name=".E7.B0.A1.E4.BB.8B">簡介</h3>
<p>Netscape 當初決定要製作 Mozilla 瀏覽器時刻意決定要支援 W3C 標準,因此 Mozilla 並不能完全回溯相容 Netscape Navigator 4.x 及 Microsoft Internet Explorer 的自有程式。舉例來說,Mozilla 不支援稍候會討論的 <code>&lt;layer&gt;</code> 標籤。此外,有些在 W3C 標準觀念尚未普及前製作的瀏覽器(如 Internet Explorer 4)內含各式怪異的花招,我們稱為怪癖(Quirk),而為了相容這些舊瀏覽器的模式便稱為 Quirks 模式。本文稍後也會討論 Mozilla 的 Quirks 模式。</p>
<p>我也會闡述其他 Mozilla 支援、但還沒有 W3C 相關規格的非標準技術,如 XMLHttpRequest 及 Rich-text 編輯功能。此處指的 W3C 規格包括:</p>
<ul>
  <li><a class="external" href="http://www.w3.org/TR/html401/">HTML 4.01</a> 和 <a class="external" href="http://www.w3.org/TR/xhtml1/">XHTML 1.0/1.1</a></li>
  <li>Cascade Style Sheets (CSS): <a class="external" href="http://www.w3.org/TR/REC-CSS1">CSS Level 1</a>、<a class="external" href="http://www.w3.org/TR/REC-CSS2">CSS Level 2</a> 及部分 <a class="external" href="http://www.w3.org/Style/CSS/current-work.html">CSS Level 3</a></li>
  <li>Document Object Model (DOM): <a class="external" href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/">DOM Level 1</a>、<a class="external" href="http://www.w3.org/DOM/DOMTR#dom2">DOM Level 2</a> 及部分 <a class="external" href="http://www.w3.org/DOM/DOMTR#dom3">DOM Level 3</a></li>
  <li>Mathematical Markup Language: <a class="external" href="http://www.w3.org/Math/">MathML Version 2.0</a></li>
  <li>Extensible Markup Language (XML): <a class="external" href="http://www.w3.org/TR/REC-xml">XML 1.0</a>、<a class="external" href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a>、<a class="external" href="http://www.w3.org/TR/xml-stylesheet/">Associating Style Sheets with XML Documents 1.0</a>、<a class="external" href="http://lists.w3.org/Archives/Public/www-xml-linking-comments/2001AprJ%20un/att-0074/01-NOTE-FIXptr-20010425.htm">Fragment Identifier for XML</a></li>
  <li>XSL Transformations: <a class="external" href="http://www.w3.org/TR/xslt">XSLT 1.0</a></li>
  <li>XML Path Language: <a class="external" href="http://www.w3.org/TR/xpath">XPath 1.0</a></li>
  <li>Resource Description Framework: <a class="external" href="http://www.w3.org/RDF/">RDF</a></li>
  <li>Simple Object Access Protocol: <a class="external" href="http://www.w3.org/TR/SOAP/%20">SOAP 1.1</a></li>
  <li>ECMA-262, revision 3 (JavaScript 1.5): <a class="external" href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMA-262</a></li>
</ul>
<h3 id=".E8.B7.A8.E7.80.8F.E8.A6.BD.E5.99.A8.E7.A8.8B.E5.BC.8F.E5.B0.8F.E6.8A.80.E5.B7.A7" name=".E8.B7.A8.E7.80.8F.E8.A6.BD.E5.99.A8.E7.A8.8B.E5.BC.8F.E5.B0.8F.E6.8A.80.E5.B7.A7">跨瀏覽器程式小技巧</h3>
<p>雖然這世上有所謂的 Web 標準,但不同的瀏覽器作法依然大不相同(即使是同一個瀏覽器,也可能因為作業系統差別而相異)。許多瀏覽器(如 Internet Explorer)在 W3C 規格形成前便提供某些功能,卻在標準制訂後忘了修改既有支援程式以符合標準。</p>
<p>在我闡述 Mozilla 與 Internet Explorer 相異之處前,我會先講點小技巧,讓你的 Web 應用程式容易擴充、在未來略事修改便能相容新瀏覽器。</p>
<p>不同瀏覽器下的某相同功能,往往也有不同的 API,所以在某些程式中你會發現不少 <code>if() else()</code> 程式區段,以便區分不同的瀏覽器。以下程式是寫給 Internet Explorer 用的:</p>
<pre>
. . . 

var elm; 

if (ns4) 
  elm = document.layers["myID"]; 
else if (ie4) 
  elm = document.all["myID"]
</pre>
<p>上面這段程式稱不上容易擴充,如果你要多相容一種瀏覽器就得改寫一次。</p>
<p>要排除遇到新的瀏覽器就要重寫網頁碼的情形,最容易的方法,就是把功能「抽」出來。與其使用一堆 <code>if() else()</code>,不如將常用的程式片段獨立為一個函式以提高效率。如此一來不但程式易讀,要支援更多瀏覽器也方便些:</p>
<pre>
var elm = getElmById("myID"); 

function getElmById(aID){ 
  var element = null; 

  if (isMozilla || isIE5) 
    element = document.getElementById(aID) 
  else if (isNetscape4) 
   element = document.layers[aID] 
  else if (isIE4) 
    element = document.all[aID]; 

  return element; 
} 
</pre>
<p>以上的程式仍得處理<strong>瀏覽器偵測</strong>的問題,通常這要靠 useragent 字串來解決,例如:</p>
<pre>
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016 
</pre>
<p>雖然 useragent 字串提供瀏覽器的詳細資訊,但處理這段字串的程式碰上新瀏覽器時還是有可能出錯,此時便需修改程式。</p>
<p>如果瀏覽器種類無關緊要(好比你已經把不支援的瀏覽器全都擋在門外了),那麼依據瀏覽器的能力來判別會比較好一點。通常可以用 JavaScript 來測試必備的功能,舉例來說,與其使用這樣的程式碼:</p>
<pre>
if (isMozilla || isIE5) 
</pre>
<p>還不如換條路走:</p>
<pre>
if (document.getElementById) 
</pre>
<p>這樣也可以讓其他支援此方法的瀏覽器(如 Opera 或 Safari)正常使用,無須更動程式。</p>
<p>而依據 useragent 字串辨識瀏覽器也並非一無是處,例如在檢查瀏覽器是否符合最低需求或除錯時都有其用途。</p>
<p>JavaScript也允許順序條件語言(inline conditional statements)以助於代碼的可讀性:</p>
<p>JavaScript 也支援判斷句簡寫法,協助你將程式寫得更易讀:</p>
<pre>
var foo = (condition)&nbsp;? conditionIsTrue&nbsp;: conditionIsFalse; 
</pre>
<p>舉例而言,要取用某元素,可以寫為:</p>
<pre>
 
function getElement(aID){ 
  return (document.getElementById)&nbsp;? document.getElementById(aID)
                                  &nbsp;: document.all[aID];
} 
</pre>
<h3 id="Mozilla_.E8.88.87_Internet_Explorer_.E7.9A.84.E5.B7.AE.E5.88.A5" name="Mozilla_.E8.88.87_Internet_Explorer_.E7.9A.84.E5.B7.AE.E5.88.A5">Mozilla 與 Internet Explorer 的差別</h3>
<p>首先,我要討論Mozilla和IE在表現HTML行為上的差別。</p>
<h4 id=".E5.B7.A5.E5.85.B7.E6.8F.90.E7.A4.BA.EF.BC.88tooltips.EF.BC.89" name=".E5.B7.A5.E5.85.B7.E6.8F.90.E7.A4.BA.EF.BC.88tooltips.EF.BC.89">工具提示(tooltips)</h4>
<p>老牌的瀏覽器透過在超連結和利用 <code>alt</code> 屬性值的 HTML 中導入工具提示來作為工具提示的內容。 最新的 W3C HTML specification 建立了 <code>title</code> 這個屬性,它包含超連結的詳細說明。 現代的瀏覽器會使用 <code>title</code> 的屬性來顯示工具提示,而且 mozilla 只支援 <code>title</code> 屬性,並不支援 <code>alt</code> 屬性。</p>
<h4 id="HTML_.E7.89.B9.E6.AE.8A.E5.AD.97.E5.85.83.EF.BC.88entities.EF.BC.89" name="HTML_.E7.89.B9.E6.AE.8A.E5.AD.97.E5.85.83.EF.BC.88entities.EF.BC.89">HTML 特殊字元(entities)</h4>
<p>HTML 標籤可以是一些在 <a class="external" href="http://www.w3.org/TR/REC-html40/sgml/entities.html">W3 standards body</a> 中已定義的字元。 您可以利用它們的數值或字符來代替字元。 舉例來說,您可以利用 <code>&amp;#160;</code> 或等同的字符參考資料 <code>&amp;nbsp;</code> 來代替空白鍵。</p>
<p>有一些很老很老的瀏覽器,像是 Internet Explorer ,它們允許在特殊字元後面拿走<code>;</code>(分號(:</p>
<pre>
&amp;nbsp Foo 
&amp;nbsp&amp;nbsp Foo 
</pre>
<p>Mozilla 依然會把 <code>&amp;nbsp</code> 當作空白鍵,既使這樣違反了 W3C 標準(W3C specification)。 但如果 <code>&amp;nbsp</code> 後面直接跟上一些其他的字元,瀏覽器就不會轉換它。 範例:</p>
<pre>
&amp;nbsp12345 
</pre>
<p>這行程式碼在 Mozilla 中就不會被執行,因為它違反了 W3 標準(W3 standard)。請使用正確的格式(<code>&amp;nbsp;</code>)來避免瀏覽器與瀏覽器之間的差異性。</p>
<h3 id="DOM_.E5.B7.AE.E7.95.B0" name="DOM_.E5.B7.AE.E7.95.B0">DOM 差異</h3>
<p>文件物件模型(The Document Object Model,簡稱DOM)是一個裝載著文件元素的樹狀結構。你可以熟練地透過已成為 W3C 標準的 JavaScript API 來操作 DOM。然而在 W3C 標準建立以前, Netscape 4 和 IE 4 實作了一些類似的 API。 Mozilla 僅在使用 W3C 標準無法達成這些 API 的效果時才予以實作。</p>
<h4 id=".E5.AD.98.E5.8F.96.E5.85.83.E7.B4.A0" name=".E5.AD.98.E5.8F.96.E5.85.83.E7.B4.A0">存取元素</h4>
<p>如果你想以跨瀏覽器的方式來取得某個元素的參考,請使用<code>document.getelementById(aID)</code> 方法,這個方法不僅可以在 IE 5.0+ 和 Mozilla 上正常運作,它還是 DOM Level 1 的規範。</p>
<p>Mozilla 不能夠以 <code>document.elementName</code> 或是元素名稱來存取元素,而 IE 可以(名為<em>全域名稱污染</em>)。 Mozilla 也不支援 Netscape 4 的 <code>document.layers</code> 和 IE 的 <code>document.all</code>。 而 <code>document.getElementById</code> 可以讓你取得某個元素,你還可以使用 <code>document.layers</code> 和 <code>document.all</code> 指定一個 tag 名稱來取得一串文件元素,像是全部的 <code>&lt;div&gt;</code> 元素。</p>
<p>在 W3C DOM Level 1 的規範中,JavaScript 應透過 <code>getElementsByTagName()</code> 取得相同標籤(tag)下的元素。這個方法會傳回一個陣列,同時這個方法也可以呼叫 <code>document</code> 或其他節點下的元素。如果你想取得,你可以透過 <code>getElementsByTagName("*")</code> 來取得整個 DOM 下的元素陣列。</p>
<p>就如下面表格一,DOM Level 1 經常被用來移動或者隱藏元素。當一個 HTML 元素可以隨意移動時,Netscape 4 所使用的 <code>&lt;layer&gt;</code> 標籤就不被 Mozilla 支援,你可以使用如同 Internet Explorer 的 <code>&lt;div&gt;</code>。根據 HTML 規範,這個標籤可以在 Mozilla 正常運行的。</p>
<p>&nbsp;</p>
<p>表格一 - 用於存取元素的方法</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>方法</th>
      <th>描述</th>
    </tr>
    <tr>
      <td>document.getElementById( aId )</td>
      <td>回傳文件中 ID 值為 aId 元素的。</td>
    </tr>
    <tr>
      <td>document.getElementsByTagName( aTagName )</td>
      <td>回傳文件中標籤名稱為 aTagName 的元素</td>
    </tr>
  </tbody>
</table>
<h4 id=".E7.B8.B1.E6.A9.AB_DOM" name=".E7.B8.B1.E6.A9.AB_DOM">縱橫 DOM</h4>
<p>Mozilla 支援透過 JavaScript 存取 DOM 樹狀圖的 W3C DOM APIs (詳見表格二)。透過他可以讀取文件中的任何一個節點。Internet Explorer 也支援這個 APIs,同時也支援一些過時的方法,像是 <code>children</code>。</p>
<p>&nbsp;</p>
<p>表格二 - 縱橫 DOM 的方法</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>屬性/方法</th>
      <th>描述</th>
    </tr>
    <tr>
      <td>childNodes</td>
      <td>回傳一個該元素下所有子節點的陣列。</td>
    </tr>
    <tr>
      <td>firstChild</td>
      <td>回傳該元素下的第一個子節點。</td>
    </tr>
    <tr>
      <td>getAttribute( aAttributeName )</td>
      <td>回傳 aAttributeName 的值。</td>
    </tr>
    <tr>
      <td>hasAttribute( aAttributeName )</td>
      <td>回傳一個關於節點 aAttributeName 是否有屬性的布林值。</td>
    </tr>
    <tr>
      <td>hasChildNodes()</td>
      <td>回傳一個關於該節點下是否仍含有子節點的布林值。</td>
    </tr>
    <tr>
      <td>lastChild</td>
      <td>回傳該元素下的最後一個子節點。</td>
    </tr>
    <tr>
      <td>nextSibling</td>
      <td>回傳當下節點後的下一個節點。</td>
    </tr>
    <tr>
      <td>nodeName</td>
      <td>回傳一個當下節點名稱的字串。</td>
    </tr>
    <tr>
      <td>nodeType</td>
      <td>回傳該節點的類型。
        <table>
          <tbody>
            <tr>
              <th>數值</th>
              <th>描述</th>
            </tr>
            <tr>
              <td>1</td>
              <td>元素節點(Element Node)</td>
            </tr>
            <tr>
              <td>2</td>
              <td>屬性節點(Attribute Node)</td>
            </tr>
            <tr>
              <td>3</td>
              <td>文字節點(Text Node)</td>
            </tr>
            <tr>
              <td>4</td>
              <td>CDATA 段落節點(CDATA Section Node)</td>
            </tr>
            <tr>
              <td>5</td>
              <td>實體參引節點(Entity Reference Node)</td>
            </tr>
            <tr>
              <td>6</td>
              <td>實體節點(Entity Node)</td>
            </tr>
            <tr>
              <td>7</td>
              <td>處理指令(Processing Instruction Node)</td>
            </tr>
            <tr>
              <td>8</td>
              <td>註解節點(Comment Node)</td>
            </tr>
            <tr>
              <td>9</td>
              <td>文件節點(Document Node)</td>
            </tr>
            <tr>
              <td>10</td>
              <td>文件型別(Document Type Node)</td>
            </tr>
            <tr>
              <td>11</td>
              <td>文件片段(Document Fragment Node)</td>
            </tr>
            <tr>
              <td>12</td>
              <td>記法節點(Notation Node)</td>
            </tr>
          </tbody>
        </table>
        <pre class="eval">
     <em>*譯注:目前參照 <a class="external" href="http://xml.ascc.net/zh/utf-8/gloss.html">中央研究院計算中心曾士熊先生提供 SGML 名詞部份的翻譯內容</a>,其中並不包含「文件片段(Document Fragment Node)」</em>
</pre>
      </td>
    </tr>
    <tr>
      <td>nodeValue</td>
      <td>回傳當下節點的值。當節點中存在文字或文段,如文字和註解節點時,此方法會回傳他們的字串值。當節點為屬性節點(attribute node)時,此方法將會回傳屬性值。除此之外,其餘的節點類型都會回傳 <code>null</code>。&nbsp;</td>
    </tr>
    <tr>
      <td>ownerDocument</td>
      <td>回傳存在於當下節點的 <code>document</code> 物件。</td>
    </tr>
    <tr>
      <td>parentNode</td>
      <td>回傳當前節點的父節點。</td>
    </tr>
    <tr>
      <td>previousSibling</td>
      <td>回傳在該節點之前的節點。</td>
    </tr>
    <tr>
      <td>removeAttribute( aName )</td>
      <td>從當前的節點中移除 aName 屬性。</td>
    </tr>
    <tr>
      <td>setAttribute( aName, aValue )</td>
      <td>將 aName 屬性的值更改為 aValue。</td>
    </tr>
  </tbody>
</table>
<p>在 Internet Explorer 中有個不正常的怪癖(quirk),上表中有許多方法會略過自動產生的空白文字節點。請注意,在 Mozilla 中這些並不會略過,所以有時候你必須區別開這些節點。每一個節點都有它的 <code>nodeType</code> 屬性。舉例來說,元素節點的類型是 1;而文字節點是 3、註解節點是 8(詳見表格二 - nodeType)。最好區別開這些空白文字節點的辦法就是指處裡節點類型為 1 的子節點:</p>
<pre>
HTML部分: 
  &lt;div id="foo"&gt;
    &lt;span&gt;Test&lt;/span&gt;
  &lt;/div&gt;

JavaScript部分: 
  var myDiv = document.getElementById("foo"); 
  var myChildren = myXMLDoc.childNodes; 
  for (var i = 0; i &lt; myChildren.length; i++) { 
    if (myChildren[i].nodeType == 1){ 
      // 元素節點
    }
  }
</pre>
<h4 id=".E5.85.A7.E5.AE.B9.E5.BB.BA.E7.AB.8B.E5.8F.8A.E8.99.95.E7.90.86" name=".E5.85.A7.E5.AE.B9.E5.BB.BA.E7.AB.8B.E5.8F.8A.E8.99.95.E7.90.86">內容建立及處理</h4>
<p>Mozilla 支援一些比較舊的動態增加 DOM 內容的方法,像是</p>
<pre class="eval">
<code>document.write</code>, <code>document.open</code> 和 document.close。&nbsp;
</pre>
<p>Mozilla 也支援 Internet Explorer 的 <code>innerHTML</code> 方法,這個方法可以用來處理所有的節點。即使這個方法無效,Mozilla 還支援 <code>outerHTML</code> (這個方法包含該元素,它與 <code>innerHTML</code> 有一定的差異) 和 <code>innerText</code> (用於存取或修改節點的文字,功能與 Mozilla 裡的 <code>textContent</code> 差不多)。</p>
<p>Internet Explorer 中存在著許多不規範也不被 Mozilla 的內容處理方法,包括回傳參數、插入數值和插入元素到節點中。像是 <code>getAdjacentElement</code>、 <code>insertAdjacentHTML</code> 等。表格三中敘述了 W3C 定義的內容處理方法,它們適用於所有的 DOM 節點。</p>
<p>&nbsp;</p>
<p>表格三 - Mozilla 使用的內容處理方法</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>方法</th>
      <th>描述</th>
    </tr>
    <tr>
      <td>appendChild( aNode )</td>
      <td>建立一個新的子節點,並回傳新子節點的參照值。</td>
    </tr>
    <tr>
      <td>cloneNode( aDeep )</td>
      <td>複製該節點並且傳回複製後的節點。如果 aDeep 的值「成立」,那個這個方法會把該節點下所有的子節點複製到新的節點。</td>
    </tr>
    <tr>
      <td>createElement( aTagName )</td>
      <td>建立並回傳一個沒有母節點(即上層沒有節點)的節點。該節點的名稱為 aTagName 。</td>
    </tr>
    <tr>
      <td>createTextNode( aTextValue )</td>
      <td>建立並回傳一個沒有母節點的文字節點,該節點值為 aTextValue。</td>
    </tr>
    <tr>
      <td>insertBefore( aNewNode, aChildNode )</td>
      <td>把 aNewNode 插入到 aChildNode 之前。(兩者都必須在當前的節點下)</td>
    </tr>
    <tr>
      <td>removeChild( aChildNode )</td>
      <td>移除 aChildNode 並回傳一個參照值。</td>
    </tr>
    <tr>
      <td>replaceChild( aNewNode, aChildNode )</td>
      <td>用 aChildNode 替代 aNewNode,並且回傳一個移除節點的參照值。</td>
    </tr>
  </tbody>
</table>
<h4 id=".E6.96.87.E4.BB.B6.E7.89.87.E6.AE.B5" name=".E6.96.87.E4.BB.B6.E7.89.87.E6.AE.B5">文件片段</h4>
<p>因為效能的緣故,你可以在記憶體中創建 document 而非在現存的 DOM 上做動作。 DOM Level 1 Core 引入了 document fragments,這是一個輕量化的 document 且支援了部份既有可用的 document interface。舉例來說,他雖不支援&nbsp;<code>getElementById</code>&nbsp;但卻支援&nbsp;<code>appendChild</code>&nbsp;。你可以很容易的按照現存的的 document 來創建 &nbsp;document fragments 。</p>
<p>在 Mozilla 中,要創造新的&nbsp;document fragments 只需要使用&nbsp;<code>document.createDocumentFragment()</code>,之後你便可取得一個空的 document fragment。</p>
<p>Internet Explorer 在實做 document fragment 上並未按照標準的 W3C standard 。倘若你在 IE 中調用此功能,只能拿回一個 regular document 而非 document fragment。</p>
<h3 id="JavaScript_.E5.B7.AE.E7.95.B0" name="JavaScript_.E5.B7.AE.E7.95.B0">JavaScript 差異</h3>
<p>Mozilla 與 Internet Explorer 之間最大的差別就是 JavaScript。 這些問題通常存在於瀏覽器所公佈的 JavaScript APIs,像是 DOM hooks。 這兩種瀏覽器各自佔有一部份 JavaScript 核心的差異性;這些遇到的問題通常也和時間有關。</p>
<h4 id="JavaScript_.E6.97.A5.E6.9C.9F.E5.B7.AE.E7.95.B0" name="JavaScript_.E6.97.A5.E6.9C.9F.E5.B7.AE.E7.95.B0">JavaScript 日期差異</h4>
<p><code>getYear</code> 這個函數是唯一 <code>Date</code> 中的不同點。根據 ECMAScript specification(JavaScript 也遵循這個 specification),這個函式不是 Y2k-compliant 。假設在 2004 年時執行 <code>new Date().getYear()</code>,它會回傳 "104" 。根據 ECMAScript specification , <code>getYear</code> 會回傳年份減去 1900,原意是回傳 "98" 來表示 1998。<code>getYear</code> 在 ECMAScript Version 3 時被 <code>getFullYear()</code> 所代替。 當 mozilla 繼續遵循規範時,Internet Explorer 已經把 <code>getYear()</code> 修改成像 <code>getFullYear()</code> 的工作方式,使它成為Y2k-compliant。</p>
<h4 id="JavaScript_.E5.9F.B7.E8.A1.8C.E5.B7.AE.E7.95.B0" name="JavaScript_.E5.9F.B7.E8.A1.8C.E5.B7.AE.E7.95.B0">JavaScript 執行差異</h4>
<p>不同的瀏覽器使用不同的方法執行 JavaScript。舉例來說,下面的程式碼假設當 <code>script</code> 執行的時候 <code>div</code> 節點已經存在於 DOM:</p>
<pre>
...
&lt;div id="foo"&gt;Loading...&lt;/div&gt;

&lt;script&gt; 
  document.getElementById("foo").innerHTML = "Done."; 
&lt;/script&gt; 
</pre>
<p>無論如何,這都不能夠確定元素(elements)是否存在。要確認所有的元素都存在,您應該將 <code>onload</code> 事件擺在 <code>&lt;body&gt;</code> 標籤:</p>
<pre>
&lt;body onload="doFinish()"&gt; 

&lt;div id="foo"&gt;Loading...&lt;/div&gt; 

&lt;script&gt; 
  function doFinish() { 
    var element = document.getElementById("foo");
	  element.innerHTML = "Done."; 
  }
&lt;/script&gt; 
... 
</pre>
<p>像這樣與時間相關的問題也和硬體有關-較慢的系統可以顯示出較快的系統中隱藏的臭蟲(bugs)。 <code>window.open</code> 是一個具體的例子: &nbsp;</p>
<pre>
&lt;script&gt; 
  function doOpenWindow(){ 
    var myWindow = window.open("about:blank"); 
    myWindow.location.href = "http://www.ibm.com"; 
  }
&lt;/script&gt; 
</pre>
<p>這段程式碼的問題是: <code>window.open</code> 的時程是非同步的-它不會阻擋 JavaScript 的執行,直到所有的新視窗載入完畢。 因此,您應該在在載入新視窗完畢後才執行 <code>window.open</code> 。 您可以透過 在新視窗中利用 <code>onload</code> 執行 <code>window.opener</code> 來回到原本開啟新視窗的視窗(母體)。</p>
<h4 id="JavaScript_.E7.94.A2.E7.94.9F.E4.B9.8B_HTML_.E5.B7.AE.E7.95.B0" name="JavaScript_.E7.94.A2.E7.94.9F.E4.B9.8B_HTML_.E5.B7.AE.E7.95.B0">JavaScript 產生之 HTML 差異</h4>
<p>&nbsp; 在 JavaScript 中,我們可以透過 <code>document.write 來從字串產生 HTML 程式碼。但這有個值得注意的地方在於,要是你的內嵌碼中中含有</code>&nbsp;<code>&lt;script&gt;</code> tag 會發生什麼事?當你的目標頁面處於 &lt;a href="#html_modes"&gt;strict rendering mode&lt;/a&gt; 下時,它將會解析位於&nbsp;&nbsp;<code>&lt;script&gt; 和&nbsp;</code>&nbsp;<code>&lt;/script&gt;</code>&nbsp; 中的內容。讓我們看個例子:</p>
<pre>
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt; 
... 
&lt;script&gt; 
  document.write("&lt;script&gt;alert("Hello")&lt;/script&gt;") 
&lt;/script&gt; 
</pre>
<p>&nbsp; 因為目前處於 strict mode 下,Mozilla 的解析器 (parser) 將會查看介於 <code>&lt;script&gt;</code>&nbsp;和&nbsp;<code>&lt;/script&gt;中的內容。這是因為在 strict mode 下解析器並不認得任何語言。但假如處在</code>&nbsp;quirks mode 下,解析器卻識得 JavaScript 語法。而事實上,Internet Explorer 總是處於 quirks mode 下 - 它並不真正之支援 XHTML。一個比較兩全其美的作法是將該內容分割成兩個部份:</p>
<pre>
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt; 
... 
&lt;script&gt; 
  document.write("&lt;script&gt;alert("Hello")&lt;/" + "script&gt;") 
&lt;/script&gt; 
</pre>
<h4 id="JavaScript_.E9.99.A4.E9.8C.AF" name="JavaScript_.E9.99.A4.E9.8C.AF">JavaScript 除錯</h4>
<p>Mozilla provides several ways to debug JavaScript-related issues found in applications created for Internet Explorer. The first tool is the built-in JavaScript console, shown in Figure 1, where errors and warnings are logged. You can access it in Mozilla by going to <strong>Tools -&gt; Web Development -&gt; JavaScript Console</strong>, or in Firefox (the standalone browser product from Mozilla) at <strong>Tools -&gt; JavaScript Console</strong>.</p>
<p>&nbsp;</p>
<p>Figure 1. JavaScript console</p>
<div>
  <img alt="Javascript Console" fileid="0" src="File:zh_tw/Media_Gallery/Migrationguide-jsconsole.jpg" /></div>
<p>The JavaScript console can show the full log list or just errors, warnings, and messages. The error message in Figure 1 says that at aol.com, line 95 tries to access an undefined variable called is_ns70. Clicking on the link will open Mozilla's internal view source window with the offending line highlighted.</p>
<p>The console also allows you to evaluate JavaScript. To evaluate the entered JavaScript syntax, type in <code>1+1</code> into the input field and press <strong>Evaluate</strong>, as Figure 2 shows.</p>
<p>&nbsp;</p>
<p>Figure 2. JavaScript console evaluating</p>
<div>
  <img alt="JavaScript Console evaluating" fileid="0" src="File:zh_tw/Media_Gallery/Migrationguide-jsconsole-eval.jpg" /></div>
<p>Mozilla's JavaScript engine has built-in support for debugging, and thus can provide powerful tools for JavaScript developers. Venkman, shown in Figure 3, is a powerful, cross-platform JavaScript debugger that integrates with Mozilla. It is usually bundled with Mozilla releases; you can find it at <strong>Tools -&gt; Web Development -&gt; JavaScript Debugger</strong>. For Firefox, the debugger isn't bundled; instead, you can download and install it from the <a class="external" href="http://www.mozilla.org/projects/venkman/">Venkman Project Page</a>. You can also find tutorials at the development page, located at the <a class="external" href="http://www.hacksrus.com/%7Eginda/venkman/">Venkman Development Page</a>.</p>
<p>&nbsp;</p>
<p>Figure 3. Mozilla's JavaScript debugger</p>
<div>
  <img alt="Mozilla's JavaScript debugger" fileid="0" src="File:zh_tw/Media_Gallery/Migrationguide-venkman.jpg" /></div>
<p>The JavaScript debugger can debug JavaScript running in the Mozilla browser window. It supports such standard debugging features as breakpoint management, call stack inspection, and variable/object inspection. All features are accessible through the user interface or through the debugger's interactive console. With the console, you al can execute arbitrary JavaScript in the same scope as the JavaScript currently being debugged.</p>
<h3 id="CSS_.E5.B7.AE.E7.95.B0" name="CSS_.E5.B7.AE.E7.95.B0">CSS 差異</h3>
<p>與 Internet Explorer 和其他的瀏覽器比較之下, Mozilla 擁有最強大的 Cascading Style Sheets 4(即 CSS) 支援, 包含大部份的 CSS1、CSS2 和部份的 CSS3 。</p>
<p>對於下列敘述的問題, Mozilla 會在 JavaScript 控制台中發出警告。 如果您遇到了 CSS 的相關問題,請確認 JavaScript 控制台。</p>
<h4 id="CSS_.E6.AA.94.E7.84.A1.E6.B3.95.E5.A5.97.E7.94.A8.EF.BC.9AMIME_Type_.E5.95.8F.E9.A1.8C" name="CSS_.E6.AA.94.E7.84.A1.E6.B3.95.E5.A5.97.E7.94.A8.EF.BC.9AMIME_Type_.E5.95.8F.E9.A1.8C">CSS 檔無法套用:MIME Type 問題</h4>
<p>CSS 定義的相關檔沒有被讀取是 CSS 的相關問題中最常見的。 這通常是伺服器將 CSS 檔案送出了錯誤的 MIME Type 。 CSS 說明書 ( CSS specification ) 中提到:「 CSS 檔案應該被作為 text/css mimetype 。」 當網頁處於嚴格的規範模式 ( strict standards mode )時, Mozilla 將遵循並只載入以 text/css 作為 mimetype 的 CSS 檔案。 在 Internet Explorer 中,無論 mimetype 是甚麼, CSS 檔案都會被載入。 當網頁的 doctype ( document type,檔案類型 ) 在網頁的開頭被指定時,他們會進入嚴格的標準模式。 要解決這個問題,您可以修改正確的 mimetype 或移除 doctype。 我們會在下個章節中討論更多關於 doctype。</p>
<h4 id="CSS_.E5.96.AE.E4.BD.8D" name="CSS_.E5.96.AE.E4.BD.8D">CSS 單位</h4>
<p>有很多網路應用程式都不在他們的 CSS 中加上單位,尤其是利用 JavaScript 設定 CSS 的時候。 當網頁不執行在標準模式時,Mozilla 不會回報錯誤。 因為 Internet Explorer 並非真正的支援 XHTML ,它不在乎有沒有具體的單位描述。 如果網頁處於嚴格的標準描述下,並且沒有使用單位,那麼 Mozilla 將忽略以下的 style :</p>
<pre class="eval">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "<span class="nowiki">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</span>"&gt; 
&lt;html&gt; 
  &lt;body&gt; 
    // works in strict mode 
    &lt;div style="width:40<span class="boldcode">px</span>; border:1px solid black;"&gt;
      Text
    &lt;/div&gt;

    // will fail in strict mode 
    &lt;div style="width:40; border:1px solid black;"&gt;
      Text
    &lt;/div&gt;
  &lt;/body&gt; 
&lt;/html&gt; 
</pre>
<p>因為上述的範例中有一個規範的 doctype (檔案類型),所以網頁將執行在嚴格的標準模式下。 第一個 div 標籤會套用 40 像素的寬度,因為它有單位,但是第二個 div 標籤將不會套用指定的寬度,因此會套用預設的 100% 寬度。 透過 JavaScript 設定寬度將會得到一樣的結果。</p>
<h4 id="JavaScript_.E5.8F.8A_CSS" name="JavaScript_.E5.8F.8A_CSS">JavaScript 及 CSS</h4>
<p>既然 Mozilla 支援 CSS 標準,它同時也支援透過 JavaScript 設定 CSS 的 CSS DOM。 您可以透過 <code>style</code> 標籤讀取、移除和修改 CSS 的屬性規則:</p>
<pre>
&lt;div id="myDiv" border:1px solid black;"&gt;
  Text
&lt;/div&gt;

&lt;script&gt; 
  var myElm = document.getElementById("myDiv"); 
  myElm.style.width = "40px"; 
&lt;/script&gt; 
</pre>
<p>您可以利用這種方式來延伸 css 的屬性。再次強調,如果網頁處於標準模式,您必須加上單位,否則 Mozilla 將忽略指令。 當您要查詢變數時,透過 <code>.style.width</code> 來達成,在 Mozilla 和 Internet Explorer 中,傳回的值中會包含單位,也就是傳回了一串字串。 您可以利用 <code>parseFloat("40px")</code> 將字串轉換成數值。</p>
<h4 id="CSS_.E6.BA.A2.E5.87.BA.E9.83.A8.E5.88.86.EF.BC.88overflow.EF.BC.89.E5.B7.AE.E7.95.B0" name="CSS_.E6.BA.A2.E5.87.BA.E9.83.A8.E5.88.86.EF.BC.88overflow.EF.BC.89.E5.B7.AE.E7.95.B0">CSS 溢出部分(overflow)差異</h4>
<p>CSS 增加了溢出(overflow)的概念,它允許您定義如何處理溢出部份;舉例來說,當 <code>div</code> 內容指定的高度高於 <code>div</code> 的高度時, CSS 規範(CSS standard)中定義了如果程式中沒有定義溢出的相關設定, <code>div</code> 的內容將會溢出。 但是 Internet Explorer 仍然不會遵循相關規範,並且會為了留住內容而擴張 <code>div</code> 的高度。 下面的例子表現了這個差異性:</p>
<pre>
&lt;div style="height:100px; border: 1px solid black;"&gt; 
  &lt;div style="height:150px; border: 1px solid red; margin:10px;"&gt;
    a
  &lt;/div&gt; 
&lt;/div&gt; 
</pre>
<p>就像你在圖片四看到的,Mozilla 依照了 CSS 規範做出了判斷。 規範中提到了在這個情況下,因為 <code>div</code> 的內部高過它的母體,所以它溢出到了按鈕的地方。 如果您這麼愛 Internet Explorer 的行為,就不要在母體(即 <code>div</code> )加上 height 這個屬性。</p>
<p>&nbsp;</p>
<p>圖片四:div溢出部份</p>
<div>
  <img alt="DIVdiv溢出部份" fileid="0" src="File:zh_tw/Media_Gallery/Migrationguide-overflow.jpg" /></div>
<h4 id="hover.EF.BC.88.E6.BB.91.E9.BC.A0.E7.A7.BB.E4.B8.8A.E6.9F.90.E5.85.83.E7.B4.A0.EF.BC.89.E6.95.88.E6.9E.9C.E5.B7.AE.E7.95.B0" name="hover.EF.BC.88.E6.BB.91.E9.BC.A0.E7.A7.BB.E4.B8.8A.E6.9F.90.E5.85.83.E7.B4.A0.EF.BC.89.E6.95.88.E6.9E.9C.E5.B7.AE.E7.95.B0">hover(滑鼠移上某元素)效果差異</h4>
<p>在一些網站上存在著 Internet Explorer 的非標準 CSS hover。 在 Mozilla 中,通常當滑鼠滑入的時候,利用改變 Text Style 來顯示它自己。 這是因為 <code>a:hover</code> ,在 Internet Explorer 中的 CSS 解析器對應 HTML 中錨點(anchor)的是 <code>&lt;a href="" /&gt;</code>,而不是 <code>&lt;a name="" /&gt;</code> 由於作者將錨點設定標記(anchor-setting markup)套用進了區塊,所以造成了文字的顏色變化:</p>
<pre>
CSS: 
  a:hover {color:green;} 

HTML: 
  &lt;a href="foo.com"&gt;This text should turn green when you hover over it.&lt;/a&gt;

  &lt;a name="anchor-name"&gt; 
    This text should change color when hovered over, but doesn't in Internet Explorer. 
  &lt;/a&gt; 
</pre>
<p>Mozilla 遵循 CSS 說明書 ( CSS specification )並且在這個例子中會把顏色變成綠色。 您可以使用這兩種方法來讓 Mozilla 擁有像 Internet Explorer 的效果,並且當滑鼠滑入時不會改變文字的顏色:</p>
<ul>
  <li>其一,您可以把 CSS 的規則改成 <code>a:link:hover {color:green;}</code>,這樣只會當該元素是超連結(有 <code>href</code> 屬性),才會改變顏色。</li>
  <li>其二,您可以修改標記,並在文字的開頭之前關閉已打開的 <code>&lt;a /&gt;</code> -採用這個方法的話,錨點(anchor)會是有效的。</li>
</ul>
<h3 id="Quirks_.E6.A8.A1.E5.BC.8F.E3.80.81.E6.A8.99.E6.BA.96.E6.A8.A1.E5.BC.8F" name="Quirks_.E6.A8.A1.E5.BC.8F.E3.80.81.E6.A8.99.E6.BA.96.E6.A8.A1.E5.BC.8F">Quirks 模式、標準模式</h3>
<p>&nbsp; 在舊的瀏覽器上 (如 Internet Explorer 4),網頁可能會被以一種被不完全正確的方式渲染網頁。當 Mozilla 企圖成為一個和標準相容的瀏覽器的情況下,它採取三種不同方式來處理在這些不太合標準的渲染方式下開發的既有網頁。你可以在 &nbsp;Mozilla 瀏覽器中的 &nbsp;<strong>View -&gt; Page Info</strong> (或 Ctrl-i) 下查看目前處於哪種模式。而該採取怎樣的模式則取決於該頁面的 doctype。</p>
<p>&nbsp; Doctypes (document type declarations) 看起來是:</p>
<p><code>&lt;!DOCTYPE HTML PUBLIC <span style="color:blue;">"-//W3C//DTD HTML 4.01 Transitional//EN"</span> <span style="color:green;">"<span class="nowiki">http://www.w3.org/TR/html4/loose.dtd</span>"</span>&gt;</code></p>
<p>&nbsp; 藍色部份稱為 public identifier,而綠色部份是為 system identifier (以 URI 方式描述)。</p>
<h4 id=".E6.A8.99.E6.BA.96.E6.A8.A1.E5.BC.8F" name=".E6.A8.99.E6.BA.96.E6.A8.A1.E5.BC.8F">Standards Mode (標準模式)</h4>
<p>&nbsp; Standards mode 是最嚴謹的渲染模式。它將完全按照 W3C HTML 以及 CSS specification 來處理,並且不支援任何除此之外的寫法。 Mozilla 會在以下情形中使用此模式:</p>
<ul>
  <li>當頁面是以&nbsp;<code>text/xml</code> mimetype 或任何其他 XML 及&nbsp;XHTML mimetype 發送時</li>
  <li>採用除了&nbsp;IBM doctype 之外的任何&nbsp;"DOCTYPE HTML SYSTEM" doctype (例如&nbsp;<code>&lt;!DOCTYPE HTML SYSTEM "<span class="nowiki">http://www.w3.org/TR/REC-html40/strict.dtd</span>"&gt;</code>)</li>
  <li>不知名的 doctypes 或沒有提供 DTDs 的 doctypes&nbsp;</li>
</ul>
<h4 id=".E8.BF.91.E4.B9.8E.E6.A8.99.E6.BA.96.E6.A8.A1.E5.BC.8F" name=".E8.BF.91.E4.B9.8E.E6.A8.99.E6.BA.96.E6.A8.A1.E5.BC.8F">Almost Standards mode (近乎標準模式)</h4>
<p>Mozilla introduced almost standards mode for one reason: a section in the CSS 2 specification breaks designs based on a precise layout of small images in table cells. Instead of forming one image to the user, each small image ends up with a gap next to it. The old IBM homepage shown in Figure 5 offers an example.</p>
<p>&nbsp;</p>
<p>Figure 5. Image gap</p>
<div>
  <img alt="Image Gap" fileid="0" src="File:zh_tw/Media_Gallery/Migrationguide-imagegap.jpg" /></div>
<p>Almost standards mode behaves almost exactly as standards mode, except when it comes to an image gap issue. The issue occurs often on standards-compliant pages and causes them to display incorrectly.</p>
<p>Mozilla uses almost standards mode for the following conditions:</p>
<ul>
  <li>For any "loose" doctype (for example, <code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"&gt;</code>, <code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<span class="nowiki">http://www.w3.org/TR/html4/loose.dtd</span>"&gt;</code>)</li>
  <li>For the IBM doctype (<code>&lt;!DOCTYPE html SYSTEM "<span class="nowiki">http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd</span>"&gt;</code>)</li>
</ul>
<p>You can read more about the <a href="/zh_tw/Images,_Tables,_and_Mysterious_Gaps" title="zh_tw/Images,_Tables,_and_Mysterious_Gaps">image gap issue</a>.</p>
<h4 id="Quirks_.E6.A8.A1.E5.BC.8F" name="Quirks_.E6.A8.A1.E5.BC.8F">Quirks Mode (怪癖模式)</h4>
<p>&nbsp; 以目前情況來說,網路上充斥著許多不完全符合標準規範的網頁。這些不合標準的網頁,卻和有著 bug 的瀏覽器配合的很好。舉例來說,在以前Netscape 居市場領導地位時,便有著 bug。而 IE 誕生石,為了能和那些網頁相容,「繼承」了這些 bug 們。對於在之後才來到市場上的新一代瀏覽器們來說,這些 bug 們便被稱為&nbsp;<strong>quirks</strong>&nbsp;(但他們大都能向下相容於這些網頁)。值得注意的是,因為這些既有網頁並非按照規格設計,所以新瀏覽器在渲染時得花上更多時間。不幸的是,絕大多數的網頁都有賴新瀏覽器們以此模式渲染。</p>
<p>Mozilla 會在以下情況使用此模式:</p>
<ul>
  <li>當網頁不指明 doctype 時</li>
  <li>當 doctypes 沒有 system identifier 時(例如&nbsp;<code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;</code>)</li>
</ul>
<p>For further reading, check out: <a class="external" href="http://www.mozilla.org/docs/web-developer/quirks/quirklist.html">List of Quirks</a> and <a class="external" href="http://www.mozilla.org/docs/web-developer/quirks/doctypes.html">List of Doctypes and What Modes They Cause</a>.</p>
<p>&nbsp;</p>
<h3 id=".E4.BA.8B.E4.BB.B6.E5.B7.AE.E7.95.B0" name=".E4.BA.8B.E4.BB.B6.E5.B7.AE.E7.95.B0">事件差異</h3>
<p>Mozilla and Internet Explorer are almost completely different in the area of events. The Mozilla event model follows the W3C and Netscape model. In Internet Explorer, if a function is called from an event, it can access the <code>event</code> object through <code>window.event</code>. Mozilla passes an <code>event</code> object to event handlers. They must specifically pass the object on to the function called through an argument. A cross-browser event handling example follows:</p>
<pre>
&lt;div onclick="handleEvent(event)"&gt;Click me!&lt;/div&gt; 

&lt;script&gt; 
  function handleEvent(aEvent) { 
    // if aEvent is null, means the Internet Explorer event model, 
    // so get window.event. 
    var myEvent = aEvent&nbsp;? aEvent&nbsp;: window.event; 
  }
&lt;/script&gt; 
</pre>
<p>The properties and functions that the event object exposes are also often named differently between Mozilla and Internet Explorer, as Table 4 shows.</p>
<p>&nbsp;</p>
<p>Table 4. Event properties differences between Mozilla and Internet Explorer</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Internet Explorer Name</th>
      <th>Mozilla Name</th>
      <th>Description</th>
    </tr>
    <tr>
      <td>altKey</td>
      <td>altKey</td>
      <td>Boolean property that returns whether the alt key was pressed during the event.</td>
    </tr>
    <tr>
      <td>cancelBubble</td>
      <td>stopPropagation()</td>
      <td>Used to stop the event from bubbling farther up the tree.</td>
    </tr>
    <tr>
      <td>clientX</td>
      <td>clientX</td>
      <td>The X coordinate of the event, in relation to the client.</td>
    </tr>
    <tr>
      <td>clientY</td>
      <td>clientY</td>
      <td>The Y coordinate of the event, in relation to the client.</td>
    </tr>
    <tr>
      <td>ctrlKey</td>
      <td>ctrlKey</td>
      <td>Boolean property that returns whether the Ctrl key was pressed during the event.</td>
    </tr>
    <tr>
      <td>fromElement</td>
      <td>relatedTarget</td>
      <td>For mouse events, this is the element from which the mouse moved away.</td>
    </tr>
    <tr>
      <td>keyCode</td>
      <td>keyCode</td>
      <td>For keyboard events, this is a number representing the key that was pressed. It is 0 for mouse events.</td>
    </tr>
    <tr>
      <td>returnValue</td>
      <td>preventDefault()</td>
      <td>Used to prevent the event's default action from occurring.</td>
    </tr>
    <tr>
      <td>screenX</td>
      <td>screenX</td>
      <td>The X coordinate of the event, in relation to the screen.</td>
    </tr>
    <tr>
      <td>screenX</td>
      <td>screenY</td>
      <td>The Y coordinate of the event, in relation to the screen.</td>
    </tr>
    <tr>
      <td>shiftKey</td>
      <td>shiftKey</td>
      <td>Boolean property that returns whether the Shift key was pressed during the event.</td>
    </tr>
    <tr>
      <td>srcElement</td>
      <td>target</td>
      <td>The element to which the event was originally dispatched.</td>
    </tr>
    <tr>
      <td>toElement</td>
      <td>currentTarget</td>
      <td>For mouse events, this is the element to which the mouse moved.</td>
    </tr>
    <tr>
      <td>type</td>
      <td>type</td>
      <td>Returns the name of the event.</td>
    </tr>
  </tbody>
</table>
<h4 id=".E5.8A.A0.E4.B8.8A.E4.BA.8B.E4.BB.B6.E6.8E.A7.E5.88.B6.E5.BC.8F" name=".E5.8A.A0.E4.B8.8A.E4.BA.8B.E4.BB.B6.E6.8E.A7.E5.88.B6.E5.BC.8F">加上事件控制式</h4>
<p>Mozilla supports two ways to attach events through JavaScript. The first, supported by all browsers, sets event properties directly on objects. To set a <code>click</code> event handler, a function reference is passed to the object's <code>onclick</code> property:</p>
<pre>
&lt;div id="myDiv"&gt;Click me!&lt;/div&gt;

&lt;script&gt;
  function handleEvent(aEvent) {
    // if aEvent is null, means the Internet Explorer event model,
    // so get window.event.
    var myEvent = aEvent&nbsp;? aEvent&nbsp;: window.event;
  }

  function onPageLoad(){
    document.getElementById("myDiv").onclick = handleEvent;
  } 
&lt;/script&gt;
</pre>
<p>Mozilla fully supports the W3C standard way of attaching listeners to DOM nodes. You use the <code>addEventListener()</code> and <code>removeEventListener()</code> methods, and have the benefit of being able to set multiple listeners for the same event type. Both methods require three parameters: the event type, a function reference, and a boolean denoting whether the listener should catch events in their capture phase. If the boolean is set to false, it will only catch bubbling events. W3C events have three phases: capturing, at target, and bubbling. Every event object has an <code>eventPhase</code> attribute indicating the phase numerically (0 indexed). Every time you trigger an event, the event starts at the DOM's outermost element, the element at the top of the DOM tree. It then walks the DOM using the most direct route toward the target, which is the capturing phase. When the event reaches the target, the event is in the target phase. &nbsp;After arriving at the target, it walks up the DOM tree back to the outermost node; this is <strong>bubbling</strong>. Internet Explorer's event model only has the bubbling phase; therefore, setting the third parameter to false results in Internet Explorer-like behavior:</p>
<pre>
&lt;div id="myDiv"&gt;Click me!&lt;/div&gt; 

&lt;script&gt; 

  function handleEvent(aEvent) {
    // if aEvent is null, it is the Internet Explorer event model,
    // so get window.event.
    var myEvent = aEvent&nbsp;? aEvent&nbsp;: window.event;
  }

  function onPageLoad() {
    var element = document.getElementById("myDiv");
    element.addEventListener("click", handleEvent, false);
  }
&lt;/script&gt;
</pre>
<p>One advantage of <code>addEventListener()</code> and <code>removeEventListener()</code> over setting properties is that you can have multiple event listeners for the same event, each calling another function. Thus, to remove an event listener requires all three parameters be the same as the ones you use when adding the listener.</p>
<p>Mozilla does not support Internet Explorer's method of converting &lt;script&gt; tags into event handlers, which extends &lt;script&gt; with <code>for</code> and <code>event</code> attributes (see Table 5). It also does not support the <code>attachEvent</code> and <code>detachEvent</code> methods. Instead, you should use the <code>addEventListener</code> and <code>removeEventListener</code> methods. Internet Explorer does not support the W3C events specification.</p>
<p>&nbsp;</p>
<p>Table 5. Event method differences between Mozilla and Internet Explorer</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Internet Explorer Method</th>
      <th>Mozilla Method</th>
      <th>Description</th>
    </tr>
    <tr>
      <td>attachEvent(aEventType, aFunctionReference)</td>
      <td>addEventListener(aEventType, aFunctionReference, aUseCapture)</td>
      <td>Adds an event listener to a DOM element.</td>
    </tr>
    <tr>
      <td>detachEvent(aEventType, aFunctionReference)</td>
      <td>removeEventListener(aEventType, aFunctionReference, aUseCapture)</td>
      <td>Removes an event listener to a DOM element.</td>
    </tr>
  </tbody>
</table>
<h3 id="Rich-text_.E7.B7.A8.E8.BC.AF" name="Rich-text_.E7.B7.A8.E8.BC.AF">Rich-text 編輯</h3>
<p>While Mozilla prides itself with being the most W3C standards-compliant browser, it does support nonstandard functionality, such as <code>innerHTML</code> and rich text editing, if no W3C equivalent exists.</p>
<p>Mozilla 1.3 introduced an implementation of Internet Explorer's designMode feature, which turns an HTML document into a rich text editor field. Once turned into the editor, commands can run on the document through the <code>execCommand</code> command. Mozilla does not support Internet Explorer's <code>contentEditable</code> attribute for making any widget editable. You can use an iframe to add a rich text editor.</p>
<h4 id="Rich-text_.E5.B7.AE.E7.95.B0" name="Rich-text_.E5.B7.AE.E7.95.B0">Rich-text 差異</h4>
<p>Mozilla supports the W3C standard of accessing iframe's document object through <code>IFrameElm.contentDocument</code>, while Internet Explorer requires you to access it through <code>document.frames{{ mediawiki.external('\"name\"') }}</code> and then access the resulting <code>document</code>:</p>
<pre>
function getIFrameDocument(aID) {
  var rv = null; 

  // if contentDocument exists, W3C compliant (Mozilla)
  if (document.getElementById(aID).contentDocument){
    rv = document.getElementById(aID).contentDocument;
  } else {
    // IE
    rv = document.frames[aID].document;
  }
  return rv;
}
</pre>
<p>Another difference between Mozilla and Internet Explorer is the HTML that the rich text editor creates. Mozilla defaults to using CSS for the generated markup. However, Mozilla allows you to toggle between HTML and CSS mode using the <code>useCSS</code> execCommand and toggling it between true and false. Internet Explorer always uses HTML markup.</p>
<pre>
Mozilla (CSS): 
  &lt;span style="color: blue;"&gt;Big Blue&lt;/span&gt; 

Mozilla (HTML): 
  &lt;font color="blue"&gt;Big Blue&lt;/font&gt; 

Internet Explorer: 
  &lt;FONT color="blue"&gt;Big Blue&lt;/FONT&gt; 
</pre>
<p>Below is a list of commands that execCommand in Mozilla supports:</p>
<p>&nbsp;</p>
<p>Table 6. Rich text editing commands</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Command Name</th>
      <th>Description</th>
      <th>Argument</th>
    </tr>
    <tr>
      <td>bold</td>
      <td>Toggles the selection's bold attribute.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>createlink</td>
      <td>Generates an HTML link from the selected text.</td>
      <td>The URL to use for the link</td>
    </tr>
    <tr>
      <td>delete</td>
      <td>Deletes the selection.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>fontname</td>
      <td>Changes the font used in the selected text.</td>
      <td>The font name to use (Arial, for example)</td>
    </tr>
    <tr>
      <td>fontsize</td>
      <td>Changes the font size used in the selected text.</td>
      <td>The font size to use</td>
    </tr>
    <tr>
      <td>fontcolor</td>
      <td>Changes the font color used in the selected text.</td>
      <td>The color to use</td>
    </tr>
    <tr>
      <td>indent</td>
      <td>Indents the block where the caret is.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>inserthorizontalrule</td>
      <td>Inserts an &lt;hr&gt; element at the cursor's position.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>insertimage</td>
      <td>Inserts an image at the cursor's position.</td>
      <td>URL of the image to use</td>
    </tr>
    <tr>
      <td>insertorderedlist</td>
      <td>Inserts an ordered list (&lt;ol&gt;) element at the cursor's position.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>insertunorderedlist</td>
      <td>Inserts an unordered list (&lt;ul&gt;) element at the cursor's position.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>italic</td>
      <td>Toggles the selection's italicize attribute.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>justifycenter</td>
      <td>Centers the content at the current line.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>justifyleft</td>
      <td>Justifies the content at the current line to the left.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>justifyright</td>
      <td>Justifies the content at the current line to the right.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>outdent</td>
      <td>Outdents the block where the caret is.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>redo</td>
      <td>Redoes the previous undo command.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>removeformat</td>
      <td>Removes all formatting from the selection.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>selectall</td>
      <td>Selects everything in the rich text editor.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>strikethrough</td>
      <td>Toggles the strikethrough of the selected text.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>subscript</td>
      <td>Converts the current selection into subscript.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>superscript</td>
      <td>Converts the current selection into superscript.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>underline</td>
      <td>Toggles the underline of the selected text.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>undo</td>
      <td>Undoes the last executed command.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>unlink</td>
      <td>Removes all link information from the selection.</td>
      <td>---</td>
    </tr>
    <tr>
      <td>useCSS</td>
      <td>Toggles the usage of CSS in the generated markup.</td>
      <td>Boolean value</td>
    </tr>
  </tbody>
</table>
<p>For more information, visit <a href="/zh_tw/Rich-Text_Editing_in_Mozilla" title="zh_tw/Rich-Text_Editing_in_Mozilla">Rich-Text Editing in Mozilla</a>.</p>
<p>&nbsp;</p>
<h3 id="XML_.E5.B7.AE.E7.95.B0" name="XML_.E5.B7.AE.E7.95.B0">XML 差異</h3>
<p>Mozilla 對 XML 與相關的技術有很完整的支援,如對 XSLT 與 Web services 等。它也支援一些 Internet Explorer 非標準的延伸,例如 XMLHttpRequest。</p>
<p>Mozilla has strong support for XML and XML-related technologies, such as XSLT and Web services. It also supports some nonstandard Internet Explorer extensions, such as XMLHttpRequest.</p>
<h4 id=".E6.8E.8C.E6.8E.A7_XML" name=".E6.8E.8C.E6.8E.A7_XML">掌控 XML</h4>
<p>如同對於標準 HTML,對於可各方面控制 XML 檔的 DOM 的支援,Mozilla 也是依 W3C 所定的 XML DOM 規格。Mozilla 與 Internet Explorer 在 XML DOM 上的不同處大多在於 Internet Explorer 非標準的處理方式。一個常見的差異是對空白字元節點的處理。 通常在建立 XML 時,XML 節點間會有空白。 Internet Explorer 用 <code>XMLNode.childNodes[]</code> 時不會包括這些空白節點,但在 Mozilla 上這些節點會在 array 裡。</p>
<p>As with standard HTML, Mozilla supports the W3C XML DOM specification, which allows you to manipulate almost any aspect of an XML document. Differences between Internet Explorer's XML DOM and Mozilla are usually caused by Internet Explorer's nonstandard behaviors. Probably the most common difference is how they handle white space text nodes. Often when XML generates, it contains white spaces between XML nodes. Internet Explorer, when using <code>XMLNode.childNodes[]</code>, will not contain these white space nodes. In Mozilla, those nodes will be in the array.</p>
<pre>
XML: 
  &lt;?xml version="1.0"?&gt; 
  &lt;myXMLdoc xmlns:myns="http://myfoo.com"&gt; 
    &lt;myns:foo&gt;bar&lt;/myns:foo&gt; 
  &lt;/myXMLdoc&gt;

JavaScript:
  var myXMLDoc = getXMLDocument().documentElement; 
  alert(myXMLDoc.childNodes.length); 
</pre>
<p>The first line of JavaScript 的第一行載入 XML 檔並用 <code>documentElement</code> 來存取它的 root 元素 (<code>myXMLDoc</code>)。第二行顯示子節點的數目。根據 W3C 規格,接在一起的空白與換行字符組成一個文字節點。在 Mozilla 上 <code>myXMLdoc</code> 節點有三個子:一個有換行字符與兩個空白的文字節點、<code>myns:foo</code> 節點、與另一個有換行字符的文字節點。Internet Explorer 並不遵循這個,因此上面的程式碼會顯示 "1",表示只有 <code>myns:foo</code> 節點。所以,如要迴走子節點並掠過文字節點,要分辨這些節點。</p>
<p>The first line of JavaScript loads the XML document and accesses the root element (<code>myXMLDoc</code>) by retrieving the <code>documentElement</code>. The second line simply alerts the number of child nodes. Per the W3C specification, the white spaces and new lines merge into one text node if they follow each other. For Mozilla, the <code>myXMLdoc</code> node has three children: a text node containing a new line and two spaces; the <code>myns:foo</code> node; and another text node with a new line. Internet Explorer, however, does not abide by this and will return "1" for the above code, namely only the <code>myns:foo</code> node. Therefore, to walk the child nodes and disregard text nodes, you must distinguish such nodes.</p>
<p>As mentioned earlier, every node has a <code>nodeType</code> attribute representing the node type. For example, an element node has type 1, while a document node has type 9. To disregard text nodes, you must check for types 3 (text node) and 8 (comment node).</p>
<pre>
XML:
  &lt;?xml version="1.0"?&gt; &nbsp; 
  &lt;myXMLdoc xmlns:myns="http://myfoo.com"&gt; 
    &lt;myns:foo&gt;bar&lt;/myns:foo&gt; 
  &lt;/myXMLdoc&gt;

JavaScript: 
  var myXMLDoc = getXMLDocument().documentElement; 
  var myChildren = myXMLDoc.childNodes; 

  for (var run = 0; run &lt; myChildren.length; run++){ 
    if ( (myChildren[run].nodeType&nbsp;!= 3) &amp;&amp;
          myChildren[run].nodeType&nbsp;!= 8) ){ 
      // not a text or comment node 
    }
  }
</pre>
<h4 id="XML_data_islands" name="XML_data_islands">XML data islands</h4>
<p>Internet Explorer has a nonstandard feature called <em>XML data islands</em>, which allow you to embed XML inside an HTML document using the nonstandard HTML tag <code>&lt;xml&gt;</code>. Mozilla does not support XML data islands and handles them as unknown HTML tags. You can achieve the same functionality using XHTML; however, because Internet Explorer's support for XHTML is weak, this is usually not an option.</p>
<p>One cross-browser solution is to use DOM parsers, which parse a string that contains a serialized XML document and generates the document for the parsed XML. Mozilla uses the <code>DOMParser</code> class, which takes the serialized string and creates an XML document out of it. In Internet Explorer, you can achieve the same functionality using ActiveX. A new <code>Microsoft.XMLDOM</code> generates and has a <code>loadXML</code> method that can take in a string and generate a document from it. The following code shows you how:</p>
<pre>
IE XML data island: 
  .. 
  &lt;xml id="xmldataisland"&gt; 
    &lt;foo&gt;bar&lt;/foo&gt; 
  &lt;/xml&gt;

Cross-browser solution: 
  var xmlString = "&lt;xml id=\"xmldataisland\"&gt;&lt;foo&gt;bar&lt;/foo&gt;&lt;/xml&gt;"; 

  var myDocument; 

  if (document.implementation.createDocument){ 
    // Mozilla, create a new DOMParser 
    var parser = new DOMParser(); 
    myDocument = parser.parseFromString(xmlString, "text/xml"); 
  } else if (window.ActiveXObject){ 
    // Internet Explorer, create a new XML document using ActiveX 
    // and use loadXML as a DOM parser. 
    myDocument = new ActiveXObject("Microsoft.XMLDOM") 
    myDocument.async="false"; 

    myDocument.loadXML(xmlString); &nbsp; 
  }
</pre>
<h4 id="XML_HTTP_request" name="XML_HTTP_request">XML HTTP request</h4>
<p>Internet Explorer allows you to send and retrieve XML files using MSXML's <code>XMLHTTP</code> class, which is instantiated through ActiveX using <code>new ActiveXObject("Msxml2.XMLHTTP")</code> or <code>new ActiveXObject("Microsoft.XMLHTTP")</code>. Since there is no standard method of doing this, Mozilla provides the same functionality in the global JavaScript <code>XMLHttpRequest</code> object. The object generates asynchronous requests by default.</p>
<p>After instantiating the object using <code>new XMLHttpRequest()</code>, you can use the <code>open</code> method to specify what type of request (GET or POST) you use, which file you load, and if it is asynchronous or not. If the call is asynchronous, then give the <code>onload</code> member a function reference, which is called once the request has completed.</p>
<p>Synchronous request:</p>
<pre class="eval">
  var myXMLHTTPRequest = new XMLHttpRequest(); 
  myXMLHTTPRequest.open("GET", "data.xml", false); 

  myXMLHTTPRequest.send(null); 

  var myXMLDocument = myXMLHTTPRequest.responseXML; 
</pre>
<p>Asynchronous request:</p>
<pre class="eval">
  var myXMLHTTPRequest; 

  function <span class="boldcode">xmlLoaded</span>() { 
    var myXMLDocument = myXMLHTTPRequest.responseXML; 
  }

  function loadXML(){ 
    myXMLHTTPRequest = new XMLHttpRequest();

    myXMLHTTPRequest.open("GET", "data.xml", true);

    myXMLHTTPRequest.onload = <span class="boldcode">xmlLoaded</span>; 

    myXMLHTTPRequest.send(null); 
  }
</pre>
<p>Table 7 features a list of available methods and properties for Mozilla's <code>XMLHttpRequest</code>.</p>
<p>&nbsp;</p>
<p>Table 7. XMLHttpRequest methods and properties</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Name</th>
      <th>Description</th>
    </tr>
    <tr>
      <td>void abort()</td>
      <td>Stops the request if it is still running.</td>
    </tr>
    <tr>
      <td>string getAllResponseHeaders()</td>
      <td>Returns all response headers as one string.</td>
    </tr>
    <tr>
      <td>string getResponseHeader(string headerName)</td>
      <td>Returns the value of the specified header.</td>
    </tr>
    <tr>
      <td>functionRef onerror</td>
      <td>If set, the references function will be called whenever an error occurs during the request.</td>
    </tr>
    <tr>
      <td>functionRef onload</td>
      <td>If set, the references function will be called when the request completes successfully and the response has been received. Use when an asynchronous request is used.</td>
    </tr>
    <tr>
      <td>void open (string HTTP_Method, string URL)<br />
        <br />
        void open (string HTTP_Method, string URL, boolean async, string userName, string password)</td>
      <td>Initializes the request for the specified URL, using either GET or POST as the HTTP method. To send the request, call the <code>send()</code> method after initialization. If <code>async</code> is false, the request is synchronous, else it defaults to asynchronous. Optionally, you can specify a username and password for the given URL needed.</td>
    </tr>
    <tr>
      <td>int readyState</td>
      <td>State of the request. Possible values:
        <table>
          <tbody>
            <tr>
              <th>Value</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>0</td>
              <td>UNINITIALIZED - open() has not been called yet.</td>
            </tr>
            <tr>
              <td>1</td>
              <td>LOADING - send() has not been called yet.</td>
            </tr>
            <tr>
              <td>2</td>
              <td>LOADED - send() has been called, headers and status are available.</td>
            </tr>
            <tr>
              <td>3</td>
              <td>INTERACTIVE - Downloading, responseText holds the partial data.</td>
            </tr>
            <tr>
              <td>4</td>
              <td>COMPLETED - Finished with all operations.</td>
            </tr>
          </tbody>
        </table>
      </td>
    </tr>
    <tr>
      <td>string responseText</td>
      <td>String containing the response.</td>
    </tr>
    <tr>
      <td>DOMDocument responseXML</td>
      <td>DOM Document containing the response.</td>
    </tr>
    <tr>
      <td>void send(variant body)</td>
      <td>Initiates the request. If <code>body</code> is defined, it issent as the body of the POST request. <code>body</code> can be an XML document or a string serialized XML document.</td>
    </tr>
    <tr>
      <td>void setRequestHeader (string headerName, string headerValue)</td>
      <td>Sets an HTTP request header for use in the HTTP request. Has to be called after <code>open()</code> is called.</td>
    </tr>
    <tr>
      <td>string status</td>
      <td>The status code of the HTTP response.</td>
    </tr>
  </tbody>
</table>
<h4 id="XSLT_.E5.B7.AE.E7.95.B0" name="XSLT_.E5.B7.AE.E7.95.B0">XSLT 差異</h4>
<p>Mozilla supports XSL Transformations (XSLT) 1.0. It also allows JavaScript to perform XSLT transformations and allows running XPATH on a document.</p>
<p>Mozilla requires that you send the XML and XSLT file holding the stylesheet with an XML mimetype (<code>text/xml</code> or <code>application/xml</code>). This is the most common reason why XSLT won't run in Mozilla but will in Internet Explorer. Mozilla is strict in that way.</p>
<p>Internet Explorer 5.0 and 5.5 supported XSLT's working draft, which is substantially different than the final 1.0 recommendation. The easiest way to distinguish what version an XSLT file was written against is to look at the namespace. The namespace for the 1.0 recommendation is <code><span class="nowiki">http://www.w3.org/1999/XSL/Transform</span></code>, while the working draft's namespace is <code><span class="nowiki">http://www.w3.org/TR/WD-xsl</span></code>. Internet Explorer 6 supports the working draft for backwards compatibility, but Mozilla does not support the working draft, only the final recommendation.</p>
<p>If XSLT requires you to distinguish the browser, you can query the "xsl:vendor" system property. Mozilla's XSLT engine will report itself as "Transformiix" and Internet Explorer will return "Microsoft."</p>
<pre>
&lt;xsl:if test="system-property('xsl:vendor') = 'Transformiix'"&gt; 
  &lt;!-- Mozilla specific markup --&gt; 
&lt;/xsl:if&gt; 
&lt;xsl:if test="system-property('xsl:vendor') = 'Microsoft'"&gt; 
  &lt;!-- Internet Explorer specific markup --&gt; 
&lt;/xsl:if&gt; 
</pre>
<p>Mozilla also provides JavaScript interfaces for XSLT, allowing a Web site to complete XSLT transformations in memory. You can do this using the global <code>XSLTProcessor</code> JavaScript object. <code>XSLTProcessor</code> requires you to load the XML and XSLT files, because it needs their DOM documents. The XSLT document, imported by the <code>XSLTProcessor</code>, allows you to manipulate XSLT parameters. <code>XSLTProcessor</code> can generate a standalone document using <code>transformToDocument()</code>, or it can create a document fragment using <code>transformToFragment()</code>, which you can easily append into another DOM document. Below is an example:</p>
<p>&nbsp;</p>
<pre>
var xslStylesheet; 
var xsltProcessor = new XSLTProcessor(); 

// load the xslt file, example1.xsl 
var myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xsl", false); 
myXMLHTTPRequest.send(null); 

// get the XML document and import it 
xslStylesheet = myXMLHTTPRequest.responseXML; 

xsltProcessor.importStylesheet(xslStylesheet); 

// load the xml file, example1.xml 
myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xml", false); 
myXMLHTTPRequest.send(null); 

var xmlSource = myXMLHTTPRequest.responseXML; 

var resultDocument = xsltProcessor.transformToDocument(xmlSource); 
</pre>
<p>After creating an <code>XSLTProcessor</code>, you load the XSLT file using <code>XMLHttpRequest</code>. The XMLHttpRequest's <code>responseXML</code> member contains the XML document of the XSLT file, which is passed to <code>importStylesheet</code>. You then use the <code>XMLHttpRequest</code> again to load the source XML document that must be transformed; that document is then passed to the <code>transformToDocument</code> method of <code>XSLTProcessor</code>. Table 8 features a list of <code>XSLTProcessor</code> methods.</p>
<p>&nbsp;</p>
<p>Table 8. XSLTProcessor methods</p>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Method</th>
      <th>Description</th>
    </tr>
    <tr>
      <td>void importStylesheet(Node styleSheet)</td>
      <td>Imports the XSLT stylesheet. The <code>styleSheet</code> argument is the root node of an XSLT stylesheet's DOM document.</td>
    </tr>
    <tr>
      <td>DocumentFragment transformToFragment(Node source, Document owner)</td>
      <td>Transforms the Node <code>source</code> by applying the stylesheet imported using the <code>importStylesheet</code> method and generates a DocumentFragment. <code>owner</code> specifies what DOM document the DocumentFragment should belong to, making it appendable to that DOM document.</td>
    </tr>
    <tr>
      <td>Document transformToDocument(Node source)</td>
      <td>Transforms the Node <code>source</code> by applying the stylesheet imported using the <code>importStylesheet</code> method and returns a standalone DOM document.</td>
    </tr>
    <tr>
      <td>void setParameter(String namespaceURI, String localName, Variant value)</td>
      <td>Sets a parameter in the imported XSLT stylesheet.</td>
    </tr>
    <tr>
      <td>Variant getParameter(String namespaceURI, String localName)</td>
      <td>Gets the value of a parameter in the imported XSLT stylesheet.</td>
    </tr>
    <tr>
      <td>void removeParameter(String namespaceURI, String localName)</td>
      <td>Removes all set parameters from the imported XSLT stylesheet and makes them default to the XSLT-defined defaults.</td>
    </tr>
    <tr>
      <td>void clearParameters()</td>
      <td>Removes all set parameters and sets them to defaults specified in the XSLT stylesheet.</td>
    </tr>
    <tr>
      <td>void reset()</td>
      <td>Removes all parameters and stylesheets.</td>
    </tr>
  </tbody>
</table>
<div class="originaldocinfo">
  <h3 id=".E5.8E.9F.E6.96.87.E8.B3.87.E8.A8.8A" name=".E5.8E.9F.E6.96.87.E8.B3.87.E8.A8.8A">原文資訊</h3>
  <ul>
    <li>原文作者:Doron Rosenberg, IBM Corporation</li>
    <li>公開日期: 26 Jul 2005</li>
    <li>原文連結: <a class="external" href="http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/" rel="freelink">http://www-128.ibm.com/developerwork...y/wa-ie2mozgd/</a></li>
  </ul>
</div>
<p>{{ languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla", "es": "es/Migrar_aplicaciones_desde_Internet_Explorer_a_Mozilla", "fr": "fr/Migration_d\'applications_d\'Internet_Explorer_vers_Mozilla", "ko": "ko/Migrate_apps_from_Internet_Explorer_to_Mozilla", "zh-cn": "cn/\u4eceInternet_Explorer\u8fc1\u79fb\u5230Mozilla" } ) }}</p>
Revert to this revision