Archivo de 'desarrollo'

Historial y botón volver en JavaScript

Cada día son más frecuentes las aplicaciones web que hace un uso extensivo de JavaScript, relegando una mayor carga computacional al cliente, dentro de la arquitectura cliente-servidor, lo que habitualmente se conoce como cliente pesado. Con ello, entre otras cosas, se logra una interfaz de usuario mucho mas rica en prestaciones.

Algunos ejemplos de webs que hacen uso de esto es el cliente de correo de Google Gmail, o las famosas redes sociales como Facebook o Tuenti. En estas aplicaciones, toda la interfaz está gobernada por JavaScript. Cuando accedemos a un enlace, generalmente no conlleva una nueva petición HTTP sino que, en su lugar, el documento actual se actualiza con nuevo contenido (AJAX).

Pero existe un inconveniente: Al hacer las webs así, no se almacenan las actualizaciones de la página en el historial del navegador, de modo que los botones de volver y avanzar del navegador no funcionan como esperaríamos. Esto ocurre porque la URL no ha cambiado, y por tanto, para el navegador no ha habido ningún cambio de página.

Pero en Facebook o GMail, pese a funcionar con JavaScript, sí funciona el botón de volver. ¿Cómo lo hacen? La magia está en el caracter almohadilla (#). Repasemos HTML: Cuando en un documento queremos hacer un enlace a una parte del mismo (Por ejemplo, para saltar a un apartado), lo hacemos con el caracter almohadilla seguido de la palabra clave. Por ejemplo:

<h1 id="top">Inicio</h1>
<p>Un párrafo con mucho contenido...</p>
<a href="#top">Volver arriba</a>

Una de las ventajas de estos enlaces es que no conllevan una nueva petición HTTP, por lo que son inmediatos. Además, el navegador tiene constancia de ellos, por lo que los almacena en el historial. Bien, pues ahí está el truco. Si nos fijamos en una URL de Facebook, veremos que son de este tipo:

http://www.facebook.com/#!/?sk=messages&filter=[fb]unread

Es decir, en este caso el enlace es a la página principal (http://www.facebook.com/) y dentro de ese documento, a un apartado (#!/?sk=messages&filter=[fb]unread). Con JavaScript podemos consultar ese apartado para, en función de él, cargar el contenido que proceda. Ya tenemos todas las piezas para hacer una aplicación web en JavaScript, donde funcionará el historial del navegador, y además podremos guardar las URLs en nuestros marcadores.

Acerca del evento hashchange

Para poder realizar eso, necesitamos un método para que, desde JavaScript, sepamos cuándo se ha actualizado el historial #hash, es decir, para saber cuándo se enlaza a otro apartado dentro del documento actual. En HTML5 queda resuelto esto con el evento windows.onhashchange. Sin embargo, al ser un evento nuevo, no está disponible en todos los navegadores, por lo que se hacen necesarios algunos hacks que permitan que nuestra aplicación funcione en la mayoría de navegadores.

En el caso de utilizar jQuery, el plugin más extendido es jQuery BBQ. Podemos leer más acerca de cómo funciona aqui:
http://benalman.com/projects/jquery-hashchange-plugin/

Implementación básica en jQuery

Este ejemplo es muy sencillo. Únicamente tendremos una lista de enlaces, y marcaremos en negrita al activo, y mostraremos su contenido. Entendiendo eso, podremos aplicarlo a todo lo demás.

En primer lugar, necesitaríamos incluir la biblioteca jquery, y además también el plugin de jquery BBQ.

<!DOCTYPE html>
<html lang="es">
<head>
<script type="text/javascript" src="jquery-1.4.1.js"></script>
<script type="text/javascript" src="jquery.ba-bbq.js"></script>
</head>
<body>
</body>
</html>

Después definimos una lista de enlaces y sus bloques de contenido:

<ul>
    <a href="#enlace1">Enlace 1</a>
    <a href="#enlace2">Enlace 2</a>
    <a href="#enlace3">Enlace 3</a>
    <a href="#enlace4">Enlace 4</a>
</ul>
<div id="enlaces">
    <div id="enlace1">Contenido Enlace 1</div>
    <div id="enlace2">Contenido Enlace 2</div>
    <div id="enlace3">Contenido Enlace 3</div>
    <div id="enlace4">Contenido Enlace 4</div>
</div>

Y ahora el código JavaScript:

$(function(){
  $(window).bind('hashchange', function(e) {
    var url = $.param.fragment();
    $('a.current').removeClass('current');
    if (url) {
        $('a[href="#' + url + '"]').addClass( 'current' );
        $("#enlaces > div").hide();
        $("#"+url).show();
    }
  });

  $(window).trigger( 'hashchange' );

});

El código hace lo siguiente:

  1. En primer lugar definimos una función que irá atada al evento ‘hashchange’. Este evento se dispara, como hemos visto, cada vez que se actualiza el #hash.
  2. En segundo lugar, consultamos el parámetro #hash y lo almacenamos en la variable ‘url’.
  3. Desactivamos el enlace previamente activo.
  4. En caso de que esté definido el parámetro #hash:
    1. Activamos el nuevo enlace activo. Tan sólo le añadimos una clase.
    2. Ocultamos todos los bloques de contenido.
    3. Mostramos el bloque de contenido activo.
  5. Lanzamos el evento hashchange para provocar una actualización, por si en la primera carga de la página ya hubiera un parámetro #hash (Por ejemplo, porque alguien ha guardado una URL en favoritos).

Finalmente, definimos el estilo para la clase “current” y ya lo tenemos.

Podéis probar una demo. Como veis, tras moverte entre los distintos apartados, los botones de Volver y Avance del navegador funcionan. Además, se pueden almacenar las URLs para su futura consulta.

Crear un componente en Joomla! 1.5

Joomla! es, junto con WordPress, quizás el CMS más popular que existe. Lo que no mucha gente sabe, o tiene en cuenta, es que es además un completo Framework de desarrollo web. No en vano, nos proporciona muchas de las funcionalidades que esperamos de un Framework:

  • Arquitectura basada en Modelo-Vista-Controlador.
  • Seguridad, con un completo sistema de perfiles de acceso.
  • Acceso a base de datos.
  • Sistema de cachés.
  • Gestión de errores.
  • Administración de formularios.
  • Sesiones.
  • Plantillas.
  • Utilidades para fechas, criptografía, XML, ficheros…

Con todo esto, podemos crear diferentes extensiones de Joomla!:

  • Component. Son las extensiones más complejas. Se trata de aplicaciones completas que se ejecutan dentro del espacio de Joomla!. Tenemos muchas de serie, como por ejemplo el componente Content (/components/com_content/), que es el encargado de manejar los artículos, categorías y secciones.
  • Module. Se trata de pequeñas piezas de contenido que se muestran en la página. A menudo, dependen de un componente, como es el caso del módulo “latest news” (/modules/mod_latestnews/). Otro ejemplo de módulos, son los menús. En los módulos, además, se debe especificar su posición dentro de la página.
  • Plugins. Son bloques de código que se disparan ante determinados eventos. Antes de Joomla! 1.5 se los llamaba Mambots.
  • Templates. Plantillas que modifican el aspecto visual de la aplicación web.
  • Languages. Las extensiones de este tipo contienen ficheros que definen cadenas de texto traducidas para distintas partes de Joomla!.

A partir de Joomla 1.6, además, tendremos dos nuevos tipos de extensiones. Library, que se tratará de un bloque de código que contenta un conjunto de funciones relacionadas entre sí. Por ejemplo, para acceder a la API de Twitter. Y también se incluirá la extensión Packages.

Como vemos, la extensión más compleja y flexible son los components. Con ellos podremos crear, por ejemplo, una completa agenda de eventos o un sistema de ecommerce. Veamos cómo podemos crear un componente básico “Hola Mundo”. Vamos a utilizar la primera parte del ejemplo que viene en la documentación de Joomla!.

Modelo Vista Controlador

Lo primero es conocer el patrón Modelo-Vista-Controlador. Queda fuera del alcance de este artículo explicar en qué consiste, de modo que en resumen diremos que se trata de una arquitectura que permite dividir una aplicaciones en tres apartados:

  1. Controlador, que es el que gobierna el comportamiento principal, y el que responde las peticiones del usuario. En Joomla: JController.
  2. Vista. Se trata del código que se encarga de generar el contenido que se le devolverá al usuario. Generalmente en HTML. En Joomla: JView.
  3. Modelo. Es una abstracción de los datos que usa la aplicación. Si bien normalmente encapsulan bases de datos, también pueden utilizar otros origines de datos como un feed RSS. En Joomla: JModel.

Crear árbol de directorios

El primer paso consiste en crear el siguiente árbol de directorio y ficheros:

Además de los ficheros en blanco index.html (Para prevenir accesos a los directorios), vemos que tenemos 5 ficheros:

  1. /site/hello.php – Punto de entrara a nuestro componente
  2. /site/controller.php – Fichero que contiene nuestro controlador.
  3. /site/views/hello/view.html.php – Clase que extiende JView que se encarga de construir la vista
  4. /site/views/hello/tmpl/default.php – Plantilla
  5. /hello.xml – Fichero XML que indica a Joomla! cómo instalar el componente.

Crear el punto de entrada

Vamos a editar el fichero /site/hello.php y vamos a guardar en el lo siguiente:

/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * components/com_hello/hello.php
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_2
 * @license    GNU/GPL
 */

// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

// Require the base controller

require_once( JPATH_COMPONENT.DS.'controller.php' );

// Require specific controller if requested
if ($controller = JRequest::getWord('controller')) {
	$path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';
	if (file_exists($path)) {
		require_once $path;
	} else {
		$controller = '';
	}
}

// Create the controller
$classname	= 'HelloController'.$controller;
$controller	= new $classname();

// Perform the Request task
$controller->execute( JRequest::getVar( 'task' ) );

// Redirect if set by the controller
$controller->redirect();

¿Qué es lo que hemos hecho? Veámoslo paso a paso:

  1. En primer lugar comprobamos que estamos ejecutando éste código dentro de Joomla mirando si está definido _JEXEC. En caso contrario, finalizamos la aplicación.
  2. Cargamos con require_once nuestro controlador.
  3. El siguiente bloque de código comprueba si se necesitan más controladores. Por ahora no es necesario, pero lo mantenemos ahí para un futuro.
  4. Después, creamos el controlador. En este caso, siempre se creará un controlador de la clase HelloController(), dado que en este ejemplo, como vimos en el paso anterior, no hay más.
  5. Posteriormente indicamos al controlador que lleve a cabo la tarea solicitada. Por defecto, si no hay ninguna, la tarea es ‘display’.
  6. Finalmente, pasamos el control al controlador, para que, si fuera necesario, lleve a cabo una redirección.

Creamos el controlador

Nuestro controlador sólo hace una cosa: Mostrar el mensaje Hello World, de modo que no se hace necesaria ninguna manipulación de datos. Guardamos el siguiente código en /site/controller.php

 /**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
 * @license    GNU/GPL
 */

// No direct access

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.controller');

/**
 * Hello World Component Controller
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HelloController extends JController
{
    /**
     * Method to display the view
     *
     * @access    public
     */
    function display()
    {
        parent::display();
    }

}

Como vemos, creamos una clase llamada HelloController que hereda a JController. Tan sólo define el método display(), pues es la tarea por defecto (Salvo que no se especifique otra). Este método tan sólo invoca al método JController::display(), que determina y carga la vista y plantilla a utilizar. En nuestro ejemplo, sólo tenemos una vista y una plantilla.

Crear la vista

La vista tan sólo carga datos y los guarda para usar en la plantilla. Para ello se usa el método assignRef(), donde el primer parámetro es el nombre de la variable en la plantilla, y el segundo la variable que se comparte.

Código de /site/views/hello/view.html.php:

/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
 * @license    GNU/GPL
*/

// no direct access

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.view');

/**
 * HTML View class for the HelloWorld Component
 *
 * @package    HelloWorld
 */

class HelloViewHello extends JView
{
    function display($tpl = null)
    {
        $greeting = "Hello World!";
        $this->assignRef( 'greeting', $greeting );

        parent::display($tpl);
    }
}

Y ahora definimos el código de la plantilla en /site/views/hello/tmpl/default.php:

<?php

// No direct access

defined('_JEXEC') or die('Restricted access'); ?>

<?php echo $this->greeting; ?>

Se trata de un fichero PHP convencional en el que tenemos accesibles todas las variables que hemos compartido desde la vista.

Juntándolo todo

Nos queda definir el fichero Manifiest que define el componente para poder instalarlo fácilmente (Sin tener que copiar los ficheros a mano y actualizar la base de datos nosotros). Contiene distinta información, como por ejemplo:

  • Descripción del componente.
  • Lista de ficheros que incluye.
  • Un fichero opcional PHP que realizar tareas de instalación.
  • Un fichero opcional SQL que se ejecuta al instalar o desinstalar


 Hello
 
 2007-02-22
 John Doe
 john.doe@example.org
 http://www.example.org
 Copyright Info
License Info
 
 1.01
 
 Description of the component ...

 
 
 
  controller.php
  hello.php
  index.html
  views/index.html
  views/hello/index.html
  views/hello/view.html.php
  views/hello/tmpl/default.php
  views/hello/tmpl/index.html
 

 
  
Hello World!

  
  
   hello.php
   index.html
  

 

Finalmente, guardamos en los ficheros index.html un contenido trivial, como por ejemplo:

<html><body bgcolor="#FFFFFF"></body></html>

Por último, comprimimos en un fichero ZIP el contenido de la carpeta com_hello, y ya podemos instalar nuestro componente desde el instalador de extensiones de Joomla.

Mostrando el componente

Ahora, para poder ver el resultado, debemos consultar el componente. Para ello, debemos acceder a la siguiente URL:

/index.php?option=com_hello&view=hello

Vemos que no se define ninguna tarea (Recordemos que por defecto se usa Display). En caso de querer ejecutar otra tarea, tendríamos que definir el parámetro GET task, por ejemplo para la tarea ‘save’:

/index.php?option=com_hello&view=hello&task=save

10 errores comunes de programadores web novatos

Hace poco comentaba que en SitePoint habían publicado una lista de los 10 errores comunes de diseñadores web novatos. Pues recientemente publicaron un nuevo artículo, pero esta vez sobre los programadores web. Aquí el resumen:

  1. Ignorar los estándares web. Destacan el uso incorrecto del DOCTYPE, uso de etiquetas antiguas de HTML, o no validar el código.
  2. Delegar en software WYSIWYG. Muy acertadamente indican que, con este tipo de software uno se centra en la visualización, y no en la estructura.
  3. Descuidar aspectos semánticos. El ejemplo que ponen es impagable: El programador novato, si quiere escribir un titular, lo pondrá encerrado en la etiqueta <h1>. Pero posteriormente es posible que “involucione”, y lo diseñe con divs anidados y estilos CSS.
  4. Nombres de clases de estilos. ¿Qué tal una clase como “columna-izquierda-50px”? ¿Y si en un futuro el ancho cambia?
  5. Prueba de navegadores tardía. Invitan al programador novato a revisar su página en varios navegadores desde el primer momento, y no dejarlo para el final. Personalmente, en este punto no estoy de acuerdo; Siempre he preferido desarrollar para una plataforma, y al final, corregir errores de las demás.
  6. Ignorar la portabilidad. Destacan enlaces a rutas absolutas, conexiones a bases de datos sin centralizar, o realizar suposiciones sobre el entorno de ejecución.
  7. Descuidar el ancho de banda. Poco más que añadir… En local un fichero de unos megas es irrelevante, no así en Internet.
  8. Pésima accesibilidad. No consiste sólo en seguir unas reglas mecánicas de código, sino en tener en cuenta aspectos funcionales como poder consultar la web sin javascript, sin flash, en un móvil, o sin ratón.
  9. Despreciar al SEO. Me encanta la definición que hacen del SEO: Es una mezcla de psicoanálisis, complejidad técnica, y misteriosas artes oscuras. En cualquier caso, indican que el desarrollador novato, dejará el SEO para el departamento de marketing una vez lanzada la página. Para entonces, ya será demasiado tarde.
  10. Actualizaciones erróneas. Destacan la práctica de muchos programadores web de tener durante horas una página web en mantenimiento, cuando suele ser una tarea que no debería llevar más de unos minutos. En este punto tampoco estoy de acuerdo. Muchas actualizaciones tan sólo consisten en añadir documentos html, imágenes, y actualizar hojas de estilo y javascript. Sin embargo, hay aplicaciones web que requieren mucho más que eso a la hora de actualizar, por ejemplo cuando cambiamos la estructura de una base de datos, y se deben reestablecer todos los índices.
  11. Como bonus, dejan una lista de otros 20 errores.

En general, este artículo me ha parecido bastante más pobre que el anterior. Sobre todo, por lo mucho que se centra en la capa de presentación HTML, que dista mucho de ser coto exclusivo de los programadores web. En ningún punto se ha mencionado ni una sola práctica o error relacionada con la programación (Salvo el punto 6, donde sugieren no incluir hard coded la conexión a base de datos).

PHP 5.3.3 liberada

Hace ya un año que PHP lanzó la versión 5.3.0, la última rama de desarrollo de la versión 5 que adelanta muchas de las funcionalidades más esperadas, como namespaces o closures. Hoy se ha liberado la versión 5.3.3. Se ha centrado sobre todo en mejorar el rendimiento y la seguridad de la rama 5.3, con más de 100 errores corregidos, por lo que se recomienda encarecidamente actualizar a la nueva versión.

Entre las novedades, se destacan:

  • Actualizada la versión de sqlite a 3.6.23.1
  • Actualizada la versión de PCRE (Expresiones Regulares Compatibles con Perl) a la versión 8.02
  • Añadido FPM (Gestor de Procesos de FastCGI) SAPI. SAPI hace referencia a los módulos de PHP que hacen de interfaz al servidor web (Server Application Programming Interface)
  • Añadido soporte para stream filter de la extensión mcrypt.

¡A disfrutarlo!

10 errores comunes de diseñadores web novatos

Hoy me he encontrado en SitePoint un curioso artículo titulado “10 Common Mistakes Made by Novice Web Designers“. Me ha parecido muy interesante, pues aunque no soy diseñador propiamente dicho, pero sí he cometido muchos de esos errores.

Y esta es la lista:

  1. No tener en cuenta la forma de visualizar del navegador. Cada navegador funciona a una resolución, y ésta normalmente no es la misma que los bocetos hechos en Photoshop. ¿Cómo se comporta la página al cambiar de tamaño?
  2. Forzar a altos y anchos fijos. ¿Qué ocurre si el texto que hay dentro es anormalmente extenso o anormalmente corto?
  3. Presuponer sobre la experiencia del usuario. Hay muchas resoluciones y muchos dispositivos a tener en cuenta.
  4. Sub-pixels en bocetos. Un boceto a 300 ppp no se verá igual en un monitor a 72 ppp.
  5. Desconocimiento de las pilas de fuentes. No todas las fuentes funcionan en todos los sistemas, ni siempre se ven igual.
  6. No tener en cuenta el desarrollo. Nos ponen el ejemplo de títulos ricos en diseño que sólo se pueden conseguir con imágenes. Es algo asumible cuando hay 5 o 50 páginas, ¿pero y si hay 500? ¿O 5000?
  7. Olvidar en los enlaces. Los links son el hilo conductor de la web, y hay que diferenciarlos bien del resto del contenido.
  8. No tener en cuenta animaciones o efectos. Esto no se puede reflejar en un diseño en photoshop.
  9. Controles de formularios extraños o inaccesibles. Nos explican que los formularios son sosos, pero que sin embargo los navegadores saben renderizarlos y los usuarios los entienden.
  10. Poca apreciación por las tecnologías. HTML y Flash no son lo mismo :)

