Migration d'applications d'Internet Explorer vers Mozilla

  • Raccourci de la révision : Migration_d'applications_d'Internet_Explorer_vers_Mozilla
  • Titre de la révision : Migration d'applications d'Internet Explorer vers Mozilla
  • ID de la révision : 139403
  • Créé :
  • Créateur : BenoitL
  • Version actuelle ? Non
  • Commentaire /* DOM differences */

Contenu de la révision

{{template.Traduction_en_cours("Migrate apps from Internet Explorer to Mozilla")}}

Introduction

Lorsque Netscape a débuté le projet Mozilla, la décision de suivre les standards du W3C a été prise en toute conscience. C'est la raison pour laquelle Mozilla n'est pas entièrement compatible avec le code anciennement conçu pour Netscape Navigator 4.x et Microsoft Internet Explorer. Par exemple, Mozilla ne reconnaît pas <layer> comme nous le verrons plus tard. Les navigateurs, comme Internet Explorer 4, qui ont été conçus avant la publication des standards du W3C ont hérité de nombreuses bizarreries. Nous parlerons dans cet article du mode quirks de Mozilla, qui offre une bonne compatibilité HTML ascendante avec Internet Explorer et d'autres anciens navigateurs.

Nous aborderons également de certaines technologies non standard, comme XMLHttpRequest et l'édition de texte enrichi, que Mozilla supporte parce qu'aucun équivalent W3C n'existait à l'époque. Parmi les standards supportés, on peut citer :

Astuces générales de codage multinavigateur

Même si les standards du Web existent, des navigateurs différents se comporteront différemment (en réalité, le même navigateur peut se comporter différemment suivant la plateforme). De nombreux navigateurs, comme Internet Explorer, gèrent également des API plus anciennes que celles du W3C et le support complet de celles-ci n'a jamais été ajouté.

Avant de se plonger dans les différences entre Mozilla et Internet Explorer, voyons quelques manières de base de rendre une application Web extensible afin qu'elle puisse fonctionner dans de nouveaux navigateurs par la suite.

Puisque des navigateurs différents utilisent parfois des API différentes pour la même fonctionnalité, on trouvera souvent une série de blocs if() else() tout au long du code pour différentier les différents navigateurs. Le code qui suit montre des blocs conçus pour for Internet Explorer :

. . . 

var elm; 

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

Ce code n'est pas extensible, par conséquent si l'on désire qu'il gère un nouveau navigateur, ces blocs doivent être mis à jour un peu partout dans l'application Web.

La manière la plus simple d'éliminer le besoin de recoder pour un nouveau navigateur est de rendre la fonctionnalité abstraite. Plutôt que d'utiliser une série de blocs if() else(), il sera plus performant d'extraire certaines tâches courantes et de les placer dans leurs propres fonctions. Non seulement le code en sera plus lisible, mais l'ajout de nouveaux clients en sera simplifié :

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

Ce code a toujours un problème, c'est qu'il utilise un « sniffing » du navigateur, c'est-à-dire qu'il détecte le navigateur utilisé par l'utilisateur. Le sniffing est généralement fait sur la chaîne d'agent utilisateur (useragent), comme celle-ci :

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

Bien que l'utilisation de la chaîne useragent pour détecter le navigateur fournisse un bon nombre d'informations détaillées sur le navigateur utilisé, le code de gestion de ces chaînes peut souvent faire des erreurs lorsque de nouvelles versions de ces navigateurs font leur apparition, ce qui oblige à modifier le code.

Si le type de navigateur n'a pas d'importance (supposons que l'accès à l'application Web ait déjà été bloqué aux navigateurs non supportés), il est nettement plus sûr et efficace de vérifier le support de capacités ou d'objets particuliers du navigateur. Cela peut généralement être réalisé en testant la fonctionnalité requise en JavaScript. Par exemple, plutôt que :

if (isMozilla || isIE5) 

On peut utiliser :

if (document.getElementById) 

Cela permettra à d'autres navigateurs supportant cette méthode standard du W3C, comme Opera ou Safari, de fonctionner sans aucun changement.

Le sniffing de la chaîne useragent reste cependant approprié lorsque la précision est importante, comme la vérification qu'un navigateur soit d'une version suffisante pour accéder à votre application Web ou si vous essayez de contourner un bug connu.

JavaScript permet également d'utiliser des instructions conditionnelles en une ligne, qui peuvent rendre le code plus lisible :

var test = (condition) ? laConditionEstVraie : laConditionEstFausse; 

Par exemple, pour retrouver un élément, on peut utiliser :

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

Une autre manière est d'utiliser l'opérateur <tt>||</tt> :

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

Différences entre Mozilla et Internet Explorer

Pour commencer, nous parlerons des différences entre la manière dont HTML se comporte dans Mozilla et dans Internet Explorer.

Bulles d'information

Les premiers navigateurs ont introduit les bulles d'information en HTML en les montrant sur les liens et en utilisant la valeur de l'attribut alt d'une image comme contenu de cette bulle. Les spécifications HTML du W3C ont cependant créé l'attribut title, prévu pour contenir une description détaillée du lien. Les navigateurs modernes utiliseront cet attribut title pour afficher des bulles d'information, et Mozilla ne les affichera que pour cet attribut, jamais pour l'attribut alt.

Entités

Le balisage HTML peut contenir plusieurs entités, qui ont été définies par le W3C. Celles-ci peuvent être référencées par leu valeur numérique ou par une chaîne de caractères. Par exemple, le caractère d'espacement #160 peut être référencé par &#160; ou par sa référence en caractères équivalente &nbsp;.

Certains navigateurs plus anciens, comme Internet Explorer, étaient permissifs jusqu'à laisser utiliser des entités sans le caractère ; (point-virgule) à la fin et continuer le texte :

&nbsp Foo 
&nbsp&nbsp Foo 

Mozilla affichera les &nbsp ci-dessus comme des espaces, même si c'est à l'encontre des spécifications du W3C. Le navigateur ne traitera par contre pas un &nbsp s'il est directement suivi d'autres caractères, par exemple :

&nbsp12345 

Ce dernier code ne fonctionnera pas dans Mozilla, puisqu'il ne respecte absolument pas les standards du W3C. Utilisez toujours la forme correcte (&nbsp;) pour éviter les différences de traitement entre les navigateurs.

