Migrate apps from Internet Explorer to Mozilla

  • 리비전 슬러그: Migrate_apps_from_Internet_Explorer_to_Mozilla
  • 리비전 제목: Migrate apps from Internet Explorer to Mozilla
  • 리비전 아이디: 121969
  • 제작일시:
  • 만든이: Redleaf
  • 현재 리비전인가요? 아니오
  • 댓글 /* JavaScript 차이 */

리비전 내용

소개

넷스케이프가 Mozilla 브라우저를 시작할때 부터 Mozilla는 W3C 표준을 지원하기로 결정되었다. 그 결과 Mozilla는 Netscape Navigator 4.x와 Microsoft Internet Explorer의 구형 코드와는 완전한 하위호환성을 가지지 못하게 되었다. 예를 들어, 뒤에서 언급하겠지만 Mozilla는 <layer>를 지원하지 않는다. W3C 표준의 개념 이전에 만들어진 IE 4와 같은 브라우저들은 많은 쿼크들을 물려받았다. 본 글에서는 IE와 기타 구형 브라우저들과의 강력한 HTML 하위 호환성을 제공하는 Mozilla의 쿼크 모드에 관해 알아볼 것이다.

또한 XMLHttpRequest와 리치 텍스트 편집과 같은, 당시에는 W3C에 이에 상응하는 것이 존재하지 않았기 때문에 Mozilla가 지원하는 비표준 기술에 대해서도 언급하겠다. 그것은 다음을 포함한다:

일반적인 크로스 브라우저 코딩 팁

웹표준이 존재하긴 하지만, 서로다른 브라우저는 서로 다르게 작동한다. (사실, 같은 브라우저라도 플랫폼에 따라 다르게 작동한다.) IE와 같은 많은 브라우저들이 W3C 이전의 API들도 지원하며 W3C 적용 API들에 대한 확장된 지원을 추가하지 않았다.

Mozilla와 IE 사이의 차이점을 논하기 전에, 추후 새로운 브라우저를 지원할 수 있도록 확장성있는 웹 어플리케이션을 만들 수 있는 기본적인 방법을 다루도록 하겠다.

서로 다른 브라우저들이 가끔 같은 기능에 대해 서로 다른 API를 사용하기 때문에, 브라우저들간에 구별을 위해 코드 전반적으로 여러개의 if() else() 블록을 사용하는 것을 종종 볼 수 있다. 다음 코드는 IE를 위해 고안된 코드 블록을 보여준다.

. . . 

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로 브라우저를 스니핑하는 것이 사용중인 브라우저에 대한 세부 정보를 제공하기는 하지만, useragents를 다루는 코드는 종종 새로운 브라우저 버전이 출시될때 실수를 일으킬 수 있으며 그래서 코드를 바꿔야 할 수도 있다.

브라우저의 타입에 상관없다면 (웹 어플리케이션 접근에 대해 지원되지 않는 브라우저는 이미 차단했다고 가정할때), 브라우저가 가진 기능이나 오브젝트 특성 지원으로부터 스니핑하는 것이 훨씬 더 좋고 더욱 신뢰성이 있다. 이것은 보통 자바스크립트에서 필요한 기능이 존재하는지를 검사해보는 것으로 행해진다. 예를들면 다음보다는:

if (isMozilla || isIE5) 

이것을 사용하는 것이다:

if (document.getElementById) 

이는 Opera와 Safari같이 W3C 표준 메소드를 지원하는 다른 브라우저들이 아무런 수정을 하지 않고도 작동할 수 있게 한다.

그러나 useragent 스니핑은 브라우저가 웹 어플리케이션의 버전 요구사항을 만족시키는지를 검사할때나 버그와 관련한 작업과 같이 정확도가 중요할때 의미가 있다.

자바스크립트는 인라인 조건문도 허용하는데 이것은 코드 가독성을 증가시킨다:

var foo = (condition) ? conditionIsTrue : conditionIsFalse; 

예를 들면, 엘리먼트를 얻기 위해 다음을 사용한다:

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

혹은 || 연산자를 사용한 다른 방법도 있다.

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

Mozilla와 IE 간의 차이점

우선 Mozilla와 IE간의 HTML이 동작하는 방법에서의 차이점 부터 알아보겠다.

툴팁

구형 브라우저들은 링크상에 툴팁을 보여주거나 툴팁의 내용으로 alt 속성 값을 사용함으로써 툴팁을 도입했다. 최근의 W3C HTML 스펙은 title 속성을 만들었는데 이것은 링크의 세부 설명을 포함할 수 있다. 오늘 날의 브라우저들은 툴팁을 보여주기 위해 title 속성을 사용할 것이다. 그리고 Mozilla는 title 속성으로 툴팁을 보여주는 것만을 지원하며 alt 속성은 지원하지 않는다.

엔티티

HTML 마크업은 몇몇 엔티티를 포함할 수 있는데, 이 엔티티는 W3C 웹 표준 본문에 정의되어 있다. 엔티티는 숫자형이나 캐릭터 레퍼런스로 참조될 수 있다. 예를 들면, 공백 문자 #160은 &#160; 또는 동등한 캐릭터 레퍼런스인 &nbsp;로 참조될 수 있다.

IE와 같은 몇몇 오래된 브라우저들은 보통의 텍스트 컨텐츠의 끝에서 ;(세미콜론)을 생략하여 엔티티를 사용하는 것을 가능하게 하는 쿼크들을 가지고 있었다.

&nbsp Foo 
&nbsp&nbsp Foo 

Mozilla는 비록 W3C 스펙에 어긋나기는 하지만 위의 &nbsp를 공백으로 렌더링한다. 브라우저는 만약 바로 직후에 다른 문자가 오면 &nbsp를 파싱하지 않는다. 예를들면,

&nbsp12345 

이 코드는 Mozilla에서는 동작하지 않는다. 왜냐하면 W3C 웹표준에 어긋나기 때문이다. 브라우저간의 불일치를 피하려면 항상 정확한 형식(&nbsp;)을 사용하라.

DOM 차이

Document Object Model (DOM)은 문서 엘리먼트를 포함하고 있는 트리구조이다. W3C가 표준화한 자바스크립트 API로 이것을 조작할 수 있다. 그러나, W3C 표준화 이전에 넷스케이프 4와 IE 4는 유사하게 API를 구현했다. Mozilla는 W3C 웹표준으로 이룰 수 없는 경우에만 구식 API를 구현했다.

엘리먼트 접근

크로스 브라우저 접근법을 사용해서 엘리먼트 레퍼런스를 탐색하기 위해서는 document.getElementById(aID)를 사용하는데, 이것은 IE 5.0+, Mozilla기반 브라우저, 그리고 다른 W3C 적용 브라우저들에서 작동하며 DOM Level 1 스펙의 일부이다.

Mozilla는 document.elementName이라던지 엘리먼트의 name을 통해서 접근하는 방법을 지원하지 않는 반면에 IE는 이를 지원한다. (global namespace polluting이라고도 부른다.) Mozilla는 넷스케이프 4의 document.layers 메소드나 IE의 document.all 메소드도 지원하지 않는다. document.getElementById가 하나의 엘리먼트를 찾아내는 방법인 반면에 document.layersdocument.all를 사용하면 모든 <div> 엘리먼트들과 같이 특정 태그명의 모든 문서 엘리먼트들의 리스트를 얻을 수 있다.

W3C DOM Level 1 메소드는 getElementsByTagName()을 통해 같은 태그명을 가진 모든 엘리먼트들에 대한 레퍼런스를 얻을 수 있다. 이 메소드는 자바스크립트에서 배열로 반환되며, document 엘리먼트에 호출되거나, 다른 노드들에 그 하위 구조만을 탐색하게 호출할 수 있다. DOM 트리에서 모든 엘리먼트들에 대한 배열을 얻으려면 getElementsByTagName("*")를 사용한다.

표 1에서 보는 바와 같이, DOM Level 1 메소드는 엘리먼트를 특정 위치로 옮기거나 (메뉴, 에니메이션 등을) 보이게 혹은 안보이게 하는데 공통적으로 쓰인다. 넷스케이프 4는 Mozilla가 지원하지 않는 <layer>태그를 아무곳에나 위치시킬 수 있는 HTML 엘리먼트로사용했다. Mozilla에서는 <div> 태그를 사용하여 어떠한 엘리먼트라도 위치시킬 수 있는데, 이것은 IE도 잘 사용되며 HTML 스펙에 나와있는 것이다.

