Support optional and custom layers in hash URL

- extend layer control to get current active layers (and more)
- access layer control in hash instead of static initial list
- use ',' layer separator and encode layers individually, so that comma
in layer name gets encoded and is not mistaken as separator as with '-'
This commit is contained in:
Norbert Renner 2019-03-29 22:20:52 +01:00
parent dbc7fce91d
commit d83ffa3fbc
5 changed files with 101 additions and 74 deletions

View file

@ -90,14 +90,9 @@ BR.Map = {
BR.debug = BR.debug || {}; BR.debug = BR.debug || {};
BR.debug.map = map; BR.debug.map = map;
var layersAndOverlays = baseLayers;
for (var o in overlays) {
layersAndOverlays[o] = overlays[o];
}
return { return {
map: map, map: map,
layersControl: layersControl, layersControl: layersControl
layers: layersAndOverlays
}; };
} }

View file

@ -0,0 +1,60 @@
BR.ControlLayers = L.Control.Layers.extend({
getActiveLayers: function () {
var result = [];
for (var i = 0; i < this._layers.length; i++) {
var obj = this._layers[i];
if (this._map.hasLayer(obj.layer)) {
if (obj.overlay) {
result.push(obj);
} else {
result.unshift(obj);
}
}
}
return result;
},
removeActiveLayers: function () {
var removed = [];
for (var i = 0; i < this._layers.length; i++) {
var obj = this._layers[i];
if (this._map.hasLayer(obj.layer)) {
this._map.removeLayer(obj.layer);
removed.push(obj);
}
}
return removed;
},
getLayer: function (name) {
for (var i = 0; i < this._layers.length; i++) {
if (this._layers[i] && this._layers[i].name === name) {
return this._layers[i];
}
}
},
activateLayer: function (name) {
var obj = this.getLayer(name);
if (obj) {
this._map.addLayer(obj.layer);
}
return obj;
},
activateFirstLayer: function () {
for (var i = 0; i < this._layers.length; i++) {
var obj = this._layers[i];
if (!obj.overlay) {
this._map.addLayer(obj.layer);
break;
}
}
}
});

View file

