[
  {
    "path": ".gitignore",
    "content": "node_modules\n.idea/\n"
  },
  {
    "path": "README.md",
    "content": "# DEPRECATED: ol3-layerswitcher is now [ol-layerswitcher](https://github.com/walkermatt/ol-layerswitcher)\n\nIf 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:\n\n    npm install git+https://github.com/walkermatt/ol3-layerswitcher.git#master\n\nBut 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).\n\n# OpenLayers LayerSwitcher\n\nGrouped layer list control for an OpenLayer v3/v4 map.\n\nAll 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.\n\n## Examples\n\nThe examples demonstrate usage and can be viewed online thanks to [RawGit](http://rawgit.com/):\n\n* [Basic usage](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/layerswitcher.html)\n    * 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.\n* [Add layer](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/addlayer.html)\n    * Add a layer to an existing layer group after the layer switcher has been added to the map.\n* [Scrolling](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/scroll.html)\n    * 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)).\n* [Browserify](examples/browserify/)\n    * Example of using ol3-layerswitcher with Browserify (see [examples/browserify/README.md](examples/browserify/README.md) for details of building.\n\nThe source for all examples can be found in [examples](examples).\n\n## Tests\n\nTo run the tests you'll need to install the dependencies via `npm`. In the root of the repository run:\n\n    npm install\n\nThen run the tests by opening [test/index.html](test/index.html) in a browser.\n\n## API\n\n### `new ol.control.LayerSwitcher(opt_options)`\n\nOpenLayers v3/v4 Layer Switcher Control.\nSee [the examples](./examples) for usage.\n\n#### Parameters:\n\n|Name|Type|Description|\n|:---|:---|:----------|\n|`opt_options`|`Object`| Control options, extends olx.control.ControlOptions adding: **`tipLabel`** `String` - the button tooltip. |\n\n#### Extends\n\n`ol.control.Control`\n\n#### Methods\n\n##### `showPanel()`\n\nShow the layer panel.\n\n##### `hidePanel()`\n\nHide the layer panel.\n\n##### `renderPanel()`\n\nRe-draw the layer panel to represent the current state of the layers.\n\n##### `setMap(map)`\n\nSet the map instance the control is associated with.\n\n###### Parameters:\n\n|Name|Type|Description|\n|:---|:---|:----------|\n|`map`|`ol.Map`| The map instance. |\n\n\n##### `(static) ol.control.LayerSwitcher.forEachRecursive(lyr,fn)`\n\n**Static** Call the supplied function for each layer in the passed layer group\nrecursing nested groups.\n\n###### Parameters:\n\n|Name|Type|Description|\n|:---|:---|:----------|\n|`lyr`|`ol.layer.Group`| The layer group to start iterating from. |\n|`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` |\n\n\n##### `(static) ol.control.LayerSwitcher.uuid()`\n\nGenerate a UUID\n\n## License\n\nMIT (c) Matt Walker.\n\n## Also see\n\nIf you find the layer switcher useful you might also like the\n[ol3-popup](https://github.com/walkermatt/ol3-popup).\n\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"ol3-layerswitcher\",\n  \"version\": \"1.1.0\",\n  \"homepage\": \"https://github.com/walkermatt/ol3-layerswitcher\",\n  \"authors\": [\n    \"Matt Walker (http://longwayaround.org.uk)\"\n  ],\n  \"description\": \"Layer switcher control for OpenLayers v3/v4\",\n  \"main\": [\n    \"src/ol3-layerswitcher.js\",\n    \"src/ol3-layerswitcher.css\"\n  ],\n  \"keywords\": [\n    \"openlayers\",\n    \"ol\",\n    \"layerswitcher\"\n  ],\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"node_modules\",\n    \"bower_components\",\n    \"test\"\n  ]\n}\n"
  },
  {
    "path": "examples/addlayer.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>OpenLayers 3 - LayerSwitcher Add Layer</title>\n    <meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no, width=device-width\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.css\" />\n    <link rel=\"stylesheet\" href=\"../src/ol3-layerswitcher.css\" />\n    <link rel=\"stylesheet\" href=\"layerswitcher.css\" />\n  </head>\n  <body>\n    <div id=\"map\"></div>\n    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->\n    <script src=\"https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.js\"></script>\n    <script src=\"../src/ol3-layerswitcher.js\"></script>\n    <script src=\"addlayer.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/addlayer.js",
    "content": "(function() {\n\n    // Create a group for overlays. Add the group to the map when it's created\n    // but add the overlay layers later\n    var overlayGroup = new ol.layer.Group({\n        title: 'Overlays',\n        layers: [\n        ]\n    });\n\n    // Create a map containing two group layers\n    var map = new ol.Map({\n        target: 'map',\n        layers: [\n            new ol.layer.Group({\n                'title': 'Base maps',\n                layers: [\n                    new ol.layer.Tile({\n                        title: 'OSM',\n                        type: 'base',\n                        source: new ol.source.OSM()\n                    })\n                ]\n            }),\n            overlayGroup\n        ],\n        view: new ol.View({\n            center: ol.proj.transform([-0.92, 52.96], 'EPSG:4326', 'EPSG:3857'),\n            zoom: 6\n        })\n    });\n\n    // Create a LayerSwitcher instance and add it to the map\n    var layerSwitcher = new ol.control.LayerSwitcher();\n    map.addControl(layerSwitcher);\n\n    // Add a layer to a pre-exiting ol.layer.Group after the LayerSwitcher has\n    // been added to the map. The layer will appear in the list the next time\n    // the LayerSwitcher is shown or LayerSwitcher#renderPanel is called.\n    overlayGroup.getLayers().push(\n        new ol.layer.Image({\n            title: 'Countries',\n            minResolution: 500,\n            maxResolution: 5000,\n            source: new ol.source.ImageArcGISRest({\n                ratio: 1,\n                params: {'LAYERS': 'show:0'},\n                url: \"https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Countries_December_2016_Boundaries/MapServer\"\n            })\n        })\n    );\n\n})();\n"
  },
  {
    "path": "examples/browserify/README.md",
    "content": "# Using ol3-layerswitcher with Browserify \n\nBased on [OpenLayers 3 Browserify Tutorial](https://openlayers.org/en/latest/doc/tutorials/browserify.html).\n\n## Building\n\nFor a one-time build run:\n\n    npm run build\n\nIf you want to make changes and have the project auto build run:\n\n    npm run start\n\n## Requiring ol3-layerswitcher\n\n    // Pass the path to `ol3-layerswitcher.js` minus the extension to `require`\n    // which will return the constructor\n    var LayerSwitcher = require('../../src/ol3-layerswitcher');\n\n    // Create an instance\n    var layerSwitcher = new LayerSwitcher();\n\n    // Add to a `ol.Map` instance as normal\n    map.addControl(layerSwitcher);\n"
  },
  {
    "path": "examples/browserify/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Using Browserify with OpenLayers</title>\n    <link rel=\"stylesheet\" href=\"node_modules/openlayers/dist/ol.css\" type=\"text/css\">\n    <link rel=\"stylesheet\" href=\"../../src/ol3-layerswitcher.css\" />\n    <link rel=\"stylesheet\" href=\"../layerswitcher.css\" />\n    <style>\n      #map {\n        width: 400px;\n        height: 250px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"map\"></div>\n    <script src=\"bundle.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/browserify/index.js",
    "content": "var ol = require('openlayers');\nvar LayerSwitcher = require('../../src/ol3-layerswitcher');\n\nvar map = new ol.Map({\n    target: 'map',\n    layers: [\n        new ol.layer.Group({\n            'title': 'Base maps',\n            layers: [\n                new ol.layer.Tile({\n                    title: 'Water color',\n                    type: 'base',\n                    visible: false,\n                    source: new ol.source.Stamen({\n                        layer: 'watercolor'\n                    })\n                }),\n                new ol.layer.Tile({\n                    title: 'OSM',\n                    type: 'base',\n                    source: new ol.source.OSM()\n                })\n            ]\n        })\n    ],\n    view: new ol.View({\n        center: [0, 0],\n        zoom: 0\n    })\n});\n\nvar layerSwitcher = new LayerSwitcher();\nmap.addControl(layerSwitcher);\n"
  },
  {
    "path": "examples/browserify/package.json",
    "content": "{\n  \"name\": \"ol3-layerswitcher-browserify\",\n  \"version\": \"1.1.2\",\n  \"description\": \"Example of using ol3-layerswitcher with Browserify\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"watchify index.js --outfile bundle.js\",\n    \"build\": \"browserify index.js | uglifyjs --compress --output bundle.js\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"browserify\": \"^13.3.0\",\n    \"openlayers\": \"^4.0.1\",\n    \"uglify-js\": \"^2.7.5\",\n    \"watchify\": \"^3.8.0\"\n  }\n}\n"
  },
  {
    "path": "examples/layerswitcher.css",
    "content": "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: 100%;\n  height: 100%;\n}\n"
  },
  {
    "path": "examples/layerswitcher.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>OpenLayers 3 - LayerSwitcher</title>\n    <meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no, width=device-width\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.css\" />\n    <link rel=\"stylesheet\" href=\"../src/ol3-layerswitcher.css\" />\n    <link rel=\"stylesheet\" href=\"layerswitcher.css\" />\n  </head>\n  <body>\n    <div id=\"map\"></div>\n    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->\n    <script src=\"https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.js\"></script>\n    <script src=\"../src/ol3-layerswitcher.js\"></script>\n    <script src=\"layerswitcher.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/layerswitcher.js",
    "content": "(function() {\n    var map = new ol.Map({\n        target: 'map',\n        layers: [\n            new ol.layer.Group({\n                'title': 'Base maps',\n                layers: [\n                    new ol.layer.Group({\n                        title: 'Water color with labels',\n                        type: 'base',\n                        combine: true,\n                        visible: false,\n                        layers: [\n                            new ol.layer.Tile({\n                                source: new ol.source.Stamen({\n                                    layer: 'watercolor'\n                                })\n                            }),\n                            new ol.layer.Tile({\n                                source: new ol.source.Stamen({\n                                    layer: 'terrain-labels'\n                                })\n                            })\n                        ]\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Water color',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.Stamen({\n                            layer: 'watercolor'\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'OSM',\n                        type: 'base',\n                        visible: true,\n                        source: new ol.source.OSM()\n                    })\n                ]\n            }),\n            new ol.layer.Group({\n                title: 'Overlays',\n                layers: [\n                    new ol.layer.Image({\n                        title: 'Countries',\n                        source: new ol.source.ImageArcGISRest({\n                            ratio: 1,\n                            params: {'LAYERS': 'show:0'},\n                            url: \"https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Countries_December_2016_Boundaries/MapServer\"\n                        })\n                    })\n                ]\n            })\n        ],\n        view: new ol.View({\n            center: ol.proj.transform([-0.92, 52.96], 'EPSG:4326', 'EPSG:3857'),\n            zoom: 6\n        })\n    });\n\n    var layerSwitcher = new ol.control.LayerSwitcher({\n        tipLabel: 'Légende' // Optional label for button\n    });\n    map.addControl(layerSwitcher);\n\n})();\n"
  },
  {
    "path": "examples/scroll.css",
    "content": "/* 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",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>OpenLayers 3 - LayerSwitcher Scrolling</title>\n    <meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no, width=device-width\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.css\" />\n    <link rel=\"stylesheet\" href=\"../src/ol3-layerswitcher.css\" />\n    <link rel=\"stylesheet\" href=\"layerswitcher.css\" />\n    <link rel=\"stylesheet\" href=\"scroll.css\" />\n  </head>\n  <body>\n    <div id=\"map\"></div>\n    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->\n    <script src=\"https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/ol3/4.0.1/ol.js\"></script>\n    <script src=\"../src/ol3-layerswitcher.js\"></script>\n    <script src=\"scroll.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/scroll.js",
    "content": "(function() {\n\n    var thunderforestAttributions = [\n        new ol.Attribution({\n            html: 'Tiles &copy; <a href=\"http://www.thunderforest.com/\">Thunderforest</a>'\n        }),\n        ol.source.OSM.ATTRIBUTION\n    ];\n\n    var map = new ol.Map({\n        target: 'map',\n        layers: [\n            new ol.layer.Group({\n                'title': 'Base maps',\n                layers: [\n                    new ol.layer.Tile({\n                        title: 'Stamen - Water color',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.Stamen({\n                            layer: 'watercolor'\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Stamen - Toner',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.Stamen({\n                            layer: 'toner'\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Thunderforest - OpenCycleMap',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.OSM({\n                            url: 'http://{a-c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',\n                            attributions: thunderforestAttributions\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Thunderforest - Outdoors',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.OSM({\n                            url: 'http://{a-c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png',\n                            attributions: thunderforestAttributions\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Thunderforest - Landscape',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.OSM({\n                            url: 'http://{a-c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png',\n                            attributions: thunderforestAttributions\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Thunderforest - Transport',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.OSM({\n                            url: 'http://{a-c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png',\n                            attributions: thunderforestAttributions\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Thunderforest - Transport Dark',\n                        type: 'base',\n                        visible: false,\n                        source: new ol.source.OSM({\n                            url: 'http://{a-c}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png',\n                            attributions: thunderforestAttributions\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'OSM',\n                        type: 'base',\n                        visible: true,\n                        source: new ol.source.OSM()\n                    })\n                ]\n            }),\n            new ol.layer.Group({\n                title: 'Overlays',\n                layers: [\n                    new ol.layer.Image({\n                        title: 'Countries',\n                        source: new ol.source.ImageArcGISRest({\n                            ratio: 1,\n                            params: {'LAYERS': 'show:0'},\n                            url: \"https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Countries_December_2016_Boundaries/MapServer\"\n                        })\n                    })\n                ]\n            })\n        ],\n        view: new ol.View({\n            center: ol.proj.transform([-0.92, 52.96], 'EPSG:4326', 'EPSG:3857'),\n            zoom: 6\n        })\n    });\n\n    map.addControl(new ol.control.LayerSwitcher());\n\n})();\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"ol3-layerswitcher\",\n  \"version\": \"1.1.2\",\n  \"description\": \"Layer switcher control for OpenLayers v3/v4\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/walkermatt/ol3-layerswitcher.git\"\n  },\n  \"author\": \"Matt Walker (http://longwayaround.org.uk)\",\n  \"contributors\": [\n    \"Thomas Gratier <thomas_gratier@yahoo.fr>\",\n    \"Poul Kjeldager Sørensen <pks@s-innovations.net>\",\n    \"Micho García <micho.garcia@geomati.co>\",\n    \"olivierdalang <olivier.dalang@gmail.com>\"\n  ],\n  \"keywords\": [\n    \"openlayers\",\n    \"layerswitcher\",\n    \"ol\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/walkermatt/ol3-layerswitcher/issues\"\n  },\n  \"scripts\": {\n    \"doc\": \"node_modules/.bin/jsdoc --explain src/ol3-layerswitcher.js | node_modules/.bin/dirtydocs util/README.md > README.md\"\n  },\n  \"dependencies\": {\n    \"openlayers\": \"~4.0.1\"\n  },\n  \"devDependencies\": {\n    \"expect.js\": \"~0.3.1\",\n    \"jquery\": \"~1.11.1\",\n    \"lodash\": \"~2.4.1\",\n    \"mocha\": \"~1.20.1\",\n    \"jsdoc\": \"~3.3.0-beta1\",\n    \"dirtydocs\": \"0.0.1\"\n  }\n}\n"
  },
  {
    "path": "src/ol3-layerswitcher.css",
    "content": ".layer-switcher.shown.ol-control {\n    background-color: transparent;\n}\n\n.layer-switcher.shown.ol-control:hover {\n    background-color: transparent;\n}\n\n.layer-switcher {\n    position: absolute;\n    top: 3.5em;\n    right: 0.5em;\n    text-align: left;\n}\n\n.layer-switcher.shown {\n    bottom: 3em;\n}\n\n.layer-switcher .panel {\n    padding: 0 1em 0 0;\n    margin: 0;\n    border: 4px solid #eee;\n    border-radius: 4px;\n    background-color: white;\n    display: none;\n    max-height: 100%;\n    overflow-y: auto;\n}\n\n.layer-switcher.shown .panel {\n    display: block;\n}\n\n.layer-switcher button {\n    float: right;\n    width: 38px;\n    height: 38px;\n    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*/;\n    background-repeat: no-repeat;\n    background-position: 2px;\n    background-color: white;\n    border: none;\n}\n\n.layer-switcher.shown button {\n    display: none;\n}\n\n.layer-switcher button:focus, .layer-switcher button:hover {\n    background-color: white;\n}\n\n.layer-switcher ul {\n    padding-left: 1em;\n    list-style: none;\n}\n\n.layer-switcher li.group {\n    padding-top: 5px;\n}\n\n.layer-switcher li.group > label {\n    font-weight: bold;\n}\n\n.layer-switcher li.layer {\n    display: table;\n}\n\n.layer-switcher li.layer label, .layer-switcher li.layer input {\n    display: table-cell;\n    vertical-align: sub;\n}\n\n.layer-switcher label.disabled {\n    opacity:0.4;\n}\n\n.layer-switcher input {\n    margin: 4px;\n}\n\n.layer-switcher.touch ::-webkit-scrollbar {\n    width: 4px;\n}\n\n.layer-switcher.touch ::-webkit-scrollbar-track {\n    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);\n    border-radius: 10px;\n}\n\n.layer-switcher.touch ::-webkit-scrollbar-thumb {\n    border-radius: 10px;\n    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);\n}\n"
  },
  {
    "path": "src/ol3-layerswitcher.js",
    "content": "(function (root, factory) {\n  if(typeof define === \"function\" && define.amd) {\n    define([\"openlayers\"], factory);\n  } else if(typeof module === \"object\" && module.exports) {\n    module.exports = factory(require(\"openlayers\"));\n  } else {\n    root.LayerSwitcher = factory(root.ol);\n  }\n}(this, function(ol) {\n    /**\n     * OpenLayers v3/v4 Layer Switcher Control.\n     * See [the examples](./examples) for usage.\n     * @constructor\n     * @extends {ol.control.Control}\n     * @param {Object} opt_options Control options, extends olx.control.ControlOptions adding:\n     *                              **`tipLabel`** `String` - the button tooltip.\n     */\n    ol.control.LayerSwitcher = function(opt_options) {\n\n        var options = opt_options || {};\n\n        var tipLabel = options.tipLabel ?\n          options.tipLabel : 'Legend';\n\n        this.mapListeners = [];\n\n        this.hiddenClassName = 'ol-unselectable ol-control layer-switcher';\n        if (ol.control.LayerSwitcher.isTouchDevice_()) {\n            this.hiddenClassName += ' touch';\n        }\n        this.shownClassName = 'shown';\n\n        var element = document.createElement('div');\n        element.className = this.hiddenClassName;\n\n        var button = document.createElement('button');\n        button.setAttribute('title', tipLabel);\n        element.appendChild(button);\n\n        this.panel = document.createElement('div');\n        this.panel.className = 'panel';\n        element.appendChild(this.panel);\n        ol.control.LayerSwitcher.enableTouchScroll_(this.panel);\n\n        var this_ = this;\n\n        button.onmouseover = function(e) {\n            this_.showPanel();\n        };\n\n        button.onclick = function(e) {\n            e = e || window.event;\n            this_.showPanel();\n            e.preventDefault();\n        };\n\n        this_.panel.onmouseout = function(e) {\n            e = e || window.event;\n            if (!this_.panel.contains(e.toElement || e.relatedTarget)) {\n                this_.hidePanel();\n            }\n        };\n\n        ol.control.Control.call(this, {\n            element: element,\n            target: options.target\n        });\n\n    };\n\n    ol.inherits(ol.control.LayerSwitcher, ol.control.Control);\n\n    /**\n     * Show the layer panel.\n     */\n    ol.control.LayerSwitcher.prototype.showPanel = function() {\n        if (!this.element.classList.contains(this.shownClassName)) {\n            this.element.classList.add(this.shownClassName);\n            this.renderPanel();\n        }\n    };\n\n    /**\n     * Hide the layer panel.\n     */\n    ol.control.LayerSwitcher.prototype.hidePanel = function() {\n        if (this.element.classList.contains(this.shownClassName)) {\n            this.element.classList.remove(this.shownClassName);\n        }\n    };\n\n    /**\n     * Re-draw the layer panel to represent the current state of the layers.\n     */\n    ol.control.LayerSwitcher.prototype.renderPanel = function() {\n\n        this.ensureTopVisibleBaseLayerShown_();\n\n        while(this.panel.firstChild) {\n            this.panel.removeChild(this.panel.firstChild);\n        }\n\n        var ul = document.createElement('ul');\n        this.panel.appendChild(ul);\n        this.renderLayers_(this.getMap(), ul);\n\n    };\n\n    /**\n     * Set the map instance the control is associated with.\n     * @param {ol.Map} map The map instance.\n     */\n    ol.control.LayerSwitcher.prototype.setMap = function(map) {\n        // Clean up listeners associated with the previous map\n        for (var i = 0, key; i < this.mapListeners.length; i++) {\n            ol.Observable.unByKey(this.mapListeners[i]);\n        }\n        this.mapListeners.length = 0;\n        // Wire up listeners etc. and store reference to new map\n        ol.control.Control.prototype.setMap.call(this, map);\n        if (map) {\n            var this_ = this;\n            this.mapListeners.push(map.on('pointerdown', function() {\n                this_.hidePanel();\n            }));\n            this.renderPanel();\n        }\n    };\n\n    /**\n     * Ensure only the top-most base layer is visible if more than one is visible.\n     * @private\n     */\n    ol.control.LayerSwitcher.prototype.ensureTopVisibleBaseLayerShown_ = function() {\n        var lastVisibleBaseLyr;\n        ol.control.LayerSwitcher.forEachRecursive(this.getMap(), function(l, idx, a) {\n            if (l.get('type') === 'base' && l.getVisible()) {\n                lastVisibleBaseLyr = l;\n            }\n        });\n        if (lastVisibleBaseLyr) this.setVisible_(lastVisibleBaseLyr, true);\n    };\n\n    /**\n     * Toggle the visible state of a layer.\n     * Takes care of hiding other layers in the same exclusive group if the layer\n     * is toggle to visible.\n     * @private\n     * @param {ol.layer.Base} The layer whos visibility will be toggled.\n     */\n    ol.control.LayerSwitcher.prototype.setVisible_ = function(lyr, visible) {\n        var map = this.getMap();\n        lyr.setVisible(visible);\n        if (visible && lyr.get('type') === 'base') {\n            // Hide all other base layers regardless of grouping\n            ol.control.LayerSwitcher.forEachRecursive(map, function(l, idx, a) {\n                if (l != lyr && l.get('type') === 'base') {\n                    l.setVisible(false);\n                }\n            });\n        }\n    };\n\n    /**\n     * Render all layers that are children of a group.\n     * @private\n     * @param {ol.layer.Base} lyr Layer to be rendered (should have a title property).\n     * @param {Number} idx Position in parent group list.\n     */\n    ol.control.LayerSwitcher.prototype.renderLayer_ = function(lyr, idx) {\n\n        var this_ = this;\n\n        var li = document.createElement('li');\n\n        var lyrTitle = lyr.get('title');\n        var lyrId = ol.control.LayerSwitcher.uuid();\n\n        var label = document.createElement('label');\n\n        if (lyr.getLayers && !lyr.get('combine')) {\n\n            li.className = 'group';\n            label.innerHTML = lyrTitle;\n            li.appendChild(label);\n            var ul = document.createElement('ul');\n            li.appendChild(ul);\n\n            this.renderLayers_(lyr, ul);\n\n        } else {\n\n            li.className = 'layer';\n            var input = document.createElement('input');\n            if (lyr.get('type') === 'base') {\n                input.type = 'radio';\n                input.name = 'base';\n            } else {\n                input.type = 'checkbox';\n            }\n            input.id = lyrId;\n            input.checked = lyr.get('visible');\n            input.onchange = function(e) {\n                this_.setVisible_(lyr, e.target.checked);\n            };\n            li.appendChild(input);\n\n            label.htmlFor = lyrId;\n            label.innerHTML = lyrTitle;\n\n            var rsl = this.getMap().getView().getResolution();\n            if (rsl > lyr.getMaxResolution() || rsl < lyr.getMinResolution()){\n                label.className += ' disabled';\n            }\n\n            li.appendChild(label);\n\n        }\n\n        return li;\n\n    };\n\n    /**\n     * Render all layers that are children of a group.\n     * @private\n     * @param {ol.layer.Group} lyr Group layer whos children will be rendered.\n     * @param {Element} elm DOM element that children will be appended to.\n     */\n    ol.control.LayerSwitcher.prototype.renderLayers_ = function(lyr, elm) {\n        var lyrs = lyr.getLayers().getArray().slice().reverse();\n        for (var i = 0, l; i < lyrs.length; i++) {\n            l = lyrs[i];\n            if (l.get('title')) {\n                elm.appendChild(this.renderLayer_(l, i));\n            }\n        }\n    };\n\n    /**\n     * **Static** Call the supplied function for each layer in the passed layer group\n     * recursing nested groups.\n     * @param {ol.layer.Group} lyr The layer group to start iterating from.\n     * @param {Function} fn Callback which will be called for each `ol.layer.Base`\n     * found under `lyr`. The signature for `fn` is the same as `ol.Collection#forEach`\n     */\n    ol.control.LayerSwitcher.forEachRecursive = function(lyr, fn) {\n        lyr.getLayers().forEach(function(lyr, idx, a) {\n            fn(lyr, idx, a);\n            if (lyr.getLayers) {\n                ol.control.LayerSwitcher.forEachRecursive(lyr, fn);\n            }\n        });\n    };\n\n    /**\n     * Generate a UUID\n     * @returns {String} UUID\n     *\n     * Adapted from http://stackoverflow.com/a/2117523/526860\n     */\n    ol.control.LayerSwitcher.uuid = function() {\n        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);\n            return v.toString(16);\n        });\n    }\n\n    /**\n    * @private\n    * @desc Apply workaround to enable scrolling of overflowing content within an\n    * element. Adapted from https://gist.github.com/chrismbarr/4107472\n    */\n    ol.control.LayerSwitcher.enableTouchScroll_ = function(elm) {\n       if(ol.control.LayerSwitcher.isTouchDevice_()){\n           var scrollStartPos = 0;\n           elm.addEventListener(\"touchstart\", function(event) {\n               scrollStartPos = this.scrollTop + event.touches[0].pageY;\n           }, false);\n           elm.addEventListener(\"touchmove\", function(event) {\n               this.scrollTop = scrollStartPos - event.touches[0].pageY;\n           }, false);\n       }\n    };\n\n    /**\n     * @private\n     * @desc Determine if the current browser supports touch events. Adapted from\n     * https://gist.github.com/chrismbarr/4107472\n     */\n    ol.control.LayerSwitcher.isTouchDevice_ = function() {\n        try {\n            document.createEvent(\"TouchEvent\");\n            return true;\n        } catch(e) {\n            return false;\n        }\n    };\n    var LayerSwitcher = ol.control.LayerSwitcher;\n    return LayerSwitcher;\n}));\n"
  },
  {
    "path": "test/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>ol3-layerswitcher spec runner</title>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../node_modules/mocha/mocha.css\">\n    <link rel=\"stylesheet\" href=\"../node_modules/openlayers/css/ol.css\" />\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../src/ol3-layerswitcher.css\">\n</head>\n<body>\n<div id=\"mocha\"></div>\n<script type=\"text/javascript\" src=\"../node_modules/jquery/dist/jquery.js\"></script>\n<script type=\"text/javascript\" src=\"../node_modules/expect.js/index.js\"></script>\n<script type=\"text/javascript\" src=\"../node_modules/mocha/mocha.js\"></script>\n<script type=\"text/javascript\" src=\"../node_modules/lodash/dist/lodash.js\"></script>\n<script>\n    mocha.setup({\n        ui: 'bdd',\n        bail: false\n    });\n</script>\n<script src=\"../node_modules/openlayers/dist/ol.js\"></script>\n<script type=\"text/javascript\" src=\"../src/ol3-layerswitcher.js\"></script>\n<script type=\"text/javascript\" src=\"spec/ol3-layerswitcher.js\"></script>\n<script type=\"text/javascript\" src=\"spec/twomaps.js\"></script>\n<script>\n    mocha.run();\n</script>\n</body>\n</html>\n\n"
  },
  {
    "path": "test/spec/ol3-layerswitcher.js",
    "content": "describe('ol.control.LayerSwitcher', function() {\n    var map, target, switcher;\n\n    beforeEach(function() {\n        target = document.createElement('div');\n        document.body.appendChild(target);\n        switcher = new ol.control.LayerSwitcher();\n        map = new ol.Map({\n            target: target,\n            layers: [\n                new ol.layer.Group({\n                    title: 'Base',\n                    layers: [\n                        new ol.layer.Tile({\n                            title: 'Foo',\n                            type: 'base',\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        }),\n                        new ol.layer.Tile({\n                            title: 'Too',\n                            type: 'base',\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        })\n                    ]\n                }),\n                // Combined base group\n                new ol.layer.Group({\n                    title: 'Combined-Base-Group',\n                    type: 'base',\n                    combine: true,\n                    layers: [\n                        new ol.layer.Tile({\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        }),\n                        new ol.layer.Tile({\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        })\n                    ]\n                }),\n                // Combined overlay group\n                new ol.layer.Group({\n                    title: 'Combined-Overlay-Group',\n                    type: 'overlay',\n                    combine: true,\n                    layers: [\n                        new ol.layer.Tile({\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        }),\n                        new ol.layer.Tile({\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        })\n                    ]\n                }),\n                // Group with no title (group and it's children should be ignored)\n                new ol.layer.Group({\n                    layers: [\n                        new ol.layer.Tile({\n                            title: 'Never shown',\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        }),\n                        new ol.layer.Tile({\n                            source: new ol.source.TileDebug({\n                                projection: 'EPSG:3857',\n                                tileGrid: ol.tilegrid.createXYZ({\n                                    maxZoom: 22\n                                })\n                            })\n                        })\n                    ]\n                }),\n                new ol.layer.Tile({\n                    title: 'Bar',\n                    minResolution: 1000,\n                    maxResolution: 5000,\n                    source: new ol.source.TileDebug({\n                        projection: 'EPSG:3857',\n                        tileGrid: ol.tilegrid.createXYZ({\n                            maxZoom: 22\n                        })\n                    })\n                }),\n                // Layer with no title (should be ignored)\n                new ol.layer.Tile({\n                    source: new ol.source.TileDebug({\n                        projection: 'EPSG:3857',\n                        tileGrid: ol.tilegrid.createXYZ({\n                            maxZoom: 22\n                        })\n                    })\n                })\n            ],\n            controls: [switcher]\n        });\n    });\n\n    afterEach(function() {\n        document.body.removeChild(target);\n        switcher = null;\n        map = null;\n        target = null;\n    });\n\n    describe('DOM creation', function() {\n        it('creates the expected DOM elements', function() {\n            expect(jQuery('.layer-switcher').length).to.be(1);\n        });\n    });\n\n    describe('Show and hide', function() {\n        it('is initially hidden', function() {\n            expect(jQuery('.layer-switcher').hasClass('.shown')).to.be(false);\n            expect(jQuery('.layer-switcher .panel:visible').length).to.be(0);\n        });\n        it('is shown on button click', function() {\n            jQuery('.layer-switcher button').click();\n            expect(jQuery('.layer-switcher.shown').length).to.be(1);\n            expect(jQuery('.layer-switcher .panel:visible').length).to.be(1);\n        });\n        it('is hidden on map click', function() {\n            jQuery('#map').click();\n            expect(jQuery('.layer-switcher').hasClass('.shown')).to.be(false);\n            expect(jQuery('.layer-switcher .panel:visible').length).to.be(0);\n        });\n    });\n\n    describe('Layer list', function() {\n        it('displays all layers with a title in reverse order', function() {\n            switcher.showPanel();\n            var titles = jQuery('.layer-switcher label').map(function() {\n                return jQuery(this).text();\n            }).get();\n            expect(titles).to.eql(['Bar', 'Combined-Overlay-Group', 'Combined-Base-Group', 'Base', 'Too', 'Foo']);\n        });\n        it('only displays layers with a title', function() {\n            switcher.showPanel();\n            var elmTitles = jQuery('.layer-switcher label').map(function() {\n                return jQuery(this).text();\n            }).get();\n            var lyrsWithTitle = shownLyrs(map.getLayerGroup());\n            expect(lyrsWithTitle.length).to.eql(elmTitles.length);\n        });\n        it('don\\'t display layers without a title', function() {\n            switcher.showPanel();\n            // This is basically to ensure that our test layers include layers without a title\n            var lyrsWithoutTitle = _.filter(allLyrs(map.getLayerGroup()), function(lyr) {return !lyr.get('title')});\n            expect(lyrsWithoutTitle.length).not.to.equal(0);\n        });\n        it('displays normal layers as checkbox', function() {\n            switcher.showPanel();\n            var titles = jQuery('.layer-switcher input[type=checkbox]').siblings('label').map(function() {\n                return jQuery(this).text();\n            }).get();\n            expect(titles).to.eql(['Bar', 'Combined-Overlay-Group']);\n        });\n        it('greys out normal layer title labels when outside of layer resolution', function() {\n            map.getView().setResolution(6000);\n            switcher.showPanel();\n            var layerResTooHigh = jQuery('.layer-switcher label.disabled').map(function() {\n                return jQuery(this).text();\n            }).get();\n            map.getView().setResolution(500);\n            var layerResTooLow = jQuery('.layer-switcher label.disabled').map(function() {\n                return jQuery(this).text();\n            }).get();\n            expect([layerResTooHigh, layerResTooLow]).to.eql([['Bar'], ['Bar']]);\n        });\n        it('displays base layers as radio buttons', function() {\n            switcher.showPanel();\n            var titles = jQuery('.layer-switcher input[type=radio]').siblings('label').map(function() {\n                return jQuery(this).text();\n            }).get();\n            expect(titles).to.eql(['Combined-Base-Group', 'Too', 'Foo']);\n        });\n        it('should display uncombined groups without an input', function() {\n            switcher.showPanel();\n            var groups = jQuery('.layer-switcher label:not([for])')\n            var titles = groups.map(function() {\n                return jQuery(this).text();\n            }).get();\n            expect(titles).to.eql(['Base']);\n            expect(groups.siblings('input').length).to.be(0);\n        });\n        it('should display combined groups with an input', function () {\n            switcher.showPanel();\n            var titles = jQuery('.layer-switcher label[for]').map(function() {\n                return jQuery(this).text();\n            }).get();\n            expect(titles).to.contain('Combined-Base-Group');\n            expect(titles).to.contain('Combined-Overlay-Group');\n        });\n        it('should display combined groups without sub layers', function () {\n            switcher.showPanel();\n            var groups = jQuery('.layer-switcher label[for]')\n            expect(groups.siblings('ul').length).to.be(0);\n        });\n    });\n\n    describe('Overlay layer visibility', function() {\n        it('Toggles overlay layer visibility on click', function() {\n            switcher.showPanel();\n            var bar = getLayerByTitle('Bar');\n            bar.setVisible(true);\n            jQuery('.layer-switcher label:contains(\"Bar\")').siblings('input').click();\n            expect(bar.getVisible()).to.be(false);\n            expect(jQuery('.layer-switcher label:contains(\"Bar\")').siblings('input').get(0).checked).to.be(bar.getVisible());\n            bar.setVisible(false)\n            jQuery('.layer-switcher label:contains(\"Bar\")').siblings('input').click();\n            expect(bar.getVisible()).to.be(true);\n            expect(jQuery('.layer-switcher label:contains(\"Bar\")').siblings('input').get(0).checked).to.be(bar.getVisible());\n        });\n    });\n\n    describe('Base layer visibility', function() {\n        it('Only one base layer is visible after renderPanel', function() {\n            var foo = getLayerByTitle('Foo');\n            var too = getLayerByTitle('Too');\n            var cbg = getLayerByTitle('Combined-Base-Group');\n            var baseLayers = [foo, too, cbg];\n            // Enable all base layers\n            _.forEach(baseLayers, function (l) {\n                l.setVisible(true);\n            });\n\n            switcher.renderPanel();\n            var visibleBaseLayerCount = _.countBy(baseLayers, function (l){\n                return l.getVisible();\n            });\n            expect(visibleBaseLayerCount.true).to.be(1);\n        });\n        it('Only top most base layer is visible after renderPanel if more than one is visible', function() {\n            var foo = getLayerByTitle('Foo');\n            var too = getLayerByTitle('Too');\n            var cbg = getLayerByTitle('Combined-Base-Group');\n            var baseLayers = [foo, too, cbg];\n            // Enable all base layers\n            _.forEach(baseLayers, function (l) {\n                l.setVisible(true);\n            });\n            switcher.renderPanel();\n            expect(cbg.getVisible()).to.be(true);\n        });\n        it('Clicking on unchecked base layer shows it', function() {\n            var too = getLayerByTitle('Too');\n            too.setVisible(false);\n            switcher.renderPanel();\n            jQuery('.layer-switcher label:contains(\"Too\")').siblings('input').click();\n            expect(too.getVisible()).to.be(true);\n            expect(jQuery('.layer-switcher label:contains(\"Too\")').siblings('input').get(0).checked).to.be(true);\n        });\n        it('Clicking on checked base layer does not change base layer', function() {\n            var foo = getLayerByTitle('Foo');\n            foo.setVisible(true);\n            switcher.renderPanel();\n            jQuery('.layer-switcher label:contains(\"Foo\")').siblings('input').click();\n            expect(foo.getVisible()).to.be(true);\n            expect(jQuery('.layer-switcher label:contains(\"Foo\")').siblings('input').get(0).checked).to.be(true);\n        });\n    });\n\n    describe('Removes cleanly', function() {\n        it('Removes cleanly when ol.Map#removeControl is called', function() {\n            map.removeControl(switcher);\n        });\n    });\n\n    /**\n     * Returns the title of a given layer or null if lyr is falsey\n     */\n    function lyrTitle(lyr) {\n        return (lyr) ? lyr.get('title') : null;\n    }\n\n    /**\n     * Returns the Layer instance that has the given title\n     */\n    function getLayerByTitle(title) {\n        var layer = null;\n        ol.control.LayerSwitcher.forEachRecursive(map, function(lyr) {\n            if (lyr.get('title') && lyr.get('title') === title) {\n                layer = lyr;\n                return;\n            }\n        });\n        return layer;\n    }\n\n    /**\n     * Return a flattened Array of all layers regardless including those not\n     * shown by the LayerSwitcher\n     */\n    function allLyrs(lyrs) {\n        return flatten(lyrs, function (lyr) {\n            return (lyr.getLayers) ? lyr.getLayers().getArray() : lyr;\n        });\n    }\n\n    /**\n     * Return a flattened Array of only those layers that the LayerSwitcher\n     * should show\n     */\n    function shownLyrs(lyrs) {\n        // Pass in the Array from the root LayerGroup as it doesn't have a\n        // title but we don't want to filter out all layers\n        lyrs = lyrs.getLayers().getArray();\n        var flat = flatten(lyrs, function (lyr) {\n            // Return a Groups layer array only if the group has a title\n            // otherwise just return the group so that it's children will be\n            // skipped\n            return (lyr.getLayers && lyr.get('title')) ? lyr.getLayers().getArray() : lyr;\n        });\n        // Only return layers with a title\n        return _.filter(flat, lyrTitle);\n    }\n\n    /**\n     * Flattens a given nested collection using the provided function getArray\n     * to get an Array of the collections children.\n     */\n    function flatten(srcCollection, getArray) {\n        getArray = getArray || function (item) {return item};\n        var src = getArray(srcCollection),\n            dest = [];\n        for (var i = 0, item; i < src.length; i++) {\n            item = src[i];\n            dest = dest.concat(item);\n            if (_.isArray(getArray(item))) {\n                dest = dest.concat(flatten(item, getArray));\n            }\n        }\n        return dest;\n    }\n\n});\n"
  },
  {
    "path": "test/spec/twomaps.js",
    "content": "describe('ol.control.LayerSwitcher - Two maps', function() {\n    var map1, map2, target1, target2, switcher1, switcher2;\n\n    beforeEach(function() {\n        target1 = document.createElement('div');\n        target1.id = 'map1';\n        document.body.appendChild(target1);\n        target2 = document.createElement('div');\n        target2.id = 'map2';\n        document.body.appendChild(target2);\n        switcher1 = new ol.control.LayerSwitcher();\n        switcher2 = new ol.control.LayerSwitcher();\n        map1 = new ol.Map({\n            target: target1,\n            layers: [\n                new ol.layer.Group({\n                title: 'Base',\n                layers: [\n                    new ol.layer.Tile({\n                        title: 'Foo',\n                        type: 'base',\n                        source: new ol.source.TileDebug({\n                            projection: 'EPSG:3857',\n                            tileGrid: ol.tilegrid.createXYZ({\n                                maxZoom: 22\n                            })\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Too',\n                        type: 'base',\n                        source: new ol.source.TileDebug({\n                            projection: 'EPSG:3857',\n                            tileGrid: ol.tilegrid.createXYZ({\n                                maxZoom: 22\n                            })\n                        })\n                    })\n                ]\n            }),\n            new ol.layer.Tile({\n                title: 'Bar',\n                source: new ol.source.TileDebug({\n                    projection: 'EPSG:3857',\n                    tileGrid: ol.tilegrid.createXYZ({\n                        maxZoom: 22\n                    })\n                })\n            }),\n            ],\n            controls: [switcher1]\n        });\n        map2 = new ol.Map({\n            target: target2,\n            layers: [\n                new ol.layer.Group({\n                title: 'Base',\n                layers: [\n                    new ol.layer.Tile({\n                        title: 'Foo',\n                        type: 'base',\n                        source: new ol.source.TileDebug({\n                            projection: 'EPSG:3857',\n                            tileGrid: ol.tilegrid.createXYZ({\n                                maxZoom: 22\n                            })\n                        })\n                    }),\n                    new ol.layer.Tile({\n                        title: 'Too',\n                        type: 'base',\n                        source: new ol.source.TileDebug({\n                            projection: 'EPSG:3857',\n                            tileGrid: ol.tilegrid.createXYZ({\n                                maxZoom: 22\n                            })\n                        })\n                    })\n                ]\n            }),\n            new ol.layer.Tile({\n                title: 'Bar',\n                source: new ol.source.TileDebug({\n                    projection: 'EPSG:3857',\n                    tileGrid: ol.tilegrid.createXYZ({\n                        maxZoom: 22\n                    })\n                })\n            }),\n            ],\n            controls: [switcher2]\n        });\n    });\n\n    afterEach(function() {\n        document.body.removeChild(target1);\n        document.body.removeChild(target2);\n        target1 = null;\n        target2 = null;\n        switcher1 = null;\n        switcher2 = null;\n        map1 = null;\n        map2 = null;\n    });\n\n    describe('Layer IDs are unique', function() {\n        it('Inputs for layers with the same title in different maps will have different IDs', function() {\n            switcher1.showPanel();\n            switcher2.showPanel();\n            var bar1Id = jQuery('#map1 .layer-switcher label:contains(\"Bar\")').siblings('input').attr('id');\n            var bar2Id = jQuery('#map2 .layer-switcher label:contains(\"Bar\")').siblings('input').attr('id');\n            expect(bar1Id).to.not.equal(bar2Id);\n        });\n    });\n\n    /**\n     * Returns the Layer instance that has the given title\n     */\n    function getLayerByTitle(map, title) {\n        var layer = null;\n        ol.control.LayerSwitcher.forEachRecursive(map, function(lyr) {\n            if (lyr.get('title') && lyr.get('title') === title) {\n                layer = lyr;\n                return;\n            }\n        });\n        return layer;\n    }\n\n});\n"
  },
  {
    "path": "util/README.md",
    "content": "# OpenLayers LayerSwitcher\n\nGrouped layer list control for an OpenLayer v3/v4 map.\n\nAll 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.\n\n## Examples\n\nThe examples demonstrate usage and can be viewed online thanks to [RawGit](http://rawgit.com/):\n\n* [Basic usage](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/layerswitcher.html)\n    * 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.\n* [Add layer](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/addlayer.html)\n    * Add a layer to an existing layer group after the layer switcher has been added to the map.\n* [Scrolling](http://rawgit.com/walkermatt/ol3-layerswitcher/master/examples/scroll.html)\n    * 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)).\n* [Browserify](examples/browserify/)\n    * Example of using ol3-layerswitcher with Browserify (see [examples/browserify/README.md](examples/browserify/README.md) for details of building.\n\nThe source for all examples can be found in [examples](examples).\n\n## Tests\n\nTo run the tests you'll need to install the dependencies via `npm`. In the root of the repository run:\n\n    npm install\n\nThen run the tests by opening [test/index.html](test/index.html) in a browser.\n\n## API\n\n{% for class in classes -%}\n\n### `new {{ class.longname }}({{ class.signature }})`\n\n{{ class.description }}\n\n#### Parameters:\n\n|Name|Type|Description|\n|:---|:---|:----------|\n{% for param in class.params %}|`{{ param.name }}`|`{{ param.type.names[0] }}`| {{ param.description }} |{% endfor %}\n\n#### Extends\n\n`{{ class.augments }}`\n\n#### Methods\n\n{% for method in class.methods -%}\n##### `{% if method.scope == 'static' %}(static) {{ class.longname }}.{% endif %}{{ method.name }}({{ method.signature }})`\n\n{{ method.description }}\n\n{% if method.params -%}\n###### Parameters:\n\n|Name|Type|Description|\n|:---|:---|:----------|\n{% for param in method.params -%}\n|`{{ param.name }}`|`{{ param.type.names[0] }}`| {{ param.description }} |\n{% endfor %}\n\n{% endif %}\n{%- endfor %}\n{%- endfor -%}\n\n## License\n\nMIT (c) Matt Walker.\n\n## Also see\n\nIf you find the layer switcher useful you might also like the\n[ol3-popup](https://github.com/walkermatt/ol3-popup).\n"
  }
]