Disclaimer: This is a personal web page. Contents written here do not represent the position of my employer.
Monday, December 05, 2005
AMUSE ya está en el SVN de Berlios
Tras unas semanas después de abrir el proyecto AMUSE en Berlios, me he animamdo a subir al repositorio de Subversion (SVN) la primera versión.
También me he animado a desarrollar un poco más en detalle lo que significa y pretende este pequeño proyecto:
Inspirado en todos los inconvenientes que le he encontrado al lenguaje JavaScript para el desarrollo web en el cliente, he creado este proyecto GPL, destinado a hacer más llevadero el desarrollo con este lenguaje.
Las siglas AMUSE significan: Ajax-based Modular Unobstrusive System for Ecmascript. Lo que se puede deducir de esto es que AMUSE es una especie de framework hecho en y para javascript (ecmascript) con el objetivo de construir un modelo consistente de desarrollo de paquetes javascript, en el que se persigue la modularización de código y separación en capas, el uso de eventos no intrusivos, y un sistema de dependencias entre paquetes.
Según mi visión (la cual está aplicada en el framework), los paquetes los dividiremos en dos tipos: librerías y módulos. Los primeros, las librerías, básicamente proporcionarán una nueva API, una serie de funciones y/o objetos de los que podrá hacer uso el programador de JavaScript. Las librerías podrán depender de otras librerías, sobre las que apoyarse para implementar su propia API, pero nunca de módulos. Los módulos podrán definir funciones y/o objetos, y podrán depender de librerías, y al invocarlos podrán incorporar funcionalidades y procesos al documento web en el que se adjuntan (al contrario que las librerías, que sólo aportan una interfaz, en lugar de automáticamente añadir funcionalidad).
Es difícil que se me entienda si no pongo un ejemplo: Veamos, normalmente los paquetes JavaScript que se pueden encontrar en internet y que son de libre uso, para utilizarlos debemos referenciarlos con una etiqueta <script> en nuestra web, y luego normalmente adjuntamos invocaciones a sus funciones en los eventos de nuestros controles web. Por ejemplo, imaginemos que tenemos un sistema para crear enlaces "mailto" para evitar el spam. Normalmente haríamos algo así:
Sin embargo, si desarrollamos un módulo teniendo en mente el sistema modular de AMUSE y el estilo de código que con éste se propugna, podríamos hacer lo siguiente:
Luego, en el <head> de la página, referenciaríamos a dos ficheros javascript externos:
El fichero "amuse.js" es el que implementa el interfaz de AMUSE. En el fichero mi_pag.js podríamos introducir lo siguiente:
De esta manera estaríamos llamando al módulo EmailAntiSpam, el cual, si miramos en su implementación interna haría cosas como:
De esta manera, el usuario de nuestro nuevo módulo, denominado "EmailAntiSpam", sólo tendría que hacer una llamada RequireOnce a nuestro módulo, adjudicar la clase correspondiente a sus nodos span y olvidarse de escribir más código javascript.
Además, evitamos el tener que escribir etiquetas <script> por cada funcionalidad que queramos añadir. De esta manera, el propio código JavaScript puede llamar a otros ficheros javascript externos. Si nos fijamos también, los módulos deben adjudicar eventos a elementos de manera no intrusiva, es decir, que los comportamientos se añaden desde el propio código javascript, en lugar de tener que escribir invocaciones y eventos en el marcado HTML/XHTML.
Este módulo EmailAntiSpam en realidad aún no está implementado, pero cualquiera puede hacerlo con un poco de tiempo. Con AMUSE también distribuyo librerías y módulos de ejemplo, entre las cuales se unirá nuestro módulo EmailAntiSpam en cuanto lo tenga desarrollado (o bien si lo desarrolla antes un voluntario, pues todo esto es software GPL).
Voy a poner una pequeña descripción de estos añadidos que aporto con AMUSE:
Librerías:
Módulos:
Como véis, algunos son muy sencillos y tontos, pero otros yo creo que muy útiles. Sobre todo el módulo PreContent.js que en mi opinión es de obligado uso si queremos resolver el problema de usar JavaScript no intrusivo (es decir, que los controles de nuestra página adquieran sus comportamientos sólo cuando la página se cargue por completo) cuando la velocidad de conexión de nuestro visitante es algo lenta y existe el peligro de que use un formulario antes de que haya llegado la página entera.
KNOWN ISSUES:
TO-DO:
También me he animado a desarrollar un poco más en detalle lo que significa y pretende este pequeño proyecto:
Inspirado en todos los inconvenientes que le he encontrado al lenguaje JavaScript para el desarrollo web en el cliente, he creado este proyecto GPL, destinado a hacer más llevadero el desarrollo con este lenguaje.
Las siglas AMUSE significan: Ajax-based Modular Unobstrusive System for Ecmascript. Lo que se puede deducir de esto es que AMUSE es una especie de framework hecho en y para javascript (ecmascript) con el objetivo de construir un modelo consistente de desarrollo de paquetes javascript, en el que se persigue la modularización de código y separación en capas, el uso de eventos no intrusivos, y un sistema de dependencias entre paquetes.
Según mi visión (la cual está aplicada en el framework), los paquetes los dividiremos en dos tipos: librerías y módulos. Los primeros, las librerías, básicamente proporcionarán una nueva API, una serie de funciones y/o objetos de los que podrá hacer uso el programador de JavaScript. Las librerías podrán depender de otras librerías, sobre las que apoyarse para implementar su propia API, pero nunca de módulos. Los módulos podrán definir funciones y/o objetos, y podrán depender de librerías, y al invocarlos podrán incorporar funcionalidades y procesos al documento web en el que se adjuntan (al contrario que las librerías, que sólo aportan una interfaz, en lugar de automáticamente añadir funcionalidad).
Es difícil que se me entienda si no pongo un ejemplo: Veamos, normalmente los paquetes JavaScript que se pueden encontrar en internet y que son de libre uso, para utilizarlos debemos referenciarlos con una etiqueta <script> en nuestra web, y luego normalmente adjuntamos invocaciones a sus funciones en los eventos de nuestros controles web. Por ejemplo, imaginemos que tenemos un sistema para crear enlaces "mailto" para evitar el spam. Normalmente haríamos algo así:
<a onclick="envia_mail('pepito','gmail.com');">pepito arroba gmail punto com</a>
Sin embargo, si desarrollamos un módulo teniendo en mente el sistema modular de AMUSE y el estilo de código que con éste se propugna, podríamos hacer lo siguiente:
<span class="email">pepito<img href="arroba.gif" alt="@" />gmail.com</span>
Luego, en el <head> de la página, referenciaríamos a dos ficheros javascript externos:
<script src="mi_ruta/amuse.js"></script>
<script src="js/mi_pag.js"></script>
El fichero "amuse.js" es el que implementa el interfaz de AMUSE. En el fichero mi_pag.js podríamos introducir lo siguiente:
RequireOnce("EmailAntiSpam.js");
De esta manera estaríamos llamando al módulo EmailAntiSpam, el cual, si miramos en su implementación interna haría cosas como:
//apoyarse en una librería de JavaScript agnóstico
RequireOnce("CrossBrowser.js");
function AddLinksToEmailSpans() {
//esta función buscaría todos los nodos 'span' que tuvieran
//la palabra "email" en su clase y les adjuntaría un nuevo
//comportamiento para su evento onclick, de manera que
//el visitante pudiera obtener un enlace "mailto:" generado
//automáticamente con código en el lado del cliente, con
//lo que evitamos el SPAM generado por los robots de búsqueda
//de direcciones de email
}
//adjuntar la función de conversión de nodos span al 'onload'
//de la página
CrossBrowser.AttachEventListener(window, "load", AddLinksToEmailSpans);
De esta manera, el usuario de nuestro nuevo módulo, denominado "EmailAntiSpam", sólo tendría que hacer una llamada RequireOnce a nuestro módulo, adjudicar la clase correspondiente a sus nodos span y olvidarse de escribir más código javascript.
Además, evitamos el tener que escribir etiquetas <script> por cada funcionalidad que queramos añadir. De esta manera, el propio código JavaScript puede llamar a otros ficheros javascript externos. Si nos fijamos también, los módulos deben adjudicar eventos a elementos de manera no intrusiva, es decir, que los comportamientos se añaden desde el propio código javascript, en lugar de tener que escribir invocaciones y eventos en el marcado HTML/XHTML.
Este módulo EmailAntiSpam en realidad aún no está implementado, pero cualquiera puede hacerlo con un poco de tiempo. Con AMUSE también distribuyo librerías y módulos de ejemplo, entre las cuales se unirá nuestro módulo EmailAntiSpam en cuanto lo tenga desarrollado (o bien si lo desarrolla antes un voluntario, pues todo esto es software GPL).
Voy a poner una pequeña descripción de estos añadidos que aporto con AMUSE:
Librerías:
- ArraysAdvanced.js (proporciona nuevos métodos útiles para el tipo de objeto array de javascript).
- CrossBrowser.js (proporciona un conjunto de API común para el acceso a ciertas características del DOM las cuales están implementadas en Internet Explorer de un modo distinto).
- CssHandling.js (proporciona funciones útiles para el tratamiento de CSS desde JavaScript).
- Debug.js (proporciona un sistema común para la muestra de mensajes a la hora de depurar JavaScript).
- FormValidation.js (proporciona un sistema de validación de formularios el cual está aún un poco en pañales y podría suponer otro proyecto GPL distinto por la cantidad de ideas que se me ocurren para ampliarlo).
- FunctionForEvent.js (proporciona un pequeño conjunto de funciones para adjudicar una función a múltiples eventos similares de un control, por ejemplo: onchange, onkeyup, keydown, keypress).
Módulos:
- AccessiblePopups.js (proporciona un sistema cómodo, accesible y no intrusivo para convertir nuestros enlaces en popups; también tiene una funcionalidad útil para hacer popups modales "crossbrowser").
- DisableAtSubmit.js (proporciona un comportamiento a los formularios de nuestra web que consiste en desactivar todos los botones una vez se haya activado el evento "submit", de manera que evitemos posibles errores de duplicación de datos o sobrecarga del servidor).
- IntroEnhancements.js (proporciona funcionalidades que tienen que ver con la pulsación de la tecla ENTER en los formularios, por ejemplo, un modo multinavegador de desactivar esta tecla, o bien que al pulsarla se consiga tener un efecto similar al haber pulsado la tecla tabulador para desviar el foco al siguiente control).
- OnlyScriptElements.js (podremos conseguir tener una funcionalidad inversa a la proporcionada por la etiqueta <noscript>).
- PreContent.js (nos permitirá mostrar un DIV transicional, al que normalmente se le pone el texto de "Cargando" y una animación, que se mostrará cuando el evento load de la página aún no haya llegado, o cuando se submita un formulario, se pinche en un enlace, o se pulse Adelante o Atrás en el navegador).
- PrintLink.js (nos permite crear enlaces que, al pulsarlos, mostrarán la interfaz de impresión del navegador del visitante).
Como véis, algunos son muy sencillos y tontos, pero otros yo creo que muy útiles. Sobre todo el módulo PreContent.js que en mi opinión es de obligado uso si queremos resolver el problema de usar JavaScript no intrusivo (es decir, que los controles de nuestra página adquieran sus comportamientos sólo cuando la página se cargue por completo) cuando la velocidad de conexión de nuestro visitante es algo lenta y existe el peligro de que use un formulario antes de que haya llegado la página entera.
KNOWN ISSUES:
- El módulo IntroEnhancements no desactiva bien el botón ENTER ni desplaza el foco a modo de tabulador si se usa la versión 1.5 de Firefox (sí funciona para la 1.0.x).
- El módulo PreContent no es compatible con el script IE7 de Dean Edwards (este problema de compatibilidad problablemente sólo aparecerá cuándo haya controles de formulario en la página).
- El sistema de dependencias de AMUSE se basa en llamadas XMLHttpRequest para obtener el contenido de los módulos. Actualmente estas llamadas se utilizan de modo síncrono, pero estoy en fase de estudio de desarrollo del modo asíncrono activable de manera opcional (por tanto, AMUSE aún no hace honor completo a su nombre aún pues usa "SJAX" en lugar de AJAX ;)
TO-DO:
- Arreglar las "Known Issues".
- Crear módulo EmailAntiSpam.js.
- Crear módulo FrameAway.js, que detecte si la web actual está englobada en un frame, en cuyo caso cambiará la URL de la barra de direcciones para mostrar sólo el frame interior, para evitar suplantaciones de webs, mediante el siguiente código:
if( window.top != window ) window.top.location = window.location;
- Integrar la función CssQuery() de Dean Edwards en mi módulo CssHandling.js.
- Crear un módulo "Marquee.js" que se encargue de emular la obsoleta y propietaria etiqueta <marquee> usando métodos JavaScript no intrusivos y funciones del nivel 2 DOM. Un pequeño ejemplo por donde podría empezar.
- Integrar "the IE Factor" en CrossBrowser.
Labels: General, Mozilla, Programacion, WebDev