E4X, Javascript y XML

noviembre 13, 2010

Hace un tiempo, acceder a documentos XML era perfectamnete posible, pero había que pasar por APIs que quizás no eran todo lo sencillas que deberían ser.

Las dos principales APIs que nos servían para procesar un documento XML eran DOM y SAX. Los nombres describían la forma de acceder al documento, mientras que en DOM se cargaba todo el documento en memoria, y podiamos acceder de una forma más sencilla, en SAX registrabamos una serie de “callbacks” a los que se nos iba llamando segun se procesaba el documento.

Sin duda DOM era mas sencilla desde el punto de vista del uso, pero menos eficiente, si nuestro documento era muy grande, necesitabamos tenerlo completamente en memoria. Por su lado SAX era más eficiente, pero la forma de desarrollar con él era bastante incomoda, ya que teniamos que separar nuestro código en multiples funciones de callback y nosotros teniamos que ser responsables de mantener el estado entre las diferentes llamadas.

Sin duda, hoy en día XML es el lenguaje de intercambio de datos más extendido (ya veremos en unos pocos años si esto sigue siendo así). Y sobre todo teniendo en cuenta que en el entorno del navegador, usar XML suele (o solía) ser común para intercambiar datos usando AJAX.

Debido a todo esto, poco a poco los lenguajes han ido incorporando mecanismos cada vez más comodos para procesar los documentos XML, como por ejemplo en Java JAXP . En este caso vamos a hablar sobre E4X, o la extensión de ECMAScript para el procesado de documentos XML.

Tratar un documento XML con esta extensión es sumamente sencillo, de hecho, el propio código habla por si mismo.

var library = <library postalcode="28000">
<books>
<book id="1">
  <title>Book Title 1</title>
  <author>Author of Book 1</author>
</book>
<book id="2">
  <title>Book Title 2</title>
  <author>Other Author of Book 2</author>
</book>
</books>
<magazines>
<magazine id="1">
<title>Magazine title 1</title>
</magazine>
</magazines>
</library>

alert(library.books.book[0].title); // Book Title 1
alert(library.books.book.(@id == "2").author); // Other Author of Book 2

Como veis, el procesado de un documento XML se simplifica de una manera dramática. Al mapear un documento XML a un objeto, su forma de acceso es practicamente similar a como lo haríamos con dicha estructura de datos.

La sintaxis de acceso al documento nos recuerda en cierta manera a XPath, pudiendo hacer cosas como:

alert(library.books..*.length()) 
	// El operador .. accede a todos los hijos.
alert(library.magazines.magazine[0].@id) 
	// Usando el operador @ accedemos a los atributos
alert(library.books.book.(@id == "2").author); 
	// Podemos filtrar por el valor de los atributos

Además de ayudar a procesar un documento, tambien tenemos facilidad para generar XML, si “encerramos” una expresion entre {}, se sustituirá por su valor, o incluso usando el operador +, añadiremos nuevos elementos al documento.

var b = "book"
var xmlDoc = <{b}><title>The Title</title></{b}>
alert(xmlDoc.toXMLString())

library.books.book += <book id="3"><title>....</book>

Después de ver todo lo que E4X puede hacer por nosotros, ahora contaremos la parte mala :).

Actúalmente, solo esta soportado en productos de Mozilla, esto es, Firefox, Thunderbird o Rhino, además de ActionScript, pero no se puede utilizar en Chrome, Safari o Internet Explorer. Y, ¿Por qué sucede esto?, pues básicamente por que los desarrolladores de los navegadores no consideran que sea necesaria esta implementación, ya que consideran que el acceso estandar usando DOM en Javascript es lo suficientemente versatil como para no necesitar nada más. Además, librerías como JQuery tienen extensiones para manejar documentos XML.

En cualquier caso, al ser un estandar nos garantizamos que si algun día deciden incorporar E4X en los navegadores actúalmente no soportados, funcionará de forma identica a la que lo hace ahora mismo en Firefox o incluso en ActionScript.

Anuncios

Aplicación de escritorio usando Javascript

noviembre 1, 2010

