combo/combo/apps/maps/static/js/combo.map.js

259 lines
11 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]];
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;
$.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});
}
});
// 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);
}
map.clustered_markers.addLayer(geo_json);
} else {
if (geojson_layer.leaflet_layer) {
geojson_layer.leaflet_layer.remove();
}
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');
}
}
});
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('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);
});
});