표 1. Methods used to access elements
Method Description
document.getElementById( aId ) Returns a reference to the element with the specified ID.
document.getElementsByTagName( aTagName ) Returns an array of elements with the specified name in the document.

DOM 탐색

Mozilla는 자바스크립트를 통하여 DOM 트리를 탐색하는 W3C DOM API를 지원한다(표 2 참조). 이 API는 문서 내에 있는 각 노드들에 대해 존재하고 아무 방향으로나 탐색하는 것이 가능하다. IE도 이 API들을 잘 지원하지만 IE는 children 속성처럼 DOM 트리를 탐색할 수 있는 구식 API들도 역시 지원한다.

표 2. Methods used to traverse the DOM
Property/Method Description
childNodes Returns an array of all child nodes of the element.
firstChild Returns the first child node of the element.
getAttribute( aAttributeName ) Returns the value for the specified attribute.
hasAttribute( aAttributeName ) Returns a boolean stating if the current node has an attribute defined with the specified name.
hasChildNodes() Returns a boolean stating whether the current node has any child nodes.
lastChild Returns the last child node of the element.
nextSibling Returns the node immediately following the current one.
nodeName Returns the name of the current node as a string.
nodeType Returns the type of the current node.
Value Description
1 Element Node
2 Attribute Node
3 Text Node
4 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
nodeValue Returns the value of the current node. For nodes that contain text, such as text and comment nodes, it will return their string value. For attribute nodes, the attribute value is returned. For all other nodes, null is returned.
ownerDocument Returns the document object containing the current node.
parentNode Returns the parent node of the current node.
previousSibling Returns the node immediately preceding the current one.
removeAttribute( aName ) Removes the specified attribute from the current node.
setAttribute( aName, aValue ) Sets the value of the specified attribute with the specified value.

IE는 비표준 쿼크를 가지는데 이들 API의 많은 수가 뉴라인 같이 생성된 공백 텍스트 노드를 무시한다. 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){ 
      // element node
    };
  };

컨텐츠의 생성과 조작

Mozilla는 document.write, document.open, document.close와 같이 DOM에 동적으로 컨텐츠를 추가하는 구형 메소드를 지원한다. Mozilla는 IE의 innerHTML 메소드도 지원하는데 이것은 거의 모든 노드에서 호출 가능하다. 그러나, outerHTML(엘리먼트 주변에 마크업을 추가하며 표준은 없다.)와 innerText(노드의 텍스트 값을 지정하며 Mozilla에서는 textContent를 사용하여 조작가능)는 지원하지 않는다.

IE는 비표준이며 Mozilla에서는 지원하지 않는 몇몇 컨텐츠 조작 메소드를 가지고 있는데 여기에는 값을 추출해 내거나 텍스트를 삽입하고 getAdjacentElement, insertAdjacentHTML와 같은 노드 주변에 엘리먼트를 삽입하는 것들이 포함된다. 표3은 W3C와 Mozilla가 어떻게 컨텐츠를 조작하는지를 보여주며, 모두 어떠한 DOM 노드에서라도 사용할 수 있는 메소드들이다.

표 3. Methods Mozilla uses to manipulate content
Method Description
appendChild( aNode ) Creates a new child node. Returns a reference to the new child node.
cloneNode( aDeep ) Makes a copy of the node it is called on and returns the copy. If aDeep is true, it copies over the node's entire subtree.
createElement( aTagName ) Creates and returns a new and parentless DOM node of the type specified by aTagName.
createTextNode( aTextValue ) Creates and returns a new and parentless DOM textnode with the data value specified by aTextValue.
insertBefore( aNewNode, aChildNode ) Inserts aNewNode before aChildNode, which must be a child of the current node.
removeChild( aChildNode ) Removes aChildNode and returns a reference to it.
replaceChild( aNewNode, aChildNode ) Replaces aChildNode with aNewNode and returns a reference to the removed node.

도큐먼트 프래그먼트

실행 성능상의 이유로 현재 존재하고 있는 문서의 DOM에서 작업하기 보다 메모리 상에서 도큐먼트를 생성할 수 있다. DOM Level 1 Core는 도큐먼트 프래그먼트를 도입했는데 이것은 보통의 도큐먼트 인터페이스의 부분집합을 가지는 경량의 도큐먼트이다. 예를 들어, getElementById는 존재하지 않지만 appendChild는 존재한다. 또한 현재 존재하고 있는 도큐먼트에 쉽게 도큐먼트 프래그먼트를 추가할 수 있다.

Mozilla 는 document.createDocumentFragment()를 통하여 빈 도큐먼트 프래그먼트를 생성할 수 있다.

그러나 IE에서의 도큐먼트 프래그먼트 구현은 W3C 웹표준을 따르지 않으며 단순히 보통의 도큐먼트를 리턴한다.

자바스크립트 차이

Mozilla와 IE간의 대부분의 차이점은 보통 자바스크립트에 대한 것이다. 그러나 이러한 문제들은 DOM hook과 같이 브라우저가 자바스크립트에 대해 드러내는 API들에서는 보통 거짓이다. 두 브라우저간 코어 자바스크립트의 차이점은 거의 없다. 문제는 타이밍 관련된 이슈에서 종종 생긴다.

자바스크립트 날짜 차이

단하나의 Date 차이점은 getYear 메소드이다. ECMAScript 스펙(자바스크립트가 따르는 명세)에 따르면 이 메소드는 Y2K 적용이 되지 않았기 때문에 2004년에 new Date().getYear()를 실행시키면 "104"를 리턴한다. ECMAScript 스펙에 따르면 getYear는 해당년도에서 1900을 뺀 수를 리턴한다. 이것은 본래 1998년에 대해 "98"을 리턴하는 의미였다. getYear는 ECMAScript 버전3에서 deprecated되었고 getFullYear()로 교체되었다. Mozilla가 표준 작동을 준수하는 반면 IE는 getYear()를 변경하여 getFullYear()와 같은 동작을 하게 하여 Y2K 적용을 시켰다.

자바스크립트 실행 차이

서로다른 브라우저는 자바스크립트를 다르게 실행한다. 예를 들어, 다음 코드는 script 코드 실행 시점에 DOM 내에 div 노드가 이미 존재하고 있음을 가정한다.

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

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

그러나, 이것은 보장할 수 없다. 모든 엘리먼트가 존재함을 보장하기 위해서는 <body>태그에 onload 이벤트 핸들러를 사용해야 한다.

<body onload="doFinish();"> 

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

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

이러한 타이밍 관련 문제에는 하드웨어도 역시 관련된다. 느린 시스템에서는 빠른 시스템에서 감춰지는 버그들이 드러날 수 있다. 확실한 예 중의 하나는 새 윈도우를 여는 window.open이다.

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

위의 코드가 갖고 있는 문제는 window.open이 비동기라는 것이다. 이것은 윈도우가 로딩을 마칠때 까지 자바스크립트 실행을 차단해 놓지 않는다. 그러므로, 새 윈도우가 뜨기도 전에 window.open 라인의 다음 라인이 실행될 수가 있다. 이것은 새 창에서 onload 핸들러를 가지게 하고 (window.opener를 사용하여) 새 창을 연 윈도우로 콜백 실행을 하게 하여 해결할 수 있다.

자바스크립트가 생성하는 HTML의 차이

자바스크립트는 document.write를 사용하여 문자열에서 HTML을 생성해낼 수 있다. 여기에서의 주요 문제는 HTML 문서 내부에 포함된 (즉, <script> 태그 내부의) 자바 스크립트가 <script>태그를 포함한 HTML을 생성하는 경우이다. 만약 문서가 strict 렌더링 모드라면 문자열 내부의 </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 type='text\/javascript'>alert('Hello');<\/script>") 
</script> 

페이지가 strict 모드이므로, Mozilla의 파서는 첫번째 <script>를 보고 이에 대한 닫는 태그를 찾을때까지, 즉 첫번째 </script>를 찾을때까지 파싱한다. 이것은 파서가 strict 모드일때 자바스크립트 (혹은 다른 언어)에 관해 모르기 때문이다. 쿼크 모드에서 파서는 파싱시 (느려짐) 자바스크립트에 대해 알고 있다. IE는 항상 쿼크 모드이다 그래서 IE는 진정한 XHTML을 지원하지 않는다. 이것을 Mozilla의 strict 모드에서 작동하게 하려면 문자열을 두부분으로 분리한다:

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