El otro día me preguntaba si seria posible hacer una aplicación de escritorio usando Javascript. Como sabemos, Javascript es uno de los lenguajes que mas peso ha tenido en los últimos años, y que ha tenido que sufrir la guerra de navegadores e implementaciones a la que hemos sido testigos recientemente.

Sin embargo, Javascript es un lenguaje fascinante, con aspectos muy avanzados y que poco a poco ha ido añadiendo cosas cada vez mas interesantes, como por ejemplo sus interesantes mecanismos de introspección y ejecución de código de forma dinámica.

Pero, en esta entrada nos vamos a centrar en como hacer una aplicación de escritorio usando Javascript, cosa que seguramente no sea muy habitual.

Para ello, nos vamos a valer de la plataforma con la que mas se confunde Javascript y que nada tiene que ver, si, estamos hablando de Java. Aun recuerdo las noches que pasaba por el IRC, mas concretamente en el canal #java, la cantidad de gente que entraba a preguntar cosas sobre javascript era tremenda. Lo cierto es que el nombre no ayuda, y la confusión es bastante probable.

Aunque hay varias opciones, he elegido Java como opción ya que aporta varias cosas importantes, por un lado es su gran librería gráfica Swing, que esta integrada en la plataforma, por otro lado su característica mas destacable, la multiplaformidad, lo mismo se ejecuta en Linux, OSX o Windows. Estas dos cosas son ventajas en su mismas de Java, lo que actúa como nexo de unión es Rhino (http://www.mozilla.org/rhino/).

Rhino es una librería hecha por mozilla, que permite integrar Javascript totalmente en la plataforma de Java. Lo cierto es que Rhino esta integrado desde la versión 1.6 dentro de Java, por lo que si queremos interpretar código javascript en Java, no necesitamos nada mas que la propia JDK, sin embargo, en el paquete de rhino, aparte de la librería, viene un interprete interactivo de javascript que es bastante útil.

Lo cierto es que gracias a la integración entre Java y Javascript, hacer una aplicación de escritorio es bastante sencillo. Si por ejemplo ejecutamos el siguiente programa:

var frame = new javax.swing.JFrame();
frame.setSize(200,200);
frame.setVisible(true);
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);

Usando el interprete de rhino:

java -jar js.jar prueba.js

Obtendremos, como esperamos, una ventana vacía.

Como vemos, este método es sencillo y bastante potente para realizar prototipos, ya que podemos probar cualquier código java, usando las comodidades de Javascript y quitandonos el paso de la compilación.

Incluso, podremos usar la consola interactiva de Javascript, para ir modificando la interfaz poco a poco, e ir viendo los cambios sobre la marcha.

Sin duda, uno de los beneficios de Javascript que aprovechamos en esta forma de interactuar con swing son la posibilidad de definir una función en la llamada que añade los listeners a los controles. Así por ejemplo, si tenemos un botón, podemos definir el código controlador que se lanza al pulsarlo, en la propia llamada al método addActionListener.

Como en el siguiente código:

function main() {
	var frame = new javax.swing.JFrame();
	frame.setSize(200,200);
	frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
	
	var button = new javax.swing.JButton("Push Me!");
	var label = new javax.swing.JLabel("JLabel");
	var panel = new javax.swing.JPanel();
	
	button.addActionListener(function() {
		label.setText("Pressed!")
	});
	
	panel.add(button);
	panel.add(label);
	
	frame.getContentPane().add(panel);
	
	frame.setVisible(true);
}

Después de ver todo esto, queda respondida la duda que iniciaba el post. Si, se pueden hacer aplicaciones de escritorio usando Javascript, claro que con la inestimable ayuda de Java y Rhino 🙂


HTML5 y Bases de Datos locales

octubre 16, 2010

Otra de las grandes novedades de HTML5 es las nuevas alternativas respecto a la forma de guardar información en el cliente por parte de una web. Hasta ahora, la única alternativa que se tenia desde una web era usar cookies. HTML5 introduce tres nuevas formas, “local” y “session” storage y por otro lado la posibilidad de manejar toda una base de datos relacional que reside en cada cliente. A diferencia del localstorage o sessionstorage, que son mas similares a las cookies, el hecho de manejar una base de datos totalmente funcional es una novedad bastante importante que puede ayudar a nuestras webs a guardar información de una forma mucho mas estructurada.

