diff --git a/package-lock.json b/package-lock.json
index 557d3962..47608090 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,10 +18,11 @@
"leaflet-contextmenu": "^1.4.0",
"leaflet-editable": "^1.2.0",
"leaflet-editinosm": "0.2.3",
- "leaflet-formbuilder": "0.2.7",
+ "leaflet-formbuilder": "0.2.9",
"leaflet-fullscreen": "1.0.2",
"leaflet-hash": "0.2.1",
"leaflet-i18n": "0.3.3",
+ "leaflet-iconlayers": "^0.2.0",
"leaflet-loading": "0.1.24",
"leaflet-measurable": "0.1.0",
"leaflet-minimap": "^3.6.1",
@@ -1384,9 +1385,9 @@
"integrity": "sha1-8HFmTEpSe3b3uPm87HRLJIiVwHE="
},
"node_modules/leaflet-formbuilder": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/leaflet-formbuilder/-/leaflet-formbuilder-0.2.7.tgz",
- "integrity": "sha512-5/QXEPmlSPNzl5r8rNlhcQOfI2Bx9vo/FBaBCV7o37MmZZ2jyA4aRu+6j91CnyRmKXfU5f/42E0yJva/Dwnqcw=="
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/leaflet-formbuilder/-/leaflet-formbuilder-0.2.9.tgz",
+ "integrity": "sha512-6akc6pqVMDqoKxTfXvurK4tfDMqnAYTxqxS8GVkOXipEXumsP9qScLFYEzhuZcMeOJ+AeKZrq8ZCsNti1syusg=="
},
"node_modules/leaflet-fullscreen": {
"version": "1.0.2",
@@ -1406,6 +1407,19 @@
"resolved": "https://registry.npmjs.org/leaflet-i18n/-/leaflet-i18n-0.3.3.tgz",
"integrity": "sha512-bl1HkR/8ZbQ9/S2x736rBQL/40P+5zSItMAW5lOpuZSrM5PK0ezsux8znug8JJQtE+2QkBBsWIngfVlGERN0AA=="
},
+ "node_modules/leaflet-iconlayers": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/leaflet-iconlayers/-/leaflet-iconlayers-0.2.0.tgz",
+ "integrity": "sha512-iSa5v+Lrovt2wLY3wQnzudatb+l7SEMUOvrmDrky2TkhUjJscrJKj8doP16xG94E2rHQaQmqxUWKGv6JNUfIOQ==",
+ "dependencies": {
+ "leaflet": "^0.7.3"
+ }
+ },
+ "node_modules/leaflet-iconlayers/node_modules/leaflet": {
+ "version": "0.7.7",
+ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-0.7.7.tgz",
+ "integrity": "sha512-H1lR7J5VxhvQJQHlW2UywtxO63zilLrnwVsDvjKeyfntffj63Ml94gCk9YPYWBkiQgxisdiA8aJ30Zoou4VhEA=="
+ },
"node_modules/leaflet-loading": {
"version": "0.1.24",
"resolved": "https://registry.npmjs.org/leaflet-loading/-/leaflet-loading-0.1.24.tgz",
@@ -3584,9 +3598,9 @@
"integrity": "sha1-8HFmTEpSe3b3uPm87HRLJIiVwHE="
},
"leaflet-formbuilder": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/leaflet-formbuilder/-/leaflet-formbuilder-0.2.7.tgz",
- "integrity": "sha512-5/QXEPmlSPNzl5r8rNlhcQOfI2Bx9vo/FBaBCV7o37MmZZ2jyA4aRu+6j91CnyRmKXfU5f/42E0yJva/Dwnqcw=="
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/leaflet-formbuilder/-/leaflet-formbuilder-0.2.9.tgz",
+ "integrity": "sha512-6akc6pqVMDqoKxTfXvurK4tfDMqnAYTxqxS8GVkOXipEXumsP9qScLFYEzhuZcMeOJ+AeKZrq8ZCsNti1syusg=="
},
"leaflet-fullscreen": {
"version": "1.0.2",
@@ -3603,6 +3617,21 @@
"resolved": "https://registry.npmjs.org/leaflet-i18n/-/leaflet-i18n-0.3.3.tgz",
"integrity": "sha512-bl1HkR/8ZbQ9/S2x736rBQL/40P+5zSItMAW5lOpuZSrM5PK0ezsux8znug8JJQtE+2QkBBsWIngfVlGERN0AA=="
},
+ "leaflet-iconlayers": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/leaflet-iconlayers/-/leaflet-iconlayers-0.2.0.tgz",
+ "integrity": "sha512-iSa5v+Lrovt2wLY3wQnzudatb+l7SEMUOvrmDrky2TkhUjJscrJKj8doP16xG94E2rHQaQmqxUWKGv6JNUfIOQ==",
+ "requires": {
+ "leaflet": "^0.7.3"
+ },
+ "dependencies": {
+ "leaflet": {
+ "version": "0.7.7",
+ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-0.7.7.tgz",
+ "integrity": "sha512-H1lR7J5VxhvQJQHlW2UywtxO63zilLrnwVsDvjKeyfntffj63Ml94gCk9YPYWBkiQgxisdiA8aJ30Zoou4VhEA=="
+ }
+ }
+ },
"leaflet-loading": {
"version": "0.1.24",
"resolved": "https://registry.npmjs.org/leaflet-loading/-/leaflet-loading-0.1.24.tgz",
diff --git a/package.json b/package.json
index 14288c65..bad0c918 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"leaflet-fullscreen": "1.0.2",
"leaflet-hash": "0.2.1",
"leaflet-i18n": "0.3.3",
+ "leaflet-iconlayers": "^0.2.0",
"leaflet-loading": "0.1.24",
"leaflet-measurable": "0.1.0",
"leaflet-minimap": "^3.6.1",
diff --git a/scripts/vendorsjs.sh b/scripts/vendorsjs.sh
index 793fbeb5..07c33cd7 100755
--- a/scripts/vendorsjs.sh
+++ b/scripts/vendorsjs.sh
@@ -28,5 +28,6 @@ mkdir -p umap/static/umap/vendors/locatecontrol/ && cp -r node_modules/leaflet.l
mkdir -p umap/static/umap/vendors/dompurify/ && cp -r node_modules/dompurify/dist/purify.js umap/static/umap/vendors/dompurify/
mkdir -p umap/static/umap/vendors/colorbrewer/ && cp node_modules/colorbrewer/index.js umap/static/umap/vendors/colorbrewer/colorbrewer.js
mkdir -p umap/static/umap/vendors/simple-statistics/ && cp node_modules/simple-statistics/dist/simple-statistics.min.js umap/static/umap/vendors/simple-statistics/
+mkdir -p umap/static/umap/vendors/iconlayers/ && cp node_modules/leaflet-iconlayers/dist/* umap/static/umap/vendors/iconlayers/
echo 'Done!'
diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js
index c2bd29df..67baa3dc 100644
--- a/umap/static/umap/js/umap.controls.js
+++ b/umap/static/umap/js/umap.controls.js
@@ -1178,7 +1178,28 @@ L.U.Map.include({
},
})
-L.U.TileLayerControl = L.Control.extend({
+/* Used in view mode to define the current tilelayer */
+L.U.TileLayerControl = L.Control.IconLayers.extend({
+ initialize: function (map, options) {
+ const layers = []
+ map.eachTileLayer((layer) => {
+ layers.push({
+ title: layer.options.name,
+ layer: layer,
+ icon: L.Util.template(layer.options.url_template, map.demoTileInfos),
+ })
+ })
+ const maxShown = 10
+ L.Control.IconLayers.prototype.initialize.call(this, layers.slice(0, maxShown), {
+ position: 'topleft',
+ manageLayers: false
+ })
+ this.on('activelayerchange', (e) => map.selectTileLayer(e.layer))
+ },
+})
+
+/* Used in edit mode to define the default tilelayer */
+L.U.TileLayerChooser = L.Control.extend({
options: {
position: 'topleft',
},
diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js
index f4149bd2..159328ee 100644
--- a/umap/static/umap/js/umap.js
+++ b/umap/static/umap/js/umap.js
@@ -60,8 +60,8 @@ L.U.Map.include({
'measure',
'editinosm',
'datalayers',
- 'tilelayers',
'star',
+ 'tilelayers',
],
initialize: function (el, geojson) {
@@ -326,7 +326,7 @@ L.U.Map.include({
})
this._controls.search = new L.U.SearchControl()
this._controls.embed = new L.Control.Embed(this, this.options.embedOptions)
- this._controls.tilelayers = new L.U.TileLayerControl(this)
+ this._controls.tilelayersChooser = new L.U.TileLayerChooser(this)
this._controls.star = new L.U.StarControl(this)
this._controls.editinosm = new L.Control.EditInOSM({
position: 'topleft',
@@ -345,6 +345,8 @@ L.U.Map.include({
this.browser = new L.U.Browser(this)
this.importer = new L.U.Importer(this)
this.drop = new L.U.DropControl(this)
+ this._controls.tilelayers = new L.U.TileLayerControl(this)
+
this.renderControls()
},
@@ -581,17 +583,15 @@ L.U.Map.include({
initTileLayers: function () {
this.tilelayers = []
- for (const i in this.options.tilelayers) {
- if (this.options.tilelayers.hasOwnProperty(i)) {
- this.tilelayers.push(this.createTileLayer(this.options.tilelayers[i]))
- if (
- this.options.tilelayer &&
- this.options.tilelayer.url_template ===
- this.options.tilelayers[i].url_template
- ) {
- // Keep control over the displayed attribution for non custom tilelayers
- this.options.tilelayer.attribution = this.options.tilelayers[i].attribution
- }
+ for (const props of this.options.tilelayers) {
+ let layer = this.createTileLayer(props)
+ this.tilelayers.push(layer)
+ if (
+ this.options.tilelayer &&
+ this.options.tilelayer.url_template === props.url_template
+ ) {
+ // Keep control over the displayed attribution for non custom tilelayers
+ this.options.tilelayer.attribution = props.attribution
}
}
if (
@@ -646,21 +646,9 @@ L.U.Map.include({
this.setOverlay()
},
- eachTileLayer: function (method, context) {
- const urls = []
- for (const i in this.tilelayers) {
- if (this.tilelayers.hasOwnProperty(i)) {
- method.call(context, this.tilelayers[i])
- urls.push(this.tilelayers[i]._url)
- }
- }
- if (
- this.customTilelayer &&
- Array.prototype.indexOf &&
- urls.indexOf(this.customTilelayer._url) === -1
- ) {
- method.call(context || this, this.customTilelayer)
- }
+ eachTileLayer: function (callback, context) {
+ if (this.customTilelayer) callback.call(context, this.customTilelayer)
+ this.tilelayers.forEach((layer) => callback.call(context, layer))
},
setOverlay: function () {
@@ -816,8 +804,8 @@ L.U.Map.include({
self.options.tilelayer = tilelayer.toJSON()
self.isDirty = true
}
- if (this._controls.tilelayers)
- this._controls.tilelayers.openSwitcher({ callback: callback, className: 'dark' })
+ if (this._controls.tilelayersChooser)
+ this._controls.tilelayersChooser.openSwitcher({ callback: callback, className: 'dark' })
},
manageDatalayers: function () {
diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css
index 1cdf7412..4c14bfc6 100644
--- a/umap/static/umap/map.css
+++ b/umap/static/umap/map.css
@@ -161,6 +161,29 @@
background-image: url('./img/16.svg');
background-position: 0px 0px;
}
+.leaflet-iconLayers-layer {
+ width: 38px;
+ height: 38px;
+ box-shadow: none;
+ border: 1px solid #bbb;
+ border-radius: 4px;
+}
+.leaflet-iconLayers-layerTitleContainer {
+ display: none;
+ left: 0;
+ overflow: hidden;
+}
+.leaflet-iconLayers-layerTitle {
+ text-align: center;
+ display: inline-block;
+}
+.leaflet-iconLayers:hover .leaflet-iconLayers-layer {
+ width: 80px;
+ height: 80px;
+}
+.leaflet-iconLayers:hover .leaflet-iconLayers-layerTitleContainer {
+ display: initial;
+}
diff --git a/umap/static/umap/test/index.html b/umap/static/umap/test/index.html
index 4f11268b..bc371d16 100644
--- a/umap/static/umap/test/index.html
+++ b/umap/static/umap/test/index.html
@@ -21,6 +21,7 @@
+
@@ -52,6 +53,7 @@
+
diff --git a/umap/templates/umap/css.html b/umap/templates/umap/css.html
index e6bd3627..120ff967 100644
--- a/umap/templates/umap/css.html
+++ b/umap/templates/umap/css.html
@@ -18,6 +18,8 @@
href="{{ STATIC_URL }}umap/vendors/fullscreen/leaflet.fullscreen.css" />
+
diff --git a/umap/templates/umap/js.html b/umap/templates/umap/js.html
index 6a5b29af..131c1a02 100644
--- a/umap/templates/umap/js.html
+++ b/umap/templates/umap/js.html
@@ -20,6 +20,7 @@
+