From 0bed05d53773e3216788418dc15a0431ee0d7434 Mon Sep 17 00:00:00 2001 From: Jan Pieter Waagmeester Date: Sat, 2 Apr 2016 20:48:31 +0200 Subject: [PATCH] Use array in L.Control.Layers to preserve layer order fixes #2086 --- debug/map/control-layers.html | 51 +++++++++++++++++++++++ spec/suites/control/Control.LayersSpec.js | 34 ++++++++++++++- src/control/Control.Layers.js | 25 +++++++---- 3 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 debug/map/control-layers.html diff --git a/debug/map/control-layers.html b/debug/map/control-layers.html new file mode 100644 index 00000000..cda52a13 --- /dev/null +++ b/debug/map/control-layers.html @@ -0,0 +1,51 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/spec/suites/control/Control.LayersSpec.js b/spec/suites/control/Control.LayersSpec.js index 8de0f015..1a167cef 100644 --- a/spec/suites/control/Control.LayersSpec.js +++ b/spec/suites/control/Control.LayersSpec.js @@ -4,6 +4,9 @@ describe("Control.Layers", function () { beforeEach(function () { map = L.map(document.createElement('div')); }); + afterEach(function () { + map.remove(); + }); describe("baselayerchange event", function () { beforeEach(function () { @@ -43,7 +46,7 @@ describe("Control.Layers", function () { map.setView([0, 0], 14); }); - it("when an included layer is addded or removed", function () { + it("when an included layer is added or removed from the map", function () { var baseLayer = L.tileLayer(), overlay = L.marker([0, 0]), layers = L.control.layers({"Base": baseLayer}, {"Overlay": overlay}).addTo(map); @@ -57,6 +60,23 @@ describe("Control.Layers", function () { expect(spy.callCount).to.eql(2); }); + it("when an included layer is added or removed from the map, it's (un)checked", function () { + document.body.appendChild(map._container); + var baseLayer = L.tileLayer(), + overlay = L.marker([0, 0]), + layers = L.control.layers({"Baselayer": baseLayer}, {"Overlay": overlay}).addTo(map); + + function isChecked() { + return !!(map._container.querySelector('.leaflet-control-layers-overlays input').checked); + } + + expect(isChecked()).to.not.be.ok(); + map.addLayer(overlay); + expect(isChecked()).to.be.ok(); + map.removeLayer(overlay); + expect(isChecked()).to.not.be.ok(); + }); + it("not when a non-included layer is added or removed", function () { var baseLayer = L.tileLayer(), overlay = L.marker([0, 0]), @@ -69,6 +89,17 @@ describe("Control.Layers", function () { expect(spy.called).to.not.be.ok(); }); + + it("updates when an included layer is removed from the control", function () { + document.body.appendChild(map._container); + var baseLayer = L.tileLayer(), + overlay = L.marker([0, 0]), + layers = L.control.layers({"Base": baseLayer}, {"Overlay": overlay}).addTo(map); + + layers.removeLayer(overlay); + expect(map._container.querySelector('.leaflet-control-layers-overlays').children.length) + .to.be.equal(0); + }); }); describe("is removed cleanly", function () { @@ -84,7 +115,6 @@ describe("Control.Layers", function () { expect(function () { map.removeLayer(baseLayer); }).to.not.throwException(); - }); }); diff --git a/src/control/Control.Layers.js b/src/control/Control.Layers.js index 3662eafd..4e23376e 100644 --- a/src/control/Control.Layers.js +++ b/src/control/Control.Layers.js @@ -59,7 +59,7 @@ L.Control.Layers = L.Control.extend({ initialize: function (baseLayers, overlays, options) { L.setOptions(this, options); - this._layers = {}; + this._layers = []; this._lastZIndex = 0; this._handlingClick = false; @@ -109,7 +109,8 @@ L.Control.Layers = L.Control.extend({ removeLayer: function (layer) { layer.off('add remove', this._onLayerChange, this); - delete this._layers[L.stamp(layer)]; + var obj = this._getLayer(L.stamp(layer)); + this._layers.splice(this._layers.indexOf(obj), 1); return (this._map) ? this._update() : this; }, @@ -188,16 +189,22 @@ L.Control.Layers = L.Control.extend({ container.appendChild(form); }, + _getLayer: function (id) { + for (var i = 0; i <= this._layers.length; i++) { + if (L.stamp(this._layers[i].layer) === id) { + return this._layers[i]; + } + } + }, + _addLayer: function (layer, name, overlay) { layer.on('add remove', this._onLayerChange, this); - var id = L.stamp(layer); - - this._layers[id] = { + this._layers.push({ layer: layer, name: name, overlay: overlay - }; + }); if (this.options.autoZIndex && layer.setZIndex) { this._lastZIndex++; @@ -237,7 +244,7 @@ L.Control.Layers = L.Control.extend({ this._update(); } - var obj = this._layers[L.stamp(e.target)]; + var obj = this._getLayer(L.stamp(e.target)); // @namespace Map // @section Layer events @@ -315,7 +322,7 @@ L.Control.Layers = L.Control.extend({ for (var i = inputs.length - 1; i >= 0; i--) { input = inputs[i]; - layer = this._layers[input.layerId].layer; + layer = this._getLayer(input.layerId).layer; hasLayer = this._map.hasLayer(layer); if (input.checked && !hasLayer) { @@ -347,7 +354,7 @@ L.Control.Layers = L.Control.extend({ for (var i = inputs.length - 1; i >= 0; i--) { input = inputs[i]; - layer = this._layers[input.layerId].layer; + layer = this._getLayer(input.layerId).layer; input.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) || (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);