자바스크립트 디버깅

Mozilla는 IE를 위해 만들어진 어플리케이션들에서 발견되는 자바스크립트 관련 문제들을 디버깅할 수 있는 몇가지 방법을 제공한다. 첫번째 툴은 그림 1에서 보는 것처럼 내장된 자바스크립트 콘솔이다. 여기에는 에러와 경고가 표시된다. Mozilla에서 도구 -> Web Development -> JavaScript Console를 실행하거나 파이어폭스 (Mozilla에서 나온 단독 브라우저 제품)에서는 도구 -> JavaScript Console를 실행한다.

그림 1. JavaScript 콘솔

Javascript 콘솔

자바스크립트 콘솔은 에러나 경고, 혹은 메시지에 대한 전체 기록 목록을 보여줄 수 있다. 그림 1의 에러 메시지는 aol.com의 95번째 라인이 is_ns70이라는 정의되지 않은 변수를 접근하려한다는 것을 알려준다. 링크를 클릭하면 Mozilla의 내부 소스보기 창이 열리고 해당 라인이 하이라이트되어 있을 것이다.

콘솔에서는 자바스크립트를 실행할 수도 있다. 입력한 자바스크립트 문법을 실행하려면 그림 2처럼 입력창에 1+1을 치고 Evaluate를 누르면 된다.

그림 2. JavaScript console evaluating

JavaScript Console evaluating

Mozilla의 자바스크립트 엔진은 디버깅에 대한 내장된 지원을 하므로 자바스크립트 개발자들에게 강력한 툴을 제공할 수 있다. 그림 3에 있는 Venkman은 Mozilla에 통합된 강력한 크로스 플랫폼 자바스크립트 디버거이다. 이것은 보통 Mozilla 릴리즈에 포함된다. 도구 -> Web Development -> JavaScript Debugger로 가면 찾을 수 있다. 파이어 폭스에서는 이 디버거가 포함되어 있지 않다. 대신에 Venkman Project Page에서 다운로드 받아 설치할 수 있다. Venkman Development Page에 있는 개발 관련 페이지에서는 튜토리얼도 찾을 수 있다.

그림 3. Mozilla의 JavaScript 디버거

Mozilla의 JavaScript 디버거

자바스크립트 디버거는 Mozilla 브라우저 창에서 실행중인 자바스크립트를 디버깅할 수 있다. 이것은 breakpoint관리, call stack inspection 혹은 variable/object inspection과 같은 표준 디버깅 기능들을 지원한다. 모든 기능들은 사용자 인터페이스를 통하거나 디버거의 대화 콘솔을 통하여 접근할 수 있다. 콘솔을 사용하면 현재 디버깅하는 자바스크립트와 같은 스코프에서 임시적인 자바스크립트를 실행시킬 수 있다.

CSS 차이

Mozilla-based products have the strongest support for Cascading Style Sheets (CSS), including most of CSS1, CSS2.1 and parts of CSS3, compared to Internet Explorer as well as all other browsers.

For most issues mentioned below, Mozilla will add an error or warning entry into the JavaScript console. Check the JavaScript console if you encounter CSS-related issues.

Mimetypes (CSS 파일이 적용되지 않았을 때)

The most common CSS-related issue is that CSS definitions inside referenced CSS files are not applied. This is usually due to the server sending the wrong mimetype for the CSS file. The CSS specification states that CSS files should be served with the text/css mimetype. Mozilla will respect this and only load CSS files with that mimetype if the Web page is in strict standards mode. Internet Explorer will always load the CSS file, no matter with which mimetype it is served. Web pages are considered in strict standards mode when they start with a strict doctype. To solve this problem, you can make the server send the right mimetype or remove the doctype. I'll discuss more about doctypes in the next section.

CSS 와 units

Many Web applications do not use units with their CSS, especially when you use JavaScript to set the CSS. Mozilla tolerates this, as long as the page is not rendered in strict mode. Since Internet Explorer does not support true XHTML, it does not care if no units are specified. If the page is in strict standards mode, and no units are used, then Mozilla ignores the style:

<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
  "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
  <head> 
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>CSS and units example</title> 
  </head> 
  <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> 

Since the above example has a strict doctype, the page is rendered in strict standards mode. The first div will have a width of 40px, since it uses units, but the second div won't get a width, and thus will default to 100% width. The same would apply if the width were set through JavaScript.

JavaScript 와 CSS

Since Mozilla supports the CSS standards, it also supports the CSS DOM standard for setting CSS through JavaScript. You can access, remove, and change an element's CSS rules through the element's style member:

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

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

You can reach every CSS attribute that way. Again, if the Web page is in strict mode, you must set a unit or else Mozilla will ignore the command. When you query a value, say through .style.width, in Mozilla and Internet Explorer, the returned value will contain the unit, meaning a string is returned. You can convert the string into a number through parseFloat("40px").

CSS overflow 차이

CSS added the notion of overflow, which allows you to define how to handle overflow; for example, when the contents of a div with a specified height are taller than that height. The CSS standard defines that if no overflow behavior is set in this case, the div contents will overflow. However, Internet Explorer does not comply with this and will expand the div beyond its set height in order to hold the contents. Below is an example that shows this difference:

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

As you can see in Figure 4, Mozilla acts like the W3C standard specifies. The W3C standard says that, in this case, the inner div overflows to the bottom since the inner content is taller than its parent. If you prefer the Internet Explorer behavior, simply do not specify a height on the outer element.

Figure 4. DIV overflow

DIV Overflow

hover 차이

The nonstandard CSS hover behavior in Internet Explorer occurs on quite a few web sites. It usually manifests itself by changing text style when hovered over in Mozilla, but not in Internet Explorer. This is because the a:hover CSS selector in Internet Explorer matches <a href="">...</a> but not <a name="">...</a>, which sets anchors in HTML. The text changes occur because authors encapsulate the areas with the 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 follows the CSS specification correctly and will change the color to green in this example. You can use two ways to make Mozilla behave like Internet Explorer and not change the color of the text when hovered over:

  • First, you can change the CSS rule to be a:link:hover {color: green;}, which will only change the color if the element is a link (has an href attribute).
  • Alternatively, you can change the markup and close the opened <a /> before the start of the text -- the anchor will continue to work this way.

Quirks 과 standards 모드

Older legacy browsers, such as Internet Explorer 4, rendered with so-called quirks under certain conditions. While Mozilla aims to be a standards-compliant browser, it has three modes that support older Web pages created with these quirky behaviors. The page's content and delivery determine which mode Mozilla will use. Mozilla will indicate the rendering mode in View -> Page Info (or Ctrl+I) ; Firefox will list the rendering mode in Tools -> Page Info. The mode in which a page is located depends on its doctype.

Doctypes (short for document type declarations) look like this:

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

The section in blue is called the public identifier, the green part is the system identifier, which is a URI.

Standards 모드

Standards mode is the strictest rendering mode -- it will render pages per the W3C HTML and CSS specifications and will not support any quirks. Mozilla uses it for the following conditions:

  • If a page is sent with a text/xml mimetype or any other XML or XHTML mimetype
  • For any "DOCTYPE HTML SYSTEM" doctype (for example, <!DOCTYPE HTML SYSTEM "http://www.w3.org/TR/REC-html40/strict.dtd">), except for the IBM doctype
  • For unknown doctypes or doctypes without DTDs

Almost standards 모드

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.

그림 5. 이미지 간격

이미지 간격

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">)

이미지 간격 이슈에서 더 많은 정보를 얻을 수 있습니다.

Quirks 모드

Currently, the Web is full of invalid HTML markup, as well as markup that only functions due to bugs in browsers. The old Netscape browsers, when they were the market leaders, had bugs. When Internet Explorer arrived, it mimicked those bugs in order to work with the content at that time. As newer browsers came to market, most of these original bugs, usually called quirks, were kept for backwards compatibility. Mozilla supports many of these in its quirks rendering mode. Note that due to these quirks, pages will render slower than if they were fully standards-compliant. Most Web pages are rendered under this mode.

