mozilla

Revision 136869 of Migrar aplicaciones desde Internet Explorer a Mozilla

  • Enlace amigable (slug) de la revisión: Migrar_aplicaciones_desde_Internet_Explorer_a_Mozilla
  • Título de la revisión: Migrar aplicaciones desde Internet Explorer a Mozilla
  • Id de la revisión: 136869
  • Creada:
  • Creador: Mgjbot
  • ¿Es la revisión actual? No
  • Comentario robot Añadido: [[zh-cn:从Internet Explorer迁移到Mozilla]] <<langbot>>

Contenido de la revisión

Introducción

Cuando Netscape comenzó con el navegador Mozilla, lo hizo con la decisión consciente de soportar los estándares del W3C. Como resultado, Mozilla no es totalmente compatible hacia atrás con el código heredado de Netscape Navigator 4.x ni de Microsoft Internet Explorer. Por ejemplo, Mozilla no soporta la etiqueta <layer> como se verá más adelante. Los navegadores como Internet Explorer 4 fueron construidos antes de la concepción de los estándares del W3C heredando muchos de sus extraños comportamientos. En este articulo se describirán las idiosincrasias de Mozilla que hacen que haya una fuerte compatibilidad del HTML hacia atrás con Internet Explorer y otros navegadores antiguos.

También se repasarán las tecnologías no estandarizadas soportadas por Mozilla, como el XMLHttpRequest y la edición de texto enriquecido, dado que existen sus equivalentes existentes en el W3C y que se incluyen en:

Trucos generales para la programación multinavegador

Pese a la existencia de los estándares web, los diferentes navegadores se comportan de manera distinta (de hecho, el mismo navegador puede comportarse de modo diferente dependiendo de la plataforma). Muchos navegadores, como Internet Explorer, también soportan el APIs anterior al W3C y nunca se han esforzado en añadir soporte para los navegadores compatibles con el W3C.

Antes de enumerar las diferencias entre Mozilla e Internet Explorer, sería conveniente cubrir algunas formas básicas en las que se pueden crear aplicaciones web ampliables a las que añadir soporte para nuevos navegadores más tarde.

Dado que los diferentes navegadores utilizan a veces diferentes APIs para una misma funcionalidad, es muy posible que encuentres múltiples bloques if() else() a lo largo y ancho del código para diferenciar el navegador que está ejecutando el documento. El siguiente código muestra un bloque diseñado para Internet Explorer:

. . . 

var elm; 

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

El anterior código no es ampliable por lo que si quieres soportar un nuevo navegador, deberás actualizar ese bloque de código en toda la aplicación web.

La forma más fácil de evitar la recodificación del documento para un nuevo navegador es abstraer la funcionalidad. En lugar de utilizar múltiples bloques if() else(), puedes incrementar la eficiencia tomando tareas comunes y abstrayéndolas en sus propias funciones. Esto no sólo hace al código más legible sino que simplifica el proceso añadir soporte para nuevos clientes.

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

El código de arriba sigue arrastrando el problema del browser sniffing o el proceso de detección para saber qué navegador está utilizando el usuario. El browser sniffing es detectado generalmente gracias al parámetro useragent, como:

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

Mientras que la utilización del parámetro useragent para detectar el navegador proporciona información detallada del navegador en uso, el código que maneja esos parámetros genera errores con frecuencia cuando son publicadas nuevas versiones de los mismos, por lo que hay que cambiar el código.

Si el tipo de navegador no importa (supongamos que se ha bloquado el acceso a la aplicación web a navegadores no soportados), será mucho mejor y más fiable detectar las capacidades del navegador o el soporte de objetos en particular. Generalmente se puede hacer esto probando la funcionalidad requerida en JavaScript, por ejemplo, en lugar de:

if (isMozilla || isIE5) 

Se debería de usar:

if (document.getElementById) 

Esto permitiría a otros navegadores que soportan ese método estandar del W3C (tales como Opera o Safari) funcionar sin ningún cambio.

La detección del agente de usuario sin embargo tiene sentido cuando es importante acertar, como cuando estás verificando que un navegador coincide con los requerimientos de versión de la aplicación web o estás intentando sortear un fallo de programación.

JavaScript también permite sentencias condicionales en línea, lo que ayuda a la legibilidad:

var foo = (condicion) ? condicionEsTrue : condicionEsFalse; 

Por ejemplo, para obtener un elemento se debería usar:

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

Diferencias entre Mozilla e Internet Explorer

Primero se discutirán las diferencias en la forma en la que se comporta el HTML en Mozilla y en Internet Explorer.

Títulos emergentes

Los títulos emergentes son pequeños textos descriptivos que aparecen normalmente cuando se deja el cursor del ratón un cierto tiempo sobre un elemento.

Los navegadores antiguos introdujeron los títulos emergentes en el HTML mostrándolos en enlaces y usando el valor del atributo alt como contenido del título. La última especificación de W3C para HTML creó el atributo title, pensado para contener una descripción detallada del enlace. Los navegadores modernos utilizan el atributo title para mostrar títulos emergentes y Mozilla sólo muestra dichos títulos basándose en el ese atributo y no en el atributo alt.

Entidades

El marcado HTML puede contener varias entidades definidas por el departamento de estándares web del W3C. Se pueden referenciar entidades a través de su referencia numérica o alfabética. Por ejemplo, puedes referenciar el carácter de espacio en blanco #160 con &#160 o con su referencia alfabética correspondiente &nbsp;.

Algunos navegadores antiguos, como Internet Explorer, son tan fulleros que permiten usar entidades reemplazando el carácter ; (punto y coma) al final con contenido normal de texto.

&nbsp Foo 
&nbsp&nbsp Foo 

Mozilla visualizará el &nbsp mostrado anteriormente como espacios en blanco, pese a que va en contra de la especificación del W3C. El navegador no analizará un &nbsp si va inmediatamente seguido por más caracteres. Por ejemplo:

&nbsp12345 

Este código no funcionará en Mozilla, dado que va en contra de los estándares del W3C. Es mejor usar la forma correcta (&nbsp;) para evitar discrepancias entre navegadores.

Diferencias en el DOM

El Modelo de Objetos de Documento (DOM) es la estructura en árbol que contiene los elementos del documento. Se puede manipular a través de las APIs de JavaScript, las cuales han sido estandarizadas por el W3C. Sin embargo, antes de la estandarización del W3C, Netscape 4 e Internet Explorer 4 implementaron las APIs de modo similar. Mozilla implementa las APIs heredadas sólo si han sido aceptadas por los estándares del W3C.

Accediendo a los elementos

Para referenciar un elemento usando una técnicas multinavegador, debe de usarse document.getElementById(id), que funciona tanto en Internet Explorer versión 5.0 y superiores, en navegadores basados en Mozilla y en otros navegadores compatibles con el W3C y es parte de la especificación DOM nivel 1.

Mozilla no soporta el acceso a elementos a través de document.elementName, ni siquiera a través del nombre del elemento; algo que Internet Explorer permite (llamado también global namespace polluting). Mozilla tampoco soporta el método document.layers de Netscape ni el document.all de Internet Explorer. Mientras que document.getElementById permite referenciar un único elemento, puedes usar document.layers y document.all para obtener una lista de todos los elementos del documento con un nombre determinado, como todos los elementos <div>.

El método del DOM nivel 1 del W3C que permite referenciar a todos los elementos con el mismo nombre de etiqueta es getElementsByTagName(). Este método devuelve un vector en JavaScript y puede ser invocado desde el elemento document o desde otros nodos para buscar sólo en su sub-árbol. Para obtener un vector con todos los elementos del árbol del DOM, se puede utilizar getElementsByTagName("*").

Los métodos del DOM nivel 1, como muestra la tabla 1, son usados comúnmente para mover un elemento a una posición en particular y cambiar su visibilidad (menús, animaciones, etc...). Netscape 4 usaba la etiqueta <layer>(algo que Mozilla no soporta) como un elemento que podía posicionarse en cualquier lugar. En Mozilla se puede posicionar cualquier elemento utilizando la etiqueta <div>, algo que Internet Explorer también utiliza y que está presente en la especificación HTML.

Tabla 1. Métodos usados para acceder a elementos
Método Descripción
document.getElementById( unId ) Devuelve una referencia al elemento cuyo atributo id coincide con el pasado como parámetro.
document.getElementsByTagName( unNombre ) Devuelve un vector de elementos cuyo nombre de etiqueta coincide con el pasado como parámetro.

Recorrer el DOM

Mozilla soporta las APIs del DOM del W3C que permiten recorrer el árbol del DOM a través de JavaScript (véase la tabla 2). Las APIs están disponibles para cada nodo del documento y permiten recorrer el árbol en cualquier dirección. Internet Explorer también soporta estas APIs y además sus APIs heredadas para recorrer el árbol del DOM, tales como la propiedad children.

Tabla 2. Métodos usados para recorrer el DOM
Propiedad/Método Descripción
childNodes Devuelve un vector con todos los nodos hijos del elemento.
firstChild Devuelve el primer nodo hijo del elemento.
getAttribute( nombre ) Devuelve el valor del atributo cuyo nombre se pasa como parámetro.
hasAttribute( nombre ) Devuelve un valor booleano que indica si el nodo actual tiene un atributo definido con el nombre especificado.
hasChildNodes() Devuelve un valor booleano que indica si el nodo actual tiene al menos un elemento hijo.
lastChild Devuelve el último nodo hijo del elemento.
nextSibling Devuelve el nodo que sigue inmediatamente al actual.
nodeName Devuelve el nombre del nodo actual como una cadena de texto.
nodeType Devuelve un valor numérico que indica el tipo del nodo actual.
Valor Descripción
1 Nodo elemento
2 Nodo atributo
3 Nodo de texto
4 Nodo de sección CDATA
5 Nodo de referencia a entidad
6 Nodo entidad
7 Nodo de instrucción de proceso
8 Nodo comentario
9 Nodo documento
10 Nodo tipo de documento
11 Nodo fragmento de documento
12 Nodo anotación
nodeValue Devuelve el valor del nodo actual. Para aquellos nodos que contentan texto, tales como los nodos de texto o los nodos comentario, se devolverá su valor alfabético. Para nodos atributo, se devolverá el valor de su atributo. Para el resto de nodos, se devolverá null.
ownerDocument Devuelve el objeto document que contiene al nodo actual.
parentNode Devuelve el nodo padre del nodo actual.
previousSibling Devuelve el nodo inmediatamente anterior al nodo actual.
removeAttribute( nombre) Elimina el atributo especificado del nodo actual.
setAttribute( nombre, valor ) Establece el valor de un atributo.

Internet Explorer se comporta de un modo no estándar donde muchas de estas APIs ignorarán los nodos de texto en blanco que son generados, por ejemplo, mediante caracteres de nueva línea. Mozilla no las ignora por lo que a veces se necesita distinguir a estos nodos. Cada nodo posee la propiedad nodeType que especifica el tipo de nodo. Por ejemplo, un nodo elemento es de tipo 1 mientras que un nodo de texto es de tipo 3, un nodo comentario es de tipo 8, etc... La mejor forma de procesar sólo los nodos elemento es iterar todos los nodos hijos y procesar sólo aquellos cuya propiedad nodeType sea igual a 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){ 
      // Nodo elemento
    };
  };

Generar y manejar contenidos

Mozilla soporta los métodos heredados para añadir contenido al DOM dinámicamente, tales como document.write, document.open y document.close. Mozilla también soporta el método de Internet Explorer innerHTML el cual puede ser llamado desde casi cualquier nodo. Sin embargo no soporta el método outerHTML (que añade marcado alrededor de un elemento y no tiene un equivalente estándar) ni innerText (el cual establece el valor alfabético de su nodo y que puede usarse en Mozilla usando textContent).

Internet Explorer tiene varios métodos de manejo de contenidos que no son estándares y no son soportados en Mozilla, incluyendo obtener valores, insertar texto e insertar elementos adyacentes a un nodo tales como getAdjacentElement y insertAdjacentHTML. La tabla 3 muestra cómo el manipulan contenidos tanto Mozilla como el estándar del W3C, siendo todos ellos métodos aplicables a cualquier nodo del DOM.

Tabla 3. Métodos usados por Mozilla para manipular contenidos
Método Descripción
appendChild( nodo ) Crea un nuevo nodo hijo. Devuelve una referencia al nuevo nodo hijo.
cloneNode( profundidad ) Crea y devuelve una copia del nodo sobre el que se hace la llamada. Si profundidad es true, copia el sub-árbol completo del nodo.
createElement( tipo ) Crea y devuelve un nuevo nodo huérfano de tipo igual al especificado por tipo.
createTextNode( valor ) Crea y devuelve un nuevo nodo de texto huérfano asignándole el valor especificado por valor.
insertBefore( nuevoNodo, nodoHijo ) Inserta el nodo nuevoNodo antes de nodoHijo, el cual debe ser un hijo del nodo actual.
removeChild( nodoHijo ) Elimina el nodo nodoHijo y devuelve una referencia a él.
replaceChild( nuevoNodo, nodoHijo ) Reemplaza el nodo nodoHijo con el nodo nuevoNodo y devuelve una referencia al nodo eliminado.

Fragmentos de documento

Por razones de eficiencia, pueden crearse documentos en memoria en lugar de trabajar con el DOM de un documento existente. El núcleo del DOM nivel 1 introdujo los fragmentos de documento, que son documentos ligeros que contienen un subconjunto de las interfaces de un documento normal. Por ejemplo, getElementById no existe pero appendChild sí. Además se pueden anexar fácilmente fragmentos de documento a los ya existentes.

Mozilla crea fragmentos de documento a través de document.createDocumentFragment(), el cual devuelve un fragmento de documento vacío.

Sin embargo, la implementación de Internet Explorer para los fragmentos de documentos no es compatible con el estándar del W3C y simplemente devuelve un documento normal.

Diferencias en JavaScript

Buscar traducción adecuada para hooks DOM. "timing related" traducido como "duración de la ejecución"

Por lo general, la mayoría de las diferencias entre Mozilla e Internet Explorer son las de JavaScript. Sin embargo, los problemas normalmente residen en las APIs que un navegador muestra a JavaScript, tales como hooks de DOM. A nivel del núcleo, los dos navegadores no poseen grandes diferencias. Los problemas se encuentran frecuentemente en la duración de la ejecución.

Diferencias en las fechas de JavaScript

La única diferencia en el objeto Date es el método getYear. Para la especificación ECMAScript (que es la que sigue JavaScript), el método no es compatible con el efecto 2000 y al ejecutar new Date().getYear() en 2004 se obtendrá un valor igual a "104". Para la especificación ECMAScript, getYear devuelve el año menos 1900 lo cual devolvía "98" para 1998. getYear quedó obsoleto en la versión 3 de ECMAScript y fue reemplazado por getFullYear. Internet Explorer cambió la implementación de getYear para que funcionara como getFullYear y fuese así compatible con el efecto 2000, mientras que Mozilla mantuvo el comportamiento estándar.

