Repository: walkermatt/ol3-layerswitcher
Branch: master
Commit: c06477ef6bc0
Files: 22
Total size: 54.7 KB
Directory structure:
gitextract_zbkqn7gv/
├── .gitignore
├── README.md
├── bower.json
├── examples/
│ ├── addlayer.html
│ ├── addlayer.js
│ ├── browserify/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── index.js
│ │ └── package.json
│ ├── layerswitcher.css
│ ├── layerswitcher.html
│ ├── layerswitcher.js
│ ├── scroll.css
│ ├── scroll.html
│ └── scroll.js
├── package.json
├── src/
│ ├── ol3-layerswitcher.css
│ └── ol3-layerswitcher.js
├── test/
│ ├── index.html
│ └── spec/
│ ├── ol3-layerswitcher.js
│ └── twomaps.js
└── util/
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules
.idea/
================================================
FILE: README.md
================================================
# DEPRECATED: ol3-layerswitcher is now [ol-layerswitcher](https://github.com/walkermatt/ol-layerswitcher)
If you require support for the ["old" `openlayers` NPM package](https://www.npmjs.com/package/openlayers) then you can use the code in the master branch of this repository via:
npm install git+https://github.com/walkermatt/ol3-layerswitcher.git#master
But you probably want to use the [`ol` package](https://www.npmjs.com/package/ol) for new projects in which case you want [ol-layerswitcher](https://github.com/walkermatt/ol-layerswitcher).
# OpenLayers LayerSwitcher
Grouped layer list control for an OpenLayer v3/v4 map.
All layers should have a `title` property and base layers should have a `type` property set to `base`. Group layers (`ol.layer.Group`) can be used to visually group layers together. See [examples/layerswitcher.js](examples/layerswitcher.js) for usage.
## Examples
The examples demonstrate usage and can be viewed online thanks to [RawGit](http://rawgit.com/):
* [Basic usage](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/layerswitcher.html)
* Create a layer switcher control. Each layer to be displayed in the layer switcher has a `title` property as does each Group; each base map layer has a `type: 'base'` property.
* [Add layer](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/addlayer.html)
* Add a layer to an existing layer group after the layer switcher has been added to the map.
* [Scrolling](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/scroll.html)
* Demonstrate the panel scrolling vertically, control the height of the layer switcher by setting the `max-height` (see [examples/scroll.css](examples/scroll.css)) and it's position relative to the bottom of the map (see the `.layer-switcher.shown` selector in [src/ol3-layerswitcher.css](src/ol3-layerswitcher.css)).
* [Browserify](examples/browserify/)
* Example of using ol3-layerswitcher with Browserify (see [examples/browserify/README.md](examples/browserify/README.md) for details of building.
The source for all examples can be found in [examples](examples).
## Tests
To run the tests you'll need to install the dependencies via `npm`. In the root of the repository run:
npm install
Then run the tests by opening [test/index.html](test/index.html) in a browser.
## API
### `new ol.control.LayerSwitcher(opt_options)`
OpenLayers v3/v4 Layer Switcher Control.
See [the examples](./examples) for usage.
#### Parameters:
|Name|Type|Description|
|:---|:---|:----------|
|`opt_options`|`Object`| Control options, extends olx.control.ControlOptions adding: **`tipLabel`** `String` - the button tooltip. |
#### Extends
`ol.control.Control`
#### Methods
##### `showPanel()`
Show the layer panel.
##### `hidePanel()`
Hide the layer panel.
##### `renderPanel()`
Re-draw the layer panel to represent the current state of the layers.
##### `setMap(map)`
Set the map instance the control is associated with.
###### Parameters:
|Name|Type|Description|
|:---|:---|:----------|
|`map`|`ol.Map`| The map instance. |
##### `(static) ol.control.LayerSwitcher.forEachRecursive(lyr,fn)`
**Static** Call the supplied function for each layer in the passed layer group
recursing nested groups.
###### Parameters:
|Name|Type|Description|
|:---|:---|:----------|
|`lyr`|`ol.layer.Group`| The layer group to start iterating from. |
|`fn`|`function`| Callback which will be called for each `ol.layer.Base` found under `lyr`. The signature for `fn` is the same as `ol.Collection#forEach` |
##### `(static) ol.control.LayerSwitcher.uuid()`
Generate a UUID
## License
MIT (c) Matt Walker.
## Also see
If you find the layer switcher useful you might also like the
[ol3-popup](https://github.com/walkermatt/ol3-popup).
================================================
FILE: bower.json
================================================
{
"name": "ol3-layerswitcher",
"version": "1.1.0",
"homepage": "https://github.com/walkermatt/ol3-layerswitcher",
"authors": [
"Matt Walker (http://longwayaround.org.uk)"
],
"description": "Layer switcher control for OpenLayers v3/v4",
"main": [
"src/ol3-layerswitcher.js",
"src/ol3-layerswitcher.css"
],
"keywords": [
"openlayers",
"ol",
"layerswitcher"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test"
]
}
================================================
FILE: examples/addlayer.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>OpenLayers 3 - LayerSwitcher Add Layer</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.css" />
<link rel="stylesheet" href="../src/ol3-layerswitcher.css" />
<link rel="stylesheet" href="layerswitcher.css" />
</head>
<body>
<div id="map"></div>
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.js"></script>
<script src="../src/ol3-layerswitcher.js"></script>
<script src="addlayer.js"></script>
</body>
</html>
================================================
FILE: examples/addlayer.js
================================================
(function() {
// Create a group for overlays. Add the group to the map when it's created
// but add the overlay layers later
var overlayGroup = new ol.layer.Group({
title: 'Overlays',
layers: [
]
});
// Create a map containing two group layers
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Group({
'title': 'Base maps',
layers: [
new ol.layer.Tile({
title: 'OSM',
type: 'base',
source: new ol.source.OSM()
})
]
}),
overlayGroup
],
view: new ol.View({
center: ol.proj.transform([-0.92, 52.96], 'EPSG:4326', 'EPSG:3857'),
zoom: 6
})
});
// Create a LayerSwitcher instance and add it to the map
var layerSwitcher = new ol.control.LayerSwitcher();
map.addControl(layerSwitcher);
// Add a layer to a pre-exiting ol.layer.Group after the LayerSwitcher has
// been added to the map. The layer will appear in the list the next time
// the LayerSwitcher is shown or LayerSwitcher#renderPanel is called.
overlayGroup.getLayers().push(
new ol.layer.Image({
title: 'Countries',
minResolution: 500,
maxResolution: 5000,
source: new ol.source.ImageArcGISRest({
ratio: 1,
params: {'LAYERS': 'show:0'},
url: "https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Countries_December_2016_Boundaries/MapServer"
})
})
);
})();
================================================
FILE: examples/browserify/README.md
================================================
# Using ol3-layerswitcher with Browserify
Based on [OpenLayers 3 Browserify Tutorial](https://openlayers.org/en/latest/doc/tutorials/browserify.html).
## Building
For a one-time build run:
npm run build
If you want to make changes and have the project auto build run:
npm run start
## Requiring ol3-layerswitcher
// Pass the path to `ol3-layerswitcher.js` minus the extension to `require`
// which will return the constructor
var LayerSwitcher = require('../../src/ol3-layerswitcher');
// Create an instance
var layerSwitcher = new LayerSwitcher();
// Add to a `ol.Map` instance as normal
map.addControl(layerSwitcher);
================================================
FILE: examples/browserify/index.html
================================================
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Using Browserify with OpenLayers</title>
<link rel="stylesheet" href="node_modules/openlayers/dist/ol.css" type="text/css">
<link rel="stylesheet" href="../../src/ol3-layerswitcher.css" />
<link rel="stylesheet" href="../layerswitcher.css" />
<style>
#map {
width: 400px;
height: 250px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="bundle.js"></script>
</body>
</html>
================================================
FILE: examples/browserify/index.js
================================================
var ol = require('openlayers');
var LayerSwitcher = require('../../src/ol3-layerswitcher');
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Group({
'title': 'Base maps',
layers: [
new ol.layer.Tile({
title: 'Water color',
type: 'base',
visible: false,
source: new ol.source.Stamen({
layer: 'watercolor'
})
}),
new ol.layer.Tile({
title: 'OSM',
type: 'base',
source: new ol.source.OSM()
})
]
})
],
view: new ol.View({
center: [0, 0],
zoom: 0
})
});
var layerSwitcher = new LayerSwitcher();
map.addControl(layerSwitcher);
================================================
FILE: examples/browserify/package.json
================================================
{
"name": "ol3-layerswitcher-browserify",
"version": "1.1.2",
"description": "Example of using ol3-layerswitcher with Browserify",
"main": "index.js",
"scripts": {
"start": "watchify index.js --outfile bundle.js",
"build": "browserify index.js | uglifyjs --compress --output bundle.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"browserify": "^13.3.0",
"openlayers": "^4.0.1",
"uglify-js": "^2.7.5",
"watchify": "^3.8.0"
}
}
================================================
FILE: examples/layerswitcher.css
================================================
html, body {
height: 100%;
padding: 0;
margin: 0;
font-family: sans-serif;
font-size: small;
}
#map {
width: 100%;
height: 100%;
}
================================================
FILE: examples/layerswitcher.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>OpenLayers 3 - LayerSwitcher</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.css" />
<link rel="stylesheet" href="../src/ol3-layerswitcher.css" />
<link rel="stylesheet" href="layerswitcher.css" />
</head>
<body>
<div id="map"></div>
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.js"></script>
<script src="../src/ol3-layerswitcher.js"></script>
<script src="layerswitcher.js"></script>
</body>
</html>
================================================
FILE: examples/layerswitcher.js
================================================
(function() {
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Group({
'title': 'Base maps',
layers: [
new ol.layer.Group({
title: 'Water color with labels',
type: 'base',
combine: true,
visible: false,
layers: [
new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'watercolor'
})
}),
new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'terrain-labels'
})
})
]
}),
new ol.layer.Tile({
title: 'Water color',
type: 'base',
visible: false,
source: new ol.source.Stamen({
layer: 'watercolor'
})
}),
new ol.layer.Tile({
title: 'OSM',
type: 'base',
visible: true,
source: new ol.source.OSM()
})
]
}),
new ol.layer.Group({
title: 'Overlays',
layers: [
new ol.layer.Image({
title: 'Countries',
source: new ol.source.ImageArcGISRest({
ratio: 1,
params: {'LAYERS': 'show:0'},
url: "https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Countries_December_2016_Boundaries/MapServer"
})
})
]
})
],
view: new ol.View({
center: ol.proj.transform([-0.92, 52.96], 'EPSG:4326', 'EPSG:3857'),
zoom: 6
})
});
var layerSwitcher = new ol.control.LayerSwitcher({
tipLabel: 'Légende' // Optional label for button
});
map.addControl(layerSwitcher);
})();
================================================
FILE: examples/scroll.css
================================================
/* Set the maxmimum height of the layerswitcher when it's shown */
.layer-switcher.shown {
max-height: 170px;
}
================================================
FILE: examples/scroll.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>OpenLayers 3 - LayerSwitcher Scrolling</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.css" />
<link rel="stylesheet" href="../src/ol3-layerswitcher.css" />
<link rel="stylesheet" href="layerswitcher.css" />
<link rel="stylesheet" href="scroll.css" />
</head>
<body>
<div id="map"></div>
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.js"></script>
<script src="../src/ol3-layerswitcher.js"></script>
<script src="scroll.js"></script>
</body>
</html>
================================================
FILE: examples/scroll.js
================================================
(function() {
var thunderforestAttributions = [
new ol.Attribution({
html: 'Tiles © <a href="http://www.thunderforest.com/">Thunderforest</a>'
}),
ol.source.OSM.ATTRIBUTION
];
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Group({
'title': 'Base maps',
layers: [
new ol.layer.Tile({
title: 'Stamen - Water color',
type: 'base',
visible: false,
source: new ol.source.Stamen({
layer: 'watercolor'
})
}),
new ol.layer.Tile({
title: 'Stamen - Toner',
type: 'base',
visible: false,
source: new ol.source.Stamen({
layer: 'toner'
})
}),
new ol.layer.Tile({
title: 'Thunderforest - OpenCycleMap',
type: 'base',
visible: false,
source: new ol.source.OSM({
url: 'http://{a-c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',
attributions: thunderforestAttributions
})
}),
new ol.layer.Tile({
title: 'Thunderforest - Outdoors',
type: 'base',
visible: false,
source: new ol.source.OSM({
url: 'http://{a-c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png',
attributions: thunderforestAttributions
})
}),
new ol.layer.Tile({
title: 'Thunderforest - Landscape',
type: 'base',
visible: false,
source: new ol.source.OSM({
url: 'http://{a-c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png',
attributions: thunderforestAttributions
})
}),
new ol.layer.Tile({
title: 'Thunderforest - Transport',
type: 'base',
visible: false,
source: new ol.source.OSM({
url: 'http://{a-c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png',
attributions: thunderforestAttributions
})
}),
new ol.layer.Tile({
title: 'Thunderforest - Transport Dark',
type: 'base',
visible: false,
source: new ol.source.OSM({
url: 'http://{a-c}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png',
attributions: thunderforestAttributions
})
}),
new ol.layer.Tile({
title: 'OSM',
type: 'base',
visible: true,
source: new ol.source.OSM()
})
]
}),
new ol.layer.Group({
title: 'Overlays',
layers: [
new ol.layer.Image({
title: 'Countries',
source: new ol.source.ImageArcGISRest({
ratio: 1,
params: {'LAYERS': 'show:0'},
url: "https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Countries_December_2016_Boundaries/MapServer"
})
})
]
})
],
view: new ol.View({
center: ol.proj.transform([-0.92, 52.96], 'EPSG:4326', 'EPSG:3857'),
zoom: 6
})
});
map.addControl(new ol.control.LayerSwitcher());
})();
================================================
FILE: package.json
================================================
{
"name": "ol3-layerswitcher",
"version": "1.1.2",
"description": "Layer switcher control for OpenLayers v3/v4",
"repository": {
"type": "git",
"url": "https://github.com/walkermatt/ol3-layerswitcher.git"
},
"author": "Matt Walker (http://longwayaround.org.uk)",
"contributors": [
"Thomas Gratier <thomas_gratier@yahoo.fr>",
"Poul Kjeldager Sørensen <pks@s-innovations.net>",
"Micho García <micho.garcia@geomati.co>",
"olivierdalang <olivier.dalang@gmail.com>"
],
"keywords": [
"openlayers",
"layerswitcher",
"ol"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/walkermatt/ol3-layerswitcher/issues"
},
"scripts": {
"doc": "node_modules/.bin/jsdoc --explain src/ol3-layerswitcher.js | node_modules/.bin/dirtydocs util/README.md > README.md"
},
"dependencies": {
"openlayers": "~4.0.1"
},
"devDependencies": {
"expect.js": "~0.3.1",
"jquery": "~1.11.1",
"lodash": "~2.4.1",
"mocha": "~1.20.1",
"jsdoc": "~3.3.0-beta1",
"dirtydocs": "0.0.1"
}
}
================================================
FILE: src/ol3-layerswitcher.css
================================================
.layer-switcher.shown.ol-control {
background-color: transparent;
}
.layer-switcher.shown.ol-control:hover {
background-color: transparent;
}
.layer-switcher {
position: absolute;
top: 3.5em;
right: 0.5em;
text-align: left;
}
.layer-switcher.shown {
bottom: 3em;
}
.layer-switcher .panel {
padding: 0 1em 0 0;
margin: 0;
border: 4px solid #eee;
border-radius: 4px;
background-color: white;
display: none;
max-height: 100%;
overflow-y: auto;
}
.layer-switcher.shown .panel {
display: block;
}
.layer-switcher button {
float: right;
width: 38px;
height: 38px;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==') /*logo.png*/;
background-repeat: no-repeat;
background-position: 2px;
background-color: white;
border: none;
}
.layer-switcher.shown button {
display: none;
}
.layer-switcher button:focus, .layer-switcher button:hover {
background-color: white;
}
.layer-switcher ul {
padding-left: 1em;
list-style: none;
}
.layer-switcher li.group {
padding-top: 5px;
}
.layer-switcher li.group > label {
font-weight: bold;
}
.layer-switcher li.layer {
display: table;
}
.layer-switcher li.layer label, .layer-switcher li.layer input {
display: table-cell;
vertical-align: sub;
}
.layer-switcher label.disabled {
opacity:0.4;
}
.layer-switcher input {
margin: 4px;
}
.layer-switcher.touch ::-webkit-scrollbar {
width: 4px;
}
.layer-switcher.touch ::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 10px;
}
.layer-switcher.touch ::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
}
================================================
FILE: src/ol3-layerswitcher.js
================================================
(function (root, factory) {
if(typeof define === "function" && define.amd) {
define(["openlayers"], factory);
} else if(typeof module === "object" && module.exports) {
module.exports = factory(require("openlayers"));
} else {
root.LayerSwitcher = factory(root.ol);
}
}(this, function(ol) {
/**
* OpenLayers v3/v4 Layer Switcher Control.
* See [the examples](./examples) for usage.
* @constructor
* @extends {ol.control.Control}
* @param {Object} opt_options Control options, extends olx.control.ControlOptions adding:
* **`tipLabel`** `String` - the button tooltip.
*/
ol.control.LayerSwitcher = function(opt_options) {
var options = opt_options || {};
var tipLabel = options.tipLabel ?
options.tipLabel : 'Legend';
this.mapListeners = [];
this.hiddenClassName = 'ol-unselectable ol-control layer-switcher';
if (ol.control.LayerSwitcher.isTouchDevice_()) {
this.hiddenClassName += ' touch';
}
this.shownClassName = 'shown';
var element = document.createElement('div');
element.className = this.hiddenClassName;
var button = document.createElement('button');
button.setAttribute('title', tipLabel);
element.appendChild(button);
this.panel = document.createElement('div');
this.panel.className = 'panel';
element.appendChild(this.panel);
ol.control.LayerSwitcher.enableTouchScroll_(this.panel);
var this_ = this;
button.onmouseover = function(e) {
this_.showPanel();
};
button.onclick = function(e) {
e = e || window.event;
this_.showPanel();
e.preventDefault();
};
this_.panel.onmouseout = function(e) {
e = e || window.event;
if (!this_.panel.contains(e.toElement || e.relatedTarget)) {
this_.hidePanel();
}
};
ol.control.Control.call(this, {
element: element,
target: options.target
});
};
ol.inherits(ol.control.LayerSwitcher, ol.control.Control);
/**
* Show the layer panel.
*/
ol.control.LayerSwitcher.prototype.showPanel = function() {
if (!this.element.classList.contains(this.shownClassName)) {
this.element.classList.add(this.shownClassName);
this.renderPanel();
}
};
/**
* Hide the layer panel.
*/
ol.control.LayerSwitcher.prototype.hidePanel = function() {
if (this.element.classList.contains(this.shownClassName)) {
this.element.classList.remove(this.shownClassName);
}
};
/**
* Re-draw the layer panel to represent the current state of the layers.
*/
ol.control.LayerSwitcher.prototype.renderPanel = function() {
this.ensureTopVisibleBaseLayerShown_();
while(this.panel.firstChild) {
this.panel.removeChild(this.panel.firstChild);
}
var ul = document.createElement('ul');
this.panel.appendChild(ul);
this.renderLayers_(this.getMap(), ul);
};
/**
* Set the map instance the control is associated with.
* @param {ol.Map} map The map instance.
*/
ol.control.LayerSwitcher.prototype.setMap = function(map) {
// Clean up listeners associated with the previous map
for (var i = 0, key; i < this.mapListeners.length; i++) {
ol.Observable.unByKey(this.mapListeners[i]);
}
this.mapListeners.length = 0;
// Wire up listeners etc. and store reference to new map
ol.control.Control.prototype.setMap.call(this, map);
if (map) {
var this_ = this;
this.mapListeners.push(map.on('pointerdown', function() {
this_.hidePanel();
}));
this.renderPanel();
}
};
/**
* Ensure only the top-most base layer is visible if more than one is visible.
* @private
*/
ol.control.LayerSwitcher.prototype.ensureTopVisibleBaseLayerShown_ = function() {
var lastVisibleBaseLyr;
ol.control.LayerSwitcher.forEachRecursive(this.getMap(), function(l, idx, a) {
if (l.get('type') === 'base' && l.getVisible()) {
lastVisibleBaseLyr = l;
}
});
if (lastVisibleBaseLyr) this.setVisible_(lastVisibleBaseLyr, true);
};
/**
* Toggle the visible state of a layer.
* Takes care of hiding other layers in the same exclusive group if the layer
* is toggle to visible.
* @private
* @param {ol.layer.Base} The layer whos visibility will be toggled.
*/
ol.control.LayerSwitcher.prototype.setVisible_ = function(lyr, visible) {
var map = this.getMap();
lyr.setVisible(visible);
if (visible && lyr.get('type') === 'base') {
// Hide all other base layers regardless of grouping
ol.control.LayerSwitcher.forEachRecursive(map, function(l, idx, a) {
if (l != lyr && l.get('type') === 'base') {
l.setVisible(false);
}
});
}
};
/**
* Render all layers that are children of a group.
* @private
* @param {ol.layer.Base} lyr Layer to be rendered (should have a title property).
* @param {Number} idx Position in parent group list.
*/
ol.control.LayerSwitcher.prototype.renderLayer_ = function(lyr, idx) {
var this_ = this;
var li = document.createElement('li');
var lyrTitle = lyr.get('title');
var lyrId = ol.control.LayerSwitcher.uuid();
var label = document.createElement('label');
if (lyr.getLayers && !lyr.get('combine')) {
li.className = 'group';
label.innerHTML = lyrTitle;
li.appendChild(label);
var ul = document.createElement('ul');
li.appendChild(ul);
this.renderLayers_(lyr, ul);
} else {
li.className = 'layer';
var input = document.createElement('input');
if (lyr.get('type') === 'base') {
input.type = 'radio';
input.name = 'base';
} else {
input.type = 'checkbox';
}
input.id = lyrId;
input.checked = lyr.get('visible');
input.onchange = function(e) {
this_.setVisible_(lyr, e.target.checked);
};
li.appendChild(input);
label.htmlFor = lyrId;
label.innerHTML = lyrTitle;
var rsl = this.getMap().getView().getResolution();
if (rsl > lyr.getMaxResolution() || rsl < lyr.getMinResolution()){
label.className += ' disabled';
}
li.appendChild(label);
}
return li;
};
/**
* Render all layers that are children of a group.
* @private
* @param {ol.layer.Group} lyr Group layer whos children will be rendered.
* @param {Element} elm DOM element that children will be appended to.
*/
ol.control.LayerSwitcher.prototype.renderLayers_ = function(lyr, elm) {
var lyrs = lyr.getLayers().getArray().slice().reverse();
for (var i = 0, l; i < lyrs.length; i++) {
l = lyrs[i];
if (l.get('title')) {
elm.appendChild(this.renderLayer_(l, i));
}
}
};
/**
* **Static** Call the supplied function for each layer in the passed layer group
* recursing nested groups.
* @param {ol.layer.Group} lyr The layer group to start iterating from.
* @param {Function} fn Callback which will be called for each `ol.layer.Base`
* found under `lyr`. The signature for `fn` is the same as `ol.Collection#forEach`
*/
ol.control.LayerSwitcher.forEachRecursive = function(lyr, fn) {
lyr.getLayers().forEach(function(lyr, idx, a) {
fn(lyr, idx, a);
if (lyr.getLayers) {
ol.control.LayerSwitcher.forEachRecursive(lyr, fn);
}
});
};
/**
* Generate a UUID
* @returns {String} UUID
*
* Adapted from http://stackoverflow.com/a/2117523/526860
*/
ol.control.LayerSwitcher.uuid = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
/**
* @private
* @desc Apply workaround to enable scrolling of overflowing content within an
* element. Adapted from https://gist.github.com/chrismbarr/4107472
*/
ol.control.LayerSwitcher.enableTouchScroll_ = function(elm) {
if(ol.control.LayerSwitcher.isTouchDevice_()){
var scrollStartPos = 0;
elm.addEventListener("touchstart", function(event) {
scrollStartPos = this.scrollTop + event.touches[0].pageY;
}, false);
elm.addEventListener("touchmove", function(event) {
this.scrollTop = scrollStartPos - event.touches[0].pageY;
}, false);
}
};
/**
* @private
* @desc Determine if the current browser supports touch events. Adapted from
* https://gist.github.com/chrismbarr/4107472
*/
ol.control.LayerSwitcher.isTouchDevice_ = function() {
try {
document.createEvent("TouchEvent");
return true;
} catch(e) {
return false;
}
};
var LayerSwitcher = ol.control.LayerSwitcher;
return LayerSwitcher;
}));
================================================
FILE: test/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>ol3-layerswitcher spec runner</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="../node_modules/mocha/mocha.css">
<link rel="stylesheet" href="../node_modules/openlayers/css/ol.css" />
<link rel="stylesheet" type="text/css" href="../src/ol3-layerswitcher.css">
</head>
<body>
<div id="mocha"></div>
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="../node_modules/expect.js/index.js"></script>
<script type="text/javascript" src="../node_modules/mocha/mocha.js"></script>
<script type="text/javascript" src="../node_modules/lodash/dist/lodash.js"></script>
<script>
mocha.setup({
ui: 'bdd',
bail: false
});
</script>
<script src="../node_modules/openlayers/dist/ol.js"></script>
<script type="text/javascript" src="../src/ol3-layerswitcher.js"></script>
<script type="text/javascript" src="spec/ol3-layerswitcher.js"></script>
<script type="text/javascript" src="spec/twomaps.js"></script>
<script>
mocha.run();
</script>
</body>
</html>
================================================
FILE: test/spec/ol3-layerswitcher.js
================================================
describe('ol.control.LayerSwitcher', function() {
var map, target, switcher;
beforeEach(function() {
target = document.createElement('div');
document.body.appendChild(target);
switcher = new ol.control.LayerSwitcher();
map = new ol.Map({
target: target,
layers: [
new ol.layer.Group({
title: 'Base',
layers: [
new ol.layer.Tile({
title: 'Foo',
type: 'base',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
new ol.layer.Tile({
title: 'Too',
type: 'base',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
})
]
}),
// Combined base group
new ol.layer.Group({
title: 'Combined-Base-Group',
type: 'base',
combine: true,
layers: [
new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
})
]
}),
// Combined overlay group
new ol.layer.Group({
title: 'Combined-Overlay-Group',
type: 'overlay',
combine: true,
layers: [
new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
})
]
}),
// Group with no title (group and it's children should be ignored)
new ol.layer.Group({
layers: [
new ol.layer.Tile({
title: 'Never shown',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
})
]
}),
new ol.layer.Tile({
title: 'Bar',
minResolution: 1000,
maxResolution: 5000,
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
// Layer with no title (should be ignored)
new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
})
],
controls: [switcher]
});
});
afterEach(function() {
document.body.removeChild(target);
switcher = null;
map = null;
target = null;
});
describe('DOM creation', function() {
it('creates the expected DOM elements', function() {
expect(jQuery('.layer-switcher').length).to.be(1);
});
});
describe('Show and hide', function() {
it('is initially hidden', function() {
expect(jQuery('.layer-switcher').hasClass('.shown')).to.be(false);
expect(jQuery('.layer-switcher .panel:visible').length).to.be(0);
});
it('is shown on button click', function() {
jQuery('.layer-switcher button').click();
expect(jQuery('.layer-switcher.shown').length).to.be(1);
expect(jQuery('.layer-switcher .panel:visible').length).to.be(1);
});
it('is hidden on map click', function() {
jQuery('#map').click();
expect(jQuery('.layer-switcher').hasClass('.shown')).to.be(false);
expect(jQuery('.layer-switcher .panel:visible').length).to.be(0);
});
});
describe('Layer list', function() {
it('displays all layers with a title in reverse order', function() {
switcher.showPanel();
var titles = jQuery('.layer-switcher label').map(function() {
return jQuery(this).text();
}).get();
expect(titles).to.eql(['Bar', 'Combined-Overlay-Group', 'Combined-Base-Group', 'Base', 'Too', 'Foo']);
});
it('only displays layers with a title', function() {
switcher.showPanel();
var elmTitles = jQuery('.layer-switcher label').map(function() {
return jQuery(this).text();
}).get();
var lyrsWithTitle = shownLyrs(map.getLayerGroup());
expect(lyrsWithTitle.length).to.eql(elmTitles.length);
});
it('don\'t display layers without a title', function() {
switcher.showPanel();
// This is basically to ensure that our test layers include layers without a title
var lyrsWithoutTitle = _.filter(allLyrs(map.getLayerGroup()), function(lyr) {return !lyr.get('title')});
expect(lyrsWithoutTitle.length).not.to.equal(0);
});
it('displays normal layers as checkbox', function() {
switcher.showPanel();
var titles = jQuery('.layer-switcher input[type=checkbox]').siblings('label').map(function() {
return jQuery(this).text();
}).get();
expect(titles).to.eql(['Bar', 'Combined-Overlay-Group']);
});
it('greys out normal layer title labels when outside of layer resolution', function() {
map.getView().setResolution(6000);
switcher.showPanel();
var layerResTooHigh = jQuery('.layer-switcher label.disabled').map(function() {
return jQuery(this).text();
}).get();
map.getView().setResolution(500);
var layerResTooLow = jQuery('.layer-switcher label.disabled').map(function() {
return jQuery(this).text();
}).get();
expect([layerResTooHigh, layerResTooLow]).to.eql([['Bar'], ['Bar']]);
});
it('displays base layers as radio buttons', function() {
switcher.showPanel();
var titles = jQuery('.layer-switcher input[type=radio]').siblings('label').map(function() {
return jQuery(this).text();
}).get();
expect(titles).to.eql(['Combined-Base-Group', 'Too', 'Foo']);
});
it('should display uncombined groups without an input', function() {
switcher.showPanel();
var groups = jQuery('.layer-switcher label:not([for])')
var titles = groups.map(function() {
return jQuery(this).text();
}).get();
expect(titles).to.eql(['Base']);
expect(groups.siblings('input').length).to.be(0);
});
it('should display combined groups with an input', function () {
switcher.showPanel();
var titles = jQuery('.layer-switcher label[for]').map(function() {
return jQuery(this).text();
}).get();
expect(titles).to.contain('Combined-Base-Group');
expect(titles).to.contain('Combined-Overlay-Group');
});
it('should display combined groups without sub layers', function () {
switcher.showPanel();
var groups = jQuery('.layer-switcher label[for]')
expect(groups.siblings('ul').length).to.be(0);
});
});
describe('Overlay layer visibility', function() {
it('Toggles overlay layer visibility on click', function() {
switcher.showPanel();
var bar = getLayerByTitle('Bar');
bar.setVisible(true);
jQuery('.layer-switcher label:contains("Bar")').siblings('input').click();
expect(bar.getVisible()).to.be(false);
expect(jQuery('.layer-switcher label:contains("Bar")').siblings('input').get(0).checked).to.be(bar.getVisible());
bar.setVisible(false)
jQuery('.layer-switcher label:contains("Bar")').siblings('input').click();
expect(bar.getVisible()).to.be(true);
expect(jQuery('.layer-switcher label:contains("Bar")').siblings('input').get(0).checked).to.be(bar.getVisible());
});
});
describe('Base layer visibility', function() {
it('Only one base layer is visible after renderPanel', function() {
var foo = getLayerByTitle('Foo');
var too = getLayerByTitle('Too');
var cbg = getLayerByTitle('Combined-Base-Group');
var baseLayers = [foo, too, cbg];
// Enable all base layers
_.forEach(baseLayers, function (l) {
l.setVisible(true);
});
switcher.renderPanel();
var visibleBaseLayerCount = _.countBy(baseLayers, function (l){
return l.getVisible();
});
expect(visibleBaseLayerCount.true).to.be(1);
});
it('Only top most base layer is visible after renderPanel if more than one is visible', function() {
var foo = getLayerByTitle('Foo');
var too = getLayerByTitle('Too');
var cbg = getLayerByTitle('Combined-Base-Group');
var baseLayers = [foo, too, cbg];
// Enable all base layers
_.forEach(baseLayers, function (l) {
l.setVisible(true);
});
switcher.renderPanel();
expect(cbg.getVisible()).to.be(true);
});
it('Clicking on unchecked base layer shows it', function() {
var too = getLayerByTitle('Too');
too.setVisible(false);
switcher.renderPanel();
jQuery('.layer-switcher label:contains("Too")').siblings('input').click();
expect(too.getVisible()).to.be(true);
expect(jQuery('.layer-switcher label:contains("Too")').siblings('input').get(0).checked).to.be(true);
});
it('Clicking on checked base layer does not change base layer', function() {
var foo = getLayerByTitle('Foo');
foo.setVisible(true);
switcher.renderPanel();
jQuery('.layer-switcher label:contains("Foo")').siblings('input').click();
expect(foo.getVisible()).to.be(true);
expect(jQuery('.layer-switcher label:contains("Foo")').siblings('input').get(0).checked).to.be(true);
});
});
describe('Removes cleanly', function() {
it('Removes cleanly when ol.Map#removeControl is called', function() {
map.removeControl(switcher);
});
});
/**
* Returns the title of a given layer or null if lyr is falsey
*/
function lyrTitle(lyr) {
return (lyr) ? lyr.get('title') : null;
}
/**
* Returns the Layer instance that has the given title
*/
function getLayerByTitle(title) {
var layer = null;
ol.control.LayerSwitcher.forEachRecursive(map, function(lyr) {
if (lyr.get('title') && lyr.get('title') === title) {
layer = lyr;
return;
}
});
return layer;
}
/**
* Return a flattened Array of all layers regardless including those not
* shown by the LayerSwitcher
*/
function allLyrs(lyrs) {
return flatten(lyrs, function (lyr) {
return (lyr.getLayers) ? lyr.getLayers().getArray() : lyr;
});
}
/**
* Return a flattened Array of only those layers that the LayerSwitcher
* should show
*/
function shownLyrs(lyrs) {
// Pass in the Array from the root LayerGroup as it doesn't have a
// title but we don't want to filter out all layers
lyrs = lyrs.getLayers().getArray();
var flat = flatten(lyrs, function (lyr) {
// Return a Groups layer array only if the group has a title
// otherwise just return the group so that it's children will be
// skipped
return (lyr.getLayers && lyr.get('title')) ? lyr.getLayers().getArray() : lyr;
});
// Only return layers with a title
return _.filter(flat, lyrTitle);
}
/**
* Flattens a given nested collection using the provided function getArray
* to get an Array of the collections children.
*/
function flatten(srcCollection, getArray) {
getArray = getArray || function (item) {return item};
var src = getArray(srcCollection),
dest = [];
for (var i = 0, item; i < src.length; i++) {
item = src[i];
dest = dest.concat(item);
if (_.isArray(getArray(item))) {
dest = dest.concat(flatten(item, getArray));
}
}
return dest;
}
});
================================================
FILE: test/spec/twomaps.js
================================================
describe('ol.control.LayerSwitcher - Two maps', function() {
var map1, map2, target1, target2, switcher1, switcher2;
beforeEach(function() {
target1 = document.createElement('div');
target1.id = 'map1';
document.body.appendChild(target1);
target2 = document.createElement('div');
target2.id = 'map2';
document.body.appendChild(target2);
switcher1 = new ol.control.LayerSwitcher();
switcher2 = new ol.control.LayerSwitcher();
map1 = new ol.Map({
target: target1,
layers: [
new ol.layer.Group({
title: 'Base',
layers: [
new ol.layer.Tile({
title: 'Foo',
type: 'base',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
new ol.layer.Tile({
title: 'Too',
type: 'base',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
})
]
}),
new ol.layer.Tile({
title: 'Bar',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
],
controls: [switcher1]
});
map2 = new ol.Map({
target: target2,
layers: [
new ol.layer.Group({
title: 'Base',
layers: [
new ol.layer.Tile({
title: 'Foo',
type: 'base',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
new ol.layer.Tile({
title: 'Too',
type: 'base',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
})
]
}),
new ol.layer.Tile({
title: 'Bar',
source: new ol.source.TileDebug({
projection: 'EPSG:3857',
tileGrid: ol.tilegrid.createXYZ({
maxZoom: 22
})
})
}),
],
controls: [switcher2]
});
});
afterEach(function() {
document.body.removeChild(target1);
document.body.removeChild(target2);
target1 = null;
target2 = null;
switcher1 = null;
switcher2 = null;
map1 = null;
map2 = null;
});
describe('Layer IDs are unique', function() {
it('Inputs for layers with the same title in different maps will have different IDs', function() {
switcher1.showPanel();
switcher2.showPanel();
var bar1Id = jQuery('#map1 .layer-switcher label:contains("Bar")').siblings('input').attr('id');
var bar2Id = jQuery('#map2 .layer-switcher label:contains("Bar")').siblings('input').attr('id');
expect(bar1Id).to.not.equal(bar2Id);
});
});
/**
* Returns the Layer instance that has the given title
*/
function getLayerByTitle(map, title) {
var layer = null;
ol.control.LayerSwitcher.forEachRecursive(map, function(lyr) {
if (lyr.get('title') && lyr.get('title') === title) {
layer = lyr;
return;
}
});
return layer;
}
});
================================================
FILE: util/README.md
================================================
# OpenLayers LayerSwitcher
Grouped layer list control for an OpenLayer v3/v4 map.
All layers should have a `title` property and base layers should have a `type` property set to `base`. Group layers (`ol.layer.Group`) can be used to visually group layers together. See [examples/layerswitcher.js](examples/layerswitcher.js) for usage.
## Examples
The examples demonstrate usage and can be viewed online thanks to [RawGit](http://rawgit.com/):
* [Basic usage](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/layerswitcher.html)
* Create a layer switcher control. Each layer to be displayed in the layer switcher has a `title` property as does each Group; each base map layer has a `type: 'base'` property.
* [Add layer](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/addlayer.html)
* Add a layer to an existing layer group after the layer switcher has been added to the map.
* [Scrolling](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/scroll.html)
* Demonstrate the panel scrolling vertically, control the height of the layer switcher by setting the `max-height` (see [examples/scroll.css](examples/scroll.css)) and it's position relative to the bottom of the map (see the `.layer-switcher.shown` selector in [src/ol3-layerswitcher.css](src/ol3-layerswitcher.css)).
* [Browserify](examples/browserify/)
* Example of using ol3-layerswitcher with Browserify (see [examples/browserify/README.md](examples/browserify/README.md) for details of building.
The source for all examples can be found in [examples](examples).
## Tests
To run the tests you'll need to install the dependencies via `npm`. In the root of the repository run:
npm install
Then run the tests by opening [test/index.html](test/index.html) in a browser.
## API
{% for class in classes -%}
### `new {{ class.longname }}({{ class.signature }})`
{{ class.description }}
#### Parameters:
|Name|Type|Description|
|:---|:---|:----------|
{% for param in class.params %}|`{{ param.name }}`|`{{ param.type.names[0] }}`| {{ param.description }} |{% endfor %}
#### Extends
`{{ class.augments }}`
#### Methods
{% for method in class.methods -%}
##### `{% if method.scope == 'static' %}(static) {{ class.longname }}.{% endif %}{{ method.name }}({{ method.signature }})`
{{ method.description }}
{% if method.params -%}
###### Parameters:
|Name|Type|Description|
|:---|:---|:----------|
{% for param in method.params -%}
|`{{ param.name }}`|`{{ param.type.names[0] }}`| {{ param.description }} |
{% endfor %}
{% endif %}
{%- endfor %}
{%- endfor -%}
## License
MIT (c) Matt Walker.
## Also see
If you find the layer switcher useful you might also like the
[ol3-popup](https://github.com/walkermatt/ol3-popup).
gitextract_zbkqn7gv/
├── .gitignore
├── README.md
├── bower.json
├── examples/
│ ├── addlayer.html
│ ├── addlayer.js
│ ├── browserify/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── index.js
│ │ └── package.json
│ ├── layerswitcher.css
│ ├── layerswitcher.html
│ ├── layerswitcher.js
│ ├── scroll.css
│ ├── scroll.html
│ └── scroll.js
├── package.json
├── src/
│ ├── ol3-layerswitcher.css
│ └── ol3-layerswitcher.js
├── test/
│ ├── index.html
│ └── spec/
│ ├── ol3-layerswitcher.js
│ └── twomaps.js
└── util/
└── README.md
SYMBOL INDEX (6 symbols across 2 files)
FILE: test/spec/ol3-layerswitcher.js
function lyrTitle (line 304) | function lyrTitle(lyr) {
function getLayerByTitle (line 311) | function getLayerByTitle(title) {
function allLyrs (line 326) | function allLyrs(lyrs) {
function shownLyrs (line 336) | function shownLyrs(lyrs) {
function flatten (line 354) | function flatten(srcCollection, getArray) {
FILE: test/spec/twomaps.js
function getLayerByTitle (line 119) | function getLayerByTitle(map, title) {
Condensed preview — 22 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (59K chars).
[
{
"path": ".gitignore",
"chars": 20,
"preview": "node_modules\n.idea/\n"
},
{
"path": "README.md",
"chars": 3804,
"preview": "# DEPRECATED: ol3-layerswitcher is now [ol-layerswitcher](https://github.com/walkermatt/ol-layerswitcher)\n\nIf you requir"
},
{
"path": "bower.json",
"chars": 510,
"preview": "{\n \"name\": \"ol3-layerswitcher\",\n \"version\": \"1.1.0\",\n \"homepage\": \"https://github.com/walkermatt/ol3-layerswitcher\",\n"
},
{
"path": "examples/addlayer.html",
"chars": 904,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>OpenLayers 3 - LayerSwitcher Add Layer</title>\n "
},
{
"path": "examples/addlayer.js",
"chars": 1720,
"preview": "(function() {\n\n // Create a group for overlays. Add the group to the map when it's created\n // but add the overlay"
},
{
"path": "examples/browserify/README.md",
"chars": 667,
"preview": "# Using ol3-layerswitcher with Browserify \n\nBased on [OpenLayers 3 Browserify Tutorial](https://openlayers.org/en/latest"
},
{
"path": "examples/browserify/index.html",
"chars": 516,
"preview": "<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <title>Using Browserify with OpenLayers</title>\n <link"
},
{
"path": "examples/browserify/index.js",
"chars": 871,
"preview": "var ol = require('openlayers');\nvar LayerSwitcher = require('../../src/ol3-layerswitcher');\n\nvar map = new ol.Map({\n "
},
{
"path": "examples/browserify/package.json",
"chars": 483,
"preview": "{\n \"name\": \"ol3-layerswitcher-browserify\",\n \"version\": \"1.1.2\",\n \"description\": \"Example of using ol3-layerswitcher w"
},
{
"path": "examples/layerswitcher.css",
"chars": 146,
"preview": "html, body {\n height: 100%;\n padding: 0;\n margin: 0;\n font-family: sans-serif;\n font-size: small;\n}\n\n#map {\n width"
},
{
"path": "examples/layerswitcher.html",
"chars": 899,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>OpenLayers 3 - LayerSwitcher</title>\n <meta n"
},
{
"path": "examples/layerswitcher.js",
"chars": 2434,
"preview": "(function() {\n var map = new ol.Map({\n target: 'map',\n layers: [\n new ol.layer.Group({\n "
},
{
"path": "examples/scroll.css",
"chars": 116,
"preview": "/* Set the maxmimum height of the layerswitcher when it's shown */\n.layer-switcher.shown {\n max-height: 170px;\n}\n"
},
{
"path": "examples/scroll.html",
"chars": 950,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>OpenLayers 3 - LayerSwitcher Scrolling</title>\n "
},
{
"path": "examples/scroll.js",
"chars": 4340,
"preview": "(function() {\n\n var thunderforestAttributions = [\n new ol.Attribution({\n html: 'Tiles © <a hre"
},
{
"path": "package.json",
"chars": 1062,
"preview": "{\n \"name\": \"ol3-layerswitcher\",\n \"version\": \"1.1.2\",\n \"description\": \"Layer switcher control for OpenLayers v3/v4\",\n "
},
{
"path": "src/ol3-layerswitcher.css",
"chars": 3125,
"preview": ".layer-switcher.shown.ol-control {\n background-color: transparent;\n}\n\n.layer-switcher.shown.ol-control:hover {\n ba"
},
{
"path": "src/ol3-layerswitcher.js",
"chars": 9762,
"preview": "(function (root, factory) {\n if(typeof define === \"function\" && define.amd) {\n define([\"openlayers\"], factory);\n } "
},
{
"path": "test/index.html",
"chars": 1122,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>ol3-layerswitcher spec runner</title>\n <meta charset=\"utf-8\">\n <link rel="
},
{
"path": "test/spec/ol3-layerswitcher.js",
"chars": 15308,
"preview": "describe('ol.control.LayerSwitcher', function() {\n var map, target, switcher;\n\n beforeEach(function() {\n ta"
},
{
"path": "test/spec/twomaps.js",
"chars": 4485,
"preview": "describe('ol.control.LayerSwitcher - Two maps', function() {\n var map1, map2, target1, target2, switcher1, switcher2;"
},
{
"path": "util/README.md",
"chars": 2755,
"preview": "# OpenLayers LayerSwitcher\n\nGrouped layer list control for an OpenLayer v3/v4 map.\n\nAll layers should have a `title` pro"
}
]
About this extraction
This page contains the full source code of the walkermatt/ol3-layerswitcher GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 22 files (54.7 KB), approximately 13.6k tokens, and a symbol index with 6 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.