En mi opinión, las más importantes a tener en cuenta (O al menos las que más problemas me han dado) son la 2, 4, 6, 8 y 10 (Curioso, justo los pares).

WebApps Working Group

Últimamente leo bastante la página del w3c (Qué acierto fue cambiar su diseño), y casi siempre me veo a mí mismo leyendo sobre el Grupo de Trabajo de Aplicaciones Web (WebApps Working Group). ¿Qué es?

El W3C Web Applications (WebApps) Working Group, una fusión de los grupos de trabajoWebAPI y WAF, se constituye para desarollar APIs estándar para el desarrollo de Aplicaciones Web del lado del cliente. Este trabajo incluirá tanto la documentación de APIs existentes como el XMLHttpRequest, como el desarrollo de nuevas APIs que enriquezcan las aplicaciones web.

Veamos en qué consisten algunas de esas APIs que están desarrollando:

Interfaz para Widgets

Cada widget podrá tener un documento de configuración que almacenará metadatos relativos al Widget. Además, cada instancia de un widget podrá almacenar datos de manera persistente.  ¿Cómo se hará esto? Gracias a otra API de almacenamiento de datos locales.

Está bastante maduro (En estado de Recomendación Candidata), y existe una suite de tests para probar su correcta implementación.

API de selectores Level 1