@ -1,4 +1,4 @@
BR.LayersTab = L.Control.Layers.extend({ BR.LayersTab = BR.ControlLayers.extend({
previewLayer: null, previewLayer: null,
saveLayers: [], saveLayers: [],
@ -123,7 +123,7 @@ BR.LayersTab = L.Control.Layers.extend({
}; };
var onUncheckNode = function (e, data) { var onUncheckNode = function (e, data) {
var obj = this._getLayerObjByName(data.node.text); var obj = this.getLayer(data.node.text);
if (!obj) return; if (!obj) return;
this.removeLayer(obj.layer); this.removeLayer(obj.layer);
@ -131,7 +131,7 @@ BR.LayersTab = L.Control.Layers.extend({
if (this._map.hasLayer(obj.layer)) { if (this._map.hasLayer(obj.layer)) {
this._map.removeLayer(obj.layer); this._map.removeLayer(obj.layer);
if (!obj.overlay) { if (!obj.overlay) {
this.addFirstLayer(); this.activateFirstLayer();
} }
} }
@ -287,41 +287,17 @@ BR.LayersTab = L.Control.Layers.extend({
this.layersConfig.storeDefaultLayers(baseLayers, overlays); this.layersConfig.storeDefaultLayers(baseLayers, overlays);
}, },
addFirstLayer: function () {
for (var i = 0; i < this._layers.length; i++) {
var obj = this._layers[i];
if (!obj.overlay) {
this._map.addLayer(obj.layer);
break;
}
}
},
_getLayerObjByName: function (name) {
for (var i = 0; i < this._layers.length; i++) {
if (this._layers[i] && this._layers[i].name === name) {
return this._layers[i];
}
}
},
createLayer: function (layerData) { createLayer: function (layerData) {
var layer = this.layersConfig.createLayer(layerData); var layer = this.layersConfig.createLayer(layerData);
layer.options.zIndex = this._lastZIndex + 1; layer.options.zIndex = this._lastZIndex + 1;
return layer; return layer;
}, },
removeSelectedLayers: function () { saveRemoveActiveLayers: function () {
for (var i = 0; i < this._layers.length; i++) { this.saveLayers = this.removeActiveLayers();
var obj = this._layers[i];
if (this._map.hasLayer(obj.layer)) {
this._map.removeLayer(obj.layer);
this.saveLayers.push(obj);
}
}
}, },
restoreSelectedLayers: function (overlaysOnly) { restoreActiveLayers: function (overlaysOnly) {
for (var i = 0; i < this.saveLayers.length; i++) { for (var i = 0; i < this.saveLayers.length; i++) {
var obj = this.saveLayers[i]; var obj = this.saveLayers[i];
@ -333,7 +309,7 @@ BR.LayersTab = L.Control.Layers.extend({
} }
} else if (!obj.overlay) { } else if (!obj.overlay) {
// saved base layer has been removed during preview, select first // saved base layer has been removed during preview, select first
this.addFirstLayer(); this.activateFirstLayer();
} }
} }
} }
@ -361,7 +337,7 @@ BR.LayersTab = L.Control.Layers.extend({
// otherwise added overlay checkbox state doesn't update // otherwise added overlay checkbox state doesn't update
setTimeout(L.Util.bind(function () { setTimeout(L.Util.bind(function () {
this.removePreviewLayer(); this.removePreviewLayer();
this.restoreSelectedLayers(true); this.restoreActiveLayers(true);
this.deselectNode(); this.deselectNode();
}, this), 0); }, this), 0);
}, },
@ -369,7 +345,7 @@ BR.LayersTab = L.Control.Layers.extend({
showPreview: function (layer) { showPreview: function (layer) {
this._map.addLayer(layer); this._map.addLayer(layer);
if (!this.removePreviewLayer()) { if (!this.removePreviewLayer()) {
this.removeSelectedLayers(); this.saveRemoveActiveLayers();
this._map.once('baselayerchange', this.onBaselayerchange, this); this._map.once('baselayerchange', this.onBaselayerchange, this);
} }
this.previewLayer = layer; this.previewLayer = layer;
@ -378,7 +354,7 @@ BR.LayersTab = L.Control.Layers.extend({
hidePreview: function (layer) { hidePreview: function (layer) {
this._map.off('baselayerchange', this.onBaselayerchange, this); this._map.off('baselayerchange', this.onBaselayerchange, this);
this.removePreviewLayer(); this.removePreviewLayer();
this.restoreSelectedLayers(); this.restoreActiveLayers();
} }
}); });

View file

@ -19,7 +19,6 @@
function initApp(mapContext) { function initApp(mapContext) {
var map = mapContext.map, var map = mapContext.map,
layersControl = mapContext.layersControl, layersControl = mapContext.layersControl,
mapLayers = mapContext.layers,
search, search,
router, router,
routing, routing,
@ -311,9 +310,9 @@
}; };
urlHash.onHashChangeCb = onHashChangeCb; urlHash.onHashChangeCb = onHashChangeCb;
urlHash.onInvalidHashChangeCb = onInvalidHashChangeCb; urlHash.onInvalidHashChangeCb = onInvalidHashChangeCb;
urlHash.layers = mapLayers; urlHash.init(map, {
urlHash.map = map; layersControl: layersControl
urlHash.init(map, mapLayers); });
routingOptions.on('update', urlHash.onMapMove, urlHash); routingOptions.on('update', urlHash.onMapMove, urlHash);
nogos.on('update', urlHash.onMapMove, urlHash); nogos.on('update', urlHash.onMapMove, urlHash);

View file

@ -23,7 +23,12 @@
var zoom = parseInt(mapsArgs[0], 10), var zoom = parseInt(mapsArgs[0], 10),
lat = parseFloat(mapsArgs[1]), lat = parseFloat(mapsArgs[1]),
lon = parseFloat(mapsArgs[2]), lon = parseFloat(mapsArgs[2]),
layers = decodeURIComponent(mapsArgs[3]).split('-'), layersParam = mapsArgs[3],
// legacy support for '-' layer separator
layerSeparator = layersParam.indexOf('-') !== -1 ? '-' : this.options.layerSeparator,
layers = layersParam.split(layerSeparator).map(function (name) {
return decodeURIComponent(name);
}),
additional = args[1]; additional = args[1];
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) { if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
return false; return false;
@ -44,26 +49,13 @@
var center = map.getCenter(), var center = map.getCenter(),
zoom = map.getZoom(), zoom = map.getZoom(),
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)), precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
layers = []; layers = this.getActiveLayers();
//console.log(this.options);
var options = this.options;
//Check active layers
for(var key in options) {
if (options.hasOwnProperty(key)) {
if (map.hasLayer(options[key])) {
layers.push(key);
};
};
};
if (layers.length == 0) {
layers.push(Object.keys(options)[0]);
}
var params = [ var params = [
zoom, zoom,
center.lat.toFixed(precision), center.lat.toFixed(precision),
center.lng.toFixed(precision), center.lng.toFixed(precision),
encodeURIComponent(layers.join("-")) layers.join(this.options.layerSeparator)
]; ];
url = "#map=" + params.join("/"); url = "#map=" + params.join("/");
if (this.additionalCb != null) { if (this.additionalCb != null) {
@ -76,6 +68,9 @@
}, },
L.Hash.prototype = { L.Hash.prototype = {
options: {
layerSeparator: ','
},
map: null, map: null,
lastHash: null, lastHash: null,
@ -95,6 +90,13 @@
} }
}, },
getActiveLayers: function () {
var objList = this.options.layersControl.getActiveLayers();
return objList.map(function (obj) {
return encodeURIComponent(obj.name);
});
},
removeFrom: function(map) { removeFrom: function(map) {
if (this.changeTimeout) { if (this.changeTimeout) {
clearTimeout(this.changeTimeout); clearTimeout(this.changeTimeout);
@ -144,27 +146,22 @@
this.map.setView(parsed.center, parsed.zoom); this.map.setView(parsed.center, parsed.zoom);
var layers = parsed.layers, var layers = parsed.layers,
options = this.options, layersControl = this.options.layersControl,
that = this; that = this;
//Add/remove layer
this.map.eachLayer(function(layer) { layersControl.removeActiveLayers();
for (alayer in that.layers) {
if (that.layers[alayer] == layer) {
that.map.removeLayer(layer);
break;
}
}
});
var added = false; var added = false;
layers.forEach(function(element, index, array) { layers.forEach(function(element, index, array) {
if (element in options) { if (!element) return;
var obj = layersControl.activateLayer(element);
if (obj && !obj.overlay) {
added = true; added = true;
that.map.addLayer(options[element]);
} }
}); });
if (!added) { if (!added) {
// if we couldn't add layers (custom ones or invalid name), add the default one // if we couldn't add layers (removed or invalid name), add the default one
this.map.addLayer(options[Object.keys(options)[0]]); layersControl.activateFirstLayer();
} }
if (this.onHashChangeCb != null) { if (this.onHashChangeCb != null) {