comment
IRC Chat
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

[JavaScript][AVANZADO] Trabajar con DOM desde Firefox e Internet Explorer

  • 0 Respuestas
  • 1563 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado arthusu

  • *
  • Underc0der
  • Mensajes: 546
  • Actividad:
    8.33%
  • Reputación 2
  • Yo solo se que no se nada - Socrátes
    • Ver Perfil
    • Arthusu BLOG
  • Skype: arthusuxD
« en: Julio 16, 2011, 07:05:12 pm »


Para un proyecto del trabajo me veo submergido en la creación dinámica de el contenido de una página web. Para realizar este trabajo, me decanté a trabajar con DOM accediendo via Javascript. Sé que existen librerías muy completas crossbrowser que realizan fácilmente el trabajo requerido, soltando código compatible para (casi) todos los navegadores, pero yo soy de ésos que prefiere jugar a un nivel más bajo (siempre que no se me compliquen las cosas en exceso).

Sabiendo que Firefox respeta mejor los estándares que Internet Explorer, llevo ya la costumbre de desarrollar para Firefox y luego adecuar el código para que funcione para Internet Explorer... pero esta vez la cosa se me ha ido de las manos...

He encontrado varios problemas relacionados con las diferencias en que el DOM es tratado por ambos navegadores, con lo que he podido observar con mis propios ojos que no siempre Firefox respeta el estándar o que la forma de trabajar de Internet Explorer acaba siendo muy sui-generis.

En este artículo presento un ejemplo básico: una página con un DIV que sirve como base para que un código Javascript monte una tabla "modelo" mediante DOM, para ilustrar las diferencias que he encontrado.

Introducción

Primero de todo, deberíamos empezar por generar nuestra página base que va a soportar toda la mecánica de DOM / Javascript que vamos a montar. Voy a proponer una estructura sencilla:
Código: HTML5
  1.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  2.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  3.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>Ejemplo de DOM</No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  4.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  5.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  6.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>Comenzar</No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  7.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta id="enlace"></No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  8.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  9.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>

Ok, con ésto tenemos ya una página normal válida con un div que nos servirá como enlace, es decir, todo lo que hagamos lo añadiremos a este DIV. Además, tenemos un SPAN que usaremos como botón para comenzar el proceso.

Vale, empecemos. Necesitamos teclear Javascript, así que necesitamos crear un espacio para él. Lo vamos a meter dentro del HEAD, justo debajo del TITLE:
Código: HTML5
  1.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  2.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>Ejemplo de DOM</No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  3.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta language="JavaScript">
  4.      
  5.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  6.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  7.  

Entonces, vamos a hacer que el SPAN sea el evento que empiece todo el proceso. Para ello, le pondremos unos atributos y algun estilo para que se nos presente como un link:

Código: HTML5
  1.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta style="cursor:pointer; text-decoration: underline;" onclick="javascript:dibujarTabla();">Comenzar</No tienes permisos para ver links. Registrate o Entra con tu cuenta>

Con ello tendremos que el texto "Comenzar" estará subrayado y al poner el ratón encima el puntero cambiará al famoso dedo. Además, le hemos dicho que cuando éste sea clicado ejecute una función Javascript llamada "dibujarTabla". Así que ahora tenemos que escribir una función dentro del espacio Javascript que hemos creado en el HEAD. Yo siempre empiezo con un alert() para comprobar que de momento todo funciona. Luego lo quitaremos, eh?:

 
Código: Javascript
  1.    function dibujarTabla()
  2.     {
  3.     alert('Parece que funciona');
  4.     }
  5.  

Al ejecutar la página, si clicamos en el texto subrayado nos saldrá una ventanita de diálogo con el texto "Parece que funciona" y un botón "Aceptar" que al clicarlo cerrará el diálogo. Ok. Hasta aquí todo bién. Ya tenemos el esqueleto funcionando. Ahora ya podemos empezar con el ejemplo de DOM.

Creación de la tabla vía DOM.

