31 octubre, 2008

Más socios en el club OpenID

Informan en este blog que LiveJournal, Microsoft Live ID (anteriormente Microsoft Passport) y Google Accounts han implementado o están implementando el estándar OpenID para permitir usar sus cuentas para acceder a servicios de terceros. Una excelente noticia que debería suponer el principio del fin de la multitud de cuentas (usuarios y contraseñas) que un usuario debe mantener para acceder a cada uno de los sitios que le ofrecen servicios.

Las ventajas del sistema no sólo afectan al usuario, los desarrolladores también pueden simplificar bastante el trabajo en cuanto al mantenimiento de cuentas y al sistema de sesiones. En esta página detallan la API de Google para dicho servicio.

28 octubre, 2008

ORMs con Javascript

Los ORM (Mapa-objeto-relación), celebres gracias al Active Record usado por Ruby on Rails, consisten en librerías basadas en una técnica de programación para convertir datos entre el sistema de tipos utilizado en un lenguaje de programación orientado a objetos y el utilizado en una base de datos relacional.

Su función es ocultar las tablas de una base de datos relacional tras la apariencia de objetos, un sistema de acceso a los datos más natural para los programadores. Es como decir "esta clase mapea esta tabla, y los objetos de esta clase mapean las filas de esa tabla". Una de las mejoras más evidentes es ocultar las sentencias SQL del código de la aplicación.

Esto permite realizar cosas como:

JazzLegend.find_by_name('Miles Davis').albums

var katzFamily = Person.filter("lastName = ?","Katz");
katzFamily.each(function(person) {
  console.log(person.firstName);
});

var mail = Mail.retrieve(msgid);
if (!mail) mail = Mail.create({ message_id: msgid, message: body });
mail.last_read((new Date).toUTCString());
mail.drop();

27 octubre, 2008

Plugin para If, ElseIf, Else, Do encadenados con jQuery

Andrea Giammarchi nos obsequia con un plugin para jQuery capaz de hacer cosas como esta:


function impares(){
    // devuelve true si el elemento contiene un número impar
    return $(this).text() & 1;
};

$(function(){
    $("div")
        .If(function(){return $(this).text() == "3" || $(this).text() == "5"})
            .text("coincide con 3 o 5")
        .ElseIf(oddNumbers)
            .text("impares")
        .ElseIf(function(){return $(this).text() == 2})
            .Do(function(){ // si se necesita una clausura ... 
                $(this).text("texto es igual a 2");
            })
        .ElseIf(function(){return $(this).text() == 6})
            .text("coincide con 6")
        .Else()
            .text("esto es 4 u 8");
})

Es decir, permite encadenar código condicional aplicable a nodos devueltos con una query. Este ejemplo muestra el resultado de aplicar el código anterior a ocho capas DIV numeradas del 1 al 8. A continuación el código del plugin:

(function($){
// Andrea Giammarchi - Mit Style Licence - V0.1b
var slice   = Array.prototype.slice;
$.fn.extend({
If:function(fn){
    var _filter = this.filter(fn);
    _filter.__If__ = {
        parent:this,
        removed:_filter
    };
    return _filter;
},
ElseIf:function(fn){
    var filter  = function(){return !~_filter.index(this)},
        _filter = this,
        self = this.__If__.parent.filter(filter);
    _filter = self.filter(fn);
    _filter.__If__ = {
        parent:this.__If__.parent,
        removed:$(slice.call(this.__If__.removed, 0).concat(slice.call(_filter, 0)))
    };
    return _filter;
},
Else:function(){
    var _filter = this.__If__.removed;
    return this.__If__.parent.filter(function(){return !~_filter.index(this)});
},
Do:function(fn){
    this.each(fn);
    return  this;
}
})})(jQuery);

Addendum: Andrea ha optimizado su plugin reduciendo el código necesario para su funcionamiento. Página oficial del plugin. Código:
;jQuery.fn.extend({
    // Andrea Giammarchi - Mit Style Licence - V0.2
    If:function(fn){
        var __If__ = this.__If__ || this,
            $ = __If__.filter(fn);
        $.__If__ = __If__.filter(function(){return !~$.index(this)});
        return $;
    },
    Else:function(){
        return this.__If__;
    },
    Do:jQuery.fn.each
}); jQuery.fn.ElseIf = jQuery.fn.If;

¿Prohibir IE6?

En HedgerWow.com:

¿Qué podría hacer el nuevo Director de Tecnología de los Estados Unidos prometido por Obama?

Prohibir el uso de IE6.



Ojalá. Es imprescindible para el avance de las nuevas tecnologías web. Aunque seguramente sería mejor obligar a Microsoft a que se rija por los estándares y no por su tendencia a desviarse de ellos para demostrar quién manda aquí.

25 octubre, 2008

Pruebas unitarias de código Javascript