Mozilla uses quirks mode for the following conditions:

  • When no doctype is specified
  • For doctypes without a system identifier (for example, <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">)

For further reading, check out: Mozilla Quirks Mode Behavior and Mozilla's DOCTYPE sniffing.

Event 차이

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>

Sometimes this doesn't work because Internet Explorer "catches" the aEvent parameter, identifiying it as not null, making it not use window.event any longer. The solution is to simply test for the window.event property:

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

<script>
  function handleEvent(aEvent) { 
    var myEvent = window.event ? window.event : aEvent;
  }
</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 element viewport.
clientY clientY The Y coordinate of the event, in relation to the element viewport.
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.
screenY 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.

Attach event handlers

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 web 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 IFrameElmRef.contentDocument, while Internet Explorer requires you to access it through document.frames{{mediawiki.external('\"IframeName\"')}} and then access the resulting document:

<script>
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;
}
</script> 

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 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.

How to handle XML

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 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.

원래 문서 정보

  • Author(s): Doron Rosenberg, IBM Corporation
  • Published: 26 Jul 2005
  • Link: http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/
{{ wiki.languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla" } ) }}

리비전 소스

<h3 name=".EC.86.8C.EA.B0.9C">소개</h3>
<p>넷스케이프가 Mozilla 브라우저를 시작할때 부터 Mozilla는 W3C 표준을 지원하기로 결정되었다. 그 결과 Mozilla는 Netscape Navigator 4.x와 Microsoft Internet Explorer의 구형 코드와는 완전한 하위호환성을 가지지 못하게 되었다. 예를 들어, 뒤에서 언급하겠지만 Mozilla는 &lt;layer&gt;를 지원하지 않는다. W3C 표준의 개념 이전에 만들어진 IE 4와 같은 브라우저들은 많은 쿼크들을 물려받았다. 본 글에서는 IE와 기타 구형 브라우저들과의 강력한 HTML 하위 호환성을 제공하는 Mozilla의 쿼크 모드에 관해 알아볼 것이다.
</p><p>또한 XMLHttpRequest와 리치 텍스트 편집과 같은, 당시에는 W3C에 이에 상응하는 것이 존재하지 않았기 때문에 Mozilla가 지원하는 비표준 기술에 대해서도 언급하겠다. 그것은 다음을 포함한다:
</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</a> and <a class="external" href="http://www.w3.org/TR/xhtml11/">XHTML 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/CSS21/">CSS Level 2.1</a> and parts of <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> and parts of <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">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 name=".EC.9D.BC.EB.B0.98.EC.A0.81.EC.9D.B8_.ED.81.AC.EB.A1.9C.EC.8A.A4_.EB.B8.8C.EB.9D.BC.EC.9A.B0.EC.A0.80_.EC.BD.94.EB.94.A9_.ED.8C.81">일반적인 크로스 브라우저 코딩 팁</h3>
<p>웹표준이 존재하긴 하지만, 서로다른 브라우저는 서로 다르게 작동한다. (사실, 같은 브라우저라도 플랫폼에 따라 다르게 작동한다.) IE와 같은 많은 브라우저들이 W3C 이전의 API들도 지원하며 W3C 적용 API들에 대한 확장된 지원을 추가하지 않았다.
</p><p>Mozilla와 IE 사이의 차이점을 논하기 전에, 추후 새로운 브라우저를 지원할 수 있도록 확장성있는 웹 어플리케이션을 만들 수 있는 기본적인 방법을 다루도록 하겠다.
</p><p>서로 다른 브라우저들이 가끔 같은 기능에 대해 서로 다른 API를 사용하기 때문에, 브라우저들간에 구별을 위해 코드 전반적으로 여러개의 if() else() 블록을 사용하는 것을 종종 볼 수 있다. 다음 코드는 IE를 위해 고안된 코드 블록을 보여준다.
</p>
<pre>. . . 

var elm; 

if (ns4) 
  elm = document.layers["myID"]; 
else if (ie4) 
  elm = document.all["myID"]
</pre>
<p>위의 코드는 확장성이 없기 때문에 새로운 브라우저를 지원하고 싶으면 웹 어플리케이션 전체에 있는 이러한 블록들을 수정해야만 한다.
</p><p>새로운 브라우저 추가를 위해 코딩을 다시하는 것을 막을 수 있는 가장 쉬운방법은 기능성을 추상화하는 것이다. 여러개의 if() else() 블록 보다는 공통적인 기능을 취하여 그 기능만으로 추상화시킴으로써 효율성을 증가시킬 수 있다. 이것은 코드의 가독성을 높일 뿐만 아니라, 새로운 클라이언트에 대한 지원을 추가하는 것을 단순화 시킨다.
</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>위의 코드는 아직 브라우저 스니핑 혹은 사용자가 어느 브라우저를 사용하고 있는가의 문제를 안고 있다. 브라우저 스니핑은 보통 다음과 같은 useragent를 통하여 행해 진다:
</p>
<pre>Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016 
</pre>  
<p>useragent로 브라우저를 스니핑하는 것이 사용중인 브라우저에 대한 세부 정보를 제공하기는 하지만, useragents를 다루는 코드는 종종 새로운 브라우저 버전이 출시될때 실수를 일으킬 수 있으며 그래서 코드를 바꿔야 할 수도 있다.
</p><p>브라우저의 타입에 상관없다면 (웹 어플리케이션 접근에 대해 지원되지 않는 브라우저는 이미 차단했다고 가정할때), 브라우저가 가진 기능이나 오브젝트 특성 지원으로부터 스니핑하는 것이 훨씬 더 좋고 더욱 신뢰성이 있다. 이것은 보통 자바스크립트에서 필요한 기능이 존재하는지를 검사해보는 것으로 행해진다. 예를들면 다음보다는:
</p>
<pre>if (isMozilla || isIE5) 
</pre> 
<p>이것을 사용하는 것이다:
</p>
<pre>if (document.getElementById) 
</pre> 
<p>이는 Opera와 Safari같이 W3C 표준 메소드를 지원하는 다른 브라우저들이 아무런 수정을 하지 않고도 작동할 수 있게 한다.
</p><p>그러나 useragent 스니핑은 브라우저가 웹 어플리케이션의 버전 요구사항을 만족시키는지를 검사할때나 버그와 관련한 작업과 같이 정확도가 중요할때 의미가 있다.
</p><p>자바스크립트는 인라인 조건문도 허용하는데 이것은 코드 가독성을 증가시킨다:
</p>
<pre>var foo = (condition) ? conditionIsTrue : conditionIsFalse; 
</pre> 
<p>예를 들면, 엘리먼트를 얻기 위해 다음을 사용한다:
</p>
<pre> 
function getElement(aID){ 
  return (document.getElementById) ? document.getElementById(aID)
                                   : document.all[aID];
} 
</pre>
<p>혹은 || 연산자를 사용한 다른 방법도 있다.
</p>
<pre>function getElement(aID){ 
  return (document.getElementById(aID)) || document.all[aID]);
}
</pre>
<h3 name="Mozilla.EC.99.80_IE_.EA.B0.84.EC.9D.98_.EC.B0.A8.EC.9D.B4.EC.A0.90">Mozilla와 IE 간의 차이점</h3>
<p>우선 Mozilla와 IE간의 HTML이 동작하는 방법에서의 차이점 부터 알아보겠다.
</p>
<h4 name=".ED.88.B4.ED.8C.81">툴팁</h4>
<p>구형 브라우저들은 링크상에 툴팁을 보여주거나 툴팁의 내용으로 <code>alt</code> 속성 값을 사용함으로써 툴팁을 도입했다. 최근의 W3C HTML 스펙은 <code>title</code> 속성을 만들었는데 이것은 링크의 세부 설명을 포함할 수 있다. 오늘 날의 브라우저들은 툴팁을 보여주기 위해 <code>title</code> 속성을 사용할 것이다. 그리고 Mozilla는 <code>title</code> 속성으로 툴팁을 보여주는 것만을 지원하며 <code>alt</code> 속성은 지원하지 않는다.
</p>
<h4 name=".EC.97.94.ED.8B.B0.ED.8B.B0">엔티티</h4>
<p>HTML 마크업은 몇몇 엔티티를 포함할 수 있는데, 이 엔티티는 W3C 웹 표준 본문에 정의되어 있다. 엔티티는 숫자형이나 캐릭터 레퍼런스로 참조될 수 있다. 예를 들면, 공백 문자 #160은 <code>&amp;#160;</code> 또는 동등한 캐릭터 레퍼런스인 <code>&amp;nbsp;</code>로 참조될 수 있다.
</p><p>IE와 같은 몇몇 오래된 브라우저들은 보통의 텍스트 컨텐츠의 끝에서 <code>;</code>(세미콜론)을 생략하여 엔티티를 사용하는 것을 가능하게 하는 쿼크들을 가지고 있었다.
</p>
<pre>&amp;nbsp Foo 
&amp;nbsp&amp;nbsp Foo 
</pre>
<p>Mozilla는 비록 W3C 스펙에 어긋나기는 하지만 위의 <code>&amp;nbsp</code>를 공백으로 렌더링한다. 브라우저는 만약 바로 직후에 다른 문자가 오면 <code>&amp;nbsp</code>를 파싱하지 않는다. 예를들면,
</p>
<pre>&amp;nbsp12345 
</pre>
<p>이 코드는 Mozilla에서는 동작하지 않는다. 왜냐하면 W3C 웹표준에 어긋나기 때문이다. 브라우저간의 불일치를 피하려면 항상 정확한 형식(<code>&amp;nbsp;</code>)을 사용하라.
</p>
<h3 name="DOM_.EC.B0.A8.EC.9D.B4">DOM 차이</h3>
<p>Document Object Model (DOM)은 문서 엘리먼트를 포함하고 있는 트리구조이다. W3C가 표준화한 자바스크립트 API로 이것을 조작할 수 있다. 그러나, W3C 표준화 이전에 넷스케이프 4와 IE 4는 유사하게 API를 구현했다. Mozilla는 W3C 웹표준으로 이룰 수 없는 경우에만 구식 API를 구현했다.
</p>
<h4 name=".EC.97.98.EB.A6.AC.EB.A8.BC.ED.8A.B8_.EC.A0.91.EA.B7.BC">엘리먼트 접근</h4>
<p>크로스 브라우저 접근법을 사용해서 엘리먼트 레퍼런스를 탐색하기 위해서는 <code>document.getElementById(aID)</code>를 사용하는데, 이것은 IE 5.0+, Mozilla기반 브라우저, 그리고 다른 W3C 적용 브라우저들에서 작동하며 DOM Level 1 스펙의 일부이다.
</p><p>Mozilla는 document.elementName이라던지 엘리먼트의 name을 통해서 접근하는 방법을 지원하지 않는 반면에 IE는 이를 지원한다. (<em>global namespace polluting</em>이라고도 부른다.) Mozilla는 넷스케이프 4의 <code>document.layers</code> 메소드나 IE의 <code>document.all</code> 메소드도 지원하지 않는다. <code>document.getElementById</code>가 하나의 엘리먼트를 찾아내는 방법인 반면에 <code>document.layers</code>나 <code>document.all</code>를 사용하면 모든 <code>&lt;div&gt;</code> 엘리먼트들과 같이 특정 태그명의 모든 문서 엘리먼트들의 리스트를 얻을 수 있다.
</p><p>W3C DOM Level 1 메소드는 <code>getElementsByTagName()</code>을 통해 같은 태그명을 가진 모든 엘리먼트들에 대한 레퍼런스를 얻을 수 있다. 이 메소드는 자바스크립트에서 배열로 반환되며, <code>document</code> 엘리먼트에 호출되거나, 다른 노드들에 그 하위 구조만을 탐색하게 호출할 수 있다. DOM 트리에서 모든 엘리먼트들에 대한 배열을 얻으려면 <code>getElementsByTagName("*")</code>를 사용한다.
</p><p>표 1에서 보는 바와 같이, DOM Level 1 메소드는 엘리먼트를 특정 위치로 옮기거나 (메뉴, 에니메이션 등을) 보이게 혹은 안보이게 하는데 공통적으로 쓰인다. 넷스케이프 4는 Mozilla가 지원하지 않는 <code>&lt;layer&gt;</code>태그를 아무곳에나 위치시킬 수 있는 HTML 엘리먼트로사용했다. Mozilla에서는 <code>&lt;div&gt;</code> 태그를 사용하여 어떠한 엘리먼트라도 위치시킬 수 있는데, 이것은 IE도 잘 사용되며 HTML 스펙에 나와있는 것이다.
</p>
<table class="standard-table">
<caption> 표 1. Methods used to access elements
</caption><tbody><tr>
<th> Method </th><th> Description
</th></tr>
<tr>
<td> document.getElementById( aId ) </td><td> Returns a reference to the element with the specified ID.
</td></tr>
<tr>
<td> document.getElementsByTagName( aTagName ) </td><td> Returns an array of elements with the specified name in the document.
</td></tr></tbody></table>
<h4 name="DOM_.ED.83.90.EC.83.89">DOM 탐색</h4>
<p>Mozilla는 자바스크립트를 통하여 DOM 트리를 탐색하는 W3C DOM API를 지원한다(표 2 참조). 이 API는 문서 내에 있는 각 노드들에 대해 존재하고 아무 방향으로나 탐색하는 것이 가능하다. IE도 이 API들을 잘 지원하지만 IE는 <code>children</code> 속성처럼 DOM 트리를 탐색할 수 있는 구식 API들도 역시 지원한다.
</p>
<table class="standard-table">
<caption> 표 2. Methods used to traverse the DOM
</caption><tbody><tr>
<th> Property/Method </th><th> Description
</th></tr>
<tr>
<td> childNodes </td><td> Returns an array of all child nodes of the element.
</td></tr>
<tr>
<td> firstChild </td><td> Returns the first child node of the element.
</td></tr>
<tr>
<td> getAttribute( aAttributeName ) </td><td> Returns the value for the specified attribute.
</td></tr>
<tr>
<td> hasAttribute( aAttributeName ) </td><td> Returns a boolean stating if the current node has an attribute defined with the specified name.
</td></tr>
<tr>
<td> hasChildNodes() </td><td> Returns a boolean stating whether the current node has any child nodes.
</td></tr>
<tr>
<td> lastChild </td><td> Returns the last child node of the element.
</td></tr>
<tr>
<td> nextSibling </td><td> Returns the node immediately following the current one.
</td></tr>
<tr>
<td> nodeName </td><td> Returns the name of the current node as a string.
</td></tr>
<tr>
<td> nodeType </td><td> Returns the type of the current node.
<table>
<tbody><tr>
<th> Value </th><th> Description
</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 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>
</td></tr>
<tr>
<td> nodeValue </td><td> Returns the value of the current node. For nodes that contain text, such as text and comment nodes, it will return their string value. For attribute nodes, the attribute value is returned. For all other nodes, <code>null</code> is returned.
</td></tr>
<tr>
<td> ownerDocument </td><td> Returns the <code>document</code> object containing the current node.
</td></tr>
<tr>
<td> parentNode </td><td> Returns the parent node of the current node.
</td></tr>
<tr>
<td> previousSibling </td><td> Returns the node immediately preceding the current one.
</td></tr>
<tr>
<td> removeAttribute( aName ) </td><td> Removes the specified attribute from the current node.
</td></tr>
<tr>
<td> setAttribute( aName, aValue ) </td><td> Sets the value of the specified attribute with the specified value.
</td></tr></tbody></table>
<p>IE는 비표준 쿼크를 가지는데 이들 API의 많은 수가 뉴라인 같이 생성된 공백 텍스트 노드를 무시한다. Mozilla는 이를 무시하지 않는다. 그래서 가끔씩 이들 노드를 구별해 줄 필요가 있다. 모든 노드들은 노드 타입을 지정하는 nodeType 속성을 가지고 있다. 예를 들어, 엘리먼트 노드는 타입 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){ 
      // element node
    };
  };
