JQuery plugin for Google Map API.

El siguiente código es un plugin escrito[1] para integrar el portal web de un cliente con las API de Google Map[2].

Código Fuente.

/**
 * jquery.gmaps.js
 *
 * Mapas - GoogleMap API plugin for jquery
 *
 * @depends jquery.js
 *
 * @author    Jorge Rodriguez Suarez
 * @copyright (c) Continuum 2008.
 * @version   $Id$
 *
 * All rights reserved by Continuum.
 *
 */
$.gMap = {
	maps: {},
	mapNum: 1
};

$.fn.gMap = function(zoom, options) {

	// If we aren't supported, we're done
	if (!window.GBrowserIsCompatible || !GBrowserIsCompatible())
            return this;

	// Default values make for easy debugging
	var lat = $(this).attr("latitude") || 0;
	var lng = $(this).attr("longitude") || 0;
	if (!zoom) zoom = 15;

	// Sanitize options
	if (!options || typeof options != 'object') options = {};
	options.mapOptions = options.mapOptions || {};
	options.controls = options.controls || {};

	// Map all our elements
	return this.each(function() {
		// Make sure we have a valid id
		if (!this.id) this.id = "gMap" + $.gMap.mapNum++;
		// Create a map and a shortcut to it at the same time
		var map = $.gMap.maps[this.id] = new GMap2(this,
                    options.mapOptions);
		var latitude = parseFloat(lat);
		var longitude = parseFloat(lng);

        var marker = new GMarker(new GLatLng(latitude, longitude));
        var html = '<div style="padding-right:10px;">'
            + $(this).attr("title") + '</div>';

        // Center and zoom the map
       	map.setCenter(new GLatLng(latitude, longitude), zoom);
       	// add the title
        map.addControl(new GSmallMapControl());
        map.addOverlay(marker);

        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(html);
        });

        marker.openInfoWindowHtml(html);

       	// Add controls to our map
       	for (var i = 0; i < options.controls.length; i++) {
	       	var c = options.controls[i];
	       	eval("map.addControl(new " + c + "());");
       	}
    });

};

Ejemplo del uso:

Un div con la clase ‘gmap’, y los atributos title, latitude y longitude. Además un link con la clase ‘btn-gmap’. A continuación el código.

<a href="javascript:void(0)" class="btn-gmap">Ver mapa</a>

<div style="display:none; border:1px solid gray; height: 300px;
width: 400px;" id="mapa1" class="gmap" title="Ejemplo de Mapa"
latitude="-33.443244"
longitude="-70.633434">
</div>

y por último el código que genera el evento sobre el link para mostrar el mapa en el div…

/**
 * gmaps.achs.js
 *
 * Mapas ACHS - GMaps integration
 *
 * @depends jquery.js, jquery.gmaps.js
 *
 * @author    Jorge Rodriguez Suarez
 * @copyright (c) Continuum 2008.
 * @version   $Id$
 *
 * All right reserved by Continuum.
 *
 */
$(document).ready(function() {
	$('.btn-gmap').click(function (e) {
		$(".gmap").fadeIn('slow').gMap(15, {
			mapOptions: ['enableScrollWheelZoom',
                            'enableDoubleClickZoom',
                            'enableDragging'],
			controls: ['GSmallMapControl',
                            'GMapTypeControl']
		});
		e.preventDefault();
	});
});

[1] Basado en un plugin de http://dyve.net/
[2] http://code.google.com/intl/es-CL/apis/maps/

Uso de DSL para minimizar la complejidad.

El objetivo de un DSL tal como lo define Martin Fowler es ser un lenguaje de programación con el puntual propósito de resolver un tipo de problema específico (a diferencia de un lenguaje de propósito general). Ejemplos de DSL son CSS, SQL o HQL (Hibernate Query Language).

Esta entrada no es para introducir los lenguajes de dominio específico, existen buenas referencias en la web, como el sitio de Martin Fowler con algunos artículos sobre DSL e incluso un libro. Esta entrada es para contar que nos motivó a usar DSL en un proyecto.

