BR.LayersConfig = L.Class.extend({
overpassFrontend: new OverpassFrontend(BR.conf.overpassBaseUrl || '//overpass-api.de/api/interpreter'),
defaultBaseLayers: BR.confLayers.defaultBaseLayers,
defaultOverlays: BR.confLayers.defaultOverlays,
legacyNameToIdMap: BR.confLayers.legacyNameToIdMap,
// hardcoded, built-in layers with an id set (for URL hash)
builtInLayers: ['route-quality'],
initialize: function (map) {
this._map = map;
this._overpassLoadingIndicator = new BR.Message('overpass_loading_indicator', { alert: false });
this._overpassActiveRequestCount = 0;
this._addLeafletProvidersLayers();
this._customizeLayers();
this.loadDefaultLayers();
this._addLanguageDefaultLayer();
},
loadDefaultLayers: function () {
if (BR.Util.localStorageAvailable()) {
var item = localStorage.getItem('map/defaultLayers');
if (item) {
var defaultLayers = JSON.parse(item);
this.defaultBaseLayers = this._replaceLegacyIds(defaultLayers.baseLayers);
this.defaultOverlays = this._replaceLegacyIds(defaultLayers.overlays);
}
}
},
storeDefaultLayers: function (baseLayers, overlays) {
if (BR.Util.localStorageAvailable()) {
var defaultLayers = {
baseLayers: baseLayers,
overlays: overlays,
};
localStorage.setItem('map/defaultLayers', JSON.stringify(defaultLayers));
}
},
_replaceLegacyIds: function (idList) {
return idList.map((id) => (id in this.legacyNameToIdMap ? this.legacyNameToIdMap[id] : id));
},
_addLeafletProvidersLayers: function () {
var includeList = BR.confLayers.leafletProvidersIncludeList;
for (var i = 0; i < includeList.length; i++) {
var id = includeList[i];
var obj = {
geometry: null,
properties: {
id: id,
name: id.replace('.', ' '),
dataSource: 'leaflet-providers',
},
type: 'Feature',
};
BR.layerIndex[id] = obj;
}
},
_customizeLayers: function () {
var propertyOverrides = BR.confLayers.getPropertyOverrides();
for (var id in propertyOverrides) {
var layer = BR.layerIndex[id];
if (layer) {
var properties = propertyOverrides[id];
for (const key in properties) {
var value = properties[key];
layer.properties[key] = value;
}
} else {
console.error('Layer not found: ' + id);
}
}
BR.layerIndex['MtbMap'].geometry = BR.confLayers.europeGeofabrik;
BR.layerIndex['1069'].geometry = BR.confLayers.europeGeofabrik;
BR.layerIndex['OpenStreetMap.CH'].geometry = BR.confLayers.switzerlandPadded;
BR.layerIndex['swisstopo-landeskarte'].geometry = BR.confLayers.switzerlandPadded;
BR.layerIndex['swisstopo-aerial'].geometry = BR.confLayers.switzerlandPadded;
BR.layerIndex['1017'].geometry = BR.confLayers.osmapaPl;
BR.layerIndex['ignf-aerial'].geometry = BR.confLayers.franceBbox;
BR.layerIndex['ignf-map'].geometry = BR.confLayers.franceBbox;
BR.layerIndex['ignf-scan25'].geometry = BR.confLayers.franceBbox;
},
_addLanguageDefaultLayer: function () {
// language code -> layer id
var languageLayersMap = {};
var i;
for (i = 0; i < BR.confLayers.languageDefaultLayers.length; i++) {
var id = BR.confLayers.languageDefaultLayers[i];
var layer = BR.layerIndex[id];
if (layer) {
var layerLanguage = layer.properties['language_code'] || layer.properties['pseudo_language_code'];
if (layerLanguage) {
languageLayersMap[layerLanguage] = id;
}
}
}
// iterate language code hierarchy, e.g ["de-DE", "de", "en"] (includes `i18next.options.fallbackLng`)
for (i = 0; i < i18next.languages.length; i++) {
var language = i18next.languages[i];
var layerId = languageLayersMap[language];
if (layerId) {
this.defaultBaseLayers.unshift(layerId);
break;
}
}
},
isDefaultLayer: function (id, overlay) {
var result = false;
if (overlay) {
result = this.defaultOverlays.indexOf(id) > -1;
} else {
result = this.defaultBaseLayers.indexOf(id) > -1;
}
return result;
},
getBaseLayers: function () {
return this._getLayers(this.defaultBaseLayers);
},
getOverlays: function () {
return this._getLayers(this.defaultOverlays);
},
_getLayers: function (ids) {
var layers = {};
for (var i = 0; i < ids.length; i++) {
var layerId = ids[i];
var layerData = BR.layerIndex[layerId];
if (layerData) {
// when key required only add if configured
var keyObj = this.getKeyName(layerData.properties.url);
if (!keyObj || (keyObj && BR.keys[keyObj.name])) {
layers[layerData.properties.name] = this.createLayer(layerData);
}
} else {
console.error('Layer not found: ' + layerId);
}
}
return layers;
},
// own convention: key placeholder with prefix
// e.g. ?api_key={keys_openrouteservice}
getKeyName: function (url) {
var result = null;
// L.Util.template only matches [\w_-]
var prefix = 'keys_';
var regex = new RegExp('{' + prefix + '([^}]*)}');
var found, name;
if (!url) return result;
found = url.match(regex);
if (found) {
name = found[1];
result = {
name: name,
urlVar: prefix + name,
};
}
return result;
},
_showOverpassLoadingIndicator: function () {
this._overpassActiveRequestCount++;
this._overpassLoadingIndicator.showLoading(i18next.t('layers.overpass-loading-indicator'));
},
_hideOverpassLoadingIndicator: function () {
if (--this._overpassActiveRequestCount === 0) {
this._overpassLoadingIndicator.hide();
}
},
getOverpassIconUrl: function (icon) {
const iconPrefix = /^(maki|temaki|fas)-/;
let iconUrl = null;
if (icon && iconPrefix.test(icon)) {
const iconName = icon.replace(iconPrefix, '');
iconUrl = `dist/images/${iconName}.svg`;
}
return iconUrl;
},
createOverpassLayer: function (query, icon) {
let markerSign = '';
const iconUrl = this.getOverpassIconUrl(icon);
if (iconUrl) {
markerSign = ``;
}
return Object.assign(
new OverpassLayer({
overpassFrontend: this.overpassFrontend,
query: query,
minZoom: 12,
feature: {
title: '{{ tags.name }}',
body: this.renderOverpassPopupBody,
markerSymbol:
'',
markerSign,
style: function (overpassObject) {
return {
// nodeFeature: 'Marker' isn't currently working well, hence use transparent circle color for nodes
color:
overpassObject.type === 'node'
? '#00000000'
: this.defaultBaseLayers?.[0] === 'cyclosm'
? 'darkorange'
: '#3388ff',
};
}.bind(this),
},
}),
{
onLoadStart: this._showOverpassLoadingIndicator.bind(this),
onLoadEnd: this._hideOverpassLoadingIndicator.bind(this),
}
);
},
renderOverpassPopupBody: function (overpassData) {
let output = '';
output += '
| ' + i18next.t('layers.overpass-table-key') + ' | ' + i18next.t('layers.overpass-table-value') + ' |
|---|---|
| ' + key + ' | '; output += '' + value + ' | '; output += '