Diferencias de ejecución en JavaScript

Diferentes navegadores ejecutarán JavaScript de modo distinto. Por ejemplo, el siguiento código asume que el nodo div ya existe en el DOM en el momento en el que el bloque script se ejecuta:

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

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

Sin embargo esto no está garantizado. Para asegurarnos de que todos los elementos existen se debería usar el manejador de evento onload en la etiqueta <body>:

<body onload="doFinish();"> 

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

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

Tales problemas relativos a la duración de la ejecución están también relacionados con el hardware; los sistemas más lentos pueden mostar fallos que los más rápidos no provocan. Un ejemplo en concreto se puede encontrar en window.open, el cual abre una nueva ventana:

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

El problema con el código es que window.open es asíncrono lo que implica que no se bloquee la ejecución de JavaScript hasta que la ventana haya terminado de cargarse. Por tanto, se puede ejecutar la línea siguiente a la línea window.open antes de que la nueva ventana haya terminado de cargarse. Se puede lidiar con esto poniendo un manejador onload en la nueva ventana y luego llamar desde ahí a la ventana padre (usando window.opener).

Diferencias en la generación HTML de JavaScript

JavaScript puede generar, a través de document.write, código HTML al vuelo a partir de una cadena de texto. El principal problema es cuando JavaScript está embebido dentro del documento HTML (es decir, dentro de la etiqueta <script>) y genera HTML que contiene una etiqueta <script>. Si el documento está en modo estricto de visualización, entonces se analizará la etiqueta </script> que se halla dentro de la cadena como la etiqueta de cierre de la etiqueta <script> que la contiene. El siguiente código ilustra mejor esto:

<!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('Hola');<\/script>") 
</script> 

Dado que la página está en modo estricto, el analizador de Mozilla verá el primer <script> y lo analizará hasta que encuentre la etiqueta de cierre correspondiente, que será cuando encuentre el primer </script>. Se hace así porque el analizador no tiene conocimiento de la existencia de JavaScript (o cualquier otro lenguaje) cuando está en modo estricto. En modo quirks, el analizador conoce de la existencia de JavaScript cuando trabaja (algo que lo ralentiza). Internet Explorer siempre funciona en modo quirks porque no soporta el auténtico XHTML. Para hacer que esto funcione en modo estricto en Mozilla se puede separar la cadena en dos partes:

<!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('Hola');</" + "script>") 
</script> 

Depurando JavaScript

Mozilla proporciona varias formas de depurar los fallos relacionados con JavaScript encontrados en las aplicaciones creadas para Internet Explorer. La primera herramienta es la consola integrada de JavaScript, mostrada en la figura 1, donde los errores y los avisos quedan registrados. Puedes acceder a ella en Mozilla yendo al menú Herramientas -> Desarrollo web -> Consola JavaScript, en Firefox 2.0 (el navegador ligero de Mozilla) en Herramientas -> Consola de errores.

Figura 1. Consola JavaScript

Javascript Console

La consola JavaScript puede mostrar el registro completo o sólo los errores, avisos o mensajes. El mensaje de error de la figura 1 dice que en aol.com, la línea 95 ha intentado acceder a una variable no definida llamada is_ns70. Al hacer clic en el enlace se abrira el visualizador de código interno de Mozilla con la línea en cuestión resaltada.

La consola además permite evaluar JavaScript. Para probar la sintaxis de JavaScript introducida, se puede escribir 1+1 en el campo de entrada y pulsar Evaluar, como muestra la figura 2.

Figure 2. Evaluación en la consola de JavaScript

JavaScript Console evaluating

El motor de JavaScript en Mozilla tiene integrado el soporte para la depuración convirtiéndose así en una potente herramienta para los desarrolladores de JavaScript. Venkman, mostrado en la figura 3, es un potente depurador multinavegador para JavaScript que se integra con Mozilla. Generalmente es empaquetado con los lanzamientos de Mozilla y puede ser encontrado en Herramientas -> Desarrollo web -> Depurador Javascript. En Firefox, el navegador no viene incluido. En lugar de eso, se puede descargar e instalar desde la página del proyecto Venkman. Además se pueden encontrar tutoriales en la página de desarrollo, ubicada en la página de desarrollo de Venkman.

Figura 3. Depurador de JavaScript de Mozilla

Mozilla's JavaScript debugger

El depurador de JavaScript puede depurar el código JavaScript que se ejecuta en la ventana del navegador de Mozilla. Soporta características estándar de depuración tales como puntos de interrupciones, revisión de la pila de llamadas e inspección de variables/objetos. Todas las caracterísitcas son accesibles a través de la interfaz de usuario y a través de la consola interactiva del depurador. Con la consola, se puede ejecutar código JavaScript arbitrario del mismo ámbito en el que JavaScript está siendo depurado.

Diferencias en CSS

Todos los productos basados en Mozilla poseen un fuerte soporte para CSS (hojas de estilo en cascada), en comparación con Internet Explorer y el resto de navegadores, ya que soportan la mayoría de CSS 1, CSS 2.1 y parte de CSS 3.

Para la mayoría de los problemas que se mostrarán a continuación, Mozilla mostrará un aviso o un error en la consola JavaScript. Se aconseja comprobar la consola JavaScript si se encuentran problemas relacionados con CSS.

Tipos MIME (cuando no se aplican a los ficheros CSS)

El problema más común relacionado con CSS ocurre cuando las definiciones CSS que se hallan dentro de los ficheros CSS referenciados no se aplican. Esto generalmente se debe a que el servidor envía un tipo MIME incorrecto para el fichero CSS. La especificación CSS dice que los ficheros CSS deberían ser servidos con el tipo MIME text/css. Mozilla respetará esto y sólo cargará los ficheros CSS con ese tipo MIME si la página web está en modo estricto de estándares. Internet Explorer siempre cargará el fichero CSS sin importar el tipo MIME con el que haya sido servido. Se considera que las páginas web están en modo estricto de estándares cuando comienzan con un doctype (tipo de documento) estricto. Para solventar este problema, se puede optar por hacer que el servidor envíe el tipo MIME correcto o eliminando el doctype. Se explicarán más a fondo los doctypes en la siguiente sección.

CSS y las unidades

Muchas aplicaciones web no usan unidades en sus hojas CSS, especialmente cuando se usa JavaScript para establecer el CSS. Mozilla permite esto sólo si la página no se visualiza en modo estricto. Dado que Internet Explorer no soporta el auténtico XHTML, no se preocupa por saber si se han especificado o no las unidades. Si la página está en modo estricto de estándares y no se usan unidades entonces Mozilla ignorará dicho estilo.

<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 y unidades - Ejemplo</title>
  </head>
  <body>
    // funciona en modo estricto
    <div style="width: 40px; border: 1px solid black;">
      Text
    </div>
    // peta en modo estricto
    <div style="width: 40; border: 1px solid black;">
      Text
    </div>
  </body>
</html>

Debido a que el ejemplo de antes tiene un doctype estricto, la página se visualizará en modo estricto de estándares. El primer div tendrá una anchura de 40px dado que se han usado unidades, pero el segundo div no tendrá anchura definida y se le asignará aquella por defecto (100%). Pasaría lo mismo si se estableciese la anchura a través de JavaScript.

JavaScript y CSS

Dado que Mozilla soporta los estándares CSS, también soporta el estándar DOM de CSS para poder establecer el estilo CSS a través de JavaScript. Se puede acceder a, eliminar y cambiar cualquier regla CSS de un elemento a través de su miembro style:

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

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

Igualmente se puede acceder a cada atributo CSS de la misma forma. De nuevo, si la página web está en modo estricto, se debe establecer una unidad o, en caso contrario, Mozilla ignorará el comando. Cuando se consulte un valor, digamos .style.width, Mozilla e Internet Explorer devolverán una cadena de texto incluyendo la unidad. Se puede convertir dicha cadena en un número a través de parseFloat("40px").

Diferencias en la propiedad CSS overflow

Con CSS, se introduce el concepto de overflow que permite definir cómo se maneja el rebasamiento, por ejemplo, cuando la altura del contenido de un div es mayor que la altura del propio div. El estándar CSS indica que en caso de rebosamiento, si no se ha establecido dicho comportamiento, el contenido del div debe de rebosar.

Sin embargo, Internet Explorer no cumple esto y alargará el div más allá de su altura hasta que pueda albergar correctamente su contenido. Más abajo hay un ejemplo que muestra esta diferencia:

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

Como se puede apreciar en la figura 4, Mozilla reacciona como especifican los estándares del W3C. Dichos estándares dicen que, en este caso, el div interior debería rebosar por la parte inferior dado que su contenido es más alto que el de su padre. Si se prefiere utilizar el comportamiento de Internet Explorer, simplemente no habría que especificar ninguna altura para el elemento exterior.

Figura 4. Rebosamiento DIV

DIV Overflow

Diferencias con la pseudoclase :hover

El comportamiento no estándar de la pseudoclase CSS :hover ocurre en un gran número de sitios web. Generalmente se manifiesta por sí mismo cambiando el estilo de texto cuando el cursor del ratón se sitúa sobre un elemento en Mozilla, pero no en Internet Explorer. Esto es así porque el selector CSS a:hover en Internet Explorer coincide con <a href="">...</a> pero no con <a name="">...</a>, el cual establece los anclajes en HTML. El cambio de texto ocurre porque los autores encapsulan áreas con el etiquetado de anclajes:

CSS:
  a:hover {color: green;}

HTML:
  <a href="foo.com">Este texto debería volverse verde cuando el cursor del ratón se sitúe sobre él.</a>

  <a name="anchor-name">
    Este texto debería cambiar el color cuando fuese sobrevolado con el cursor pero no ocurre en Internet Explorer.
  </a>

Mozilla sigue la especificación CSS correctamente y cambiará el color a verde en este ejemplo. Se pueden utilizar dos formas para que Mozilla se comporte como Internet Explorer y no cambie el color del texto cuando éste sea sobrevolado:

  • Primero, se puede cambiar la regla CSS para que sea a:link:hover {color: green;}, lo que provocará que sólo se cambie el color si un elemento es un enlace (tiene un atributo href).
  • Alternativamente, es posible cambiar el marcado y cerrar la < a/> abierta antes de que empiece el texto; el anclaje continuará funcionando de este modo.

Modo quirks vs. modo estándar

Los antiguos navegadores, como Internet Explorer 4, visualizaban los documentos bajo ciertas condiciones con el llamado modo quirks (modo chapucero). Aunque Mozilla apunta a convertirse en un navegador respetuoso con los estándares, posee 3 modos que permiten soportar las antiguas páginas creadas para comportarse de ese modo tan peculiar. El contenido de la página y la forma en la que nos es enviada determinan el modo que Mozilla debe de utilizar. Mozilla muestra dicho modo en Ver -> Información de página (o Ctrl+I) y Firefox lo hace en Herramientas -> Información de la página. El modo en el que una página es visualizada depende de su doctype.

Los doctypes (contracción inglesa para las declaraciones de tipos de documento) tiene este aspecto:

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

La parte azul es llamada identificador público, la verde es el identificador de sistema que es un URI.

Modo estándar

El modo estándar es el modo de visualización más estricto: visualizará las páginas según las especificaciones HTML y CSS del W3C y no permitirá ninguna chapuza. Mozilla lo usa bajo las siguientes condiciones:

  • Cuando una página es enviada con un tipo MIME igual a text/xml o cualquier otro tipo MIME XML o XHTML.
  • Con cualquier doctype "DOCTYPE HTML SYSTEM" (por ejemplo, <!DOCTYPE HTML SYSTEM "http://www.w3.org/TR/REC-html40/strict.dtd">), exceptuando el doctype de IBM
  • Cuando se especifique un doctype desconocido o éste no esté asociado a un DTD.

Modo casi estándar

Mozilla introdujo el modo casi estándar por una razón: una sección en la especificación CSS 2 daba al traste con los diseños que se basaban en la maquetación con tablas que contenían pequeñas imágenes. El usuario, en lugar de ver una imagen completa, veía cada imagen separada con un pequeño espacio en blanco. La antigua página de IBM mostrada en la figura 5 es un ejemplo de ello.

Figura 5. Hueco en imágenes

Image Gap

El modo casi estándar se comporta de modo muy parecido al modo estándar exceptuando el problema del hueco en imágenes. Este problema ocurre frecuentemente en páginas diseñadas acorde a los estándares y hace que se muestren incorrectamente.

Mozilla utiliza el modo casi estándar bajo las siguientes condiciones:

  • Ante cualquier doctype de tipo "loose" (obsoleto), por ejemplo <!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">
  • Para el doctype de IBM (<!DOCTYPE html SYSTEM "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd">)

Para más información, véase el problema de los huecos con imágenes

Modo quirks

Actualmente, el web está plagado de sitios con HTML no válido, además de marcado que sólo funciona gracias a fallos de ciertos navegadores. Los antiguos navegadores de Netscape, cuando eran los amos del mercado, tenían fallos. Cuando desembarcó Internet Explorer, plagió esos mismos fallos para poder visualizar correctamente las páginas de aquella época. Más tarde cuando los nuevos navegadores llegaron al mercado, la mayoría de estos fallos originales, usualmente llamados quirks, fueron mantenidos por razones de compatibilidad hacia atrás. Mozilla soporta muchos de estos fallos cuando visualiza páginas en modo quirks. Nótese que debido a estos quirks, las páginas se visualizan más lentamente que si estuvieran escritas para respetar los estándares. La mayoría de las páginas web son visualizadas utilizando este modo.