</pre>
<h4 name=".EC.BB.A8.ED.85.90.EC.B8.A0.EC.9D.98_.EC.83.9D.EC.84.B1.EA.B3.BC_.EC.A1.B0.EC.9E.91">컨텐츠의 생성과 조작</h4>
<p>Mozilla는 <code>document.write</code>, <code>document.open</code>, <code>document.close</code>와 같이 DOM에 동적으로 컨텐츠를 추가하는 구형 메소드를 지원한다. Mozilla는 IE의 <code>innerHTML</code> 메소드도 지원하는데 이것은 거의 모든 노드에서 호출 가능하다. 그러나, <code>outerHTML</code>(엘리먼트 주변에 마크업을 추가하며 표준은 없다.)와 <code>innerText</code>(노드의 텍스트 값을 지정하며 Mozilla에서는 <code>textContent</code>를 사용하여 조작가능)는 지원하지 않는다.
</p><p>IE는 비표준이며 Mozilla에서는 지원하지 않는 몇몇 컨텐츠 조작 메소드를 가지고 있는데 여기에는 값을 추출해 내거나 텍스트를 삽입하고 <code>getAdjacentElement</code>, <code>insertAdjacentHTML</code>와 같은 노드 주변에 엘리먼트를 삽입하는 것들이 포함된다. 표3은 W3C와 Mozilla가 어떻게 컨텐츠를 조작하는지를 보여주며, 모두 어떠한 DOM 노드에서라도 사용할 수 있는 메소드들이다.
</p>
<table class="standard-table">
<caption> 표 3. Methods Mozilla uses to manipulate content
</caption><tbody><tr>
<th> Method </th><th> Description
</th></tr>
<tr>
<td> appendChild( aNode ) </td><td> Creates a new child node. Returns a reference to the new child node.
</td></tr>
<tr>
<td> cloneNode( aDeep ) </td><td> Makes a copy of the node it is called on and returns the copy. If aDeep is true, it copies over the node's entire subtree.
</td></tr>
<tr>
<td> createElement( aTagName ) </td><td> Creates and returns a new and parentless DOM node of the type specified by aTagName.
</td></tr>
<tr>
<td> createTextNode( aTextValue ) </td><td> Creates and returns a new and parentless DOM textnode with the data value specified by aTextValue.
</td></tr>
<tr>
<td> insertBefore( aNewNode, aChildNode ) </td><td> Inserts aNewNode before aChildNode, which must be a child of the current node.
</td></tr>
<tr>
<td> removeChild( aChildNode ) </td><td> Removes aChildNode and returns a reference to it.
</td></tr>
<tr>
<td> replaceChild( aNewNode, aChildNode ) </td><td> Replaces aChildNode with aNewNode and returns a reference to the removed node.
</td></tr></tbody></table>
<h4 name=".EB.8F.84.ED.81.90.EB.A8.BC.ED.8A.B8_.ED.94.84.EB.9E.98.EA.B7.B8.EB.A8.BC.ED.8A.B8">도큐먼트 프래그먼트</h4>
<p>실행 성능상의 이유로 현재 존재하고 있는 문서의 DOM에서 작업하기 보다 메모리 상에서 도큐먼트를 생성할 수 있다. DOM Level 1 Core는 도큐먼트 프래그먼트를 도입했는데 이것은 보통의 도큐먼트 인터페이스의 부분집합을 가지는 경량의 도큐먼트이다. 예를 들어, <code>getElementById</code>는 존재하지 않지만 <code>appendChild</code>는 존재한다. 또한 현재 존재하고 있는 도큐먼트에 쉽게 도큐먼트 프래그먼트를 추가할 수 있다.
</p><p>Mozilla 는 <code>document.createDocumentFragment()</code>를 통하여 빈 도큐먼트 프래그먼트를 생성할 수 있다.
</p><p>그러나 IE에서의 도큐먼트 프래그먼트 구현은 W3C 웹표준을 따르지 않으며 단순히 보통의 도큐먼트를 리턴한다.
</p>
<h3 name=".EC.9E.90.EB.B0.94.EC.8A.A4.ED.81.AC.EB.A6.BD.ED.8A.B8_.EC.B0.A8.EC.9D.B4">자바스크립트 차이</h3>
<p>Mozilla와 IE간의 대부분의 차이점은 보통 자바스크립트에 대한 것이다. 그러나 이러한 문제들은 DOM hook과 같이 브라우저가 자바스크립트에 대해 드러내는 API들에서는 보통 거짓이다. 두 브라우저간 코어 자바스크립트의 차이점은 거의 없다. 문제는 타이밍 관련된 이슈에서 종종 생긴다.
</p>
<h4 name=".EC.9E.90.EB.B0.94.EC.8A.A4.ED.81.AC.EB.A6.BD.ED.8A.B8_.EB.82.A0.EC.A7.9C_.EC.B0.A8.EC.9D.B4">자바스크립트 날짜 차이</h4>
<p>단하나의 <code>Date</code> 차이점은 <code>getYear</code> 메소드이다. ECMAScript 스펙(자바스크립트가 따르는 명세)에 따르면 이 메소드는 Y2K 적용이 되지 않았기 때문에 2004년에 <code>new Date().getYear()</code>를 실행시키면 "104"를 리턴한다. ECMAScript 스펙에 따르면 <code>getYear</code>는 해당년도에서 1900을 뺀 수를 리턴한다. 이것은 본래 1998년에 대해 "98"을 리턴하는 의미였다. getYear는 ECMAScript 버전3에서 deprecated되었고 <code>getFullYear()</code>로 교체되었다. Mozilla가 표준 작동을 준수하는 반면 IE는 <code>getYear()</code>를 변경하여 <code>getFullYear()</code>와 같은 동작을 하게 하여 Y2K 적용을 시켰다.
</p>
<h4 name=".EC.9E.90.EB.B0.94.EC.8A.A4.ED.81.AC.EB.A6.BD.ED.8A.B8_.EC.8B.A4.ED.96.89_.EC.B0.A8.EC.9D.B4">자바스크립트 실행 차이</h4>
<p>서로다른 브라우저는 자바스크립트를 다르게 실행한다. 예를 들어, 다음 코드는 <code>script</code> 코드 실행 시점에 DOM 내에 <code>div</code> 노드가 이미 존재하고 있음을 가정한다.
</p>
<pre>...
&lt;div id="foo"&gt;Loading...&lt;/div&gt;

