diff --git a/css/style.css b/css/style.css
index b038e0d..1d4394d 100644
--- a/css/style.css
+++ b/css/style.css
@@ -423,6 +423,12 @@ table.dataTable.display tbody tr.even:hover {
margin-top: 5px;
}
+.tree-code {
+ font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
+ margin-right: 7px;
+ color: #666; /* like root nodes, jstree-disabled */
+}
+
/* hide currently unused bottom tabs container because of touch border artefacts */
.leaflet-sidebar-tabs > ul:last-child {
diff --git a/js/LayersConfig.js b/js/LayersConfig.js
index 952e6d9..9cb033a 100644
--- a/js/LayersConfig.js
+++ b/js/LayersConfig.js
@@ -83,46 +83,103 @@ BR.LayersConfig = L.Class.extend({
BR.layerIndex['HikeBike.HillShading'].properties.overlay = true;
+ var propertyOverrides = {
+ 'standard': {
+ 'name': i18next.t('map.layer.osm'),
+ 'mapUrl': 'https://www.openstreetmap.org/#map={zoom}/{lat}/{lon}'
+ },
+ 'osm-mapnik-german_style': {
+ 'name': i18next.t('map.layer.osmde'),
+ 'language_code': 'de',
+ 'mapUrl': 'https://www.openstreetmap.de/karte.html?zoom={zoom}&lat={lat}&lon={lon}&layers=B000TF'
+ },
+ 'OpenTopoMap': {
+ 'name': i18next.t('map.layer.topo'),
+ 'mapUrl': 'https://opentopomap.org/#map={zoom}/{lat}/{lon}'
+ },
+ 'Stamen.Terrain': {
+ 'name': i18next.t('map.layer.stamen-terrain'),
+ 'mapUrl': 'http://maps.stamen.com/#terrain/{zoom}/{lat}/{lon}'
+ },
+ 'opencylemap': {
+ 'name': i18next.t('map.layer.cycle'),
+ 'nameShort': 'OpenCycleMap',
+ 'mapUrl': 'https://www.opencyclemap.org/?zoom={zoom}&lat={lat}&lon={lon}&layers=B0000'
+ },
+ '1061': {
+ 'name': i18next.t('map.layer.outdoors'),
+ 'nameShort': 'Outdoors',
+ 'mapUrl': 'https://www.opencyclemap.org/?zoom={zoom}&lat={lat}&lon={lon}&layers=000B0'
+ },
+ 'Esri.WorldImagery': {
+ 'name': i18next.t('map.layer.esri'),
+ 'nameShort': i18next.t('credits.esri-tiles'),
+ 'mapUrl': 'http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9'
+ },
+ 'HikeBike.HillShading': {
+ 'name': i18next.t('map.layer.hikebike-hillshading'),
+ 'nameShort': i18next.t('map.hikebike-hillshading'),
+ 'mapUrl': 'http://hikebikemap.org/?zoom={zoom}&lat={lat}&lon={lon}&layer=HikeBikeMap'
+ },
+ 'Waymarked_Trails-Cycling': {
+ 'name': i18next.t('map.layer.cycling'),
+ 'nameShort': i18next.t('map.cycling'),
+ 'mapUrl': 'http://cycling.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}'
+ },
+ 'Waymarked_Trails-Hiking': {
+ 'name': i18next.t('map.layer.hiking'),
+ 'nameShort': i18next.t('map.hiking'),
+ 'mapUrl': 'http://hiking.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}'
+ },
+ 'OpenStreetMap.CH': {
+ 'country_code': 'CH'
+ },
+ 'topplus-open': {
+ 'country_code': 'DE'
+ },
+ 'osm-cambodia_laos_thailand_vietnam-bilingual': {
+ 'country_code': 'TH+'
+ },
+ 'osmfr': {
+ 'language_code': 'fr'
+ },
+ // kosmosnimki.ru
+ '1023': {
+ 'language_code': 'ru'
+ },
+ // sputnik.ru
+ '1021': {
+ 'language_code': 'ru'
+ },
+ // Osmapa.pl - Mapa OpenStreetMap Polska
+ '1017': {
+ 'language_code': 'pl'
+ },
+ 'osmfr-basque': {
+ 'language_code': 'eu'
+ },
+ 'osmfr-breton': {
+ 'language_code': 'br'
+ },
+ 'osmfr-occitan': {
+ 'language_code': 'oc'
+ }
+ };
+
+ for (id in propertyOverrides) {
+ var layer = BR.layerIndex[id];
- function setProperty(layerId, key, value) {
- var layer = BR.layerIndex[layerId];
if (layer) {
- layer.properties[key] = value;
+ var properties = propertyOverrides[id];
+
+ for (key in properties) {
+ var value = properties[key];
+ layer.properties[key] = value;
+ }
} else {
- console.error('Layer not found: ' + layerId);
+ console.error('Layer not found: ' + id);
}
}
- function setMapUrl(layerId, url) {
- setProperty(layerId, 'mapUrl', url);
- }
- function setName(layerId, url) {
- setProperty(layerId, 'name', url);
- }
-
- // Layer attribution here only as short link to original site,
- // to keep current position use placeholders: {zoom}/{lat}/{lon}
- // Copyright attribution in index.html #credits
- setMapUrl('standard', 'OpenStreetMap');
- setMapUrl('osm-mapnik-german_style', 'OpenStreetMap.de');
- setMapUrl('OpenTopoMap', 'OpenTopoMap');
- setMapUrl('Stamen.Terrain', '' + i18next.t('map.layer.stamen-terrain') + '');
- setMapUrl('opencylemap', 'OpenCycleMap');
- setMapUrl('1061', 'Outdoors');
- setMapUrl('Esri.WorldImagery', '' + i18next.t('credits.esri-tiles') + '');
- setMapUrl('HikeBike.HillShading', '' + i18next.t('map.hikebike-hillshading') + '');
- setMapUrl('Waymarked_Trails-Cycling', '' + i18next.t('map.cycling') + '');
- setMapUrl('Waymarked_Trails-Hiking', '' + i18next.t('map.hiking') + '');
-
- setName('standard', i18next.t('map.layer.osm'));
- setName('osm-mapnik-german_style', i18next.t('map.layer.osmde'));
- setName('OpenTopoMap', i18next.t('map.layer.topo'));
- setName('Stamen.Terrain', i18next.t('map.layer.stamen-terrain'));
- setName('opencylemap', i18next.t('map.layer.cycle'));
- setName('1061', i18next.t('map.layer.outdoors'));
- setName('Esri.WorldImagery', i18next.t('map.layer.esri'));
- setName('HikeBike.HillShading', i18next.t('map.layer.hikebike-hillshading'));
- setName('Waymarked_Trails-Cycling', i18next.t('map.layer.cycling'));
- setName('Waymarked_Trails-Hiking', i18next.t('map.layer.hiking'));
},
isDefaultLayer: function(id, overlay) {
@@ -212,9 +269,11 @@ BR.LayersConfig = L.Class.extend({
var options = {
- maxZoom: this._map.getMaxZoom(),
- mapUrl: props.mapUrl
+ maxZoom: this._map.getMaxZoom()
};
+ if (props.mapUrl) {
+ options.mapLink = '' + (props.nameShort || props.name) + '';
+ }
var keyObj = this.getKeyName(url);
if (keyObj && BR.keys[keyObj.name]) {
@@ -257,8 +316,11 @@ BR.LayersConfig = L.Class.extend({
}
}
+ // Layer attribution here only as short link to original site,
+ // to keep current position use placeholders: {zoom}/{lat}/{lon}
+ // Copyright attribution in index.html #credits
var getAttribution = function () {
- return this.options.mapUrl;
+ return this.options.mapLink;
}
layer.getAttribution = getAttribution;
diff --git a/js/control/LayersTab.js b/js/control/LayersTab.js
index 560cc96..4b9fb37 100644
--- a/js/control/LayersTab.js
+++ b/js/control/LayersTab.js
@@ -19,8 +19,8 @@ BR.LayersTab = BR.ControlLayers.extend({
this.initButtons();
var structure = {
- 'Base layers': {
- 'Worldwide international': [
+ 'base-layers': {
+ 'worldwide-international': [
'standard',
'OpenTopoMap',
'Stamen.Terrain',
@@ -34,49 +34,63 @@ BR.LayersTab = BR.ControlLayers.extend({
'1016', // 4UMaps,
'openmapsurfer'
],
- 'Worldwide monolingual': [
+ 'worldwide-monolingual': [
'osm-mapnik-german_style',
'osmfr',
- '1023', // Osmapa.pl - Mapa OpenStreetMap Polska
- '1021', // kosmosnimki.ru
- '1017' // sputnik.ru
+ '1017', // Osmapa.pl - Mapa OpenStreetMap Polska
+ '1023', // kosmosnimki.ru
+ '1021' // sputnik.ru
],
- 'Europe': [
+ 'europe': [
'MtbMap',
'1069' // MRI (maps.refuges.info)
],
- 'Country': [
- 'topplus-open',
- 'OpenStreetMap.CH',
- 'Freemap.sk-Car',
- 'Freemap.sk-Hiking',
- 'Freemap.sk-Cyclo',
- 'OpenStreetMap-turistautak',
- 'Israel_Hiking',
- 'Israel_MTB',
- 'osmbe',
- 'osmbe-fr',
- 'osmbe-nl',
+ 'europe-monolingual': [
'osmfr-basque',
'osmfr-breton',
- 'osmfr-occitan',
+ 'osmfr-occitan'
+ ],
+ 'country': [
+ {
+ 'BE': [
+ 'osmbe',
+ 'osmbe-fr',
+ 'osmbe-nl',
+ ]
+ },
+ 'OpenStreetMap.CH',
+ 'topplus-open',
+ 'OpenStreetMap-turistautak',
+ {
+ 'IL': [
+ 'Israel_Hiking',
+ 'Israel_MTB',
+ ]
+ },
'mtbmap-no',
+ {
+ 'SK': [
+ 'Freemap.sk-Car',
+ 'Freemap.sk-Hiking',
+ 'Freemap.sk-Cyclo',
+ ]
+ },
'osm-cambodia_laos_thailand_vietnam-bilingual'
]
},
- 'Overlays': {
- 'World-wide': [
+ 'overlays': {
+ 'worldwide': [
'HikeBike.HillShading',
- 'Waymarked_Trails-Hiking',
'Waymarked_Trails-Cycling',
+ 'Waymarked_Trails-Hiking',
'Waymarked_Trails-MTB',
'mapillary-coverage-raster'
],
- 'Country': [
+ 'country': [
'historic-place-contours',
'hu-hillshade',
{
- 'PL - Poland': [
+ 'PL': [
'mapaszlakow-cycle',
'mapaszlakow-bike',
'mapaszlakow-hike',
@@ -123,7 +137,7 @@ BR.LayersTab = BR.ControlLayers.extend({
};
var onUncheckNode = function (e, data) {
- var obj = this.getLayer(data.node.text);
+ var obj = this.getLayerById(data.node.id);
if (!obj) return;
this.removeLayer(obj.layer);
@@ -195,22 +209,34 @@ BR.LayersTab = BR.ControlLayers.extend({
},
toJsTree: function (layerTree) {
- var data = [];
+ var data = {
+ children: []
+ };
var self = this;
function createRootNode(name) {
- var children = [];
var rootNode = {
- 'text': name,
+ 'text': i18next.t('sidebar.layers.category.' + name, name),
'state': {
'disabled': true
},
- 'children': children
+ 'children': []
};
return rootNode;
}
- function createNode(id, layerData) {
+ function getText(props, parent) {
+ var text = '';
+ var code = props.country_code || props.language_code;
+ if (code && parent.text !== code) {
+ text += '' + code + '';
+ }
+ text += props.name;
+
+ return text;
+ }
+
+ function createNode(id, layerData, parent) {
var props = layerData.properties;
var url = props.url;
var keyObj = self.layersConfig.getKeyName(url);
@@ -220,7 +246,7 @@ BR.LayersTab = BR.ControlLayers.extend({
if (!keyObj || keyObj && BR.keys[keyObj.name]) {
childNode = {
'id': id,
- 'text': props.name,
+ 'text': getText(props, parent),
'state': {
'checked': self.layersConfig.isDefaultLayer(id, props.overlay)
}
@@ -235,8 +261,8 @@ BR.LayersTab = BR.ControlLayers.extend({
var value = obj[name];
var rootNode = createRootNode(name)
- outTree.push(rootNode);
- walkTree(value, rootNode.children);
+ outTree.children.push(rootNode);
+ walkTree(value, rootNode);
}
}
@@ -249,9 +275,9 @@ BR.LayersTab = BR.ControlLayers.extend({
var layer = BR.layerIndex[entry];
if (layer) {
- var childNode = createNode(entry, layer);
+ var childNode = createNode(entry, layer, outTree);
if (childNode) {
- outTree.push(childNode);
+ outTree.children.push(childNode);
}
} else {
console.error('Layer "' + entry + '" not found');
@@ -264,7 +290,7 @@ BR.LayersTab = BR.ControlLayers.extend({
}
walkTree(layerTree, data);
- return data;
+ return data.children;
},
storeDefaultLayers: function () {
diff --git a/locales/en.json b/locales/en.json
index a941489..d420af6 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -160,6 +160,16 @@
"title": "Itinerary"
},
"layers": {
+ "category": {
+ "base-layers": "Base layers",
+ "country": "Country",
+ "europe": "Europe",
+ "europe-monolingual": "Europe monolingual",
+ "overlays": "Overlays",
+ "worldwide": "Worldwide",
+ "worldwide-international": "Worldwide international",
+ "worldwide-monolingual": "Worldwide monolingual"
+ },
"collapse": "Collapse all",
"custom-layers": "Custom layers",
"customize": "Add or remove custom layers",
diff --git a/locales/keys.js b/locales/keys.js
index d62adfd..23f5255 100644
--- a/locales/keys.js
+++ b/locales/keys.js
@@ -18,4 +18,13 @@ i18next.t('navbar.profile.trekking-noferries');
i18next.t('navbar.profile.trekking-nosteps');
i18next.t('navbar.profile.trekking-steep');
i18next.t('navbar.profile.vm-forum-liegerad-schnell');
-i18next.t('navbar.profile.vm-forum-velomobil-schnell');
\ No newline at end of file
+i18next.t('navbar.profile.vm-forum-velomobil-schnell');
+
+i18next.t('sidebar.layers.category.base-layers', 'Base layers');
+i18next.t('sidebar.layers.category.worldwide-international', 'Worldwide international');
+i18next.t('sidebar.layers.category.worldwide-monolingual', 'Worldwide monolingual');
+i18next.t('sidebar.layers.category.europe', 'Europe');
+i18next.t('sidebar.layers.category.europe-monolingual', 'Europe monolingual');
+i18next.t('sidebar.layers.category.country', 'Country');
+i18next.t('sidebar.layers.category.overlays', 'Overlays');
+i18next.t('sidebar.layers.category.worldwide', 'Worldwide');