Mozilla utiliza este modo cuando encuentra las siguientes condiciones:

  • Cuando no se ha especificado un doctype.
  • Cuando se ha especificado un doctype sin su identificador de sistema (por ejemplo, <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"></code>)

Para más información, véase Mozilla Quirks Mode Behavior and Mozilla's DOCTYPE sniffing.

Diferencias en eventos

Mozilla e Internet Explorer son prácticamente incompatibles en cuanto al manejo de eventos se refiere. El modelo de eventos de Mozilla sigue al del W3C y al de Netscape. En Internet Explorer, si una función es llamada desde un evento, se puede acceder al objeto event a través de window.event. En cambio Mozilla pasa un objeto event a los manejadores de eventos. Éstos deben de pasar específicamente el objeto a la función llamada a través de un argumento. A continuación se muestra un ejemplo multiplataforma de manejador de evento:

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

<script>
  function handleEvent(evento) { 
    // if evento es null, significa que es el modelo de eventos de IE
    // así que se utiliza window.event
    var miEvento = evento ? evento : window.event; 
  }
</script>

A veces, esto no funciona ya que Internet Explorer coge el parámetro evento, identificándolo como no nulo, lo que en el códico provoca que no se pueda asignar window.event. La solución consiste en comprobar la propiedad window.event:

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

<script>
  function handleEvent(aEvent) { 
    var myEvent = window.event ? window.event : aEvent;
  }
</script>

Las propiedades y funciones que el objeto event muestra son nombradas con frecuencia de forma diferente entre Mozilla e Internet Explorer, como muestra la tabla 4:

Tabla 4. Diferencias entre las propiedades de eventos entre Mozilla e Internet Explorer
Nombre en Internet Explorer Nombre en Mozilla Descripción
altKey altKey Propiedad booleana que indica si la tecla alt estaba pulsada durante el evento.
cancelBubble stopPropagation() Usado para evitar que el evento sea propagado hacia los elementos ancestros en el árbol.
clientX clientX Coordenada X del evento, relativa al viewport.
clientY clientY Coordenada Y del evento, relativa al viewport.
ctrlKey ctrlKey Propiedad booleana que indica si la tecla Ctrl estaba pulsada durante el evento.
fromElement relatedTarget Para eventos de ratón, es el elemento desde el que partió el cursor del ratón.
keyCode keyCode Para eventos de teclado, es el número que representa a la tecla que estaba pulsada. 0 para los eventos de ratón.
returnValue preventDefault() Usado para evitar que se ejecute la acción por defecto del evento.
screenX screenX Coordenada X del evento, relativa a la pantalla.
screenY screenY Coordenada Y del evento, relativa a la pantalla.
shiftKey shiftKey Propiedad booleana que indica si la tecla shift estaba pulsada durante el evento.
srcElement target El elemento que provocó el evento.
toElement currentTarget Para eventos de ratón, es el elemento al que el ratón se dirigió cuando terminó el mismo.
type type Devuelve el nombre del evento.

Añadir manejadores de eventos

Mozilla posee dos formas de añadir eventos a través de JavaScript. El primero, soportado por todos los navegadores, consiste en establecer propiedades de eventos directamente en los objetos. Para asignar un manejador de evento al evento click hay que pasar una referencia a dicha función manejadora a la propiedad onclick del objeto.

<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 soporta al 100% la forma estándar del W3C para añadir escuchadores a los nodos del DOM: usando los métodos addEventListener() y removeEventListener(); y además con el beneplácito de poder añadir múltiples escuchadores para un mismo tipo de evento. Ambos métodos necesitan tres parámetros: el tipo de evento, una referencia a la función y un valor booleano que indica si el escuchador debe de capturar los eventos en su fase captura. Si el booleano es puesto a false, sólo capturará los eventos en la fase burbuja. Los eventos del W3C tienen tres fases: captura, objetivo y burbuja. Cada objeto event tiene un atributo eventPhase que indica la fase en la que se encuentra el evento mediante un número de base 0. Cuando se provoca un evento, éste comienza en el elemento más externamente situado del DOM, o sea, en el elemento superior del árbol DOM. Luego va atravesando el DOM usando el camino más corto hacia el objetivo. Estamos en la fase de captura. Cuando el evento alcanza al objetivo, el evento está en la fase objetivo. Tras alcanzar el objetivo, regresa por el árbol hasta alcanzar de nuevo el nodo más exteriormente situado. Esta es la fase burbuja. El modelo de eventos de Internet Explorer sólo tiene la fase burbuja por lo que estableciendo el tercer parámetro a false se conseguirá un comportamiento igual al de Internet Explorer.

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

Una ventaja de addEventListener() y removeEventListener() sobre asignar las propiedades es que se pueden tener múltiples escuchadores de eventos para el mismo evento, cada cual llamando a una función diferente. Así, para eliminar un escuchador de evento se necesita que los tres parámetros sean los mismos que se usaron para añadir el escuchador.

Mozilla no soporta el método de Internet Explorer de convertir etiquetas <script> en manejadores de eventos, la cual amplía a <script> con los atributos for y event (véase tabla 5). Tampoco suporta los métodos attachEvent ni detachEvent. En vez de eso, se deberían de usar los métodos addEventListener y removeEventListener. Internet Explorer no soporta la especificación de eventos del W3C.

Tabla 5. Diferencias en los métodos de eventos entre Mozilla e Internet Explorer
Método de Internet Explorer Método de Mozilla Descripción
attachEvent(tipoEvento, referenciaFuncion) addEventListener(tipoEvento, referenciaFuncion, usarCaptura) Añade un manejador de evento a un elemento del DOM
detachEvent(tipoEvento, referenciaFuncion) removeEventListener(tipoEvento, referenciaFuncion, usarCaptura) Elimina un manejador de evento a un elemento del DOM

Edición de texto enriquecido

Aunque Mozilla está orgulloso de ser el navegador más compatible con los estándares del W3C, sigue soportando funcionalidades no estándar, tales como innerHTML o editores de texto enriquecido, al no existir los equivalentes del W3C.

Con Mozilla 1.3 se introdujo una implementación de la característica designMode de Internet Explorer, la cual convierte a un documento HTML en un editor de texto enriquecido.

Una vez se ha cambiado al editor, los comandos pueden ser ejecutados en el documento a través del comando execCommand. Mozilla no soporta el atributo contentEditable de Internet Explorer para hacer editable cualquier control. Se puede usar un iframe para crear un editor de texto enriquecido.

Diferencias en el texto enriquecido

Mozilla soporta el método estándar del W3C para acceder al objeto document del iframe a través de IFrameElmRef.contentDocument mientras que Internet Explorer lo hace a través de document.frames{{ mediawiki.external('\"IframeName\"') }} y luego accede al document resultante.

<script>
function getIFrameDocument(aID) {
  var rv = null; 

  // if contentDocument existe, entonces es compatible con el W3C (Mozilla)
  if (document.getElementById(aID).contentDocument){
    rv = document.getElementById(aID).contentDocument;
  } else {
    // IE
    rv = document.frames[aID].document;
  }
  return rv;
}
</script> 

Otra diferencia entre Mozilla e Internet Explorer es el HTML que crea el editor de texto enriquecido. Por defecto, Mozilla usa CSS para generar marcado. Sin embargo, Mozilla permite alternar entre el modo HTML y CSS usando el comando useCSS del execCommand cambiándolo entre true y false. Internet Explorer siempre usa el marcado HTML.

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

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

Internet Explorer: 
  <FONT color="blue">Azul</FONT> 

Más abajo hay una lista de comandos soportados por execCommand en Mozilla:

Tabla 6. Comandos del editor de texto enriquecido.
Nombre Descripción Argumentos
bold Alterna el modo en negrita de la selección. ---
createlink Genera un enlace HTML a partir del texto seleccionado. URL a usar para el enlace
delete Borra la selección. ---
fontname Cambia la fuente del texto seleccionado. Nombre de la fuente (por ejemplo, Arial)
fontsize Cambia el tamaño del texto seleccionado. Tamaño de la fuente
fontcolor Cambia el color de la fuente del texto seleccionado. Color a usar
indent Indenta el bloque donde el se encuentra el cursor. ---
inserthorizontalrule Inserta un elemento <hr> en la posición del cursor. ---
insertimage Inserta una imagen en la posición del cursor. URL de la imagen
insertorderedlist Inserta un elemento de lista ordeanda (<ol>) en la posición del cursor. ---
insertunorderedlist Inserta un elemento de lista no ordenada (<ul>) en la posición del cursor. ---
italic Alterna el modo en cursiva de la selección. ---
justifycenter Centra el contenido de la línea actual. ---
justifyleft Alinea el contenido de la línea actual a la izquierda. ---
justifyright Alinea el contenido de la línea actual a la derecha. ---
outdent Elimina la indentación del bloque donde se halla el cursor. ---
redo Rehace el anterior comando deshecho. ---
removeformat Elimina todo el formato de la selección. ---
selectall Selecciona todo el texto del editor. ---
strikethrough Alterna el modo tachado del texto seleccionado. ---
subscript Convierte la selección actual a subíndice. ---
superscript Convierte la selección actual a superíndice. ---
underline Alterna el modo subrayado del texto seleccionado. ---
undo Deshace el último comando ejecutado. ---
unlink Elimina toda la información sobre enlaces de la selección. ---
useCSS Alterna el uso de CSS en el marcado generado. Valor booleano

Para más información, véase Rich-Text Editing in Mozilla

Diferencias en XML

Mozilla posee un fuerte soporte para XML y todas sus tecnologías relacionadas, tales como XSLT y servicios web. Además soporta algunas extensiones no estándar de Internet Explorer, tales como XMLHttpRequest.

Cómo manejar XMLs

Al igual que ocurre con el estándar HTML, Mozilla soporta la especificación del DOM para XML del W3C, la cual permite manipular prácticamente cualquier aspecto de cualquier documento XML. Las diferencias entre el DOM para XML de Internet Explorer y Mozilla son provocadas por el comportamiento no estándar de Internet Explorer. Probablemente la diferencia más común es cómo ambos manejan los espacios en blanco en los nodos de texto. Con frecuencia cuando se genera un XML, contiene espacios en blanco entre los nodos XML. Internet Explorer, cuando usa XMLNode.childNodes[] no contendrá estos nodos de espacios en blanco. En Mozilla, estos nodos se incluirán en el vector.

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

La primera línea de JavaScript carga el documento XML y accede a su elemento ráiz (myXMLDoc) recuperando el documentElement. La segunda línea simplemente muestra el número de nodos hijos. Para la especificación del W3C, los espacios en blanco y los retornos de carro se unen bajo un nodo de texto si uno es seguido del otro. Para Mozilla, el nodo myXMLdoc tiene tres hijos: un nodo de texto que contiene un retorno de carro y dos espacios, el nodo myns:foo, y otro nodo de texto con un retorno de carro. No obstante, Internet Explorer no obedece esto y devolverá "1" para el anterior código, considerando sólamente el nodo myns:foo Por elli, para recorrer los nodos hijos y desechar los nodos de texto se deben distinguir tales nodos del resto.

Como se mencionó antes, cada nodo tiene un atributo nodeType que representa el tipo de nodo. Por ejemplo, un nodo elemento tiene tipo 1 mientras que un nodo documento posee tipo 9. Para distinguir los nodos de texto se deben buscar los nodos de tipo 3 (nodos de texto) y los de tipo 8 (nodos comentario).

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

Islas de datos XML

Internet Explorer posee una peculiaridad no estándar llamada islas de datos XML (XML data islands), que permite incrustar XML dentro de un documento HTML usando la etiqueta HTML no estándar <xml>. Mozilla no soporta las islas de datos XML y las maneja como etiquetas HTML desconocidas. Se puede obtener la misma funcionalidad utilizando XHTML, sin embargo, debido a que el soporte de Internet Explorer para XHTML es débil, esto no es generalmente una opción.

Una solución multiplataforma es usar analizadores DOM que generan, a partir de un documento XML serializado, el documento XML analizado. Mozilla usa la clase DOMParser la cual toma una cadena serializada crea un documento XML a partir de ella. En Internet Explorer se puede obtener la misma funcionalidad usando ActiveX. El nuevo Microsoft.XMLDOM genera y posee el método un método llamado loadXML que acepta una cadena de texto y genera un documento a partir de ella. El siguiente código muestra su funcionamiento:


Isla de datos XML para IE
  .. 
  <xml id="xmldataisland"> 
    <foo>bar</foo> 
  </xml>

Solución multiplataforma: 
  var xmlString = "<xml id=\"xmldataisland\"><foo>bar</foo></xml>"; 

  var myDocument; 

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

    myDocument.loadXML(xmlString);
  }

Peticiones HTTP para XML

Internet Explorer permite el envío y recuperación de ficheros XML usando la clase de MSXML XMLHTTP, instanciada a través de ActiveX usando new ActiveXObject("Msxml2.XMLHTTP") o new ActiveXObject("Microsoft.XMLHTTP"). Dado que no hay un método estándar para hacer esto, Mozilla proporciona la misma funcionalidad en el objeto global XMLHttpRequest de JavaScript. El objeto genera peticiones asíncronas de modo predeterminado.

Tras instanciar el objeto usando new XMLHttpRequest() se puede usar el método open para especificar qué tipo de petición (GET o POST) se quiere usar, qué fichero se va a cargar y si será una petición asíncrona o no. Si la llamada es asíncrona, será necesario facilitar al miembro onload una referencia a una función que será invocada una vez la petición ha sido completada.

Petición síncrona:

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

  myXMLHTTPRequest.send(null); 

  var myXMLDocument = myXMLHTTPRequest.responseXML; 

Petición asíncrona:

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

La tabla 7 muestra una lista de métodos y propiedades disponibles para el objeto XMLHttpRequest de Mozilla.

Tabla 7. Métodos y propiedades XMLHttpRequest
Nombre Descripción
void abort() Detiene la petición si ésta aún está en curso.
string getAllResponseHeaders() Devuelve todas las cabeceras de respuesta como una única cadena.
string getResponseHeader(string headerName) Devuelve el valor de la cabecera especificada.
functionRef onerror La función que se le asigne será invocada cuando ocurran errores durante una petición.
functionRef onload La función que se le asigne será invocada cuando la petición se complete con éxito y se haya recibido una respuesta. Se usa con las peticiones asíncronas.
void open (string HTTP_Method, string URL)

void open (string HTTP_Method, string URL, boolean async, string userName, string password)
Inicializa la petición para la URL especificada, usando tanto GET o POST como el método HTTP. Para enviar la petición, es necesario llamar al método send() tras la inicialización. Si async se establece a false, la petición será síncrona. De modo predeterminado es asíncrona. Opcionalmente se puede especificar un nombre de usuario y contraseña por si la necesita la URL facilitada. 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 Estado de la petición. Valores posibles:
Valor Descripción
0 UNINITIALIZED - open() aún no ha sido llamado.
1 LOADING - send() aún no ha sido llamado.
2 LOADED - send() ha sido llamado y las cabeceras y el estado están disponibles.
3 INTERACTIVE - Descargando. responseText contiene datos parciales.
4 COMPLETED - Todas las operaciones han sido completadas.
string responseText Cadena que contiene la respuesta.
DOMDocument responseXML Documento DOM que contiene la respuesta.
void send(variant body) Realiza la petición. Si body está definido, será enviado como el cuerpo de la petición POST. body puede ser un documento XML o una cadena conteniendo un XML serializado.
void setRequestHeader (string headerName, string headerValue) Establece una cabecera de petición HTTP para usarla en la petición HTTP. Ha de ser llamada tras invocar al método open().
string status El código de estado de la respuesta HTTP.

Diferencias en XSLT

