Unas notas para la actualización de Google Reader

“Actualización” es un eufemismo muy informático. Lo que ha ocurrido con Google Reader, uno de los lectores de noticias (feeds) más populares, a principios de esta semana es más bien una transformación. A peor. No entraré en consideraciones estéticas aunque el nuevo diseño, gastando espacio vertical como un Cadillac de los sesenta engullía combustible, daña la usabilidad en plataformas pequeñas —los netbooks, hoy, siguen teniendo pantallas de 600 puntos de altura. Me limitaré a comentar cómo la eliminación de las características de red social han impactado mi vida cotidiana en una plataforma completamente distinta, Twitter. ¡Con lo que me quejé de ellas algo después de que las incorporaran en la prehistoria… hace dos años! Continue reading “Unas notas para la actualización de Google Reader”

Anuncios

Valid XHTML within Blogger…

… In your dreams! Google seems to maintain an attitude of Olympic disdain to standards. While we are all busy booing Microsoft for their trademarked Embrace&Extinguish move, Google can and does get off with just a collective pat on the back. I understand —and share— the Google fascination, as I understood —and shared, much to my current chagrin— the Microsoft fascination that was prevalent on the nineties. But ‘standards are good’ is as powerful a as it can be, and moreover, it’s actually true.

If Google bit the bullet and implemented the rather meager changes needed to make possible actual XHTML compliance into Blogger’s template engine, very few bloggers would take the task of ensuring their pages’ validity upon themselves. A wasted effort? Let’s have a look from the other side: I feel I’m denied a freedom when I can’t comply, no matter how hard I try, with a standard I consider as a basic building block of the (some call this Web 3.0, but given the current state of affairs, it might well be called Web Millenium Edition or, even worse, Web Vista).

I am not alone. I want my blog, unimportant as it might be, readable by people and machines alike; and not just by smart ones like Google employees and Googlebots. I want maximum accesibility without having to cast undocumented incantations (versus W3C documented ones, I mean). I know standards are pointless, difficult and boring, and Google is all about instant gratification, do-what-I-mean interfaces and having fun. I know standards are for nerds. Unattractive, glamour-less nerds. Please, let me try.

Aviación… ¿expañola?


No hay como el mes de agosto para encontrar bromas en Google Earth. Pero a cada uno lo suyo: los datos de redes de transporte reflejados en Google son aportados, generalmente, por los transportistas. Lo que indica que la broma surge de entre las paredes de Metro de Madrid. ¿Será una señal, un menxaje xecreto de su dueña (de un cuarto, para ser exactos), doña “Experanza”? ¿Quién quiere realmente dextruir Expaña?

Por cierto, muy interesante el GTFS. Competencia para TransXChange; otro acrónimo de tres letras con cuatro letras para aprender.

Cita del Día

Sobre estas líneas se debería ver (¿funciona?) mi último proyecto: la Cita del Día para Blogger. De hecho, debería poder instalarse en cualquier sitio. Sólo necesita que JQuery esté disponible en la página, aunque sería bastante fácil reescribir el código para eliminar la dependencia. Las citas están publicadas en una hoja de cálculo de Google Spreadsheets.

[¡Peligro! ¡Palabrería informática!] El protocolo implementado por las APIs de GData, como extensión de Atom, permite manipular documentos de todo pelaje alojados en los múltiples servicios de Google. Una pequeña adición, la posibilidad de disponer de los resultados en formato JSON, y más concretamente, como JSON evaluado en un script, permite superar gran parte de las limitaciones de seguridad impuestas por los navegadores sobre Ajax. Es posible así realizar cross-site scripting, incorporando contenidos de documentos disponibles mediante feeds de GData en páginas web, sin disponer de control sobre el servidor.

Necesitamos una hoja de cálculo publicada con dos columnas (citas y autores).

http://spreadsheets.google.com/pub?key=pK3d1irR7cVxUSt9KBb8GFw&output=html&gid=0&single=true&range=A1:B4

Un pequeño script permitirá extraer el contenido de esta hoja conociendo algunos de sus datos:

  • Su clave de publicación (key).
  • El identificador único de la página a publicar (una hoja puede tener varias páginas).
  • El rango de celdas del que se va a extraer la información.

Esos datos pueden obtenerse a partir de la URL de publicación de feeds que aparece en las “opciones adicionales de publicación” de la pestaña “Publicación” de una hoja de cálculo. Armados con la información apropiada, podemos programar algo interesante:

var CiteSpreadsheet = {
    'rows': 159,
    'getJsonUrl': function(idx) {
        var baseSpreadsheet = 'http://spreadsheets.google.com/feeds/';
        var feedType = 'cells/';
        var key = 'o06661241339204957995.1659223542184495700/';
        var sheetId = 'od6/';
        var feedAccess = 'public/basic?';
        var range = 'range=A' + idx + ":B" + idx;
        var output = '&alt=json-in-script';
        var callback = '&callback=CiteSpreadsheet.processJsonResponse';
        return baseSpreadsheet + feedType + key + sheetId + feedAccess + range + output + callback;
    },
    'createScriptElem': function(url) {
        var html = '<script type="text/javascript" src="' + url + '"></script>';
        $(html).appendTo('body');
    },
    'getIndex': function() {
        var today = new Date();
        var startDate = new Date(today.getYear(), 0, 1);
        var delta = today.getTime() - startDate.getTime();
        var dayOfYear = Math.ceil(delta / 86400000);
        return dayOfYear % CiteSpreadsheet.rows;
    },
    'processJsonResponse': function(jsonData) {
        var retrievedContent = "<span>" + jsonData.feed.entry[0].content.$t +
            " <cite>" + jsonData.feed.entry[1].content.$t + "</cite></span>";
        $(".cite").append(retrievedContent);
    }
};