&lt;script&gt; 
  document.getElementById("foo").innerHTML = "Done."; 
&lt;/script&gt; 
</pre>
<p>그러나, 이것은 보장할 수 없다. 모든 엘리먼트가 존재함을 보장하기 위해서는 <code>&lt;body&gt;</code>태그에 <code>onload</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>이러한 타이밍 관련 문제에는 하드웨어도 역시 관련된다. 느린 시스템에서는 빠른 시스템에서 감춰지는 버그들이 드러날 수 있다. 확실한 예 중의 하나는 새 윈도우를 여는  <code>window.open</code>이다.
</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>이 비동기라는 것이다. 이것은 윈도우가 로딩을 마칠때 까지 자바스크립트 실행을 차단해 놓지 않는다. 그러므로, 새 윈도우가 뜨기도 전에  <code>window.open</code> 라인의 다음 라인이 실행될 수가 있다. 이것은 새 창에서 <code>onload</code> 핸들러를 가지게 하고 (<code>window.opener</code>를 사용하여) 새 창을 연 윈도우로 콜백 실행을 하게 하여 해결할 수 있다.
</p>
<h4 name=".EC.9E.90.EB.B0.94.EC.8A.A4.ED.81.AC.EB.A6.BD.ED.8A.B8.EA.B0.80_.EC.83.9D.EC.84.B1.ED.95.98.EB.8A.94_HTML.EC.9D.98_.EC.B0.A8.EC.9D.B4">자바스크립트가 생성하는 HTML의 차이</h4>
<p>자바스크립트는 <code>document.write</code>를 사용하여 문자열에서 HTML을 생성해낼 수 있다. 여기에서의 주요 문제는 HTML 문서 내부에 포함된 (즉, <code>&lt;script&gt;</code> 태그 내부의) 자바 스크립트가 <code>&lt;script&gt;</code>태그를 포함한 HTML을 생성하는 경우이다. 만약 문서가 strict 렌더링 모드라면 문자열 내부의 <code>&lt;/script&gt;</code> 태그를 바깥쪽의 <code>&lt;script&gt;</code>에 대한 닫는 태그로서 파싱할 것이다. 다음 코드는 이것을 가장 잘 설명한다.
</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 type='text\/javascript'&gt;alert('Hello');&lt;\/script&gt;") 
&lt;/script&gt; 
</pre>
<p>페이지가 strict 모드이므로, Mozilla의 파서는 첫번째 <code>&lt;script&gt;</code>를 보고 이에 대한 닫는 태그를 찾을때까지, 즉 첫번째 <code>&lt;/script&gt;</code>를 찾을때까지  파싱한다. 이것은 파서가 strict 모드일때 자바스크립트 (혹은 다른 언어)에 관해 모르기 때문이다. 쿼크 모드에서 파서는 파싱시 (느려짐) 자바스크립트에 대해 알고 있다. IE는 항상 쿼크 모드이다 그래서 IE는 진정한 XHTML을 지원하지 않는다. 이것을 Mozilla의 strict 모드에서 작동하게 하려면 문자열을 두부분으로 분리한다:
</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 type='text\/javascript'&gt;alert('Hello');&lt;/" + "script&gt;") 
&lt;/script&gt; 
</pre>
<h4 name=".EC.9E.90.EB.B0.94.EC.8A.A4.ED.81.AC.EB.A6.BD.ED.8A.B8_.EB.94.94.EB.B2.84.EA.B9.85">자바스크립트 디버깅</h4>
<p>Mozilla는 IE를 위해 만들어진 어플리케이션들에서 발견되는 자바스크립트 관련 문제들을 디버깅할 수 있는 몇가지 방법을 제공한다. 첫번째 툴은 그림 1에서 보는 것처럼 내장된 자바스크립트 콘솔이다. 여기에는 에러와 경고가 표시된다. Mozilla에서 <b>도구 -&gt;  Web Development -&gt; JavaScript Console</b>를 실행하거나 파이어폭스 (Mozilla에서 나온 단독 브라우저 제품)에서는 <b>도구 -&gt; JavaScript Console</b>를 실행한다.
</p><p>그림 1. JavaScript 콘솔
</p><p><img alt="Javascript 콘솔" src="File:ko/Media_Gallery/Migrationguide-jsconsole.jpg">
</p><p>자바스크립트 콘솔은 에러나 경고, 혹은 메시지에 대한 전체 기록 목록을 보여줄 수 있다. 그림 1의 에러 메시지는 aol.com의 95번째 라인이 is_ns70이라는 정의되지 않은 변수를 접근하려한다는 것을 알려준다. 링크를 클릭하면 Mozilla의 내부 소스보기 창이 열리고 해당 라인이 하이라이트되어 있을 것이다.
</p><p>콘솔에서는 자바스크립트를 실행할 수도 있다. 입력한 자바스크립트 문법을 실행하려면 그림 2처럼 입력창에 <code>1+1</code>을 치고 <b>Evaluate</b>를 누르면 된다.
</p><p>그림 2. JavaScript console evaluating
</p><p><img alt="JavaScript Console evaluating" src="File:ko/Media_Gallery/Migrationguide-jsconsole-eval.jpg">
</p><p>Mozilla의 자바스크립트 엔진은 디버깅에 대한 내장된 지원을 하므로 자바스크립트 개발자들에게 강력한 툴을 제공할 수 있다. 그림 3에 있는 Venkman은 Mozilla에 통합된 강력한 크로스 플랫폼 자바스크립트 디버거이다. 이것은 보통 Mozilla 릴리즈에 포함된다. <b>도구 -&gt; Web Development -&gt; JavaScript Debugger</b>로 가면 찾을 수 있다. 파이어 폭스에서는 이 디버거가 포함되어 있지 않다. 대신에 Venkman Project Page에서 다운로드 받아 설치할 수 있다. Venkman Development Page에 있는 개발 관련 페이지에서는 튜토리얼도 찾을 수 있다.
</p><p>그림 3. Mozilla의 JavaScript 디버거
</p><p><img alt="Mozilla의 JavaScript 디버거" src="File:ko/Media_Gallery/Migrationguide-venkman.jpg">
</p><p>자바스크립트 디버거는 Mozilla 브라우저 창에서 실행중인 자바스크립트를 디버깅할 수 있다. 이것은 breakpoint관리, call stack inspection 혹은 variable/object inspection과 같은 표준 디버깅 기능들을 지원한다. 모든 기능들은 사용자 인터페이스를 통하거나 디버거의 대화 콘솔을 통하여 접근할 수 있다. 콘솔을 사용하면 현재 디버깅하는 자바스크립트와 같은 스코프에서 임시적인 자바스크립트를 실행시킬 수 있다.
</p>
<h3 name="CSS_.EC.B0.A8.EC.9D.B4">CSS 차이</h3>
<p>Mozilla-based products have the strongest support for Cascading Style Sheets (CSS), including most of CSS1, CSS2.1 and parts of CSS3, compared to Internet Explorer as well as all other browsers. 
</p><p>For most issues mentioned below, Mozilla will add an error or warning 
entry into the JavaScript console. Check the JavaScript console if you encounter CSS-related issues. 
</p>
<h4 name="Mimetypes_.28CSS_.ED.8C.8C.EC.9D.BC.EC.9D.B4_.EC.A0.81.EC.9A.A9.EB.90.98.EC.A7.80_.EC.95.8A.EC.95.98.EC.9D.84_.EB.95.8C.29">Mimetypes (CSS 파일이 적용되지 않았을 때)</h4>
<p>The most common CSS-related issue is that CSS definitions inside 
referenced CSS files are not applied. This is usually due to the server 
sending the wrong mimetype for the CSS file. The CSS specification states 
that CSS files should be served with the <code>text/css</code> mimetype. Mozilla will respect this and only load CSS files with that mimetype if the Web page is in strict standards mode. Internet Explorer will always load the CSS file, no matter with 
which mimetype it is served. Web pages are considered in strict standards 
mode when they start with a strict doctype. To solve this problem, you can 
make the server send the right mimetype or remove the doctype. I'll 
discuss more about doctypes in the next section. 
</p>
<h4 name="CSS_.EC.99.80_units">CSS 와 units</h4>
<p>Many Web applications do not use units with their CSS, especially when 
you use JavaScript to set the CSS. Mozilla tolerates this, as long as the 
page is not rendered in strict mode. Since Internet Explorer does not 
support true XHTML, it does not care if no units are specified. If the 
page is in strict standards mode, and no units are used, then Mozilla 
ignores the style:  
</p>
<pre class="eval">&lt;DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
  "<span class="plain">http://www.w3.org/TR/html4/strict.dtd</span>"&gt; 