Mozilla soporta las transformaciones XSL 1.0 (XSLT). Además permite a JavaScript realizar tanto transformaciones XSLT como consultas XPath sobre un documento.

Mozilla necesita que se le pase el fichero XML y XSLT que contiene la hoja de estilos con un tipo MIME XML (text/xml o application/xml). Este es el motivo más común por el cual los XSLT no funcionan en Mozilla pero sí en Internet Explorer. En ese sentido, Mozilla es estricto.

Internet Explorer 5.0 y 5.5 soportan el borrador de XSLT, el cual es sustancialmente diferente a la recomendación final 1.0. La forma más fácil de distinguir la versión en la que ha sido escrito un fichero XSLT es mirando su espacio de nombres. El espacio de nombres para la recomendación 1.0 es http://www.w3.org/1999/XSL/Transform mientras que el espacio de nombres del borrador es http://www.w3.org/TR/WD-xsl. Internet Explorer 6 soporta el borrador por razones de compatibilidad hacia atrás. Mozilla no soporta dicho borrador, sólo la recomendación final.

Si el XSLT necesita distinguir el navegador, se puede consultar la propiedad de sistema "xsl:vendor". El motor XSLT de Mozilla devolverá "Transformiix" mientras que Internet Explorer devolverá "Microsoft".

<xsl:if test="system-property('xsl:vendor') = 'Transformiix'"> 
  <!-- Marcado específico de Mozilla --> 
</xsl:if> 
<xsl:if test="system-property('xsl:vendor') = 'Microsoft'"> 
  <!-- Marcado específico de Internet Explorer --> 
</xsl:if> 

Mozilla también proporciona una interfaz de JavaScript para XSLT, permitiendo a un sitio web completar transformaciones XSLT en memoria. Esto puede hacerse usando el objeto global de JavaScript XSLTProcessor. XSLTProcessor necesita que se carge el XML y los ficheros XSLT ya que necesita sus documentos DOM. El documento XSLT importado por XSLTProcessor permite manipular los parámetros XSLT. XSLTProcessor puede generar un documento independiente utilizando transformToDocument() o puede crear un fragmento de documento utilizando transformToFragment() para poder ser anexado fácilmente a otro documento DOM. Más abajo se muestra un ejemplo:

var xslStylesheet; 
var xsltProcessor = new XSLTProcessor(); 

// carga el fichero XSLT example1.xsl 
var myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xsl", false); 
myXMLHTTPRequest.send(null); 

// obtiene el documento XML y lo importa
xslStylesheet = myXMLHTTPRequest.responseXML; 

xsltProcessor.importStylesheet(xslStylesheet); 

// carga el fichero xml example1.xml 
myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xml", false); 
myXMLHTTPRequest.send(null); 

var xmlSource = myXMLHTTPRequest.responseXML; 

var resultDocument = xsltProcessor.transformToDocument(xmlSource); 

Tras crear un objeto XSLTProcessor, hay que cargar el fichero XSLT a través de XMLHttpRequest. El miembro responseXML del XMLHttpRequest contiene el documento XML del fichero XSLT, el cuas es pasado a importStylesheet. Luego hay que usar de nuevo XMLHttpRequest para cargar el documento XML que va a ser transformado. Ese documento es entonces pasado al método transformToDocument de XSLTProcessor. La tabla 8 muestra una lista con los métodos de XSLTProcessor.

Tabla 8. Métodos de XSLTProcessor
Método Descripción
void importStylesheet(Node styleSheet) Importa la hoja de estilo XSLT. El argumento styleSheet es el nodo ráiz del documento DOM de la hoja de estilos XSLT.
DocumentFragment transformToFragment(Node source, Document owner) Transforma el nodo source aplicando la hoja de estilos importada con el método importStylesheet y genera un DocumentFragment. owner especifica a qué documento DOM debe anexarse el DocumentFragment, haciéndolo compatible con ese documento DOM.
Document transformToDocument(Node source) Transforma el nodo source aplicando la hoja de estilos importada a través del método importStylesheet y devuelve un documento DOM independiente.
void setParameter(String namespaceURI, String localName, Variant value) Establece un parámetro en la hoja de estilos XSLT importada.
Variant getParameter(String namespaceURI, String localName) Obtiene el valor de un parámetro en la hoja de estilos XSLT importada.
void removeParameter(String namespaceURI, String localName) Elimina todos los parámetros establecidos para la hoja de estilos XSLT importada y establece sus valores a los predeterminados para el XSLT.
void clearParameters() Elimina todos los parámetros establecidos y establece sus valores a los predeterminados en la hoja de estilos XSLT.
void reset() Elimina todos los parámetros y hojas de estilos.

Original Document Information