Como hemos dicho, la base de datos es de tipo relacional, por lo que el lenguaje para “hablar” con ella será enteramente SQL.

Aunque expresamente la W3 desaconseja ligar el estándar a una implementación concreta, en la practica, prácticamente la totalidad de navegadores han usado SQL lite para implementar la gestión de la base de datos.

Como sabemos, no el SQL que entiende todas las bases de datos es igual, existen lo que se denominan “dialectos”, debido a que SQL lite es casi la opción “de-facto” podremos usar el “dialecto” del SQL lite en las sentencias. Aunque, al igual que el estándar desaconsejaba ligarse a una implementación, no es buena idea ligar el código a un dialecto, pues puede ser que en algún momento uno de los navegadores decida utilizar otro “backend” de bases de datos, y haga nuestro código incompatible. Lo ideal es usar, en la medida de lo posible, el SQL mas cercano al estándar.

Pese a todo esto, de momento y hasta que no se plantee una implementación independiente, el estándar de HTML5 respecto al “WebSQL” apunta a que el dialecto a seguir es del SQL lite.

Pasando ya a como usar la base de datos desde javascript, el primer paso es obtener una referencia a la base de datos para poder operar con ella. Para ello usaremos la función openDatabase() donde le pasaremos, el nombre de la base de datos, la versión del esquema y el tamaño estimado.

Una vez tenemos la referencia de la base de datos, vamos a ver que, prácticamente la totalidad de los métodos son asíncronos, por lo que típicamente los argumentos serán callbacks. En este caso Javascript sale a nuestra ayuda, como seguramente sabremos, en Javascript podemos encapsular en una variable la declaración de una función, por lo que la forma mas común de pasar los parámetros a las funciones que operan en la base de datos es incluir la declaración de los propios callbacks, ya que habitualmente, no será muy útil reutilizar dichos callbacks.

Las dos funciones más usadas sin duda van a ser “transaction” y “executeSql”, con la primera crearemos una transacción que se ejecutará contra la base de datos de forma atómica (bueno, esa es la definición de transacción, no?), mientras que con la segunda, como su nombre indica ejecutaremos las propias sentencias sql.

A continuación veremos un simple ejemplo en el que creamos una base de datos de usuarios en el cliente, donde guardamos cosas como su nombre de usuario o password.

<html>
<head>
<script type="text/javascript">
    var db;
    function init() {
        db = openDatabase("DB Prueba", "0.1", "Database Prueba", 200000);
        if (db) {
            // Database opened
			db.transaction( function(tx) {
				tx.executeSql("CREATE TABLE IF NOT EXISTS usuarios(userid integer primary key autoincrement, username text, password text)")
			});
        }

		listUsers();

    }

	function showUsers(users) {
		var place = document.getElementById("usersDiv");
		if (place.getElementsByTagName("ul").length > 0 )
			place.removeChild(place.getElementsByTagName("ul")[0]);
		var list = document.createElement("ul");

		for ( var i = 0; i < users.length; i++) {
			var item = document.createElement("li");
			item.innerHTML += "<b>userId:</b>" + users[i][0] + " <b>userName:</b>"
					+ users[i][1] + " <b>password:</b>" + users[i][2] +
					"<button onclick='removeUser("+ users[i][0]+")'>Remove</button>";
			list.appendChild(item);
		}
		place.appendChild(list);
	}

	function listUsers() {
		db.transaction( function(tx) {
			tx.executeSql("SELECT * FROM usuarios", [],
				function(tx, result){
					var output = [];
					for(var i=0; i < result.rows.length; i++) {
						output.push([result.rows.item(i)['userid'],
								result.rows.item(i)['username'],
								result.rows.item(i)['password']]);
					}

					showUsers(output);

				});
		});
	}

	function addUser(username, password) {
		db.transaction( function(tx) {
			tx.executeSql("INSERT INTO usuarios(username, password) VALUES(?,?)", [username, password]);
		});
		listUsers();
	}

	function removeUser(userId) {
		db.transaction(function(tx) {
			tx.executeSql("DELETE FROM usuarios WHERE userId=?",[userId], listUsers);
		})
	}
