4
votes

I am trying to build an application based on backbone.js and leaflet. Users could drag the map and see markers on the map. Markers can be selected by clicking on them. When selected they have to change their icon and the marker detailed information shown on a (not popup).

my backbone model consists of several entities:

Marker model contains latitude, longitude type, title, isSelected

Map model contains: center of the map, markers collection, selected marker

anyone has any idea how i could make this kind of functionality? how can i make leaflet markers as backbone views?

1

1 Answers

2
votes

Backbone views and the leaflet object model are not a perfect fit, because the markers aren't contained within a DOM element, which is what Backbone.View.el is supposed to represent. Markers do of course have an element (accessible via marker._icon), but it doesn't exist until the marker is rendered to the map.

That said, you can represent the markers with Backbone views, you just can't use the events or any el related functionality. I've implemented similar views successfully using OpenLayers, which has the same "problem", and it works fine.

I think this is easiest to explain with code:

//MarkerView has no element
App.Views.MarkerView = Backbone.View.extend({

    initialize: function(options) {
        //pass map instance to the marker
        this.map = options.map;
        //create the marker object
        this.marker = L.marker([this.model.get('longitude'), this.model.get('latitude')]);
    },

    render: function() {    
        //append marker to the map
        this.marker.addTo(this.map);

        //can't use events hash, because the events are bound
        //to the marker, not the element. It would be possible
        //to set the view's element to this.marker._icon after
        //adding it to the map, but it's a bit hacky.
        this.marker.on('click', this.onClick);
    },

    onClick: function() {
        alert("click");
    }
});

//MapView renders a map to the #map element
App.Views.MapView = Backbone.View.extend({
    id:"#map",
    render: function() {
        //render map element
        var map = this.map =  L.map(this.$el.attr('id'))
            .setView([this.model.get('centerLon'),  this.model.get('centerLat') ], 13)
            .addLayer(L.tileLayer(this.model.get('layerUrl'), { maxZoom: 18 }));

        //render each marker
        this.markerViews = this.model.get('markers').map(function(marker) {
            return new App.Views.MarkerView({model:marker, map:map}).render();
        });
    }
});

Here's a demo on JSFiddle.