Supongamos el siguiente bloque de código HTML 4.01:

<table id="score">
  <thead>
    <tr>
      <th>Test
      <th>Result
  <tfoot>
    <tr>
      <th>Average
      <td>82%
  <tbody>
    <tr>
      <td>A
      <td>87%
    <tr>
      <td>B
      <td>78%
    <tr>
      <td>C
      <td>81%
</table>

Si quisiéramos obtener los valores de todas las celdas tendríamos que ejecutar algo similar a esto con la API de DOM Level 2:

var table = document.getElementById("score");
var groups = table.tBodies;
var rows = null;
var cells = [];

for (var i = 0; i < groups.length; i++) {
  rows = groups[i].rows;
  for (var j = 0; j < rows.length; j++) {
    cells.push(rows[j].cells[1]);
  }
}

¡Qué feo! La nueva API permite hacerlo de este modo mucho más conciso:

var cells = document.querySelectorAll("#score>tbody>tr>td:nth-of-type(2)");

Como véis, es exactamente igual que lo que ya hacemos con los selectores de jQuery, salvo que en un tiempo podremos realizarlo directamente desde el motor de JavaScript del navegador, sin necesidad de frameworks.

Esta API también está muy madura, y al igual que la anterior es una Recomendación Candidata. Está disponible en Firefox desde su versión 3.1+, en Internet Explorer 8 y en Safari 3.1+. Pero hasta que no borremos del mapa a IE6 e IE7 tendremos que seguir utilizando herramientas como jQuery.