Différences dans le DOM

Le Document Object Model (DOM) est la structure arborescente contenant les éléments du document. Celle-ci peut être manipulée au travers d'API JavaScript qui ont été standardisées par le W3C. Cependant, avant cette standardisation, Netscape 4 et Internet Explorer 4 avaient déjà implémenté des API similaires. Mozilla n'implémente ces anciennes API que si elles ne sont pas réplicables avec les standards Web du W3C.

Accès aux éléments

Pour obtenir une référence à un élément en utilisant une approche multinavigateur, on utilise document.getElementById(aID) qui fonctionne dans Internet Explorer 5.0+, les navigateurs basés sur Mozilla, les autres navigateurs suivant le W3C et fait partie de la spécification DOM Level 1.

Mozilla ne permet pas d'accéder à un élément via document.elementName ou même par le nom d'un élément, ce que fait Internet Explorer (et qu'on peut appeler pollution de l'espace de noms global). Mozilla ne permet pas non plus d'utiliser les méthodes document.layers de Netscape et document.all d'Internet Explorer. Alors que document.getElementById permet de trouver un seul élément, document.layers et document.all servaient également à obtenir une liste de tous les éléments portant un certain nom de balise, comme tous les éléments <div>.

La méthode du DOM Level 1 du W3C obtient les références de tous les éléments portant le même nom de balise par getElementsByTagName(). Cette méthode renvoie un tableau en JavaScript, et peut également être appelée sur l'élément document ou sur d'autres nœuds pour chercher uniquement parmi leurs descendants dans l'arbre. Pour obtenir un tableau de tous les éléments dans l'arbre DOM, on peut utiliser getElementsByTagName("*").

Les méthodes du DOM Level 1, telles que montrées dans le Tableau 1, sont souvent utilisées pour déplacer un élément à un certain endroit et modifier sa visibilité (menus, animations). Netscape 4 utilisait la balise <layer>, qui n'est pas reconnue par Mozilla, comme élément HTML pouvant être positionné n'importe où. Dans Mozilla, n'importe quel élément utilisant la balise <div> peut être repositionné, ce qui est également utilisé par Internet Explorer et figure dans la spécification HTML.

Tableau 1. Méthodes utilisées pour accéder aux éléments
Méthode Description
document.getElementById(unID) Renvoie une référence à l'élément portant l'ID spécifié.
document.getElementsByTagName(nomBalise) Renvoie un tableau des éléments portant le nom spécifié dans le document.

Parcours du DOM

Mozilla supporte les API du DOM W3C pour le parcours de l'arbre DOM depuis JavaScript (voir le Tableau 2). Ces API existent pour chaque nœud dans le docment et permettent de parcourir l'arbre dans toutes les directions. Internet Explorer supporte également ces API, outre ses anciennes API de parcours de l'arbre DOM comme la propriété children.

Tableau 2. Méthodes utilisées pour parcourir le DOM
Propriété/Méthode Description
childNodes Renvoie un tableau de tous les nœuds enfants de l'élément.
firstChild Renvoie le premier nœud enfant de l'élément.
getAttribute(nomAttribut) Renvoie la valeur de l'attribut spécifié.
hasAttribute(nomAttribut) Renvoie une valeur booléenne précisant si le nœud courant a un attribut défini portant le nom spécifié.
hasChildNodes() Renvoie une valeur booléenne précisant si le nœud courant a des nœuds enfants.
lastChild Renvoie le dernier nœud enfant de l'élément.
nextSibling Renvoie le nœud suivant directement le nœud courant.
nodeName Renvoie le nom du nœud courant sous la forme d'une chaîne.
nodeType Renvoie le type du nœud courant.
Valeur Description
1 Nœud d'élément
2 Nœud d'attribut
3 Nœud texte
4 Nœud de section CDATA
5 Nœud de référence à une entité
6 Nœud d'entité
7 Nœud d'instruction de traitement
8 Nœud de commentaire
9 Nœud de document
10 Nœud de type de document
11 Nœud de fragment de document
12 Nœud de notation
nodeValue Renvoie la valeur du nœud courant. Pour les nœuds contenant du texte, comme les nœuds texte et de commentaires, il s'agira de ce texte. Pour les nœuds d'attributs, leur valeur d'attribut. Pour tous les autres nœuds, null sera renvoyé.
ownerDocument Renvoie l'objet document contenant le nœud courant.
parentNode Renvoie le nœud parent du nœud courant.
previousSibling Renvoie le nœud qui précède immédiatement le nœud courant.
removeAttribute(nom) Retire l'attribut spécifié du nœud courant.
setAttribute(nom, valeur) Définit la valeur de l'attribut spécifié avec sur le nœud courant.

Internet Explorer a un comportement s'éloignant du standard, dans le sens où beaucoup de ces API ignoreront les nœuds comportant uniquement des espaces blancs, générés par exemple par les caractères de retour à la ligne. Mozilla ne les ignorera pas, il sera donc parfois nécessaire de les distinguer. Chaque nœud a une propriété nodeType indiquant le type de nœud. Par exemple, un élément aura le type 1, un nœud texte le type 3 et un nœud de commentaire le type 8. La meilleure manière de ne traiter que les nœuds d'éléments et de ne pas parcourir tous les nœuds enfants et de ne traiter que ceux dont l'attribut nodeType vaut 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){ 
      // nœud élément
    };
  };

Génération et manipulation de contenu

Mozilla supporte les anciennes méthodes d'ajout dynamique de contenu dans le DOM, comme document.write, document.open et document.close. Mozilla gère également la méthode innerHTML d'Internet Explorer, qui peut être appelée sur presque tous les nœuds. Il ne supporte cependant pas outerHTML (qui ajoute des balises autour d'un élément, et n'a pas d'équivalent standard) ni innerText (qui change la valeur textuelle du nœud, et qui peut être remplacée dans Mozilla par l'utilisation de textContent).

Internet Explorer dispose de plusieurs méthodes de manipulation du contenu qui ne sont pas standard et ne sont pas gérées par Mozilla, permettant de récupérer la valeur, d'insérer du texte et des éléments à côté d'un nœud, comme getAdjacentElement et insertAdjacentHTML. Le Tableau 3 montre comment manipuler le contenu avec le standard W3C et Mozilla, avec des méthodes disponibles sur tous les nœuds DOM.