Una relación de proyectos orientados a la realización de baterías de pruebas unitarias para verificar la corrección de código javascript:

Addendum: He encontrado una buena recopilación en este blog sobre el tema de este artículo.

24 octubre, 2008

Una breve reflexión sobre la nube

Amazon anuncia que puede ejecutar instancias de Windows en sus servidores EC2 alquiladas por tiempo. Aquí comentan cómo hacerlo. El precio incluye el alquiler de la licencia por horas. Las posibilidades que esta nueva opción trae son inmensas. Auténticos terminales tontos que muestren en pantalla lo que se está ejecutando, no ya a unos metros (esa opción ya existe desde hace tiempo), sino a varios miles de kilómetros. La nube ya está aquí, y va a traer consigo una mejora de varias magnitudes en las comunicaciones. Quizás lo que Microsoft no ha conseguido (convertir sus productos en servicios) lo acaben ofreciendo otras compañías.

Implementación de CouchDB

Ricky Ho publica en su blog una detallada explicación del funcionamiento de la base de datos de nueva generación CouchDB. Ya he hablado anteriormente de ella. Está basada en utilizar un almacenamiento perezoso de los datos conservando las versiones de los cambios. Igualmente utiliza JSON (versatilidad), Javascript (flexibilidad) y Erlang (extensibilidad) como paradigmas, aunque la lista de Ho es más exhaustiva:

  • API RESTful
  • Almacenamiento de documentos sin esquema (en formato JSON)
  • modelo de control de concurrencia con Multi-Version
  • Consultas definidas por el usuario estructuradas como map/reduce
  • actualización de índices mediante un mecanismo incremental
  • modelo de replicación Multi-Master
  • escritor en Erlang

CSS HTTP Request

Aunque últimamente están apareciendo muchos problemas de seguridad en el navegador debido al auge de la programación con Javascript (hay que recordar que la mayor parte de los virus atacan a Windows porque tiene el 85% de cuota de mercado), hay una protección que está bien implementada: la restricción de Cross-Domain que impide que se pueda realizar directamente una petición a un servicio web de otro dominio.

Han surgido distintas soluciones para resolver ese problema, siendo la más reciente la que se explica en esta página (via Willison).

CSS HTTP Request (CHR) se sirve del hecho de que los archivos CSS no se ven afectados por la política de same-origin por lo que puede utilizarse para transportar datos si se controla desde Javascript. Además cuenta con la ventaja de que, a diferencia de JSONP que utiliza una etiqueta SCRIPT para realizar la llamada, no se cede el control al servicio web, lo que está considerado como un agujero de seguridad.

La función propuesta en su librería tiene dos parámetros, la URL del servicio web y la función que se llamará cuando se disponga de los datos:

CSSHttpRequest.get(
    "http://www.nb.io/hacks/csshttprequest/hello-world/",
    function(respuesta) { alert(respuesta); }
);
El funcionamiento es curioso: en el servidor, los datos se dividen en bloques de 2KB y se codifican en líneas @import(about:chr:DATA)

Como último detalle, en Firefox 3 los archivos CSS sí que tienen la restricción de Same-Origin pero los autores han conseguido resolver el problema y también funciona correctamente con el navegador.

Descargar. Addendum: JSONet es una librería pensada para aprovechar esta técnica de comunicación con el servidor sin la limitación Same-Origin.

17 octubre, 2008

Apuntes sobre JavaScript 2.0

Llevo tiempo retrasando este artículo (de hecho está incompleto) sobre ECMAscript 4 (también conocido como Javascript 2) pero han habido cambios importantes en la especificación que parecen querer conservar la simplicidad y flexibilidad que han hecho del lenguaje lo que es. Si es así, son buenas noticias.

Breve historia de ECMAscript 4

La última versión mayor de Javascript se liberó en 1999, eso son 9 años sin actualizar el lenguaje. Durante estos últimos años, el grupo detrás de ECMAscript 4 ha estado muy activo. Las principales características de la nueva versión pretenden preparar el lenguaje para crear proyectos de envergadura dado que desde el principio ha estado orientado a crear programas cortos que interactuen sólo con el navegador (a través del DOM). Aunque chocaba el nulo interés que mostraba Microsoft por participar de los avances. Justo cuando estaban a punto de aprobar las especificaciones definitivas, Chris Wilson de Microsoft, se desmarcó de los avances y hubo una discusión bastante fuerte entre él y Brendan Eich, el creador del lenguaje, principalmente motivada porque Microsoft sólo dio señales de vida al final y para discrepar del trabajo de los demás. Microsoft y Yahoo! optaron por escindir la corriente principal y respaldar lo que se conoce como ECMAscript 3.1, mucho menos radical y más acorde con sus intereses. Se llegó a un punto en el que el grupo del 3.1 necesitaba añadir características que eran incompatibles con la futura versión 4, por lo que el tema estaba cada vez más caliente.