</script>
</head>
<body onload="init()">
<div id="usersDiv">
	Usuarios en local
</div>
<div id="newuser">
	Crear nuevo usuario<br/>
	Usuario: <input type="text" id="username"/><br/>
	Password: <input type="password" id="password"/><br/>
	<button onclick="addUser(username.value, password.value)">Add User</button>
</div>
</body>

</html>

Desde luego es una gozada que sea tan sencillo trabajar con una base de datos de una forma tan sencilla 🙂

Además, tenemos que sumarle la gran calidad de las herramientas de depuración que nos aportan los navegadores, en la captura que encabeza la entrada podemos ver la que tiene Safari. Si somos usuarios de chrome veremos que la ventana es idéntica, esto es por que Chrome al igual que Safari se basa en webkit.

Después de leer el post, podemos sacar la conclusión de que es muy sencillo operar con bases de datos en cliente, y es totalmente cierto, pero ahora hay que pensar bien cuando esta opción es la mejor y cuando los datos solo se guardan en el servidor.


Juego de la Vida en un canvas de HTML5

septiembre 13, 2010

Poco a poco HTML5 va tomando forma, lo que hace un tiempo era poco mas que un proyecto de estandar, hoy en día ya es una realidad en la mayoría de los navegadores.

Si usamos Safari, Firefox o Chrome ya somos capaces de disfrutar de la mayoría de las ventajas que el nuevo estandar nos propone.

Una de las grandes mejoras es la habilidad para ponder “pintar” en una zona especialmente diseñada para ello. Dicha zona se conoce como “canvas” y vamos a poder utilizarla como si de cualquier otro contexto gráfico se tratara.

Seguramente pensareis que esto no es tan gran novedad, esto ya se podia hacer antes con cosas como Flash o Applets de Java, pero el canvas de HTML5 va un paso mas adelante.

Sin duda la principal novedad de dicho canvas no es tanto el que nos permita dibujar en el navegador sino que es que es propio navegador quien decide como tratar esa zona. A diferencia de la aproximación de flash o java donde era necesario un plugin en comunicación con el navegador.

Este cambio supone un salto drástico en el rendimiento de este tipo de aplicaciones. Seguro que si habéis usado flash o applets java os habréis dado cuenta lo exigente que era para las cosas que mostraban por pantalla. Sin embargo, con el canvas y una buena implementación por parte del navegador, no solo este rendimiento será mejor, sino que además podremos usar cosas como la acceleración nativa 3D.

Además, la ausencia de la necesidad de plugins facilita enormemente la labor de porting a otras plataformas, si el navegador soporta HTML5, no se necesitará nada mas.

Y para terminar con las ventajas, estamos hablando de un estándar, libre de patentes, no controlado por ninguna empresa y con los requerimientos totalmente abiertos. Cualquiera puede implementar un navegador HTML5 sin tener que pagar nada a nadie.

Se me nota entusiasmado, ¿no? :). Creo que es para estarlo, pues la web es uno de los medios de comunicacion mas importante hoy en día, y el hecho de estandarizar algo tan común en la web como son estas aplicaciones es para estar de enhorabuena.

Pues bien, investigando un poco en como se usa el canvas de HTML5, me vino a la mente lo fácil que sería hacer un simulador del famoso “juego” “Juego de la Vida” de Conway.

El juego de la vida, es como se define en la wikipedia, un juego de 0 jugadores. ¿Un Juego sin jugadores? :), básicamente diseñamos una situación inicial y lo único que hacemos es ver como evoluciona la población de células que forman el juego.