Table 3. Méthodes standards utilisées par Mozilla pour manipuler le contenu
Méthode Description
appendChild(nœud) Crée un nouveau nœud enfant. Renvoie une référence à ce nouveau nœud.
cloneNode(profond) Crée une copie du nœud depuis lequel la méthode est appelée, et renvoie cette copie. Si le paramètre profond vaut true, copie également tous les descendants du nœud.
createElement(nomDeBalise) Crée et renvoie un nouveau nœud DOM orphelin (sans parent), du type d'élément spécifié par le paramètre nomDeBalise.
createTextNode(valeurTexte) Crée et renvoie un nouveau nœud DOM orphelin de type texte avec la valeur spécifiée dans valeurTexte.
insertBefore(nouveauNœud, nœudEnfant) Insère le nœud nouveauNœud avant le nœud nœudEnfant, qui doit être un enfant du nœud courant.
removeChild(nœudEnfant) Retire le nœud nœudEnfant des enfants du nœud courant, et renvoie une référence vers ce nœud.
replaceChild(nouveauNœud, nœudEnfant) Remplace le nœud nœudEnfant par nouveauNœud dans les nœuds enfants de l'élément courant et renvoie une référence vers le nœud retiré.

Fragments de document

Pour des questions de performances, il est possible de créer des documents en mémoire plutôt que de travailler avec le DOM du document existant. Le DOM Level 1 Core propose pour cela les fragments de document, qui sont des documents légers contenant un sous-ensemble des interfaces d'un document normal. Par exemple, getElementById n'y existe pas, mais appendChild bien. Il est aisé d'ajouter des fragments de document à un document existant.

Mozilla permet de créer des fragments de document à l'aide de document.createDocumentFragment(), qui renvoie un fragment de document vide.

L'implémentation des fragments de document dans Internet Explorer, par contre, ne respecte pas les standards du W3C et renvoie simplement un document normal.

JavaScript differences

Most differences between Mozilla and Internet Explorer are usually blamed on JavaScript. However, the issues usually lie in the APIs that a browser exposes to JavaScript, such as the DOM hooks. The two browsers possess few core JavaScript differences; issues encountered are often timing related.

JavaScript date differences

The only Date difference is the getYear method. As per the ECMAScript specification (which is the specification JavaScript follows), the method is not Y2k-compliant, and running new Date().getYear() in 2004 will return "104". Per the ECMAScript specification, getYear returns the year minus 1900, originally meant to return "98" for 1998. getYear was deprecated in ECMAScript Version 3 and replaced with getFullYear(). Internet Explorer changed getYear() to work like getFullYear() and make it Y2k-compliant, while Mozilla kept the standard behavior.

JavaScript execution differences

Different browsers execute JavaScript differently. For example, the following code assumes that the div node already exists in the DOM by the time the script block executes:

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

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

However, this is not guaranteed. To be sure that all elements exist, you should use the onload event handler on the <body> tag:

<body onload="doFinish();"> 

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

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

Such timing-related issues are also hardware-related -- slower systems can reveal bugs that faster systems hide. One concrete example is window.open, which opens a new window:

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

The problem with the code is that window.open is asynchronous -- it does not block the JavaScript execution until the window has finished loading. Therefore, you may execute the line after the window.open line before the new window has finished. You can deal with this by having an onload handler in the new window and then call back into the opener window (using window.opener).

Differences in JavaScript-generating HTML

JavaScript can, through document.write, generate HTML on the fly from a string. The main issue here is when JavaScript, embedded inside an HTML document (thus, inside an <script> tag), generates HTML that contains a <script> tag. If the document is in strict rendering mode, it will parse the </script> inside the string as the closing tag for the enclosing <script>. The following code illustrates this best:

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

Since the page is in strict mode, Mozilla's parser will see the first <script> and parse until it finds a closing tag for it, which would be the first </script>. This is because the parser has no knowledge about JavaScript (or any other language) when in strict mode. In quirks mode, the parser is aware of JavaScript when parsing (which slows it down). Internet Explorer is always in quirks mode, as it does not support true XHTML. To make this work in strict mode in Mozilla, separate the string into two parts:

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

Debug JavaScript

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

Figure 1. JavaScript console

Javascript Console

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

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

Figure 2. JavaScript console evaluating

JavaScript Console evaluating

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

Figure 3. Mozilla's JavaScript debugger

Mozilla's JavaScript debugger

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

CSS differences

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 (when CSS files are not applied)

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 and 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 and 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 differences

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 differences

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 versus standards mode

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 mode

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 mode

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

Figure 5. Image gap

Image Gap

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

Mozilla uses almost standards mode for the following conditions:

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

You can read more about the image gap issue.

Quirks mode

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 differences

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 (note that it means you can't define a global variable named event in your code):

<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 in 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. For keypress events (not keydown/keyup) of keys that produce output, the Mozilla equivalent is charCode, not keyCode.
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 editing

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 differences

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 differences

Mozilla has strong support for XML and XML-related technologies, such as XSLT and Web services. It also supports some non-standard 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 Node.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 property 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 
    };
  };

See Whitespace in the DOM for more detailed discussion and a possible solution.

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.

IE XML data island:

<xml id="xmldataisland"> 
  <foo>bar</foo> 
</xml>

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 object, which takes the serialized string and creates an XML document out of it. In Internet Explorer, you can achieve the same functionality using ActiveX. The object created using new ActiveXObject("Microsoft.XMLDOM") has a loadXML method that can take in a string and generate a document from it. The following code shows you how:

var xmlString = "<xml id=\"xmldataisland\"><foo>bar</foo></xml>"; 
var myDocument; 

if (window.DOMParser) {
  // This browser appears to support 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);
} else {
  // Not supported.
}

See Using XML Data Islands in Mozilla for an alternative approach.

XMLHttpRequest

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. Since version 7 IE also supports the "native" XMLHttpRequest object.

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 differences

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

