[#64,view/map] Add source docs and links from home page
This commit is contained in:
107
src/view-map.js
107
src/view-map.js
@@ -5,27 +5,29 @@ this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
|
||||
// ## Map view for a Dataset using Leaflet mapping library.
|
||||
//
|
||||
// This view allows to plot gereferenced documents on a map. The location
|
||||
// information can be provided either via a field with
|
||||
// [GeoJSON](http://geojson.org) objects or two fields with latitude and
|
||||
// longitude coordinates.
|
||||
//
|
||||
// Initialization arguments:
|
||||
//
|
||||
// * options: initial options. They must contain a model:
|
||||
//
|
||||
// {
|
||||
// model: {recline.Model.Dataset}
|
||||
// }
|
||||
//
|
||||
// * config: (optional) map configuration hash (not yet used)
|
||||
//
|
||||
//
|
||||
my.Map = Backbone.View.extend({
|
||||
|
||||
tagName: 'div',
|
||||
className: 'data-map-container',
|
||||
|
||||
latitudeFieldNames: ['lat','latitude'],
|
||||
longitudeFieldNames: ['lon','longitude'],
|
||||
geometryFieldNames: ['geom','the_geom','geometry','spatial','location'],
|
||||
|
||||
//TODO: In case we want to change the default markers
|
||||
/*
|
||||
markerOptions: {
|
||||
radius: 5,
|
||||
color: 'grey',
|
||||
fillColor: 'orange',
|
||||
weight: 2,
|
||||
opacity: 1,
|
||||
fillOpacity: 1
|
||||
},
|
||||
*/
|
||||
|
||||
template: ' \
|
||||
<div class="editor"> \
|
||||
<form class="form-stacked"> \
|
||||
@@ -81,6 +83,13 @@ my.Map = Backbone.View.extend({
|
||||
</div> \
|
||||
',
|
||||
|
||||
// These are the default field names that will be used if found.
|
||||
// If not found, the user will need to define the fields via the editor.
|
||||
latitudeFieldNames: ['lat','latitude'],
|
||||
longitudeFieldNames: ['lon','longitude'],
|
||||
geometryFieldNames: ['geom','the_geom','geometry','spatial','location'],
|
||||
|
||||
// Define here events for UI elements
|
||||
events: {
|
||||
'click .editor-update-map': 'onEditorSubmit',
|
||||
'change .editor-field-type': 'onFieldTypeChange'
|
||||
@@ -91,6 +100,8 @@ my.Map = Backbone.View.extend({
|
||||
var self = this;
|
||||
|
||||
this.el = $(this.el);
|
||||
|
||||
// Listen to changes in the fields
|
||||
this.model.bind('change', function() {
|
||||
self._setupGeometryField();
|
||||
});
|
||||
@@ -99,11 +110,13 @@ my.Map = Backbone.View.extend({
|
||||
self._setupGeometryField()
|
||||
self.render()
|
||||
});
|
||||
|
||||
// Listen to changes in the documents
|
||||
this.model.currentDocuments.bind('add', function(doc){self.redraw('add',doc)});
|
||||
this.model.currentDocuments.bind('remove', function(doc){self.redraw('remove',doc)});
|
||||
this.model.currentDocuments.bind('reset', function(){self.redraw('reset')});
|
||||
|
||||
// If the div is hidden, Leaflet needs to recalculate some sizes
|
||||
// If the div was hidden, Leaflet needs to recalculate some sizes
|
||||
// to display properly
|
||||
this.bind('view:show',function(){
|
||||
self.map.invalidateSize();
|
||||
@@ -114,6 +127,9 @@ my.Map = Backbone.View.extend({
|
||||
this.render();
|
||||
},
|
||||
|
||||
// Public: Adds the necessary elements to the page.
|
||||
//
|
||||
// Also sets up the editor fields and the map if necessary.
|
||||
render: function() {
|
||||
|
||||
var self = this;
|
||||
@@ -123,7 +139,6 @@ my.Map = Backbone.View.extend({
|
||||
$(this.el).html(htmls);
|
||||
this.$map = this.el.find('.panel.map');
|
||||
|
||||
// Setup editor fields
|
||||
if (this.geomReady && this.model.fields.length){
|
||||
if (this._geomFieldName){
|
||||
this._selectOption('editor-geom-field',this._geomFieldName);
|
||||
@@ -149,6 +164,15 @@ my.Map = Backbone.View.extend({
|
||||
return this;
|
||||
},
|
||||
|
||||
// Public: Redraws the features on the map according to the action provided
|
||||
//
|
||||
// Actions can be:
|
||||
//
|
||||
// * reset: Clear all features
|
||||
// * add: Add one or n features (documents)
|
||||
// * remove: Remove one or n features (documents)
|
||||
// * refresh: Clear existing features and add all current documents
|
||||
//
|
||||
redraw: function(action,doc){
|
||||
|
||||
var self = this;
|
||||
@@ -157,24 +181,27 @@ my.Map = Backbone.View.extend({
|
||||
|
||||
if (this.geomReady && this.mapReady){
|
||||
if (action == 'reset'){
|
||||
// Clear all features
|
||||
this.features.clearLayers();
|
||||
} else if (action == 'add' && doc){
|
||||
// Add one or n features
|
||||
this._add(doc);
|
||||
} else if (action == 'remove' && doc){
|
||||
// Remove one or n features
|
||||
this._remove(doc);
|
||||
} else if (action == 'refresh'){
|
||||
// Clear and rebuild all features
|
||||
this.features.clearLayers();
|
||||
this._add(this.model.currentDocuments.models);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* UI Event handlers */
|
||||
//
|
||||
// UI Event handlers
|
||||
//
|
||||
|
||||
// Public: Update map with user options
|
||||
//
|
||||
// Right now the only configurable option is what field(s) contains the
|
||||
// location information.
|
||||
//
|
||||
onEditorSubmit: function(e){
|
||||
e.preventDefault();
|
||||
if ($('#editor-field-type-geom').attr('checked')){
|
||||
@@ -191,6 +218,9 @@ my.Map = Backbone.View.extend({
|
||||
return false;
|
||||
},
|
||||
|
||||
// Public: Shows the relevant select lists depending on the location field
|
||||
// type selected.
|
||||
//
|
||||
onFieldTypeChange: function(e){
|
||||
if (e.target.value == 'geom'){
|
||||
$('.editor-field-type-geom').show();
|
||||
@@ -201,6 +231,14 @@ my.Map = Backbone.View.extend({
|
||||
}
|
||||
},
|
||||
|
||||
// Private: Add one or n features to the map
|
||||
//
|
||||
// For each document passed, a GeoJSON geometry will be extracted and added
|
||||
// to the features layer. If an exception is thrown, the process will be
|
||||
// stopped and an error notification shown.
|
||||
//
|
||||
// Each feature will have a popup associated with all the document fields.
|
||||
//
|
||||
_add: function(doc){
|
||||
|
||||
var self = this;
|
||||
@@ -237,6 +275,8 @@ my.Map = Backbone.View.extend({
|
||||
});
|
||||
},
|
||||
|
||||
// Private: Remove one or n features to the map
|
||||
//
|
||||
_remove: function(doc){
|
||||
|
||||
var self = this;
|
||||
@@ -253,6 +293,8 @@ my.Map = Backbone.View.extend({
|
||||
|
||||
},
|
||||
|
||||
// Private: Return a GeoJSON geomtry extracted from the document fields
|
||||
//
|
||||
_getGeometryFromDocument: function(doc){
|
||||
if (this.geomReady){
|
||||
if (this._geomFieldName){
|
||||
@@ -272,11 +314,13 @@ my.Map = Backbone.View.extend({
|
||||
}
|
||||
},
|
||||
|
||||
// Private: Check if there is a field with GeoJSON geometries or alternatively,
|
||||
// two fields with lat/lon values.
|
||||
//
|
||||
// If not found, the user can define them via the UI form.
|
||||
_setupGeometryField: function(){
|
||||
var geomField, latField, lonField;
|
||||
|
||||
// Check if there is a field with GeoJSON geometries or alternatively,
|
||||
// two fields with lat/lon values
|
||||
this._geomFieldName = this._checkField(this.geometryFieldNames);
|
||||
this._latFieldName = this._checkField(this.latitudeFieldNames);
|
||||
this._lonFieldName = this._checkField(this.longitudeFieldNames);
|
||||
@@ -284,6 +328,10 @@ my.Map = Backbone.View.extend({
|
||||
this.geomReady = (this._geomFieldName || (this._latFieldName && this._lonFieldName));
|
||||
},
|
||||
|
||||
// Private: Check if a field in the current model exists in the provided
|
||||
// list of names.
|
||||
//
|
||||
//
|
||||
_checkField: function(fieldNames){
|
||||
var field;
|
||||
var modelFieldNames = this.model.fields.pluck('id');
|
||||
@@ -296,17 +344,20 @@ my.Map = Backbone.View.extend({
|
||||
return null;
|
||||
},
|
||||
|
||||
// Private: Sets up the Leaflet map control and the features layer.
|
||||
//
|
||||
// The map uses a base layer from [MapQuest](http://www.mapquest.com) based
|
||||
// on [OpenStreetMap](http://openstreetmap.org).
|
||||
//
|
||||
_setupMap: function(){
|
||||
|
||||
this.map = new L.Map(this.$map.get(0));
|
||||
|
||||
// MapQuest OpenStreetMap base map
|
||||
var mapUrl = "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
|
||||
var osmAttribution = 'Map data © 2011 OpenStreetMap contributors, Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">';
|
||||
var bg = new L.TileLayer(mapUrl, {maxZoom: 18, attribution: osmAttribution ,subdomains: '1234'});
|
||||
this.map.addLayer(bg);
|
||||
|
||||
// Layer to hold the features
|
||||
this.features = new L.GeoJSON();
|
||||
this.features.on('featureparse', function (e) {
|
||||
if (e.properties && e.properties.popupContent){
|
||||
@@ -324,6 +375,8 @@ my.Map = Backbone.View.extend({
|
||||
this.mapReady = true;
|
||||
},
|
||||
|
||||
// Private: Helper function to select an option from a select list
|
||||
//
|
||||
_selectOption: function(id,value){
|
||||
var options = $('.' + id + ' > select > option');
|
||||
if (options){
|
||||
|
||||
Reference in New Issue
Block a user