El juego está formado por un conjunto de células, representadas por un punto, si la célula esta viva, se pintará de color verde, y si la célula esta muerta, no se pintará. Según ciertas condiciones dependientes del numero de vecinos, cada célula vivirá, morirá o nacerá en la siguiente generación. La implementación es muy sencilla y al igual que con la entrada anterior sobre Mandelbrot, los resultados son bastante interesantes y sin duda algunos patrones de evolución son bastante vistosos.

Aconsejo echar un vistazo a la entrada de la wikipedia para saber un poco más en que consiste el juego.

Hablando de la implementación, pintar en el canvas de HTML5 es bastante sencillo, básicamente, se reduce a 3 lineas

// ...
var context = canvas.getContext("2d");
context.fillStyle = "rgb(100,0,100)";
context.fillRect(10,10, 100, 100);
// ...

Con esas 3 líneas dibujamos un cuadrado en la posicion 10, 10 del canvas. De hecho una vez que obtenemos el contexto, podemos hacer las típicas operaciones, como dibujar cuadrados, arcos, rutas o imagenes.

Para mas detalles, os aconsejo que visiteis el sitio de desarrolladores de mozilla, donde tienen un fantastico tutorial de lo que se puede hacer con el canvas: https://developer.mozilla.org/en/Canvas_tutorial

Finalmente, os dejo con el código fuente de una implementación sencilla del juego de la vida y que como no puedo incrustar en este post de wordpress, podeis ver aquí

<html>
<head>
	<script type="text/javascript">
		var cellSize=10;
		var hcells = 70;
		var vcells = 40;
		var board;
		var canvas;
		var context; 
		var timerId = undefined;
		
		function drawShapeInBoard()
		{
			// Draw Some shapes in the board
			
			board[10][10] = board[12][10] = board[12][9] = board[14][8] = board[14][7] = board[14][6] = board[16][7] = board[16][6] = board[16][5] = board[16][6] = 1;
			
			board[25][30] = board[26][30] = board[27][30]  = board[28][30] = board[29][30] = board[29][30] = board[30][30] = board[31][30] = board[33][30] = board[34][30] = board[35][30] = board[29][30] = 1;
		}
		
		function initGame() {
			canvas = document.getElementById("gameoflife");
			context = canvas.getContext("2d");		
			canvas.addEventListener("click", onCanvasClick, false);	
			initBoard();
			drawShapeInBoard();
			drawBoard();
		}
		
		function onMouseMove(evt) {
			context.fillStyle = "rgb(200,200,200)"			
			context.fillRect(evt.clientX - canvas.offsetLeft, evt.clientY - canvas.offsetTop, cellSize, cellSize);
		}
		
		function onCanvasClick(evt) {
			var x = evt.clientX - canvas.offsetLeft;
			var y = evt.clientY - canvas.offsetTop;
			var boardX = parseInt(x / cellSize);
			var boardY = parseInt(y / cellSize);
			if ( isAlive(boardX, boardY) ) board[boardX][boardY] = 0
			else board[boardX][boardY] = 1;
			
			drawBoard();
		}
		
		function initBoard() {
			board = [];
			for ( i = 0; i < hcells; i++) {
				board[i] = [];
				for ( j = 0; j < vcells; j++ ) {
					board[i][j] = 0;
				}
			}
		}
		
		function drawBoard() {
			for ( i = 0; i < hcells; i++) {
				for ( j = 0; j < vcells; j++ ) {
					if ( board[i][j] == 0){
						context.fillStyle = "rgb(180,180,180)";
					} else {
						context.fillStyle = "rgb(0,170,0)";
					}					
					context.fillRect(i*cellSize, j*cellSize, cellSize, cellSize);					
				}
			}
		}
		
		function isAlive(x,y) {
			if ( board[x] ) 
				if ( board[x][y] == 1) return true;
			return false;
		}
		
		function numberOfNeighbours(x, y) {
			var count = 0;
			if ( isAlive(x-1, y   ) ) count++;
			if ( isAlive(x-1, y-1 ) ) count++;
			if ( isAlive(x-1, y+1 ) ) count++;
			if ( isAlive(x  , y-1 ) ) count++;
			if ( isAlive(x  , y+1 ) ) count++;
			if ( isAlive(x+1, y-1 ) ) count++;
			if ( isAlive(x+1, y+1 ) ) count++;
			if ( isAlive(x+1, y ) ) count++;
			
			return count;
		}
		
		function nextStep() {
			var newBoard = [];
			for ( i = 0; i < hcells; i++) {
				newBoard[i] = [];
				for ( j = 0; j < vcells; j++ ) {
					var neighbours = numberOfNeighbours(i, j);
					if ( isAlive(i,j) && neighbours < 2) newBoard[i][j] = 0;
					else if ( isAlive(i,j) && neighbours > 3 ) newBoard[i][j] = 0;
					else if ( isAlive(i,j) && (neighbours == 2 || neighbours == 3) ) newBoard[i][j] = 1;
					else if ( !isAlive(i,j) && (neighbours == 3) ) newBoard[i][j] = 1;
					else newBoard[i][j] = 0;
				}
			}
			board = newBoard;
		}
		
		function computeNS() {
			nextStep();
			drawBoard();
		}
		
		function startNS() {
			if ( ! timerId) {
				timerId = setInterval("computeNS()", 150);
				var status = document.getElementById("status");
				status.innerHTML = "<b>Running</b>";
			}
		}
		
		function stopNS() {
			clearInterval(timerId);
			timerId = undefined;
			var status = document.getElementById("status");
			status.innerHTML = "<b>Stopped</b>";
		}
		
		function clearBoard() {
			initBoard();
			drawBoard();
		}
		
	</script>