CiteSpreadsheet.createScriptElem(
    CiteSpreadsheet.getJsonUrl(
        CiteSpreadsheet.getIndex()));

El objeto del código es insertar, dinámicamente, una marca <script> en el documento actual, que apunte mediante su atributo src a una URL específica de consulta válida para la hoja de cálculo deseada, con formato de salida json-in-script, lo que devuelve un script listo para ejecutar con los datos pedidos en un objeto (en el enlace anterior se describe su estructura; Firefox, Firebug y un punto de ruptura ayudan considerablemente).

El feed obtenido ofrecerá información sobre celdas concretas de la hoja en el rango An:Bn, donde n es el número de fila deseado. Como en la hoja hay 159 citas, para dar una diferente cada día calculamos el índice como el número del día actual dentro del año módulo el total de filas.

Por último, para incorporar la cita al DOM de la página, necesitamos un elemento al que anclarlo. Para ello, se incluye en la plantilla de la bitácora, en el lugar donde deba aparecer la cita, un módulo HTML/Javascript con el contenido

<span class="cite"/>

(podría valer un <div>). En otras plataformas de blogging esto se podrá hacer editando directamente la plantilla o de algún otro modo.

Quote of the Day

You should see over these lines the result of my last project: a Quote of the Day implementation for Blogger It should be a piece of cake to port to other blogging platforms: the only requirement for the code to work is to have a recent version of the JQuery Javascript library loaded. Rewriting the code to eliminate that dependency should also be easy. Quips are published on Google Spreadsheets.

[Warning! Buzzword-enabled text ahead!] GData APIs implement an Atom extension that enables remote document querying and editing. What’s more, query results can be obtained as evaluated JSON objects; this technique allows to bypass most cross-site scripting security constraints, so Ajax widgets can be implemented without control over the server side.

We will need a published spreadsheet sporting quips and authors in two columns.

http://spreadsheets.google.com/pub?key=pK3d1irR7cVxUSt9KBb8GFw&output=html&gid=0&single=true&range=A1:B4

A tiny little script will get us the sheet’s contents. We only have to look for these pieces of information in order to make it work:

  • Publishing key.
  • Unique identifier for the desired sheet (a spreadsheet is organized as a book, so it can contain several sheets).
  • Desired cell range.

These can be obtained from the feed publishing URL that appears in Publish/More publishing options in the Google Spreadsheets interface. There goes the script:

var CiteSpreadsheet = {
    'rows': 159,
    'getJsonUrl': function(idx) {
        var baseSpreadsheet = 'http://spreadsheets.google.com/feeds/';
        var feedType = 'cells/';
        var key = 'o06661241339204957995.1659223542184495700/';
        var sheetId = 'od6/';
        var feedAccess = 'public/basic?';
        var range = 'range=A' + idx + ":B" + idx;
        var output = '&alt=json-in-script';
        var callback = '&callback=CiteSpreadsheet.processJsonResponse';
        return baseSpreadsheet + feedType + key + sheetId + feedAccess + range + output + callback;
    },
    'createScriptElem': function(url) {
        var html = '<script type="text/javascript" src="' + url + '"></script>';
        $(html).appendTo('body');
    },
    'getIndex': function() {
        var today = new Date();
        var startDate = new Date(today.getYear(), 0, 1);
        var delta = today.getTime() - startDate.getTime();
        var dayOfYear = Math.ceil(delta / 86400000);
        return dayOfYear % CiteSpreadsheet.rows;
    },
    'processJsonResponse': function(jsonData) {
        var retrievedContent = "<span>" + jsonData.feed.entry[0].content.$t +
            " <cite>" + jsonData.feed.entry[1].content.$t + "</cite></span>";
        $(".cite").append(retrievedContent);
    }
};

CiteSpreadsheet.createScriptElem(
    CiteSpreadsheet.getJsonUrl(
        CiteSpreadsheet.getIndex()));

What the code does, in short, is dynamically inserting a <script> tag in the document, with its src attribute pointing to a specific query URL for the spreadsheet. Output format should be json-in-script; this returns a ready-to-execute script that wraps data in a Javascript object. Its general format is described in the previous link, but Firefox, Firebug and a judicious break point go all the way to get a hold on the gory details.

We’ve got a feed with information about certain cells (range An:Bn, where n is a row index). As the sheet contains 159 quotations, in order to provide a different one daily we compute that row index as the current day in year modulus total number of rows.

