From 883f4ba3a9df097a3866d7ba65a76e714cd867cf Mon Sep 17 00:00:00 2001 From: Nathan Rennie-Waldock Date: Wed, 14 Feb 2018 09:09:10 +0000 Subject: [PATCH] Adding feature to make individual groups collapsable ismyrnow/leaflet-groupedlayercontrol#46 squashed + lint fixed Collapsable Groups. Added a config option "groupsCollapsable" which if set to true, will make each group header individually collapsable. This is useful when dealing with either small map elements, or a larger number of layers within the groups. Also added two supporting config settings: "groupsCollapseClass" and "groupsExpandClass" which control the css styles used for the toggle indicators, allowing users to override the default +/- indicators. Setting one to "glyphicon glyphicon-chevron-right" will use the glyphicon provided with bootstrap for example. --- README.md | 19 +++++++++++++ example/collapsable-advanced.html | 42 ++++++++++++++++++++++++++++ example/collapsable-basic.html | 39 ++++++++++++++++++++++++++ preview-collapsable.png | Bin 0 -> 4764 bytes src/leaflet.groupedlayercontrol.css | 20 +++++++++++++ src/leaflet.groupedlayercontrol.js | 35 +++++++++++++++++++++-- 6 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 example/collapsable-advanced.html create mode 100644 example/collapsable-basic.html create mode 100644 preview-collapsable.png diff --git a/README.md b/README.md index 1de8bc5..0398c38 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,25 @@ L.control.groupedLayers(baseLayers, groupedOverlays, options).addTo(map); ![advanced preview](preview-advanced.png) +#### Collapsable Groups + +Enabling collapsable groups in the switcher can be done with the following options + +```javascript +var options = { + // enable basic collapsability + groupsCollapsable: true, + // (Optional) The css class(es) used to indicated the group is expanded + groupsExpandedClass: "glyphicon glyphicon-chevron-down", + // (Optional) The css class(es) used to indicated the group is collapsed + groupsCollapsedClass: "glyphicon glyphicon-chevron-right" +}; + +L.control.groupedLayers(baseLayers, groupedOverlays, options).addTo(map); +``` + +![collapsable preview](preview-collapsable.png) + ### Adding a layer Adding a layer individually works similarly to the default layer control, diff --git a/example/collapsable-advanced.html b/example/collapsable-advanced.html new file mode 100644 index 0000000..c47a091 --- /dev/null +++ b/example/collapsable-advanced.html @@ -0,0 +1,42 @@ + + + + Collapsable Example (Bootstrap Glyphicons) + + + + + + + + + +
+ + + + + + + diff --git a/example/collapsable-basic.html b/example/collapsable-basic.html new file mode 100644 index 0000000..ecac5ff --- /dev/null +++ b/example/collapsable-basic.html @@ -0,0 +1,39 @@ + + + + Collapsable Example + + + + + + +
+ + + + + + + diff --git a/preview-collapsable.png b/preview-collapsable.png new file mode 100644 index 0000000000000000000000000000000000000000..a55157de5fef24753fe2bf6e2d41ab5aa437cee5 GIT binary patch literal 4764 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 XhBu7jOdNqfN+fz(hMKkN52OACDwaN+ literal 0 HcmV?d00001 diff --git a/src/leaflet.groupedlayercontrol.css b/src/leaflet.groupedlayercontrol.css index 3be2cc4..aebaaaa 100644 --- a/src/leaflet.groupedlayercontrol.css +++ b/src/leaflet.groupedlayercontrol.css @@ -12,3 +12,23 @@ overflow-y: scroll; padding-right: 10px; } + +.leaflet-control-layers-group.group-collapsable.collapsed .leaflet-control-layers-group-collapse, +.leaflet-control-layers-group.group-collapsable:not(.collapsed) .leaflet-control-layers-group-expand, +.leaflet-control-layers-group.group-collapsable.collapsed label:not(.leaflet-control-layers-group-label){ + display: none; +} + +.leaflet-control-layers-group-expand-default:before{ + content: "+"; + width: 12px; + display: inline-block; + text-align: center; +} + +.leaflet-control-layers-group-collapse-default:before{ + content: "-"; + width: 12px; + display: inline-block; + text-align: center; +} \ No newline at end of file diff --git a/src/leaflet.groupedlayercontrol.js b/src/leaflet.groupedlayercontrol.js index a660cea..b7f20b6 100644 --- a/src/leaflet.groupedlayercontrol.js +++ b/src/leaflet.groupedlayercontrol.js @@ -10,10 +10,13 @@ L.Control.GroupedLayers = L.Control.extend({ autoZIndex: true, exclusiveGroups: [], groupCheckboxes: false, + groupsCollapsable: false, + groupsExpandedClass: 'leaflet-control-layers-group-collapse-default', + groupsCollapsedClass: 'leaflet-control-layers-group-expand-default', // Whether to sort the layers. When `false`, layers will keep the order // in which they were added to the control. sortLayers: false, - // A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) + // A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) // that will be used for sorting the layers, when `sortLayers` is `true`. // The function receives both the `L.Layer` instances and their names, as in // `sortFunction(layerA, layerB, nameA, nameB)`. @@ -83,7 +86,7 @@ L.Control.GroupedLayers = L.Control.extend({ var id = L.Util.stamp(layer); var _layer = this._getLayer(id); if (_layer) { - delete this.layers[this.layers.indexOf(_layer)]; + this._layers.splice(this._layers.indexOf(_layer), 1); } this._update(); return this; @@ -296,6 +299,21 @@ L.Control.GroupedLayers = L.Control.extend({ } } + if (this.options.groupsCollapsable) { + groupContainer.classList.add('group-collapsable'); + groupContainer.classList.add('collapsed'); + + var groupMin = document.createElement('span'); + groupMin.className = 'leaflet-control-layers-group-collapse '+this.options.groupsExpandedClass; + groupLabel.appendChild(groupMin); + + var groupMax = document.createElement('span'); + groupMax.className = 'leaflet-control-layers-group-expand '+this.options.groupsCollapsedClass; + groupLabel.appendChild(groupMax); + + L.DomEvent.on(groupLabel, 'click', this._onGroupCollapseToggle, groupContainer); + } + var groupName = document.createElement('span'); groupName.className = 'leaflet-control-layers-group-name'; groupName.innerHTML = obj.group.name; @@ -317,7 +335,18 @@ L.Control.GroupedLayers = L.Control.extend({ return label; }, - _onGroupInputClick: function () { + _onGroupCollapseToggle: function (event) { + L.DomEvent.stopPropagation(event); + L.DomEvent.preventDefault(event); + if (this.classList.contains('group-collapsable') && this.classList.contains('collapsed')) { + this.classList.remove('collapsed'); + } else if (this.classList.contains('group-collapsable') && !this.classList.contains('collapsed')) { + this.classList.add('collapsed'); + } + }, + + _onGroupInputClick: function (event) { + L.DomEvent.stopPropagation(event); var i, input, obj; var this_legend = this.legend;