{{ languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla", "fr": "fr/Migration_d\'applications_d\'Internet_Explorer_vers_Mozilla", "ko": "ko/Migrate_apps_from_Internet_Explorer_to_Mozilla", "zh-cn": "cn/\u4eceInternet_Explorer\u8fc1\u79fb\u5230Mozilla", "zh-tw": "zh_tw/\u8f49\u63db\u7db2\u9801\u7a0b\u5f0f\uff1a\u5f9e_IE_\u5230_Mozilla" } ) }}

Fuente de la revisión

<h3 name="Introducci.C3.B3n">Introducción</h3>
<p>Cuando Netscape comenzó con el navegador Mozilla, lo hizo con la decisión consciente de soportar los estándares del W3C. Como resultado, Mozilla no es totalmente compatible hacia atrás con el código heredado de Netscape Navigator 4.x ni de Microsoft Internet Explorer. Por ejemplo, Mozilla no soporta la etiqueta <code>&lt;layer&gt;</code> como se verá más adelante. Los navegadores como Internet Explorer 4 fueron construidos antes de la concepción de los estándares del W3C heredando muchos de sus extraños comportamientos. En este articulo se describirán las idiosincrasias de Mozilla que hacen que haya una fuerte compatibilidad del HTML hacia atrás con Internet Explorer y otros navegadores antiguos.
</p><p>También se repasarán las tecnologías no estandarizadas soportadas por Mozilla, como el XMLHttpRequest y la edición de texto enriquecido, dado que existen sus equivalentes existentes en el W3C y que se incluyen en: </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> y <a class="external" href="http://www.w3.org/TR/xhtml11/">XHTML 1.1</a>
</li><li>Hojas de estilo en cascada (CSS): <a class="external" href="http://www.w3.org/TR/REC-CSS1">CSS nivel 1</a>, <a class="external" href="http://www.w3.org/TR/CSS21/">CSS nivel 2.1</a> y parte del <a class="external" href="http://www.w3.org/Style/CSS/current-work.html">CSS nivel 3</a>
</li><li>Modelo de objetos de documento (DOM): <a class="external" href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/">DOM nivel 1</a>, <a class="external" href="http://www.w3.org/DOM/DOMTR#dom2">DOM nivel 2</a> y parte del <a class="external" href="http://www.w3.org/DOM/DOMTR#dom3">DOM nivel 3</a>
</li><li>Lenguaje de etiquetado matemático (MathML): <a class="external" href="http://www.w3.org/Math/">MathML versión 2.0</a>
</li><li>Lenguaje de etiquetado ampliable (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/">Espacios de nombres en XML</a>, <a class="external" href="http://www.w3.org/TR/xml-stylesheet/">Asociando hojas de estilos con documentos 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">Fragment Identifier for XML</a>
</li><li>Transformaciones XSL: <a class="external" href="http://www.w3.org/TR/xslt">XSLT 1.0</a>
</li><li>Lenguaje XPath: <a class="external" href="http://www.w3.org/TR/xpath">XPath 1.0</a>
</li><li>Resource Description Framework (Infraestructura para la descripción de recursos): <a class="external" href="http://www.w3.org/RDF/">RDF</a>
</li><li>Simple Object Access Protocol (Protocolo simple de acceso a objetos): <a class="external" href="http://www.w3.org/TR/soap">SOAP 1.1</a>
</li><li>ECMA-262, revision 3 (JavaScript 1.5): <a class="external" href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMA-262</a>
</li></ul>
<h3 name="Trucos_generales_para_la_programaci.C3.B3n_multinavegador">Trucos generales para la programación multinavegador</h3>
<p>Pese a la existencia de los estándares web, los diferentes navegadores se comportan de manera distinta (de hecho, el mismo navegador puede comportarse de modo diferente dependiendo de la plataforma). Muchos navegadores, como Internet Explorer, también soportan el APIs anterior al W3C y nunca se han esforzado en añadir soporte para los navegadores compatibles con el W3C.
</p><p>Antes de enumerar las diferencias entre Mozilla e Internet Explorer, sería conveniente cubrir algunas formas básicas en las que se pueden crear aplicaciones web ampliables a las que añadir soporte para nuevos navegadores más tarde.
</p><p>Dado que los diferentes navegadores utilizan a veces diferentes APIs para una misma funcionalidad, es muy posible que encuentres múltiples bloques <code>if() else()</code> a lo largo y ancho del código para diferenciar el navegador que está ejecutando el documento. El siguiente código muestra un bloque diseñado para Internet Explorer:
</p>
<pre>. . . 

var elm; 

if (ns4) 
  elm = document.layers["myID"]; 
else if (ie4) 
  elm = document.all["myID"]
</pre>
<p>El anterior código no es ampliable por lo que si quieres soportar un nuevo navegador, deberás actualizar ese bloque de código en toda la aplicación web.
</p><p>La forma más fácil de evitar la recodificación del documento para un nuevo navegador es abstraer la funcionalidad. En lugar de utilizar múltiples bloques <code>if() else()</code>, puedes incrementar la eficiencia tomando tareas comunes y abstrayéndolas en sus propias funciones. Esto no sólo hace al código más legible sino que simplifica el proceso añadir soporte para nuevos clientes.
</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>El código de arriba sigue arrastrando el problema del <i>browser sniffing</i> o el proceso de detección para saber qué navegador está utilizando el usuario. El browser sniffing es detectado generalmente gracias al parámetro <i>useragent</i>, como:
</p>
<pre>Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016 
</pre> <p>Mientras que la utilización del parámetro <i>useragent</i> para detectar el navegador proporciona información detallada del navegador en uso, el código que maneja esos parámetros genera errores con frecuencia cuando son publicadas nuevas versiones de los mismos, por lo que hay que cambiar el código.
</p><p>Si el tipo de navegador no importa (supongamos que se ha bloquado el acceso a la aplicación web a navegadores no soportados), <strong>será mucho mejor y más fiable detectar las capacidades del navegador o el soporte de objetos en particular</strong>. Generalmente se puede hacer esto probando la funcionalidad requerida en JavaScript, por ejemplo, en lugar de:
</p>
<pre>if (isMozilla || isIE5) 
</pre> <p>Se debería de usar:
</p>
<pre>if (document.getElementById) 
</pre> <p>Esto permitiría a otros navegadores que soportan ese método estandar del W3C (tales como Opera o Safari) funcionar sin ningún cambio.
</p><p>La detección del agente de usuario sin embargo tiene sentido cuando es importante acertar, como cuando estás verificando que un navegador coincide con los requerimientos de versión de la aplicación web o estás intentando sortear un fallo de programación.
</p><p>JavaScript también permite sentencias condicionales en línea, lo que ayuda a la legibilidad:
</p>
<pre>var foo = (condicion) ? condicionEsTrue : condicionEsFalse; 
</pre> <p>Por ejemplo, para obtener un elemento se debería usar:
</p>
<pre> 
function getElement(aID){ 
  return (document.getElementById) ? document.getElementById(aID)
                                   : document.all[aID];
} 
</pre>
<h3 name="Diferencias_entre_Mozilla_e_Internet_Explorer">Diferencias entre Mozilla e Internet Explorer</h3>
<p>Primero se discutirán las diferencias en la forma en la que se comporta el HTML en Mozilla y en Internet Explorer.
</p>
<h4 name="T.C3.ADtulos_emergentes">Títulos emergentes</h4>
<p>Los títulos emergentes son pequeños textos descriptivos que aparecen normalmente cuando se deja el cursor del ratón un cierto tiempo sobre un elemento.
</p><p>Los navegadores antiguos introdujeron los títulos emergentes en el HTML mostrándolos en enlaces y usando el valor del atributo <code>alt</code> como contenido del título. La última especificación de W3C para HTML creó el atributo <code>title</code>, pensado para contener una descripción detallada del enlace. Los navegadores modernos utilizan el atributo <code>title</code> para mostrar títulos emergentes y Mozilla sólo muestra dichos títulos basándose en el ese atributo y no en el atributo <code>alt</code>.
</p>
<h4 name="Entidades">Entidades</h4>
<p>El marcado HTML puede contener varias entidades definidas por el <a class="external" href="http://www.w3.org/TR/REC-html40/sgml/entities.html">departamento de estándares web del W3C</a>. Se pueden referenciar entidades a través de su referencia numérica o alfabética. Por ejemplo, puedes referenciar el carácter de espacio en blanco #160 con <code>&amp;#160</code> o con su referencia alfabética correspondiente <code>&amp;nbsp;</code>.
</p><p>Algunos navegadores antiguos, como Internet Explorer, son tan fulleros que permiten usar entidades reemplazando el carácter <code>;</code> (punto y coma) al final con contenido normal de texto.
</p>
<pre>&amp;nbsp Foo 
&amp;nbsp&amp;nbsp Foo 
</pre>
<p>Mozilla visualizará el <code>&amp;nbsp</code> mostrado anteriormente como espacios en blanco, pese a que va en contra de la especificación del W3C. El navegador no analizará un <code>&amp;nbsp</code> si va inmediatamente seguido por más caracteres. Por ejemplo:
</p>
<pre>&amp;nbsp12345 
</pre>
<p>Este código no funcionará en Mozilla, dado que va en contra de los estándares del W3C. Es mejor usar la forma correcta (<code>&amp;nbsp;</code>) para evitar discrepancias entre navegadores.
</p>
<h3 name="Diferencias_en_el_DOM"> Diferencias en el DOM </h3>
<p>El Modelo de Objetos de Documento (DOM) es <b>la estructura en árbol que contiene los elementos del documento</b>. Se puede manipular a través de las APIs de JavaScript, las cuales han sido estandarizadas por el W3C. Sin embargo, antes de la estandarización del W3C, Netscape 4 e Internet Explorer 4 implementaron las APIs de modo similar. Mozilla implementa las APIs heredadas sólo si han sido aceptadas por los estándares del W3C.
</p>
<h4 name="Accediendo_a_los_elementos"> Accediendo a los elementos </h4>
<p>Para referenciar un elemento usando una técnicas multinavegador, debe de usarse <code>document.getElementById(id)</code>, que funciona tanto en Internet Explorer versión 5.0 y superiores, en navegadores basados en Mozilla y en otros navegadores compatibles con el W3C y es parte de la especificación DOM nivel 1.
</p><p>Mozilla no soporta el acceso a elementos a través de <code>document.elementName</code>, ni siquiera a través del nombre del elemento; algo que Internet Explorer permite (llamado también <em>global namespace polluting</em>). Mozilla tampoco soporta el método <code>document.layers</code> de Netscape ni el <code>document.all</code> de Internet Explorer. Mientras que <code>document.getElementById</code> permite referenciar un único elemento, puedes usar <code>document.layers</code> y <code>document.all</code> para obtener una lista de todos los elementos del documento con un nombre determinado, como todos los elementos <code>&lt;div&gt;</code>.
</p><p>El método del DOM nivel 1 del W3C que permite referenciar a todos los elementos con el mismo nombre de etiqueta es <code>getElementsByTagName()</code>. Este método devuelve un vector en JavaScript y puede ser invocado desde el elemento <code>document</code> o desde otros nodos para buscar sólo en su sub-árbol. Para obtener un vector con todos los elementos del árbol del DOM, se puede utilizar <code>getElementsByTagName("*")</code>.
</p><p>Los métodos del DOM nivel 1, como muestra la tabla 1, son usados comúnmente para mover un elemento a una posición en particular y cambiar su visibilidad (menús, animaciones, etc...). Netscape 4 usaba la etiqueta <code>&lt;layer&gt;</code>(algo que Mozilla no soporta) como un elemento que podía posicionarse en cualquier lugar. En Mozilla se puede posicionar cualquier elemento utilizando la etiqueta <code>&lt;div&gt;</code>, algo que Internet Explorer también utiliza y que está presente en la especificación HTML.
</p>
<table class="standard-table">
<caption> Tabla 1. Métodos usados para acceder a elementos
</caption><tbody><tr>
<th> Método </th><th> Descripción
</th></tr>
<tr>
<td> document.getElementById( unId ) </td><td> Devuelve una referencia al elemento cuyo atributo id coincide con el pasado como parámetro.
</td></tr>
<tr>
<td> document.getElementsByTagName( unNombre ) </td><td> Devuelve un vector de elementos cuyo nombre de etiqueta coincide con el pasado como parámetro.
</td></tr></tbody></table>
<h4 name="Recorrer_el_DOM">Recorrer el DOM</h4>
<p>Mozilla soporta las APIs del DOM del W3C que permiten recorrer el árbol del DOM a través de JavaScript (véase la tabla 2). Las APIs están disponibles para cada nodo del documento y permiten recorrer el árbol en cualquier dirección. Internet Explorer también soporta estas APIs y además sus APIs heredadas para recorrer el árbol del DOM, tales como la propiedad <code>children</code>.
</p>
<table class="standard-table">
<caption> Tabla 2. Métodos usados para recorrer el DOM
</caption><tbody><tr>
<th> Propiedad/Método </th><th> Descripción
</th></tr>
<tr>
<td> childNodes </td><td> Devuelve un vector con todos los nodos hijos del elemento.
</td></tr>
<tr>
<td> firstChild </td><td> Devuelve el primer nodo hijo del elemento.
</td></tr>
<tr>
<td> getAttribute( nombre ) </td><td> Devuelve el valor del atributo cuyo nombre se pasa como parámetro.
</td></tr>
<tr>
<td> hasAttribute( nombre ) </td><td> Devuelve un valor booleano que indica si el nodo actual tiene un atributo definido con el nombre especificado.
</td></tr>
<tr>
<td> hasChildNodes() </td><td> Devuelve un valor booleano que indica si el nodo actual tiene al menos un elemento hijo.
</td></tr>
<tr>
<td> lastChild </td><td> Devuelve el último nodo hijo del elemento.
</td></tr>
<tr>
<td> nextSibling </td><td> Devuelve el nodo que sigue inmediatamente al actual.
</td></tr>
<tr>
<td> nodeName </td><td> Devuelve el nombre del nodo actual como una cadena de texto.
</td></tr>
<tr>
<td> nodeType </td><td> Devuelve un valor numérico que indica el tipo del nodo actual.
<table>
<tbody><tr>
<th> Valor </th><th> Descripción
</th></tr>
<tr>
<td> 1 </td><td> Nodo elemento
</td></tr>
<tr>
<td> 2 </td><td> Nodo atributo
</td></tr>
<tr>
<td> 3 </td><td> Nodo de texto
</td></tr>
<tr>
<td> 4 </td><td> Nodo de sección CDATA
</td></tr>
<tr>
<td> 5 </td><td> Nodo de referencia a entidad
</td></tr>
<tr>
<td> 6 </td><td> Nodo entidad
</td></tr>
<tr>
<td> 7 </td><td> Nodo de instrucción de proceso
</td></tr>
<tr>
<td> 8 </td><td> Nodo comentario
</td></tr>
<tr>
<td> 9 </td><td> Nodo documento
</td></tr>
<tr>
<td> 10 </td><td> Nodo tipo de documento
</td></tr>
<tr>
<td> 11 </td><td> Nodo fragmento de documento
</td></tr>
<tr>
<td> 12 </td><td> Nodo anotación
</td></tr></tbody></table>
</td></tr>
<tr>
<td> nodeValue </td><td> Devuelve el valor del nodo actual. Para aquellos nodos que contentan texto, tales como los nodos de texto o los nodos comentario, se devolverá su valor alfabético. Para nodos atributo, se devolverá el valor de su atributo. Para el resto de nodos, se devolverá <code>null</code>.
</td></tr>
<tr>
<td> ownerDocument </td><td> Devuelve el objeto <code>document</code> que contiene al nodo actual.
</td></tr>
<tr>
<td> parentNode </td><td> Devuelve el nodo padre del nodo actual.
</td></tr>
<tr>
<td> previousSibling </td><td> Devuelve el nodo inmediatamente anterior al nodo actual.
</td></tr>
<tr>
<td> removeAttribute( nombre) </td><td> Elimina el atributo especificado del nodo actual.
</td></tr>
<tr>
<td> setAttribute( nombre, valor ) </td><td> Establece el valor de un atributo.
</td></tr></tbody></table>
<p>Internet Explorer se comporta de un modo no estándar donde muchas de estas APIs ignorarán los nodos de texto en blanco que son generados, por ejemplo, mediante caracteres de nueva línea. Mozilla no las ignora por lo que a veces se necesita distinguir a estos nodos. Cada nodo posee la propiedad <code>nodeType</code> que especifica el tipo de nodo. Por ejemplo, un nodo elemento es de tipo 1 mientras que un nodo de texto es de tipo 3, un nodo comentario es de tipo 8, etc...
La mejor forma de procesar sólo los nodos elemento es iterar todos los nodos hijos y procesar sólo aquellos cuya propiedad nodeType sea igual a 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){ 
      // Nodo elemento
    };
  };
</pre>
<h4 name="Generar_y_manejar_contenidos">Generar y manejar contenidos</h4>
<p>Mozilla soporta los métodos heredados para añadir contenido al DOM dinámicamente, tales como <code>document.write</code>, <code>document.open</code> y <code>document.close</code>. Mozilla también soporta el método de Internet Explorer <code>innerHTML</code> el cual puede ser llamado desde casi cualquier nodo. Sin embargo no soporta el método <code>outerHTML</code> (que añade marcado alrededor de un elemento y no tiene un equivalente estándar) ni <code>innerText</code> (el cual establece el valor alfabético de su nodo y que puede usarse en Mozilla usando <code>textContent</code>).
</p><p>Internet Explorer tiene varios métodos de manejo de contenidos que no son estándares y no son soportados en Mozilla, incluyendo obtener valores, insertar texto e insertar elementos adyacentes a un nodo tales como <code>getAdjacentElement</code> y <code>insertAdjacentHTML</code>. La tabla 3 muestra cómo el manipulan contenidos tanto Mozilla como el estándar del W3C, siendo todos ellos métodos aplicables a cualquier nodo del DOM.
</p>
<table class="standard-table">
<caption> Tabla 3. Métodos usados por Mozilla para manipular contenidos
</caption><tbody><tr>
<th> Método </th><th> Descripción
</th></tr>
<tr>
<td> appendChild( nodo ) </td><td> Crea un nuevo nodo hijo. Devuelve una referencia al nuevo nodo hijo.
</td></tr>
<tr>
<td> cloneNode( profundidad ) </td><td> Crea y devuelve una copia del nodo sobre el que se hace la llamada. Si <i>profundidad</i> es true, copia el sub-árbol completo del nodo.
</td></tr>
<tr>
<td> createElement( tipo ) </td><td> Crea y devuelve un nuevo nodo huérfano de tipo igual al especificado por <i>tipo</i>.
</td></tr>
<tr>
<td> createTextNode( valor ) </td><td> Crea y devuelve un nuevo nodo de texto huérfano asignándole el valor especificado por <i>valor</i>.
</td></tr>
<tr>
<td> insertBefore( nuevoNodo, nodoHijo ) </td><td> Inserta el nodo <i>nuevoNodo</i> antes de <i>nodoHijo</i>, el cual debe ser un hijo del nodo actual.
</td></tr>
<tr>
<td> removeChild( nodoHijo ) </td><td> Elimina el nodo <i>nodoHijo</i> y devuelve una referencia a él.
</td></tr>
<tr>
<td> replaceChild( nuevoNodo, nodoHijo ) </td><td> Reemplaza el nodo <i>nodoHijo</i> con el nodo <i>nuevoNodo</i> y devuelve una referencia al nodo eliminado.
</td></tr></tbody></table>
<h4 name="Fragmentos_de_documento"> Fragmentos de documento </h4>
<p>Por razones de eficiencia, pueden crearse documentos en memoria en lugar de trabajar con el DOM de un documento existente. El núcleo del DOM nivel 1 introdujo los fragmentos de documento, que son documentos ligeros que contienen un subconjunto de las interfaces de un documento normal. Por ejemplo, <code>getElementById</code> no existe pero <code>appendChild</code> sí. Además se pueden anexar fácilmente fragmentos de documento a los ya existentes.
</p><p>Mozilla crea fragmentos de documento a través de <code>document.createDocumentFragment()</code>, el cual devuelve un fragmento de documento vacío.
</p><p>Sin embargo, la implementación de Internet Explorer para los fragmentos de documentos no es compatible con el estándar del W3C y simplemente devuelve un documento normal.
</p>
<h3 name="Diferencias_en_JavaScript">Diferencias en JavaScript</h3>
<p><span class="comment">Buscar traducción adecuada para hooks DOM. "timing related" traducido como "duración de la ejecución"</span>
</p><p>Por lo general, la mayoría de las diferencias entre Mozilla e Internet Explorer son las de JavaScript. Sin embargo, los problemas normalmente residen en las APIs que un navegador muestra a JavaScript, tales como hooks de DOM. A nivel del núcleo, los dos navegadores no poseen grandes diferencias. Los problemas se encuentran frecuentemente en la duración de la ejecución.
</p>
<h4 name="Diferencias_en_las_fechas_de_JavaScript"> Diferencias en las fechas de JavaScript </h4>
<p>La única diferencia en el objeto <code>Date</code> es el método <code>getYear</code>. Para la especificación ECMAScript (que es la que sigue JavaScript), el método no es compatible con el efecto 2000 y al ejecutar <code>new Date().getYear()</code> en 2004 se obtendrá un valor igual a "104". Para la especificación ECMAScript, <code>getYear</code> devuelve el año menos 1900 lo cual devolvía "98" para 1998. <code>getYear</code> quedó obsoleto en la versión 3 de ECMAScript y fue reemplazado por <code>getFullYear</code>. Internet Explorer cambió la implementación de <code>getYear</code> para que funcionara como <code>getFullYear</code> y fuese así compatible con el efecto 2000, mientras que Mozilla mantuvo el comportamiento estándar.
</p>
<h4 name="Diferencias_de_ejecuci.C3.B3n_en_JavaScript"> Diferencias de ejecución en JavaScript </h4>
<p>Diferentes navegadores ejecutarán JavaScript de modo distinto. Por ejemplo, el siguiento código asume que el nodo <code>div</code> ya existe en el DOM en el momento en el que el bloque <code>script</code> se ejecuta:
</p>
<pre>...
&lt;div id="foo"&gt;Cargando...&lt;/div&gt;

&lt;script&gt; 
  document.getElementById("foo").innerHTML = "Cargado."; 
&lt;/script&gt; 
</pre>
<p>Sin embargo esto no está garantizado. Para asegurarnos de que todos los elementos existen se debería usar el manejador de evento <code>onload</code> en la etiqueta <code>&lt;body&gt;</code>:
</p>
<pre>&lt;body onload="doFinish();"&gt; 

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

&lt;script&gt; 
  function doFinish() { 
    var element = document.getElementById("foo");
    element.innerHTML = "Cargado."; 
  }
&lt;/script&gt; 
... 
</pre>
<p>Tales problemas relativos a la duración de la ejecución están también relacionados con el hardware; los sistemas más lentos pueden mostar fallos que los más rápidos no provocan. Un ejemplo en concreto se puede encontrar en <code>window.open</code>, el cual abre una nueva ventana:
</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>El problema con el código es que <code>window.open</code> es asíncrono lo que implica que no se bloquee la ejecución de JavaScript hasta que la ventana haya terminado de cargarse. Por tanto, se puede ejecutar la línea siguiente a la línea <code>window.open</code> antes de que la nueva ventana haya terminado de cargarse. Se puede lidiar con esto poniendo un manejador <code>onload</code> en la nueva ventana y luego llamar desde ahí a la ventana padre (usando <code>window.opener</code>).
</p>
<h4 name="Diferencias_en_la_generaci.C3.B3n_HTML_de_JavaScript"> Diferencias en la generación HTML de JavaScript </h4>
<p>JavaScript puede generar, a través de <code>document.write</code>, código HTML al vuelo a partir de una cadena de texto. El principal problema es cuando JavaScript está embebido dentro del documento HTML (es decir, dentro de la etiqueta <code>&lt;script&gt;</code>) y genera HTML que contiene una etiqueta <code>&lt;script&gt;</code>. Si el documento está en modo estricto de visualización, entonces se analizará la etiqueta <code>&lt;/script&gt;</code> que se halla dentro de la cadena como la etiqueta de cierre de la etiqueta <code>&lt;script&gt;</code> que la contiene. El siguiente código ilustra mejor esto:
</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('Hola');&lt;\/script&gt;") 
&lt;/script&gt; 
</pre>
<p>Dado que la página está en modo estricto, el analizador de Mozilla verá el primer <code>&lt;script&gt;</code> y lo analizará hasta que encuentre la etiqueta de cierre correspondiente, que será cuando encuentre el primer <code>&lt;/script&gt;</code>. Se hace así porque el analizador no tiene conocimiento de la existencia de JavaScript (o cualquier otro lenguaje) cuando está en modo estricto. En modo quirks, el analizador conoce de la existencia de JavaScript cuando trabaja (algo que lo ralentiza). Internet Explorer siempre funciona en modo quirks porque no soporta el auténtico XHTML. Para hacer que esto funcione en modo estricto en Mozilla se puede separar la cadena en dos partes:
</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('Hola');&lt;/" + "script&gt;") 
&lt;/script&gt; 
</pre>
<h4 name="Depurando_JavaScript"> Depurando JavaScript </h4>
<p>Mozilla proporciona varias formas de depurar los fallos relacionados con JavaScript encontrados en las aplicaciones creadas para Internet Explorer. La primera herramienta es la consola integrada de JavaScript, mostrada en la figura 1, donde los errores y los avisos quedan registrados. Puedes acceder a ella en Mozilla yendo al menú <b>Herramientas -&gt; Desarrollo web -&gt; Consola JavaScript</b>, en Firefox 2.0 (el navegador ligero de Mozilla) en <b>Herramientas -&gt; Consola de errores</b>.
</p><p>Figura 1. Consola JavaScript
</p><p><img alt="Javascript Console" fileid="0" src="File:es/Media_Gallery/Migrationguide-jsconsole.jpg">
</p><p>La consola JavaScript puede mostrar el registro completo o sólo los errores, avisos o mensajes. El mensaje de error de la figura 1 dice que en aol.com, la línea 95 ha intentado acceder a una variable no definida llamada is_ns70. Al hacer clic en el enlace se abrira el visualizador de código interno de Mozilla con la línea en cuestión resaltada.
</p><p>La consola además permite evaluar JavaScript. Para probar la sintaxis de JavaScript introducida, se puede escribir <code>1+1</code> en el campo de entrada y pulsar <b>Evaluar</b>, como muestra la figura 2.
</p><p>Figure 2. Evaluación en la consola de JavaScript
</p><p><img alt="JavaScript Console evaluating" fileid="0" src="File:es/Media_Gallery/Migrationguide-jsconsole-eval.jpg">
</p><p>El motor de JavaScript en Mozilla tiene integrado el soporte para la depuración convirtiéndose así en una potente herramienta para los desarrolladores de JavaScript. Venkman, mostrado en la figura 3, es un potente depurador multinavegador para JavaScript que se integra con Mozilla. Generalmente es empaquetado con los lanzamientos de Mozilla y puede ser encontrado en <b>Herramientas -&gt; Desarrollo web -&gt; Depurador Javascript</b>. En Firefox, el navegador no viene incluido. En lugar de eso, se puede descargar e instalar desde la <a class="external" href="http://www.mozilla.org/projects/venkman/">página del proyecto Venkman</a>. Además se pueden encontrar tutoriales en la página de desarrollo, ubicada en la <a class="external" href="http://www.hacksrus.com/%7Eginda/venkman/">página de desarrollo de Venkman</a>.
</p><p>Figura 3. Depurador de JavaScript de Mozilla
</p><p><img alt="Mozilla's JavaScript debugger" fileid="0" src="File:es/Media_Gallery/Migrationguide-venkman.jpg">
</p><p>El depurador de JavaScript puede depurar el código JavaScript que se ejecuta en la ventana del navegador de Mozilla. Soporta características estándar de depuración tales como puntos de interrupciones, revisión de la pila de llamadas e inspección de variables/objetos. Todas las caracterísitcas son accesibles a través de la interfaz de usuario y a través de la consola interactiva del depurador. Con la consola, se puede ejecutar código JavaScript arbitrario del mismo ámbito en el que JavaScript está siendo depurado.
</p>
<h3 name="Diferencias_en_CSS"> Diferencias en CSS </h3>
<p>Todos los productos basados en Mozilla poseen un fuerte soporte para CSS (hojas de estilo en cascada), en comparación con Internet Explorer y el resto de navegadores, ya que soportan la mayoría de CSS 1, CSS 2.1 y parte de CSS 3.
</p><p>Para la mayoría de los problemas que se mostrarán a continuación, Mozilla mostrará un aviso o un error en la consola JavaScript. Se aconseja comprobar la consola JavaScript si se encuentran problemas relacionados con CSS.
</p>
<h4 name="Tipos_MIME_.28cuando_no_se_aplican_a_los_ficheros_CSS.29"> Tipos MIME (cuando no se aplican a los ficheros CSS) </h4>
<p>El problema más común relacionado con CSS ocurre cuando las definiciones CSS que se hallan dentro de los ficheros CSS referenciados no se aplican. Esto generalmente se debe a que el servidor envía un tipo MIME incorrecto para el fichero CSS. La especificación CSS dice que los ficheros CSS deberían ser servidos con el tipo MIME <code>text/css</code>. Mozilla respetará esto y sólo cargará los ficheros CSS con ese tipo MIME si la página web está en modo estricto de estándares. Internet Explorer siempre cargará el fichero CSS sin importar el tipo MIME con el que haya sido servido. Se considera que las páginas web están en modo estricto de estándares cuando comienzan con un doctype (tipo de documento) estricto. Para solventar este problema, se puede optar por hacer que el servidor envíe el tipo MIME correcto o eliminando el doctype. Se explicarán más a fondo los doctypes en la siguiente sección.
</p>
<h4 name="CSS_y_las_unidades"> CSS y las unidades </h4>
<p>Muchas aplicaciones web no usan unidades en sus hojas CSS, especialmente cuando se usa JavaScript para establecer el CSS. Mozilla permite esto sólo si la página no se visualiza en modo estricto. Dado que Internet Explorer no soporta el auténtico XHTML, no se preocupa por saber si se han especificado o no las unidades. Si la página está en modo estricto de estándares y no se usan unidades entonces Mozilla ignorará dicho estilo.
</p>
<pre class="eval">&lt;DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "<span class="nowiki">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 y unidades - Ejemplo&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    // funciona en modo estricto
    &lt;div style="width: 40<span class="boldcode">px</span>; border: 1px solid black;"&gt;
      Text
    &lt;/div&gt;
</pre>
<pre class="eval">    // peta en modo estricto
    &lt;div style="width: 40; border: 1px solid black;"&gt;
      Text
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Debido a que el ejemplo de antes tiene un doctype estricto, la página se visualizará en modo estricto de estándares. El primer div tendrá una anchura de 40px dado que se han usado unidades, pero el segundo div no tendrá anchura definida y se le asignará aquella por defecto (100%). Pasaría lo mismo si se estableciese la anchura a través de JavaScript.
</p>
<h4 name="JavaScript_y_CSS">JavaScript y CSS</h4>
<p>Dado que Mozilla soporta los estándares CSS, también soporta el estándar DOM de CSS para poder establecer el estilo CSS a través de JavaScript. Se puede acceder a, eliminar y cambiar cualquier regla CSS de un elemento a través de su miembro <code>style</code>:
</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>Igualmente se puede acceder a cada atributo CSS de la misma forma. De nuevo, si la página web está en modo estricto, se debe establecer una unidad o, en caso contrario, Mozilla ignorará el comando. Cuando se consulte un valor, digamos <code>.style.width</code>, Mozilla e Internet Explorer devolverán una cadena de texto incluyendo la unidad. Se puede convertir dicha cadena en un número a través de <code>parseFloat("40px")</code>.
</p>
<h4 name="Diferencias_en_la_propiedad_CSS_overflow"> Diferencias en la propiedad CSS overflow </h4>
<p>Con CSS, se introduce el concepto de overflow que permite definir cómo se maneja el rebasamiento, por ejemplo, cuando la altura del contenido de un <code>div</code> es mayor que la altura del propio <code>div</code>. El estándar CSS indica que en caso de rebosamiento, si no se ha establecido dicho comportamiento, el contenido del <code>div</code> debe de rebosar.
</p><p>Sin embargo, Internet Explorer no cumple esto y alargará el <code>div</code> más allá de su altura hasta que pueda albergar correctamente su contenido. Más abajo hay un ejemplo que muestra esta diferencia:
</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>Como se puede apreciar en la figura 4, Mozilla reacciona como especifican los estándares del W3C. Dichos estándares dicen que, en este caso, el <code>div</code> interior debería rebosar por la parte inferior dado que su contenido es más alto que el de su padre. Si se prefiere utilizar el comportamiento de Internet Explorer, simplemente no habría que especificar ninguna altura para el elemento exterior.
</p><p>Figura 4. Rebosamiento DIV
</p><p><img alt="DIV Overflow" fileid="0" src="File:es/Media_Gallery/Migrationguide-overflow.jpg">
</p>
<h4 name="Diferencias_con_la_pseudoclase_:hover"> Diferencias con la pseudoclase :hover </h4>
<p>El comportamiento no estándar de la pseudoclase CSS :hover ocurre en un gran número de sitios web. Generalmente se manifiesta por sí mismo cambiando el estilo de texto cuando el cursor del ratón se sitúa sobre un elemento en Mozilla, pero no en Internet Explorer. Esto es así porque el selector CSS <code>a:hover</code> en Internet Explorer coincide con <code>&lt;a href=""&gt;...&lt;/a&gt;</code> pero no con <code>&lt;a name=""&gt;...&lt;/a&gt;</code>, el cual establece los anclajes en HTML. El cambio de texto ocurre porque los autores encapsulan áreas con el etiquetado de anclajes:
</p>
<pre>CSS:
  a:hover {color: green;}

HTML:
  &lt;a href="foo.com"&gt;Este texto debería volverse verde cuando el cursor del ratón se sitúe sobre él.&lt;/a&gt;

  &lt;a name="anchor-name"&gt;
    Este texto debería cambiar el color cuando fuese sobrevolado con el cursor pero no ocurre en Internet Explorer.
  &lt;/a&gt;
</pre>
<p>Mozilla sigue la especificación CSS correctamente y cambiará el color a verde en este ejemplo. Se pueden utilizar dos formas para que Mozilla se comporte como Internet Explorer y no cambie el color del texto cuando éste sea sobrevolado:
</p>
<ul><li>Primero, se puede cambiar la regla CSS para que sea <code>a:link:hover {color: green;}</code>, lo que provocará que sólo se cambie el color si un elemento es un enlace (tiene un atributo <code>href</code>).
</li><li>Alternativamente, es posible cambiar el marcado y cerrar la <code>&lt; a/&gt;</code> abierta antes de que empiece el texto; el anclaje continuará funcionando de este modo.
</li></ul>
<h3 name="Modo_quirks_vs._modo_est.C3.A1ndar">Modo quirks vs. modo estándar</h3>
<p>Los antiguos navegadores, como Internet Explorer 4, visualizaban los documentos bajo ciertas condiciones con el llamado modo quirks (modo chapucero). Aunque Mozilla apunta a convertirse en un navegador respetuoso con los estándares, posee 3 modos que permiten soportar las antiguas páginas creadas para comportarse de ese modo tan peculiar. El contenido de la página y la forma en la que nos es enviada determinan el modo que Mozilla debe de utilizar. Mozilla muestra dicho modo en <b>Ver -&gt; Información de página</b> (o <kbd>Ctrl+I</kbd>) y Firefox lo hace en <b>Herramientas -&gt; Información de la página</b>. El modo en el que una página es visualizada depende de su doctype.
</p><p>Los doctypes (contracción inglesa para las declaraciones de tipos de documento) tiene este aspecto:
</p><p><code>&lt;!DOCTYPE HTML PUBLIC <span style="color: blue;">"-//W3C//DTD HTML 4.01 Transitional//EN"</span> <span style="color: green;">"<span class="nowiki">http://www.w3.org/TR/html4/loose.dtd</span>"</span>&gt;</code>
</p><p>La parte azul es llamada identificador público, la verde es el identificador de sistema que es un URI.
</p>
<h4 name="Modo_est.C3.A1ndar"> Modo estándar </h4>
<p>El modo estándar es el modo de visualización más estricto: visualizará las páginas según las especificaciones HTML y CSS del W3C y no permitirá ninguna chapuza.
Mozilla lo usa bajo las siguientes condiciones:
</p>
<ul><li>Cuando una página es enviada con un tipo MIME igual a <code>text/xml</code> o cualquier otro tipo MIME XML o XHTML.
</li><li>Con cualquier doctype "DOCTYPE HTML SYSTEM" (por ejemplo, <code>&lt;!DOCTYPE HTML SYSTEM "<span class="nowiki">http://www.w3.org/TR/REC-html40/strict.dtd</span>"&gt;</code>), exceptuando el doctype de IBM
</li><li>Cuando se especifique un doctype desconocido o éste no esté asociado a un DTD.
</li></ul>
<h4 name="Modo_casi_est.C3.A1ndar"> Modo <i>casi</i> estándar </h4>
<p>Mozilla introdujo el modo <i>casi</i> estándar por una razón: una sección en la especificación CSS 2 daba al traste con los diseños que se basaban en la maquetación con tablas que contenían pequeñas imágenes. El usuario, en lugar de ver una imagen completa, veía cada imagen separada con un pequeño espacio en blanco. La antigua página de IBM mostrada en la figura 5 es un ejemplo de ello.
</p><p>Figura 5. Hueco en imágenes
</p><p><img alt="Image Gap" fileid="0" src="File:es/Media_Gallery/Migrationguide-imagegap.jpg">
</p><p>El modo <i>casi</i> estándar se comporta de modo muy parecido al modo estándar exceptuando el problema del hueco en imágenes. Este problema ocurre frecuentemente en páginas diseñadas acorde a los estándares y hace que se muestren incorrectamente.
</p><p>Mozilla utiliza el modo <i>casi</i> estándar bajo las siguientes condiciones:
</p>
<ul><li>Ante cualquier doctype de tipo "loose" (obsoleto), por ejemplo <code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"&gt;</code>, <code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<span class="nowiki">http://www.w3.org/TR/html4/loose.dtd</span>"&gt;</code>
</li><li> Para el doctype de IBM (<code>&lt;!DOCTYPE html SYSTEM "<span class="nowiki">http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd</span>"&gt;</code>)
</li></ul>
<p>Para más información, véase el <a href="es/Im%c3%a1genes%2c_tablas_y_huecos_misteriosos">problema de los huecos con imágenes</a>
</p>
<h4 name="Modo_quirks"> Modo quirks </h4>
<p>Actualmente, el web está plagado de sitios con HTML no válido, además de marcado que sólo funciona gracias a fallos de ciertos navegadores. Los antiguos navegadores de Netscape, cuando eran los amos del mercado, tenían fallos. Cuando desembarcó Internet Explorer, plagió esos mismos fallos para poder visualizar correctamente las páginas de aquella época. Más tarde cuando los nuevos navegadores llegaron al mercado, la mayoría de estos fallos originales, usualmente llamados <b>quirks</b>, fueron mantenidos por razones de compatibilidad hacia atrás.
Mozilla soporta muchos de estos fallos cuando visualiza páginas en modo quirks. Nótese que debido a estos quirks, las páginas se visualizan más lentamente que si estuvieran escritas para respetar los estándares. La mayoría de las páginas web son visualizadas utilizando este modo.
</p><p>Mozilla utiliza este modo cuando encuentra las siguientes condiciones:
</p>
<ul><li>Cuando no se ha especificado un doctype.
</li><li>Cuando se ha especificado un doctype sin su identificador de sistema (por ejemplo, &lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;&lt;/code&gt;)
</li></ul>
<p>Para más información, véase <a href="es/Mozilla_Quirks_Mode_Behavior">Mozilla Quirks Mode Behavior</a> and <a href="es/Mozilla's_DOCTYPE_sniffing">Mozilla's DOCTYPE sniffing</a>.
</p>
<h3 name="Diferencias_en_eventos">Diferencias en eventos</h3>
<p>Mozilla e Internet Explorer son prácticamente incompatibles en cuanto al manejo de eventos se refiere. El modelo de eventos de Mozilla sigue al del W3C y al de Netscape. En Internet Explorer, si una función es llamada desde un evento, se puede acceder al objeto <code>event</code> a través de <code>window.event</code>. En cambio Mozilla pasa un objeto <code>event</code> a los manejadores de eventos. Éstos deben de pasar específicamente el objeto a la función llamada a través de un argumento. A continuación se muestra un ejemplo multiplataforma de manejador de evento:
</p>
<pre>&lt;div onclick="handleEvent(event);"&gt;Click me!&lt;/div&gt;

&lt;script&gt;
  function handleEvent(evento) { 
    // if evento es null, significa que es el modelo de eventos de IE
    // así que se utiliza window.event
    var miEvento = evento ? evento : window.event; 
  }
&lt;/script&gt;
</pre>
<p>A veces, esto no funciona ya que Internet Explorer <i>coge</i> el parámetro <code>evento</code>, identificándolo como no nulo, lo que en el códico provoca que no se pueda asignar window.event. La solución consiste en comprobar la propiedad window.event:
</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>Las propiedades y funciones que el objeto <code>event</code> muestra son nombradas con frecuencia de forma diferente entre Mozilla e Internet Explorer, como muestra la tabla 4:
</p>
<table class="standard-table">
<caption> Tabla 4. Diferencias entre las propiedades de eventos entre Mozilla e Internet Explorer
</caption><tbody><tr>
<th> Nombre en Internet Explorer </th><th> Nombre en Mozilla </th><th> Descripción
</th></tr>
<tr>
<td> altKey </td><td> altKey
</td><td> Propiedad booleana que indica si la tecla <kbd>alt</kbd> estaba pulsada durante el evento.
</td></tr>
<tr>
<td> cancelBubble </td><td> stopPropagation()
</td><td> Usado para evitar que el evento sea propagado hacia los elementos ancestros en el árbol.
</td></tr>
<tr>
<td> clientX </td><td> clientX
</td><td> Coordenada X del evento, relativa al viewport.
</td></tr>
<tr>
<td> clientY </td><td> clientY
</td><td> Coordenada Y del evento, relativa al viewport.
</td></tr>
<tr>
<td> ctrlKey </td><td> ctrlKey
</td><td> Propiedad booleana que indica si la tecla <kbd>Ctrl</kbd> estaba pulsada durante el evento.
</td></tr>
<tr>
<td> fromElement </td><td> relatedTarget
</td><td> Para eventos de ratón, es el elemento desde el que partió el cursor del ratón.
</td></tr>
<tr>
<td> keyCode </td><td> keyCode
</td><td> Para eventos de teclado, es el número que representa a la tecla que estaba pulsada. 0 para los eventos de ratón.
</td></tr>
<tr>
<td> returnValue </td><td> preventDefault()
</td><td> Usado para evitar que se ejecute la acción por defecto del evento.
</td></tr>
<tr>
<td> screenX </td><td> screenX
</td><td> Coordenada X del evento, relativa a la pantalla.
</td></tr>
<tr>
<td> screenY </td><td> screenY
</td><td> Coordenada Y del evento, relativa a la pantalla.
</td></tr>
<tr>
<td> shiftKey </td><td> shiftKey
</td><td> Propiedad booleana que indica si la tecla <kbd>shift</kbd> estaba pulsada durante el evento.
</td></tr>
<tr>
<td> srcElement </td><td> target
</td><td> El elemento que provocó el evento.
</td></tr>
<tr>
<td> toElement </td><td> currentTarget
</td><td> Para eventos de ratón, es el elemento al que el ratón se dirigió cuando terminó el mismo.
</td></tr>
<tr>
<td> type </td><td> type
</td><td> Devuelve el nombre del evento.
</td></tr></tbody></table>
<h4 name="A.C3.B1adir_manejadores_de_eventos"> Añadir manejadores de eventos </h4>
<p>Mozilla posee dos formas de añadir eventos a través de JavaScript. El primero, soportado por todos los navegadores, consiste en establecer propiedades de eventos directamente en los objetos. Para asignar un manejador de evento al evento <code>click</code> hay que pasar una referencia a dicha función manejadora a la propiedad <code>onclick</code> del objeto.
</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 soporta al 100% la forma estándar del W3C para añadir <i>escuchadores</i> a los nodos del DOM: usando los métodos <code>addEventListener()</code> y <code>removeEventListener()</code>; y además con el beneplácito de poder añadir múltiples escuchadores para un mismo tipo de evento.
Ambos métodos necesitan tres parámetros: el tipo de evento, una referencia a la función y un valor booleano que indica si el escuchador debe de capturar los eventos en su fase <i>captura</i>. Si el booleano es puesto a false, sólo capturará los eventos en la fase <i>burbuja</i>. Los eventos del W3C tienen tres fases: captura, objetivo y burbuja. Cada objeto <code>event</code> tiene un atributo <code>eventPhase</code> que indica la fase en la que se encuentra el evento mediante un número de base 0.
Cuando se provoca un evento, éste comienza en el elemento más externamente situado del DOM, o sea, en el elemento superior del árbol DOM. Luego va atravesando el DOM usando el camino más corto hacia el objetivo. Estamos en la fase de <b>captura</b>. Cuando el evento alcanza al objetivo, el evento está en la fase <b>objetivo</b>. Tras alcanzar el objetivo, regresa por el árbol hasta alcanzar de nuevo el nodo más exteriormente situado. Esta es la fase <b>burbuja</b>. El modelo de eventos de Internet Explorer sólo tiene la fase burbuja por lo que estableciendo el tercer parámetro a false se conseguirá un comportamiento igual al de Internet Explorer.
</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>Una ventaja de <code>addEventListener()</code> y <code>removeEventListener()</code> sobre asignar las propiedades es que se pueden tener múltiples escuchadores de eventos para el mismo evento, cada cual llamando a una función diferente. Así, para eliminar un escuchador de evento se necesita que los tres parámetros sean los mismos que se usaron para añadir el escuchador.
</p><p>Mozilla no soporta el método de Internet Explorer de convertir etiquetas &lt;script&gt; en manejadores de eventos, la cual amplía a &lt;script&gt; con los atributos <code>for</code> y <code>event</code> (véase tabla 5). Tampoco suporta los métodos <code>attachEvent</code> ni <code>detachEvent</code>. En vez de eso, se deberían de usar los métodos <code>addEventListener</code> y <code>removeEventListener</code>. Internet Explorer no soporta la especificación de eventos del W3C.
</p>
<table class="standard-table">
<caption> Tabla 5. Diferencias en los métodos de eventos entre Mozilla e Internet Explorer
</caption><tbody><tr>
<th> Método de Internet Explorer </th><th> Método de Mozilla </th><th> Descripción
</th></tr>
<tr>
<td> attachEvent(tipoEvento, referenciaFuncion)
</td><td> addEventListener(tipoEvento, referenciaFuncion, usarCaptura)
</td><td> Añade un manejador de evento a un elemento del DOM
</td></tr>
<tr>
<td> detachEvent(tipoEvento, referenciaFuncion)
</td><td> removeEventListener(tipoEvento, referenciaFuncion, usarCaptura)
</td><td> Elimina un manejador de evento a un elemento del DOM
</td></tr></tbody></table>
<h3 name="Edici.C3.B3n_de_texto_enriquecido">Edición de texto enriquecido</h3>
<p>Aunque Mozilla está orgulloso de ser el navegador más compatible con los estándares del W3C, sigue soportando funcionalidades no estándar, tales como <code>innerHTML</code> o <a href="es/Midas">editores de texto enriquecido</a>, al no existir los equivalentes del W3C.
</p><p>Con Mozilla 1.3 se introdujo una implementación de la característica <a href="es/Rich-Text_Editing_in_Mozilla/Class_xbDesignMode">designMode</a> de Internet Explorer, la cual convierte a un documento HTML en un editor de texto enriquecido.
</p><p>Una vez se ha cambiado al editor, los comandos pueden ser ejecutados en el documento a través del comando <code>execCommand</code>. Mozilla no soporta el atributo <code>contentEditable</code> de Internet Explorer para hacer editable cualquier control. Se puede usar un <code>iframe</code> para crear un editor de texto enriquecido.
</p>
<h4 name="Diferencias_en_el_texto_enriquecido"> Diferencias en el texto enriquecido </h4>
<p>Mozilla soporta el método estándar del W3C para acceder al objeto <code>document</code> del iframe a través de <code>IFrameElmRef.contentDocument</code> mientras que Internet Explorer lo hace a través de <code>document.frames{{ mediawiki.external('\"IframeName\"') }}</code> y luego accede al <code>document</code> resultante.
</p>
<pre>&lt;script&gt;
function getIFrameDocument(aID) {
  var rv = null; 

  // if contentDocument existe, entonces es compatible con el W3C (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>Otra diferencia entre Mozilla e Internet Explorer es el HTML que crea el editor de texto enriquecido. Por defecto, Mozilla usa CSS para generar marcado. Sin embargo, Mozilla permite alternar entre el modo HTML y CSS usando el comando <code>useCSS</code> del execCommand cambiándolo entre true y false. Internet Explorer siempre usa el marcado HTML.
</p>
<pre>Mozilla (CSS): 
  &lt;span style="color: blue;"&gt;Azul&lt;/span&gt; 

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

Internet Explorer: 
  &lt;FONT color="blue"&gt;Azul&lt;/FONT&gt; 
</pre> <p>Más abajo hay una lista de comandos soportados por execCommand en Mozilla:
</p>
<table class="standard-table">
<caption> Tabla 6. Comandos del editor de texto enriquecido.
</caption><tbody><tr>
<th> Nombre </th><th> Descripción </th><th> Argumentos
</th></tr>
<tr>
<td> bold </td><td> Alterna el modo en negrita de la selección. </td><td> ---
</td></tr>
<tr>
<td> createlink </td><td> Genera un enlace HTML a partir del texto seleccionado. </td><td> URL a usar para el enlace
</td></tr>
<tr>
<td> delete </td><td> Borra la selección. </td><td> ---
</td></tr>
<tr>
<td> fontname </td><td> Cambia la fuente del texto seleccionado. </td><td> Nombre de la fuente (por ejemplo, Arial)
</td></tr>
<tr>
<td> fontsize </td><td> Cambia el tamaño del texto seleccionado. </td><td> Tamaño de la fuente
</td></tr>
<tr>
<td> fontcolor </td><td> Cambia el color de la fuente del texto seleccionado. </td><td> Color a usar
</td></tr>
<tr>
<td> indent </td><td> Indenta el bloque donde el se encuentra el cursor. </td><td> ---
</td></tr>
<tr>
<td> inserthorizontalrule </td><td> Inserta un elemento &lt;hr&gt; en la posición del cursor. </td><td> ---
</td></tr>
<tr>
<td> insertimage </td><td> Inserta una imagen en la posición del cursor. </td><td> URL de la imagen
</td></tr>
<tr>
<td> insertorderedlist </td><td> Inserta un elemento de lista ordeanda (&lt;ol&gt;) en la posición del cursor. </td><td> ---
</td></tr>
<tr>
<td> insertunorderedlist </td><td> Inserta un elemento de lista no ordenada (&lt;ul&gt;) en la posición del cursor. </td><td> ---
</td></tr>
<tr>
<td> italic </td><td> Alterna el modo en cursiva de la selección. </td><td> ---
</td></tr>
<tr>
<td> justifycenter </td><td> Centra el contenido de la línea actual. </td><td> ---
</td></tr>
<tr>
<td> justifyleft </td><td> Alinea el contenido de la línea actual a la izquierda. </td><td> ---
</td></tr>
<tr>
<td> justifyright </td><td> Alinea el contenido de la línea actual a la derecha. </td><td> ---
</td></tr>
<tr>
<td> outdent </td><td> Elimina la indentación del bloque donde se halla el cursor. </td><td> ---
</td></tr>
<tr>
<td> redo </td><td> Rehace el anterior comando deshecho. </td><td> ---
</td></tr>
<tr>
<td> removeformat </td><td> Elimina todo el formato de la selección. </td><td> ---
</td></tr>
<tr>
<td> selectall </td><td> Selecciona todo el texto del editor. </td><td> ---
</td></tr>
<tr>
<td> strikethrough </td><td> Alterna el modo tachado del texto seleccionado. </td><td> ---
</td></tr>
<tr>
<td> subscript </td><td> Convierte la selección actual a subíndice. </td><td> ---
</td></tr>
<tr>
<td> superscript </td><td> Convierte la selección actual a superíndice. </td><td> ---
</td></tr>
<tr>
<td> underline </td><td> Alterna el modo subrayado del texto seleccionado. </td><td> ---
</td></tr>
<tr>
<td> undo </td><td> Deshace el último comando ejecutado. </td><td> ---
</td></tr>
<tr>
<td> unlink </td><td> Elimina toda la información sobre enlaces de la selección. </td><td> ---
</td></tr>
<tr>
<td> useCSS </td><td> Alterna el uso de CSS en el marcado generado. </td><td> Valor booleano
</td></tr></tbody></table>
<p>Para más información, véase <a href="es/Rich-Text_Editing_in_Mozilla">Rich-Text Editing in Mozilla</a>
</p>
<h3 name="Diferencias_en_XML"> Diferencias en XML </h3>
<p>Mozilla posee un fuerte soporte para XML y todas sus tecnologías relacionadas, tales como XSLT y servicios web. Además soporta algunas extensiones no estándar de Internet Explorer, tales como XMLHttpRequest.
</p>
<h4 name="C.C3.B3mo_manejar_XMLs"> Cómo manejar XMLs </h4>
<p>Al igual que ocurre con el estándar HTML, Mozilla soporta la especificación del DOM para XML del W3C, la cual permite manipular prácticamente cualquier aspecto de cualquier documento XML.
Las diferencias entre el DOM para XML de Internet Explorer y Mozilla son provocadas por el comportamiento no estándar de Internet Explorer. Probablemente la diferencia más común es cómo ambos manejan los espacios en blanco en los nodos de texto. Con frecuencia cuando se genera un XML, contiene espacios en blanco entre los nodos XML. Internet Explorer, cuando usa <code>XMLNode.childNodes[]</code> no contendrá estos nodos de espacios en blanco. En Mozilla, estos nodos se incluirán en el vector.
</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>La primera línea de JavaScript carga el documento XML y accede a su elemento ráiz (<code>myXMLDoc</code>) recuperando el <code>documentElement</code>. La segunda línea simplemente muestra el número de nodos hijos. Para la especificación del W3C, los espacios en blanco y los retornos de carro se unen bajo un nodo de texto si uno es seguido del otro. Para Mozilla, el nodo <code>myXMLdoc</code> tiene tres hijos: un nodo de texto que contiene un retorno de carro y dos espacios, el nodo <code>myns:foo</code>, y otro nodo de texto con un retorno de carro. No obstante, Internet Explorer no obedece esto y devolverá "1" para el anterior código, considerando sólamente el nodo <code>myns:foo</code>
Por elli, para recorrer los nodos hijos y desechar los nodos de texto se deben distinguir tales nodos del resto.
</p><p>Como se mencionó antes, cada nodo tiene un atributo <code>nodeType</code> que representa el tipo de nodo. Por ejemplo, un nodo elemento tiene tipo 1 mientras que un nodo documento posee tipo 9. Para distinguir los nodos de texto se deben buscar los nodos de tipo 3 (nodos de texto) y los de tipo 8 (nodos comentario).
</p>
<pre>XML:
  &lt;?xml version="1.0"?&gt;   
  &lt;myXMLdoc xmlns:myns="http://myfoo.com"&gt; 
    &lt;myns:foo&gt;bar&lt;/myns:foo&gt; 
  &lt;/myXMLdoc&gt;

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

  for (var run = 0; run &lt; myChildren.length; run++){ 
    if ( (myChildren[run].nodeType != 3) &amp;&amp;
          myChildren[run].nodeType != 8) ){ 
      // not a text or comment node 
    };
  };
</pre>
<h4 name="Islas_de_datos_XML">Islas de datos XML</h4>
<p>Internet Explorer posee una peculiaridad no estándar llamada <em>islas de datos XML (XML data islands)</em>, que permite incrustar XML dentro de un documento HTML usando la etiqueta HTML no estándar <code>&lt;xml&gt;</code>. Mozilla no soporta las islas de datos XML y las maneja como etiquetas HTML desconocidas. Se puede obtener la misma funcionalidad utilizando XHTML, sin embargo, debido a que el soporte de Internet Explorer para XHTML es débil, esto no es generalmente una opción.
</p><p>Una solución multiplataforma es usar analizadores DOM que generan, a partir de un documento XML serializado, el documento XML analizado. Mozilla usa la clase <code>DOMParser</code> la cual toma una cadena serializada crea un documento XML a partir de ella. En Internet Explorer se puede obtener la misma funcionalidad usando ActiveX. El nuevo <code>Microsoft.XMLDOM</code> genera y posee el método un método llamado <code>loadXML</code> que acepta una cadena de texto y genera un documento a partir de ella. El siguiente código muestra su funcionamiento:
</p><p><br>
</p>
<pre>Isla de datos XML para IE
  .. 
  &lt;xml id="xmldataisland"&gt; 
    &lt;foo&gt;bar&lt;/foo&gt; 
  &lt;/xml&gt;

Solución multiplataforma: 
  var xmlString = "&lt;xml id=\"xmldataisland\"&gt;&lt;foo&gt;bar&lt;/foo&gt;&lt;/xml&gt;"; 

  var myDocument; 

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

    myDocument.loadXML(xmlString);
  }