&lt;html&gt; 
  &lt;head&gt; 
   &lt;meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"&gt;
   &lt;title&gt;CSS and units example&lt;/title&gt; 
  &lt;/head&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>Since the above example has a strict doctype, the page is rendered in 
strict standards mode. The first div will have a width of 40px, since it 
uses units, but the second div won't get a width, and thus will default to 
100% width. The same would apply if the width were set through JavaScript.
</p>
<h4 name="JavaScript_.EC.99.80_CSS">JavaScript 와 CSS</h4>
<p>Since Mozilla supports the CSS standards, it also supports the CSS DOM 
standard for setting CSS through JavaScript. You can access, remove, and 
change an element's CSS rules through the element's <code>style</code> member:  
</p>
<pre>&lt;div id="myDiv" style="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>You can reach every CSS attribute that way. Again, if the Web page is in strict mode, you must set a unit or else Mozilla will ignore the command. When you query a value, say through <code>.style.width</code>, in Mozilla and Internet Explorer, the returned value will contain the unit, meaning a string is returned. You can convert the string into a number through <code>parseFloat("40px")</code>.
</p>
<h4 name="CSS_overflow_.EC.B0.A8.EC.9D.B4">CSS overflow 차이</h4>
<p>CSS added the notion of overflow, which allows you to define how to 
handle overflow; for example, when the contents of a <code>div</code> with a specified height are taller than that height. The CSS standard defines that if no overflow behavior is set in this case, the <code>div</code> contents will overflow. 
However, Internet Explorer does not comply with this and will expand the 
<code>div</code> beyond its set height in order to hold the 
contents. Below is an example that shows this difference: 
</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>As you can see in Figure 4, Mozilla acts like the W3C standard specifies. 
The W3C standard says that, in this case, the inner <code>div</code> overflows to the bottom since the inner content is taller than its parent. If you prefer the Internet Explorer behavior, simply do not specify a height on the outer element. 
</p><p>Figure 4. DIV overflow
</p><p><img alt="DIV Overflow" src="File:ko/Media_Gallery/Migrationguide-overflow.jpg">
</p>
<h4 name="hover_.EC.B0.A8.EC.9D.B4">hover 차이</h4>
<p>The nonstandard CSS hover behavior in Internet Explorer occurs on quite 
a few web sites. It usually manifests itself by changing text style 
when hovered over in Mozilla, but not in Internet Explorer. This is because the <code>a:hover</code> CSS selector in Internet Explorer matches 
<code>&lt;a href=""&gt;...&lt;/a&gt;</code> but not <code>&lt;a name=""&gt;...&lt;/a&gt;</code>, which sets anchors in HTML. The 
text changes occur because authors encapsulate the areas with the 
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 follows the CSS specification correctly and will change the 
color to green in this example. You can use two ways to make Mozilla behave 
like Internet Explorer and not change the color of the text when hovered 
over:
</p>
<ul><li>First, you can change the CSS rule to be <code>a:link:hover {color: green;}</code>, which will only change the color if the element is a link (has an <code>href</code> attribute).
</li><li>Alternatively, you can change the markup and close the opened <code>&lt;a /&gt;</code> before the start of the text -- the anchor will continue to work this way.
</li></ul>
<h3 name="Quirks_.EA.B3.BC_standards_.EB.AA.A8.EB.93.9C">Quirks 과 standards 모드</h3>
<p>Older legacy browsers, such as Internet Explorer 4, rendered with so-called quirks 
under certain conditions. While Mozilla aims to be a standards-compliant 
browser, it has three modes that support older Web pages created with 
these quirky behaviors. The page's content and delivery determine which 
mode Mozilla will use. Mozilla will indicate the rendering mode in <b>View -&gt; Page Info</b> (or <kbd>Ctrl+I</kbd>) ; Firefox will list the rendering mode in <b>Tools -&gt; Page Info</b>. The mode in which a page is located depends on its doctype. 
</p><p>Doctypes (short for document type declarations) look like this: 
</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="plain">http://www.w3.org/TR/html4/loose.dtd</span>"</span>&gt;</code>
</p><p>The section in blue is called the public identifier, the green part is 
the system identifier, which is a URI. 
</p>
<h4 name="Standards_.EB.AA.A8.EB.93.9C">Standards 모드</h4>
<p>Standards mode is the strictest rendering mode -- it will render pages 
per the W3C HTML and CSS specifications and will not support any quirks. 
Mozilla uses it for the following conditions: 
</p>
<ul><li>If a page is sent with a <code>text/xml</code> mimetype or any other XML or XHTML mimetype
</li><li>For any "DOCTYPE HTML SYSTEM" doctype (for example, <code>&lt;!DOCTYPE HTML SYSTEM "<span class="plain">http://www.w3.org/TR/REC-html40/strict.dtd</span>"&gt;</code>), except for the IBM doctype
</li><li>For unknown doctypes or doctypes without DTDs
</li></ul>
<h4 name="Almost_standards_.EB.AA.A8.EB.93.9C">Almost standards 모드</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>그림 5. 이미지 간격
</p><p><img alt="이미지 간격" src="File:ko/Media_Gallery/Migrationguide-imagegap.jpg">
</p><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="plain">http://www.w3.org/TR/html4/loose.dtd</span>"&gt;</code>)
</li><li>For the IBM doctype (<code>&lt;!DOCTYPE html SYSTEM "<span class="plain">http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd</span>"&gt;</code>)
</li></ul>
<p><a href="ko/Images%2c_Tables%2c_and_Mysterious_Gaps">이미지 간격 이슈</a>에서 더 많은 정보를 얻을 수 있습니다.
</p>
<h4 name="Quirks_.EB.AA.A8.EB.93.9C">Quirks 모드</h4>
<p>Currently, the Web is full of invalid HTML markup, as well as markup 
that only functions due to bugs in browsers. The old Netscape browsers, 
when they were the market leaders, had bugs. When Internet Explorer 
arrived, it mimicked those bugs in order to work with the content at that 
time. As newer browsers came to market, most of these original bugs, 
usually called <b>quirks</b>, were kept for backwards compatibility. 
Mozilla supports many of these in its quirks rendering mode. Note that due 
to these quirks, pages will render slower than if they were fully 
standards-compliant. Most Web pages are rendered under this mode. 
</p><p>Mozilla uses quirks mode for the following conditions:
</p>
<ul><li>When no doctype is specified
</li><li>For doctypes without a system identifier (for example, <code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;</code>)
</li></ul>
<p>For further reading, check out: <a href="ko/Mozilla_Quirks_Mode_Behavior">Mozilla Quirks Mode Behavior</a> and <a href="ko/Mozilla's_DOCTYPE_sniffing">Mozilla's DOCTYPE sniffing</a>.
</p>
<h3 name="Event_.EC.B0.A8.EC.9D.B4">Event 차이</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 ? aEvent : window.event; 
  }