Para empezar, qué tiene una tabla de toda la vida? Pues un tag TABLE que encierra varios tags TR que son las filas, y cada TR encierra varios tags TD que son las columnas. Pues vamos allá. Eliminamos el alert() y tecleamos las instrucciones del DOM para la creación de la tabla. Para los que no estén acostumbrados al DOM, diré (así por encima) que se toma una página HTML como un XML, es decir, un conjunto de elementos que contienen hijos y éstos a su vez contienen otros hijos. Así que la construcción de una tabla se basa en la declaración de el padre, luego el hijo, luego el hijo lo añadimos al padre, y así sucesivamente:

   
Código: Javascript
  1.  function dibujarTabla()
  2.     {
  3.     TABLA = document.createElement('table');
  4.     FILA = document.creaateElement('tr');
  5.     COLUMNA1 = document.createElement('td');
  6.     TEXTO1 = document.createTextNode('celda 1');
  7.     COLUMNA1.appendChild(TEXTO1);
  8.     COLUMNA2 = document.createElement('td');
  9.     TEXTO2 = document.createTextNode('celda 2');
  10.     COLUMNA2.appendChild(TEXTO2);
  11.     FILA.appendChild(COLUMNA1);
  12.     FILA.appendChild(COLUMNA2);
  13.     TABLA.appendChild(FILA);
  14.     document.getElementById('enlace').appendChild(TABLA);
  15.     }

Hemos hecho lo siguiente: primero creamos el elemento tabla, luego el elemento fila, luego un elemento columna1, luego un elemento de tipo texto (con algo de texto dentro), y ligamos el elemento de texto a la columna. Luego hacemos otra columna repitiendo los pasos de la columna. Luego hemos ligado las columnas a la fila, luego la fila a la tabla y luego (y aquí está la madre del cordero) la tabla al DIV que habíamos llamado "enlace".

Si ahora nos vamos al Firefox veremos que al darle al link "Comenzar" nos genera una tabla de dos columnas justo debajo (en realidad lo crea donde esté situado el DIV). Muy bién. Y si lo probamos en el Internet Explorer? Pues no funciona!!!

Cómo podemos hacer para que funcione? Pues después de mucho rebuscar me encontré con que las especificaciones del objeto de tabla, en el W3C, mandan unos elementos agrupadores llamados THEAD, TBODY y TFOOT. A la hora de parsear una página normal parece que no son necesarios, pero la implementación de Internet Explorer requiere obligatoriamente que un elemento de éstos esté creado y funcionando entre el elemento TABLE y el elemento TR. Consulta las especificaciones del elemento en la página del W3C para más info.

Total, no sé si se debe a que la implementación de Internet Explorer está mal hecha no permitiendo escribir tablas via DOM sin TBODY o que el Firefox peca de elástico permitiendo algo que la W3C no recomienda, pero el caso es que sin un tag de éstos en Internet Explorer no funciona. Así que deberemos modificar la creación de la tabla para contemplar éste tag:

   
Código: Javascript
  1.  function dibujarTabla()
  2.     {
  3.     TABLA = document.createElement('table');
  4.     TBODY = document.createElement('tbody');
  5.     FILA = document.creaateElement('tr');
  6.     COLUMNA1 = document.createElement('td');
  7.     TEXTO1 = document.createTextNode('celda 1');
  8.     COLUMNA1.appendChild(TEXTO1);
  9.     COLUMNA2 = document.createElement('td');
  10.     TEXTO2 = document.createTextNode('celda 2');
  11.     COLUMNA2.appendChild(TEXTO2);
  12.     FILA.appendChild(COLUMNA1);
  13.     FILA.appendChild(COLUMNA2);
  14.     TBODY.appendChild(FILA);
  15.     TABLA.appendChild(TBODY);
  16.     document.getElementById('enlace').appendChild(TABLA);
  17.     }

Ahora ya tenemos éste código compatible con Internet Explorer y Firefox. El código de la página quedaría de la siguiente forma:

Código: HTML5
  1.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  2.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  3.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>Ejemplo de DOM</No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  4.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta language="JavaScript">
  5.     function dibujarTabla()
  6.     {
  7.     TABLA = document.createElement('table');
  8.     TBODY = document.createElement('tbody');
  9.     FILA = document.creaateElement('tr');
  10.     COLUMNA1 = document.createElement('td');
  11.     TEXTO1 = document.createTextNode('celda 1');
  12.     COLUMNA1.appendChild(TEXTO1);
  13.     COLUMNA2 = document.createElement('td');
  14.     TEXTO2 = document.createTextNode('celda 2');
  15.     COLUMNA2.appendChild(TEXTO2);
  16.     FILA.appendChild(COLUMNA1);
  17.     FILA.appendChild(COLUMNA2);
  18.     TBODY.appendChild(FILA);
  19.     TABLA.appendChild(TBODY);
  20.     document.getElementById('enlace').appendChild(TABLA);
  21.     }
  22.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  23.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  24.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  25.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta style="cursor:pointer; text-decoration: underline;" onclick="javascript:dibujarTabla();">Comenzar</No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  26.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta id="enlace"></No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  27.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  28.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  29.  

Añadiendo CSS

Para los que trabajamos con HTML amenudo estamos acostumbrados definir páginas de estilos que especifiquen los conjuntos de colores, fuentes y estilos varios en vez de irlos declarando en cada elemento. Es una forma de trabajar reconocida y aconsejada, además que realmente resulta muy práctica a la larga, pues te ahora mucho tiempo en las modificaciones típicas a posteriori.

Pero trabajar con clases CSS también comporta problemas cuando necesitamos que el DOM las defina en ambos navegadores. Pero no corramos tanto... vamos a definir una clase simple de estilo y vamos a intentar agregarla a nuestro script. Para ello debemos abrir un espacio dentro del HEAD que nos permita definir clases de estilos. Y allí crearemos una clase "negrita" y el estilo que queremos que tengan todos los elementos que adquieran de ésta clase:

   
Código: HTML5
  1.  <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  2.     .negrita
  3.     {
  4.     font-weight: bold;
  5.     }
  6.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  7.  

Ok, ya tenemos la clase definida. Usando el sentido común, sabremos que para definir una clase a un elemento le debemos agregar a ese elemento un atributo llamado class e igualarlo al nombre de la classe CSS que queramos. Así que si el atributo se llama class, deberíamos hacer algo así:
Código: Javascript
  1. COLUMNA1.setAttribute('class','negrita');

Vale, vale, voy a poner todo el trozo javascript para que no nos liemos:

   
Código: Javascript
  1. function dibujarTabla()
  2.     {
  3.     TABLA = document.createElement('table');
  4.     TBODY = document.createElement('tbody');
  5.     FILA = document.creaateElement('tr');
  6.     COLUMNA1 = document.createElement('td');
  7.     COLUMNA1.setAttribute('class','negrita');
  8.     TEXTO1 = document.createTextNode('celda 1');
  9.     COLUMNA1.appendChild(TEXTO1);
  10.     COLUMNA2 = document.createElement('td');
  11.     COLUMNA2.setAttribute('class','negrita');
  12.     TEXTO2 = document.createTextNode('celda 2');
  13.     COLUMNA2.appendChild(TEXTO2);
  14.     FILA.appendChild(COLUMNA1);
  15.     FILA.appendChild(COLUMNA2);
  16.     TBODY.appendChild(FILA);
  17.     TABLA.appendChild(TBODY);
  18.     document.getElementById('enlace').appendChild(TABLA);
  19.     }

Ahora que ya lo tenemos agregado, vamos al Firefox y ejecutamos: funciona perfecto ;) Entonces, vamos al Internet Explorer y... no hay estilo!! Cómo? mmmm... Qué toca ahora? Googlear. Finalmente encuentro una página dónde, a parte del problema anterior, se presenta este mismo problema con los CSS. La explicación que se da es que el Internet Explorer mapea la instrucción

Citar
elemento.setAttribute(nombre,valor)

por

Citar
elemento[nombre]=valor