</pre>
<h4 name="Peticiones_HTTP_para_XML"> Peticiones HTTP para XML </h4>
<p>Internet Explorer permite el envío y recuperación de ficheros XML usando la clase de MSXML <code>XMLHTTP</code>, instanciada a través de ActiveX usando <code>new ActiveXObject("Msxml2.XMLHTTP")</code> o <code>new ActiveXObject("Microsoft.XMLHTTP")</code>. Dado que no hay un método estándar para hacer esto, Mozilla proporciona la misma funcionalidad en el objeto global <code>XMLHttpRequest</code> de JavaScript. El objeto genera peticiones asíncronas de modo predeterminado.
</p><p>Tras instanciar el objeto usando <code>new XMLHttpRequest()</code> se puede usar el método <code>open</code> para especificar qué tipo de petición (GET o POST) se quiere usar, qué fichero se va a cargar y si será una petición asíncrona o no. Si la llamada es asíncrona, será necesario facilitar al miembro <code>onload</code> una referencia a una función que será invocada una vez la petición ha sido completada.
</p><p>Petición síncrona:
</p>
<pre class="eval">  var myXMLHTTPRequest = new XMLHttpRequest(); 
  myXMLHTTPRequest.open("GET", "data.xml", false); 

  myXMLHTTPRequest.send(null); 

  var myXMLDocument = myXMLHTTPRequest.responseXML; 