&lt;/script&gt;
</pre>
<p>Sometimes this doesn't work because Internet Explorer "catches" the aEvent parameter, identifiying it as not null, making it not use window.event any longer. The solution is to simply test for the window.event property:
</p>
<pre>&lt;div onclick="handleEvent(event);"&gt;Click me!&lt;/div&gt;

&lt;script&gt;
  function handleEvent(aEvent) { 
    var myEvent = window.event ? window.event : aEvent;
  }
&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>
<table class="standard-table">
<caption> Table 4. Event properties differences between Mozilla and Internet Explorer
</caption><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 element viewport.
</td></tr>
<tr>
<td> clientY </td><td> clientY
</td><td> The Y coordinate of the event, in relation to the element viewport.
</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> screenY </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 name="Attach_event_handlers">Attach event handlers</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 ? aEvent : 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. After 
arriving at the target, it walks up the DOM tree back to the outermost 
node; this is <b>bubbling</b>. 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 ? aEvent : 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>
<table class="standard-table">
<caption> Table 5. Event method differences between Mozilla and Internet Explorer
</caption><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 name="Rich_text_.ED.8E.B8.EC.A7.91">Rich text 편집</h3>
<p>While Mozilla prides itself with being the most W3C web standards compliant 
browser, it does support nonstandard functionality, such as <code>innerHTML</code> and <a href="ko/Midas">rich text editing</a>, if no W3C equivalent exists.
</p><p>Mozilla 1.3 introduced an implementation of Internet Explorer's 
<a href="ko/Rich-Text_Editing_in_Mozilla/Class_xbDesignMode">designMode</a> 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 name="Rich_text_.EC.B0.A8.EC.9D.B4">Rich text 차이</h4>
<p>Mozilla supports the W3C standard of accessing iframe's document object 
through <code>IFrameElmRef.contentDocument</code>, while Internet Explorer 
requires you to access it through <code>document.frames{{mediawiki.external('\"IframeName\"')}}</code> and then access the resulting <code>document</code>:
</p>
<pre>&lt;script&gt;
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;
}
&lt;/script&gt; 
</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>
<table class="standard-table">
<caption> Table 6. Rich text editing commands
</caption><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="ko/Rich-Text_Editing_in_Mozilla">Rich-Text Editing in Mozilla</a>.
</p>
<h3 name="XML_.EC.B0.A8.EC.9D.B4">XML 차이</h3>
<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 name="How_to_handle_XML">How to handle XML</h4>
<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 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;   
  &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 != 3) &amp;&amp;
          myChildren[run].nodeType != 8) ){ 
      // not a text or comment node 
    };
  };
</pre>
<h4 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);
  }
</pre>
<h4 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>
<table class="standard-table">
<caption>Table 7. XMLHttpRequest methods and properties</caption> 
  <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 name="XSLT_.EC.B0.A8.EC.9D.B4">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="plain">http://www.w3.org/1999/XSL/Transform</span></code>, while the 
working draft's namespace is <code><span class="plain">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>
<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>
<table class="standard-table">
<caption>Table 8. XSLTProcessor methods</caption>
  <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 name=".EC.9B.90.EB.9E.98_.EB.AC.B8.EC.84.9C_.EC.A0.95.EB.B3.B4"> 원래 문서 정보 </h3>
<ul><li> Author(s): Doron Rosenberg, IBM Corporation
</li><li> Published: 26 Jul 2005
</li><li> Link: http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/
</li></ul>
</div>
{{ wiki.languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla" } ) }}
Revert to this revision