319 lines
14 KiB
JavaScript
319 lines
14 KiB
JavaScript
$(function() {
|
|
L.Map.include(
|
|
{
|
|
init_geojson_layers: function(layers) {
|
|
if (Array.isArray(layers)) { // backward compatibility
|
|
this.geojson_layers = Object();
|
|
for (var i=0; i<layers.length; i++) {
|
|
this.geojson_layers[layers[i].slug] = Object();
|
|
this.geojson_layers[layers[i].slug].url = layers[i].url;
|
|
}
|
|
} else {
|
|
this.geojson_layers = layers;
|
|
}
|
|
},
|
|
|
|
load_geojson_layers: function(callback) {
|
|
var layer_slugs = Object.keys(this.geojson_layers);
|
|
this.bounds = null;
|
|
for (var i=0; i<layer_slugs.length; i++) {
|
|
var layer = this.geojson_layers[layer_slugs[i]];
|
|
if (typeof layer.enabled === 'undefined') {
|
|
layer.enabled = true;
|
|
}
|
|
layer.status = 'loading';
|
|
this.add_geojson_layer(callback, layer);
|
|
}
|
|
},
|
|
|
|
add_geojson_layer: function(callback, geojson_layer) {
|
|
var map = this;
|
|
var $map_widget = $(map.getContainer());
|
|
var cell = $map_widget.parents('div.cell')[0];
|
|
var geojson_url = geojson_layer.url;
|
|
|
|
if (map.query_string) {
|
|
geojson_url = geojson_url + '?' + map.query_string;
|
|
}
|
|
|
|
$.getJSON(geojson_url).done(
|
|
function(data) {
|
|
var geo_json = L.geoJson(data, {
|
|
onEachFeature: function(feature, layer) {
|
|
$(cell).trigger('combo:map-feature-prepare',
|
|
{'feature': feature, 'layer': layer, 'geojson_layer': geojson_layer});
|
|
var marker_behaviour_onclick = $map_widget.data('marker-behaviour-onclick');
|
|
if (marker_behaviour_onclick === 'display_data') {
|
|
var popup = '';
|
|
if (feature.properties.display_fields) {
|
|
var popup = '';
|
|
$.each(feature.properties.display_fields, function(idx, field) {
|
|
var $popup_field = $('<div><div class="popup-field property-' + field.varname + '"><span class="field-label"></span><span class="field-value"></span></div></div>');
|
|
$popup_field.find('.field-label').text(field.label);
|
|
if (field.html_value){
|
|
$popup_field.find('.field-value').html(field.html_value);
|
|
} else {
|
|
$popup_field.find('.field-value').text(field.value);
|
|
}
|
|
popup += $popup_field.html();
|
|
});
|
|
} else {
|
|
var ordered_keys = geojson_layer.properties;
|
|
if (! ordered_keys) {
|
|
ordered_keys = Object.keys(properties).sort();
|
|
}
|
|
var properties = feature.properties;
|
|
$.each(ordered_keys, function(idx, field) {
|
|
// exclude object type properties
|
|
if (typeof(properties[field]) !== 'object') {
|
|
var $popup_field = $('<div><div class="popup-field property-' + field + '"></span><span class="field-value"></span></div></div>');
|
|
$popup_field.find('.field-value').text(properties[field]);
|
|
popup += $popup_field.html()
|
|
}
|
|
});
|
|
}
|
|
layer.bindPopup(popup);
|
|
}
|
|
},
|
|
pointToLayer: function (feature, latlng) {
|
|
var markerStyles = "background-color: " + geojson_layer.marker_colour + ";";
|
|
marker = L.divIcon({
|
|
iconAnchor: [0, 0],
|
|
popupAnchor: [5, -45],
|
|
html: '<span class="layer-' +
|
|
geojson_layer.slug +
|
|
'" style="' + markerStyles + '"><i class="leaflet-marker-icon ' +
|
|
geojson_layer.icon + '" style="color:' +
|
|
geojson_layer.icon_colour +'"></i></span>'
|
|
});
|
|
return L.marker(latlng, {icon: marker});
|
|
},
|
|
style: function (feature) {
|
|
return {weight: 2, color: geojson_layer.marker_colour, fillColor: geojson_layer.marker_colour};
|
|
}
|
|
});
|
|
|
|
// track global marker bounds
|
|
var bounds = geo_json.getBounds();
|
|
if (bounds.isValid()) {
|
|
if (!map.bounds) {
|
|
map.bounds = L.latLngBounds(bounds);
|
|
} else {
|
|
map.bounds.extend(bounds);
|
|
}
|
|
}
|
|
|
|
if ($map_widget.data('group-markers')) {
|
|
if (geojson_layer.leaflet_layer) {
|
|
map.clustered_markers.removeLayer(geojson_layer.leaflet_layer);
|
|
}
|
|
if (geojson_layer.enabled)
|
|
map.clustered_markers.addLayer(geo_json);
|
|
} else {
|
|
if (geojson_layer.leaflet_layer) {
|
|
geojson_layer.leaflet_layer.remove();
|
|
}
|
|
if (geojson_layer.enabled)
|
|
geo_json.addTo(map);
|
|
}
|
|
geojson_layer.leaflet_layer = geo_json;
|
|
if (callback) {
|
|
callback(geo_json);
|
|
}
|
|
geojson_layer.status = 'loaded';
|
|
}).fail(function(jqxhr, textStatus, error) {
|
|
geojson_layer.status = 'error';
|
|
}).always(function() {
|
|
map.trigger_markers_if_ready();
|
|
});
|
|
},
|
|
|
|
trigger_markers_if_ready: function() {
|
|
var map = this;
|
|
var $map_widget = $(map.getContainer());
|
|
var cell = $map_widget.parents('div.cell')[0];
|
|
var layer_slugs = Object.keys(this.geojson_layers);
|
|
var loading = 0;
|
|
for (var i=0; i<layer_slugs.length; i++) {
|
|
var layer = this.geojson_layers[layer_slugs[i]];
|
|
if (layer.status == 'loading') loading++;
|
|
}
|
|
if (loading == 0) {
|
|
$(cell).trigger('combo:map-markers-ready');
|
|
}
|
|
},
|
|
|
|
each_marker: function(callback) {
|
|
// iterate over all markers, with context(this) being set to relative
|
|
// geojson_layer.
|
|
var layer_slugs = Object.keys(this.geojson_layers);
|
|
for (var i=0; i<layer_slugs.length; i++) {
|
|
var layer = this.geojson_layers[layer_slugs[i]];
|
|
if (layer.leaflet_layer) {
|
|
layer.leaflet_layer.eachLayer(callback, layer);
|
|
}
|
|
}
|
|
},
|
|
|
|
disable_layer: function(slug) {
|
|
var layer = this.geojson_layers[slug];
|
|
var group = this.clustered_markers || this;
|
|
if (layer && layer.leaflet_layer) {
|
|
layer.enabled = false;
|
|
group.removeLayer(layer.leaflet_layer);
|
|
}
|
|
},
|
|
|
|
enable_layer: function(slug) {
|
|
var layer = this.geojson_layers[slug];
|
|
var group = this.clustered_markers || this;
|
|
if (layer && layer.leaflet_layer) {
|
|
layer.enabled = true;
|
|
group.addLayer(layer.leaflet_layer);
|
|
}
|
|
},
|
|
|
|
disable_all_layers: function() {
|
|
var layer_slugs = Object.keys(this.geojson_layers);
|
|
for (var i=0; i<layer_slugs.length; i++) {
|
|
this.disable_layer(layer_slugs[i]);
|
|
}
|
|
},
|
|
|
|
enable_all_layers: function() {
|
|
var layer_slugs = Object.keys(this.geojson_layers);
|
|
for (var i=0; i<layer_slugs.length; i++) {
|
|
this.enable_layer(layer_slugs[i]);
|
|
}
|
|
},
|
|
|
|
});
|
|
|
|
function render_map(cell) {
|
|
var $map_widget = $(cell).find('div.combo-cell-map');
|
|
var map_options = Object();
|
|
var initial_zoom = parseInt($map_widget.data('init-zoom'));
|
|
if (! isNaN(initial_zoom)) {
|
|
map_options.zoom = initial_zoom;
|
|
} else {
|
|
map_options.zoom = 13;
|
|
}
|
|
var init_state = $map_widget.data('init-state');
|
|
var max_zoom = parseInt($map_widget.data('max-zoom'));
|
|
if (!isNaN(max_zoom)) {
|
|
map_options.maxZoom = max_zoom;
|
|
} else {
|
|
map_options.maxZoom = 19;
|
|
}
|
|
var min_zoom = parseInt($map_widget.data('min-zoom'));
|
|
if (!isNaN(min_zoom)) map_options.minZoom = min_zoom;
|
|
map_options.zoomControl = false;
|
|
var latlng = [$map_widget.data('init-lat'), $map_widget.data('init-lng')];
|
|
if ($map_widget.data('max-bounds-lat1')) {
|
|
map_options.maxBounds = L.latLngBounds(
|
|
L.latLng($map_widget.data('max-bounds-lat1'), $map_widget.data('max-bounds-lng1')),
|
|
L.latLng($map_widget.data('max-bounds-lat2'), $map_widget.data('max-bounds-lng2')))
|
|
}
|
|
map_options.gestureHandling = true;
|
|
var map = L.map($map_widget[0], map_options);
|
|
if ($map_widget.data('query-string')) {
|
|
map.query_string = $map_widget.data('query-string');
|
|
}
|
|
if ($map_widget.data('group-markers')) {
|
|
var disable_clustering_at_zoom = $map_widget.data('disable-clustering-at-zoom');
|
|
if (disable_clustering_at_zoom) {
|
|
disable_clustering_at_zoom = parseInt(disable_clustering_at_zoom);
|
|
} else {
|
|
disable_clustering_at_zoom = null;
|
|
}
|
|
map.clustered_markers = L.markerClusterGroup({
|
|
showCoverageOnHover: false,
|
|
zoomToBoundsOnClick: true,
|
|
disableClusteringAtZoom: disable_clustering_at_zoom,
|
|
removeOutsideVisibleBounds: true,
|
|
iconCreateFunction: function (cluster) {
|
|
var icon_size = 60;
|
|
var childCount = cluster.getChildCount();
|
|
var icon_html = '<div><span>' + childCount + '</span></div>';
|
|
var c = ' marker-cluster-';
|
|
if (childCount < 10) {
|
|
c += 'small';
|
|
} else if (childCount < 100) {
|
|
c += 'medium';
|
|
} else {
|
|
c += 'large';
|
|
}
|
|
return new L.DivIcon({html: icon_html, className: 'marker-cluster' + c, iconSize: new L.Point(icon_size, icon_size)});
|
|
}
|
|
});
|
|
map.addLayer(map.clustered_markers);
|
|
}
|
|
if ($map_widget.data('draggable') === false) {
|
|
map.dragging.disable();
|
|
}
|
|
var map_controls_position = $('body').data('map-controls-position') || 'topleft';
|
|
if (map_options.maxZoom != map_options.minZoom) {
|
|
new L.Control.Zoom({
|
|
position: map_controls_position,
|
|
zoomInTitle: gettext('Zoom in'),
|
|
zoomOutTitle: gettext('Zoom out')
|
|
}).addTo(map);
|
|
}
|
|
var gps_control = null;
|
|
if (L.Control.Gps && $map_widget.data('include-geoloc-button')) {
|
|
gps_control = new L.Control.Gps({
|
|
position: map_controls_position,
|
|
tooltipTitle: gettext('Display my position')});
|
|
map.addControl(gps_control);
|
|
}
|
|
|
|
$map_widget[0].leaflet_map = map;
|
|
map.setView(latlng, map_options.zoom);
|
|
|
|
if (init_state == 'device-location') {
|
|
$map_widget.addClass('waiting-for-geolocation');
|
|
map.locate({timeout: 10000, maximumAge: 300000, enableHighAccuracy: false});
|
|
map.on('locationfound', function(e) {
|
|
$map_widget.removeClass('waiting-for-geolocation');
|
|
if (map_options.maxBounds && ! map_options.maxBounds.contains(e.latlng)) {
|
|
/* ouf of bounds, keep map centered on default position */
|
|
return;
|
|
}
|
|
map.setView(e.latlng, map_options.zoom);
|
|
if (gps_control) {
|
|
gps_control.addLayer();
|
|
}
|
|
});
|
|
map.on('locationerror', function(e) {
|
|
$map_widget.removeClass('waiting-for-geolocation');
|
|
$map_widget.addClass('geolocation-error');
|
|
});
|
|
}
|
|
|
|
var map_id = $map_widget.data('cell-id');
|
|
var tiles_layers = window['tiles_'+map_id];
|
|
$.each(tiles_layers, function(idx, layer) {
|
|
L.tileLayer(
|
|
layer.tile_urltemplate,
|
|
{
|
|
attribution: layer.map_attribution,
|
|
opacity: layer.opacity,
|
|
maxZoom: map_options.maxZoom
|
|
}
|
|
).addTo(map);
|
|
});
|
|
map.bounds = null;
|
|
map.init_geojson_layers(window['geojson_'+map_id]);
|
|
if (init_state == 'fit-markers') {
|
|
$(cell).on('combo:map-markers-ready', function() {
|
|
map.fitBounds(map.bounds);
|
|
});
|
|
}
|
|
map.load_geojson_layers()
|
|
$(cell).trigger('combo:map-ready');
|
|
};
|
|
$('div.cell.map').each(function() {
|
|
render_map(this);
|
|
});
|
|
});
|