March, 2006


17
Mar 06

Ajax The Right Way

Tantos proyectos y tan poco tiempo, entre la universidad y el trabajo me queda muy poco tiempo para trabajar con Caleio. Más si tenemos en cuenta que esta semana pasaba re-escribí mi CMS y rediseñé la página. Y por si esto no fuera poco estoy escribiendo un programa bastante importante en C# (no pregunten porque no voy a responder).

El punto es que quería escribir un artículo sobre Ajax. Ultimamente estuve usandolo mucho en el trabajo y con Caleio y me crucé con un problema interesante. La definición de Ajax en inglés es: Asynchronous JavaScript + XML según quien acuño el termino. Notese el XML del finál. Importante ese XML ya que todo el mundo parece ignorarlo… Investigando un poco más en dicha página aparece esta ‘lista’ de tecnologías que se incluyen en el concepto de Ajax:

  • standards-based presentation using XHTML and CSS;
  • dynamic display and interaction using the Document Object Model;
  • data interchange and manipulation using XML and XSLT;
  • asynchronous data retrieval using XMLHttpRequest;
    and JavaScript binding everything together.

Por alguna extraña razón NADIE que yo haya visto hasta ahora usa XML para pasar la información entre el servidor y el cliente. Es más, este problema surgió porque yo no sabía muy bien como hacerlo y buscaba un framework ya escrito para usarlo en Caleio, pero no encontré ninguno! Absolutamente ninguno, y eso que miré en varios. Esto fue antes de navidades así que capaz que la situación cambió pero en cualquier caso el 90% o más de la gente que usa Ajax no usa XML para pasar la información. El método que usa todo el mundo es el de hacer un REQUEST al servidor incluyendo la información en las variables GET o en el caso de lo más osados en las variables POST, a su vez el servidor responde con cachos de HTML que son mostrados en la página por medio de la propiedad innerHTML.

Esto hace que el código quede muy feo, que sea poco portable y limita el uso de la aplicación. Pero lo más importante es que viola totalmente la regla de separación de contenido y presentación. Tanto XHTML y CSS para después hacer esa guarrería :P

Al final conseguí un ‘framework’ bastante ligerito que recibía XML pero no lo enviaba, así que con un poco de manipulación conseguí lo que necesitaba. Es un script muy básico y en realidad no es un framework, lo único que hace es crear el objecto xmlhttprequest y luego enviar y recibir XML. Lo pueden encontrar en la sección de Code » tw-sack.js.

Así que ahí va un pequeño y corto tutorial de como hacerlo bien usando ese script. El ejemplo que usaré será una página que invierta el texto escrito en un input. El enfásis esta en como funcióna Ajax y no tanto en que se puede hacer en el servidor, es muy fácil modificar este ejemplo para que haga cosas mucho más complejas.

HTML + CSS

En primer lugar creamos una simple página HTML y le añadimos unos estilos con CSS. Para nuestro ejemplo solo necesitamos un input, un boton y un div donde mostrar el texto invertido.

<html>
	<head>
		<title>Ejemplo Ajax</title>
	</head>
	<body>
		<form action="#" method="post" onsubmit="return sendText()">
			<label for="texto">Texto:</label>
			<input type="text" id="texto" name="texto" /><br />

			<label for="submit"> </label>
			<input type="submit" id="submit" name="submit" value="Enviar" />
		</form>
		<p id="areaResultado"> </p>
	</body>
</html>

Falta el CSS y la inclusión de los archivos Javascript, pero se pueden dar una idea, nada complicado. Se podría no usar el form y llamar a la función sendText() desde el onClick() del botón, pero hecho así es más facil hacer la aplicacion compatible con los usuarios que no tengan activado Javascript ya que el formulario se ejecutará y ahí podemos hacer que el servidor se haga cargo como normalmente lo hace.

Javascript de ida

Así que el usuario ha apretado el boton y quiere saber como queda su texto al vesre. Creamos una función que saque el valor del campo, lo meta en el XML y lo mande.

function sendText()
{
	texto = document.getElementById('texto').value;

	xml = xml = '<?xml version="1.0" encoding="UTF-8" ?>'+
"<request>"+
	"<texto>""+texto+"</texto>""+
"</request>";

	ajax.object = document.getElementById('areaResultado');
	ajax.onCompletion = recieveText;
	ajax.runAJAX(xml);
}

Acá es donde hay una parte complicada, en la ante-última linea, donde pone ajax.onCompletion = recieveText. Esta parte es necesaria por la forma en que funcióna xmlhttprequest y Javascript. Cuando el script llega a la parte de enviar el XML no espera el resultado, sino que sigue la ejecución, asi que si fueramos a hacer:

	// crear xml
	ajax.runAjax(xml)
	alert(ajax.reponse);