Resig hace referencia a la reciente reunión en Oslo del TC39 y a las palabras de Brendan Eich en las que resume la reunión de Oslo y el acuerdo de unión entre los dos grupos con los siguientes puntos (lo que se llamó ECMAScript Harmony):
  1. Enfocar el trabajo en ECMAscript 3.1 por todas las partes y buscar dos implementaciones interoperables para el año que viene.
  2. Colaborar en el siguiente paso más alla de ECMAscript 3.1, que incluirá extensiones sintácticas pero que será más modesto que ECMAscript 4 en cuanto a innovación sintáctica y semántica.
  3. Algunas propuestas de ECMAscript 4 han sido descartadas por inadecuadas para la web, y están fuera de la mesa para siempre: packages, namespaces y enlazado temprano. Esta conclusión es clave para Harmony.
  4. Otras metas e ideas de ECMAscript 4 están siendo reformuladas para mantener el consenso en el comité; estas incluyen la noción de clases basadas en los conceptos existentes de ES3 combinadas con las extensiones propuestas en ES 3.1.
En definitiva, todos los cambios son conservadores y, en mi opinión, muy acertados (y no soy el único) al alejarse de características extrañas para los programadores de Javascript y que parecen venir de programadores de aplicaciones que generan código de salida en Javascript y que quieren más potencia en el navegador pero que no programan directamente en el lenguaje.

Características en ES3.1

  • Getters y Setters para ejecutar cuando se lee o escribe una propiedad de una clase
    class Programador {
      var _nombre;
      function get nombre(){ return _nombre; }
      function set nombre(valor){
        _nombre = valor + " Resig";
      }
    }
    var p = new Programador;
    p.nombre = "John";
    alert( p.nombre ); // "John Resig"
    
  • Catch-All o método para capturar todas las llamadas a miembros de una clase
    dynamic class Programador {
      meta function get(nombre) { ... }
      meta function set(nombre, valor) {
        alert("Poniendo " + nombre + " a " + valor);
      }
    }
    var p = new Programador
    p.nombre = "John"; // alert("Poniendo name a John");
    
  • Catch-All o método para capturar todas las llamadas a miembros de una clase
  • Object.getPrototypeOf(obj) para obtener el prototipo de una clase

Características en ES4

  • Getters y Setters para ejecutar cuando se lee o escribe una propiedad de una clase
    class Artista {
      function pintar() { alert("Pintando!"); }
    }
    class Disenyador extends Artista {
      override function pintar() {
        alert("Disenyando!");
      }
    }
    var d = new Disenyador
    d.pintar(); // alert("Disenyando!");
    
    // los métodos 'final' no pueden solaparse
    class Artista {
      final function pintar() {alert("Pintando!");}
    }
    class Disenyador extends Artista {
      // ERROR: No se puede solapar el método 'pintar'
      override function pintar() {
        alert("Disenyando!");
      }
    }
    
    // las clases 'final' no pueden heredarse
    final class Artista {
      function pintar() { alert("Pintando!"); }
    }
    // ERROR: No se puede heredar de 'Artista'
    class Disenyador extends Artista {
      ...
    }
    
  • Metaclases o métodos estáticos. Pueden llamarse sin instanciar la clase
    // proveen funciones y propiedades globales sobre un objeto class
    class Usuarios {
      static function encontrar( nombre ) {
        // ...
      }
    }
    // Nótese que no se instancia con (new Usuarios()).encontrar( "John" )
    Usuarios.encontrar( "John" ); 
    
  • Interfícies, verifican que una clase implementa los métodos de otra
    interface Artista {
      function pintar();
    }
    class Disenyador implements Artista {
      function pintar() { alert("Disenyando!"); }
    }
    var d = new Disenyador();
    if ( d is Artista ) alert("Los Disenyadores son Artistas!");
    
  • Tipos Especificación de tipos:
    var nombre : string = "John";
    let x : double = 5.3;
    function stuff( x: int, obj: Object ) : boolean {} // Sólo devuelve boolean
    function cada( este: Array, valor: int ) { // sólo acepta Arrays como primer parámetro
      for ( var i = 0; i < this.length; i++ )
        alert( this[i] );
    }
    cada.call( [0,1,2], 3 ); // alert(0); alert(1); alert(2);
    cada.call( {a: "b"}, 4); // ERROR al ser un objeto el primer parámetro
    function stuff( nombre, ...valores ){ // la sintaxis ...valores indica que el resto de parámetros se guardarán en la variable valores
      alert( valores.length );
    }
    stuff( "John", 1, 2, 3, 4 ); // alert( 4 ); o sea, la cantidad de parámetros que han entrado como valores ~= [1,2,3,4]
    var test : (string, int, double) = "test"; // test sólo acepta cadenas, o números
    test = 3;
    test = false; // ERROR
    type CualquierNumero = (byte, int, double, decimal, uint);
    var test : CualquierNumero = 3
    
    // las dos siguientes líneas son equivalentes
    var test2 : * = "test";
    var test2 = "test";
    type Punto = { x: int, y: int }; // así defino el nuevo tipo Punto
    var p : Punto = { x: 3, y: 24 };
    
    // evitar aceptar null
    var nombre : String! = "John"; // previene que las variables acepten valores null
    nombre = null; // ERROR
    function test( name: String? ) { // parámetro obligatorio
      alert( name );
    }
    class Usuario {
      var nombre : string!; // propiedad que debe inicializarse obligatoriamente
      var apellidos : string!;
      function Usuario( n, l ) : nombre = n, apellidos = l {
        // ...
      }
    }
    
    // uso de like
    if ( { x: 3, y: 5 } like Punto ) alert( "Eso parece un punto" );
    function cada( a: like { length: uint } ) { // recorre lo que se parezca a array
      for ( var i = 0; i < a.length; i++ ) alert( a[i] );
    }
    

