Los Principios del Java Script No Obstrusivo
- Artículo anterior—Mejores prácticas de JavaScript
- Siguiente artículo—Funciones en JavaScript
- Tabla de contenidos
Introducción
En los artículos anteriores hablamos bastante sobre HTML, CSS y de como implementarlos de manera adecuada, además hemos pasado por los aspectos básicos de JavaScript— qué es, qué puede hacer por ti, y por qué deberías conocerlo. Antes de ir al detalle del uso práctico de JavaScript, necesitamos pensar en cómo usar JavaScript con sensibilidad de manera que no excluyamos a nadie de nuestro sitio web. Esa es la idea central del JavaScript no obstructivo. Para entender esto de una manera fácil, consideremos las muchas incertidumbres que envuelven a la programación con JavaScript:
- Algunos navegadores pueden ignorar tus scripts completamente, ya sea porque no soportan JavaScript o porque el soporte es muy anticuado.
- Aún cuando el navegador pudiese soportar JavaScript, los usuarios podrían tenerlo desactivado por razones de seguridad, o porque el firewall corporativo lo bloquea al eliminar todos los elementos
<script>
. - Aún cuando el navegador pudiese soportar JavaScript, este podría no entender partes del script porque tiene una implementación propietaria de algunas partes de la especificación del DOM (IE es usualmente el culpable en estos casos).
- Aún cuando el script sea interpretado correctamente, podría depender de código HTML muy complicado y/o que podría cambiar de manera impredecible.
- Aún cuando tu contexto de programación ha sido bendecido con un HTML perfecto, no tienes manera de estar seguro de qué dispositivo utilizará el usuario. Muchos scripts funcionan solamente cuando el usuario utiliza un ratón, y olvidan a las personas que usan el teclado (muchos usuarios con discapacidad no pueden usar el ratón, y otros simplemente prefieren usar el teclado.
- La definición de JavaScript no obstructivo
- Separación de la estructura y el comportamiento
- Agregando una capa de usabilidad
- HTML semántico y limpio
- Compatibilidad con los navegadores
- Resumen
- Suposición: todos los navegadores soportan JavaScript. falso: A fin de ser no obstructivo a los usuarios, quitar el script no debería evitar que puedan utilizar tu sitio, aunque su interacción sea menos rica que la de los usuarios cuyos navegadores sí soportan JavaScript.
- Suposición: todos los navegadores funcionan igual. falso: A fin de ser no obstructivo a los navegadores, tu script debe evitar errores y problemas de compatibilidad, y tomar en consideración dispositivos especiales como lectores de pantalla y teléfonos móviles.
- Suposición: todo el mundo entenderá mi código. falso: A fin de ser no obstructivo a los compañeros programadores, tus scripts deben consistir de código limpio y claro con abundantes comentarios que indiquen lo que tu código está haciendo (o debería hacer).
Esa es una lista bastante larga de problemas, la mayoría de ellos no son de naturaleza técnica sino conceptual o, si lo deseas, filosófica. Adicionalmente, mientras que los dos últimos problemas se presentan en otros lenguajes, los primeros cuatro son únicos del entorno de programación de JavaScript, así que la experiencia en programación no te ayudará en esos casos.
En resumen, JavaScript no obstructivo es una manera de escribir JavaScript de modo que los visitantes de tu sitio no se queden por fuera por alguna de esas razones—aún cuando tu JavaScript no funcione correctamente para ellos, aunque sea de una manera más básica. Este artículo discutirá los principios y prácticas del JavaScript no obstructivo y te preparará adecuadamente para el resto del curso.
La estructura de este artículo es la siguiente:
La definición de JavaScript no obstructivo
A fin de solucionar los problemas listados anteriormente, es de suma importancia que entiendas lo que estás haciendo y por qué. Lo que necesitamos es una teoría para el adecuado desarrollo con JavaScript.
Dicha teoría es provista por el JavaScript no obstructivo. No es una técnica como tal; el JavaScript no obstructivo no consiste en agregar una llamada a la función hacerNoObstructivo()
para entrar en el nirvana. Al contrario, es una manera de pensar. Para asegurarte que tus scripts no causen molestias a nadie, debes asegurarte que estos no hagan ninguna suposición.
Ahora, “que tus scripts no hagan ninguna suposición” es algo difícil. Afortunadamente podemos dividir la no obstructividad en tres categorías: tus scripts deben ser no obstructivos a los usuarios, a los navegadores y a los demás programadores.
Este artículo tratará las dos primeras suposiciones en detalle.
Adicionalmente a evitar estas suposiciones, el JavaScript no obstructivo requiere que separes tu código JavaScript del HTML. Como ese es, por mucho, el aspecto más técnico de esta filosofía de programación, lo cubriremos primero y volveremos a las luego.
Separación de la estructura y el comportamiento
De la misma manera como debemos separar la estructura de la presentación poniendo todo el CSS en un archivo separado y evitando el uso del atributo style
u otros tipos de marcaje presentacional, también debemos separar nuestra estructura HTML del comportamiento con JavaScript. Las razones son las mismas: Separa tus ocupaciones, mantiene el código limpio y te permite trabajar en el JavaScript sin tocar el HTML o CSS.
La regla básica es simple: un archivo HTML no debe contener JavaScript, de la misma manera que no debe contener CSS. Hay dos cosas que los autores colocan en sus archivos HTML: Scripts incrustados y manejadores de eventos. Eliminarlos es la manera más simple de lograr la separación de la estructura y el comportamiento.
Como aprendiste en el artículo anterior, los scripts incrustados son pedazos de código JavaScript dentro de la pagina HTML entre elementos <script>
. Pueden ser movidos fácilmente a un archivo JavaScript externo, así que no representan un gran problema.
Manejadores de eventos definidos en línea como el siguiente <a href="somewhere.html" onmouseover="hideAll()">
son un poco más difíciles de remover. Estos definen que manejadores de eventos (funciones JavaScript) deben ejecutarse cuando cierto evento ocurre. Lo que debemos hacer para hacerlo no obstructivo es mover la asignación del manejador del evento a un archivo aparte. Esto significa que el script externo primero debe encontrar el elemento correcto y luego asignar el manejador del evento.
Para aprender más sobre manejadores de eventos, revisa el artículo Handling events with JavaScript.
La manera más fácil de permitir que un elemento sea encontrado es dándole un ID. Por ejemplo:
<!-- HTML: -->
<a href="somewhere.html" id="somewhereLink">
<!-- JavaScript: -->
var x = document.getElementById('somewhereLink');
if (x) {
x.onmouseover = hideAll;
}
La función hideAll()
se ejecuta siempre que el usuario coloque el cursor del ratón sobre el enlace, por lo tanto este poco de código es equivalente a <a href="somewhere.html" onmouseover="hideAll()">
.
Aun mejor, estas dos lineas de de código funcionan en cualquier pagina que contenga un elemento con id="somewhereLink"
, de modo que no tienes que repetirte una y otra vez. Y si la pagina no contiene dicho elemento, el chequeo if (x)
se asegura de que no se generen mensajes de error: Asigna el manejador del evento sólo cuando el elemento x
realmente existe.
¿Y si el navegador del usuario no soporta JavaScript? Obviamente, el evento mouseover no funcionará. El enlace sigue siendo un enlace, por lo tanto aún puede ser seguido.
Ahora nuestro código, adicional a que es más claro, es mucho más mantenible.
Por ejemplo, generalmente es bueno juntar los eventos mouseover
y focus
. El evento mouseover
sólo funciona cuando el usuario utiliza un ratón. Las personas que no utiliza ratón colocarán el foco en el enlace que quieren presionar con el teclado y eso dispara el evento focus
. Si registramos nuestra función manejadora con ese evento también (es decir, si le decimos a la función que debe ejecutarse cuando se dispare ese evento), nos habremos asegurado que nuestra aplicación también funciona con el teclado.
Eso es muy fácil de hacer cuando el script está separado adecuadamente del HTML:
var x = document.getElementById('somewhereLink');
if (x) {
x.onmouseover = x.onfocus = hideAll;
}
Al agregar esos 12 caracteres hemos hecho esa parte de la aplicación accesible por medio de teclado. ¿Fácil no?
Ahora, pensemos en qué tendríamos que hacer si usáramos eventos definidos en línea. Tendríamos que manualmente ir por todos los enlaces del sitio que tengan onmouseover
y agregarles onfocus="hideAll()"
. No sólo nos haría perder mucho tiempo que podría ser utilizado en algo útil, sino que es una forma de trabajar propensa a errores, ya que podríamos olvidar un enlace en alguna oscura plantilla que es utilizada en pocas ocasiones, o podría ocurrir algo tan simple como un error de tecleo.
Por lo tanto, de la misma manera que es sabio separar el HTML y el CSS, es buena idea separar el HTML y el JavaScript. Eliminar los scripts incrustados y los eventos definidos en línea es bastante fácil, y mejora la calidad y mantenibilidad del código de manera inmediata.
Agregando una capa de usabilidad
Ya que hemos tratado el aspecto más técnico del JavaScript no obstructivo, es hora de volver a las suposiciones discutidas anteriormente. La más importante es nunca suponer que todos soportan JavaScript, y esto se une directamente con el propósito general detrás de agregar scripts as un sitio web.
El propósito de JavaScript es agregar una capa de usabilidad a tu sitio. Toma nota de que se trata de "agregar": si el script es la capa de usabilidad completa (en otras palabras, si el sitio no es usable sin JavaScript), has cometido un error muy grave y tu script es obstructivo.
Ejemplo—validación de formularios
Un ejemplo servirá para clarificarlo, discutamos acerca de la validación de formularios. Los datos insertados por el usuario siempre deben ser revisados en el servidor antes de almacenarlos en una base de datos, porque confiar ciegamente en los datos que un usuario al azar, posiblemente malicioso, rellene en el formulario es la manera más segura de lograr que tu sitio sea hackeado—siempre debemos revisar los datos antes de aceptarlos.
La desventaja de la validación del lado del servidor, es que puede tomar un poco más. El usuario envía el formulario al servidor y el servidor genera una página de respuesta que notifica al usuario si hubo errores o no en el envío de los datos. Sin importar cuán rápido responda el servidor, siempre habrá un pequeño retraso entre el momento en que se hace el envío y la respuesta—digamos, medio segundo.
Peor aún, si el usuario comete un error—como olvidar su dirección— tendrá que corregir el problema y enviar el formulario una vez más, lo que significará medio segundo adicional. No es mucho, pero se agregan en la mente del usuario, especialmente si tiene que hacerlo varias veces.
Es aquí cuando JavaScript entra en el dibujo. Si agregas un script que revise el formulario antes de enviarlo al servidor, podrás atrapar los errores de usuario típicos sin necesidad de hacer el viaje de ida y vuelta al servidor, y la interfaz parecerá funcionar rápidamente y de manera fluida.
Así que usar JavaScript para la validación de formularios es una buena idea. Sin embargo—y este es el verdadero punto— JavaScript debe ser usado adicionalmente a la validación del lado del servidor. La primera te dará una interfaz más fluida, pero la segunda te dará la seguridad verdadera (es fácil sortear la validación con JavaScript si deseas generar daño: sólo desactiva JavaScript) así como una opción alternativa en caso de que el navegador del usuario no soporte JavaScript.
Desde principios de 2009 (esto podría cambiar en el futuro próximo) Opera tiene una ventaja sobre otros navegadores ya que soporta la especificación de Formularios Web 2.0 de HTML 5, que es básicamente una forma avanzada de crear formularios en HTML, que incluye una forma de validación del lado del cliente que no requiere JavaScript, de modo que no puede ser sorteada al desactivarla. Para aprender más sobre Formularios Web 2.0, revisa el artículo Mejora tus formularios usando HTML 5.
Principios
Este ejemplo ilustra unos principios importantes:
- Tu sitio debería funcionar sin JavaScript.
- Si JavaScript está habilitado, puedes presentar al usuario una capa adicional de usabilidad; una capa le permite al usuario realizar las tareas de una manera más rápida y evita en, donde sea posible, recargas a las páginas.
- JavaScript no es seguro. Es decir, *nunca* debes confiar en rutinas JavaScript tareas vitales como chequear los datos introducidos por el usuario. Después de todo, un usuario malicioso puede desactivarlo y sortear tus defensas.
Ahora, exactamente, ¿Qué significa que tu sitio debe funcionar sin JavaScript? Significa que cualquier usuario, sin importar que dispositivo y software use, debe poder leer el contenido de tu sitio y usar la navegación y demás funciones críticas. Nada más, y (más importante aún) nada menos.
La parte importante es que no es necesario ofrecer a tus usuarios que no soportan scripts la misma funcionalidad que a los que sí manejan scripts. En el ejemplo de la validación, los usuario sin scripts deberán esperar medio segundo antes de conocer los resultados del envío del formulario y por lo tanto tendrán una experiencia un tanto peor que aquellos que sí soportan scripts.
De hecho, eso es una regla general. Cuando JavaScript está desactivado, sufre la usabilidad, y tu trabajo como desarrollador es asegurarte que la gente pueda hacer uso de los aspectos básicos de tu sitio: Contenido y navegación. Todas los demás características se vuelven opcionales.
Ejemplo—ventanas emergentes
Consideremos otro ejemplo, ventanas emergentes. Algunas veces son realmente útiles, y crearlas es relativamente sencillo—si el navegador soporta JavaScript. Sin embargo, si no lo soporta los usuarios no verán la ventana. ¿Cómo mantienes tu sitio accesible a la vez que ofreces a los navegadores con JavaScript activado una interfaz más fluida?
En HTML: <a href="somewhere.html" class="popup">Ir a algún lugar</a> En JavaScript: var x = document.getElementsByClassName('popup'); // una función propia for (var i=0;i<x.length;i+=1) { x[i].onclick = function () { window.open(this.href,'popup','arguments'); return false; } }
El aspecto crucial acá es el atributo href
del enlace. Este define la página que deberá aparecer en la ventana emergente, pero adicionalmente se asegura que si JavaScript está desactivado el usuario pueda seguir el enlace. Así, este ejemplo es perfectamente accesible sin JavaScript —sólo que menos amigable.
Cuando JavaScript está activado agregas una capa adicional de usabilidad: La ventana emergente. Encuentras todos los enlaces que tengan class="popup"
y les agregas un manejador de evento onclick
que abre la ventana emergente. ¿Qué página debe mostrarse en la ventana? la que está definida en el atributo href
del enlace (this.href
).
Un ejemplo diferente, mismo principio. Primero asegúrate que cualquier usuario tenga acceso a la información; luego agrega un poco de JavaScript encima para hacer que la interfaz funciones de manera más fluida.
Ejemplo—Ajax
Esta teoría a veces es difícil de aplicar en la práctica, especialmente cuando quieres desarrollar un sitio web Ajax y eres novato en esto del desarrollo web. Un truco útil para entender esta técnica es pensar en capas. ¿Cuál es la funcionalidad básica del sitio? Esta funcionalidad debería ser colocada en la capa inferior, la cual es accesible con o sin JavaScript. Encima de eso puedes aplicar el número de capas de usabilidad que desees con JavaScript de modo de hacer el sitio más fácil de usar. Dichas capas no interfieren con el funcionamiento básico del sitio; sólo ofrecen elementos adicionales.
Utilicemos un ejemplo para aclarar esta regla general. Supongamos que tu sitio es sobre comparativas de teléfonos móviles. La funcionalidad básica de tu sitio será algo como esto:
- Buscar ciertos teléfonos móviles, ya sea por criterios generales como “soporta wifi” o “puede ser sincronizado con el computador personal”.
- Obtener una lista de teléfonos que coincidan con la búsqueda.
- Ordenar dicha lista por precio, nombre/tipo, o relevancia.
Todas esas funciones pueden ser creadas sin una sola línea de Javascript, y tu primera tarea es hacer justamente eso. Así que creas:
- Una página de búsqueda.
- Una página para la lista, generada por el servidor, basado en la búsqueda.
- Enlaces en dicha página obtienen el mismo listado ordenado de manera distinta por el servidor.
Una vez que has hecho estas página sin scripts, has creado la capa básica que funcionara más o menos con cualquier dispositivo.
Una vez que has hecho esto, añades funcionalidad JavaScript a esas páginas básicas. Lo más obvio es un script para ordenar. Después de todo, los datos son necesarios para realizar el ordenamiento—tales como el precio y las capacidades—ya se encuentran en la tabla en la página y no necesitas una solicitud más al servidor para obtenerla. Tan sólo necesitas escribir un código que reordene los elementos <tr>
de dicha tabla.
Una vez que has escrito tu script debes asegurarte que el usuario realmente puede utilizarlo. Darle al usuario un enlace para dicha funcionalidad es la solución más obvia.
El punto importante aquí es que tú ya tienes los enlaces en la tabla: los enlaces que obtienen del servidor las listas ordenadas en distintas formas. Por mucho, la mejor solución es anular el comportamiento original de esos enlaces, de la misma manera que hicimos con el ejemplo de las ventanas emergentes.
Así, escribes una función adicional que asigna el manejador de evento onclick
de modo que al hacer click se ejecute el script de ordenamiento en lugar de la página en el servidor
Por lo tanto, todos los usuarios verán los mismos enlaces para ordenar, pero el comportamiento exacto dependerá de que el navegador soporte la capa adicional de usabilidad agregada con JavaScript. Si puede, ejecutará tu script, y si no solicitará la página al servidor.
Anular el funcionamiento original de un elemento HTML es uno de los principales ejemplos de JavaScript no obstructivo. Si el navegador del usuario soporta tus scripts, perfecto, los ejecuta. Si no, volverá al funcionamiento original del elemento HTML. Siempre y cuando de adhieras a este principio, tus scripts serán no obstructivos.
HTML semántico y limpio
Los script son ejecutados en el contexto de las páginas web. ¿Qué tipo de páginas web? En teoría, cualquier página servirá mientras hayan elementos HTML que manipular. En la práctica, sin embargo, te darás cuenta rápidamente que las páginas respetuosas de los estándares y que usan HTML semántico, bien estructurado y que separa adecuadamente el HTML del CSS son mucho más fáciles para trabajar que aquellas monstruosidades de tablas generadas por algunos editores WYSIWYG.
Supón que estás trabajando en un sitio de noticias y quieres que todas las páginas tengan una tabla de contenidos a cada título en el artículo. La manera más sencilla de lograrlo es recorrer todos los elementos de encabezado (<h1>
, <h2>
, etc.), crear una lista, y asegurarse que al hacer click en cada elemento de la lista lleve al usuario al encabezado apropiado. Script hecho, siguiente trabajo. (A propósito, este script también es no obstructivo. La funcionalidad de ir a un encabezado es un extra agradable, pero si no estuviese el usuario aún podría leer el contenido y utilizar la navegación.)
Ahora supón que el sitio en el que estás trabajando no tuvo la suerte de ser creado con HTML semántico y CSS como has aprendido. Supón que se ve así:
<div class="contentcontainer">
<p class="maincontent"><b class="headline">McCain suspende la campaña para pasar más tiempo con su economía</b><br>
En una movida que sorprendió a los observadores políticos [etc etc]</p>
</div>
¿Podrías escribir un script para generar la tabla de contenidos con una página marcada de sea manera tan deficiente? Seguro. Sólo debes recorrer todos los elementos <b>
y especificar que cada uno que tenga class="headline"
es de hecho un encabezado—así tu script debería funcionar.
No obstante, algo que se ha perdido es el anidamiento estructural que está implícito en los niveles de encabezado. Una página limpia y semántica imparte, inmediatamente, el conocimiento de que un encabezado <h3>
será un subtítulo del <h2>
que lo precede, y tu script puede tomar ventaja de ese hecho.
En una página no-semántica como la anterior, tendrías que buscar la manera de determinar si un <b class="headline">
se refería a un título, un subtítulo, un subsubtítulo o algo diferente.
Ahora, aún ese problema puede ser resuelto, pero ese no es el punto. El punto es que si el autor del HTML utiliza los elementos adecuados para marcar los encabezados, estarás absolutamente seguro de que tu script encontrará la información correcta sin importar donde se ejecute. En cambio, si el autor del HTML usa cosas como <b class="headline">
, él no sabe realmente lo que está haciendo, lo que significa que subsiguientes versiones del HTML podrían utilizar elementos <strong> o <span>. Y cada vez que el HTML cambia, tendrás que cambiar tu script también.
Por lo tanto, los scripts que funcionan con páginas limpias y semánticas son generalmente más fáciles de escribir y siempre serán mucho más fáciles de mantener que aquellos que funcionan con una sopa de etiquetas.
Compatibilidad con los navegadores
El JavaScript no obstructivo también pide que los scripts sean no obstructivos a los navegadores. En la práctica lo que significa es que el script debe funcionar en la mayor cantidad de navegadores, y si no funciona no debe generar un mensaje de error sino degradarse de manera elegante, dejando al visitante con una página con su funcionalidad trabajando. Esto suena perfecto, pero es uno de los aspectos más difíciles de dominar en el desarrollo con JavaScript.
El gurú del desarrollo con JavaScript Douglas Crockford llama a los navegadores “el entorno de desarrollo más hostil del mundo.” No sólo que el navegador es una verdadera plataforma de desarrollo de aplicaciones con un mal récord de proveer cosas como depuradores de errores - debuggers - (aunque en ese caso, también, las situación está mejorando), pero sólo la cantidad de diferencias entre ellos puede rápidamente llevar a la locura a los novatos.
Desafortunadamente las incompatibilidades son un hecho de la vida. Tan pronto cuando tratas de escribir código JavaScript no trivial, descubrirás que el comportamiento de los distintos navegador puede diferir significativamente. Comúnmente sucederá que tu script funciona en todos los navegadores excepto IE, aunque los demás navegadores también tienen su cuota de problemas.
La raíz de estas incompatibilidades es que los principales navegadores tienen sus propios motores para el análisis sintáctico del código, y dichos motores difieren el uno del otro.
La fuente más común de problemas proviene de Internet Explorer; hay una buena cantidad de funcionalidades que se comportan distinto a otros navegadores, o que simplemente no están soportadas. El equipo de MSIE está trabajando en hacer este navegador más obedientes a los estándares, pero no ha culminado el trabajo aún. Así que puedes esperar algunos problemas.
Aún si esos problemas fueran solucionados de manera mágica, bastantes incompatibilidades continuarían existiendo, simplemente porque algún navegador aún no soporta cierto método, o porque sus programadores cometieron un error honesto mientras lo implementaban.
Así que tenemos un problema y no desaparecerá pronto. ¿Cómo lidiamos con él?
La mejor estrategia es aceptarlo y enfocarse en los detalles técnicos, los cuales serán discutidos en artículos posteriores de la serie. Desafortunadamente, aprender de memoria todas las incompatibilidades entre los navegadores es imposible, pero hay varias ayudas para los programadores que empiezan a usar JavaScript. QuirksMode.org ofrece tablas que muestran cuales métodos y propiedades son soportados por cuales navegadores, y ofrece copiosas notas sobre errores.
Adicionalmente, muchas personas han transitado ese camino antes. Algunos de ellos decidieron crear librerías JavaScript que sortean los peores problemas por ti. Por lo tanto, usar una librería para resolver los problemas de incompatibilidad entre los navegadores es una estrategia viable.
No obstante, ten cuidado. Como novato en JavaScript, deberías considerar escribir tu primer proyecto sin la ayuda de librerías. La razón es que un programador JavaScript experimentado debes trabajar duro para obtener los conocimientos de qué es lo que sucede internamente. Hacerlo así te permitirá obtener un sentido de las formas en que los navegadores pueden destrozar tu código, lo que ayudará a tu desarrollo como programador JavaScript.
Así que sí, usa librerías para sortear los problemas, pero resiste a la tentación de usarlas de inmediato. Trata de trabajar sin ellas para obtener una idea de a qué te enfrentas.
Resumen
JavaScript no obstructivo es más una filosofía que una técnica. Por mucho su componente más importante es saber a qué capa pertenece cada funcionalidad. Todas las funcionalidades absolutamente indispensables deben ser codificadas en HTML puro, pero una vez que has creado esa base puedes agregar encima una capa de JavaScript de modo que los navegadores que lo soporten obtengan una interfaz más clara, agradable y ágil.
Además, JavaScript no obstructivo
- Separa la estructura del comportamiento, de modo que el código sea más limpio y el mantenimiento del script más fácil
- Previene las incompatibilidades entre los navegadores
- Trabaja con una capa de HTML limpia y semántica
El JavaScript no obstructivo no es tan difícil. Es, más que todo, un truco de la mente; una vez que has pasado unas horas planificando un script no obstructivo notarás que tomar la decisión correcta se hace cada vez más fácil.
Una vez que te acostumbras al JavaScript no obstructivo, no querrás volver al viejo modelo obstructivo.
- Artículo anterior—Mejores prácticas de JavaScript
- Siguiente artículo—Funciones en JavaScript
- Tabla de contenidos
Acerca del autor
Peter-Paul Koch es un desarrollador web freelance de en Amsterdam, Países Bajos. El escribe y mantiene quirksmode.org, actualmente una de las mejores fuentes sobre JavaScript disponibles en Internet. Su Tabla de Compatibilidades del DOM de la W3C, especialmente, le ha ahorrado a los desarrolladores web un estimado de GBP 5 millones en implantes de cabello y productos de cuidado capilar. Proveedores de navegadores como Microsoft, Opera, y Apple usan dichas tablas para solucionar errores en sus productos.
This article is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported license.
Comments
The forum archive of this article is still available on My Opera.