diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js index a364b2313..7592a4125 100644 --- a/umap/static/umap/js/umap.controls.js +++ b/umap/static/umap/js/umap.controls.js @@ -514,12 +514,45 @@ L.U.DataLayersControl = L.Control.extend({ update: function () { if (this._datalayers_container && this._map) { this._datalayers_container.innerHTML = '' - this._map.eachDataLayerReverse(function (datalayer) { - this.addDataLayer(this._datalayers_container, datalayer) - }, this) + const hasGroups = !!Object.keys(this._map.groups_index).length + L.DomUtil.classIf(this._datalayers_container, 'grouped', hasGroups) + if (hasGroups) this.renderGroupedList() + else this.renderFlatList() } }, + renderFlatList: function () { + this._map.eachDataLayerReverse(function (datalayer) { + this.addDataLayer(this._datalayers_container, datalayer) + }, this) + }, + + renderGroupedList: function () { + const groups = Object.keys(this._map.groups_index).sort(L.Util.naturalSort) + for (let group of groups) { + let ids = this._map.groups_index[group] + this.addGroupHeader(group, ids) + for (let id of ids) { + this.addDataLayer(this._datalayers_container, this._map.datalayers[id]) + } + } + }, + + addGroupHeader: function (group, ids) { + const header = L.DomUtil.add('h4', 'layer-group', this._datalayers_container, group) + const toggle = L.DomUtil.create('i', 'group-toggle', header) + L.DomEvent.on(toggle, 'click', () => { + let show, datalayer + for (let id of ids) { + datalayer = this._map.datalayers[id] + // Show/hide all according to first datalayer + if (typeof(show) === 'undefined') show = !datalayer.isVisible() + if (show) datalayer.show() + else datalayer.hide() + } + }) + }, + expand: function () { L.DomUtil.addClass(this._container, 'expanded') }, @@ -676,7 +709,6 @@ L.U.DataLayer.addInitHook(function () { }) L.U.Map.include({ - _openFacet: function () { const container = L.DomUtil.create('div', 'umap-facet-search'), title = L.DomUtil.add('h3', 'umap-filter-title', container, L._('Facet search')), diff --git a/umap/static/umap/js/umap.core.js b/umap/static/umap/js/umap.core.js index a9398945f..965d7e20c 100644 --- a/umap/static/umap/js/umap.core.js +++ b/umap/static/umap/js/umap.core.js @@ -198,6 +198,16 @@ L.Util.greedyTemplate = (str, data, ignore) => { ) } +L.Util.naturalSort = (a, b) => { + return a + .toString() + .toLowerCase() + .localeCompare(b.toString().toLowerCase(), L.lang || 'en', { + sensitivity: 'base', + numeric: true, + }) +} + L.Util.sortFeatures = (features, sortKey) => { const sortKeys = (sortKey || 'name').split(',') @@ -216,13 +226,7 @@ L.Util.sortFeatures = (features, sortKey) => { } else if (!valB) { score = 1 } else { - score = valA - .toString() - .toLowerCase() - .localeCompare(valB.toString().toLowerCase(), L.lang || 'en', { - sensitivity: 'base', - numeric: true, - }) + score = L.Util.naturalSort(valA, valB) } if (score === 0 && sortKeys[i + 1]) return sort(a, b, i + 1) return score * reverse diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 87ff4e1da..30c65bdca 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -158,6 +158,7 @@ L.U.Map.include({ // Global storage for retrieving datalayers and features this.datalayers = {} this.datalayers_index = [] + this.groups_index = {} this.dirty_datalayers = [] this.features_index = {} this.facets = {} @@ -438,16 +439,29 @@ L.U.Map.include({ indexDatalayers: function () { const panes = this.getPane('overlayPane') - let pane this.datalayers_index = [] - for (let i = 0; i < panes.children.length; i++) { + for (let i = 0, pane, datalayer; i < panes.children.length; i++) { pane = panes.children[i] if (!pane.dataset || !pane.dataset.id) continue - this.datalayers_index.push(this.datalayers[pane.dataset.id]) + datalayer = this.datalayers[pane.dataset.id] + this.datalayers_index.push(datalayer) } + this.indexGroups() this.updateDatalayersControl() }, + indexGroups: function () { + this.groups_index = {} + this.eachDataLayer(this.indexGroup) + }, + + indexGroup: function (datalayer) { + const group = datalayer.options.group + if (!group) return + this.groups_index[group] = this.groups_index[group] || [] + this.groups_index[group].push(L.stamp(datalayer)) + }, + ensurePanesOrder: function () { this.eachDataLayer((datalayer) => { datalayer.bringToTop() @@ -1014,14 +1028,14 @@ L.U.Map.include({ eachDataLayer: function (method, context) { for (let i = 0; i < this.datalayers_index.length; i++) { - method.call(context, this.datalayers_index[i]) + method.call(context || this, this.datalayers_index[i]) } }, eachDataLayerReverse: function (method, context, filter) { for (let i = this.datalayers_index.length - 1; i >= 0; i--) { if (filter && !filter.call(context, this.datalayers_index[i])) continue - method.call(context, this.datalayers_index[i]) + method.call(context || this, this.datalayers_index[i]) } }, diff --git a/umap/static/umap/js/umap.layer.js b/umap/static/umap/js/umap.layer.js index 7f0b03fce..2f7b6cf48 100644 --- a/umap/static/umap/js/umap.layer.js +++ b/umap/static/umap/js/umap.layer.js @@ -487,6 +487,7 @@ L.U.DataLayer = L.Evented.extend({ this.map.datalayers[id] = this if (L.Util.indexOf(this.map.datalayers_index, this) === -1) this.map.datalayers_index.push(this) + this.map.indexGroup(this) } this.map.updateDatalayersControl() }, @@ -853,6 +854,7 @@ L.U.DataLayer = L.Evented.extend({ metadataFields = [ 'options.name', 'options.description', + ['options.group', { handler: 'BlurInput', label: L._('Layer group'), datalist: Object.keys(this.map.groups_index)}], ['options.type', { handler: 'LayerTypeChooser', label: L._('Type of layer') }], ['options.displayOnLoad', { label: L._('Display on load'), handler: 'Switch' }], [ @@ -867,6 +869,7 @@ L.U.DataLayer = L.Evented.extend({ const title = L.DomUtil.add('h3', '', container, L._('Layer properties')) let builder = new L.U.FormBuilder(this, metadataFields, { callback: function (e) { + this.map.indexGroups() this.map.updateDatalayersControl() if (e.helper.field === 'options.type') { this.resetLayer() diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css index cef43e392..8f080fe39 100644 --- a/umap/static/umap/map.css +++ b/umap/static/umap/map.css @@ -694,6 +694,7 @@ a.map-name:after { max-height: 15em; overflow-y: auto; } +.layer-group i, .search-result-tools i, .leaflet-inplace-toolbar a, .umap-browse-features i, @@ -717,6 +718,12 @@ a.map-name:after { margin-right: 5px; cursor: move; } +.umap-browse-datalayers.grouped li { + padding-left: 10px; +} +.umap-browse-datalayers.grouped h4 { + margin-bottom: 0; +} .leaflet-inplace-toolbar a { background-image: url('./img/16-white.svg'); background-color: #323737!important; @@ -730,6 +737,7 @@ a.map-name:after { .leaflet-control-browse .umap-browse-datalayers .off i { cursor: inherit; } +.group-toggle, .layer-toggle { background-position: -49px -31px; }