Además, como class es una palabra reservada en Javascript, se mapea className en vez de class para el atributo class. Así que tenemos que cambiar la construcción del setAttribute:

 
Código: Javascript
  1.    function dibujarTabla()
  2.     {
  3.     TABLA = document.createElement('table');
  4.     TBODY = document.createElement('tbody');
  5.     FILA = document.creaateElement('tr');
  6.     COLUMNA1 = document.createElement('td');
  7.     COLUMNA1.setAttribute('className','negrita');
  8.     TEXTO1 = document.createTextNode('celda 1');
  9.     COLUMNA1.appendChild(TEXTO1);
  10.     COLUMNA2 = document.createElement('td');
  11.     COLUMNA2.setAttribute('className','negrita');
  12.     TEXTO2 = document.createTextNode('celda 2');
  13.     COLUMNA2.appendChild(TEXTO2);
  14.     FILA.appendChild(COLUMNA1);
  15.     FILA.appendChild(COLUMNA2);
  16.     TBODY.appendChild(FILA);
  17.     TABLA.appendChild(TBODY);
  18.     document.getElementById('enlace').appendChild(TABLA);
  19.     }
  20.  

Vamos a verificar que en Internet Explorer funciona. Ok, ahora ya sale el texto en negrita. Y sólo por curiosidad... vamos a probarlo en Firefox... Ahora no sale en Firefox!! Cagundena! Qué podemos hacer?? Pues hay dos posibilidades. La primera es liarnos la manta a la cabeza y distinguir qué navegador es el que está ejecutando el código, y para cada navegador realizar una cosa u otra. Ésta es una buena solución pero a yo intento evitarlo siempre que no es absolutamente necesario. Encuentro bastante barroco un código simple cuando se empieza a llenar de condicionales de si es un navegador u otro. La otra opción, no tan elegante pero completamente funcional, es definir las dos órdenes, la que funciona para Firefox y la que funciona para Internet Explorer. La orden que un navegador no entienda la va a obviar, así que adelante:

   
Código: Javascript
  1.  function dibujarTabla()
  2.     {
  3.     TABLA = document.createElement('table');
  4.     TBODY = document.createElement('tbody');
  5.     FILA = document.creaateElement('tr');
  6.     COLUMNA1 = document.createElement('td');
  7.     COLUMNA1.setAttribute('className','negrita');
  8.     COLUMNA1.setAttribute('class','negrita');
  9.     TEXTO1 = document.createTextNode('celda 1');
  10.     COLUMNA1.appendChild(TEXTO1);
  11.     COLUMNA2 = document.createElement('td');
  12.     COLUMNA2.setAttribute('className','negrita');
  13.     COLUMNA2.setAttribute('class','negrita');
  14.     TEXTO2 = document.createTextNode('celda 2');
  15.     COLUMNA2.appendChild(TEXTO2);
  16.     FILA.appendChild(COLUMNA1);
  17.     FILA.appendChild(COLUMNA2);
  18.     TBODY.appendChild(FILA);
  19.     TABLA.appendChild(TBODY);
  20.     document.getElementById('enlace').appendChild(TABLA);
  21.     }
  22.  

Así que tenemos el archivo final de la siguiente manera:

   
Código: HTML5
  1.  <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  2.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  3.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>Ejemplo de DOM</No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  4.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta language="JavaScript">
  5.     function dibujarTabla()
  6.     {
  7.     TABLA = document.createElement('table');
  8.     TBODY = document.createElement('tbody');
  9.     FILA = document.creaateElement('tr');
  10.     COLUMNA1 = document.createElement('td');
  11.     COLUMNA1.setAttribute('className','negrita');
  12.     COLUMNA1.setAttribute('class','negrita');
  13.     TEXTO1 = document.createTextNode('celda 1');
  14.     COLUMNA1.appendChild(TEXTO1);
  15.     COLUMNA2 = document.createElement('td');
  16.     COLUMNA2.setAttribute('className','negrita');
  17.     COLUMNA2.setAttribute('class','negrita');
  18.     TEXTO2 = document.createTextNode('celda 2');
  19.     COLUMNA2.appendChild(TEXTO2);
  20.     FILA.appendChild(COLUMNA1);
  21.     FILA.appendChild(COLUMNA2);
  22.     TBODY.appendChild(FILA);
  23.     TABLA.appendChild(TBODY);
  24.     document.getElementById('enlace').appendChild(TABLA);
  25.     }
  26.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  27.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  28.     .negrita
  29.     {
  30.     font-weight: bold;
  31.     }
  32.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  33.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  34.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  35.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta style="cursor:pointer; text-decoration: underline;" onclick="javascript:dibujarTabla();">Comenzar</No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  36.     <No tienes permisos para ver links. Registrate o Entra con tu cuenta id="enlace"></No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  37.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  38.     </No tienes permisos para ver links. Registrate o Entra con tu cuenta>
  39.  

