Sunteți pe pagina 1din 176

ESCUELA TCNICA SUPERIOR DE INGENIERA INFORMTICA

INGENIERA TCNICA INFORMTICA DE SISTEMAS

AJAX, fundamentos y aplicaciones.

Realizado por

JUAN MARIANO FUENTES SERNA

Dirigido por

SERGIO GLVEZ ROJAS

Departamento

LENGUAJES Y CIENCIAS DE LA COMPUTACIN

UNIVERSIDAD DE MLAGA

MLAGA, (mes y ao)

UNIVERSIDAD DE MLAGA
ESCUELA TCNICA SUPERIOR DE INGENIERA INFORMTICA INGENIERA TCNICA INFORMTICA DE SISTEMAS

Reunido el tribunal examinador en el da de la fecha, constituido por: Presidente D/D._____________________________________________________________________________ Secretario D/D. _____________________________________________________________________________ Vocal D/D. ________________________________________________________________________________ para juzgar el proyecto Fin de Carrera titulado: AJAX, fundamentos y aplicaciones. del alumno D. Juan Mariano Fuentes Serna dirigido por D. Sergio Glvez Rojas

ACORD POR______________________ OTORGAR LA CALIFICACIN DE ________________________

Y PARA QUE CONSTE, SE EXTIENDE FIRMADA POR LOS COMPARECIENTES DEL TRIBUNAL, LA PRESENTE DILIGENCIA.

Mlaga, a

de

del 200_

El Presidente

El Secretario

El Vocal

Fdo:

Fdo:

Fdo:

AJAX, fundamentos y aplicaciones

ndice
Introduccin............................................................... iv Objetivos del proyecto ............................................... x PARTE 1: DOCUMENTACIN DE AJAX 1. El objeto XMLHttpRequest................................. 1
1.1. 1.2. 1.3. 1.4. 1.5. 1.6. 1.7. 1.8. 1.9. Descripcin del captulo....................................................................1 Razones para utilizar una librera en el lado cliente..........................1 La dependencia de los navegadores ..................................................2 Navegadores compatibles..................................................................5 Mtodos y propiedades del objeto.....................................................5 Constructor del objeto XMLHttpRequest .........................................7 Peticiones sncronas y asncronas......................................................8 La clase peticin AJAX...................................................................12 Escribir clases en Javascript............................................................17 1.9.1. Clases VS prototipos. ............................................................17 1.9.2. Prototype VS encerrar las funciones. ....................................18 1.9.3. Variables pblicas VS variables privadas. ............................19

2. Herramientas de depuracin ............................. 20


2.1. 2.2. 2.3. 2.4. 2.5. 2.6. Descripcin del captulo..................................................................20 Instalacin .......................................................................................20 La consola Javascript ......................................................................21 Document Model Object Inspector (inspector del DOM) ...............22 Venkman (Depurador de Javascript)...............................................24 Firebug (Todo lo anterior en uno) ...................................................28 2.6.1. Pestaa de consola.................................................................29 2.6.2. Pestaa de debugger (depurador). .........................................31 2.6.3. Pestaa del inspector. ............................................................32

3. Tcnicas bsicas de peticin de informacin ... 33


3.1. 3.2. 3.3. 3.4. 3.5. 3.6. 3.7. Descripcin del captulo..................................................................33 Insertar cdigo HTML ....................................................................33 Insertando imgenes usando el DOM .............................................35 Insertar cdigo Javascript................................................................38 DOM API........................................................................................41 DOM API e innerHTML enfrentados .............................................42 Encapsulacin del objeto XMLHttpRequest ...................................44 3.7.1. Peticin de cdigo HTML o texto.........................................45 3.7.2. Peticin de la direccin de una imagen. ................................46 3.7.3. Peticin de cdigo Javascript y lanzarlo. ..............................48 Manejo de errores............................................................................49 Dar soporte al usuario .....................................................................50

3.8. 3.9.

4. Ejemplos reales de uso para AJAX................... 54


4.1. 4.2. 4.3. Descripcin del captulo..................................................................54 La web actual ..................................................................................54 Mtodos GET, POST y caracteres especiales en internet ...............55 4.3.1. Introduccin a los mtodos GET y POST. ............................55 4.3.2. Caracteres especiales.............................................................55 4.3.3. Cambios en la librera para que acepte los 2 mtodos...........56 4.3.4. Ejemplo de uso de los mtodos GET y POST.......................57

AJAX, fundamentos y aplicaciones

4.4. 4.5. 4.6. 4.7. 4.8.

Leer las cabeceras del objeto XMLHttpRequest .............................59 Auto verificacin y rendimiento en AJAX......................................60 Pidiendo y analizando documentos XML .......................................63 Refrescar la pantalla automticamente............................................66 Una base de datos creada con el DOM y guardada con AJAX .......68 4.8.1. Crear una tabla dinmicamente .............................................70 4.8.2. Guardar informacin de innerHTML usando AJAX.............71 4.9. Dar informacin dinmicamente usando los eventos y el DOM.....75 4.9.1. Ejemplo 1 - Tabla relativa a otra tabla ..................................76 4.9.2. Ejemplo 2 - Tabla relativa al puntero del ratn .....................79 4.10. Auto completado empleando AJAX................................................81

5. Problemas de seguridad y desarrollo................ 86


5.1. 5.2. 5.3. 5.4. 5.5. 5.6. Descripcin del captulo..................................................................86 Problemas de desarrollo ..................................................................86 Problemas de seguridad...................................................................87 Poltica de mismo origen.................................................................89 AJAX Cross-site Scripting (AXSS) ................................................90 Desarrollo de una aplicacin web segura ........................................91 5.6.1. Cosas a tener en cuenta .........................................................91 5.6.1.1. Conexin cifrada ......................................................91 5.6.1.2. Sin cookies ...............................................................91 5.6.1.3. Verificacin completa del usuario............................91 5.6.1.4. Evitar la insercin de cdigo ....................................91 5.6.1.5. Verificacin completa de datos ................................91 5.6.1.6. Base de datos no accesible exteriormente ................91 5.6.1.7. Minimizar la superficie de impacto ..........................91 5.6.2. Esquema general de una aplicacin de ejmplo sencilla.........92 5.6.3. Resultados visibles de la aplicacin de ejemplo....................94 5.6.3.1. Funcionamiento de la aplicacin ..............................94 5.6.3.2. Aspectos que no se han cubierto ..............................97 5.6.3.3. Posibles puntos de ataque y mal funcionamiento .....97 Futuro de AJAX ..............................................................................97

5.7.

PARTE 2: DOCUMENTACIN DE LA APLICACIN 6. El poder de AJAX: Documentacin.................. 99


6.1. 6.2. Descripcin del captulo..................................................................99 Parte offline del juego ...................................................................100 6.2.1. Los juegos mas interactivos son solo bucles y banderas .....100 6.2.2. Representacin grfica en HTML, la necesidad de generar y destruir cdigo..................................................................102 6.2.3. Paso de parmetros en Javascript, la necesidad de emplear variables globales ................................................................103 6.2.4. Los eventos y el DOM, debemos de conocer algunos ........104 6.2.5. Leer el teclado para hacer los controles ..............................104 6.2.6. Algoritmos de control..........................................................105 6.2.7. Algoritmos de colisiones basados en hojas de estilo y optimizarlos.........................................................................106 6.2.8. Propiedades que deben cumplir los grficos para el juego..110 6.2.9. Precarga de imgenes ..........................................................111 6.2.10. Precarga de sonido ............................................................111 6.2.11. Cuadros de informacin: vida, objetos, mapa y consola ...112 6.2.12. Sistema de batalla y golpes ...............................................113 Parte online del juego....................................................................115 6.3.1. Disear la base de datos dependiendo de las necesidades del juego ..............................................................................115

6.3.

ii

AJAX, fundamentos y aplicaciones

6.4.

6.5.

6.3.2. La I.A. de los enemigos, los debe mover el servidor para evitar trampas ......................................................................116 6.3.3. Los objetos deben ser asignados por el servidor para evitar trampas ................................................................................119 6.3.4. El dao de un jugador a otro debe ser notificado por el que se ve golpeado ....................................................................121 6.3.5. El cambio de pantalla debe ser notificado y aceptado antes de realizarlo ................................................................121 6.3.6. Actualizar la posicin del jugador.......................................123 6.3.7. Actualizar objetos al cogerlos (Asncronamente)................123 A fondo .........................................................................................124 6.4.1. El archivo "servidor.jsp" .....................................................124 6.4.2. El archivo "calculosColisiones.js".......................................125 Requisitos de sistema y conexin..................................................127

PARTE 3: DOCUMENTACIN DE TOOLKITS 7. Un mundo de Toolkits y Frameworks ............ 128


7.1. 7.2. Descripcin del captulo................................................................128 Tipos de Toolkits y Frameworks sobre Java .................................128 7.2.1. Libreras Javascript en el lado cliente .................................128 7.2.2. Tecnologas Wrapper: jMaki...............................................129 7.2.3. Componentes Java Server Faces que utilizan AJAX...........129 7.2.4. Traductor Java a HTML/Javascript: Google Web Toolkit ..130 Tipos de Toolkits y Frameworks sobre lenguajes no Java ............130 7.3.1. .NET Frameworks ...............................................................130 7.3.2. Flash Frameworks ...............................................................130 7.3.3. PHP Frameworks ................................................................130 7.3.4. Otros Frameworks ...............................................................130 Conclusiones sobre el uso de los Toolkits.....................................130 Notas finales del captulo ..............................................................131

7.3.

7.4. 7.5.

8. Google Web Toolkit.......................................... 132


8.1. 8.2. Descripcin del captulo................................................................132 Los componentes de GWT............................................................132 8.2.1. Qu es Google Web Toolkit? ............................................132 8.2.2. Por qu usar GWT? ...........................................................133 Instalacin .....................................................................................133 Documentacin de GWT...............................................................135 Aplicacin de Ejemplo ..................................................................136 8.5.1. Iniciando un nuevo proyecto ...............................................136 8.5.2. Clases de intertaz de usuario de GWT ................................137 8.5.3. Manejadores de eventos en GWT .......................................139 8.5.4. Hojas de estilo CSS en GWT ..............................................142 8.5.5. Comunicaciones asncronas (AJAX) en GWT....................144 Notas finales sobre GWT ..............................................................147

8.3. 8.4. 8.5.

8.6.

PARTE 4: CONCLUSIONES, APNDICES Y BIBLIOGRAFA Conclusiones y Trabajo Futuro ............................ 150 Apndice HTML y XHTML ................................. 152 Apndice XML........................................................ 158 Apndice Javascript ............................................... 159 Bibliografa.............................................................. 162

iii

AJAX, fundamentos y aplicaciones

Introduccin
Antes de emprender la lectura de este texto hay ciertas cosas que sera bueno conocer para entender perfectamente que es AJAX y en qu lugar se ubica dentro del desarrollo de aplicaciones web. Por ello aprovecharemos esta introduccin para hablar del entorno que rodea a AJAX para que, cuando se comience el primer captulo, el lector est mejor preparado.

Las Tecnologas Web


Para comenzar, vamos a hacer un recorrido por la evolucin de la web hasta su estado actual para conocer en qu momento estamos y con qu tecnologas vamos a trabajar. En 1994 naci el Consorcio del World Wide Web de la mano de Berners-Lee, como mecanismo de estandarizacin para evitar guerras como las desencadenadas entre Internet Explorer y Netscape por las etiquetas HTML con las que se crean las pginas web (ya que cada navegador aada sus propias a las ya establecidas y muchas veces haba que realizar la misma aplicacin para uno y otro, y detectar el navegador antes de lanzarla). Como muestra de su esmero, este consorcio hoy en da sigue 7 pasos para la aprobacin de cualquier estndar web. A continuacin, se va a hacer una pasada rpida sobre los lenguajes bsicos utilizados para desarrollar aplicaciones web; estos lenguajes se explican brevemente y de forma prctica en los apndices. Es importante entender que mantienen mucha compatibilidad hacia atrs ya que en Internet conviven, hoy por hoy, pginas hechas con todas las versiones y stas a veces evolucionan a un ritmo sorprendente, as pues, cada versin normalmente extiende la anterior y no suele cambiar su sintaxis. La base de la web, el lenguaje HTML (HyperText Markup Language) HTML es el lenguaje bsico con el que podemos crear pginas web, con el paso del tiempo se han ido aadiendo etiquetas a las que ya tena adems de dar soporte a otros lenguajes como CSS (Cascade Style Sheets). Las versiones anteriores a la 3.2 del lenguaje estn ya caducadas y no son tiles hoy da; hoy en da un nuevo proyecto se debera emprender intentando seguir el estndar XHTML que es la ltima versin, aprobada en enero 2000. El lenguaje XHTML (eXtensible HTML) Este lenguaje es el que ha supuesto el mayor cambio desde 1997 (HTML 3.2), ya que busca proporcionar pginas web ricas en contenido a un amplio abanico de dispositivos PC, Mviles y dispositivos con conexin inalmbrica. XML (eXtensible Markup Language) XML es un metalenguaje que fue ideado para describir un conjunto de datos como pudiera ser los campos de una tabla para intercambiar informacin de forma rpida y fcil. Tambin permite especificar cmo tienen que ser los datos, por lo que se decidi especificar el lenguaje HTML con XML y naci XHTML. CSS (Cascade Style Sheets), Hojas de estilo En los primeros tiempos de las pginas web, tenamos en un mismo documento .html tanto los prrafos de texto e imgenes como su estilo, e indicbamos el tipo de atributos del texto dentro de las etiquetas HTML. Ahora que tenemos las CSS, asignamos a las etiquetas una clase dentro del documento .html, y a esa clase contenida en otro documento le especificamos el formato, de esta forma tenemos dos documentos:

iv

AJAX, fundamentos y aplicaciones

uno con los datos y otro que dice cmo deben representarse. Si quisiramos hacer un cambio en la representacin de una web compuesta por 100 pginas y las 100 leen el mismo CSS, con un solo cambio en el .css habramos cambiado toda la representacin automticamente.

DOM (Document Object Model) Cuando se carga una pgina Web en nuestro navegador, ste crea asociado a la pgina una serie de objetos en forma jerrquica, de manera que mediante un lenguaje utilizable en la parte del navegador, como Javascript, pueden modificarse las caractersticas de esos objetos y con ello la pgina en s. Ya que la pgina se actualiza inmediatamente si realizamos algn cambio con Javascript mientras sta est siendo visualizada, se habla de HTML dinmico: DHTML (Dynamic HTML). Lenguajes de Cliente, (Javascript principalmente) Cuando el usuario ve una pgina web en su navegador, sta puede tener, aparte del cdigo HTML o XHTML, cdigo escrito en un lenguaje de script que se utiliza normalmente para dotar de dinamismo a las pginas y obtener DHTML. El principal lenguaje utilizado hoy da es Javascript; naci con Netscape 2.0 y la versin actual es la 1.5 que implementan Netscape 6 y Mozilla Firefox. Por su parte Microsoft tambin ha evolucionado hasta presentar su versin 5.5 de Jscript (es una implementacin abierta de Javascript). Lenguajes de Servidor, (JSP, Java Server Pages) A veces necesitamos enviar informacin al servidor y que ste la procese y nos responda (por ejemplo al conectarse a nuestra cuenta de correo), o que guarde informacin (por ejemplo en un foro). Para este procesamiento se utilizan los lenguajes de servidor PHP, JSP (el que utiliza este texto), ASP, etc. Puedes elegir el que ms te guste con sus pros y sus contras, y su dinmica de funcionamiento es la siguiente: Tenemos una pgina web con cdigo de alguno de estos lenguajes guardada en el servidor; cuando un usuario (cliente) accede a sta, el servidor la ejecuta y le devuelve el resultado al cliente, que ser solo HTML, no contendr lenguajes del lado del servidor ya que el navegador no los comprende. Visin en Conjunto Tendremos un usuario que carga en su navegador una pgina compuesta por XHTML y Javascript cuyo estilo est en un archivo CSS si lo separamos; el navegador crea el DOM asociado a la pgina y el Javascript lo modifica para conseguir dinamismo. Tenemos en el servidor pginas hechas con JSP, cuando el usuario pide una de estas pginas, el servidor la ejecuta y devuelve el resultado al usuario ya sea una pgina XHTML u otro tipo informacin.

Las RIA (Rich Internet Application Technologies)


Para que entendamos la necesidad de uso de AJAX, vamos a ver una serie de trminos, problemas y posibles soluciones y ver cul es el papel de AJAX dentro de todo esto. CARACTERISTICAS DE UNA APLICACIN DE ESCRITORIO Si le echamos un vistazo a una aplicacin tpica de escritorio vemos que tiene las siguientes cualidades. Responde de forma intuitiva y rpida. Da respuesta inmediata a los actos del usuario. CARACTERISTICAS DE UNA APLICACIN WEB CONVENCIONAL Cliqueamos, esperamos y la pgina se refresca. La pgina refresca todos los eventos, envos y datos de la navegacin. El usuario debe esperar la respuesta. Modelo de peticin/respuesta de comunicaciones sncronos. El estado del trabajo que estamos desarrollando se basa en qu pgina estamos.

AJAX, fundamentos y aplicaciones

PROBLEMAS DE UNA APLICACIN WEB CONVENCIONAL Respuesta lenta. Prdida del contexto durante el refresco. Perdemos informacin en la pantalla que habamos rellenado. Perdemos la posicin del scroll de la pantalla. No tenemos respuesta inmediata a nuestros actos. Tenemos que esperar que llegue la siguiente pgina. Por estas razones nacieron las (RIA), Rich Internet Application Technologies. FORMAN PARTE DE LAS RIA Las siguientes ideas y tecnologas son, si no todas, las mas importantes y utilizadas en las paginas web actualmente. -Applet -Adobe Flash -Java WebStart -DHTML Hace un par de aos se empez a usar AJAX. -AJAX Desglosemos cada una de las RIA para ver sus pros y sus contras. APPLET POSITIVO o Puede hacer uso de todas las APIS Java. o Su desarrollo tiene un patrn de trabajo bien definido. o Puede manipular grficos, diferentes hebras y crear Interfaces Usuario avanzadas. NEGATIVO o El navegador necesita un plug-in. o El tiempo de bajada del APPLET puede ser muy grande. ADOBE FLASH Fue diseado para ver Pelculas Interactivas aunque ahora se utiliza mucho para hacer juegos monousuario para web ya que es programable con ActionScript. POSITIVO o Es capaz de dar un aspecto visual inigualable actualmente con otras tecnologas para una pgina web. o Muy bueno para mostrar grficos vectoriales 3D. NEGATIVO o El navegador necesita un plug-in. o ActionScript es una tecnologa propietaria. o El tiempo de bajada del vdeo o programa suele ser muy grande (lo bonito se paga). JAVA WEBSTART Podemos decir que nos proporciona desde Internet una aplicacin de escritorio. POSITIVO o Una vez cargado, nos da una experiencia similar a una aplicacin de escritorio. o Utiliza Tecnologa muy extendida como Java. o Las aplicaciones se pueden firmar digitalmente. o Se pueden seguir utilizando una vez desconectado NEGATIVO o El navegador necesita un plug-in. o Problema de compatibilidad con las aplicaciones viejas ya que se han cambiado algunas cosas. o El tiempo que puede tardar en descargar una aplicacin de escritorio es demasiado grande.

vi

AJAX, fundamentos y aplicaciones

DHTML = HTML + Javascript + DOM + CSS POSITIVO o Se utiliza para crear aplicaciones interactivas y ms rpidas. NEGATIVO o La comunicacin es sncrona. o Requiere el refresco completo de la pgina, perdiendo parte del contexto. AJAX = DHTML + XMLHttpRequest Es un refinamiento del DHTML, utiliza todas sus herramientas, sumndole el objeto XMLHttpRequest para obtener informacin asincronamente y refrescar solo la parte necesaria de la pgina sin perder nada del contexto, se terminaron los problemas del DHTML. POSITIVO o La mejor tecnologa RIA hasta el momento. o Est en su mejor momento para la industria. o No necesitamos descargar plug-in. NEGATIVO o Todava existen incompatibilidades entre navegadores (cada vez menos). o Desarrollo con Javascript, hoy da no suficientemente explorado. Con todo lo anterior, vemos que hoy en da la mejor posibilidad y ms nueva para ofrecer una experiencia rica al usuario es la utilizacin de AJAX y la verdad es que proporciona todo lo que promete, como se puede ver en los ejemplos reales en los que se ha utilizado.

Algunos ejemplos reales de AJAX


Lo mejor es ver algunas posibilidades del uso de AJAX, se va a hacer mencin primero a la que fue la primera aplicacin AJAX conocida, Microsoft invent el objeto XMLHttpRequest y lo us en su versin web del Outlook en 1998.

Figura 0.1 Outlook Web Access, imagen encontrada buscando en google Cmo, se preguntaran algunas personas, hasta el ao 2005 no se empez a utilizar esta tecnologa realmente?, la respuesta es sencilla, solo Internet Explorer era capaz de generar el objeto XMLHttpRequest(llamado de otro modo). Cuando Mozilla Firefox, el navegador ms grande de la competencia, implement un objeto compatible, y ms tarde el resto de navegadores de cdigo abierto, empez el boom.

vii

AJAX, fundamentos y aplicaciones

Otro gran ejemplo del uso de AJAX es Google Maps ( http://maps.google.com/ ), que ha sido mas conocido debido a que es ms actual y la verdad llama muchsimo ms la atencin por la cantidad de zoom que se puede hacer en los mapas, convirtindose en una verdadera gua para no perdernos por la ciudad.

Figura 0.2 Google Maps, vista de es Espaa desde el mapa hbrido (Mapa+Satlite)

Figura 0.3 Google Maps, vista de la residencia de estudiantes de la universidad de Mlaga Como se puede apreciar en la figura 0.3, en la que se ha subrayado la residencia de estudiantes oficial de la universidad, la aplicacin tiene una calidad en las imgenes envidiable y todava nos podemos acercar ms y movernos, todo como si fuera una aplicacin de escritorio, sin cambiar de pgina en ningn momento, todo el mapa se va generando asincronamente haciendo peticiones por debajo al servidor.

viii

AJAX, fundamentos y aplicaciones

Notas finales
Como muestra la evolucin de las tecnologas web y los ejemplos reales del uso de AJAX llega el momento en que las compaas que se dedican al desarrollo web hagan los cursillos de reciclaje a sus empleados, la documentacin que sigue ha sido desarrollada basndose en muchas fuentes, se ha hecho intentando que la curva de aprendizaje sea lo menos pronunciada posible por si hay personas que se quieren iniciar en el desarrollo web con AJAX.

ix

AJAX, fundamentos y aplicaciones

Objetivos del proyecto


El proyecto se puede dividir en 2 grandes bloques que coinciden con sus objetivos: El primero es desarrollar una documentacin completa y amena en espaol, con sus ejemplos y cdigos fuente fciles de leer sobre la tcnica de programacin AJAX ya que al empezar este proyecto no exista apenas nada en espaol. En las fechas en las que se finaliz el proyecto surgieron un par de libros, pero stos son de pago con lo cual resultan menos atractivos que una documentacin de libre reproduccin. El segundo objetivo es desarrollar una demostracin que intente llevar al lmite el uso de la tcnica de programacin, ya que esta tcnica se basa en la comunicacin asncrona y en segundo plano con el servidor la idea fue desarrollar como demostracin un juego multijugador online y se consigui satisfactoriamente. Con estos dos grandes bloques terminados se habra conseguido tanto una documentacin libre para la comunidad de usuarios con inters en el aprendizaje de esta tcnica como una demostracin de sus posibilidades que muestre que estas son enormes. Como aadido a lo que se especificaba en el anteproyecto se ha aadido un tercer bloque que habla de los diversos Frameworks y Toolkits de desarrollo AJAX, centrndose finalmente en Google Web Toolkit ya que es de uso libre y utiliza la tecnologa Java por debajo por lo que resulta muy atractivo.

AJAX, fundamentos y aplicaciones

Captulo 1:
El objeto XMLHttpRequest
1 Introduccin

1.1 Descripcin del captulo


Para comenzar se va a construir una pequea librera (archivo cargado por el navegador) programada haciendo uso de Javascript, primero para comprender cmo funciona el objeto XMLHttpRequest que se ha hecho muy famoso ya que constituye las entraas de AJAX y segundo porque es muy recomendable utilizar una librera en el lado cliente para ahorrarnos no slo problemas, como veremos seguidamente, sino tambin para no repetir el mismo cdigo continuamente. Los apartados del captulo con su descripcin general son las siguientes: 1.2 Razones para utilizar una librera en el lado cliente Enumeraremos las razones para hacer la librera ya que sino no tiene mucho sentido hacerla. 1.3 La dependencia de los navegadores Veremos las diferencias a la hora de crear el objeto en los diferentes navegadores, pero tambin veremos que el modo de empleo es igual. 1.4 Navegadores compatibles Aunque el objeto no es 100% compatible con todos los navegadores debemos hacernos a la idea que s en casi todas las ltimas versiones de los navegadores actuales. 1.5 Mtodos y propiedades del objeto En este apartado tendremos una visin general de todas las funciones y propiedades a las que podemos acceder y en qu momento tiene sentido utilizarlas. 1.6 Constructor del objeto XMLHttpRequest Haremos una funcin que construya el objeto compatible al navegador con el que estamos usando. 1.7 Peticiones sncronas y asncronas Comprender qu diferencia hay entre ellas cuando se utilizan haciendo uso del objeto XMLHttpRequest y por qu slo usaremos las asncronas. 1.8 La clase peticin AJAX Construiremos una clase que nos libere del trabajo repetitivo de crear ciertas funciones que son necesarias en cada peticin. 1.9 Escribir clases en Javascript Comprender el por qu est construida la clase peticin AJAX de la forma que est, as como una visin de cmo se crean los prototipos (clases de javascript) y las diferencias de stos con las clases de Java que son mas conocidas para que se comprenda bien tanto el cdigo de la clase peticin AJAX como el siguiente cdigo que escribamos en Javascript.

1.2 Razones para utilizar una librera en el lado cliente


Caractersticas bsicas que debe cubrir una librera en el lado del cliente La tecnologa que use el servidor debe ser indiferente, es decir no debe actuar directamente con tecnologas como PHP, JSP, ASP, etc... Debe ser accesible en cualquier momento, localmente a ser posible. Debe manejar las incompatibilidades de los navegadores y hacer el cdigo compatible. Debe manejar la comunicacin asncrona ocultando las operaciones a bajo nivel. Debe dar al desarrollador una forma fcil de acceder al DOM (Document Object Model). Debe dar cierto manejo ante errores, primero para que el programa no se rompa y segundo para

-1-

AJAX, fundamentos y aplicaciones

proporcionar cierta informacin al desarrollador. Debera de intentar seguir una programacin orientada a objetos y que stos fueran reutilizables.

Como puede verse las libreras ahorrarn multitud de problemas, de otra manera intentar hacer una aplicacin Web medianamente vistosa se convierte en un trabajo para chinos, que adems ser casi imposible de mantener. Caractersticas avanzadas que podra cubrir una librera en el lado del cliente o cmo ayuda al desarrollo Proporcionar diferentes objetos grficamente agradables directamente, como calendarios, botones, ventanas desplegables, etc... Proporcionar interfaces de usuario avanzadas, con animaciones y diferentes efectos grficos que hagan la experiencia ms agradable. Razones comerciales para utilizar una de las libreras avanzadas ya existentes en Internet Son mejores que la tuya propia ya que estn echas normalmente por multitud de desarrolladores. Establecen comunidades de forma que la comunidad le aade prestaciones y es fcil conseguir ayuda en sus foros. Los entornos IDE no tardarn mucho tiempo en darle soporte, al menos a las ms importantes de cdigo abierto. La librera que construiremos cubrir las caractersticas bsicas; para cubrir las caractersticas avanzadas existen multitud de libreras de cdigo abierto y comerciales, adems no aportan demasiado a la comprensin del problema que resuelve AJAX sino ms bien, como he dicho ya, mejoran la experiencia visual. Adems muchas de ellas pueden ser difciles de utilizar para el usuario no experto y las que pueden ser mas fciles esconden totalmente el problema, las usaremos para trabajar mas fcilmente una vez sepamos utilizar AJAX a bajo nivel. Si vamos a utilizar AJAX a bajo nivel lo primero que debemos aprender es como crear el objeto en los diferentes navegadores y las similitudes y diferencias que son mnimas al tratarlo en uno y otro, adems de solucionarlas, as que empezaremos por aqu en el siguiente punto.

1.3 La dependencia de los navegadores


Antes de empezar a trabajar debemos de saber que el objeto XMLHttpRequest no es estndar, fue originariamente inventado por Microsoft, usado desde Internet Explorer 5.0 como un objeto ActiveX, siendo accesible mediante Javascript. Mozilla en su versin 1.0 implement un objeto compatible. Ya que estos dos son los navegadores mas difundidos y adems hay navegadores basados en el cdigo de Mozilla, intentaremos que lo que hagamos sea compatible en ambos, de esta manera conseguiremos que nuestro cdigo funcione mas del 90% de las veces ya que estos navegadores abarcan el mercado. Ejemplo 1 en Internet Explorer Archivo ejemploIE.html <html> <head> <title>Pgina de ejemplo</title> <script language="JavaScript" type="text/javascript"> var peticion01 = null; //Creamos la variable para el objeto XMLHttpRequest //Como este ejemplo es de Internet Explorer creamos un objeto ActiveX peticion01 = new ActiveXObject("Microsoft.XMLHTTP"); function Coger(url) //Funcin coger, en esta caso le entra una direccin relativa al documento actual. { if(peticion01) //Si tenemos el objeto peticion01 { peticion01.open('GET', url, false); //Abrimos la url, false=forma sncrona peticion01.send(null); //No le enviamos datos al servidor. //Escribimos la respuesta en el campo con ID=resultado

-2-

AJAX, fundamentos y aplicaciones

document.getElementById('resultado').innerHTML = peticion01.responseText; } } </script> </head> <body> <!--Cuando ocurra el evento oneclick se llamara la funcin coger--> <button onclick="Coger('datos/videoclub.xml')">Coge un documento</button> <table border="4"> <tr> <!--El campo con id=resultado se sustituir por causa de que ese id est en la funcin coger--> <td><span id="resultado">Sin resultado</span></td> </tr> </table> </body> </html>

Archivo datos/videoclub.xml <?xml version="1.0" encoding="UTF-8"?> <VideoClub> <Pelicula> <Titulo>El rey Leon</Titulo> <Duracion>87 Min</Duracion> <Genero>Animacion infantil</Genero> </Pelicula> <Pelicula> <Titulo>Aladin</Titulo> <Duracion>86 Min</Duracion> <Genero>Animacion infantil</Genero> </Pelicula> </VideoClub> Por ahora no usar archivos XML con acentos, ya que estos caracteres saldrn sustituidos por el smbolo de interrogacin y es un problema que no se va a resolver aqu.

Primero Cargamos la pgina: Figura 1.1 Primer ejemplo, antes de pulsar el botn Segundo pulsamos el botn:

-3-

AJAX, fundamentos y aplicaciones

Figura 1.2 Primer ejemplo, despus de recibir la informacin Como vemos se ha actualizado el campo de la pgina sin necesidad de refrescarla con el botn del navegador, pero este ejemplo no funcionara en Mozilla Firefox, veamos los cambios que habran en el cdigo.

Ejemplo 1 en Mozilla Firefox Lo nico que tendremos que hacer ser copiar el archivo ejemploIE.html, renombrarlo ejemploMF.html y cambiar la lnea: peticion01 = new ActiveXObject("Microsoft.XMLHTTP"); Por la siguiente: peticion01 = new XMLHttpRequest(); En los siguientes ejemplos, el cdigo remarcado resalta qu cambia entre un ejemplo y el siguiente. Con esto generamos en vez del Objeto ActiveX el XMLHttpRequest que es compatible con ste, al ser compatible no necesitamos cambiar mas lneas de cdigo, veamos el ejemplo otra vez, funcionando ahora en Mozilla Firefox. Primero Cargamos la pgina:

Figura 1.3 Primer ejemplo, ahora cargado en Mozilla Firefox Segundo pulsamos el botn:

Figura 1.4 Primer ejemplo, mostrando el resultado en Mozilla Firefox

-4-

AJAX, fundamentos y aplicaciones

Como hemos visto la diferencia en el cdigo no es mas que cambiar el objeto que se crea, para que el ejemplo funcione en cualquier navegador bastara con detectar el tipo de navegador y crear un objeto u otro; como esto es posible, es lo siguiente que haremos, as dejaremos de pensar en los navegadores, pero antes sera bueno que le echemos un vistazo a los navegadores compatibles y las propiedades del objeto, as terminaremos con la parte mas terica.

1.4 Navegadores compatibles


Aunque nos centremos en Mozilla Firefox e Internet Explorer, la lista completa de los navegadores que actualmente soportan el objeto XMLHttpRequest es la siguiente: Mozilla Firefox 1.0 y superiores Netscape version 7.1 y superiores Apple Safari 1.2 y superiores Microsoft Internet Exporer 5 y superiores Konqueror Opera 7.6 y superiores Como vemos esta muy extendido aunque no todos los navegadores lo soportan, ya que hay ms, pero podemos decir que en ordenadores personales superamos el 95% de los posibles clientes, adems de esto se est trabajando actualmente en navegadores para llevar AJAX hasta los dispositivos mviles.

1.5 Mtodos y propiedades del objeto


MTODOS Ya sea en Internet Explorer como en Mozilla Firefox, como hemos visto anteriormente, el objeto tiene una serie de mtodos (funciones) que usamos para hacer la peticin y se hace de igual manera en los dos navegadores. Los mtodos open y send son los que empleamos para establecer la conexin e iniciar la conexin, podemos decir que son los obligatorios y los que vamos a utilizar ms. Mtodos Descripcin Segn el mtodo (GET o POST) y la url se prepara y abre la peticin. Si la banderaAsync=true Peticin asncrona, si es fase la peticin es open(metodo,URL,banderaAsync, sncrona. nombreuser, password) Nombreuser y password solo se usan para acceder a recursos protegidos. Ejecuta la peticin, donde la variable contenido son datos que se send(contenido) envan al servidor. abort() Para la peticin que est procesando. getAllResponseHeaders() Devuelve todas las cabeceras de la llamada HTTP como un string. getResponseHeader(cabecera) Devuelve la cabecera identificada por la etiqueta. Establece el valor de una etiqueta de las cabeceras de peticin antes setRequestHeader(etiqueta,valor) de que se haga la peticin. PROPIEDADES Adems el objeto tambin tiene una serie de propiedades que cuando hacemos una peticin de informacin nos indican cmo fue la peticin (una vez terminada) y que normalmente utilizaremos de la siguiente manera.

//Cdigo devuelto por el servidor, del tipo 404 (documento no encontrado) o 200 (OK). document.getElementById('estado').innerHTML = peticion01.status; //Mensaje de texto enviado por el servidor junto al cdigo (status), para el caso de cdigo 200 contendr OK. document.getElementById('txtestado').innerHTML = peticion01.statusText; //Los datos devueltos por el servidor en forma de cadena. document.getElementById('txtresultado').innerHTML = peticion01.responseText;

-5-

AJAX, fundamentos y aplicaciones

//Datos devueltos por el servidor en forma de documento XML que puede ser recorrido mediante las funciones del DOM (getEementsByTagName, etc). document.getElementById('xmlresultado').innerHTML = peticion01.responseXML;

Como vemos ahora, en el ejemplo anterior se ha utilizado el responseText para coger los datos del documento XML como texto (un string) y como hemos hecho en el ejemplo anterior podemos aadir campos a la tabla con el id indicado y obtener el siguiente resultado.

Figura 1.5 Propiedades del objeto mostradas en Internet Explorer y Mozilla Firefox En la figura 1.5 se tiene que las 3 primeras propiedades del objeto son iguales en los 2 navegadores, en cambio en la ltima dependiendo del navegador se muestra un texto diferente. A todo lo anterior podemos sumar otras propiedades que podemos consultar mientras dura la peticin para conocer su estado.

/*Sus valores varan desde 0(no iniciada) hasta 4(completado), en cualquier caso tienes que hacer un switch, no puedes escribir su valor directamente.*/ document.getElementById('estadoconexion').innerHTML = peticion01.readyState; /*Contiene el nombre de la funcin ejecutada cada vez que el estado conexin cambia, es decir, nosotros asignamos una funcin que cada vez que el estado dado por readyState cambia se lanza, por ejemplo podramos poner un grfico cuando estemos en el estado de carga, etc..., como la anterior, no la puedes escribir directamente como texto*/ document.getElementById('estadocambiante').innerHTML = peticion01.onreadystatechange

Con lo cual, el cuadro resumen, de las propiedades del objeto seria el siguiente: Propiedades status statusText responseText responseXML readyState Descripcin Cdigo devuelto por el servidor Texto que acompaa al cdigo Datos devueltos formato string Datos devueltos formato Objeto XML Estado actual de la peticin. 0: Sin iniciar

-6-

AJAX, fundamentos y aplicaciones

Propiedades

onreadystatechange

Descripcin 1: Cargando 2: Cargado 3: Interactivo (algunos datos devueltos) 4: Completado Puntero a la funcin del manejador que se llama cuando cambia readyState.

Lo que hemos dicho aqu lo usaremos en los ejemplos siguientes ya que AJAX se basa en jugar con el objeto XMLHttpRequest como ya hemos dicho anteriormente.

1.6 Constructor del objeto XMLHttpRequest


Llegados a este punto y como hemos dicho anteriormente, haremos una sencilla funcin que detectar el navegador dnde est funcionando la pagina web y segn ste se crear el objeto de Internet Explorer o Mozilla Firefox o lo que es lo mismo el objeto ActiveX de Microsoft o el objeto XMLHttpRequest estndar que soportan el resto de los navegadores. Los cambios en el cdigo principal del ejemplo anterior son mnimos y estn remarcados, lo nico que vamos a hacer va a ser aadir una librera que contendr una funcin a la que llamamos en vez de la funcin XMLHttpRequest() o ActiveXObject(). Archivo ejemplo.html <html> <head> <title>Pgina de ejemplo</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" type="text/javascript"> var peticion01 = null; //Creamos la variable para el objeto xmlhttprequest //Este ejemplo emplea un contructor, debera funcionar en cualquier navegador. peticion01 = new ConstructorXMLHttpRequest(); function Coger(url) //Funcin coger, en esta caso le entra una direccin relativa al documento actual. { if(peticion01) //Si tenemos el objeto peticion01 { peticion01.open('GET', url, false); //Abrimos la url, false=forma sncrona peticion01.send(null); //No le enviamos datos al servidor //Escribimos la respuesta en el campo con ID=resultado document.getElementById('resultado').innerHTML = peticion01.responseText; } } </script> </head> <body> <!--Cuando ocurra el evento oneclick se llamara la funcin coger--> <button onclick="Coger('datos/videoclub.xml')">Coge un documento</button> <table border="4"> <tr> <!--El campo con id=resultado se sustituir por causa de que ese id est en la funcin coger--> <td><span id="resultado">Sin resultado</span></td> </tr> </table> </body> </html>

Esta es la parte ms sencilla, ahora dmosle un vistazo a la funcin interesante, detectaremos el navegador o ms bien si tiene un mtodo de creacin XMLHttpRequest o ActiveXObject, estos se pueden comprobar si estn en el objeto window que en Javascript es el objeto ms alto en la jerarqua del navegador.

-7-

AJAX, fundamentos y aplicaciones

Archivo lib\ConstructorXMLHttpRequest.js Function ConstructorXMLHttpRequest() { if(window.XMLHttpRequest) /*Vemos si el objeto window (la base de la ventana del navegador) posee el mtodo XMLHttpRequest(Navegadores como Mozilla y Safari). */ { return new XMLHttpRequest(); //Si lo tiene, crearemos el objeto con este mtodo. } else if(window.ActiveXObject) /*Sino tena el mtodo anterior, debera ser el Internet Exp. un navegador que emplea objetos ActiveX, lo mismo, miramos si tiene el mtodo de creacin. */ { /*Hay diferentes versiones del objeto, creamos un array, que contiene los diferentes tipos desde la versin mas reciente, hasta la mas antigua */ var versionesObj = new Array( 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'); for (var i = 0; i < versionesObj.length; i++) { try { /*Intentamos devolver el objeto intentando crear las diferentes versiones se puede intentar crear uno que no existe y se producir un error. */ return new ActiveXObject(versionesObj[i]); } catch (errorControlado) //Capturamos el error, ya que podra crearse otro objeto. { } } } /* Si el navegador llego aqu es porque no posee manera alguna de crear el objeto, emitimos un mensaje de error. */ throw new Error("No se pudo crear el objeto XMLHttpRequest"); } Para su mejor comprensin se ha comentado el cdigo con mucha atencin, si se lee tranquilamente se entiende perfectamente. Ahora podemos dejar de preocuparnos por el navegador, y nos podemos centrar en utilizar el objeto correctamente.

1.7 Peticiones sncronas y asncronas


Si volvemos sobre nuestro ejemplo y nos fijamos en la siguiente lnea: peticion01.open('GET', url, false); //Abrimos la url, false=forma sncrona Si pensamos un momento la tcnica AJAX viene de Asncrono, entonces porqu estamos haciendo peticiones sncronas y que diferencia hay?, esto es lo siguiente que vamos a ver. Si realizamos un peticin sncrona el navegador queda bloqueado hasta que recibe la informacin, hasta ahora no lo hemos notado ya que estamos haciendo unas pruebas muy sencillas y no estamos recibiendo gran cantidad de informacin. Para darnos cuenta de la situacin vamos a pedir una pgina hecha en JSP que tiene una espera corta, seguimos basndonos en nuestro ejemplo, cambiando una lnea:

-8-

AJAX, fundamentos y aplicaciones

Archivo ejemplo.html <html> <head> <title>Pgina de ejemplo</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" type="text/javascript"> var peticion01 = null; //Creamos la variable para el objeto xmlhttprequest peticion01 = new ConstructorXMLHttpRequest(); function Coger(url) //Funcin coger, en esta caso le entra una direccin relativa al documento actual. { if(peticion01) //Si tenemos el objeto peticion01 { peticion01.open('GET', url, false); //Abrimos la url, false=forma sncrona peticion01.send(null); //No le enviamos datos al servidor //Escribimos la respuesta en el campo con ID=resultado document.getElementById('resultado').innerHTML = peticion01.responseText; } } </script> </head> <body> <!--Cuando ocurra el evento oneclick se llamara la funcin coger--> <button onclick="Coger('espera.jsp')">Coge un documento</button> <table border="4"> <tr> <!--El campo con id=resultado se sustituir por causa de que ese id est en la funcin coger--> <td><span id="resultado">Sin resultado</span></td> </tr> </table> </body> </html>

Archivo espera.jsp <% Thread.sleep(1000); out.print("Es molesto tener que esperar de esta manera porque no puedes hacer nada."); %> Aparte de esto, seguiremos utilizando el constructor que hemos hecho, tal como est, ejecutemos la pgina ver el resultado.

-9-

AJAX, fundamentos y aplicaciones

Figura 1.6 Problemas de una peticin sncrona, mostrados en Mozilla Firefox. El botn permanece pulsado y la pgina bloqueada (no responde) hasta que se recibe la informacin pedida. En cambio si realizamos una peticin asncrona el usuario queda libre de seguirse movindose por la pgina hasta que recibe la informacin, es decir, aumentamos la interactividad, en el ejemplo anterior, no nos quedaramos con el botn pulsado esperando algo y podramos seguir desplazndonos por la pgina (somos conscientes de que en este ejemplo no hay mucho por donde desplazarse), para esto bastara con cambiar el false por un true: peticion01.open('GET', url, true); //Abrimos la url, true=forma asncrona El bloque de cdigo Javascript funciona igual, slo que queda bloqueado en segundo plano a la espera de recibir el resultado de la peticin pero sin bloquear al navegador; de ahora en adelante utilizaremos peticiones asncronas para aumentar la interactividad. Ahora surge un problema, cmo sabe el usuario que est esperando la informacin, si no tiene muestra alguna de ello?, l slo sabe que ha pulsado un botn (en nuestro ejemplo), lo ideal sera que recibiera alguna seal, bueno eso es lo que haremos en el siguiente ejemplo, de forma asncrona. Archivo ejemplo.html

- 10 -

AJAX, fundamentos y aplicaciones

<html> <head> <title>Pgina de ejemplo</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" type="text/javascript"> var peticion01 = null; //Creamos la variable para el objeto xmlhttprequest peticion01 = new ConstructorXMLHttpRequest(); function estadoPeticion() //Funcin que se llama cada vez que cambia el estado de peticion01.readyState. { switch(peticion01.readyState) //Segn el estado de la peticin devolvemos un Texto. { case 0: document.getElementById('estado').innerHTML = "Sin iniciar"; break; case 1: document.getElementById('estado').innerHTML = "Cargando"; break; case 2: document.getElementById('estado').innerHTML = "Cargado"; break; case 3: document.getElementById('estado').innerHTML = "Interactivo"; break; case 4: document.getElementById('estado').innerHTML = "Completado"; //Si ya hemos completado la peticin, devolvemos adems la informacin. document.getElementById('resultado').innerHTML = peticion01.responseText; break; } } function Coger(url) //Funcin coger, en esta caso le entra una direccin relativa al documento actual. { if(peticion01) //Si tenemos el objeto peticion01 { peticion01.open('GET', url, true); //Abrimos la url, true=forma asncrona /*Asignamos la funcin que se llama cada vez que cambia el estado de peticion01.readyState Y LO HACEMOS ANTES THE HACER EL SEND porque inicia la transmisin.*/ peticion01.onreadystatechange = estadoPeticion; peticion01.send(null); //No le enviamos datos a la pagina que abrimos. } } </script> </head> <body> <!--Cuando ocurra el evento oneclick se llamara la funcin coger--> <button onclick="Coger('espera.jsp')">Coge un documento</button> <table border="4"> <tr> <td><span id="estado">Estado peticin</span></td> <!--Campo para indicar el estado de la peticin--> <td><span id="resultado">Sin resultado</span></td> </tr> </table> </body> </html> Adems es bueno cambiar el texto del archivo JSP, por uno mas acorde. Archivo espera.jsp

- 11 -

AJAX, fundamentos y aplicaciones

<% Thread.sleep(1000); out.print("Ahora la espera es menos molesta."); %> Probamos la pgina y el resultado que nos queda es:

Figura 1.7 Una peticin asncrona, mostrada en Mozilla Firefox El resultado es satisfactorio, el texto que hemos puesto tampoco es que vaya a distraer mucho al usuario Pero, cuando avancemos un poco ms, podremos cargar imgenes que perfectamente pueden ser GIFs animados y mostrar as los diferentes estados de carga y error, quedando mucho ms vistoso.

1.8 La clase peticin AJAX


Por ahora hemos hecho un recorrido que nos ha ayudado a comprender cmo utilizar el objeto XMLHttpRequest para pedir informacin de forma muy bsica y hemos visto tanto sus mtodos como propiedades. Llegado aqu debemos fijarnos en el anterior ejemplo, para hacer una simple peticin y poder controlar toda la informacin que nos da el objeto nos hemos visto obligados a hacer una funcin coger(url) y una estadoPeticion(), juntas son unas tres cuartas partes del documento. Vamos a construir una clase que contenga el objeto y sus funciones principales, de esta forma obtendremos un cdigo ms limpio y reutilizable, ya que tendremos una caja negra que funciona sin que nosotros tengamos que pensar demasiado (una vez que comprendamos lo que hace, por supuesto).

- 12 -

AJAX, fundamentos y aplicaciones

Primera aproximacin (Errnea): Como el objeto XMLHttpRequest no tiene un campo de identificador, vamos a aadrselo, de esta manera podremos reconocerlo(o eso podemos pensar), si tenemos varios simultneamente. Archivo ejemploMalo.html <html> <head> <title>Pgina de ejemplo</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" type="text/javascript"> function estadoPeticion() { window.alert( "Que peticin llego? (" + this.nombre + ")"); //Se supone que debera ser la del objeto al que se asign. } function Coger(peticionAjax, url) //Le pusimos un campo mas, para usarla con cualquier peticin. { if(peticionAjax){ //Hacemos la peticion Ajax estandar peticionAjax.open('GET', url, true); peticionAjax.onreadystatechange = estadoPeticion; peticionAjax.send(null); } } var Peticion01 = ConstructorXMLHttpRequest(); //Usamos el constructor para obtener un objeto compatible. Peticion01.nombre = "Peticion01"; //Un campo nombre, para saver quien es. window.alert( "Comprobando objeto 01 (nombre) = (" + Peticion01.nombre + ")"); //Vemos que se le asigna el nombre var Peticion02 = ConstructorXMLHttpRequest(); //Usamos el constructor para obtener un objeto compatible. Peticion02.nombre = "Peticion02"; //Un campo nombre, para saver quien es. window.alert( "Comprobando objeto 02 (nombre) = (" + Peticion02.nombre + ")"); //Vemos que se le asigna el nombre </script> </head> <body> <!--Cuando ocurra el evento oneclick se llamara la funcin coger--> <button onclick="Coger(Peticion01, 'datos/espera.jsp')">Coge el documento 01</button> <button onclick="Coger(Peticion02, 'datos/videoclub.xml')">Coge el documento 02</button> </body> </html>

Figura 1.8 Fallo en la orientacin a objetos de Javascript, mostrada en Mozilla Firefox Pero para nuestra sorpresa (desagradable), esta solucin tan sencilla nos dara el mensaje de la figura 1.8. Esto ocurre porque cuando asignamos con el cdigo: peticionAjax.onreadystatechange = estadoPeticion; No es que se copie la funcin estadoPeticion para el objeto de la peticin actual, est utilizando la funcin global y nuestro objeto de peticin no entra en la funcin de ninguna manera, slo la dispara cuando

- 13 -

AJAX, fundamentos y aplicaciones

cambia de estado y, por tanto, this no hace referencia al objeto peticionAjax. Por lo tanto, este tipo de aproximaciones son intiles debido a la orientacin a objetos de Javascript. Segunda aproximacin (La buena): Ahora vamos a ver primero la clase que solucionara el problema y luego el cdigo principal, los he aadido en pginas separadas para que no quedara el cdigo cortado, lo he comentado atentamente y lo he simplificado todo lo que he podido con el nico nimo de que pueda comprenderse leyndolo, ya que por ms que lo comente si no lo comprendes no hacemos nada. Lelo detenidamente, hasta ahora es lo ms complejo que nos hemos encontrado en este texto y este cdigo va a ser tu amigo, si comprendes bien este apartado, no tendrs problemas ms adelante. Se recomienda echar un primer vistazo a este cdigo y, posteriormente, aclarar conceptos en la siguiente seccin. Por ltimo, un nuevo vistazo al cdigo resolver el resto de las dudas. Archivo lib\ClasePeticionAjax.js /* El objetivo de este fichero es crear la clase objetoAjax (en Javascript a las clases se les llama prototipos) */ function objetoAjax( ) { /*Primero necesitamos un objeto XMLHttpRequest que cogeremos del constructor para que sea compatible con la mayora de navegadores posible. */ this.objetoRequest = new ConstructorXMLHttpRequest(); } function peticionAsincrona(url) //Funcin asignada al mtodo coger del objetoAjax. { /*Copiamos el objeto actual, si usamos this dentro de la funcin que asignemos a onreadystatechange, no funcionara.*/ var objetoActual = this; this.objetoRequest.open('GET', url, true); //Preparamos la conexin. /*Aqu no solo le asignamos el nombre de la funcin, sino la funcin completa, as cada vez que se cree un nuevo objetoAjax se asignara una nueva funcin. */ this.objetoRequest.onreadystatechange = function() { switch(objetoActual.objetoRequest.readyState) { case 1: //Funcin que se llama cuando se est cargando. objetoActual.cargando(); break; case 2: //Funcin que se llama cuando se a cargado. objetoActual.cargado(); break; case 3: //Funcin que se llama cuando se est en interactivo. objetoActual.interactivo(); break; case 4: /*Funcin que se llama cuando se completo la transmisin, se le envan 4 parmetros.*/ objetoActual.completado(objetoActual.objetoRequest.status, objetoActual.objetoRequest.statusText, objetoActual.objetoRequest.responseText, objetoActual.objetoRequest.responseXML); break; } } this.objetoRequest.send(null); //Iniciamos la transmisin de datos. } /*Las siguientes funciones las dejo en blanco ya que las redefiniremos segn nuestra necesidad hacindolas muy sencillas o complejas dentro de la pgina o omitiendolas sino son necesarias.*/

- 14 -

AJAX, fundamentos y aplicaciones

function objetoRequestCargando() {} function objetoRequestCargado() {} function objetoRequestInteractivo() {} function objetoRequestCompletado(estado, estadoTexto, respuestaTexto, respuestaXML) {} /* Por ltimo diremos que las funciones que hemos creado, pertenecen al ObjetoAJAX, con prototype, de esta manera todos los objetoAjax que se creen, lo harn conteniendo estas funciones en ellos*/ //Definimos la funcin de recoger informacin. objetoAjax.prototype.coger = peticionAsincrona ; //Definimos una serie de funciones que sera posible utilizar y las dejamos en blanco en esta clase. objetoAjax.prototype.cargando = objetoRequestCargando ; objetoAjax.prototype.cargado = objetoRequestCargado ; objetoAjax.prototype.interactivo = objetoRequestInteractivo ; objetoAjax.prototype.completado = objetoRequestCompletado ;

Archivo ejemploBueno.html <html> <head> <title>Pgina de ejemplo</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { /* En el ejemplo vamos a utilizar todos los parmetros para ver como queda, en un futuro prximo, solo te interesare la respuesta en texto o XML */ document.getElementById('estado01').innerHTML = estado; document.getElementById('estadoTexto01').innerHTML = estadoTexto; document.getElementById('respuestaTexto01').innerHTML = respuestaTexto; document.getElementById('respuestaXML01').innerHTML = respuestaXML; } var PeticionAjax02 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax02.completado = objetoRequestCompletado02; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado02(estado, estadoTexto, respuestaTexto, respuestaXML) { /* En el ejemplo vamos a utilizar todos los parmetros para ver como queda, en un futuro prximo, solo te interesare la respuesta en texto o XML */ document.getElementById('estado02').innerHTML = estado; document.getElementById('estadoTexto02').innerHTML = estadoTexto; document.getElementById('respuestaTexto02').innerHTML = respuestaTexto; document.getElementById('respuestaXML02').innerHTML = respuestaXML; } </script> </head> <body> <!--Cuando ocurra el evento oneclick se llamara a la funcin coger DE CADA OBJETO--> <button onclick="PeticionAjax01.coger('datos/espera.jsp')">Coge el documento 01</button> <button onclick="PeticionAjax02.coger('datos/videoclub.xml')">Coge el documento 02</button> <table border="4"> <tr> <td>Documento 01</td> <!--Todos los campos del documento 01 les hemos asignado un id como de costumbre para recibir la info-->

- 15 -

AJAX, fundamentos y aplicaciones

<td><span id="estado01">estado no recibido</span></td> <td><span id="estadoTexto01">texto estado no recibido</span></td> <td><span id="respuestaTexto01">texto respuesta no recibido</span></td> <td><span id="respuestaXML01">xml respuesta no recibido</span></td></tr> </tr> <tr> <td>Documento 02</td> <!--Todos los campos del documento 02 les hemos asignado un id como de costumbre para recibir la info--> <td><span id="estado02">estado no recibido</span></td> <td><span id="estadoTexto02">texto estado no recibido</span></td> <td><span id="respuestaTexto02">texto respuesta no recibido</span></td> <td><span id="respuestaXML02">xml respuesta no recibido</span></td></tr> </tr> </table> </body> </html> Como puedes ver en el cdigo de la pgina principal, seguimos reutilizando los archivos espera.jsp y videoclub.xml colocndolos en una carpeta llamada datos, ahora veamos como queda el ejemplo completo, primero pediremos el primer documento y luego el segundo.

Figura 1.10 Resultado correcto a la hora de usar las clases construidas A causa de la espera, llega el segundo objeto antes que el primero y como lo hemos hecho de forma asncrona no hemos tenido que esperar para poder pulsar el segundo botn, si hemos llegado hasta aqu

- 16 -

AJAX, fundamentos y aplicaciones

comprendindolo todo, estamos listos para empezar a cargar de diferentes formas, HTML, imgenes, Javascript, etc... , empleando AJAX que es nuestro objetivo.

1.9 Escribir clases en Javascript


Aun sin ser un lenguaje ni mucho menos raro, Javascript no esta altamente difundido ni se ha usado demasiado hasta ahora, DHTML no tuvo mucho xito, es ahora cuando ha surgido AJAX cuando se est viendo por parte de los desarrolladores ciertas medidas para escribir cdigo ms limpio y comprensible.

1.9.1 Clases VS Prototipos


Ahora que hemos visto los primeros ejemplos vamos a comparar Javascript con Java que seguramente conocemos ms para ver las diferencias y tomar ciertas medidas de ahora en adelante para escribir cdigo, Java es un lenguaje basado en clases como muchos sabremos pero Javascript es un lenguaje basado en prototipos. Basado clases (Java) Clases e instancias son entidades diferentes. Defines una clase con una definicin de clase, instancias una clase con su constructor. Creas un nuevo objeto con el operador new. Basado prototipos (Javascript) Todos los objetos son instancias. Defines y creas los objetos con los constructores.

Igual Construyes una jerarquia de objetos asignando un Construyes una jerarquia de objetos usando objeto como el prototipo asociado a una funcin definiciones de clases para definir subclases. constructor. Heredan las propiedades siguiendo una cadena de Heredan las propiedades usando una cadena de clases. prototipos. La funcin constructora o prototipo especifica el Una definicin de clase describe todas las conjunto de propiedades inicial, luego se pueden propiedades de todas las instancias de la clase, no aadir mas ya sea a unos pocos o todos los objetos se pueden aadir dinmicamente. creados. Traducido de Core Javascript Guide de Netscape Communications Corp

Con el siguiente ejemplo se va a ver muchsimo mas claro:

- 17 -

AJAX, fundamentos y aplicaciones

Jerarqua de Objetos

Objetos Individuales

Empleado function Empleado () { this.nombre = ""; this.departamento = "general"; } Empleado.prototype.especialidad = "ninguna";

Juan = new Empleado; Juan.especialidad es "ninguna"

Trabajador function Trabajador () { this.proyectos = []; } Trabajador.prototype = new Empleado;

Lucas = new Trabajador; Lucas.especialidad es "ninguna"

Ingeniero function Ingeniero () { this.departamento = "ingenieria"; this.ordenador = ""; } Ingeniero.prototype = new Trabajador; Ingeniero.prototype.especialidad = "codigo";

David = new Ingeniero; David.especialidad es "codigo"

Figura 1.11 Ejemplo de uso de prototipos, traducido de Core Javascript Guide

1.9.2 Prototype VS encerrar las funciones


Por supuesto todo lo que viene ahora, est visto y razonado desde el punto de vista de quien escribe estas lneas y no representan ningn estndar, otros autores pueden presentar sus propias alegaciones y recomendar justamente lo contrario. Ahora se ve mejor porqu hemos utilizado la palabra reservada prototype para construir la clase anterior, vamos a discutir este tema, porque podramos haberlo hecho sin usarla y el cdigo quedara incluso ms claro. Otra forma de escribir la ClasePeticionAjax sera la siguiente: ClasePeticionAjaxV2.js function objetoAjax( ) { /*Primero necesitamos un objeto XMLHttpRequest que cogeremos del constructor para que sea compatible con la mayoria de navegadores posible. */ this.objetoRequest = new ConstructorXMLHttpRequest(); //Definimos la funcion de recoger informacion. this.coger = function peticionAsincrona(url) //Funcin asignada al mtodo coger del objetoAjax. { /*Copiamos el objeto actual, si usamos this dentro de la funcin que asignemos a onreadystatechange, no funcionara.*/ var objetoActual = this; this.objetoRequest.open('GET', url, true); //Preparamos la conexin. /*Aqu no solo le asignamos el nombre de la funcin, sino la funcin completa, as cada vez que se cree un nuevo objetoAjax se asignara una nueva funcin. */ this.objetoRequest.onreadystatechange = function() {

- 18 -

AJAX, fundamentos y aplicaciones

switch(objetoActual.objetoRequest.readyState) { case 1: //Funcin que se llama cuando se est cargando. objetoActual.cargando(); break; case 2: //Funcin que se llama cuando se a cargado. objetoActual.cargado(); break; case 3: //Funcin que se llama cuando se est en interactivo. objetoActual.interactivo(); break; case 4: /* Funcin que se llama cuando se completo la transmisin, se le envan 4 parmetros. */ objetoActual.completado(objetoActual.objetoRequest.status, objetoActual.objetoRequest.statusText, objetoActual.objetoRequest.responseText, objetoActual.objetoRequest.responseXML); break; } } this.objetoRequest.send(null); //Iniciamos la transmisin de datos. } //Definimos una serie de funciones que sera posible utilizar y las dejamos en blanco. this.cargando = function objetoRequestCargando() {} this.cargado = function objetoRequestCargado() {} this.interactivo = function objetoRequestInteractivo() {} this.completado = function objetoRequestCompletado(estado, estadoTexto, respuestaTexto, respuestaXML) {} } Vemos que todo queda encerrado dentro del mismo constructor, y slo hacemos referencia a una funcin declarada fuera que construye el objeto XMLHttpRequest y que podramos tener tambin dentro, de manera que el objeto se auto contendra. Aunque pueda parecer bonito encerrar las funciones en el constructor y es una buena tcnica para limpiar cdigo que podemos recomendar, tiene un problema tcnico. Encerrar las funciones puede ser ineficiente desde el punto de vista del rendimiento y memoria, cada vez que hay una funcin encerrada en el constructor sta se crea para cada objeto, lo que no es un problema si vamos a crear pocos objetos a la vez en un PC de hoy en da. Pero, qu pasa con otros terminales mas desfavorecidos como los diferentes terminales mviles que en un futuro podran soportar el objeto XMLHttpRequest?, ya que no nos cuesta nada mejorar el rendimiento en esta ocasin, dejemos la funcin constructora como estaba antes.

1.9.3 Variables pblicas VS variables privadas


Los mtodos de ClasePeticionAjax son todos pblicos y la variable XMLHttpRequest tambin, podemos sentir la tentacin en algunas ocasiones de declararlos como privados para que el desarrollador final que utilice nuestra clase no pueda tocarlos en el transcurso del programa y por consiguiente estropear algo de manera que tuviera que crear un nuevo objeto para cada peticin (como en javascript no existe un public y un private, tendramos que poner esas variables y mtodos en un lugar donde no tuviera visibilidad el creador del objeto), a cambio estamos perdiendo mucha funcionalidad ya que en ocasiones ser necesario reutilizarlo para facilitar la creacin de algn programa o debido a que la memoria en terminales pequeos no es gratuita; por ello en principio las variables y mtodos de los objetos que creemos sern pblicos debido a las necesidades de trabajo que pueden surgir con AJAX.

- 19 -

AJAX, fundamentos y aplicaciones

Captulo 2:
Herramientas de depuracin
Introduccin

2.1 Descripcin del captulo


En el captulo anterior se ha ledo bastante cdigo, si el lector en algn momento ha intentado hacer modificaciones puede que el navegador le diera algn error y que este no le fuera muy comprensible, adems el objetivo de este texto es que el lector sea capaz de manejarse con la tcnica y ya que principalmente se trabajar con Javascript dentro de un entorno Web, este entorno debemos aprender a depurarlo, para ello vamos a ver en este captulo las herramientas necesarias para ello. Puede que hayan ms herramientas; se han escogido con el criterio de que sean tanto gratuitas como potentes, adems tenemos la suerte de que las que vamos a ver se integran en un mismo programa, el navegador Mozilla Firefox.

2.2 Instalacin
Todo lo que necesitamos para la instalacin es lo siguiente: Paquete instalacin de Mozilla Firefox : Lo podemos bajar de la pgina principal de Mozilla Firefox que es http://www.mozilla.com/firefox/ . Paquete xpi de Firefug : Firefox plugin(extensin que aade funcionalidades), se puede bajar de la web de plugins de Firefox que es https://addons.mozilla.org/firefox .

Vamos a empezar instalando Mozilla Firefox, cuando hagamos las instalacin debemos elegir hacer la instalacin personalizada, elegiremos instalar las herramientas para desarrolladores.

Figura 2.1 Cuadro seleccin componentes de la instalacin personalizada de Mozilla Firefox Una vez que est instalado Mozilla Firefox deberemos instalar el plug-in. Para esto solo tenemos que ir a la barra de herramientas, archivo->Abrir archivo y seleccionamos el archivo si lo habamos bajado antes, Firefox detectar que es una de sus extensiones y te preguntar si quieres instalarlo, reiniciamos Firefox y ya lo tendremos instalado.

- 20 -

AJAX, fundamentos y aplicaciones

Una vez que terminemos deberamos tener las siguientes utilidades al iniciar Mozilla Firefox si miramos en la pestaa herramientas.

Figura 2.2 Aspecto de la ventana de herramientas tras la instalacin de las diferentes utilidades de desarrollo. Resumiendo contamos con las siguientes utilidades (las menciono en orden en el que las vamos a ver). Consola Javascript. DOM Inspector Javascript Debugger (Venkman) FireBug

2.3 La consola Javascript


Para ver el funcionamiento de la consola vamos a hacer uso del siguiente ejemplo. depuracion1.html <html> <head><title>depuracion</title></head> <script language="JavaScript" type="text/javascript"> var nombre = "Juan" ; function agoalgo() { longitud = nombre.length(); //Aqu hemos introducido un error. alert("La longitud del nombre es : " + longitud); } </script> <body> PGINA PARA HACER PRUEBAS DE DEPURACIN SIMPLES <br> <a href="javascript:agoalgo();">Llamo Funcin agoalgo</a> </body> </html> Si cargamos la siguiente pgina y si sacamos la consola y pinchamos en el link que hemos puesto a la funcin obtendremos lo siguiente, miremos la figura 2.3 .

Figura 2.3 Resultado en la consola de hacer clic sobre el link en la pgina web

- 21 -

AJAX, fundamentos y aplicaciones

Como vemos la propia consola se ha dado cuenta de que los objetos String no tienen una funcin llamada length. Si pulsamos encima del link de la consola nos llevar al punto del cdigo que produjo el error, mostrado en la figura 2.4 .

Figura 2.4 Cdigo que produjo un error mostrado por el propio Firefox Es muy recomendable combinar el uso de la consola con mensajes alert para depurar programas muy pequeos, cuando Javascript encuentra un error como el anterior, el programa se rompe y no continua, si nos fijamos vemos que haba puesto una funcin alert detrs de la lnea donde se encuentra el error y no se ha ejecutado, as se puede estar seguro de que el programa no llega a ejecutar esa lnea, adems de que se puede monitorizar antes y despus del error el valor que puede tener una variable problemtica, es sencillo y esta herramienta no tiene mas complicacin. Solucin del error anterior, length no es una funcin sino una propiedad; con quitar de la lnea los parntesis de la funcin length() y dejarlo en length se solucionara.

2.4 Document Object Model inspector (inspector del DOM)


Esta herramienta nos permite ver el rbol de objetos del documento con todos los campos de cada etiqueta, su utilidad es la siguiente. Imagnate que hemos hecho una insercin de cdigo HTML en la pgina mediante el objeto XMLHttpRequest, pero dicho cambio no es apreciable y la consola no nos da ningn error. Esto es porque el cdigo insertado puede ser correcto pero no hace lo que debera, la solucin es ver qu hemos insertado realmente mediante el inspector del DOM para buscar el error luego dentro del cdigo que hemos insertado, vemoslo con el siguiente ejemplo. depuracion2.html <html> <head><title>depuracion</title></head> <script language="JavaScript" type="text/javascript"> function insertoalgo() { zona = document.getElementById('zonaInsercion') ; zona.innerHTML = "<center><img src= \"hamsters.jpg\" idth=\"320\" eight=\"240\" border=\"0\" alt=\"Hamsters\"/></center>" ; //Aqu hemos introducido un error, en el alto y ancho, le hemos quitado una letra. } </script>

- 22 -

AJAX, fundamentos y aplicaciones

<body> PGINA PARA HACER PRUEBAS DE DEPURACIN SIMPLES <br> <span id="zonaInsercion"> <a href="javascript:insertoalgo();">Llamo Funcin insertoalgo</a> </span> </body> </html> Vamos a insertar directamente una imagen, puesto que sabemos donde est y no hacemos ninguna peticin al servidor esto no es AJAX, pero puede sernos til alguna vez. Nuestra imagen es una imagen con una resolucin 1024x768 y pensamos insertar en un espacio 320x240, si abrimos la pgina y pinchamos sobre el link que dispara la peticin obtenemos el siguiente resultado, mostrado en la figura 2.5.

Figura 2.5 Resultado del cdigo depuracion2.html visto en Mozilla Firefox Como vemos no hay ningn error en la consola Javascript y la imagen se ha insertado con su tamao original, no respetando las medidas que pretendamos, el error se encuentra en el cdigo HTML, este ejemplo es sencillo y fcil, pero la primera vez que nos pasa puede llevarnos de cabeza, con el DOM inspector podemos ver qu propiedades se han insertado correctamente y cules no. Abrimos pues la ventana del DOM y abrimos las sucesivas pestaas del rbol jerrquico que forman las etiquetas HTML como muestra la figura 2.6 hasta llegar a la imagen.

- 23 -

AJAX, fundamentos y aplicaciones

Figura 2.6 Ejemplo de uso de la utilidad DOM inspector Hemos insertado border, alt, eight, idth y src, vemos que eight y idth tienen los valores 240 y 320, lstima que todava no existan como propiedades que interpretan los navegadores, las hemos escrito mal, corrijmoslo y problema solucionado.

2.5 Venkman(Depurador de Javascript)


Venkman es un depurador convencional, lo utilizaremos para poner puntos de ruptura en el cdigo, de forma que Mozilla Firefox parar su ejecucin y no nos dejar continuar hasta que lo digamos en el depurador. Si nos paramos dentro de una funcin, podremos ver cmo cambian los valores de sus variables locales sobre la marcha si hacemos un step by step. Vamos al ejemplo, es una versin modificada de depuracion1.html, algo mas compleja y que parece no tener sentido, nos valdr para aprender algunas cosas. depuracion3.html <html> <head><title>depuracion</title></head> <script language="JavaScript" type="text/javascript"> function agoalgo() { var nombre = "Juan" ; agoalgo2() ; } function agoalgo2() { agoalgoreal(); } function agoalgoreal() { longitud = nombre.length; alert("La longitud del nombre es : " + longitud); } </script> <body> PGINA PARA HACER PRUEBAS DE DEPURACIN SIMPLES

- 24 -

AJAX, fundamentos y aplicaciones

<br> <a href="javascript:agoalgo();">Llamo Funcion agoalgo</a> <a href="javascript:agoalgo2();">Llamo Funcion agoalgo2</a> <a href="javascript:agoalgoreal();">Llamo Funcion agoalgoreal</a> </body> </html> Lo primero que vamos a hacer despus de abrir la pgina es abrir Venkman (el depurador de Javascript), la cosa debera quedar como en la figura 2.7 .

Figura 2.7 Pantalla de inicio de Venkman con el fichero depuracion3.html cargado en Firefox Solucin de problemas (windows): Si alguna vez intentas abrir alguna herramienta de Mozilla Firefox y sta no abre es porque de alguna manera se ha quedado colgada la ltima vez que la iniciaste, sale del navegador y pulsa CONTROL+ALT+SUP, vete a la pestaa de procesos y termina el proceso llamado firefox que sigue abierto incluso cuando tienes el navegador cerrado, esto ocurre normalmente con los depuradores si no se cierran correctamente. Sigue estas instrucciones: 1. Abre la pestaa de H depuracin3.html. 2. Acomdate la ventana para poder ver el cdigo. 3. Pon los siguientes Puntos de ruptura pulsando con el botn izquierdo del ratn donde aparecen las B de (breakpoint) en la figura 2.8, vers que hay unas barras horizontales, eso es porque es una zona seleccionable para un punto ruptura. Te debera quedar todo como muestra la figura 2.8.

- 25 -

AJAX, fundamentos y aplicaciones

Figura 2.8 Venkman con el fichero depuracion3.html cargado, despus de poner algunos breakpoints 4. Ahora ve a la pgina Web y pulsa sobre el primer link, vers que cuando el cdigo llegue al punto de ruptura se detendr, como en la figura 2.9.

Figura 2.9 Venkman con el fichero depuracion3.html cargado, detenido por un punto de ruptura Si te fijas en la ventana de variables locales vers que la variable nombre, pero queremos hacer uso de esta variable en agoalgoreal().

- 26 -

AJAX, fundamentos y aplicaciones

5. Vamos a ir a la ventana de watches y vamos a aadir una expresin con su nombre, esto ser suficiente. 6. Damos un paso, con esto el estado debera ser el mostrado por la figura 2.10.

Figura 2.10 Vemos que la variable existe con su valor actual, tras el paso 6 de la explicacin 7. Damos varios pasos hasta llegar a la funcin agoalgoreal().

Figura 2.11 Estado tras el paso 7 de la explicacin

- 27 -

AJAX, fundamentos y aplicaciones

Vemos que ahora la variable nombre tiene el valor {Error}, esto es porque nada mas salirnos de la funcin, ya no la vemos, aunque haya sido llamada la funcin por una anterior que tiene la variable, no podemos acceder a ella, Javascript no guarda la misma localidad que lenguajes como C, es un fastidio, pero nos queda declararla como global o declarar una funcin dentro de otra como hemos hecho al hacer la ClasePeticionAjax. Bueno esto es bsicamente lo que podemos hacer con el depurador que no es poco, nos permite examinar el cdigo paso por paso viendo el valor de las variables que queramos.

2.6 Firebug (Todo lo anterior en uno)


Este es tal vez el depurador ms nuevo y potente que hay, nos va a dar toda la informacin que nos dan los otros programas pero de forma mas rpida cuando nos acostumbremos. Vamos a volver a utilizar el archivo depuracion3 para el ejemplo de su uso. Lo abrimos en Mozilla Firefox y pulsamos sobre el icono de la esquina inferior derecha como muestra la figura 2.12, de esta manera iniciamos Firebug.

Figura 2.12 Botn de inicio de Firebug

Figura 2.13 Ventana de Firebug abierta

- 28 -

AJAX, fundamentos y aplicaciones

Tenemos 3 pestaas, veamos su funcionamiento una por una.

2.6.1 Pestaa de consola


La consola nos dar toda la informacin que nos daba la consola de Javascript normal sumndole informacin extra que podemos mostrar si queremos. Entre esta informacin extra, estn los errores de las hojas de estilo CSS, los errores XML y dos que nos ayudarn mucho, mostrar la pila de llamadas que lleg hasta un error y mostrar las llamadas XMLHttpRequest, estos dos nos sern muy tiles. El botn clear simplemente borra toda la informacin acumulada en la consola y el inspect nos llevar a la pestaa del inspector.

Figura 2.14 Posibilidades de la consola de Firebug

Hasta aqu una consola de errores convencional pero que nos muestra algo ms de informacin, vamos a prestar atencin a dos cosas, la pila de llamadas que nos muestra el camino hasta el error y los mensajes de error que podemos configurar nosotros mismos. Para ver lo primero no tenemos ms que tener seleccionado en opciones Show Stack Trace For Errors y pulsar sobre cualquier botn de nuestro ejemplo, yo voy a pulsar los 3 seguidos para que veamos bien como acta en la figura 2.15.

Figura 2.15 Errores mostrados por la consola de Firebug Vemos que las seales de error tienen una flecha al lado, mirando al error, dicen que no est definida donde se ha utilizado la variable nombre.

Figura 2.16 Pila de llamadas de los errores mostrados en la consola de Firebug Si pulsamos sobre la primera flecha se nos muestra la pila de llamadas, si llamamos a la primera funcin agoalgo(), sta llama a las 2 siguientes y termina en agoalgoreal(), si seguimos la pila llegamos a la primera funcin, agoalgo(), igual para el resto, de esta forma podemos seguir la secuencia de acontecimientos que desemboc en error.

- 29 -

AJAX, fundamentos y aplicaciones

Sobre los mensajes de error que podemos configurar nosotros mismos, estos se aaden al cdigo y los interpreta Firebug, son los siguientes. depuracion32.html con los mensajes personalizables en amarillo. <html> <head><title>depuracion</title></head> <script language="JavaScript" type="text/javascript"> function consola() { var a = 10; var b = "hola"; var c = [10, 20, 30, 40] ; console.log(a); //Podemos poner simplemente una o varias variables. console.log(a,b); console.log("El valor de a es %d y el de b es %s",a,b); //Podemos usar la sintaxis del printf de c para los mensajes. console.info(c); console.warn(b); console.error("Prueba de error, el valor de b es %s.",b); } function agoalgo() { var nombre = "Juan" ; agoalgo2() ; } function agoalgo2() { agoalgoreal(); } function agoalgoreal() { longitud = nombre.length; alert("La longitud del nombre es : " + longitud); } </script> <body> PGINA PARA HACER PRUEBAS DE DEPURACIN SIMPLES <br> <a href="javascript:agoalgo();">Llamo Funcion agoalgo</a> <a href="javascript:agoalgo2();">Llamo Funcion agoalgo2</a> <a href="javascript:agoalgoreal();">Llamo Funcion agoalgoreal</a> <a href="javascript:consola();">Llamo Funcion consola</a> </body> </html> Si ahora llamamos a la funcin consola, obtenemos el siguiente resultado, mostrado en la figura 2.17.

Figura 2.17 Los diferentes mensajes de error de Firebug, mostrados del archivo depuracion32.html

Los mensajes console.log() no muestran ningn cartel de atencin especial.

- 30 -

AJAX, fundamentos y aplicaciones


Los mensajes console.info() muestran un cartel de informacin. Los mensajes console.warn() muestran un cartel de alerta. Los mensajes console.error() muestran un cartel de error, pero el programa no se rompe. El programa Javascript se romper como hara normalmente si metemos en algn mensaje de error algo no vlido como una variable que no existe.

2.6.2 Pestaa de debugger (depurador)


Funciona exactamente igual que Venkman, ponemos puntos de ruptura y cuando llegue el programa a este punto se parar, para seguir pulsamos sobre los botones, podemos ir paso a paso y se nos muestran las variables locales de la funcin en la parte derecha, voy a sumarle al ejemplo una variable global para que veamos como podran verla desde dentro de la funcin. Solucin de problemas (windows): Si alguna vez te sale un mensaje de alarma en la consola cuando pones un punto de ruptura dentro del navegador, sal del navegador y pulsa CONTROL+ALT+SUP, vete a la pestaa de procesos y termina el proceso de Firefox que sigue abierto incluso cuando tienes el navegador cerrado, esto ocurre normalmente con los depuradores si no se cierran correctamente, adems algunas veces tenemos que repetir varias veces el proceso en la pagina Web para que coja el punto de ruptura Firebug.

Figura 2.18 Pestaa de debugger de Firebug con un punto de ruptura No hemos salido de la pantalla navegador y estamos pudiendo probarlo todo abriendo el depurador, en esto le gana a Venkman, Firebug es mucho ms cmodo. Si queremos ver una variable global tenemos que abrir la pestaa de window en la parte derecha y buscar su valor, realmente estamos mirando entre el DOM. La variable global se llamaba nombregloval y su valor es Perico, encontrarla no ha sido tan cmodo como los watches de Venkman.

Figura 2.19 Mostrando el rbol de objetos Javascript del DOM con Firebug

- 31 -

AJAX, fundamentos y aplicaciones

2.6.3 Pestaa del inspector


Su uso en general es muy sencillo, tiene 5 sub. pestaas, nos centraremos en la pestaa Source. Si conocemos hojas de estilo y Javascript utilizar el resto ser muy sencillo. Nos muestra el mismo cdigo html que hemos escrito, pero nos deja desplegar las etiquetas y nos recuadra en el navegador la zona de la pgina que forma parte del cdigo que se estamos sealando con el puntero del ratn.

Figura 2.20 Inspector de cdigo web de Firebug Como se ve por el subrayado estaba sealando el hiperenlace a la segunda funcin y en el navegador se recuadra, es muy sencillo de utilizar, lo malo es que nos muestra la pgina que cargamos al comenzar y si insertamos mucho cdigo HTML dinmicamente nos podemos encontrar muchas veces con que no es coherente con lo que se est mostrando en el navegador, con esto terminamos el vistazo a Firebug.

- 32 -

AJAX, fundamentos y aplicaciones

Captulo 3:
Tcnicas bsicas de peticin de informacin
Introduccin

3.1 Descripcin del captulo


Por ahora se ha visto todo lo relacionado al objeto XMLHttpRequest que es el corazn de AJAX y terminamos el captulo anterior construyendo una librera que nos dejar utilizarlo de forma mas cmoda, pero que todava no nos abstrae totalmente del uso del objeto XMLHttpRequest. Lo realmente interesante de este objeto es utilizarlo para traer a nuestra pgina los componentes que se utilizan en las pginas Web actuales, HTML, Javascript, imgenes, entre otros, pero estos son los bsicos y despus mejorar la librera para abstraernos del famoso objeto y tener una sencilla funcin que lo haga todo por nosotros. Mientras que se trabaja con Javascript es muy fcil que cometamos algn error, por lo que se han visto primero las herramientas de depuracin. En este captulo vamos a ver: 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 Insertar Cdigo HTML (Y con ello, lo que contenga el cdigo) Insertar Una imagen usando el DOM no como cdigo HTML. Insertar Javascript. El DOM y Javascript Diferencia entre insertar cdigo HTML directamente o crearlo con el DOM. Encapsular el objeto XMLHttpRequest facilitando su uso. Manejo de Errores en la librera. Dar soporte al usuario mientras realizamos las peticiones.

Todo con sus ejemplos funcionando como siempre para que el lector pueda jugar con ellos y comprender bien su funcionamiento que es lo que se pretende.

3.2 Insertar cdigo HTML


Esto es lo ms fcil, adems nos ayudar a comprender algunas cosas de forma sencilla. Vamos a seguir utilizando la librera que construimos en el apartado anterior, primero vamos a ver el ejemplo y luego se explicar, se van a resaltar las partes ms importantes para explicarlas posteriormente. insertarHTML.html <html> <head> <title>Insertar HTML</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; /*Funcin completado del objetoAjax redefinida. */ function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById('ParteHTML').innerHTML = respuestaTexto; //Solo nos interesa la respuesta como texto } </script>

- 33 -

AJAX, fundamentos y aplicaciones

</head> <body> <span id="ParteHTML"> //Principio del cdigo que se va a sustituir <center> <button onclick="PeticionAjax01.coger('pag01.html')">Coge la pag01</button> </center> </span> //Final del cdigo que se va a sustituir </body> </html> pag01.html <center><b> Os presento al hamster guerrero </b> </center> <center><img src="img/guerrero.jpg"><center> img/guerrero.jpg

Figura 3.1 Imagen divertida de un hmster para amenizar el ejemplo Cargar en formato texto: document.getElementById('ParteHTML').innerHTML = respuestaTexto; //Solo nos interesa la respuesta como texto Con esto busco que nos demos cuenta de que estoy introduciendo texto dentro del cdigo HTML, pero da la casualidad de que ese texto, es mas cdigo HTML y cuando el navegador lo interprete, lo interpretar como HTML que es, esto es porque lo est insertando en innerHTML. La parte del documento que sustituimos: <center> <button onclick="PeticionAjax01.coger('pag01.html')">Coge la pag01</button> </center> Hasta ahora no haba mencionado a la etiqueta <span> que se lleva utilizando desde el primer ejemplo, sta define una seccin dentro del documento, en el caso que nos ocupa la seccin comienza antes del botn y termina despus de ste, adems esa es la seccin de cdigo que vamos a sustituir, con lo que el botn desaparecer de la pgina. Esto es muy til, ya que podemos definir la pgina como una tabla y est en secciones, de forma que podemos ir cambiando secciones con un men sin cambiar de pgina. Tener claro donde esta nuestra pgina: pag01.html <center><b> Os presento al hamster guerrero </b> </center> <center><img src="img/guerrero.jpg"><center> Estamos en la pgina insertarHTML.html, por lo tanto no es necesario volver a insertar las cabeceras, <html>, <head>,<body>, etc... img/guerrero.jpg El navegador acta de manera que el cdigo nuevo formaba parte de la pgina original, con esto quiero decir que si insertamos algo que contenga una direccin (como una imagen), esa direccin debe ser relativa a la pgina original, no a la que hemos cargado. Dicho todo lo anterior, veamos el resultado en la figura 3.2:

- 34 -

AJAX, fundamentos y aplicaciones

Figura 3.2 Primer ejemplo til de AJAX Si pulsamos el botn la cosa queda como muestra la figura 3.3.

Figura 3.3 Cdigo HTML insertado correctamente Como vemos seguimos en la misma pgina ya que permanece el mensaje de --Aqu voy a insertar cdigo HTML--, adems de que el texto ha sido interpretado como cdigo HTML. Pues esto es AJAX, una tcnica que nos permite cargar en una misma pgina diferentes elementos, bajo demanda.

3.3 Insertar imgenes usando el DOM


Aunque podemos insertar imgenes como HTML, tambin podemos crear la etiqueta utilizando el API del DOM, pero algo mas curioso es lo siguiente, debido a las necesidades de nuestra aplicacin podemos querer que, aunque no est la imagen o las imgenes cargadas, aparezca el hueco donde estarn en un futuro, como en principio parece que no tiene utilidad voy a mostrar un ejemplo prctico real de una aplicacin Web AJAX.

- 35 -

AJAX, fundamentos y aplicaciones

Figura 3.4 Google maps sin terminar de cargar imgenes Si nos fijamos en la barra de abajo del navegador, pone transfiriendo datos...., mientras que estos datos que son las imgenes se transfieren, tienen su espacio ya guardado, de esta forma no se desfigura la representacin del mapa. Por supuesto que la complejidad de google Maps no se haya en la insercin de las imgenes. Veamos un ejemplo de cmo hacer esto; como en el apartado anterior se resaltar lo ms importante para ms tarde tratarlo con detalle. insertarImag.html <html> <head> <title>Insertar una imagen</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById('Imagen01').src = respuestaTexto; //Solo nos interesa la respuesta como texto } </script> </head> <body> <center><button onclick="PeticionAjax01.coger('DireccionImagen01.txt')">Coge la Imagen 01</button></center> <br> <!- Esta imagen no tiene el campo source --> <center><img id="Imagen01" width="412" height="450" /></center> </body> </html> DireccionImagen01.txt img/gatito.jpg

- 36 -

AJAX, fundamentos y aplicaciones

Img/gatito.jpg

Figura 3.5 Una imagen graciosa para el ejemplo De este ejemplo podemos destacar 3 cosas: La primera, es que le hemos otorgado a una imagen, un id, en vez de utilizar una etiqueta <spam> como hasta ahora y sustituir un campo del cdigo, no solo eso sino que adems le hemos puesto a la imagen el tamao que tendr, pero no el campo src donde se encuentra, de forma que en el cuadro que aparecer vaco para una imagen podemos insertar la imagen que queramos. Segundo, la direccin de la imagen se encuentra en un txt, podra estar en un fichero html, pero en contenido sera el mismo, las extensiones dan igual, estamos eligiendo un fichero de donde cargar texto, se ha puesto as para que quede ms claro. Y tercero, Como le estamos diciendo que queremos cargar el campo src de una imagen? document.getElementById('Imagen01').src Si te fijas, en los ejemplos anteriores en vez de escribir .src, escribamos .innerHTML. Ahora toca explicar esto en ms profundidad para los que no conocen el DOM (Document Object Model), estamos accediendo mediante javascript, primero a document que es nuestra pagina web, estamos eligiendo un elemento de la pgina con getElementById que es la imagen a la que le hemos dado un id, y por ultimo estamos accediendo al campo .src de la imagen01, que aunque no lo hemos escrito, existe, es nulo, pero existe, y estamos diciendo que es = a la respuesta en formato texto, con lo cual le acabamos de indicar dnde se encuentra la imagen, si se extrapola lo anterior esto se puede hacer con todo, la mente del lector puede empezar a maquinar. En los ejemplos anteriores accedamos al cdigo HTML delimitado por la etiqueta <spam>, as que estbamos sustituyendo dentro de la propiedad que contiene el cdigo HTML, por eso nuestro texto se interpretaba como cdigo. Con todo lo anterior veamos como queda el ejemplo en la figura 3.6:

Figura 3.6 El antes y el despus del ejemplo que nos ocupa

- 37 -

AJAX, fundamentos y aplicaciones

Ahora ya sabemos cmo cambiar campos del DOM dinmicamente cargando su contenido mediante AJAX, en este caso, lo hemos utilizado para cargar el src de una imagen contenida en un txt, si se hubiera insertado directamente ya que conocamos el camino sin hacer una peticin al servidor para averiguarlo no sera AJAX, el uso del DOM tiene ms posibilidades aunque como veremos mas tarde, su uso es muy tedioso para programadores inexpertos, sin sumarle las incompatibilidades entre navegadores, una vez aprendido y con prctica ser una herramienta potentsima que ser la culpable de poder hacer verdaderas virgueras.

3.4 Insertar cdigo Javascript


Una cosa interesante, ya que puede ser necesaria a la hora de realizar ciertos programas, es la posibilidad de evaluar cdigo Javascript con la funcin eval(); lo bueno ahora, es que gracias a la tcnica de programacin AJAX, podemos recoger ese cdigo de un archivo que podemos haber preparado antes o puede ser generado por el servidor dinmicamente y devuelto. Un ejemplo sencillo de llamar ejecutar cdigo Javascript con AJAX sera: insertarJavascript.html <html> <head> <title>Insertar Javascript</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { eval(respuestaTexto); //Solo nos interesa la respuesta como texto para lanzar el cdigo Javascript } </script> </head> <body> <center><button onclick="PeticionAjax01.coger('CodigoJavascript01.txt')">Llama a una Funcin</button></center> </body> </html> CodigoJavascript01.txt alert("Has llamado a un codigo javascript usando AJAX."); El resultado se ve en la figura 3.7 que es la siguiente:

Figura 3.7 Cdigo Javascript devuelto por AJAX y evaluado

- 38 -

AJAX, fundamentos y aplicaciones

Como vemos no es difcil y ya que podemos cargar cdigo Javascript, tambin podemos cargar ms peticiones AJAX, desde una peticin AJAX, es decir, peticiones indirectas. Un ejemplo de peticin indirecta sera el siguiente: insercionesIndirectas.html <html> <head> <title>Insertar HTML</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { eval(respuestaTexto); //Solo nos interesa la respuesta como texto para lanzar el cdigo Javascript } </script> </head> <body> <center> <button onclick="PeticionAjax01.coger('CodigoJavascriptCargaInd01.txt')">Llama a una Funcion</button> </center> <center> <span id="Lugar01"></span> </center> </body> </html> CodigoJavascriptCargaInd01.txt //Hemos llamado a una peticionAjax var PeticionAjax02 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax02.completado = objetoRequestCompletado02; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado02(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById('Lugar01').innerHTML = respuestaTexto; //Insertamos en el lugar01 } PeticionAjax02.coger('pag01.html') //Cogemos el cdigo HTML con la PeticionAjax02 Vamos a cargar a la pag01.html que hemos utilizado en un ejemplo anterior, aun as aqu est el cdigo para que no haya confusin: pag01.html <center><b> Os presento al hamster guerrero </b> </center> <center><img src="img/guerrero.jpg"><center> Img/guerrero.jpg

- 39 -

AJAX, fundamentos y aplicaciones

Figura 3.8 El hmster guerrero contraataca

Para hacer algo como esto, este ejemplo sera demasiado costoso, pero para retratar cmo usar una peticin indirecta lo mejor es algo simple, hemos llamado a la primera peticin AJAX, que ha ejecutado un cdigo Javascript contenido dentro de un fichero de texto, este contena una llamada AJAX que cargaba un pedazo de cdigo HTML dentro de un pedazo contenido por una etiqueta <span>. Como el lector puede ver, no estamos ms que dndole una vuelta ms a todo lo que hemos empleado anteriormente, viendo las posibilidades de utilizacin; por supuesto a la hora de utilizarlo realmente deberemos elegir la ms adecuada a la situacin, las peticiones indirectas son buenas para que una peticin haga generar al servidor la segunda peticin de forma dinmica si estamos buscando una informacin que no se sabe dnde est y el servidor s. El resultado del ejemplo es este:

Figura 3.9 Cdigo html cargado realizando una peticin indirecta Con esto terminamos las tcnicas bsicas, ya hemos visto como cargar las cosas como texto, como introducirlas dentro de los objetos del DOM y como lanzar cdigo Javascript, todo utilizando AJAX.

- 40 -

AJAX, fundamentos y aplicaciones

3.5 DOM API


El DOM esta ntimamente relacionado con Javascript que aun por su nombre, no es un lenguaje orientado a objetos como java, es un lenguaje orientado a unos objetos, los del navegador, el DOM y los que creemos (diferentes de java), adems carece de caractersticas importantes como la herencia, se basa en prototipos. Ya que el lenguaje interacta con los objetos del navegador, nos hacemos a la idea de que cuando descargamos una pgina HTML que contiene Javascript, este cdigo sigue estando dentro de la pgina ya que el lenguaje acta en la parte del cliente, en cambio lenguajes como ASP, PHP o JSP generan lenguaje HTML desde el servidor y el usuario nunca llegar a ver su cdigo en la pgina que descargue. En el DOM el objeto principal es el objeto window:

Figura 3.10 Jerarqua de objetos del navegador No es necesario (pero puedes hacerlo) implicar el objeto window en la llamada ya que est de forma implcita, como se ve en el siguiente ejemplo. <html> <body> El dominio de esta pgina web es: <script type="text/javascript"> document.write(document.domain) </script> </body> </html> Se han remarcado las etiquetas HTML que nos dejan insertar cdigo Javascript dentro de una pgina HTML convencional, el cdigo Javascript debe estar delimitado por estos tags de principio y fin, el resultado es el siguiente.

Figura 3.11 Ejemplo de uso de los objetos del navegador

- 41 -

AJAX, fundamentos y aplicaciones

Internet Explorer extiende los objetos de navegador con algunos propios, el usarlos significara la prdida de compatibilidad con otros navegadores y obligara a los usuarios a utilizar ste, no solo esto sino que ciertas cosas que se salen de las que podramos llamar estndar se tratan de manera diferente dependiendo del navegador lo que obliga a crear cdigo con bifurcaciones que primero detecte el navegador y dependiendo de este ejecute un pedazo de programa u otro sin dar errores. Es normal que los diferentes toolkits que hay para programar aplicaciones Web orientadas a AJAX resuelvan estas incompatibilidades por el programador cuando no queda mas remedio en cambio en la mayora de las ocasiones es posible encontrar un camino estndar que exista en todos los navegadores. El rbol de objetos del navegador es un rbol general que contiene tanto mtodos y propiedades del navegador como las que creemos nosotros mismos, si echamos un vistazo rpidamente con Firebug.

Figura 3.12 DOM de una pgina web en Mozilla Firefox 1.5 visto con Firebug Dentro del DOM cada etiqueta tiene una propiedad llamada innerHTML, hasta ahora modificando esta hemos modificado el documento, es decir cambiando el texto HTML cambia la pgina, en cambio tambin se puede modificar el documento cambiando las diferentes propiedades de cada nodo, esto es ms complejo y laborioso pero tiene su recompensa cuando estamos creando entornos realmente atractivos, podemos ir creando las etiquetas, insertando texto y ellas y modificar sus propiedades programando en Javascript.

3.6 DOM API e innerHTML enfrentados


Hasta este momento hemos estado utilizando la propiedad InnerHTML de las etiquetas que delimitan zonas de la pgina y en ningn momento lo hemos discutido, vamos a ver otra posibilidad que aun existiendo, en principio y a no ser que surgiera algo que lo requiriera forzadamente su uso en ningn caso utilizaremos debido a que dispara la complejidad de la solucin del problema. Como dispara la complejidad, vamos a hacer algo tan sencillo como insertar una lnea de texto plano, as comprenderemos rpidamente que no es una posibilidad que debiramos escoger por gusto, adems obliga al estudio en mas profundidad del DOM.

- 42 -

AJAX, fundamentos y aplicaciones

La causa que hace que modificar el documento haciendo uso de innerHTML sea ms fcil que modificar el DOM es que mientras que innerHTML modifica la estructura textual del documento, al usar el DOM modificamos la estructura lgica que se encuentra a un nivel ms bajo. Para comprender el siguiente cdigo debemos entender que el DOM de una pgina Web es un rbol General, as pues un nodo puede tener muchos hijos, si sustituimos el nodo directamente y no ponemos sus hijos al nodo nuevo, habremos destrozado la pgina, debemos llevar cierto cuidado. dom api.html <html> <head> <title>Insertar con DOMAPI</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { var viejaParte = document.getElementById('ParteHTML'); /*Recogemos el elemento que vamos a cambiar como normalmente./* var nuevaParte = document.createTextNode(respuestaTexto); /*Creamos un nuevo nodo de texto, con el texto de respuesta.*/ if (viejaParte.childNodes[0]) //Vemos si el nodo tena hijos. { viejaParte.replaceChild(nuevaParte, viejaParte.childNodes[0]); /*Cambiamos el nodo hijo del padre por lo nuevo */ } else { viejaParte.appendChild(nuevaParte); //Le aadimos un hijo nuevo sino tiene } } </script> </head> <body> <button onclick="PeticionAjax01.coger('Texto.txt')">Coge el documento 01</button> <span id="ParteHTML"> --Aqu voy a insetar Texto-</span> </body> </html> He sealado en azul claro el cdigo necesario para utilizar el DOM directamente, como vemos es trabajar con las funciones de un rbol y recordemos que no estamos dando formato al texto, aunque ahora podramos usar hojas de estilo CSS como piden los documentos XHTML estrictos, la verdad es que debido a lo estrictos que son se termina poniendo la extensin html normal para que algn navegador no salte por cualquier error. Ahora con InnerHTML: innerhtml.html

- 43 -

AJAX, fundamentos y aplicaciones

<html> <head> <title>Insertar con DOMAPI</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById('ParteHTML').innerHTML = respuestaTexto; //insercin innerHTML tpica } </script> </head> <body> <button onclick="PeticionAjax01.coger('Texto.txt')">Coge el documento 01</button> <span id="ParteHTML"> --Aqu voy a insetar Texto-</span> </body> </html> texto.txt Una linea de texto. Como vemos despus de esto y todos los ejemplos anteriores, mientras insertemos algo como cdigo html, la complejidad es la misma. El resultado del ejemplo anterior en los 2 casos es el mostrado por la figura 3.10:

Figura 3.13 Ejemplo de insercin con innerHTML y DOM, todava no usamos acentos al insertar cdigo.

3.7 Encapsulacin del objeto XMLHttpRequest


Ya hemos visto algunas cosas que se pueden hacer con el objeto XMLHttpRequest que no son pocas, si le aadimos un programa en el lado del servidor que nos d la informacin las posibilidades son muchsimas debido a que ya sabemos cmo pedir cdigo en formato de texto, imgenes y Javascript. Lo siguiente ser

- 44 -

AJAX, fundamentos y aplicaciones

poder hacerlo con una lnea de cdigo y olvidarnos de la programacin a bajo nivel. Es lo que haremos, te puedes imaginar que estas a punto de leer un montn de cdigo; tmatelo con calma, ejectalo y mira como acta, esta es la parte ms fea de este tema.

3.7.1 Peticin de cdigo HTML o texto


Como siempre, es mejor verlo con un ejemplo, voy a reutilizar archivos de los ejemplos anteriores ya que estamos familiarizados con ellos y se comprender ms fcilmente. insertarhtml.html <html> <head> <title>Insertar HTML</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjaxHtml.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjaxHtml01 = new objetoAjaxHtml("pag01.html","ParteHTML"); /*Pedimos una pgina y decimos en que campo colocarla. */ </script> </head> <body> <center>--Aqu voy a insetar cdigo html--</center> <span id="ParteHTML"> <center> <button onclick="PeticionAjaxHtml01.cogerHtml()">Coge una pag html</button> </center> </span> </body> </html> Y la clase que nos permite hacerlo es la siguiente. ClasePeticionAjaxHtml.js /* Objeto que crea el automticamente el XMLHttpRequest, pide la informacin que recoge como texto y la inserta en el sitio pedido. */ function objetoAjaxHtml(ruta,idDondeInsertar) { this.ruta = ruta; //Ruta que llega asta el archivo con su nombre y extensin this.id = idDondeInsertar; //El campo donde insertar } function cogerHtml() { var idActual = this.id ; /*Dentro de las funciones el this. no funcionara, as que creamos una variable con su contenido, como anteriormente.*/ this.completado = function(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById(idActual).innerHTML = respuestaTexto; } this.coger(this.ruta); /*Si alguien ha llamado a la funcin cogerHtml es porque quiere lanzar la peticin y nosotros lanzamos la peticin xmlhttprequest. */ } //Esta nueva clase hereda como prototipo la ClasePeticionAjax objetoAjaxHtml.prototype = new objetoAjax; //Definimos las funciones nuevas pertenecientes al objeto Html en particular. objetoAjaxHtml.prototype.cogerHtml = cogerHtml; //Le aadimos la funcin cogerHtml.

- 45 -

AJAX, fundamentos y aplicaciones

Con todo esto cogeramos la misma pgina del ejemplo del ratn y el resultado sera el mismo que anteriormente, cabe destacar el uso de prototipos, sta clase es un objetoAjax especializado para el manejo de HTML.

3.7.2 Peticin de la direccin de una imagen


Anteriormente hemos visto dos tipos de insercin con el innerHTML(tipo1) y con el DOM(tipo2), la clase que haga esta tarea nos dejar hacer los dos tipos de inserciones. insertarImagen1.html <html> <head> <title>Insertar Imagen</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjaxImagen.js"></script> <script language="JavaScript" type="text/javascript"> //Definimos un nuevo objetoAjaxImag de tipo 1 y las propiedades de la imagen //De izquierda a derecha las propiedades son las siguientes //El archivo que devuelve la direccin de la imagen. //Donde insertar la imagen una vez obtenida //Tipo de insercin 1=InnerHtml 2=DOM //Alto, Ancho, borde y alt var PeticionAjaxImag01 = new objetoAjaxImagen("direccion.txt","ParteHTML",1,"391","350","0","guerrero"); </script> </head> <body> <center>--Aqu voy a insetar cdigo html--</center> <span id="ParteHTML"> <center> <button onclick="PeticionAjaxImag01.cogerImagen()">Coge una imagen tipo 1</button> </center> </span> </body> </html> En cambio si vamos a insertar directamente en el DOM, suponemos que las caractersticas de la imagen ya estn en la pgina y solo necesitamos que nos devuelvan su direccin. insertarImagen2.html <html> <head> <title>Insertar Imagen</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjaxImagen.js"></script> <script language="JavaScript" type="text/javascript"> //Definimos un nuevo objetoAjaxImag de tipo 1 y las propiedades de la imagen //De izquierda a derecha las propiedades son las siguientes //El archivo que devuelve la direccin de la imagen. //Donde insertar la imagen una vez obtenida //Tipo de insercin 1=InnerHtml 2=DOM var PeticionAjaxImag01 = new objetoAjaxImagen("direccion.txt","ParteImag",2); </script> </head>

- 46 -

AJAX, fundamentos y aplicaciones

<body> <center>--Aqu voy a insetar cdigo html--</center> <span id="ParteHTML"> <center> <button onclick="PeticionAjaxImag01.cogerImagen()">Coge una imagen tipo 2</button> </center> <center> <img id="ParteImag" height="391" width="350" /> <center> </span> </body> </html> direccion.txt guerrero.jpg La clase que nos permite operar de la forma anterior sera la siguiente. ClasePeticionAjaxImagen.js function objetoAjaxImagen(ruta,idDondeInsertar,tipoInsercion,alto,ancho,borde,alter) { this.ruta = ruta; //Ruta que llega asta el archivo que contiene la direccin del a imagen. this.id = idDondeInsertar; //El campo donde insertar this.tipoInsercion = tipoInsercion; //Tipo inseccin 1=InnerHtml 2=DOM //Propiedades de la imagen this.alto = alto; this.ancho = ancho; this.borde = borde; this.alternativa = alter; } function cogerImagen() { /*Dentro de las funciones el this. no funcionara, as que creamos una variable nueva con su contenido, como anteriormente.*/ var idActual = this.id ; var tipoInsercionActual = this.tipoInsercion ; var anchoActual = this.ancho ; var altoActual = this.alto ; var bordeActual = this.borde ; var alterActual = this.alter ; this.completado = function(estado, estadoTexto, respuestaTexto, respuestaXML) { var rutaImagen = respuestaTexto; switch(tipoInsercionActual) //Realizamos la inseccin { case 1: /* Insercin Tipo 1, insertamos cdigo XHTML segn sus especificaciones, es decir, con las comillas para los atributos y el cierre al final.*/ document.getElementById(idActual).innerHTML = "<center><img src= \"" + rutaImagen + "\" width=\"" + anchoActual + "\" height=\"" + altoActual + "\" border=\"" + bordeActual + "\" alt=\"" + alterActual + "\" /></center>" ; break;

- 47 -

AJAX, fundamentos y aplicaciones

case 2: //Insercion Tipo 2, insertamos directamente en el DOM document.getElementById(idActual).src = rutaImagen; break; } } this.coger(this.ruta); /* Cogemos la ruta que contiene la direccin de la imagen, NO ES LA IMAGEN, SI SUPIERAMOS DONDE ESTA PARA QUE QUEREMOS AJAX!! (Para los que no se hayan enterado todava, si sabemos dnde est la imagen, podemos cambiar su src document.getElementById(idActual).src = rutaImagen; directamente en Javascript sin necesidad de invocar al servidor mediante el objeto XMLHttpRequest) */ } //Esta nueva clase hereda como prototipo la ClasePeticionAjax y la extiende. objetoAjaxImagen.prototype = new objetoAjax; //Funciones propias solo de esta clase. objetoAjaxImagen.prototype.cogerImagen = cogerImagen; //La funcin de coger propia de las imgenes. El resultado de lo anterior sera mostrar la imagen del ratn, no aade nada nuevo, as que la omitimos tambin.

3.7.3 Peticin de cdigo Javascript y lanzarlo


Este es con diferencia la clase ms sencilla, se ha dejado para el final para las mentes cansadas. LanzarJavascript.html <html> <head> <title>Insertar Javascript</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjaxJavascript.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjaxjavascriptl01 = new objetoAjaxJavascript("alertaejemplo.js"); /* Definimos un nuevo objetoAjaxJavascript */ </script> </head> <body> <center> <button onclick="PeticionAjaxjavascriptl01.cogerJavascript()">Lanza cdigo Javascript</button> </center> </body> </html> ClasePeticionAjaxJavascript.js function objetoAjaxJavascript(ruta) //Solo necesitaremos la ruta. { this.Ruta = ruta; //Ruta, que adems podemos redefinir durante el programa. } function cogerJavascript() { this.completado = function(estado, estadoTexto, respuestaTexto, respuestaXML) { eval(respuestaTexto); //Lanzamos el cdigo javascript. } this.coger(this.Ruta); //Si alguien lanza la peticin nosotros hacemos lo mismo. }

- 48 -

AJAX, fundamentos y aplicaciones

//Esta nueva clase hereda como prototipo la ClasePeticionAjax objetoAjaxJavascript.prototype = new objetoAjax; //Prototipos propios de la clase objetoAjaxJavascript objetoAjaxJavascript.prototype.cogerJavascript = cogerJavascript; /*Aadimos la funcin de coger al objeto. */ alertaejemplo.js alert("Has llamado a un codigo javascript usando AJAX."); Con todo lo anterior ahora podemos aprovechar AJAX abstrayndonos de tener que pensar en el objeto XMLHttpRequest lo que es un gran avance.

3.8 Manejo de errores


Podemos preguntarnos un momento qu ocurre si hacemos una peticin de informacin a una url inexistente dentro de un servidor que s existe, puedes introducir una en tu navegador, el servidor te devolver el cdigo de error 404, pgina no encontrada. Tal y como est hecha ClasePeticionAjax.js ahora mismo, aunque la url no existiese se entrara en estado 4 y ocurrira lo siguiente.

Figura 3.14 Aunque una pgina no se encuentre la clase AJAX actual la tratara igual Como vemos en la pequea ventana de la derecha hemos recibido un cdigo 404 y el servidor nos ha devuelto la tpica pgina de error, vamos a insertar la pgina de error!, parece que no es muy grave, en verdad nos vamos a enterar del error perfectamente, pero quedara ms bonito que saliera una alarma dndonos la misma informacin y no ocurriera nada, adems existen ms cdigos de error menos tpicos. Hasta ahora todo lo que hemos hecho si funciona correctamente devuelve el cdigo 200, por lo que cualquier cosa que no sea 200 ahora mismo la tomamos como extrao. Una pequea deteccin de errores sera la siguiente (como el cdigo es largo se han puesto puntos suspensivos en las partes innecesarias):

- 49 -

AJAX, fundamentos y aplicaciones

function peticionAsincrona(url) //Funcin asignada al mtodo coger del objetoAjax. { ... this.objetoRequest.onreadystatechange = function() { switch(objetoActual.objetoRequest.readyState) { case 1: //Funcin que se llama cuando se est cargando. objetoActual.cargando(); break; case 2: //Funcin que se llama cuando se a cargado. objetoActual.cargado(); break; case 3: //Funcin que se llama cuando se est en interactivo. objetoActual.interactivo(); break; case 4: /*Deteccin de errores, solo nos fijamos en el codigo que nos llega normalmente como bueno, como por ahora no es necesario elevar la complejidad de la deteccin la dejamos as. */ if(objetoActual.objetoRequest.status != 200) { alert("Posible Error: " + objetoActual.objetoRequest.status + ", Descripcin: " + objetoActual.objetoRequest.statusText); //Por si queremos hacer algo con el error manejadorError(objetoActual.objetoRequest.status); } else //Si no hubo error, se deja al programa seguir su flujo normal. { /*Funcin que se llama cuando se completo la transmisin, se le envan 4 parmetros.*/ objetoActual.completado(objetoActual.objetoRequest.status, objetoActual.objetoRequest.statusText, objetoActual.objetoRequest.responseText, objetoActual.objetoRequest.responseXML); } break; } } this.objetoRequest.send(null); //Iniciamos la transmisin de datos. } //Declaramos los manejadores function objetoRequestCargando() {} ... La deteccin de errores est enmarcada en amarillo para que se vea ms claro, es un pequeo cambio pero uno que nos dar informacin sin necesidad de estar utilizando un depurador, sin contar que es bastante ms elegante detectar un posible error que dejar ver lo que pasa y si encima queremos tratarlo de alguna manera, podemos hacerlo con un manejador que est por defecto en blanco y se puede redefinir.

3.9 Dar soporte al usuario


Una de las cosas que debemos tener clara es que el usuario final, navegante, cliente, etc. que se encuentre con nuestra pagina Web o programa que use tecnologa AJAX pulsar sus botones y esperara que ocurra algo, y desesperar, por ello estara bien que viera algo mientras espera, un barra de carga, un mono saltando, etc. depende de la naturaleza de nuestra aplicacin.

- 50 -

AJAX, fundamentos y aplicaciones

Vamos a aadir a nuestra librera, exactamente al objeto de pedir cdigo HTML una funcin que se llamar cuadroEstadoCarga, que no ser obligatorio usarla y que se podr redefinir en el cdigo de la pgina, por si no nos gusta el que hacemos por defecto, pero que si quisiramos usar, funcionar sin que tengamos que hacer nada ms que decrselo, con los siguientes resultados.

He utilizado un texto un poco raro del que hay que dar crdito al creador de la librera isiAJAX en unos foros, us este texto para uno de sus ejemplos de carga largos y podemos encontrar su trabajo en sourceforge, es un archivo de texto de unos 20 Megas, si estas haciendo las pruebas en un servidor instalado en tu PC de casa es mejor que sea un archivo grande, si adems es un archivo de texto y el navegador se ve obligado a procesarlo puede ayudar a que veas el cuadrito de carga, si no, pasar como un flash y no se apreciar. La pgina principal del ejemplo anterior es la misma que en los ejemplos anteriores con los siguientes cambios: insertarHtml.html

- 51 -

AJAX, fundamentos y aplicaciones

<html> <head> <title>Insertar HTML</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjaxHtml.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjaxHtml01 = new objetoAjaxHtml("largo.txt","ParteHTML","PeticionAjaxHtml01"); </script> </head> <body> <center>--Aqu voy a insetar cdigo html--</center> <span id="ParteHTML"> <center> <button onclick="PeticionAjaxHtml01.cogerHtml()">Coge una pag html</button> </center> </span> </body> </html> Como ves hemos aadido un tercer componente a la llamada de la funcin, es optativo y debe ser nombre de la variable para que, cuando generemos el cdigo HTML del cuadro cancelar que has visto en la imagen, podamos poner que la imagen del cuadro cancelar es un link al mtodo abort del objeto XMLHttpRequest de la variable. Para mostrar el cuadro lo nico que hacemos es colocarlo en el lugar donde ir el texto ya que tenemos su id y cuando llegue el texto la funcin de completado volver a sustituir automticamente el cdigo que hay en InnerHtml. Explicado lo anterior, el cdigo de la clase AJAX tendra la siguiente modificacin: ClasePeticionAjaxHtml.js /* NombreVariable es el nombre de la variable que controla la cancelacin, no necesita ser la variable del objeto, de forma que un objetoAjax podra cancelar a otro diferente. */ function objetoAjaxHtml(ruta,idDondeInsertar,nombreVariable) { this.ruta = ruta; //Ruta que llega asta el archivo con su nombre y extensin. this.id = idDondeInsertar; //El campo donde insertar. this.nombreVariable = nombreVariable; //Nombre de esta variable para poner el cuadro de carga. } function cogerHtml() { var idActual = this.id ; //Dentro de las funciones el this. no funcionara. this.completado = function(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById(idActual).innerHTML = respuestaTexto; } if (this.nombreVariable) //Sin nombre no hay cuadro, lo mostramos antes de empezar la peticin. { this.cuadroEstadoCarga(); /*Sacamos un icono de carga que hipnotiza al usuario, as tardar mas en desesperar. */ } this.coger(this.ruta); /* Si alguien ha llamado a la funcin cogerHtml lanzamos la peticin xmlhttprequest. */ }

- 52 -

AJAX, fundamentos y aplicaciones

function cuadroEstadoCarga() { //Mostramos un cuadrito de carga en el lugar donde ir lo que estamos cargando. document.getElementById(this.id).innerHTML = "<center>" + "<img src=\"lib/img/cargando.gif\" alt=\"load\" width=\"40\" height=\"40\" />" + "<a href=\"javascript:" + this.nombreVariable + ".objetoRequest.abort();\">" + "<img border=\"0\" src=\"lib/img/cancelar.jpg\" alt=\"cancel\" width=\"86\" height=\"40\">" + "</a>" + "</center>" } //Esta nueva clase hereda como prototipo la ClasePeticionAjax objetoAjaxHtml.prototype = new objetoAjax; //Definimos las funciones nuevas pertenecientes al objeto Html en particular. objetoAjaxHtml.prototype.cogerHtml = cogerHtml; //Le aadimos la funcin cogerHtml. objetoAjaxHtml.prototype.cuadroEstadoCarga = cuadroEstadoCarga; /* El cuadro que indica el estado de la carga. */ Se ha sealado el cdigo nuevo referente al cuadro de carga, el cuadro aparece por defecto centrado para dar un mejor aspecto como se ve en el cdigo HTML generado, no es ms que un par de imgenes y un link con muchas barras invertidas para quitarle a las comillas su sentido de carcter especial. Igual que hemos hecho esto aqu se podra aadir a la peticin de las imgenes de Tipo 1 pero, como no aade nada nuevo, no lo explicaremos ya que haramos exactamente lo mismo; lo aadiramos antes de que apareciera la imagen y luego sta lo sustituira.

- 53 -

AJAX, fundamentos y aplicaciones

Captulo 4:
Ejemplos reales de uso para AJAX
Introduccin

4.1 Descripcin del captulo


Tras lo visto en el capitulo 3 se puede decir que se sabe manejar el objeto bastante bien, solo se ha dejado en el tintero un par de funciones del objeto, muy sencillas, stas sern lo primero que se ver en el captulo que nos ocupa, adems se solucionar el problema de los caracteres especiales en Internet, como los acentos, para que a la hora de transferir informacin se pueda hacer respetando la lengua de origen, tras esto se vern una serie de ejemplos tpicos del uso que se le da normalmente AJAX en la web para que el lector se familiarice con su uso y se cree la base para emplear AJAX en futuros desarrollos. Los ejemplos de este captulo ya comienzan a ser considerablemente ms grandes que en captulos anteriores, sera bastante bueno que el lector probara los ejemplos y mirara su cdigo completo en un bloc de notas que colore el cdigo para que se situ mejor ya que se omitirn asiduamente las cabeceras y algn pedazo de cdigo menos relevante aparecer como puntos suspensivos alguna vez. Otra cosa interesante es que en este captulo se ha validado el cdigo html siguiendo el estndar xhtml estricto marcado por consorcio world wide web, esto se ha hecho con una extensin para Mozilla Firefox llamada tidy, pero despus de esto se han usado como documentos html normales para evitar ciertos problemas.

4.2 La web actual


Antes de empezar con las ltimas pinceladas al uso del objeto XMLHttpRequest y ver los ejemplos de uso tiles se ver un primer ejemplo que se podra hacer haciendo uso de lo visto hasta ahora y que es ms que interesante.

Figura 4.1 Esquema de una pgina web actual

- 54 -

AJAX, fundamentos y aplicaciones

Las pginas web actuales tienen un modelo que siguen ms o menos todas, por no decir que todas, si nos fijamos en la figura 4.1 veremos una pgina web de ejemplo en la que se han delimitado ciertas zonas, esta pgina tiene todas las zonas tpicas que podemos encontrar en un portal web; aunque puede variar su posicin y su aspecto grfico su funcionamiento es igual, al menos siempre nos vamos a encontrar con un ttulo(zona 4 de la figura 4.1) y un men(zona 5 de la figura 4.1), estos rara vez van a desaparecer de la pgina, en cambio el cuerpo de la pgina(zona 1 del a figura 4.1), va a cambiar dependiendo de la seccin. Lo ideal sera que cuando cambiamos de seccin solo variara esto y con lo que hemos aprendido hasta ahora es posible hacerlo, antes de AJAX se podan usar Frames, ahora la solucin con AJAX es ms elegante y permite hacer a los desarrolladores ms virgueras.

4.3 Mtodos GET, POST y caracteres especiales en Internet


Se vern primero los mtodos de forma terica, seguido se solventar el problema de los caracteres especiales y se juntar todo en un ejemplo para que quede mucho ms claro adems de tener una base para copiar y pegar en un uso posterior.

4.3.1 Introduccin a los mtodos GET y POST


Algunos lectores conocern ya estos mtodos con sus diferencias, bondades y malicias pero para los que no y ya que tenemos que adaptar nuestro objeto AJAX a su uso, vemoslos brevemente. Mtodo GET Es el que hemos estado utilizando hasta ahora, sin discutir en ningn momento su uso, con este mtodo la url de la direccin pedida junto con los valores que se envan forman una misma cadena. Ejemplo: Las 2 lneas forman 1 sola cadena de caracteres GET https://localhost:8443/pruevas/servidorRespuestas.jsp?Nombre=Juan%20Mariano&Apellidos=Fuen tes%20Serna&Cumple=29%20de%20Diciembre&TimeStamp=1160758169187 Esto mtodo tiene un inconveniente bastante malo, si te fijas en el historial de tu navegador tendrs muchsimas pginas que debido a que usan este mtodo guardan junto con la direccin, las variables y su valor, si esto eran datos confidenciales ests perdido, pero si adems pensamos que hay servidores que guardan un historial de las paginas web pedidas este tipo de informacin es ya un verdadero atentado contra la privacidad. Por esto, lo primero que debemos cambiar es el uso del mtodo GET al POST que se ver seguidamente, mencionar que por defecto la mayora de toolkits AJAX usan el mtodo GET, su usas alguno para desarrollar una aplicacin furzalo a utilizar el mtodo POST si es posible. Mtodo POST Cadena de peticin POST https://localhost:8443/pruevas/servidorRespuestas.jsp Cadena de valores de la peticin POST Nombre=Juan Mariano&Apellidos=Fuentes Serna&Cumple=29 de Diciembre&TimeStamp=1160 758191375 Todo queda mucho ms separado y limpio, adems se evita que quede en los historiales que es su punto fuerte.

4.8.1

Caracteres especiales

Este problema surge debido a las diferentes codificaciones que hay para los caracteres en texto plano, si estas viendo una pgina que has hecho tu mismo de forma local no hay problema pero si es un servidor quien est generando informacin y utiliza otra codificacin es casi seguro que los acentos se van a estropear por el camino y cuando se muestren al final sern unos signos de interrogacin algo pintorescos y extraos. Para solventar este problema vamos a hacer dos cosas, la primera es que guardaremos las pginas web que se escriban en formato de texto UTF-8 que contiene todos los smbolos, una vez que hemos terminado la pgina web utilizando nuestro editor favorito si este no tiene opciones para guardar en

- 55 -

AJAX, fundamentos y aplicaciones

formato UTF-8 no tenemos ms que abrir el archivo html como si de un texto normal se tratase con el bloc de notas en Windows e irnos al men archivo->Guardar como

Figura 4.2 Como guardar en formato UTF-8 con el bloc de notas de Windows La segunda parte importante es que en la parte del servidor tenemos que decirle que el archivo est guardado tambin en ese formato (adems de guardarlo) y cuando recojamos los parmetros enviados por el cliente hacerlo tambin aclarando que estn en formato UTF-8, para esto aadiremos al archivo jsp las siguientes lneas que se pondrn correctamente en el ejemplo. <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> request.setCharacterEncoding("UTF-8");

4.8.1

Cambios en la librera para que acepte los 2 mtodos

Anteriormente utilizaba siempre el mtodo get, ahora con especificar cul usar al crear el objeto y seleccionar ms tarde el mtodo con una estructura de seleccin simple ser suficiente, remarcaremos lo interesante en el cdigo y omitiremos lo que no sea necesario. function objetoAjax(metodo) { this.metodo = metodo; } function peticionAsincrona(url,valores) //Funcin asignada al mtodo coger del objetoAjax. // El parmetro valores slo se usa en el caso POST { /*Copiamos el objeto actual, si usamos this dentro de la funcin que asignemos a onreadystatechange, no funcionara.*/ var objetoActual = this; this.objetoRequest.open(this.metodo, url, true); //Preparamos la conexin. if (this.metodo == "GET") { this.objetoRequest.send(null); //Iniciamos la transmisin de datos. } else if(this.metodo == "POST") {

- 56 -

AJAX, fundamentos y aplicaciones

this.objetoRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); this.objetoRequest.send(valores); } } Como se aprecia, ahora cuando lancemos la peticin si se utiliza el mtodo POST debemos dar los valores en una cadena aparte, esto ser suficiente para su buen comportamiento. NOTA IMPORTANTE: El cambio hecho en este momento hace que si se quiere hacer uso de los objetos encapsulados del captulo anterior junto con esta nueva versin del objetoAjax, se tengan que realizar ciertas modificaciones sencillas sobre ellos, este ejercicio se deja propuesto al lector interesado.

4.8.1

Ejemplo de uso de los mtodos GET y POST

Figura 4.3 Ejemplo de los mtodos GET y POST

A la hora de escribir cdigo en el lado del servidor no cambia nada el utilizar los mtodos GET o POST como se ve en el cdigo siguiente que no tiene nada especial para tratar la peticin dependiendo del mtodo usado: servidorRespuestas.jsp <!-- Para resolver los problemas con los acentos y la debemos aadir la siguiente directiva y guardar este archivo con codificacin UTF-8 con el bloc de notas, guardar como --> <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <% request.setCharacterEncoding("UTF-8"); //Para resolver problemas con los acentos //Gracias al TimeStamp podemos hacer una comprovacin de viveza si queremos //ej: Si los datos tienen mas de 5 segundos, no hacemos nada ya que puede ser un paquete viejo. String TimeStamp; TimeStamp = request.getParameter( "TimeStamp" );

- 57 -

AJAX, fundamentos y aplicaciones

String Nombre; Nombre=request.getParameter( "Nombre" ); String Apellidos; Apellidos=request.getParameter( "Apellidos" ); String Cumple; Cumple=request.getParameter( "Cumple" ); //Devolvemos una respuesta al usuario out.print("Hola " + Nombre + " " + Apellidos + " tu cumpleaos es el :" + Cumple); %> Sobre la parte HTML del ejemplo, lo ms interesante es la diferencia a la hora de usar un mtodo u otro ya que el mtodo POST enva los valores en una cadena aparte de la url, el cdigo fuente completo lo puedes encontrar en los cdigos fuente del libro. Peticion.html(solo parte del archivo) function datosCuestionarioEnCadena() //Esta funcin construye una cadena con los 3 datos { //Cogemos los datos de cada campo y los metemos en una variable cada uno var Nombre = document.getElementById( "Nombre" ).value; var Apellidos = document.getElementById( "Apellidos" ).value; var Cumple = document.getElementById( "Cumple" ).value; //Construimos una cadena con ellos con el formato estndar de enviar informacin var cadenaPeticionCuestionario = "Nombre=" + Nombre + "&Apellidos=" + Apellidos + "&Cumple=" + Cumple; return cadenaPeticionCuestionario; //Devolvemos la cadena que se usara en otras funciones } function peticionUsandoGET() { darInfo01= new objetoAjax("GET"); //Construimos un objetoAjax que utilizar el mtodo GET /*Cuando se usa el mtodo GET la pgina a la que enviamos los datos y los datos van unidos en la misma cadena */ var cadenaPeticionGET = "servidorRespuestas.jsp?"; //La pgina. cadenaPeticionGET = cadenaPeticionGET + datosCuestionarioEnCadena() + "&TimeStamp=" + new Date().getTime(); //Unimos la pgina con el resto de los datos. darInfo01.completado = objetoRequestCompletado01; darInfo01.coger(cadenaPeticionGET); //Enviamos tanto la pgina como los datos en la misma cadena. } function peticionUsandoPOST() { darInfo01= new objetoAjax( "POST" ); //Construimos un objetoAjax que utilizar el mtodo POST //Cuando se utiliza el mtodo POST la pgina a la que enviamos los datos y los datos van en cadenas diferentes. //Cadena de los datos var datosPOST = datosCuestionarioEnCadena() + "&TimeStamp=" + new Date().getTime(); darInfo01.completado = objetoRequestCompletado01; //Enviamos la pgina y los datos en cadenas diferentes. darInfo01.coger( "servidorRespuestas.jsp" , datosPOST); } Con esto hemos terminado el vistazo a los ejemplos GET y POST adems de solucionar el problema de los caracteres especiales.

- 58 -

AJAX, fundamentos y aplicaciones

4.4 Leer las cabeceras del objeto XMLHttpRequest


Este punto nos servir para dos cosas, para ver cmo leer las cabeceras del objeto XMLHttpRequest y para, segn qu cabeceras nos lleguen, actuar de una forma u otra. Es bueno reutilizar los objetos y facilita muchos problemas a veces, si se pudiera hacer una peticin y que segn una seal que la respuesta se tratase de una forma u otra sera algo muy til, esto se puede hacer mucho mejor y se har, haciendo uso de XML, por ahora vamos a ver el ejemplo usando las cabeceras. Es bastante simple, hacemos una peticin como cualquier otra y leemos sus cabeceras, leemos una u otra dependiendo de una variable que se cambia a causa del botn que pulsamos.

Figura 4.4 Ejemplo de leer las cabeceras del objeto XMLHttpRequest Como el archivo que recibimos en la peticin no se usa en este caso prescindimos de el. cabecerasDeLaRespuesta.html <html> <head> <title>Leer los datos de la cabecera del objeto XMLHttpRequest</title> <script language="JavaScript" type="text/javascript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" type="text/javascript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> function peticionCabeceras(cabecera) { var quecabecera = cabecera; var recogerInfo01 = new objetoAjax("GET"); //Construimos un objetoAjax que utilizar el mtodo GET

- 59 -

AJAX, fundamentos y aplicaciones

recogerInfo01.completado = function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { if(quecabecera == "todas") { alert(recogerInfo01.objetoRequest.getAllResponseHeaders()); } else if(quecabecera == "servidor") { alert(recogerInfo01.objetoRequest.getResponseHeader("Server")); } else if(quecabecera == "ultimaModificacion") { alert(recogerInfo01.objetoRequest.getResponseHeader("Last-Modified")); } } recogerInfo01.coger("videoclub.xml"); //Enviamos tanto la pgina como los datos en la misma cadena. } </script> </head> <body> <h1>Leer los datos de la cabecera del objeto XMLHttpRequest:</h1> <a href="javascript:peticionCabeceras('todas');">Leer todas las cabeceras.</a> <br /> <a href="javascript:peticionCabeceras('servidor');">Leer el servidor.</a> <br /> <a href="javascript:peticionCabeceras('ultimaModificacion');">Leer ltima modificacin.</a> </body> </html> Como podr apreciar el lector si se fij en la figura 4.4 para pedir una cabecera sola hay que utilizar el nombre por el cual est llamada cuando las pedimos todas.

4.5 Auto verificacin y rendimiento en AJAX


La auto verificacin es una de esas cosas sencillas que puede ayudar muchsimo al usuario y hacer que nuestro portal tenga algo diferente respecto de otros, pero tambin puede ser una manera de cargar tanto el servidor que tengamos que comprar uno 10 veces mas grande. Consiste bsicamente en que ciertas acciones, como podra ser ver si una pgina Web existe o un usuario existe, se realicen sin necesidad de que el usuario tenga que pulsar ningn botn. Estas acciones se realizan automticamente cuando fueran tiles, evitando muchas veces cargar una pgina de error, el ejemplo que nos ocupa trata una hipottica creacin de usuario, estoy seguro de que ms de un lector ha tenido problemas para registrarse debido a que los nombres de usuario que le gustaban estaban ya en uso, este ejemplo intenta resolver esto de forma ms elegante sin tener que recibir una pgina nueva que diga el nombre de usuario esta cogido, con la consecuente prdida de tiempo. El ejemplo siguiente consta de 3 archivos, uno .html que tiene tanto cdigo Javascript como HTML y dos archivos .jsp, el nico archivo que no es pequeo es el html que se dividir en dos partes para mostrarlo en este texto, dicho esto comenzamos con el ejemplo. autoVerificar.html (Parte HTML) <body onload="desconectaBoton(1)"> <h1>EJEMPLO DE VERIFICACION DE USUARIOS USANDO AJAX</h1> <br /> Tenemos una hipottica base de datos (simulada) solo con dos usuarios, JuanMa y Sergio. <br />

- 60 -

AJAX, fundamentos y aplicaciones

Queremos crear un nuevo usuario. <br /> El sistema comprobar mientras que escribes si tu nombre de usuario esta ya en la base de datos o no. El nombre debe ser de al menos 4 caracteres de largo. <br /> <form action="insertar.jsp" method="get"> <table border="0"> <tr> <!--Si usamos el atributo id, la variable idUsuario no se enviara a la pagina insertar.jps y si usamos name no referenciaremos el objeto dentro de esta pgina, solucin, usar los 2 --> <td> <input type="text" id="idUsuario" name="idUsuario" size="20" onkeyup="validarUsuario()" /> </td> <td> <span id="mensajeValidacion"> </span> </td> </tr> </table> <input type="Submit" id="botonAceptacion" value="Crear Cuenta" /> </form> </body> Como se ve es un formulario muy sencillo, se destaca la primera lnea debido a que tiene una cosa algo curiosa, nada ms terminar de cargar la pgina se lanza una funcin, esta funcin desconectar el botn ya que ste se activar y desactivar dependiendo de si el usuario introducido es vlido o no, el aspecto del ejemplo es el mostrado en la figura 4.5.

Figura 4.5 Ejemplo verificacin automtica utilizando AJAX autoVerificar.html (Parte Javascript) <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax("GET"); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida.

- 61 -

AJAX, fundamentos y aplicaciones

function validarUsuario() { if (!posibleUsuario) //Crea una variable con el nombre del Posible nuevo usuario { var posibleUsuario = document.getElementById("idUsuario"); } // Enva el nombre a la url de verificacin si este es de al menos 4 caracteres de largo. if (escape(posibleUsuario.value.length) > 3) { var url = "validarUsuario.jsp?id=" + escape(posibleUsuario.value); PeticionAjax01.coger(url); } else { desconectaBoton(1); //Desactivamos el botn si el nombre es muy corto. document.getElementById('mensajeValidacion').innerHTML = "Nombre muy corto."; //Si haba texto lo borramos. } } function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { //La pagina jsp devolver true si el nombre se puede usar y false si ya est usando por otro usuario. if(respuestaTexto == "true") { document.getElementById('mensajeValidacion').innerHTML = "<div style=\"color:green\">Nombre usuario libre.</ div>"; desconectaBoton(0); //Si se puede usar mantenemos el botn activado. } else { document.getElementById('mensajeValidacion').innerHTML = "<div style=\"color:red\">Nombre de usuario ya cogido.</ div>"; desconectaBoton(1); //Si no se puede usar desactivamos el botn. } } function desconectaBoton(opcion) { var boton = document.getElementById("botonAceptacion"); boton.disabled = opcion; } </script> La idea es muy sencilla, la funcin validarUsuario() enva el nombre al servidor al archivo validarUsuario.jsp si ste es de al menos de cuatro caracteres, el servidor slo nos puede contestar true(el nombre se puede usar) o false(nombre ocupado). Dependiendo de esta respuesta que se recibe en la funcin objetoRequestCompletado01() se deja el botn activo o se desactiva, de esta manera al usuario no le llegar la tpica pgina diciendo que su nick de registro est ya cogido cada vez que intenta registrarse y se evita con ello perder el contexto y los datos de la pgina donde estamos. Con lo anterior explicado los estados posibles en los que puede estar la pgina son los mostrados en la figura 4.6:

- 62 -

AJAX, fundamentos y aplicaciones

Figura 4.6 Ejemplo de verificacin, estados posibles Aunque no aade mucho al ejemplo aqu estn los archivos jsp ya que pueden aclarar de dnde se saca el valor de respuesta y cmo se ha simulado el mirar en una base de datos. validarUsuario.jsp <% String usuario; usuario=request.getParameter("id"); //Tenemos una hipotetica base de datos solo con JuanMa y Sergio, la simulamos de esta manera. if ( (usuario.equals("JuanMa")) || (usuario.equals("Sergio"))) { out.print("false"); } else { out.print("true"); } %> insertar.jsp <html> <head><title></title></head> <body> <!--Simulamos la insercin del usuario en la base datos, pero no es real, no se inserta nada. --> Usuario insertado: <%= request.getParameter("idUsuario") %> <br /> <a href="index.html">Vuelve a la pgina principal</a>. </body> </html> Esta como muchas otras cosas que se pueden realizar haciendo chequeos consecutivos al servidor empleando AJAX tienen un coste en trminos de CPU y ancho de banda; en algunos casos AJAX ayuda a ahorrar mientras que en otros hace que caiga el rendimiento considerablemente, este es uno de los segundos, cada vez que nuestro usuario libere una tecla se enviar una peticin, si se llena una pgina de servicios como ste y el servidor ya estaba ms o menos copado puede ser un gran problema, por ello el diseador de la aplicacin web debe tener estas cosas en cuenta y saber bien con qu est trabajando.

4.6 Pidiendo y analizando documentos XML


En este apartado se va a iniciar al lector en el uso de archivos XML para recibir una respuesta, analizarla y mostrar el resultado en pantalla. Recorrer el DOM de un archivo XML y sacar informacin es similar a hacerlo en un documento HTML, aunque en la prctica es mucho ms sencillo y en esto es donde se centra el ejemplo. En captulos posteriores se ver cmo generar dinmicamente el archivo XML desde el servidor, por ahora se comenzar pidiendo un archivo ya existente que se tratar haciendo uso de Javascript desde la pgina web principal, este ejemplo pues, solo tendr dos archivos significativos, el

- 63 -

AJAX, fundamentos y aplicaciones

archivo .xml y la pgina web .html que contendr el cdigo Javascript necesario, como siempre, se seguir haciendo uso de la librera AJAX construida anteriormente. El lector podr notar que no se hace uso de las clases encapsuladas (ClasePeticionAjaxHtml.js, ClasePeticionAjaxImagen.js, ClasePeticionAjaxJavascript.js) en este captulo, si el lector revisa el apartado 4.3 donde se explicaban los mtodos GET y POST ver que se hizo uso del ObjetoAjax aunque hubiera sido posible evitarlo realizando las modificaciones oportunas a ClasePeticionAjaxHtml.js, entonces no se hizo as ya que haba que hacer cambios en la librera y es ms instructivo verlo en el objeto mas genrico, pero en el caso del ejemplo que nos ocupa tenemos que definir un manejador diferente al que esta clase aporta y ya que no se ahorra trabajo, se ha preferido utilizar el objeto principal directamente. Ya que un documento XML contiene informacin guardada de una manera estructurada y lo que se pretende es rescatar esta informacin del servidor, filtrar la parte til y mostrarla dinmicamente a causa de una peticin del usuario, haremos esto rescatando un archivo XML de un hipottico videoclub, hacindolo lo mas sencillo posible. El ejemplo es el siguiente: videoclub.xml <?xml version="1.0" encoding="UTF-8"?> <VideoClub> <Infantil> <Titulo>El rey Leon</Titulo> <Titulo>Aladn</Titulo> </Infantil> <Adultos> <Titulo>Eraser</Titulo> <Titulo>Instinto Bsico</Titulo> </Adultos> </VideoClub> AnalizarXML.html (Parte HTML) <body> <h1>Analizando una respuesta XML de un videclub.</h1> <br/><br/> <form action="#"> <input type="button" value="Ver todas las pelculas" onclick="comenzarPeticion('Todas');"/> <br/><br/> <input type="button" value="Ver solo las infantiles" onclick="comenzarPeticion('Infantiles')"/> </form> <br /> <span id="respuestaServidor"></span> </body> Antes de ver la parte Javascript que es la compleja sera bueno que el lector se familiarizara con el resultado que se espera, que en este caso es muy sencillo y est mostrado en la figura 4.7.

- 64 -

AJAX, fundamentos y aplicaciones

Figura 4.7 Resultado del anlisis de un documento XML recibido con AJAX AnalizarXML.html (Parte Javascript) peticion01= new objetoAjax("GET"); //Construimos un objetoAjax que utilizar el mtodo GET function comenzarPeticion(listaPedidaBoton) { //Podemos tener varias opciones a la hora de mostrar la informacin. var listaPedida = listaPedidaBoton ; peticion01.completado = function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { //Dependiendo de lo pedido debemos procesar la informacin de una manera u otra. if(listaPedida == "Todas") { listarTodo(respuestaXML); } else if (listaPedida == "Infantiles") { listarParte(respuestaXML); } } peticion01.coger("videoclub.xml"); } function listarTodo(documentoXML) { //Cogemos todo lo que contienen las etiquetas ttulo. var documentoCompleto = documentoXML.getElementsByTagName("Titulo"); imprimirLista(" --Todos los videos-- ", documentoCompleto); } function listarParte(documentoXML) { //Primero nos quedamos con la etiqueta Infantil. var parte = documentoXML.getElementsByTagName("Infantil")[0]; var parteDeLaParte = parte.getElementsByTagName("Titulo"); //Luego con las etiquetas Ttulo dentro de la etiqueta Infantil. imprimirLista(" --Videos Infantiles-- ", parteDeLaParte); } function imprimirLista(titulo,informacion) { salida = titulo; // Comenzamos poniendo el titulo, luego encadenaremos todo el documento aqu. var campoActual = null; for(var i = 0; i < informacion.length; i++)

- 65 -

AJAX, fundamentos y aplicaciones

{ /* Cogemos el nodo correspondiente a la iteracin (puesta para clarificar, podramos hacerlo de la variable informacin directamente). */ campoActual = informacion[i]; //Lo aadimos a la salida dejando un retorno de carro. salida = salida + "<br>" + campoActual.childNodes[0].nodeValue; } /*Incrustamos la salida en la pgina, le hemos dado un formato plano para que el ejemplo sea sencillo, pero podramos crear una tabla con links recogiendo mas capos e insertndolos, etc.. */ document.getElementById("respuestaServidor").innerHTML = salida; } El anlisis del documento XML se hace de la forma mostrada anteriormente independientemente de lo complejo que el documento sea, si lo fuera ms se tendra que ir pidiendo etiquetas dentro de otras etiquetas como se ha mostrado, gracias a esto se pueden desarrollar programas mas complejos y como el lector puede vislumbrar toda la dificultad de la parte AJAX de cualquier programa ser crear los manejadores para enviar, recibir y manejar la informacin que se transmita, que con un poco de prctica se convertir en una tarea repetitiva.

4.7 Refrescar la pantalla automticamente


Este ejemplo es para mostrar una funcin de Javascript que puede tener una importancia crtica en el desarrollo de ciertos programas con necesidades de tiempo y muchas veces concurrentes, gracias a AJAX ahora a esto podemos sumar el coger informacin de lado servidor con lo cual las posibilidades son ilimitadas. El ejemplo del uso del funcin setTimeout es bastante sencillo pero siempre es mejor ver el resultado antes para comprender mejor qu hace el cdigo; bsicamente se va a refrescar la pantalla automticamente mostrando un mensaje que ir cambiando a otro dinmicamente, stos estn almacenados en el servidor.

Figura 4.8 Ejemplo de refresco automtico haciendo uso funcin setTimeout y AJAX

- 66 -

AJAX, fundamentos y aplicaciones

El ejemplo tiene dos elementos que debemos destacar ya, el primero y ms notable es que los cambios en la pgina se hacen sin permiso del usuario, l no dispara la accin. En principio hay quien puede pensar que esto es peligroso, y es verdad, lo es, pero tambin es poco evitable y muy til para un desarrollador. El segundo es que los mensajes son enviados por el servidor en este ejemplo, son algo que genera el servidor y que podra crearse de forma dinmica si hiciera falta cualquier tipo de informacin que necesita refresco, claro est en este ejemplo es todo muy simple. El ejemplo consta solo de 2 archivos, bastante pequeos, seguimos haciendo uso de la misma librera AJAX creada anteriormente. autoRefrescar.html <html> <head> <title>Refrescar automaticamente la pgina</title> <script language="JavaScript" type="text/javascript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" type="text/javascript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var tiempo = 0; function refrescarAuto() { tiempo++; document.getElementById("tiempo").innerHTML ="El contador de tiempo es :" + tiempo; if((tiempo%2) == 0) //En los nmeros pares (cada 2 segundos), hacemos la peticin. { peticionFrase(); } setTimeout("refrescarAuto()", 1000); //Incrementamos la cuenta cada segundo } function peticionFrase() { peticion01= new objetoAjax("GET"); //Construimos un objetoAjax que utilizar el mtodo GET peticion01.completado = function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById("respuesta").innerHTML = respuestaTexto; } url = "cuentameAlgo.jsp?tiempo=" + tiempo; peticion01.coger(url); } </script> </head> <body> <h1>Refrescar automticamente la pgina.</h1> <table border="1"> <tr> <td><span id="tiempo"></span></td> <td><span id="respuesta"></span></td> </tr> </table> <script language="JavaScript" type="text/javascript"> refrescarAuto(); </script> </body> </html> cuentameAlgo.jsp

- 67 -

AJAX, fundamentos y aplicaciones

<!-- Para resolver los problemas con los acentos y la debemos aadir la siguiente directiva y guardar este archivo con codificacin UTF-8 con el bloc de notas, guardar como --> <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% //Para resolver problemas con los acentos a la hora de recoger la informacin. request.setCharacterEncoding("UTF-8"); int tiempo = 0; tiempo = Integer.parseInt( request.getParameter("tiempo")); switch(tiempo) { case 2: out.print("Este pequeo ejemplo"); break; case 4: out.print("te puede ser til"); break; case 6: out.print("."); break; case 8: out.print("..."); break; case 10: out.print("...................."); break; default: out.print("Todava sigues esperando? Ya termin por si no te has dado cuenta."); } %> Como se puede apreciar el cdigo es bastante sencillo, se hace una peticin cada 2 segundos y se inserta el texto enviado por el servidor en el cuadro del cliente, las peticiones al servidor se hacen solo en los nmeros pares con lo cual un nmero impar nunca llegar al default de la estructura caso del servidor. Por ltimo comentar que antes de AJAX se poda simular algo parecido teniendo una pgina .jsp que recibe la informacin de su construccin dinmicamente cada vez que se llama con lo que puede cambiar, como existe la posibilidad de hacer que la pgina completa se recargue cada cierto tiempo sta se actualizaba, pero claro recargando la pgina entera haciendo que el servidor la genere de nuevo, ahora gracias a AJAX tenemos algo que con lo que utilizando menos recursos obtenemos ms potencia. Ejemplo recarga antes de poder coger informacin usando AJAX: <META http-equiv= "refresh" content = "16;URL=index.jsp">

4.8 Una base de datos creada con el DOM y guardada con AJAX
Antes de nada, para posicionarnos en el ejemplo, que nadie se engae no vamos a hacer una interfaz SQL ni nada por el estilo, la idea es generar dinmicamente una tabla con informacin dada por el usuario con la siguiente interfaz, vista en la figura 4.9.

- 68 -

AJAX, fundamentos y aplicaciones

Figura 4.9 Tabla generada dinmicamente haciendo uso del DOM Esto no tiene nada que ver con AJAX, es solo una muestra de que se puede ir generando los elementos necesarios dinmicamente, esto es un gran avance ya que gracias a ello podemos realizar programas con un aspecto visual agradable rpidamente si los programamos en un web. Pero necesitamos guardar la informacin que generamos si no, no tendra ningn sentido. Llegado este momento podemos elegir archivo o base de datos, en este caso elegimos archivo, le enviaremos los datos a una pgina jsp que crear el archivo, de forma que la cosa grficamente quedara como se ve en la figura 4.10.

Figura 4.10 Interfaz simple para guardar y cargar de un archivo El ejemplo se ha intentado hacer lo ms simple posible aun as su cdigo es un poco largo, se ha generado la tabla haciendo uso del DOM por lo cual se complica un poco, pero en cambio guardamos en un archivo y rescatamos la informacin haciendo uso de la propiedad innerHTML lo que simplifica muchsimo esta parte. En otras palabras, el archivo almacena la informacin directamente en HTML pues sera una redundancia crear nuestro propio formato XML disponiendo ya de uno: el HTML.

- 69 -

AJAX, fundamentos y aplicaciones

4.8.1

Crear una tabla dinmicamente

Comenzaremos mostrando cmo alcanzar el resultado mostrado en la figura 4.9 que es generar la tabla jugando con el DOM, esto lo hacemos as porque para una persona que no est acostumbrada a generar cdigo de esta manera ya es suficiente problema y un escollo grande que se debe salvar para hacer aplicaciones grandes, nuestro ejemplo consta de solo un archivo que contiene tanto el cdigo HTML como Javascript y como no estamos haciendo uso de AJAX no nos hacen falta las libreras. El archivo est comentado y es suficientemente auto explicativo pero algo largo por lo cual se ha decidido partir en tres partes: dos partes Javascript cada una con una funcin y una parte html.

baseDatosB.html(Parte 1 Javascript) var identificadorUnico = 0; function nuevoDisco() //Aadimos un disco a la tabla. { //1.Recogemos los valores de entrada. var autor = document.getElementById("autor").value; var titulo = document.getElementById("titulo").value; var estilo = document.getElementById("estilo").value; //2.Nos cercionamos de que tengan sentido. if(autor == "" || titulo == "" || estilo == "") { return; } else { //3.Limpiamos las entradas. document.getElementById("autor").value = ""; document.getElementById("titulo").value = ""; document.getElementById("estilo").value = ""; //4.Creamos una nueva fila para la tabla, usando el DOM y le aadimos las celdas var fila = document.createElement("tr"); fila.setAttribute("id",identificadorUnico); //Le damos un identificador nico para poder reconocerla. var celda1 = document.createElement("td"); celda1.appendChild(document.createTextNode(identificadorUnico)); fila.appendChild(celda1); var celda2 = document.createElement("td"); celda2.appendChild(document.createTextNode(autor)); fila.appendChild(celda2); var celda3 = document.createElement("td"); celda3.appendChild(document.createTextNode(titulo)); fila.appendChild(celda3); var celda4 = document.createElement("td"); celda4.appendChild(document.createTextNode(estilo)); fila.appendChild(celda4); //5.Creamos un botn para asignrselo a la fila var botonborrar = document.createElement("input"); botonborrar.setAttribute("type", "button"); botonborrar.setAttribute("value", "Borrar Elemento"); /*Hay al menos 3 maneras de hacer lo siguiente, yo lo voy a guardar como formato texto, as podemos guardar el cdigo html despus en formato texto y que la referencia al id se guarde, sino se perder */

- 70 -

AJAX, fundamentos y aplicaciones

botonborrar.setAttribute("onclick", "borrarDisco(" + identificadorUnico + ")"); //6.Metemos el botn dentro de una celda y lo aadimos a la fila var celda5 = document.createElement("td"); celda5.appendChild(botonborrar); fila.appendChild(celda5); //7.Aumentamos el valor del contador de los identificadores nicos. identificadorUnico++; //8.Actualizamos la tabla document.getElementById("tablaDiscos").appendChild(fila); } } baseDatosB.html(Parte 2 Javascript) function borrarDisco(BorrarIdentificadorUnico) //Borramos un disco de la tabla { var borrarFila = document.getElementById(BorrarIdentificadorUnico); var tablaDiscos = document.getElementById("tablaDiscos"); tablaDiscos.removeChild(borrarFila); } baseDatosB.html(Parte 3 HTML) <body> <h1>Base de datos de Discos</h1> <h2>Aadir datos:</h2> <form action="#"> <table width="80%" border="0"> <tr> <td>Autor: <input type="text" id="autor"/></td> <td>Ttulo: <input type="text" id="titulo"/></td> <td>Estilo: <input type="text" id="estilo"/></td> <td colspan="3" align="center"> <input type="button" value="Aadir" onclick="nuevoDisco()" /> </td> </tr> </table> </form> <h2>Tabla de Discos:</h2> <table border="1" width="80%"> <tbody id="tablaDiscos"> <tr> <th>Id</th> <th>Autor</th> <th>Ttulo</th> <th>Estilo</th> <th>Operaciones</th> </tr> </tbody> </table> </body> El funcionamiento (que no el cdigo Javascript) es bastante simple, tenemos una funcin que aade filas y otra que las borra, stas se llaman debido a los eventos disparados por los botones de aadir y borrar, como en los programas de toda la vida pero en formato web, lo siguiente sera no perder la informacin al salirnos del navegador.

4.9.1

Guardar informacin de innerHTML usando AJAX

Una forma rudimentaria pero eficaz de guardar y cargar informacin si sta estaba en formato HTML es guardar directamente la cadena de texto que hay dentro de la propiedad innerHTML en un archivo y la

- 71 -

AJAX, fundamentos y aplicaciones

forma ms sencilla de recuperarla es leer la cadena e introducirla dentro de la propiedad innerHTML directamente, por supuesto se guardar en el servidor, cosa que puede ser muy til en una empresa mediana donde queremos que los comerciales vayan dejando los pedidos de los clientes nada ms confirmarlos por si se necesita cargar algo y no se deje para el da siguiente, etc. Es decir, con AJAX podemos guardar cdigo generado dinmicamente sin necesidad de una base de datos y luego recuperarlo. Ahora el ejemplo constar de 3 archivos, el ya visto con alguna modificacin y 2 archivos .jsp uno que guarda una cadena en un archivo y otro que la carga. La idea es bastante sencilla, tal vez lo mas difcil de todo sea generar el archivo de texto y cargarlo si no se tiene mucha experiencia con Java, se vern primero las modificaciones a la pgina principal, se han aadido cuatro funciones Javascript que son las siguientes y no se han modificado las anteriores, adems se han incluido las libreras AJAX. baseDatos.html(Modificaciones con respecto a baseDatosB.html, parte Javascript) function guardar() { darInfo01= new objetoAjax("GET"); //Construimos un objetoAjax que utilizar el mtodo GET //Cuando se usa el mtodo GET la pgina a la que enviamos los datos y los datos van unidos en la misma cadena. var cadenaPeticionGET = "guardarDatos.jsp?"; //La pgina. var datos ="&guardarEnFormatoTexto=" + document.getElementById("tablaDiscos").innerHTML + "&nombreArchivo=" + document.getElementById("nombreArchivo").value; cadenaPeticionGET =cadenaPeticionGET + datos; //Unimos la pgina con el resto de los datos. darInfo01.completado = function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById("resultadoGuardar").innerHTML = respuestaTexto; setTimeout("borrarResultado()", 2000); } darInfo01.coger(cadenaPeticionGET); //Enviamos tanto la pgina como los datos en la misma cadena. } function borrarResultado() { document.getElementById("resultadoGuardar").innerHTML = ""; } function cargar() { cogerInfo02= new objetoAjax("GET"); //Construimos un objetoAjax que utilizar el mtodo GET //Cuando se usa el mtodo GET la pgina a la que enviamos los datos y los datos van unidos en la misma cadena. var cadenaPeticionGET = "cargarDatos.jsp?"; //La pgina. var datos ="&nombreArchivo=" + document.getElementById("nombreArchivo").value; cadenaPeticionGET =cadenaPeticionGET + datos; //Unimos la pgina con el resto de los datos. cogerInfo02.completado = function objetoRequestCompletado02(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById("tablaDiscos").innerHTML = respuestaTexto; actualizarIdUnico(); } cogerInfo02.coger(cadenaPeticionGET); //Enviamos tanto la pgina como los datos en la misma cadena. }

function actualizarIdUnico() {

- 72 -

AJAX, fundamentos y aplicaciones

// El mayor identificador siempre se encuentra al final, as cuando cargamos un archivo estar en la ltima fila de la tabla. var tabla = document.getElementById("tablaDiscos"); var ultimaFila = tabla.childNodes.length - 1; identificadorUnico = tabla.childNodes[ultimaFila].id; //Le damos el valor del id de la ltima fila. identificadorUnico++; //Lo adelantamos al siguiente valor, as su valor ya ser valido como nuevo ID. } Como podrs apreciar, si lo lees atentamente, no se ha hecho un gran control de errores, pero si guardamos correctamente se indica al usuario y luego el mensaje desaparece, esta es una pequea utilidad de la funcin setTimeout, seguimos con la parte HTML a la que le hemos aadido el siguiente cdigo perteneciente a la tabla de cargar y guardar. baseDatos.html (parte HTML) <h2>Guardar archivo de la tabla en el servidor:</h2> <form action="#"> <table width="80%" border="0"> <tr> <td width="40%">Nombre Archivo: <input type="text" id="nombreArchivo"/> </td> <td width="40%"><input type="button" value=" Guardar " onclick="guardar()" /> <input type="button" value=" Cargar " onclick="cargar()" /> </td> </tr> <tr> <td width="40%">Informacin Servidor: </td> <td width="40%"><span id="resultadoGuardar"></span></td> </tr> </table> </form> Queda por ver las pginas .jsp que guardan y cargan de un archivo. guardarDatos.jsp <!-- Para resolver los problemas con los acentos y la debemos aadir la siguiente directiva y guardar este archivo con codificacin UTF-8 con el bloc de notas, guardar como --> <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.io.*" %> <% request.setCharacterEncoding("UTF-8"); /*Para resolver problemas con los acentos a la hora de recoger la informacin.*/ try { String cadenaParaEscribir = request.getParameter("guardarEnFormatoTexto"); String nombreArchivo = request.getParameter("nombreArchivo"); //0.Lo siguiente es para hacer pruebas, salo en vez de usar las 2 lneas de arriba. //String cadenaParaEscribir = "Hola Mundo." ; //String nombreArchivo = "HolaMundo.txt"; //1.Preparamos lo que queremos en formato de cadena dentro del buffer, se va almacenando. StringBuffer bufferSalida = new StringBuffer(); bufferSalida.append(cadenaParaEscribir);

//2.Preparamos el archivo para escribir. String camino = application.getRealPath("/" + nombreArchivo);

- 73 -

AJAX, fundamentos y aplicaciones

File archivo = new File(camino); FileOutputStream cadenaSalida = new FileOutputStream(archivo); PrintWriter punteroEscritura = new PrintWriter(cadenaSalida); /* // Esto se hace por convencin de estratificacin. PrintWriter punteroEscritura = new PrintWriter( new FileOutputStream( application.getRealPath("/"+nombreArchivo) ) ); punteroEscritura.print(cadenaParaEscribir); punteroEscritura.close(); */ //3.Escribimos el archivo. punteroEscritura.print(bufferSalida); //4.Limpiamos y cerramos lo que hemos estado utilizando. punteroEscritura.flush(); punteroEscritura.close(); cadenaSalida.flush(); cadenaSalida.close(); out.print("<div style=\"color:green\">El archivo se guardo correctamente.</ div>"); } catch (Exception e) { out.print("<div style=\"color:red\">No se pudo guardar el archivo.</ div>"); } %> Para que el cdigo anterior funcione correctamente la aplicacin tiene que tener permiso de escritura en el directorio, puede parecer obvio pero es importante ya que la configuracin de un servidor real puede ser algo restrictiva, lo nico que quedara por ver es la carga de datos. cargarDatos.jsp <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.io.*" %> <% request.setCharacterEncoding("UTF-8"); /* Para resolver problemas con los acentos a la hora de recoger la informacin. */ try { //1.Variables para el proceso de lectura. String nombreArchivo = request.getParameter("nombreArchivo"); String cadenaSalida = ""; String cadenaAuxiliar; //2.Preparamos el archivo para Leer. String camino = application.getRealPath("/" + nombreArchivo); FileReader archivoLectura= new FileReader(camino); BufferedReader cabezaLectora = new BufferedReader(archivoLectura); //3.Leemos el archivo (Tcnica de primera lectura adelantada). cadenaAuxiliar = cabezaLectora.readLine(); while(cadenaAuxiliar != null) { cadenaSalida = cadenaSalida.concat(cadenaAuxiliar);

- 74 -

AJAX, fundamentos y aplicaciones

cadenaAuxiliar = cabezaLectora.readLine(); } //4.Limpiamos y cerramos lo que hemos estado utilizando. cabezaLectora.close(); //5.Devolvemos el resultado. out.print(cadenaSalida); } catch (Exception e) { out.print("<div style=\"color:red\">No se pudo cargar el archivo, hubo un error.</ div>"); } %> Como el lector podr apreciar en el momento que se escribe un pequeo programa que pudiera tener una utilidad real el n de lneas de cdigo que tiene se dispara, pero peor todava, nos estamos concentrando en AJAX y lo nico que hemos hecho es enviar y recibir una cadena de texto, podramos haber hecho un ejemplo mas pequeo para esto, seguro, pero es tambin objeto de este texto ofrecer algunas posibilidades de uso. Normalmente todos los ejemplos explicados son muy pequeos y realmente no hace falta ms ya que ensean lo necesario para desarrollar aplicaciones reales; como se ve en sta, la complejidad no se haya en la parte AJAX sino en generar dinmicamente la tabla haciendo uso del DOM y en desarrollar la parte .jsp.

4.9 Dar informacin dinmicamente utilizando los eventos y el DOM


En este ejemplo no vamos a utilizar AJAX, es ms bien DHTML ya que no hacemos uso del objeto XMLHttpRequest, pero nos va a ser muy til cuando construyamos programas ms grandes ya que necesitamos entornos mas interactivos para que sean atractivos. El lector se habr dado cuenta cuando abre un men que, al desplazar el ratn sobre l, muchas veces aparecen nuevas opciones automticamente o que si espera un par de segundos con el puntero del ratn sobre un botn de una barra de herramientas aparece una descripcin de su utilidad, todo esto se ve en la figura 4.11.

Figura 4.11 Men tpico de un programa actual en este caso las imgenes son de Mozilla Firefox Este tipo de cosas, por increble que parezca, se pueden hacer en un entorno web de forma relativamente sencilla y es lo que veremos en el siguiente ejemplo ya que, una vez que sepamos generar tablas dinmicamente donde nos plazca, las posibilidades que se nos abren son muchas; entre otras se nos abre el campo de los videojuegos, no solo hacer barras de herramientas, ya que podemos mostrar cualquier grfico como fondo de una tabla y mover la tabla y modificar el grfico dinmicamente a causa de los eventos del teclado o ratn del usuario, esto unido a AJAX es potentsimo.

- 75 -

AJAX, fundamentos y aplicaciones

4.9.1

Ejemplo 1 Tabla relativa a otra tabla

Es muy importante cuando queremos posicionar un elemento relativo a otro comprender la forma en que se calculan las coordenadas, tenemos que pensar que trabajamos con etiquetas anidadas en HTML, esto lo menciono porque es muy importante cuando pedimos la posicin de una tabla que se cre al cargar el documento la posicin de la etiqueta de esta tabla que tiene sus propiedades y son relativas al padre. Es decir, para obtener su posicin absoluta necesitamos como direccin base la del padre y sumarle el desplazamiento del hijo, como se ve en la figura 4.12.
Objeto padre. top

Objeto hijo. left height width

Figura 4.12 Las posiciones suelen ser relativas a otras

Pero lo peor es que si el padre tiene otro padre el comportamiento es recursivo como muestra la figura 4.13.
PGINA PRINCIPAL TABLA 1 TABLA 2

Figura 4.13 Tablas anidadas La solucin es bastante sencilla, mientras que un elemento tenga padre, le sumamos los desplazamientos del padre de forma recursiva. Esto se ha explicado detenidamente para la mejor comprensin del cdigo del ejemplo cuyo resultado se muestra en la figura 4.14.

- 76 -

AJAX, fundamentos y aplicaciones

Figura 4.14 Generacin de cuadros de informacin dinmicos. Con todo lo anterior explicado ya, el ejemplo consta de solo un archivo del cual dividiremos el cdigo en parte HTML y parte Javascript. Informacion1.html(Parte Javascript) function cogerInfo(Elemento) { crearInformacion(Elemento); posicionVentanaInformacion(Elemento); } function borrarInfo() { var ventanaborrar = document.getElementById("ventanaDatosCuerpo"); var indice = ventanaborrar.childNodes.length; for (var i = indice - 1; i >= 0 ; i--) { ventanaborrar.removeChild(ventanaborrar.childNodes[i]); } document.getElementById("ventanaInformacion").style.border = "none"; } function crearInformacion(Elemento) { //1.Creamos la fila var fila = document.createElement("tr"); //2.Creamos la columna con la informacin. var celda1 = document.createElement("td"); switch(Elemento.id) { case "instrumento0": celda1.innerHTML = "Intrumento de viento."; break; case "instrumento1": celda1.innerHTML = "Instrumento de cuerda."; break; case "instrumento2": celda1.innerHTML = "Instrumento de percusin."; break; case "instrumento3": celda1.innerHTML = "Instrumento Electrnico.";

- 77 -

AJAX, fundamentos y aplicaciones

break; } //3.Aadimos la columna a la fila y la fila a la tabla. fila.appendChild(celda1); document.getElementById("ventanaDatosCuerpo").appendChild(fila); } function posicionVentanaInformacion(Elemento) { //1.Vamos a reposicionar la ventana de informacin respecto al elemento que ha pedido informacin. var reposicionar = document.getElementById("ventanaInformacion"); //2.Calcular la posicin absoluta que ocupara la ventana. /* 2.1 Para calcular el desplazamiento a la izquierda cogemos el ancho de la tabla de al lado que es casi todo el desplazamiento, luego le sumamos algo. */ var izquierdaDesplazado = Elemento.offsetWidth + 13; /* 2.2 Para calcular lo desplazado que esta el elemento del borde superior usamos una funcin, le pasamos el elemento y le decimos el borde que queremos calcular. */ var altoDesplazado = calcularEsquina(Elemento, "offsetTop"); //3.Le aplicamos las propiedades calculadas. reposicionar.style.border = "black 1px solid"; reposicionar.style.left = izquierdaDesplazado + "px"; reposicionar.style.top = altoDesplazado + "px"; } function calcularEsquina(elemento, atributoEsquina) //ej: campo = objetoDeLaPagina , atributoEsquina = "offsetTop" { var desplazamiento = 0; while(elemento) //Mientras exista el elemento { desplazamiento += elemento[atributoEsquina]; //Le sumamos al desplazamiento, el desplazamiento del elemento. /*Normalmente cada elemento solo contiene su desplazamiento respecto al padre, no de manera absoluta, as que pasamos al elemento padre, si existe en la siguiente iteracin se sumara su desplazamiento tambin, sino terminara. */ elemento = elemento.offsetParent; } return desplazamiento; } Informacion1.html(Parte HTML) <body> <h1>Dar informacin con un evento disparado por el ratn:</h1> <h3>Instrumentos Musicales</h3> <table id="instrumentos" bgcolor="#F2FAFA" border="1" cellspacing="0" cellpadding="2"> <tbody> <tr> <td id="instrumento0" onmouseover="cogerInfo(this);" onmouseout="borrarInfo();">Flauta</td> </tr> <tr> <td id="instrumento1" onmouseover="cogerInfo(this);" onmouseout="borrarInfo();">Guitarra</td> </tr> <tr> <td id="instrumento2" onmouseover="cogerInfo(this);" onmouseout="borrarInfo();">Batera</td> </tr> <tr> <td id="instrumento3" onmouseover="cogerInfo(this);" onmouseout="borrarInfo();">Teclado Elctrico</td> </tr> </tbody> </table>

- 78 -

AJAX, fundamentos y aplicaciones

<div style="position:absolute;" id="ventanaInformacion"> <table id="ventanaDatos" bgcolor="#F2FAFA"> <tbody id="ventanaDatosCuerpo"></tbody> </table> </div> </body> Como se ve en una de las lneas subrayadas de la parte HTML se puede asignar ms de un evento a una etiqueta, en este caso se hace desaparecer el elemento si quitamos el ratn de encima debido a que solo estamos dando informacin, no es un men, la parte ms importante de este ejemplo es cmo calculamos la posicin y generamos la tabla dinmica.

4.9.2

Ejemplo 2 Tabla relativa al puntero del ratn

Como se ha mostrado en la figura 4.11, para dar informacin al usuario tpicamente se emplea una tabla adyacente a otra o se muestra la informacin junto al puntero del ratn en un cuadro. Este segundo ejemplo encara precisamente esta segunda vertiente, que es muchsimo mas sencilla ya que solo tenemos que coger las coordenadas del puntero e incrustar la tabla en una posicin adyacente. El aspecto grfico del siguiente ejemplo se encuentra en la figura 4.15

Figura 4.15 Tabla colocada donde se encuentra el puntero del ratn. Si nos fijamos bien, no es que coloquemos la tabla encima justo del ratn, esto quedara un poco antiesttico, normalmente se coloca debajo de l o un poco a la derecha como es el caso, sumndole unos pocos pxeles a las coordenadas. El ejemplo consta de un solo archivo que es el siguiente, divido tambin en parte HTML y Javascript Informacion2.html (Parte HTML) <body> <h1>Dar informacin con un evento disparado por el ratn:</h1> <h3>Barra Herramientras</h3> <img src="0.jpg" id="Nuevo documento." onmouseover="cogerInfo(this,event);" onmouseout="borrarInfo();" /> <img src="1.jpg" id="Guardar documento." onmouseover="cogerInfo(this,event);" onmouseout="borrarInfo();" /> <img src="2.jpg" id="Abrir documento." onmouseover="cogerInfo(this,event);" onmouseout="borrarInfo();" /> <div style="position:absolute;" id="ventanaInformacion">

- 79 -

AJAX, fundamentos y aplicaciones

<table id="ventanaDatos" bgcolor="#F2FAFA"> <tbody id="ventanaDatosCuerpo"></tbody> </table> </div> </body> Informacion2.html (Parte Javascript) function cogerInfo(Elemento, event) { crearInformacion(Elemento); posicionVentanaInformacion(Elemento, event); } function borrarInfo() { var ventanaborrar = document.getElementById("ventanaDatosCuerpo"); var indice = ventanaborrar.childNodes.length; for (var i = indice - 1; i >= 0 ; i--) { ventanaborrar.removeChild(ventanaborrar.childNodes[i]); } document.getElementById("ventanaInformacion").style.border = "none"; } function crearInformacion(Elemento) { //1.Creamos la fila var fila = document.createElement("tr"); //2.Creamos la columna con la informacin. var celda1 = document.createElement("td"); celda1.innerHTML = Elemento.id; //3.Aadimos la columna a la fila y la fila a la tabla. fila.appendChild(celda1); document.getElementById("ventanaDatosCuerpo").appendChild(fila); } function posicionVentanaInformacion(Elemento,event) { 1. Vamos a reposicionar la ventana de informacin respecto al elemento que ha pedido informacin. var reposicionar = document.getElementById("ventanaInformacion"); /* 2.El objeto event, existe solo en el momento que ocurre un evento por si lo necesitas en el manejador y contiene cosas como la posicin y estado de las teclas y ratn. */ var ancho = event.clientX; var alto = event.clientY; //3.Le aplicamos las propiedades calculadas. reposicionar.style.border = "black 1px solid"; reposicionar.style.left = ancho + 15 + "px"; reposicionar.style.top = alto + "px"; } El lector podr apreciar que se ha dedicado mucho tiempo en el apartado 4.9 en explicar algo que no afecta directamente a AJAX (ya que no implica un trfico de informacin dinmica con el servidor) sino que es ms bien un artificio grfico que juega con coordenadas, esto es porque este artificio grfico se va a usar junto con AJAX y es en parte el culpable de que se puedan hacer cosas ms que interesantes.

4.10 Auto completado empleando AJAX


Para explicarlo rpidamente lo mejor es ver el resultado primero, mostrado en la figura 4.16.

- 80 -

AJAX, fundamentos y aplicaciones

Figura 4.16 Ejemplo de auto completado empleando AJAX Como el lector puede ver en la figura 4.16 no existe un botn de aceptar la seleccin, tenemos que elegir de entre las que hay y entonces se lanzara la peticin, aunque en una hipottica bsqueda en una base de datos estamos ahorrando tiempo y esto es verdad, a cambio cada vez que pulsamos una tecla se est lanzando una peticin al servidor con toda la sobrecarga que ello supone. Esto mismo lo podemos ver hecho por Google en Google Suggest mostrado en la figura 4.17.

Figura 4.17 Google suggest

- 81 -

AJAX, fundamentos y aplicaciones

Si el lector recuerda las operaciones con cuadritos del apartado 4.9, este mismo tipo de clculos se realizan para colocar dinmicamente la tabla justo debajo del recuadro de escritura, dando la sensacin de ser un men que se despliega automticamente. El ejemplo que nos ocupa tiene dos archivos sin contar las libreras AJAX, autoCompletar.html y pedirInfo.jsp, como el archivo autoCompletar.html no es excesivamente largo lo pondremos completo sin cortes, contiene tres partes: una pequea hoja de estilo, el cdigo Javascript y el cdigo HTML, mientras que a la pgina jsp simplemente le llega la cadena de texto que hay en el cuadro y devuelve un documento XML con las referencias encontradas. autoCompletar.html <html > <head> <title>Auto Completar</title> <style type="text/css"> .ratonFuera { background: #A9A9A9; color: #000000; } .ratonEncima { background: #5F9EA0; color: #000000; } </style> <script language="JavaScript" type="text/javascript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" type="text/javascript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> function buscarNombres(elemento) { if(elemento.value == "") //Si no hay nada escrito es que el usuario ha borrado, as que borramos la lista. { borrarInfo(); return; } var elementoActual = elemento; //Necesitaremos la variable en una funcin interior, as que la redeclaramos. borrarInfo(); //Borramos la informacin de la ventana, por si quedaba algo, no se aada al final lo nuevo y se repita. pedirInfo01= new objetoAjax("GET"); //Construimos un objetoAjax que utilizar el mtodo GET //Cuando se usa el mtodo GET la pgina a la que enviamos los datos y los datos van unidos en la misma cadena. var cadenaPeticionGET = "pedirInfo.jsp?"; //La pgina. var datos ="&cadenaTexto=" + elemento.value; //Los datos cadenaPeticionGET =cadenaPeticionGET + datos; //Unimos la pgina con el resto de los datos. /*Asignamos la funcin de completado, que llevara la carga de generar las nuevas celdas con la informacin recibida, en esta ocasin, aunque lo mas correcto sera que tuviramos una funcin propia que lo haga, esto es solo un ejemplo sencillo */ pedirInfo01.completado = function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { //Cogemos lo que nos interesa de XML. var documentoCompleto = respuestaXML.getElementsByTagName("nombre"); if(documentoCompleto.length != 0) //Si tenemos alguna respuesta aadimos informacin, sino no. { posicionVentanaInformacion(elementoActual);

- 82 -

AJAX, fundamentos y aplicaciones

for(var i = 0; i < documentoCompleto.length; i++) { //1.Creamos la fila de la tabla y le damos la informacin. var fila = document.createElement("tr"); var celda = document.createElement("td"); .innerHTML = documentoCompleto[i].childNodes[0].nodeValue; //2.Le aplicamos el estilo para que sea interactivo dependiendo de los eventos. celda.onmouseout = function() {this.className='ratonFuera';}; // Referencia a la hoja CSS celda.onmouseover = function() {this.className='ratonEncima';}; // Referencia a la hoja CSS celda.setAttribute("bgcolor", "#A9A9A9"); //3.Si pulsamos sobre uno de los sugeridos se sustituir el valor de bsqueda por este. celda.onclick = function() { ponerNombre(this);}; //4.Unimos la nueva fila a la tabla. fila.appendChild(celda); document.getElementById("cuerpoTablaSugerancias").appendChild(fila); } } } pedirInfo01.coger(cadenaPeticionGET); //Enviamos tanto la pgina como los datos en la misma cadena. } function borrarInfo() { var ventanaborrar = document.getElementById("cuerpoTablaSugerancias"); var indice = ventanaborrar.childNodes.length; for (var i = indice - 1; i >= 0 ; i--) { ventanaborrar.removeChild(ventanaborrar.childNodes[i]); } document.getElementById("tablaSugerancias").style.border = "none"; } function posicionVentanaInformacion(elemento) { //1.Vamos a reposicionar la ventana de informacin respecto al elemento que ha pedido informacin. var reposicionar = document.getElementById("tablaSugerancias"); //2.Calcular la posicin absoluta que ocupara la ventana. var anchoCelda = elemento.offsetWidth; //El mismo ancho que lel input. var izquierdaDesplazado = calcularEsquina(elemento, "offsetLeft"); //El desplazamiento a la izquierda total del input //Desplazamiento del alto del input + el alto del input. var altoDesplazado = calcularEsquina(elemento, "offsetTop") + elemento.offsetHeight; //3.Le aplicamos las propiedades a la ventana. reposicionar.style.border = "black 1px solid"; reposicionar.style.width = anchoCelda + "px"; reposicionar.style.left = izquierdaDesplazado + "px"; reposicionar.style.top = altoDesplazado + "px"; } function calcularEsquina(elemento, atributoEsquina) //ej: campo = objetoDeLaPagina , atributoEsquina = "offsetTop" { var desplazamiento = 0; while(elemento) //Mientras exista el elemento { desplazamiento += elemento[atributoEsquina]; //Le sumamos al desplazamiento, el desplazamiento del elemento. /*Normalmente cada elemento solo contiene su desplazamiento respecto al padre, no de manera absoluta, as que pasamos al elemento padre, si existe en la siguiente iteracin se sumara su desplazamiento tambin, sino terminara. */ elemento = elemento.offsetParent; } return desplazamiento;

- 83 -

AJAX, fundamentos y aplicaciones

} function ponerNombre(celda) { document.getElementById("nombres").value = celda.firstChild.nodeValue; borrarInfo(); } </script> </head> <body> <h1>Auto Completar</h1> <h3>Los nombres que hay en el fichero jsp del servidor empiezan por A y por N.</h3> <form action="null"> Nombres: <input type="text" size="20" id="nombres" onkeyup="buscarNombres(this);" style="height:20;"/> </form> <table id="tablaSugerancias" bgcolor="#A9A9A9" border="0" cellspacing="0" cellpadding="0" style="position:absolute;"> <tbody id="cuerpoTablaSugerancias"></tbody> </table> </body> </html> Se han resaltado dos funciones para remarcar algo interesante: La funcin buscarNombres hace una peticin bastante sencilla y comprensible: hace una peticin en base a lo que el usuario ha escrito en el cuadro de texto. Cuando llega el resultado, ste va a la funcin objetoRequestCompletado01 que recoge el documento XML, lo analiza sacando los nombres y crea la tabla dinmicamente Todos los elementos que componen el ejemplo los hemos visto ya, y los hemos remarcado precisamente para dejar patente que ya se han cubierto todos los aspectos principales de la programacin usando AJAX: a partir de aqu es la imaginacin lo que ms cuenta realmente. Para terminar aqu est el archivo .jsp que realiza la bsqueda y genera el documento XML, se ha programado una bsqueda para que los lectores con pocos conocimientos del lenguaje puedan comprenderlo en vez de utilizar una funcin preconstruida. pedirInfo.jsp <%@ page import="java.io.*,java.util.*,java.lang.*" contentType="text/xml; charset=UTF-8" pageEncoding="UTF-8"%> <% response.setHeader("Cache-Control", "no-cache"); //1.Recuperamos la cadena de la peticin request.setCharacterEncoding("UTF-8"); String prefijo = request.getParameter("cadenaTexto"); //2.Creamos las sugerencias ArrayList listanombres = new ArrayList(); listanombres.add("Ana"); listanombres.add("Anamaria"); listanombres.add("Anastasia"); listanombres.add("Adolfo"); listanombres.add("Alex"); listanombres.add("Naomi"); listanombres.add("Noelia"); listanombres.add("Nora"); listanombres.add("Nox"); //3.Miramos las que coinciden y construimos un documento XML. //3.1 Variables necesarias

- 84 -

AJAX, fundamentos y aplicaciones

Iterator i = listanombres.iterator(); boolean valido = true; //3.2 Iteracion para construir el cdigo (Es lineal y pesado). out.println("<listaNombres>"); while( i.hasNext() ) { String nombre=(String)i.next(); //Comprobacin de igualdad de la vieja escuela. if (prefijo.length() <= nombre.length()) { char[] nombre2 = nombre.toCharArray(); char[] prefijo2= prefijo.toCharArray(); int j=0; while (j < prefijo.length() && (prefijo2[j] == nombre2[j]) ) { j++; } valido = (j == prefijo.length()); } else { valido = false; } if(valido) { out.println("<nombre>" + nombre + "</nombre>"); valido = false; } } out.println("</listaNombres>"); out.close(); %> El ejemplo termina aqu; slo comentar nuevamente que este tipo de pequeas aplicaciones crea tantas peticiones al servidor como teclas pulsamos: si escribo un nombre de 6 caracteres se lanzaran 6 peticiones. Se podra poner una espera y que solo se hiciera la peticin a los dos segundos de haberse modificado el texto, con lo que al usuario le dara tiempo de escribir varias letras y la bsqueda realizada por el servidor quedara ms refinada y eficiente.

- 85 -

AJAX, fundamentos y aplicaciones

Captulo 5:
Problemas de seguridad y desarrollo
Introduccin

5.1 Descripcin del captulo


Como cualquier otra tcnica o tecnologa que se emplee en un entorno Web, el uso de AJAX est sujeto a inconvenientes. La experiencia ensea que con el tiempo estos inconvenientes se suplen cuando el mercado apoya una tecnologa y sta se estandariza lo suficiente como para que los distintos navegadores no den problemas con ella, ya sean estos de compatibilidad o de seguridad. AJAX permite realizar ahora cosas que antes no se podan o necesitaban uso de plugins, adems de aumentar la interactividad al poder mantener la conexin con el servidor de forma sencilla. Por este motivo la industria se ha volcado mucho ltimamente en desarrollar software con AJAX, pero ste es todava un poco inmaduro. En este captulo comentaremos los principales problemas de los entornos Web que utilicen AJAX as como los problemas de desarrollo que supone.

5.2 Problemas de desarrollo


Vamos a enumerar los problemas debajo de un ttulo que marque su naturaleza para que se vea claro que los problemas de desarrollo no solo son muchos sino que no son pequeos. Internet Oscura: Como las pginas generadas por AJAX generan informacin dinmicamente los robots de Google no encuentran muchas veces nada en la pgina, obteniendo un ranking deficiente, para evitarlo, deben crearse pginas especiales de recorrido completo. Complejidad Aumentada: Los desarrolladores de la parte cliente de la aplicacin deben entender la parte lgica del programa suficientemente como para que se combine satisfactoriamente con la parte servidor. Por tanto, es fcil mezclar lgica de presentacin y lgica de negocio. Los desarrolladores de pginas Web deben tener habilidad para trabajar con Javascript. Aplicaciones difciles de mantener: Javascript es difcil de testear. No hay unos patrones de diseo con Javascript claros ya que no se ha utilizado apenas. La modularidad de Javascript es muy limitada. Las herramientas de desarrollo usando AJAX son inmaduras: Como es ahora cuando se est empezando a emplear el objeto XMLHttpRequest las herramientas de desarrollo todava estn en fase beta. El objeto XMLHttpRequest no est estandarizado: Una futura versin de Internet Explorer podra solucionar esto. El objeto XMLHttpRequest no est en navegadores antiguos: Obliga a las personas que quieran utilizar aplicaciones AJAX a actualizarse, cosa que no es demasiado grave para cualquier usuario medio. Dependencia de la tecnologa Javascript: Javascript debe estar activado para que las aplicaciones funcionen. Hay pequeas incompatibilidades entre navegadores lo que obliga a testear el cdigo en todos aqullos en los que queramos que funcione correctamente. Cualquier persona con algo de experiencia en el uso de AJAX se da cuenta de todo lo que esto supone, el uso de AJAX para poder crear una aplicacin exitosa obliga a tener conocimientos de Javascript y del DOM y, durante su desarrollo y una vez terminada, a testarla en los diferentes navegadores donde se quiera utilizar y a corregir los problemas. Si no se es disciplinado el desarrollo con AJAX sale realmente muy caro a una empresa, tanto en tiempo como en la necesidad de profesionales cualificados.

- 86 -

AJAX, fundamentos y aplicaciones

5.3 Problemas de seguridad


Cuando queramos analizar la seguridad de un programa en red tenemos dos partes claramente diferenciadas: servidor y cliente/s. El anlisis de seguridad se debe hacer pensando que el atacante conoce perfectamente todo el funcionamiento del sistema ya que no se puede confiar en que ayude mantenerlo en secreto; sus mismos desarrolladores pueden atacarlo. Parte del cliente: En principio todas las aplicaciones Web estn sujetas a los mismos problemas de seguridad ya que todas se suelen correr sobre el mismo software del servidor al que le llegan las peticiones de los usuarios no identificados ya que nunca podemos asegurarnos realmente de quien hay al otro lado de la lnea, si la aplicacin necesita de seguridad deber ser el servidor el que la proporcione. A nadie se le ocurrira poner la seguridad en el lado cliente ya que equivale a servir en bandeja al cracker todo el control de seguridad. Problemas viejos que nos ha recordado AJAX: El cdigo Javascript es visible al usuario, que perfectamente puede ser un potencial Hacker, puede buscar la forma de utilizar el cdigo, como est o con las modificaciones oportunas para explotar las debilidades de la aplicacin.

Solucin Mala: Encriptarlo, si se ejecuta es porque nuestra mquina es capaz de desencriptarlo con lo cual seguro que es posible la ingeniera inversa. Solucin Buena: No existe, el cdigo debe ser visible para que se ejecute. El cdigo Javascript puede ser bajado y evaluado (eval) en el cliente, como hemos visto en los ejemplos, si fuera cdigo con malas intenciones el cliente podra hacer poco ante ello.

Solucin 1: Utilizar algn tipo de rea de pruebas para el cdigo antes de lanzarlo directamente que lo analice, existen ya algunos filtros que evitan la ejecucin de ciertas funciones o envo de ciertas etiquetas. Solucin 2: El cdigo Javascript podra estar Firmado digitalmente, sera una buena solucin futura, pero hoy es solo una idea. Si queremos que la informacin de nuestras peticiones no sea visible deberemos utilizar un canal HTTPS.

Parte del servidor: Formas de proporcionar seguridad en el lado servidor: Solo dejar utilizar la aplicacin a los clientes que puedan validarse realmente con su firma digital, (hoy da todava muy raro). Utilizar los mecanismos de identificacin de sesin que pueda proporcionarnos el servidor de forma que podamos validar y autorizar al usuario comprobando sus privilegios. (lo mas aceptado actualmente). Problemas agravados por el uso de AJAX: El principal problema del uso de AJAX respecto al de una aplicacin Web normal es que, debido a su naturaleza (hacer peticiones para luego refrescar trozos una pgina), el desarrollador puede perfectamente desglosar las diferentes partes de la pgina JSP, incluidas las que necesitan autenticacin y autorizacin, o incluir otros servicios que necesiten por ejemplo de una base de datos. Al terminar la aplicacin a un desarrollador no demasiado experto puede quedarle el esquema de la figura 5.1 que si bien puede funcionar correctamente es fcilmente atacable ya que tiene una GRAN SUPERFICIE DE IMPACTO (este problema surge al dividir un programa en mdulos accesibles individualmente ya que tambin se pueden intentar atacar individualmente buscando un comportamiento incorrecto que genere algn agujero de seguridad), este es el gran problema de AJAX, pero puede solventarse.

- 87 -

AJAX, fundamentos y aplicaciones

PARTE CLIENTE

PARTE SERVIDOR (Accesibles directamente por una direccin) Necesitan validacin PARTE 2

CLIENTE

VALIDADOR

No necesitan validacin

BASE DE DATOS

PARTE 1

Figura 5.1 Aplicacin desarrollada con una seguridad ineficiente En la figura 5.1 el cliente tiene acceso directo a todas las partes de la aplicacin, lo que resulta abominable ya que la validacin no sirve de nada si no se hace antes de cualquier servicio que lo necesite lo que requiere mucha repeticin de cdigo, adems al equipo de desarrollo se le puede escapar alguna validacin y como los servicios se pueden acceder individualmente (en este caso) puede haber algn agujero de seguridad en alguno. Lo ideal para proporcionar seguridad sera el caso de la figura 5.2.
Servidor accedible por una direccin No necesitan validacin SERVICIO 1 Cliente Servidor (No accesible directamente o por una direccin) Necesitan validacin CONTROLADOR B.D BASE DE DATOS

VISTA

VALIDADOR

SERVICIO 2

Figura 5.2 Aplicacin desarrollada con una seguridad correcta Como vemos, el hecho de que el lado servidor de nuestra aplicacin est diseado de forma segura es la verdadera clave de la seguridad en las aplicaciones Web ya que todo el cdigo de la parte cliente es visible a ataques y modificaciones en la memoria del cliente para atacar a la parte servidor. Notas finales: Con todo lo anterior ya dicho, remarcamos lo siguiente: La parte cliente es totalmente vulnerable ya que el usuario puede modificar su cdigo para atacar al servidor.

- 88 -

AJAX, fundamentos y aplicaciones

La parte servidora tiene que negar el acceso a las zonas criticas a una persona no identificada sin dejarle ninguna posibilidad de acceso y debe verificar al usuario antes de cada operacin. Como el mtodo GET deja que se enven cadenas de variables junto con la URL debemos emplear el mtodo POST ya que las URL accedidas suelen ser guardadas por los navegadores en un histrico, lo que permitira ver la informacin confidencial escrita en un formulario HTML enviado al servidor.

Lo siguiente que se va a tratar son las polticas de origen de datos y el lanzamiento de cdigo malicioso ya que AJAX es vulnerable a estos problemas si la aplicacin no est diseada con un perfil de seguridad muy riguroso.

5.4 Poltica de mismo origen


La poltica de mismo origen data de Netscape Navigator 2.0, fue una importante medida de seguridad introducida para proporcionar seguridad en el lado cliente cuando se esta ejecutando cdigo sobre el navegador (en mayor parte de los casos Javascript). Esta poltica evita que un documento o script cargado desde un determinado sitio web pueda realizar peticiones a otro sitio web diferente; es interesante que a la hora de desarrollar las aplicaciones utilizando AJAX sepamos esto ya que es un lmite impuesto para garantizar la seguridad, vemoslo con un ejemplo. CargarOtroDominio.html <html> <head> <title>Insertar HTML</title> <script language="JavaScript" src="lib/ConstructorXMLHttpRequest.js"></script> <script language="JavaScript" src="lib/ClasePeticionAjax.js"></script> <script language="JavaScript" type="text/javascript"> var PeticionAjax01 = new objetoAjax(); //Definimos un nuevo objetoAjax. PeticionAjax01.completado = objetoRequestCompletado01; //Funcin completado del objetoAjax redefinida. function objetoRequestCompletado01(estado, estadoTexto, respuestaTexto, respuestaXML) { document.getElementById('ParteHTML').innerHTML = respuestaTexto; //Solo nos interesa la respuesta como texto } </script> </head> <body> <span id="ParteHTML"> //Principio del cdigo que se va a sustituir <center> <button onclick="PeticionAjax01.coger('http://www.google.es/')">Coge http://www.google.es/</button> </center> </span> //Final del cdigo que se va a sustituir </body> </html> Estamos insertando el cdigo HTML de la pgina de Google de forma poco elegante, pero como ejemplo nos vale. En este ejemplo, la pgina CargarOtroDominio.html est cargada desde el dominio localhost con el puerto 8080, y si alguno de estos parmetros cambia en una peticin AJAX, la poltica de mismo origen entrar en juego. En las versiones actuales de Mozilla Firefox, simplemente no cargar nada y nos extraaremos, ahora si miramos en herramientas la consola Javascript veremos que nos ha dado un error, podemos ver un ejemplo en la figura 5.3.

- 89 -

AJAX, fundamentos y aplicaciones

Figura 5.3 Mozilla Firefox 1.4 mostrando un cuadro de error debido a la poltica de mismo origen En cambio Internet Explorer, nos mostrara una alarma y nos preguntar si queremos permitirlo, recordndonos que es un riesgo de seguridad, podemos verlo en la figura 5.4.

Figura 5.4 Internet Explorer 6 pidiendo una confirmacin debido a un posible riesgo de seguridad

Si queremos permitir la carga de dominios diferentes sin problemas deberemos modificar ciertos parmetros de nuestro navegador. En cualquier caso, a nivel de utilidad real, no esperemos que ningn usuario se ponga a modificar los parmetros de su navegador para poder ver nuestra super pgina web, porque no lo har, es ms, hay navegadores que ni siquiera proporcionan esta posibilidad: no se pueden configurar y simplemente negarn el acceso ya que esto atenta contra la seguridad.

5.5 AJAX Cross-site scripting(AXSS)


Tenemos que la poltica de mismo origen protege al usuario de que alguien muy malo le haga algn feo recogiendo cdigo fuera del dominio, pero si ya estamos dentro del dominio de donde coger el cdigo malicioso estamos perdidos, los AXSS se basan en usar cualquier tipo de vulnerabilidad para introducir un objeto XMLHttpRequest y desde ah enviar contenido sin conocimiento del usuario, esto es posible en pginas Web que dejan insertar cdigo HTML al usuario, wikipedias, foros, etc. Si su filtro de etiquetas no es suficientemente bueno o si los navegadores leen cdigo javascript fuera de las etiquetas <script> colocadas explcitamente, un atacante puede insertar cdigo malicioso en una pgina Web de la que hace uso una comunidad de usuarios; imaginemos las consecuencias, se podra enviar a un servidor con una base de datos informacin de las variables de usuario que puede contener entre otras cosas si la pgina no

- 90 -

AJAX, fundamentos y aplicaciones

esta bien diseada (que es lo que causa los agujeros de seguridad al final) la informacin para acceder a su cuenta.

5.6 Desarrollo de una aplicacin Web segura


Se va a enumerar una serie de cosas que se deberan tener en cuenta en el planteamiento inicial del proyecto si estamos desarrollando una aplicacin Web crtica, como es el caso de la pequea tienda virtual que se va a exponer a continuacin.

5.6.1 Cosas a tener en cuenta


Enumeremos brevemente los aspectos ms relevantes en los que deberamos fijarnos para evitar ataques, estos no son solo para AJAX pero marcaremos los ms relacionados.

5.6.3.1 Conexin cifrada


La conexin debera estar cifrada desde la pgina principal para que cuando el usuario mande sus datos personales estos estn codificados, aunque esto haga gastar ms recursos. Hay que configurarlo en el servidor, en nuestro caso Tomcat.

5.6.1.2 Sin cookies


Entre otras cosas, gracias a AJAX, al no necesitar cambiar de Web e ir modificando dinmicamente la actual, podemos darle al usuario un identificador al comenzar la sesin, apuntarlo en la base de datos y no necesitar usar ningn cookie sino una variable que contenga el identificador y que se borrar al cerrar el navegador, de esta manera enviando ese identificador con cada peticin identificaramos al usuario.

5.6.1.3 Verificacin completa del usuario


Al desarrollar un sitio Web debemos dividirlo en dos partes claramente diferenciadas: una a la que se puede entrar sin verificacin y otra en la que ser obligada. Por ejemplo si tenemos una tienda, podemos tener una parte de noticias pblica, donde el usuario adems pueda ver los productos pero en caso de que quiera realizar una compra el usuario tenga que introducir su nombre y contrasea que ha dado anteriormente cuando se registr, dando sus datos de cuenta y dems, aunque estos se podran especificar ms tarde por si quiere cambiar el domicilio de envo o cualquier otra informacin personal.

5.6.1.4 Evitar la insercin de cdigo


El usuario no debera poder introducir informacin en ningn momento, la pgina debe estar hecha completamente para su cometido, que es realizar las compras a golpe de clic, en caso de dudas que se hagan por correo-e.

5.6.1.5 Verificacin completa de datos


Cuando el usuario decida pagar por su carrito de la compra, se deber comparar toda la informacin enviada de nombre del artculo, su identificador nico y su precio de manera que sepamos que la peticin es correcta ya que el usuario podra cambiar los precios de los artculos usando alguna herramienta de depuracin, como Firebug.

5.6.1.6 Base de datos no accesible exteriormente


Solamente debe de poder trabajar con ella la parte del servidor Web y debe tener un usuario que solo debe poder acceder a su base de datos para evitar que se cambien los precios aqu, si es que tenemos una tienda. Adems, en una aplicacin Web el usuario no necesita acceder directamente al servidor por SQL a no ser que sea precisamente para esto como el ISQLPlus de Oracle, en cuyo caso est diseado expresamente para esto.

5.6.1.7 Minimizar la superficie de impacto


El cliente solo debe poder acceder a una pgina que luego delegar dependiendo la peticin realizada por el usuario el trabajo en otras contenidas en el servidor no accesibles desde fuera.

- 91 -

AJAX, fundamentos y aplicaciones

5.6.2 Esquema general de una aplicacin de ejemplo sencilla


Es una buena prctica y se us para realizar este ejemplo el realizar algunos esquemas que muestren como debera de ser el modelo lgico, si bien algunas veces la aplicacin final, debido a algn factor que no hemos controlado inicialmente, no tiene porque ser exactamente igual, nos va a ayudar mucho para saber lo siguiente en lo que tenemos que trabajar. Los esquemas que se realizaron para hacer la aplicacin que nos ocupa son los mostrados en las figuras 5.5, 5.6 y 5.7.
PARTE 01 ENTRADA A LA TIENDA. OPERACIONES CON USUARIO SIN AUTENTIFICAR.

ESTADO 001 index.html Usuario No existente Login Password ... Usuario Existente Login Password

SOLO ESTADO 001 servicios.jsp Servicio 001 Crear Usuario

ID SESIN

ESTADO 002

index.html LOGOUT PAGINA PRINCIPAL DE LA TIENDA Noticias Comprar Carrito actual

Servicio 002 Comenzar Sesin

Figura 5.5 Planificacin de la aplicacin, acciones del usuario sin validar.

PARTE 02 USO DE LA TIENDA, OPERACIONES CON USUARIO AUTENTIFICADO.

ID SESIN

ESTADO 002

SOLO ESTADO 002 servicios.jsp Servicio 003 Peticion Pgina auxiliar por parte del usuario xxxx Servicio 004 Aadir al carrito del usuario xxxx producto xxxx Servicio 005 Borrar del carrito del usuario xxxx producto xxxx Servicio 006 Acceptar el carrito del usuario xxxx.

index.html LOGOUT PAGINA PRINCIPAL DE LA TIENDA Noticias Comprar Carrito actual

Servicio 007 LOGOUT

Figura 5.6 Planificacin de la aplicacin, acciones del usuario autentificado

- 92 -

AJAX, fundamentos y aplicaciones

PARTE 03 POSIBLES ACTUACIONES CON LA BASE DE DATOS INTERNA, NO ACCESIBLE DESDE INTERNET DIRECTAMENTE, ACCEDE SOLO LA PGINA DE SERVICIOS.

Servicio 001 Existe usuario xxxx?

Servicio 002 usuario xxxx esperando confirmacion mail para dar de alta. Servicio 003 usuario xxxx dado de alta.

SOLO ESTADO 001

Servicio 004 Existe usuario xxxx? Con password xxxx?

Servicio 005 Sesin usuario xxxx con ID xxxx Iniciada.

Servicio 006 Sesin usuario xxxx con ID xxxx Terminada. Servicio 007 Sesin con ID xxxx aade al carrito del usuario xxxx, producto x. SOLO ESTADO 002

Figura 5.7 Planificacin de la aplicacin, acciones con la base de datos Como se ve, al realizar la aplicacin solo hay en el esquema una pgina html y una pgina jsp, realmente hay una pgina html ms pero se inserta el cdigo de esta en la principal, se hizo as por simplificar y no tener que crear una enorme pgina dinmicamente, pero en ningn caso sta incluye nada ms, es texto plano, todas las libreras (archivos .js) para el funcionamiento correcto en la parte cliente se incluyen con la pgina ndice, la aplicacin va tomando forma teniendo con los siguientes archivos.

Figura 5.8 Archivos que componen la aplicacin El cdigo de la aplicacin son unas 600 lneas de cdigo, ms que menos, no es objeto de este captulo perder 25 pginas documentndola, es un ejemplo prctico del que se ha visto el modelo terico que est presente en los esquemas de las figuras 5.5, 5.6 y 5.7 que respetan fielmente el esquema de la figura 5.2 que se puso como un ideal aunque se encuentren los diferentes bloques de verificacin, vista, servicios y

- 93 -

AJAX, fundamentos y aplicaciones

el controlador de la base de datos en el archivo pasarelaDeSeguridad.jsp , la carpeta tiendaPedidos debe estar protegida para que no se lea va Web. Por ltimo comentar que las sesiones se establecen de la siguiente manera, el cliente enva su nombre y contrasea al servidor (pasarelaDeSeguridad.jsp), ste comprueba que la informacin dada es correcta y establece un identificador de sesin que guarda en la base de datos, nos devuelve el identificador y lo usaremos de ahora en adelante para comunicarnos con el servidor.

Figura 5.9 Parte de los datos de la tabla de clientes, una fila por cliente, en ella se guarda tambin el identificador de sesin.

5.6.3 Resultados visibles de la aplicacin de ejemplo


Primero se ver el funcionamiento de la aplicacin, segundo se dir qu aspectos no se han cubierto por no aadir ms complejidad pero que, para cualquier desarrollador de este tipo de aplicaciones, son irrelevantes ya que no cuesta nada incluirlos, por ltimo se buscar algn problema de seguridad en la aplicacin, buscando posibles agujeros de seguridad.

5.6.3.1 Funcionamiento de la aplicacin


Lo ms fcil es probablemente verlo con algunas imgenes.

Figura 5.10 Primera pgina Si nos fijamos en la figura 5.9, tenemos dos reas un rea de registro y una para ingresar, tal como se muestra en la figura 5.5 son los nicos servicios a los que un usuario no identificado debera tener acceso, si esto fuera una tienda de verdad querramos que los visitantes pudieran ver los productos aunque no

- 94 -

AJAX, fundamentos y aplicaciones

compraran, esto se podra hacer mostrndoles una rplica de la tienda para comprar pero sin la opcin del carrito y de cierre de sesin.

Figura 5.11 Pgina interior Si hemos alcanzado lo que muestra la figura 5.10 es que el usuario se ha validado correctamente, en caso contrario obtendramos el consecuente mensaje de error en la pgina anterior y no ocurrira nada, es bueno que recordemos a los clientes que cierren la sesin al salir, en este ejemplo se ha querido dejar muy claro y es difcil que vean los productos sin darse cuenta. En el caso de esta aplicacin la sesin se guarda con un identificador en la base de datos que se le da al usuario tambin para que lo enve con cada peticin y sepamos quin es evitando as el uso de cookies, cada vez que cualquier usuario registrado entra a la tienda se le da un identificador nuevo y stos no se repiten (tericamente) ya que son aleatorios.

Figura 5.12 Pgina de compras En este ejemplo se hace uso intensivo de los documentos XML para recibir las respuestas del servidor, es ms los productos estn en una base de datos, el archivo JSP los lee, prepara un documento XML y lo enva, el cliente los lee y los muestra, sta es una solucin excelente bajo AJAX ya que si se termina un

- 95 -

AJAX, fundamentos y aplicaciones

producto evitamos que la base de datos lo muestre y si tenemos que aadir uno se mostrara inmediatamente la prxima vez que entrramos en la pgina, igual si lo quitamos debido a que se agotaron. Las pginas JSP estn pensadas para presentacin y la estamos usando para generar un documento (presentarlo y devolverlo al cliente pero en segundo plano), debido a AJAX ahora surge esta utilidad que tal vez no respeta del todo algunos esquemas de trabajo de la calle, en esta ocasin se ha realizado as ya que es simple y seguro, pero todo el cdigo del tratamiento del XML en el cliente y la generacin del XML en el servidor estn acoplados y una alteracin en uno puede conllevar a rehacer trabajo en el otro lado.

Figura 5.13 Terminando de hacer la compra, se cierra la sesin automticamente Por motivos de diseo, se decidi que no se pudiera hacer ms de 1 compra con el mismo identificador, para usarlo como parte del nombre del archivo de compra, es decir solo puede haber un carrito (lleno con diferentes objetos) por cada identificador que corresponder con una hoja de pedido como la siguiente.
************** HOJA DE PEDIDO ************** DATOS DEL USUARIO: -----------------ID NICO: 31 NOMBRE: Luc APELLIDOS: Ramos CORREO ELECTRNICO: loco@tom.com NMERO TARGETA: 000 PROVINCIA: 0000 CIUDAD: 0000 DOMICILIO: 0000 CDIGO POSTAL: 0000 ESTADO SESIN EN EL MOMENTO DEL PEDIDO: --------------------------------------ESTADO SESIN: iniciada ID DE SESIN: 8.873812011247969E138.385907809230895E13 PRODUCTOS DEL PEDIDO: --------------------ID DEL PRODUCTO: 2 NOMBRE DEL PRODUCTO: Pantaln Corto PRECIO DEL PRODUCTO: 7 CANTIDAD SOLICITADA: 2 ID DEL PRODUCTO: 1 NOMBRE DEL PRODUCTO: Camiseta Roja PRECIO DEL PRODUCTO: 3 CANTIDAD SOLICITADA: 2 CANTIDAD TOTAL A ABONAR: -----------------------TOTAL: 20.0

- 96 -

AJAX, fundamentos y aplicaciones

Por ltimo, sta es una hoja de pedido que se crea. Este tipo de cosas siempre las debe hacer el servidor verificando que todos los productos que ha pedido el cliente son correctos, tanto en nombre como en precio.

5.6.3.2 Aspectos que no se han cubierto


Hay un par de cosas que no se han hecho en el ejemplo: La primera es que se pueden crear usuarios fraudulentamente, la creacin de un usuario debera ser tras comprobar que la direccin de correo-e que ha dado es correcta teniendo el usuario que aceptar la creacin de su cuenta desde l y no dejar ms de un usuario por direccin de mail, de esta forma se evitara que se llenara la base de datos de usuarios broma. La segunda es que se debera comprobar que el formateado de los datos al crear el usuario es correcto, filtrndolos por una funcin que diga si pertenecen o no a este tipo, si nos fijamos en la figura 5.13 el nmero de tarjeta es incorrecto, quitando que todos los datos son falsos y no se ha dado tampoco el domicilio completo.

5.6.3.3 Posibles puntos de ataque y mal funcionamiento


En principio el atacante puede intentar o suplantar a alguien o usar su propia cuenta pero cambiando los precios. Lo primero es tericamente poco probable, no se pueden conseguir los datos de otra persona debido a: No se tiene acceso a la base de datos desde el exterior. No se pueden capturar cookies ni nada parecido porque existen temporalmente en la memoria del usuario y no se puede acceder a la base de datos. El identificador del usuario se enva en un canal cifrado, aunque el usuario no cerrara la sesin correctamente sera imposible deducirlo o capturarlo, igual para su nombre o contrasea. Si se genera la hoja de peticin la sesin se cierra con lo que da igual que se lea el identificador. Lo segundo es definitivamente imposible porque: No se puede cambiar los precios en la base de datos porque no se puede acceder a la base de datos desde el exterior. No se pueden cambiar los precios en el navegador ya que si se enva informacin con el precio cambiado se detecta y se cierra la sesin automticamente. En cambio sera posible suplantar a una persona si la tenemos fsicamente al lado y los dos tenemos una cuenta abierta; yo, el atacante, deber mirar el identificador de sesin del otro usuario (est en una variable Javascript del navegador) y copiarla a la ma, cuando compremos cualquiera de los dos se cerrara la sesin con lo que solo podra comprar uno. Para hacer esto tenemos que, cuando estemos en la pgina del carrito los dos, abrir con un depurador el DOM de la pgina y copiar el identificador de uno en otro pero es MUY POCO PROBABLE que un amigo nuestro nos deje estafarle o que otro nos d tiempo a hacerlo, este tipo de ataques no son muy evitables que digamos, si te ponen una pistola en la espalda seguro que le das tu tarjeta o no? Se concluye mencionando que si se deja la sesin abierta ya sea por descuido o porque se entra en la tienda abrindola dos veces haciendo uso de dos ventanas del navegador, cada vez que se entre se asignar un identificador nuevo, con lo cual la ventana anterior es un programa muerto al que ya no se le dejara realizar ningn tipo de tareas.

5.7 Futuro de AJAX


Como se ha visto AJAX no genera nuevos problemas realmente, en cambio solventa problemas de interactividad y el de las cookies ya que no es necesario cambiar de pgina, no necesita plugins pero, en cambio, tiene que estar bien soportado por todos los navegadores y ser compatible. Es algo nuevo pero con una esperanza de vida grande ya que hay multitud de pequeas comunidades y grandes compaas desarrollando alrededor de l ltimamente.

- 97 -

AJAX, fundamentos y aplicaciones

En un futuro no muy lejano se espera de l lo siguiente: Creacin de unas libreras estndar, libres de fallos y de agujeros de seguridad, la mayor parte de los toolkits actuales suelen emplear el mtodo GET por defecto lo que parece increble pero cierto. Estandarizacin del objeto XMLHttpRequest. Mejora del soporte por parte de los navegadores con lo que se podrn hacer todava ms virgueras. Mejora de los patrones de diseo con Javascript y esto ltimo es muy importante. Con todo lo aprendido hasta el momento durante todos los captulos de este podemos concluir este captulo diciendo que gracias a AJAX se pueden realizar aplicaciones de gran calidad, rpidas, sin agujeros de seguridad, vistosas grficamente y muy interactivas pero que requiere de un equipo bastante experto.

- 98 -

AJAX, fundamentos y aplicaciones

Captulo 6:
El poder de AJAX: Documentacin
6.1 Descripcin del captulo
El captulo actual recoge y explica simplificadamente los diferentes problemas que surgieron en el diseo y la implementacin de El Poder de AJAX, antes de leerlo sera bueno que jugaras un poco. Aqu tienes un guin de las cosas que vamos a aprender sobre el juego, que nos introducir en toda la problemtica de programar entornos interactivos con unas necesidades extremas ya que se hacen una gran cantidad de peticiones asncronas adems de cargar al navegador con una intensidad de clculos y tratamiento dinmico que para l no es normal. Se ha intentado que el orden en que se ven las cosas permita un aprendizaje lo ms natural posible, se evitar a toda costa intentar ensear las ideas con el cdigo, para eso est ya el juego de ejemplo muy comentado pero complejo, lo mas recomendable sera leer cada seccin y luego la parte de cdigo asociado si es que al lector le interesa (se comentar el archivo donde se encuentra y el nombre de las funciones), ya que ser en ese momento cuando lo ver ms fcil, aun as no desesperes si te cuesta comprenderlo, los juegos son muy complejos, usan una gran cantidad de ideas que no son tuyas, hace falta estudiarlos con tranquilidad durante algn tiempo para entenderlos, adems, este, est hecho por un novato que ha resuelto todos estos problemas por su cuenta, porque quera hacerlo y disfrutaba con ello. Parte offline del juego Introduccin. Los juegos ms interactivos son solo bucles y banderas (Flags). Representacin grfica en HTML, la necesidad de generar y destruir cdigo. Paso de parmetros en Javascript, la necesidad de emplear variables globales. Los eventos y el DOM, debemos conocer algunos. Leer del teclado para hacer los controles. Algoritmos de control. Algoritmos de colisiones basados en hojas de estilo y optimizarlos. Propiedades que deben cumplir los grficos para el juego. Precarga de imgenes. Precarga de sonido. Cuadros de informacin: vida, objetos, mapa y consola. Sistema de batalla y golpes. Parte online del juego Disear la base de datos dependiendo de las necesidades del juego. La I.A. de los enemigos, los debe mover el servidor para evitar trampas. Los objetos deben ser asignados por el servidor para evitar trampas. El dao de un jugador a otro debe de ser notificado por el que se ve golpeado. El cambio de pantalla debe ser notificado y aceptado antes de realizarlo. Actualizar la posicin del jugador. Actualizar objetos al cogerlos (Asncronamnete). A fondo El archivo servidor.jsp. El archivo calculosColisiones.js. Requisitos del sistema y conexin Gran consumo de memoria y CPU por parte de los navegadores. Necesidades de conexin.

- 99 -

AJAX, fundamentos y aplicaciones

6.2 Parte offline del juego


Se ha separado en dos partes las diferentes cosas que se van a ensear por dos motivos, el primero es que para hacer un juego en un entorno Web no necesita necesariamente que sea multijugador o Online. El segundo motivo fue que el juego de ejemplo en principio fue diseado offline y la parte online se aadi cuando se llevaban partes de su desarrollo, realmente la parte de diseo online no estaba completada cuando se comenz a programar pero se pens en un diseo lo suficientemente escalable como para que no hubiera demasiados problemas, y no los hubo. El juego comenz siendo offline para probar la capacidad del entorno Web actual de los navegadores ms punteros y ver si era realizable en una cantidad de tiempo viable, unas 120-130 horas. Mientras que hablemos de la parte offline del juego nos sumergiremos en los problemas propios de querer representar las cosas en una pgina Web, haciendo uso de las hojas de estilo, tambin veremos lo bonito que es Javascript, algunas veces lo adoraremos, muchas veces lo odiaremos, y por supuesto no olvidaremos que buscamos una compatibilidad muy alta entre navegadores, a da de hoy el juego funciona perfectamente en Mozilla 1.5, 2.0 y I.E.7, no se han probado mas navegadores durante la parte de desarrollo para no alargarla mas.

6.2.1

Los juegos ms interactivos son solo bucles y banderas (Flags)

Existen muchos tipos de juegos, si los encapsulamos en 2 grandes grupos tenemos los que se juegan por turnos (los de tablero) y los que se juegan en tiempo real, normalmente los que se juegan en tiempo real son ms complejos, como es el caso que nos ocupa, y tienen unos requerimientos de tiempo de respuesta alto en contrapartida a los de tablero en los que esperas a que mueva el otro jugador o la mquina. Los de tablero no son ningn problema en un entorno Web y el hacerlos multijugador ahora con AJAX tampoco, en cambio los de tiempo real son un problema GORDO. En nuestro caso tenemos un problema GORDO, pero no importa, en cualquier caso los juegos son bucles, unos ms complejos que otros, pero bucles: Ejemplo(bucle principal de broma): while(jugando) { moverJugador(); calcularColisiones(); } Primero se mueve el jugador y luego se calculan las colisiones, las restricciones de movimiento y de las colisiones se deciden mediante Banderas (flags). Lo que aade de complejo un juego como el que vamos a disear son las banderas, vamos a tener unas cuantas, por no decir muchas, normalmente se utilizan para evitar rebotes. Definicin rebote o repeticin: Una accin que debera ocurrir una vez, pero se repite indefinidamente al no haber cortado la posibilidad de que ocurra otra vez mientras ocurre. Ejemplo: Un enemigo me golpea, mientras que dure la animacin del golpe el enemigo no puede volver a golpear al jugador, en otro caso este morira instantneamente ya que habran repeticiones, esto se arregla rpidamente de la siguiente manera, miramos el seudo cdigo. if(colision(jugador,enemigo01) && !jugadorGolpeado) { jugadorGolpeado = true; //Cuando comienza la accin se activa. jugador.vida--; animacionGolpeado(jugador); }

- 100 -

AJAX, fundamentos y aplicaciones

animacionGolpeado(objeto) { cambiarAnimacion(jugador,golpe); moverGolpe(jugador); esperar(500); //En milisegundos jugadorGolpeado=false; //Cuando termina la accin se desactiva. } En este caso jugadorGolpeado es una bandera, bueno si estamos haciendo un juego como el que nos ocupa, vamos a tener muchas, para muchas cosas, no son ms que variables booleanas globales, esta idea es sencilla. Un esquema del funcionamiento del bucle principal es el siguiente:

- 101 -

AJAX, fundamentos y aplicaciones

BUCLE PRINCIPAL

NO SI JUGAR

SI

SI MOVIMIENTO_JUGA_PERMITIDO Y !JUGADOR_MUERTO

NO

SI

MOVIMIENTO JUGADOR

SI !JUGADOR_MUERTO Y !JUGADOR_GOLPEADO

NO

SI

CLCULO COLISIONES OBJETOS TOCABLES

ESPERAR "X" SEGUNDOS

FLAGS USADOS(VARIABLES BOOLEANAS GLOBALES QUE ACTIVAN Y DESACTIVAN ACCIONES POSIBLES): JUGANDO:ACTIVADO CUANDO DEBE GIRAR EL BUCLE, CUANDO NO ES ESTA CAMBIAND DE PANTALLA, ETC... MOVIMIENTO JUGADOR PERMITIDO: ACTIVADO SI EL JUGADOR PUEDE MOVERSE, NO ESTA SIENDO GOLPEADO, ETC... JUGADOR MUERTO: ACTIVADO CUANDO EL JUGADOR MUERE JUGADOR GOLPEADO: ACTIVADO MIENTRAS DURA UN GOLPE, PARA EVITAR REBOTES.

Figura 6.1 Bucle principal

6.2.2

Representacin grfica en HTML, la necesidad de generar y destruir cdigo

Creo que no hace falta explicar que cuando hacemos una pgina Web, si queremos mostrar un dibujo, debemos emplear la etiqueta correspondiente, pero cmo lo quitamos sobre la marcha?, cmo lo volvemos a poner?

- 102 -

AJAX, fundamentos y aplicaciones

Tenemos 2 opciones, la propiedad innerHTML que tienen etiquetas como la div, o podemos utilizar las funciones del DOM. Veamos lo bueno y lo malo de cada una para esto: innerHTML : Es fcil, basta con hacer algo como innerHTML = innerHTML + nuevo, en contrapartida realmente estamos sobrescribiendo completamente lo anterior y aunque parezca una tontera no lo es, ya que se cambia el rbol en memoria podemos decir adis a los punteros que hayamos creado y deberemos recalcularlos, si solo tenemos un par y solo cambian bajo ciertas condiciones es una buena opcin ya que volver a buscar un par de elementos por etiqueta de vez en cuando no es costoso, pero si pretendemos realizar 1600 bsquedas por segundo olvidmoslo. DOM : Tenemos que saber hacer buen uso de las funciones lo que lo hace mas complejo, pero no es tan difcil, realmente se puede llegar a utilizar de forma bastante mecnica y es la mejor opcin para destruir una etiqueta y con ello el pedazo de cdigo que contenga, este pedazo de cdigo puede ser perfectamente una imagen o cualquier elemento html al que le podamos poner un id. Justamente en el juego de ejemplo se utiliza mucho el innerHTML para crear y el DOM para destruir, cuando se crea o destruye un objeto, algo que no es muy usual, el puntero que apunta al jugador se recalcula, podramos crear las cosas haciendo uso de las funciones del DOM y que no fuera necesario esto? , la respuesta es tal vez, seguramente NO, si vamos a insertar pedazos de cdigo de 4 o 5 lneas ya es MUY ENGORROSO usar las funciones del DOM, por lo cual insertaremos mucho cdigo A SACO y que el navegador se preocupe de crear el rbol de objetos. Ejemplo destruir usando el DOM de la divisin pantalla: function borrarObjetoPantalla(nombreID) { var borrarNodo = document.getElementById(nombreID); var PadreNodo = document.getElementById("pantalla"); PadreNodo.removeChild(borrarNodo); } Como vemos es muy simple, no tenemos ms que coger el objeto que debe tener un identificador, coger al padre con otro identificador, y decirle al padre que borre al hijo. Ejemplo de crear (solo parte del cdigo); document.getElementById("pantalla").innerHTML= document.getElementById("pantalla").innerHTML + "<table id=\""+nombre+"\" class=\""+tipoObjeto+"\" style=\"border: none ; position: absolute; left: "+posicionLeft+"px; top: "+posicionTop+"px; width: "+ancho+"px; height: "+alto+"px;\">"+ "<tr><td id=\"cajon"+nombre+"\" class=\"cajonObjetoCogible\"></td></tr>"+ "</table>"; Es muy difcil leerlo en un libro, mejor mira los archivos constructorObjetos.js ya que todos ellos insertan cdigo y no te desesperes si no lo entiendes todo ya que no ests preparado, pero se ve que estamos aadiendo cdigo que rellena los valores de las propiedades usando variables, te imaginas crear eso usando el DOM, si fuera mas rpido merecera la pena, pero si creamos un objeto de vez en cuando no es realmente necesario, no hace falta decir que cada objeto que tengamos debe tener un identificador nico, si no, no tenemos forma de buscarlo luego.

6.2.3

Paso de parmetros en Javascript, la necesidad de emplear variables globales

Entre las cosas graciosas que tiene Javascript el paso de parmetros es de las mejores, las variables solo se pasan por valor y los objetos solo por referencia, tenlo en cuenta a la hora de disear las funciones, la verdad es que podras crear un objeto y meterlo dentro una cadena, pero muchas veces es una tontera ya

- 103 -

AJAX, fundamentos y aplicaciones

que si la variable va a ser reutilizada reiteradamente 20000 por segundo en un par de funciones lo mejor es hacerla global ya que el objeto lo sera tambin. Otra cosa importante a tener en cuenta es que si son globales, ni se crean ni tampoco se destruyen, simplemente existen, de manera que ganamos mucha eficiencia si las creamos al empezar y las dejamos esperando a que sean necesarias. Esto es especialmente recomendable en las funciones de clculo de colisiones ya que estas operaciones son crticas y se deben realizar una cantidad aceptable de veces por segundo de forma rpida, de manera que no se crearan nuevas variables dentro de estas funciones, se usarn las que ya hay. Este problema no existe con los objetos ya que se pasan por referencia, algn listillo puede pensar que crear y destruir un objeto es una operacin mas costosa que una variable, pero como ya hemos dicho, los objetos se crean y destruyen de vez en cuando, en cambio las variables que se usan en los clculos de colisiones lo hacen 8variables*60iteraciones*3pixelesPorIteracion*numObjetos=1440*numObjetos por segundo, creo que con 5 objetos en la pantalla, ya sera bastante pesado, en cambio crear 5 objetos NO!! .

6.2.4

Los eventos y el DOM, debemos de conocer algunos

Como en cualquier cosa, cuanto ms conocimiento tengas de ello, ms fcilmente hars exactamente lo que deseas. No hace falta tener un conocimiento extremadamente alto del rbol del DOM realmente, pero el suficiente para que las operaciones que hagas sean compatibles con la mayora de los navegadores, por ejemplo, si queremos coger un dato de un documento XML lo suyo sera llegar hasta un nodo hoja y coger el valor de nodevalue que es ms estndar, si lo cogemos de nodetext no funcionar en Internet Explorer que no genera esa propiedad, etc. Sobre los eventos, realmente en el juego se hace un uso justo de ellos, para leer el teclado y para saber cundo est cargado el juego, porque no querrs que el jugador intente ponerse a jugar cuando el navegador todava est cargando y empiece a generar errores.

6.2.5

Leer del teclado para hacer los controles

sta es a da de hoy, tal vez, la incompatibilidad entre navegadores ms grande, ya que entre los dos ms usados Mozilla Firefox e Internet Explorer se hace de forma totalmente diferente. Esto es un juego, as que queremos coger todas las pulsaciones de teclas, las que sean tiles harn algo, las que no simplemente se desestimarn, pero necesitamos un manejador que las coja todas porque as funciona Javascript, eso lo hacemos con el siguiente pedazo de cdigo: document.onkeydown = jugadorPulsaTecla; document.onkeyup = jugadorDesPulsaTecla; Lo que asignamos es el nombre de la funcin a la que se llamar, y la funcin debe ser algo as: var arriba = 38; //FLECHA ARRIBA var abajo = 40; //FLECHA ABAJO var izquierda = 37; //FLECHA IZQUIERDA var derecha = 39; //FLECHA DERECHA var ataque = 65; //TECLA "A" function jugadorPulsaTecla(evento) { if(!evento) { var tecla=window.event.keyCode; //Internet Explorer } else { var tecla=evento.which; //Mozilla Firefox

- 104 -

AJAX, fundamentos y aplicaciones

} switch(tecla) { case arriba: teclaArribaPulsada = true; break; . . . } } Como puedes ver Mozilla Firefox mete por defecto en esta funcin el objeto event que contiene los datos del evento, en cambio Internet Explorer no, y hay que mirarlo en su DOM que contiene el objeto pero que no tiene Mozilla Firefox. Del ejemplo se han quitado las banderas, s, hasta esta funcin las tiene, para evitar que se cojan eventos de movimiento cuando por ejemplo, el juego no ha terminado de cargar y para algunas cosas del sistema de batalla. Si quieres saber mas consulta el archivo controladoresEventos.js de las libreras del juego, por ltimo recordar que leeremos las teclas solamente si la ventana del navegador es la activa en ese momento, si tenemos el navegador en segundo plano esto no ocurrir como es normal, ya que estamos programando sobre el.

6.2.6

Algoritmos de control

Este puede ser muy sencillo o muy complejo dependiendo de las necesidades que tenemos, cuntas ms cosas haga nuestro personaje, ms animado este, etc., pues nos dar ms problemas. Como pauta bsica la funcin que controle el movimiento no se debe hallar introducida en los controladores de eventos de teclado, primero porque son cosas diferentes y si enguarramos los eventos tendremos problemas ms tarde, segundo porque no conseguiremos un control tan fluido y nos dar problemas. Los controladores de eventos de teclado dependen de las interrupciones, si nuestro PC repite las teclas porque lo tenemos configurado para ello, es decir, dejo pulsadoooooooooooooo la tecla o y escribe un montn, entonces con mantener pulsada una tecla de movimiento el efecto sera el mismo, en cambio si solo escribe una, el personaje dara un paso y se quedara en el sitio, nuestro control no debe depender de esto. Para no depender de esto si se pulsa la tecla arriba debe haber una bandera que ponga teclaArribaPulsada = true y si se despulsa la tecla se pondr a false, esto se hace en los manejadores pero mover el personaje NO!! Ahora haremos otra funcin que mover el jugador en una direccin u otra dependiendo de las banderas, en el juego el control es en 8 direcciones, es decir, se permiten las diagonales, esto es posible precisamente gracias a las banderas ya que puede haber ms de una true, en cambio los eventos de teclado son 1 por tecla y no se podra hacer. Las diagonales que son 2 teclas se miran primero, antes de las teclas por separado si no nunca llegaras a moverte en diagonal, el orden tambin es importante, como ves hay que echarle mucha imaginacin, esto es un problema de los videojuegos pero nos vendr bien la experiencia para tener ideas en el futuro. Ahora si te interesa podras echarle un vistazo al archivo movimientoJugador.js, es muy complejo ahora mismo todava, veras un montn de banderas desconocidas pero con nombres muy obvios, como son las de los muros, por ms que quieras moverte a la derecha, si hay un muro en ese lado no se entrar en el bucle, adems aqu dentro es donde se cambia la animacin ya que sta depende del movimiento del personaje en nuestro caso y hay una funcin para ello, un esquema de lo que se hace en el archivo algo simplificado es el siguiente:

- 105 -

AJAX, fundamentos y aplicaciones

BUCLE DE MOVIMIENTO GENRICO DEL JUGADOR

NOTA:PRIMERO SE MIRAN LAS DIAGONALES PARA EVITAR REBOTES. NO TIENE EL JUGADOR PULSADA "X" DIRECCIN/ES?

SI INFO: LAS VARIABLES DE MURO SON GLOBALES Y SE RECALCULAN SIEMPRE QUE EL PERSONAJE SE MUEVE YA SEA POR MANDATO DEL JUGADOR O POR ALGN AGENTE EXTERNO. NOTA:SE CALCULAN EN LAS COLISIONES. SI HAY UN MURO?

NO I= 0

NOTA:SE CALCULAN LOS MUROS CADA VEZ QUE TE MUEVES 1 PIXEL PARA QUE NO LOS ATRAVIESES. MOVER 1 PIXEL MIENTRAS "I"< NUMPIXELES Y !MURO_EN_ESA_DIRECCIN NO SI CALCULAR COLISIN MUROS

I++

FIN

COSAS QUE AADIR AL ALGORITMO ANTERIOR QUE TIENE EL FINAL: 1.PUNTO DE VISTA DEL PERSONAJE, CAMBIARLO Y BLOQUEARLO BAJO CIERTAS CIRCUNSTANCIAS. 2.SE ENTRE FORZADAMENTE CON EL PERSONAJE PARADO PARA REFRESCAR LA IMAGEN DEBIDO A CIERTAS CIRCUNSANCIAS QUE LO NECESITARAN. PUNTOS FUERTES: 1.SOLO ES PESADO SI EL PERSONAJE SE MUEVE. 2.MOVIMIENTO EN 8 DIRECCIONES, SI EL MOVIMIENTO SE DISPARARA POR UNA INTERRUPCIN NO SERA POSIBLE. 3.EL MOVIMIENTO ES SUAVE Y EL JUGADOR SE MUEVE AL RITMO DEL JUEGO. PUNTOS DBILES: 1. ES COMPLEJO.

Figura 6.2 Bucle de movimiento

6.2.7 Algoritmos de colisiones basados en hojas de estilo y optimizarlos


Justamente aqu comenz el juego, echndole un vistazo a las propiedades de estilo que puede tener un objeto encontramos lo siguiente.

- 106 -

AJAX, fundamentos y aplicaciones

Objeto padre. top

Objeto hijo. left height width

Figura 6.3 Propiedades de estilo de las tablas El hijo tiene 4 propiedades muy interesantes, left, top, width, height: left: Desplazamiento absoluto por la izquierda respecto al padre(que ser la pantalla). top: Desplazamiento absoluto por arriba respecto al padre(que ser la pantalla). width: Anchura absoluta del objeto. height; Altura absoluta del objeto. Podramos decir que las 4 esquinas son, (left,top), (left+width,top), (left,top+height) y (left+width,top+height), si tenemos esto tenemos los cuatro lados y si algn objeto rectangular ha metido una de sus esquinas dentro de otro objeto rectangular (ya sea el primer objeto o el segundo como veremos), ha colisionado con l, no hay truco posible ni falla en ello. Esta idea es simple, pero nos va a obligar a que todos los objetos que tiene nuestro juego estn contenidos en rectngulos, con el alto y ancho que nos apetezca, por supuesto lo que hagamos intentaremos que quede lo mas apretado posible, de esta manera el aspecto quedar muy natural y no se notar.

Figura 6.4 Frames de animacin del juego Esto se lleva haciendo mucho tiempo en los Game Makers 2D, de esta manera se ahorra mucho trabajo ya que la gente puede compartir sus recursos. En estos entornos, los scripts suelen ser tambin interpretados y los grficos contenidos en archivos de poco peso como es el caso de javascript y los entornos Web. Nosotros tambin podremos aprovechar algunos recursos, tendremos que adaptarlos a lo que estamos haciendo pero ya no tendremos que pintar nada, tenemos muchos escenarios y personajes de libre distribucin, hechos por fans y que podremos usar sin infringir ningn copyright. En el juego de ejemplo se han dividido las colisiones en 3 tipos diferentes: El jugador con la pantalla: sta no se puede atravesar y se comprueba cada vez que el jugador se mueve 1 pxel. El jugador contra los muros: Estos no se pueden atravesar y se comprueba cada vez que el jugador se mueve 1 pxel. El jugador contra los objetos: Estos se pueden atravesar un poco ya que disparan una accin, se comprobarn 1 vez por iteracin del bucle principal, en una iteracin el jugador se puede mover como mximo 3 pxeles que es el paso por defecto.

- 107 -

AJAX, fundamentos y aplicaciones

La pantalla podran ser 4 muros la verdad, pero es mas rpido tratarla como tal, es una colisin de dentro de un objeto la pantalla hacia fuera, ya que intentamos salirnos de ella.

De dentro hacia fuera es imposible colisionar con otro lado que no sea el mismo, si son 2 rectangulos

Figura 6.5 Colisin interna de rectngulos

Posibles Colisiones: Lado de arriba del jugador con el lado de arriba de la pantalla. Lado izquierdo del jugador con el lado izquierdo de la pantalla. Lado derecho del jugador con el lado derecho de la pantalla. Lado abajo del jugador con el lado de abajo de la pantalla. No tiene sentido comprobar otras, porque no ocurrirn, como el jugador nunca va a salir de la pantalla no puede colisionar su lado derecho con el lado izquierdo de sta, etc. Los muros, son objetos rectangulares que podemos pintar cuando estemos haciendo el juego pero que luego dejaremos invisibles y colocaremos un dibujo de fondo con los arbolitos, la mazmorra o lo que sea de lo que vaya el juego, en nuestro juego tenemos bosque, cueva y un castillo.

Siempre colisionaremos con el lado contrario si son colisiones externas entre 2 rectngulos.

Figura 6.6 Colisin externa de rectngulos Posibles colisiones: Lado de arriba del jugador con el lado de abajo del muro. Lado de abajo del jugador con el lado de arriba del muro. Lado izquierdo del jugador con el lado derecho el muro. Lado derecho del jugador con el lado izquierdo del muro. Con los objetos es exactamente igual, solo que como es un desperdicio de recursos comprobar unas colisiones que no generan ninguna bandera de muro, ya que normalmente los objetos nada ms tocarlos se cogen, el que los atravesemos un par de pxeles no importa, con esto dicho solo comprobaremos sus

- 108 -

AJAX, fundamentos y aplicaciones

colisiones 1 vez por iteracin del bucle principal, pero solo comprobaremos si colisionan, no como los muros que adems de comprobarlo tenemos que saber qu lado colision para activar la bandera de muro correspondiente; esto con los objetos da igual y en caso de que el objeto no se deba atravesar, por ejemplo un cofre o una puerta, el objeto contendr un muro, pero una moneda que se coge o un corazn no necesita esto, debemos recordar que los objetos y los muros son cosas diferentes, pero que un objeto puede contener un muro. Preparando los objetos para el algoritmo Llegado este punto debemos recordar que tenemos objetos mviles e inmviles, destruibles e inmortales, tenemos que decidir la estructura que tendrn los objetos para poder acceder a los datos con nuestro algoritmo de colisiones. Clasificacin 1: Mviles: Jugador, enemigos. Inmviles: Pantalla, muros, objetos (monedas, cofres, puertas, etc...). Clasificacin 2: Destruibles: enemigos y objetos (monedas, cofres, puertas, etc...). Inmortales: jugador, muros y pantalla. En el juego de ejemplo se decidi que como las colisiones dependen de si el objeto era la pantalla, muro u otro objeto habra 2 arrays y 2 objetos globales que existen siempre, de una pantalla a otra pueden variar los muros pero no el jugador y la pantalla. Arrays Globales de objetos que cambian en cada pantalla: ArrayMuros: Los objetos inmviles e Inmortales. (Solo muros). ArrayObjetos: Los objetos destruibles. (Enemigos, monedas, puertas, etc.) Objetos que existen siempre: Jugador: Como nunca cambia tiene un puntero que apunta a su objeto DOM (optimizacin), esta optimizacin ayuda muchsimo a la hora de actualizar sus datos porque es un objeto mvil, los enemigos no lo tienen ya que si cambia el rbol del DOM debido a que insertamos cdigo y hay que coger otra vez los punteros seria un poco ms complejo, no mucho pero con las optimizaciones que hacemos ya funciona correctamente, se puede optimizar ms pero con un coste de tiempo que en este caso no es aceptable ya que apenas mejora el rendimiento. Pantalla: Como nunca cambia hay 4 variables, una por cada lado, que contienen su posicin aunque se podran poner como constantes. Ya sabemos que tenemos estos 2 arrays y 2 objetos, qu estructura tienen, depende de sus necesidades y acciones que pueden realizar pero para calcular las colisiones hay 4 propiedades que van a tener siempre y que son las 4 para calcular sus esquinas o lados (LA MEJOR OPTIMIZACIN), queda prohibido buscar DOM para mirar sus propiedades, solo para realizar cambios. En el caso de los muros que nunca cambian de posicin y del resto de objetos inmviles, como nunca tenemos que buscar en el DOM dividimos entre 6 y 8 el tiempo necesario para realizar las operaciones; es decir, si antes conseguamos dar 10 vueltas al bucle principal en 1 segundo, ahora conseguimos dar 60, con el consiguiente aumento de rendimiento y por fin es posible realizar nuestro juego en javascript y que funcione en un ordenador medio. En el caso del objeto jugador miramos sus propiedades y solo accedemos al DOM con un puntero para hacer cambios, pero nunca para leer, ya que cuando hacemos un cambio en el DOM, tambin lo hacemos en sus propiedades. En el caso de los enemigos miramos sus propiedades y slo accedemos al DOM para hacer cambios, buscando el enemigo por nombre (la operacin ms costosa que utilizamos). El algoritmo: Slo se calculan las colisiones del jugador con el resto de objetos, los otros jugadores hacen lo mismo, y no hace falta calcular las colisiones de los enemigos con los muros ya que su movimiento se volvera mas

- 109 -

AJAX, fundamentos y aplicaciones

complejo y con que corran hacia el jugador es suficiente en nuestro juego ya que el que no tengan otros clculos de colisiones en la inmensa mayora de las ocasiones ni se notar (si el jugador no atraviesa muros y los enemigos siguen al jugador, los enemigos no atravesarn muros tampoco en la mayora de ocasiones). Tenemos 3 algoritmos y 2 manejadores de algoritmos que los llaman: Un manejador que se encarga de la pantalla y los muros: 1. Accede a la funcin de colisiones para la pantalla. 2. Recorre el array de muros y los mete uno por uno en la funcin de colisiones para los muros junto con el jugador. Un manejador que se encarga de los objetos creables y destruibles: 1. Recorre el array de objetos y los mete uno por uno en la funcin de colisiones para los objetos con el jugador (la segunda funcin ms difcil de leer del juego). Todo lo anterior se encuentra en el archivo calculosColisiones.js.

6.2.8

Propiedades que deben cumplir los grficos para el juego

Sobre los grficos de los objetos Todos los elementos grficos del juego con los que se detectan colisiones deben tener un tamao estable, es decir, desde que se crean hasta que se destruyen el rectngulo (tabla HTML) que los encierra debe tener el mismo tamao, todo esto lo hacemos con las hojas de estilo, incluso si el jugador o un enemigo utiliza imgenes un par de pxeles ms grande en alguna ocasin para algn movimiento, la tabla no cambia de tamao y corta las imgenes si es necesario; si esto no ocurriera as, si dejramos que el tamao fuera variable, los clculos de colisiones que hay hechos podran fallar y habra algn truco mediante el cual el jugador podra atravesar los muros, se ha comprobado y ocurre as. Este problema se podra solucionar?, despus de cambiar una imagen de tamao, habra que ver si ha atravesado un muro y moverla en sentido opuesto hasta que no lo atravesara, solucionado esto se devolvera el control al jugador, esto se tarda en hacer un par de milisegundos pero es engorroso, la solucin ms sencilla y prctica es dejar las imgenes de tamao fijo, igual que los rpg makers, con la salvedad de que el tamao de nuestros objetos es fijo pero pueden ser todo lo grandes o pequeos que queramos mientras que en los rpg makers el tamao es fijo y su ancho y altura es igual para todos los personajes mviles, aunque esto se solucion en la ultima versin de uno de estos programas, ahora te deja elegir entre al menos dos tamaos (risas), nosotros tenemos muchas mas opciones en este sentido. Para el formato de las imgenes la nica opcin viable eran las imgenes gif, las nicas que nos permitan crear animaciones y dejar un color transparente, adems de tener un tamao pequeo. Sobre los fondos Para hacer los fondos del juego se han seguido los siguientes pasos: 1. Los fondos estn hechos con rpg maker, despus a stos se le sac un screenshot, las imgenes originales eran de 320x240. 2. Se estiraron con un programa de retoque fotogrfico a 640x480 y se index la paleta para que tuviera 256 colores pero fueran los colores que usaba la imagen. 3. Si el fondo necesitaba de una animacin como es el fondo del lago con la cascada, se sacaron los frames necesarios para crear la animacin. 4. Una vez preparadas correctamente las imgenes se us un programa para crear los gif a partir de estas imgenes, ya sean animados o sin animar. Como puedes leer, para hacer el juego se ha aprovechado todo lo que sea ha podido el trabajo hecho por otra gente, si quisiramos generar los fondos por tiles y que stas tuvieran cada una sus propiedades

- 110 -

AJAX, fundamentos y aplicaciones

cargaramos mucho el navegador, sin contar el trabajo de programacin que sera, haciendo los fondos como imgenes gif y poniendo muros invisibles hemos ahorrado muchsimo trabajo.

6.2.9

Precarga de imgenes

Cuando llegamos a una pgina Web nuestro navegador empieza a cargar los elementos que est empleando, en un juego o entorno muy cambiante estara pidiendo informacin continuamente al servidor, es ms, muchas veces antes de que le llegara esa informacin sera ya atrasada y estara pidiendo nueva, con lo cual nunca terminara de cargar nada y no llegara a mostrarlo, el resultado es que el entorno Web se visualizara mal. Lo anterior en un juego es todava mas crtico, no deberamos de pedir nada grfico al servidor ya que estos archivos pesan mucho y no van a llegar a tiempo casi nunca, lo ideal es que antes de comenzar el juego se cargaran en memoria todos los archivos de grficos que vamos a emplear. Para hacer esto hay una serie de rdenes en Javascript que meteremos en la cabecera del documento, mientras que no lleguen los grficos no debera seguir cargando, pero en cualquier caso mientras que no termine la pgina entera de cargar no dejaremos que el jugador comience a jugar. Si leemos el archivo precargaImagenes.js que es muy sencillo podemos leer lneas como las siguientes: var fondos = new Array(); fondos[0]=new Image(); fondos[0].src ="escenarios/A4.gif"; fondos[1]=new Image(); fondos[1].src ="escenarios/B3.gif"; En el juego de ejemplo para un mayor orden se ha introducido las imgenes en arrays con un nombre que indique a que pertenecen, en cualquier caso, no vamos a coger las imgenes de los arrays. Esto es solo para obligar a la pgina Web a cargarlas por primera vez, ahora que las imgenes estn en cach, con volver a pedirlas al servidor nuestro navegador por arte de magia sabr que esas imgenes las tiene y nos las devolver instantneamente, al menos as es en IE 7 y Mozilla Firefox 1.5 y 2.0 .

6.2.10 Precarga de sonido


Este apartado dio muchos quebraderos de cabeza, iniciar la reproduccin de un sonido que no se tuviera ya cargado deja al navegador bloqueado al menos un par de segundos, da igual el tamao del archivo, lo que le cuesta ms al navegador es cargar el reproductor e iniciarlo. Otro pequeo gran problema es que Mozilla Firefox solo deja reproducir sonido si esta incrustado con la etiqueta embed y an as necesita una extensin que se instala con el programa Quick Time para poder reproducir, en cambio Internet Explorer no necesita extensiones ninguna y deja reproducir sonido con un par de etiquetas mas. Sabiendo esto, tenemos que mirar directamente las posibilidades que tenemos con la etiqueta embed, adems de que Mozilla Firefox va a necesitar de la extensin que le da Quick Time. La solucin que se encontr al problema fue la siguiente: <embed id="musicaTitulo" name="musicaTitulo" src="musica/titulo.mid" width="0" height="0" autostart="false" loop="true" enablejavascript="true"> Las msicas deben estar en el cuerpo del documento, si no, no funcionar lo que pretendemos hacer correctamente, les pondremos tanto la propiedad id como name para ilustrar dos formas de reproducirlo, diremos que el ancho y alto del reproductor son 0 pxeles para que no se muestre, nosotros elegiremos cundo reproducir la msica, no el usuario, autostart ser falso para que cuando se carguen las msicas al cargar la pgina web no comience ninguna, como ya hemos dicho controlaremos la reproduccin mediante Javascript, por ltimo las msicas se repetirn, es decir, loop=true mientras que los efectos de sonido no, loop=false. Dicho lo anterior, todas las msicas y efectos de sonido al igual que los grficos se cargan cuando se inicie la pgina, en este caso se han elegido midis de pocos ks y como el juego intenta ser un clon del Zelda se han cogido msicas hechas por fans de varios juegos de la saga.

- 111 -

AJAX, fundamentos y aplicaciones

Para reproducir la msica cuando queramos, si miramos el archivo sonido.js, lo nico que hacemos es coger la etiqueta ya sea por id o name dependiendo si es msica o sonido (podramos haberlo hecho igual) y tocarlo y pararlo con las propiedades play y stop, se ha dejado ilustradas las dos maneras porque el resultado es idntico y slo cambia una lnea de cdigo.

6.2.11 Cuadros de informacin: vida, objetos, mapa y consola


Todos los cuadros de informacin, incluso la pantalla, son tablas. Se ha utilizado hojas de estilo para dividirlos y se le han dado clases a sus celdas. Cuando cogemos los objetos lo nico que ocurre es que le cambiamos la clase a la celda y las hojas de estilo hacen el resto, la vida y el mapa funcionan exactamente igual; por supuesto al mismo tiempo que realizamos los cambios grficos, se realizan tambin en el objeto jugador, asignndole los objetos y se enva la informacin al servidor para mantener la consistencia. Objetos 1. Tenemos un fondo que hemos dividido de la misma forma que esta hecha la tabla.

Figura 6.7 Cuadro de objetos

2. Tenemos una tabla, con clases en sus celdas en el archivo mochila.js. "<table id=\"mochilaReal\" class=\"mochilaReal\" style=\"border: none; position: absolute; left:0px; top:0px; \">"+ "<tr class=\"mochilaRealFila\">"+ "<td id=\"objeto01\" class=\"cajonMochilaInactivo\"></td>" + "<td id=\"objeto02\" class=\"cajonMochilaInactivo\"></td>" + 3. Tenemos en la hoja de estilo, las clases que asignan los dibujitos de fondo de las celdas, si miras el archivo interface.css a la seccin de Mochila, vers que se han asignado a cada clase un fondo y unas propiedades. Vida y mapa

Figura 6.8 Cuadro de vida y mapa

- 112 -

AJAX, fundamentos y aplicaciones

Funcionan exactamente igual, lo nico que hacemos es encender y apagar las casillas haciendo uso de las clases de las hojas de estilo. Para cambiarle la clase a un objeto de forma sencilla debemos de asignarle un identificador, por eso todas las celdas de toda la interfaz tienen uno. Donde se ve ms fcilmente es en el mapa, si echamos un vistazo al archivo mapa.js, veremos que siempre apagamos una celda y encendemos otra haciendo uso de las clases, haciendo uso de la funcin siguiente. function cambiarCajonActivo(cajonActualNombre,cajonNuevoNombre) { var cajonActual = document.getElementById(cajonActualNombre); var cajonNuevo = document.getElementById(cajonNuevoNombre); if(cajonActual != null) { cajonActual.className = "cajonMapaEspera"; } cajonNuevo.className = "cajonMapaActivo"; cajonActualID = cajonNuevoNombre; } Hay 3 tipos de clases para los cajones en el mapa, Inactivo (no visitado), Espera (ha sido visitado pero no estamos actualmente), Activo (donde estamos). Si al principio todo el mapa esta inactivo, solo con esta funcin se harn todos los cambios de forma natural, siempre que cambiamos de pantalla dejamos el cajn actual en espera si es que existe (la primera vez que entramos al juego no ha habido un cajn anterior) y ponemos el nuevo como activo. El cajn actual se guarda en una variable global y esta funcin como se llama al cambiar de pantalla est en los scripts que pintan las pantallas. En la carpeta escenarios. El cuadro de la vida funciona exactamente igual, o no hay un corazn, o lo hay, o lo hay pero est negro porque no tenemos el mximo de vida. Tanto la tabla como las funciones que suman y restan vida se encuentran en estadoJugador.js. Consola

Figura 6.9 Consola de informacin

sta indica con un mensaje cuando coges un objeto, no es ms que una tabla vaca con un dibujo de fondo que est puesto haciendo uso de la hoja de estilo, para escribir y borrar de la tabla hay dos funciones que se utilizan en el archivo accionesObjetosCogibles.js y son mas que sencillas: escriben en el innerHTML de la tabla y lo borran entero dado una cantidad de tiempo, para que no se llene la tabla, esto se podra haber mejorado y hacer una especie de log que tenga desplazamiento, pero para el uso que tiene actualmente es suficiente.

6.2.12 Sistema de batalla y golpes


Para que un juego de accin resulte adictivo, ste es tal vez el punto ms importante, incluso ms que los grficos, pero ms difcil de programar, teniendo en mente que nuestros clculos de colisiones son con rectngulos y que intentamos simular un Zelda de Super Nintendo tenemos que pensar en las siguientes ideas: En el juego original de consola, cuando sacabas la espada, est te haca a la vez tambin de escudo ante otras armas blancas ya que chocaban y quedaba gracioso, adems te movas ms lento porque al ponerte en posicin de combate no puedes ir corriendo, pero te podas mover dejando el punto de vista fijo, es decir se supone que si sacas la espada es porque hay un enemigo y no quieres darle la espada, as que si estas mirando a la izquierda mientras tengas el botn de ataque pulsado te quedas mirando hacia la izquierda, por ltimo cuando sacas el arma haba una animacin, para nuestra suerte todo es posible, lo

- 113 -

AJAX, fundamentos y aplicaciones

nico eliminado es la animacin de sacar la espada ya que no tenemos unos grficos originales disponibles que se adecuen al personaje que se ha elegido. Movimiento Si aprietas el botn de ataque (El botn A por defecto), en el archivo controladoresEventos.js, el controlador de evento de teclado de pulsar la tecla A se pone la bandera teclaAtaquePulsada = true y jugador.atacando = true;, realmente es la misma bandera, se termin utilizando la que pertenece al objeto jugador, se cambia la animacin del personaje y se fija el punto de vista con la bandera puntoVistaBloqueado = true, como ves hasta aqu ningn problema, por ltimo para que el personaje valla mas lento se cambia la variable numeroMovimientosPaso de 3 a 1, cuando despulsas la tecla en el manejador de despulsar la tecla del mismo archivo se deshacen todos estos cambios, como ves el movimiento ha sido relativamente sencillo. Las banderas puntoVistaBloqueado y numeroMovimientosPaso se utilizan en el movimiento del jugador en el archivo movimientoJugador.js mientras que la bandera jugador.atacando se utiliza en el archivo calculosColisiones.js. Colisiones entre enemigos stas estn calculadas en el archivo calculosColisiones.js, pero hay una serie de puntos a tener en cuenda, tanto el jugador como el enemigo son objetos en la pantalla, con 3 propiedades importantes que definen como termina la situacin. Propiedad 1: Punto de vista, para atacar satisfactoriamente el jugador tiene que golpear al enemigo mirndole en cambio al enemigo esto le da igual si tomas contacto con el te golpea. Propiedad 2: bandera de ataque, el jugador no slo tiene que dar contra el enemigo de frente sino con la espada fuera, el cambio el enemigo siempre esta en ataque. Propiedad 3: Tienen que estar alineados, de manera que la espada toque al enemigo, vemoslo con el siguiente ejemplo:
Ataque del jugador satisfactorio.

Punto de vista: El jugador lleva las de ganar. Bandera de ataque: El jugador puede golpear. Alineacin: correcta, la cabeza del jugador no sobrepasa la del enemigo.

Ataque del jugador no satisfactorio.

Punto de vista: El jugador lleva las de ganar. Bandera de ataque: El jugador puede golpear. Alineacin: incorrecta, el final del cuerpo del jugador donde mira sobrepasa al del enemigo.

Figura 6.10 Cuadro de objetos Esta ltima propiedad es tal vez la mas compleja, por ltimo cuando dos soldados (objeto de tipo jugador o enemigo con espada) se enfrentan, si se golpean los 2 mirndose a la cara el ataque les rebota a los 2.

- 114 -

AJAX, fundamentos y aplicaciones

Todo lo comentado tanto la colisin del jugador con un enemigo como el jugador con otro jugador estn en el archivo calculosColisiones.js, en los clculos de objeto tocables, puede parecer algo complejo pero son estas ideas plasmadas en cdigo, no hay ms. Golpe al jugador Hay para el personaje jugador una animacin de golpe para cada lado pero se ha copiado la misma para ahorrar tiempo pintando, puedes mirarlo en el directorio personajes y ver las del jugador principal, stas se reproducen solo para nuestro personaje, no para los jugadores enemigos. Si miramos la funcin de clculo de colisiones de objetos tocables dentro del archivo calculosColisiones.js, se llama a la funcin iniciarGolpe() dentro del archivo golpeJugador.js. Esta funcin depende de un par de variables globales que se encuentran en el mismo archivo, tiempoGolpe y pixelesGolpe, de manera que se pueda modificar si es necesario dependiendo del enemigo, en el juego no ha sido necesario, durante un golpe se activa la bandera jugadorGolpeado y se bloquea el punto de vista con su bandera puntoVistaBloqueado para que el jugador se quede mirando donde estaba, cada vez que se mueve un pxel (se hace con las funciones hechas como interfaz, no directamente), se comprueban los muros para no atravesarlos y por ltimo para simplificar (y hacer un guio al Zelda 2 de NES) no importa por qu lado nos golpeen, el jugador saldr disparado en la direccin contraria de donde est mirando, divertido verdad, es muy frustrante para quien juega, lo llegar a odiar. Todo esto se hace con 2 funciones una que inicia el golpe y otra que se llama luego recursivamente hasta finalizarlo, iniciarGolpe() y golpeJugador().

6.3 Parte online del juego


Llegado a este punto te habrs dado cuenta de que la verdadera dificultad de crear esta pequea demo radica en parte en las ideas que hay que tener para hacerlo y en tener conocimiento suficiente del entorno Web que nos manejamos, CSS+Javascript+DOM, ya que en verdad el uso de un entorno Web facilita mucho el trabajo, ya que no hay que hacer ningn proceso complejo para pintar en pantalla, ni tampoco para el sonido, ni los controles ya que podemos crear manejadores fcilmente, etc. Ahora llegado el momento de hacerlo online vamos a utilizar una pequea base de datos SQL y realizaremos operaciones con ella enviado parmetros a una pgina JSP que nos va ha devolver las respuestas de la base de datos. Tenemos que tener muy claro que cualquier cosa que se haga en el entorno cliente, es decir, el navegador, est expuesto a ataques, para hacer el juego mas ligero no vamos a hacer una seguridad de hierro, pero al menos nos vamos a molestar en cifrar la conexin, que sea el servidor quien autorice al jugador tener objetos y mover los enemigos tambin con el servidor, pero claro, es el jugador quien notifica que un enemigo le ha golpeado, si te preguntas por qu no hacemos esto en el servidor es simple: hara falta un mejor tiempo de respuesta y este es el gran problema que tiene el juego, por ms que queramos estamos trabajando sobre el protocolo http, las conexiones se abren, se enva lo que se tiene que enviar y se cierran, no hay ningn canal abierto que mantenga la conexin y solo tenemos un puerto, el gran reto hoy en da para este tipo de entornos interactivos es precisamente conseguir una interactividad inmediata cliente/servidor sobre http.

6.3.1

Disear la base de datos dependiendo de las necesidades del juego

Esta parte ser la culpable en parte del rendimiento online, cuanto menos bsquedas y mas rpidas sean, mejor ser el rendimiento. Cada objeto en la parte servidor tiene que tener un objeto en la parte cliente y si el objeto se cogi el servidor nos dir que esta inactivo y este debe estar vaci en el cliente, para que las bsquedas de estos fueran directas no importa el tipo de operaciones que se quiera realizar, se hizo que ya que precisamente los objetos que se crean y destruyen tienen un array en la parte cliente y dentro de l tienen una posicin, el servidor debera de adecuarse a esto y debera de tener estos mismos objetos en tablas y la idea fue que sera una tabla por pantalla y que esta tendra los objetos ordenados por un ID numrico nico que sera su posicin en el array de la parte cliente, de esta forma al tener la misma posicin(mas o menos 1 ya que

- 115 -

AJAX, fundamentos y aplicaciones

los arrays en Javascript empiezan en 0 y la tabla SQL en 1) las bsquedas serian lo mas rpido que pueden ser.
Forma de localizar los objetos: Cliente Variable global: pantallaActual=a4 Array Objetos: indice=1 Servidor JSP Servidor SQL Jugadores a4 b4 ndice+1 tablas ID 1 2 Nombre ... ... Etc...

Figura 6.11 Diseo de la base de datos

Ya hemos visto una parte grande del funcionamiento del juego, para que tengamos algo de idea de que manera los diferentes bloques interactan entre ellos aqu tenemos un esquema, en l se han excluido algunas pequeas cosas para facilitar su comprensin:
PARTE OFFLINE LEYENDA VARIABLES GLOBALES BUCLES PARTE ONLINE

BUCLE PRINCIPAL BASE DATOS BASE DATOS DE JUGADORES Y OBJETOS EN LAS PANTALLAS

VARIABLES

MOVIMIENTO DEL JUGADOR DEPENDIENTE INTERRUPCIONES

OTRAS FUNCIONES

BUCLE PETICIN INFORMACIN SERVIDOR (ENVIA Y RECIBE INFORMACIN CADA X TIEMPO)

OBJETO JUGADOR

ARRAY OBJETOS TOCABLES MARCADOS: 1- EXISTIR 2-CREARSE 3-DESTRUIRSE NUCLEO DE CLCULO COLISIONES

BUCLE DE ACTUALIZAR POSICIN DE LOS ENEMIGOS (ENVIA INFORMACIN BAJO CIERTAS CONDICIONES)

ARRAY MUROS

ENVIA INFORMACIN SERVIDOR DE OBJETOS TOCADOS

INTERFACE CREAR O ELIMINAR UN OBJETO

DISPARA ACCIN OBJETOS TOCADOS BUCLE DE MOVIMIENTO DE LOS ENEMIGOS

CONSTRUCTORES DE OBJETOS

Figura 6.12 Esquema general de interaccin entre los diferentes componentes de la aplicacin

6.3.2

La I.A. de los enemigos, los debe mover el servidor para evitar trampas

Si estamos jugando a un juego online multijugador necesitamos cierta consistencia, tanto con los objetos como con los enemigos, es decir si yo golpeo un enemigo, lo he golpeado yo, si yo he cogido un objeto, lo he cogido yo, no otro jugador que estaba a mi lado y lo ha hecho casi al mismo tiempo que yo, adems debemos ver las cosas igual. La I.A de los enemigos es bastante simple, si el jugador est cerca de ellos, con un radio de 250 pxeles, el enemigo se lanza hacia el jugador. El servidor le dice al enemigo la nueva posicin del jugador una vez que ste ha llegado al destino anterior ya que si el enemigo no se para un momento nunca (si no hay latencia en la decisin de un nuevo movimiento) el jugador no puede librarse de l de ninguna manera y

- 116 -

AJAX, fundamentos y aplicaciones

el juego tendra poca jugabilidad. No hay otro tipo de I.A en nuestro juego debido a que solo hay soldados y este tipo de I.A. se adecua muy bien. Como estamos utilizando AJAX para la conexin con el servidor la nueva posicin la pide el cliente cada vez que el enemigo ha llegado a su posicin anterior, esto se hace dentro del archivo bucleMovimientoEnemigos.js en la segunda funcin, refrescoPuntoMovimientoEnemigos(), que sigue el siguiente diagrama:
BUCLE ACTUALIZAR POSICIN DEL ENEMIGO

NO SI JUGANDO Y MOVIMIENTO ENEMIGOS PERMITIDO SI i=0

NO i < NUMERO_OBJETOS

SI

SI ARRAY_OBJETOS[i].TIPO == ENEMIGO Y !ACTUALIZANDO_ENEMIGO

NO

SI

NO EST EN SU POSICIN FINAL

SI

ENVIAR PETICIN AL SERVIDOR PARA QUE LO MUEVA

i++

ESPERAR "X" SEGUNDOS

COSAS QUE FALTA AADIR AL DIAGRAMA: 1.LOS JUGADORES TAMBIEN SE ACTUALIZAN, SE PONEN MIRANDO A LA POSICIN QUE DEBEN YA QUE AL MOVERLOS SE PIERDE. COSAS MALAS: 1.NO SE ACTUALIZA MAS DE UN ENEMIGO A LA VEZ PARA NO SOBRECARGAR EL CLIENTE/SERVIDOR CON PETICIONES, POR LO QUE PUEDE QUE SI HAY MUCHOS ENEMIGOS A LOS LTIMOS NO LES LLEGUE NUNCA TURNO. COSAS BUENAS: 1.LO ANTERIOR SE PUEDE ARREGLAR SIN PERDER RENDIMIENTO METIENDO ESTAS ACCIONES EN LAS DE REFRESCO GENERAL ONLINE, LO MALO ES QUE COMPLICARA EL MODELO AUN MAS, DE ESTA MANERA ES MAS FCIL HACER CAMBIOS.

Figura 6.13 Esquema del bucle de actualizar la posicin de los enemigos

- 117 -

AJAX, fundamentos y aplicaciones

Para que el movimiento entre su posicin actual y la nueva sea suave hay otra funcin que mueve los enemigos por el camino ms corto, dentro del archivo bucleMovimientoEnemigos.js, la funcin MovimientoEnemigos(), su esquema es el siguiente:
BUCLE MOVIMIENTO ENEMIGOS

NO SI JUGANDO Y MOVIMIENTO ENEMIGOS PERMITIDO SI i=0

NO i < NUMERO_OBJETOS

SI

SI ARRAY_OBJETOS[i].TIPO == ENEMIGO ARRAY_OBJETOS[i].TIPO == OTROJUGADOR

NO

SI

SI EST EN SU POSICIN FINAL

NO

MOVER POR EL CAMINO MAS CORTO

i++

ESPERAR "X" SEGUNDOS

Figura 6.14 Esquema del bucle de movimiento de los enemigos

- 118 -

AJAX, fundamentos y aplicaciones

6.3.3

Los objetos deben ser asignados por el servidor para evitar trampas

Como en otros tantos juegos online en los que el jugador puede coger algo del suelo, que ocurre si dos jugador cogen al mismo tiempo un objeto, pues que gana la primera peticin que llega al servidor, en otro caso podra haber truco y eso no es aceptable. Por ello los objetos tienen una marca, que dice si existen y entonces el navegador Web los muestra o si se han cogido y hay que esperar a que reaparezcan (si es que reaparecen). En este juego todos los objetos reaparecen, es decir todos los objetos del array de objetos creables/destruibles, que es el punto de conexin en el diagrama general entre la parte offline y online del juego. Como ya se habl en la parte de construccin de la base de datos, los objetos se guardan en el mismo sitio para agilizar las bsquedas aparte de que gracias a ello tambin se enva muy poca informacin. Peticiones Sncronas En principio por decisiones de diseo hay un mximo de 20 objetos por pantalla, la razn principal es que hay que enviar en cada peticin AJAX unas 15 lneas de datos XML por objeto desde el servidor, sin contar que luego el navegador Web del cliente tiene que recorrer el documento XML, extraer la informacin y refrescar el estado de los objetos en pantalla, se han hecho pruebas con un Pentium M a 1.6GHz y 512Mb RAM a 400MHz y las pruebas han sido satisfactorias con las latencias 1300, 700 y 350 milisegundos, no se ha intentado bajar ms la latencia ya que enviando la informacin 3 veces por segundo en principio sera suficiente si llegara suficientemente rpido, habra que mejorar el procesamiento del documento XML en la parte cliente para agilizar un poco mas el recorrido evitando utilizar la funcin getElementsByTagName que es considerada lenta, como cualquier funcin de bsqueda, durante todo el desarrollo del juego se ha intentado no emplearlas en puntos crticos y este es un punto donde no deberan estar, todo esto que est aqu redactado es bucle online que est en el archivo bucle online.ddd, un esquema de su funcionamiento es el siguiente, representa los sucesos que ocurren en la funcin bucleOnline(),refrescoServidor(), enviarMiEstadoYpedirEstadoObjetos() y actualizarEstadoObjetos(datos):

- 119 -

AJAX, fundamentos y aplicaciones

BUCLE DE PETICIN DE INFORMACIN AL SERVIDOR NOTA: EL SERVIDOR NO ES MAS QUE UN ARCHIVO JSP Y UNA B.D. SQL PEDIRLE AL SERVIDOR QUE ACTUALICE LA BASE DE DATOS. (PARA QUE REAPAREZCAN LOS OBJETOS SI PASO EL TIEMPO SUFICIENTE)

ENVIAR POSICIN ACTUAL DEL JUGADOR

NOTA: EL SERVIDOR ENVIA UN XML CON LA INFORMACIN FORMATEADA. RECIBIR ESTADO DE LOS OBJETOS

SI EL ESTADO ES IGUAL AL ACTUAL?

NO NOTA: CREAR Y DESTRUIR SE HACE DENTRO DEL NUCLEO DE COLISIONES. DEPENDIENDO DE LAS NECESIDADES DEL OBJETO: -MARCARLO PARA CREAR (HA REAPARECIDO). -MARCARLO PARA DESTRUIR (SE COGIO O MURIO). -ACTUALIZAR POSICIN DEL ENEMIGO.

ESPERAR "X" SEGUNDOS

NOTA: SE HAN QUITADO LAS BANDERAS PARA FACILITAR LA COMPRENSIN.

Figura 6.15 Bucle que actualiza la informacin del servidor y la del jugador en el servidor

Peticiones Asncronas Si no fuera suficiente por todo lo anterior, cada vez que coges un objeto, se abre una puerta o cofre que tambin son objetos o golpeas un enemigo, todos objetos del array de objetos creables/destruibles, se realiza una peticin asncrona que le enva el suceso al servidor para que actualice la base de datos SQL, de esta manera, instantneamente todo es consistente otra vez y se actualiza en las pantallas del resto de jugadores. Si hacemos 3 peticiones por segundo para el refresco general de los objetos no sera mas fcil incluir esto tambin en ello?, seguramente s pero complicara tambin la programacin de las funciones y habra que realizar todava mas operaciones en ellas, la peor consecuencia de esto es que el cdigo sera mas difcil de mantener y modificar.

- 120 -

AJAX, fundamentos y aplicaciones

Cundo se lanzan las peticiones asncronas?: Usando la funcin decirleServidorCogidoObjeto(indiceTablaObjetosSQL) que se encuentra en el archivo bucleOnline.js desde colisionesObjetosTocables() dentro del archivo calculosColisiones.js. Cundo se crean o destruyen los objetos?: Desde colisionesObjetosTocables() dentro del archivo calculosColisiones.js, debido a una peticin sncrona que lo marc o a que hemos cogido el objeto y hemos hecho una peticin asncrona. Cundo se marcan para crear o destruir los objetos?: Usando la funcin actualizarEstadoObjetos(datos) que se encuentra en el archivo bucleOnline.js, si el refresco es por una peticin sncrona. Otros Objetos Todo lo dicho anteriormente tambin es vlido para los otros jugadores y los enemigos, los otros jugadores son objetos especiales que se encuentran en el array entre la posicin 20 y xx, tambin se ha restringido esto para resolver un problema de consistencia, si el jugador cambiaba de una pantalla a otra como haba desaparecido de la que estabas no se borraba debido al esquema de funcionamiento planteado, ya que si el objeto no existe ya en la pantalla no nos llega la informacin que dice que lo borremos. Es posible arreglar esto sin que exista esta restriccin?, S que lo es, pero es ms complejo y ms lento. NOTA: La nueva funcin de actualizacin resuelve este problema, esta parte est obsoleta. 1 solucin: Crear un array de objetos nuevo con cada peticin XML ya que esos son los objetos que hay en la pantalla, y borrar todo lo dems, esta solucin es abominable y llevarla a la prctica por la carga que requerira no es muy recomendable. 2 solucin: Los objetos con que llegan con un ID mayor que 20 son jugadores, creamos un array con el nombre de estos ID (el de los jugadores no se puede repetir), recorremos nuestro array de objetos y comprobamos que cada objeto mayor que 20 tenga su nombre en este array que hemos creado. Es decir, realizar una bsqueda, esto es un poco lento.

6.3.4

El dao de un jugador a otro debe ser notificado por el que se ve golpeado

Est claro que un enemigo no est en ningn lado para decir si le han matado o no y tenemos que confiar en que el navegador Web que le dice al servidor que ha sido golpeado no esta mintiendo, con los jugadores esta decisin no es tan fcil. Si golpeas otro jugador quien le dice al servidor quien ha sido golpeado, tenemos 3 posibilidades: Lo dicen los dos para confirmar: Esta opcin tal vez sea la mejor PERO es muy complicado hacerlo ya que habra que guardar los datos en algn sitio por en medio ya que primero llega el dato de un jugador y luego el del otro. Lo dice el jugador que golpea: Esto no es nada justo ya que si el jugador tiene una mala conexin el jugador al que golpea estar mas quieto que movindose y no es justo, adems puede que ya ni siquiera est en la pantalla cuando le golpea. Lo dice el jugador que es golpeado: Si, es la nica opcin fcil que nos queda, adems, es el quien tiene su posicin ms actualizada y es justo que lo diga l y adems si mintiera en el peor de los casos sera inmortal, si miente dando los datos de los golpes a otros jugadores ira matando a todo el mundo, aunque ser inmortal se lo pone ms fcil, no los matar directamente, por supuesto todo lo anterior son suposiciones que ocurriran si se hackeara al juego. Bueno dicho lo anterior, todo esto se hace como no en la ya famosa funcin de clculo de colisiones de objetos tocables del archivo calculosColisiones.js.

6.3.5

El cambio de pantalla debe ser notificado y aceptado antes de realizarlo

El cambio de pantalla es una peticin asncrona, no forma parte del refresco general, se hace en el archivo transicionPantalla.js (solo tiene una funcin) que llama a la funcin cambiarPantallaOnline(pantallaNueva) que se encuentra en el archivo bucleOnline.js , una vez que se confirma el cambio de pantalla por parte del servidor se pinta la pantalla nueva, mientras el servidor confirma la peticin, se borran los objetos de la pantalla anterior (si se estuviera procesando una peticin

- 121 -

AJAX, fundamentos y aplicaciones

de refresco sncrona que entr durante el cambio, los objetos se borraran) y el bucleOnline() que hace el refresco sncrono de los objetos est parado por una bandera de forma que no se generan nuevas, aunque el bucle se haya parado puede que llegue la ltima peticin que se envi de la pantalla anterior, sta se puede rechazar de dos maneras: en la parte servidor se hace una comprobacin que hace que se pueda rechazar la peticin (si llega la peticin de cambio de pantalla antes que la de refresco aunque se haya enviado despus), aparte de esto durante el cambio de pantalla no se puede empezar a procesar ninguna peticin de refresco aunque llegue durante el cambio porque la bandera de refresco de pantalla lo impide. Es muy enrevesado leerlo en un bloque as que mejor hacemos un esquema:
PROBLEMAS ONLINE: CASO A: PETICIN QUE LLEGA TARDE AL SERVIDOR: EL SERVIDOR LA RECHAZA: -LO HACE COMPROBANDO LA PANTALLA ACTUAL DEL JUGADOR. CLIENTE

PANTALLA A

TRANSICIN

PANTALLA B

SERVIDOR CASO B: PETICIN QUE LLEGA TARDE AL CLIENTE: EL CLIENTE LA RECHAZA: -LO HACE LA BANDERA DE CAMBIO DE PANTALLA QUE NO DEJA QUE SE PROCESE. CLIENTE

PANTALLA A

TRANSICIN

PANTALLA B

SERVIDOR

PROBLEMAS OFFLINE: CASO C: LA PETICIN EMPEZ A PROCESARSE ANTES DEL CAMBIO Y SE TERMIN DURANTE EL CAMBIO: -LAS OPERACIONES DEL CAMBIO TARDAN MILSIMAS DE SEGUNDO Y AL TERMINAR BORRAN EL ARRAY DE OBJETOS Y LO REFRESCAN.

CASO D: LA PETICIN EMPEZ A PROCESARSE ANTES DEL CAMBIO Y SE TERMIN DESPUS DEL CAMBIO: -EL ARRAY HA SIDO BORRADO DURANTE EL CAMBIO, AUN AS PODRA OCURRIR ALGN ERROR, DESPUES DE MUCHOS TESTEOS NO SE ENCONTR NINGUNO, SIN CONTAR QUE ESTA POSIBILIDAD ES MUY REMOTA.

Figura 6.16 Problemas derivados de necesitar consistencia en los datos Creo que con esto ha quedado mucho mas claro, adems de estos hay un problema ms: Qu pasa si hacemos una peticin nmero01 y luego hacemos una nmero02 y nos llega primero la segunda?, pues que cuando llegue la primera sta se rechaza porque ha llegado una ms nueva, la razn es porque slo se atienden las mayores que la ltima peticin recibida, esto se hace en la funcin enviarMiEstadoYpedirEstadoObjetos() del archivo bucleOnline.js. Cosas buenas: Si llegan respuestas a destiempo estas se rechazan, y lo mejor, si se pierde una no pasa nada. Cosas Mejores: Se pueden minimizar la llegada de peticiones con informacin atrasada subiendo el nmero de la variable numeroSecuenciaLimite cada vez que cogemos un objeto (peticin asncrona), por un lado ahorramos procesar una peticin con informacin atrasada y por otro lado hay menos rebotes visuales, esto se hace en la funcin decirleServidorCogidoObjeto(indiceTablaObjetosSQL) del archivo bucleOnline.js.

- 122 -

AJAX, fundamentos y aplicaciones

6.3.6

Actualizar la posicin del jugador

La posicin del jugador est dentro del refresco de datos sncrono del que ya hemos hablado muchsimo y aunque esto ya se ha comentado en el apartado Los objetos deben ser asignados por el servidor para evitar trampas ahora lo remarcaremos hablando de los jugadores ya que con los objetos no es tan crtico el tiempo de respuesta: si un jugador coge un objeto otro ya no puede aunque le llegue el refresco tarde, en cambio si dos jugadores quieren pelearse, es imposible si no tienen un refresco decente los dos. Al comienzo los refrescos eran cada 2 segundos, ahora son cada 0.35 segundos, an as ste es el gran problema de que el juego se sostenga bajo el protocolo HTTP, ahora mismo el juego cuenta con la versin 2.0 del protocolo que mantiene la conexin sncrona con el servidor, el jugador solo enva su pantalla y posicin y el servidor devuelve solo, los objetos activos en pantalla y jugadores que estn en ella. Con lo anterior solucionado se ha conseguido mucha ms eficiencia y ahora se puede mantener a muchos ms jugadores jugando en el mismo servidor, en las pruebas actuales se permiten un mximo de 80 aunque se aumentar a 400 en las siguientes. La frmula que mide el tiempo de refresco es la siguiente:
Trefresco = RetrasoRed +TiempoCrearPeticinCliente+ TiempoProc.PeticinServidor+ TiempoAct.B.D.+ TiempoDevolverInf.Act.

Despus de diversas pruebas domsticas con un servidor ideal, es decir que no est sobrecargado con ms de 10 peticiones por segundo, (si estuvieran jugando 200 personas seran unas 500), podramos dejar la frmula como la siguiente.
Trefresco = RetrasoRed+ (200ms aprox)

En el diseo del juego esto es muy importante porque normalmente los juegos online se juegan a golpe de ratn, no con las teclas y siguen el siguiente protocolo. 1. Jugador dice donde quiere moverse al servidor haciendo clic en dicha posicin con el ratn. 2. El servidor guarda la nueva posicin. 3. El servidor enva a todos los jugadores cercanos la posicin a la que se va a mover el jugador que lo ha pedido. 4.Se reproduce la animacin del movimiento en todos los clientes a la vez. Los pasos 3 y 4 ocurren a la vez con lo que la animacin transcurre igual en las pantallas de todos los jugadores y no hay problema ya que el termino RetrasoRed se vuelve despreciable debido a este protocolo. El diseo de El poder de AJAX vuelve crtico este trmino, si el cliente y el servidor fueran la misma mquina, es decir, lo ms ideal, quedara.
Trefresco = 200ms aprox

Con lo cual se podra actualizar 5 veces por segundo, pero esto no es as con lo cual nos conformaremos con 2 o 3 veces, adems de tener en cuenta toda la problemtica de la prdida de alguna peticin o la posibilidad de que lleguen en mal orden.

6.3.7

Actualizar objetos al cogerlos (Asncronamente)

La idea es simple, las peticiones AJAX sncronas refrescan lo que se ve en la pantalla nicamente, las peticiones AJAX asncronas se utilizan para hacer algn cambio instantneo y son las que pueden sumar algo al inventario del jugador. En este ltimo caso el manejador tanto en la parte cliente como servidor tiene que ser lo mas pequeo posible ya que hasta que el servidor no te da la respuesta no se hacen los cambios, pero debemos adecuarnos a nuestro diseo, tenemos un tipo llamado objetosCogibles en las colisiones, pues un manejador para estos objetos, si hubiramos separado cada objeto en si mismo se podran haber hecho manejadores de accin mas ligeros todava a cambio de tener que escribir un manejador por objeto en vez de uno genrico.

- 123 -

AJAX, fundamentos y aplicaciones

Para mejorar esto, el subtipo de objeto dentro de los objetosCogibles es el mismo nombre que la funcin que dispara la accin de ese subtipo y como Javascript puede evaluar texto como cdigo evaluamos su nombre directamente y ya tenemos una forma sencilla de disparar las acciones de todos los objetos con una funcin, y es rpido. Todas las acciones de los objetos estn en los archivos accionesObjetosCogibles.js y accionesObjetosAccion.js, las primeros se resumen a reflejar en el objeto jugador y grficamente en la mochila o el status los cambios realizados al tocar el objeto y los segundos para disparar una accin no solo los tienes que tocar sino que tienes que cumplir alguna condicin, para las puertas tienes que tener su llave y mirarlas de frente y para los cofres tambin tienes que mirarlos de frente, de estas forma no basta con estar al lado de un objeto de estos tipos para usarlo ya que sera absurdo abrir un cofre o una puerta de espaldas, etc.

6.4 A fondo
Llegados a este punto y comprendido cmo funciona el juego vamos a prestar atencin especial a un par de archivos gordos por su tamao que no excesivamente complejos, aun as es mejor facilitar su lectura.

6.4.1

El archivo servidor.jsp

El archivo est dividido en tres secciones o pasos: Primer paso: creamos los objetos necesarios en todas las opciones. Segundo paso: qu quiere hacer nuestro usuario. Tercer paso: cerramos la comunicacin sql necesaria en todas las operaciones. Cualquier peticin del usuario pasa por estos 3 pasos. En el primero se crean las variables necesarias para hacer la comunicacin sql, esta comunicacin con la base de datos es necesaria con todas las operaciones, el motivo por que existe este archivo es precisamente para hacer de puente con la base de datos. En el segundo paso lo primero que se hace es recoger el parmetro de servicio enviado por el usuario, contiene la operacin que se debe realizar, la estructura del segundo paso es la siguiente. if(servicio.equals("pedirSesion")) { } else if(servicio.equals("refrescoServidor")) { } else if(servicio.equals("refrescoNormal")) { } else if(servicio.equals("cogerObjeto")) { } else if(servicio.equals("cambiarPantalla")) { } else if(servicio.equals("actualizarPosicionEnemigo")) { } else if(servicio.equals("restarVidaJugador")) { } else if(servicio.equals("restarVidaEnemigo")) { } else if(servicio.equals("cerrarSesion"))

- 124 -

AJAX, fundamentos y aplicaciones

{ } else if(servicio.equals("registro")) { } Dependiendo del servicio se harn las operaciones necesarias con la base de datos, son todas consultas y modificaciones muy sencillas, sin tener conocimientos de sql se pueden comprender. Como respuesta al usuario cada operacin genera un documento XML con la informacin necesaria para actualizar la pantalla y el interfaz, como ves est todo muy dividido, esto es bueno para encontrar los errores y no hacer un cambio que lo rompa todo. Por ltimo, en el tercer paso se cierran las variables y la conexin sql que se abrieron en el primer paso.

6.4.2

El archivo calculosColisiones.js

Contiene las siguientes funciones: Estos son los dos manejadores que acceden a las funciones que hacen los clculos: colisionesObjetosFijos() colisionesObjetosTocables() Las funciones que hacen los clculos son: calcularColisionPantalla(objeto) calcularColisionBordesExternos(objeto1,objeto2) calcularColisionInterna(objeto1,objeto2) Primero hablemos de las funciones de hacer clculos, despus de los manejadores, en las 3 funciones de hacer clculos el primer objeto que entra debe ser de tipo jugador, realmente en el juego con lo nico con lo que se calculan colisiones en con el jugador, los enemigos no se matan entre ellos, ni cosas parecidas. calcularColisionPantalla(objeto): Se realizan los clculos pertinentes entre en objeto jugador y las variables ladoIzquierdoPantalla, ladoDerechoPantalla, ladoArribaPantalla, ladoAbajoPantalla, stas se crean al comenzar el juego y ya no se vuelven a tocar, como necesitan realizar bsquedas (la funcin coger elemento por nombre) sera un desperdicio muy grande de recursos, no solo crear las variables sino calcularlas en cada llamada, estas variables son en realidad constantes, pero Javascript no tiene constantes. Las variables de las que hace uso la funcin estn fuera de ella como globales para que no se creen y destruyan en cada llamada y ganar rendimiento, son las siguientes: var ladoIzquierdoObjeto; var ladoDerechoObjeto; var ladoArribaObjeto; var ladoAbajoObjeto; calcularColisionBordesExternos(objeto1,objeto2): Se realizan los clculos entre los lados del objeto1 que es el jugador con los del objeto2 que es de tipo muro, es una funcin preparada para activar y desactivar las banderas que impiden al jugador andar por donde hay un muro, la funcin no devuelve nada y variables de las que hace uso estn declaradas como globales para ganar rendimiento. var ladoIzquierdoObjeto1; var ladoDerechoObjeto1; var ladoArribaObjeto1; var ladoAbajoObjeto1; var ladoIzquierdoObjeto2; var ladoDerechoObjeto2; var ladoArribaObjeto2; var ladoAbajoObjeto2;

- 125 -

AJAX, fundamentos y aplicaciones

calcularColisionInterna(objeto1,objeto2): Es una rplica de la funcin anterior, en cambio no toca las banderas de muro ya que estos objetos se pueden atravesar, es decir en este caso el objeto2 no es un muro, pertenece al array de objetos que se crean y se destruyen, devuelve true si hay colisin y false si no la hay. Las variables de las que hace uso estn declaradas como globales para ganar rendimiento como en todas las funciones de clculo de colisiones. var ladoIzquierdoObjeto1I; var ladoDerechoObjeto1I; var ladoArribaObjeto1I; var ladoAbajoObjeto1I; var ladoIzquierdoObjeto2I; var ladoDerechoObjeto2I; var ladoArribaObjeto2I; var ladoAbajoObjeto2I; Sobre los manejadores, son precisamente dos por lo siguiente: El primer manejador est dirigido a que el jugador no atraviese los muros, es decir controla las banderas de muro que se miran en el movimiento, por lo que hace uso de las 2 primeras funciones de hacer clculos que cambian las banderas. El segundo manejador solo se encarga de las colisiones con los objetos, pero su trabajo es mucho ms duro ya que este manejador crea y destruye los objetos, adems de disparar algunas acciones. El esquema de la funcin es el siguiente: function colisionesObjetosTocables() { var i; for(i=0; i < numeroObjetos; i++) { if((arrayObjetos[i].marcadoParaEliminar == true) && (arrayObjetos[i].tipo != "objetoVacio")) { } else if(arrayObjetos[i].tipo == "jugadorE") { } else if((arrayObjetos[i].tipo == "enemigo")) { } else if((arrayObjetos[i].tipo == "objetoVacio") && (arrayObjetos[i].marcadoGenerar == false)) { } else if((arrayObjetos[i].tipo == "objetoVacio") && (arrayObjetos[i].marcadoGenerar == true)) { } else { var colision = calcularColisionInterna(jugador,arrayObjetos[i]); if (colision == true) { colision = false; if(arrayObjetos[i].tipo == "objetoCogible") { } else if(arrayObjetos[i].tipo == "objetoAccionPuerta") {

- 126 -

AJAX, fundamentos y aplicaciones

} else if(arrayObjetos[i].tipo == "ObjetoAccionCofre") { } else if(arrayObjetos[i].tipo == "teletransporte") { } else if(arrayObjetos[i].tipo == "enemigoInanimadoInmortal") { } } } } } El esquema de la funcin es sencillo, sus operaciones no, dependiendo del tipo de objeto que tengamos ste dispara unas acciones u otras cuando es tocado, aunque por la temtica del asunto est bastante claro lo que puede hacer cada objeto, los cofres se abren, los teletransportadores te cambian de pantalla, etc.

6.5 Requisitos de sistema y conexin


Necesidades de memoria Todos los archivos del juego no alcanzan los 2,7 Mega bites en disco duro, es sorprendente la cantidad de memoria que llegan a emplear los navegadores al crear el DOM del juego: Algunos nmeros sobre el consumo de memoria RAM: I. Explorer 7 iniciado con una pgina plana: Cerca de 30 Megabytes. I. Explorer 7 con el juego cargado en la pantalla de login: Cerca de 60 Megabytes. I. Explorer 7 jugando: Entre 60 y 70 Megabytes. M. Firefox 1.5 iniciado con una pgina plana: Cerca de los 21 Megabytes. M. Firefox 1.5 con el juego cargado en la pantalla de login: Cerca de 62 Megabytes. M. Firefox 1.5 jugando: Cerca de los 60 Megabytes. Algunos nmeros sobre el rendimiento El PC de pruebas es un Pentium M 1.6 Ghz con 512Mbytes RAM a 400 MHz, no es ni muy nuevo ni muy viejo, adems es un porttil, podra entrar dentro de los PCs de gama baja actualmente, aunque en los hogares hay equipos ms viejos todava, este es un buen punto medio. Claramente desde el principio I. Explorer 7 an consumiendo ms RAM ha conseguido un rendimiento muy superior antes M. Firefox 1.5 si hablamos de nmero de FPS (realmente iteraciones del bucle principal en nuestro caso). Internet Explorer 7: Jugando obtiene los 54-63 FPS sin problemas y no pega bajones. M. Firefox 1.5: Jugando obtiene los 54-63 FPS tambin, pero pega bajones por debajo de los 40 FPS mas veces de lo deseable. Necesidades de conexin Las pruebas actuales se han hecho de manera local y en Internet, los resultados han sido aceptables consiguiendo que el juego sea jugable con una conexin poco mejor que una lnea de 56kb, ya que una vez que el juego esta cargado en memoria solo enva y recibe cadenas de texto para mantener la conexin.

- 127 -

AJAX, fundamentos y aplicaciones

Captulo 7:
Un mundo de Toolkits y Frameworks
7.1 Descripcin del captulo
En los captulos anteriores hemos estado trabajando intensamente con HTML y Javascript. Aunque estamos obligados a utilizar estos dos lenguajes cuando hablamos de AJAX, es posible usarlos directamente (como hemos hecho hasta ahora) o indirectamente (lo que ser nuestro objetivo en el presente captulo), es decir, existe la posibilidad de trabajar sobre una capa de abstraccin de alto nivel que ms tarde generar automticamente el cdigo HTML y Javascript necesario para que nuestra aplicacin funcione como una pgina web dinmica. Cuanto mejor y ms flexible sea esta capa, ms nos alejar de los intrincados recovecos de la programacin web AJAX directa, facilitando as el trabajo. Cada toolkit o framework posee una filosofa diferente y proporciona una capa de alto nivel con distintas caractersticas y lenguajes propios.

7.2

Tipos de Toolkits y Frameworks sobre Java

A da de hoy existen ms de 50 toolkits y frameworks diferentes para trabajar con AJAX, la inmensa mayora gratuitos y algunos otros de pago. En una bsqueda del ms adecuado para nuestros propsitos, nos podemos sentir desbordados y no saber cul escoger y porqu. Para arrojar un poco de luz en este asunto, primero se va a realizar una pequea clasificacin que, en cualquier caso, se quedar pequea en cuanto pase algo de tiempo ya que siempre estn apareciendo nuevas ideas para utilizar AJAX partiendo de diferentes tecnologas de alto nivel. En este apartado nos centraremos en las bibliotecas que generan Javascript y que incorporan tecnologa Java por lo que los siguientes puntos intentan abarcar gran parte de las soluciones java actuales para trabajar con AJAX.

7.2.1 Bibliotecas Javascript en el lado cliente


stas son tal vez las que menos abstraccin nos dan ya que estamos trabajando directamente sobre Javascript y HTML, como ocurre por ejemplo en la biblioteca construida durante los primeros captulos del presente volumen (aunque sta es muy simple y no cubre todas las necesidades, la usamos para aprender). Caractersticas principales: Funcionan igual no importa el tipo de tecnologa que usemos en el servidor: PHP, Java, Ruby, etc. Son accesibles durante el transcurso del programa ya sea localmente o a travs de una URL. Pueden combinarse en una misma aplicacin. Razones tcnicas para utilizar stas: Manejan las comunicaciones asncronas. Manejan las incompatibilidades entre Navegadores. Usan un IFrame (Frame invisible al usuario que carga la informacin que necesitamos en la aplicacin abriendo la pgina correspondiente sin usar el objeto XMLHttpRequest) si el Navegador no soporta AJAX. Proveen una buena navegacin dando soporte para los botones de Ir a la pgina anterior e Ir a la pgina siguiente que muchas veces al hacer una aplicacin dinmica pierden su utilidad. Proporcionan Widgets listos para usar, como rboles, calendarios, etc. Proporcionan una API de acceso al DOM ms sencilla que la original. Proporcionan manejadores de errores. Proporcionan manejadores de eventos sencillos. Proporcionan facilidades para construir interfaces de usuario avanzadas. Facilitan una mejor programacin orientada a objetos. Razones comerciales para utilizar stas: Han sido probadas en el mercado por lo que suelen ser mejores que las de uno mismo.

- 128 -

AJAX, fundamentos y aplicaciones

Poseen comunidades de desarrolladores por lo que es fcil encontrar ayuda. Son fciles de usar aunque primero hay que aprender a usarlas, lo que no es directo ni mucho menos. Los entornos IDE como Netbeans y Eclipse tienen plugins que dan soporte a muchas de estas bibliotecas facilitando el desarrollo.

Ejemplos de este tipo de bibliotecas son: Dojo Toolkit: o La ms utilizada y comprensible. o Est ganando el liderazgo. o Tiene el mayor soporte por parte de la industria (Sun e IBM). o http://dojotoolkit.com/ Prototype: o Usada como base para otras bibliotecas. o http://prototype.conio.net/ Script.aculo.us: o Construida sobre Prototype. o Buen conjunto de efectos visuales y controles. o http://script.aculo.us/ Rico: o o o

Construida sobre Prototype. Rica en componentes para la comunicacin asncrona. http://openrico.org/

Como conclusin puede decirse que son buenas y se pueden coger widgets de diferentes fuentes. Lo malo es que el desarrollador tiene que aprender Javascript y cada biblioteca suele tener su propia sintaxis.

7.2.2 Tecnologas Wrapper: jMaki


jMaki proporciona una capa Java de abstraccin sobre Javascript, de esta manera podemos utilizar Widgets de las diferentes bibliotecas del lado cliente (las soportadas, como Dojo, Scriptaculus, Yahoo UI Widgets, DHTML Goodies) bajo una sintaxis Java comn. De esta manera se facilita el trabajo a los programadores Java para los que Javascript suele ser algo muy extrao, su web es https:/ajax.dev.java.net/. Como conclusin puede decirse que an a las diferentes bibliotecas bajo un modelo de programacin comn y tiene plugin para Netbeans 5.5. Su nico problema (que tambin puede verse como una ventaja) es que est en constante evolucin ya que sus desarrolladores se encargan de que soporte las bibliotecas Javascript de ltima generacin. NOTA: jMaki tambin permite trabajar con PHP, no solo con Java.

7.2.3

Componentes Java Server Faces que utilizan AJAX

Con estos componentes no necesitamos conocer nada de Javascript delegando esta complejidad a los autores de los componentes. Con esto pueden hacerse las pginas a base de coger y arrastrar componentes a travs de los entornos IDE que soportan Java Server Faces. Algunas implementaciones de esta idea son: Componentes Blueprint con soporte AJAX (cdigo abierto): o Web: http://developers.sun.com/ajax/componentscatalog.jsp o Web: https://bpcatalog.dev.java.net/ajax/jsf-ajax/ Ajax4jsf (cdigo abierto): o Web: https://ajax4jsf.dev.java.net/ ICEfaces (ICESoft) (comercial):

- 129 -

AJAX, fundamentos y aplicaciones

Web: http://www.icesoft.com/products/icefaces.html

Dynafaces (cdigo abierto) o Web: https://jsf-extensions.dev.java.net/nonav/mvn/slides.html

Como conclusin puede decirse que es muy sencillo de utilizar ya que los componentes se usan arrastrndolos sobre el espacio de trabajo. No obstante, crear nuevos componentes personalizados no es una tarea sencilla.

7.2.4

Traductor Java a HTML/Javascript: Google Web Toolkit

Con este toolkit todo el desarrollo se hace bajo Java, (ms bien un subconjunto de sus bibliotecas bastante pequeo) junto con una serie de bibliotecas desarrolladas por Google para el desarrollo web que son las que integran realmente el toolkit y que, realmente, son las que utilizaremos. Es posible emplear constantemente el lenguaje Java a que estamos acostumbrados (asumiendo que se sabe Java) en el seno del toolkit para el desarrollo y la depuracin. Una vez que todo funcione correctamente se utilizar el preprocesador del toolkit que traducir la aplicacin escrita en Java a HTML y Javascript. La web es http://code.google.com/webtoolkit/. Como conclusin puede decirse que Java es la mejor capa de abstraccin que nos aleja del HTML/Javascript todo lo que se puede. Adems tiene un buen soporte. El nico inconveniente es que no nos aleja totalmente de las hojas de estilo y del DOM.

7.3

Tipos de Toolkits y Frameworks sobre lenguajes no Java

Como puede suponer el lector, no slo hay suficientes toolkits y frameworks, sino tambin demasiados y variopintos como para hablar de todos ellos, si bien vamos a mencionar algunas de las plataformas de programacin y lenguajes ms usuales.

7.3.1

.NET Frameworks

Hay una gran cantidad de compaas que utilizan tecnologa Microsoft por lo que podremos encontrar tambin una gran cantidad de frameworks basados en .NET, ya que el nmero de usuarios potenciales es muy grande. Uno de los ms interesantes es: Atlas: es la apuesta de Microsoft para desarrollar web, integra desarrollo del lado cliente con un desarrollo del servidor basado en las bibliotecas ASP .NET 2.0.

Existen ms frameworks entre los que podramos mencionar: Ajax Engine, Bitkraft, MagicAjax, Monorral y zumiPage.

7.3.2

Flash Frameworks

La tecnologa Flash se est introduciendo vertiginosamente en el mundo web y ganando adeptos gracias a la facilidad de desarrollo que proporciona. AJAX no poda ser menos y se dispone de: Flex Framework FABride: es una pequea biblioteca que puede ser insertada en una aplicacin o componente Flex o incluso en un archivo swf vaco y exponerlo al cdigo dinmico en el navegador; ahora es cdigo abierto.

7.3.3

PHP Frameworks

Pueden encontrarse ms de 15 frameworks y no parece haber un claro ganador entre ellas; slo el tiempo lo dir. Por mencionar algunos: AjaxAC, AJAX AGENT, Cajax, CakePHP, Flexible Ajax, My-BIC, PAJAJ, Pipeline, TinyAjax, symfony, xajax, XOAD, Zoop, etc

7.3.4

Otros Frameworks

Tambin se pueden encontrar desde frameworks que no dependan de la tecnologa del servidor, hasta algunos para usar con ColdFusion, Perl, Python, Lisp y un largo etctera con lo que hay para todos los gustos y colores.

- 130 -

AJAX, fundamentos y aplicaciones

7.4

Conclusiones sobre el uso de los Toolkits

Ya que existen tantas aproximaciones diferentes sobre una misma idea como es AJAX y debemos elegir una manera de trabajar que use una o varias de stas (si es que son compatibles), de las opciones anteriores debemos hacer nuestra eleccin con detenimiento ya que esto condicionar de manera importante el esquema de nuestra aplicacin. No se sabra decir cual es la mejor forma de trabajar, ya que ello depende de muchos factores. Por ello, la ms idnea sea seguramente la ms cercana a cada programador particular: un programador web se puede ver cmodo con las bibliotecas del lado cliente si no conoce Java, mientras que a un programador Java le puede resultar complicado aprender Javascript en un principio por las carencias de programacin orientada a objetos de ste.

7.5

Notas Finales del captulo

Todos los toolkits y frameworks prometen ser maravillosos y facilitar la vida muchsimo al programador. Los mejores de ellos o los que intentan captar ms al desarrollador tienen demostraciones en la misma pgina web, con el cdigo fuente para que pueda apreciarse rpidamente la filosofa y facilidad de uso. A este respecto, uno de los que ms impresiona es ZS en el que el cdigo es realmente mnimo, pudiendo programar con sus etiquetas tipo HTML; tambin GWT o Google Web Toolkit es muy tentador, ya que intenta hacerlo todo con Java. Hemos de ser conscientes de que nos encontramos en un momento en el que la industria intenta captar usuarios (muchos de los Toolkits y Frameworks son gratuitos), y ya que no hay una lnea de trabajo definida el campo est abonado para que vayan apareciendo y crezcan mltiples soluciones. Slo el tiempo dir cules prevalecen y cules se dejan de actualizar por su desuso.

- 131 -

AJAX, fundamentos y aplicaciones

Captulo 8:
Google Web Toolkit (GWT)
8.1 Descripcin del captulo
Este captulo introduce GWT al lector, para que pueda comprobar por s mismo lo fcil o difcil que es desarrollar aplicaciones web bajo este toolkit, para ello: Necesitaremos: o Netbeans o Google Web Toolkit o Plugin de GWT para Netbeans Seguiremos los siguientes Pasos: o Explicacin de los componentes de GWT o Instalacin de GWT sobre Netbeans o Vista rpida a la documentacin que incorpora GWT o Creacin de una pequea aplicacin (Un escritorio web) en el que aprenderemos: Usar varios tipos de Widgets para crear la interfaz de usuario Manejar los tpicos eventos web en Java Utilizar Hojas de Estilo en GWT (no nos podemos deshacer de ellas) Acceder a las clases Window y DOM que son un API que interacta con los objetos del navegador directamente Realizar una peticin AJAX al servidor para ver cmo se usa la interfaz y que el servlet se crea automticamente a partir de la clase que creamos nosotros.

8.2

Los componentes de GWT

8.2.1 Qu es Google Web Toolkit?


Google web toolkit es bsicamente un framework que permite desarrollar aplicaciones web sobre el lenguaje Java permitiendo al desarrollador utilizar entornos de desarrollo como Netbeans o Eclipse; cuando la aplicacin est lista y ha sido depurada en Java mediante ciertas herramientas de apoyo, como ltima fase la aplicacin pasa a travs de un preprocesador que la traduce en HTML y Javascript. De esta manera tenemos dos maneras de ejecutar una aplicacin hecha en Google Web Toolkit: la primera es sobre un navegador simulado que incorpora GWT que realmente esta corriendo sobre la Java Virtual Machine y que nos permite depurar la aplicacin en Java; una vez lista se preprocesa y es posible probarla sobre un navegador web. Este preprocesador (realmente es un traductor fuente-fuente) y el navegador-simulador son las dos herramientas de desarrollo que proporciona GWT, como muestra la figura 8.1. Al desarrollar la aplicacin bajo Java tenemos un compilador que nos avisa de todos los errores de tipos tpicos y podemos desarrollar utilizando una programacin Orientada a Objetos, para muchos programadores ms sencillo que el sistema de prototipos que proporciona Javascript. Adems podemos desarrollar tanto la parte cliente (paginas html) como servidora (servlets java) de la aplicacin sobre el mismo entorno IDE que nos proporciona tambin como es en el caso de Netbeans el servidor Tomcat para realizar las pruebas rpidamente . En la prctica es muy cmodo y es una buena opcin para una empresa que desarrolle aplicaciones medianas, adems si sus programadores conocen Java el camino est bastante allanado. Por si no fuera suficiente el no tener que aprender a utilizar Javascript, GWT maneja las incompatibilidades entre navegadores por nosotros, evita hasta cierto punto tener que acceder al DOM y proporciona una API ms sencilla que el de Javascript para ello. Adems proporciona soporte para los botones de siguiente y anterior de los navegadores que pierden soporte normalmente en las aplicaciones dinmicas y proporciona los Widgets ms usuales que necesita cualquier desarrollador para construir la interfaz de usuario mediante la clase UI, como se muestra la figura 8.1. Tambin es capaz de compilar en

- 132 -

AJAX, fundamentos y aplicaciones

Javascript algunas de las clases mas utilizadas en la programacin Java a travs de su JRE emulation library que tambin se muestra en la figura 8.1 en las class libraries.

Figura 8.1 Diagrama de bloques de GWT, extrado de su pgina web.

8.2.1

Instalacin

Una vez bajados Netbeans y GWT de sus pginas oficiales y obtenido el plugin de GWT para Netbeans (que no es ms que un Proyect Template que nos construye la correcta estructura de directorios) procederemos de la siguiente manera. 1. Instalar Netbeans como cualquier programa normal eligiendo los directorios. Si se instala sobre el directorio raz y se quita del nombre de su carpeta las rayas y puntos del nombre por defecto nos ahorraremos algunas complicaciones que puede dar diciendo que no encuentra las bibliotecas (problema en Windows). Instalar el plugin sobre Netbeans, para ello seguimos los siguientes pasos: 2.1 Abrimos el Update Center mostrado en la figura 8.2 :

2.

Figura 8.2 Primer paso para instalar un plugin en Netbeans.

- 133 -

AJAX, fundamentos y aplicaciones

Figura 8.3 Asistente de instalacin de mdulos de Netbeans. 2.2 Nos sale el asistente que se muestra en la figura 8.3 para instalar mdulos, elegimos la opcin de abajo Install Manually Downloaded Modules y pulsamos siguiente.

Figura 8.4 Asistente de instalacin de mdulos de Netbeans (2 paso). 2.3 Llegamos a la figura 8.4 a partir de aqu pulsamos siguiente y decimos que si a todo, hasta que termine la instalacin. 3. La siguiente vez que creemos un nuevo proyecto en la categora web podemos elegir Google Web Toolkit aplicacin, como muestra la figura 8.5.

- 134 -

AJAX, fundamentos y aplicaciones

Figura 8.5 Creando un nuevo proyecto con Netbeans. 3.1 Cuando creemos la primera aplicacin nos preguntar el directorio donde est GWT, ahora es el momento de descomprimirlo y dejarlo en un directorio donde ya no lo vamos a tocar: elegiremos el directorio en Netbeans y listo, se termin la instalacin.

8.3

Documentacin de GWT

Cuando descomprimimos por primera vez el archivo comprimido del toolkit vemos que dentro de la carpeta de ste hay otras dos carpetas doc y samples. Dentro de la primera podemos encontrar una carpeta con la documentacin de las CSS proporcionndonos el toolkit una con el nombre de los estilos por defecto de cada objeto, otra carpeta con la documentacin en HTML y una tercera con la documentacin en formato Javadoc, es decir las clases y la informacin que las relaciona con el resto de componentes. La hoja de estilo y el Javadoc (mostrado en la figura 8.6) sern de consulta obligatoria mientras estemos haciendo nuestros primeros programas.

Figura 8.6 Documentacin en formato Javadoc de GWT.

- 135 -

AJAX, fundamentos y aplicaciones

Dentro de la carpeta html tenemos un largo tutorial con una lista de contenidos que nos puede ser til si nos atascamos intentando manejar algo que aqu explique explcitamente. La segunda carpeta que contiene el directorio principal samples, que posee el cdigo fuente de los ejemplos que hay en la pgina web Este cdigo fuente nos ayudar muchas veces a trabajar ms rpido, por ejemplo a la hora de crear ciertos elementos grficos en la demostracin kitchenSink encontraremos cdigo de ejemplo de todos los elementos tpicos que incorpora GWT como se muestra en la figura 8.7.

Figura 8.7 Ejemplo KitchenSink mostrando los mens. Con todo lo anterior si el lector se sienta un rato delante del ordenador y sigue la gua siguiente para desarrollar su primera prueba debera ver que no presupone ningn gran esfuerzo desarrollar pequeas aplicaciones con este toolkit, si bien primero hay que aprender ya que nada es mgico en esta vida (excepto la aparicin de nuevos impuestos gubernamentales).

8.4

Aplicacin de Ejemplo

Como la mejor forma de aprender es con la prctica se irn explicando la forma de crear mens, aplicar estilos, manejar eventos, etc., realizando una pequea aplicacin.

8.5.1 Iniciando un nuevo proyecto


Al iniciar un nuevo proyecto en blanco nos encontraremos con que podemos rellenar tres campos que poseen valores por defecto: 1) este proyecto se llamara EscritorioWeb, 2) como directorio de trabajo el lector puede elegir el que le sea ms cmodo y 3) la clase principal la llamaremos EscritorioWeb.client.Escritorio, es decir, en nuestro proyecto EscritorioWeb en la carpeta de la parte cliente, la clase principal se llamar Escritorio. Si abres esta clase te encontraras con: public class Escritorio implements EntryPoint { /** Creates a new instance of Escritorio */ public Escritorio() { } public void onModuleLoad() { } } EntryPoint es lo que sera la clase ejecutable, es decir cuando ejecutemos nuestra aplicacin se crear un objeto de esta clase y se ejecutar el mtodo onModuleLoad() por lo que el cdigo relevante estar aqu

- 136 -

AJAX, fundamentos y aplicaciones

dentro, el constructor public Escritorio() {} se puede borrar ahora mismo ya que nuestro ejemplo no lo usar para inicializar nada y el sistema es capaz de dar un constructor por defecto. En esta aplicacin de ejemplo seguiremos el siguiente esquema: public class Escritorio implements EntryPoint { //Variables privadas importantes (por poner un poco de orden) public void onModuleLoad() { //programa principal } } //Otras funciones secundarias necesarias Si bien Java nos obliga a una programacin orientada a objetos, en este ejemplo no vamos a crear muchos archivos con muchas clases y mucha herencia, lo vamos a simplificar todo ya que se busca la comprensin del funcionamiento de GWT y no realizar una aplicacin real que respete todas las normas de diseo.

8.5.2 Clases de la interfaz de usuario de GWT


El apartado grfico es renderizado usando HTML creado dinmicamente. Aunque es posible manipular el DOM mediante un API, es ms sencillo utilizar los Widgets que incorpora GWT ya que stos estn hechos para funcionar por igual en todos los navegadores de forma que se evitan incompatibilidades. Primero disearemos la interfaz de nuestro escritorio como muestra la figura 8.8. Para ello usaremos varios Widgets ya definidos, no tendremos que crear ninguno extra, que son bsicamente un men (con varios submens adheridos) y tres imgenes que harn el papel de iconos; el fondo del escritorio y el estilo del men estarn dentro de una hoja de estilos .css de la que se hablar luego. Crearemos estos componentes por este orden: men, iconos y hoja de estilo CSS.

Figura 8.8 Ejemplo Completado. Se van a utilizar tres applets Java para desarrollar este escritorio de ejemplo, igual que se pueden utilizar cualquier otro; stos se han encontrado en Internet y son de libre distribucin. Para crear la barra de men seguiremos los siguientes pasos: 0. Importamos las clases necesarias en la cabecera del cdigo 1. Configuramos la ventana del navegador 2. Creamos los comandos que lanza el men

- 137 -

AJAX, fundamentos y aplicaciones

3. 4.

Creamos el men Lo aadimos a la pgina. Si se te olvida, se ver la pgina en blanco!

Un comando es una funcin que se lanza al pulsar clic sobre una de las opciones del men y que est asociada a ste. En nuestro caso los comandos invocarn la orden open del objeto window utilizando una API, de esta manera lanzarn otra pgina web que da la casualidad que es un applet java con una pequea aplicacin, para nosotros el como funcionan estos applets carece de importancia: son cajas negras. El cdigo de Escritorio.java sera el siguiente: package EscritorioWeb.client; //Clase ejecutable import com.google.gwt.core.client.EntryPoint; //Clases que se usan para la interfaz de usuario import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.MenuBar; import com.google.gwt.user.client.ui.MenuItem; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.ui.Image; //APIs que actan directamente sobre el navegador import com.google.gwt.user.client.Window; public class Escritorio implements EntryPoint { //El panel "AbsolutePanel" permite posicionar Widgets en una posicin exacta private AbsolutePanel escritorio; //La clase "MenuBar" se usa para crear mens private MenuBar barraInicio; //Imgenes que usaremos como iconos a las que le asignaremos manejadores mas tarde private Image calendario,calculadora,bloques; public void onModuleLoad() { //1.Poner a punto la ventana //El panel principal es RootPanel, le aadimos el fondo de escritorio (en la css) Window.enableScrolling(false); //Desactivamos la barra de desplazamiento //2.Crear los comandos que lanzara el men. Command cmdCalendario = new Command() { public void execute() { Window.open("./calendario/applet.html","Calendario","width=250px, height=340px"); } }; Command cmdCalculadora = new Command() { public void execute() { Window.open("./calculadora/applet.html","Calculadora","width=215px, height=280px"); } }; Command cmdBloques = new Command() { public void execute() { Window.open("./bloques/applet.html","Bloques","width=210px, height=330px"); } }; //3.Crear la barra de inicio MenuBar programas = new MenuBar(true); //Si "true" genera el men verticalmente

- 138 -

AJAX, fundamentos y aplicaciones

programas.addItem("<b>Calendario</b>", true,cmdCalendario); programas.addItem("<b>Calculadora</b>", true,cmdCalculadora); MenuBar juegos = new MenuBar(true); juegos.addItem("<b>Bloques</b>", true,cmdBloques); MenuBar principal = new MenuBar(true); principal.addItem("<b>Programas</b>", true,programas); principal.addItem("<b>Juegos</b>", true,juegos); barraInicio = new MenuBar(); barraInicio.addItem(new MenuItem("INICIO", principal)); //Algunas opciones configurables de "MenuBar" barraInicio.setTitle("Barra de Inicio"); barraInicio.setAutoOpen(true); //4.Aadimos la barra de inicio al "RootPanel" RootPanel.get().add(barraInicio); // Aade a la pagina } }

Figura 8.9 Resultado del men sin aplicarle ningn estilo. Tal y como muestra la figura 8.9 por ahora el aspecto del men es muy pobre. ATENCIN AL ERROR: Si pulsas sobre Calendario, Calculadora o Bloques se lanzar una nueva ventana con el Applet por el comando que tienen asignado, si haces esto sobre el Navegador de GWT puede que obtengas un error (lo ms probable): no te preocupes, pulsa sobre el botn de Compile/Browse y prubalo sobre un navegador web real que es donde funcionan correctamente los applets. Por ahora el navegador GWT no soporta los applets.

8.5.3

Manejadores de eventos en GWT

En el men anterior nada ms pulsar con el ratn sobre la opcin deseada se abre el applet correspondiente, ahora vamos poner 3 iconos, estos son 3 imgenes, cada una con su manejador de eventos de ratn que slo se diferencia en el applet que abre. Para crear los iconos seguiremos los siguientes pasos: 0. Importamos las clases necesarias en la cabecera del cdigo

- 139 -

AJAX, fundamentos y aplicaciones

1. 2. 3.

Creamos una clase abstracta que maneja los eventos de ratn de los iconos Creamos una clase por icono que implementa la clase abstracta anterior aadindole el mtodo que le falta (mtodo que lanza en cada icono un applet distinto). Creamos un Absolute Panel del tamao que tendr el espacio donde podemos posicionar iconos, en nuestro caso 800x600 en el que colocaremos las imgenes en una posicin fija asignndole a cada una su manejador de eventos de ratn. El Absolute Panel es un elemento organizativo no visible al ojo del usuario.

Los eventos de ratn que podemos manejar en GWT son equivalentes a los que tiene cualquier navegador web, si bien nos encontramos con que las pequeas diferencias a la hora de hacer un manejador de teclado o ratn que puede haber entre navegadores como Mozilla Firefox e Internet Explorer las resuelve GWT perfectamente, lo que ahorra quebraderos de cabeza al desarrollador. Primero aadiremos las siguientes clases a la cabecera del archivo: //APIs que actan directamente sobre el navegador import com.google.gwt.user.client.DOM; //Clases necesarias para los manejadores del ratn import com.google.gwt.user.client.ui.MouseListenerAdapter; import com.google.gwt.user.client.ui.Widget; Segundo, detrs del mtodo onModuleLoad pero dentro de la clase EntryPoint debemos aadir las siguientes clases que manejan los eventos del ratn. /* // CLASE ABSTRACTA QUE SIMULA UN COMPORTAMIENTO PARECIDO AL RATN DE // ESCRITORIO Y CLASES QUE HEREDAN ESTE COMPORTAMIENTO PARA CADA ICONO // CON SU COMANDO */ abstract class ControladorIcono extends MouseListenerAdapter { public boolean pulsado = false; public boolean desPulsado = false; //NOTA: Los manejadores de cuando se pulsa y se despulsa el ratn //son algo complejos para que reaccionen como si estuviramos pulsando //sobre un escritorio de verdad y no se den reacciones raras como que //se inicie la accin soltando el ratn fuera del icono, etc... public void onMouseDown(Widget sender,int x,int y) { pulsado = !pulsado; } public void onMouseUp(Widget sender,int x,int y) { this.desPulsado=true; if(pulsado && desPulsado) { //Hiciste un click this.accion(); pulsado=false; desPulsado=false; } else { desPulsado=false; } } public void onMouseMove(Widget sender, int x, int y) { sender.setStyleName("iconoSobre"); } public void onMouseLeave(Widget sender) { sender.setStyleName("iconoLejos");

- 140 -

AJAX, fundamentos y aplicaciones

} abstract void accion(); } private class ControladorIconoCalendario extends ControladorIcono { public void accion() { Window.open("./calendario/applet.html","Calendario","width=250px, height=340px"); } } private class ControladorIconoCalculadora extends ControladorIcono { public void accion() { Window.open("./calculadora/applet.html","Calculadora","width=215px, height=280px"); } } private class ControladorIconoBloques extends ControladorIcono { public void accion() { Window.open("./bloques/applet.html","Bloques","width=210px, height=330px"); } } Por ltimo y lo ms sencillo, crear un Absolute Panel en el que pegamos las imgenes cada una en una posicin exacta y de la que no se movern, para esto, aadimos las siguientes lneas de cdigo antes del punto 4 del cdigo donde actualmente solo se esta aadiendo la barra de inicio al RootPanel. //3.1 Creamos el escritorio y los iconos //Creamos el escritorio escritorio = new AbsolutePanel(); //Crea el panel del escritorio escritorio.setSize("800px","600px"); //Damos un tamao al escritorio invisible //Icono de la calculadora calculadora = new Image("./calculadora.gif"); calculadora.setSize("120px","140px"); calculadora.addMouseListener(new ControladorIconoCalculadora()); //Controlador de eventos de raton de iconos DOM.setStyleAttribute(calculadora.getElement(),"cursor","pointer"); //API de acceso al DOM escritorio.add(calculadora,10,20); //Posicion absoluta dentro del escritorio //Icono del calenario calendario = new Image("./calendario.gif"); calendario.setSize("140px","140px"); calendario.addMouseListener(new ControladorIconoCalendario()); //Controlador de eventos de raton de iconos DOM.setStyleAttribute(calendario.getElement(),"cursor","pointer"); //API de acceso al DOM escritorio.add(calendario,140,20); //Posicion absoluta dentro del escritorio //Icono del juego bloques bloques = new Image("./bloques.gif"); bloques.setSize("140px","140px"); bloques.addMouseListener(new ControladorIconoBloques()); //Controlador de eventos de raton de iconos DOM.setStyleAttribute(bloques.getElement(),"cursor","pointer"); //API de acceso al DOM escritorio.add(bloques,10,200); //Posicion absoluta dentro del escritorio Y que no se olvide, aadir el panel del escritorio al RootPanel, detrs del men, debera quedar as: //4.Aadimos la barra de inicio y el escritorio al "RootPanel" RootPanel.get().add(barraInicio); // Aade a la pgina la barra de inicio RootPanel.get().add(escritorio); //Aade a la pgina el escritorio con los iconos

- 141 -

AJAX, fundamentos y aplicaciones

Como resultado de aadir todo lo anterior el escritorio debera quedar como se ve en la figura 8.10 (una vez abiertas las tres aplicaciones por el usuario).

Figura 8.10 Ahora el escritorio tiene iconos pero sigue sin ningn estilo. Un aadido que dejara este ejemplo como un autentico escritorio en lo que se refiere al tratamiento de los iconos sera conseguir que pudiramos arrastrar estos por el fondo, y sin ser demasiado complejo, tampoco es fcil por lo que no est en el ejemplo bsico, si bien vamos a dar ciertas nociones para su diseo. Podemos cambiar una imagen de posicin a voluntad con el mtodo setWidgetPosition() que tiene el objeto AbsolutePanel que es en nuestro caso el escritorio que contiene las imgenes que son Widgets, el objeto AbsolutePanel tambin tiene mtodos para obtener sus coordenadas actuales por lo que podramos pensar estos sern de obligado uso. Si el icono est pulsado y movemos el ratn entonces ste debera seguir las coordenadas del ratn que obtenemos de los mtodos onMouseMove() y onMouseUp() contenidos en el manejador del ratn de las imgenes o iconos en nuestro caso. Como las variables pulsado y despulsado son de la clase, son accesibles desde el mtodo onMouseMove() y onMouseUp() que reciben las coordenadas del ratn y como la variable escritorio es global tambin podemos cambiar la posicin de una imagen desde estas funciones. De esta manera si pulsamos el ratn dentro de un icono, lo despulsamos fuera y la posicin del ratn ha cambiado, podemos pensar que el usuario quera mover el icono, no ejecutarlo, por lo que podemos moverlo a la nueva posicin. Esto sera muy sencillo si pudiramos aadir este comportamiento directamente en el icono pero el mtodo onMouseUp() no se ejecutar al despulsar fuera de ste ya que no est el ratn encima del icono, con lo cual algo que en principio pareca sencillo se convierte en un ejercicio de programacin divertido pero que ensuciara el ejemplo por lo que dejamos para el lector interesado. La opcin que hemos comentado pero que no funciona correctamente sera la siguiente: abstract class ControladorIcono extends MouseListenerAdapter { public boolean pulsado = false; public boolean desPulsado = false; public int xC,yC;

- 142 -

AJAX, fundamentos y aplicaciones

//NOTA: Los manejadores de cuando se pulsa y se despulsa el ratn //son algo complejos para que reaccionen como si estuviramos pulsando //sobre un escritorio de verdad y no se den reacciones raras como que //se inicie la accin soltando el ratn fuera del icono, etc. public void onMouseDown(Widget sender,int x,int y) { this.pulsado = true; this.xC=x; this.yC=y; } public void onMouseUp(Widget sender,int x,int y) { this.desPulsado=true; if(pulsado && desPulsado && this.xC == x && this.yC == y) { this.accion();//Hiciste un click } else if(pulsado && desPulsado && this.xC != x && this.yC != y) { escritorio.setWidgetPosition(sender,x,y); //No funciona correctamente } pulsado=false; desPulsado=false; } public void onMouseMove(Widget sender, int x, int y) { sender.setStyleName("iconoSobre"); } public void onMouseLeave(Widget sender) { sender.setStyleName("iconoLejos"); } abstract void accion(); }

8.5.4

Hojas de estilo CSS en GWT

Antes de nada es bueno que sepamos que por defecto GWT tiene un nombre de estilo asignado a cada elemento, por ejemplo, la clase MenuBar tiene por defecto el estilo gwt-MenuBar y como sta controla los eventos del ratn automticamente (asignando y cambiando su estilo segn si el ratn est encima de ella o no), es mejor usar este nombre, ya que si lo cambiamos deberemos de implementar un manejador de eventos del ratn que cambie el estilo cuando se pase el ratn por encima dando, por ejemplo, un efecto de iluminacin como muestra la imagen 8.11, lo que es un trabajo innecesario.

Figura 8.11 Men de inicio con el estilo aplicado. Es hora de aplicar algn estilo grfico al escritorio, lo que puede hacerse con dos sencillos pasos: 1. Aadir al documento XML de configuracin de la aplicacin el nombre de la hoja de estilo. 2. Crear la hoja de estilo. Editar el archivo de configuracin es muy fcil con dejarlo tal y como est en la figura 8.12 donde se seala el archivo y su contenido es suficiente.

- 143 -

AJAX, fundamentos y aplicaciones

Figura 8.12 Archivo de configuracin de un proyecto de GWT. Como se puede apreciar lo nico que indicaba anteriormente era la clase ejecutable, ahora le aadimos la hoja de estilo, para terminar crearemos el archivo Escritorio.css dentro de la carpeta public que tendr el siguiente contenido. body { background-image: url("Stonehenge.jpg"); } .gwt-MenuBar { background-color: #E8EEF7; border: 1px solid #87B3FF; cursor: default; } .gwt-MenuItem { background-color: #E8EEF7; cursor: default; } .gwt-MenuItem-selected { background-color: #FFFFFF; cursor: pointer } .iconoSobre { filter: alpha(opacity=50); -moz-opacity: 0.5; } .iconoLejos { filter: alpha(opacity=100); -moz-opacity: 1; } Como se puede apreciar en lo que se refiere al men de inicio se han mantenido los nombres de las clases por defecto de MenuBar y MenuItem como se coment anteriormente. Por ltimo nombrar que los efectos de opacidad asignados a los iconos forman parte de las CSS3 con lo que todava no est totalmente estandarizado y no siempre el efecto funciona en el navegador simulado de GWT (a veces si, otras no). No solo esto sino que cada navegador puede tener una implementacin diferente, por eso hay dos lneas para hacer lo mismo (filter: alpha(opacity=100); y -moz-opacity: 1; ), la primera est dedicada a Internet Explorer y la segunda a Mozilla Firefox, los resultados de aplicar este efecto se pueden ver en la figura 8.13.

- 144 -

AJAX, fundamentos y aplicaciones

Figura 8.13 Efecto de transparencia para resaltar mejor cuando un icono est seleccionado. Una vez que tenemos el estilo aplicado los resultados son los mostrados en la figura 8.14.

Figura 8.14 Escritorio completado.

8.5.5

Comunicaciones asncronas (AJAX) en GWT.

Hasta ahora y aunque no se haya mencionado explcitamente el lector habr podido sospechar que si en algn momento hemos utilizado algo que tenga que ver con AJAX, esto est muy escondido ya que en ningn momento hemos efectuado ninguna comunicacin con el servidor, esto es as porque no lo hemos hecho, por ahora solo se ha construido una Interfaz de Usuario de manera sencilla pero solo eso; los applets se cargan en una nueva ventana por una orden que le damos a la pgina, como si abriramos un link, es verdad que se cargan bajo demanda, pero esto no es AJAX ya que desde el principio tenemos conocimiento de dnde se encuentran, por esto estamos hablando de DHTML simplemente. Llega la hora de sumar a todo lo hecho anteriormente una pequea demostracin del uso del Objeto XMLHttpRequest, un simple saludo de bienvenida que provenga del servidor. El cliente dar su nombre al servlet y ste le devolver una cadena de texto. La realizacin de esta pequea tarea ha sido posible gracias a un ejemplo encontrado en Javapasin hecho por Sang Shin al que se le tiene que agradecer mucho su trabajo en tutoriales de Java y AJAX (con ms de 400.000 visitas) entre otras cosas.

- 145 -

AJAX, fundamentos y aplicaciones

Los pasos que se seguirn son los siguientes: 1. Crear la interfaz que extiende la clase RemoteServiceServlet. 2. Crear una interfaz que use una comunicacin asncrona. 3. Crear un servlet que implemente la primera interfaz. 4. Aadir el servlet a la hoja de configuracin XML del proyecto. IMPORTANTE! 5. Crear una funcin que realice una llamada al servlet y reciba la respuesta. Los dos primeros pasos forman parte del lado cliente de la aplicacin, mientras que el servlet forma parte del servidor. Cada una de estas dos primeras interfaces se crearn en un archivo nuevo y son muy sencillas.

Figura 8.15 Archivos de las clases interfaz. De esta manera debemos crear los dos archivos que se muestran en la figura 8.15; se puede empezar con el archivo HolaRemoto.java que es la interfaz que extiende la clase RemoteServiceServlet y que respetarn tanto la interfaz de la llamada asncrona que se usar en la parte cliente como el servlet del servidor. //Interfaz del servicio remoto que deber implementar el servidor. package EscritorioWeb.client; import com.google.gwt.user.client.rpc.RemoteService; public interface HolaRemoto extends RemoteService{ public String saludo(String s); } El siguiente es el archivo HolaRemotoAsync.java que tiene la interfaz que hace uso de una llamada asncrona que es la que se usar en la parte cliente. //Interfaz de llamada asncrona que usara el cliente, compatible con el interfaz HolaRemoto. package EscritorioWeb.client; import com.google.gwt.user.client.rpc.AsyncCallback; public interface HolaRemotoAsync { void saludo(String s,AsyncCallback arg2); } Lo siguiente ser crear un servlet que implemente la interfaz HolaRemoto y aadirlo al archivo de configuracin de la aplicacin. La clase que implementa el servlet se crear bajo la carpeta server dentro de la jerarqua de carpetas de la aplicacin en Netbeans, tal y como se muestra en la figura 8.16.

- 146 -

AJAX, fundamentos y aplicaciones

Figura 8.16 Ya falta poco para terminar. El archivo se ha llamado en este caso ServicioHolaRemoto.java ya que el saludo es un servicio que nos da el servidor y al que debemos llamar asincronamente, su contenido es el siguiente. //Servicio de saludo Remoto, se le puede enviar el final de la cadena. package EscritorioWeb.server; import EscritorioWeb.client.HolaRemoto; import com.google.gwt.user.server.rpc.RemoteServiceServlet; public class ServicioHolaRemoto extends RemoteServiceServlet implements HolaRemoto { public String saludo(String s) { return "Bienvenido a esta pequea demostracin de GWT "+s+", espero que te guste"; } } Para que el servicio funcione falta aadir una lnea al archivo de configuracin de la aplicacin donde se indica el nombre del servlet y la clase que lo implementa como se muestra en la figura 8.17.

Figura 8.17 Incorporando un servlet al proyecto. Por ltimo aadiremos la siguiente funcin al archivo Escritorio.java detrs de los manejadores de ratn pero dentro de la clase Escritorio y las clases necesarias para su uso en la cabecera del archivo con el resto. //Clases necesarias para emplear el servlet implementado import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget;

/* // FUNCIN DEL SERVICIO DE SALUDO */ void llamadaAlServicioSaludo(){

- 147 -

AJAX, fundamentos y aplicaciones

//1.Creamos la variable "miServicio" que hace la comunicacin HolaRemotoAsync miServicio = (HolaRemotoAsync) GWT.create(HolaRemoto.class); //2.Encontramos la direccion del servlet y se la damos a "miServicio" ServiceDefTarget destino = (ServiceDefTarget) miServicio; String direccionRelativa = GWT.getModuleBaseURL() + "saludoUsuario"; destino.setServiceEntryPoint(direccionRelativa); //3.Creamos un manejador de llegada AsyncCallback manejadorLlegada = new AsyncCallback() { public void onSuccess(Object result) { // Mostrar el correcto funcionamiento de alguna manera Window.alert((String)result); } public void onFailure(Throwable caught) { // Mostrar el error de alguna manera } }; //4.Efectuamos la llamada de "miServicio" con el manejador anterior miServicio.saludo("Sergio", manejadorLlegada); } Y para hacer que todo lo anterior funcione debemos llamar a la funcin llamadaAlServicioSaludo() en nuestro programa, en la figura 8.8 se ve como el men tiene una opcin ms, pero para probarlo rpido lo mejor es que llamemos a la funcin al final del programa principal, despus de aadir el men principal y el escritorio al RootPanel, de esta forma el saludo se har al entrar en la aplicacin una vez cargados los elementos anteriores dando el resultado de la figura 8.18.

Figura 8.18 Ejemplo completado durante el tema, llamada asncrona. Ahora una vez hecho este ejemplo sera bueno que reflexionsemos un momento sobre cmo funciona la estructura de la llamada, por qu hemos implementado estas clases y no otras. Para ello es bueno que le echemos un vistazo a la figura 8.19 sacada de la pgina de GWT.

- 148 -

AJAX, fundamentos y aplicaciones

Figura 8.19 Esquema de clases que utiliza GWT para realizar llamadas asncronas. Hemos implementado justamente las 3 clases que piden, la clase YourServiceImpl es la clase implementada en la carpeta server que se aadi al archivo de configuracin XML y que extiende la clase RemoteServiceServlet y las otras dos son las interfaces en el lado cliente que corrern como cdigo Javascript en el lado cliente que cumplen tambin los requisitos del cuadro, todo y funciona. Ahora hablemos un poco ms de la clase AsincCallback ya que es segn la documentacin el primer paso para realizar una llamada y la que usa el cliente realmente para comunicarse, nuestra interfaz HolaRemotoAsync hereda de sta adems. Esta clase tiene por defecto 2 manejadores de llegada, uno para cuando la llamada llega correctamente y uno para fallos. De esta manera podemos hacer el tpico tratamiento de errores en java de forma cmoda y las operaciones debidas si la llamada termina correctamente y obtenemos la informacin que queramos. El uso de esta clase se puede ver en la funcin llamadaAlServicioSaludo() del archivo Escritorio.java. Como puede ver el lector, no es difcil usar GWT, si bien merece la pena pararse una maana tranquilamente a hacer el ejemplo que propone este tema y estudiar el cdigo de otros ejemplos vistosos proporcionados por Google; y la comunidad de usuarios de GWT de forma que se tenga conocimiento de sus posibilidades.

8.5

Notas finales sobre GWT

Nos encontramos ante una magnfica herramienta para el desarrollo web utilizando Java: apenas ha dado problemas la realizacin del ejemplo anterior y la documentacin est muy bien. Si tuviramos que ponerle alguna pega es que todava contiene algunos fallos (bugs) encontrados por gente experimentada al hacer aplicaciones ms grandes que el equipo de desarrollo va subsanando poco a poco.

- 149 -

AJAX, fundamentos y aplicaciones

Conclusiones y Trabajo Futuro


Conclusiones
Las conclusiones estn divididas en personales, acadmicas y profesionales, las primeras proporcionan mi visin particular sobre el desarrollo del proyecto, las segundas tienen que ver con mi formacin en el contexto de la Ingeniera Tcnica en Informtica de Sistemas y las ltimas son tanto de carcter tcnico como de repercusin en el mundo del desarrollo web.

Personal
Se me ha brindado la oportunidad de hacer algo que quera, con lo cual ha sido una experiencia no solo bien aprovechada sino muy satisfactoria. La redaccin de la documentacin de una tcnica de programacin como AJAX, que est difundindose muchsimo actualmente me ha dado un cierto reconocimiento en la comunidad lo que, ocasionalmente, me puede facilitar un poco la vida profesional en el futuro.

Acadmico
El haber trabajado durante la realizacin del proyecto con documentacin en ingls y de forma autodidacta (apoyado por el director) me ha dado cierta autonoma totalmente indispensable para el informtico de hoy da. Esto se debe a que la Informtica es una disciplina en constante evolucin, y resulta indispensable saber realizar labores de investigacin y bsqueda de documentacin. Asignaturas como Sistemas en Tiempo Real muestran toda su utilidad cuando se desarrollan aplicaciones como la presentada en este proyecto. La velocidad de respuesta del servidor a los distintos clientes conectados marca la diferencia entre una aplicacin ldica jugable y no jugable. La creacin del proyecto me ha dado una slida base para desarrollar aplicaciones web, base que no me haba proporcionado antes la carrera y que puedo llegar a utilizar durante mi vida laboral.

Profesional
Durante el desarrollo de la aplicacin surgieron diferentes problemas con el clculo de colisiones y tratamiento del movimiento, entre otros. Una vez solucionados hemos obtenido una calidad similar que daban los juegos comerciales de la poca, es decir, la propia de las consolas de 16 bits lo que nos hace suponer que se han tomado las decisiones adecuadas. Los MORPGs (Massive Online Rol Playing Games) comerciales utilizan un protocolo basado en el uso del ratn para permitir una mejor interaccin en tiempo real entre los jugadores; en nuestro caso, utilizando el teclado, las peticiones AJAX y solamente el puerto 80, no se puede dar la misma solucin. Los gigantes del software de hoy en da apuestan por AJAX, lo que asegura su imposicin a corto plazo ya que stos estn desarrollando capas de abstraccin para no tener que trabajar a bajo nivel. Por esto ltimo nos sentimos muy positivos en el uso de AJAX de cara al futuro. Las aplicaciones web normales no necesitan la cantidad de parafernalia (grfica, de sonido, algortmica, de protocolo, etc.) mostrada en El poder de AJAX por lo que sus tiempos de respuesta e interactividad resultan ms agradables.

- 150 -

AJAX, fundamentos y aplicaciones

Trabajo futuro Documentacin


Se podran explorar ms toolkits pero eligindolos con cuidado ya que al haber tantos la mayora estn condenados a desaparecer. Mejorar el captulo 5 en lo referente a la seguridad; para ello sera necesario disear una aplicacin compleja que hiciera uso de toda la tecnologa actual y explicarla paso a paso para principiantes.

Aplicacin
Realizar una nueva versin en la que la base de datos guarde mejor el estado actual de la animacin del resto de jugadores de manera que se refleje mejor en los clientes el movimiento de los otros participantes. Esto se debe a que en la versin actual no se reproduce la animacin de los golpes recibidos por los dems jugadores.

- 151 -

AJAX, fundamentos y aplicaciones

Apndice:
HTML y XHTML
Introduccin HyperText Markup Language (lenguaje de marcado de hipertexto) es el lenguaje base con el que podemos hacer una pgina web, no necesitamos ningn servidor que gestione nada para poder visualizar una pgina que solo contiene HTML ya que el contenido es esttico. Sobr una pgina HTML se pueden insertar pedazos de cdigo de otros lenguajes para los que estn preparados los servidores y navegadores actuales, como Javascript, Jsp, etc... , stos son los que vuelven compleja la arquitectura de las pginas web actuales, no el HTML. Conceptos bsicos de HTML El lenguaje est pensado para hacer documentos; normalmente los documentos contienen texto, prrafos (texto), imgenes(con el nombre de su archivo que es texto), tablas(que contienen texto), etc. y mantienen una estructura sencilla, pues as de simple ser el HTML, acta mediante tags sobre el texto. <tag> Texto sobre el que acta la tag </tag> <tag> indica el comienzo de la tag y </tag> el fin, estas encierran el texto sobre el que actan, por ejemplo tenemos la tag <b>...</b> que pone el texto en negrita, las tags se pueden escribir tanto en mayscula como en minscula, es indiferente, el lenguaje no es sensible a ello. Estructura del documento HTML, ejemplo bsico <HTML> <HEAD> <TITLE>Hola mundo (Si me dieran 1 cada vez que lo leo)</TITLE> </HEAD> <BODY> <B> Hola mundo. </B> </BODY> </HTML> Hay 3 tags que describen las partes del documento y que nos sern imprescindibles: <html> y </html> Nos indican el principio y fin del cdigo html. <head> y </head> Especifica el protocolo y tiene el tag <title> que es utilizado como ttulo de la pgina por el navegador. <body> y </body>Contiene el resto del documento, el contenido. Si abrimos directamente la pgina con Mozilla Firefox desde nuestro disco duro, deberamos obtener el siguiente resultado.

Figura A.1 El eterno primer ejemplo

- 152 -

AJAX, fundamentos y aplicaciones

Como has podido ver en el ejemplo anterior, todo lo que hacemos es encerrar texto entre tags para formatearlo, centrarlo, etc. casi todo lo que nos dejara hacer un procesador de textos actual. Tags de imagen y tabla. Cosas como las imgenes al tener que leer la imagen de un archivo y tablas debido a la anidacin de los campos pueden ser algo ms complejas. Primero las imgenes: <HTML> <HEAD> <TITLE> Estamos cargando la imagen de unos perritos graciosos </TITLE> </HEAD> <BODY> <B> Perritos graciosos </B> <IMG src="img/perros.jpg" width=396 height=247 border=0 alt="Perritos graciosos"> </BODY> </HTML> Vemos que la tag de imagen <IMG> no tiene un final </IMG>, esto no es necesario ya que simplemente estamos actuando sobre un objeto de la pgina que asignamos dentro de la tag. Dentro de la tag <IMG> tenemos 5 campos que explicaremos ahora: src: Es el nico campo obligatorio, indica donde se encuentra la imagen, yo por ejemplo he creado un directorio llamado img que se encuentra al mismo nivel que la pgina para guardar todas las imgenes de la pgina y tener cierto orden. width y height: Indican el ancho y alto, no es necesario indicarlo, pero ayuda al navegador a representarlo ya que podemos querer que una imagen grande se muestre pequea, o viceversa, si no lo indicamos el navegador utilizar su tamao original. border: Indica si queremos que la imagen tenga un marco. alt: Es el texto que se muestra, si la imagen est cargando, no se carga o posicionamos el ratn encima de ella(Esto ltimo en IE). Veamos los resultados:

Figura A.2 Ejemplo de insertar una imagen en HTML

- 153 -

AJAX, fundamentos y aplicaciones

Visualizamos la imagen, pero quedara mas esttico si apareciera Perritos graciosos como ttulo y la imagen debajo, adems podramos dejarlo centrado. Para que aparezcan en lneas diferentes tenemos que poner un fin de lnea despus de Perritos graciosos, con el tag <BR>, que como <IMG> no tiene parte final ya que no encierra nada. Para centrar tanto la frase Perritos graciosos como la imagen podramos poner el tag <center> antes de la frase y el final </center> detrs del tag de la imagen, o ponerlo 2 veces, una para cada el texto y otra para la imagen, esto ltimo es lo recomendable, por si queremos hacer un cambio y ste no afecte a la otra parte del documento ms tarde. <HTML> <HEAD> <TITLE> Estamos cargando la imagen de unos perritos graciosos </TITLE> </HEAD> <BODY> <CENTER><B> Perritos graciosos </B></CENTER> <BR> <CENTER> <IMG src="img/perros.jpg" width=396 height=247 border=12 alt="Perritos graciosos"> </CENTER> </BODY> </HTML>

Figura A.3 Aadiendo ms etiquetas para mejorar la esttica Ahora las tablas: Es muy normal encontrarnos con que realmente la pgina que estamos visualizando es una tabla invisible dividida en 4 o 6 partes, una conteniendo un men, otra el ttulo de la pgina, otra el contenido, etc. Digo esto para que tengamos constancia de que son un elemento muy importante hoy, aadamos una tabla al ejemplo anterior.

- 154 -

AJAX, fundamentos y aplicaciones

<HTML> <HEAD> <TITLE> Estamos cargando la imagen de unos perritos graciosos </TITLE> </HEAD> <BODY> <CENTER><B> Perritos graciosos </B></CENTER><BR> <CENTER> <IMG src="img/perros.jpg" width=396 height=247 border=12 alt="Perritos graciosos"> </CENTER><BR> <CENTER> <TABLE border="4"> <TR> <TH>Nombre Perritos</TH> <TH>Color pelo</TH> <TH>Numero hermanos</TH> </TR> <TR> <TD>Tom</TD> <TD>Marron claro</TD> <TD>10</TD> </TR> <TR> <TD>Sam</TD> <TD>Marron oscuro</TD> <TD>11</TD> </TR> </TABLE> </CENTER> </BODY> </HTML> <Tabla>...</Tabla> Contiene toda la tabla y dentro es donde se pueden usar los tags <TR> Y <TH> Y <TD>. <TR>...<TR>Contienen una fila, dentro de ellos se usan las etiquetas <TH> y <TD>. <TH>...</TH>Contienen un cuadro de encabezado(negrita) dentro de una fila. <TD>...<TD>Contienen un cuadro dentro de una fila.

Figura A.4 Aadiendo tablas

- 155 -

AJAX, fundamentos y aplicaciones

Hiperenlaces: Si queremos redireccionar a otra pgina no tendramos ms que aadir a nuestro ejemplo: <A href=http://www.google.es/>Buen buscador</A> Y aparecer la frase buen buscador resaltada, si pulsamos sobre ella, iramos a la pgina de Google. Mas cosas: Este es el fin de la gua rpida y bsica de HTML, a partir de aqu lo nico necesario es una gua de etiquetas, colores y atributos para seguir aadiendo cosas a nuestra pgina de los perritos, pero no hay conceptos bsicos nuevos. XHTML la respuesta a los puristas Como has visto, en HTML puedes utilizar las etiquetas en mayscula y minscula, incluso aunque te olvidaras de cerrar alguna, no terminara en un fiasco total, debido a que los navegadores actuales se tragan literalmente muchos abusos, debido a esto que ensucia mucho el cdigo y a lenguajes nuevos como XML se creo XHTML. Como ocurre con la lengua oral, el HTML es un lenguaje sencillo que ha terminando usndose muchsimo y debido a esto se ha ido degradando un poco su uso ya que no todos formamos parte de la real academia, XHTML es una forma estricta de escribir HTML ya que esta definido en XML y tiene un documento DTD de validacin. Esta forma de escribir es totalmente compatible con HTML 4.01 ya que se defini a partir de ste, con lo cual, cualquier navegador puede leerlo. Las Diferencias ms importantes entre XHTML Y HTML: 1. Los elementos deben estar correctamente anidados. 2. Los nombres de los tags deben estar en minscula. 3. Los tags deben tener su etiqueta de fin. Ejemplo: AS NO!!! <b><i>Estas cosas funcionan con HTML </B></I> AS SI <b><i>Este es un texto XHTML vlido </i></b> 4. Los documentos deben estar bien formados: Esto significa que cada etiquetas tienen sus sub-etiquetas que pueden usarse dentro de ellas y no fuera o en otra parte del documento como ocurre con los navegadores actuales. Ejemplo: <html> <head> <title> ... </title> ...</head> <body> ... </body> </html> 5. Los tags que eran nicos y no tenan tag de cierre, ahora llevan el smbolo de finalizacin, <br> ahora se escribira como <br /> dejando un espacio entre br y / para que sea compatible con los navegadores actuales. Ejemplo: <IMG src="img/perros.jpg" width=396 height=247 border=12 alt="Perritos graciosos"> //Esto es HTML <img src="img/perros.jpg" width=396 height=247 border=12 alt="Perritos graciosos" /> //Esto es XHTML 6.Los nombres de los atributos deben estar en minscula y su contenido entrecomillado, como en el ejemplo anterior que repetimos. <img src="img/perros.jpg" width=396 height=247 border=12 alt="Perritos graciosos" /> //Esto es XHTML

- 156 -

AJAX, fundamentos y aplicaciones

7. Los atributos ahora se tienen que escribir de la siguiente manera. HTML compact checked declare readonly disabled selected defer ismap nohref noshade nowrap multiple noresize XHTML compact="compact" checked="checked" declare="declare" readonly="readonly" disabled="disabled" selected="selected" defer="defer" ismap="ismap" nohref="nohref" noshade="noshade" nowrap="nowrap" multiple="multiple" noresize="noresize"

8. El atributo id sustituye al atributo name, su utilidad es la misma, darle un nombre al objeto. 9. Se pueden usar los atributos Lang y xml:lang para especificar el lenguaje de un elemento, el atributo xml:lang tiene preferencia. 10. El documento bsico XHTML debe contener la declaracin DOCTIPE obligadamente, de esta forma el documento quedara: <!DOCTYPE ...> <html> <head> <title>... </title> </head> <body> ... </body> </html> 11. Hay 3 tipos de documentos XHTML: 11.1 XHTML 1.0 Estricto
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

Se utiliza cuando queremos un cdigo limpio, con todo lo que hemos estado explicando, para combinarlo con CSS. 11.2 XHTML 1.0 Transicional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">

Se utiliza cuando queremos tomar ventaja de las capacidades de presentacin de HTML y cuando quieres soportar navegadores que no aceptan CSS. 11.3 XHTML 1.0 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1frameset.dtd">

Se utiliza cuando quieres usar frames. 12. Validando nuestra pgina web El Consorcio Word Wide Web tiene la siguiente una pgina web que contiene una aplicacin para validar ya sean pginas XHTML, CSS, etc. y ver que estn correctamente construidas, su direccin es thttp://validator.w3.org/.

- 157 -

AJAX, fundamentos y aplicaciones

Apndice:
XML
Hagamos una pequea introduccin al lenguaje XML para las personas que no lo conocen: XML es un metalenguaje que se usa para definir otro lenguaje o estructura de datos (para lo que nosotros lo usaremos durante el texto), bsicamente es un lenguaje de etiquetado como HTML con sus etiquetas de principio y fin, solo que los nombres de las etiquetas las decidimos nosotros segn nos convenga para crear nuestros formatos, luego podremos recoger el texto que contienen las etiquetas seleccionndolas por su nombre, esto ya se ver durante el texto. biblioteca.xml

<?xml version="1.0" encoding="UTF-8"?> <Biblioteca> <Libro> <ISBN>84-688-4704-6</ISBN> <Titulo>J2ME (Java 2 Micro Edition)</Titulo> <Autor>Sergio Galvez Rojas y Lucas Ortega Diaz</Autor> </Libro> <Libro> <ISBN>84-689-1037-6</ISBN> <Titulo>Traductores y Compiladores con Lex/Yacc, JFlex/Cup y JavaCC</Titulo> <Autor>Sergio Galvez Rojas y Miguel Angel Mora Mata</Autor> </Libro> </Biblioteca>

Como he querido ilustrar aqu, tenemos una biblioteca que contiene libros, y esos libros contienen a su vez ciertos campos, esto es lo que se llama un documento bien formado, es decir, cumple las especificaciones del lenguaje, pero no esta sujeto a un DTD (Definicin tipo documento). Si adems sigue una estructura sujeta a un DTD diremos que el documento es vlido. Esto es ms que nada una gua rpida y prctica, para quien quiera tratarlo con mas profundidad y ver la sintaxis de un DTD le recomiendo que le eche un vistazo a la bibliografa o a las mltiples paginas web que tratan sobre lenguajes orientados a Internet.

- 158 -

AJAX, fundamentos y aplicaciones

Apndice:
Javascript
Antes de nada, estoy suponiendo que el lector sabe programar ya, esto es una gua de Javascript y no te enseara desde 0, Javascript an por su nombre, no es un lenguaje orientado a objetos como java, es un lenguaje orientado a unos objetos, los del navegador y los que creemos (diferentes de java), adems carece de caractersticas importantes como la herencia, se basa en prototipos. Crear un nuevo objeto: Como en cualquier otro lenguaje, no tiene ninguna particularidad especial aparte de que Javascript tiene su sintaxis. var miObjetoPruevas = new constructorObjeto(param01,...,paramN); Crear un nuevo constructor: function constructorObjeto (param01,...,paramN) { this.variable01 = param01; //Las variables creadas con this son pblicas. Var privada01 = Soy privada; //Las variables creadas con var son privadas. ... this.variableN = paramN; this.funcion01 = funcion01; ... this.funcionN = funcionN; var funcionprivada = funcionprivada() { alert(Soy privada);} //Funcin privada } Como ves utilizamos this refirindonos al objeto que estamos creando, le hemos asignado una serie de variables a las que le hemos otorgado los parmetros de creacin del objeto, aunque estos podran ser nulos, y le hemos asignado una serie de funciones que no hemos declarado ni siquiera hemos puesto sus parmetros. Adems aqu no hay control de accesos como en java, no existen mtodos (funciones) o propiedades (variables), declaradas como publicas, privadas y protegidas, si creas un objeto y quieres que algo sea publico o privado debes seguir lo mostrado en el ejemplo de arriba. Asignar un mtodo a un objeto: Si queremos crear una funcin y que est ligada a un objeto desde su creacin sin necesidad de especificarlo durante su creacin, lo mejor es emplear prototipos como se vio en el captulo uno, pero tambin podemos asignar una funcin en cualquier momento al una variable como vemos aqu, esto se usa a lo largo de todo el libro para reasignar los manejadores de la claseAJAX. function funcionX(argumento01,...,argumentoM) { Cdigo de la funcin. } <html> <body> Vamos a hacer un pastel. <script language="JavaScript" type="text/javascript"> function constructorPastel(chocolate,nata,galletas) { this.chocolate = chocolate; this.galletas = galletas; this.nata = nata; this.ingredienteSecreto; this.montarPastel = montar;

- 159 -

AJAX, fundamentos y aplicaciones

} function montar() { window.alert(" Montado el pastel con " + this.ingredienteSecreto + " de ingrediente secreto"); } var pastelSoloChocolate= new constructorPastel(100,0,100); pastelSoloChocolate.ingredienteSecreto = 20; pastelSoloChocolate.montarPastel(); </script> </body> </html>

Figura A3.1 Primer ejemplo de las peculiaridades de Javascript

Abusos permitidos por el lenguaje: Javascript nos permite cosas como emplear variables sin declarar, dentro o fuera de objetos y reasignar funciones a objetos entre otras cosas, estamos por lo tanto ante un lenguaje dbilmente tipado, como muestra el siguiente ejemplo. <html> <body> Vamos a hacer un pastel. <script language="JavaScript" type="text/javascript"> function constructorPastel(chocolate,nata,galletas) { this.chocolate = chocolate; this.galletas = galletas; this.nata = nata; this.ingredienteSecreto; //No hace falta que le asignemos ningn valor. this.montarPastel = montar; } function montar() { window.alert(" Montado el pastel con " + this.ingredienteSecreto + " de ingrediente secreto."); } var pastelSoloChocolate= new constructorPastel(100,0,100); pastelSoloChocolate.ingredienteSecreto = 20; //Abusos que permite el lenguaje con los objetos pastelSoloChocolate.ingredienteRaro = 2000; //Variable no declarada function montarBorde() { window.alert(" Tu pastel esta muy malo, tiene " + this.ingredienteRaro + " de ingrediente raro."); } pastelSoloChocolate.montarPastel = montarBorde; //Reasignar una funcin

- 160 -

AJAX, fundamentos y aplicaciones

pastelSoloChocolate.montarPastel(); //Abusos que permite el lenguaje con las variables ingredienteRaroSinDeclarar = 100; window.alert(" Variable sin declarar con valor " + ingredienteRaroSinDeclarar) </script> </body> </html> Si accedemos a la pgina deberamos obtener el siguiente resultado:

Figura A3.2 Segundo ejemplo de las peculiaridades de Javascript No solo esto que hemos visto, sino adems una variable que en principio empezamos a usar como entero podemos utilizar mas tarde como una cadena, etc. Con esto finalizo las peculiaridades bsicas del Javascript, Si queremos una gua mas amplia podemos encontrarla en la bibliografa.

- 161 -

AJAX, fundamentos y aplicaciones

Bibliografa
Aqu aparecen las referencias a libros y pginas web que se han empleado para desarrollar tanto la documentacin como la aplicacin. Si algo se parece a lo expresado en esta memoria no es casualidad, ya que parte de los ejemplos aqu expuestos estn basados en otros previamente estudiados. El objetivo ha sido utilizar aqullos que ya han sido puestos a prueba y demostrado sus cualidades didcticas y de simplicidad, lo que abunda en un aprendizaje progresivo y fcil.

Libros
Christian Gross Ryan Asleson y Nathaniel T. Schutta Ajax Patterns and Best Practices Foundations of Ajax Ed. Apress, 2006 Ed. Apress, 2006

Pequeos o grandes tutoriales y donde buscarlos


Sang Shin Sergio Glvez Angel Barbero Lola Crdenas Jos C. Garca 10-Week Free AJAX Programming JSP(Java server pages) Tutorial de XML Curso de Javascript Curso de Hojas de Estilo http://www.javapassion.com/ajaxcodecamp/ www.sicuma.uma.es www.lawebdelprogramador.com www.lawebdelprogramador.com www.lawebdelprogramador.com

Webs
W3C W3 Web estilo www.w3schools.com http://www.w3.org/ http://www.webestilo.com/html/

- 162 -

S-ar putea să vă placă și