Web Storage

Es un nuevo mecanismo de almacenamiento local que, a diferencia de las Cookies, permite almacenar un gran volumen de datos (Por ejemplo, los emails de una cuenta, haciendo innecesario plugins como Google Gears), y también permite almacenarlo accesible a todas las ventanas del dominio al que pertenecen.

Todo se realizaría de un modo muy sencillo: Simplemente accediendo al atributo que proceda dentro del objeto localStorage.

De nuevo, está disponible ya en Firefox 3.5, IE8, Safari 4.0, Chromium…

Web Workers

Permite lanzar distintos hilos de ejecución que se ejecutan en paralelo a la página principal. De este modo, se puede trabjar en un entorno thread-like trabajando con un mecanismo de coordinación de pase de mensajes.

Como ejemplos, podríamos:

  • Generar una hebra que busque números primos en background.
  • Un worker que actualice una base de datos local. Estaría permanentemente escuchando al servidor mediante un WebSocket, y cuando hubiera algún cambio, modificaría la base de datos local.
  • Operaciones de Lectura/Escritura de fondo.
  • Workers compartido. Distintas ventanas podría compartir un único Worker que, en un momento dado, podría actualizar a todas a la vez.
  • Delegación. Aprovechando las distintas CPUs de los microprocesadores multi-core.

