Noticias Weblogs Foros Wiki Código

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Sponsors

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin

Koalite's blog

Modificar una clase en Javascript: Eliminar los markers de Google Maps

Noviembre 24th, 2011 - [Enlace local]

Desde que empecé a jugar con javascript he ido aprendiendo muchas cosas nuevas, pero sin duda una de las más curiosas para alguien como yo, acostumbrado a lenguajes estáticos, ha sido la posibilidad de modificar las clases que ya existen.

En C#, si queremos cambiar el comportamiento de una clase tenemos disponibles varias técnicas, pero todas ellas implican crear una nueva clase:

Sin embargo, en Javascript podemos cambiar no sólo el comportamiento de una clase ya definida, sino hasta el de un objeto ya creado.

El problema: eliminar todos los marcadores de un mapa

Para profundizar un poco en esto vamos a ver un ejemplo práctico: jugando con las APIs de Google Maps quería buscar una forma de eliminar todos los marcadores (markers) que había añadido sobre un mapa para indicar puntos de interés. Aparentemente esto era algo sencillo en la versión 2, pero no tan fácil en la versión 3.

Como siempre he pensado que es importante saber lo que uno está haciendo, en lugar de copiar el código a ciegas el código de StackOverflow, decidí tratar de entenderlo.

El API original de Google Maps es algo así:

var map = new google.maps.Map(...);

// Para añadir un marker:
var marker = new google.maps.Marker({
    map: map,
    position: new google.maps.LatLng(3, 17),
    icon: 'img/marker.png',
    title: '¡Hola!'
});

// Para eliminar el marker:
marker.setMap(null);

Básicamente, al crear un Marker le asignamos un Map y el Marker se pinta sobre él. Cuando queremos eliminarlo, establecemos el Map del Marker a null y ya está. Fácil.

El problema es que Map no almacena ninguna referencia a los Markers que se han pintado sobre él, por lo que no es posible eliminarlos a menos que mantengamos externamente una lista con todos los Markers que hemos ido añadiendo. Esa es una solución viable, pero queda feo. Podemos hacerlo mejor.

La solución: modificar las clases Marker y Map

Volvemos al principio del artículo, la modificación de clases en javascript, porque esa es justo la solución más elegante al problema. Vamos a modificar las clases Map y Marker para que entre ambas mantegan la lista de markers de forma interna y así podamos luego borrarlos limpiamente.

En javascript podemos modificar un objeto con sólo añadirle propiedades de cualquier tipo, y teniendo en cuenta que las funciones son un tipo más en javacript, eso quiere decir que podemos añadirle sin ningún problema nuevos métodos e incluso sobreescribir los que ya existen.

var lucas = {
    name: 'lucas',
    sing: function() {
        console.log('estoy cantando');
    },
};

lucas.dance= function() {
    console.log('estoy bailando');
}

// Ahora lucas sabe cantar y bailar
lucas.sing()
lucas.dance()

Podemos añadir las propiedades a un objeto especial (el prototipo de la clase) para que la modificación afecte a todos los objetos de una clase (incluyendo los que ya se han creado y los que se crearán):

var Person = function(name) {
    this.name = name;
};

var lucas = new Person('lucas');
// Aquí lucas no sabe hacer nada todavía

Person.prototype.dance = function() {
    console.log('¡mira como bailo!);
};

// Ahora lucas ya sabe bailar
lucas.dance();

Con estos, ejem, profundos conocimientos de como funciona el prototipado en javascript, podemos lanzarnos a hacer nuestra modificación a Map y Marker:

(function() {
    // Añado a Map un array con los markers que contiene
    google.maps.Map.prototype.markers = new Array();

    // Añado a Map un método clearMakers que borrar los markers
    google.maps.Map.prototype.clearMarkers = function() {
        for (var i = 0; i < this.markers.length; i++) {
            this.markers[i].setMap(null);
        }
        this.markers = new Array();
	};

    // Reescribo el método setMap de Marker para que cuando se
    // asigne el map se guarde en la propiedad markers del map
    // OJO: almaceno en oldSetMap el antiguo método setMap
    //      para poder seguir utilizándolo
    var oldSetMap = google.maps.Marker.prototype.setMap;
    google.maps.Marker.prototype.setMap = function(map) {
        if (map) {
            map.markers.push(this);
        }
        oldSetMap.call(this, map);
    }
})();

Creo que con los comentarios queda bastante claro lo que está pasando. Un par de cosas destacables:

Lo interesante

Para mi lo más interesante de este ejemplo no es cómo borrar los Markers (aunque en su momento era el problema que quería resolver), sino lo diferente que es la solución en javascript a la que hubiera sido en un lenguaje estático.

La idea de poder modificar "al vuelo" clases es una técnica muy poderosa, pero como decía el tío Ben: un gran poder conlleva una gran resposabilidad. Me da la impresión de que esta técnica hay que aplicarla con cuidado y cariño o puede causar caos y destrucción.

Compartir enlace:
Facebook Twitter Email

» Leer más, comentarios, etc...

Información legal y técnica