Setando atributos a los elementos

Seguimos con la gama de problemas. Hasta ahora, el único atributo que hemos setado es el referente a las clases CSS. Pero existen varios más, como el colspan de una celda por ejemplo. El sentido común nos dicta que si los atributos se setan con .setAttribute, la construcción normal para un colspan sería:

Citar
COLUMNA3.setAttribute('colspan','2');

Pues bién, en Firefox funciona perfectamente pero en Internet Explorer no (para variar). Cómo lo hacemos para Internet Explorer? Pues de la siguiente manera:

Citar
COLUMNA3.colSpan=2;

que funcionará tanto para Internet Explorer como para Firefox. Prestad atención a la 'S' mayúscula del colSpan.

Pero, en cambio, hay otros atributos que se setan perfectamente en ambos navegadores usando la sintaxi .setAttribute('atributo', 'valor'), como el size de un INPUT de texto o su value. Increible pero cierto. Conclusión? En principio se debería usar la construcción .setAttribute, y si se ve que no funciona, probar con la sintaxi .atributo ... es lo que hay...

Más cosas. Resulta que Internet Explorer hay una limitación sobre el atributo name en los INPUTs, tal como describe la MSDN:

Citar
The NAME attribute cannot be set at run time on elements dynamically created with the createElement method. To create an element with a name attribute, include the attribute and value when using the createElement method.

Esta cuestión está ámpliamente discutida en easy-reader.net y alt-tag.com (seguid también el hilo de los comentarios) y proponen usar una función que intente setar el nombre al estilo del Internet Explorer y si falla que lo sete al estilo de Firefox, para poder cumplir ambos requerimientos:

Código: Javascript
  1.     function createElementWithName(type, name) {
  2.     var element;
  3.     // First try the IE way; if this fails then use the standard way
  4.     if (document.all) {
  5.     element =
  6.     document.createElement('<'+type+' name="'+name+'" />');
  7.     } else {
  8.     element = document.createElement(type);
  9.     element.setAttribute('name', name);
  10.     }
  11.     return element;
  12.     }
  13.  
  14.  

Setar eventos a los elementos


Los eventos tampoco se libran. Si se quieren usar los eventos, en Firefox podemos seguir la tónica habitual:

Citar
elemento.setAttribute("onclick","javascript:mi_funcion('"+param_texto+"',"+param_numero+")");

Pero claro, en Internet Explorer tampoco funciona... En Ovillo plantean una posible solución, pero no me ha funcionado. Personalmente, ahora mismo me estoy peleando con ésto. Si encuentro alguna solución la postearé.

Fuente: No tienes permisos para ver links. Registrate o Entra con tu cuenta
« Última modificación: Septiembre 07, 2013, 04:55:56 pm por Destructor.php »

 

¿Te gustó el post? COMPARTILO!



[XHTML] XHTML desde cero

Iniciado por ANTRAX

Respuestas: 0
Vistas: 1221
Último mensaje Febrero 24, 2010, 11:55:48 am
por ANTRAX
[HTML] Curso HTML desde cero

Iniciado por ANTRAX

Respuestas: 0
Vistas: 1136
Último mensaje Febrero 24, 2010, 11:50:54 am
por ANTRAX
Curso Bootstrap 4: El Curso Completo, Práctico y Desde Cero

Iniciado por Mr.Kratos

Respuestas: 0
Vistas: 202
Último mensaje Julio 30, 2018, 05:29:54 pm
por Mr.Kratos
[VIDEOTUTORIAL 1080 HD] [UDEMY] Monta un cluster Hadoop Big Data desde cero

Iniciado por akame_night_raid

Respuestas: 0
Vistas: 1533
Último mensaje Mayo 28, 2016, 01:23:16 pm
por akame_night_raid
[VIDEOTUTORIAL] Full Stack Developer - Desde HTML hasta PYTHON - 15 GB

Iniciado por graphixx

Respuestas: 5
Vistas: 7923
Último mensaje Abril 01, 2018, 02:46:38 pm
por graphixx