Lógicamente, esto abre un gran número de posibilidades en cuanto al rendimiento de las páginas web.

Por el momento disponible en Firefox 3.5+, Safari 4, Chromium.

Server-Sent Events

La API que define esta especificación puede no parecer muy revolucionaria: Permite recivir notificaciones PUSH desde el servidor en forma de evento DOM. Perfectamente podemos lograr el mismo objetivo mediante XHR o un iframe. Sin embargo, dada su naturaleza, permitiria que, cuando el navegador se pueda coordinar con el operador de red, se ahorraran notablemente recursos de red. Uno de los efectos colaterales sería aumentar la duración de las baterías de los dispositivos portátiles.

WebSockets API

Esta API permite una auténtica conexión bidireccional entre el navegador y el servidor. Ya fue cubierta en este blog cuando Google Chrome anunció su implementación.

Web SQL Database

Es exactamente lo que su nombre sugiere. Consiste en una especificación de un API que permitirá almacenar información en una base de datos locale accesible mediante SQL.

Veamos un ejemplo de su funcionamiento:

function prepareDatabase(ready, error) {
  return openDatabase('documents', '1.0', 'Offline document storage', 5*1024*1024, function (db) {
    db.changeVersion('', '1.0', function (t) {
      t.executeSql('CREATE TABLE docids (id, name)');
    }, error);
  });
}