Informations sur le document original

  • Auteur(s) : Doron Rosenberg, IBM Corporation
  • Publié le : 26 juillet 2005
  • Lien : http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/
{{ wiki.languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla", "ko": "ko/Migrate_apps_from_Internet_Explorer_to_Mozilla", "zh-tw": "zh_tw/\u8f49\u63db\u7db2\u9801\u7a0b\u5f0f\uff1a\u5f9e_IE_\u5230_Mozilla" } ) }}

Source de la révision

<p>{{template.Traduction_en_cours("Migrate apps from Internet Explorer to Mozilla")}}
</p>
<h3 name="Introduction">Introduction</h3>
<p>Lorsque Netscape a débuté le projet Mozilla, la décision de suivre les standards du W3C a été prise en toute conscience. C'est la raison pour laquelle Mozilla n'est pas entièrement compatible avec le code anciennement conçu pour Netscape Navigator 4.x et Microsoft Internet Explorer. Par exemple, Mozilla ne reconnaît pas <code>&lt;layer&gt;</code> comme nous le verrons plus tard. Les navigateurs, comme Internet Explorer 4, qui ont été conçus avant la publication des standards du W3C ont hérité de nombreuses bizarreries. Nous parlerons dans cet article du mode quirks de Mozilla, qui offre une bonne compatibilité HTML ascendante avec Internet Explorer et d'autres anciens navigateurs.
</p><p>Nous aborderons également de certaines technologies non standard, comme XMLHttpRequest et l'édition de texte enrichi, que Mozilla supporte parce qu'aucun équivalent W3C n'existait à l'époque. Parmi les standards supportés, on peut citer : 
</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> et <a class="external" href="http://www.w3.org/TR/xhtml11/">XHTML 1.1</a>
</li><li> Les feuilles de style en cascade (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> et certaines parties de <a class="external" href="http://www.w3.org/Style/CSS/current-work.html">CSS Level 3</a>
</li><li> Le 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> et certaines parties de <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/">les espaces de noms en XML</a>, <a class="external" href="http://www.w3.org/TR/xml-stylesheet/">l'association de feuilles de style avec des documents XML 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">les identificateurs de fragments 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, troisième édition (JavaScript 1.5) : <a class="external" href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMA-262</a>
</li></ul>
<h3 name="Astuces_g.C3.A9n.C3.A9rales_de_codage_multinavigateur"> Astuces générales de codage multinavigateur </h3>
<p>Même si les standards du Web existent, des navigateurs différents se comporteront différemment (en réalité, le même navigateur peut se comporter différemment suivant la plateforme). De nombreux navigateurs, comme Internet Explorer, gèrent également des API plus anciennes que celles du W3C et le support complet de celles-ci n'a jamais été ajouté.
</p><p>Avant de se plonger dans les différences entre Mozilla et Internet Explorer, voyons quelques manières de base de rendre une application Web extensible afin qu'elle puisse fonctionner dans de nouveaux navigateurs par la suite.
</p><p>Puisque des navigateurs différents utilisent parfois des API différentes pour la même fonctionnalité, on trouvera souvent une série de blocs <code>if() 
else()</code> tout au long du code pour différentier les différents navigateurs. Le code qui suit montre des blocs conçus pour for Internet Explorer :
</p>
<pre>. . . 

var elm; 

if (ns4) 
  elm = document.layers["monID"]; 
else if (ie4) 
  elm = document.all["monID"]
</pre>
<p>Ce code n'est pas extensible, par conséquent si l'on désire qu'il gère un nouveau navigateur, ces blocs doivent être mis à jour un peu partout dans l'application Web.
</p><p>La manière la plus simple d'éliminer le besoin de recoder pour un nouveau navigateur est de rendre la fonctionnalité abstraite. Plutôt que d'utiliser une série de blocs <code>if() 
else()</code>, il sera plus performant d'extraire certaines tâches courantes et de les placer dans leurs propres fonctions. Non seulement le code en sera plus lisible, mais l'ajout de nouveaux clients en sera simplifié :
</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>Ce code a toujours un problème, c'est qu'il utilise un « sniffing » du navigateur, c'est-à-dire qu'il détecte le navigateur utilisé par l'utilisateur. Le sniffing est généralement fait sur la chaîne d'agent utilisateur (useragent), comme celle-ci :
</p>
<pre>Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016 
</pre>  
<p>Bien que l'utilisation de la chaîne useragent pour détecter le navigateur fournisse un bon nombre d'informations détaillées sur le navigateur utilisé, le code de gestion de ces chaînes peut souvent faire des erreurs lorsque de nouvelles versions de ces navigateurs font leur apparition, ce qui oblige à modifier le code.
</p><p>Si le type de navigateur n'a pas d'importance (supposons que l'accès à l'application Web ait déjà été bloqué aux navigateurs non supportés), <strong>il est nettement plus sûr et efficace de vérifier le support de capacités ou d'objets particuliers du navigateur</strong>. Cela peut généralement être réalisé en testant la fonctionnalité requise en JavaScript. Par exemple, plutôt que :
</p>
<pre>if (isMozilla || isIE5) 
</pre> 
<p>On peut utiliser :
</p>
<pre>if (document.getElementById) 
</pre> 
<p>Cela permettra à d'autres navigateurs supportant cette méthode standard du W3C, comme Opera ou Safari, de fonctionner sans aucun changement.
</p><p>Le sniffing de la chaîne useragent reste cependant approprié lorsque la précision est importante, comme la vérification qu'un navigateur soit d'une version suffisante pour accéder à votre application Web ou si vous essayez de contourner un bug connu.
</p><p>JavaScript permet également d'utiliser des instructions conditionnelles en une ligne, qui peuvent rendre le code plus lisible :
</p>
<pre class="eval">var test = (condition) ? laConditionEstVraie : laConditionEstFausse; 
</pre>
<p>Par exemple, pour retrouver un élément, on peut utiliser :
</p>
<pre class="eval">function getElement(aID){ 
  return (document.getElementById) ? document.getElementById(aID)
                                   : document.all[aID]);
} 
</pre>
<p>Une autre manière est d'utiliser l'opérateur <tt>||</tt> :
</p>
<pre class="eval">function getElement(aID){ 
  return (document.getElementById(aID)) || document.all[aID]);
}
</pre>
<h3 name="Diff.C3.A9rences_entre_Mozilla_et_Internet_Explorer"> Différences entre Mozilla et Internet Explorer</h3>
<p>Pour commencer, nous parlerons des différences entre la manière dont HTML se comporte dans Mozilla et dans Internet Explorer.
</p>
<h4 name="Bulles_d.27information"> Bulles d'information </h4>
<p>Les premiers navigateurs ont introduit les bulles d'information en HTML en les montrant sur les liens et en utilisant la valeur de l'attribut <code>alt</code> d'une image comme contenu de cette bulle. Les spécifications HTML du W3C ont cependant créé l'attribut <code>title</code>, prévu pour contenir une description détaillée du lien. Les navigateurs modernes utiliseront cet attribut <code>title</code> pour afficher des bulles d'information, et Mozilla ne les affichera que pour cet attribut, jamais pour l'attribut <code>alt</code>.
</p>
<h4 name="Entit.C3.A9s"> Entités </h4>
<p>Le balisage HTML peut contenir plusieurs entités, qui ont été <a class="external" href="http://www.w3.org/TR/REC-html40/sgml/entities.html">définies par le W3C</a>. Celles-ci peuvent être référencées par leu valeur numérique ou par une chaîne de caractères. Par exemple, le caractère d'espacement #160 peut être référencé par <code>&amp;#160;</code>  ou par sa référence en caractères équivalente <code>&amp;nbsp;</code>.
</p><p>Certains navigateurs plus anciens, comme Internet Explorer, étaient permissifs jusqu'à laisser utiliser des entités sans le caractère <code>;</code> 
(point-virgule) à la fin et continuer le texte :
</p>
<pre>&amp;nbsp Foo 
&amp;nbsp&amp;nbsp Foo 
</pre>
<p>Mozilla affichera les <code>&amp;nbsp</code> ci-dessus comme des espaces, même si c'est à l'encontre des spécifications du W3C. Le navigateur ne traitera par contre pas un <code>&amp;nbsp</code> s'il est directement suivi d'autres caractères, par exemple :
</p>
<pre>&amp;nbsp12345 
</pre>
<p>Ce dernier code ne fonctionnera pas dans Mozilla, puisqu'il ne respecte absolument pas les standards du W3C. Utilisez toujours la forme correcte (<code>&amp;nbsp;</code>) pour éviter les différences de traitement entre les navigateurs.
</p>
<h3 name="Diff.C3.A9rences_dans_le_DOM"> Différences dans le DOM </h3>
<p>Le Document Object Model (DOM) est <b>la structure arborescente contenant les éléments du document</b>. Celle-ci peut être manipulée au travers d'API JavaScript qui ont été standardisées par le W3C. Cependant, avant cette standardisation, Netscape 4 et Internet Explorer 4 avaient déjà implémenté des API similaires. Mozilla n'implémente ces anciennes API que si elles ne sont pas réplicables avec les standards Web du W3C.
</p>
<h4 name="Acc.C3.A8s_aux_.C3.A9l.C3.A9ments"> Accès aux éléments </h4>
<p>Pour obtenir une référence à un élément en utilisant une approche multinavigateur, on utilise <code>document.getElementById(<i>aID</i>)</code> qui fonctionne dans Internet Explorer 5.0+, les navigateurs basés sur Mozilla, les autres navigateurs suivant le W3C et fait partie de la spécification DOM Level 1.
</p><p>Mozilla ne permet pas d'accéder à un élément via <code>document.elementName</code> ou même par le nom d'un élément, ce que fait Internet Explorer (et qu'on peut appeler <em>pollution de l'espace de noms global</em>). Mozilla ne permet pas non plus d'utiliser les méthodes <code>document.layers</code> de Netscape et <code>document.all</code> d'Internet Explorer. Alors que <code>document.getElementById</code> permet de trouver un seul élément, <code>document.layers</code> et <code>document.all</code> servaient également à obtenir une liste de tous les éléments portant un certain nom de balise, comme tous les éléments <code>&lt;div&gt;</code>.
</p><p>La méthode du DOM Level 1 du W3C obtient les références de tous les éléments portant le même nom de balise par <code>getElementsByTagName()</code>. Cette méthode renvoie un tableau en JavaScript, et peut également être appelée sur l'élément <code>document</code> ou sur d'autres nœuds pour chercher uniquement parmi leurs descendants dans l'arbre. Pour obtenir un tableau de tous les éléments dans l'arbre DOM, on peut utiliser <code>getElementsByTagName("*")</code>.
</p><p>Les méthodes du DOM Level 1, telles que montrées dans le Tableau 1, sont souvent utilisées pour déplacer un élément à un certain endroit et modifier sa visibilité (menus, animations). Netscape 4 utilisait la balise <code>&lt;layer&gt;</code>, qui n'est pas reconnue par Mozilla, comme élément HTML pouvant être positionné n'importe où. Dans Mozilla, n'importe quel élément utilisant la balise <code>&lt;div&gt;</code> peut être repositionné, ce qui est également utilisé par Internet Explorer et figure dans la spécification HTML.
</p>
<table class="standard-table">
<caption> Tableau 1. Méthodes utilisées pour accéder aux éléments
</caption><tbody><tr>
<th> Méthode </th><th> Description
</th></tr>
<tr>
<td> <code>document.getElementById(<i>unID</i>)</code> </td><td> Renvoie une référence à l'élément portant l'ID spécifié.
</td></tr>
<tr>
<td> <code>document.getElementsByTagName(<i>nomBalise</i>)</code> </td><td> Renvoie un tableau des éléments portant le nom spécifié dans le document.
</td></tr></tbody></table>
<h4 name="Parcours_du_DOM"> Parcours du DOM </h4>
<p>Mozilla supporte les API du DOM W3C pour le parcours de l'arbre DOM depuis JavaScript (voir le Tableau 2). Ces API existent pour chaque nœud dans le docment et permettent de parcourir l'arbre dans toutes les directions. Internet Explorer supporte également ces API, outre ses anciennes API de parcours de l'arbre DOM comme la propriété <code>children</code>.
</p>
<table class="standard-table">
<caption> Tableau 2. Méthodes utilisées pour parcourir le DOM
</caption><tbody><tr>
<th> Propriété/Méthode </th><th> Description
</th></tr>
<tr>
<td> <code>childNodes</code> </td><td> Renvoie un tableau de tous les nœuds enfants de l'élément.
</td></tr>
<tr>
<td> <code>firstChild</code> </td><td> Renvoie le premier nœud enfant de l'élément.
</td></tr>
<tr>
<td> <code>getAttribute(<i>nomAttribut</i>)</code> </td><td> Renvoie la valeur de l'attribut spécifié.
</td></tr>
<tr>
<td> <code>hasAttribute(<i>nomAttribut</i>)</code> </td><td> Renvoie une valeur booléenne précisant si le nœud courant a un attribut défini portant le nom spécifié.
</td></tr>
<tr>
<td> <code>hasChildNodes()</code> </td><td> Renvoie une valeur booléenne précisant si le nœud courant a des nœuds enfants.
</td></tr>
<tr>
<td> <code>lastChild</code> </td><td> Renvoie le dernier nœud enfant de l'élément.
</td></tr>
<tr>
<td> <code>nextSibling</code> </td><td> Renvoie le nœud suivant directement le nœud courant.
</td></tr>
<tr>
<td> <code>nodeName</code> </td><td> Renvoie le nom du nœud courant sous la forme d'une chaîne.
</td></tr>
<tr>
<td> <code>nodeType</code> </td><td> Renvoie le type du nœud courant.
<table>
<tbody><tr>
<th> Valeur </th><th> Description
</th></tr>
<tr>
<td> 1 </td><td> Nœud d'élément
</td></tr>
<tr>
<td> 2 </td><td> Nœud d'attribut
</td></tr>
<tr>
<td> 3 </td><td> Nœud texte
</td></tr>
<tr>
<td> 4 </td><td> Nœud de section CDATA
</td></tr>
<tr>
<td> 5 </td><td> Nœud de référence à une entité
</td></tr>
<tr>
<td> 6 </td><td> Nœud d'entité
</td></tr>
<tr>
<td> 7 </td><td> Nœud d'instruction de traitement
</td></tr>
<tr>
<td> 8 </td><td> Nœud de commentaire
</td></tr>
<tr>
<td> 9 </td><td> Nœud de document
</td></tr>
<tr>
<td> 10 </td><td> Nœud de type de document
</td></tr>
<tr>
<td> 11 </td><td> Nœud de fragment de document
</td></tr>
<tr>
<td> 12 </td><td> Nœud de notation
</td></tr></tbody></table>
</td></tr>
<tr>
<td> <code>nodeValue</code> </td><td> Renvoie la valeur du nœud courant. Pour les nœuds contenant du texte, comme les nœuds texte et de commentaires, il s'agira de ce texte. Pour les nœuds d'attributs, leur valeur d'attribut. Pour tous les autres nœuds, <code>null</code> sera renvoyé.
</td></tr>
<tr>
<td> <code>ownerDocument</code> </td><td> Renvoie l'objet <code>document</code> contenant le nœud courant.
</td></tr>
<tr>
<td> <code>parentNode</code> </td><td> Renvoie le nœud parent du nœud courant.
</td></tr>
<tr>
<td> <code>previousSibling</code> </td><td> Renvoie le nœud qui précède immédiatement le nœud courant.
</td></tr>
<tr>
<td> <code>removeAttribute(<i>nom</i>)</code> </td><td> Retire l'attribut spécifié du nœud courant.
</td></tr>
<tr>
<td> <code>setAttribute(<i>nom</i>, <i>valeur</i>)</code> </td><td> Définit la valeur de l'attribut spécifié avec sur le nœud courant.
</td></tr></tbody></table>
<p>Internet Explorer a un comportement s'éloignant du standard, dans le sens où beaucoup de ces API ignoreront les nœuds comportant uniquement des espaces blancs, générés par exemple par les caractères de retour à la ligne. Mozilla ne les ignorera pas, il sera donc parfois nécessaire de les distinguer. Chaque nœud a une propriété <code>nodeType</code> indiquant le type de nœud. Par exemple, un élément aura le type 1, un nœud texte le type 3 et un nœud de commentaire le type 8. La meilleure manière de ne traiter que les nœuds d'éléments et de ne pas parcourir tous les nœuds enfants et de ne traiter que ceux dont l'attribut <code>nodeType</code> vaut 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){ 
      // nœud élément
    };
  };