Tamarin, V8 y ScreamingMonkey

Tamarin es una máquina virtual de Javascript 2 que Adobe ha realizado para el plugin de Flash (Actionscript). Aún se desconoce si Adobe ofrecerá a través de su ubicuo Flash la opción de ejecutar Javascript 2 en todos los navegadores. En caso de que no lo haga, el proyecto Screaming Monkey es un plugin abierto para Internet Explorer (basado en Tamarin) que permitirá utilizar Javascript 2 en ese navegador en el caso de que Microsoft mantenga su intención de no pasar de ECMAscript 3.1.

Finalmente, el último motor aparecido es el de Google Chrome. V8 ha sido la primera versión publicada y activada en un navegador de la siguiente generación de intérpretes de alto rendimiento. Sin duda, el lenguaje promete.

16 octubre, 2008

De una tabla de la Wikipedia a un mapa en Google Maps

Me he quedado un poco noqueado con el procedimiento realizado en Data Scraping Wikipedia with Google Spreadsheets para convertir una tabla en una página de la Wikipedia en un completo mapa con las ciudades marcadas y su población. Paso a detallar:

En esta página de la Wikipedia (List_of_largest_United_Kingdom_settlements_by_population) aparece una tabla con las mayores agrupaciones de población del Reino Unido.



Gracias a la función =importHTML(url,"table",n) de Google Spreadsheet (la hoja de cálculo online de Google) es posible obtener esa información tabular. El primer parámetro indica la URL de la página de la que queremos extraer la información, el segundo indica que queremos una tabla y el tercero el orden de la tabla deseada dentro de la página:




=ImportHtml(”http://en.wikipedia.org/wiki/List_of_largest_United_Kingdom_settlements_by_population”,”table”,1)



Y automágicamente:



Google ya cuenta con herramientas para trabajar con esos datos y mostrar alguna gráfica:



Pero la potencia viene de exportar la información:




¿Más opciones de publicación?



El CSV es interesante:



A Yahoo! Pipes le encantan los CSV.





Quitamos esos asteriscos que molestan y pedimos datos desde la fila 2 porque ¿quién quiere esa cabecera?



Ahora podemos... crear un feed con los datos... o extraer los datos de localización...



Esto tiene buena pinta...



Aprovechamos aún más opciones de exportación de Pipes, como ese KML que Google Maps pide a gritos:





Recapitulando, hemos extraído información de una página de la wikipedia y la hemos introducido en una hoja de cálculo de Google Spreadsheet usando su función =importHTML, hemos publicado unas cuantas filas como CSV, que hemos aprovechado para alimentar un pipe (tubería) de Yahoo! Pipes para acabar generando un archivo KML y que finalmente nos ha servido para mostrar los datos en un mapa.

Mi conclusión: cuesta más pensar en obtener la información y presentarla de una forma que en realizar el proceso en sí.

Estilos más sencillos sólo para IE

Si utilizas este HTML:

<!--[if IE ]>
  <body class="ie">
<![endif]-->
<!--[if !IE]>-->
  <body>
<!--<![endif]-->
con un CSS como éste:
div.foo {
    color: inherit;
}
.ie div.foo {
    color: #ff8000;
}
así se consiguen todas las ventajas del uso de comentarios condicionales para evitar los problemas de Internet Explorer, sin la petición HTTP extra de una hoja de estilos específica para IE. Via Paul Hammond.

15 octubre, 2008

Salvando la web del ClickJacking

El gurú Douglas Crackford hace referencia a esta entrada (traducción) sobre el reciente fenómeno conocido como ClickJacking en el que acertadamente se indica por qué pasa y cómo resolverlo.

En resumen, los ataques de Cross-site Request Forgery (del que se podría considerar que el clickJacking es un subconjunto) vienen del hecho de que la información de usuario esté disponible directamente y sin ningún control de acceso tanto si la solicita el mismo usuario como si lo hace cualquier desarrollador de páginas visitables.

Todos los problemas conocidos hasta el momento y derivados de esta falta de control pueden solucionarse fácilmente si para mostrar cualquier página el servidor web requiere un token de seguridad generado por una página anterior del mismo sitio y con una validez limitada, de forma que la URL de acceso a las páginas no sea adivinable. Las soluciones que se están planteando no atacan la raíz del problema por lo que de no hacerse correctamente, es probable que sigan apareciendo otros agujeros de seguridad del mismo tipo.

Bookmarklet anti-distracción

En algún momento a lo largo del día de hoy, me he quedado mirando la típica columna estrecha que aparece junto al contenido de muchas páginas y que suele incluir enlaces, fotos y publicidad que no hacen sino molestar y distraer la atención. Tengo instalada la extensión Nuke Anything Enhanced que permite cualquier objeto con el menú contextual, pero no deja de ser un juego intentar eliminar así las malditas columnas.

Así que se ha encendido la bombillita y he creado un bookmarklet que al ser pulsado identifica las capas DIV que tienen un ancho inferior a 400 píxeles y las oculta. Arrastrar este enlace (cols) a la barra de herramientas del navegador y pulsar sobre ella en cualquier página que tenga una de esas columnas para verla desaparecer (lamentablemente este blog es demasiado limpio para servir como prueba ;-).

// definición de la función recursiva que busca los divs empezando por un elemento
var hideNarrowCols= function(elm) {
 if ( typeof elm.childNodes == "undefined" ) return;
 // comprobación de cada hijo del elemento actual
 for ( var i=0; i<elm.childNodes.length; i++ ) {
   var c= elm.childNodes[i];
   // si no es un DIV no interesa y continua con el siguiente hijo
   if ( c.tagName != "DIV" ) continue;
   if ( !c.style ) return;
   // si su anchura es inferior a 400, la oculta
   if ( c.clientWidth<400 ) c.style.display= 'none';
   // comprueba a su vez los hijos de este DIV (recursividad)
   hideNarrowCols(c);
 }
};
// empieza a buscar directamente a partir de document.body
hideNarrowCols(document.body);
// evita devolver un valor para evitar que la página entera lo muestre
void(0);
Addendum: David Delgado propone la siguiente versión del bookmarklet que tiene en cuenta también la altura de la capa y usa la función getElementsByTagName que es mucho más lógica. (cols)
var hideNarrowCols= function(sqr){
  var elm= document.getElementsByTagName('DIV');
  for ( var i=0; c=elm[i]; i++) { 
    if ( c.offsetWidth < sqr && c.offsetHeight > sqr )
      c.style.visibility='hidden';
  }
};
hideNarrowCols(400);
void(0);
Addendum: La versión que estoy usando actualmente, también cambia el fondo de las capas y de la página a blanco para facilitar aún más la lectura.
var hideNarrowCols=function(sqr){
  var elm=document.getElementsByTagName('DIV');
  for(var i=0;c=elm[i];i++){
    if(c.offsetWidthsqr) c.style.display='none';
    c.style.background='#fff';
  }
};
hideNarrowCols(400);
document.body.background='';
document.body.style.backgroundColor='white';
document.body.style.color='black';
document.body.aLink='#ff0000';
void(0);

BlackBird.js para depurar código Javascript

BlackBird es una pequeña librería que permite mostrar mensajes de depuración al estilo de la consola de Firebug y evitar así el extendido uso de alert() para esta finalidad. Es posible indicar distintos tipos de mensajes, filtrarlos, esconder la ventana o borrar la lista de mensajes acumulados. Funciona con Internet Explorer 6+, Firefox 2+, Safari 2+, Opera 9.5. Un ejemplo de uso:
<html>
<head>
<script type="text/javascript" src="blackbird.js"></script>
<link type="text/css" rel="Stylesheet" href="blackbird.css" />
</head>
<body>
<script type="text/javascript">
  log.debug( 'this is a debug message' );
  log.info( 'this is an info message' );
  log.warn( 'this is a warning message' );
  log.error( 'this is an error message' );
</script>
</body>
</html>

Firefox 3.1 beta

Liberada la versión 3.1 beta del navegador por excelencia. Pero esta vez, y debido al movimiento del sector, incluye muchas e importantes mejoras:

  • Geolocalización: Gracias a Geode, es posible averiguar la localización aproximada del punto de conexión que se está utilizando para navegar.

  • @font-face: con el siguiente código es posible utilizar una fuente no estándar e indicar dónde está ubicada para que cualquier navegador pueda visualizarla aunque no la tenga instalada.


    @font-face {
      font-family: "Bitstream Vera Serif Bold";
      src: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");
    }
    

  • Vídeo y audio: con estos ejemplos es posible comprobar es soporte de etiquetas de vídeo y audio con soporte para los códecs abiertos OGG Theora y OGG Vorbis.

    La web sigue teniendo pendiente resolver este problema y el soporte nativo en el navegador es ideal para intentar unificar los códecs usando los estándares abiertos. Permitiendo cosas como integrar multimedia con canvas, svg y HTML o sobreponer una capa semitransparente sobre la película desde HTML.

  •  Mejoras en XHR (XMLHTTPRequest), la técnica más utilizada por Ajax. Ahora se incluye soporte para la notificación del progreso de la consulta con los métodos progress, load, abort, error, loadstart, y progress. El evento uploadprogress de la versión anterior está desaconsejado.

    También se incluye un nuevo sistema de control de acceso para permitir, siguiendo unas condiciones, el acceso a contenido de un dominio distinto al de la página actual (cross-site). Un problema para el desarrollo debido al enfoque que se le ha dado a la seguridad y que ha obligado a hacer rodeos (p.ej. proxies) para obtener información externa. La especificación puede servir de base para obtener más información.

  • Y por último, pero más importante, se ha incluido el nuevo motor de Javascript TraceMonkey. Aunque no viene activado por defecto, sólo hay que acudir a about:config y habilitar la opción javascript.options.jit.content a True.
Via Ajaxian.

14 octubre, 2008

¿Qué pasa con OpenID?

En este estudio realizado por Yahoo! (via developer.yahoo.net) se muestran los resultados de un estudio llevado a cabo por la compañía para comprobar el comportamiento de los usuarios a la hora de acceder a un sitio de evaluación de productos mediante la tecnología OpenID.

Recordemos que OpenID nació con la idea de servir de identificación universal para evitar el tener que darse de alta en cada uno de las páginas web que lo soliciten. Hace poco experimentó un cierto auge con el soporte de empresas como Yahoo!, MySpace o The New York Times.

El resultado es que la experiencia de usuario es pésima. Los usuarios no saben dónde introducir su usuario y contraseña y no entienden por qué se les solicita una URL en lugar de una dirección de correo (la forma de identificar al usuario más extendida). Aunque en parte eso se ha suplido con ciertas técnicas que permiten mapear una dirección de correo electrónico a la URL para que el usuario no tenga que hacerlo, no parece comprenderse correctamente el concepto de OpenID. Además, el hecho de que justo tras el alta en lugar de dirigirse a la página pretendida se soliciten nuevos datos desorienta aún más a los usuarios.

Bluetooth está considerado un estándar complejo. Algunos lo justifican debido a la cantidad de dispositivos y distintos métodos que debe soportar el estándar. Sin embargo, los casos más comunes se reducen a dos: conexión dispositivo - auriculares, conexión de envío de archivos entre dispositivo.

En OpenID el caso es único: entrar en un sitio web que soporta el estándar utilizando una cuenta que ya poseemos (MySpace o Yahoo!). Debería ser mucho más fácil, por ejemplo:

  1. opción alternativa: tengo cuenta en (desplegable proveedores)
  2. solicitar e-mail
  3. se redirige a una página del proveedor con el aspecto de la página en la que se intenta entrar y que solicita la contraseña (debe ser la única página que se vea del proveedor)
  4. una vez dentro de la página incluir en algún sitio un enlace de configuración de la cuenta OpenID en el proveedor

Aptimize RPO

Se trata de un componente para ASP.NET y Sharepoint (la versión para Apache está en camino) que intercepta el código HTML generado para ser enviado al cliente y lo optimiza al vuelo antes del envío y de forma transparente. Entre sus funciones:

  • minimiza, combina y comprime archivos JavaScript
  • minimiza, combina y comprime hojas de estilo (CSS)
  • combina imágenes en sprites CSS (una sóla imagen)
  • inyecta imágenes dentro de la hoja de estilo (inline)
  • activa la compresion gzip 
  • establece cabeceras de expiración (Expire) en un futuro lejano (para aumentar la validez del caché)
  • carga los scripts asíncronamente


La mejora resulta más que evidente para el usuario.

Jaxer 1.0 Release candidate

Hace unos meses, Aptana, conocida por su entorno de programación orientado a Javascript (Aptana Studio), hacía pública un nuevo servidor web abierto, Jaxer, basado en un concepto novedoso: unir javascript con la posibilidad de trabajar con el DOM del navegador pero en el lado del servidor y antes de mandarle la página al cliente.

No se trataba sólo de unificar lenguajes a ambos lados de la conexión sino llegar un paso más lejos y utilizar también el mismo entorno a ambos lados estrechando mucho la línea que los separa. Además cuenta con la posibilidad de realizar llamadas a código del servidor directamente desde el cliente. A cambio, el concepto arrastra una carga intrínseca: la obligación de renderizar el árbol XHTML (DOM) de la página a enviar para poder trabajar con ella.

La comunidad no parece haber correspondido a lo revolucionario del concepto, por lo que se han publicado unas comparativas en las que se muestra cómo el rendimiento se acerca en muchos casos al del mismo PHP y vence, con cierta claridad, a Ruby on Rails. Además, al utilizar el mismo motor que Firefox (TraceMonkey) se va a beneficiar de las sustanciales mejoras que aquel incorpora.

Desde hace unos días está disponible la versión 1.0 Release Candidate previa a la definitiva 1.0. Entre sus principales mejoras destacan:

  • Jaxer.Sandbox: Control a nivel de HTTP; soporta readyState, toHTML, waitForCompletion
  • Tratamiento incorporado y extensible de peticiones de servicio RESTful y RPC
  • Soporte rápido y nativo de JSON
  • APIs mejoradas para la Petición y Respuesta de HTTP
  • Manejo más flexible de configuración de la aplicación
  • Otras mejoras...


En fin, una plataforma excelente que probar con la importantísima ventaja de unificar el lenguaje utilizado a ambos lados de la conexión. Como sugerencia, aquí hay un buen artículo de IBM Developer Works: Build Ajax applications using the first real Ajax server: Aptana Jaxer.

09 octubre, 2008


Object.prototype.toString.apply(valor) === '[object Array]'

Esta es la única comprobación válida en Javascript para saber si valor es un array o un objeto. Esto se debe a que el operador typeof no funciona correctamente devolviendo object en ambos casos. Via el gurú Crockford.

Algo más que un Contenedor de Código (Pastebin)

Hace unos días John Resig publicó su presentación online  http://ejohn.org/apps/learn/ basado en varias diapositivas que incluían un segmento de código Javascript que se podía ejecutar directamente.

Hoy, y siguiendo la idea de que el mejor entorno para probar Javascript es el propio navegador, llega este post de Ajaxian que he traducido:

Los contenedores de código (Pastebins) se han convertido en una parte importante para compartir código con los colegas. Sitios como Pastebin o Pastie.org son extremadamente populares porque son fáciles y muy efectivos al dejar que la gente compare notas sobre su código fuente, especialmente para dar soporte.

Remy Sharp ha querido llevar el concepto de contenedor de código un paso más allá, pasando de pegar estáticamente de código. Su idea, que originó hace 6 meses, finalmente se materializó en la forma de JS Bin, un nuevo contenedor de código pero de un modo diferente:

JS Bin es una forma de contenedor, pero con un giro. Permite incluir el HTML y el CSS para dar contexto al código aportado. Como tal, significa que puedes ejecutar realmente el Javascript y pasarlo a un colega para que ayude a depurarlo.
Esta es una excelente idea que permite reparar tu código mientras compruebas los resultados inmediatamente. La lista de características también está bien pensada:
  • Guardar snippet privado
  • Depuración de Ajax remoto
  • Las URLs de los snippets funcionan por sí mismas (p.e. sin necesidad del framework de JS Bin)
  • Soporte para inyectar rápidamente las principales librerías JS incluyendo jQuery, jQuery UI, Prototype, Scriptaculous, Dojo, MooTools y YUI
  • Guarda el estado dentro de la ventana abierta (p.e. refresca la página y el código no se reiniciará)
La habilidad de inyectar algunas de las librerías más populares de Javascript es especialmente importante y recomendaría a los equipos de proyectos individuales que contactasen con Remy directamente para que incluyan sus librerías.

Para empezar, sugeriría ir a la web de JS Bin y jugar con ella. Además, Remy ha creado un par de vídeos que llegan al detalle sobre cómo aprovechar JS Bin:

07 octubre, 2008

Es interesante notar que la colección de mejoras del motor de Javascript hechas por el equipo de WebKit, han llegado incluso antes de que su versión anterior del motor (SquirrelFish) se incluyese en un navegador. La competición en rendimiento y el ritmo de publicaciones de los motores Javascript está siendo de tal velocidad que están empezando a solapar el ciclo de producción de los propios navegadores.
John Resig en ArsTechnica.com.

Novedades en Internet Explorer 8 Beta 2

Interesantes las novedades que la última versión en desarrollo de Internet Explorer incluye de cara a la programación de aplicaciones web:

  • XDomainRequest (XDR) permitirá realizar desde el navegador peticiones a otros dominios de forma seguro y sencilla. Para evitar problemas de seguridad requiere una autorización explícita en ambos lados, cliente y servidor.
  • Cross-document Messaging (XDM) permite el intercambio de mensajes entre frames cargados en el documento al estilo de Opera. El evento window.onmessage será disparado en el frame que reciba un mensaje de este tipo; la propiedad e.origin del evento pasado incluirá el dominio desde el que se ha originado el mensaje.
  • DOM Storage permite guardar tuplas de información que persisten sólo durante la vida de la pestaña en la que está abierta la aplicación. Se trata de un mecanismo alternativo al uso de cookies.
  • El evento Connectivity permite averiguar si el navegador tiene disponible una conexión activa. Usada junto con el DOM Storage permite un comportamiento similar a Google Gears, es decir, cachear la información en cuanto se detecte que no hay conexión. El tradicional XMLHttpRequest contará ahora con una nueva propiedad timeout para indicar el tiempo de espera de una respuesta del servidor ante una petición.
  • toStaticHTML es un nuevo método para sanitizar o eliminar de cadenas de texto los intentos potenciales de ejecución de código no deseado. toJSON y fromJSON permiten realizar conversiones rápidas (serialización/deserialización) entre cadenas de texto y objetos, evitando así el peligroso eval() y la lenta json2.js.
Via Ajaxian.

Addendum: Anne van Kesteren de Opera Software ha estado echando un vistazo y ya menciona las pegas, en la línea tradicional de Microsoft de ser incompatibles para romper la experiencia en el resto de navegadores. La desventaja de esa estrategia corporativa es que cuando dejen de ser los que tengan más cuota de mercado caerán en picado porque los desarrolladores dejarán de implementar sus características exóticas.

04 octubre, 2008

Otro vulnerabilidad: el "clickjacking"

Llevamos unos días ajetreados con el descubrimiento de un nuevo agujero de seguridad encontrado en los navegadores y que se ha bautizado como clickjacking (secuestro de clicks). La idea es ubicar sobre una página visible un iframe que cubra zonas con las que el usuario pueda hacer click (como un botón) y haciéndolas invisibles. De esa forma, el usuario estará pulsando sobre la un control de la página oculta en lugar de sobre donde cree que lo está haciendo (el botón que ve).

Giorgio Maone es el autor de la conocida extensión NoScript de Firefox, cuyo objetivo es navegar con la seguridad de que ningún intento oculto de acceso a los datos del usuario se realizará sin que lo perciba. Él es quien ha descrito el problema, y de hecho, él mismo ha estado usando esa técnica durante meses para conseguir que la extensión se instalase desde su página sin necesidad de que Firefox solicite permiso (en realidad se está pulsando el botón verde de la página de la extensión en addons.mozilla.org. Para comprobarlo, entrar en esta página e introducir el siguiente código en la barra de direcciones para dejar al descubierto el iframe invisible que cubre el botón de Install Now.


javascript:document.getElementById('amo-installer').style.opacity=0.7;void(0)

Así, el iframe oculto queda al descubierto.

Estamos viendo como el auge de las aplicaciones web está descubriendo un montón de problemas resultantes de la combinación de los elementos Javascript, IFrames, Ajax, y ahora también, CSS. La definición de HTML5 está a varios años de ser aprobada finalmente (hacia el 2020), por lo que es importante que se estudie bien el origen de todos estos problemas y se empiecen a implementar remedios en los navegadores que frenen la aparición de estos problemas sin que ello suponga un escollo para el desarrollo de las aplicaciones.

Así, Mark Pilgrim propone en el blog de WhatWG varias soluciones, entre las que me llama la atención la siguiente:
Rediseñar todo lo que sabemos sobre los modelos de seguridad de HTML y el navegador para hacer posible que los dominios y las páginas indiquen políticas muy específicas de inclusión y exclusión para todo tipo de enlazado (como src= o href=) o referenciado de forma que evitar este tipo de vulnerabilidades consista sólo en indicar alguno de los casos controlados por este mecanismo.
Lo cierto es que estos problemas suponen un hándicap al desarrollo de las aplicaciones web y avanzaríamos mucho más rápido si resultase más fácil evitarlos.

Problemas con Google App Engine

Aral Balkan denuncia en su blog los problemas que Google App Engine está ocasionando con sus limitaciones a los desarrolladores de aplicaciones web. En especial los siguientes puntos están resultando especialmente problemáticos:

  • Límite de 1MB en las estructuras de datos. Ni siquiera permite descargar un archivo estático de un tamaño superior.
  • Las cuotas se manejan de forma que pueden hacer inaccesible una aplicación precisamente en el momento en que llegan más visitas. La cuota de CPU a corto plazo no funciona correctamente y no tiene sentido en su actual forma.
  • Existe un límite de acceso en las consultas más allá de la posición 1000, lo que unido a otro límite a devolver más de 1000 registros hace imposible acceder a registros de una tabla superiores a la posición 2000.
  • No incluye soporte para procesos de larga duración.
  • Se echa en falta un sistema de administración libre de todas las limitaciones y orientada a facilitar la gestión de la aplicación.
Alternativas como AppJet.com siguen estando disponibles y, aunque la marca Google está considerada una garantía, un producto que debería ser considerado como estrella de cara a la comunidad de desarrolladores no puede sufrir carencias tan graves.

Últimos links en indiza.com