diff --git a/spec/suites/control/Control.LayersSpec.js b/spec/suites/control/Control.LayersSpec.js index 1f85f6133..c47f3a607 100644 --- a/spec/suites/control/Control.LayersSpec.js +++ b/spec/suites/control/Control.LayersSpec.js @@ -140,4 +140,87 @@ describe("Control.Layers", function () { }); }); + describe("sortLayers", function () { + beforeEach(function () { + map.setView([0, 0], 14); + }); + + it("keeps original order by default", function () { + var baseLayerOne = L.tileLayer('').addTo(map); + var baseLayerTwo = L.tileLayer('').addTo(map); + var markerC = L.marker([0, 2]).addTo(map); + var markerB = L.marker([0, 1]).addTo(map); + var markerA = L.marker([0, 0]).addTo(map); + + var layersCtrl = L.control.layers({ + 'Base One': baseLayerOne, + 'Base Two': baseLayerTwo + }, { + 'Marker C': markerC, + 'Marker B': markerB, + 'Marker A': markerA + }).addTo(map); + + var elems = map.getContainer().querySelectorAll('div.leaflet-control-layers label span'); + expect(elems[0].innerHTML.trim()).to.be.equal('Base One'); + expect(elems[1].innerHTML.trim()).to.be.equal('Base Two'); + expect(elems[2].innerHTML.trim()).to.be.equal('Marker C'); + expect(elems[3].innerHTML.trim()).to.be.equal('Marker B'); + expect(elems[4].innerHTML.trim()).to.be.equal('Marker A'); + }); + + it("sorts alphabetically if no function is specified", function () { + var baseLayerOne = L.tileLayer('').addTo(map); + var baseLayerTwo = L.tileLayer('').addTo(map); + var markerA = L.marker([0, 0]).addTo(map); + var markerB = L.marker([0, 1]).addTo(map); + var markerC = L.marker([0, 2]).addTo(map); + + var layersCtrl = L.control.layers({ + 'Base Two': baseLayerTwo, + 'Base One': baseLayerOne + }, { + 'Marker A': markerA, + 'Marker C': markerC, + 'Marker B': markerB + }, { + sortLayers: true + }).addTo(map); + + var elems = map.getContainer().querySelectorAll('div.leaflet-control-layers label span'); + expect(elems[0].innerHTML.trim()).to.be.equal('Base One'); + expect(elems[1].innerHTML.trim()).to.be.equal('Base Two'); + expect(elems[2].innerHTML.trim()).to.be.equal('Marker A'); + expect(elems[3].innerHTML.trim()).to.be.equal('Marker B'); + expect(elems[4].innerHTML.trim()).to.be.equal('Marker C'); + }); + + it("uses the compare function to sort layers", function () { + var baseLayerOne = L.tileLayer('', {customOption: 999}).addTo(map); + var baseLayerTwo = L.tileLayer('', {customOption: 998}).addTo(map); + var markerA = L.marker([0, 0], {customOption: 102}).addTo(map); + var markerB = L.marker([0, 1], {customOption: 100}).addTo(map); + var markerC = L.marker([0, 2], {customOption: 101}).addTo(map); + + var layersCtrl = L.control.layers({ + 'Base One': baseLayerOne, + 'Base Two': baseLayerTwo + }, { + 'Marker A': markerA, + 'Marker B': markerB, + 'Marker C': markerC + }, { + sortLayers: true, + sortFunction: function (a, b) { return a.options.customOption - b.options.customOption; } + }).addTo(map); + + var elems = map.getContainer().querySelectorAll('div.leaflet-control-layers label span'); + expect(elems[0].innerHTML.trim()).to.be.equal('Base Two'); + expect(elems[1].innerHTML.trim()).to.be.equal('Base One'); + expect(elems[2].innerHTML.trim()).to.be.equal('Marker B'); + expect(elems[3].innerHTML.trim()).to.be.equal('Marker C'); + expect(elems[4].innerHTML.trim()).to.be.equal('Marker A'); + }); + }); + }); diff --git a/src/control/Control.Layers.js b/src/control/Control.Layers.js index aab3b2e27..ddb3d2742 100644 --- a/src/control/Control.Layers.js +++ b/src/control/Control.Layers.js @@ -53,7 +53,22 @@ L.Control.Layers = L.Control.extend({ // @option hideSingleBase: Boolean = false // If `true`, the base layers in the control will be hidden when there is only one. - hideSingleBase: false + hideSingleBase: false, + + // @option sortLayers: Boolean = false + // Whether to sort the layers. When `false`, layers will keep the order + // in which they were added to the control. + sortLayers: false, + + // @option sortFunction: Function = * + // 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)`. + // By default, it sorts layers alphabetically by their name. + sortFunction: function (layerA, layerB, nameA, nameB) { + return nameA < nameB ? -1 : (nameB < nameA ? 1 : 0); + } }, initialize: function (baseLayers, overlays, options) { @@ -209,6 +224,12 @@ L.Control.Layers = L.Control.extend({ overlay: overlay }); + if (this.options.sortLayers) { + this._layers.sort(L.bind(function (a, b) { + return this.options.sortFunction(a.layer, b.layer, a.name, b.name); + }, this)); + } + if (this.options.autoZIndex && layer.setZIndex) { this._lastZIndex++; layer.setZIndex(this._lastZIndex);