1. Import

This commit is contained in:
2026-03-29 10:34:57 +02:00
parent b0e00c1259
commit a1129565af
4899 changed files with 3007593 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
{
"rules": {
"camelcase": 2,
"quotes": [2, "single", "avoid-escape"],
"indent": 2,
"space-before-function-paren": [2, "never"],
"space-in-parens": 2,
"object-curly-spacing": 2,
"space-before-blocks": 2,
"keyword-spacing": 2,
"no-lonely-if": 2,
"comma-spacing": [2, {"after": true}],
"comma-style": 2,
"no-underscore-dangle": 0,
"no-constant-condition": 0,
"no-multi-spaces": 2,
"strict": 0,
"key-spacing": 2,
"no-shadow": 0,
"no-console": 2,
"no-trailing-spaces": 2,
},
"globals": {
"L": true,
"module": true,
"define": true
},
"plugins": [
"html"
],
"settings": {
"html/report-bad-indent": 2,
"html/indent": "space"
}
}

View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,5 @@
language: node_js
sudo: false
node_js:
- "stable"

View File

@@ -0,0 +1,61 @@
.leaflet-control-layers-toggle.leaflet-layerstree-named-toggle {
margin: 2px 5px;
width: auto;
height: auto;
background-image: none;
}
.leaflet-layerstree-node {
}
.leaflet-layerstree-header input{
margin-left: 0px;
}
.leaflet-layerstree-header {
}
.leaflet-layerstree-header-pointer {
cursor: pointer;
}
.leaflet-layerstree-header label {
display: inline-block;
cursor: pointer;
}
.leaflet-layerstree-header-label {
}
.leaflet-layerstree-header-name {
}
.leaflet-layerstree-header-space {
}
.leaflet-layerstree-children {
padding-left: 10px;
}
.leaflet-layerstree-children-nopad {
padding-left: 0px;
}
.leaflet-layerstree-closed {
}
.leaflet-layerstree-opened {
}
.leaflet-layerstree-hide {
display: none;
}
.leaflet-layerstree-nevershow {
display: none;
}
.leaflet-layerstree-expand-collapse {
cursor: pointer;
}

View File

@@ -0,0 +1,396 @@
/*
* Control like L.Control.Layers, but showing layers in a tree.
* Do not forget to include the css file.
*/
(function(L) {
if (typeof L === 'undefined') {
throw new Error('Leaflet must be included first');
}
/*
* L.Control.Layers.Tree extends L.Control.Layers because it reuses
* most of its functionality. Only the HTML creation is different.
*/
L.Control.Layers.Tree = L.Control.Layers.extend({
options: {
closedSymbol: '+',
openedSymbol: '−',
spaceSymbol: ' ',
selectorBack: false,
namedToggle: false,
collapseAll: '',
expandAll: '',
},
// Class names are error prone texts, so write them once here
_initClassesNames: function() {
this.cls = {
children: 'leaflet-layerstree-children',
childrenNopad: 'leaflet-layerstree-children-nopad',
hide: 'leaflet-layerstree-hide',
closed: 'leaflet-layerstree-closed',
opened: 'leaflet-layerstree-opened',
space: 'leaflet-layerstree-header-space',
pointer: 'leaflet-layerstree-header-pointer',
header: 'leaflet-layerstree-header',
neverShow: 'leaflet-layerstree-nevershow',
node: 'leaflet-layerstree-node',
name: 'leaflet-layerstree-header-name',
label: 'leaflet-layerstree-header-label',
};
},
initialize: function(baseTree, overlaysTree, options) {
this._scrollTop = 0;
this._initClassesNames();
this._baseTree = null;
this._overlaysTree = null;
L.Util.setOptions(this, options);
L.Control.Layers.prototype.initialize.call(this, null, null, options);
this._setTrees(baseTree, overlaysTree);
},
setBaseTree: function(tree) {
return this._setTrees(tree);
},
setOverlayTree: function(tree) {
return this._setTrees(undefined, tree);
},
addBaseLayer: function(layer, name) {
throw 'addBaseLayer is disabled';
},
addOverlay: function(layer, name) {
throw 'addOverlay is disabled';
},
removeLayer: function(layer) {
throw 'removeLayer is disabled';
},
collapse: function() {
this._scrollTop = this._sect().scrollTop;
return L.Control.Layers.prototype.collapse.call(this);
},
expand: function() {
var ret = L.Control.Layers.prototype.expand.call(this);
this._sect().scrollTop = this._scrollTop;
},
onAdd: function(map) {
function changeName(layer) {
if (layer._layersTreeName) {
toggle.innerHTML = layer._layersTreeName;
}
}
var ret = L.Control.Layers.prototype.onAdd.call(this, map);
if (this.options.namedToggle) {
var toggle = this._container.getElementsByClassName('leaflet-control-layers-toggle')[0];
L.DomUtil.addClass(toggle, 'leaflet-layerstree-named-toggle');
// Start with this value...
map.eachLayer(function(layer) {changeName(layer);});
// ... and change it whenever the baselayer is changed.
map.on('baselayerchange', function(e) {changeName(e.layer);}, this);
}
return ret;
},
// Expands the whole tree (base other overlays)
expandTree: function(overlay) {
var container = overlay ? this._overlaysList : this._baseLayersList;
if (container) {
this._applyOnTree(container, false);
}
return this._localExpand();
},
// Collapses the whole tree (base other overlays)
collapseTree: function(overlay) {
var container = overlay ? this._overlaysList : this._baseLayersList;
if (container) {
this._applyOnTree(container, true);
}
return this._localExpand();
},
// Expands the tree, only to show the selected inputs
expandSelected: function(overlay) {
function iter(el) {
// Function to iterate the whole DOM upwards
var p = el.parentElement;
if (p) {
if (L.DomUtil.hasClass(p, that.cls.children) &&
!L.DomUtil.hasClass(el, that.cls.childrenNopad)) {
L.DomUtil.removeClass(p, hide);
}
if (L.DomUtil.hasClass(p, that.cls.node)) {
var h = p.getElementsByClassName(that.cls.header)[0];
that._applyOnTree(h, false);
}
iter(p);
}
}
var that = this;
var container = overlay ? this._overlaysList : this._baseLayersList;
if (!container) return this;
var hide = this.cls.hide;
var inputs = this._layerControlInputs || container.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
// Loop over every (valid) input.
var input = inputs[i];
if (this._getLayer && !!this._getLayer(input.layerId).overlay != !!overlay) continue
if (input.checked) {
// Get out of the header,
// to not open the posible (but rare) children
iter(input.parentElement.parentElement.parentElement.parentElement);
}
}
return this._localExpand();
},
// "private" methods, not exposed in the API
_sect: function() {
// to keep compatibility after 1.3 https://github.com/Leaflet/Leaflet/pull/6380
return this._section || this._form;
},
_setTrees: function(base, overlays) {
var id = 0; // to keep unique id
function iterate(tree, output, overlays) {
if (tree && tree.layer) {
if (!overlays) {
tree.layer._layersTreeName = tree.name || tree.label;
}
output[id++] = tree.layer;
}
if (tree && tree.children && tree.children.length) {
tree.children.forEach(function(child) {
iterate(child, output, overlays);
});
}
return output;
}
// We accept arrays, but convert into an object with children
function forArrays(input) {
if (Array.isArray(input)) {
return {noShow: true, children: input};
} else {
return input
}
}
// Clean everything, and start again.
if (this._layerControlInputs) {
this._layerControlInputs = [];
}
for (var i = 0; i < this._layers.length; ++i) {
this._layers[i].layer.off('add remove', this._onLayerChange, this);
}
this._layers = [];
if (base !== undefined) this._baseTree = forArrays(base);
if (overlays !== undefined) this._overlaysTree = forArrays(overlays);
var bflat = iterate(this._baseTree, {});
for (var i in bflat) {
this._addLayer(bflat[i], i);
}
var oflat = iterate(this._overlaysTree, {}, true);
for (i in oflat) {
this._addLayer(oflat[i], i, true);
}
return (this._map) ? this._update() : this;
},
// Used to update the vertical scrollbar
_localExpand: function() {
if (this._map && L.DomUtil.hasClass(this._container, 'leaflet-control-layers-expanded')) {
var top = this._sect().scrollTop;
this.expand();
this._sect().scrollTop = top; // to keep the scroll location
this._scrollTop = top;
}
return this;
},
// collapses or expands the tree in the containter.
_applyOnTree: function(container, collapse) {
var iters = [
{cls: this.cls.children, hide: collapse},
{cls: this.cls.opened, hide: collapse},
{cls: this.cls.closed, hide: !collapse},
];
iters.forEach(function(it) {
var els = container.getElementsByClassName(it.cls);
for (var i = 0; i < els.length; i++) {
var el = els[i];
if (L.DomUtil.hasClass(el, this.cls.childrenNopad)) {
// do nothing
} else if (it.hide) {
L.DomUtil.addClass(el, this.cls.hide);
} else {
L.DomUtil.removeClass(el, this.cls.hide);
}
}
}, this);
},
// it is called in the original _update, and shouldn't do anything.
_addItem: function(obj) {
},
// overwrite _update function in Control.Layers
_update: function() {
if (!this._container) { return this; }
L.Control.Layers.prototype._update.call(this);
this._addTreeLayout(this._baseTree, false);
this._addTreeLayout(this._overlaysTree, true);
return this._localExpand();
},
// Create the DOM objects for the tree
_addTreeLayout: function(tree, overlay) {
if (!tree) return;
var container = overlay ? this._overlaysList : this._baseLayersList;
this._expandCollapseAll(overlay, this.options.collapseAll, this.collapseTree);
this._expandCollapseAll(overlay, this.options.expandAll, this.expandTree);
this._iterateTreeLayout(tree, container, overlay, tree.noShow)
if (this._checkDisabledLayers) {
// to keep compatibility
this._checkDisabledLayers();
}
},
// Create the "Collapse all" or expand, if needed.
_expandCollapseAll: function(overlay, text, fn, ctx) {
var container = overlay ? this._overlaysList : this._baseLayersList;
ctx = ctx ? ctx : this;
if (text) {
var o = document.createElement('div');
o.className = 'leaflet-layerstree-expand-collapse';
container.appendChild(o);
o.innerHTML = text;
o.tabIndex = 0;
L.DomEvent.on(o, 'click keydown', function(e) {
if (e.type !== 'keydown' || e.keyCode === 32) {
o.blur()
fn.call(ctx, overlay);
this._localExpand();
}
}, this);
}
},
// recursive funtion to create the DOM children
_iterateTreeLayout: function(tree, container, overlay, noShow) {
if (!tree) return;
function creator(type, cls, append, innerHTML) {
var obj = L.DomUtil.create(type, cls, append);
if (innerHTML) obj.innerHTML = innerHTML;
return obj;
}
// create the header with it fields
var header = creator('div', this.cls.header, container);
var sel = creator('span');
var entry = creator('span');
var closed = creator('span', this.cls.closed, sel, this.options.closedSymbol);
var opened = creator('span', this.cls.opened, sel, this.options.openedSymbol);
var space = creator('span', this.cls.space, null, this.options.spaceSymbol);
if (this.options.selectorBack) {
sel.insertBefore(space, closed);
header.appendChild(entry);
header.appendChild(sel);
} else {
sel.appendChild(space);
header.appendChild(sel);
header.appendChild(entry);
}
var hide = this.cls.hide; // To toggle state
// create the children group, with the header event click
if (tree.children) {
var children = creator('div', this.cls.children, container);
var sensible = tree.layer ? sel : header;
L.DomUtil.addClass(sensible, this.cls.pointer);
sensible.tabIndex = 0;
L.DomEvent.on(sensible, 'click keydown', function(e) {
if (e.type === 'keydown' && e.keyCode !== 32) {
return
}
sensible.blur();
if (L.DomUtil.hasClass(opened, hide)) {
// it is not opened, so open it
L.DomUtil.addClass(closed, hide);
L.DomUtil.removeClass(opened, hide);
L.DomUtil.removeClass(children, hide);
} else {
// close it
L.DomUtil.removeClass(closed, hide);
L.DomUtil.addClass(opened, hide);
L.DomUtil.addClass(children, hide);
}
this._localExpand();
}, this);
tree.children.forEach(function(child) {
var node = creator('div', this.cls.node, children)
this._iterateTreeLayout(child, node, overlay);
}, this);
} else {
// no children, so the selector makes no sense.
L.DomUtil.addClass(sel, this.cls.neverShow);
}
// create the input and label, as in Control.Layers
var label = creator(tree.layer ? 'label' : 'span', this.cls.label, entry);
if (tree.layer) {
// now create the element like in _addItem
var checked = this._map.hasLayer(tree.layer)
var input;
var radioGroup = overlay ? tree.radioGroup : 'leaflet-base-layers_' + L.Util.stamp(this);
if (radioGroup) {
input = this._createRadioElement(radioGroup, checked);
} else {
input = this._createCheckboxElement(checked);
}
if (this._layerControlInputs) {
// to keep compatibility with 1.0.3
this._layerControlInputs.push(input);
}
input.layerId = L.Util.stamp(tree.layer);
L.DomEvent.on(input, 'click', this._onInputClick, this);
label.appendChild(input);
}
var name = creator('span', this.cls.name, label, tree.label);
L.DomUtil.addClass(closed, hide);
if (noShow) {
L.DomUtil.addClass(header, this.cls.neverShow);
L.DomUtil.addClass(children, this.cls.childrenNopad);
}
},
_createCheckboxElement: function(checked) {
var input = document.createElement('input');
input.type = 'checkbox';
input.className = 'leaflet-control-layers-selector';
input.defaultChecked = checked;
return input;
},
});
L.control.layers.tree = function(base, overlays, options) {
return new L.Control.Layers.Tree(base, overlays, options);
}
})(L);