</pre>
<h4 name="G.C3.A9n.C3.A9ration_et_manipulation_de_contenu"> Génération et manipulation de contenu </h4>
<p>Mozilla supporte les anciennes méthodes d'ajout dynamique de contenu dans le DOM, comme <code>document.write</code>, <code>document.open</code> et <code>document.close</code>. Mozilla gère également la méthode <code>innerHTML</code> d'Internet Explorer, qui peut être appelée sur presque tous les nœuds. Il ne supporte cependant pas <code>outerHTML</code> (qui ajoute des balises autour d'un élément, et n'a pas d'équivalent standard) ni <code>innerText</code> (qui change la valeur textuelle du nœud, et qui peut être remplacée dans Mozilla par l'utilisation de <code>textContent</code>). 
</p><p>Internet Explorer dispose de plusieurs méthodes de manipulation du contenu qui ne sont pas standard et ne sont pas gérées par Mozilla, permettant de récupérer la valeur, d'insérer du texte et des éléments à côté d'un nœud, comme <code>getAdjacentElement</code> et <code>insertAdjacentHTML</code>. Le Tableau 3 montre comment manipuler le contenu avec le standard W3C et Mozilla, avec des méthodes disponibles sur tous les nœuds DOM.
</p>
<table class="standard-table">
<caption> Table 3. Méthodes standards utilisées par Mozilla pour manipuler le contenu
</caption><tbody><tr>
<th> Méthode </th><th> Description
</th></tr>
<tr>
<td> <code>appendChild(<i>nœud</i>)</code> </td><td> Crée un nouveau nœud enfant. Renvoie une référence à ce nouveau nœud.
</td></tr>
<tr>
<td> <code>cloneNode(<i>profond</i>)</code> </td><td> Crée une copie du nœud depuis lequel la méthode est appelée, et renvoie cette copie. Si le paramètre <code>profond</code> vaut <code>true</code>, copie également tous les descendants du nœud.
</td></tr>
<tr>
<td> <code>createElement(<i>nomDeBalise</i>)</code> </td><td> Crée et renvoie un nouveau nœud DOM orphelin (sans parent), du type d'élément spécifié par le paramètre <code>nomDeBalise</code>.
</td></tr>
<tr>
<td> <code>createTextNode(<i>valeurTexte</i>)</code> </td><td> Crée et renvoie un nouveau nœud DOM orphelin de type texte avec la valeur spécifiée dans <code>valeurTexte</code>.
</td></tr>
<tr>
<td> <code>insertBefore(<i>nouveauNœud</i>, <i>nœudEnfant</i>)</code> </td><td> Insère le nœud <code>nouveauNœud</code> avant le nœud <code>nœudEnfant</code>, qui doit être un enfant du nœud courant.
</td></tr>
<tr>
<td> <code>removeChild(<i>nœudEnfant</i>)</code> </td><td> Retire le nœud <code>nœudEnfant</code> des enfants du nœud courant, et renvoie une référence vers ce nœud.
</td></tr>
<tr>
<td> <code>replaceChild(<i>nouveauNœud</i>, <i>nœudEnfant</i>)</code> </td><td> Remplace le nœud <code>nœudEnfant</code> par <code>nouveauNœud</code> dans les nœuds enfants de l'élément courant et renvoie une référence vers le nœud retiré.
</td></tr></tbody></table>
<h4 name="Fragments_de_document"> Fragments de document </h4>
<p>Pour des questions de performances, il est possible de créer des documents en mémoire plutôt que de travailler avec le DOM du document existant. Le DOM Level 1 Core propose pour cela les fragments de document, qui sont des documents légers contenant un sous-ensemble des interfaces d'un document normal. Par exemple, <code>getElementById</code> n'y existe pas, mais <code>appendChild</code> bien. Il est aisé d'ajouter des fragments de document à un document existant.
</p><p>Mozilla permet de créer des fragments de document à l'aide de <code>document.createDocumentFragment()</code>, qui renvoie un fragment de document vide.
</p><p>L'implémentation des fragments de document dans Internet Explorer, par contre, ne respecte pas les standards du W3C et renvoie simplement un document normal.
</p>
<h3 name="JavaScript_differences">JavaScript differences</h3>
<p>Most differences between Mozilla and Internet Explorer are usually 
blamed on JavaScript. However, the issues usually lie in the APIs that a 
browser exposes to JavaScript, such as the DOM hooks. The two browsers 
possess few core JavaScript differences; issues encountered are often 
timing related.
</p>
<h4 name="JavaScript_date_differences">JavaScript date differences</h4>
<p>The only <code>Date</code> difference is the <code>getYear</code> method. As per the ECMAScript specification (which is the specification JavaScript follows), the method is not Y2k-compliant, and running <code>new Date().getYear()</code> in 2004 will return "104". Per the ECMAScript specification, <code>getYear</code> returns the year minus 1900, originally meant 
to return "98" for 1998. <code>getYear</code> was deprecated in ECMAScript Version 3 and replaced with <code>getFullYear()</code>. Internet Explorer changed <code>getYear()</code> to work like <code>getFullYear()</code> and make it Y2k-compliant, while Mozilla kept the standard behavior.
</p>
<h4 name="JavaScript_execution_differences">JavaScript execution differences</h4>
<p>Different browsers execute JavaScript differently. For example, the 
following code assumes that the <code>div</code> node 
already exists in the DOM by the time the <code>script</code> block executes: 
</p>
<pre>...
&lt;div id="foo"&gt;Loading...&lt;/div&gt;