Last but not least, we need a hook; someplace in the blog template to anchor the newly retrieved content. We do so by adding to the template an HTML/Javascript module where we want our quip to appear. Its contents should be, at the very least,

<span class="cite"/>

(a <div> would also work —in fact, any container element with class cite). For other blogging platforms the same effect could be achieved by directly editing the template, or by some other means which I leave as exercise for the reader.

Trabaja conmigo

Tal vez esta información sea relevante para un amiguete que ha enviado su CV a Google: un conjunto de vídeos de YouTube en el que empleados de la compañía intentan parecer naturales, con mayor o menor éxito, mientras describen lo que para un 99,9999% de la población mundial con unos estudios o experiencia remotamente relacionados es un sueño inalcanzable.

Si algo traslucen los vídeos es, precisamente, la cualidad acogedora y absorbente como hogar para geeks del googlespacio. Deberían aprender esas empresas, generalmente del sector tecnológico, que buscan empleados con el mayor número posible de esta lista de cualidades:

  • Joven. Menor de treinta. Si puede ser, menor de veinticinco. Cuanto más joven más barato y manejable.
  • Con muchos estudios. Si es posible, todos. 20 años de experiencia en Java, como poco.
  • Soltero. Idealmente, no tan feo como para que al jefe le de asco mirarte, pero sí lo suficiente como para no comerse una rosca en años.
  • Desplazados, viviendo con seres del mismo sexo en un piso compartido.

Si Google pide todo eso, al menos parece que da algo a cambio. Afortunadamente, parece que incluso en este país pueden encontrarse otros huecos donde trabajar más o menos a gusto, destacar (aunque sea sólo un poquito) y tener una vida entre horas. Esta lista de las 50 empresas con más futuro de España da algunas pistas; creedme, lo sé por experiencia. No todo es trabajo basura.

El día después (del GDD)

Ahora que el Google Developer Day (GDD) ha pasado al otro lado de mi cono de luz, puedo recapitular con una ráfaga de críticas en orden aleatorio de importancia, espero que constructivas. Ayudaré a esto último indicando posibles remedios en cada punto:

  • Bisoñez, bisoñez, bisoñez. Fallos de organización, pequeños pero pervasivos.
    Remedio: más práctica. ¡A por el próximo GDD!
  • Tendencia a pastorear a la masa de asistentes. Quizá una consecuencia sugerida por la escasa edad media de dicha masa. Estoy acostumbrado a que me traten como a un adulto que puede saltarse una sesión porque tenga que hacer gestiones al teléfono, prolongar esa interesante conversación que ayuda a cuidar de la red de contactos o, llanamente, hacer novillos porque sí.
    Remedio: megafonía (poco intrusiva), control de tiempos y libertad con puño de hierro (se avisa de que no se podrá entrar a las sesiones con un retraso superior a 5 minutos, por ejemplo).
  • ¿Más de la mitad de las sesiones plenarias por teleconferencia? De acuerdo en que suena muy moderno, pero también suena muy barato. Sobre todo con la resolución del stream de vídeo, que hacía obligado interpretar las transparencias de los teleconferenciantes con una ouija a mano.
    Remedio: menos teleconferencias y más invitados.
  • Y hablando de teleconferencias, los maestros Larry y Sergey hicieron una tele-espantá (primicia mundial). Primero se cayó uno del cartel, luego el otro, y el testigo (también llamado brown) de la sustitución fue rodando pirámide abajo por el organigrama de Google. Hubo suerte de que no acabara en el cocinero (ya ha pasado algo así).
    Remedio: más planificación, más compromiso. Google se nutre de sus usuarios avanzados, después de todo.
  • El ancho de banda escaseó (¿paradójicamente?) obligando a un servidor a desenfundar la PCMCIA HSDPA de cuya marca no quiero acordarme, pero que por una vez funcionó como se esperaba.
    Remedio: esta es complicada. La WiFi en plan masivo es lo que tiene. Una buena cantidad de puntos de acceso, con los canales radio adecuadamente distribuidos, ayuda. Pero no es una panacea.
  • Los ejercicios propuestos en los talleres eran innecesariamente farragosos. O tal vez soy yo, que no tecleo a más de 130 pulsaciones por minuto, y mi CI no pasa de 250. Lo juro, ambas cosas son rigurosamente ciertas; tampoco mido más de 3 metros.
    Remedio: planificación. El público ha hecho un esfuerzo para asistir (lo sé, es dudoso con tanto yogurín que lo único que tendría es algún examen en la agenda, pero); hay que intentar no frustrarlo.

Seguro que me dejo algo en el tintero. Lo que no quiero es olvidarme de los aspectos positivos de la jornada y de las personas que los hicieron posibles, incluso dedicándome algo de tiempo. En particular, quiero dar las gracias a Mark Stahl, Tech Lead de las APIs GData, con quien sostuve una interesante conversación acerca del curso general de la tecnología de Google; a Enrique Muñoz, Product Manager de la AJAX Search API, a quien di (poco) la brasa con mis bibliolinks y algunos planes de futuro; y a las gentes de marketing: Bernardo Hernández (director en España) y mi tocaya Clara Rivera.