</pre>
<p>Petición asíncrona: </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>La tabla 7 muestra una lista de métodos y propiedades disponibles para el objeto <code>XMLHttpRequest</code> de Mozilla.
</p>
<table class="standard-table">
<caption>Tabla 7. Métodos y propiedades XMLHttpRequest</caption> <tbody><tr> <th>Nombre</th> <th>Descripción</th> </tr> <tr> <td>void abort()</td> <td>Detiene la petición si ésta aún está en curso.</td> </tr> <tr> <td>string getAllResponseHeaders()</td> <td>Devuelve todas las cabeceras de respuesta como una única cadena.</td> </tr> <tr> <td>string getResponseHeader(string headerName)</td> <td>Devuelve el valor de la cabecera especificada.</td> </tr> <tr> <td>functionRef onerror</td> <td>La función que se le asigne será invocada cuando ocurran errores durante una petición.</td> </tr> <tr> <td>functionRef onload</td> <td>La función que se le asigne será invocada cuando la petición se complete con éxito y se haya recibido una respuesta. Se usa con las peticiones asíncronas.</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>Inicializa la petición para la URL especificada, usando tanto GET o POST como el método HTTP. Para enviar la petición, es necesario llamar al método <code>send()</code> tras la inicialización. Si <code>async</code> se establece a false, la petición será síncrona. De modo predeterminado es asíncrona. Opcionalmente se puede especificar un nombre de usuario y contraseña por si la necesita la URL facilitada.
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>Estado de la petición. Valores posibles: <table> <tbody><tr> <th>Valor</th> <th>Descripción</th> </tr> <tr> <td>0</td> <td>UNINITIALIZED - open() aún no ha sido llamado.</td> </tr> <tr> <td>1</td> <td>LOADING - send() aún no ha sido llamado.</td> </tr> <tr> <td>2</td> <td>LOADED - send() ha sido llamado y las cabeceras y el estado están disponibles.</td> </tr> <tr> <td>3</td> <td>INTERACTIVE - Descargando. responseText contiene datos parciales.</td> </tr> <tr> <td>4</td> <td>COMPLETED - Todas las operaciones han sido completadas.</td> </tr> </tbody></table></td> </tr> <tr> <td>string responseText</td> <td>Cadena que contiene la respuesta.</td> </tr> <tr> <td>DOMDocument responseXML</td> <td>Documento DOM que contiene la respuesta.</td> </tr> <tr> <td>void send(variant body)</td> <td>Realiza la petición. Si <code>body</code> está definido, será enviado como el cuerpo de la petición POST. <code>body</code> puede ser un documento XML o una cadena conteniendo un XML serializado.</td> </tr> <tr> <td>void setRequestHeader (string headerName, string headerValue)</td> <td>Establece una cabecera de petición HTTP para usarla en la petición HTTP. Ha de ser llamada tras invocar al método <code>open()</code>.</td> </tr> <tr> <td>string status</td> <td>El código de estado de la respuesta HTTP.</td> </tr>
</tbody></table>
<h4 name="Diferencias_en_XSLT"> Diferencias en XSLT </h4>
<p>Mozilla soporta las transformaciones XSL 1.0 (XSLT). Además permite a JavaScript realizar tanto transformaciones XSLT como consultas XPath sobre un documento.
</p><p>Mozilla necesita que se le pase el fichero XML y XSLT que contiene la hoja de estilos con un tipo MIME XML (<code>text/xml</code> o <code>application/xml</code>). Este es el motivo más común por el cual los XSLT no funcionan en Mozilla pero sí en Internet Explorer. En ese sentido, Mozilla es estricto.
</p><p>Internet Explorer 5.0 y 5.5 soportan el borrador de XSLT, el cual es sustancialmente diferente a la recomendación final 1.0. La forma más fácil de distinguir la versión en la que ha sido escrito un fichero XSLT es mirando su espacio de nombres. El espacio de nombres para la recomendación 1.0 es <code><span class="nowiki">http://www.w3.org/1999/XSL/Transform</span></code> mientras que el espacio de nombres del borrador es <code><span class="nowiki">http://www.w3.org/TR/WD-xsl</span></code>. Internet Explorer 6 soporta el borrador por razones de compatibilidad hacia atrás. Mozilla no soporta dicho borrador, sólo la recomendación final.
</p><p>Si el XSLT necesita distinguir el navegador, se puede consultar la propiedad de sistema "xsl:vendor". El motor XSLT de Mozilla devolverá "Transformiix" mientras que Internet Explorer devolverá "Microsoft".
</p>
<pre>&lt;xsl:if test="system-property('xsl:vendor') = 'Transformiix'"&gt; 
  &lt;!-- Marcado específico de Mozilla --&gt; 