&lt;script&gt; 
  document.getElementById("foo").innerHTML = "Done."; 
&lt;/script&gt; 
</pre>
<p>However, this is not guaranteed. To be sure that all elements exist, 
you should use the <code>onload</code> event handler on the <code>&lt;body&gt;</code> tag:
</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>Such timing-related issues are also hardware-related -- slower systems 
can reveal bugs that faster systems hide. One concrete example is <code>window.open</code>, which opens a new window:
</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>The problem with the code is that <code>window.open</code> is asynchronous -- it does not block the JavaScript execution until the window has finished loading. Therefore, you may execute the line after the <code>window.open</code> line 
before the new window has finished. You can deal with this by having an 
<code>onload</code> handler in the new window and then call 
back into the opener window (using <code>window.opener</code>).
</p>
<h4 name="Differences_in_JavaScript-generating_HTML">Differences in JavaScript-generating HTML</h4>
<p>JavaScript can, through <code>document.write</code>, generate 
HTML on the fly from a string. The main issue here is when JavaScript, 
embedded inside an HTML document (thus, inside an <code>&lt;script&gt;</code> tag), generates HTML that contains a 
<code>&lt;script&gt;</code> tag. If the document is in strict rendering mode, it will parse the <code>&lt;/script&gt;</code> inside the string as the closing tag 
for the enclosing <code>&lt;script&gt;</code>. The following 
code illustrates this best:
</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>Since the page is in strict mode, Mozilla's parser will see the first <code>&lt;script&gt;</code> and parse until it finds a closing tag for it, which would be the first <code>&lt;/script&gt;</code>. This is because the parser has no knowledge about JavaScript (or any other language) when in strict mode. In quirks mode, the parser is aware of JavaScript when parsing (which slows it down). Internet Explorer is always in quirks mode, as it does not support true XHTML. To make this work in strict mode in Mozilla, separate the string into two parts: 
</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="Debug_JavaScript">Debug JavaScript</h4>
<p>Mozilla provides several ways to debug JavaScript-related issues found 
in applications created for Internet Explorer. The first tool is the 
built-in JavaScript console, shown in Figure 1, where errors and warnings 
are logged. You can access it in Mozilla by going to <b>Tools -&gt; Web Development -&gt; JavaScript Console</b> or in Firefox (the standalone browser product from Mozilla) at <b>Tools -&gt; JavaScript Console</b>. 
</p><p>Figure 1. JavaScript console
</p><p><img alt="Javascript Console" src="File:fr/Media_Gallery/Migrationguide-jsconsole.jpg">
</p><p>The JavaScript console can show the full log list or just 
errors, warnings, and messages. The error message in Figure 1 says that at 
aol.com, line 95 tries to access an undefined variable called is_ns70. 
Clicking on the link will open Mozilla's internal view source window with 
the offending line highlighted.
</p><p>The console also allows you to evaluate JavaScript. To evaluate the entered JavaScript syntax, type in <code>1+1</code> into the input field and press <b>Evaluate</b>, as Figure 2 shows.
</p><p>Figure 2. JavaScript console evaluating
</p><p><img alt="JavaScript Console evaluating" src="File:fr/Media_Gallery/Migrationguide-jsconsole-eval.jpg">
</p><p>Mozilla's JavaScript engine has built-in support for debugging, and 
thus can provide powerful tools for JavaScript developers. Venkman, shown 
in Figure 3, is a powerful, cross-platform JavaScript debugger that 
integrates with Mozilla. It is usually bundled with Mozilla releases; you 
can find it at <b>Tools -&gt; Web Development -&gt; JavaScript 
Debugger</b>. For Firefox, the debugger isn't bundled; instead, you can 
download and install it from the <a class="external" href="http://www.mozilla.org/projects/venkman/">Venkman Project Page</a>. You can also find 
tutorials at the development page, located at the <a class="external" href="http://www.hacksrus.com/%7Eginda/venkman/">Venkman Development Page</a>.
</p><p>Figure 3. Mozilla's JavaScript debugger
</p><p><img alt="Mozilla's JavaScript debugger" src="File:fr/Media_Gallery/Migrationguide-venkman.jpg">
</p><p>The JavaScript debugger can debug JavaScript running in the Mozilla 
browser window. It supports such standard debugging features as breakpoint 
management, call stack inspection, and variable/object inspection. All 
features are accessible through the user interface or through the debugger's 
interactive console. With the console, you can execute arbitrary 
JavaScript in the same scope as the JavaScript currently being debugged.
</p>
<h3 name="CSS_differences">CSS differences</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_.28when_CSS_files_are_not_applied.29">Mimetypes (when CSS files are not applied)</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_and_units">CSS and 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_and_CSS">JavaScript and 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_differences">CSS overflow differences</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:fr/Media_Gallery/Migrationguide-overflow.jpg">
</p>
<h4 name="hover_differences">hover differences</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_versus_standards_mode">Quirks versus standards mode</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_mode">Standards mode</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_mode">Almost standards mode</h4>
<p>Mozilla introduced almost standards mode for one reason: a section in 
the CSS 2 specification breaks designs based on a precise layout of small 
images in table cells. Instead of forming one image to the user, each 
small image ends up with a gap next to it. The old IBM homepage shown in 
Figure 5 offers an example. 
</p><p>Figure 5. Image gap
</p><p><img alt="Image Gap" src="File:fr/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>You can read more about the <a href="fr/Images%2c_Tables%2c_and_Mysterious_Gaps">image gap issue</a>.
</p>
<h4 name="Quirks_mode">Quirks mode</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="fr/Mozilla_Quirks_Mode_Behavior">Mozilla Quirks Mode Behavior</a> and <a href="fr/Mozilla's_DOCTYPE_sniffing">Mozilla's DOCTYPE sniffing</a>.
</p>
<h3 name="Event_differences">Event differences</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.
</p><p>A cross-browser event handling example follows (note that it means you can't define a global variable named <code>event</code> in your code):
</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 in 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. For keypress events (not keydown/keyup) of keys that produce output, the Mozilla equivalent is charCode, not keyCode.
</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_editing">Rich text editing</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="fr/Midas">rich text editing</a>, if no W3C equivalent exists.
</p><p>Mozilla 1.3 introduced an implementation of Internet Explorer's 
<a href="fr/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_differences">Rich text differences</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="fr/Rich-Text_Editing_in_Mozilla">Rich-Text Editing in Mozilla</a>.
</p>
<h3 name="XML_differences">XML differences</h3>
<p>Mozilla has strong support for XML and XML-related technologies, such as <a href="fr/XSLT">XSLT</a> and Web services. It also supports some non-standard Internet Explorer extensions, such as <code><a href="fr/XMLHttpRequest">XMLHttpRequest</a></code>.
</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><a href="fr/DOM/element.childNodes">Node.childNodes</a></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><a href="fr/DOM/document.documentElement">documentElement</a></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><a href="fr/DOM/element.nodeType">nodeType</a></code> property 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>
<p>See <a href="fr/Whitespace_in_the_DOM">Whitespace in the DOM</a> for more detailed discussion and a possible solution.
</p>
<h4 name="XML_data_islands"> XML data islands </h4>
<p>Internet Explorer has a nonstandard feature called <a class="external" href="http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/xml.asp">XML data islands</a>, 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>IE XML data island: 
</p>
<pre class="eval">&lt;xml id="xmldataisland"&gt; 
  &lt;foo&gt;bar&lt;/foo&gt; 
&lt;/xml&gt;
</pre>
<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><a href="fr/DOMParser">DOMParser</a></code> object, which takes the serialized string and creates an XML document out of it. In Internet Explorer, you can achieve the same functionality using ActiveX. The object created using <code>new ActiveXObject("Microsoft.XMLDOM")</code> 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 class="eval">var xmlString = "&lt;xml id=\"xmldataisland\"&gt;&lt;foo&gt;bar&lt;/foo&gt;&lt;/xml&gt;"; 
var myDocument; 

if (window.DOMParser) {
  // This browser appears to support 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);
} else {
  // Not supported.
}
</pre>
<p>See <a href="fr/Using_XML_Data_Islands_in_Mozilla">Using XML Data Islands in Mozilla</a> for an alternative approach.
</p>
<h4 name="XMLHttpRequest"> XMLHttpRequest </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><a href="fr/XMLHttpRequest">XMLHttpRequest</a></code> object. Since version 7 IE also supports the "native" <code>XMLHttpRequest</code> object.
</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><a href="fr/XMLHttpRequest">XMLHttpRequest</a></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_differences">XSLT differences</h4>
<p>Mozilla supports XSL Transformations (<a href="fr/XSLT">XSLT</a>) 1.0. It also allows JavaScript to perform XSLT transformations and allows running <a href="fr/XPath">XPath</a> on a document. 
</p><p>Mozilla requires that you send the XML and XSLT files 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><a href="fr/XSLTProcessor">XSLTProcessor</a></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.
</p><p><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="Informations_sur_le_document_original"> Informations sur le document original </h3>
<ul><li> Auteur(s) : Doron Rosenberg, IBM Corporation
</li><li> Publié le : 26 juillet 2005
</li><li> Lien : http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/
</li></ul>
</div>
{{ wiki.languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla", "ko": "ko/Migrate_apps_from_Internet_Explorer_to_Mozilla", "zh-tw": "zh_tw/\u8f49\u63db\u7db2\u9801\u7a0b\u5f0f\uff1a\u5f9e_IE_\u5230_Mozilla" } ) }}
Revenir à cette révision