Se trata de un “catálogo de servicios”. Hay servicios de diferente naturaleza (Web Services, MQ, Stored Procedure, REST, etc). Al registrar un nuevo servicio necesitamos agregar metadata sobre las operaciones que pueden ejecutarse. La metadata puede ser usada por autómatas para generar invocaciones dinámicas de los diferentes servicios. Por ejemplo, un servicio de ruteo en una arquitectura ESB puede leer la metadata de un servicio MQ para saber en que cola colocar el mensaje y si además debe colocar información de contexto extra, etc.

En la forma clásica del diseño de la aplicación (el catálogo), uno pudiera crear un mantenedor de servicios donde la metadata es separada en objetos (Operaciones, Parámetros, Resultado, Excepciones, PreCondiciones, PostCondiciones, etc.) y usar algun CRM como Hibernate para generar la persistencia. Por otro lado tener una capa de servicios que permita generar la metadata desde estas operaciones (quizás usar flexjson para serializar a JSON el árbol de objetos que retorne Hibernate de la definición de los hbm (hibernate mapping). Pero esta es la vía complicada que nos obligan a tomar lenguajes antinaturales y antiexpresivos como java y todas las APIs y frameworks que se han gestado a su alrededor.

El diseño de lenguajes de programación como Ruby permite escribir código como:

class Comment < ActiveRecord::Base
    belongs_to :post
    validates_precence_of :body, :email, :author
end

Este código es un DSL escrito en Ruby en una forma natural (un comentario pertenece a un post y debe tener al menos body, email y autor).

En vez de usar un árbol de objetos complejos para definir la metadata y complicarnos la existencia con implementaciones CRM o código JDBC complejos, nuestro diseño se basó en las siguientes consideraciones:

  1. Usa un DSL interno para definir la metadata.
  2. El lenguaje usado para crear el DSL fue Javascript por ser dinámico (lenguajes dinámicos son mejores para escribir DSL), por ser expresivo, por ser sencillo; y principalmente porque puede ejecutarse de forma nativa en la web (donde corren la mayoría de las aplicaciones hoy en día).
  3. La notación usada para escribir la especifcación del DSL es JSON porque “…It is easy for humans to read and write. It is easy for machines to parse and generate…” y (personalmente por estar cansados de parsear XML).
  4. El DSL se inserta tal como viene en la columna de metadata.
  5. El cliente de los servicios de persistencia crea la metadata (siguiendo la especificación del DSL).
  6. El cliente de los servicios de persistencia es responsable de parsear el DSL en busca de datos (Por ejemplo el servicio de ruteo del ESB es reponsable de extraer la cola donde colocar el mensaje). En el caso de usar Javascript, el parseo es nativo por usarse JSON. Para el caso de Python[1] o Ruby[2] puede usarse un parser JSON (es sencillo por ser lenguajes dinámicos). En el caso de Java puede usarse Rinho para dar soporte Javascript y parsear en forma natural el DSL.

La especificación del DSL para el catálogo aún esta en proceso de definición. Actualizaré esta entrada con ejemplos del DSL y códigos de parseo cuando este listo.

Plus: Un excelente ejemplo del uso de DSL y Metaprogramming puede ser encontrado en este blog y su inspiración en esta librería.

[1].- SimpleJson o The Standard Python Library

[2].- JSON Implementation for Ruby.

Comet y Web Socket. Un enfoque diferente a Ajax

Ajax es el estándar de facto para construir RIA (del acrónimo en ingles Rich Internet Application). Es la tecnología soportada por todos los browsers modernos (W3C) y la base de la mayoría de los frameworks JavaScripts (digase prototypejs, jQuery, Dojo o extjs, por nombrar los más conocidos) y de otras tecnologías como Flex, GWT o M$ Silverlight. Ajax ha permitido dar un nuevo enfoque al WWW y está colaborando en la creación de la nueva burbuja de internet con la versión 2.0 de la web. Ha permitido también ver al browser como una plataforma donde se pueden ejecutar aplicaciones complejas que minimizan el esfuerzo del usuario y hace más agradable su uso.

No obstante Ajax no es la única opción. A continuación hablaremos de Comet y WebSocket como opciones substitutas para la contrucción de aplicaciones con interfaces y comportamiento complejos que en el caso de Comet no gozan de la popularidad de Ajax ni se ha convertido en estándar por no tener una espalda empresarial como Microsoft[1], Google o Yahoo!. El caso de Web Socket es diferente por haber nacido como parte de una especificación creada y en desarrollo por parte de W3C.

Comet:

Alex Russell (creador de Dojo[2]) descubre una nueva forma de comunicación ‘no estándar’ entre el browser y el servidor usado por aplicaciones como Google Talk, Meebo o JotLive (ahora de Google) diferente a la tradicional Ajax y decide denominarla Comet como una forma de poder referenciarla a futuro.

La diferencia de Comet con Ajax es que en Ajax, las peticiones de ejecución en el server nacen en el browser (la dirección es la tradicional, del browser al servidor). En Comet sin embargo se abre una linea de comunicación entre el browser y el server, reduciendo la latencia de enviar paquetes desde el browser cada vez que se necesite un requerimiento y permitiendo que sea el server quien envie los paquetes al browser de forma autónoma (la comunicación es bidireccional, ahora el servidor también puede enviar peticiones al browser). A continuación se ilustra la diferencia entre las formas de comunicación del enfoque Ajax vs Comet.

Comet

Una aplicación Comet puede enviar datos al browser en cualquier momento, lo que permite crear aplicaciones más “real time” (por ejemplo monitoreo o colaboración online entre usuarios) a diferencia de Ajax donde el browser encola las peticiones enviadas al servidor de forma asíncrona.

Dado que Comet no está contruida sobre la base de comunicación estándar HTTP Request/Response es necesario instalar componentes de parte del server. Apache provee un módulo ‘comet-ready’ en su versión 2.2, existen también soluciones como Twisted (para desarrollos en python), o POE (para perl), la lista aumenta a medida que Comet se convierte en una opción popular.

HTML 5 WebSocket:

Web Socket es la alternativa estándar (escrita desde cero) para la especificación de la versión 5 del lenguaje HTML ( que en su versión expresada en XML se podrá llamar XHTML ) y por tanto con implementación nativa para los browsers que cumplan dicha especificación.

La diferencia que da valor agregado a Web Socket ( a parte de ser estándar ) radica en que provee una conexión duplex entre el browser y el server con una sola conexión TCP/IP (a diferencia de Comet que abre conexiones para cada requerimiento) y por otro lado genera pocos headers HTTP en los mensajes ( a diferencia de Comet que se basa en escribir mucha información en el header haciendo más pesados los mensajes). Además el protocolo de transporte que usa Web Socket puede ser usado en una diversidad de clientes (e.g. JavaScript, Adobe Flex, JavaFX, Microsoft Silverlight, etc.) sin usar transformación de mensajes a diferencia de Comet que usa el protocolo Bayeux o JSON de la parte cliente, requeriendo transformación cuando el server trabaja con otro protocolo como JMS, XMPP o IMAP.

Conclusiones

Ajax no es la única alternativa técnica para la comunicación entre el browser y el server cuando se desarrollan RIA. Existen opciones como Comet ( usadas por aplicaciones como Google Talk, o Meebo ) y el futuro y prometedor estándar Web Socket de la especificación HTML versión 5.0.

1.- Microsoft se acredita la invención de Ajax con su implementación de XMLHTTP a finales de los 90 mientras escribían la interface web del MS Exchange Server 2000.

2.- Dojo fue diseñado con soporte para Comet a traves de su interfaz dojo.io.bind() (Ver Dojo toolkit para más información.)

« Entradas Anteriores

Conócenos

Tel: +56 2 9341951

e-mail: info@continuum.cl

Copyright © 2010 Continuum Ltda.
Coronel Pereira 72. Oficina 903. Las Condes. Santiago. Chile