├── .gitignore ├── Gruntfile.js ├── README.md ├── dist ├── leaflet-panel-layers.min.css ├── leaflet-panel-layers.min.js ├── leaflet-panel-layers.src.css └── leaflet-panel-layers.src.js ├── examples ├── collapsible-panel.html ├── config-layers.json ├── custom-item.html ├── data │ ├── bar.js │ ├── caves.json │ ├── drinking_water.js │ ├── fuel.js │ ├── lakes.json │ ├── parking.js │ └── river.json ├── dynamic-layers.html ├── embedded-layers.html ├── group-layers-exclusive.html ├── group-layers-selector-group.html ├── group-layers.html ├── icon-layer.html ├── icons.css ├── images │ ├── icons │ │ ├── bar.png │ │ ├── drinking_water.png │ │ ├── fuel.png │ │ └── parking.png │ ├── leaflet-panel.png │ ├── markers │ │ ├── bar.png │ │ ├── drinking_water.png │ │ ├── fuel.png │ │ └── parking.png │ └── screenshot │ │ ├── imagen.png │ │ └── leaflet-panel-layers-layout.jpg ├── layer-thumbnails.html ├── multiple-panels.html └── style.css ├── index.html ├── license.txt ├── package.json └── src ├── leaflet-panel-layers.css └── leaflet-panel-layers.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (https://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | # parcel-bundler cache (https://parceljs.org/) 65 | .cache 66 | 67 | # next.js build output 68 | .next 69 | 70 | # nuxt.js build output 71 | .nuxt 72 | 73 | # vuepress build output 74 | .vuepress/dist 75 | 76 | # Serverless directories 77 | .serverless 78 | 79 | 80 | # End of https://www.gitignore.io/api/node 81 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(grunt) { 4 | 5 | grunt.loadNpmTasks('grunt-contrib-uglify'); 6 | grunt.loadNpmTasks('grunt-contrib-concat'); 7 | grunt.loadNpmTasks('grunt-contrib-clean'); 8 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 9 | grunt.loadNpmTasks('grunt-contrib-jshint'); 10 | grunt.loadNpmTasks('grunt-contrib-watch'); 11 | grunt.loadNpmTasks('grunt-banner'); 12 | 13 | grunt.initConfig({ 14 | pkg: grunt.file.readJSON('package.json'), 15 | meta: { 16 | banner: 17 | '/*! @preserve\n'+ 18 | ' * Leaflet Panel Layers v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n'+ 19 | ' *\n'+ 20 | ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>\n'+ 21 | ' * <%= pkg.author.email %>\n'+ 22 | ' * <%= pkg.author.url %>\n'+ 23 | ' *\n'+ 24 | ' * Licensed under the <%= pkg.license %> license.\n'+ 25 | ' *\n'+ 26 | ' * Demos:\n'+ 27 | ' * <%= pkg.homepage %>\n'+ 28 | ' *\n'+ 29 | ' * Source:\n'+ 30 | ' * <%= pkg.repository.url %>\n'+ 31 | ' */\n' 32 | }, 33 | clean: { 34 | dist: { 35 | src: ['dist/*'] 36 | } 37 | }, 38 | jshint: { 39 | options: { 40 | globals: { 41 | console: true, 42 | module: true, 43 | }, 44 | }, 45 | files: ['src/*.js'] 46 | }, 47 | concat: { 48 | //TODO cut out SearchMarker 49 | options: { 50 | banner: '<%= meta.banner %>' 51 | }, 52 | dist: { 53 | files: { 54 | 'dist/leaflet-panel-layers.src.js': ['src/leaflet-panel-layers.js'], 55 | 'dist/leaflet-panel-layers.src.css': ['src/leaflet-panel-layers.css'] 56 | } 57 | } 58 | }, 59 | uglify: { 60 | dist: { 61 | files: { 62 | 'dist/leaflet-panel-layers.min.js': ['dist/leaflet-panel-layers.src.js'] 63 | } 64 | } 65 | }, 66 | cssmin: { 67 | combine: { 68 | files: { 69 | 'dist/leaflet-panel-layers.min.css': ['src/leaflet-panel-layers.css'] 70 | } 71 | }, 72 | minify: { 73 | expand: true, 74 | cwd: 'dist/', 75 | files: { 76 | 'dist/leaflet-panel-layers.min.css': ['src/leaflet-panel-layers.css'] 77 | } 78 | } 79 | }, 80 | usebanner: { 81 | options: { 82 | position: 'top', 83 | linebreak: false 84 | }, 85 | css: { 86 | options: { 87 | banner: '<%= meta.banner %>' 88 | }, 89 | files: { 90 | src: 'dist/leaflet-panel-layers.min.css' 91 | } 92 | }, 93 | js: { 94 | options: { 95 | banner: '<%= meta.banner %>' 96 | }, 97 | files: { 98 | src: 'dist/leaflet-panel-layers.min.js' 99 | } 100 | } 101 | }, 102 | watch: { 103 | dist: { 104 | options: { livereload: true }, 105 | files: ['src/*','examples/*'], 106 | tasks: ['clean','concat','cssmin','jshint'] 107 | } 108 | } 109 | }); 110 | 111 | grunt.registerTask('default', [ 112 | 'clean', 113 | 'concat', 114 | 'cssmin', 115 | 'usebanner:css', 116 | 'jshint', 117 | 'uglify', 118 | 'usebanner:js' 119 | ]); 120 | 121 | }; 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Leaflet Panel Layers 2 | ============== 3 | 4 | [![npm version](https://badge.fury.io/js/leaflet-panel-layers.svg)](https://badge.fury.io/js/leaflet-panel-layers) 5 | 6 | Leaflet Control Layers extended with support groups and icons 7 | 8 | Copyright [Stefano Cudini](https://opengeo.tech/stefano-cudini/) 9 | 10 | If this project helped your work help me to keep this alive by [Paypal **DONATION ❤**](https://www.paypal.me/stefanocudini) 11 | 12 | Tested in Leaflet v1.6.x 13 | 14 | **Demo:** 15 | 16 | [opengeo.tech/maps/leaflet-panel-layers](https://opengeo.tech/maps/leaflet-panel-layers/) 17 | 18 | **Source code:** 19 | 20 | [Github](https://github.com/stefanocudini/leaflet-panel-layers) 21 | 22 | ### Use Cases: 23 | 24 | * [Interactive tool by researchers from the Australian Antarctic Division](https://nilas.org/) 25 | * [EnviroMap by EnvironSensing](https://dev-server.uca.es/) 26 | * [Leaflet Control Search (Official demos)](https://opengeo.tech/maps/leaflet-search/) 27 | * [Pine Interactive Map](https://pine.blackpinguin.de/) 28 | 29 | ![Image](https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/master/examples/images/screenshot/leaflet-panel-layers-layout.jpg) 30 | 31 | # Options 32 | | Option | Default | Description | 33 | | --------------- | -------- | ----------------------------------------- | 34 | | compact | false | panel height minor of map height | 35 | | collapsed | false | panel collapsed at startup | 36 | | autoZIndex | true | set zindex layer by order definition | 37 | | collapsibleGroups| false | groups of layers is collapsible by button | 38 | | groupCheckboxes | false | adds a checkbox to the group title to de-/select all layers in the group | 39 | | selectorGroup | false | select all layer of a group | 40 | | buildItem | null | function that return row item html node(or html string) | 41 | | title | '' | title of panel | 42 | | className | '' | additional class name for panel | 43 | | position | 'topright' | position of control | 44 | 45 | # Events 46 | | Event | Data | Description | 47 | | ---------------------- | ---------------------- | ----------------------------------------- | 48 | | 'panel:selected' | {layerDef} | fired after moved and show markerLocation | 49 | | 'panel:unselected' | {} | fired after control was expanded | 50 | 51 | # Methods 52 | | Method | Arguments | Description | 53 | | ---------------------- | --------------------- | -------------------------------------------------------- | 54 | | addBaseLayer() | layerDef,group,collapsed | add new layer item definition to panel as baselayers | 55 | | addOverlay() | 'Text message' | add new layer item definition to panel as overlay | 56 | | removeLayer() | 'Text searched' | remove layer item from panel | 57 | | configToControlLayers()| 'Text searched' | convert config from Control.PanelLayers to Control.Layers| 58 | 59 | # Usage 60 | 61 | **Panel Item Definition formats** 62 | ```javascript 63 | { 64 | name: "Bar", 65 | icon: iconByName('bar'), 66 | layer: L.geoJson(Bar, {pointToLayer: featureToMarker }) 67 | } 68 | ``` 69 | definition in JSON format permit to store simply the configuration 70 | type contains a Leaflet method in this case L.geoJson() 71 | args is the arguments passed to the method: L.geoJson(river) 72 | ```javascript 73 | { 74 | layer: { 75 | type: "geoJson", 76 | args: [ river ] 77 | }, 78 | } 79 | ``` 80 | definition of a group 81 | 82 | ```javascript 83 | { 84 | group: "Title Group", 85 | collapsed: true, 86 | layers: [ 87 | ...other items... 88 | ] 89 | } 90 | ``` 91 | 92 | **Multiple active layers with icons** 93 | ```javascript 94 | var baseLayers = [ 95 | { 96 | active: true, 97 | name: "OpenStreetMap", 98 | layer: L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png') 99 | } 100 | ]; 101 | var overLayers = [ 102 | { 103 | name: "Drinking Water", 104 | icon: '', 105 | layer: L.geoJson(WaterGeoJSON) 106 | }, 107 | { 108 | active: true, 109 | name: "Parking", 110 | icon: '', 111 | layer: L.geoJson(ParkingGeoJSON) 112 | } 113 | ]; 114 | map.addControl( new L.Control.PanelLayers(baseLayers, overLayers) ); 115 | ``` 116 | 117 | **Build panel layers from pure JSON Config** 118 | ```javascript 119 | var panelJsonConfig = { 120 | "baselayers": [ 121 | { 122 | "active": true, 123 | "name": "Open Cycle Map", 124 | "layer": { 125 | "type": "tileLayer", 126 | "args": [ 127 | "https://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png" 128 | ] 129 | } 130 | }, 131 | { 132 | "name": "Landscape", 133 | "layer": { 134 | "type": "tileLayer", 135 | "args": [ 136 | "https://{s}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png" 137 | ] 138 | } 139 | }, 140 | { 141 | "name": "Transports", 142 | "layer": { 143 | "type": "tileLayer", 144 | "args": [ 145 | "https://{s}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png" 146 | ] 147 | } 148 | } 149 | ], 150 | "overlayers": [ 151 | { 152 | "name": "Terrain", 153 | "layer": { 154 | "type": "tileLayer", 155 | "args": [ 156 | "https://toolserver.org/~cmarqu/hill/{z}/{x}/{y}.png", { 157 | "opacity": 0.5 158 | } 159 | ] 160 | } 161 | } 162 | ] 163 | }; 164 | L.control.panelLayers(panelJsonConfig.baseLayers, panelJsonConfig.overLayers).addTo(map); 165 | ``` 166 | 167 | **Grouping of layers** 168 | ```javascript 169 | L.control.panelLayers( 170 | [ 171 | { 172 | name: "Open Street Map", 173 | layer: osmLayer 174 | }, 175 | { 176 | group: "Walking layers", 177 | layers: [ 178 | { 179 | name: "Open Cycle Map", 180 | layer: L.tileLayer('https://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png') 181 | }, 182 | { 183 | name: "Hiking", 184 | layer: L.tileLayer("https://toolserver.org/tiles/hikebike/{z}/{x}/{y}.png") 185 | } 186 | ] 187 | }, 188 | { 189 | group: "Road layers", 190 | layers: [ 191 | { 192 | name: "Transports", 193 | layer: L.tileLayer("https://{s}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png") 194 | } 195 | ] 196 | } 197 | ], 198 | {collapsibleGroups: true} 199 | ).addTo(map); 200 | ``` 201 | 202 | **Collapse some layers' groups** 203 | ```javascript 204 | L.control.panelLayers([ 205 | { 206 | name: "Open Street Map", 207 | layer: osmLayer 208 | }, 209 | { 210 | group: "Walking layers", 211 | layers: [ 212 | { 213 | name: "Open Cycle Map", 214 | layer: L.tileLayer('https://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png') 215 | }, 216 | { 217 | name: "Hiking", 218 | layer: L.tileLayer("https://toolserver.org/tiles/hikebike/{z}/{x}/{y}.png") 219 | } 220 | ] 221 | }, 222 | { 223 | group: "Road layers", 224 | collapsed: true, 225 | layers: [ 226 | { 227 | name: "Transports", 228 | layer: L.tileLayer("https://{s}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png") 229 | } 230 | ] 231 | } 232 | ]).addTo(map); 233 | ``` 234 | 235 | **Add layers dynamically at runtime** 236 | ```javascript 237 | var panel = L.control.panelLayers(); 238 | 239 | $.getJSON('some/url/path.geojson', function(data){ 240 | panel.addOverlay({ 241 | name: "Drinking Water", 242 | icon: '', 243 | layer: L.geoJson(data) 244 | }); 245 | }); 246 | ``` 247 | 248 | 249 | # Build 250 | 251 | This plugin support [Grunt](https://gruntjs.com/) for building process. 252 | Therefore the deployment require [NPM](https://npmjs.org/) installed in your system. 253 | After you've made sure to have npm working, run this in command line: 254 | ```bash 255 | npm install 256 | grunt 257 | ``` 258 | -------------------------------------------------------------------------------- /dist/leaflet-panel-layers.min.css: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Leaflet Panel Layers v1.3.1 - 2022-11-18 3 | * 4 | * Copyright 2022 Stefano Cudini 5 | * stefano.cudini@gmail.com 6 | * https://opengeo.tech/ 7 | * 8 | * Licensed under the MIT license. 9 | * 10 | * Demos: 11 | * https://opengeo.tech/maps/leaflet-panel-layers/ 12 | * 13 | * Source: 14 | * git@github.com:stefanocudini/leaflet-panel-layers.git 15 | */ 16 | .leaflet-panel-layers .leaflet-panel-layers-list{display:block}.leaflet-panel-layers.expanded .leaflet-panel-layers-list{display:block}.leaflet-top.leaflet-right .leaflet-panel-layers:not(.compact){margin:0}.leaflet-panel-layers{width:30px;min-width:30px}.leaflet-panel-layers.expanded{width:auto;overflow-x:hidden;overflow-y:auto}.leaflet-panel-layers.expanded .leaflet-panel-layers-list{display:block}.leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-grouplabel,.leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-selector,.leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-title>span{display:none}.leaflet-panel-layers-separator{clear:both}.leaflet-panel-layers-item .leaflet-panel-layers-title{display:block;white-space:nowrap;float:none;cursor:pointer}.leaflet-panel-layers-title .leaflet-panel-layers-selector{float:right}.leaflet-panel-layers-group{position:relative;width:auto;height:auto;clear:both;overflow:hidden}.leaflet-panel-layers-icon{text-align:center;float:left}.leaflet-panel-layers-group.collapsible:not(.expanded){height:20px}.leaflet-panel-layers-group.collapsible:not(.expanded) .leaflet-panel-layers-grouplabel{height:20px;overflow:hidden}.leaflet-panel-layers-group.collapsible:not(.expanded) .leaflet-panel-layers-item{display:none}.leaflet-panel-layers-group.collapsible .leaflet-panel-layers-grouplabel{display:block;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.leaflet-panel-layers-item{display:block;height:auto;clear:both;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.leaflet-panel-layers-overlays .leaflet-panel-layers-item{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;width:auto;display:block}.leaflet-panel-layers-base .leaflet-panel-layers-selector{float:left}.leaflet-panel-layers-overlays .leaflet-panel-layers-selector{float:right}.leaflet-panel-layers.expanded .leaflet-panel-layers-overlays input{display:block}.leaflet-control-layers-selector{float:left}.leaflet-panel-layers-grouplabel .leaflet-panel-layers-selector{visibility:hidden;position:absolute;top:1px;right:7px}.leaflet-panel-layers-group:hover .leaflet-panel-layers-selector{visibility:visible}.leaflet-panel-layers{padding:4px;background:rgba(255,255,255,.5);box-shadow:-2px 0 8px rgba(0,0,0,.3)}.leaflet-panel-layers.expanded{padding:4px}.leaflet-panel-layers-selector{position:relative;top:1px;margin-top:2px}.leaflet-panel-layers-separator{height:8px;margin:12px 4px 0 4px;border-top:1px solid rgba(0,0,0,.3)}.leaflet-panel-layers-item{min-height:20px}.leaflet-panel-layers-margin{height:25px}.leaflet-panel-layers-icon{line-height:20px;display:inline-block;height:20px;width:20px;background:#fff}.leaflet-panel-layers-group.collapsible .leaflet-panel-layers-icon:first-child{min-width:20px;font-size:16px;text-align:center;background:0 0}.leaflet-panel-layers-group{padding:2px 4px;margin-bottom:4px;border:1px solid rgba(0,0,0,.3);background:rgba(255,255,255,.6);border-radius:3px}.leaflet-panel-layers-overlays .leaflet-panel-layers-item{margin-bottom:4px;padding:2px;background:#fff;border:1px solid rgba(0,0,0,.3);border-radius:4px}.leaflet-panel-layers-overlays .leaflet-panel-layers-item:hover{border:1px solid #888;cursor:pointer} -------------------------------------------------------------------------------- /dist/leaflet-panel-layers.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Leaflet Panel Layers v1.3.1 - 2022-11-18 3 | * 4 | * Copyright 2022 Stefano Cudini 5 | * stefano.cudini@gmail.com 6 | * https://opengeo.tech/ 7 | * 8 | * Licensed under the MIT license. 9 | * 10 | * Demos: 11 | * https://opengeo.tech/maps/leaflet-panel-layers/ 12 | * 13 | * Source: 14 | * git@github.com:stefanocudini/leaflet-panel-layers.git 15 | */ 16 | !function(e){if("function"==typeof define&&define.amd)define(["leaflet"],e);else if("undefined"!=typeof module)module.exports=e(require("leaflet"));else{if(void 0===window.L)throw"Leaflet must be loaded first";e(window.L)}}(function(l){return l.Control.PanelLayers=l.Control.Layers.extend({includes:"1"===l.version[0]?l.Evented.prototype:l.Mixin.Events,options:{compact:!1,compactOffset:0,collapsed:!1,autoZIndex:!0,collapsibleGroups:!1,selectorGroup:!1,buildItem:null,title:"",className:"",position:"topright"},initialize:function(e,t,a){var i,s,r;for(i in l.setOptions(this,a),this._layers=[],this._groups={},this._items={},this._layersActives=[],this._lastZIndex=0,this._handlingClick=!1,this.className="leaflet-panel-layers",e)if(e[i].group&&e[i].layers)for(s in r=e[i].collapsed||!1,e[i].layers)this._addLayer(e[i].layers[s],!1,e[i].group,r);else this._addLayer(e[i],!1);for(i in t)if(t[i].group&&t[i].layers)for(s in r=t[i].collapsed||!1,t[i].layers)this._addLayer(t[i].layers[s],!0,t[i].group,r);else this._addLayer(t[i],!0)},onAdd:function(e){var t,a=this;for(t in this._layersActives)e.addLayer(this._layersActives[t]);return l.Control.Layers.prototype.onAdd.call(this,e),this._map.on("resize",function(e){a._updateHeight(e.newSize.y)}),this._onInputClick(),this._container},addBaseLayer:function(e,t,a){return e.name=t||e.name||"",this._addLayer(e,!1,a),this._update(),this},addOverlay:function(e,t,a){return e.name=t||e.name||"",this._addLayer(e,!0,a),this._update(),this},removeLayer:function(e){e=e.hasOwnProperty("layer")?this._layerFromDef(e):e;return this._map.removeLayer(e),l.Control.Layers.prototype.removeLayer.call(this,e),this},clearLayers:function(){for(var e=0;e"+this.options.title+"",t.appendChild(e)),t.appendChild(this._form)},_updateHeight:function(e){e=e||this._map.getSize().y,this.options.compact?this._form.style.maxHeight=e-this.options.compactOffset+"px":this._form.style.height=e+"px"},_expand:function(){l.DomUtil.addClass(this._container,"expanded")},_collapse:function(){this._container.className=this._container.className.replace("expanded","")},_getPath:function(e,t){var a=t.split("."),t=a.pop(),i=a.length,s=a[0],r=1;if(0 span, 39 | .leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-selector, 40 | .leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-grouplabel { 41 | display: none; 42 | } 43 | .leaflet-panel-layers-separator { 44 | clear: both; 45 | } 46 | 47 | .leaflet-panel-layers-item .leaflet-panel-layers-title { 48 | display: block; 49 | white-space: nowrap; 50 | float: none; 51 | cursor: pointer; 52 | } 53 | .leaflet-panel-layers-title .leaflet-panel-layers-selector { 54 | float: right; 55 | } 56 | 57 | .leaflet-panel-layers-group { 58 | position: relative; 59 | width: auto; 60 | height: auto; 61 | clear: both; 62 | overflow: hidden; 63 | } 64 | .leaflet-panel-layers-icon { 65 | text-align: center; 66 | float: left; 67 | } 68 | .leaflet-panel-layers-group.collapsible:not(.expanded) { 69 | height: 20px; 70 | } 71 | .leaflet-panel-layers-group.collapsible:not(.expanded) .leaflet-panel-layers-grouplabel { 72 | height: 20px; 73 | overflow: hidden; 74 | } 75 | .leaflet-panel-layers-group.collapsible:not(.expanded) .leaflet-panel-layers-item { 76 | display: none; 77 | } 78 | .leaflet-panel-layers-group.collapsible .leaflet-panel-layers-grouplabel { 79 | display: block; 80 | cursor: pointer; 81 | -webkit-touch-callout: none; 82 | -webkit-user-select: none; 83 | -khtml-user-select: none; 84 | -moz-user-select: none; 85 | -ms-user-select: none; 86 | user-select: none; 87 | } 88 | .leaflet-panel-layers-item { 89 | display: block; 90 | height: auto; 91 | clear: both; 92 | white-space: nowrap; 93 | -webkit-touch-callout: none; 94 | -webkit-user-select: none; 95 | -khtml-user-select: none; 96 | -moz-user-select: none; 97 | -ms-user-select: none; 98 | user-select: none; 99 | } 100 | .leaflet-panel-layers-overlays .leaflet-panel-layers-item { 101 | white-space: pre-wrap; 102 | white-space: -moz-pre-wrap; 103 | white-space: -pre-wrap; 104 | white-space: -o-pre-wrap; 105 | word-wrap: break-word; 106 | width: auto; 107 | display: block; 108 | } 109 | .leaflet-panel-layers-base .leaflet-panel-layers-selector { 110 | float: left; 111 | } 112 | .leaflet-panel-layers-overlays .leaflet-panel-layers-selector { 113 | float: right; 114 | } 115 | .leaflet-panel-layers.expanded .leaflet-panel-layers-overlays input { 116 | display: block; 117 | } 118 | .leaflet-control-layers-selector { 119 | float: left; 120 | } 121 | 122 | .leaflet-panel-layers-grouplabel .leaflet-panel-layers-selector { 123 | visibility: hidden; 124 | position: absolute; 125 | top: 1px; 126 | right: 7px; 127 | } 128 | 129 | .leaflet-panel-layers-group:hover .leaflet-panel-layers-selector { 130 | visibility: visible; 131 | } 132 | 133 | 134 | 135 | /* theming style */ 136 | 137 | .leaflet-panel-layers { 138 | padding: 4px; 139 | background: rgba(255,255,255,0.5); 140 | box-shadow: -2px 0 8px rgba(0,0,0,0.3); 141 | } 142 | .leaflet-panel-layers.expanded { 143 | padding: 4px; 144 | } 145 | .leaflet-panel-layers-selector { 146 | position: relative; 147 | top: 1px; 148 | margin-top: 2px; 149 | } 150 | .leaflet-panel-layers-separator { 151 | height: 8px; 152 | margin: 12px 4px 0 4px; 153 | border-top:1px solid rgba(0,0,0,0.3); 154 | } 155 | .leaflet-panel-layers-item { 156 | min-height: 20px; 157 | } 158 | .leaflet-panel-layers-margin { 159 | height: 25px; 160 | } 161 | .leaflet-panel-layers-icon { 162 | line-height: 20px; 163 | display: inline-block; 164 | height: 20px; 165 | width: 20px; 166 | background: #fff; 167 | } 168 | .leaflet-panel-layers-group.collapsible .leaflet-panel-layers-icon:first-child { 169 | min-width: 20px; 170 | font-size: 16px; 171 | text-align: center; 172 | background: none; 173 | } 174 | .leaflet-panel-layers-group { 175 | padding: 2px 4px; 176 | margin-bottom: 4px; 177 | border: 1px solid rgba(0,0,0,0.3); 178 | background: rgba(255,255,255,0.6); 179 | border-radius: 3px; 180 | } 181 | .leaflet-panel-layers-overlays .leaflet-panel-layers-item { 182 | margin-bottom: 4px; 183 | padding: 2px; 184 | background: #fff; 185 | border: 1px solid rgba(0,0,0,0.3); 186 | border-radius: 4px; 187 | } 188 | .leaflet-panel-layers-overlays .leaflet-panel-layers-item:hover { 189 | border: 1px solid #888; 190 | cursor: pointer; 191 | } 192 | -------------------------------------------------------------------------------- /dist/leaflet-panel-layers.src.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Leaflet Panel Layers v1.3.1 - 2022-11-18 3 | * 4 | * Copyright 2022 Stefano Cudini 5 | * stefano.cudini@gmail.com 6 | * https://opengeo.tech/ 7 | * 8 | * Licensed under the MIT license. 9 | * 10 | * Demos: 11 | * https://opengeo.tech/maps/leaflet-panel-layers/ 12 | * 13 | * Source: 14 | * git@github.com:stefanocudini/leaflet-panel-layers.git 15 | */ 16 | (function (factory) { 17 | if (typeof define === 'function' && define.amd) { 18 | //AMD 19 | define(['leaflet'], factory); 20 | } else if (typeof module !== 'undefined') { 21 | // Node/CommonJS 22 | module.exports = factory(require('leaflet')); 23 | } else { 24 | // Browser globals 25 | if (typeof window.L === 'undefined') 26 | throw 'Leaflet must be loaded first'; 27 | factory(window.L); 28 | } 29 | })(function (L) { 30 | 31 | L.Control.PanelLayers = L.Control.Layers.extend({ 32 | 33 | includes: L.version[0]==='1' ? L.Evented.prototype : L.Mixin.Events, 34 | 35 | options: { 36 | compact: false, 37 | compactOffset: 0, 38 | collapsed: false, 39 | autoZIndex: true, 40 | collapsibleGroups: false, 41 | selectorGroup: false, //select all layer of a group 42 | buildItem: null, //function that return row item html node(or html string) 43 | title: '', //title of panel 44 | className: '', //additional class name for panel 45 | position: 'topright' 46 | }, 47 | 48 | initialize: function (baseLayers, overlays, options) { 49 | L.setOptions(this, options); 50 | this._layers = []; 51 | this._groups = {}; 52 | this._items = {}; 53 | this._layersActives = []; 54 | this._lastZIndex = 0; 55 | this._handlingClick = false; 56 | 57 | this.className = 'leaflet-panel-layers'; 58 | 59 | var i, n, isCollapsed; 60 | 61 | for (i in baseLayers) { 62 | if (baseLayers[i].group && baseLayers[i].layers) { 63 | isCollapsed = baseLayers[i].collapsed || false; 64 | for (n in baseLayers[i].layers) 65 | this._addLayer(baseLayers[i].layers[n], false, baseLayers[i].group, isCollapsed); 66 | } 67 | else 68 | this._addLayer(baseLayers[i], false); 69 | } 70 | 71 | for (i in overlays) { 72 | if (overlays[i].group && overlays[i].layers) { 73 | isCollapsed = overlays[i].collapsed || false; 74 | for (n in overlays[i].layers) 75 | this._addLayer(overlays[i].layers[n], true, overlays[i].group, isCollapsed); 76 | } 77 | else 78 | this._addLayer(overlays[i], true); 79 | } 80 | }, 81 | 82 | onAdd: function (map) { 83 | 84 | var self = this; 85 | 86 | for (var i in this._layersActives) { 87 | map.addLayer(this._layersActives[i]); 88 | } 89 | 90 | L.Control.Layers.prototype.onAdd.call(this, map); 91 | 92 | this._map.on('resize', function(e) { 93 | self._updateHeight(e.newSize.y); 94 | }); 95 | 96 | // update group checkboxes 97 | this._onInputClick(); 98 | 99 | return this._container; 100 | }, 101 | 102 | //TODO addBaseLayerGroup 103 | //TODO addOverlayGroup 104 | 105 | addBaseLayer: function (layer, name, group) { 106 | layer.name = name || layer.name || ''; 107 | this._addLayer(layer, false, group); 108 | this._update(); 109 | return this; 110 | }, 111 | 112 | addOverlay: function (layer, name, group) { 113 | layer.name = name || layer.name || ''; 114 | this._addLayer(layer, true, group); 115 | this._update(); 116 | return this; 117 | }, 118 | 119 | removeLayer: function (layerDef) { 120 | var layer = layerDef.hasOwnProperty('layer') ? this._layerFromDef(layerDef) : layerDef; 121 | 122 | this._map.removeLayer(layer); 123 | 124 | L.Control.Layers.prototype.removeLayer.call(this, layer); 125 | return this; 126 | }, 127 | 128 | clearLayers: function () { 129 | for (var i = 0; i < this._layers.length; i++) { 130 | this.removeLayer(this._layers[i]); 131 | } 132 | }, 133 | 134 | _layerFromDef: function (layerDef) { 135 | for (var i = 0; i < this._layers.length; i++) { 136 | var id = L.stamp(this._layers[i].layer); 137 | //TODO add more conditions to comparing definitions 138 | if (this._getLayer(id).name === layerDef.name) 139 | return this._getLayer(id).layer; 140 | } 141 | }, 142 | 143 | _update: function () { 144 | this._groups = {}; 145 | this._items = {}; 146 | L.Control.Layers.prototype._update.call(this); 147 | }, 148 | 149 | _getLayer: function (id) { 150 | for (var i = 0; i < this._layers.length; i++) { 151 | if (this._layers[i] && this._layers[i].id == id) { 152 | return this._layers[i]; 153 | } 154 | } 155 | }, 156 | 157 | _addLayer: function (layerDef, overlay, group, isCollapsed) { 158 | 159 | if(!layerDef.layer) 160 | throw new Error('layer not defined in item: '+(layerDef.name||'')); 161 | 162 | if (!(layerDef.layer instanceof L.Class) && 163 | (layerDef.layer.type && layerDef.layer.args)) { 164 | layerDef.layer = this._getPath(L, layerDef.layer.type).apply(L, layerDef.layer.args); 165 | } 166 | 167 | if(!layerDef.hasOwnProperty('id')) 168 | layerDef.id = L.stamp(layerDef.layer); 169 | 170 | if(layerDef.active) 171 | this._layersActives.push(layerDef.layer); 172 | 173 | this._layers.push(L.Util.extend(layerDef, { 174 | collapsed: isCollapsed, 175 | overlay: overlay, 176 | group: group 177 | })); 178 | 179 | if (this.options.autoZIndex && layerDef.layer && layerDef.layer.setZIndex) { 180 | this._lastZIndex++; 181 | layerDef.layer.setZIndex(this._lastZIndex); 182 | } 183 | 184 | }, 185 | 186 | _createItem: function (obj) { 187 | 188 | var self = this; 189 | 190 | var item, input, checked; 191 | 192 | item = L.DomUtil.create('div', this.className + '-item' + (obj.active ? ' active' : '')); 193 | 194 | checked = this._map.hasLayer(obj.layer); 195 | 196 | if (obj.overlay) { 197 | if (typeof obj.exclusiveGroup !== "undefined"){ 198 | input = this._createRadioElement(obj.exclusiveGroup.replace('', '_'), checked, obj); 199 | }else{ 200 | input = L.DomUtil.create('input', this.className + '-selector'); 201 | input.type = 'checkbox'; 202 | input.defaultChecked = checked; 203 | }//TODO name 204 | } else 205 | input = this._createRadioElement('leaflet-base-layers', checked, obj); 206 | 207 | input.value = obj.id; 208 | input.layerId = obj.id; 209 | input.id = obj.id; 210 | input._layer = obj; 211 | 212 | L.DomEvent.on(input, 'click', function (e) { 213 | 214 | self._onInputClick(); 215 | 216 | if (e.target.checked) { 217 | self.fire('panel:selected', e.target._layer); 218 | } else { 219 | self.fire('panel:unselected', e.target._layer); 220 | } 221 | 222 | }, this); 223 | 224 | var label = L.DomUtil.create('label', this.className + '-title'); 225 | //TODO label.htmlFor = input.id; 226 | var title = L.DomUtil.create('span'); 227 | title.innerHTML = obj.name || ''; 228 | 229 | if (obj.icon) { 230 | var icon = L.DomUtil.create('i', this.className + '-icon'); 231 | 232 | if (typeof obj.icon === 'string') 233 | icon.innerHTML = obj.icon || ''; 234 | else 235 | icon.appendChild(obj.icon); 236 | 237 | label.appendChild(icon); 238 | } 239 | 240 | label.appendChild(input); 241 | label.appendChild(title); 242 | item.appendChild(label); 243 | 244 | if (this.options.buildItem) { 245 | var node = this.options.buildItem.call(this, obj); //custom node node or html string 246 | if (typeof node === 'string') { 247 | var tmp = L.DomUtil.create('div'); 248 | tmp.innerHTML = node; 249 | item.appendChild(tmp.firstChild); 250 | } 251 | else 252 | item.appendChild(node); 253 | } 254 | 255 | this._items[input.value] = item; 256 | 257 | return item; 258 | }, 259 | 260 | // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) 261 | _createRadioElement: function (name, checked, obj) { 262 | 263 | var radioHtml = '= 0.5; 471 | } 472 | } 473 | 474 | this._refocusOnMap(); 475 | }, 476 | 477 | 478 | _initLayout: function () { 479 | var container = this._container = L.DomUtil.create('div', this.className); 480 | 481 | if(this.options.compact) 482 | L.DomUtil.addClass(container, 'compact'); 483 | 484 | //Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released 485 | container.setAttribute('aria-haspopup', true); 486 | 487 | L.DomEvent 488 | .disableClickPropagation(container) 489 | .disableScrollPropagation(container); 490 | 491 | if (this.options.className) 492 | L.DomUtil.addClass(container, this.options.className); 493 | 494 | this._section = this._form = L.DomUtil.create('form', this.className + '-list'); 495 | 496 | this._updateHeight(); 497 | 498 | if (this.options.collapsed) { 499 | 500 | if (L.Browser.android) 501 | L.DomEvent 502 | .on(container, 'click', this._expand, this); 503 | else { 504 | L.DomEvent 505 | .on(container, 'mouseenter', this._expand, this) 506 | .on(container, 'mouseleave', this._collapse, this); 507 | } 508 | 509 | this._map.on('click', this._collapse, this); 510 | 511 | } else { 512 | this._expand(); 513 | } 514 | 515 | this._baseLayersList = L.DomUtil.create('div', this.className + '-base', this._form); 516 | this._separator = L.DomUtil.create('div', this.className + '-separator', this._form); 517 | this._overlaysList = L.DomUtil.create('div', this.className + '-overlays', this._form); 518 | 519 | /* maybe useless 520 | if (!this.options.compact) 521 | L.DomUtil.create('div', this.className + '-margin', this._form);*/ 522 | 523 | if (this.options.title) { 524 | var titlabel = L.DomUtil.create('label', this.className + '-title'); 525 | titlabel.innerHTML = '' + this.options.title + ''; 526 | container.appendChild(titlabel); 527 | } 528 | 529 | container.appendChild(this._form); 530 | }, 531 | 532 | _updateHeight: function (h) { 533 | h = h || this._map.getSize().y; 534 | 535 | if (this.options.compact) 536 | this._form.style.maxHeight = (h - this.options.compactOffset) + 'px'; 537 | else 538 | this._form.style.height = h + 'px'; 539 | }, 540 | 541 | _expand: function () { 542 | L.DomUtil.addClass(this._container, 'expanded'); 543 | }, 544 | 545 | _collapse: function () { 546 | this._container.className = this._container.className.replace('expanded', ''); 547 | }, 548 | 549 | _getPath: function (obj, prop) { 550 | var parts = prop.split('.'), 551 | last = parts.pop(), 552 | len = parts.length, 553 | cur = parts[0], 554 | i = 1; 555 | 556 | if (len > 0) 557 | while ((obj = obj[cur]) && i < len) 558 | cur = parts[i++]; 559 | 560 | if (obj) 561 | return obj[last]; 562 | } 563 | }); 564 | 565 | L.control.panelLayers = function (baseLayers, overlays, options) { 566 | return new L.Control.PanelLayers(baseLayers, overlays, options); 567 | }; 568 | 569 | return L.Control.PanelLayers; 570 | 571 | }); 572 | -------------------------------------------------------------------------------- /examples/collapsible-panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

Leaflet Panel Layers

15 |

Collapsible panel

16 |
17 |
18 | 19 | 20 | 21 | Github 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /examples/config-layers.json: -------------------------------------------------------------------------------- 1 | { 2 | "baselayers": [ 3 | { 4 | "name": "Open Cycle Map", 5 | "layer": { 6 | "type": "tileLayer", 7 | "args": [ 8 | "http://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png" 9 | ] 10 | } 11 | }, 12 | { 13 | "active": true, 14 | "name": "Landscape", 15 | "layer": { 16 | "type": "tileLayer", 17 | "args": [ 18 | "http://{s}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png" 19 | ] 20 | } 21 | }, 22 | { 23 | "name": "Transports", 24 | "layer": { 25 | "type": "tileLayer", 26 | "args": [ 27 | "http://{s}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png" 28 | ] 29 | } 30 | } 31 | ], 32 | "overlayers": [ 33 | { 34 | "name": "Water", 35 | "layer": { 36 | "type": "geoJson", 37 | "args": [ 38 | { 39 | "type": "Feature", 40 | "geometry": { 41 | "type": "MultiPoint", 42 | "coordinates": [ 43 | [12.5107845,42.5214998], 44 | [12.4392016,42.4776585], 45 | [12.4707083,42.5363499] 46 | ] 47 | } 48 | } 49 | ] 50 | } 51 | }, 52 | { 53 | "name": "Bars", 54 | "layer": { 55 | "type": "geoJson", 56 | "args": [ 57 | { 58 | "type": "Feature", 59 | "geometry": { 60 | "type": "MultiPoint", 61 | "coordinates": [ 62 | [12.5107845,42.5204998], 63 | [12.4892016,42.4786585], 64 | [12.4907083,42.5373499] 65 | ] 66 | } 67 | } 68 | ] 69 | } 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /examples/custom-item.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |

Leaflet Panel Layers

19 |

Custom List Layer Example: multiple base layers and overlays with Custom icon and opacity slider

20 |
21 |
22 | 23 | 24 | 25 | Github 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /examples/data/bar.js: -------------------------------------------------------------------------------- 1 | var Bar = { 2 | "type": "FeatureCollection", 3 | "generator": "overpass-turbo", 4 | "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.", 5 | "timestamp": "2014-05-04T04:09:02Z", 6 | "features": [ 7 | { 8 | "type": "Feature", 9 | "id": "node/668137857", 10 | "properties": { 11 | "@id": "node/668137857", 12 | "amenity": "bar", 13 | "cuisine": "italian", 14 | "name": "ala d'oro" 15 | }, 16 | "geometry": { 17 | "type": "Point", 18 | "coordinates": [ 19 | 12.4803732, 20 | 42.4512828 21 | ] 22 | } 23 | }, 24 | { 25 | "type": "Feature", 26 | "id": "node/749981880", 27 | "properties": { 28 | "@id": "node/749981880", 29 | "amenity": "bar" 30 | }, 31 | "geometry": { 32 | "type": "Point", 33 | "coordinates": [ 34 | 12.5357213, 35 | 42.521372 36 | ] 37 | } 38 | }, 39 | { 40 | "type": "Feature", 41 | "id": "node/963955589", 42 | "properties": { 43 | "@id": "node/963955589", 44 | "amenity": "bar", 45 | "name": "Bar Etoile" 46 | }, 47 | "geometry": { 48 | "type": "Point", 49 | "coordinates": [ 50 | 12.3936976, 51 | 42.4681102 52 | ] 53 | } 54 | }, 55 | { 56 | "type": "Feature", 57 | "id": "node/1164303238", 58 | "properties": { 59 | "@id": "node/1164303238", 60 | "amenity": "bar" 61 | }, 62 | "geometry": { 63 | "type": "Point", 64 | "coordinates": [ 65 | 12.527257, 66 | 42.484558 67 | ] 68 | } 69 | }, 70 | { 71 | "type": "Feature", 72 | "id": "node/1976448319", 73 | "properties": { 74 | "@id": "node/1976448319", 75 | "amenity": "bar", 76 | "name": "Bar Cospea" 77 | }, 78 | "geometry": { 79 | "type": "Point", 80 | "coordinates": [ 81 | 12.6303813, 82 | 42.5495197 83 | ] 84 | } 85 | }, 86 | { 87 | "type": "Feature", 88 | "id": "node/2683277782", 89 | "properties": { 90 | "@id": "node/2683277782", 91 | "amenity": "bar" 92 | }, 93 | "geometry": { 94 | "type": "Point", 95 | "coordinates": [ 96 | 12.5159955, 97 | 42.5184603 98 | ] 99 | } 100 | }, 101 | { 102 | "type": "Feature", 103 | "id": "node/2683287208", 104 | "properties": { 105 | "@id": "node/2683287208", 106 | "amenity": "bar" 107 | }, 108 | "geometry": { 109 | "type": "Point", 110 | "coordinates": [ 111 | 12.5158106, 112 | 42.5189334 113 | ] 114 | } 115 | } 116 | ] 117 | }; 118 | -------------------------------------------------------------------------------- /examples/data/caves.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "name": "caves", 4 | "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, 5 | "features": [ 6 | { "type": "Feature", "properties": { "full_id": "n659865250", "osm_id": "659865250", "osm_type": "node", "natural": "cave_entrance", "ele": null, "name": "Grotta della miniera" }, "geometry": { "type": "Point", "coordinates": [ 12.48829, 42.50264 ] } }, 7 | { "type": "Feature", "properties": { "full_id": "n2282648285", "osm_id": "2282648285", "osm_type": "node", "natural": "cave_entrance", "ele": null, "name": null }, "geometry": { "type": "Point", "coordinates": [ 12.4942, 42.49873 ] } }, 8 | { "type": "Feature", "properties": { "full_id": "n4798501461", "osm_id": "4798501461", "osm_type": "node", "natural": "cave_entrance", "ele": "300", "name": "Grotta del Curvone" }, "geometry": { "type": "Point", "coordinates": [ 12.52282, 42.49401 ] } }, 9 | { "type": "Feature", "properties": { "full_id": "n4798501464", "osm_id": "4798501464", "osm_type": "node", "natural": "cave_entrance", "ele": "280", "name": "Grotta dei Cappuccini" }, "geometry": { "type": "Point", "coordinates": [ 12.54755, 42.50372 ] } }, 10 | { "type": "Feature", "properties": { "full_id": "n4801781963", "osm_id": "4801781963", "osm_type": "node", "natural": "cave_entrance", "ele": "382", "name": "Grotta del Bastione" }, "geometry": { "type": "Point", "coordinates": [ 12.52311, 42.5115 ] } }, 11 | { "type": "Feature", "properties": { "full_id": "n4801781965", "osm_id": "4801781965", "osm_type": "node", "natural": "cave_entrance", "ele": "390", "name": "Grotta di Piero" }, "geometry": { "type": "Point", "coordinates": [ 12.50451, 42.51179 ] } }, 12 | { "type": "Feature", "properties": { "full_id": "n4801781966", "osm_id": "4801781966", "osm_type": "node", "natural": "cave_entrance", "ele": null, "name": "Grotta 2a della strada Statale Ortana" }, "geometry": { "type": "Point", "coordinates": [ 12.51449, 42.50844 ] } }, 13 | { "type": "Feature", "properties": { "full_id": "n4801781967", "osm_id": "4801781967", "osm_type": "node", "natural": "cave_entrance", "ele": "100", "name": "Grotta 1a della strada Statale Ortana" }, "geometry": { "type": "Point", "coordinates": [ 12.5145, 42.50816 ] } }, 14 | { "type": "Feature", "properties": { "full_id": "n4801781968", "osm_id": "4801781968", "osm_type": "node", "natural": "cave_entrance", "ele": "280", "name": "Grotta di Montepilli" }, "geometry": { "type": "Point", "coordinates": [ 12.51783, 42.50651 ] } }, 15 | { "type": "Feature", "properties": { "full_id": "n4801781969", "osm_id": "4801781969", "osm_type": "node", "natural": "cave_entrance", "ele": "275", "name": "Grotta D'Orlando" }, "geometry": { "type": "Point", "coordinates": [ 12.5177, 42.50579 ] } }, 16 | { "type": "Feature", "properties": { "full_id": "n4801781970", "osm_id": "4801781970", "osm_type": "node", "natural": "cave_entrance", "ele": "275", "name": "Grotta del Presepe" }, "geometry": { "type": "Point", "coordinates": [ 12.52061, 42.50262 ] } }, 17 | { "type": "Feature", "properties": { "full_id": "n4801781971", "osm_id": "4801781971", "osm_type": "node", "natural": "cave_entrance", "ele": "85", "name": "Grotta del Fiume" }, "geometry": { "type": "Point", "coordinates": [ 12.51228, 42.50373 ] } }, 18 | { "type": "Feature", "properties": { "full_id": "n4801781972", "osm_id": "4801781972", "osm_type": "node", "natural": "cave_entrance", "ele": "98", "name": "Galleria di Recentino" }, "geometry": { "type": "Point", "coordinates": [ 12.5106, 42.50457 ] } }, 19 | { "type": "Feature", "properties": { "full_id": "n4801781973", "osm_id": "4801781973", "osm_type": "node", "natural": "cave_entrance", "ele": "90", "name": "Grotta della Sorgente" }, "geometry": { "type": "Point", "coordinates": [ 12.50923, 42.50317 ] } }, 20 | { "type": "Feature", "properties": { "full_id": "n4801781974", "osm_id": "4801781974", "osm_type": "node", "natural": "cave_entrance", "ele": "170", "name": "Grotta del Cimitero" }, "geometry": { "type": "Point", "coordinates": [ 12.50577, 42.50117 ] } }, 21 | { "type": "Feature", "properties": { "full_id": "n4801781975", "osm_id": "4801781975", "osm_type": "node", "natural": "cave_entrance", "ele": "176", "name": "Buca di Taizzano" }, "geometry": { "type": "Point", "coordinates": [ 12.50132, 42.49756 ] } }, 22 | { "type": "Feature", "properties": { "full_id": "n4801781976", "osm_id": "4801781976", "osm_type": "node", "natural": "cave_entrance", "ele": "310", "name": "Grotta del Monastero" }, "geometry": { "type": "Point", "coordinates": [ 12.49848, 42.50293 ] } }, 23 | { "type": "Feature", "properties": { "full_id": "n4801781977", "osm_id": "4801781977", "osm_type": "node", "natural": "cave_entrance", "ele": "300", "name": "Grotta della Topa" }, "geometry": { "type": "Point", "coordinates": [ 12.49643, 42.50094 ] } }, 24 | { "type": "Feature", "properties": { "full_id": "n4801781978", "osm_id": "4801781978", "osm_type": "node", "natural": "cave_entrance", "ele": "290", "name": "Grotta dello Svizzero" }, "geometry": { "type": "Point", "coordinates": [ 12.49562, 42.50122 ] } }, 25 | { "type": "Feature", "properties": { "full_id": "n4801781979", "osm_id": "4801781979", "osm_type": "node", "natural": "cave_entrance", "ele": "180", "name": "Grotta di Stifone o del Pungitopo" }, "geometry": { "type": "Point", "coordinates": [ 12.49533, 42.49568 ] } }, 26 | { "type": "Feature", "properties": { "full_id": "n4801781980", "osm_id": "4801781980", "osm_type": "node", "natural": "cave_entrance", "ele": "185", "name": "Grotta di Stifone 2a o dell'Ossa" }, "geometry": { "type": "Point", "coordinates": [ 12.49506, 42.49539 ] } }, 27 | { "type": "Feature", "properties": { "full_id": "n4801781981", "osm_id": "4801781981", "osm_type": "node", "natural": "cave_entrance", "ele": "130", "name": "Caverna presso la diga di Stifone" }, "geometry": { "type": "Point", "coordinates": [ 12.49031, 42.49877 ] } }, 28 | { "type": "Feature", "properties": { "full_id": "n4801781982", "osm_id": "4801781982", "osm_type": "node", "natural": "cave_entrance", "ele": "230", "name": "Buca delle Streghe" }, "geometry": { "type": "Point", "coordinates": [ 12.48893, 42.5065 ] } }, 29 | { "type": "Feature", "properties": { "full_id": "n4801781983", "osm_id": "4801781983", "osm_type": "node", "natural": "cave_entrance", "ele": "196", "name": "Grotta di Podere Lubriano" }, "geometry": { "type": "Point", "coordinates": [ 12.48727, 42.50512 ] } }, 30 | { "type": "Feature", "properties": { "full_id": "n4801781984", "osm_id": "4801781984", "osm_type": "node", "natural": "cave_entrance", "ele": "218", "name": "Grotta du Fossu" }, "geometry": { "type": "Point", "coordinates": [ 12.48838, 42.50485 ] } }, 31 | { "type": "Feature", "properties": { "full_id": "n4801781985", "osm_id": "4801781985", "osm_type": "node", "natural": "cave_entrance", "ele": "230", "name": "Grotta dell'Orso" }, "geometry": { "type": "Point", "coordinates": [ 12.48894, 42.50483 ] } }, 32 | { "type": "Feature", "properties": { "full_id": "n4801781986", "osm_id": "4801781986", "osm_type": "node", "natural": "cave_entrance", "ele": "195", "name": "Grotta dei Nuovi" }, "geometry": { "type": "Point", "coordinates": [ 12.48811, 42.50428 ] } }, 33 | { "type": "Feature", "properties": { "full_id": "n4801781987", "osm_id": "4801781987", "osm_type": "node", "natural": "cave_entrance", "ele": "273", "name": "Grotta Celeste" }, "geometry": { "type": "Point", "coordinates": [ 12.49265, 42.50341 ] } }, 34 | { "type": "Feature", "properties": { "full_id": "n4801781988", "osm_id": "4801781988", "osm_type": "node", "natural": "cave_entrance", "ele": "280", "name": "Grotta dei Veli" }, "geometry": { "type": "Point", "coordinates": [ 12.49292, 42.50331 ] } }, 35 | { "type": "Feature", "properties": { "full_id": "n4801781991", "osm_id": "4801781991", "osm_type": "node", "natural": "cave_entrance", "ele": "95", "name": "Grotta del Ponte" }, "geometry": { "type": "Point", "coordinates": [ 12.48533, 42.50178 ] } }, 36 | { "type": "Feature", "properties": { "full_id": "n4801817761", "osm_id": "4801817761", "osm_type": "node", "natural": "cave_entrance", "ele": "290", "name": "Buca o Soffiatoio presso il Podere Monti" }, "geometry": { "type": "Point", "coordinates": [ 12.47644, 42.52027 ] } }, 37 | { "type": "Feature", "properties": { "full_id": "n4801817762", "osm_id": "4801817762", "osm_type": "node", "natural": "cave_entrance", "ele": "330", "name": "Buca dei Cani" }, "geometry": { "type": "Point", "coordinates": [ 12.4845, 42.52066 ] } }, 38 | { "type": "Feature", "properties": { "full_id": "n4801817763", "osm_id": "4801817763", "osm_type": "node", "natural": "cave_entrance", "ele": "330", "name": "Grotta della Polveriera" }, "geometry": { "type": "Point", "coordinates": [ 12.48477, 42.5215 ] } }, 39 | { "type": "Feature", "properties": { "full_id": "n4801817764", "osm_id": "4801817764", "osm_type": "node", "natural": "cave_entrance", "ele": "350", "name": "Buca del Casalino" }, "geometry": { "type": "Point", "coordinates": [ 12.48728, 42.51873 ] } }, 40 | { "type": "Feature", "properties": { "full_id": "n4801817765", "osm_id": "4801817765", "osm_type": "node", "natural": "cave_entrance", "ele": "100", "name": "Grotta innominata" }, "geometry": { "type": "Point", "coordinates": [ 12.51088, 42.52261 ] } }, 41 | { "type": "Feature", "properties": { "full_id": "n4801817766", "osm_id": "4801817766", "osm_type": "node", "natural": "cave_entrance", "ele": "100", "name": "Grotta di San Casciano" }, "geometry": { "type": "Point", "coordinates": [ 12.51184, 42.52125 ] } }, 42 | { "type": "Feature", "properties": { "full_id": "n4801817767", "osm_id": "4801817767", "osm_type": "node", "natural": "cave_entrance", "ele": "94", "name": "Grotta di Narni" }, "geometry": { "type": "Point", "coordinates": [ 12.51172, 42.52095 ] } }, 43 | { "type": "Feature", "properties": { "full_id": "n4801817768", "osm_id": "4801817768", "osm_type": "node", "natural": "cave_entrance", "ele": "237", "name": "Grotta di Casa Rossa" }, "geometry": { "type": "Point", "coordinates": [ 12.50756, 42.51956 ] } }, 44 | { "type": "Feature", "properties": { "full_id": "n4801817769", "osm_id": "4801817769", "osm_type": "node", "natural": "cave_entrance", "ele": "246", "name": "Grotta Mearelli" }, "geometry": { "type": "Point", "coordinates": [ 12.51839, 42.51705 ] } }, 45 | { "type": "Feature", "properties": { "full_id": "n4801817770", "osm_id": "4801817770", "osm_type": "node", "natural": "cave_entrance", "ele": "194", "name": "Grotta del Corno" }, "geometry": { "type": "Point", "coordinates": [ 12.51394, 42.51761 ] } }, 46 | { "type": "Feature", "properties": { "full_id": "n4801817771", "osm_id": "4801817771", "osm_type": "node", "natural": "cave_entrance", "ele": "195", "name": "Grotta del Gradino 3a" }, "geometry": { "type": "Point", "coordinates": [ 12.51416, 42.5179 ] } }, 47 | { "type": "Feature", "properties": { "full_id": "n4801817772", "osm_id": "4801817772", "osm_type": "node", "natural": "cave_entrance", "ele": "170", "name": "Grotta del Gradino 2a" }, "geometry": { "type": "Point", "coordinates": [ 12.51372, 42.51784 ] } }, 48 | { "type": "Feature", "properties": { "full_id": "n4801817773", "osm_id": "4801817773", "osm_type": "node", "natural": "cave_entrance", "ele": "170", "name": "Grotta del Gradino 1a" }, "geometry": { "type": "Point", "coordinates": [ 12.51366, 42.51789 ] } }, 49 | { "type": "Feature", "properties": { "full_id": "n4801817774", "osm_id": "4801817774", "osm_type": "node", "natural": "cave_entrance", "ele": "110", "name": "Grotta dei Grilli" }, "geometry": { "type": "Point", "coordinates": [ 12.51171, 42.51706 ] } }, 50 | { "type": "Feature", "properties": { "full_id": "n4801817775", "osm_id": "4801817775", "osm_type": "node", "natural": "cave_entrance", "ele": "160", "name": "Grotta (o caverna) dell'Eremita" }, "geometry": { "type": "Point", "coordinates": [ 12.5109, 42.51625 ] } }, 51 | { "type": "Feature", "properties": { "full_id": "n4801817776", "osm_id": "4801817776", "osm_type": "node", "natural": "cave_entrance", "ele": "168", "name": "Grotta inferiore dell'Eremo" }, "geometry": { "type": "Point", "coordinates": [ 12.51088, 42.51622 ] } }, 52 | { "type": "Feature", "properties": { "full_id": "n4801817777", "osm_id": "4801817777", "osm_type": "node", "natural": "cave_entrance", "ele": "165", "name": "Grotta della Capra" }, "geometry": { "type": "Point", "coordinates": [ 12.51144, 42.51596 ] } }, 53 | { "type": "Feature", "properties": { "full_id": "n4801817778", "osm_id": "4801817778", "osm_type": "node", "natural": "cave_entrance", "ele": "165", "name": "Grotta della Rupe" }, "geometry": { "type": "Point", "coordinates": [ 12.51116, 42.51594 ] } }, 54 | { "type": "Feature", "properties": { "full_id": "n4801817779", "osm_id": "4801817779", "osm_type": "node", "natural": "cave_entrance", "ele": "190", "name": "Grotta dei Cocci" }, "geometry": { "type": "Point", "coordinates": [ 12.5106, 42.51567 ] } }, 55 | { "type": "Feature", "properties": { "full_id": "n4801817780", "osm_id": "4801817780", "osm_type": "node", "natural": "cave_entrance", "ele": "280", "name": "Grotta della Rupe del Monte Santa Croce" }, "geometry": { "type": "Point", "coordinates": [ 12.50978, 42.51651 ] } }, 56 | { "type": "Feature", "properties": { "full_id": "n4801817781", "osm_id": "4801817781", "osm_type": "node", "natural": "cave_entrance", "ele": "220", "name": "Grotta del Monte Santa Croce" }, "geometry": { "type": "Point", "coordinates": [ 12.50894, 42.51651 ] } }, 57 | { "type": "Feature", "properties": { "full_id": "n4801817782", "osm_id": "4801817782", "osm_type": "node", "natural": "cave_entrance", "ele": "225", "name": "Grotta di San Jago" }, "geometry": { "type": "Point", "coordinates": [ 12.50866, 42.5165 ] } }, 58 | { "type": "Feature", "properties": { "full_id": "n4801817783", "osm_id": "4801817783", "osm_type": "node", "natural": "cave_entrance", "ele": "220", "name": "Grotta dei Cocci Superiore" }, "geometry": { "type": "Point", "coordinates": [ 12.51045, 42.5143 ] } }, 59 | { "type": "Feature", "properties": { "full_id": "n9601093073", "osm_id": "9601093073", "osm_type": "node", "natural": "cave_entrance", "ele": null, "name": "Grotta degli archi" }, "geometry": { "type": "Point", "coordinates": [ 12.49216, 42.50674 ] } } 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /examples/data/drinking_water.js: -------------------------------------------------------------------------------- 1 | var Drinking_water = { 2 | "type": "FeatureCollection", 3 | "generator": "overpass-turbo", 4 | "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.", 5 | "timestamp": "2014-05-04T04:10:02Z", 6 | "features": [ 7 | { 8 | "type": "Feature", 9 | "id": "node/749981989", 10 | "properties": { 11 | "@id": "node/749981989", 12 | "amenity": "drinking_water" 13 | }, 14 | "geometry": { 15 | "type": "Point", 16 | "coordinates": [ 17 | 12.5107845, 18 | 42.5204998 19 | ] 20 | } 21 | }, 22 | { 23 | "type": "Feature", 24 | "id": "node/749982528", 25 | "properties": { 26 | "@id": "node/749982528", 27 | "amenity": "drinking_water", 28 | "name": "Santa Pudenziana", 29 | "natural": "spring" 30 | }, 31 | "geometry": { 32 | "type": "Point", 33 | "coordinates": [ 34 | 12.4892016, 35 | 42.4786585 36 | ] 37 | } 38 | }, 39 | { 40 | "type": "Feature", 41 | "id": "node/749987962", 42 | "properties": { 43 | "@id": "node/749987962", 44 | "amenity": "drinking_water" 45 | }, 46 | "geometry": { 47 | "type": "Point", 48 | "coordinates": [ 49 | 12.4907083, 50 | 42.5373499 51 | ] 52 | } 53 | }, 54 | { 55 | "type": "Feature", 56 | "id": "node/867428079", 57 | "properties": { 58 | "@id": "node/867428079", 59 | "amenity": "drinking_water" 60 | }, 61 | "geometry": { 62 | "type": "Point", 63 | "coordinates": [ 64 | 12.5856662, 65 | 42.4652808 66 | ] 67 | } 68 | }, 69 | { 70 | "type": "Feature", 71 | "id": "node/919072243", 72 | "properties": { 73 | "@id": "node/919072243", 74 | "amenity": "drinking_water" 75 | }, 76 | "geometry": { 77 | "type": "Point", 78 | "coordinates": [ 79 | 12.6228916, 80 | 42.5246762 81 | ] 82 | } 83 | }, 84 | { 85 | "type": "Feature", 86 | "id": "node/963839211", 87 | "properties": { 88 | "@id": "node/963839211", 89 | "amenity": "drinking_water" 90 | }, 91 | "geometry": { 92 | "type": "Point", 93 | "coordinates": [ 94 | 12.3461439, 95 | 42.415475 96 | ] 97 | } 98 | }, 99 | { 100 | "type": "Feature", 101 | "id": "node/963955653", 102 | "properties": { 103 | "@id": "node/963955653", 104 | "amenity": "drinking_water" 105 | }, 106 | "geometry": { 107 | "type": "Point", 108 | "coordinates": [ 109 | 12.3801559, 110 | 42.460281 111 | ] 112 | } 113 | }, 114 | { 115 | "type": "Feature", 116 | "id": "node/1227200162", 117 | "properties": { 118 | "@id": "node/1227200162", 119 | "amenity": "drinking_water" 120 | }, 121 | "geometry": { 122 | "type": "Point", 123 | "coordinates": [ 124 | 12.6287993, 125 | 42.4518862 126 | ] 127 | } 128 | }, 129 | { 130 | "type": "Feature", 131 | "id": "node/1293353906", 132 | "properties": { 133 | "@id": "node/1293353906", 134 | "amenity": "drinking_water" 135 | }, 136 | "geometry": { 137 | "type": "Point", 138 | "coordinates": [ 139 | 12.5568084, 140 | 42.4899744 141 | ] 142 | } 143 | }, 144 | { 145 | "type": "Feature", 146 | "id": "node/1432209466", 147 | "properties": { 148 | "@id": "node/1432209466", 149 | "amenity": "drinking_water" 150 | }, 151 | "geometry": { 152 | "type": "Point", 153 | "coordinates": [ 154 | 12.6057575, 155 | 42.4552141 156 | ] 157 | } 158 | }, 159 | { 160 | "type": "Feature", 161 | "id": "node/2272651420", 162 | "properties": { 163 | "@id": "node/2272651420", 164 | "amenity": "drinking_water" 165 | }, 166 | "geometry": { 167 | "type": "Point", 168 | "coordinates": [ 169 | 12.442251, 170 | 42.4505736 171 | ] 172 | } 173 | }, 174 | { 175 | "type": "Feature", 176 | "id": "node/2311280313", 177 | "properties": { 178 | "@id": "node/2311280313", 179 | "amenity": "drinking_water" 180 | }, 181 | "geometry": { 182 | "type": "Point", 183 | "coordinates": [ 184 | 12.6353162, 185 | 42.5491132 186 | ] 187 | } 188 | }, 189 | { 190 | "type": "Feature", 191 | "id": "node/2493523689", 192 | "properties": { 193 | "@id": "node/2493523689", 194 | "amenity": "drinking_water" 195 | }, 196 | "geometry": { 197 | "type": "Point", 198 | "coordinates": [ 199 | 12.4686986, 200 | 42.5046063 201 | ] 202 | } 203 | } 204 | ] 205 | }; 206 | -------------------------------------------------------------------------------- /examples/data/fuel.js: -------------------------------------------------------------------------------- 1 | var Fuel = { 2 | "type": "FeatureCollection", 3 | "generator": "overpass-turbo", 4 | "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.", 5 | "timestamp": "2014-05-04T04:13:02Z", 6 | "features": [ 7 | { 8 | "type": "Feature", 9 | "id": "node/228085144", 10 | "properties": { 11 | "@id": "node/228085144", 12 | "amenity": "fuel", 13 | "brand": "Metano", 14 | "name": "Metano", 15 | "operator": "Metano" 16 | }, 17 | "geometry": { 18 | "type": "Point", 19 | "coordinates": [ 20 | 12.601597, 21 | 42.543722 22 | ] 23 | } 24 | }, 25 | { 26 | "type": "Feature", 27 | "id": "node/228257837", 28 | "properties": { 29 | "@id": "node/228257837", 30 | "amenity": "fuel", 31 | "brand": "Total", 32 | "name": "Total", 33 | "operator": "Total" 34 | }, 35 | "geometry": { 36 | "type": "Point", 37 | "coordinates": [ 38 | 12.351578, 39 | 42.41617 40 | ] 41 | } 42 | }, 43 | { 44 | "type": "Feature", 45 | "id": "node/370946751", 46 | "properties": { 47 | "@id": "node/370946751", 48 | "amenity": "fuel", 49 | "name": "Agip" 50 | }, 51 | "geometry": { 52 | "type": "Point", 53 | "coordinates": [ 54 | 12.4188559, 55 | 42.4604455 56 | ] 57 | } 58 | }, 59 | { 60 | "type": "Feature", 61 | "id": "node/665498285", 62 | "properties": { 63 | "@id": "node/665498285", 64 | "amenity": "fuel", 65 | "name": "agip" 66 | }, 67 | "geometry": { 68 | "type": "Point", 69 | "coordinates": [ 70 | 12.4804402, 71 | 42.4520117 72 | ] 73 | } 74 | }, 75 | { 76 | "type": "Feature", 77 | "id": "node/804160547", 78 | "properties": { 79 | "@id": "node/804160547", 80 | "amenity": "fuel", 81 | "name": "IP" 82 | }, 83 | "geometry": { 84 | "type": "Point", 85 | "coordinates": [ 86 | 12.6271556, 87 | 42.4965185 88 | ] 89 | } 90 | }, 91 | { 92 | "type": "Feature", 93 | "id": "node/1331638752", 94 | "properties": { 95 | "@id": "node/1331638752", 96 | "amenity": "fuel", 97 | "fuel:diesel": "no", 98 | "fuel:lpg": "yes" 99 | }, 100 | "geometry": { 101 | "type": "Point", 102 | "coordinates": [ 103 | 12.5155381, 104 | 42.5306333 105 | ] 106 | } 107 | }, 108 | { 109 | "type": "Feature", 110 | "id": "node/1811037448", 111 | "properties": { 112 | "@id": "node/1811037448", 113 | "amenity": "fuel", 114 | "brand": "TotalErg", 115 | "fuel:biodiesel": "no", 116 | "fuel:biogas": "no", 117 | "fuel:diesel": "yes", 118 | "fuel:e85": "yes", 119 | "fuel:electricity": "no" 120 | }, 121 | "geometry": { 122 | "type": "Point", 123 | "coordinates": [ 124 | 12.407974, 125 | 42.4388468 126 | ] 127 | } 128 | }, 129 | { 130 | "type": "Feature", 131 | "id": "node/1818884642", 132 | "properties": { 133 | "@id": "node/1818884642", 134 | "amenity": "fuel", 135 | "brand": "Tamoil" 136 | }, 137 | "geometry": { 138 | "type": "Point", 139 | "coordinates": [ 140 | 12.387061, 141 | 42.4582678 142 | ] 143 | } 144 | }, 145 | { 146 | "type": "Feature", 147 | "id": "node/1818884643", 148 | "properties": { 149 | "@id": "node/1818884643", 150 | "amenity": "fuel", 151 | "brand": "TotalErg" 152 | }, 153 | "geometry": { 154 | "type": "Point", 155 | "coordinates": [ 156 | 12.3780541, 157 | 42.4598251 158 | ] 159 | } 160 | }, 161 | { 162 | "type": "Feature", 163 | "id": "node/1818884645", 164 | "properties": { 165 | "@id": "node/1818884645", 166 | "amenity": "fuel", 167 | "brand": "Q8" 168 | }, 169 | "geometry": { 170 | "type": "Point", 171 | "coordinates": [ 172 | 12.3892899, 173 | 42.4599715 174 | ] 175 | } 176 | }, 177 | { 178 | "type": "Feature", 179 | "id": "node/1863388719", 180 | "properties": { 181 | "@id": "node/1863388719", 182 | "amenity": "fuel", 183 | "name": "Esso", 184 | "operator": "Esso" 185 | }, 186 | "geometry": { 187 | "type": "Point", 188 | "coordinates": [ 189 | 12.4229429, 190 | 42.463564 191 | ] 192 | } 193 | }, 194 | { 195 | "type": "Feature", 196 | "id": "node/1863423016", 197 | "properties": { 198 | "@id": "node/1863423016", 199 | "amenity": "fuel", 200 | "fuel:cng": "yes", 201 | "fuel:diesel": "yes", 202 | "fuel:lpg": "yes" 203 | }, 204 | "geometry": { 205 | "type": "Point", 206 | "coordinates": [ 207 | 12.4524038, 208 | 42.485146 209 | ] 210 | } 211 | }, 212 | { 213 | "type": "Feature", 214 | "id": "node/1904273315", 215 | "properties": { 216 | "@id": "node/1904273315", 217 | "amenity": "fuel", 218 | "name": "Eni" 219 | }, 220 | "geometry": { 221 | "type": "Point", 222 | "coordinates": [ 223 | 12.5203313, 224 | 42.535809 225 | ] 226 | } 227 | }, 228 | { 229 | "type": "Feature", 230 | "id": "node/2314471894", 231 | "properties": { 232 | "@id": "node/2314471894", 233 | "amenity": "fuel", 234 | "brand": "Esso", 235 | "operator": "Esso" 236 | }, 237 | "geometry": { 238 | "type": "Point", 239 | "coordinates": [ 240 | 12.6154986, 241 | 42.5467135 242 | ] 243 | } 244 | } 245 | ] 246 | }; 247 | -------------------------------------------------------------------------------- /examples/data/lakes.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "name": "lakes", 4 | "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, 5 | "features": [ 6 | { "type": "Feature", "properties": { "natural": "water", "name": "Lago di Recentino" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.54322, 42.51866 ], [ 12.54348, 42.51937 ], [ 12.54398, 42.52031 ], [ 12.54458, 42.52144 ], [ 12.54487, 42.52197 ], [ 12.54503, 42.5222 ], [ 12.54545, 42.52233 ], [ 12.54568, 42.52229 ], [ 12.54607, 42.5221 ], [ 12.54651, 42.52186 ], [ 12.54655, 42.5217 ], [ 12.54687, 42.52152 ], [ 12.5474, 42.52106 ], [ 12.54926, 42.52075 ], [ 12.55003, 42.52083 ], [ 12.5512, 42.52067 ], [ 12.552, 42.52066 ], [ 12.55296, 42.52046 ], [ 12.55424, 42.52051 ], [ 12.55496, 42.52038 ], [ 12.5556, 42.52025 ], [ 12.55608, 42.52009 ], [ 12.55634, 42.52002 ], [ 12.5564, 42.51986 ], [ 12.55648, 42.51973 ], [ 12.55667, 42.51957 ], [ 12.55668, 42.51936 ], [ 12.55666, 42.51884 ], [ 12.55652, 42.51861 ], [ 12.55624, 42.51844 ], [ 12.55588, 42.51841 ], [ 12.55564, 42.51837 ], [ 12.55555, 42.51834 ], [ 12.55511, 42.51804 ], [ 12.55518, 42.51782 ], [ 12.5555, 42.51776 ], [ 12.5558, 42.51778 ], [ 12.55608, 42.51789 ], [ 12.55639, 42.51798 ], [ 12.55662, 42.51796 ], [ 12.55693, 42.51783 ], [ 12.55701, 42.51766 ], [ 12.55664, 42.51745 ], [ 12.55684, 42.517 ], [ 12.55673, 42.51669 ], [ 12.55686, 42.5166 ], [ 12.55687, 42.51652 ], [ 12.55707, 42.51644 ], [ 12.55711, 42.51627 ], [ 12.55743, 42.51619 ], [ 12.55751, 42.51598 ], [ 12.55736, 42.51583 ], [ 12.55715, 42.51582 ], [ 12.55705, 42.51576 ], [ 12.55712, 42.51564 ], [ 12.55687, 42.51559 ], [ 12.55639, 42.51566 ], [ 12.55592, 42.51578 ], [ 12.55552, 42.51593 ], [ 12.55491, 42.51584 ], [ 12.55437, 42.51566 ], [ 12.55363, 42.51556 ], [ 12.55321, 42.51557 ], [ 12.55298, 42.51545 ], [ 12.55266, 42.51539 ], [ 12.55204, 42.51504 ], [ 12.55139, 42.51502 ], [ 12.55078, 42.5151 ], [ 12.55048, 42.51519 ], [ 12.55008, 42.51509 ], [ 12.5498, 42.51492 ], [ 12.54961, 42.5149 ], [ 12.54877, 42.51496 ], [ 12.54777, 42.51537 ], [ 12.54699, 42.51571 ], [ 12.54573, 42.51627 ], [ 12.54558, 42.5164 ], [ 12.54555, 42.51652 ], [ 12.54536, 42.51655 ], [ 12.54522, 42.51681 ], [ 12.54486, 42.51699 ], [ 12.5439, 42.51802 ], [ 12.5432, 42.51837 ], [ 12.54322, 42.51866 ] ] ] ] } }, 7 | { "type": "Feature", "properties": { "natural": "water", "name": "Lago di San Liberato" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.43529, 42.46766 ], [ 12.43536, 42.46752 ], [ 12.43529, 42.4674 ], [ 12.43518, 42.46735 ], [ 12.43507, 42.46713 ], [ 12.43511, 42.46706 ], [ 12.43502, 42.46694 ], [ 12.43485, 42.46684 ], [ 12.43469, 42.4666 ], [ 12.43472, 42.46644 ], [ 12.43495, 42.46627 ], [ 12.43535, 42.4661 ], [ 12.43558, 42.46601 ], [ 12.43582, 42.46592 ], [ 12.43595, 42.46584 ], [ 12.4359, 42.4655 ], [ 12.4358, 42.46504 ], [ 12.43575, 42.46466 ], [ 12.43575, 42.46432 ], [ 12.43578, 42.46407 ], [ 12.43587, 42.46381 ], [ 12.43613, 42.46343 ], [ 12.4365, 42.46303 ], [ 12.43661, 42.46294 ], [ 12.43668, 42.46279 ], [ 12.43684, 42.46274 ], [ 12.43701, 42.4628 ], [ 12.43712, 42.46282 ], [ 12.43722, 42.46283 ], [ 12.4376, 42.46292 ], [ 12.43801, 42.46314 ], [ 12.4384, 42.46345 ], [ 12.43875, 42.46394 ], [ 12.43902, 42.46422 ], [ 12.43919, 42.46442 ], [ 12.43953, 42.46456 ], [ 12.43965, 42.46486 ], [ 12.43997, 42.46506 ], [ 12.44041, 42.46541 ], [ 12.44079, 42.46559 ], [ 12.44101, 42.46572 ], [ 12.44125, 42.46566 ], [ 12.44144, 42.46559 ], [ 12.44159, 42.46561 ], [ 12.44154, 42.46569 ], [ 12.44147, 42.46573 ], [ 12.44126, 42.46573 ], [ 12.44114, 42.4658 ], [ 12.44123, 42.46593 ], [ 12.44137, 42.46598 ], [ 12.44147, 42.46603 ], [ 12.44174, 42.46605 ], [ 12.44198, 42.46621 ], [ 12.4421, 42.46632 ], [ 12.44211, 42.46654 ], [ 12.44223, 42.46665 ], [ 12.44233, 42.46665 ], [ 12.44251, 42.46651 ], [ 12.44247, 42.46669 ], [ 12.44258, 42.46681 ], [ 12.44295, 42.46666 ], [ 12.44277, 42.46682 ], [ 12.44257, 42.46689 ], [ 12.4425, 42.46701 ], [ 12.44228, 42.46732 ], [ 12.44217, 42.46787 ], [ 12.44213, 42.46869 ], [ 12.44189, 42.46967 ], [ 12.44127, 42.47028 ], [ 12.44111, 42.47065 ], [ 12.44035, 42.47111 ], [ 12.43942, 42.47191 ], [ 12.43896, 42.47241 ], [ 12.43875, 42.47305 ], [ 12.43846, 42.47354 ], [ 12.4382, 42.47359 ], [ 12.4376, 42.47427 ], [ 12.43712, 42.47454 ], [ 12.43697, 42.47445 ], [ 12.43752, 42.47384 ], [ 12.43816, 42.473 ], [ 12.43849, 42.47259 ], [ 12.43828, 42.47239 ], [ 12.43737, 42.47331 ], [ 12.43647, 42.47409 ], [ 12.43639, 42.47437 ], [ 12.43668, 42.47482 ], [ 12.43614, 42.47501 ], [ 12.43579, 42.47424 ], [ 12.4362, 42.47356 ], [ 12.43679, 42.47287 ], [ 12.43699, 42.47263 ], [ 12.43683, 42.47229 ], [ 12.43708, 42.47157 ], [ 12.43737, 42.47087 ], [ 12.43737, 42.47048 ], [ 12.4373, 42.47001 ], [ 12.43699, 42.46959 ], [ 12.43664, 42.46948 ], [ 12.4363, 42.46947 ], [ 12.43529, 42.46766 ] ] ] ] } }, 8 | { "type": "Feature", "properties": { "natural": "water", "name": "Sorgente principale di Stifone" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.49286, 42.49744 ], [ 12.49283, 42.49741 ], [ 12.49284, 42.49737 ], [ 12.49297, 42.49728 ], [ 12.49304, 42.49726 ], [ 12.4931, 42.49725 ], [ 12.49314, 42.49726 ], [ 12.49315, 42.49729 ], [ 12.49286, 42.49744 ] ] ] ] } }, 9 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.56984, 42.53571 ], [ 12.5702, 42.53609 ], [ 12.5705, 42.53632 ], [ 12.57083, 42.53655 ], [ 12.57143, 42.53682 ], [ 12.57205, 42.53702 ], [ 12.57251, 42.53711 ], [ 12.57285, 42.53715 ], [ 12.57315, 42.53716 ], [ 12.57362, 42.53717 ], [ 12.57599, 42.53717 ], [ 12.57792, 42.53717 ], [ 12.57793, 42.53726 ], [ 12.57792, 42.53734 ], [ 12.576, 42.53735 ], [ 12.57359, 42.53734 ], [ 12.57309, 42.53733 ], [ 12.57278, 42.53731 ], [ 12.57246, 42.53726 ], [ 12.57199, 42.53717 ], [ 12.57153, 42.53702 ], [ 12.57118, 42.53689 ], [ 12.57069, 42.53666 ], [ 12.57033, 42.53643 ], [ 12.57, 42.53616 ], [ 12.56964, 42.53581 ], [ 12.5694, 42.53546 ], [ 12.56922, 42.5351 ], [ 12.56906, 42.53469 ], [ 12.56894, 42.53429 ], [ 12.56885, 42.53393 ], [ 12.56871, 42.53363 ], [ 12.56855, 42.53343 ], [ 12.56826, 42.5331 ], [ 12.56798, 42.53285 ], [ 12.5675, 42.53258 ], [ 12.56681, 42.53222 ], [ 12.56607, 42.53181 ], [ 12.56528, 42.53138 ], [ 12.56404, 42.5307 ], [ 12.56311, 42.53019 ], [ 12.56199, 42.52959 ], [ 12.56145, 42.52933 ], [ 12.56096, 42.5292 ], [ 12.56024, 42.52905 ], [ 12.5593, 42.52882 ], [ 12.55852, 42.52863 ], [ 12.55766, 42.52844 ], [ 12.55704, 42.5283 ], [ 12.55649, 42.52826 ], [ 12.55563, 42.52824 ], [ 12.55431, 42.5282 ], [ 12.55353, 42.52819 ], [ 12.5527, 42.52815 ], [ 12.55203, 42.52802 ], [ 12.55157, 42.52785 ], [ 12.55111, 42.52756 ], [ 12.5507, 42.52712 ], [ 12.5505, 42.52685 ], [ 12.55025, 42.52644 ], [ 12.54991, 42.52596 ], [ 12.54984, 42.52583 ], [ 12.54983, 42.52579 ], [ 12.54988, 42.52578 ], [ 12.54992, 42.52576 ], [ 12.54998, 42.52581 ], [ 12.55009, 42.52592 ], [ 12.55041, 42.52633 ], [ 12.55073, 42.52682 ], [ 12.551, 42.52719 ], [ 12.5514, 42.52757 ], [ 12.5517, 42.52774 ], [ 12.55217, 42.52789 ], [ 12.55265, 42.52796 ], [ 12.55317, 42.52799 ], [ 12.55461, 42.52803 ], [ 12.5558, 42.52806 ], [ 12.55694, 42.52813 ], [ 12.55757, 42.52825 ], [ 12.55932, 42.52865 ], [ 12.56061, 42.52893 ], [ 12.56145, 42.52915 ], [ 12.5619, 42.52934 ], [ 12.56266, 42.52972 ], [ 12.56362, 42.53027 ], [ 12.56542, 42.53125 ], [ 12.5663, 42.53171 ], [ 12.56726, 42.53223 ], [ 12.56805, 42.53266 ], [ 12.56848, 42.533 ], [ 12.56879, 42.53335 ], [ 12.56903, 42.53376 ], [ 12.5692, 42.53429 ], [ 12.56932, 42.53471 ], [ 12.56952, 42.53521 ], [ 12.56984, 42.53571 ] ] ] ] } }, 10 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.45831, 42.49636 ], [ 12.45755, 42.49666 ], [ 12.45774, 42.49698 ], [ 12.45814, 42.49745 ], [ 12.45848, 42.49762 ], [ 12.45869, 42.49785 ], [ 12.45877, 42.49816 ], [ 12.45885, 42.49817 ], [ 12.45882, 42.49781 ], [ 12.45872, 42.49747 ], [ 12.45857, 42.49696 ], [ 12.45841, 42.49656 ], [ 12.45831, 42.49636 ] ] ] ] } }, 11 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.45365, 42.49449 ], [ 12.45256, 42.49444 ], [ 12.45247, 42.49554 ], [ 12.45239, 42.49599 ], [ 12.45228, 42.49633 ], [ 12.45208, 42.49682 ], [ 12.4524, 42.49663 ], [ 12.45263, 42.49613 ], [ 12.45273, 42.49592 ], [ 12.45312, 42.49544 ], [ 12.45365, 42.49449 ] ] ] ] } }, 12 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.46737, 42.4635 ], [ 12.46709, 42.46332 ], [ 12.46719, 42.46315 ], [ 12.4674, 42.463 ], [ 12.46752, 42.4631 ], [ 12.46741, 42.46325 ], [ 12.4675, 42.46339 ], [ 12.46737, 42.4635 ] ] ] ] } }, 13 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.57484, 42.45865 ], [ 12.57477, 42.45862 ], [ 12.57477, 42.45856 ], [ 12.57484, 42.45851 ], [ 12.57492, 42.45849 ], [ 12.57496, 42.45856 ], [ 12.5749, 42.45862 ], [ 12.57484, 42.45865 ] ] ] ] } }, 14 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.48143, 42.49865 ], [ 12.48173, 42.49859 ], [ 12.48198, 42.49846 ], [ 12.48224, 42.49839 ], [ 12.4822, 42.49832 ], [ 12.48204, 42.49834 ], [ 12.48197, 42.49832 ], [ 12.4819, 42.49819 ], [ 12.4817, 42.49824 ], [ 12.48159, 42.4982 ], [ 12.48127, 42.49826 ], [ 12.48143, 42.49865 ] ] ] ] } }, 15 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.48137, 42.4982 ], [ 12.48161, 42.49816 ], [ 12.4817, 42.49819 ], [ 12.48205, 42.49813 ], [ 12.4817, 42.49789 ], [ 12.4813, 42.49797 ], [ 12.48137, 42.4982 ] ] ] ] } }, 16 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.48146, 42.49894 ], [ 12.4817, 42.49896 ], [ 12.48229, 42.49889 ], [ 12.48226, 42.49876 ], [ 12.48167, 42.49882 ], [ 12.48146, 42.49889 ], [ 12.48146, 42.49894 ] ] ] ] } }, 17 | { "type": "Feature", "properties": { "natural": "water", "name": "Piscina" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.53713, 42.51084 ], [ 12.53712, 42.5108 ], [ 12.53719, 42.51079 ], [ 12.5372, 42.51083 ], [ 12.53713, 42.51084 ] ] ] ] } }, 18 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.42486, 42.50892 ], [ 12.4249, 42.50872 ], [ 12.4249, 42.50863 ], [ 12.42481, 42.50859 ], [ 12.42396, 42.50883 ], [ 12.42393, 42.50888 ], [ 12.42392, 42.50894 ], [ 12.42401, 42.50902 ], [ 12.42434, 42.50915 ], [ 12.42451, 42.50915 ], [ 12.42469, 42.50911 ], [ 12.42476, 42.50905 ], [ 12.42486, 42.50892 ] ] ] ] } }, 19 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.42761, 42.51976 ], [ 12.42753, 42.51975 ], [ 12.42745, 42.51967 ], [ 12.42738, 42.51952 ], [ 12.42739, 42.51944 ], [ 12.42744, 42.51939 ], [ 12.42749, 42.51937 ], [ 12.42756, 42.5194 ], [ 12.42766, 42.51957 ], [ 12.42768, 42.51965 ], [ 12.42769, 42.51971 ], [ 12.42765, 42.51975 ], [ 12.42761, 42.51976 ] ] ] ] } }, 20 | { "type": "Feature", "properties": { "natural": "water", "name": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 12.48133, 42.49964 ], [ 12.48156, 42.49977 ], [ 12.4818, 42.49978 ], [ 12.48207, 42.49969 ], [ 12.48225, 42.49949 ], [ 12.48209, 42.49941 ], [ 12.48157, 42.49943 ], [ 12.48149, 42.49945 ], [ 12.48133, 42.49964 ] ] ] ] } } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/data/parking.js: -------------------------------------------------------------------------------- 1 | var Parking = { 2 | "type": "FeatureCollection", 3 | "generator": "overpass-turbo", 4 | "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.", 5 | "timestamp": "2014-05-04T18:46:02Z", 6 | "features": [ 7 | { 8 | "type": "Feature", 9 | "id": "node/761478529", 10 | "properties": { 11 | "@id": "node/761478529", 12 | "amenity": "parking", 13 | "parking": "surface" 14 | }, 15 | "geometry": { 16 | "type": "Point", 17 | "coordinates": [ 18 | 12.5530447, 19 | 42.5580052 20 | ] 21 | } 22 | }, 23 | { 24 | "type": "Feature", 25 | "id": "node/761478656", 26 | "properties": { 27 | "@id": "node/761478656", 28 | "amenity": "parking", 29 | "fee": "no", 30 | "parking": "surface" 31 | }, 32 | "geometry": { 33 | "type": "Point", 34 | "coordinates": [ 35 | 12.5539606, 36 | 42.5578498 37 | ] 38 | } 39 | }, 40 | { 41 | "type": "Feature", 42 | "id": "node/761478704", 43 | "properties": { 44 | "@id": "node/761478704", 45 | "amenity": "parking", 46 | "parking": "surface" 47 | }, 48 | "geometry": { 49 | "type": "Point", 50 | "coordinates": [ 51 | 12.5769166, 52 | 42.5585291 53 | ] 54 | } 55 | }, 56 | { 57 | "type": "Feature", 58 | "id": "node/1036378104", 59 | "properties": { 60 | "@id": "node/1036378104", 61 | "amenity": "parking", 62 | "park_ride": "no", 63 | "parking": "surface" 64 | }, 65 | "geometry": { 66 | "type": "Point", 67 | "coordinates": [ 68 | 12.4768955, 69 | 42.4974104 70 | ] 71 | } 72 | }, 73 | { 74 | "type": "Feature", 75 | "id": "node/1036378856", 76 | "properties": { 77 | "@id": "node/1036378856", 78 | "amenity": "parking", 79 | "park_ride": "no", 80 | "parking": "surface" 81 | }, 82 | "geometry": { 83 | "type": "Point", 84 | "coordinates": [ 85 | 12.4761391, 86 | 42.4968288 87 | ] 88 | } 89 | }, 90 | { 91 | "type": "Feature", 92 | "id": "node/1198813159", 93 | "properties": { 94 | "@id": "node/1198813159", 95 | "amenity": "parking" 96 | }, 97 | "geometry": { 98 | "type": "Point", 99 | "coordinates": [ 100 | 12.5195732, 101 | 42.5355886 102 | ] 103 | } 104 | }, 105 | { 106 | "type": "Feature", 107 | "id": "node/1818881687", 108 | "properties": { 109 | "@id": "node/1818881687", 110 | "amenity": "parking" 111 | }, 112 | "geometry": { 113 | "type": "Point", 114 | "coordinates": [ 115 | 12.3860203, 116 | 42.4592315 117 | ] 118 | } 119 | }, 120 | { 121 | "type": "Feature", 122 | "id": "node/1902905796", 123 | "properties": { 124 | "@id": "node/1902905796", 125 | "amenity": "parking" 126 | }, 127 | "geometry": { 128 | "type": "Point", 129 | "coordinates": [ 130 | 12.617636, 131 | 42.5464726 132 | ] 133 | } 134 | }, 135 | { 136 | "type": "Feature", 137 | "id": "node/1902914101", 138 | "properties": { 139 | "@id": "node/1902914101", 140 | "amenity": "parking" 141 | }, 142 | "geometry": { 143 | "type": "Point", 144 | "coordinates": [ 145 | 12.6223947, 146 | 42.5492746 147 | ] 148 | } 149 | } 150 | ] 151 | }; 152 | -------------------------------------------------------------------------------- /examples/data/river.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "type":"FeatureCollection", 4 | "generator":"JOSM", 5 | "features":[ 6 | { 7 | "type":"Feature", 8 | "properties":{ 9 | "source":"PCN", 10 | "name":"Nera", 11 | "waterway":"river" 12 | }, 13 | "geometry":{ 14 | "type":"LineString", 15 | "coordinates":[ 16 | [ 17 | 12.6186404, 18 | 42.5606258 19 | ], 20 | [ 21 | 12.6186969, 22 | 42.5619256 23 | ], 24 | [ 25 | 12.618582, 26 | 42.5625508 27 | ], 28 | [ 29 | 12.6181222, 30 | 42.5634104 31 | ], 32 | [ 33 | 12.6166721, 34 | 42.564231 35 | ], 36 | [ 37 | 12.6162831, 38 | 42.5642766 39 | ], 40 | [ 41 | 12.6155757, 42 | 42.5641138 43 | ], 44 | [ 45 | 12.6121451, 46 | 42.5623164 47 | ], 48 | [ 49 | 12.6115869, 50 | 42.5622072 51 | ], 52 | [ 53 | 12.6110311, 54 | 42.5621926 55 | ], 56 | [ 57 | 12.6085819, 58 | 42.5625378 59 | ], 60 | [ 61 | 12.6081663, 62 | 42.5625769 63 | ], 64 | [ 65 | 12.6078215, 66 | 42.5624987 67 | ], 68 | [ 69 | 12.6074501, 70 | 42.5622773 71 | ], 72 | [ 73 | 12.6066613, 74 | 42.5613614 75 | ], 76 | [ 77 | 12.6061592, 78 | 42.5610725 79 | ], 80 | [ 81 | 12.6055445, 82 | 42.5609876 83 | ], 84 | [ 85 | 12.6048153, 86 | 42.5610009 87 | ], 88 | [ 89 | 12.6044665, 90 | 42.5610872 91 | ], 92 | [ 93 | 12.60362, 94 | 42.5615349 95 | ], 96 | [ 97 | 12.602375, 98 | 42.5621015 99 | ], 100 | [ 101 | 12.6019063, 102 | 42.5621926 103 | ], 104 | [ 105 | 12.6000142, 106 | 42.5622968 107 | ], 108 | [ 109 | 12.598626, 110 | 42.5627136 111 | ], 112 | [ 113 | 12.5979541, 114 | 42.5630197 115 | ], 116 | [ 117 | 12.5972919, 118 | 42.5631113 119 | ], 120 | [ 121 | 12.5970402, 122 | 42.5629972 123 | ], 124 | [ 125 | 12.5962907, 126 | 42.5620819 127 | ], 128 | [ 129 | 12.5960177, 130 | 42.5619191 131 | ], 132 | [ 133 | 12.5953015, 134 | 42.561867 135 | ], 136 | [ 137 | 12.5948064, 138 | 42.5617628 139 | ], 140 | [ 141 | 12.5923837, 142 | 42.5601868 143 | ], 144 | [ 145 | 12.5919682, 146 | 42.5600891 147 | ], 148 | [ 149 | 12.5907038, 150 | 42.5593532 151 | ], 152 | [ 153 | 12.5897754, 154 | 42.5590992 155 | ], 156 | [ 157 | 12.587229, 158 | 42.5591969 159 | ], 160 | [ 161 | 12.5863094, 162 | 42.5590992 163 | ], 164 | [ 165 | 12.5850451, 166 | 42.5587475 167 | ], 168 | [ 169 | 12.5840459, 170 | 42.558246 171 | ], 172 | [ 173 | 12.5824389, 174 | 42.5570938 175 | ], 176 | [ 177 | 12.5817208, 178 | 42.5566365 179 | ], 180 | [ 181 | 12.5809303, 182 | 42.5563235 183 | ], 184 | [ 185 | 12.5805745, 186 | 42.5562536 187 | ], 188 | [ 189 | 12.5802582, 190 | 42.556285 191 | ], 192 | [ 193 | 12.5799579, 194 | 42.5563846 195 | ], 196 | [ 197 | 12.578913, 198 | 42.5570823 199 | ], 200 | [ 201 | 12.5783448, 202 | 42.5572219 203 | ], 204 | [ 205 | 12.5771897, 206 | 42.5574282 207 | ], 208 | [ 209 | 12.5716778, 210 | 42.5579694 211 | ], 212 | [ 213 | 12.5680119, 214 | 42.5586336 215 | ], 216 | [ 217 | 12.5659387, 218 | 42.5593929 219 | ], 220 | [ 221 | 12.565144, 222 | 42.5596547 223 | ], 224 | [ 225 | 12.5647247, 226 | 42.5597348 227 | ], 228 | [ 229 | 12.5642665, 230 | 42.5598032 231 | ], 232 | [ 233 | 12.5631155, 234 | 42.559803 235 | ], 236 | [ 237 | 12.5619068, 238 | 42.559392 239 | ], 240 | [ 241 | 12.5614569, 242 | 42.5591293 243 | ], 244 | [ 245 | 12.5608787, 246 | 42.5584762 247 | ], 248 | [ 249 | 12.560795, 250 | 42.5574177 251 | ], 252 | [ 253 | 12.5599882, 254 | 42.5550599 255 | ], 256 | [ 257 | 12.5597037, 258 | 42.554703 259 | ], 260 | [ 261 | 12.5592764, 262 | 42.5543979 263 | ], 264 | [ 265 | 12.5572492, 266 | 42.5542485 267 | ], 268 | [ 269 | 12.5559639, 270 | 42.5542224 271 | ], 272 | [ 273 | 12.5554465, 274 | 42.5541473 275 | ], 276 | [ 277 | 12.5549407, 278 | 42.5539542 279 | ], 280 | [ 281 | 12.5547068, 282 | 42.5537667 283 | ], 284 | [ 285 | 12.5545775, 286 | 42.5535641 287 | ], 288 | [ 289 | 12.5544759, 290 | 42.552871 291 | ], 292 | [ 293 | 12.5545654, 294 | 42.5521642 295 | ], 296 | [ 297 | 12.5548648, 298 | 42.55169 299 | ], 300 | [ 301 | 12.5556811, 302 | 42.551221 303 | ], 304 | [ 305 | 12.5569513, 306 | 42.5506383 307 | ], 308 | [ 309 | 12.5578389, 310 | 42.5499148 311 | ], 312 | [ 313 | 12.5585933, 314 | 42.549154 315 | ], 316 | [ 317 | 12.5593196, 318 | 42.5482544 319 | ], 320 | [ 321 | 12.5599125, 322 | 42.5473671 323 | ], 324 | [ 325 | 12.5601298, 326 | 42.5465652 327 | ], 328 | [ 329 | 12.5600647, 330 | 42.5461979 331 | ], 332 | [ 333 | 12.5599217, 334 | 42.5458577 335 | ], 336 | [ 337 | 12.5596663, 338 | 42.5455339 339 | ], 340 | [ 341 | 12.5593451, 342 | 42.5452498 343 | ], 344 | [ 345 | 12.5589264, 346 | 42.5450168 347 | ], 348 | [ 349 | 12.5559205, 350 | 42.5441244 351 | ], 352 | [ 353 | 12.5545679, 354 | 42.5436423 355 | ], 356 | [ 357 | 12.5528533, 358 | 42.5429392 359 | ], 360 | [ 361 | 12.5524651, 362 | 42.5429586 363 | ], 364 | [ 365 | 12.5520381, 366 | 42.5430757 367 | ], 368 | [ 369 | 12.5517631, 370 | 42.543392 371 | ], 372 | [ 373 | 12.5509144, 374 | 42.5464414 375 | ], 376 | [ 377 | 12.5506237, 378 | 42.5468665 379 | ], 380 | [ 381 | 12.5501973, 382 | 42.5472964 383 | ], 384 | [ 385 | 12.5497677, 386 | 42.5474837 387 | ], 388 | [ 389 | 12.5495066, 390 | 42.5475508 391 | ], 392 | [ 393 | 12.5492284, 394 | 42.547547 395 | ], 396 | [ 397 | 12.5435413, 398 | 42.5448536 399 | ], 400 | [ 401 | 12.5422342, 402 | 42.5440212 403 | ], 404 | [ 405 | 12.5412522, 406 | 42.5436527 407 | ], 408 | [ 409 | 12.5397342, 410 | 42.5433211 411 | ], 412 | [ 413 | 12.5391832, 414 | 42.5432828 415 | ], 416 | [ 417 | 12.5383804, 418 | 42.543366 419 | ], 420 | [ 421 | 12.5374622, 422 | 42.5433627 423 | ], 424 | [ 425 | 12.5369992, 426 | 42.5431694 427 | ], 428 | [ 429 | 12.5365902, 430 | 42.542826 431 | ], 432 | [ 433 | 12.5362597, 434 | 42.5422176 435 | ], 436 | [ 437 | 12.5362691, 438 | 42.5417211 439 | ], 440 | [ 441 | 12.537142, 442 | 42.5377542 443 | ], 444 | [ 445 | 12.5371109, 446 | 42.5373606 447 | ], 448 | [ 449 | 12.5370123, 450 | 42.5371817 451 | ], 452 | [ 453 | 12.5368641, 454 | 42.5370306 455 | ], 456 | [ 457 | 12.5365873, 458 | 42.5368685 459 | ], 460 | [ 461 | 12.5359601, 462 | 42.5366661 463 | ], 464 | [ 465 | 12.5328691, 466 | 42.5368379 467 | ], 468 | [ 469 | 12.5318709, 470 | 42.5368039 471 | ], 472 | [ 473 | 12.5311499, 474 | 42.5364598 475 | ], 476 | [ 477 | 12.5308596, 478 | 42.5361477 479 | ], 480 | [ 481 | 12.5305417, 482 | 42.5358967 483 | ], 484 | [ 485 | 12.5303879, 486 | 42.535583 487 | ], 488 | [ 489 | 12.530632, 490 | 42.5351572 491 | ], 492 | [ 493 | 12.5311903, 494 | 42.5348261 495 | ], 496 | [ 497 | 12.5352488, 498 | 42.5337852 499 | ], 500 | [ 501 | 12.5357949, 502 | 42.5337713 503 | ], 504 | [ 505 | 12.5369312, 506 | 42.5340372 507 | ], 508 | [ 509 | 12.5375318, 510 | 42.534026 511 | ], 512 | [ 513 | 12.5383248, 514 | 42.5339463 515 | ], 516 | [ 517 | 12.5387768, 518 | 42.533752 519 | ], 520 | [ 521 | 12.5397779, 522 | 42.5334314 523 | ], 524 | [ 525 | 12.5406108, 526 | 42.5330203 527 | ], 528 | [ 529 | 12.5408316, 530 | 42.5328367 531 | ], 532 | [ 533 | 12.5409443, 534 | 42.5325698 535 | ], 536 | [ 537 | 12.5409455, 538 | 42.5322887 539 | ], 540 | [ 541 | 12.5406076, 542 | 42.53201 543 | ], 544 | [ 545 | 12.5395856, 546 | 42.5313824 547 | ], 548 | [ 549 | 12.5388221, 550 | 42.5306995 551 | ], 552 | [ 553 | 12.5384665, 554 | 42.5301971 555 | ], 556 | [ 557 | 12.5384307, 558 | 42.5299597 559 | ], 560 | [ 561 | 12.5385687, 562 | 42.5295923 563 | ], 564 | [ 565 | 12.5394242, 566 | 42.528623 567 | ], 568 | [ 569 | 12.5397244, 570 | 42.5281252 571 | ], 572 | [ 573 | 12.5397502, 574 | 42.5279358 575 | ], 576 | [ 577 | 12.539692, 578 | 42.5277958 579 | ], 580 | [ 581 | 12.539434, 582 | 42.5275435 583 | ], 584 | [ 585 | 12.5391978, 586 | 42.5274338 587 | ], 588 | [ 589 | 12.5388606, 590 | 42.5273928 591 | ], 592 | [ 593 | 12.5383995, 594 | 42.5274225 595 | ], 596 | [ 597 | 12.5380083, 598 | 42.527543 599 | ], 600 | [ 601 | 12.5371721, 602 | 42.5279527 603 | ], 604 | [ 605 | 12.5364664, 606 | 42.5283797 607 | ], 608 | [ 609 | 12.5358302, 610 | 42.5285236 611 | ], 612 | [ 613 | 12.5354834, 614 | 42.5285515 615 | ], 616 | [ 617 | 12.5345964, 618 | 42.5284496 619 | ], 620 | [ 621 | 12.5338834, 622 | 42.5281023 623 | ], 624 | [ 625 | 12.5328833, 626 | 42.5275298 627 | ], 628 | [ 629 | 12.5316105, 630 | 42.5269949 631 | ], 632 | [ 633 | 12.5305544, 634 | 42.5267734 635 | ], 636 | [ 637 | 12.528793, 638 | 42.5265767 639 | ], 640 | [ 641 | 12.5277884, 642 | 42.5265158 643 | ], 644 | [ 645 | 12.5267429, 646 | 42.5265677 647 | ], 648 | [ 649 | 12.5256672, 650 | 42.526764 651 | ], 652 | [ 653 | 12.5250627, 654 | 42.5271145 655 | ], 656 | [ 657 | 12.5239824, 658 | 42.528086 659 | ], 660 | [ 661 | 12.5230887, 662 | 42.5285307 663 | ], 664 | [ 665 | 12.5213597, 666 | 42.5289171 667 | ], 668 | [ 669 | 12.5208892, 670 | 42.5288857 671 | ], 672 | [ 673 | 12.5202131, 674 | 42.5286617 675 | ], 676 | [ 677 | 12.5178865, 678 | 42.5271593 679 | ], 680 | [ 681 | 12.5172278, 682 | 42.5265781 683 | ], 684 | [ 685 | 12.5169674, 686 | 42.5260645 687 | ], 688 | [ 689 | 12.5165189, 690 | 42.5258091 691 | ], 692 | [ 693 | 12.5159752, 694 | 42.5255495 695 | ], 696 | [ 697 | 12.5152689, 698 | 42.5253751 699 | ], 700 | [ 701 | 12.5133933, 702 | 42.5253678 703 | ], 704 | [ 705 | 12.5128708, 706 | 42.5252276 707 | ], 708 | [ 709 | 12.5122798, 710 | 42.524984 711 | ], 712 | [ 713 | 12.5117518, 714 | 42.5246391 715 | ], 716 | [ 717 | 12.5112313, 718 | 42.5241566 719 | ], 720 | [ 721 | 12.5107415, 722 | 42.5231693 723 | ], 724 | [ 725 | 12.5108293, 726 | 42.5225079 727 | ], 728 | [ 729 | 12.5111438, 730 | 42.521904 731 | ], 732 | [ 733 | 12.5115671, 734 | 42.5205738 735 | ], 736 | [ 737 | 12.5116475, 738 | 42.5190767 739 | ], 740 | [ 741 | 12.511873, 742 | 42.518259 743 | ], 744 | [ 745 | 12.5121936, 746 | 42.5174868 747 | ], 748 | [ 749 | 12.5129464, 750 | 42.5164552 751 | ], 752 | [ 753 | 12.5136984, 754 | 42.5150087 755 | ], 756 | [ 757 | 12.513989, 758 | 42.5142951 759 | ], 760 | [ 761 | 12.5143286, 762 | 42.5130826 763 | ], 764 | [ 765 | 12.5140378, 766 | 42.5121368 767 | ], 768 | [ 769 | 12.5136574, 770 | 42.5114523 771 | ], 772 | [ 773 | 12.5136847, 774 | 42.5107095 775 | ], 776 | [ 777 | 12.5138429, 778 | 42.5094438 779 | ], 780 | [ 781 | 12.5134288, 782 | 42.507986 783 | ], 784 | [ 785 | 12.5134581, 786 | 42.507445 787 | ], 788 | [ 789 | 12.5139315, 790 | 42.5062213 791 | ], 792 | [ 793 | 12.5141157, 794 | 42.5055066 795 | ], 796 | [ 797 | 12.513921, 798 | 42.5051202 799 | ], 800 | [ 801 | 12.5132713, 802 | 42.5047453 803 | ], 804 | [ 805 | 12.5128878, 806 | 42.5042893 807 | ], 808 | [ 809 | 12.5126143, 810 | 42.5038334 811 | ], 812 | [ 813 | 12.5124216, 814 | 42.5036824 815 | ], 816 | [ 817 | 12.5121611, 818 | 42.5035467 819 | ], 820 | [ 821 | 12.5104083, 822 | 42.503056 823 | ], 824 | [ 825 | 12.5097696, 826 | 42.503056 827 | ], 828 | [ 829 | 12.5085951, 830 | 42.5032195 831 | ], 832 | [ 833 | 12.5078864, 834 | 42.503208 835 | ], 836 | [ 837 | 12.5058645, 838 | 42.5026941 839 | ], 840 | [ 841 | 12.5036337, 842 | 42.5018878 843 | ], 844 | [ 845 | 12.5027611, 846 | 42.5014545 847 | ], 848 | [ 849 | 12.5014106, 850 | 42.5003811 851 | ], 852 | [ 853 | 12.5003658, 854 | 42.4992199 855 | ], 856 | [ 857 | 12.499396, 858 | 42.4984748 859 | ], 860 | [ 861 | 12.4990587, 862 | 42.4979814 863 | ], 864 | [ 865 | 12.4987941, 866 | 42.4977595 867 | ], 868 | [ 869 | 12.4982346, 870 | 42.4974864 871 | ], 872 | [ 873 | 12.4976303, 874 | 42.4973085 875 | ], 876 | [ 877 | 12.4963744, 878 | 42.4971527 879 | ], 880 | [ 881 | 12.4954974, 882 | 42.4972485 883 | ], 884 | [ 885 | 12.4950862, 886 | 42.4971537 887 | ], 888 | [ 889 | 12.4946586, 890 | 42.4971498 891 | ], 892 | [ 893 | 12.4939477, 894 | 42.497232 895 | ], 896 | [ 897 | 12.4934287, 898 | 42.497358 899 | ], 900 | [ 901 | 12.4921477, 902 | 42.4982158 903 | ], 904 | [ 905 | 12.4914262, 906 | 42.4987637 907 | ], 908 | [ 909 | 12.4904024, 910 | 42.4993571 911 | ], 912 | [ 913 | 12.4881429, 914 | 42.5013301 915 | ], 916 | [ 917 | 12.4877477, 918 | 42.5014522 919 | ], 920 | [ 921 | 12.4871752, 922 | 42.5014421 923 | ], 924 | [ 925 | 12.4867017, 926 | 42.5013493 927 | ], 928 | [ 929 | 12.4860942, 930 | 42.500969 931 | ], 932 | [ 933 | 12.4845216, 934 | 42.5001858 935 | ], 936 | [ 937 | 12.4840094, 938 | 42.4997801 939 | ], 940 | [ 941 | 12.4831869, 942 | 42.4995892 943 | ], 944 | [ 945 | 12.481568, 946 | 42.499536 947 | ], 948 | [ 949 | 12.4806148, 950 | 42.499306 951 | ], 952 | [ 953 | 12.4802128, 954 | 42.4988085 955 | ], 956 | [ 957 | 12.4801612, 958 | 42.498463 959 | ], 960 | [ 961 | 12.4799997, 962 | 42.4980535 963 | ], 964 | [ 965 | 12.4793206, 966 | 42.4970728 967 | ], 968 | [ 969 | 12.4785868, 970 | 42.4957445 971 | ], 972 | [ 973 | 12.4781205, 974 | 42.4950733 975 | ], 976 | [ 977 | 12.4775026, 978 | 42.4945138 979 | ], 980 | [ 981 | 12.4770916, 982 | 42.4941924 983 | ], 984 | [ 985 | 12.4759841, 986 | 42.4936347 987 | ], 988 | [ 989 | 12.4752169, 990 | 42.4934514 991 | ], 992 | [ 993 | 12.4748117, 994 | 42.4932721 995 | ], 996 | [ 997 | 12.4742822, 998 | 42.4929614 999 | ], 1000 | [ 1001 | 12.4738284, 1002 | 42.4927861 1003 | ], 1004 | [ 1005 | 12.4727154, 1006 | 42.4925192 1007 | ] 1008 | ] 1009 | } 1010 | } 1011 | ] 1012 | } 1013 | -------------------------------------------------------------------------------- /examples/dynamic-layers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 26 | 27 | 28 | 29 |

Leaflet Panel Layers

30 |

Dynamic Example: build panel dynamically from JSON config

31 |
32 | 33 |
34 |
35 |
36 |
37 | baselayers 38 |
39 |
40 |
41 | overlayers 42 |
43 | 44 | 45 | 46 | Github 47 | 48 | 49 | 50 | 51 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /examples/embedded-layers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | 19 |

Leaflet Panel Layers

20 |

Embedded JSON Example: build panel and layers from GeoJSON

21 |
22 |
23 | 24 | 25 | 26 | 27 | Github 28 | 29 | 30 | 31 | 32 | 33 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /examples/group-layers-exclusive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

Leaflet Panel Layers

16 |

Groups Example: exclusive groups of overlayers in different groups

17 |
18 |
19 | 20 | 21 | 22 | Github 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /examples/group-layers-selector-group.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

Leaflet Panel Layers

16 |

Groups Example: selector all layers in a group

17 |
18 |
19 | 20 | 21 | 22 | Github 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /examples/group-layers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

Leaflet Panel Layers

16 |

Groups Example: multiple groups of layers

17 |
18 |
19 | 20 | 21 | 22 | Github 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /examples/icon-layer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Leaflet Panel Layers

14 |

Points Of Interest Example: list multiple base layers and overlays with Custom icon

15 |
16 |
17 | 18 | 19 | 20 | Github 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /examples/icons.css: -------------------------------------------------------------------------------- 1 | .icon { 2 | display: inline-block; 3 | margin: 2px; 4 | height: 16px; 5 | width: 16px; 6 | background-color: #ccc; 7 | } 8 | 9 | /* ICONS */ 10 | .icon-bar { 11 | background: url('images/icons/bar.png') center center no-repeat; 12 | } 13 | .icon-fuel { 14 | background: url('images/icons/fuel.png') center center no-repeat; 15 | } 16 | .icon-parking { 17 | background: url('images/icons/parking.png') center center no-repeat; 18 | } 19 | .icon-drinking_water { 20 | background: url('images/icons/drinking_water.png') center center no-repeat; 21 | } 22 | 23 | /* MARKERS */ 24 | .leaflet-marker-icon { 25 | padding: 2px; 26 | text-align: center; 27 | } 28 | .marker-bar { 29 | background: url('images/markers/bar.png') center center no-repeat; 30 | } 31 | .marker-fuel { 32 | background: url('images/markers/fuel.png') center center no-repeat; 33 | } 34 | .marker-parking { 35 | background: url('images/markers/parking.png') center center no-repeat; 36 | } 37 | .marker-drinking_water { 38 | background: url('images/markers/drinking_water.png') center center no-repeat; 39 | } 40 | -------------------------------------------------------------------------------- /examples/images/icons/bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/icons/bar.png -------------------------------------------------------------------------------- /examples/images/icons/drinking_water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/icons/drinking_water.png -------------------------------------------------------------------------------- /examples/images/icons/fuel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/icons/fuel.png -------------------------------------------------------------------------------- /examples/images/icons/parking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/icons/parking.png -------------------------------------------------------------------------------- /examples/images/leaflet-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/leaflet-panel.png -------------------------------------------------------------------------------- /examples/images/markers/bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/markers/bar.png -------------------------------------------------------------------------------- /examples/images/markers/drinking_water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/markers/drinking_water.png -------------------------------------------------------------------------------- /examples/images/markers/fuel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/markers/fuel.png -------------------------------------------------------------------------------- /examples/images/markers/parking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/markers/parking.png -------------------------------------------------------------------------------- /examples/images/screenshot/imagen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/screenshot/imagen.png -------------------------------------------------------------------------------- /examples/images/screenshot/leaflet-panel-layers-layout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanocudini/leaflet-panel-layers/9d3f7ec6d5ad92b8e4e8de5b655443ce8f0596a0/examples/images/screenshot/leaflet-panel-layers-layout.jpg -------------------------------------------------------------------------------- /examples/layer-thumbnails.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 27 | 28 | 29 | 30 |

Leaflet Panel Layers

31 |

Build custom panel layer contains thumbnail by tile layer

32 |
33 |
34 | 35 | 36 | 37 | Github 38 | 39 | 40 | 41 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /examples/multiple-panels.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 22 | 23 | 24 | 25 |

Leaflet Panel Layers

26 |

Multiple panels in compact mode

27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | > 35 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /examples/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background:#b5d0d0; 3 | color:#285585; 4 | font-family:Arial; 5 | } 6 | body#home { 7 | background:url('images/leaflet-panel.png') no-repeat top left #b5d0d0; 8 | margin-left:200px; 9 | } 10 | 11 | a { 12 | color:#1978cf; 13 | } 14 | a:hover { 15 | color:#fff; 16 | } 17 | h2, h3, h4 { 18 | white-space:nowrap; 19 | margin:1em 0 0 0; 20 | } 21 | h3 a, 22 | h3 a:hover { 23 | text-decoration:none; 24 | } 25 | #desc { 26 | float: left; 27 | margin-bottom: 1em; 28 | position: relative; 29 | white-space:nowrap; 30 | font-size:1em; 31 | } 32 | #map { 33 | border-radius:.125em; 34 | border:2px solid #1978cf; 35 | box-shadow: 0 0 8px #999; 36 | float:left; 37 | width:100%; 38 | max-width: 600px; 39 | height:600px; 40 | } 41 | label { 42 | float: left; 43 | } 44 | pre { 45 | font-family: "Courier New"; 46 | font-size: .85em; 47 | color: #333; 48 | float: left; 49 | clear: both; 50 | padding: 10px; 51 | margin: 10px 0; 52 | background-color: #eee; 53 | box-shadow: inset 2px 2px 4px #ccc; 54 | } 55 | #copy { 56 | position:fixed; 57 | z-index:1000; 58 | right:150px; 59 | top:-8px; 60 | font-size:.85em; 61 | padding:8px 8px 2px 8px; 62 | background: #323b44; 63 | border: 2px solid #737c85; 64 | border-radius:.7em; 65 | opacity: 0.9; 66 | box-shadow:0 0 8px #5f7182; 67 | color:#eee 68 | } 69 | #copy a { 70 | color:#ccc; 71 | text-decoration:none 72 | } 73 | #copy a:hover { 74 | color:#fff 75 | } 76 | #ribbon { 77 | position: absolute; 78 | top: 0; 79 | right: 0; 80 | border: 0; 81 | filter: alpha(opacity=80); 82 | -khtml-opacity: .8; 83 | -moz-opacity: .8; 84 | opacity: .8; 85 | } 86 | 87 | #comments { 88 | margin-top:50px; 89 | clear:both; 90 | } 91 | 92 | #config { 93 | margin: 0 10px; 94 | padding: 0; 95 | height: 370px; 96 | width: 600px; 97 | font-size: 10px; 98 | box-shadow: inset 2px 2px 4px #ccc; 99 | border: 2px solid #1978cf; 100 | } 101 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Panel Layers 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Leaflet Panel Layers

12 |

13 | Leaflet Control Layers extended for group of layers and icons legend. 14 | 15 |
16 | Other useful stuff for Web Mapping... 17 |

18 | 19 |
20 | If any of these open source solutions help your work and saved you time consider sending a donation 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 |
33 |

Features

34 |
    35 |
  • Grouping of layers
  • 36 |
  • Custom layer item
  • 37 |
  • Auto collapsible layers list
  • 38 |
  • Infinite scrollable list of layers
  • 39 |
  • Configurable panel from JSON
  • 40 |
  • Grouping of multiple layers
  • 41 |
  • Embeddable GeoJSON layers
  • 42 |
  • Add layers dynamically
  • 43 |
44 |

Examples

45 | 58 |
59 | 60 |
61 |

Code repositories

62 | Github.com 63 |
64 | Node Packaged Module 65 |
66 | Bitbucket.org 67 |
68 | 70 | 71 |

Website

72 | opengeo.tech/maps/leaflet-panel-layers 73 |
74 | 75 |

Download

76 | 81 |
82 | 83 | Github 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2020 Stefano Cudini 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leaflet-panel-layers", 3 | "version": "1.3.1", 4 | "description": "Leaflet Control Layers extended for group of layers and icons legend", 5 | "repository": { 6 | "type": "git", 7 | "url": "git@github.com:stefanocudini/leaflet-panel-layers.git" 8 | }, 9 | "homepage": "https://opengeo.tech/maps/leaflet-panel-layers/", 10 | "main": "dist/leaflet-panel-layers.src.js", 11 | "author": { 12 | "name": "Stefano Cudini", 13 | "email": "stefano.cudini@gmail.com", 14 | "url": "https://opengeo.tech/" 15 | }, 16 | "license": "MIT", 17 | "keywords": [ 18 | "gis", 19 | "map", 20 | "panel", 21 | "leaflet" 22 | ], 23 | "scripts": { 24 | "build": "npx grunt" 25 | }, 26 | "dependencies": { 27 | "leaflet": "~1.6.0" 28 | }, 29 | "devDependencies": { 30 | "grunt": "^1.4.1", 31 | "grunt-banner": "^0.6.0", 32 | "grunt-contrib-clean": "^2.0.0", 33 | "grunt-contrib-concat": "^2.0.0", 34 | "grunt-contrib-cssmin": "^4.0.0", 35 | "grunt-contrib-jshint": "^3.2.0", 36 | "grunt-contrib-uglify": "^5.0.1", 37 | "grunt-contrib-watch": "^1.1.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/leaflet-panel-layers.css: -------------------------------------------------------------------------------- 1 | /* PANEL LAYERS */ 2 | .leaflet-panel-layers .leaflet-panel-layers-list { 3 | display: block; 4 | } 5 | .leaflet-panel-layers.expanded .leaflet-panel-layers-list { 6 | display: block; 7 | } 8 | .leaflet-top.leaflet-right .leaflet-panel-layers:not(.compact) { 9 | margin: 0; 10 | } 11 | .leaflet-panel-layers { 12 | width: 30px; 13 | min-width: 30px; 14 | } 15 | .leaflet-panel-layers.expanded { 16 | width: auto; 17 | overflow-x: hidden; 18 | overflow-y: auto; 19 | } 20 | .leaflet-panel-layers.expanded .leaflet-panel-layers-list { 21 | display: block; 22 | } 23 | .leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-title > span, 24 | .leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-selector, 25 | .leaflet-panel-layers:not(.expanded) .leaflet-panel-layers-grouplabel { 26 | display: none; 27 | } 28 | .leaflet-panel-layers-separator { 29 | clear: both; 30 | } 31 | 32 | .leaflet-panel-layers-item .leaflet-panel-layers-title { 33 | display: block; 34 | white-space: nowrap; 35 | float: none; 36 | cursor: pointer; 37 | } 38 | .leaflet-panel-layers-title .leaflet-panel-layers-selector { 39 | float: right; 40 | } 41 | 42 | .leaflet-panel-layers-group { 43 | position: relative; 44 | width: auto; 45 | height: auto; 46 | clear: both; 47 | overflow: hidden; 48 | } 49 | .leaflet-panel-layers-icon { 50 | text-align: center; 51 | float: left; 52 | } 53 | .leaflet-panel-layers-group.collapsible:not(.expanded) { 54 | height: 20px; 55 | } 56 | .leaflet-panel-layers-group.collapsible:not(.expanded) .leaflet-panel-layers-grouplabel { 57 | height: 20px; 58 | overflow: hidden; 59 | } 60 | .leaflet-panel-layers-group.collapsible:not(.expanded) .leaflet-panel-layers-item { 61 | display: none; 62 | } 63 | .leaflet-panel-layers-group.collapsible .leaflet-panel-layers-grouplabel { 64 | display: block; 65 | cursor: pointer; 66 | -webkit-touch-callout: none; 67 | -webkit-user-select: none; 68 | -khtml-user-select: none; 69 | -moz-user-select: none; 70 | -ms-user-select: none; 71 | user-select: none; 72 | } 73 | .leaflet-panel-layers-item { 74 | display: block; 75 | height: auto; 76 | clear: both; 77 | white-space: nowrap; 78 | -webkit-touch-callout: none; 79 | -webkit-user-select: none; 80 | -khtml-user-select: none; 81 | -moz-user-select: none; 82 | -ms-user-select: none; 83 | user-select: none; 84 | } 85 | .leaflet-panel-layers-overlays .leaflet-panel-layers-item { 86 | white-space: pre-wrap; 87 | white-space: -moz-pre-wrap; 88 | white-space: -pre-wrap; 89 | white-space: -o-pre-wrap; 90 | word-wrap: break-word; 91 | width: auto; 92 | display: block; 93 | } 94 | .leaflet-panel-layers-base .leaflet-panel-layers-selector { 95 | float: left; 96 | } 97 | .leaflet-panel-layers-overlays .leaflet-panel-layers-selector { 98 | float: right; 99 | } 100 | .leaflet-panel-layers.expanded .leaflet-panel-layers-overlays input { 101 | display: block; 102 | } 103 | .leaflet-control-layers-selector { 104 | float: left; 105 | } 106 | 107 | .leaflet-panel-layers-grouplabel .leaflet-panel-layers-selector { 108 | visibility: hidden; 109 | position: absolute; 110 | top: 1px; 111 | right: 7px; 112 | } 113 | 114 | .leaflet-panel-layers-group:hover .leaflet-panel-layers-selector { 115 | visibility: visible; 116 | } 117 | 118 | 119 | 120 | /* theming style */ 121 | 122 | .leaflet-panel-layers { 123 | padding: 4px; 124 | background: rgba(255,255,255,0.5); 125 | box-shadow: -2px 0 8px rgba(0,0,0,0.3); 126 | } 127 | .leaflet-panel-layers.expanded { 128 | padding: 4px; 129 | } 130 | .leaflet-panel-layers-selector { 131 | position: relative; 132 | top: 1px; 133 | margin-top: 2px; 134 | } 135 | .leaflet-panel-layers-separator { 136 | height: 8px; 137 | margin: 12px 4px 0 4px; 138 | border-top:1px solid rgba(0,0,0,0.3); 139 | } 140 | .leaflet-panel-layers-item { 141 | min-height: 20px; 142 | } 143 | .leaflet-panel-layers-margin { 144 | height: 25px; 145 | } 146 | .leaflet-panel-layers-icon { 147 | line-height: 20px; 148 | display: inline-block; 149 | height: 20px; 150 | width: 20px; 151 | background: #fff; 152 | } 153 | .leaflet-panel-layers-group.collapsible .leaflet-panel-layers-icon:first-child { 154 | min-width: 20px; 155 | font-size: 16px; 156 | text-align: center; 157 | background: none; 158 | } 159 | .leaflet-panel-layers-group { 160 | padding: 2px 4px; 161 | margin-bottom: 4px; 162 | border: 1px solid rgba(0,0,0,0.3); 163 | background: rgba(255,255,255,0.6); 164 | border-radius: 3px; 165 | } 166 | .leaflet-panel-layers-overlays .leaflet-panel-layers-item { 167 | margin-bottom: 4px; 168 | padding: 2px; 169 | background: #fff; 170 | border: 1px solid rgba(0,0,0,0.3); 171 | border-radius: 4px; 172 | } 173 | .leaflet-panel-layers-overlays .leaflet-panel-layers-item:hover { 174 | border: 1px solid #888; 175 | cursor: pointer; 176 | } 177 | -------------------------------------------------------------------------------- /src/leaflet-panel-layers.js: -------------------------------------------------------------------------------- 1 | (function (factory) { 2 | if (typeof define === 'function' && define.amd) { 3 | //AMD 4 | define(['leaflet'], factory); 5 | } else if (typeof module !== 'undefined') { 6 | // Node/CommonJS 7 | module.exports = factory(require('leaflet')); 8 | } else { 9 | // Browser globals 10 | if (typeof window.L === 'undefined') 11 | throw 'Leaflet must be loaded first'; 12 | factory(window.L); 13 | } 14 | })(function (L) { 15 | 16 | L.Control.PanelLayers = L.Control.Layers.extend({ 17 | 18 | includes: L.version[0]==='1' ? L.Evented.prototype : L.Mixin.Events, 19 | 20 | options: { 21 | compact: false, 22 | compactOffset: 0, 23 | collapsed: false, 24 | autoZIndex: true, 25 | collapsibleGroups: false, 26 | selectorGroup: false, //select all layer of a group 27 | buildItem: null, //function that return row item html node(or html string) 28 | title: '', //title of panel 29 | className: '', //additional class name for panel 30 | position: 'topright' 31 | }, 32 | 33 | initialize: function (baseLayers, overlays, options) { 34 | L.setOptions(this, options); 35 | this._layers = []; 36 | this._groups = {}; 37 | this._items = {}; 38 | this._layersActives = []; 39 | this._lastZIndex = 0; 40 | this._handlingClick = false; 41 | 42 | this.className = 'leaflet-panel-layers'; 43 | 44 | var i, n, isCollapsed; 45 | 46 | for (i in baseLayers) { 47 | if (baseLayers[i].group && baseLayers[i].layers) { 48 | isCollapsed = baseLayers[i].collapsed || false; 49 | for (n in baseLayers[i].layers) 50 | this._addLayer(baseLayers[i].layers[n], false, baseLayers[i].group, isCollapsed); 51 | } 52 | else 53 | this._addLayer(baseLayers[i], false); 54 | } 55 | 56 | for (i in overlays) { 57 | if (overlays[i].group && overlays[i].layers) { 58 | isCollapsed = overlays[i].collapsed || false; 59 | for (n in overlays[i].layers) 60 | this._addLayer(overlays[i].layers[n], true, overlays[i].group, isCollapsed); 61 | } 62 | else 63 | this._addLayer(overlays[i], true); 64 | } 65 | }, 66 | 67 | onAdd: function (map) { 68 | 69 | var self = this; 70 | 71 | for (var i in this._layersActives) { 72 | map.addLayer(this._layersActives[i]); 73 | } 74 | 75 | L.Control.Layers.prototype.onAdd.call(this, map); 76 | 77 | this._map.on('resize', function(e) { 78 | self._updateHeight(e.newSize.y); 79 | }); 80 | 81 | // update group checkboxes 82 | this._onInputClick(); 83 | 84 | return this._container; 85 | }, 86 | 87 | //TODO addBaseLayerGroup 88 | //TODO addOverlayGroup 89 | 90 | addBaseLayer: function (layer, name, group) { 91 | layer.name = name || layer.name || ''; 92 | this._addLayer(layer, false, group); 93 | this._update(); 94 | return this; 95 | }, 96 | 97 | addOverlay: function (layer, name, group) { 98 | layer.name = name || layer.name || ''; 99 | this._addLayer(layer, true, group); 100 | this._update(); 101 | return this; 102 | }, 103 | 104 | removeLayer: function (layerDef) { 105 | var layer = layerDef.hasOwnProperty('layer') ? this._layerFromDef(layerDef) : layerDef; 106 | 107 | this._map.removeLayer(layer); 108 | 109 | L.Control.Layers.prototype.removeLayer.call(this, layer); 110 | return this; 111 | }, 112 | 113 | clearLayers: function () { 114 | for (var i = 0; i < this._layers.length; i++) { 115 | this.removeLayer(this._layers[i]); 116 | } 117 | }, 118 | 119 | _layerFromDef: function (layerDef) { 120 | for (var i = 0; i < this._layers.length; i++) { 121 | var id = L.stamp(this._layers[i].layer); 122 | //TODO add more conditions to comparing definitions 123 | if (this._getLayer(id).name === layerDef.name) 124 | return this._getLayer(id).layer; 125 | } 126 | }, 127 | 128 | _update: function () { 129 | this._groups = {}; 130 | this._items = {}; 131 | L.Control.Layers.prototype._update.call(this); 132 | }, 133 | 134 | _getLayer: function (id) { 135 | for (var i = 0; i < this._layers.length; i++) { 136 | if (this._layers[i] && this._layers[i].id == id) { 137 | return this._layers[i]; 138 | } 139 | } 140 | }, 141 | 142 | _addLayer: function (layerDef, overlay, group, isCollapsed) { 143 | 144 | if(!layerDef.layer) 145 | throw new Error('layer not defined in item: '+(layerDef.name||'')); 146 | 147 | if (!(layerDef.layer instanceof L.Class) && 148 | (layerDef.layer.type && layerDef.layer.args)) { 149 | layerDef.layer = this._getPath(L, layerDef.layer.type).apply(L, layerDef.layer.args); 150 | } 151 | 152 | if(!layerDef.hasOwnProperty('id')) 153 | layerDef.id = L.stamp(layerDef.layer); 154 | 155 | if(layerDef.active) 156 | this._layersActives.push(layerDef.layer); 157 | 158 | this._layers.push(L.Util.extend(layerDef, { 159 | collapsed: isCollapsed, 160 | overlay: overlay, 161 | group: group 162 | })); 163 | 164 | if (this.options.autoZIndex && layerDef.layer && layerDef.layer.setZIndex) { 165 | this._lastZIndex++; 166 | layerDef.layer.setZIndex(this._lastZIndex); 167 | } 168 | 169 | }, 170 | 171 | _createItem: function (obj) { 172 | 173 | var self = this; 174 | 175 | var item, input, checked; 176 | 177 | item = L.DomUtil.create('div', this.className + '-item' + (obj.active ? ' active' : '')); 178 | 179 | checked = this._map.hasLayer(obj.layer); 180 | 181 | if (obj.overlay) { 182 | if (typeof obj.exclusiveGroup !== "undefined"){ 183 | input = this._createRadioElement(obj.exclusiveGroup.replace('', '_'), checked, obj); 184 | }else{ 185 | input = L.DomUtil.create('input', this.className + '-selector'); 186 | input.type = 'checkbox'; 187 | input.defaultChecked = checked; 188 | }//TODO name 189 | } else 190 | input = this._createRadioElement('leaflet-base-layers', checked, obj); 191 | 192 | input.value = obj.id; 193 | input.layerId = obj.id; 194 | input.id = obj.id; 195 | input._layer = obj; 196 | 197 | L.DomEvent.on(input, 'click', function (e) { 198 | 199 | self._onInputClick(); 200 | 201 | if (e.target.checked) { 202 | self.fire('panel:selected', e.target._layer); 203 | } else { 204 | self.fire('panel:unselected', e.target._layer); 205 | } 206 | 207 | }, this); 208 | 209 | var label = L.DomUtil.create('label', this.className + '-title'); 210 | //TODO label.htmlFor = input.id; 211 | var title = L.DomUtil.create('span'); 212 | title.innerHTML = obj.name || ''; 213 | 214 | if (obj.icon) { 215 | var icon = L.DomUtil.create('i', this.className + '-icon'); 216 | 217 | if (typeof obj.icon === 'string') 218 | icon.innerHTML = obj.icon || ''; 219 | else 220 | icon.appendChild(obj.icon); 221 | 222 | label.appendChild(icon); 223 | } 224 | 225 | label.appendChild(input); 226 | label.appendChild(title); 227 | item.appendChild(label); 228 | 229 | if (this.options.buildItem) { 230 | var node = this.options.buildItem.call(this, obj); //custom node node or html string 231 | if (typeof node === 'string') { 232 | var tmp = L.DomUtil.create('div'); 233 | tmp.innerHTML = node; 234 | item.appendChild(tmp.firstChild); 235 | } 236 | else 237 | item.appendChild(node); 238 | } 239 | 240 | this._items[input.value] = item; 241 | 242 | return item; 243 | }, 244 | 245 | // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) 246 | _createRadioElement: function (name, checked, obj) { 247 | 248 | var radioHtml = '= 0.5; 456 | } 457 | } 458 | 459 | this._refocusOnMap(); 460 | }, 461 | 462 | 463 | _initLayout: function () { 464 | var container = this._container = L.DomUtil.create('div', this.className); 465 | 466 | if(this.options.compact) 467 | L.DomUtil.addClass(container, 'compact'); 468 | 469 | //Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released 470 | container.setAttribute('aria-haspopup', true); 471 | 472 | L.DomEvent 473 | .disableClickPropagation(container) 474 | .disableScrollPropagation(container); 475 | 476 | if (this.options.className) 477 | L.DomUtil.addClass(container, this.options.className); 478 | 479 | this._section = this._form = L.DomUtil.create('form', this.className + '-list'); 480 | 481 | this._updateHeight(); 482 | 483 | if (this.options.collapsed) { 484 | 485 | if (L.Browser.android) 486 | L.DomEvent 487 | .on(container, 'click', this._expand, this); 488 | else { 489 | L.DomEvent 490 | .on(container, 'mouseenter', this._expand, this) 491 | .on(container, 'mouseleave', this._collapse, this); 492 | } 493 | 494 | this._map.on('click', this._collapse, this); 495 | 496 | } else { 497 | this._expand(); 498 | } 499 | 500 | this._baseLayersList = L.DomUtil.create('div', this.className + '-base', this._form); 501 | this._separator = L.DomUtil.create('div', this.className + '-separator', this._form); 502 | this._overlaysList = L.DomUtil.create('div', this.className + '-overlays', this._form); 503 | 504 | /* maybe useless 505 | if (!this.options.compact) 506 | L.DomUtil.create('div', this.className + '-margin', this._form);*/ 507 | 508 | if (this.options.title) { 509 | var titlabel = L.DomUtil.create('label', this.className + '-title'); 510 | titlabel.innerHTML = '' + this.options.title + ''; 511 | container.appendChild(titlabel); 512 | } 513 | 514 | container.appendChild(this._form); 515 | }, 516 | 517 | _updateHeight: function (h) { 518 | h = h || this._map.getSize().y; 519 | 520 | if (this.options.compact) 521 | this._form.style.maxHeight = (h - this.options.compactOffset) + 'px'; 522 | else 523 | this._form.style.height = h + 'px'; 524 | }, 525 | 526 | _expand: function () { 527 | L.DomUtil.addClass(this._container, 'expanded'); 528 | }, 529 | 530 | _collapse: function () { 531 | this._container.className = this._container.className.replace('expanded', ''); 532 | }, 533 | 534 | _getPath: function (obj, prop) { 535 | var parts = prop.split('.'), 536 | last = parts.pop(), 537 | len = parts.length, 538 | cur = parts[0], 539 | i = 1; 540 | 541 | if (len > 0) 542 | while ((obj = obj[cur]) && i < len) 543 | cur = parts[i++]; 544 | 545 | if (obj) 546 | return obj[last]; 547 | } 548 | }); 549 | 550 | L.control.panelLayers = function (baseLayers, overlays, options) { 551 | return new L.Control.PanelLayers(baseLayers, overlays, options); 552 | }; 553 | 554 | return L.Control.PanelLayers; 555 | 556 | }); 557 | --------------------------------------------------------------------------------