Esto fallaría, porque el proceso de conseguir el resultado es largo y el Javascript no espera. Así que el truco es decirle al script que función queremos que ejecute después de haber conseguido el resultado, en este caso la función es recieveText(). Lo de ajax.object es para ‘guardar’ el objeto donde queremos luego insertar o modificar algo. Esto sirve más cuando a la función la llamamos con un ‘this‘ y navegamos por los nodos cercanos que posiblemente no se puedan o no querramos agarrar con un getElementById().

Pero primero el PHP

Antes de recibir el resultado hay que leer el texto con PHP y darlo vuelta. Cuando por primera vez llegué a esta parte me quede frito, cómo cuernos leo yo el XML en PHP? Y la solución es mucho más simple de lo que parece, yo ya estaba pensando en que iba a tener usar sockets de alguna manera extraña y seguramente depravada, pero no, resulta que la variable $HTTP_RAW_POST_DATA contiene, como bien indica su nombre, todo el contenido POST de manera ‘cruda’, es decir, sin procesar. Asi que leer el valor de texto es cuestion de parsear la variable como XML así:

<?php
	$xml = $HTTP_RAW_POST_DATA;

	$p = new xmlParser;
	$p->read($xml);
	$texto = $p->getTagValue('texto');

	header('Content-Type: text/xml');

	echo
'<'.'?xml version="1.0" encoding="utf-8" ?'.'>'.
'<response>'.
	'<texto>'.strrev($texto);.'</texto>'.
'</response>';
?>

Las lineas 4,5 y 6 hacen uso de una pequeña clase que escribí para parsear XML, es muy básica y la pueden encontrar acá. En cualquier caso, lo único que tienen que saber es que lee el XML y le saca el texto a la primera etiqueta <texto>. Usa principalmente xml_parse_into_struct que convierte el XML en un array, y de ahí en adelante es tan fácil como hacer un loop para buscar etiquetas, atributos y valores. Luego mandamos el header de text/xml, porque sino después xmlhttprequest no crea reponseXML, con lo cual no obtenemos las ventajas del DOM. Y finalmente escupimos el resultado usando strrev() para invertir la cadena.

Vuelta al Javascript

Antes de enviar el XML con Javascript había especificado que función quería que se ejecutase una vez que hubiese terminado de recibir la respuesta del servidor. Así que llegamos al paso final, leer el XML, sacar el valor de la cadena invertida y meterlo en #areaResultado.

function recieveText()
{
	xml = ajax.responseXML;
	texto = xml.getElementsByTagName('texto')[0].childNodes[0].data;

	ajax.object.innerHTML = texto;
}

Otra simple función, si es que esto del Ajax esta tirao. Primero agarramos el XML que nos devolvío el servidor, como ajax esta declarado como global podemos acceder desde cualquier función. Luego navegar por el árbol de XML es igual que hacerlo por el de HTML, solo que hay que añadir algunas cosillas más para llegar a la información, y finalmente asignamos el texto al innerHTML de #areaResultado que se asignó a ajax.object antes de enviar el XML. Era por mostrar esa funciónalidad nada más, tranquilamente podriamos esquivar ese paso y hacer el getElementById() en esta función.

<voz-del-flaco-de-bricolaje>
ya veis chavales, aqui tenemos nuestro propio sistemita Ajax, recordemos los pasos que hemos seguido:
</voz>

  1. Escribimos el HTML y añadimos la acción que llamará al Javascript
  2. Escribimos la primera función Javascript que envía el XML
  3. Escribimos el script PHP que procesa el XML y devuelve más XML
  4. Y finalmente escribimos la segunda función Javascript que nos permite leer el resultado y mostrarlo en el HTML

Es verdaderamente fácil una vez que uno se acostumbrar, pero para ayudar construí una demo con todos los archivos de este ejemplo. Que disfruten, y al próximo que vea que recibe HTML y lo mete asi nomás con innerHTML…


15
Mar 06

Londres – Feb 2006

Vuelto he de Londres y si tuviese que resumir el viaje en dos palabras estas serían frio y caminar. A quien ose aventurarse a la cápital del ‘Imperio de los Horteras’ en estas fechas le pongo de sobreaviso: llevese abrigo. Mucho abrigo. No porque haga mucho frio, sino que porque al estar caminando y estando afuera mucho tiempo el frio se siente mucho más. Tanto así que no era raro el último día verme viajando en metro el andergraun con gorro, guantes y bufanda.