function showDocCount(db, span) {
  db.readTransaction(function (t) {
    t.executeSql('SELECT COUNT(*) AS c FROM docids', [], function (t, r) {
      span.textContent = r.rows[0].c;
    }, function (t, e) {
      // couldn't read database
      span.textContent = '(unknown: ' + e.message + ')';
    });
  });
}

prepareDatabase(function(db) {
  // got database
  var span = document.getElementById('doc-count');
  showDocCount(db, span);
}, function (e) {
  // error getting database
  alert(e.message);
});

En primer lugar se define la función prepareDatabase() que, en caso de que fuera necesario, crea la base de datos con una tabla llamada “docids” con dos columnas (“id” y “name”). Si hay éxito, o no es necesario crearla, se llama a la función getDatabase(), que obtiene un manejador de la base de datos, y entonces llama a la función que hace realmente el trabajo, en este caso showDocCount().

File API

Como último ejemplo de apartados en los que trabaja el WebApps Working Group, voy a mosotrar la File API. Permitirá un manejo avanzado de ficheros desde JavaScript, pudiendo:

  • Una vez que el usuario conceda permisos, el navegador permitirá leer y parsear un fichero.
  • Se podrá almacenar información de forma local.
  • Se permitirá guardar los archivos, del mismo modo que ahora se pueden descargar ficheros de servidores remotos.
  • Se podrán enviar ficheros grandes a servidores de un modo más eficiente que el actual. Por ejemplo, se podrá dividir en porciones.
  • Los navegadores implementarán mecanismos para poder cancelar o impedir los casos de uso enumerados anteriormente.

Sin duda, APIs como éstas permitirán realizar aplicaciones reales que funcionen en el navegador sin necesidad de un servidor. Como ejemplo, un reproductor multimedia avanzado, que guarde una caché local con metadatos de nuestra música y películas.

Creo que muy pronto comenzaremos a ver todas estas nuevas aplicaciones ir aparenciendo, poco a poco, hasta que un día el navegador realmente sea un framework de aplicaciones más.