</head>
<body onload="initGame()">
	<p align="center">
		The Game of Life
	</p>
	<p align="center">
		<canvas id="gameoflife" width="700" height="400" border="1"></canvas>
		<br/>
		<button onclick="computeNS()">Next Step</button>
		<button onclick="startNS()">Start</button>
		<button onclick="stopNS()">Stop</button>
		<button onclick="clearBoard()">Clear</button>
		<br/>
		<span id="status"><b>Stopped</b></span>
	</p>
</body>	
</html>

Dashcode, como hacer widgets para OSX

diciembre 20, 2009

Cuando hablamos sobre desarrollo en OSX, raudo y veloz aparece en nuestra mente el nombre de XCode. Si bien es cierto que es la herramienta de referencia ( Sin olvidarnos de Interface Builder, claro), hay otra alternativa para desarrollar software en OSX.

Esta otra manera es mas o menos reciente, y la aplicación que nos va ayudar a crearla se llama Dashcode. La primera versión del sistema operativo de apple en el que podemos usar esta herramienta es en Leopard 10.5, y forma parte del grupo de herramientas para desarrolladores. Actualmente se puede usar Dashcode tanto para crear widgets para el Dashboard como para crear webs personalizadas para el iPhone. Este último dato es lo que lo convierte en una alternativa para desarrollar aplicaciones para el smartphone de apple.

Esta aproximación al desarrollo de aplicaciones para el iPhone tiene como gran punto negativo las limitaciones que impone el que realmente estas desarrollando una aplicacion web, pero pero como puntos positivos tiene el hecho de que no hace falta comprar ninguna licencia para desarrollar, y que la dificultad de desarrollo con respecto a la programación de aplicaciones nativas es bastante mas asequible.

Uno de los aspectos que hacen el desarrollo más sencillo es el lenguaje escogido para desarrollar dichas aplicaciones. HTML + Javascript hacen las veces de Objective-C en Dashcode, nuestros widgets realmente se pueden asemejar a porciones de páginas web. Aún así esta eleccion no nos debe hacer pensar que estamos limitando las posibilidades, pues en el caso de los widgets para el dashboard podremos usar mucha de la funcionalidad que tambien podemos acceder desde una aplicación Cocoa, ya que desde javascript podemos acceder a estos modulos mas cercanos al Sistema Operativo.

Para muestra, un boton, en el siguiente enlace podreis ver algunos de los widgets actuales para dashcode.

Junto con Dashcode se incorpora un montón de componentes “prefabricados” como listas, botones, paneles, que podemos usar en el desarrollo de nuestros widgets.