View File

@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2017, Javier Jimenez Shaw
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,125 @@
# Leaflet.Control.Layers.Tree
[![Build Status](https://travis-ci.org/jjimenezshaw/Leaflet.Control.Layers.Tree.svg)](https://travis-ci.org/jjimenezshaw/Leaflet.Control.Layers.Tree)
[![NPM version](https://img.shields.io/npm/v/leaflet.control.layers.tree.svg)](https://www.npmjs.com/package/leaflet.control.layers.tree)
[![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg?style=flat)](LICENSE)
[![Leaflet 1.x compatible!](https://img.shields.io/badge/Leaflet%201.x-%E2%9C%93-1EB300.svg?style=flat)](http://leafletjs.com/reference.html)
A Tree Layers Control for Leaflet.
## Description
This plugin extends [`Control.Layers`](http://leafletjs.com/reference-1.4.0.html#control-layers) allowing a tree structure for the layers layout. In `Control.Layers` you can only display a flat list of layers (baselayers and overlays), that is usually enough for small sets. If you have a long list of baselayers or overlays, and you want to organize them in a tree (allowing the user collapse and expand branches), this is a good option.
[Some live examples here](https://jjimenezshaw.github.io/Leaflet.Control.Layers.Tree/examples/)
## Installation
Using npm for browserify `npm install leaflet.control.layers.tree` (and `require('leaflet.control.layers.tree')`), or just download `L.Control.Layers.Tree.js` and `L.Control.Layers.Tree.css` and add a script and link tag for it in your html.
## Compatibility
This plugin has been tested with Leaflet 1.0.3, 1.1.0, 1.2.0, 1.3.1. and 1.4.0
## Usage
1. Create your layers. Do this as usual.
2. Create your layers tree, like the one just below.
3. Create the control and add to the map: `L.control.layers.tree(baseTree, overalysTree, options).addTo(map);`
4. Voilà!
```javascript
var baseTree = {
label: 'Base Layers',
children: [
{
label: 'World &#x1f5fa;',
children: [
{ label: 'OpenStreetMap', layer: osm },
{ label: 'Esri', layer: esri },
{ label: 'Google Satellite', layer: g_s },
/* ... */
]
},
{
label: 'Europe',
children: [
{ label: 'France', layer: france },
{ label: 'Germany', layer: germany },
{ label: 'Spain', layer: spain },
/* ... */
]
},
{
label: 'USA',
children: [
{
label: 'General',
children: [
{ label: 'Nautical', layer: usa_naut },
{ label: 'Satellite', layer: usa_sat },
{ label: 'Topographical', layer: usa_topo },
]
},
{
label: 'States',
children: [
{ label: 'CA', layer: usa_ca },
{ label: 'NY', layer: usa_ny },
/* ... */
]
}
]
},
]
};
```
![small tree sample](smalltree.png)
## API
### `L.Control.Layers.Tree`
The main (and only) 'class' involved in this plugin. It exteds `L.Control.Layers`, so most of its methods are available. `addBaseLayer`, `addOverlay` and `removeLayer` are non usable in `L.Control.Layers.Tree`.
#### `L.control.layers.tree(baseTree, overlayTree, options)`
Creates the control. The arguments are:
* `baseTree`: `<Object>` or `<Array>` Tree defining the base layers (like the one above). You can also provide an `Array` of nodes, if you want to start with a flat level.
* `overlayTree`: `<Object>` or `<Array>` Similar than baseTree, but for overlays.
* `options`: `<Object>` specific options for the tree. See that it includes `L.Control.Layer` [options](http://leafletjs.com/reference-1.4.0.html#control-layers)
##### constructor options
* `closedSymbol`: `<String>` Symbol displayed on a closed node (that you can click to open). Default '+'.
* `openedSymbol`: `<String>` Symbol displayed on a opened node (that you can click to close). Default '&minus;' (`&minus;`).
* `spaceSymbol`: `<String>` Symbol between the closed or opened symbol, and the text. Default ' ' (a normal space).
* `selectorBack`: `<Boolean>` Flag to indicate if the selector (+ or &minus;) is _after_ the text. Default 'false'.
* `namedToggle`: `<Boolean>` Flag to replace the toggle image (box with the layers image) with the 'name' of the selected base layer. If the `name` field is not present in the tree for this layer, `label` is used. See that you can show a different name when control is collapsed than the one that appears in the tree when it is expanded. Your node in the tree can be `{ label: 'OSM', name: 'OpenStreetMap', layer: layer }`. Default 'false'.
* `collapseAll`: `<String>` Text for an entry in control that collapses the tree (baselayers or overlays). If empty, no entry is created. Default ''.
* `expandAll`: `<String>` Text for an entry in control that expands the tree. If empty, no entry is created. Default ''.
See that those strings can be html code, with unicode, images or whatever you want.
#### `setBaseTree(tree)`
Resets the base layers tree (like in constructor, an `<Object>` or `<Array>`). Internally removes and adds all the layers, so you may be notified if you registered those events. Returns `this`.
#### `setOverlayTree(tree)`
Resets the overlay layers tree (like in constructor, an `<Object>` or `<Array>`). Internally removes and adds all the layers, so you may be notified if you registered those events. Returns `this`.
#### `expandTree(overlays)`
This method expands the tree. When `overlays` is `true` expands the overlays tree. Otherwise expands the baselayers tree. Returns `this`.
#### `collapseTree(overlays)`
This method collapses the tree. When `overlays` is `true` collapses the overlays tree. Otherwise collapses the baselayers tree. Returns `this`.
#### `expandSelected(overlays)`
This method expands only the selected item in the tree. When `overlays` is `true` affects the overlays tree. Otherwise affects the baselayers tree. Returns `this`.
## Tricks about the tree
The layers tree is a normal `Object`s tree like in the example above. The valid elements are:
* `children`: `<Array>` Array of children nodes for this node. Nothing special.
* `label`: `<String>` Text displayed in the tree for this node. It may contain HTML code.
* `layer`: `<L.Layer>` The layer itself. You can create with `L.tileLayer`, `L.marker`, or however you want.
* `name`: `<String>` Text displayed in the toggle when control is minimized. If not present, `label` is used. It makes sense only when `namedToggle` is `true`, and with base layers.
* `radioGroup`: `<String>` Text to identify different radio button groups. It is used in the `name` attribute in the [radio button](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio). It is used only in the overlays layers (ignored in the base layers), allowing you to have radio buttons instead of checkboxes. See that radio groups cannot be unselected, so create a 'fake' layer (like `L.layersGroup([])`) if you want to disable it. Deafult `''` (that means checkbox).
You can see an example of a baselayers tree (the javascript code) above. You can provide a tree, or an array of trees.
Non leaf nodes (that is, those with `children`) can also have a layer. In this case you will be able to select the layer, and only the icon will collapse or expand this branch.
You can include HTML code, not only ascii chars, in the `label` attribute. It will be included as `innerHTML`. Be carefull with unicodes, because not every browser supports them all.
A leaf node without `layer` attribute is also posible. Only with `label`. This can be used to include special commands calling a javascript function, or a separator, or whatever you like. An example of separator node is
```javascript
{label: '<div class="leaflet-control-layers-separator"></div>'}
```

View File

@@ -0,0 +1,25 @@
{
"name": "leaflet.control.layers.tree",
"version": "0.1.1",
"description": "Control Layers in a Tree structure",
"homepage": "https://github.com/jjimenezshaw/Leaflet.Control.Layers.Tree",
"authors": [
"Javier Jimenez Shaw"
],
"main": "L.Control.Layers.Tree.js",
"style": "L.Control.Layers.Tree.css",
"keywords": [
"Leaflet",
"map",
"geo",
"tree",
"control",
"layers"
],
"license": "BSD-3-Clause",
"ignore": [
"**/.*",
"node_modules",
"test"
]
}

View File

@@ -0,0 +1,295 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Leaflet Layers Tree Demo: Airports in Europe</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet-src.js" crossorigin=""></script>
<!--link rel="stylesheet" href="../../Leaflet/dist/leaflet.css" crossorigin=""/>
<script src="../../Leaflet/dist/leaflet-src.js" crossorigin=""></script-->
<style type="text/css">
html, body { width: 100%; height: 100%; margin: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<link rel="stylesheet" href="../L.Control.Layers.Tree.css" crossorigin=""/>
<script src="../L.Control.Layers.Tree.js"></script>
<script type="text/javascript">
var center = [40, 0];
var osm = L.tileLayer(
'//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var osmBw = L.tileLayer(
'http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var thunderAttr = {attribution: '© OpenStreetMap contributors. Tiles courtesy of Andy Allan'}
var transport = L.tileLayer(
'//{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png',
thunderAttr
);
var cycle = L.tileLayer(
'//{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',
thunderAttr
);
var map = L.map('map', {
layers: [osm],
center: center,
zoom: 5
});
var baseTree = {
label: 'BaseLayers',
noShow: true,
children: [
{
label: 'OpenStreeMap',
layer: osm,
children: [
{label: 'B&W', layer: osmBw, name: 'OpenStreeMap B&W'},
]
},
{
label: 'Thunder',
children: [
{label: 'Cycle', layer: cycle},
{label: 'Transport', layer: transport},
]
},
]
};
var ctl = L.control.layers.tree(baseTree, null,
{
collapsed: true,
namedToggle: true,
collapseAll: 'Collapse all',
expandAll: 'Expand all',
});
ctl.addTo(map).collapseTree().expandSelected();
var airportsEurope = [
/* start aiports from http://www.partow.net/miscellaneous/airportdatabase/#Download */
{label: 'GERMANY', children: [
{label: 'AACHEN - AAH', layer: L.marker([50.823000, 6.187000])},
{label: 'ALTENBURG - AOC', layer: L.marker([50.982000, 12.506000])},
{label: 'ARNSBERG - ZCA', layer: L.marker([51.483000, 7.899000])},
{label: 'AUGSBURG - AGB', layer: L.marker([48.425000, 10.932000])},
{label: 'BADEN-BADEN - ZCC', layer: L.marker([48.791000, 8.187000])},
{label: 'BAUTZEN - BBJ', layer: L.marker([51.193000, 14.520000])},
{label: 'BAYREUTH - BYU', layer: L.marker([49.984000, 11.638000])},
{label: 'BERLIN - SXF', layer: L.marker([52.380000, 13.523000])},
{label: 'BERLIN - THF', layer: L.marker([52.473000, 13.404000])},
{label: 'BERLIN - TXL', layer: L.marker([52.559000, 13.287000])},
{label: 'BORKUM - BMK', layer: L.marker([53.595000, 6.709000])},
{label: 'BRAUNSCHWEIG - BWE', layer: L.marker([52.319000, 10.556000])},
{label: 'BREMEN - BRE', layer: L.marker([53.047000, 8.787000])},
{label: 'BREMERHAVEN - BRV', layer: L.marker([53.503000, 8.573000])},
{label: 'BRUEGGEN - BGN', layer: L.marker([51.200000, 6.132000])},
{label: 'CELLE - ZCN', layer: L.marker([52.591000, 10.022000])},
{label: 'COLOGNE - CGN', layer: L.marker([50.866000, 7.143000])},
{label: 'DONAUESCHINGEN - ZQL', layer: L.marker([47.973000, 8.522000])},
{label: 'DORTMUND - DTM', layer: L.marker([51.518000, 7.612000])},
{label: 'DRESDEN - DRS', layer: L.marker([51.133000, 13.767000])},
{label: 'DUESSELDORF - DUS', layer: L.marker([51.289000, 6.767000])},
{label: 'EMDEN - EME', layer: L.marker([53.391000, 7.227000])},
{label: 'ERFURT - ERF', layer: L.marker([50.980000, 10.958000])},
{label: 'ESSEN - ESS', layer: L.marker([51.401000, 6.936000])},
{label: 'FRANKFURT - FRA', layer: L.marker([50.026000, 8.543000])},
{label: 'FRIEDRICHSHAFEN - FDH', layer: L.marker([47.671000, 9.511000])},
{label: 'FUERSTENFELDBRUCK - FEL', layer: L.marker([48.206000, 11.267000])},
{label: 'GEILENKIRCHEN - GKE', layer: L.marker([50.961000, 6.042000])},
{label: 'GIEBELSTADT - GHF', layer: L.marker([49.648000, 9.966000])},
{label: 'GOTHA OST - GWW', layer: L.marker([35.461000, -77.965000])},
{label: 'GUETERSLOH - GUT', layer: L.marker([51.923000, 8.306000])},
{label: 'HAHN - HHN', layer: L.marker([49.950000, 7.264000])},
{label: 'HAMBURG - HAM', layer: L.marker([53.630000, 9.988000])},
{label: 'HAMBURG - XFW', layer: L.marker([53.535000, 9.835000])},
{label: 'HANAU - ZNF', layer: L.marker([50.169000, 8.961000])},
{label: 'HANNOVER - HAJ', layer: L.marker([52.461000, 9.685000])},
{label: 'HEIDELBERG - QHD', layer: L.marker([49.393000, 8.652000])},
{label: 'HOF - HOQ', layer: L.marker([50.289000, 11.855000])},
{label: 'KASSEL - KSF', layer: L.marker([51.408000, 9.378000])},
{label: 'KIEL - KEL', layer: L.marker([54.379000, 10.145000])},
{label: 'KOBLENZ - ZNV', layer: L.marker([50.325000, 7.531000])},
{label: 'LAAGE - RLG', layer: L.marker([53.918000, 12.279000])},
{label: 'LAARBRUCH - LRC', layer: L.marker([51.602000, 6.143000])},
{label: 'LEIPZIG - LEJ', layer: L.marker([51.424000, 12.236000])},
{label: 'LEMWERDER - LEM', layer: L.marker([53.143000, 8.623000])},
{label: 'LUEBECK - LBC', layer: L.marker([53.805000, 10.719000])},
{label: 'MANNHEIM - MHG', layer: L.marker([49.473000, 8.514000])},
{label: 'MOENCHENGLADBACH - MGL', layer: L.marker([51.230000, 6.504000])},
{label: 'MUENSTER/OSNABRUECK - FMO', layer: L.marker([52.134000, 7.685000])},
{label: 'MUNICH - MUC', layer: L.marker([48.354000, 11.786000])},
{label: 'NORDERNEY - NRD', layer: L.marker([53.707000, 7.230000])},
{label: 'NUERNBERG - NUE', layer: L.marker([49.499000, 11.078000])},
{label: 'OBERPFAFFENHOFEN - OBF', layer: L.marker([48.081000, 11.283000])},
{label: 'PADERBORN - PAD', layer: L.marker([51.614000, 8.616000])},
{label: 'PARCHIM - SZW', layer: L.marker([53.427000, 11.783000])},
{label: 'RAMSTEIN - RMS', layer: L.marker([49.438000, 7.601000])},
{label: 'SAARBRUECKEN - SCN', layer: L.marker([49.214000, 7.109000])},
{label: 'SPANGDAHLEM - SPM', layer: L.marker([49.973000, 6.692000])},
{label: 'SPEYER - ZQC', layer: L.marker([49.302000, 8.451000])},
{label: 'STUTTGART - STR', layer: L.marker([48.690000, 9.222000])},
{label: 'TRIER - ZQF', layer: L.marker([49.863000, 6.789000])},
{label: 'WESTERLAND - GWT', layer: L.marker([54.913000, 8.340000])},
{label: 'WILHELMSHAVEN - WVN', layer: L.marker([53.505000, 8.053000])},
]},
{label: 'SPAIN', children: [
{label: 'ALICANTE - ALC', layer: L.marker([38.282000, -0.558000])},
{label: 'ALMERIA - LEI', layer: L.marker([36.844000, -2.370000])},
{label: 'AVILES - OVD', layer: L.marker([43.563000, -6.034000])},
{label: 'BADAJOZ - BJZ', layer: L.marker([38.891000, -6.821000])},
{label: 'BARCELONA - BCN', layer: L.marker([41.297000, 2.078000])},
{label: 'BILBAO - BIO', layer: L.marker([43.301000, -2.911000])},
{label: 'CORDOBA - ODB', layer: L.marker([37.842000, -4.849000])},
{label: 'GERONA - GRO', layer: L.marker([41.901000, 2.760000])},
{label: 'GRANADA - GRX', layer: L.marker([37.133000, -3.636000])},
{label: 'GRANADA - GRX', layer: L.marker([37.189000, -3.777000])},
{label: 'IBIZA - IBZ', layer: L.marker([38.873000, 1.373000])},
{label: 'JEREZ - XRY', layer: L.marker([36.744000, -6.060000])},
{label: 'LA CORUNA - LCG', layer: L.marker([43.302000, -8.377000])},
{label: 'MADRID - MAD', layer: L.marker([40.472000, -3.561000])},
{label: 'MADRID - TOJ', layer: L.marker([40.487000, -3.458000])},
{label: 'MALAGA - AGP', layer: L.marker([36.674000, -4.499000])},
{label: 'MENORCA - MAH', layer: L.marker([39.863000, 4.219000])},
{label: 'MURCIA - MJV', layer: L.marker([37.775000, -0.812000])},
{label: 'PALMA DE MALLORCA - PMI', layer: L.marker([39.550000, 2.733000])},
{label: 'PAMPLONA - PNA', layer: L.marker([42.770000, -1.646000])},
{label: 'REUS - REU', layer: L.marker([41.147000, 1.167000])},
{label: 'SALAMANCA - SLM', layer: L.marker([40.952000, -5.502000])},
{label: 'SAN SEBASTIAN - EAS', layer: L.marker([43.356000, -1.791000])},
{label: 'SANTA CRUZ DE LA PALMA - SPC', layer: L.marker([28.626000, -17.756000])},
{label: 'SANTANDER - SDR', layer: L.marker([43.427000, -3.820000])},
{label: 'SANTIAGO - SCQ', layer: L.marker([42.896000, -8.415000])},
{label: 'SEO DE URGEL - LEU', layer: L.marker([42.339000, 1.409000])},
{label: 'SEVILLA - OZP', layer: L.marker([37.175000, -5.616000])},
{label: 'SEVILLA - SVQ', layer: L.marker([37.418000, -5.893000])},
{label: 'VALENCIA - VLC', layer: L.marker([39.489000, -0.481000])},
{label: 'VALLADOLID - VLL', layer: L.marker([41.706000, -4.852000])},
{label: 'VIGO - VGO', layer: L.marker([42.232000, -8.627000])},
{label: 'VITORIA - VIT', layer: L.marker([42.883000, -2.724000])},
{label: 'ZARAGOZA - ZAZ', layer: L.marker([41.666000, -1.041000])},
]},
{label: 'FRANCE', children: [
{label: 'AGEN - AGF', layer: L.marker([44.175000, 0.591000])},
{label: 'AIX-LES-MILLES - QXB', layer: L.marker([43.505000, 5.368000])},
{label: 'ALBI - LBI', layer: L.marker([43.914000, 2.113000])},
{label: 'ANGOULEME - ANG', layer: L.marker([45.729000, 0.221000])},
{label: 'ANNECY - NCY', layer: L.marker([45.929000, 6.099000])},
{label: 'ANNEMASSE - QNJ', layer: L.marker([46.192000, 6.268000])},
{label: 'ARCACHON - XAC', layer: L.marker([44.596000, -1.111000])},
{label: 'AUBENAS-VALS-LANAS - OBS', layer: L.marker([44.544000, 4.372000])},
{label: 'AURILLAC - AUR', layer: L.marker([44.891000, 2.422000])},
{label: 'AUXERRE - AUF', layer: L.marker([47.850000, 3.497000])},
{label: 'AVIGNON - AVN', layer: L.marker([43.907000, 4.902000])},
{label: 'BEAUVAIS - BVA', layer: L.marker([49.454000, 2.113000])},
{label: 'BERGERAC - EGC', layer: L.marker([44.825000, 0.519000])},
{label: 'BEZIERS - BZR', layer: L.marker([43.324000, 3.356000])},
{label: 'BIARRITZ-BAYONNE - BIQ', layer: L.marker([43.468000, -1.523000])},
{label: 'BORDEAUX - BOD', layer: L.marker([44.828000, -0.716000])},
{label: 'BOURG - XBK', layer: L.marker([46.201000, 5.292000])},
{label: 'BOURGES - BOU', layer: L.marker([47.058000, 2.370000])},
{label: 'BREST - BES', layer: L.marker([48.448000, -4.418000])},
{label: 'BRIVE - BVE', layer: L.marker([45.151000, 1.469000])},
{label: 'CAEN - CFR', layer: L.marker([49.173000, -0.450000])},
{label: 'CALAIS - CQF', layer: L.marker([50.962000, 1.955000])},
{label: 'CANNES - CEQ', layer: L.marker([43.542000, 6.953000])},
{label: 'CARCASSONNE - CCF', layer: L.marker([43.216000, 2.306000])},
{label: 'CASTRES - DCM', layer: L.marker([43.556000, 2.289000])},
{label: 'CHALON - XCD', layer: L.marker([46.826000, 4.817000])},
{label: 'CHAMBERY - CMF', layer: L.marker([45.638000, 5.880000])},
{label: 'CHATEAUROUX - CHR', layer: L.marker([46.862000, 1.731000])},
{label: 'CHERBOURG - CER', layer: L.marker([49.650000, -1.470000])},
{label: 'CHOLET - CET', layer: L.marker([47.082000, -0.877000])},
{label: 'CLERMONT FERRAND - CFE', layer: L.marker([45.786000, 3.169000])},
{label: 'COGNAC - CNG', layer: L.marker([45.658000, -0.318000])},
{label: 'COLMAR - CMR', layer: L.marker([48.110000, 7.359000])},
{label: 'CREIL - CSF', layer: L.marker([49.253000, 2.519000])},
{label: 'DEAUVILLE - DOL', layer: L.marker([49.365000, 0.154000])},
{label: 'DIJON - DIJ', layer: L.marker([47.269000, 5.090000])},
{label: 'DINARD - DNR', layer: L.marker([48.588000, -2.080000])},
{label: 'DOLE - DLE', layer: L.marker([47.039000, 5.427000])},
{label: 'EPINAL - EPL', layer: L.marker([48.325000, 6.070000])},
{label: 'GRENOBLE - GNB', layer: L.marker([45.363000, 5.329000])},
{label: 'HYERES - TLN', layer: L.marker([43.097000, 6.146000])},
{label: 'LA ROCHE-SUR-YON - EDM', layer: L.marker([46.702000, -1.379000])},
{label: 'LA ROCHELLE - LRH', layer: L.marker([43.449000, 1.263000])},
{label: 'LANNION - LAI', layer: L.marker([48.754000, -3.471000])},
{label: 'LAVAL - LVA', layer: L.marker([48.031000, -0.743000])},
{label: 'LE CASTELLET - CTT', layer: L.marker([43.252000, 5.785000])},
{label: 'LE HAVRE - LEH', layer: L.marker([49.534000, 0.088000])},
{label: 'LE MANS - LME', layer: L.marker([47.949000, 0.202000])},
{label: 'LE PUY - LPY', layer: L.marker([45.079000, 3.765000])},
{label: 'LE TOURQUET - LTQ', layer: L.marker([50.515000, 1.627000])},
{label: 'LILLE - LIL', layer: L.marker([50.562000, 3.089000])},
{label: 'LIMOGES - LIG', layer: L.marker([45.863000, 1.179000])},
{label: 'LORIENT - LRT', layer: L.marker([47.761000, -3.440000])},
{label: 'LYON - LYN', layer: L.marker([45.728000, 4.945000])},
{label: 'LYON - LYS', layer: L.marker([45.726000, 5.091000])},
{label: 'MACON - QNX', layer: L.marker([46.295000, 4.796000])},
{label: 'MARSEILLE - MRS', layer: L.marker([43.436000, 5.214000])},
{label: 'MENDE - MEN', layer: L.marker([44.502000, 3.533000])},
{label: 'METZ - ETZ', layer: L.marker([48.982000, 6.254000])},
{label: 'METZ - MZM', layer: L.marker([49.072000, 6.132000])},
{label: 'MONTLUCON-GUERET - MCU', layer: L.marker([46.224000, 2.363000])},
{label: 'MONTLUCON - MCU', layer: L.marker([46.352000, 2.570000])},
{label: 'MONTPELLIER - MPL', layer: L.marker([43.576000, 3.963000])},
{label: 'MORLAIX - MXN', layer: L.marker([48.603000, -3.816000])},
{label: 'MOULINS - XMU', layer: L.marker([46.534000, 3.424000])},
{label: 'MULHOUSE - MLH', layer: L.marker([47.589000, 7.530000])},
{label: 'NANCY - ENC', layer: L.marker([48.692000, 6.230000])},
{label: 'NANTES - NTE', layer: L.marker([47.153000, -1.611000])},
{label: 'NEVERS - NVS', layer: L.marker([47.001000, 3.114000])},
{label: 'NICE - NCE', layer: L.marker([43.661000, 7.218000])},
{label: 'NIMES - FNI', layer: L.marker([43.757000, 4.416000])},
{label: 'NIORT - NIT', layer: L.marker([46.311000, -0.401000])},
{label: 'ORLEANS - ORE', layer: L.marker([47.988000, 1.761000])},
{label: 'PARIS - CDG', layer: L.marker([49.013000, 2.550000])},
{label: 'PARIS - LBG', layer: L.marker([48.969000, 2.441000])},
{label: 'PARIS - ORY', layer: L.marker([48.725000, 2.359000])},
{label: 'PAU - PUF', layer: L.marker([43.380000, -0.419000])},
{label: 'PERIGUEUX - PGX', layer: L.marker([45.198000, 0.816000])},
{label: 'PERPIGNAN - PGF', layer: L.marker([42.740000, 2.871000])},
{label: 'POITIERS - PIS', layer: L.marker([46.588000, 0.307000])},
{label: 'PONTOISE - POX', layer: L.marker([49.096000, 2.041000])},
{label: 'QUIMPER - UIP', layer: L.marker([47.975000, -4.168000])},
{label: 'REIMS - RHE', layer: L.marker([49.310000, 4.050000])},
{label: 'RENNES - RNS', layer: L.marker([48.069000, -1.735000])},
{label: 'ROANNE - RNE', layer: L.marker([46.058000, 4.001000])},
{label: 'ROCHEFORT - RCO', layer: L.marker([45.888000, -0.983000])},
{label: 'RODEZ - RDZ', layer: L.marker([44.408000, 2.482000])},
{label: 'ROUEN - URO', layer: L.marker([49.384000, 1.175000])},
{label: 'ROYAN - RYN', layer: L.marker([45.628000, -0.973000])},
{label: 'ST.-BRIEUC ARMOR - SBK', layer: L.marker([48.538000, -2.854000])},
{label: 'ST.-ETIENNE - EBU', layer: L.marker([45.540000, 4.296000])},
{label: 'ST.-NAZAIRE - SNR', layer: L.marker([47.312000, -2.149000])},
{label: 'STRASSBOURG - SXB', layer: L.marker([48.538000, 7.628000])},
{label: 'TARBES - LDE', layer: L.marker([43.179000, -0.006000])},
{label: 'TOULOUSE - TLS', layer: L.marker([43.629000, 1.364000])},
{label: 'TOURS - TUF', layer: L.marker([47.432000, 0.728000])},
{label: 'TOUSSOUS-LE-NOBLE - TNF', layer: L.marker([48.752000, 2.106000])},
{label: 'TROYES - QYR', layer: L.marker([48.323000, 4.018000])},
{label: 'VALENCE - VAF', layer: L.marker([44.921000, 4.970000])},
{label: 'VANNES - VNE', layer: L.marker([47.723000, -2.718000])},
{label: 'VICHY - VHY', layer: L.marker([46.169000, 3.404000])},
{label: 'VILEFRANCE - XVF', layer: L.marker([45.916000, 4.641000])},
]}
];
/* ends aiports */
ctl.setOverlayTree(airportsEurope).collapseTree(true).expandSelected(true);
</script>
</body>
</html>

View File

@@ -0,0 +1,79 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Leaflet Layers Tree Basic Demo</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet-src.js" crossorigin=""></script>
<style type="text/css">
html, body { width: 100%; height: 100%; margin: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<link rel="stylesheet" href="../L.Control.Layers.Tree.css" crossorigin=""/>
<script src="../L.Control.Layers.Tree.js"></script>
<script type="text/javascript">
var center = [40, 0];
// Define some base layers
var osm = L.tileLayer(
'//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var osmBw = L.tileLayer(
'http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var otopomap = L.tileLayer(
'//{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors. OpenTopoMap.org'}
);
var thunderAttr = {attribution: '© OpenStreetMap contributors. Tiles courtesy of Andy Allan'}
var transport = L.tileLayer(
'//{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png',
thunderAttr
);
var cycle = L.tileLayer(
'//{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',
thunderAttr
);
// The tree containing the layers
var baseTree = [
{
label: 'OpenStreeMap',
children: [
{label: 'OSM', layer: osm, name: 'OpenStreeMap'},
{label: 'B&W', layer: osmBw, name: 'OpenStreeMap <b>B&W</b>'},
{label: 'OpenTopoMap', layer: otopomap, name: 'Topographic - OSM'},
]
},
{
label: 'Thunder',
children: [
{label: 'Cycle', layer: cycle},
{label: 'Transport', layer: transport},
]
},
];
// The map
var map = L.map('map', {
layers: [osm],
center: center,
zoom: 5
});
L.control.layers.tree(baseTree).addTo(map);
</script>
</body>
</html>

View File

@@ -0,0 +1,79 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Leaflet Layers Tree Basic Demo</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet-src.js" crossorigin=""></script>
<style type="text/css">
html, body { width: 100%; height: 100%; margin: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<link rel="stylesheet" href="../L.Control.Layers.Tree.css" crossorigin=""/>
<script src="../L.Control.Layers.Tree.js"></script>
<script type="text/javascript">
var center = [40, 0];
// Define some base layers
var osm = L.tileLayer(
'//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var osmBw = L.tileLayer(
'http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var otopomap = L.tileLayer(
'//{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors. OpenTopoMap.org'}
);
var thunderAttr = {attribution: '© OpenStreetMap contributors. Tiles courtesy of Andy Allan'}
var transport = L.tileLayer(
'//{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png',
thunderAttr
);
var cycle = L.tileLayer(
'//{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',
thunderAttr
);
// The tree containing the layers
var baseTree = [
{
label: 'OpenStreeMap',
children: [
{label: 'OSM', layer: osm, name: 'OpenStreeMap'},
{label: 'B&W', layer: osmBw, name: 'OpenStreeMap <b>B&W</b>'},
{label: 'OpenTopoMap', layer: otopomap, name: 'Topographic - OSM'},
]
},
{
label: 'Thunder',
children: [
{label: 'Cycle', layer: cycle},
{label: 'Transport', layer: transport},
]
},
];
// The map
var map = L.map('map', {
layers: [osm],
center: center,
zoom: 5
});
L.control.layers.tree(baseTree).addTo(map);
</script>
</body>
</html>

View File

@@ -0,0 +1,10 @@
<html>
<body>
<ul>
<li><a href="./basic.html">basic.html</a></li>
<li><a href="./options.html">options.html</a></li>
<li><a href="./airports.html">airports.html</a></li>
<li><a href="./basic_1.3.4.html">basic_1.3.4.html</a></li>
</ul>
</body>
</html>

View File

@@ -0,0 +1,127 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Leaflet Layers Tree Demo</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet-src.js" crossorigin=""></script>
<style type="text/css">
html, body { width: 100%; height: 100%; margin: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<link rel="stylesheet" href="../L.Control.Layers.Tree.css" crossorigin=""/>
<script src="../L.Control.Layers.Tree.js"></script>
<script type="text/javascript">
var center = [40, 0];
var osm = L.tileLayer(
'//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var osmBw = L.tileLayer(
'http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors'}
);
var otopomap = L.tileLayer(
'//{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap contributors. OpenTopoMap.org'}
);
var thunderAttr = {attribution: '© OpenStreetMap contributors. Tiles courtesy of Andy Allan'}
var transport = L.tileLayer(
'//{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png',
thunderAttr
);
var cycle = L.tileLayer(
'//{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',
thunderAttr
);
var map = L.map('map', {
layers: [osm],
center: center,
zoom: 5
});
var baseTree = [
{
label: 'OpenStreeMap',
layer: osm,
children: [
{label: 'B&W', layer: osmBw, name: 'OpenStreeMap <b>B&W</b>'},
{label: 'OpenTopoMap', layer: otopomap, name: 'Topographic - OSM'},
]
},
{
label: 'Thunder',
children: [
{label: 'Cycle', layer: cycle},
{label: 'Transport', layer: transport},
]
},
];
var overlaysTree = {
label: 'Some cities',
children: [
{label: '<div id="onlysel">-Show only selected-</div>'},
{label: 'France', children: [
{label: 'Lyon', layer: L.marker([45.728, 4.945])},
{label: 'Paris', layer: L.marker([48.725, 2.359])},
{label: 'Toulouse', layer: L.marker([43.629, 1.364])},
]},
{label: 'Germany', children: [
{label: 'Berlin', layer: L.marker([52.559, 13.287])},
{label: 'Cologne', layer: L.marker([50.866, 7.143])},
{label: 'Hamburg', layer: L.marker([53.630, 9.988])},
{label: 'Munich', layer: L.marker([48.354, 11.786])},
]},
{label: 'Spain', children: [
{label: 'Madrid', layer: L.marker([40.472, -3.561])},
{label: 'Andalucia', children: [
{label: 'Granada', layer: L.marker([37.133, -3.636])},
{label: 'Málaga', layer: L.marker([36.674, -4.499])},
{label: 'Sevilla', layer: L.marker([37.418, -5.893])},
]},
{label: 'Bask Country', children: [
{label: '---', layer: L.layerGroup([]), radioGroup: 'bc'},
{label: 'Bilbao', layer: L.marker([43.301, -2.911]), radioGroup: 'bc'},
{label: 'San Sebastian', layer: L.marker([43.356, -1.791]), radioGroup: 'bc'},
{label: 'Vitoria', layer: L.marker([42.883, -2.724]), radioGroup: 'bc'},
]},
{label: 'Catalonia', children: [
{label: 'Barcelona', layer: L.marker([41.297, 2.078])},
{label: 'Gerona', layer: L.marker([41.901, 2.760])},
]},
]},
]
}
var lay = L.control.layers.tree(baseTree, overlaysTree,
{
namedToggle: true,
selectorBack: false,
closedSymbol: '&#8862; &#x1f5c0;',
openedSymbol: '&#8863; &#x1f5c1;',
collapseAll: 'Collapse all',
expandAll: 'Expand all',
});
lay.addTo(map).collapseTree().expandSelected().collapseTree(true);
L.DomEvent.on(L.DomUtil.get('onlysel'), 'click', function() {
lay.collapseTree(true).expandSelected(true);
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
{
"name": "leaflet.control.layers.tree",
"version": "0.1.1",
"description": "Control Layers in a Tree structure",
"main": "L.Control.Layers.Tree.js",
"style": "L.Control.Layers.Tree.css",
"directories": {
"test": "test"
},
"license": "BSD-3-Clause",
"scripts": {
"lint": "eslint L.*.js test/* examples/*",
"lintfix": "eslint L.*.js test/* examples/* --fix",
"spec": "phantomjs ./node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html",
"test": "npm run lint && npm run spec"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jjimenezshaw/Leaflet.Control.Layers.Tree.git"
},
"keywords": [
"Leaflet",
"map",
"geo",
"tree",
"control",
"layers"
],
"devDependencies": {
"blanket": "^1.2.3",
"chai": "~4.1.2",
"chai-leaflet": "^0.0.13",
"eslint": "^4.19.1",
"eslint-plugin-html": "^4.0.6",
"happen": "^0.3.2",
"leaflet": "^1.4.0",
"mocha": "^5.2.0",
"mocha-phantomjs-core": "^2.1.2",
"phantomjs-prebuilt": "^2.1.16"
},
"peerDependencies": {
"leaflet": "^1.1.0"
},
"author": "Javier Jimenez Shaw",
"readmeFilename": "README.md"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,53 @@
<html>
<head>
<meta charset="utf-8">
<title>Leaflet.Control.Layers.Tree Tests</title>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
<link rel="stylesheet" href="../node_modules/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="../L.Control.Layers.Tree.css" />
<style>
.map, .label {
width: 400px;
height: 400px;
float: left;
}
.label {
width: 40px;
text-align: left;
font-size: 40px;
padding: 20px 30px;
}
#mocha {
clear: both;
}
</style>
</head>
<body>
<div id="maps">
<div id="mapA" class="map"></div>
</div>
<div id="mocha"></div>
<script src="../node_modules/leaflet/dist/leaflet.js"></script>
<script src="../L.Control.Layers.Tree.js" data-cover></script>
<script src="../node_modules/chai/chai.js"></script>
<script src="../node_modules/mocha/mocha.js"></script>
<script src="../node_modules/happen/happen.js"></script>
<script src="../node_modules/chai-leaflet/chai-leaflet.js"></script>
<!--script src="../node_modules/blanket/dist/mocha/blanket_mocha.js"></script-->
<script>
mocha.setup('bdd');
</script>
<script src="spec.js"></script>
<script>
mocha.globals(['L']);
(window.mochaPhantomJS || mocha).run();
</script>
</body>
</html>

View File

@@ -0,0 +1,574 @@
'use strict';
var layerA = L.tileLayer('');
var layerB = L.tileLayer('');
function baseArray1() {
return [
{label: 'Leaf one', name: 'Name Leaf one', layer: L.tileLayer('')},
{label: 'Leaf two', name: 'Name Leaf two', layer: L.tileLayer('', {idx: 'two'})},
{
label: 'Node 1',
children: [
{label: 'Leaf 11', name: 'Name Leaf 11', layer: layerA},
{label: 'Leaf 12', layer: L.tileLayer('')}
]
},
{label: 'Leaf three', name: 'Name Leaf three', layer: layerB}
];
}
function baseArray2() {
return [
{label: 'Leaf one', name: 'Name Leaf one', layer: layerA},
{label: 'Leaf two', name: 'Name Leaf two', layer: layerB},
];
}
function baseTree1() {
return {
noShow: false,
label: 'Root node',
children: baseArray1()
};
}
var markerO = L.marker([0, 0]);
var markerA = L.marker([40, 0]);
var markerB = L.marker([0, 30]);
function overlaysArray1() {
return [
{label: 'Over one', name: 'Name Over one', layer: markerO},
{label: 'Over two', name: 'Name Over two', layer: L.layerGroup([])},
{
label: 'O Node 1',
children: [
{label: 'Over 11', name: 'Name Over 11', layer: markerA},
{label: 'Over 12', layer: L.layerGroup([])}
]
},
{label: 'Over three', name: 'Name Over three', layer: markerB}
]
}
function overlaysTree1() {
return {
noShow: false,
label: 'Root O node',
children: overlaysArray1()
};
}
function overlaysArray2() {
return [
{label: 'Over A', name: 'Name Over A', layer: markerA},
{label: 'Over B', name: 'Name Over B', layer: markerB},
];
}
function isHidden(el) {
// https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom
return (el.offsetParent === null)
}
function checkHidden(list, value, first) {
first = first || 0;
if (!Array.isArray(value)) {
var v = value;
value = [];
for (var i = 0; i < list.length; i++) value.push(v);
}
for (var i = first; i < list.length; i++) {
isHidden(list[i]).should.be.equal(!!value[i], 'position ' + i);
}
}
describe('L.Control.Layers.Tree', function() {
chai.should();
this.timeout(5000);
var map;
beforeEach(function() {
map && map.remove();
//map = L.map(document.createElement('div'));
map = L.map('mapA');
document.body.appendChild(map._container);
});
afterEach(function() {
//map.remove();
});
describe('Functions in place', function() {
beforeEach(function() {
map.setView([0, 0], 14);
});
it('L.Control.Layers.Tree has correct func', function() {
L.control.layers.tree.should.be.a('function');
});
it('L.control.layers.tree object creation', function() {
var t = L.control.layers.tree();
t.should.be.a('object');
});
});
describe('Disabled functions', function() {
var t = L.control.layers.tree();
var methods = [t.addBaseLayer, t.addOverlay, t.removeLayer];
methods.forEach(function(method) {
(function() {
method();
}).should.throw(method.name + ' is disabled');
});
});
describe('Simple base tests', function() {
beforeEach(function() {
map.setView([0, 0], 14);
});
it('they are there', function() {
var ctl = L.control.layers.tree(baseTree1(), null,
{collapsed: false}).addTo(map);
var inputs = map._container.querySelectorAll('.leaflet-control-layers-base input');
inputs.length.should.be.equal(5);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers.length.should.be.equal(7);
checkHidden(headers, false, 0);
ctl.collapseTree();
checkHidden(headers, true, 1);
});
it('they are accesible on mouseover', function() {
var ctrl = L.control.layers.tree(baseTree1()).addTo(map);
var inputs = map._container.querySelectorAll('.leaflet-control-layers-base input');
inputs.length.should.be.equal(5);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers.length.should.be.equal(7);
// Nothing visible because the contrl is collapsed
checkHidden(inputs, true, 0);
checkHidden(headers, true, 0);
// mouse over the control to show it.
happen.once(ctrl._container, {type: 'mouseover'});
checkHidden(inputs, false, 0);
checkHidden(headers, false, 0);
// Hi, let it as you found it.
happen.once(ctrl._container, {type: 'mouseout'});
});
});
describe('Simple base tests with array', function() {
beforeEach(function() {
map.setView([0, 0], 14);
});
it('they are accesible on mouseover', function() {
var ctrl = L.control.layers.tree(baseArray1()).addTo(map);
var inputs = map._container.querySelectorAll('.leaflet-control-layers-base input');
inputs.length.should.be.equal(5);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers.length.should.be.equal(7); // The root is hidden, but it is there
// Nothing visible because the contrl is collapsed
checkHidden(inputs, true, 0);
checkHidden(headers, true, 0);
// mouse over the control to show it.
happen.once(ctrl._container, {type: 'mouseover'});
checkHidden(inputs, false, 0);
checkHidden(headers, false, 1);
checkHidden(headers, [1, 0, 0, 0, 0, 0, 0], 0); // see, root is hidden!
// Hi, let it as you found it.
happen.once(ctrl._container, {type: 'mouseout'});
});
});
describe('Simple overlays tests', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('they are there', function() {
var ctl = L.control.layers.tree(null, overlaysTree1(),
{collapsed: false}).addTo(map);
var inputs = map._container.querySelectorAll('.leaflet-control-layers-overlays input');
inputs.length.should.be.equal(5);
var headers = map._container.querySelectorAll('.leaflet-control-layers-overlays .leaflet-layerstree-header');
headers.length.should.be.equal(7);
checkHidden(headers, false, 0);
ctl.collapseTree(true);
checkHidden(headers, true, 1);
});
it('they are accesible on mouseover', function() {
var ctrl = L.control.layers.tree(null, overlaysTree1()).addTo(map);
var inputs = map._container.querySelectorAll('.leaflet-control-layers-overlays input');
inputs.length.should.be.equal(5);
var headers = map._container.querySelectorAll('.leaflet-control-layers-overlays .leaflet-layerstree-header');
headers.length.should.be.equal(7);
// Nothing visible because the contrl is collapsed
checkHidden(inputs, true, 0);
checkHidden(headers, true, 0);
// mouse over the control to show it.
happen.once(ctrl._container, {type: 'mouseover'});
checkHidden(inputs, false, 0);
checkHidden(headers, false, 0);
// Hi, let it as you found it.
happen.once(ctrl._container, {type: 'mouseout'});
});
});
describe('Simple overlays array tests', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('they are accesible on mouseover', function() {
var ctrl = L.control.layers.tree(null, overlaysArray1()).addTo(map);
var inputs = map._container.querySelectorAll('.leaflet-control-layers-overlays input');
inputs.length.should.be.equal(5);
var headers = map._container.querySelectorAll('.leaflet-control-layers-overlays .leaflet-layerstree-header');
headers.length.should.be.equal(7);
// Nothing visible because the contrl is collapsed
checkHidden(inputs, true, 0);
checkHidden(headers, true, 0);
// mouse over the control to show it.
happen.once(ctrl._container, {type: 'mouseover'});
checkHidden(inputs, false, 0);
checkHidden(headers, false, 1);
checkHidden(headers, [1, 0, 0, 0, 0, 0, 0], 0);
// Hi, let it as you found it.
happen.once(ctrl._container, {type: 'mouseout'});
});
});
describe('Select', function() {
beforeEach(function() {
map.setView([0, 0], 14);
});
it('sel layer B and A', function() {
var ctl = L.control.layers.tree(baseTree1(), null, {collapsed: false}).addTo(map);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers.length.should.be.equal(7);
happen.click(headers[6].querySelector('label'));
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
happen.click(headers[4].querySelector('label'));
map._layers[L.Util.stamp(layerA)].should.be.equal(layerA);
});
});
describe('Labels', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('labels base', function() {
var ctl = L.control.layers.tree(baseTree1(), null, {collapsed: false}).addTo(map);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers[3].querySelector('.leaflet-layerstree-header-name').outerText.should.be.equal('Node 1');
headers[4].querySelector('.leaflet-layerstree-header-name').outerText.should.be.equal('Leaf 11');
headers[6].querySelector('.leaflet-layerstree-header-name').outerText.should.be.equal('Leaf three');
});
});
describe('Expand and collapse', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('Show only selected', function() {
var ctrl = L.control.layers.tree(baseTree1(), null, {collapsed: false}).addTo(map);
map.addLayer(layerB);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers.length.should.be.equal(7);
checkHidden(headers, false, 0);
ctrl.collapseTree().expandSelected(false);
checkHidden(headers, [0, 0, 0, 0, 1, 1, 0], 0);
});
it('Collapse', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false}).addTo(map);
map.addLayer(layerB);
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
checkHidden(headers, false, 0);
ctrl.collapseTree();
checkHidden(headers, [0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], 0);
ctrl.collapseTree(true);
checkHidden(headers, [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], 0);
});
it('Expand', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false}).addTo(map);
map.addLayer(layerB);
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
checkHidden(headers, false, 0);
ctrl.collapseTree().collapseTree(true);
ctrl.expandTree();
checkHidden(headers, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], 0);
ctrl.expandTree(true);
checkHidden(headers, 0, 0);
});
});
describe('Names', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('Named Toogle', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {namedToggle: true}).addTo(map);
map.addLayer(layerB);
var toggle = map._container.querySelector('.leaflet-control-layers-toggle');
toggle.innerHTML.should.be.equal('Name Leaf three');
var inputs = map._container.querySelectorAll('.leaflet-control-layers-list input');
happen.click(inputs[0]);
toggle.innerHTML.should.be.equal('Name Leaf one');
happen.click(inputs[2]);
toggle.innerHTML.should.be.equal('Name Leaf 11');
happen.click(inputs[8]);
toggle.innerHTML.should.be.equal('Name Leaf 11');
});
});
describe('Symbols', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('Defaults', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false}).addTo(map);
var items = map._container.querySelectorAll('.leaflet-layerstree-closed');
items.length.should.be.equal(14);
for (var i = 0; i < items.length; i++) {
items[i].innerHTML.should.be.equal('+');
}
items = map._container.querySelectorAll('.leaflet-layerstree-opened');
items.length.should.be.equal(14);
for (var i = 0; i < items.length; i++) {
items[i].innerHTML.should.be.equal('');
}
items = map._container.querySelectorAll('.leaflet-layerstree-header-space');
items.length.should.be.equal(14);
for (var i = 0; i < items.length; i++) {
items[i].innerHTML.should.be.equal(' ');
}
});
it('Closed', function() {
var symbol = '^';
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, closedSymbol: symbol}).addTo(map);
map.addLayer(layerB);
var items = map._container.querySelectorAll('.leaflet-layerstree-closed');
items.length.should.be.equal(14);
for (var i = 0; i < items.length; i++) {
items[i].innerHTML.should.be.equal(symbol);
}
});
it('Opened', function() {
var symbol = 'v';
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, openedSymbol: symbol}).addTo(map);
var items = map._container.querySelectorAll('.leaflet-layerstree-opened');
items.length.should.be.equal(14);
for (var i = 0; i < items.length; i++) {
items[i].innerHTML.should.be.equal(symbol);
}
});
it('Space', function() {
var symbol = '_*_';
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, spaceSymbol: symbol}).addTo(map);
var items = map._container.querySelectorAll('.leaflet-layerstree-header-space');
items.length.should.be.equal(14);
for (var i = 0; i < items.length; i++) {
items[i].innerHTML.should.be.equal(symbol);
}
});
});
describe('Selector back', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('Default', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false}).addTo(map);
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
for (var h = 0; h < headers.length; h++) {
var things = [];
var keys = ['closed', 'opened', 'space', 'label']
var items = headers[h].querySelectorAll('span, label, div');
for (var i = 0; i < items.length; i++) {
keys.forEach(function(key) {
if (items[i].className.indexOf(key) > 0) {
things.push(key);
}
});
}
things[2].should.be.equal('space');
things[3].should.be.equal('label');
}
});
it('Back', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, selectorBack: true}).addTo(map);
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
for (var h = 0; h < headers.length; h++) {
var things = [];
var keys = ['closed', 'opened', 'space', 'label']
var items = headers[h].querySelectorAll('span, label, div');
for (var i = 0; i < items.length; i++) {
keys.forEach(function(key) {
if (items[i].className.indexOf(key) > 0) {
things.push(key);
}
});
}
things[1].should.be.equal('space');
things[0].should.be.equal('label');
}
});
});
describe('Expand and collapse all', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('expandAll', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, expandAll: 'exp'}).addTo(map);
ctrl.collapseTree().collapseTree(true);
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
checkHidden(headers, [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], 0);
var ct = map._container.querySelectorAll('.leaflet-layerstree-expand-collapse');
ct.length.should.be.equal(2);
happen.click(ct[0]);
checkHidden(headers, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], 0);
happen.click(ct[1]);
checkHidden(headers, false, 0);
});
it('collapseAll', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, collapseAll: 'col'}).addTo(map);
ctrl.expandTree().expandTree(true);
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
checkHidden(headers, false, 0);
var ct = map._container.querySelectorAll('.leaflet-layerstree-expand-collapse');
ct.length.should.be.equal(2);
happen.click(ct[0]);
checkHidden(headers, [0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], 0);
happen.click(ct[1]);
checkHidden(headers, [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], 0);
});
it('Empties', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, collapseAll: '', expandAll: ''}).addTo(map);
var ct = map._container.querySelectorAll('.leaflet-layerstree-expand-collapse');
ct.length.should.be.equal(0);
});
it('All', function() {
var ctrl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false, collapseAll: 'col', expandAll: 'exp'}).addTo(map);
var ct = map._container.querySelectorAll('.leaflet-layerstree-expand-collapse');
ct.length.should.be.equal(4);
});
it('Arrays', function() {
var ctrl = L.control.layers.tree(baseArray1(), overlaysArray1(), {collapsed: false, collapseAll: 'col'}).addTo(map);
var ct = map._container.querySelectorAll('.leaflet-layerstree-expand-collapse');
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
checkHidden(headers, [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], 0);
var ct = map._container.querySelectorAll('.leaflet-layerstree-expand-collapse');
ct.length.should.be.equal(2);
happen.click(ct[0]);
checkHidden(headers, [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0], 0);
happen.click(ct[1]);
checkHidden(headers, [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0], 0);
});
});
describe('Reset trees', function() {
beforeEach(function() {
map.setView([0, 0], 1);
});
it('case 1', function() {
var ctl = L.control.layers.tree(baseArray2(), null, {collapsed: false}).addTo(map);
map.addLayer(layerB);
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers.length.should.be.equal(3); // including the hidden root
ctl.setBaseTree(baseTree1());
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(7)
happen.click(headers[4].querySelector('label'));
map._layers[L.Util.stamp(layerA)].should.be.equal(layerA);
});
it('case 2', function() {
var ctl = L.control.layers.tree(baseArray2(), overlaysTree1(), {collapsed: false}).addTo(map);
map.addLayer(layerB);
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
var headers = map._container.querySelectorAll('.leaflet-control-layers-base .leaflet-layerstree-header');
headers.length.should.be.equal(3); // including the hidden root
ctl.setBaseTree(baseTree1());
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14)
});
it('case 3', function() {
var ctl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false}).addTo(map);
map.addLayer(layerB);
map.addLayer(markerA);
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
map._layers[L.Util.stamp(markerA)].should.be.equal(markerA);
var headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(14);
var inputs = map._container.querySelectorAll('.leaflet-layerstree-header input');
inputs.length.should.be.equal(10);
inputs[4].checked.should.be.true;
inputs[7].checked.should.be.true;
ctl.setBaseTree(baseArray2());
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
map._layers[L.Util.stamp(markerA)].should.be.equal(markerA);
headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(10)
inputs = map._container.querySelectorAll('.leaflet-layerstree-header input');
inputs.length.should.be.equal(7);
inputs[1].checked.should.be.true;
inputs[4].checked.should.be.true;
ctl.setOverlayTree(overlaysArray2());
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
map._layers[L.Util.stamp(markerA)].should.be.equal(markerA);
headers = map._container.querySelectorAll('.leaflet-layerstree-header');
headers.length.should.be.equal(6)
inputs = map._container.querySelectorAll('.leaflet-layerstree-header input');
inputs.length.should.be.equal(4);
inputs[1].checked.should.be.true;
inputs[2].checked.should.be.true;
});
it('case 4', function() {
var ctl = L.control.layers.tree(baseTree1(), overlaysTree1(), {collapsed: false}).addTo(map);
map.addLayer(layerB);
map.addLayer(markerO);
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
map._layers[L.Util.stamp(markerO)].should.be.equal(markerO);
ctl.setOverlayTree(overlaysArray2());
map._layers[L.Util.stamp(layerB)].should.be.equal(layerB);
map._layers[L.Util.stamp(markerO)].should.be.equal(markerO);
var inputs = map._container.querySelectorAll('.leaflet-layerstree-header input');
inputs.length.should.be.equal(7);
inputs[5].checked.should.be.false;
inputs[6].checked.should.be.false;
});
});
});