En Londres me encontré el Viernes a las 2 con mi amigo David y sus dos amigos que también venian, Pablo y Miguel. Muy buena gente, entre discusiones sobre .NET 3.0, el efecto del vagón de metro sobre las corrientes de aire y algorítmos genéticos tuvimos tiempo de ver casi todas las cosas interesantes de Londres en esos 4 días.

Tristemente mi camara murió el segundo día, se me cayó de un segundo piso cuando estaba abierta y correctamente siguiendo las escrituras de un tal Murphy le pego al suelo justo con el lente. Es una camara muy fuerte, si hubiese aterrizado con el costado u otro lado seguro que hubiese sobrevivido con algún golpe minimo, pero no, tenía que caer justo con el lente ¬_¬. Por suerte pude rescatar las fotos de la tarjeta de memoria y los otros chicos también llevaban camaras, así que cuando me manden sus fotos termino de completar los enlaces.

Museos

El segundo día visitamos el Natural History Museum y el Science Museum, el tercer día fuimos a ver el British Musuem y el National Gallery, y el cuarto estuvimos en el Imperial War Museum. A mi me recomendaron también el Victoria and Albert Museum pero ese no tuvimos tiempo de ver. En el Natural History Museum pasamos demasiado tiempo, es un museo de naturaleza normalito, tiene algunos esqueletos de bicharracos bastante interesante, pero nada del otro mundo. ¿Lo más interesante? Los espejos distorsionadores.

El Science Museum es uno de los altamente recomendables, mucho más interesante (al menos para un geek ;-) que el de historia natural. Tiene una zona de aeronautica con modelos (casi?) reales de aviones, un motor Rolls Royce de avión de linea, un Harrier y una ‘tajada’ de un 747. Una zona de la historia de la tecnología que es un pasillo ordenado cronológicamente que incluye cualquier cosa relacionada con la tecnología, aviones, coches, un motor de diferencia, supercomputadores Cray, estructuras de ADN, una computadora para la muerta asistida (eutanasia), modelos de cosas raras y muchísimo más. No es un museo demasiado grande pero es recomendable ir con tiempo :-).

El British Musuem es un clásico, nosotros fuimos porque pensabamos que ahí estaba Tutankhamon (resulta que está en otro museo). Al final nos tuvimos que conformar con la piedra Rosetta. En este pasamos poco tiempo porque teníamos poco tiempo y tampoco nos interesaba tanto. Al contrario que con el museo de historia natural este no estaba lleno de réplicas, los ingleses a falta de historia propia se la robaron al resto del mundo :-D.

El National Gallery al parecer también es un clásico, en frente de Trafalgar Square es uno de los museos de cuadros más famosos. Entramos un rato para pasar el rato pero poco más. Un ‘must see’ para cualquier interesado en el arte ya que tiene bastantes obras importantes de muchos pintores internacionales.

El Imperial War Museum fué el último que visitamos y en mi opinión esta empatado con el Science Museum en cuanto a cálidad. Tristemente como fué el último que visitamos no tuvimos tiempo de verlo todo porque llegamos dos horas antes de que cerrase. Es un museo principalmente dedicado a todas las guerras en las que se ha visto involucrado el ‘British Empire’. En la entrada tiene modelos de verdad de todo tipo de cosas de guerra, cohetes V2, cazas Spitfire, tanques variados, una réplica de la bomba de Hiroshima ‘Little Boy’ y otros objetos miscelaneos. Ahí solo nos tiramos una hora y es una salita chiquita comparada al resto del museo. También tuvimos tiempo de ver mitad del sotano, la sección de la Segunda Guerra Mundial y otros conflictos desde WWII (el de las Malvinas, Vietnam, Suez, etc). Lo increible de este museo es que no hay casi réplicas, tiene cachos del muro de Berlin originales, el aguila que estaba encima del Reichstag durante WWII y casi todos los vehículos y armas son de verdad, muchos de ellos con marcas de bala o projectiles de tanque. En resumén, otro museo obligatorio.

Edificios/lugares emblemáticos

Visitamos el Big Ben, Picadilly Circus, Covent Garden, Buckingham Palace, London Eye, la torre de homenaje al incendio de 1666, Soho, Tower Bridge, Trafalgar Square, Tower of London, Westminster Abbey, catedral de San Pablo, Chelsea y Notting Hill. Nada destacable de lo habitual, lindos lugares que hay que ver al visitar Londres. Mejor ver las fotos cuando estén.