El propio IDE también nos facilita mucho el trabajo, sin tener mucha idea de como funciona todo podemos realizar ejemplo sencillo en cuestion de minutos. Estas ayudas se traducen en autocompleting de Javascript y HTML, edición gráfica de los widgets, y debugger incluido.

Aunque tampoco debemos dejarnos engañar, como con casi todo, manejar a fondo los componentes ( llamados “parts” ) que se pueden insertar en los widgets lleva su tiempo de aprendizaje.

En general podemos concluir que siendo consciente de sus limitaciones, es una gran alternativa al desarrollo tradicional de aplicaciones.


Navegadores y futuro de las aplicaciones web

diciembre 3, 2009

Poco a poco nos estamos dando cuenta que el futuro de las aplicaciones apuntan a “la nube”. Google ha apostado por ello con cosas como GMail, Wave o el reciente Chrome OS. Como elemento imprescindible en esta migración, estan los navegadores, los “vehiculos” hacia la nube. Pero, ¿están preparados los navegadores para esta migración?

Cuando la web empezo a ser web, nadie se podía plantear que de aquel lenguaje de marcado derivado del SGML como era el HTML se podría crear todo una plataforma de desarrollo de aplicaciones. Para que esto fuera posible se incorporó un lenguaje que dotara de dinamismo a las, por aquel entonces novedosas, paginas webs. Estamos hablando de ECMAScript, mas conocido con el “desafortunado” nombre Javascript. Desafortunado por su parecido con Java, del que no tiene nada que ver.

Indudablemente se podría hablar mucho de Javascript, como por ejemplo de las primeras implementaciones en los navegadores, de JScript, de su caprichosa sintaxis, etc., pero este, no es el objetivo de esta entrada 😉

Javascript ha sido uno de los grandes “culpables” de que hoy contemplemos como futuro las nuevas aplicaciones web, sin embargo, también ha sido el culpable de muchos quebraderos de cabeza para los desarrolladores de navegadores. Dichos navegadores llevan intentando optimizar el motor que se encarga de interpretar el Javascript desde hace mucho tiempo, sin embargo el desarrollo de dichas aplicaciones ha acelerado mas rápido que la esperada optimización.

Google juega uno de los papeles mas importantes en esta evolución y es muy consciente que a día de hoy, Javascript es un “problema” desde el punto de vista del rendimiento. Uno de los pilares de la presentacion de Chrome fué precisamente un nuevo motor opensource de javascript, el V8. Sin embargo, actúalmente parece que el problema sigue latente.

Además de la nueva implementación de google existen multitud de motores de Javascript, como Rhino de la fundación Mozilla, JavaScriptCore que implementa Safari o Carakan en Opera, pero a vista de los resultados actuales parece que mas de uno sigue sufriendo cuando debe ejecutar una aplicación compleja.

Para darse cuenta de todo esto, solo hace falta escoger un navegador y ponerse a dar vueltas por la aplicación web de moda, Google Wave. Si bien es cierto que la propia aplicación esta en una fase muy previa a considerarse estable, es cierto que el problema también se presenta en otros casos similares como por ejemplo Google Maps, aunque es cierto que de una manera mucho menos acusada. En el caso de Google Wave el problema es tan grave que deja el navegador totalmente inusable, en el caso de navegadores “monoproceso” como firefox, la unica solucion es “matar” al propio navegador.

Para probarlo en nuestras carnes, solo hace falta introducir una busqueda que incluya waves publicos, como por ejemplo introducciendo el texto “rpg with:public” y empezar a navegar por los waves. Rápidamente obtendremos resultados como los de las siguientes imágenes.

Firefox en linux ejecutando wave

Safari en OSX ejecutando wave

Chrome en Windows ejecutando wave

Por tanto a la pregunta del inicio del post, yo de momento tengo que decir, no, los navegadores aún no estan preparados para un salto total a la nube. Y si además introducimos en la ecuación los navegadores de dispositivos menos potentes como smartphones y versiones “light” de chrome o safari, aún la situacion se complica mas.