&lt;/xsl:if&gt; 
&lt;xsl:if test="system-property('xsl:vendor') = 'Microsoft'"&gt; 
  &lt;!-- Marcado específico de Internet Explorer --&gt; 
&lt;/xsl:if&gt; 
</pre>
<p>Mozilla también proporciona una interfaz de JavaScript para XSLT, permitiendo a un sitio web completar transformaciones XSLT en memoria. Esto puede hacerse usando el objeto global de JavaScript <code>XSLTProcessor</code>. <code>XSLTProcessor</code> necesita que se carge el XML y los ficheros XSLT ya que necesita sus documentos DOM. El documento XSLT importado por <code>XSLTProcessor</code> permite manipular los parámetros XSLT. <code>XSLTProcessor</code> puede generar un documento independiente utilizando <code>transformToDocument()</code> o puede crear un fragmento de documento utilizando <code>transformToFragment()</code> para poder ser anexado fácilmente a otro documento DOM. Más abajo se muestra un ejemplo:
</p>
<pre>var xslStylesheet; 
var xsltProcessor = new XSLTProcessor(); 

// carga el fichero XSLT example1.xsl 
var myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xsl", false); 
myXMLHTTPRequest.send(null); 

// obtiene el documento XML y lo importa
xslStylesheet = myXMLHTTPRequest.responseXML; 

xsltProcessor.importStylesheet(xslStylesheet); 

// carga el fichero xml 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>Tras crear un objeto <code>XSLTProcessor</code>, hay que cargar el fichero XSLT a través de <code>XMLHttpRequest</code>. El miembro <code>responseXML</code> del XMLHttpRequest contiene el documento XML del fichero XSLT, el cuas es pasado a <code>importStylesheet</code>. Luego hay que usar de nuevo <code>XMLHttpRequest</code> para cargar el documento XML que va a ser transformado. Ese documento es entonces pasado al método <code>transformToDocument</code> de <code>XSLTProcessor</code>. La tabla 8 muestra una lista con los métodos de <code>XSLTProcessor</code>. </p>
<table class="standard-table">
<caption>Tabla 8. Métodos de XSLTProcessor</caption> <tbody><tr> <th>Método</th> <th>Descripción</th> </tr> <tr> <td>void importStylesheet(Node styleSheet)</td> <td>Importa la hoja de estilo XSLT. El argumento <code>styleSheet</code> es el nodo ráiz del documento DOM de la hoja de estilos XSLT.</td> </tr> <tr> <td>DocumentFragment transformToFragment(Node source, Document owner)</td> <td>Transforma el nodo <code>source</code> aplicando la hoja de estilos importada con el método <code>importStylesheet</code> y genera un DocumentFragment. <code>owner</code> especifica a qué documento DOM debe anexarse el DocumentFragment, haciéndolo compatible con ese documento DOM.</td> </tr> <tr> <td>Document transformToDocument(Node source)</td> <td>Transforma el nodo <code>source</code> aplicando la hoja de estilos importada a través del método <code>importStylesheet</code> y devuelve un documento DOM independiente.</td> </tr> <tr> <td>void setParameter(String namespaceURI, String localName, Variant value)</td> <td>Establece un parámetro en la hoja de estilos XSLT importada.</td> </tr> <tr> <td>Variant getParameter(String namespaceURI, String localName)</td> <td>Obtiene el valor de un parámetro en la hoja de estilos XSLT importada.</td> </tr> <tr> <td>void removeParameter(String namespaceURI, String localName)</td> <td>Elimina todos los parámetros establecidos para la hoja de estilos XSLT importada y establece sus valores a los predeterminados para el XSLT.</td> </tr> <tr> <td>void clearParameters()</td> <td>Elimina todos los parámetros establecidos y establece sus valores a los predeterminados en la hoja de estilos XSLT.</td> </tr> <tr> <td>void reset()</td> <td>Elimina todos los parámetros y hojas de estilos.</td> </tr>
</tbody></table>
<div class="originaldocinfo">
<h3 name="Original_Document_Information"> Original Document Information </h3>
<ul><li> Author(s): Doron Rosenberg, IBM Corporation
</li><li> Published: 26 Jul 2005
</li><li> Link: <a class=" external" href="http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/" rel="freelink">http://www-128.ibm.com/developerwork...y/wa-ie2mozgd/</a>
</li></ul>
</div>
<p><br>
</p>
<div class="noinclude">
</div>
{{ languages( { "en": "en/Migrate_apps_from_Internet_Explorer_to_Mozilla", "fr": "fr/Migration_d\'applications_d\'Internet_Explorer_vers_Mozilla", "ko": "ko/Migrate_apps_from_Internet_Explorer_to_Mozilla", "zh-cn": "cn/\u4eceInternet_Explorer\u8fc1\u79fb\u5230Mozilla", "zh-tw": "zh_tw/\u8f49\u63db\u7db2\u9801\u7a0b\u5f0f\uff1a\u5f9e_IE_\u5230_Mozilla" } ) }}
Revertir a esta revisión