En fin, que lo de caminar fue mortal, a pesar del uso intensivo del underground nos pegamos una paliza de campeonato. El último día la idea de sentarnos en la linea circular y dar vueltas hasta que fuese hora de irnos era muy tentadora. El ‘Avalon Hotel‘ donde nos quedamos no estaba mal, desayuno incluido, duchas unisex, el cuarto estaba un poco frio pero al alquilar un cuarto para cuatro nos salió relativamente barato.

Sobre el dinero: LONDRES ES CARO. Eso tiene que quedar claro, damos gracias que todos los museos eran gratis, que sino nos ibamos a tener que vendernos a la noche para pagar el viaje. Ahí van algunos precios:

1 Libra = 1.45 Euros = 1.74 Dolares

  • El underground cuesta 4,90 un pasaje para todo el día aunque si se compra muy temprano puede salir 6.
  • En un bar me cobraron 3,5 una botella de 33cl de cerveza marca pistola.
  • En otros bares nos quisieron cobrar 8 libras la entrada.
  • Un menu normal en un fastfood sale más o menos 4 libras.
  • Una noche en el hotel con un cuarto de cuatro sale 65 libras (16/persona).
  • El London Dungeon costaba 15 libras (JA! los va a pagar su madre, encima había una cola larguísima para entrar)

El viaje me salió más o menos 120 libras – (50 del hospedaje + 20 del underground (4.90*4)) = 50 libras de gasto para comida y bebida porque como soy un tacaño miserable regalos no compré, 12.5 por día es bastante barato. Eso si, nosotros fuimos en modo ahorro máximo, comprando pan, queso y jamón en los supermercados para hacernos sandwiches en la calle. Con lo cual aunque Londres sea caro se puede ir y hacer mucho por un precio relativamente bajo.

Buen viaje, habrá que repetir y tendré que volver a Londres para terminar de ver el Imperial War Museum.


8
Mar 06

Londres, here I come!

Con motivo de la venida de unos locos de Sevilla, entre ellos el chico con el que compartí departamento durante el verano, me voy a Londres del Jueves al Domingo. Habra fiesta, un poco de turismo, más fiesta, frio, todavía más fiesta y muchas fotos (espero). Ya veremos cuando vuelva. No me rompan el chiringuito :P


4
Mar 06

Debugging Javascript

Me saca de quicio que la gente que diseña y escribe programas pongan funcionalidad extra que no se puede desactivar. Como por ejemplo la consola de Javascript de Firefox, antes era la ‘Javascript Console’ y solo mostraba errores de Javascript, pero ahora con la versión 1.5 se llama ‘Error Console’ y también muestra los errores de CSS. Porque alguien querría ver los errores de CSS me supera, especialmente teniendo en cuenta la cantidad de hacks que hay que usar hoy en día para que quede todo igual en todos los navegadores, lo único que hace es que la consola se inunde de errores que no importan o que son a propósito. Esto no sería tan malo si se pudiese desactivar… pero no, al menos yo no encontre la manera de hacerlo. Asi que buscando en Google me encuentro con una extensión llamada Console² que permite seleccionar el nivel de error (Error, Warning, Message), que tipo de error (JS, CSS, XML) y donde (Chrome, Content).

Pero lo que más me gusto de esa página fue la pequeña funcion que aparece abajo:

function debug(aMsg) {
   setTimeout(function() { throw new Error("[debug] " + aMsg); }, 0);
}

Esta función permite tirar errores sin que para la ejecución del script y los muestra en la consola como Messages. Es especialmente útil para Ajax, ya que permite seguir el funcionamiento del script por todos sus pasos y ver la información de las variables. Buenísima la extensión y la función, totalmente indispensable para trabajar con Javascript. Si yo tuviese que escribir Javascript y solo pudiese usar IE me pegaba un tiro.

console2


3
Mar 06

Ya era hora

Inspirado por el reciente cambio de Microsiervos yo también decidí rediseñar. La pimera razón es que llevaba mucho tiempo con el diseño viejo por falta de tiempo, la segunda es que mi CMS estaba hecho un asco. Había probado usar Smarty para los templates pero no me gustó nada, y agregar cualquier página por más nimia que fuera era mucho más complicado de lo que debería ser.

Usé parte de la estructura MVC de Caleio para el weblog y el resto de las secciones son casi totalmente HTML estático (a excepción de un header y footer incluido por PHP).

Esta todo casi terminado, me falta por agregar el formulario de contacto, agregar algunas cosas al panel de control y pasar todas las traducciones al wiki. El enlace de las traducciones desapareció, pero ellas siguen ahí.

Espero que guste, y si alguien ve o nota algún problema que me lo haga saber a hermann.kaser@gmail.com (a falta de formulario de contacto…)

Por cierto, a que no adivinan a quién le robé el diseño del formulario de comentarios? :P