Commit 15167bf3d4eb6b85d6e9f6dbe032ff1fd87e58a8
Merge branch 'master' of http://service.routetopa.eu:7480/WebCompDev/COMPONENTS
Showing
16 changed files
with
9923 additions
and
5 deletions
controllets/data-table-controllet/data-table-controllet.html
| ... | ... | @@ -335,13 +335,14 @@ |
| 335 | 335 | |
| 336 | 336 | this._resize(); |
| 337 | 337 | |
| 338 | - this.$.tooltip_wornings.show(); | |
| 338 | + this.async(function() { | |
| 339 | + this.$.tooltip_wornings.show(); | |
| 340 | + }, 100); | |
| 339 | 341 | }, |
| 340 | 342 | |
| 341 | 343 | reset : function(){ |
| 342 | 344 | this.setData([]); |
| 343 | 345 | $(this.$.tbody).animate({ scrollTop: 0}, 0); |
| 344 | -// this.filter = ""; | |
| 345 | 346 | }, |
| 346 | 347 | |
| 347 | 348 | _onPrevClick : function(){ |
| ... | ... | @@ -478,7 +479,7 @@ |
| 478 | 479 | var w = $(this.$.data_table_container).width(); |
| 479 | 480 | $(this.$.tbody).width(w).height(h); |
| 480 | 481 | $(this.$.tbody).perfectScrollbar('update'); |
| 481 | - }, 1); | |
| 482 | + }, 0); | |
| 482 | 483 | } |
| 483 | 484 | |
| 484 | 485 | }); | ... | ... |
controllets/select-visualization-controllet/select-datalet-inputs.html
| ... | ... | @@ -276,7 +276,11 @@ |
| 276 | 276 | |
| 277 | 277 | setInputs : function(inputs) { |
| 278 | 278 | var temp = this._copy(inputs); |
| 279 | - if (inputs.constructor != Array) {//table --> 1 input | |
| 279 | + if (inputs.constructor != Array && inputs.name == "GEOJSON") { | |
| 280 | + temp = []; | |
| 281 | + temp.push(inputs); | |
| 282 | + } | |
| 283 | + else if (inputs.constructor != Array) {//table --> 1 input | |
| 280 | 284 | var name = inputs.name; |
| 281 | 285 | var description = inputs.description; |
| 282 | 286 | var selection = inputs.selection; | ... | ... |
datalets/base-ajax-json-alasql-datalet/base-ajax-json-alasql-datalet.html
| ... | ... | @@ -34,7 +34,7 @@ |
| 34 | 34 | <script type="text/javascript" src="../../alasql-utility/alasql.min.js"></script> |
| 35 | 35 | <script type="text/javascript" src="../../alasql-utility/alasql-utility.js"></script> |
| 36 | 36 | |
| 37 | -<script type="text/javascript" src="../../bower_components/JSDataChecker/jsdatachecker.min.js"></script> | |
| 37 | +<script type="text/javascript" src="../../bower_components/jsdatachecker/jsdatachecker.min.js"></script> | |
| 38 | 38 | |
| 39 | 39 | <!-- |
| 40 | 40 | The `base-ajax-json-jsonpath-datalet` extend the base component and define the mechanism to access and select data. | ... | ... |
datalets/leafletjs-geojson-datalet/demo/index.html
0 โ 100755
| 1 | +<!DOCTYPE html> | |
| 2 | +<html lang="en"> | |
| 3 | +<head> | |
| 4 | + <meta charset="UTF-8"> | |
| 5 | + <title></title> | |
| 6 | + | |
| 7 | + <script> | |
| 8 | + </script> | |
| 9 | + | |
| 10 | +</head> | |
| 11 | +<body> | |
| 12 | + | |
| 13 | +<script src="https://code.jquery.com/jquery-2.1.4.min.js" type="text/javascript"></script> | |
| 14 | +<link rel="import" href="../leafletjs-datalet.html" /> | |
| 15 | + | |
| 16 | +<leafletjs-datalet data-url="http://ckan.routetopa.eu/api/action/datastore_search?resource_id=73e02092-85a1-434e-85fe-0c9a43aa9a52&limit=10000" | |
| 17 | + fields='["result,records,Lat","result,records,Lng", "result,records,Link"]'></leafletjs-datalet> | |
| 18 | + | |
| 19 | + | |
| 20 | +</body> | |
| 21 | +</html> | |
| 0 | 22 | \ No newline at end of file | ... | ... |
datalets/leafletjs-geojson-datalet/docs.html
0 โ 100755
| 1 | +<!DOCTYPE html> | |
| 2 | +<html lang="en"> | |
| 3 | +<head> | |
| 4 | + <link rel="import" href="../../bower_components/iron-component-page/iron-component-page.html"> | |
| 5 | + <meta charset="UTF-8"> | |
| 6 | +</head> | |
| 7 | +<body> | |
| 8 | + | |
| 9 | +<iron-component-page src="leafletjs-datalet.html"></iron-component-page> | |
| 10 | + | |
| 11 | +</body> | |
| 12 | +</html> | |
| 0 | 13 | \ No newline at end of file | ... | ... |
datalets/leafletjs-geojson-datalet/leafletjs-geojson-datalet.html
0 โ 100755
| 1 | +<!-- | |
| 2 | +@license | |
| 3 | + The MIT License (MIT) | |
| 4 | + | |
| 5 | + Copyright (c) 2015 Dipartimento di Informatica - Universitร di Salerno - Italy | |
| 6 | + | |
| 7 | + Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 8 | + of this software and associated documentation files (the "Software"), to deal | |
| 9 | + in the Software without restriction, including without limitation the rights | |
| 10 | + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 11 | + copies of the Software, and to permit persons to whom the Software is | |
| 12 | + furnished to do so, subject to the following conditions: | |
| 13 | + | |
| 14 | + The above copyright notice and this permission notice shall be included in | |
| 15 | + all copies or substantial portions of the Software. | |
| 16 | + | |
| 17 | + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 18 | + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 19 | + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 20 | + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 21 | + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 22 | + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 23 | + THE SOFTWARE. | |
| 24 | +--> | |
| 25 | + | |
| 26 | +<!-- | |
| 27 | +* Developed by : | |
| 28 | +* ROUTE-TO-PA Project - grant No 645860. - www.routetopa.eu | |
| 29 | +* | |
| 30 | +--> | |
| 31 | + | |
| 32 | +<link rel="import" href="../base-ajax-json-alasql-datalet/base-ajax-json-alasql-datalet.html"> | |
| 33 | + | |
| 34 | +<!-- | |
| 35 | + | |
| 36 | +`leafletjs-datalet` is a map datalet based on open source project leafletjs <http://leafletjs.com/> | |
| 37 | + | |
| 38 | +Example: | |
| 39 | + | |
| 40 | + <leafletjs-datalet | |
| 41 | + data-url="http://ckan.routetopa.eu/api/action/datastore_search?resource_id=#" | |
| 42 | + fields='["field1","field2"]'> | |
| 43 | + </leafletjs-datalet> | |
| 44 | + | |
| 45 | +@element leafletjs-datalet | |
| 46 | +@status v0.1 | |
| 47 | +@demo demo/index.html | |
| 48 | +@group datalets | |
| 49 | +--> | |
| 50 | + | |
| 51 | +<dom-module name="leafletjs-geojson-datalet"> | |
| 52 | + <template> | |
| 53 | + <link rel="stylesheet" href="leafletsjs/leaflet.css" /> | |
| 54 | + <style> | |
| 55 | + #leafletjs {height: 600px;} | |
| 56 | + </style> | |
| 57 | + | |
| 58 | + <div id="leafletjs"></div> | |
| 59 | + <base-ajax-json-alasql-datalet data-url="{{dataUrl}}" fields="{{fields}}" data="{{data}}" title="{{title}}" description="{{description}}" export_menu="{{export_menu}}"></base-ajax-json-alasql-datalet> | |
| 60 | + | |
| 61 | + </template> | |
| 62 | + | |
| 63 | + <script src="leafletsjs/leaflet.js"></script> | |
| 64 | + | |
| 65 | + <script> | |
| 66 | + | |
| 67 | + var leafletjsBehavior = { | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * Read markers coordinates from the data object and add the marker to the map. | |
| 71 | + * Call a method for the map redraw and set the viewport in order to fit all the markers in the viewport.. | |
| 72 | + * | |
| 73 | + * @method transformData | |
| 74 | + */ | |
| 75 | + presentData: function(){ | |
| 76 | + | |
| 77 | + var t = this; | |
| 78 | + try{ | |
| 79 | + this._component.map = L.map(this._component.$.leafletjs).setView([0, 0], 13, {reset:true}); | |
| 80 | + }catch(e){} | |
| 81 | + | |
| 82 | + | |
| 83 | + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |
| 84 | + maxZoom: 18, | |
| 85 | + attribution: 'Map data ยฉ <a href="http://openstreetmap.org">OpenStreetMap</a> contributors' | |
| 86 | + }).addTo(this._component.map); | |
| 87 | + | |
| 88 | + | |
| 89 | + L.Icon.Default.imagePath = 'http://services.routetopa.eu/DEEalerProvider/COMPONENTS/datalets/leafletjs-datalet/leafletsjs/images'; | |
| 90 | + | |
| 91 | + var coordinates = []; | |
| 92 | + var coordinates_index = 0; | |
| 93 | + var isArray = t.data[0].data[0].constructor === Array; | |
| 94 | + | |
| 95 | + for(var i=0; i<t.data[0].data.length; i++) | |
| 96 | + { | |
| 97 | + if(isArray) | |
| 98 | + { | |
| 99 | + if(!isNaN(t.data[0].data[i][0]) && !isNaN(t.data[0].data[i][1])) | |
| 100 | + coordinates.push([parseFloat(t.data[0].data[i][0]), parseFloat(t.data[0].data[i][1])]); | |
| 101 | + else | |
| 102 | + continue; | |
| 103 | + } | |
| 104 | + else | |
| 105 | + { | |
| 106 | + if(!isNaN(t.data[0].data[i]) && !isNaN(t.data[1].data[i])) | |
| 107 | + coordinates.push([parseFloat(t.data[0].data[i]), parseFloat(t.data[1].data[i])]); | |
| 108 | + else | |
| 109 | + continue; | |
| 110 | + } | |
| 111 | + | |
| 112 | + var marker = L.marker([coordinates[coordinates_index][0], coordinates[coordinates_index][1]]).addTo(t._component.map); | |
| 113 | + coordinates_index++; | |
| 114 | + | |
| 115 | + if(t.data.length > 2) | |
| 116 | + { | |
| 117 | + var popupText = ""; | |
| 118 | + for(var j=2; j<t.data.length; j++) | |
| 119 | + { | |
| 120 | + if(typeof t.data[j] != 'undefined' && typeof t.data[j].data[i] != 'undefined') | |
| 121 | + { | |
| 122 | + if (t.data[j].data[i].toString().match(new RegExp("^(http[s]?:\\/\\/(www\\.)?|ftp:\\/\\/(www\\.)?|www\\.){1}([0-9A-Za-z-\\.@:%_\+~#=]+)+((\\.[a-zA-Z]{2,3})+)(/(.)*)?(\\?(.)*)?"))) | |
| 123 | + popupText += '<image height="100" width="100" src="' + t.data[j].data[i] + '" /><br/>'; | |
| 124 | + else | |
| 125 | + popupText += '<span>' + t.data[j].name + ' : ' + t.data[j].data[i] + '</span><br/>' | |
| 126 | + } | |
| 127 | + } | |
| 128 | + | |
| 129 | + var popup = L.popup().setContent(popupText); | |
| 130 | + marker.bindPopup(popup); | |
| 131 | + } | |
| 132 | + } | |
| 133 | + | |
| 134 | + t._component.map._onResize(); | |
| 135 | + t._component.map.invalidateSize(false); | |
| 136 | + t._component.map.fitBounds(coordinates); | |
| 137 | + | |
| 138 | + } | |
| 139 | + }; | |
| 140 | + | |
| 141 | + | |
| 142 | + Polymer({ | |
| 143 | + | |
| 144 | + is : 'leafletjs-geojson-datalet', | |
| 145 | + | |
| 146 | + properties : { | |
| 147 | + /** | |
| 148 | + * Store a reference to the leafletjs map object created in 'ready' callback | |
| 149 | + * @attribute map | |
| 150 | + * @type Object | |
| 151 | + */ | |
| 152 | + map : | |
| 153 | + { | |
| 154 | + type: Object, | |
| 155 | + value:null | |
| 156 | + }, | |
| 157 | + /** | |
| 158 | + * An Array with all the markers extracted from the dataset | |
| 159 | + * @attribute markers | |
| 160 | + * @type Array | |
| 161 | + */ | |
| 162 | + markers : | |
| 163 | + { | |
| 164 | + type : Array, | |
| 165 | + value : [] | |
| 166 | + }, | |
| 167 | + /** | |
| 168 | + * It's the component behavior | |
| 169 | + * | |
| 170 | + * @attribute behavior | |
| 171 | + * @type Object | |
| 172 | + * @default {} | |
| 173 | + */ | |
| 174 | + behavior : { | |
| 175 | + type : Object, | |
| 176 | + value : {} | |
| 177 | + }, | |
| 178 | + /** | |
| 179 | + * Control the export menu | |
| 180 | + * xxxx BITMASK. FROM RIGHT : HTML, PNG, RTF, MY SPACE (eg. 1111 show all, 0000 hide all) | |
| 181 | + * | |
| 182 | + * @attribute export_menu | |
| 183 | + * @type Number | |
| 184 | + * @default 15 | |
| 185 | + */ | |
| 186 | + export_menu : { | |
| 187 | + type : Number, | |
| 188 | + value : 9 // xxxx BITMASK. FROM RIGHT : HTML, PNG, RTF, MY SPACE (eg. 1111 show all, 0000 hide all) | |
| 189 | + } | |
| 190 | + }, | |
| 191 | + | |
| 192 | + /** | |
| 193 | + * 'ready' callback create the map object, set the tileLayer to openstreetmap and the default icon image path. | |
| 194 | + * Moreover extend the leafletjsComponentBehavior with BaseDataletBehavior, WorkcycleBehavior and leafletjsBehavior | |
| 195 | + * and run the Datalet workcycle. | |
| 196 | + * | |
| 197 | + * @method ready | |
| 198 | + */ | |
| 199 | + ready: function(){ | |
| 200 | + this.behavior = $.extend(true, {}, BaseDataletBehavior, WorkcycleBehavior, AjaxJsonAlasqlBehavior, leafletjsBehavior); | |
| 201 | + this.async(function(){this.behavior.init(this)},100); | |
| 202 | + } | |
| 203 | + }); | |
| 204 | + </script> | |
| 205 | +</dom-module> | |
| 206 | + | ... | ... |
datalets/leafletjs-geojson-datalet/leafletjs-geojson-datalet.png
0 โ 100644
5.32 KB
datalets/leafletjs-geojson-datalet/leafletsjs/images/layers-2x.png
0 โ 100755
2.83 KB
datalets/leafletjs-geojson-datalet/leafletsjs/images/layers.png
0 โ 100755
1.47 KB
datalets/leafletjs-geojson-datalet/leafletsjs/images/marker-icon-2x.png
0 โ 100755
3.94 KB
datalets/leafletjs-geojson-datalet/leafletsjs/images/marker-icon.png
0 โ 100755
1.71 KB
datalets/leafletjs-geojson-datalet/leafletsjs/images/marker-shadow.png
0 โ 100755
797 Bytes
datalets/leafletjs-geojson-datalet/leafletsjs/leaflet-src.js
0 โ 100755
Changes suppressed. Click to show
| 1 | +/* | |
| 2 | + Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com | |
| 3 | + (c) 2010-2013, Vladimir Agafonkin | |
| 4 | + (c) 2010-2011, CloudMade | |
| 5 | +*/ | |
| 6 | +(function (window, document, undefined) { | |
| 7 | +var oldL = window.L, | |
| 8 | + L = {}; | |
| 9 | + | |
| 10 | +L.version = '0.7.3'; | |
| 11 | + | |
| 12 | +// define Leaflet for Node module pattern loaders, including Browserify | |
| 13 | +if (typeof module === 'object' && typeof module.exports === 'object') { | |
| 14 | + module.exports = L; | |
| 15 | + | |
| 16 | +// define Leaflet as an AMD module | |
| 17 | +} else if (typeof define === 'function' && define.amd) { | |
| 18 | + define(L); | |
| 19 | +} | |
| 20 | + | |
| 21 | +// define Leaflet as a global L variable, saving the original L to restore later if needed | |
| 22 | + | |
| 23 | +L.noConflict = function () { | |
| 24 | + window.L = oldL; | |
| 25 | + return this; | |
| 26 | +}; | |
| 27 | + | |
| 28 | +window.L = L; | |
| 29 | + | |
| 30 | + | |
| 31 | +/* | |
| 32 | + * L.Util contains various utility functions used throughout Leaflet code. | |
| 33 | + */ | |
| 34 | + | |
| 35 | +L.Util = { | |
| 36 | + extend: function (dest) { // (Object[, Object, ...]) -> | |
| 37 | + var sources = Array.prototype.slice.call(arguments, 1), | |
| 38 | + i, j, len, src; | |
| 39 | + | |
| 40 | + for (j = 0, len = sources.length; j < len; j++) { | |
| 41 | + src = sources[j] || {}; | |
| 42 | + for (i in src) { | |
| 43 | + if (src.hasOwnProperty(i)) { | |
| 44 | + dest[i] = src[i]; | |
| 45 | + } | |
| 46 | + } | |
| 47 | + } | |
| 48 | + return dest; | |
| 49 | + }, | |
| 50 | + | |
| 51 | + bind: function (fn, obj) { // (Function, Object) -> Function | |
| 52 | + var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null; | |
| 53 | + return function () { | |
| 54 | + return fn.apply(obj, args || arguments); | |
| 55 | + }; | |
| 56 | + }, | |
| 57 | + | |
| 58 | + stamp: (function () { | |
| 59 | + var lastId = 0, | |
| 60 | + key = '_leaflet_id'; | |
| 61 | + return function (obj) { | |
| 62 | + obj[key] = obj[key] || ++lastId; | |
| 63 | + return obj[key]; | |
| 64 | + }; | |
| 65 | + }()), | |
| 66 | + | |
| 67 | + invokeEach: function (obj, method, context) { | |
| 68 | + var i, args; | |
| 69 | + | |
| 70 | + if (typeof obj === 'object') { | |
| 71 | + args = Array.prototype.slice.call(arguments, 3); | |
| 72 | + | |
| 73 | + for (i in obj) { | |
| 74 | + method.apply(context, [i, obj[i]].concat(args)); | |
| 75 | + } | |
| 76 | + return true; | |
| 77 | + } | |
| 78 | + | |
| 79 | + return false; | |
| 80 | + }, | |
| 81 | + | |
| 82 | + limitExecByInterval: function (fn, time, context) { | |
| 83 | + var lock, execOnUnlock; | |
| 84 | + | |
| 85 | + return function wrapperFn() { | |
| 86 | + var args = arguments; | |
| 87 | + | |
| 88 | + if (lock) { | |
| 89 | + execOnUnlock = true; | |
| 90 | + return; | |
| 91 | + } | |
| 92 | + | |
| 93 | + lock = true; | |
| 94 | + | |
| 95 | + setTimeout(function () { | |
| 96 | + lock = false; | |
| 97 | + | |
| 98 | + if (execOnUnlock) { | |
| 99 | + wrapperFn.apply(context, args); | |
| 100 | + execOnUnlock = false; | |
| 101 | + } | |
| 102 | + }, time); | |
| 103 | + | |
| 104 | + fn.apply(context, args); | |
| 105 | + }; | |
| 106 | + }, | |
| 107 | + | |
| 108 | + falseFn: function () { | |
| 109 | + return false; | |
| 110 | + }, | |
| 111 | + | |
| 112 | + formatNum: function (num, digits) { | |
| 113 | + var pow = Math.pow(10, digits || 5); | |
| 114 | + return Math.round(num * pow) / pow; | |
| 115 | + }, | |
| 116 | + | |
| 117 | + trim: function (str) { | |
| 118 | + return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); | |
| 119 | + }, | |
| 120 | + | |
| 121 | + splitWords: function (str) { | |
| 122 | + return L.Util.trim(str).split(/\s+/); | |
| 123 | + }, | |
| 124 | + | |
| 125 | + setOptions: function (obj, options) { | |
| 126 | + obj.options = L.extend({}, obj.options, options); | |
| 127 | + return obj.options; | |
| 128 | + }, | |
| 129 | + | |
| 130 | + getParamString: function (obj, existingUrl, uppercase) { | |
| 131 | + var params = []; | |
| 132 | + for (var i in obj) { | |
| 133 | + params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); | |
| 134 | + } | |
| 135 | + return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); | |
| 136 | + }, | |
| 137 | + template: function (str, data) { | |
| 138 | + return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) { | |
| 139 | + var value = data[key]; | |
| 140 | + if (value === undefined) { | |
| 141 | + throw new Error('No value provided for variable ' + str); | |
| 142 | + } else if (typeof value === 'function') { | |
| 143 | + value = value(data); | |
| 144 | + } | |
| 145 | + return value; | |
| 146 | + }); | |
| 147 | + }, | |
| 148 | + | |
| 149 | + isArray: Array.isArray || function (obj) { | |
| 150 | + return (Object.prototype.toString.call(obj) === '[object Array]'); | |
| 151 | + }, | |
| 152 | + | |
| 153 | + emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' | |
| 154 | +}; | |
| 155 | + | |
| 156 | +(function () { | |
| 157 | + | |
| 158 | + // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ | |
| 159 | + | |
| 160 | + function getPrefixed(name) { | |
| 161 | + var i, fn, | |
| 162 | + prefixes = ['webkit', 'moz', 'o', 'ms']; | |
| 163 | + | |
| 164 | + for (i = 0; i < prefixes.length && !fn; i++) { | |
| 165 | + fn = window[prefixes[i] + name]; | |
| 166 | + } | |
| 167 | + | |
| 168 | + return fn; | |
| 169 | + } | |
| 170 | + | |
| 171 | + var lastTime = 0; | |
| 172 | + | |
| 173 | + function timeoutDefer(fn) { | |
| 174 | + var time = +new Date(), | |
| 175 | + timeToCall = Math.max(0, 16 - (time - lastTime)); | |
| 176 | + | |
| 177 | + lastTime = time + timeToCall; | |
| 178 | + return window.setTimeout(fn, timeToCall); | |
| 179 | + } | |
| 180 | + | |
| 181 | + var requestFn = window.requestAnimationFrame || | |
| 182 | + getPrefixed('RequestAnimationFrame') || timeoutDefer; | |
| 183 | + | |
| 184 | + var cancelFn = window.cancelAnimationFrame || | |
| 185 | + getPrefixed('CancelAnimationFrame') || | |
| 186 | + getPrefixed('CancelRequestAnimationFrame') || | |
| 187 | + function (id) { window.clearTimeout(id); }; | |
| 188 | + | |
| 189 | + | |
| 190 | + L.Util.requestAnimFrame = function (fn, context, immediate, element) { | |
| 191 | + fn = L.bind(fn, context); | |
| 192 | + | |
| 193 | + if (immediate && requestFn === timeoutDefer) { | |
| 194 | + fn(); | |
| 195 | + } else { | |
| 196 | + return requestFn.call(window, fn, element); | |
| 197 | + } | |
| 198 | + }; | |
| 199 | + | |
| 200 | + L.Util.cancelAnimFrame = function (id) { | |
| 201 | + if (id) { | |
| 202 | + cancelFn.call(window, id); | |
| 203 | + } | |
| 204 | + }; | |
| 205 | + | |
| 206 | +}()); | |
| 207 | + | |
| 208 | +// shortcuts for most used utility functions | |
| 209 | +L.extend = L.Util.extend; | |
| 210 | +L.bind = L.Util.bind; | |
| 211 | +L.stamp = L.Util.stamp; | |
| 212 | +L.setOptions = L.Util.setOptions; | |
| 213 | + | |
| 214 | + | |
| 215 | +/* | |
| 216 | + * L.Class powers the OOP facilities of the library. | |
| 217 | + * Thanks to John Resig and Dean Edwards for inspiration! | |
| 218 | + */ | |
| 219 | + | |
| 220 | +L.Class = function () {}; | |
| 221 | + | |
| 222 | +L.Class.extend = function (props) { | |
| 223 | + | |
| 224 | + // extended class with the new prototype | |
| 225 | + var NewClass = function () { | |
| 226 | + | |
| 227 | + // call the constructor | |
| 228 | + if (this.initialize) { | |
| 229 | + this.initialize.apply(this, arguments); | |
| 230 | + } | |
| 231 | + | |
| 232 | + // call all constructor hooks | |
| 233 | + if (this._initHooks) { | |
| 234 | + this.callInitHooks(); | |
| 235 | + } | |
| 236 | + }; | |
| 237 | + | |
| 238 | + // instantiate class without calling constructor | |
| 239 | + var F = function () {}; | |
| 240 | + F.prototype = this.prototype; | |
| 241 | + | |
| 242 | + var proto = new F(); | |
| 243 | + proto.constructor = NewClass; | |
| 244 | + | |
| 245 | + NewClass.prototype = proto; | |
| 246 | + | |
| 247 | + //inherit parent's statics | |
| 248 | + for (var i in this) { | |
| 249 | + if (this.hasOwnProperty(i) && i !== 'prototype') { | |
| 250 | + NewClass[i] = this[i]; | |
| 251 | + } | |
| 252 | + } | |
| 253 | + | |
| 254 | + // mix static properties into the class | |
| 255 | + if (props.statics) { | |
| 256 | + L.extend(NewClass, props.statics); | |
| 257 | + delete props.statics; | |
| 258 | + } | |
| 259 | + | |
| 260 | + // mix includes into the prototype | |
| 261 | + if (props.includes) { | |
| 262 | + L.Util.extend.apply(null, [proto].concat(props.includes)); | |
| 263 | + delete props.includes; | |
| 264 | + } | |
| 265 | + | |
| 266 | + // merge options | |
| 267 | + if (props.options && proto.options) { | |
| 268 | + props.options = L.extend({}, proto.options, props.options); | |
| 269 | + } | |
| 270 | + | |
| 271 | + // mix given properties into the prototype | |
| 272 | + L.extend(proto, props); | |
| 273 | + | |
| 274 | + proto._initHooks = []; | |
| 275 | + | |
| 276 | + var parent = this; | |
| 277 | + // jshint camelcase: false | |
| 278 | + NewClass.__super__ = parent.prototype; | |
| 279 | + | |
| 280 | + // add method for calling all hooks | |
| 281 | + proto.callInitHooks = function () { | |
| 282 | + | |
| 283 | + if (this._initHooksCalled) { return; } | |
| 284 | + | |
| 285 | + if (parent.prototype.callInitHooks) { | |
| 286 | + parent.prototype.callInitHooks.call(this); | |
| 287 | + } | |
| 288 | + | |
| 289 | + this._initHooksCalled = true; | |
| 290 | + | |
| 291 | + for (var i = 0, len = proto._initHooks.length; i < len; i++) { | |
| 292 | + proto._initHooks[i].call(this); | |
| 293 | + } | |
| 294 | + }; | |
| 295 | + | |
| 296 | + return NewClass; | |
| 297 | +}; | |
| 298 | + | |
| 299 | + | |
| 300 | +// method for adding properties to prototype | |
| 301 | +L.Class.include = function (props) { | |
| 302 | + L.extend(this.prototype, props); | |
| 303 | +}; | |
| 304 | + | |
| 305 | +// merge new default options to the Class | |
| 306 | +L.Class.mergeOptions = function (options) { | |
| 307 | + L.extend(this.prototype.options, options); | |
| 308 | +}; | |
| 309 | + | |
| 310 | +// add a constructor hook | |
| 311 | +L.Class.addInitHook = function (fn) { // (Function) || (String, args...) | |
| 312 | + var args = Array.prototype.slice.call(arguments, 1); | |
| 313 | + | |
| 314 | + var init = typeof fn === 'function' ? fn : function () { | |
| 315 | + this[fn].apply(this, args); | |
| 316 | + }; | |
| 317 | + | |
| 318 | + this.prototype._initHooks = this.prototype._initHooks || []; | |
| 319 | + this.prototype._initHooks.push(init); | |
| 320 | +}; | |
| 321 | + | |
| 322 | + | |
| 323 | +/* | |
| 324 | + * L.Mixin.Events is used to add custom events functionality to Leaflet classes. | |
| 325 | + */ | |
| 326 | + | |
| 327 | +var eventsKey = '_leaflet_events'; | |
| 328 | + | |
| 329 | +L.Mixin = {}; | |
| 330 | + | |
| 331 | +L.Mixin.Events = { | |
| 332 | + | |
| 333 | + addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object]) | |
| 334 | + | |
| 335 | + // types can be a map of types/handlers | |
| 336 | + if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; } | |
| 337 | + | |
| 338 | + var events = this[eventsKey] = this[eventsKey] || {}, | |
| 339 | + contextId = context && context !== this && L.stamp(context), | |
| 340 | + i, len, event, type, indexKey, indexLenKey, typeIndex; | |
| 341 | + | |
| 342 | + // types can be a string of space-separated words | |
| 343 | + types = L.Util.splitWords(types); | |
| 344 | + | |
| 345 | + for (i = 0, len = types.length; i < len; i++) { | |
| 346 | + event = { | |
| 347 | + action: fn, | |
| 348 | + context: context || this | |
| 349 | + }; | |
| 350 | + type = types[i]; | |
| 351 | + | |
| 352 | + if (contextId) { | |
| 353 | + // store listeners of a particular context in a separate hash (if it has an id) | |
| 354 | + // gives a major performance boost when removing thousands of map layers | |
| 355 | + | |
| 356 | + indexKey = type + '_idx'; | |
| 357 | + indexLenKey = indexKey + '_len'; | |
| 358 | + | |
| 359 | + typeIndex = events[indexKey] = events[indexKey] || {}; | |
| 360 | + | |
| 361 | + if (!typeIndex[contextId]) { | |
| 362 | + typeIndex[contextId] = []; | |
| 363 | + | |
| 364 | + // keep track of the number of keys in the index to quickly check if it's empty | |
| 365 | + events[indexLenKey] = (events[indexLenKey] || 0) + 1; | |
| 366 | + } | |
| 367 | + | |
| 368 | + typeIndex[contextId].push(event); | |
| 369 | + | |
| 370 | + | |
| 371 | + } else { | |
| 372 | + events[type] = events[type] || []; | |
| 373 | + events[type].push(event); | |
| 374 | + } | |
| 375 | + } | |
| 376 | + | |
| 377 | + return this; | |
| 378 | + }, | |
| 379 | + | |
| 380 | + hasEventListeners: function (type) { // (String) -> Boolean | |
| 381 | + var events = this[eventsKey]; | |
| 382 | + return !!events && ((type in events && events[type].length > 0) || | |
| 383 | + (type + '_idx' in events && events[type + '_idx_len'] > 0)); | |
| 384 | + }, | |
| 385 | + | |
| 386 | + removeEventListener: function (types, fn, context) { // ([String, Function, Object]) or (Object[, Object]) | |
| 387 | + | |
| 388 | + if (!this[eventsKey]) { | |
| 389 | + return this; | |
| 390 | + } | |
| 391 | + | |
| 392 | + if (!types) { | |
| 393 | + return this.clearAllEventListeners(); | |
| 394 | + } | |
| 395 | + | |
| 396 | + if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; } | |
| 397 | + | |
| 398 | + var events = this[eventsKey], | |
| 399 | + contextId = context && context !== this && L.stamp(context), | |
| 400 | + i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed; | |
| 401 | + | |
| 402 | + types = L.Util.splitWords(types); | |
| 403 | + | |
| 404 | + for (i = 0, len = types.length; i < len; i++) { | |
| 405 | + type = types[i]; | |
| 406 | + indexKey = type + '_idx'; | |
| 407 | + indexLenKey = indexKey + '_len'; | |
| 408 | + | |
| 409 | + typeIndex = events[indexKey]; | |
| 410 | + | |
| 411 | + if (!fn) { | |
| 412 | + // clear all listeners for a type if function isn't specified | |
| 413 | + delete events[type]; | |
| 414 | + delete events[indexKey]; | |
| 415 | + delete events[indexLenKey]; | |
| 416 | + | |
| 417 | + } else { | |
| 418 | + listeners = contextId && typeIndex ? typeIndex[contextId] : events[type]; | |
| 419 | + | |
| 420 | + if (listeners) { | |
| 421 | + for (j = listeners.length - 1; j >= 0; j--) { | |
| 422 | + if ((listeners[j].action === fn) && (!context || (listeners[j].context === context))) { | |
| 423 | + removed = listeners.splice(j, 1); | |
| 424 | + // set the old action to a no-op, because it is possible | |
| 425 | + // that the listener is being iterated over as part of a dispatch | |
| 426 | + removed[0].action = L.Util.falseFn; | |
| 427 | + } | |
| 428 | + } | |
| 429 | + | |
| 430 | + if (context && typeIndex && (listeners.length === 0)) { | |
| 431 | + delete typeIndex[contextId]; | |
| 432 | + events[indexLenKey]--; | |
| 433 | + } | |
| 434 | + } | |
| 435 | + } | |
| 436 | + } | |
| 437 | + | |
| 438 | + return this; | |
| 439 | + }, | |
| 440 | + | |
| 441 | + clearAllEventListeners: function () { | |
| 442 | + delete this[eventsKey]; | |
| 443 | + return this; | |
| 444 | + }, | |
| 445 | + | |
| 446 | + fireEvent: function (type, data) { // (String[, Object]) | |
| 447 | + if (!this.hasEventListeners(type)) { | |
| 448 | + return this; | |
| 449 | + } | |
| 450 | + | |
| 451 | + var event = L.Util.extend({}, data, { type: type, target: this }); | |
| 452 | + | |
| 453 | + var events = this[eventsKey], | |
| 454 | + listeners, i, len, typeIndex, contextId; | |
| 455 | + | |
| 456 | + if (events[type]) { | |
| 457 | + // make sure adding/removing listeners inside other listeners won't cause infinite loop | |
| 458 | + listeners = events[type].slice(); | |
| 459 | + | |
| 460 | + for (i = 0, len = listeners.length; i < len; i++) { | |
| 461 | + listeners[i].action.call(listeners[i].context, event); | |
| 462 | + } | |
| 463 | + } | |
| 464 | + | |
| 465 | + // fire event for the context-indexed listeners as well | |
| 466 | + typeIndex = events[type + '_idx']; | |
| 467 | + | |
| 468 | + for (contextId in typeIndex) { | |
| 469 | + listeners = typeIndex[contextId].slice(); | |
| 470 | + | |
| 471 | + if (listeners) { | |
| 472 | + for (i = 0, len = listeners.length; i < len; i++) { | |
| 473 | + listeners[i].action.call(listeners[i].context, event); | |
| 474 | + } | |
| 475 | + } | |
| 476 | + } | |
| 477 | + | |
| 478 | + return this; | |
| 479 | + }, | |
| 480 | + | |
| 481 | + addOneTimeEventListener: function (types, fn, context) { | |
| 482 | + | |
| 483 | + if (L.Util.invokeEach(types, this.addOneTimeEventListener, this, fn, context)) { return this; } | |
| 484 | + | |
| 485 | + var handler = L.bind(function () { | |
| 486 | + this | |
| 487 | + .removeEventListener(types, fn, context) | |
| 488 | + .removeEventListener(types, handler, context); | |
| 489 | + }, this); | |
| 490 | + | |
| 491 | + return this | |
| 492 | + .addEventListener(types, fn, context) | |
| 493 | + .addEventListener(types, handler, context); | |
| 494 | + } | |
| 495 | +}; | |
| 496 | + | |
| 497 | +L.Mixin.Events.on = L.Mixin.Events.addEventListener; | |
| 498 | +L.Mixin.Events.off = L.Mixin.Events.removeEventListener; | |
| 499 | +L.Mixin.Events.once = L.Mixin.Events.addOneTimeEventListener; | |
| 500 | +L.Mixin.Events.fire = L.Mixin.Events.fireEvent; | |
| 501 | + | |
| 502 | + | |
| 503 | +/* | |
| 504 | + * L.Browser handles different browser and feature detections for internal Leaflet use. | |
| 505 | + */ | |
| 506 | + | |
| 507 | +(function () { | |
| 508 | + | |
| 509 | + var ie = 'ActiveXObject' in window, | |
| 510 | + ielt9 = ie && !document.addEventListener, | |
| 511 | + | |
| 512 | + // terrible browser detection to work around Safari / iOS / Android browser bugs | |
| 513 | + ua = navigator.userAgent.toLowerCase(), | |
| 514 | + webkit = ua.indexOf('webkit') !== -1, | |
| 515 | + chrome = ua.indexOf('chrome') !== -1, | |
| 516 | + phantomjs = ua.indexOf('phantom') !== -1, | |
| 517 | + android = ua.indexOf('android') !== -1, | |
| 518 | + android23 = ua.search('android [23]') !== -1, | |
| 519 | + gecko = ua.indexOf('gecko') !== -1, | |
| 520 | + | |
| 521 | + mobile = typeof orientation !== undefined + '', | |
| 522 | + msPointer = window.navigator && window.navigator.msPointerEnabled && | |
| 523 | + window.navigator.msMaxTouchPoints && !window.PointerEvent, | |
| 524 | + pointer = (window.PointerEvent && window.navigator.pointerEnabled && window.navigator.maxTouchPoints) || | |
| 525 | + msPointer, | |
| 526 | + retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) || | |
| 527 | + ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') && | |
| 528 | + window.matchMedia('(min-resolution:144dpi)').matches), | |
| 529 | + | |
| 530 | + doc = document.documentElement, | |
| 531 | + ie3d = ie && ('transition' in doc.style), | |
| 532 | + webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23, | |
| 533 | + gecko3d = 'MozPerspective' in doc.style, | |
| 534 | + opera3d = 'OTransition' in doc.style, | |
| 535 | + any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs; | |
| 536 | + | |
| 537 | + | |
| 538 | + // PhantomJS has 'ontouchstart' in document.documentElement, but doesn't actually support touch. | |
| 539 | + // https://github.com/Leaflet/Leaflet/pull/1434#issuecomment-13843151 | |
| 540 | + | |
| 541 | + var touch = !window.L_NO_TOUCH && !phantomjs && (function () { | |
| 542 | + | |
| 543 | + var startName = 'ontouchstart'; | |
| 544 | + | |
| 545 | + // IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.Pointer) or WebKit, etc. | |
| 546 | + if (pointer || (startName in doc)) { | |
| 547 | + return true; | |
| 548 | + } | |
| 549 | + | |
| 550 | + // Firefox/Gecko | |
| 551 | + var div = document.createElement('div'), | |
| 552 | + supported = false; | |
| 553 | + | |
| 554 | + if (!div.setAttribute) { | |
| 555 | + return false; | |
| 556 | + } | |
| 557 | + div.setAttribute(startName, 'return;'); | |
| 558 | + | |
| 559 | + if (typeof div[startName] === 'function') { | |
| 560 | + supported = true; | |
| 561 | + } | |
| 562 | + | |
| 563 | + div.removeAttribute(startName); | |
| 564 | + div = null; | |
| 565 | + | |
| 566 | + return supported; | |
| 567 | + }()); | |
| 568 | + | |
| 569 | + | |
| 570 | + L.Browser = { | |
| 571 | + ie: ie, | |
| 572 | + ielt9: ielt9, | |
| 573 | + webkit: webkit, | |
| 574 | + gecko: gecko && !webkit && !window.opera && !ie, | |
| 575 | + | |
| 576 | + android: android, | |
| 577 | + android23: android23, | |
| 578 | + | |
| 579 | + chrome: chrome, | |
| 580 | + | |
| 581 | + ie3d: ie3d, | |
| 582 | + webkit3d: webkit3d, | |
| 583 | + gecko3d: gecko3d, | |
| 584 | + opera3d: opera3d, | |
| 585 | + any3d: any3d, | |
| 586 | + | |
| 587 | + mobile: mobile, | |
| 588 | + mobileWebkit: mobile && webkit, | |
| 589 | + mobileWebkit3d: mobile && webkit3d, | |
| 590 | + mobileOpera: mobile && window.opera, | |
| 591 | + | |
| 592 | + touch: touch, | |
| 593 | + msPointer: msPointer, | |
| 594 | + pointer: pointer, | |
| 595 | + | |
| 596 | + retina: retina | |
| 597 | + }; | |
| 598 | + | |
| 599 | +}()); | |
| 600 | + | |
| 601 | + | |
| 602 | +/* | |
| 603 | + * L.Point represents a point with x and y coordinates. | |
| 604 | + */ | |
| 605 | + | |
| 606 | +L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) { | |
| 607 | + this.x = (round ? Math.round(x) : x); | |
| 608 | + this.y = (round ? Math.round(y) : y); | |
| 609 | +}; | |
| 610 | + | |
| 611 | +L.Point.prototype = { | |
| 612 | + | |
| 613 | + clone: function () { | |
| 614 | + return new L.Point(this.x, this.y); | |
| 615 | + }, | |
| 616 | + | |
| 617 | + // non-destructive, returns a new point | |
| 618 | + add: function (point) { | |
| 619 | + return this.clone()._add(L.point(point)); | |
| 620 | + }, | |
| 621 | + | |
| 622 | + // destructive, used directly for performance in situations where it's safe to modify existing point | |
| 623 | + _add: function (point) { | |
| 624 | + this.x += point.x; | |
| 625 | + this.y += point.y; | |
| 626 | + return this; | |
| 627 | + }, | |
| 628 | + | |
| 629 | + subtract: function (point) { | |
| 630 | + return this.clone()._subtract(L.point(point)); | |
| 631 | + }, | |
| 632 | + | |
| 633 | + _subtract: function (point) { | |
| 634 | + this.x -= point.x; | |
| 635 | + this.y -= point.y; | |
| 636 | + return this; | |
| 637 | + }, | |
| 638 | + | |
| 639 | + divideBy: function (num) { | |
| 640 | + return this.clone()._divideBy(num); | |
| 641 | + }, | |
| 642 | + | |
| 643 | + _divideBy: function (num) { | |
| 644 | + this.x /= num; | |
| 645 | + this.y /= num; | |
| 646 | + return this; | |
| 647 | + }, | |
| 648 | + | |
| 649 | + multiplyBy: function (num) { | |
| 650 | + return this.clone()._multiplyBy(num); | |
| 651 | + }, | |
| 652 | + | |
| 653 | + _multiplyBy: function (num) { | |
| 654 | + this.x *= num; | |
| 655 | + this.y *= num; | |
| 656 | + return this; | |
| 657 | + }, | |
| 658 | + | |
| 659 | + round: function () { | |
| 660 | + return this.clone()._round(); | |
| 661 | + }, | |
| 662 | + | |
| 663 | + _round: function () { | |
| 664 | + this.x = Math.round(this.x); | |
| 665 | + this.y = Math.round(this.y); | |
| 666 | + return this; | |
| 667 | + }, | |
| 668 | + | |
| 669 | + floor: function () { | |
| 670 | + return this.clone()._floor(); | |
| 671 | + }, | |
| 672 | + | |
| 673 | + _floor: function () { | |
| 674 | + this.x = Math.floor(this.x); | |
| 675 | + this.y = Math.floor(this.y); | |
| 676 | + return this; | |
| 677 | + }, | |
| 678 | + | |
| 679 | + distanceTo: function (point) { | |
| 680 | + point = L.point(point); | |
| 681 | + | |
| 682 | + var x = point.x - this.x, | |
| 683 | + y = point.y - this.y; | |
| 684 | + | |
| 685 | + return Math.sqrt(x * x + y * y); | |
| 686 | + }, | |
| 687 | + | |
| 688 | + equals: function (point) { | |
| 689 | + point = L.point(point); | |
| 690 | + | |
| 691 | + return point.x === this.x && | |
| 692 | + point.y === this.y; | |
| 693 | + }, | |
| 694 | + | |
| 695 | + contains: function (point) { | |
| 696 | + point = L.point(point); | |
| 697 | + | |
| 698 | + return Math.abs(point.x) <= Math.abs(this.x) && | |
| 699 | + Math.abs(point.y) <= Math.abs(this.y); | |
| 700 | + }, | |
| 701 | + | |
| 702 | + toString: function () { | |
| 703 | + return 'Point(' + | |
| 704 | + L.Util.formatNum(this.x) + ', ' + | |
| 705 | + L.Util.formatNum(this.y) + ')'; | |
| 706 | + } | |
| 707 | +}; | |
| 708 | + | |
| 709 | +L.point = function (x, y, round) { | |
| 710 | + if (x instanceof L.Point) { | |
| 711 | + return x; | |
| 712 | + } | |
| 713 | + if (L.Util.isArray(x)) { | |
| 714 | + return new L.Point(x[0], x[1]); | |
| 715 | + } | |
| 716 | + if (x === undefined || x === null) { | |
| 717 | + return x; | |
| 718 | + } | |
| 719 | + return new L.Point(x, y, round); | |
| 720 | +}; | |
| 721 | + | |
| 722 | + | |
| 723 | +/* | |
| 724 | + * L.Bounds represents a rectangular area on the screen in pixel coordinates. | |
| 725 | + */ | |
| 726 | + | |
| 727 | +L.Bounds = function (a, b) { //(Point, Point) or Point[] | |
| 728 | + if (!a) { return; } | |
| 729 | + | |
| 730 | + var points = b ? [a, b] : a; | |
| 731 | + | |
| 732 | + for (var i = 0, len = points.length; i < len; i++) { | |
| 733 | + this.extend(points[i]); | |
| 734 | + } | |
| 735 | +}; | |
| 736 | + | |
| 737 | +L.Bounds.prototype = { | |
| 738 | + // extend the bounds to contain the given point | |
| 739 | + extend: function (point) { // (Point) | |
| 740 | + point = L.point(point); | |
| 741 | + | |
| 742 | + if (!this.min && !this.max) { | |
| 743 | + this.min = point.clone(); | |
| 744 | + this.max = point.clone(); | |
| 745 | + } else { | |
| 746 | + this.min.x = Math.min(point.x, this.min.x); | |
| 747 | + this.max.x = Math.max(point.x, this.max.x); | |
| 748 | + this.min.y = Math.min(point.y, this.min.y); | |
| 749 | + this.max.y = Math.max(point.y, this.max.y); | |
| 750 | + } | |
| 751 | + return this; | |
| 752 | + }, | |
| 753 | + | |
| 754 | + getCenter: function (round) { // (Boolean) -> Point | |
| 755 | + return new L.Point( | |
| 756 | + (this.min.x + this.max.x) / 2, | |
| 757 | + (this.min.y + this.max.y) / 2, round); | |
| 758 | + }, | |
| 759 | + | |
| 760 | + getBottomLeft: function () { // -> Point | |
| 761 | + return new L.Point(this.min.x, this.max.y); | |
| 762 | + }, | |
| 763 | + | |
| 764 | + getTopRight: function () { // -> Point | |
| 765 | + return new L.Point(this.max.x, this.min.y); | |
| 766 | + }, | |
| 767 | + | |
| 768 | + getSize: function () { | |
| 769 | + return this.max.subtract(this.min); | |
| 770 | + }, | |
| 771 | + | |
| 772 | + contains: function (obj) { // (Bounds) or (Point) -> Boolean | |
| 773 | + var min, max; | |
| 774 | + | |
| 775 | + if (typeof obj[0] === 'number' || obj instanceof L.Point) { | |
| 776 | + obj = L.point(obj); | |
| 777 | + } else { | |
| 778 | + obj = L.bounds(obj); | |
| 779 | + } | |
| 780 | + | |
| 781 | + if (obj instanceof L.Bounds) { | |
| 782 | + min = obj.min; | |
| 783 | + max = obj.max; | |
| 784 | + } else { | |
| 785 | + min = max = obj; | |
| 786 | + } | |
| 787 | + | |
| 788 | + return (min.x >= this.min.x) && | |
| 789 | + (max.x <= this.max.x) && | |
| 790 | + (min.y >= this.min.y) && | |
| 791 | + (max.y <= this.max.y); | |
| 792 | + }, | |
| 793 | + | |
| 794 | + intersects: function (bounds) { // (Bounds) -> Boolean | |
| 795 | + bounds = L.bounds(bounds); | |
| 796 | + | |
| 797 | + var min = this.min, | |
| 798 | + max = this.max, | |
| 799 | + min2 = bounds.min, | |
| 800 | + max2 = bounds.max, | |
| 801 | + xIntersects = (max2.x >= min.x) && (min2.x <= max.x), | |
| 802 | + yIntersects = (max2.y >= min.y) && (min2.y <= max.y); | |
| 803 | + | |
| 804 | + return xIntersects && yIntersects; | |
| 805 | + }, | |
| 806 | + | |
| 807 | + isValid: function () { | |
| 808 | + return !!(this.min && this.max); | |
| 809 | + } | |
| 810 | +}; | |
| 811 | + | |
| 812 | +L.bounds = function (a, b) { // (Bounds) or (Point, Point) or (Point[]) | |
| 813 | + if (!a || a instanceof L.Bounds) { | |
| 814 | + return a; | |
| 815 | + } | |
| 816 | + return new L.Bounds(a, b); | |
| 817 | +}; | |
| 818 | + | |
| 819 | + | |
| 820 | +/* | |
| 821 | + * L.Transformation is an utility class to perform simple point transformations through a 2d-matrix. | |
| 822 | + */ | |
| 823 | + | |
| 824 | +L.Transformation = function (a, b, c, d) { | |
| 825 | + this._a = a; | |
| 826 | + this._b = b; | |
| 827 | + this._c = c; | |
| 828 | + this._d = d; | |
| 829 | +}; | |
| 830 | + | |
| 831 | +L.Transformation.prototype = { | |
| 832 | + transform: function (point, scale) { // (Point, Number) -> Point | |
| 833 | + return this._transform(point.clone(), scale); | |
| 834 | + }, | |
| 835 | + | |
| 836 | + // destructive transform (faster) | |
| 837 | + _transform: function (point, scale) { | |
| 838 | + scale = scale || 1; | |
| 839 | + point.x = scale * (this._a * point.x + this._b); | |
| 840 | + point.y = scale * (this._c * point.y + this._d); | |
| 841 | + return point; | |
| 842 | + }, | |
| 843 | + | |
| 844 | + untransform: function (point, scale) { | |
| 845 | + scale = scale || 1; | |
| 846 | + return new L.Point( | |
| 847 | + (point.x / scale - this._b) / this._a, | |
| 848 | + (point.y / scale - this._d) / this._c); | |
| 849 | + } | |
| 850 | +}; | |
| 851 | + | |
| 852 | + | |
| 853 | +/* | |
| 854 | + * L.DomUtil contains various utility functions for working with DOM. | |
| 855 | + */ | |
| 856 | + | |
| 857 | +L.DomUtil = { | |
| 858 | + get: function (id) { | |
| 859 | + return (typeof id === 'string' ? document.getElementById(id) : id); | |
| 860 | + }, | |
| 861 | + | |
| 862 | + getStyle: function (el, style) { | |
| 863 | + | |
| 864 | + var value = el.style[style]; | |
| 865 | + | |
| 866 | + if (!value && el.currentStyle) { | |
| 867 | + value = el.currentStyle[style]; | |
| 868 | + } | |
| 869 | + | |
| 870 | + if ((!value || value === 'auto') && document.defaultView) { | |
| 871 | + var css = document.defaultView.getComputedStyle(el, null); | |
| 872 | + value = css ? css[style] : null; | |
| 873 | + } | |
| 874 | + | |
| 875 | + return value === 'auto' ? null : value; | |
| 876 | + }, | |
| 877 | + | |
| 878 | + getViewportOffset: function (element) { | |
| 879 | + | |
| 880 | + var top = 0, | |
| 881 | + left = 0, | |
| 882 | + el = element, | |
| 883 | + docBody = document.body, | |
| 884 | + docEl = document.documentElement, | |
| 885 | + pos; | |
| 886 | + | |
| 887 | + do { | |
| 888 | + top += el.offsetTop || 0; | |
| 889 | + left += el.offsetLeft || 0; | |
| 890 | + | |
| 891 | + //add borders | |
| 892 | + top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0; | |
| 893 | + left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0; | |
| 894 | + | |
| 895 | + pos = L.DomUtil.getStyle(el, 'position'); | |
| 896 | + | |
| 897 | + if (el.offsetParent === docBody && pos === 'absolute') { break; } | |
| 898 | + | |
| 899 | + if (pos === 'fixed') { | |
| 900 | + top += docBody.scrollTop || docEl.scrollTop || 0; | |
| 901 | + left += docBody.scrollLeft || docEl.scrollLeft || 0; | |
| 902 | + break; | |
| 903 | + } | |
| 904 | + | |
| 905 | + if (pos === 'relative' && !el.offsetLeft) { | |
| 906 | + var width = L.DomUtil.getStyle(el, 'width'), | |
| 907 | + maxWidth = L.DomUtil.getStyle(el, 'max-width'), | |
| 908 | + r = el.getBoundingClientRect(); | |
| 909 | + | |
| 910 | + if (width !== 'none' || maxWidth !== 'none') { | |
| 911 | + left += r.left + el.clientLeft; | |
| 912 | + } | |
| 913 | + | |
| 914 | + //calculate full y offset since we're breaking out of the loop | |
| 915 | + top += r.top + (docBody.scrollTop || docEl.scrollTop || 0); | |
| 916 | + | |
| 917 | + break; | |
| 918 | + } | |
| 919 | + | |
| 920 | + el = el.offsetParent; | |
| 921 | + | |
| 922 | + } while (el); | |
| 923 | + | |
| 924 | + el = element; | |
| 925 | + | |
| 926 | + do { | |
| 927 | + if (el === docBody) { break; } | |
| 928 | + | |
| 929 | + top -= el.scrollTop || 0; | |
| 930 | + left -= el.scrollLeft || 0; | |
| 931 | + | |
| 932 | + el = el.parentNode; | |
| 933 | + } while (el); | |
| 934 | + | |
| 935 | + return new L.Point(left, top); | |
| 936 | + }, | |
| 937 | + | |
| 938 | + documentIsLtr: function () { | |
| 939 | + if (!L.DomUtil._docIsLtrCached) { | |
| 940 | + L.DomUtil._docIsLtrCached = true; | |
| 941 | + L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr'; | |
| 942 | + } | |
| 943 | + return L.DomUtil._docIsLtr; | |
| 944 | + }, | |
| 945 | + | |
| 946 | + create: function (tagName, className, container) { | |
| 947 | + | |
| 948 | + var el = document.createElement(tagName); | |
| 949 | + el.className = className; | |
| 950 | + | |
| 951 | + if (container) { | |
| 952 | + container.appendChild(el); | |
| 953 | + } | |
| 954 | + | |
| 955 | + return el; | |
| 956 | + }, | |
| 957 | + | |
| 958 | + hasClass: function (el, name) { | |
| 959 | + if (el.classList !== undefined) { | |
| 960 | + return el.classList.contains(name); | |
| 961 | + } | |
| 962 | + var className = L.DomUtil._getClass(el); | |
| 963 | + return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); | |
| 964 | + }, | |
| 965 | + | |
| 966 | + addClass: function (el, name) { | |
| 967 | + if (el.classList !== undefined) { | |
| 968 | + var classes = L.Util.splitWords(name); | |
| 969 | + for (var i = 0, len = classes.length; i < len; i++) { | |
| 970 | + el.classList.add(classes[i]); | |
| 971 | + } | |
| 972 | + } else if (!L.DomUtil.hasClass(el, name)) { | |
| 973 | + var className = L.DomUtil._getClass(el); | |
| 974 | + L.DomUtil._setClass(el, (className ? className + ' ' : '') + name); | |
| 975 | + } | |
| 976 | + }, | |
| 977 | + | |
| 978 | + removeClass: function (el, name) { | |
| 979 | + if (el.classList !== undefined) { | |
| 980 | + el.classList.remove(name); | |
| 981 | + } else { | |
| 982 | + L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' '))); | |
| 983 | + } | |
| 984 | + }, | |
| 985 | + | |
| 986 | + _setClass: function (el, name) { | |
| 987 | + if (el.className.baseVal === undefined) { | |
| 988 | + el.className = name; | |
| 989 | + } else { | |
| 990 | + // in case of SVG element | |
| 991 | + el.className.baseVal = name; | |
| 992 | + } | |
| 993 | + }, | |
| 994 | + | |
| 995 | + _getClass: function (el) { | |
| 996 | + return el.className.baseVal === undefined ? el.className : el.className.baseVal; | |
| 997 | + }, | |
| 998 | + | |
| 999 | + setOpacity: function (el, value) { | |
| 1000 | + | |
| 1001 | + if ('opacity' in el.style) { | |
| 1002 | + el.style.opacity = value; | |
| 1003 | + | |
| 1004 | + } else if ('filter' in el.style) { | |
| 1005 | + | |
| 1006 | + var filter = false, | |
| 1007 | + filterName = 'DXImageTransform.Microsoft.Alpha'; | |
| 1008 | + | |
| 1009 | + // filters collection throws an error if we try to retrieve a filter that doesn't exist | |
| 1010 | + try { | |
| 1011 | + filter = el.filters.item(filterName); | |
| 1012 | + } catch (e) { | |
| 1013 | + // don't set opacity to 1 if we haven't already set an opacity, | |
| 1014 | + // it isn't needed and breaks transparent pngs. | |
| 1015 | + if (value === 1) { return; } | |
| 1016 | + } | |
| 1017 | + | |
| 1018 | + value = Math.round(value * 100); | |
| 1019 | + | |
| 1020 | + if (filter) { | |
| 1021 | + filter.Enabled = (value !== 100); | |
| 1022 | + filter.Opacity = value; | |
| 1023 | + } else { | |
| 1024 | + el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; | |
| 1025 | + } | |
| 1026 | + } | |
| 1027 | + }, | |
| 1028 | + | |
| 1029 | + testProp: function (props) { | |
| 1030 | + | |
| 1031 | + var style = document.documentElement.style; | |
| 1032 | + | |
| 1033 | + for (var i = 0; i < props.length; i++) { | |
| 1034 | + if (props[i] in style) { | |
| 1035 | + return props[i]; | |
| 1036 | + } | |
| 1037 | + } | |
| 1038 | + return false; | |
| 1039 | + }, | |
| 1040 | + | |
| 1041 | + getTranslateString: function (point) { | |
| 1042 | + // on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate | |
| 1043 | + // makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care | |
| 1044 | + // (same speed either way), Opera 12 doesn't support translate3d | |
| 1045 | + | |
| 1046 | + var is3d = L.Browser.webkit3d, | |
| 1047 | + open = 'translate' + (is3d ? '3d' : '') + '(', | |
| 1048 | + close = (is3d ? ',0' : '') + ')'; | |
| 1049 | + | |
| 1050 | + return open + point.x + 'px,' + point.y + 'px' + close; | |
| 1051 | + }, | |
| 1052 | + | |
| 1053 | + getScaleString: function (scale, origin) { | |
| 1054 | + | |
| 1055 | + var preTranslateStr = L.DomUtil.getTranslateString(origin.add(origin.multiplyBy(-1 * scale))), | |
| 1056 | + scaleStr = ' scale(' + scale + ') '; | |
| 1057 | + | |
| 1058 | + return preTranslateStr + scaleStr; | |
| 1059 | + }, | |
| 1060 | + | |
| 1061 | + setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean]) | |
| 1062 | + | |
| 1063 | + // jshint camelcase: false | |
| 1064 | + el._leaflet_pos = point; | |
| 1065 | + | |
| 1066 | + if (!disable3D && L.Browser.any3d) { | |
| 1067 | + el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point); | |
| 1068 | + } else { | |
| 1069 | + el.style.left = point.x + 'px'; | |
| 1070 | + el.style.top = point.y + 'px'; | |
| 1071 | + } | |
| 1072 | + }, | |
| 1073 | + | |
| 1074 | + getPosition: function (el) { | |
| 1075 | + // this method is only used for elements previously positioned using setPosition, | |
| 1076 | + // so it's safe to cache the position for performance | |
| 1077 | + | |
| 1078 | + // jshint camelcase: false | |
| 1079 | + return el._leaflet_pos; | |
| 1080 | + } | |
| 1081 | +}; | |
| 1082 | + | |
| 1083 | + | |
| 1084 | +// prefix style property names | |
| 1085 | + | |
| 1086 | +L.DomUtil.TRANSFORM = L.DomUtil.testProp( | |
| 1087 | + ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']); | |
| 1088 | + | |
| 1089 | +// webkitTransition comes first because some browser versions that drop vendor prefix don't do | |
| 1090 | +// the same for the transitionend event, in particular the Android 4.1 stock browser | |
| 1091 | + | |
| 1092 | +L.DomUtil.TRANSITION = L.DomUtil.testProp( | |
| 1093 | + ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); | |
| 1094 | + | |
| 1095 | +L.DomUtil.TRANSITION_END = | |
| 1096 | + L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ? | |
| 1097 | + L.DomUtil.TRANSITION + 'End' : 'transitionend'; | |
| 1098 | + | |
| 1099 | +(function () { | |
| 1100 | + if ('onselectstart' in document) { | |
| 1101 | + L.extend(L.DomUtil, { | |
| 1102 | + disableTextSelection: function () { | |
| 1103 | + L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault); | |
| 1104 | + }, | |
| 1105 | + | |
| 1106 | + enableTextSelection: function () { | |
| 1107 | + L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault); | |
| 1108 | + } | |
| 1109 | + }); | |
| 1110 | + } else { | |
| 1111 | + var userSelectProperty = L.DomUtil.testProp( | |
| 1112 | + ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); | |
| 1113 | + | |
| 1114 | + L.extend(L.DomUtil, { | |
| 1115 | + disableTextSelection: function () { | |
| 1116 | + if (userSelectProperty) { | |
| 1117 | + var style = document.documentElement.style; | |
| 1118 | + this._userSelect = style[userSelectProperty]; | |
| 1119 | + style[userSelectProperty] = 'none'; | |
| 1120 | + } | |
| 1121 | + }, | |
| 1122 | + | |
| 1123 | + enableTextSelection: function () { | |
| 1124 | + if (userSelectProperty) { | |
| 1125 | + document.documentElement.style[userSelectProperty] = this._userSelect; | |
| 1126 | + delete this._userSelect; | |
| 1127 | + } | |
| 1128 | + } | |
| 1129 | + }); | |
| 1130 | + } | |
| 1131 | + | |
| 1132 | + L.extend(L.DomUtil, { | |
| 1133 | + disableImageDrag: function () { | |
| 1134 | + L.DomEvent.on(window, 'dragstart', L.DomEvent.preventDefault); | |
| 1135 | + }, | |
| 1136 | + | |
| 1137 | + enableImageDrag: function () { | |
| 1138 | + L.DomEvent.off(window, 'dragstart', L.DomEvent.preventDefault); | |
| 1139 | + } | |
| 1140 | + }); | |
| 1141 | +})(); | |
| 1142 | + | |
| 1143 | + | |
| 1144 | +/* | |
| 1145 | + * L.LatLng represents a geographical point with latitude and longitude coordinates. | |
| 1146 | + */ | |
| 1147 | + | |
| 1148 | +L.LatLng = function (lat, lng, alt) { // (Number, Number, Number) | |
| 1149 | + lat = parseFloat(lat); | |
| 1150 | + lng = parseFloat(lng); | |
| 1151 | + | |
| 1152 | + if (isNaN(lat) || isNaN(lng)) { | |
| 1153 | + throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); | |
| 1154 | + } | |
| 1155 | + | |
| 1156 | + this.lat = lat; | |
| 1157 | + this.lng = lng; | |
| 1158 | + | |
| 1159 | + if (alt !== undefined) { | |
| 1160 | + this.alt = parseFloat(alt); | |
| 1161 | + } | |
| 1162 | +}; | |
| 1163 | + | |
| 1164 | +L.extend(L.LatLng, { | |
| 1165 | + DEG_TO_RAD: Math.PI / 180, | |
| 1166 | + RAD_TO_DEG: 180 / Math.PI, | |
| 1167 | + MAX_MARGIN: 1.0E-9 // max margin of error for the "equals" check | |
| 1168 | +}); | |
| 1169 | + | |
| 1170 | +L.LatLng.prototype = { | |
| 1171 | + equals: function (obj) { // (LatLng) -> Boolean | |
| 1172 | + if (!obj) { return false; } | |
| 1173 | + | |
| 1174 | + obj = L.latLng(obj); | |
| 1175 | + | |
| 1176 | + var margin = Math.max( | |
| 1177 | + Math.abs(this.lat - obj.lat), | |
| 1178 | + Math.abs(this.lng - obj.lng)); | |
| 1179 | + | |
| 1180 | + return margin <= L.LatLng.MAX_MARGIN; | |
| 1181 | + }, | |
| 1182 | + | |
| 1183 | + toString: function (precision) { // (Number) -> String | |
| 1184 | + return 'LatLng(' + | |
| 1185 | + L.Util.formatNum(this.lat, precision) + ', ' + | |
| 1186 | + L.Util.formatNum(this.lng, precision) + ')'; | |
| 1187 | + }, | |
| 1188 | + | |
| 1189 | + // Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula | |
| 1190 | + // TODO move to projection code, LatLng shouldn't know about Earth | |
| 1191 | + distanceTo: function (other) { // (LatLng) -> Number | |
| 1192 | + other = L.latLng(other); | |
| 1193 | + | |
| 1194 | + var R = 6378137, // earth radius in meters | |
| 1195 | + d2r = L.LatLng.DEG_TO_RAD, | |
| 1196 | + dLat = (other.lat - this.lat) * d2r, | |
| 1197 | + dLon = (other.lng - this.lng) * d2r, | |
| 1198 | + lat1 = this.lat * d2r, | |
| 1199 | + lat2 = other.lat * d2r, | |
| 1200 | + sin1 = Math.sin(dLat / 2), | |
| 1201 | + sin2 = Math.sin(dLon / 2); | |
| 1202 | + | |
| 1203 | + var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2); | |
| 1204 | + | |
| 1205 | + return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | |
| 1206 | + }, | |
| 1207 | + | |
| 1208 | + wrap: function (a, b) { // (Number, Number) -> LatLng | |
| 1209 | + var lng = this.lng; | |
| 1210 | + | |
| 1211 | + a = a || -180; | |
| 1212 | + b = b || 180; | |
| 1213 | + | |
| 1214 | + lng = (lng + b) % (b - a) + (lng < a || lng === b ? b : a); | |
| 1215 | + | |
| 1216 | + return new L.LatLng(this.lat, lng); | |
| 1217 | + } | |
| 1218 | +}; | |
| 1219 | + | |
| 1220 | +L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Number) | |
| 1221 | + if (a instanceof L.LatLng) { | |
| 1222 | + return a; | |
| 1223 | + } | |
| 1224 | + if (L.Util.isArray(a)) { | |
| 1225 | + if (typeof a[0] === 'number' || typeof a[0] === 'string') { | |
| 1226 | + return new L.LatLng(a[0], a[1], a[2]); | |
| 1227 | + } else { | |
| 1228 | + return null; | |
| 1229 | + } | |
| 1230 | + } | |
| 1231 | + if (a === undefined || a === null) { | |
| 1232 | + return a; | |
| 1233 | + } | |
| 1234 | + if (typeof a === 'object' && 'lat' in a) { | |
| 1235 | + return new L.LatLng(a.lat, 'lng' in a ? a.lng : a.lon); | |
| 1236 | + } | |
| 1237 | + if (b === undefined) { | |
| 1238 | + return null; | |
| 1239 | + } | |
| 1240 | + return new L.LatLng(a, b); | |
| 1241 | +}; | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | +/* | |
| 1246 | + * L.LatLngBounds represents a rectangular area on the map in geographical coordinates. | |
| 1247 | + */ | |
| 1248 | + | |
| 1249 | +L.LatLngBounds = function (southWest, northEast) { // (LatLng, LatLng) or (LatLng[]) | |
| 1250 | + if (!southWest) { return; } | |
| 1251 | + | |
| 1252 | + var latlngs = northEast ? [southWest, northEast] : southWest; | |
| 1253 | + | |
| 1254 | + for (var i = 0, len = latlngs.length; i < len; i++) { | |
| 1255 | + this.extend(latlngs[i]); | |
| 1256 | + } | |
| 1257 | +}; | |
| 1258 | + | |
| 1259 | +L.LatLngBounds.prototype = { | |
| 1260 | + // extend the bounds to contain the given point or bounds | |
| 1261 | + extend: function (obj) { // (LatLng) or (LatLngBounds) | |
| 1262 | + if (!obj) { return this; } | |
| 1263 | + | |
| 1264 | + var latLng = L.latLng(obj); | |
| 1265 | + if (latLng !== null) { | |
| 1266 | + obj = latLng; | |
| 1267 | + } else { | |
| 1268 | + obj = L.latLngBounds(obj); | |
| 1269 | + } | |
| 1270 | + | |
| 1271 | + if (obj instanceof L.LatLng) { | |
| 1272 | + if (!this._southWest && !this._northEast) { | |
| 1273 | + this._southWest = new L.LatLng(obj.lat, obj.lng); | |
| 1274 | + this._northEast = new L.LatLng(obj.lat, obj.lng); | |
| 1275 | + } else { | |
| 1276 | + this._southWest.lat = Math.min(obj.lat, this._southWest.lat); | |
| 1277 | + this._southWest.lng = Math.min(obj.lng, this._southWest.lng); | |
| 1278 | + | |
| 1279 | + this._northEast.lat = Math.max(obj.lat, this._northEast.lat); | |
| 1280 | + this._northEast.lng = Math.max(obj.lng, this._northEast.lng); | |
| 1281 | + } | |
| 1282 | + } else if (obj instanceof L.LatLngBounds) { | |
| 1283 | + this.extend(obj._southWest); | |
| 1284 | + this.extend(obj._northEast); | |
| 1285 | + } | |
| 1286 | + return this; | |
| 1287 | + }, | |
| 1288 | + | |
| 1289 | + // extend the bounds by a percentage | |
| 1290 | + pad: function (bufferRatio) { // (Number) -> LatLngBounds | |
| 1291 | + var sw = this._southWest, | |
| 1292 | + ne = this._northEast, | |
| 1293 | + heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, | |
| 1294 | + widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; | |
| 1295 | + | |
| 1296 | + return new L.LatLngBounds( | |
| 1297 | + new L.LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), | |
| 1298 | + new L.LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); | |
| 1299 | + }, | |
| 1300 | + | |
| 1301 | + getCenter: function () { // -> LatLng | |
| 1302 | + return new L.LatLng( | |
| 1303 | + (this._southWest.lat + this._northEast.lat) / 2, | |
| 1304 | + (this._southWest.lng + this._northEast.lng) / 2); | |
| 1305 | + }, | |
| 1306 | + | |
| 1307 | + getSouthWest: function () { | |
| 1308 | + return this._southWest; | |
| 1309 | + }, | |
| 1310 | + | |
| 1311 | + getNorthEast: function () { | |
| 1312 | + return this._northEast; | |
| 1313 | + }, | |
| 1314 | + | |
| 1315 | + getNorthWest: function () { | |
| 1316 | + return new L.LatLng(this.getNorth(), this.getWest()); | |
| 1317 | + }, | |
| 1318 | + | |
| 1319 | + getSouthEast: function () { | |
| 1320 | + return new L.LatLng(this.getSouth(), this.getEast()); | |
| 1321 | + }, | |
| 1322 | + | |
| 1323 | + getWest: function () { | |
| 1324 | + return this._southWest.lng; | |
| 1325 | + }, | |
| 1326 | + | |
| 1327 | + getSouth: function () { | |
| 1328 | + return this._southWest.lat; | |
| 1329 | + }, | |
| 1330 | + | |
| 1331 | + getEast: function () { | |
| 1332 | + return this._northEast.lng; | |
| 1333 | + }, | |
| 1334 | + | |
| 1335 | + getNorth: function () { | |
| 1336 | + return this._northEast.lat; | |
| 1337 | + }, | |
| 1338 | + | |
| 1339 | + contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean | |
| 1340 | + if (typeof obj[0] === 'number' || obj instanceof L.LatLng) { | |
| 1341 | + obj = L.latLng(obj); | |
| 1342 | + } else { | |
| 1343 | + obj = L.latLngBounds(obj); | |
| 1344 | + } | |
| 1345 | + | |
| 1346 | + var sw = this._southWest, | |
| 1347 | + ne = this._northEast, | |
| 1348 | + sw2, ne2; | |
| 1349 | + | |
| 1350 | + if (obj instanceof L.LatLngBounds) { | |
| 1351 | + sw2 = obj.getSouthWest(); | |
| 1352 | + ne2 = obj.getNorthEast(); | |
| 1353 | + } else { | |
| 1354 | + sw2 = ne2 = obj; | |
| 1355 | + } | |
| 1356 | + | |
| 1357 | + return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && | |
| 1358 | + (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); | |
| 1359 | + }, | |
| 1360 | + | |
| 1361 | + intersects: function (bounds) { // (LatLngBounds) | |
| 1362 | + bounds = L.latLngBounds(bounds); | |
| 1363 | + | |
| 1364 | + var sw = this._southWest, | |
| 1365 | + ne = this._northEast, | |
| 1366 | + sw2 = bounds.getSouthWest(), | |
| 1367 | + ne2 = bounds.getNorthEast(), | |
| 1368 | + | |
| 1369 | + latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), | |
| 1370 | + lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); | |
| 1371 | + | |
| 1372 | + return latIntersects && lngIntersects; | |
| 1373 | + }, | |
| 1374 | + | |
| 1375 | + toBBoxString: function () { | |
| 1376 | + return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); | |
| 1377 | + }, | |
| 1378 | + | |
| 1379 | + equals: function (bounds) { // (LatLngBounds) | |
| 1380 | + if (!bounds) { return false; } | |
| 1381 | + | |
| 1382 | + bounds = L.latLngBounds(bounds); | |
| 1383 | + | |
| 1384 | + return this._southWest.equals(bounds.getSouthWest()) && | |
| 1385 | + this._northEast.equals(bounds.getNorthEast()); | |
| 1386 | + }, | |
| 1387 | + | |
| 1388 | + isValid: function () { | |
| 1389 | + return !!(this._southWest && this._northEast); | |
| 1390 | + } | |
| 1391 | +}; | |
| 1392 | + | |
| 1393 | +//TODO International date line? | |
| 1394 | + | |
| 1395 | +L.latLngBounds = function (a, b) { // (LatLngBounds) or (LatLng, LatLng) | |
| 1396 | + if (!a || a instanceof L.LatLngBounds) { | |
| 1397 | + return a; | |
| 1398 | + } | |
| 1399 | + return new L.LatLngBounds(a, b); | |
| 1400 | +}; | |
| 1401 | + | |
| 1402 | + | |
| 1403 | +/* | |
| 1404 | + * L.Projection contains various geographical projections used by CRS classes. | |
| 1405 | + */ | |
| 1406 | + | |
| 1407 | +L.Projection = {}; | |
| 1408 | + | |
| 1409 | + | |
| 1410 | +/* | |
| 1411 | + * Spherical Mercator is the most popular map projection, used by EPSG:3857 CRS used by default. | |
| 1412 | + */ | |
| 1413 | + | |
| 1414 | +L.Projection.SphericalMercator = { | |
| 1415 | + MAX_LATITUDE: 85.0511287798, | |
| 1416 | + | |
| 1417 | + project: function (latlng) { // (LatLng) -> Point | |
| 1418 | + var d = L.LatLng.DEG_TO_RAD, | |
| 1419 | + max = this.MAX_LATITUDE, | |
| 1420 | + lat = Math.max(Math.min(max, latlng.lat), -max), | |
| 1421 | + x = latlng.lng * d, | |
| 1422 | + y = lat * d; | |
| 1423 | + | |
| 1424 | + y = Math.log(Math.tan((Math.PI / 4) + (y / 2))); | |
| 1425 | + | |
| 1426 | + return new L.Point(x, y); | |
| 1427 | + }, | |
| 1428 | + | |
| 1429 | + unproject: function (point) { // (Point, Boolean) -> LatLng | |
| 1430 | + var d = L.LatLng.RAD_TO_DEG, | |
| 1431 | + lng = point.x * d, | |
| 1432 | + lat = (2 * Math.atan(Math.exp(point.y)) - (Math.PI / 2)) * d; | |
| 1433 | + | |
| 1434 | + return new L.LatLng(lat, lng); | |
| 1435 | + } | |
| 1436 | +}; | |
| 1437 | + | |
| 1438 | + | |
| 1439 | +/* | |
| 1440 | + * Simple equirectangular (Plate Carree) projection, used by CRS like EPSG:4326 and Simple. | |
| 1441 | + */ | |
| 1442 | + | |
| 1443 | +L.Projection.LonLat = { | |
| 1444 | + project: function (latlng) { | |
| 1445 | + return new L.Point(latlng.lng, latlng.lat); | |
| 1446 | + }, | |
| 1447 | + | |
| 1448 | + unproject: function (point) { | |
| 1449 | + return new L.LatLng(point.y, point.x); | |
| 1450 | + } | |
| 1451 | +}; | |
| 1452 | + | |
| 1453 | + | |
| 1454 | +/* | |
| 1455 | + * L.CRS is a base object for all defined CRS (Coordinate Reference Systems) in Leaflet. | |
| 1456 | + */ | |
| 1457 | + | |
| 1458 | +L.CRS = { | |
| 1459 | + latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point | |
| 1460 | + var projectedPoint = this.projection.project(latlng), | |
| 1461 | + scale = this.scale(zoom); | |
| 1462 | + | |
| 1463 | + return this.transformation._transform(projectedPoint, scale); | |
| 1464 | + }, | |
| 1465 | + | |
| 1466 | + pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng | |
| 1467 | + var scale = this.scale(zoom), | |
| 1468 | + untransformedPoint = this.transformation.untransform(point, scale); | |
| 1469 | + | |
| 1470 | + return this.projection.unproject(untransformedPoint); | |
| 1471 | + }, | |
| 1472 | + | |
| 1473 | + project: function (latlng) { | |
| 1474 | + return this.projection.project(latlng); | |
| 1475 | + }, | |
| 1476 | + | |
| 1477 | + scale: function (zoom) { | |
| 1478 | + return 256 * Math.pow(2, zoom); | |
| 1479 | + }, | |
| 1480 | + | |
| 1481 | + getSize: function (zoom) { | |
| 1482 | + var s = this.scale(zoom); | |
| 1483 | + return L.point(s, s); | |
| 1484 | + } | |
| 1485 | +}; | |
| 1486 | + | |
| 1487 | + | |
| 1488 | +/* | |
| 1489 | + * A simple CRS that can be used for flat non-Earth maps like panoramas or game maps. | |
| 1490 | + */ | |
| 1491 | + | |
| 1492 | +L.CRS.Simple = L.extend({}, L.CRS, { | |
| 1493 | + projection: L.Projection.LonLat, | |
| 1494 | + transformation: new L.Transformation(1, 0, -1, 0), | |
| 1495 | + | |
| 1496 | + scale: function (zoom) { | |
| 1497 | + return Math.pow(2, zoom); | |
| 1498 | + } | |
| 1499 | +}); | |
| 1500 | + | |
| 1501 | + | |
| 1502 | +/* | |
| 1503 | + * L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping | |
| 1504 | + * and is used by Leaflet by default. | |
| 1505 | + */ | |
| 1506 | + | |
| 1507 | +L.CRS.EPSG3857 = L.extend({}, L.CRS, { | |
| 1508 | + code: 'EPSG:3857', | |
| 1509 | + | |
| 1510 | + projection: L.Projection.SphericalMercator, | |
| 1511 | + transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5), | |
| 1512 | + | |
| 1513 | + project: function (latlng) { // (LatLng) -> Point | |
| 1514 | + var projectedPoint = this.projection.project(latlng), | |
| 1515 | + earthRadius = 6378137; | |
| 1516 | + return projectedPoint.multiplyBy(earthRadius); | |
| 1517 | + } | |
| 1518 | +}); | |
| 1519 | + | |
| 1520 | +L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, { | |
| 1521 | + code: 'EPSG:900913' | |
| 1522 | +}); | |
| 1523 | + | |
| 1524 | + | |
| 1525 | +/* | |
| 1526 | + * L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists. | |
| 1527 | + */ | |
| 1528 | + | |
| 1529 | +L.CRS.EPSG4326 = L.extend({}, L.CRS, { | |
| 1530 | + code: 'EPSG:4326', | |
| 1531 | + | |
| 1532 | + projection: L.Projection.LonLat, | |
| 1533 | + transformation: new L.Transformation(1 / 360, 0.5, -1 / 360, 0.5) | |
| 1534 | +}); | |
| 1535 | + | |
| 1536 | + | |
| 1537 | +/* | |
| 1538 | + * L.Map is the central class of the API - it is used to create a map. | |
| 1539 | + */ | |
| 1540 | + | |
| 1541 | +L.Map = L.Class.extend({ | |
| 1542 | + | |
| 1543 | + includes: L.Mixin.Events, | |
| 1544 | + | |
| 1545 | + options: { | |
| 1546 | + crs: L.CRS.EPSG3857, | |
| 1547 | + | |
| 1548 | + /* | |
| 1549 | + center: LatLng, | |
| 1550 | + zoom: Number, | |
| 1551 | + layers: Array, | |
| 1552 | + */ | |
| 1553 | + | |
| 1554 | + fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android23, | |
| 1555 | + trackResize: true, | |
| 1556 | + markerZoomAnimation: L.DomUtil.TRANSITION && L.Browser.any3d | |
| 1557 | + }, | |
| 1558 | + | |
| 1559 | + initialize: function (id, options) { // (HTMLElement or String, Object) | |
| 1560 | + options = L.setOptions(this, options); | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + this._initContainer(id); | |
| 1564 | + this._initLayout(); | |
| 1565 | + | |
| 1566 | + // hack for https://github.com/Leaflet/Leaflet/issues/1980 | |
| 1567 | + this._onResize = L.bind(this._onResize, this); | |
| 1568 | + | |
| 1569 | + this._initEvents(); | |
| 1570 | + | |
| 1571 | + if (options.maxBounds) { | |
| 1572 | + this.setMaxBounds(options.maxBounds); | |
| 1573 | + } | |
| 1574 | + | |
| 1575 | + if (options.center && options.zoom !== undefined) { | |
| 1576 | + this.setView(L.latLng(options.center), options.zoom, {reset: true}); | |
| 1577 | + } | |
| 1578 | + | |
| 1579 | + this._handlers = []; | |
| 1580 | + | |
| 1581 | + this._layers = {}; | |
| 1582 | + this._zoomBoundLayers = {}; | |
| 1583 | + this._tileLayersNum = 0; | |
| 1584 | + | |
| 1585 | + this.callInitHooks(); | |
| 1586 | + | |
| 1587 | + this._addLayers(options.layers); | |
| 1588 | + }, | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + // public methods that modify map state | |
| 1592 | + | |
| 1593 | + // replaced by animation-powered implementation in Map.PanAnimation.js | |
| 1594 | + setView: function (center, zoom) { | |
| 1595 | + zoom = zoom === undefined ? this.getZoom() : zoom; | |
| 1596 | + this._resetView(L.latLng(center), this._limitZoom(zoom)); | |
| 1597 | + return this; | |
| 1598 | + }, | |
| 1599 | + | |
| 1600 | + setZoom: function (zoom, options) { | |
| 1601 | + if (!this._loaded) { | |
| 1602 | + this._zoom = this._limitZoom(zoom); | |
| 1603 | + return this; | |
| 1604 | + } | |
| 1605 | + return this.setView(this.getCenter(), zoom, {zoom: options}); | |
| 1606 | + }, | |
| 1607 | + | |
| 1608 | + zoomIn: function (delta, options) { | |
| 1609 | + return this.setZoom(this._zoom + (delta || 1), options); | |
| 1610 | + }, | |
| 1611 | + | |
| 1612 | + zoomOut: function (delta, options) { | |
| 1613 | + return this.setZoom(this._zoom - (delta || 1), options); | |
| 1614 | + }, | |
| 1615 | + | |
| 1616 | + setZoomAround: function (latlng, zoom, options) { | |
| 1617 | + var scale = this.getZoomScale(zoom), | |
| 1618 | + viewHalf = this.getSize().divideBy(2), | |
| 1619 | + containerPoint = latlng instanceof L.Point ? latlng : this.latLngToContainerPoint(latlng), | |
| 1620 | + | |
| 1621 | + centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale), | |
| 1622 | + newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset)); | |
| 1623 | + | |
| 1624 | + return this.setView(newCenter, zoom, {zoom: options}); | |
| 1625 | + }, | |
| 1626 | + | |
| 1627 | + fitBounds: function (bounds, options) { | |
| 1628 | + | |
| 1629 | + options = options || {}; | |
| 1630 | + bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds); | |
| 1631 | + | |
| 1632 | + var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]), | |
| 1633 | + paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]), | |
| 1634 | + | |
| 1635 | + zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR)), | |
| 1636 | + paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), | |
| 1637 | + | |
| 1638 | + swPoint = this.project(bounds.getSouthWest(), zoom), | |
| 1639 | + nePoint = this.project(bounds.getNorthEast(), zoom), | |
| 1640 | + center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom); | |
| 1641 | + | |
| 1642 | + zoom = options && options.maxZoom ? Math.min(options.maxZoom, zoom) : zoom; | |
| 1643 | + | |
| 1644 | + return this.setView(center, zoom, options); | |
| 1645 | + }, | |
| 1646 | + | |
| 1647 | + fitWorld: function (options) { | |
| 1648 | + return this.fitBounds([[-90, -180], [90, 180]], options); | |
| 1649 | + }, | |
| 1650 | + | |
| 1651 | + panTo: function (center, options) { // (LatLng) | |
| 1652 | + return this.setView(center, this._zoom, {pan: options}); | |
| 1653 | + }, | |
| 1654 | + | |
| 1655 | + panBy: function (offset) { // (Point) | |
| 1656 | + // replaced with animated panBy in Map.PanAnimation.js | |
| 1657 | + this.fire('movestart'); | |
| 1658 | + | |
| 1659 | + this._rawPanBy(L.point(offset)); | |
| 1660 | + | |
| 1661 | + this.fire('move'); | |
| 1662 | + return this.fire('moveend'); | |
| 1663 | + }, | |
| 1664 | + | |
| 1665 | + setMaxBounds: function (bounds) { | |
| 1666 | + bounds = L.latLngBounds(bounds); | |
| 1667 | + | |
| 1668 | + this.options.maxBounds = bounds; | |
| 1669 | + | |
| 1670 | + if (!bounds) { | |
| 1671 | + return this.off('moveend', this._panInsideMaxBounds, this); | |
| 1672 | + } | |
| 1673 | + | |
| 1674 | + if (this._loaded) { | |
| 1675 | + this._panInsideMaxBounds(); | |
| 1676 | + } | |
| 1677 | + | |
| 1678 | + return this.on('moveend', this._panInsideMaxBounds, this); | |
| 1679 | + }, | |
| 1680 | + | |
| 1681 | + panInsideBounds: function (bounds, options) { | |
| 1682 | + var center = this.getCenter(), | |
| 1683 | + newCenter = this._limitCenter(center, this._zoom, bounds); | |
| 1684 | + | |
| 1685 | + if (center.equals(newCenter)) { return this; } | |
| 1686 | + | |
| 1687 | + return this.panTo(newCenter, options); | |
| 1688 | + }, | |
| 1689 | + | |
| 1690 | + addLayer: function (layer) { | |
| 1691 | + // TODO method is too big, refactor | |
| 1692 | + | |
| 1693 | + var id = L.stamp(layer); | |
| 1694 | + | |
| 1695 | + if (this._layers[id]) { return this; } | |
| 1696 | + | |
| 1697 | + this._layers[id] = layer; | |
| 1698 | + | |
| 1699 | + // TODO getMaxZoom, getMinZoom in ILayer (instead of options) | |
| 1700 | + if (layer.options && (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom))) { | |
| 1701 | + this._zoomBoundLayers[id] = layer; | |
| 1702 | + this._updateZoomLevels(); | |
| 1703 | + } | |
| 1704 | + | |
| 1705 | + // TODO looks ugly, refactor!!! | |
| 1706 | + if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { | |
| 1707 | + this._tileLayersNum++; | |
| 1708 | + this._tileLayersToLoad++; | |
| 1709 | + layer.on('load', this._onTileLayerLoad, this); | |
| 1710 | + } | |
| 1711 | + | |
| 1712 | + if (this._loaded) { | |
| 1713 | + this._layerAdd(layer); | |
| 1714 | + } | |
| 1715 | + | |
| 1716 | + return this; | |
| 1717 | + }, | |
| 1718 | + | |
| 1719 | + removeLayer: function (layer) { | |
| 1720 | + var id = L.stamp(layer); | |
| 1721 | + | |
| 1722 | + if (!this._layers[id]) { return this; } | |
| 1723 | + | |
| 1724 | + if (this._loaded) { | |
| 1725 | + layer.onRemove(this); | |
| 1726 | + } | |
| 1727 | + | |
| 1728 | + delete this._layers[id]; | |
| 1729 | + | |
| 1730 | + if (this._loaded) { | |
| 1731 | + this.fire('layerremove', {layer: layer}); | |
| 1732 | + } | |
| 1733 | + | |
| 1734 | + if (this._zoomBoundLayers[id]) { | |
| 1735 | + delete this._zoomBoundLayers[id]; | |
| 1736 | + this._updateZoomLevels(); | |
| 1737 | + } | |
| 1738 | + | |
| 1739 | + // TODO looks ugly, refactor | |
| 1740 | + if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { | |
| 1741 | + this._tileLayersNum--; | |
| 1742 | + this._tileLayersToLoad--; | |
| 1743 | + layer.off('load', this._onTileLayerLoad, this); | |
| 1744 | + } | |
| 1745 | + | |
| 1746 | + return this; | |
| 1747 | + }, | |
| 1748 | + | |
| 1749 | + hasLayer: function (layer) { | |
| 1750 | + if (!layer) { return false; } | |
| 1751 | + | |
| 1752 | + return (L.stamp(layer) in this._layers); | |
| 1753 | + }, | |
| 1754 | + | |
| 1755 | + eachLayer: function (method, context) { | |
| 1756 | + for (var i in this._layers) { | |
| 1757 | + method.call(context, this._layers[i]); | |
| 1758 | + } | |
| 1759 | + return this; | |
| 1760 | + }, | |
| 1761 | + | |
| 1762 | + invalidateSize: function (options) { | |
| 1763 | + if (!this._loaded) { return this; } | |
| 1764 | + | |
| 1765 | + options = L.extend({ | |
| 1766 | + animate: false, | |
| 1767 | + pan: true | |
| 1768 | + }, options === true ? {animate: true} : options); | |
| 1769 | + | |
| 1770 | + var oldSize = this.getSize(); | |
| 1771 | + this._sizeChanged = true; | |
| 1772 | + this._initialCenter = null; | |
| 1773 | + | |
| 1774 | + var newSize = this.getSize(), | |
| 1775 | + oldCenter = oldSize.divideBy(2).round(), | |
| 1776 | + newCenter = newSize.divideBy(2).round(), | |
| 1777 | + offset = oldCenter.subtract(newCenter); | |
| 1778 | + | |
| 1779 | + if (!offset.x && !offset.y) { return this; } | |
| 1780 | + | |
| 1781 | + if (options.animate && options.pan) { | |
| 1782 | + this.panBy(offset); | |
| 1783 | + | |
| 1784 | + } else { | |
| 1785 | + if (options.pan) { | |
| 1786 | + this._rawPanBy(offset); | |
| 1787 | + } | |
| 1788 | + | |
| 1789 | + this.fire('move'); | |
| 1790 | + | |
| 1791 | + if (options.debounceMoveend) { | |
| 1792 | + clearTimeout(this._sizeTimer); | |
| 1793 | + this._sizeTimer = setTimeout(L.bind(this.fire, this, 'moveend'), 200); | |
| 1794 | + } else { | |
| 1795 | + this.fire('moveend'); | |
| 1796 | + } | |
| 1797 | + } | |
| 1798 | + | |
| 1799 | + return this.fire('resize', { | |
| 1800 | + oldSize: oldSize, | |
| 1801 | + newSize: newSize | |
| 1802 | + }); | |
| 1803 | + }, | |
| 1804 | + | |
| 1805 | + // TODO handler.addTo | |
| 1806 | + addHandler: function (name, HandlerClass) { | |
| 1807 | + if (!HandlerClass) { return this; } | |
| 1808 | + | |
| 1809 | + var handler = this[name] = new HandlerClass(this); | |
| 1810 | + | |
| 1811 | + this._handlers.push(handler); | |
| 1812 | + | |
| 1813 | + if (this.options[name]) { | |
| 1814 | + handler.enable(); | |
| 1815 | + } | |
| 1816 | + | |
| 1817 | + return this; | |
| 1818 | + }, | |
| 1819 | + | |
| 1820 | + remove: function () { | |
| 1821 | + if (this._loaded) { | |
| 1822 | + this.fire('unload'); | |
| 1823 | + } | |
| 1824 | + | |
| 1825 | + this._initEvents('off'); | |
| 1826 | + | |
| 1827 | + try { | |
| 1828 | + // throws error in IE6-8 | |
| 1829 | + delete this._container._leaflet; | |
| 1830 | + } catch (e) { | |
| 1831 | + this._container._leaflet = undefined; | |
| 1832 | + } | |
| 1833 | + | |
| 1834 | + this._clearPanes(); | |
| 1835 | + if (this._clearControlPos) { | |
| 1836 | + this._clearControlPos(); | |
| 1837 | + } | |
| 1838 | + | |
| 1839 | + this._clearHandlers(); | |
| 1840 | + | |
| 1841 | + return this; | |
| 1842 | + }, | |
| 1843 | + | |
| 1844 | + | |
| 1845 | + // public methods for getting map state | |
| 1846 | + | |
| 1847 | + getCenter: function () { // (Boolean) -> LatLng | |
| 1848 | + this._checkIfLoaded(); | |
| 1849 | + | |
| 1850 | + if (this._initialCenter && !this._moved()) { | |
| 1851 | + return this._initialCenter; | |
| 1852 | + } | |
| 1853 | + return this.layerPointToLatLng(this._getCenterLayerPoint()); | |
| 1854 | + }, | |
| 1855 | + | |
| 1856 | + getZoom: function () { | |
| 1857 | + return this._zoom; | |
| 1858 | + }, | |
| 1859 | + | |
| 1860 | + getBounds: function () { | |
| 1861 | + var bounds = this.getPixelBounds(), | |
| 1862 | + sw = this.unproject(bounds.getBottomLeft()), | |
| 1863 | + ne = this.unproject(bounds.getTopRight()); | |
| 1864 | + | |
| 1865 | + return new L.LatLngBounds(sw, ne); | |
| 1866 | + }, | |
| 1867 | + | |
| 1868 | + getMinZoom: function () { | |
| 1869 | + return this.options.minZoom === undefined ? | |
| 1870 | + (this._layersMinZoom === undefined ? 0 : this._layersMinZoom) : | |
| 1871 | + this.options.minZoom; | |
| 1872 | + }, | |
| 1873 | + | |
| 1874 | + getMaxZoom: function () { | |
| 1875 | + return this.options.maxZoom === undefined ? | |
| 1876 | + (this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) : | |
| 1877 | + this.options.maxZoom; | |
| 1878 | + }, | |
| 1879 | + | |
| 1880 | + getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number | |
| 1881 | + bounds = L.latLngBounds(bounds); | |
| 1882 | + | |
| 1883 | + var zoom = this.getMinZoom() - (inside ? 1 : 0), | |
| 1884 | + maxZoom = this.getMaxZoom(), | |
| 1885 | + size = this.getSize(), | |
| 1886 | + | |
| 1887 | + nw = bounds.getNorthWest(), | |
| 1888 | + se = bounds.getSouthEast(), | |
| 1889 | + | |
| 1890 | + zoomNotFound = true, | |
| 1891 | + boundsSize; | |
| 1892 | + | |
| 1893 | + padding = L.point(padding || [0, 0]); | |
| 1894 | + | |
| 1895 | + do { | |
| 1896 | + zoom++; | |
| 1897 | + boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom)).add(padding); | |
| 1898 | + zoomNotFound = !inside ? size.contains(boundsSize) : boundsSize.x < size.x || boundsSize.y < size.y; | |
| 1899 | + | |
| 1900 | + } while (zoomNotFound && zoom <= maxZoom); | |
| 1901 | + | |
| 1902 | + if (zoomNotFound && inside) { | |
| 1903 | + return null; | |
| 1904 | + } | |
| 1905 | + | |
| 1906 | + return inside ? zoom : zoom - 1; | |
| 1907 | + }, | |
| 1908 | + | |
| 1909 | + getSize: function () { | |
| 1910 | + if (!this._size || this._sizeChanged) { | |
| 1911 | + this._size = new L.Point( | |
| 1912 | + this._container.clientWidth, | |
| 1913 | + this._container.clientHeight); | |
| 1914 | + | |
| 1915 | + this._sizeChanged = false; | |
| 1916 | + } | |
| 1917 | + return this._size.clone(); | |
| 1918 | + }, | |
| 1919 | + | |
| 1920 | + getPixelBounds: function () { | |
| 1921 | + var topLeftPoint = this._getTopLeftPoint(); | |
| 1922 | + return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize())); | |
| 1923 | + }, | |
| 1924 | + | |
| 1925 | + getPixelOrigin: function () { | |
| 1926 | + this._checkIfLoaded(); | |
| 1927 | + return this._initialTopLeftPoint; | |
| 1928 | + }, | |
| 1929 | + | |
| 1930 | + getPanes: function () { | |
| 1931 | + return this._panes; | |
| 1932 | + }, | |
| 1933 | + | |
| 1934 | + getContainer: function () { | |
| 1935 | + return this._container; | |
| 1936 | + }, | |
| 1937 | + | |
| 1938 | + | |
| 1939 | + // TODO replace with universal implementation after refactoring projections | |
| 1940 | + | |
| 1941 | + getZoomScale: function (toZoom) { | |
| 1942 | + var crs = this.options.crs; | |
| 1943 | + return crs.scale(toZoom) / crs.scale(this._zoom); | |
| 1944 | + }, | |
| 1945 | + | |
| 1946 | + getScaleZoom: function (scale) { | |
| 1947 | + return this._zoom + (Math.log(scale) / Math.LN2); | |
| 1948 | + }, | |
| 1949 | + | |
| 1950 | + | |
| 1951 | + // conversion methods | |
| 1952 | + | |
| 1953 | + project: function (latlng, zoom) { // (LatLng[, Number]) -> Point | |
| 1954 | + zoom = zoom === undefined ? this._zoom : zoom; | |
| 1955 | + return this.options.crs.latLngToPoint(L.latLng(latlng), zoom); | |
| 1956 | + }, | |
| 1957 | + | |
| 1958 | + unproject: function (point, zoom) { // (Point[, Number]) -> LatLng | |
| 1959 | + zoom = zoom === undefined ? this._zoom : zoom; | |
| 1960 | + return this.options.crs.pointToLatLng(L.point(point), zoom); | |
| 1961 | + }, | |
| 1962 | + | |
| 1963 | + layerPointToLatLng: function (point) { // (Point) | |
| 1964 | + var projectedPoint = L.point(point).add(this.getPixelOrigin()); | |
| 1965 | + return this.unproject(projectedPoint); | |
| 1966 | + }, | |
| 1967 | + | |
| 1968 | + latLngToLayerPoint: function (latlng) { // (LatLng) | |
| 1969 | + var projectedPoint = this.project(L.latLng(latlng))._round(); | |
| 1970 | + return projectedPoint._subtract(this.getPixelOrigin()); | |
| 1971 | + }, | |
| 1972 | + | |
| 1973 | + containerPointToLayerPoint: function (point) { // (Point) | |
| 1974 | + return L.point(point).subtract(this._getMapPanePos()); | |
| 1975 | + }, | |
| 1976 | + | |
| 1977 | + layerPointToContainerPoint: function (point) { // (Point) | |
| 1978 | + return L.point(point).add(this._getMapPanePos()); | |
| 1979 | + }, | |
| 1980 | + | |
| 1981 | + containerPointToLatLng: function (point) { | |
| 1982 | + var layerPoint = this.containerPointToLayerPoint(L.point(point)); | |
| 1983 | + return this.layerPointToLatLng(layerPoint); | |
| 1984 | + }, | |
| 1985 | + | |
| 1986 | + latLngToContainerPoint: function (latlng) { | |
| 1987 | + return this.layerPointToContainerPoint(this.latLngToLayerPoint(L.latLng(latlng))); | |
| 1988 | + }, | |
| 1989 | + | |
| 1990 | + mouseEventToContainerPoint: function (e) { // (MouseEvent) | |
| 1991 | + return L.DomEvent.getMousePosition(e, this._container); | |
| 1992 | + }, | |
| 1993 | + | |
| 1994 | + mouseEventToLayerPoint: function (e) { // (MouseEvent) | |
| 1995 | + return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e)); | |
| 1996 | + }, | |
| 1997 | + | |
| 1998 | + mouseEventToLatLng: function (e) { // (MouseEvent) | |
| 1999 | + return this.layerPointToLatLng(this.mouseEventToLayerPoint(e)); | |
| 2000 | + }, | |
| 2001 | + | |
| 2002 | + | |
| 2003 | + // map initialization methods | |
| 2004 | + | |
| 2005 | + _initContainer: function (id) { | |
| 2006 | + var container = this._container = L.DomUtil.get(id); | |
| 2007 | + | |
| 2008 | + if (!container) { | |
| 2009 | + throw new Error('Map container not found.'); | |
| 2010 | + } else if (container._leaflet) { | |
| 2011 | + throw new Error('Map container is already initialized.'); | |
| 2012 | + } | |
| 2013 | + | |
| 2014 | + container._leaflet = true; | |
| 2015 | + }, | |
| 2016 | + | |
| 2017 | + _initLayout: function () { | |
| 2018 | + var container = this._container; | |
| 2019 | + | |
| 2020 | + L.DomUtil.addClass(container, 'leaflet-container' + | |
| 2021 | + (L.Browser.touch ? ' leaflet-touch' : '') + | |
| 2022 | + (L.Browser.retina ? ' leaflet-retina' : '') + | |
| 2023 | + (L.Browser.ielt9 ? ' leaflet-oldie' : '') + | |
| 2024 | + (this.options.fadeAnimation ? ' leaflet-fade-anim' : '')); | |
| 2025 | + | |
| 2026 | + var position = L.DomUtil.getStyle(container, 'position'); | |
| 2027 | + | |
| 2028 | + if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') { | |
| 2029 | + container.style.position = 'relative'; | |
| 2030 | + } | |
| 2031 | + | |
| 2032 | + this._initPanes(); | |
| 2033 | + | |
| 2034 | + if (this._initControlPos) { | |
| 2035 | + this._initControlPos(); | |
| 2036 | + } | |
| 2037 | + }, | |
| 2038 | + | |
| 2039 | + _initPanes: function () { | |
| 2040 | + var panes = this._panes = {}; | |
| 2041 | + | |
| 2042 | + this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container); | |
| 2043 | + | |
| 2044 | + this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane); | |
| 2045 | + panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane); | |
| 2046 | + panes.shadowPane = this._createPane('leaflet-shadow-pane'); | |
| 2047 | + panes.overlayPane = this._createPane('leaflet-overlay-pane'); | |
| 2048 | + panes.markerPane = this._createPane('leaflet-marker-pane'); | |
| 2049 | + panes.popupPane = this._createPane('leaflet-popup-pane'); | |
| 2050 | + | |
| 2051 | + var zoomHide = ' leaflet-zoom-hide'; | |
| 2052 | + | |
| 2053 | + if (!this.options.markerZoomAnimation) { | |
| 2054 | + L.DomUtil.addClass(panes.markerPane, zoomHide); | |
| 2055 | + L.DomUtil.addClass(panes.shadowPane, zoomHide); | |
| 2056 | + L.DomUtil.addClass(panes.popupPane, zoomHide); | |
| 2057 | + } | |
| 2058 | + }, | |
| 2059 | + | |
| 2060 | + _createPane: function (className, container) { | |
| 2061 | + return L.DomUtil.create('div', className, container || this._panes.objectsPane); | |
| 2062 | + }, | |
| 2063 | + | |
| 2064 | + _clearPanes: function () { | |
| 2065 | + this._container.removeChild(this._mapPane); | |
| 2066 | + }, | |
| 2067 | + | |
| 2068 | + _addLayers: function (layers) { | |
| 2069 | + layers = layers ? (L.Util.isArray(layers) ? layers : [layers]) : []; | |
| 2070 | + | |
| 2071 | + for (var i = 0, len = layers.length; i < len; i++) { | |
| 2072 | + this.addLayer(layers[i]); | |
| 2073 | + } | |
| 2074 | + }, | |
| 2075 | + | |
| 2076 | + | |
| 2077 | + // private methods that modify map state | |
| 2078 | + | |
| 2079 | + _resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) { | |
| 2080 | + | |
| 2081 | + var zoomChanged = (this._zoom !== zoom); | |
| 2082 | + | |
| 2083 | + if (!afterZoomAnim) { | |
| 2084 | + this.fire('movestart'); | |
| 2085 | + | |
| 2086 | + if (zoomChanged) { | |
| 2087 | + this.fire('zoomstart'); | |
| 2088 | + } | |
| 2089 | + } | |
| 2090 | + | |
| 2091 | + this._zoom = zoom; | |
| 2092 | + this._initialCenter = center; | |
| 2093 | + | |
| 2094 | + this._initialTopLeftPoint = this._getNewTopLeftPoint(center); | |
| 2095 | + | |
| 2096 | + if (!preserveMapOffset) { | |
| 2097 | + L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0)); | |
| 2098 | + } else { | |
| 2099 | + this._initialTopLeftPoint._add(this._getMapPanePos()); | |
| 2100 | + } | |
| 2101 | + | |
| 2102 | + this._tileLayersToLoad = this._tileLayersNum; | |
| 2103 | + | |
| 2104 | + var loading = !this._loaded; | |
| 2105 | + this._loaded = true; | |
| 2106 | + | |
| 2107 | + this.fire('viewreset', {hard: !preserveMapOffset}); | |
| 2108 | + | |
| 2109 | + if (loading) { | |
| 2110 | + this.fire('load'); | |
| 2111 | + this.eachLayer(this._layerAdd, this); | |
| 2112 | + } | |
| 2113 | + | |
| 2114 | + this.fire('move'); | |
| 2115 | + | |
| 2116 | + if (zoomChanged || afterZoomAnim) { | |
| 2117 | + this.fire('zoomend'); | |
| 2118 | + } | |
| 2119 | + | |
| 2120 | + this.fire('moveend', {hard: !preserveMapOffset}); | |
| 2121 | + }, | |
| 2122 | + | |
| 2123 | + _rawPanBy: function (offset) { | |
| 2124 | + L.DomUtil.setPosition(this._mapPane, this._getMapPanePos().subtract(offset)); | |
| 2125 | + }, | |
| 2126 | + | |
| 2127 | + _getZoomSpan: function () { | |
| 2128 | + return this.getMaxZoom() - this.getMinZoom(); | |
| 2129 | + }, | |
| 2130 | + | |
| 2131 | + _updateZoomLevels: function () { | |
| 2132 | + var i, | |
| 2133 | + minZoom = Infinity, | |
| 2134 | + maxZoom = -Infinity, | |
| 2135 | + oldZoomSpan = this._getZoomSpan(); | |
| 2136 | + | |
| 2137 | + for (i in this._zoomBoundLayers) { | |
| 2138 | + var layer = this._zoomBoundLayers[i]; | |
| 2139 | + if (!isNaN(layer.options.minZoom)) { | |
| 2140 | + minZoom = Math.min(minZoom, layer.options.minZoom); | |
| 2141 | + } | |
| 2142 | + if (!isNaN(layer.options.maxZoom)) { | |
| 2143 | + maxZoom = Math.max(maxZoom, layer.options.maxZoom); | |
| 2144 | + } | |
| 2145 | + } | |
| 2146 | + | |
| 2147 | + if (i === undefined) { // we have no tilelayers | |
| 2148 | + this._layersMaxZoom = this._layersMinZoom = undefined; | |
| 2149 | + } else { | |
| 2150 | + this._layersMaxZoom = maxZoom; | |
| 2151 | + this._layersMinZoom = minZoom; | |
| 2152 | + } | |
| 2153 | + | |
| 2154 | + if (oldZoomSpan !== this._getZoomSpan()) { | |
| 2155 | + this.fire('zoomlevelschange'); | |
| 2156 | + } | |
| 2157 | + }, | |
| 2158 | + | |
| 2159 | + _panInsideMaxBounds: function () { | |
| 2160 | + this.panInsideBounds(this.options.maxBounds); | |
| 2161 | + }, | |
| 2162 | + | |
| 2163 | + _checkIfLoaded: function () { | |
| 2164 | + if (!this._loaded) { | |
| 2165 | + throw new Error('Set map center and zoom first.'); | |
| 2166 | + } | |
| 2167 | + }, | |
| 2168 | + | |
| 2169 | + // map events | |
| 2170 | + | |
| 2171 | + _initEvents: function (onOff) { | |
| 2172 | + if (!L.DomEvent) { return; } | |
| 2173 | + | |
| 2174 | + onOff = onOff || 'on'; | |
| 2175 | + | |
| 2176 | + L.DomEvent[onOff](this._container, 'click', this._onMouseClick, this); | |
| 2177 | + | |
| 2178 | + var events = ['dblclick', 'mousedown', 'mouseup', 'mouseenter', | |
| 2179 | + 'mouseleave', 'mousemove', 'contextmenu'], | |
| 2180 | + i, len; | |
| 2181 | + | |
| 2182 | + for (i = 0, len = events.length; i < len; i++) { | |
| 2183 | + L.DomEvent[onOff](this._container, events[i], this._fireMouseEvent, this); | |
| 2184 | + } | |
| 2185 | + | |
| 2186 | + if (this.options.trackResize) { | |
| 2187 | + L.DomEvent[onOff](window, 'resize', this._onResize, this); | |
| 2188 | + } | |
| 2189 | + }, | |
| 2190 | + | |
| 2191 | + _onResize: function () { | |
| 2192 | + L.Util.cancelAnimFrame(this._resizeRequest); | |
| 2193 | + this._resizeRequest = L.Util.requestAnimFrame( | |
| 2194 | + function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container); | |
| 2195 | + }, | |
| 2196 | + | |
| 2197 | + _onMouseClick: function (e) { | |
| 2198 | + if (!this._loaded || (!e._simulated && | |
| 2199 | + ((this.dragging && this.dragging.moved()) || | |
| 2200 | + (this.boxZoom && this.boxZoom.moved()))) || | |
| 2201 | + L.DomEvent._skipped(e)) { return; } | |
| 2202 | + | |
| 2203 | + this.fire('preclick'); | |
| 2204 | + this._fireMouseEvent(e); | |
| 2205 | + }, | |
| 2206 | + | |
| 2207 | + _fireMouseEvent: function (e) { | |
| 2208 | + if (!this._loaded || L.DomEvent._skipped(e)) { return; } | |
| 2209 | + | |
| 2210 | + var type = e.type; | |
| 2211 | + | |
| 2212 | + type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type)); | |
| 2213 | + | |
| 2214 | + if (!this.hasEventListeners(type)) { return; } | |
| 2215 | + | |
| 2216 | + if (type === 'contextmenu') { | |
| 2217 | + L.DomEvent.preventDefault(e); | |
| 2218 | + } | |
| 2219 | + | |
| 2220 | + var containerPoint = this.mouseEventToContainerPoint(e), | |
| 2221 | + layerPoint = this.containerPointToLayerPoint(containerPoint), | |
| 2222 | + latlng = this.layerPointToLatLng(layerPoint); | |
| 2223 | + | |
| 2224 | + this.fire(type, { | |
| 2225 | + latlng: latlng, | |
| 2226 | + layerPoint: layerPoint, | |
| 2227 | + containerPoint: containerPoint, | |
| 2228 | + originalEvent: e | |
| 2229 | + }); | |
| 2230 | + }, | |
| 2231 | + | |
| 2232 | + _onTileLayerLoad: function () { | |
| 2233 | + this._tileLayersToLoad--; | |
| 2234 | + if (this._tileLayersNum && !this._tileLayersToLoad) { | |
| 2235 | + this.fire('tilelayersload'); | |
| 2236 | + } | |
| 2237 | + }, | |
| 2238 | + | |
| 2239 | + _clearHandlers: function () { | |
| 2240 | + for (var i = 0, len = this._handlers.length; i < len; i++) { | |
| 2241 | + this._handlers[i].disable(); | |
| 2242 | + } | |
| 2243 | + }, | |
| 2244 | + | |
| 2245 | + whenReady: function (callback, context) { | |
| 2246 | + if (this._loaded) { | |
| 2247 | + callback.call(context || this, this); | |
| 2248 | + } else { | |
| 2249 | + this.on('load', callback, context); | |
| 2250 | + } | |
| 2251 | + return this; | |
| 2252 | + }, | |
| 2253 | + | |
| 2254 | + _layerAdd: function (layer) { | |
| 2255 | + layer.onAdd(this); | |
| 2256 | + this.fire('layeradd', {layer: layer}); | |
| 2257 | + }, | |
| 2258 | + | |
| 2259 | + | |
| 2260 | + // private methods for getting map state | |
| 2261 | + | |
| 2262 | + _getMapPanePos: function () { | |
| 2263 | + return L.DomUtil.getPosition(this._mapPane); | |
| 2264 | + }, | |
| 2265 | + | |
| 2266 | + _moved: function () { | |
| 2267 | + var pos = this._getMapPanePos(); | |
| 2268 | + return pos && !pos.equals([0, 0]); | |
| 2269 | + }, | |
| 2270 | + | |
| 2271 | + _getTopLeftPoint: function () { | |
| 2272 | + return this.getPixelOrigin().subtract(this._getMapPanePos()); | |
| 2273 | + }, | |
| 2274 | + | |
| 2275 | + _getNewTopLeftPoint: function (center, zoom) { | |
| 2276 | + var viewHalf = this.getSize()._divideBy(2); | |
| 2277 | + // TODO round on display, not calculation to increase precision? | |
| 2278 | + return this.project(center, zoom)._subtract(viewHalf)._round(); | |
| 2279 | + }, | |
| 2280 | + | |
| 2281 | + _latLngToNewLayerPoint: function (latlng, newZoom, newCenter) { | |
| 2282 | + var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos()); | |
| 2283 | + return this.project(latlng, newZoom)._subtract(topLeft); | |
| 2284 | + }, | |
| 2285 | + | |
| 2286 | + // layer point of the current center | |
| 2287 | + _getCenterLayerPoint: function () { | |
| 2288 | + return this.containerPointToLayerPoint(this.getSize()._divideBy(2)); | |
| 2289 | + }, | |
| 2290 | + | |
| 2291 | + // offset of the specified place to the current center in pixels | |
| 2292 | + _getCenterOffset: function (latlng) { | |
| 2293 | + return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint()); | |
| 2294 | + }, | |
| 2295 | + | |
| 2296 | + // adjust center for view to get inside bounds | |
| 2297 | + _limitCenter: function (center, zoom, bounds) { | |
| 2298 | + | |
| 2299 | + if (!bounds) { return center; } | |
| 2300 | + | |
| 2301 | + var centerPoint = this.project(center, zoom), | |
| 2302 | + viewHalf = this.getSize().divideBy(2), | |
| 2303 | + viewBounds = new L.Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), | |
| 2304 | + offset = this._getBoundsOffset(viewBounds, bounds, zoom); | |
| 2305 | + | |
| 2306 | + return this.unproject(centerPoint.add(offset), zoom); | |
| 2307 | + }, | |
| 2308 | + | |
| 2309 | + // adjust offset for view to get inside bounds | |
| 2310 | + _limitOffset: function (offset, bounds) { | |
| 2311 | + if (!bounds) { return offset; } | |
| 2312 | + | |
| 2313 | + var viewBounds = this.getPixelBounds(), | |
| 2314 | + newBounds = new L.Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset)); | |
| 2315 | + | |
| 2316 | + return offset.add(this._getBoundsOffset(newBounds, bounds)); | |
| 2317 | + }, | |
| 2318 | + | |
| 2319 | + // returns offset needed for pxBounds to get inside maxBounds at a specified zoom | |
| 2320 | + _getBoundsOffset: function (pxBounds, maxBounds, zoom) { | |
| 2321 | + var nwOffset = this.project(maxBounds.getNorthWest(), zoom).subtract(pxBounds.min), | |
| 2322 | + seOffset = this.project(maxBounds.getSouthEast(), zoom).subtract(pxBounds.max), | |
| 2323 | + | |
| 2324 | + dx = this._rebound(nwOffset.x, -seOffset.x), | |
| 2325 | + dy = this._rebound(nwOffset.y, -seOffset.y); | |
| 2326 | + | |
| 2327 | + return new L.Point(dx, dy); | |
| 2328 | + }, | |
| 2329 | + | |
| 2330 | + _rebound: function (left, right) { | |
| 2331 | + return left + right > 0 ? | |
| 2332 | + Math.round(left - right) / 2 : | |
| 2333 | + Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right)); | |
| 2334 | + }, | |
| 2335 | + | |
| 2336 | + _limitZoom: function (zoom) { | |
| 2337 | + var min = this.getMinZoom(), | |
| 2338 | + max = this.getMaxZoom(); | |
| 2339 | + | |
| 2340 | + return Math.max(min, Math.min(max, zoom)); | |
| 2341 | + } | |
| 2342 | +}); | |
| 2343 | + | |
| 2344 | +L.map = function (id, options) { | |
| 2345 | + return new L.Map(id, options); | |
| 2346 | +}; | |
| 2347 | + | |
| 2348 | + | |
| 2349 | +/* | |
| 2350 | + * Mercator projection that takes into account that the Earth is not a perfect sphere. | |
| 2351 | + * Less popular than spherical mercator; used by projections like EPSG:3395. | |
| 2352 | + */ | |
| 2353 | + | |
| 2354 | +L.Projection.Mercator = { | |
| 2355 | + MAX_LATITUDE: 85.0840591556, | |
| 2356 | + | |
| 2357 | + R_MINOR: 6356752.314245179, | |
| 2358 | + R_MAJOR: 6378137, | |
| 2359 | + | |
| 2360 | + project: function (latlng) { // (LatLng) -> Point | |
| 2361 | + var d = L.LatLng.DEG_TO_RAD, | |
| 2362 | + max = this.MAX_LATITUDE, | |
| 2363 | + lat = Math.max(Math.min(max, latlng.lat), -max), | |
| 2364 | + r = this.R_MAJOR, | |
| 2365 | + r2 = this.R_MINOR, | |
| 2366 | + x = latlng.lng * d * r, | |
| 2367 | + y = lat * d, | |
| 2368 | + tmp = r2 / r, | |
| 2369 | + eccent = Math.sqrt(1.0 - tmp * tmp), | |
| 2370 | + con = eccent * Math.sin(y); | |
| 2371 | + | |
| 2372 | + con = Math.pow((1 - con) / (1 + con), eccent * 0.5); | |
| 2373 | + | |
| 2374 | + var ts = Math.tan(0.5 * ((Math.PI * 0.5) - y)) / con; | |
| 2375 | + y = -r * Math.log(ts); | |
| 2376 | + | |
| 2377 | + return new L.Point(x, y); | |
| 2378 | + }, | |
| 2379 | + | |
| 2380 | + unproject: function (point) { // (Point, Boolean) -> LatLng | |
| 2381 | + var d = L.LatLng.RAD_TO_DEG, | |
| 2382 | + r = this.R_MAJOR, | |
| 2383 | + r2 = this.R_MINOR, | |
| 2384 | + lng = point.x * d / r, | |
| 2385 | + tmp = r2 / r, | |
| 2386 | + eccent = Math.sqrt(1 - (tmp * tmp)), | |
| 2387 | + ts = Math.exp(- point.y / r), | |
| 2388 | + phi = (Math.PI / 2) - 2 * Math.atan(ts), | |
| 2389 | + numIter = 15, | |
| 2390 | + tol = 1e-7, | |
| 2391 | + i = numIter, | |
| 2392 | + dphi = 0.1, | |
| 2393 | + con; | |
| 2394 | + | |
| 2395 | + while ((Math.abs(dphi) > tol) && (--i > 0)) { | |
| 2396 | + con = eccent * Math.sin(phi); | |
| 2397 | + dphi = (Math.PI / 2) - 2 * Math.atan(ts * | |
| 2398 | + Math.pow((1.0 - con) / (1.0 + con), 0.5 * eccent)) - phi; | |
| 2399 | + phi += dphi; | |
| 2400 | + } | |
| 2401 | + | |
| 2402 | + return new L.LatLng(phi * d, lng); | |
| 2403 | + } | |
| 2404 | +}; | |
| 2405 | + | |
| 2406 | + | |
| 2407 | + | |
| 2408 | +L.CRS.EPSG3395 = L.extend({}, L.CRS, { | |
| 2409 | + code: 'EPSG:3395', | |
| 2410 | + | |
| 2411 | + projection: L.Projection.Mercator, | |
| 2412 | + | |
| 2413 | + transformation: (function () { | |
| 2414 | + var m = L.Projection.Mercator, | |
| 2415 | + r = m.R_MAJOR, | |
| 2416 | + scale = 0.5 / (Math.PI * r); | |
| 2417 | + | |
| 2418 | + return new L.Transformation(scale, 0.5, -scale, 0.5); | |
| 2419 | + }()) | |
| 2420 | +}); | |
| 2421 | + | |
| 2422 | + | |
| 2423 | +/* | |
| 2424 | + * L.TileLayer is used for standard xyz-numbered tile layers. | |
| 2425 | + */ | |
| 2426 | + | |
| 2427 | +L.TileLayer = L.Class.extend({ | |
| 2428 | + includes: L.Mixin.Events, | |
| 2429 | + | |
| 2430 | + options: { | |
| 2431 | + minZoom: 0, | |
| 2432 | + maxZoom: 18, | |
| 2433 | + tileSize: 256, | |
| 2434 | + subdomains: 'abc', | |
| 2435 | + errorTileUrl: '', | |
| 2436 | + attribution: '', | |
| 2437 | + zoomOffset: 0, | |
| 2438 | + opacity: 1, | |
| 2439 | + /* | |
| 2440 | + maxNativeZoom: null, | |
| 2441 | + zIndex: null, | |
| 2442 | + tms: false, | |
| 2443 | + continuousWorld: false, | |
| 2444 | + noWrap: false, | |
| 2445 | + zoomReverse: false, | |
| 2446 | + detectRetina: false, | |
| 2447 | + reuseTiles: false, | |
| 2448 | + bounds: false, | |
| 2449 | + */ | |
| 2450 | + unloadInvisibleTiles: L.Browser.mobile, | |
| 2451 | + updateWhenIdle: L.Browser.mobile | |
| 2452 | + }, | |
| 2453 | + | |
| 2454 | + initialize: function (url, options) { | |
| 2455 | + options = L.setOptions(this, options); | |
| 2456 | + | |
| 2457 | + // detecting retina displays, adjusting tileSize and zoom levels | |
| 2458 | + if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) { | |
| 2459 | + | |
| 2460 | + options.tileSize = Math.floor(options.tileSize / 2); | |
| 2461 | + options.zoomOffset++; | |
| 2462 | + | |
| 2463 | + if (options.minZoom > 0) { | |
| 2464 | + options.minZoom--; | |
| 2465 | + } | |
| 2466 | + this.options.maxZoom--; | |
| 2467 | + } | |
| 2468 | + | |
| 2469 | + if (options.bounds) { | |
| 2470 | + options.bounds = L.latLngBounds(options.bounds); | |
| 2471 | + } | |
| 2472 | + | |
| 2473 | + this._url = url; | |
| 2474 | + | |
| 2475 | + var subdomains = this.options.subdomains; | |
| 2476 | + | |
| 2477 | + if (typeof subdomains === 'string') { | |
| 2478 | + this.options.subdomains = subdomains.split(''); | |
| 2479 | + } | |
| 2480 | + }, | |
| 2481 | + | |
| 2482 | + onAdd: function (map) { | |
| 2483 | + this._map = map; | |
| 2484 | + this._animated = map._zoomAnimated; | |
| 2485 | + | |
| 2486 | + // create a container div for tiles | |
| 2487 | + this._initContainer(); | |
| 2488 | + | |
| 2489 | + // set up events | |
| 2490 | + map.on({ | |
| 2491 | + 'viewreset': this._reset, | |
| 2492 | + 'moveend': this._update | |
| 2493 | + }, this); | |
| 2494 | + | |
| 2495 | + if (this._animated) { | |
| 2496 | + map.on({ | |
| 2497 | + 'zoomanim': this._animateZoom, | |
| 2498 | + 'zoomend': this._endZoomAnim | |
| 2499 | + }, this); | |
| 2500 | + } | |
| 2501 | + | |
| 2502 | + if (!this.options.updateWhenIdle) { | |
| 2503 | + this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); | |
| 2504 | + map.on('move', this._limitedUpdate, this); | |
| 2505 | + } | |
| 2506 | + | |
| 2507 | + this._reset(); | |
| 2508 | + this._update(); | |
| 2509 | + }, | |
| 2510 | + | |
| 2511 | + addTo: function (map) { | |
| 2512 | + map.addLayer(this); | |
| 2513 | + return this; | |
| 2514 | + }, | |
| 2515 | + | |
| 2516 | + onRemove: function (map) { | |
| 2517 | + this._container.parentNode.removeChild(this._container); | |
| 2518 | + | |
| 2519 | + map.off({ | |
| 2520 | + 'viewreset': this._reset, | |
| 2521 | + 'moveend': this._update | |
| 2522 | + }, this); | |
| 2523 | + | |
| 2524 | + if (this._animated) { | |
| 2525 | + map.off({ | |
| 2526 | + 'zoomanim': this._animateZoom, | |
| 2527 | + 'zoomend': this._endZoomAnim | |
| 2528 | + }, this); | |
| 2529 | + } | |
| 2530 | + | |
| 2531 | + if (!this.options.updateWhenIdle) { | |
| 2532 | + map.off('move', this._limitedUpdate, this); | |
| 2533 | + } | |
| 2534 | + | |
| 2535 | + this._container = null; | |
| 2536 | + this._map = null; | |
| 2537 | + }, | |
| 2538 | + | |
| 2539 | + bringToFront: function () { | |
| 2540 | + var pane = this._map._panes.tilePane; | |
| 2541 | + | |
| 2542 | + if (this._container) { | |
| 2543 | + pane.appendChild(this._container); | |
| 2544 | + this._setAutoZIndex(pane, Math.max); | |
| 2545 | + } | |
| 2546 | + | |
| 2547 | + return this; | |
| 2548 | + }, | |
| 2549 | + | |
| 2550 | + bringToBack: function () { | |
| 2551 | + var pane = this._map._panes.tilePane; | |
| 2552 | + | |
| 2553 | + if (this._container) { | |
| 2554 | + pane.insertBefore(this._container, pane.firstChild); | |
| 2555 | + this._setAutoZIndex(pane, Math.min); | |
| 2556 | + } | |
| 2557 | + | |
| 2558 | + return this; | |
| 2559 | + }, | |
| 2560 | + | |
| 2561 | + getAttribution: function () { | |
| 2562 | + return this.options.attribution; | |
| 2563 | + }, | |
| 2564 | + | |
| 2565 | + getContainer: function () { | |
| 2566 | + return this._container; | |
| 2567 | + }, | |
| 2568 | + | |
| 2569 | + setOpacity: function (opacity) { | |
| 2570 | + this.options.opacity = opacity; | |
| 2571 | + | |
| 2572 | + if (this._map) { | |
| 2573 | + this._updateOpacity(); | |
| 2574 | + } | |
| 2575 | + | |
| 2576 | + return this; | |
| 2577 | + }, | |
| 2578 | + | |
| 2579 | + setZIndex: function (zIndex) { | |
| 2580 | + this.options.zIndex = zIndex; | |
| 2581 | + this._updateZIndex(); | |
| 2582 | + | |
| 2583 | + return this; | |
| 2584 | + }, | |
| 2585 | + | |
| 2586 | + setUrl: function (url, noRedraw) { | |
| 2587 | + this._url = url; | |
| 2588 | + | |
| 2589 | + if (!noRedraw) { | |
| 2590 | + this.redraw(); | |
| 2591 | + } | |
| 2592 | + | |
| 2593 | + return this; | |
| 2594 | + }, | |
| 2595 | + | |
| 2596 | + redraw: function () { | |
| 2597 | + if (this._map) { | |
| 2598 | + this._reset({hard: true}); | |
| 2599 | + this._update(); | |
| 2600 | + } | |
| 2601 | + return this; | |
| 2602 | + }, | |
| 2603 | + | |
| 2604 | + _updateZIndex: function () { | |
| 2605 | + if (this._container && this.options.zIndex !== undefined) { | |
| 2606 | + this._container.style.zIndex = this.options.zIndex; | |
| 2607 | + } | |
| 2608 | + }, | |
| 2609 | + | |
| 2610 | + _setAutoZIndex: function (pane, compare) { | |
| 2611 | + | |
| 2612 | + var layers = pane.children, | |
| 2613 | + edgeZIndex = -compare(Infinity, -Infinity), // -Infinity for max, Infinity for min | |
| 2614 | + zIndex, i, len; | |
| 2615 | + | |
| 2616 | + for (i = 0, len = layers.length; i < len; i++) { | |
| 2617 | + | |
| 2618 | + if (layers[i] !== this._container) { | |
| 2619 | + zIndex = parseInt(layers[i].style.zIndex, 10); | |
| 2620 | + | |
| 2621 | + if (!isNaN(zIndex)) { | |
| 2622 | + edgeZIndex = compare(edgeZIndex, zIndex); | |
| 2623 | + } | |
| 2624 | + } | |
| 2625 | + } | |
| 2626 | + | |
| 2627 | + this.options.zIndex = this._container.style.zIndex = | |
| 2628 | + (isFinite(edgeZIndex) ? edgeZIndex : 0) + compare(1, -1); | |
| 2629 | + }, | |
| 2630 | + | |
| 2631 | + _updateOpacity: function () { | |
| 2632 | + var i, | |
| 2633 | + tiles = this._tiles; | |
| 2634 | + | |
| 2635 | + if (L.Browser.ielt9) { | |
| 2636 | + for (i in tiles) { | |
| 2637 | + L.DomUtil.setOpacity(tiles[i], this.options.opacity); | |
| 2638 | + } | |
| 2639 | + } else { | |
| 2640 | + L.DomUtil.setOpacity(this._container, this.options.opacity); | |
| 2641 | + } | |
| 2642 | + }, | |
| 2643 | + | |
| 2644 | + _initContainer: function () { | |
| 2645 | + var tilePane = this._map._panes.tilePane; | |
| 2646 | + | |
| 2647 | + if (!this._container) { | |
| 2648 | + this._container = L.DomUtil.create('div', 'leaflet-layer'); | |
| 2649 | + | |
| 2650 | + this._updateZIndex(); | |
| 2651 | + | |
| 2652 | + if (this._animated) { | |
| 2653 | + var className = 'leaflet-tile-container'; | |
| 2654 | + | |
| 2655 | + this._bgBuffer = L.DomUtil.create('div', className, this._container); | |
| 2656 | + this._tileContainer = L.DomUtil.create('div', className, this._container); | |
| 2657 | + | |
| 2658 | + } else { | |
| 2659 | + this._tileContainer = this._container; | |
| 2660 | + } | |
| 2661 | + | |
| 2662 | + tilePane.appendChild(this._container); | |
| 2663 | + | |
| 2664 | + if (this.options.opacity < 1) { | |
| 2665 | + this._updateOpacity(); | |
| 2666 | + } | |
| 2667 | + } | |
| 2668 | + }, | |
| 2669 | + | |
| 2670 | + _reset: function (e) { | |
| 2671 | + for (var key in this._tiles) { | |
| 2672 | + this.fire('tileunload', {tile: this._tiles[key]}); | |
| 2673 | + } | |
| 2674 | + | |
| 2675 | + this._tiles = {}; | |
| 2676 | + this._tilesToLoad = 0; | |
| 2677 | + | |
| 2678 | + if (this.options.reuseTiles) { | |
| 2679 | + this._unusedTiles = []; | |
| 2680 | + } | |
| 2681 | + | |
| 2682 | + this._tileContainer.innerHTML = ''; | |
| 2683 | + | |
| 2684 | + if (this._animated && e && e.hard) { | |
| 2685 | + this._clearBgBuffer(); | |
| 2686 | + } | |
| 2687 | + | |
| 2688 | + this._initContainer(); | |
| 2689 | + }, | |
| 2690 | + | |
| 2691 | + _getTileSize: function () { | |
| 2692 | + var map = this._map, | |
| 2693 | + zoom = map.getZoom() + this.options.zoomOffset, | |
| 2694 | + zoomN = this.options.maxNativeZoom, | |
| 2695 | + tileSize = this.options.tileSize; | |
| 2696 | + | |
| 2697 | + if (zoomN && zoom > zoomN) { | |
| 2698 | + tileSize = Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * tileSize); | |
| 2699 | + } | |
| 2700 | + | |
| 2701 | + return tileSize; | |
| 2702 | + }, | |
| 2703 | + | |
| 2704 | + _update: function () { | |
| 2705 | + | |
| 2706 | + if (!this._map) { return; } | |
| 2707 | + | |
| 2708 | + var map = this._map, | |
| 2709 | + bounds = map.getPixelBounds(), | |
| 2710 | + zoom = map.getZoom(), | |
| 2711 | + tileSize = this._getTileSize(); | |
| 2712 | + | |
| 2713 | + if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { | |
| 2714 | + return; | |
| 2715 | + } | |
| 2716 | + | |
| 2717 | + var tileBounds = L.bounds( | |
| 2718 | + bounds.min.divideBy(tileSize)._floor(), | |
| 2719 | + bounds.max.divideBy(tileSize)._floor()); | |
| 2720 | + | |
| 2721 | + this._addTilesFromCenterOut(tileBounds); | |
| 2722 | + | |
| 2723 | + if (this.options.unloadInvisibleTiles || this.options.reuseTiles) { | |
| 2724 | + this._removeOtherTiles(tileBounds); | |
| 2725 | + } | |
| 2726 | + }, | |
| 2727 | + | |
| 2728 | + _addTilesFromCenterOut: function (bounds) { | |
| 2729 | + var queue = [], | |
| 2730 | + center = bounds.getCenter(); | |
| 2731 | + | |
| 2732 | + var j, i, point; | |
| 2733 | + | |
| 2734 | + for (j = bounds.min.y; j <= bounds.max.y; j++) { | |
| 2735 | + for (i = bounds.min.x; i <= bounds.max.x; i++) { | |
| 2736 | + point = new L.Point(i, j); | |
| 2737 | + | |
| 2738 | + if (this._tileShouldBeLoaded(point)) { | |
| 2739 | + queue.push(point); | |
| 2740 | + } | |
| 2741 | + } | |
| 2742 | + } | |
| 2743 | + | |
| 2744 | + var tilesToLoad = queue.length; | |
| 2745 | + | |
| 2746 | + if (tilesToLoad === 0) { return; } | |
| 2747 | + | |
| 2748 | + // load tiles in order of their distance to center | |
| 2749 | + queue.sort(function (a, b) { | |
| 2750 | + return a.distanceTo(center) - b.distanceTo(center); | |
| 2751 | + }); | |
| 2752 | + | |
| 2753 | + var fragment = document.createDocumentFragment(); | |
| 2754 | + | |
| 2755 | + // if its the first batch of tiles to load | |
| 2756 | + if (!this._tilesToLoad) { | |
| 2757 | + this.fire('loading'); | |
| 2758 | + } | |
| 2759 | + | |
| 2760 | + this._tilesToLoad += tilesToLoad; | |
| 2761 | + | |
| 2762 | + for (i = 0; i < tilesToLoad; i++) { | |
| 2763 | + this._addTile(queue[i], fragment); | |
| 2764 | + } | |
| 2765 | + | |
| 2766 | + this._tileContainer.appendChild(fragment); | |
| 2767 | + }, | |
| 2768 | + | |
| 2769 | + _tileShouldBeLoaded: function (tilePoint) { | |
| 2770 | + if ((tilePoint.x + ':' + tilePoint.y) in this._tiles) { | |
| 2771 | + return false; // already loaded | |
| 2772 | + } | |
| 2773 | + | |
| 2774 | + var options = this.options; | |
| 2775 | + | |
| 2776 | + if (!options.continuousWorld) { | |
| 2777 | + var limit = this._getWrapTileNum(); | |
| 2778 | + | |
| 2779 | + // don't load if exceeds world bounds | |
| 2780 | + if ((options.noWrap && (tilePoint.x < 0 || tilePoint.x >= limit.x)) || | |
| 2781 | + tilePoint.y < 0 || tilePoint.y >= limit.y) { return false; } | |
| 2782 | + } | |
| 2783 | + | |
| 2784 | + if (options.bounds) { | |
| 2785 | + var tileSize = options.tileSize, | |
| 2786 | + nwPoint = tilePoint.multiplyBy(tileSize), | |
| 2787 | + sePoint = nwPoint.add([tileSize, tileSize]), | |
| 2788 | + nw = this._map.unproject(nwPoint), | |
| 2789 | + se = this._map.unproject(sePoint); | |
| 2790 | + | |
| 2791 | + // TODO temporary hack, will be removed after refactoring projections | |
| 2792 | + // https://github.com/Leaflet/Leaflet/issues/1618 | |
| 2793 | + if (!options.continuousWorld && !options.noWrap) { | |
| 2794 | + nw = nw.wrap(); | |
| 2795 | + se = se.wrap(); | |
| 2796 | + } | |
| 2797 | + | |
| 2798 | + if (!options.bounds.intersects([nw, se])) { return false; } | |
| 2799 | + } | |
| 2800 | + | |
| 2801 | + return true; | |
| 2802 | + }, | |
| 2803 | + | |
| 2804 | + _removeOtherTiles: function (bounds) { | |
| 2805 | + var kArr, x, y, key; | |
| 2806 | + | |
| 2807 | + for (key in this._tiles) { | |
| 2808 | + kArr = key.split(':'); | |
| 2809 | + x = parseInt(kArr[0], 10); | |
| 2810 | + y = parseInt(kArr[1], 10); | |
| 2811 | + | |
| 2812 | + // remove tile if it's out of bounds | |
| 2813 | + if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) { | |
| 2814 | + this._removeTile(key); | |
| 2815 | + } | |
| 2816 | + } | |
| 2817 | + }, | |
| 2818 | + | |
| 2819 | + _removeTile: function (key) { | |
| 2820 | + var tile = this._tiles[key]; | |
| 2821 | + | |
| 2822 | + this.fire('tileunload', {tile: tile, url: tile.src}); | |
| 2823 | + | |
| 2824 | + if (this.options.reuseTiles) { | |
| 2825 | + L.DomUtil.removeClass(tile, 'leaflet-tile-loaded'); | |
| 2826 | + this._unusedTiles.push(tile); | |
| 2827 | + | |
| 2828 | + } else if (tile.parentNode === this._tileContainer) { | |
| 2829 | + this._tileContainer.removeChild(tile); | |
| 2830 | + } | |
| 2831 | + | |
| 2832 | + // for https://github.com/CloudMade/Leaflet/issues/137 | |
| 2833 | + if (!L.Browser.android) { | |
| 2834 | + tile.onload = null; | |
| 2835 | + tile.src = L.Util.emptyImageUrl; | |
| 2836 | + } | |
| 2837 | + | |
| 2838 | + delete this._tiles[key]; | |
| 2839 | + }, | |
| 2840 | + | |
| 2841 | + _addTile: function (tilePoint, container) { | |
| 2842 | + var tilePos = this._getTilePos(tilePoint); | |
| 2843 | + | |
| 2844 | + // get unused tile - or create a new tile | |
| 2845 | + var tile = this._getTile(); | |
| 2846 | + | |
| 2847 | + /* | |
| 2848 | + Chrome 20 layouts much faster with top/left (verify with timeline, frames) | |
| 2849 | + Android 4 browser has display issues with top/left and requires transform instead | |
| 2850 | + (other browsers don't currently care) - see debug/hacks/jitter.html for an example | |
| 2851 | + */ | |
| 2852 | + L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome); | |
| 2853 | + | |
| 2854 | + this._tiles[tilePoint.x + ':' + tilePoint.y] = tile; | |
| 2855 | + | |
| 2856 | + this._loadTile(tile, tilePoint); | |
| 2857 | + | |
| 2858 | + if (tile.parentNode !== this._tileContainer) { | |
| 2859 | + container.appendChild(tile); | |
| 2860 | + } | |
| 2861 | + }, | |
| 2862 | + | |
| 2863 | + _getZoomForUrl: function () { | |
| 2864 | + | |
| 2865 | + var options = this.options, | |
| 2866 | + zoom = this._map.getZoom(); | |
| 2867 | + | |
| 2868 | + if (options.zoomReverse) { | |
| 2869 | + zoom = options.maxZoom - zoom; | |
| 2870 | + } | |
| 2871 | + | |
| 2872 | + zoom += options.zoomOffset; | |
| 2873 | + | |
| 2874 | + return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom; | |
| 2875 | + }, | |
| 2876 | + | |
| 2877 | + _getTilePos: function (tilePoint) { | |
| 2878 | + var origin = this._map.getPixelOrigin(), | |
| 2879 | + tileSize = this._getTileSize(); | |
| 2880 | + | |
| 2881 | + return tilePoint.multiplyBy(tileSize).subtract(origin); | |
| 2882 | + }, | |
| 2883 | + | |
| 2884 | + // image-specific code (override to implement e.g. Canvas or SVG tile layer) | |
| 2885 | + | |
| 2886 | + getTileUrl: function (tilePoint) { | |
| 2887 | + return L.Util.template(this._url, L.extend({ | |
| 2888 | + s: this._getSubdomain(tilePoint), | |
| 2889 | + z: tilePoint.z, | |
| 2890 | + x: tilePoint.x, | |
| 2891 | + y: tilePoint.y | |
| 2892 | + }, this.options)); | |
| 2893 | + }, | |
| 2894 | + | |
| 2895 | + _getWrapTileNum: function () { | |
| 2896 | + var crs = this._map.options.crs, | |
| 2897 | + size = crs.getSize(this._map.getZoom()); | |
| 2898 | + return size.divideBy(this._getTileSize())._floor(); | |
| 2899 | + }, | |
| 2900 | + | |
| 2901 | + _adjustTilePoint: function (tilePoint) { | |
| 2902 | + | |
| 2903 | + var limit = this._getWrapTileNum(); | |
| 2904 | + | |
| 2905 | + // wrap tile coordinates | |
| 2906 | + if (!this.options.continuousWorld && !this.options.noWrap) { | |
| 2907 | + tilePoint.x = ((tilePoint.x % limit.x) + limit.x) % limit.x; | |
| 2908 | + } | |
| 2909 | + | |
| 2910 | + if (this.options.tms) { | |
| 2911 | + tilePoint.y = limit.y - tilePoint.y - 1; | |
| 2912 | + } | |
| 2913 | + | |
| 2914 | + tilePoint.z = this._getZoomForUrl(); | |
| 2915 | + }, | |
| 2916 | + | |
| 2917 | + _getSubdomain: function (tilePoint) { | |
| 2918 | + var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; | |
| 2919 | + return this.options.subdomains[index]; | |
| 2920 | + }, | |
| 2921 | + | |
| 2922 | + _getTile: function () { | |
| 2923 | + if (this.options.reuseTiles && this._unusedTiles.length > 0) { | |
| 2924 | + var tile = this._unusedTiles.pop(); | |
| 2925 | + this._resetTile(tile); | |
| 2926 | + return tile; | |
| 2927 | + } | |
| 2928 | + return this._createTile(); | |
| 2929 | + }, | |
| 2930 | + | |
| 2931 | + // Override if data stored on a tile needs to be cleaned up before reuse | |
| 2932 | + _resetTile: function (/*tile*/) {}, | |
| 2933 | + | |
| 2934 | + _createTile: function () { | |
| 2935 | + var tile = L.DomUtil.create('img', 'leaflet-tile'); | |
| 2936 | + tile.style.width = tile.style.height = this._getTileSize() + 'px'; | |
| 2937 | + tile.galleryimg = 'no'; | |
| 2938 | + | |
| 2939 | + tile.onselectstart = tile.onmousemove = L.Util.falseFn; | |
| 2940 | + | |
| 2941 | + if (L.Browser.ielt9 && this.options.opacity !== undefined) { | |
| 2942 | + L.DomUtil.setOpacity(tile, this.options.opacity); | |
| 2943 | + } | |
| 2944 | + // without this hack, tiles disappear after zoom on Chrome for Android | |
| 2945 | + // https://github.com/Leaflet/Leaflet/issues/2078 | |
| 2946 | + if (L.Browser.mobileWebkit3d) { | |
| 2947 | + tile.style.WebkitBackfaceVisibility = 'hidden'; | |
| 2948 | + } | |
| 2949 | + return tile; | |
| 2950 | + }, | |
| 2951 | + | |
| 2952 | + _loadTile: function (tile, tilePoint) { | |
| 2953 | + tile._layer = this; | |
| 2954 | + tile.onload = this._tileOnLoad; | |
| 2955 | + tile.onerror = this._tileOnError; | |
| 2956 | + | |
| 2957 | + this._adjustTilePoint(tilePoint); | |
| 2958 | + tile.src = this.getTileUrl(tilePoint); | |
| 2959 | + | |
| 2960 | + this.fire('tileloadstart', { | |
| 2961 | + tile: tile, | |
| 2962 | + url: tile.src | |
| 2963 | + }); | |
| 2964 | + }, | |
| 2965 | + | |
| 2966 | + _tileLoaded: function () { | |
| 2967 | + this._tilesToLoad--; | |
| 2968 | + | |
| 2969 | + if (this._animated) { | |
| 2970 | + L.DomUtil.addClass(this._tileContainer, 'leaflet-zoom-animated'); | |
| 2971 | + } | |
| 2972 | + | |
| 2973 | + if (!this._tilesToLoad) { | |
| 2974 | + this.fire('load'); | |
| 2975 | + | |
| 2976 | + if (this._animated) { | |
| 2977 | + // clear scaled tiles after all new tiles are loaded (for performance) | |
| 2978 | + clearTimeout(this._clearBgBufferTimer); | |
| 2979 | + this._clearBgBufferTimer = setTimeout(L.bind(this._clearBgBuffer, this), 500); | |
| 2980 | + } | |
| 2981 | + } | |
| 2982 | + }, | |
| 2983 | + | |
| 2984 | + _tileOnLoad: function () { | |
| 2985 | + var layer = this._layer; | |
| 2986 | + | |
| 2987 | + //Only if we are loading an actual image | |
| 2988 | + if (this.src !== L.Util.emptyImageUrl) { | |
| 2989 | + L.DomUtil.addClass(this, 'leaflet-tile-loaded'); | |
| 2990 | + | |
| 2991 | + layer.fire('tileload', { | |
| 2992 | + tile: this, | |
| 2993 | + url: this.src | |
| 2994 | + }); | |
| 2995 | + } | |
| 2996 | + | |
| 2997 | + layer._tileLoaded(); | |
| 2998 | + }, | |
| 2999 | + | |
| 3000 | + _tileOnError: function () { | |
| 3001 | + var layer = this._layer; | |
| 3002 | + | |
| 3003 | + layer.fire('tileerror', { | |
| 3004 | + tile: this, | |
| 3005 | + url: this.src | |
| 3006 | + }); | |
| 3007 | + | |
| 3008 | + var newUrl = layer.options.errorTileUrl; | |
| 3009 | + if (newUrl) { | |
| 3010 | + this.src = newUrl; | |
| 3011 | + } | |
| 3012 | + | |
| 3013 | + layer._tileLoaded(); | |
| 3014 | + } | |
| 3015 | +}); | |
| 3016 | + | |
| 3017 | +L.tileLayer = function (url, options) { | |
| 3018 | + return new L.TileLayer(url, options); | |
| 3019 | +}; | |
| 3020 | + | |
| 3021 | + | |
| 3022 | +/* | |
| 3023 | + * L.TileLayer.WMS is used for putting WMS tile layers on the map. | |
| 3024 | + */ | |
| 3025 | + | |
| 3026 | +L.TileLayer.WMS = L.TileLayer.extend({ | |
| 3027 | + | |
| 3028 | + defaultWmsParams: { | |
| 3029 | + service: 'WMS', | |
| 3030 | + request: 'GetMap', | |
| 3031 | + version: '1.1.1', | |
| 3032 | + layers: '', | |
| 3033 | + styles: '', | |
| 3034 | + format: 'image/jpeg', | |
| 3035 | + transparent: false | |
| 3036 | + }, | |
| 3037 | + | |
| 3038 | + initialize: function (url, options) { // (String, Object) | |
| 3039 | + | |
| 3040 | + this._url = url; | |
| 3041 | + | |
| 3042 | + var wmsParams = L.extend({}, this.defaultWmsParams), | |
| 3043 | + tileSize = options.tileSize || this.options.tileSize; | |
| 3044 | + | |
| 3045 | + if (options.detectRetina && L.Browser.retina) { | |
| 3046 | + wmsParams.width = wmsParams.height = tileSize * 2; | |
| 3047 | + } else { | |
| 3048 | + wmsParams.width = wmsParams.height = tileSize; | |
| 3049 | + } | |
| 3050 | + | |
| 3051 | + for (var i in options) { | |
| 3052 | + // all keys that are not TileLayer options go to WMS params | |
| 3053 | + if (!this.options.hasOwnProperty(i) && i !== 'crs') { | |
| 3054 | + wmsParams[i] = options[i]; | |
| 3055 | + } | |
| 3056 | + } | |
| 3057 | + | |
| 3058 | + this.wmsParams = wmsParams; | |
| 3059 | + | |
| 3060 | + L.setOptions(this, options); | |
| 3061 | + }, | |
| 3062 | + | |
| 3063 | + onAdd: function (map) { | |
| 3064 | + | |
| 3065 | + this._crs = this.options.crs || map.options.crs; | |
| 3066 | + | |
| 3067 | + this._wmsVersion = parseFloat(this.wmsParams.version); | |
| 3068 | + | |
| 3069 | + var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs'; | |
| 3070 | + this.wmsParams[projectionKey] = this._crs.code; | |
| 3071 | + | |
| 3072 | + L.TileLayer.prototype.onAdd.call(this, map); | |
| 3073 | + }, | |
| 3074 | + | |
| 3075 | + getTileUrl: function (tilePoint) { // (Point, Number) -> String | |
| 3076 | + | |
| 3077 | + var map = this._map, | |
| 3078 | + tileSize = this.options.tileSize, | |
| 3079 | + | |
| 3080 | + nwPoint = tilePoint.multiplyBy(tileSize), | |
| 3081 | + sePoint = nwPoint.add([tileSize, tileSize]), | |
| 3082 | + | |
| 3083 | + nw = this._crs.project(map.unproject(nwPoint, tilePoint.z)), | |
| 3084 | + se = this._crs.project(map.unproject(sePoint, tilePoint.z)), | |
| 3085 | + bbox = this._wmsVersion >= 1.3 && this._crs === L.CRS.EPSG4326 ? | |
| 3086 | + [se.y, nw.x, nw.y, se.x].join(',') : | |
| 3087 | + [nw.x, se.y, se.x, nw.y].join(','), | |
| 3088 | + | |
| 3089 | + url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)}); | |
| 3090 | + | |
| 3091 | + return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox; | |
| 3092 | + }, | |
| 3093 | + | |
| 3094 | + setParams: function (params, noRedraw) { | |
| 3095 | + | |
| 3096 | + L.extend(this.wmsParams, params); | |
| 3097 | + | |
| 3098 | + if (!noRedraw) { | |
| 3099 | + this.redraw(); | |
| 3100 | + } | |
| 3101 | + | |
| 3102 | + return this; | |
| 3103 | + } | |
| 3104 | +}); | |
| 3105 | + | |
| 3106 | +L.tileLayer.wms = function (url, options) { | |
| 3107 | + return new L.TileLayer.WMS(url, options); | |
| 3108 | +}; | |
| 3109 | + | |
| 3110 | + | |
| 3111 | +/* | |
| 3112 | + * L.TileLayer.Canvas is a class that you can use as a base for creating | |
| 3113 | + * dynamically drawn Canvas-based tile layers. | |
| 3114 | + */ | |
| 3115 | + | |
| 3116 | +L.TileLayer.Canvas = L.TileLayer.extend({ | |
| 3117 | + options: { | |
| 3118 | + async: false | |
| 3119 | + }, | |
| 3120 | + | |
| 3121 | + initialize: function (options) { | |
| 3122 | + L.setOptions(this, options); | |
| 3123 | + }, | |
| 3124 | + | |
| 3125 | + redraw: function () { | |
| 3126 | + if (this._map) { | |
| 3127 | + this._reset({hard: true}); | |
| 3128 | + this._update(); | |
| 3129 | + } | |
| 3130 | + | |
| 3131 | + for (var i in this._tiles) { | |
| 3132 | + this._redrawTile(this._tiles[i]); | |
| 3133 | + } | |
| 3134 | + return this; | |
| 3135 | + }, | |
| 3136 | + | |
| 3137 | + _redrawTile: function (tile) { | |
| 3138 | + this.drawTile(tile, tile._tilePoint, this._map._zoom); | |
| 3139 | + }, | |
| 3140 | + | |
| 3141 | + _createTile: function () { | |
| 3142 | + var tile = L.DomUtil.create('canvas', 'leaflet-tile'); | |
| 3143 | + tile.width = tile.height = this.options.tileSize; | |
| 3144 | + tile.onselectstart = tile.onmousemove = L.Util.falseFn; | |
| 3145 | + return tile; | |
| 3146 | + }, | |
| 3147 | + | |
| 3148 | + _loadTile: function (tile, tilePoint) { | |
| 3149 | + tile._layer = this; | |
| 3150 | + tile._tilePoint = tilePoint; | |
| 3151 | + | |
| 3152 | + this._redrawTile(tile); | |
| 3153 | + | |
| 3154 | + if (!this.options.async) { | |
| 3155 | + this.tileDrawn(tile); | |
| 3156 | + } | |
| 3157 | + }, | |
| 3158 | + | |
| 3159 | + drawTile: function (/*tile, tilePoint*/) { | |
| 3160 | + // override with rendering code | |
| 3161 | + }, | |
| 3162 | + | |
| 3163 | + tileDrawn: function (tile) { | |
| 3164 | + this._tileOnLoad.call(tile); | |
| 3165 | + } | |
| 3166 | +}); | |
| 3167 | + | |
| 3168 | + | |
| 3169 | +L.tileLayer.canvas = function (options) { | |
| 3170 | + return new L.TileLayer.Canvas(options); | |
| 3171 | +}; | |
| 3172 | + | |
| 3173 | + | |
| 3174 | +/* | |
| 3175 | + * L.ImageOverlay is used to overlay images over the map (to specific geographical bounds). | |
| 3176 | + */ | |
| 3177 | + | |
| 3178 | +L.ImageOverlay = L.Class.extend({ | |
| 3179 | + includes: L.Mixin.Events, | |
| 3180 | + | |
| 3181 | + options: { | |
| 3182 | + opacity: 1 | |
| 3183 | + }, | |
| 3184 | + | |
| 3185 | + initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) | |
| 3186 | + this._url = url; | |
| 3187 | + this._bounds = L.latLngBounds(bounds); | |
| 3188 | + | |
| 3189 | + L.setOptions(this, options); | |
| 3190 | + }, | |
| 3191 | + | |
| 3192 | + onAdd: function (map) { | |
| 3193 | + this._map = map; | |
| 3194 | + | |
| 3195 | + if (!this._image) { | |
| 3196 | + this._initImage(); | |
| 3197 | + } | |
| 3198 | + | |
| 3199 | + map._panes.overlayPane.appendChild(this._image); | |
| 3200 | + | |
| 3201 | + map.on('viewreset', this._reset, this); | |
| 3202 | + | |
| 3203 | + if (map.options.zoomAnimation && L.Browser.any3d) { | |
| 3204 | + map.on('zoomanim', this._animateZoom, this); | |
| 3205 | + } | |
| 3206 | + | |
| 3207 | + this._reset(); | |
| 3208 | + }, | |
| 3209 | + | |
| 3210 | + onRemove: function (map) { | |
| 3211 | + map.getPanes().overlayPane.removeChild(this._image); | |
| 3212 | + | |
| 3213 | + map.off('viewreset', this._reset, this); | |
| 3214 | + | |
| 3215 | + if (map.options.zoomAnimation) { | |
| 3216 | + map.off('zoomanim', this._animateZoom, this); | |
| 3217 | + } | |
| 3218 | + }, | |
| 3219 | + | |
| 3220 | + addTo: function (map) { | |
| 3221 | + map.addLayer(this); | |
| 3222 | + return this; | |
| 3223 | + }, | |
| 3224 | + | |
| 3225 | + setOpacity: function (opacity) { | |
| 3226 | + this.options.opacity = opacity; | |
| 3227 | + this._updateOpacity(); | |
| 3228 | + return this; | |
| 3229 | + }, | |
| 3230 | + | |
| 3231 | + // TODO remove bringToFront/bringToBack duplication from TileLayer/Path | |
| 3232 | + bringToFront: function () { | |
| 3233 | + if (this._image) { | |
| 3234 | + this._map._panes.overlayPane.appendChild(this._image); | |
| 3235 | + } | |
| 3236 | + return this; | |
| 3237 | + }, | |
| 3238 | + | |
| 3239 | + bringToBack: function () { | |
| 3240 | + var pane = this._map._panes.overlayPane; | |
| 3241 | + if (this._image) { | |
| 3242 | + pane.insertBefore(this._image, pane.firstChild); | |
| 3243 | + } | |
| 3244 | + return this; | |
| 3245 | + }, | |
| 3246 | + | |
| 3247 | + setUrl: function (url) { | |
| 3248 | + this._url = url; | |
| 3249 | + this._image.src = this._url; | |
| 3250 | + }, | |
| 3251 | + | |
| 3252 | + getAttribution: function () { | |
| 3253 | + return this.options.attribution; | |
| 3254 | + }, | |
| 3255 | + | |
| 3256 | + _initImage: function () { | |
| 3257 | + this._image = L.DomUtil.create('img', 'leaflet-image-layer'); | |
| 3258 | + | |
| 3259 | + if (this._map.options.zoomAnimation && L.Browser.any3d) { | |
| 3260 | + L.DomUtil.addClass(this._image, 'leaflet-zoom-animated'); | |
| 3261 | + } else { | |
| 3262 | + L.DomUtil.addClass(this._image, 'leaflet-zoom-hide'); | |
| 3263 | + } | |
| 3264 | + | |
| 3265 | + this._updateOpacity(); | |
| 3266 | + | |
| 3267 | + //TODO createImage util method to remove duplication | |
| 3268 | + L.extend(this._image, { | |
| 3269 | + galleryimg: 'no', | |
| 3270 | + onselectstart: L.Util.falseFn, | |
| 3271 | + onmousemove: L.Util.falseFn, | |
| 3272 | + onload: L.bind(this._onImageLoad, this), | |
| 3273 | + src: this._url | |
| 3274 | + }); | |
| 3275 | + }, | |
| 3276 | + | |
| 3277 | + _animateZoom: function (e) { | |
| 3278 | + var map = this._map, | |
| 3279 | + image = this._image, | |
| 3280 | + scale = map.getZoomScale(e.zoom), | |
| 3281 | + nw = this._bounds.getNorthWest(), | |
| 3282 | + se = this._bounds.getSouthEast(), | |
| 3283 | + | |
| 3284 | + topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), | |
| 3285 | + size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), | |
| 3286 | + origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); | |
| 3287 | + | |
| 3288 | + image.style[L.DomUtil.TRANSFORM] = | |
| 3289 | + L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') '; | |
| 3290 | + }, | |
| 3291 | + | |
| 3292 | + _reset: function () { | |
| 3293 | + var image = this._image, | |
| 3294 | + topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()), | |
| 3295 | + size = this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(topLeft); | |
| 3296 | + | |
| 3297 | + L.DomUtil.setPosition(image, topLeft); | |
| 3298 | + | |
| 3299 | + image.style.width = size.x + 'px'; | |
| 3300 | + image.style.height = size.y + 'px'; | |
| 3301 | + }, | |
| 3302 | + | |
| 3303 | + _onImageLoad: function () { | |
| 3304 | + this.fire('load'); | |
| 3305 | + }, | |
| 3306 | + | |
| 3307 | + _updateOpacity: function () { | |
| 3308 | + L.DomUtil.setOpacity(this._image, this.options.opacity); | |
| 3309 | + } | |
| 3310 | +}); | |
| 3311 | + | |
| 3312 | +L.imageOverlay = function (url, bounds, options) { | |
| 3313 | + return new L.ImageOverlay(url, bounds, options); | |
| 3314 | +}; | |
| 3315 | + | |
| 3316 | + | |
| 3317 | +/* | |
| 3318 | + * L.Icon is an image-based icon class that you can use with L.Marker for custom markers. | |
| 3319 | + */ | |
| 3320 | + | |
| 3321 | +L.Icon = L.Class.extend({ | |
| 3322 | + options: { | |
| 3323 | + /* | |
| 3324 | + iconUrl: (String) (required) | |
| 3325 | + iconRetinaUrl: (String) (optional, used for retina devices if detected) | |
| 3326 | + iconSize: (Point) (can be set through CSS) | |
| 3327 | + iconAnchor: (Point) (centered by default, can be set in CSS with negative margins) | |
| 3328 | + popupAnchor: (Point) (if not specified, popup opens in the anchor point) | |
| 3329 | + shadowUrl: (String) (no shadow by default) | |
| 3330 | + shadowRetinaUrl: (String) (optional, used for retina devices if detected) | |
| 3331 | + shadowSize: (Point) | |
| 3332 | + shadowAnchor: (Point) | |
| 3333 | + */ | |
| 3334 | + className: '' | |
| 3335 | + }, | |
| 3336 | + | |
| 3337 | + initialize: function (options) { | |
| 3338 | + L.setOptions(this, options); | |
| 3339 | + }, | |
| 3340 | + | |
| 3341 | + createIcon: function (oldIcon) { | |
| 3342 | + return this._createIcon('icon', oldIcon); | |
| 3343 | + }, | |
| 3344 | + | |
| 3345 | + createShadow: function (oldIcon) { | |
| 3346 | + return this._createIcon('shadow', oldIcon); | |
| 3347 | + }, | |
| 3348 | + | |
| 3349 | + _createIcon: function (name, oldIcon) { | |
| 3350 | + var src = this._getIconUrl(name); | |
| 3351 | + | |
| 3352 | + if (!src) { | |
| 3353 | + if (name === 'icon') { | |
| 3354 | + throw new Error('iconUrl not set in Icon options (see the docs).'); | |
| 3355 | + } | |
| 3356 | + return null; | |
| 3357 | + } | |
| 3358 | + | |
| 3359 | + var img; | |
| 3360 | + if (!oldIcon || oldIcon.tagName !== 'IMG') { | |
| 3361 | + img = this._createImg(src); | |
| 3362 | + } else { | |
| 3363 | + img = this._createImg(src, oldIcon); | |
| 3364 | + } | |
| 3365 | + this._setIconStyles(img, name); | |
| 3366 | + | |
| 3367 | + return img; | |
| 3368 | + }, | |
| 3369 | + | |
| 3370 | + _setIconStyles: function (img, name) { | |
| 3371 | + var options = this.options, | |
| 3372 | + size = L.point(options[name + 'Size']), | |
| 3373 | + anchor; | |
| 3374 | + | |
| 3375 | + if (name === 'shadow') { | |
| 3376 | + anchor = L.point(options.shadowAnchor || options.iconAnchor); | |
| 3377 | + } else { | |
| 3378 | + anchor = L.point(options.iconAnchor); | |
| 3379 | + } | |
| 3380 | + | |
| 3381 | + if (!anchor && size) { | |
| 3382 | + anchor = size.divideBy(2, true); | |
| 3383 | + } | |
| 3384 | + | |
| 3385 | + img.className = 'leaflet-marker-' + name + ' ' + options.className; | |
| 3386 | + | |
| 3387 | + if (anchor) { | |
| 3388 | + img.style.marginLeft = (-anchor.x) + 'px'; | |
| 3389 | + img.style.marginTop = (-anchor.y) + 'px'; | |
| 3390 | + } | |
| 3391 | + | |
| 3392 | + if (size) { | |
| 3393 | + img.style.width = size.x + 'px'; | |
| 3394 | + img.style.height = size.y + 'px'; | |
| 3395 | + } | |
| 3396 | + }, | |
| 3397 | + | |
| 3398 | + _createImg: function (src, el) { | |
| 3399 | + el = el || document.createElement('img'); | |
| 3400 | + el.src = src; | |
| 3401 | + return el; | |
| 3402 | + }, | |
| 3403 | + | |
| 3404 | + _getIconUrl: function (name) { | |
| 3405 | + if (L.Browser.retina && this.options[name + 'RetinaUrl']) { | |
| 3406 | + return this.options[name + 'RetinaUrl']; | |
| 3407 | + } | |
| 3408 | + return this.options[name + 'Url']; | |
| 3409 | + } | |
| 3410 | +}); | |
| 3411 | + | |
| 3412 | +L.icon = function (options) { | |
| 3413 | + return new L.Icon(options); | |
| 3414 | +}; | |
| 3415 | + | |
| 3416 | + | |
| 3417 | +/* | |
| 3418 | + * L.Icon.Default is the blue marker icon used by default in Leaflet. | |
| 3419 | + */ | |
| 3420 | + | |
| 3421 | +L.Icon.Default = L.Icon.extend({ | |
| 3422 | + | |
| 3423 | + options: { | |
| 3424 | + iconSize: [25, 41], | |
| 3425 | + iconAnchor: [12, 41], | |
| 3426 | + popupAnchor: [1, -34], | |
| 3427 | + | |
| 3428 | + shadowSize: [41, 41] | |
| 3429 | + }, | |
| 3430 | + | |
| 3431 | + _getIconUrl: function (name) { | |
| 3432 | + var key = name + 'Url'; | |
| 3433 | + | |
| 3434 | + if (this.options[key]) { | |
| 3435 | + return this.options[key]; | |
| 3436 | + } | |
| 3437 | + | |
| 3438 | + if (L.Browser.retina && name === 'icon') { | |
| 3439 | + name += '-2x'; | |
| 3440 | + } | |
| 3441 | + | |
| 3442 | + var path = L.Icon.Default.imagePath; | |
| 3443 | + | |
| 3444 | + if (!path) { | |
| 3445 | + throw new Error('Couldn\'t autodetect L.Icon.Default.imagePath, set it manually.'); | |
| 3446 | + } | |
| 3447 | + | |
| 3448 | + return path + '/marker-' + name + '.png'; | |
| 3449 | + } | |
| 3450 | +}); | |
| 3451 | + | |
| 3452 | +L.Icon.Default.imagePath = (function () { | |
| 3453 | + var scripts = document.getElementsByTagName('script'), | |
| 3454 | + leafletRe = /[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/; | |
| 3455 | + | |
| 3456 | + var i, len, src, matches, path; | |
| 3457 | + | |
| 3458 | + for (i = 0, len = scripts.length; i < len; i++) { | |
| 3459 | + src = scripts[i].src; | |
| 3460 | + matches = src.match(leafletRe); | |
| 3461 | + | |
| 3462 | + if (matches) { | |
| 3463 | + path = src.split(leafletRe)[0]; | |
| 3464 | + return (path ? path + '/' : '') + 'images'; | |
| 3465 | + } | |
| 3466 | + } | |
| 3467 | +}()); | |
| 3468 | + | |
| 3469 | + | |
| 3470 | +/* | |
| 3471 | + * L.Marker is used to display clickable/draggable icons on the map. | |
| 3472 | + */ | |
| 3473 | + | |
| 3474 | +L.Marker = L.Class.extend({ | |
| 3475 | + | |
| 3476 | + includes: L.Mixin.Events, | |
| 3477 | + | |
| 3478 | + options: { | |
| 3479 | + icon: new L.Icon.Default(), | |
| 3480 | + title: '', | |
| 3481 | + alt: '', | |
| 3482 | + clickable: true, | |
| 3483 | + draggable: false, | |
| 3484 | + keyboard: true, | |
| 3485 | + zIndexOffset: 0, | |
| 3486 | + opacity: 1, | |
| 3487 | + riseOnHover: false, | |
| 3488 | + riseOffset: 250 | |
| 3489 | + }, | |
| 3490 | + | |
| 3491 | + initialize: function (latlng, options) { | |
| 3492 | + L.setOptions(this, options); | |
| 3493 | + this._latlng = L.latLng(latlng); | |
| 3494 | + }, | |
| 3495 | + | |
| 3496 | + onAdd: function (map) { | |
| 3497 | + this._map = map; | |
| 3498 | + | |
| 3499 | + map.on('viewreset', this.update, this); | |
| 3500 | + | |
| 3501 | + this._initIcon(); | |
| 3502 | + this.update(); | |
| 3503 | + this.fire('add'); | |
| 3504 | + | |
| 3505 | + if (map.options.zoomAnimation && map.options.markerZoomAnimation) { | |
| 3506 | + map.on('zoomanim', this._animateZoom, this); | |
| 3507 | + } | |
| 3508 | + }, | |
| 3509 | + | |
| 3510 | + addTo: function (map) { | |
| 3511 | + map.addLayer(this); | |
| 3512 | + return this; | |
| 3513 | + }, | |
| 3514 | + | |
| 3515 | + onRemove: function (map) { | |
| 3516 | + if (this.dragging) { | |
| 3517 | + this.dragging.disable(); | |
| 3518 | + } | |
| 3519 | + | |
| 3520 | + this._removeIcon(); | |
| 3521 | + this._removeShadow(); | |
| 3522 | + | |
| 3523 | + this.fire('remove'); | |
| 3524 | + | |
| 3525 | + map.off({ | |
| 3526 | + 'viewreset': this.update, | |
| 3527 | + 'zoomanim': this._animateZoom | |
| 3528 | + }, this); | |
| 3529 | + | |
| 3530 | + this._map = null; | |
| 3531 | + }, | |
| 3532 | + | |
| 3533 | + getLatLng: function () { | |
| 3534 | + return this._latlng; | |
| 3535 | + }, | |
| 3536 | + | |
| 3537 | + setLatLng: function (latlng) { | |
| 3538 | + this._latlng = L.latLng(latlng); | |
| 3539 | + | |
| 3540 | + this.update(); | |
| 3541 | + | |
| 3542 | + return this.fire('move', { latlng: this._latlng }); | |
| 3543 | + }, | |
| 3544 | + | |
| 3545 | + setZIndexOffset: function (offset) { | |
| 3546 | + this.options.zIndexOffset = offset; | |
| 3547 | + this.update(); | |
| 3548 | + | |
| 3549 | + return this; | |
| 3550 | + }, | |
| 3551 | + | |
| 3552 | + setIcon: function (icon) { | |
| 3553 | + | |
| 3554 | + this.options.icon = icon; | |
| 3555 | + | |
| 3556 | + if (this._map) { | |
| 3557 | + this._initIcon(); | |
| 3558 | + this.update(); | |
| 3559 | + } | |
| 3560 | + | |
| 3561 | + if (this._popup) { | |
| 3562 | + this.bindPopup(this._popup); | |
| 3563 | + } | |
| 3564 | + | |
| 3565 | + return this; | |
| 3566 | + }, | |
| 3567 | + | |
| 3568 | + update: function () { | |
| 3569 | + if (this._icon) { | |
| 3570 | + var pos = this._map.latLngToLayerPoint(this._latlng).round(); | |
| 3571 | + this._setPos(pos); | |
| 3572 | + } | |
| 3573 | + | |
| 3574 | + return this; | |
| 3575 | + }, | |
| 3576 | + | |
| 3577 | + _initIcon: function () { | |
| 3578 | + var options = this.options, | |
| 3579 | + map = this._map, | |
| 3580 | + animation = (map.options.zoomAnimation && map.options.markerZoomAnimation), | |
| 3581 | + classToAdd = animation ? 'leaflet-zoom-animated' : 'leaflet-zoom-hide'; | |
| 3582 | + | |
| 3583 | + var icon = options.icon.createIcon(this._icon), | |
| 3584 | + addIcon = false; | |
| 3585 | + | |
| 3586 | + // if we're not reusing the icon, remove the old one and init new one | |
| 3587 | + if (icon !== this._icon) { | |
| 3588 | + if (this._icon) { | |
| 3589 | + this._removeIcon(); | |
| 3590 | + } | |
| 3591 | + addIcon = true; | |
| 3592 | + | |
| 3593 | + if (options.title) { | |
| 3594 | + icon.title = options.title; | |
| 3595 | + } | |
| 3596 | + | |
| 3597 | + if (options.alt) { | |
| 3598 | + icon.alt = options.alt; | |
| 3599 | + } | |
| 3600 | + } | |
| 3601 | + | |
| 3602 | + L.DomUtil.addClass(icon, classToAdd); | |
| 3603 | + | |
| 3604 | + if (options.keyboard) { | |
| 3605 | + icon.tabIndex = '0'; | |
| 3606 | + } | |
| 3607 | + | |
| 3608 | + this._icon = icon; | |
| 3609 | + | |
| 3610 | + this._initInteraction(); | |
| 3611 | + | |
| 3612 | + if (options.riseOnHover) { | |
| 3613 | + L.DomEvent | |
| 3614 | + .on(icon, 'mouseover', this._bringToFront, this) | |
| 3615 | + .on(icon, 'mouseout', this._resetZIndex, this); | |
| 3616 | + } | |
| 3617 | + | |
| 3618 | + var newShadow = options.icon.createShadow(this._shadow), | |
| 3619 | + addShadow = false; | |
| 3620 | + | |
| 3621 | + if (newShadow !== this._shadow) { | |
| 3622 | + this._removeShadow(); | |
| 3623 | + addShadow = true; | |
| 3624 | + } | |
| 3625 | + | |
| 3626 | + if (newShadow) { | |
| 3627 | + L.DomUtil.addClass(newShadow, classToAdd); | |
| 3628 | + } | |
| 3629 | + this._shadow = newShadow; | |
| 3630 | + | |
| 3631 | + | |
| 3632 | + if (options.opacity < 1) { | |
| 3633 | + this._updateOpacity(); | |
| 3634 | + } | |
| 3635 | + | |
| 3636 | + | |
| 3637 | + var panes = this._map._panes; | |
| 3638 | + | |
| 3639 | + if (addIcon) { | |
| 3640 | + panes.markerPane.appendChild(this._icon); | |
| 3641 | + } | |
| 3642 | + | |
| 3643 | + if (newShadow && addShadow) { | |
| 3644 | + panes.shadowPane.appendChild(this._shadow); | |
| 3645 | + } | |
| 3646 | + }, | |
| 3647 | + | |
| 3648 | + _removeIcon: function () { | |
| 3649 | + if (this.options.riseOnHover) { | |
| 3650 | + L.DomEvent | |
| 3651 | + .off(this._icon, 'mouseover', this._bringToFront) | |
| 3652 | + .off(this._icon, 'mouseout', this._resetZIndex); | |
| 3653 | + } | |
| 3654 | + | |
| 3655 | + this._map._panes.markerPane.removeChild(this._icon); | |
| 3656 | + | |
| 3657 | + this._icon = null; | |
| 3658 | + }, | |
| 3659 | + | |
| 3660 | + _removeShadow: function () { | |
| 3661 | + if (this._shadow) { | |
| 3662 | + this._map._panes.shadowPane.removeChild(this._shadow); | |
| 3663 | + } | |
| 3664 | + this._shadow = null; | |
| 3665 | + }, | |
| 3666 | + | |
| 3667 | + _setPos: function (pos) { | |
| 3668 | + L.DomUtil.setPosition(this._icon, pos); | |
| 3669 | + | |
| 3670 | + if (this._shadow) { | |
| 3671 | + L.DomUtil.setPosition(this._shadow, pos); | |
| 3672 | + } | |
| 3673 | + | |
| 3674 | + this._zIndex = pos.y + this.options.zIndexOffset; | |
| 3675 | + | |
| 3676 | + this._resetZIndex(); | |
| 3677 | + }, | |
| 3678 | + | |
| 3679 | + _updateZIndex: function (offset) { | |
| 3680 | + this._icon.style.zIndex = this._zIndex + offset; | |
| 3681 | + }, | |
| 3682 | + | |
| 3683 | + _animateZoom: function (opt) { | |
| 3684 | + var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); | |
| 3685 | + | |
| 3686 | + this._setPos(pos); | |
| 3687 | + }, | |
| 3688 | + | |
| 3689 | + _initInteraction: function () { | |
| 3690 | + | |
| 3691 | + if (!this.options.clickable) { return; } | |
| 3692 | + | |
| 3693 | + // TODO refactor into something shared with Map/Path/etc. to DRY it up | |
| 3694 | + | |
| 3695 | + var icon = this._icon, | |
| 3696 | + events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu']; | |
| 3697 | + | |
| 3698 | + L.DomUtil.addClass(icon, 'leaflet-clickable'); | |
| 3699 | + L.DomEvent.on(icon, 'click', this._onMouseClick, this); | |
| 3700 | + L.DomEvent.on(icon, 'keypress', this._onKeyPress, this); | |
| 3701 | + | |
| 3702 | + for (var i = 0; i < events.length; i++) { | |
| 3703 | + L.DomEvent.on(icon, events[i], this._fireMouseEvent, this); | |
| 3704 | + } | |
| 3705 | + | |
| 3706 | + if (L.Handler.MarkerDrag) { | |
| 3707 | + this.dragging = new L.Handler.MarkerDrag(this); | |
| 3708 | + | |
| 3709 | + if (this.options.draggable) { | |
| 3710 | + this.dragging.enable(); | |
| 3711 | + } | |
| 3712 | + } | |
| 3713 | + }, | |
| 3714 | + | |
| 3715 | + _onMouseClick: function (e) { | |
| 3716 | + var wasDragged = this.dragging && this.dragging.moved(); | |
| 3717 | + | |
| 3718 | + if (this.hasEventListeners(e.type) || wasDragged) { | |
| 3719 | + L.DomEvent.stopPropagation(e); | |
| 3720 | + } | |
| 3721 | + | |
| 3722 | + if (wasDragged) { return; } | |
| 3723 | + | |
| 3724 | + if ((!this.dragging || !this.dragging._enabled) && this._map.dragging && this._map.dragging.moved()) { return; } | |
| 3725 | + | |
| 3726 | + this.fire(e.type, { | |
| 3727 | + originalEvent: e, | |
| 3728 | + latlng: this._latlng | |
| 3729 | + }); | |
| 3730 | + }, | |
| 3731 | + | |
| 3732 | + _onKeyPress: function (e) { | |
| 3733 | + if (e.keyCode === 13) { | |
| 3734 | + this.fire('click', { | |
| 3735 | + originalEvent: e, | |
| 3736 | + latlng: this._latlng | |
| 3737 | + }); | |
| 3738 | + } | |
| 3739 | + }, | |
| 3740 | + | |
| 3741 | + _fireMouseEvent: function (e) { | |
| 3742 | + | |
| 3743 | + this.fire(e.type, { | |
| 3744 | + originalEvent: e, | |
| 3745 | + latlng: this._latlng | |
| 3746 | + }); | |
| 3747 | + | |
| 3748 | + // TODO proper custom event propagation | |
| 3749 | + // this line will always be called if marker is in a FeatureGroup | |
| 3750 | + if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) { | |
| 3751 | + L.DomEvent.preventDefault(e); | |
| 3752 | + } | |
| 3753 | + if (e.type !== 'mousedown') { | |
| 3754 | + L.DomEvent.stopPropagation(e); | |
| 3755 | + } else { | |
| 3756 | + L.DomEvent.preventDefault(e); | |
| 3757 | + } | |
| 3758 | + }, | |
| 3759 | + | |
| 3760 | + setOpacity: function (opacity) { | |
| 3761 | + this.options.opacity = opacity; | |
| 3762 | + if (this._map) { | |
| 3763 | + this._updateOpacity(); | |
| 3764 | + } | |
| 3765 | + | |
| 3766 | + return this; | |
| 3767 | + }, | |
| 3768 | + | |
| 3769 | + _updateOpacity: function () { | |
| 3770 | + L.DomUtil.setOpacity(this._icon, this.options.opacity); | |
| 3771 | + if (this._shadow) { | |
| 3772 | + L.DomUtil.setOpacity(this._shadow, this.options.opacity); | |
| 3773 | + } | |
| 3774 | + }, | |
| 3775 | + | |
| 3776 | + _bringToFront: function () { | |
| 3777 | + this._updateZIndex(this.options.riseOffset); | |
| 3778 | + }, | |
| 3779 | + | |
| 3780 | + _resetZIndex: function () { | |
| 3781 | + this._updateZIndex(0); | |
| 3782 | + } | |
| 3783 | +}); | |
| 3784 | + | |
| 3785 | +L.marker = function (latlng, options) { | |
| 3786 | + return new L.Marker(latlng, options); | |
| 3787 | +}; | |
| 3788 | + | |
| 3789 | + | |
| 3790 | +/* | |
| 3791 | + * L.DivIcon is a lightweight HTML-based icon class (as opposed to the image-based L.Icon) | |
| 3792 | + * to use with L.Marker. | |
| 3793 | + */ | |
| 3794 | + | |
| 3795 | +L.DivIcon = L.Icon.extend({ | |
| 3796 | + options: { | |
| 3797 | + iconSize: [12, 12], // also can be set through CSS | |
| 3798 | + /* | |
| 3799 | + iconAnchor: (Point) | |
| 3800 | + popupAnchor: (Point) | |
| 3801 | + html: (String) | |
| 3802 | + bgPos: (Point) | |
| 3803 | + */ | |
| 3804 | + className: 'leaflet-div-icon', | |
| 3805 | + html: false | |
| 3806 | + }, | |
| 3807 | + | |
| 3808 | + createIcon: function (oldIcon) { | |
| 3809 | + var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'), | |
| 3810 | + options = this.options; | |
| 3811 | + | |
| 3812 | + if (options.html !== false) { | |
| 3813 | + div.innerHTML = options.html; | |
| 3814 | + } else { | |
| 3815 | + div.innerHTML = ''; | |
| 3816 | + } | |
| 3817 | + | |
| 3818 | + if (options.bgPos) { | |
| 3819 | + div.style.backgroundPosition = | |
| 3820 | + (-options.bgPos.x) + 'px ' + (-options.bgPos.y) + 'px'; | |
| 3821 | + } | |
| 3822 | + | |
| 3823 | + this._setIconStyles(div, 'icon'); | |
| 3824 | + return div; | |
| 3825 | + }, | |
| 3826 | + | |
| 3827 | + createShadow: function () { | |
| 3828 | + return null; | |
| 3829 | + } | |
| 3830 | +}); | |
| 3831 | + | |
| 3832 | +L.divIcon = function (options) { | |
| 3833 | + return new L.DivIcon(options); | |
| 3834 | +}; | |
| 3835 | + | |
| 3836 | + | |
| 3837 | +/* | |
| 3838 | + * L.Popup is used for displaying popups on the map. | |
| 3839 | + */ | |
| 3840 | + | |
| 3841 | +L.Map.mergeOptions({ | |
| 3842 | + closePopupOnClick: true | |
| 3843 | +}); | |
| 3844 | + | |
| 3845 | +L.Popup = L.Class.extend({ | |
| 3846 | + includes: L.Mixin.Events, | |
| 3847 | + | |
| 3848 | + options: { | |
| 3849 | + minWidth: 50, | |
| 3850 | + maxWidth: 300, | |
| 3851 | + // maxHeight: null, | |
| 3852 | + autoPan: true, | |
| 3853 | + closeButton: true, | |
| 3854 | + offset: [0, 7], | |
| 3855 | + autoPanPadding: [5, 5], | |
| 3856 | + // autoPanPaddingTopLeft: null, | |
| 3857 | + // autoPanPaddingBottomRight: null, | |
| 3858 | + keepInView: false, | |
| 3859 | + className: '', | |
| 3860 | + zoomAnimation: true | |
| 3861 | + }, | |
| 3862 | + | |
| 3863 | + initialize: function (options, source) { | |
| 3864 | + L.setOptions(this, options); | |
| 3865 | + | |
| 3866 | + this._source = source; | |
| 3867 | + this._animated = L.Browser.any3d && this.options.zoomAnimation; | |
| 3868 | + this._isOpen = false; | |
| 3869 | + }, | |
| 3870 | + | |
| 3871 | + onAdd: function (map) { | |
| 3872 | + this._map = map; | |
| 3873 | + | |
| 3874 | + if (!this._container) { | |
| 3875 | + this._initLayout(); | |
| 3876 | + } | |
| 3877 | + | |
| 3878 | + var animFade = map.options.fadeAnimation; | |
| 3879 | + | |
| 3880 | + if (animFade) { | |
| 3881 | + L.DomUtil.setOpacity(this._container, 0); | |
| 3882 | + } | |
| 3883 | + map._panes.popupPane.appendChild(this._container); | |
| 3884 | + | |
| 3885 | + map.on(this._getEvents(), this); | |
| 3886 | + | |
| 3887 | + this.update(); | |
| 3888 | + | |
| 3889 | + if (animFade) { | |
| 3890 | + L.DomUtil.setOpacity(this._container, 1); | |
| 3891 | + } | |
| 3892 | + | |
| 3893 | + this.fire('open'); | |
| 3894 | + | |
| 3895 | + map.fire('popupopen', {popup: this}); | |
| 3896 | + | |
| 3897 | + if (this._source) { | |
| 3898 | + this._source.fire('popupopen', {popup: this}); | |
| 3899 | + } | |
| 3900 | + }, | |
| 3901 | + | |
| 3902 | + addTo: function (map) { | |
| 3903 | + map.addLayer(this); | |
| 3904 | + return this; | |
| 3905 | + }, | |
| 3906 | + | |
| 3907 | + openOn: function (map) { | |
| 3908 | + map.openPopup(this); | |
| 3909 | + return this; | |
| 3910 | + }, | |
| 3911 | + | |
| 3912 | + onRemove: function (map) { | |
| 3913 | + map._panes.popupPane.removeChild(this._container); | |
| 3914 | + | |
| 3915 | + L.Util.falseFn(this._container.offsetWidth); // force reflow | |
| 3916 | + | |
| 3917 | + map.off(this._getEvents(), this); | |
| 3918 | + | |
| 3919 | + if (map.options.fadeAnimation) { | |
| 3920 | + L.DomUtil.setOpacity(this._container, 0); | |
| 3921 | + } | |
| 3922 | + | |
| 3923 | + this._map = null; | |
| 3924 | + | |
| 3925 | + this.fire('close'); | |
| 3926 | + | |
| 3927 | + map.fire('popupclose', {popup: this}); | |
| 3928 | + | |
| 3929 | + if (this._source) { | |
| 3930 | + this._source.fire('popupclose', {popup: this}); | |
| 3931 | + } | |
| 3932 | + }, | |
| 3933 | + | |
| 3934 | + getLatLng: function () { | |
| 3935 | + return this._latlng; | |
| 3936 | + }, | |
| 3937 | + | |
| 3938 | + setLatLng: function (latlng) { | |
| 3939 | + this._latlng = L.latLng(latlng); | |
| 3940 | + if (this._map) { | |
| 3941 | + this._updatePosition(); | |
| 3942 | + this._adjustPan(); | |
| 3943 | + } | |
| 3944 | + return this; | |
| 3945 | + }, | |
| 3946 | + | |
| 3947 | + getContent: function () { | |
| 3948 | + return this._content; | |
| 3949 | + }, | |
| 3950 | + | |
| 3951 | + setContent: function (content) { | |
| 3952 | + this._content = content; | |
| 3953 | + this.update(); | |
| 3954 | + return this; | |
| 3955 | + }, | |
| 3956 | + | |
| 3957 | + update: function () { | |
| 3958 | + if (!this._map) { return; } | |
| 3959 | + | |
| 3960 | + this._container.style.visibility = 'hidden'; | |
| 3961 | + | |
| 3962 | + this._updateContent(); | |
| 3963 | + this._updateLayout(); | |
| 3964 | + this._updatePosition(); | |
| 3965 | + | |
| 3966 | + this._container.style.visibility = ''; | |
| 3967 | + | |
| 3968 | + this._adjustPan(); | |
| 3969 | + }, | |
| 3970 | + | |
| 3971 | + _getEvents: function () { | |
| 3972 | + var events = { | |
| 3973 | + viewreset: this._updatePosition | |
| 3974 | + }; | |
| 3975 | + | |
| 3976 | + if (this._animated) { | |
| 3977 | + events.zoomanim = this._zoomAnimation; | |
| 3978 | + } | |
| 3979 | + if ('closeOnClick' in this.options ? this.options.closeOnClick : this._map.options.closePopupOnClick) { | |
| 3980 | + events.preclick = this._close; | |
| 3981 | + } | |
| 3982 | + if (this.options.keepInView) { | |
| 3983 | + events.moveend = this._adjustPan; | |
| 3984 | + } | |
| 3985 | + | |
| 3986 | + return events; | |
| 3987 | + }, | |
| 3988 | + | |
| 3989 | + _close: function () { | |
| 3990 | + if (this._map) { | |
| 3991 | + this._map.closePopup(this); | |
| 3992 | + } | |
| 3993 | + }, | |
| 3994 | + | |
| 3995 | + _initLayout: function () { | |
| 3996 | + var prefix = 'leaflet-popup', | |
| 3997 | + containerClass = prefix + ' ' + this.options.className + ' leaflet-zoom-' + | |
| 3998 | + (this._animated ? 'animated' : 'hide'), | |
| 3999 | + container = this._container = L.DomUtil.create('div', containerClass), | |
| 4000 | + closeButton; | |
| 4001 | + | |
| 4002 | + if (this.options.closeButton) { | |
| 4003 | + closeButton = this._closeButton = | |
| 4004 | + L.DomUtil.create('a', prefix + '-close-button', container); | |
| 4005 | + closeButton.href = '#close'; | |
| 4006 | + closeButton.innerHTML = '×'; | |
| 4007 | + L.DomEvent.disableClickPropagation(closeButton); | |
| 4008 | + | |
| 4009 | + L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this); | |
| 4010 | + } | |
| 4011 | + | |
| 4012 | + var wrapper = this._wrapper = | |
| 4013 | + L.DomUtil.create('div', prefix + '-content-wrapper', container); | |
| 4014 | + L.DomEvent.disableClickPropagation(wrapper); | |
| 4015 | + | |
| 4016 | + this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper); | |
| 4017 | + | |
| 4018 | + L.DomEvent.disableScrollPropagation(this._contentNode); | |
| 4019 | + L.DomEvent.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation); | |
| 4020 | + | |
| 4021 | + this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container); | |
| 4022 | + this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer); | |
| 4023 | + }, | |
| 4024 | + | |
| 4025 | + _updateContent: function () { | |
| 4026 | + if (!this._content) { return; } | |
| 4027 | + | |
| 4028 | + if (typeof this._content === 'string') { | |
| 4029 | + this._contentNode.innerHTML = this._content; | |
| 4030 | + } else { | |
| 4031 | + while (this._contentNode.hasChildNodes()) { | |
| 4032 | + this._contentNode.removeChild(this._contentNode.firstChild); | |
| 4033 | + } | |
| 4034 | + this._contentNode.appendChild(this._content); | |
| 4035 | + } | |
| 4036 | + this.fire('contentupdate'); | |
| 4037 | + }, | |
| 4038 | + | |
| 4039 | + _updateLayout: function () { | |
| 4040 | + var container = this._contentNode, | |
| 4041 | + style = container.style; | |
| 4042 | + | |
| 4043 | + style.width = ''; | |
| 4044 | + style.whiteSpace = 'nowrap'; | |
| 4045 | + | |
| 4046 | + var width = container.offsetWidth; | |
| 4047 | + width = Math.min(width, this.options.maxWidth); | |
| 4048 | + width = Math.max(width, this.options.minWidth); | |
| 4049 | + | |
| 4050 | + style.width = (width + 1) + 'px'; | |
| 4051 | + style.whiteSpace = ''; | |
| 4052 | + | |
| 4053 | + style.height = ''; | |
| 4054 | + | |
| 4055 | + var height = container.offsetHeight, | |
| 4056 | + maxHeight = this.options.maxHeight, | |
| 4057 | + scrolledClass = 'leaflet-popup-scrolled'; | |
| 4058 | + | |
| 4059 | + if (maxHeight && height > maxHeight) { | |
| 4060 | + style.height = maxHeight + 'px'; | |
| 4061 | + L.DomUtil.addClass(container, scrolledClass); | |
| 4062 | + } else { | |
| 4063 | + L.DomUtil.removeClass(container, scrolledClass); | |
| 4064 | + } | |
| 4065 | + | |
| 4066 | + this._containerWidth = this._container.offsetWidth; | |
| 4067 | + }, | |
| 4068 | + | |
| 4069 | + _updatePosition: function () { | |
| 4070 | + if (!this._map) { return; } | |
| 4071 | + | |
| 4072 | + var pos = this._map.latLngToLayerPoint(this._latlng), | |
| 4073 | + animated = this._animated, | |
| 4074 | + offset = L.point(this.options.offset); | |
| 4075 | + | |
| 4076 | + if (animated) { | |
| 4077 | + L.DomUtil.setPosition(this._container, pos); | |
| 4078 | + } | |
| 4079 | + | |
| 4080 | + this._containerBottom = -offset.y - (animated ? 0 : pos.y); | |
| 4081 | + this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x + (animated ? 0 : pos.x); | |
| 4082 | + | |
| 4083 | + // bottom position the popup in case the height of the popup changes (images loading etc) | |
| 4084 | + this._container.style.bottom = this._containerBottom + 'px'; | |
| 4085 | + this._container.style.left = this._containerLeft + 'px'; | |
| 4086 | + }, | |
| 4087 | + | |
| 4088 | + _zoomAnimation: function (opt) { | |
| 4089 | + var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center); | |
| 4090 | + | |
| 4091 | + L.DomUtil.setPosition(this._container, pos); | |
| 4092 | + }, | |
| 4093 | + | |
| 4094 | + _adjustPan: function () { | |
| 4095 | + if (!this.options.autoPan) { return; } | |
| 4096 | + | |
| 4097 | + var map = this._map, | |
| 4098 | + containerHeight = this._container.offsetHeight, | |
| 4099 | + containerWidth = this._containerWidth, | |
| 4100 | + | |
| 4101 | + layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom); | |
| 4102 | + | |
| 4103 | + if (this._animated) { | |
| 4104 | + layerPos._add(L.DomUtil.getPosition(this._container)); | |
| 4105 | + } | |
| 4106 | + | |
| 4107 | + var containerPos = map.layerPointToContainerPoint(layerPos), | |
| 4108 | + padding = L.point(this.options.autoPanPadding), | |
| 4109 | + paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding), | |
| 4110 | + paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding), | |
| 4111 | + size = map.getSize(), | |
| 4112 | + dx = 0, | |
| 4113 | + dy = 0; | |
| 4114 | + | |
| 4115 | + if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right | |
| 4116 | + dx = containerPos.x + containerWidth - size.x + paddingBR.x; | |
| 4117 | + } | |
| 4118 | + if (containerPos.x - dx - paddingTL.x < 0) { // left | |
| 4119 | + dx = containerPos.x - paddingTL.x; | |
| 4120 | + } | |
| 4121 | + if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom | |
| 4122 | + dy = containerPos.y + containerHeight - size.y + paddingBR.y; | |
| 4123 | + } | |
| 4124 | + if (containerPos.y - dy - paddingTL.y < 0) { // top | |
| 4125 | + dy = containerPos.y - paddingTL.y; | |
| 4126 | + } | |
| 4127 | + | |
| 4128 | + if (dx || dy) { | |
| 4129 | + map | |
| 4130 | + .fire('autopanstart') | |
| 4131 | + .panBy([dx, dy]); | |
| 4132 | + } | |
| 4133 | + }, | |
| 4134 | + | |
| 4135 | + _onCloseButtonClick: function (e) { | |
| 4136 | + this._close(); | |
| 4137 | + L.DomEvent.stop(e); | |
| 4138 | + } | |
| 4139 | +}); | |
| 4140 | + | |
| 4141 | +L.popup = function (options, source) { | |
| 4142 | + return new L.Popup(options, source); | |
| 4143 | +}; | |
| 4144 | + | |
| 4145 | + | |
| 4146 | +L.Map.include({ | |
| 4147 | + openPopup: function (popup, latlng, options) { // (Popup) or (String || HTMLElement, LatLng[, Object]) | |
| 4148 | + this.closePopup(); | |
| 4149 | + | |
| 4150 | + if (!(popup instanceof L.Popup)) { | |
| 4151 | + var content = popup; | |
| 4152 | + | |
| 4153 | + popup = new L.Popup(options) | |
| 4154 | + .setLatLng(latlng) | |
| 4155 | + .setContent(content); | |
| 4156 | + } | |
| 4157 | + popup._isOpen = true; | |
| 4158 | + | |
| 4159 | + this._popup = popup; | |
| 4160 | + return this.addLayer(popup); | |
| 4161 | + }, | |
| 4162 | + | |
| 4163 | + closePopup: function (popup) { | |
| 4164 | + if (!popup || popup === this._popup) { | |
| 4165 | + popup = this._popup; | |
| 4166 | + this._popup = null; | |
| 4167 | + } | |
| 4168 | + if (popup) { | |
| 4169 | + this.removeLayer(popup); | |
| 4170 | + popup._isOpen = false; | |
| 4171 | + } | |
| 4172 | + return this; | |
| 4173 | + } | |
| 4174 | +}); | |
| 4175 | + | |
| 4176 | + | |
| 4177 | +/* | |
| 4178 | + * Popup extension to L.Marker, adding popup-related methods. | |
| 4179 | + */ | |
| 4180 | + | |
| 4181 | +L.Marker.include({ | |
| 4182 | + openPopup: function () { | |
| 4183 | + if (this._popup && this._map && !this._map.hasLayer(this._popup)) { | |
| 4184 | + this._popup.setLatLng(this._latlng); | |
| 4185 | + this._map.openPopup(this._popup); | |
| 4186 | + } | |
| 4187 | + | |
| 4188 | + return this; | |
| 4189 | + }, | |
| 4190 | + | |
| 4191 | + closePopup: function () { | |
| 4192 | + if (this._popup) { | |
| 4193 | + this._popup._close(); | |
| 4194 | + } | |
| 4195 | + return this; | |
| 4196 | + }, | |
| 4197 | + | |
| 4198 | + togglePopup: function () { | |
| 4199 | + if (this._popup) { | |
| 4200 | + if (this._popup._isOpen) { | |
| 4201 | + this.closePopup(); | |
| 4202 | + } else { | |
| 4203 | + this.openPopup(); | |
| 4204 | + } | |
| 4205 | + } | |
| 4206 | + return this; | |
| 4207 | + }, | |
| 4208 | + | |
| 4209 | + bindPopup: function (content, options) { | |
| 4210 | + var anchor = L.point(this.options.icon.options.popupAnchor || [0, 0]); | |
| 4211 | + | |
| 4212 | + anchor = anchor.add(L.Popup.prototype.options.offset); | |
| 4213 | + | |
| 4214 | + if (options && options.offset) { | |
| 4215 | + anchor = anchor.add(options.offset); | |
| 4216 | + } | |
| 4217 | + | |
| 4218 | + options = L.extend({offset: anchor}, options); | |
| 4219 | + | |
| 4220 | + if (!this._popupHandlersAdded) { | |
| 4221 | + this | |
| 4222 | + .on('click', this.togglePopup, this) | |
| 4223 | + .on('remove', this.closePopup, this) | |
| 4224 | + .on('move', this._movePopup, this); | |
| 4225 | + this._popupHandlersAdded = true; | |
| 4226 | + } | |
| 4227 | + | |
| 4228 | + if (content instanceof L.Popup) { | |
| 4229 | + L.setOptions(content, options); | |
| 4230 | + this._popup = content; | |
| 4231 | + } else { | |
| 4232 | + this._popup = new L.Popup(options, this) | |
| 4233 | + .setContent(content); | |
| 4234 | + } | |
| 4235 | + | |
| 4236 | + return this; | |
| 4237 | + }, | |
| 4238 | + | |
| 4239 | + setPopupContent: function (content) { | |
| 4240 | + if (this._popup) { | |
| 4241 | + this._popup.setContent(content); | |
| 4242 | + } | |
| 4243 | + return this; | |
| 4244 | + }, | |
| 4245 | + | |
| 4246 | + unbindPopup: function () { | |
| 4247 | + if (this._popup) { | |
| 4248 | + this._popup = null; | |
| 4249 | + this | |
| 4250 | + .off('click', this.togglePopup, this) | |
| 4251 | + .off('remove', this.closePopup, this) | |
| 4252 | + .off('move', this._movePopup, this); | |
| 4253 | + this._popupHandlersAdded = false; | |
| 4254 | + } | |
| 4255 | + return this; | |
| 4256 | + }, | |
| 4257 | + | |
| 4258 | + getPopup: function () { | |
| 4259 | + return this._popup; | |
| 4260 | + }, | |
| 4261 | + | |
| 4262 | + _movePopup: function (e) { | |
| 4263 | + this._popup.setLatLng(e.latlng); | |
| 4264 | + } | |
| 4265 | +}); | |
| 4266 | + | |
| 4267 | + | |
| 4268 | +/* | |
| 4269 | + * L.LayerGroup is a class to combine several layers into one so that | |
| 4270 | + * you can manipulate the group (e.g. add/remove it) as one layer. | |
| 4271 | + */ | |
| 4272 | + | |
| 4273 | +L.LayerGroup = L.Class.extend({ | |
| 4274 | + initialize: function (layers) { | |
| 4275 | + this._layers = {}; | |
| 4276 | + | |
| 4277 | + var i, len; | |
| 4278 | + | |
| 4279 | + if (layers) { | |
| 4280 | + for (i = 0, len = layers.length; i < len; i++) { | |
| 4281 | + this.addLayer(layers[i]); | |
| 4282 | + } | |
| 4283 | + } | |
| 4284 | + }, | |
| 4285 | + | |
| 4286 | + addLayer: function (layer) { | |
| 4287 | + var id = this.getLayerId(layer); | |
| 4288 | + | |
| 4289 | + this._layers[id] = layer; | |
| 4290 | + | |
| 4291 | + if (this._map) { | |
| 4292 | + this._map.addLayer(layer); | |
| 4293 | + } | |
| 4294 | + | |
| 4295 | + return this; | |
| 4296 | + }, | |
| 4297 | + | |
| 4298 | + removeLayer: function (layer) { | |
| 4299 | + var id = layer in this._layers ? layer : this.getLayerId(layer); | |
| 4300 | + | |
| 4301 | + if (this._map && this._layers[id]) { | |
| 4302 | + this._map.removeLayer(this._layers[id]); | |
| 4303 | + } | |
| 4304 | + | |
| 4305 | + delete this._layers[id]; | |
| 4306 | + | |
| 4307 | + return this; | |
| 4308 | + }, | |
| 4309 | + | |
| 4310 | + hasLayer: function (layer) { | |
| 4311 | + if (!layer) { return false; } | |
| 4312 | + | |
| 4313 | + return (layer in this._layers || this.getLayerId(layer) in this._layers); | |
| 4314 | + }, | |
| 4315 | + | |
| 4316 | + clearLayers: function () { | |
| 4317 | + this.eachLayer(this.removeLayer, this); | |
| 4318 | + return this; | |
| 4319 | + }, | |
| 4320 | + | |
| 4321 | + invoke: function (methodName) { | |
| 4322 | + var args = Array.prototype.slice.call(arguments, 1), | |
| 4323 | + i, layer; | |
| 4324 | + | |
| 4325 | + for (i in this._layers) { | |
| 4326 | + layer = this._layers[i]; | |
| 4327 | + | |
| 4328 | + if (layer[methodName]) { | |
| 4329 | + layer[methodName].apply(layer, args); | |
| 4330 | + } | |
| 4331 | + } | |
| 4332 | + | |
| 4333 | + return this; | |
| 4334 | + }, | |
| 4335 | + | |
| 4336 | + onAdd: function (map) { | |
| 4337 | + this._map = map; | |
| 4338 | + this.eachLayer(map.addLayer, map); | |
| 4339 | + }, | |
| 4340 | + | |
| 4341 | + onRemove: function (map) { | |
| 4342 | + this.eachLayer(map.removeLayer, map); | |
| 4343 | + this._map = null; | |
| 4344 | + }, | |
| 4345 | + | |
| 4346 | + addTo: function (map) { | |
| 4347 | + map.addLayer(this); | |
| 4348 | + return this; | |
| 4349 | + }, | |
| 4350 | + | |
| 4351 | + eachLayer: function (method, context) { | |
| 4352 | + for (var i in this._layers) { | |
| 4353 | + method.call(context, this._layers[i]); | |
| 4354 | + } | |
| 4355 | + return this; | |
| 4356 | + }, | |
| 4357 | + | |
| 4358 | + getLayer: function (id) { | |
| 4359 | + return this._layers[id]; | |
| 4360 | + }, | |
| 4361 | + | |
| 4362 | + getLayers: function () { | |
| 4363 | + var layers = []; | |
| 4364 | + | |
| 4365 | + for (var i in this._layers) { | |
| 4366 | + layers.push(this._layers[i]); | |
| 4367 | + } | |
| 4368 | + return layers; | |
| 4369 | + }, | |
| 4370 | + | |
| 4371 | + setZIndex: function (zIndex) { | |
| 4372 | + return this.invoke('setZIndex', zIndex); | |
| 4373 | + }, | |
| 4374 | + | |
| 4375 | + getLayerId: function (layer) { | |
| 4376 | + return L.stamp(layer); | |
| 4377 | + } | |
| 4378 | +}); | |
| 4379 | + | |
| 4380 | +L.layerGroup = function (layers) { | |
| 4381 | + return new L.LayerGroup(layers); | |
| 4382 | +}; | |
| 4383 | + | |
| 4384 | + | |
| 4385 | +/* | |
| 4386 | + * L.FeatureGroup extends L.LayerGroup by introducing mouse events and additional methods | |
| 4387 | + * shared between a group of interactive layers (like vectors or markers). | |
| 4388 | + */ | |
| 4389 | + | |
| 4390 | +L.FeatureGroup = L.LayerGroup.extend({ | |
| 4391 | + includes: L.Mixin.Events, | |
| 4392 | + | |
| 4393 | + statics: { | |
| 4394 | + EVENTS: 'click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose' | |
| 4395 | + }, | |
| 4396 | + | |
| 4397 | + addLayer: function (layer) { | |
| 4398 | + if (this.hasLayer(layer)) { | |
| 4399 | + return this; | |
| 4400 | + } | |
| 4401 | + | |
| 4402 | + if ('on' in layer) { | |
| 4403 | + layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this); | |
| 4404 | + } | |
| 4405 | + | |
| 4406 | + L.LayerGroup.prototype.addLayer.call(this, layer); | |
| 4407 | + | |
| 4408 | + if (this._popupContent && layer.bindPopup) { | |
| 4409 | + layer.bindPopup(this._popupContent, this._popupOptions); | |
| 4410 | + } | |
| 4411 | + | |
| 4412 | + return this.fire('layeradd', {layer: layer}); | |
| 4413 | + }, | |
| 4414 | + | |
| 4415 | + removeLayer: function (layer) { | |
| 4416 | + if (!this.hasLayer(layer)) { | |
| 4417 | + return this; | |
| 4418 | + } | |
| 4419 | + if (layer in this._layers) { | |
| 4420 | + layer = this._layers[layer]; | |
| 4421 | + } | |
| 4422 | + | |
| 4423 | + layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this); | |
| 4424 | + | |
| 4425 | + L.LayerGroup.prototype.removeLayer.call(this, layer); | |
| 4426 | + | |
| 4427 | + if (this._popupContent) { | |
| 4428 | + this.invoke('unbindPopup'); | |
| 4429 | + } | |
| 4430 | + | |
| 4431 | + return this.fire('layerremove', {layer: layer}); | |
| 4432 | + }, | |
| 4433 | + | |
| 4434 | + bindPopup: function (content, options) { | |
| 4435 | + this._popupContent = content; | |
| 4436 | + this._popupOptions = options; | |
| 4437 | + return this.invoke('bindPopup', content, options); | |
| 4438 | + }, | |
| 4439 | + | |
| 4440 | + openPopup: function (latlng) { | |
| 4441 | + // open popup on the first layer | |
| 4442 | + for (var id in this._layers) { | |
| 4443 | + this._layers[id].openPopup(latlng); | |
| 4444 | + break; | |
| 4445 | + } | |
| 4446 | + return this; | |
| 4447 | + }, | |
| 4448 | + | |
| 4449 | + setStyle: function (style) { | |
| 4450 | + return this.invoke('setStyle', style); | |
| 4451 | + }, | |
| 4452 | + | |
| 4453 | + bringToFront: function () { | |
| 4454 | + return this.invoke('bringToFront'); | |
| 4455 | + }, | |
| 4456 | + | |
| 4457 | + bringToBack: function () { | |
| 4458 | + return this.invoke('bringToBack'); | |
| 4459 | + }, | |
| 4460 | + | |
| 4461 | + getBounds: function () { | |
| 4462 | + var bounds = new L.LatLngBounds(); | |
| 4463 | + | |
| 4464 | + this.eachLayer(function (layer) { | |
| 4465 | + bounds.extend(layer instanceof L.Marker ? layer.getLatLng() : layer.getBounds()); | |
| 4466 | + }); | |
| 4467 | + | |
| 4468 | + return bounds; | |
| 4469 | + }, | |
| 4470 | + | |
| 4471 | + _propagateEvent: function (e) { | |
| 4472 | + e = L.extend({ | |
| 4473 | + layer: e.target, | |
| 4474 | + target: this | |
| 4475 | + }, e); | |
| 4476 | + this.fire(e.type, e); | |
| 4477 | + } | |
| 4478 | +}); | |
| 4479 | + | |
| 4480 | +L.featureGroup = function (layers) { | |
| 4481 | + return new L.FeatureGroup(layers); | |
| 4482 | +}; | |
| 4483 | + | |
| 4484 | + | |
| 4485 | +/* | |
| 4486 | + * L.Path is a base class for rendering vector paths on a map. Inherited by Polyline, Circle, etc. | |
| 4487 | + */ | |
| 4488 | + | |
| 4489 | +L.Path = L.Class.extend({ | |
| 4490 | + includes: [L.Mixin.Events], | |
| 4491 | + | |
| 4492 | + statics: { | |
| 4493 | + // how much to extend the clip area around the map view | |
| 4494 | + // (relative to its size, e.g. 0.5 is half the screen in each direction) | |
| 4495 | + // set it so that SVG element doesn't exceed 1280px (vectors flicker on dragend if it is) | |
| 4496 | + CLIP_PADDING: (function () { | |
| 4497 | + var max = L.Browser.mobile ? 1280 : 2000, | |
| 4498 | + target = (max / Math.max(window.outerWidth, window.outerHeight) - 1) / 2; | |
| 4499 | + return Math.max(0, Math.min(0.5, target)); | |
| 4500 | + })() | |
| 4501 | + }, | |
| 4502 | + | |
| 4503 | + options: { | |
| 4504 | + stroke: true, | |
| 4505 | + color: '#0033ff', | |
| 4506 | + dashArray: null, | |
| 4507 | + lineCap: null, | |
| 4508 | + lineJoin: null, | |
| 4509 | + weight: 5, | |
| 4510 | + opacity: 0.5, | |
| 4511 | + | |
| 4512 | + fill: false, | |
| 4513 | + fillColor: null, //same as color by default | |
| 4514 | + fillOpacity: 0.2, | |
| 4515 | + | |
| 4516 | + clickable: true | |
| 4517 | + }, | |
| 4518 | + | |
| 4519 | + initialize: function (options) { | |
| 4520 | + L.setOptions(this, options); | |
| 4521 | + }, | |
| 4522 | + | |
| 4523 | + onAdd: function (map) { | |
| 4524 | + this._map = map; | |
| 4525 | + | |
| 4526 | + if (!this._container) { | |
| 4527 | + this._initElements(); | |
| 4528 | + this._initEvents(); | |
| 4529 | + } | |
| 4530 | + | |
| 4531 | + this.projectLatlngs(); | |
| 4532 | + this._updatePath(); | |
| 4533 | + | |
| 4534 | + if (this._container) { | |
| 4535 | + this._map._pathRoot.appendChild(this._container); | |
| 4536 | + } | |
| 4537 | + | |
| 4538 | + this.fire('add'); | |
| 4539 | + | |
| 4540 | + map.on({ | |
| 4541 | + 'viewreset': this.projectLatlngs, | |
| 4542 | + 'moveend': this._updatePath | |
| 4543 | + }, this); | |
| 4544 | + }, | |
| 4545 | + | |
| 4546 | + addTo: function (map) { | |
| 4547 | + map.addLayer(this); | |
| 4548 | + return this; | |
| 4549 | + }, | |
| 4550 | + | |
| 4551 | + onRemove: function (map) { | |
| 4552 | + map._pathRoot.removeChild(this._container); | |
| 4553 | + | |
| 4554 | + // Need to fire remove event before we set _map to null as the event hooks might need the object | |
| 4555 | + this.fire('remove'); | |
| 4556 | + this._map = null; | |
| 4557 | + | |
| 4558 | + if (L.Browser.vml) { | |
| 4559 | + this._container = null; | |
| 4560 | + this._stroke = null; | |
| 4561 | + this._fill = null; | |
| 4562 | + } | |
| 4563 | + | |
| 4564 | + map.off({ | |
| 4565 | + 'viewreset': this.projectLatlngs, | |
| 4566 | + 'moveend': this._updatePath | |
| 4567 | + }, this); | |
| 4568 | + }, | |
| 4569 | + | |
| 4570 | + projectLatlngs: function () { | |
| 4571 | + // do all projection stuff here | |
| 4572 | + }, | |
| 4573 | + | |
| 4574 | + setStyle: function (style) { | |
| 4575 | + L.setOptions(this, style); | |
| 4576 | + | |
| 4577 | + if (this._container) { | |
| 4578 | + this._updateStyle(); | |
| 4579 | + } | |
| 4580 | + | |
| 4581 | + return this; | |
| 4582 | + }, | |
| 4583 | + | |
| 4584 | + redraw: function () { | |
| 4585 | + if (this._map) { | |
| 4586 | + this.projectLatlngs(); | |
| 4587 | + this._updatePath(); | |
| 4588 | + } | |
| 4589 | + return this; | |
| 4590 | + } | |
| 4591 | +}); | |
| 4592 | + | |
| 4593 | +L.Map.include({ | |
| 4594 | + _updatePathViewport: function () { | |
| 4595 | + var p = L.Path.CLIP_PADDING, | |
| 4596 | + size = this.getSize(), | |
| 4597 | + panePos = L.DomUtil.getPosition(this._mapPane), | |
| 4598 | + min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)._round()), | |
| 4599 | + max = min.add(size.multiplyBy(1 + p * 2)._round()); | |
| 4600 | + | |
| 4601 | + this._pathViewport = new L.Bounds(min, max); | |
| 4602 | + } | |
| 4603 | +}); | |
| 4604 | + | |
| 4605 | + | |
| 4606 | +/* | |
| 4607 | + * Extends L.Path with SVG-specific rendering code. | |
| 4608 | + */ | |
| 4609 | + | |
| 4610 | +L.Path.SVG_NS = 'http://www.w3.org/2000/svg'; | |
| 4611 | + | |
| 4612 | +L.Browser.svg = !!(document.createElementNS && document.createElementNS(L.Path.SVG_NS, 'svg').createSVGRect); | |
| 4613 | + | |
| 4614 | +L.Path = L.Path.extend({ | |
| 4615 | + statics: { | |
| 4616 | + SVG: L.Browser.svg | |
| 4617 | + }, | |
| 4618 | + | |
| 4619 | + bringToFront: function () { | |
| 4620 | + var root = this._map._pathRoot, | |
| 4621 | + path = this._container; | |
| 4622 | + | |
| 4623 | + if (path && root.lastChild !== path) { | |
| 4624 | + root.appendChild(path); | |
| 4625 | + } | |
| 4626 | + return this; | |
| 4627 | + }, | |
| 4628 | + | |
| 4629 | + bringToBack: function () { | |
| 4630 | + var root = this._map._pathRoot, | |
| 4631 | + path = this._container, | |
| 4632 | + first = root.firstChild; | |
| 4633 | + | |
| 4634 | + if (path && first !== path) { | |
| 4635 | + root.insertBefore(path, first); | |
| 4636 | + } | |
| 4637 | + return this; | |
| 4638 | + }, | |
| 4639 | + | |
| 4640 | + getPathString: function () { | |
| 4641 | + // form path string here | |
| 4642 | + }, | |
| 4643 | + | |
| 4644 | + _createElement: function (name) { | |
| 4645 | + return document.createElementNS(L.Path.SVG_NS, name); | |
| 4646 | + }, | |
| 4647 | + | |
| 4648 | + _initElements: function () { | |
| 4649 | + this._map._initPathRoot(); | |
| 4650 | + this._initPath(); | |
| 4651 | + this._initStyle(); | |
| 4652 | + }, | |
| 4653 | + | |
| 4654 | + _initPath: function () { | |
| 4655 | + this._container = this._createElement('g'); | |
| 4656 | + | |
| 4657 | + this._path = this._createElement('path'); | |
| 4658 | + | |
| 4659 | + if (this.options.className) { | |
| 4660 | + L.DomUtil.addClass(this._path, this.options.className); | |
| 4661 | + } | |
| 4662 | + | |
| 4663 | + this._container.appendChild(this._path); | |
| 4664 | + }, | |
| 4665 | + | |
| 4666 | + _initStyle: function () { | |
| 4667 | + if (this.options.stroke) { | |
| 4668 | + this._path.setAttribute('stroke-linejoin', 'round'); | |
| 4669 | + this._path.setAttribute('stroke-linecap', 'round'); | |
| 4670 | + } | |
| 4671 | + if (this.options.fill) { | |
| 4672 | + this._path.setAttribute('fill-rule', 'evenodd'); | |
| 4673 | + } | |
| 4674 | + if (this.options.pointerEvents) { | |
| 4675 | + this._path.setAttribute('pointer-events', this.options.pointerEvents); | |
| 4676 | + } | |
| 4677 | + if (!this.options.clickable && !this.options.pointerEvents) { | |
| 4678 | + this._path.setAttribute('pointer-events', 'none'); | |
| 4679 | + } | |
| 4680 | + this._updateStyle(); | |
| 4681 | + }, | |
| 4682 | + | |
| 4683 | + _updateStyle: function () { | |
| 4684 | + if (this.options.stroke) { | |
| 4685 | + this._path.setAttribute('stroke', this.options.color); | |
| 4686 | + this._path.setAttribute('stroke-opacity', this.options.opacity); | |
| 4687 | + this._path.setAttribute('stroke-width', this.options.weight); | |
| 4688 | + if (this.options.dashArray) { | |
| 4689 | + this._path.setAttribute('stroke-dasharray', this.options.dashArray); | |
| 4690 | + } else { | |
| 4691 | + this._path.removeAttribute('stroke-dasharray'); | |
| 4692 | + } | |
| 4693 | + if (this.options.lineCap) { | |
| 4694 | + this._path.setAttribute('stroke-linecap', this.options.lineCap); | |
| 4695 | + } | |
| 4696 | + if (this.options.lineJoin) { | |
| 4697 | + this._path.setAttribute('stroke-linejoin', this.options.lineJoin); | |
| 4698 | + } | |
| 4699 | + } else { | |
| 4700 | + this._path.setAttribute('stroke', 'none'); | |
| 4701 | + } | |
| 4702 | + if (this.options.fill) { | |
| 4703 | + this._path.setAttribute('fill', this.options.fillColor || this.options.color); | |
| 4704 | + this._path.setAttribute('fill-opacity', this.options.fillOpacity); | |
| 4705 | + } else { | |
| 4706 | + this._path.setAttribute('fill', 'none'); | |
| 4707 | + } | |
| 4708 | + }, | |
| 4709 | + | |
| 4710 | + _updatePath: function () { | |
| 4711 | + var str = this.getPathString(); | |
| 4712 | + if (!str) { | |
| 4713 | + // fix webkit empty string parsing bug | |
| 4714 | + str = 'M0 0'; | |
| 4715 | + } | |
| 4716 | + this._path.setAttribute('d', str); | |
| 4717 | + }, | |
| 4718 | + | |
| 4719 | + // TODO remove duplication with L.Map | |
| 4720 | + _initEvents: function () { | |
| 4721 | + if (this.options.clickable) { | |
| 4722 | + if (L.Browser.svg || !L.Browser.vml) { | |
| 4723 | + L.DomUtil.addClass(this._path, 'leaflet-clickable'); | |
| 4724 | + } | |
| 4725 | + | |
| 4726 | + L.DomEvent.on(this._container, 'click', this._onMouseClick, this); | |
| 4727 | + | |
| 4728 | + var events = ['dblclick', 'mousedown', 'mouseover', | |
| 4729 | + 'mouseout', 'mousemove', 'contextmenu']; | |
| 4730 | + for (var i = 0; i < events.length; i++) { | |
| 4731 | + L.DomEvent.on(this._container, events[i], this._fireMouseEvent, this); | |
| 4732 | + } | |
| 4733 | + } | |
| 4734 | + }, | |
| 4735 | + | |
| 4736 | + _onMouseClick: function (e) { | |
| 4737 | + if (this._map.dragging && this._map.dragging.moved()) { return; } | |
| 4738 | + | |
| 4739 | + this._fireMouseEvent(e); | |
| 4740 | + }, | |
| 4741 | + | |
| 4742 | + _fireMouseEvent: function (e) { | |
| 4743 | + if (!this.hasEventListeners(e.type)) { return; } | |
| 4744 | + | |
| 4745 | + var map = this._map, | |
| 4746 | + containerPoint = map.mouseEventToContainerPoint(e), | |
| 4747 | + layerPoint = map.containerPointToLayerPoint(containerPoint), | |
| 4748 | + latlng = map.layerPointToLatLng(layerPoint); | |
| 4749 | + | |
| 4750 | + this.fire(e.type, { | |
| 4751 | + latlng: latlng, | |
| 4752 | + layerPoint: layerPoint, | |
| 4753 | + containerPoint: containerPoint, | |
| 4754 | + originalEvent: e | |
| 4755 | + }); | |
| 4756 | + | |
| 4757 | + if (e.type === 'contextmenu') { | |
| 4758 | + L.DomEvent.preventDefault(e); | |
| 4759 | + } | |
| 4760 | + if (e.type !== 'mousemove') { | |
| 4761 | + L.DomEvent.stopPropagation(e); | |
| 4762 | + } | |
| 4763 | + } | |
| 4764 | +}); | |
| 4765 | + | |
| 4766 | +L.Map.include({ | |
| 4767 | + _initPathRoot: function () { | |
| 4768 | + if (!this._pathRoot) { | |
| 4769 | + this._pathRoot = L.Path.prototype._createElement('svg'); | |
| 4770 | + this._panes.overlayPane.appendChild(this._pathRoot); | |
| 4771 | + | |
| 4772 | + if (this.options.zoomAnimation && L.Browser.any3d) { | |
| 4773 | + L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-animated'); | |
| 4774 | + | |
| 4775 | + this.on({ | |
| 4776 | + 'zoomanim': this._animatePathZoom, | |
| 4777 | + 'zoomend': this._endPathZoom | |
| 4778 | + }); | |
| 4779 | + } else { | |
| 4780 | + L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-hide'); | |
| 4781 | + } | |
| 4782 | + | |
| 4783 | + this.on('moveend', this._updateSvgViewport); | |
| 4784 | + this._updateSvgViewport(); | |
| 4785 | + } | |
| 4786 | + }, | |
| 4787 | + | |
| 4788 | + _animatePathZoom: function (e) { | |
| 4789 | + var scale = this.getZoomScale(e.zoom), | |
| 4790 | + offset = this._getCenterOffset(e.center)._multiplyBy(-scale)._add(this._pathViewport.min); | |
| 4791 | + | |
| 4792 | + this._pathRoot.style[L.DomUtil.TRANSFORM] = | |
| 4793 | + L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ') '; | |
| 4794 | + | |
| 4795 | + this._pathZooming = true; | |
| 4796 | + }, | |
| 4797 | + | |
| 4798 | + _endPathZoom: function () { | |
| 4799 | + this._pathZooming = false; | |
| 4800 | + }, | |
| 4801 | + | |
| 4802 | + _updateSvgViewport: function () { | |
| 4803 | + | |
| 4804 | + if (this._pathZooming) { | |
| 4805 | + // Do not update SVGs while a zoom animation is going on otherwise the animation will break. | |
| 4806 | + // When the zoom animation ends we will be updated again anyway | |
| 4807 | + // This fixes the case where you do a momentum move and zoom while the move is still ongoing. | |
| 4808 | + return; | |
| 4809 | + } | |
| 4810 | + | |
| 4811 | + this._updatePathViewport(); | |
| 4812 | + | |
| 4813 | + var vp = this._pathViewport, | |
| 4814 | + min = vp.min, | |
| 4815 | + max = vp.max, | |
| 4816 | + width = max.x - min.x, | |
| 4817 | + height = max.y - min.y, | |
| 4818 | + root = this._pathRoot, | |
| 4819 | + pane = this._panes.overlayPane; | |
| 4820 | + | |
| 4821 | + // Hack to make flicker on drag end on mobile webkit less irritating | |
| 4822 | + if (L.Browser.mobileWebkit) { | |
| 4823 | + pane.removeChild(root); | |
| 4824 | + } | |
| 4825 | + | |
| 4826 | + L.DomUtil.setPosition(root, min); | |
| 4827 | + root.setAttribute('width', width); | |
| 4828 | + root.setAttribute('height', height); | |
| 4829 | + root.setAttribute('viewBox', [min.x, min.y, width, height].join(' ')); | |
| 4830 | + | |
| 4831 | + if (L.Browser.mobileWebkit) { | |
| 4832 | + pane.appendChild(root); | |
| 4833 | + } | |
| 4834 | + } | |
| 4835 | +}); | |
| 4836 | + | |
| 4837 | + | |
| 4838 | +/* | |
| 4839 | + * Popup extension to L.Path (polylines, polygons, circles), adding popup-related methods. | |
| 4840 | + */ | |
| 4841 | + | |
| 4842 | +L.Path.include({ | |
| 4843 | + | |
| 4844 | + bindPopup: function (content, options) { | |
| 4845 | + | |
| 4846 | + if (content instanceof L.Popup) { | |
| 4847 | + this._popup = content; | |
| 4848 | + } else { | |
| 4849 | + if (!this._popup || options) { | |
| 4850 | + this._popup = new L.Popup(options, this); | |
| 4851 | + } | |
| 4852 | + this._popup.setContent(content); | |
| 4853 | + } | |
| 4854 | + | |
| 4855 | + if (!this._popupHandlersAdded) { | |
| 4856 | + this | |
| 4857 | + .on('click', this._openPopup, this) | |
| 4858 | + .on('remove', this.closePopup, this); | |
| 4859 | + | |
| 4860 | + this._popupHandlersAdded = true; | |
| 4861 | + } | |
| 4862 | + | |
| 4863 | + return this; | |
| 4864 | + }, | |
| 4865 | + | |
| 4866 | + unbindPopup: function () { | |
| 4867 | + if (this._popup) { | |
| 4868 | + this._popup = null; | |
| 4869 | + this | |
| 4870 | + .off('click', this._openPopup) | |
| 4871 | + .off('remove', this.closePopup); | |
| 4872 | + | |
| 4873 | + this._popupHandlersAdded = false; | |
| 4874 | + } | |
| 4875 | + return this; | |
| 4876 | + }, | |
| 4877 | + | |
| 4878 | + openPopup: function (latlng) { | |
| 4879 | + | |
| 4880 | + if (this._popup) { | |
| 4881 | + // open the popup from one of the path's points if not specified | |
| 4882 | + latlng = latlng || this._latlng || | |
| 4883 | + this._latlngs[Math.floor(this._latlngs.length / 2)]; | |
| 4884 | + | |
| 4885 | + this._openPopup({latlng: latlng}); | |
| 4886 | + } | |
| 4887 | + | |
| 4888 | + return this; | |
| 4889 | + }, | |
| 4890 | + | |
| 4891 | + closePopup: function () { | |
| 4892 | + if (this._popup) { | |
| 4893 | + this._popup._close(); | |
| 4894 | + } | |
| 4895 | + return this; | |
| 4896 | + }, | |
| 4897 | + | |
| 4898 | + _openPopup: function (e) { | |
| 4899 | + this._popup.setLatLng(e.latlng); | |
| 4900 | + this._map.openPopup(this._popup); | |
| 4901 | + } | |
| 4902 | +}); | |
| 4903 | + | |
| 4904 | + | |
| 4905 | +/* | |
| 4906 | + * Vector rendering for IE6-8 through VML. | |
| 4907 | + * Thanks to Dmitry Baranovsky and his Raphael library for inspiration! | |
| 4908 | + */ | |
| 4909 | + | |
| 4910 | +L.Browser.vml = !L.Browser.svg && (function () { | |
| 4911 | + try { | |
| 4912 | + var div = document.createElement('div'); | |
| 4913 | + div.innerHTML = '<v:shape adj="1"/>'; | |
| 4914 | + | |
| 4915 | + var shape = div.firstChild; | |
| 4916 | + shape.style.behavior = 'url(#default#VML)'; | |
| 4917 | + | |
| 4918 | + return shape && (typeof shape.adj === 'object'); | |
| 4919 | + | |
| 4920 | + } catch (e) { | |
| 4921 | + return false; | |
| 4922 | + } | |
| 4923 | +}()); | |
| 4924 | + | |
| 4925 | +L.Path = L.Browser.svg || !L.Browser.vml ? L.Path : L.Path.extend({ | |
| 4926 | + statics: { | |
| 4927 | + VML: true, | |
| 4928 | + CLIP_PADDING: 0.02 | |
| 4929 | + }, | |
| 4930 | + | |
| 4931 | + _createElement: (function () { | |
| 4932 | + try { | |
| 4933 | + document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml'); | |
| 4934 | + return function (name) { | |
| 4935 | + return document.createElement('<lvml:' + name + ' class="lvml">'); | |
| 4936 | + }; | |
| 4937 | + } catch (e) { | |
| 4938 | + return function (name) { | |
| 4939 | + return document.createElement( | |
| 4940 | + '<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">'); | |
| 4941 | + }; | |
| 4942 | + } | |
| 4943 | + }()), | |
| 4944 | + | |
| 4945 | + _initPath: function () { | |
| 4946 | + var container = this._container = this._createElement('shape'); | |
| 4947 | + | |
| 4948 | + L.DomUtil.addClass(container, 'leaflet-vml-shape' + | |
| 4949 | + (this.options.className ? ' ' + this.options.className : '')); | |
| 4950 | + | |
| 4951 | + if (this.options.clickable) { | |
| 4952 | + L.DomUtil.addClass(container, 'leaflet-clickable'); | |
| 4953 | + } | |
| 4954 | + | |
| 4955 | + container.coordsize = '1 1'; | |
| 4956 | + | |
| 4957 | + this._path = this._createElement('path'); | |
| 4958 | + container.appendChild(this._path); | |
| 4959 | + | |
| 4960 | + this._map._pathRoot.appendChild(container); | |
| 4961 | + }, | |
| 4962 | + | |
| 4963 | + _initStyle: function () { | |
| 4964 | + this._updateStyle(); | |
| 4965 | + }, | |
| 4966 | + | |
| 4967 | + _updateStyle: function () { | |
| 4968 | + var stroke = this._stroke, | |
| 4969 | + fill = this._fill, | |
| 4970 | + options = this.options, | |
| 4971 | + container = this._container; | |
| 4972 | + | |
| 4973 | + container.stroked = options.stroke; | |
| 4974 | + container.filled = options.fill; | |
| 4975 | + | |
| 4976 | + if (options.stroke) { | |
| 4977 | + if (!stroke) { | |
| 4978 | + stroke = this._stroke = this._createElement('stroke'); | |
| 4979 | + stroke.endcap = 'round'; | |
| 4980 | + container.appendChild(stroke); | |
| 4981 | + } | |
| 4982 | + stroke.weight = options.weight + 'px'; | |
| 4983 | + stroke.color = options.color; | |
| 4984 | + stroke.opacity = options.opacity; | |
| 4985 | + | |
| 4986 | + if (options.dashArray) { | |
| 4987 | + stroke.dashStyle = L.Util.isArray(options.dashArray) ? | |
| 4988 | + options.dashArray.join(' ') : | |
| 4989 | + options.dashArray.replace(/( *, *)/g, ' '); | |
| 4990 | + } else { | |
| 4991 | + stroke.dashStyle = ''; | |
| 4992 | + } | |
| 4993 | + if (options.lineCap) { | |
| 4994 | + stroke.endcap = options.lineCap.replace('butt', 'flat'); | |
| 4995 | + } | |
| 4996 | + if (options.lineJoin) { | |
| 4997 | + stroke.joinstyle = options.lineJoin; | |
| 4998 | + } | |
| 4999 | + | |
| 5000 | + } else if (stroke) { | |
| 5001 | + container.removeChild(stroke); | |
| 5002 | + this._stroke = null; | |
| 5003 | + } | |
| 5004 | + | |
| 5005 | + if (options.fill) { | |
| 5006 | + if (!fill) { | |
| 5007 | + fill = this._fill = this._createElement('fill'); | |
| 5008 | + container.appendChild(fill); | |
| 5009 | + } | |
| 5010 | + fill.color = options.fillColor || options.color; | |
| 5011 | + fill.opacity = options.fillOpacity; | |
| 5012 | + | |
| 5013 | + } else if (fill) { | |
| 5014 | + container.removeChild(fill); | |
| 5015 | + this._fill = null; | |
| 5016 | + } | |
| 5017 | + }, | |
| 5018 | + | |
| 5019 | + _updatePath: function () { | |
| 5020 | + var style = this._container.style; | |
| 5021 | + | |
| 5022 | + style.display = 'none'; | |
| 5023 | + this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug | |
| 5024 | + style.display = ''; | |
| 5025 | + } | |
| 5026 | +}); | |
| 5027 | + | |
| 5028 | +L.Map.include(L.Browser.svg || !L.Browser.vml ? {} : { | |
| 5029 | + _initPathRoot: function () { | |
| 5030 | + if (this._pathRoot) { return; } | |
| 5031 | + | |
| 5032 | + var root = this._pathRoot = document.createElement('div'); | |
| 5033 | + root.className = 'leaflet-vml-container'; | |
| 5034 | + this._panes.overlayPane.appendChild(root); | |
| 5035 | + | |
| 5036 | + this.on('moveend', this._updatePathViewport); | |
| 5037 | + this._updatePathViewport(); | |
| 5038 | + } | |
| 5039 | +}); | |
| 5040 | + | |
| 5041 | + | |
| 5042 | +/* | |
| 5043 | + * Vector rendering for all browsers that support canvas. | |
| 5044 | + */ | |
| 5045 | + | |
| 5046 | +L.Browser.canvas = (function () { | |
| 5047 | + return !!document.createElement('canvas').getContext; | |
| 5048 | +}()); | |
| 5049 | + | |
| 5050 | +L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({ | |
| 5051 | + statics: { | |
| 5052 | + //CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value | |
| 5053 | + CANVAS: true, | |
| 5054 | + SVG: false | |
| 5055 | + }, | |
| 5056 | + | |
| 5057 | + redraw: function () { | |
| 5058 | + if (this._map) { | |
| 5059 | + this.projectLatlngs(); | |
| 5060 | + this._requestUpdate(); | |
| 5061 | + } | |
| 5062 | + return this; | |
| 5063 | + }, | |
| 5064 | + | |
| 5065 | + setStyle: function (style) { | |
| 5066 | + L.setOptions(this, style); | |
| 5067 | + | |
| 5068 | + if (this._map) { | |
| 5069 | + this._updateStyle(); | |
| 5070 | + this._requestUpdate(); | |
| 5071 | + } | |
| 5072 | + return this; | |
| 5073 | + }, | |
| 5074 | + | |
| 5075 | + onRemove: function (map) { | |
| 5076 | + map | |
| 5077 | + .off('viewreset', this.projectLatlngs, this) | |
| 5078 | + .off('moveend', this._updatePath, this); | |
| 5079 | + | |
| 5080 | + if (this.options.clickable) { | |
| 5081 | + this._map.off('click', this._onClick, this); | |
| 5082 | + this._map.off('mousemove', this._onMouseMove, this); | |
| 5083 | + } | |
| 5084 | + | |
| 5085 | + this._requestUpdate(); | |
| 5086 | + | |
| 5087 | + this.fire('remove'); | |
| 5088 | + this._map = null; | |
| 5089 | + }, | |
| 5090 | + | |
| 5091 | + _requestUpdate: function () { | |
| 5092 | + if (this._map && !L.Path._updateRequest) { | |
| 5093 | + L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map); | |
| 5094 | + } | |
| 5095 | + }, | |
| 5096 | + | |
| 5097 | + _fireMapMoveEnd: function () { | |
| 5098 | + L.Path._updateRequest = null; | |
| 5099 | + this.fire('moveend'); | |
| 5100 | + }, | |
| 5101 | + | |
| 5102 | + _initElements: function () { | |
| 5103 | + this._map._initPathRoot(); | |
| 5104 | + this._ctx = this._map._canvasCtx; | |
| 5105 | + }, | |
| 5106 | + | |
| 5107 | + _updateStyle: function () { | |
| 5108 | + var options = this.options; | |
| 5109 | + | |
| 5110 | + if (options.stroke) { | |
| 5111 | + this._ctx.lineWidth = options.weight; | |
| 5112 | + this._ctx.strokeStyle = options.color; | |
| 5113 | + } | |
| 5114 | + if (options.fill) { | |
| 5115 | + this._ctx.fillStyle = options.fillColor || options.color; | |
| 5116 | + } | |
| 5117 | + }, | |
| 5118 | + | |
| 5119 | + _drawPath: function () { | |
| 5120 | + var i, j, len, len2, point, drawMethod; | |
| 5121 | + | |
| 5122 | + this._ctx.beginPath(); | |
| 5123 | + | |
| 5124 | + for (i = 0, len = this._parts.length; i < len; i++) { | |
| 5125 | + for (j = 0, len2 = this._parts[i].length; j < len2; j++) { | |
| 5126 | + point = this._parts[i][j]; | |
| 5127 | + drawMethod = (j === 0 ? 'move' : 'line') + 'To'; | |
| 5128 | + | |
| 5129 | + this._ctx[drawMethod](point.x, point.y); | |
| 5130 | + } | |
| 5131 | + // TODO refactor ugly hack | |
| 5132 | + if (this instanceof L.Polygon) { | |
| 5133 | + this._ctx.closePath(); | |
| 5134 | + } | |
| 5135 | + } | |
| 5136 | + }, | |
| 5137 | + | |
| 5138 | + _checkIfEmpty: function () { | |
| 5139 | + return !this._parts.length; | |
| 5140 | + }, | |
| 5141 | + | |
| 5142 | + _updatePath: function () { | |
| 5143 | + if (this._checkIfEmpty()) { return; } | |
| 5144 | + | |
| 5145 | + var ctx = this._ctx, | |
| 5146 | + options = this.options; | |
| 5147 | + | |
| 5148 | + this._drawPath(); | |
| 5149 | + ctx.save(); | |
| 5150 | + this._updateStyle(); | |
| 5151 | + | |
| 5152 | + if (options.fill) { | |
| 5153 | + ctx.globalAlpha = options.fillOpacity; | |
| 5154 | + ctx.fill(); | |
| 5155 | + } | |
| 5156 | + | |
| 5157 | + if (options.stroke) { | |
| 5158 | + ctx.globalAlpha = options.opacity; | |
| 5159 | + ctx.stroke(); | |
| 5160 | + } | |
| 5161 | + | |
| 5162 | + ctx.restore(); | |
| 5163 | + | |
| 5164 | + // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature | |
| 5165 | + }, | |
| 5166 | + | |
| 5167 | + _initEvents: function () { | |
| 5168 | + if (this.options.clickable) { | |
| 5169 | + // TODO dblclick | |
| 5170 | + this._map.on('mousemove', this._onMouseMove, this); | |
| 5171 | + this._map.on('click', this._onClick, this); | |
| 5172 | + } | |
| 5173 | + }, | |
| 5174 | + | |
| 5175 | + _onClick: function (e) { | |
| 5176 | + if (this._containsPoint(e.layerPoint)) { | |
| 5177 | + this.fire('click', e); | |
| 5178 | + } | |
| 5179 | + }, | |
| 5180 | + | |
| 5181 | + _onMouseMove: function (e) { | |
| 5182 | + if (!this._map || this._map._animatingZoom) { return; } | |
| 5183 | + | |
| 5184 | + // TODO don't do on each move | |
| 5185 | + if (this._containsPoint(e.layerPoint)) { | |
| 5186 | + this._ctx.canvas.style.cursor = 'pointer'; | |
| 5187 | + this._mouseInside = true; | |
| 5188 | + this.fire('mouseover', e); | |
| 5189 | + | |
| 5190 | + } else if (this._mouseInside) { | |
| 5191 | + this._ctx.canvas.style.cursor = ''; | |
| 5192 | + this._mouseInside = false; | |
| 5193 | + this.fire('mouseout', e); | |
| 5194 | + } | |
| 5195 | + } | |
| 5196 | +}); | |
| 5197 | + | |
| 5198 | +L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : { | |
| 5199 | + _initPathRoot: function () { | |
| 5200 | + var root = this._pathRoot, | |
| 5201 | + ctx; | |
| 5202 | + | |
| 5203 | + if (!root) { | |
| 5204 | + root = this._pathRoot = document.createElement('canvas'); | |
| 5205 | + root.style.position = 'absolute'; | |
| 5206 | + ctx = this._canvasCtx = root.getContext('2d'); | |
| 5207 | + | |
| 5208 | + ctx.lineCap = 'round'; | |
| 5209 | + ctx.lineJoin = 'round'; | |
| 5210 | + | |
| 5211 | + this._panes.overlayPane.appendChild(root); | |
| 5212 | + | |
| 5213 | + if (this.options.zoomAnimation) { | |
| 5214 | + this._pathRoot.className = 'leaflet-zoom-animated'; | |
| 5215 | + this.on('zoomanim', this._animatePathZoom); | |
| 5216 | + this.on('zoomend', this._endPathZoom); | |
| 5217 | + } | |
| 5218 | + this.on('moveend', this._updateCanvasViewport); | |
| 5219 | + this._updateCanvasViewport(); | |
| 5220 | + } | |
| 5221 | + }, | |
| 5222 | + | |
| 5223 | + _updateCanvasViewport: function () { | |
| 5224 | + // don't redraw while zooming. See _updateSvgViewport for more details | |
| 5225 | + if (this._pathZooming) { return; } | |
| 5226 | + this._updatePathViewport(); | |
| 5227 | + | |
| 5228 | + var vp = this._pathViewport, | |
| 5229 | + min = vp.min, | |
| 5230 | + size = vp.max.subtract(min), | |
| 5231 | + root = this._pathRoot; | |
| 5232 | + | |
| 5233 | + //TODO check if this works properly on mobile webkit | |
| 5234 | + L.DomUtil.setPosition(root, min); | |
| 5235 | + root.width = size.x; | |
| 5236 | + root.height = size.y; | |
| 5237 | + root.getContext('2d').translate(-min.x, -min.y); | |
| 5238 | + } | |
| 5239 | +}); | |
| 5240 | + | |
| 5241 | + | |
| 5242 | +/* | |
| 5243 | + * L.LineUtil contains different utility functions for line segments | |
| 5244 | + * and polylines (clipping, simplification, distances, etc.) | |
| 5245 | + */ | |
| 5246 | + | |
| 5247 | +/*jshint bitwise:false */ // allow bitwise operations for this file | |
| 5248 | + | |
| 5249 | +L.LineUtil = { | |
| 5250 | + | |
| 5251 | + // Simplify polyline with vertex reduction and Douglas-Peucker simplification. | |
| 5252 | + // Improves rendering performance dramatically by lessening the number of points to draw. | |
| 5253 | + | |
| 5254 | + simplify: function (/*Point[]*/ points, /*Number*/ tolerance) { | |
| 5255 | + if (!tolerance || !points.length) { | |
| 5256 | + return points.slice(); | |
| 5257 | + } | |
| 5258 | + | |
| 5259 | + var sqTolerance = tolerance * tolerance; | |
| 5260 | + | |
| 5261 | + // stage 1: vertex reduction | |
| 5262 | + points = this._reducePoints(points, sqTolerance); | |
| 5263 | + | |
| 5264 | + // stage 2: Douglas-Peucker simplification | |
| 5265 | + points = this._simplifyDP(points, sqTolerance); | |
| 5266 | + | |
| 5267 | + return points; | |
| 5268 | + }, | |
| 5269 | + | |
| 5270 | + // distance from a point to a segment between two points | |
| 5271 | + pointToSegmentDistance: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { | |
| 5272 | + return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true)); | |
| 5273 | + }, | |
| 5274 | + | |
| 5275 | + closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { | |
| 5276 | + return this._sqClosestPointOnSegment(p, p1, p2); | |
| 5277 | + }, | |
| 5278 | + | |
| 5279 | + // Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm | |
| 5280 | + _simplifyDP: function (points, sqTolerance) { | |
| 5281 | + | |
| 5282 | + var len = points.length, | |
| 5283 | + ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, | |
| 5284 | + markers = new ArrayConstructor(len); | |
| 5285 | + | |
| 5286 | + markers[0] = markers[len - 1] = 1; | |
| 5287 | + | |
| 5288 | + this._simplifyDPStep(points, markers, sqTolerance, 0, len - 1); | |
| 5289 | + | |
| 5290 | + var i, | |
| 5291 | + newPoints = []; | |
| 5292 | + | |
| 5293 | + for (i = 0; i < len; i++) { | |
| 5294 | + if (markers[i]) { | |
| 5295 | + newPoints.push(points[i]); | |
| 5296 | + } | |
| 5297 | + } | |
| 5298 | + | |
| 5299 | + return newPoints; | |
| 5300 | + }, | |
| 5301 | + | |
| 5302 | + _simplifyDPStep: function (points, markers, sqTolerance, first, last) { | |
| 5303 | + | |
| 5304 | + var maxSqDist = 0, | |
| 5305 | + index, i, sqDist; | |
| 5306 | + | |
| 5307 | + for (i = first + 1; i <= last - 1; i++) { | |
| 5308 | + sqDist = this._sqClosestPointOnSegment(points[i], points[first], points[last], true); | |
| 5309 | + | |
| 5310 | + if (sqDist > maxSqDist) { | |
| 5311 | + index = i; | |
| 5312 | + maxSqDist = sqDist; | |
| 5313 | + } | |
| 5314 | + } | |
| 5315 | + | |
| 5316 | + if (maxSqDist > sqTolerance) { | |
| 5317 | + markers[index] = 1; | |
| 5318 | + | |
| 5319 | + this._simplifyDPStep(points, markers, sqTolerance, first, index); | |
| 5320 | + this._simplifyDPStep(points, markers, sqTolerance, index, last); | |
| 5321 | + } | |
| 5322 | + }, | |
| 5323 | + | |
| 5324 | + // reduce points that are too close to each other to a single point | |
| 5325 | + _reducePoints: function (points, sqTolerance) { | |
| 5326 | + var reducedPoints = [points[0]]; | |
| 5327 | + | |
| 5328 | + for (var i = 1, prev = 0, len = points.length; i < len; i++) { | |
| 5329 | + if (this._sqDist(points[i], points[prev]) > sqTolerance) { | |
| 5330 | + reducedPoints.push(points[i]); | |
| 5331 | + prev = i; | |
| 5332 | + } | |
| 5333 | + } | |
| 5334 | + if (prev < len - 1) { | |
| 5335 | + reducedPoints.push(points[len - 1]); | |
| 5336 | + } | |
| 5337 | + return reducedPoints; | |
| 5338 | + }, | |
| 5339 | + | |
| 5340 | + // Cohen-Sutherland line clipping algorithm. | |
| 5341 | + // Used to avoid rendering parts of a polyline that are not currently visible. | |
| 5342 | + | |
| 5343 | + clipSegment: function (a, b, bounds, useLastCode) { | |
| 5344 | + var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds), | |
| 5345 | + codeB = this._getBitCode(b, bounds), | |
| 5346 | + | |
| 5347 | + codeOut, p, newCode; | |
| 5348 | + | |
| 5349 | + // save 2nd code to avoid calculating it on the next segment | |
| 5350 | + this._lastCode = codeB; | |
| 5351 | + | |
| 5352 | + while (true) { | |
| 5353 | + // if a,b is inside the clip window (trivial accept) | |
| 5354 | + if (!(codeA | codeB)) { | |
| 5355 | + return [a, b]; | |
| 5356 | + // if a,b is outside the clip window (trivial reject) | |
| 5357 | + } else if (codeA & codeB) { | |
| 5358 | + return false; | |
| 5359 | + // other cases | |
| 5360 | + } else { | |
| 5361 | + codeOut = codeA || codeB; | |
| 5362 | + p = this._getEdgeIntersection(a, b, codeOut, bounds); | |
| 5363 | + newCode = this._getBitCode(p, bounds); | |
| 5364 | + | |
| 5365 | + if (codeOut === codeA) { | |
| 5366 | + a = p; | |
| 5367 | + codeA = newCode; | |
| 5368 | + } else { | |
| 5369 | + b = p; | |
| 5370 | + codeB = newCode; | |
| 5371 | + } | |
| 5372 | + } | |
| 5373 | + } | |
| 5374 | + }, | |
| 5375 | + | |
| 5376 | + _getEdgeIntersection: function (a, b, code, bounds) { | |
| 5377 | + var dx = b.x - a.x, | |
| 5378 | + dy = b.y - a.y, | |
| 5379 | + min = bounds.min, | |
| 5380 | + max = bounds.max; | |
| 5381 | + | |
| 5382 | + if (code & 8) { // top | |
| 5383 | + return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y); | |
| 5384 | + } else if (code & 4) { // bottom | |
| 5385 | + return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y); | |
| 5386 | + } else if (code & 2) { // right | |
| 5387 | + return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx); | |
| 5388 | + } else if (code & 1) { // left | |
| 5389 | + return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx); | |
| 5390 | + } | |
| 5391 | + }, | |
| 5392 | + | |
| 5393 | + _getBitCode: function (/*Point*/ p, bounds) { | |
| 5394 | + var code = 0; | |
| 5395 | + | |
| 5396 | + if (p.x < bounds.min.x) { // left | |
| 5397 | + code |= 1; | |
| 5398 | + } else if (p.x > bounds.max.x) { // right | |
| 5399 | + code |= 2; | |
| 5400 | + } | |
| 5401 | + if (p.y < bounds.min.y) { // bottom | |
| 5402 | + code |= 4; | |
| 5403 | + } else if (p.y > bounds.max.y) { // top | |
| 5404 | + code |= 8; | |
| 5405 | + } | |
| 5406 | + | |
| 5407 | + return code; | |
| 5408 | + }, | |
| 5409 | + | |
| 5410 | + // square distance (to avoid unnecessary Math.sqrt calls) | |
| 5411 | + _sqDist: function (p1, p2) { | |
| 5412 | + var dx = p2.x - p1.x, | |
| 5413 | + dy = p2.y - p1.y; | |
| 5414 | + return dx * dx + dy * dy; | |
| 5415 | + }, | |
| 5416 | + | |
| 5417 | + // return closest point on segment or distance to that point | |
| 5418 | + _sqClosestPointOnSegment: function (p, p1, p2, sqDist) { | |
| 5419 | + var x = p1.x, | |
| 5420 | + y = p1.y, | |
| 5421 | + dx = p2.x - x, | |
| 5422 | + dy = p2.y - y, | |
| 5423 | + dot = dx * dx + dy * dy, | |
| 5424 | + t; | |
| 5425 | + | |
| 5426 | + if (dot > 0) { | |
| 5427 | + t = ((p.x - x) * dx + (p.y - y) * dy) / dot; | |
| 5428 | + | |
| 5429 | + if (t > 1) { | |
| 5430 | + x = p2.x; | |
| 5431 | + y = p2.y; | |
| 5432 | + } else if (t > 0) { | |
| 5433 | + x += dx * t; | |
| 5434 | + y += dy * t; | |
| 5435 | + } | |
| 5436 | + } | |
| 5437 | + | |
| 5438 | + dx = p.x - x; | |
| 5439 | + dy = p.y - y; | |
| 5440 | + | |
| 5441 | + return sqDist ? dx * dx + dy * dy : new L.Point(x, y); | |
| 5442 | + } | |
| 5443 | +}; | |
| 5444 | + | |
| 5445 | + | |
| 5446 | +/* | |
| 5447 | + * L.Polyline is used to display polylines on a map. | |
| 5448 | + */ | |
| 5449 | + | |
| 5450 | +L.Polyline = L.Path.extend({ | |
| 5451 | + initialize: function (latlngs, options) { | |
| 5452 | + L.Path.prototype.initialize.call(this, options); | |
| 5453 | + | |
| 5454 | + this._latlngs = this._convertLatLngs(latlngs); | |
| 5455 | + }, | |
| 5456 | + | |
| 5457 | + options: { | |
| 5458 | + // how much to simplify the polyline on each zoom level | |
| 5459 | + // more = better performance and smoother look, less = more accurate | |
| 5460 | + smoothFactor: 1.0, | |
| 5461 | + noClip: false | |
| 5462 | + }, | |
| 5463 | + | |
| 5464 | + projectLatlngs: function () { | |
| 5465 | + this._originalPoints = []; | |
| 5466 | + | |
| 5467 | + for (var i = 0, len = this._latlngs.length; i < len; i++) { | |
| 5468 | + this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]); | |
| 5469 | + } | |
| 5470 | + }, | |
| 5471 | + | |
| 5472 | + getPathString: function () { | |
| 5473 | + for (var i = 0, len = this._parts.length, str = ''; i < len; i++) { | |
| 5474 | + str += this._getPathPartStr(this._parts[i]); | |
| 5475 | + } | |
| 5476 | + return str; | |
| 5477 | + }, | |
| 5478 | + | |
| 5479 | + getLatLngs: function () { | |
| 5480 | + return this._latlngs; | |
| 5481 | + }, | |
| 5482 | + | |
| 5483 | + setLatLngs: function (latlngs) { | |
| 5484 | + this._latlngs = this._convertLatLngs(latlngs); | |
| 5485 | + return this.redraw(); | |
| 5486 | + }, | |
| 5487 | + | |
| 5488 | + addLatLng: function (latlng) { | |
| 5489 | + this._latlngs.push(L.latLng(latlng)); | |
| 5490 | + return this.redraw(); | |
| 5491 | + }, | |
| 5492 | + | |
| 5493 | + spliceLatLngs: function () { // (Number index, Number howMany) | |
| 5494 | + var removed = [].splice.apply(this._latlngs, arguments); | |
| 5495 | + this._convertLatLngs(this._latlngs, true); | |
| 5496 | + this.redraw(); | |
| 5497 | + return removed; | |
| 5498 | + }, | |
| 5499 | + | |
| 5500 | + closestLayerPoint: function (p) { | |
| 5501 | + var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null; | |
| 5502 | + | |
| 5503 | + for (var j = 0, jLen = parts.length; j < jLen; j++) { | |
| 5504 | + var points = parts[j]; | |
| 5505 | + for (var i = 1, len = points.length; i < len; i++) { | |
| 5506 | + p1 = points[i - 1]; | |
| 5507 | + p2 = points[i]; | |
| 5508 | + var sqDist = L.LineUtil._sqClosestPointOnSegment(p, p1, p2, true); | |
| 5509 | + if (sqDist < minDistance) { | |
| 5510 | + minDistance = sqDist; | |
| 5511 | + minPoint = L.LineUtil._sqClosestPointOnSegment(p, p1, p2); | |
| 5512 | + } | |
| 5513 | + } | |
| 5514 | + } | |
| 5515 | + if (minPoint) { | |
| 5516 | + minPoint.distance = Math.sqrt(minDistance); | |
| 5517 | + } | |
| 5518 | + return minPoint; | |
| 5519 | + }, | |
| 5520 | + | |
| 5521 | + getBounds: function () { | |
| 5522 | + return new L.LatLngBounds(this.getLatLngs()); | |
| 5523 | + }, | |
| 5524 | + | |
| 5525 | + _convertLatLngs: function (latlngs, overwrite) { | |
| 5526 | + var i, len, target = overwrite ? latlngs : []; | |
| 5527 | + | |
| 5528 | + for (i = 0, len = latlngs.length; i < len; i++) { | |
| 5529 | + if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') { | |
| 5530 | + return; | |
| 5531 | + } | |
| 5532 | + target[i] = L.latLng(latlngs[i]); | |
| 5533 | + } | |
| 5534 | + return target; | |
| 5535 | + }, | |
| 5536 | + | |
| 5537 | + _initEvents: function () { | |
| 5538 | + L.Path.prototype._initEvents.call(this); | |
| 5539 | + }, | |
| 5540 | + | |
| 5541 | + _getPathPartStr: function (points) { | |
| 5542 | + var round = L.Path.VML; | |
| 5543 | + | |
| 5544 | + for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) { | |
| 5545 | + p = points[j]; | |
| 5546 | + if (round) { | |
| 5547 | + p._round(); | |
| 5548 | + } | |
| 5549 | + str += (j ? 'L' : 'M') + p.x + ' ' + p.y; | |
| 5550 | + } | |
| 5551 | + return str; | |
| 5552 | + }, | |
| 5553 | + | |
| 5554 | + _clipPoints: function () { | |
| 5555 | + var points = this._originalPoints, | |
| 5556 | + len = points.length, | |
| 5557 | + i, k, segment; | |
| 5558 | + | |
| 5559 | + if (this.options.noClip) { | |
| 5560 | + this._parts = [points]; | |
| 5561 | + return; | |
| 5562 | + } | |
| 5563 | + | |
| 5564 | + this._parts = []; | |
| 5565 | + | |
| 5566 | + var parts = this._parts, | |
| 5567 | + vp = this._map._pathViewport, | |
| 5568 | + lu = L.LineUtil; | |
| 5569 | + | |
| 5570 | + for (i = 0, k = 0; i < len - 1; i++) { | |
| 5571 | + segment = lu.clipSegment(points[i], points[i + 1], vp, i); | |
| 5572 | + if (!segment) { | |
| 5573 | + continue; | |
| 5574 | + } | |
| 5575 | + | |
| 5576 | + parts[k] = parts[k] || []; | |
| 5577 | + parts[k].push(segment[0]); | |
| 5578 | + | |
| 5579 | + // if segment goes out of screen, or it's the last one, it's the end of the line part | |
| 5580 | + if ((segment[1] !== points[i + 1]) || (i === len - 2)) { | |
| 5581 | + parts[k].push(segment[1]); | |
| 5582 | + k++; | |
| 5583 | + } | |
| 5584 | + } | |
| 5585 | + }, | |
| 5586 | + | |
| 5587 | + // simplify each clipped part of the polyline | |
| 5588 | + _simplifyPoints: function () { | |
| 5589 | + var parts = this._parts, | |
| 5590 | + lu = L.LineUtil; | |
| 5591 | + | |
| 5592 | + for (var i = 0, len = parts.length; i < len; i++) { | |
| 5593 | + parts[i] = lu.simplify(parts[i], this.options.smoothFactor); | |
| 5594 | + } | |
| 5595 | + }, | |
| 5596 | + | |
| 5597 | + _updatePath: function () { | |
| 5598 | + if (!this._map) { return; } | |
| 5599 | + | |
| 5600 | + this._clipPoints(); | |
| 5601 | + this._simplifyPoints(); | |
| 5602 | + | |
| 5603 | + L.Path.prototype._updatePath.call(this); | |
| 5604 | + } | |
| 5605 | +}); | |
| 5606 | + | |
| 5607 | +L.polyline = function (latlngs, options) { | |
| 5608 | + return new L.Polyline(latlngs, options); | |
| 5609 | +}; | |
| 5610 | + | |
| 5611 | + | |
| 5612 | +/* | |
| 5613 | + * L.PolyUtil contains utility functions for polygons (clipping, etc.). | |
| 5614 | + */ | |
| 5615 | + | |
| 5616 | +/*jshint bitwise:false */ // allow bitwise operations here | |
| 5617 | + | |
| 5618 | +L.PolyUtil = {}; | |
| 5619 | + | |
| 5620 | +/* | |
| 5621 | + * Sutherland-Hodgeman polygon clipping algorithm. | |
| 5622 | + * Used to avoid rendering parts of a polygon that are not currently visible. | |
| 5623 | + */ | |
| 5624 | +L.PolyUtil.clipPolygon = function (points, bounds) { | |
| 5625 | + var clippedPoints, | |
| 5626 | + edges = [1, 4, 2, 8], | |
| 5627 | + i, j, k, | |
| 5628 | + a, b, | |
| 5629 | + len, edge, p, | |
| 5630 | + lu = L.LineUtil; | |
| 5631 | + | |
| 5632 | + for (i = 0, len = points.length; i < len; i++) { | |
| 5633 | + points[i]._code = lu._getBitCode(points[i], bounds); | |
| 5634 | + } | |
| 5635 | + | |
| 5636 | + // for each edge (left, bottom, right, top) | |
| 5637 | + for (k = 0; k < 4; k++) { | |
| 5638 | + edge = edges[k]; | |
| 5639 | + clippedPoints = []; | |
| 5640 | + | |
| 5641 | + for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { | |
| 5642 | + a = points[i]; | |
| 5643 | + b = points[j]; | |
| 5644 | + | |
| 5645 | + // if a is inside the clip window | |
| 5646 | + if (!(a._code & edge)) { | |
| 5647 | + // if b is outside the clip window (a->b goes out of screen) | |
| 5648 | + if (b._code & edge) { | |
| 5649 | + p = lu._getEdgeIntersection(b, a, edge, bounds); | |
| 5650 | + p._code = lu._getBitCode(p, bounds); | |
| 5651 | + clippedPoints.push(p); | |
| 5652 | + } | |
| 5653 | + clippedPoints.push(a); | |
| 5654 | + | |
| 5655 | + // else if b is inside the clip window (a->b enters the screen) | |
| 5656 | + } else if (!(b._code & edge)) { | |
| 5657 | + p = lu._getEdgeIntersection(b, a, edge, bounds); | |
| 5658 | + p._code = lu._getBitCode(p, bounds); | |
| 5659 | + clippedPoints.push(p); | |
| 5660 | + } | |
| 5661 | + } | |
| 5662 | + points = clippedPoints; | |
| 5663 | + } | |
| 5664 | + | |
| 5665 | + return points; | |
| 5666 | +}; | |
| 5667 | + | |
| 5668 | + | |
| 5669 | +/* | |
| 5670 | + * L.Polygon is used to display polygons on a map. | |
| 5671 | + */ | |
| 5672 | + | |
| 5673 | +L.Polygon = L.Polyline.extend({ | |
| 5674 | + options: { | |
| 5675 | + fill: true | |
| 5676 | + }, | |
| 5677 | + | |
| 5678 | + initialize: function (latlngs, options) { | |
| 5679 | + L.Polyline.prototype.initialize.call(this, latlngs, options); | |
| 5680 | + this._initWithHoles(latlngs); | |
| 5681 | + }, | |
| 5682 | + | |
| 5683 | + _initWithHoles: function (latlngs) { | |
| 5684 | + var i, len, hole; | |
| 5685 | + if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { | |
| 5686 | + this._latlngs = this._convertLatLngs(latlngs[0]); | |
| 5687 | + this._holes = latlngs.slice(1); | |
| 5688 | + | |
| 5689 | + for (i = 0, len = this._holes.length; i < len; i++) { | |
| 5690 | + hole = this._holes[i] = this._convertLatLngs(this._holes[i]); | |
| 5691 | + if (hole[0].equals(hole[hole.length - 1])) { | |
| 5692 | + hole.pop(); | |
| 5693 | + } | |
| 5694 | + } | |
| 5695 | + } | |
| 5696 | + | |
| 5697 | + // filter out last point if its equal to the first one | |
| 5698 | + latlngs = this._latlngs; | |
| 5699 | + | |
| 5700 | + if (latlngs.length >= 2 && latlngs[0].equals(latlngs[latlngs.length - 1])) { | |
| 5701 | + latlngs.pop(); | |
| 5702 | + } | |
| 5703 | + }, | |
| 5704 | + | |
| 5705 | + projectLatlngs: function () { | |
| 5706 | + L.Polyline.prototype.projectLatlngs.call(this); | |
| 5707 | + | |
| 5708 | + // project polygon holes points | |
| 5709 | + // TODO move this logic to Polyline to get rid of duplication | |
| 5710 | + this._holePoints = []; | |
| 5711 | + | |
| 5712 | + if (!this._holes) { return; } | |
| 5713 | + | |
| 5714 | + var i, j, len, len2; | |
| 5715 | + | |
| 5716 | + for (i = 0, len = this._holes.length; i < len; i++) { | |
| 5717 | + this._holePoints[i] = []; | |
| 5718 | + | |
| 5719 | + for (j = 0, len2 = this._holes[i].length; j < len2; j++) { | |
| 5720 | + this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]); | |
| 5721 | + } | |
| 5722 | + } | |
| 5723 | + }, | |
| 5724 | + | |
| 5725 | + setLatLngs: function (latlngs) { | |
| 5726 | + if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { | |
| 5727 | + this._initWithHoles(latlngs); | |
| 5728 | + return this.redraw(); | |
| 5729 | + } else { | |
| 5730 | + return L.Polyline.prototype.setLatLngs.call(this, latlngs); | |
| 5731 | + } | |
| 5732 | + }, | |
| 5733 | + | |
| 5734 | + _clipPoints: function () { | |
| 5735 | + var points = this._originalPoints, | |
| 5736 | + newParts = []; | |
| 5737 | + | |
| 5738 | + this._parts = [points].concat(this._holePoints); | |
| 5739 | + | |
| 5740 | + if (this.options.noClip) { return; } | |
| 5741 | + | |
| 5742 | + for (var i = 0, len = this._parts.length; i < len; i++) { | |
| 5743 | + var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport); | |
| 5744 | + if (clipped.length) { | |
| 5745 | + newParts.push(clipped); | |
| 5746 | + } | |
| 5747 | + } | |
| 5748 | + | |
| 5749 | + this._parts = newParts; | |
| 5750 | + }, | |
| 5751 | + | |
| 5752 | + _getPathPartStr: function (points) { | |
| 5753 | + var str = L.Polyline.prototype._getPathPartStr.call(this, points); | |
| 5754 | + return str + (L.Browser.svg ? 'z' : 'x'); | |
| 5755 | + } | |
| 5756 | +}); | |
| 5757 | + | |
| 5758 | +L.polygon = function (latlngs, options) { | |
| 5759 | + return new L.Polygon(latlngs, options); | |
| 5760 | +}; | |
| 5761 | + | |
| 5762 | + | |
| 5763 | +/* | |
| 5764 | + * Contains L.MultiPolyline and L.MultiPolygon layers. | |
| 5765 | + */ | |
| 5766 | + | |
| 5767 | +(function () { | |
| 5768 | + function createMulti(Klass) { | |
| 5769 | + | |
| 5770 | + return L.FeatureGroup.extend({ | |
| 5771 | + | |
| 5772 | + initialize: function (latlngs, options) { | |
| 5773 | + this._layers = {}; | |
| 5774 | + this._options = options; | |
| 5775 | + this.setLatLngs(latlngs); | |
| 5776 | + }, | |
| 5777 | + | |
| 5778 | + setLatLngs: function (latlngs) { | |
| 5779 | + var i = 0, | |
| 5780 | + len = latlngs.length; | |
| 5781 | + | |
| 5782 | + this.eachLayer(function (layer) { | |
| 5783 | + if (i < len) { | |
| 5784 | + layer.setLatLngs(latlngs[i++]); | |
| 5785 | + } else { | |
| 5786 | + this.removeLayer(layer); | |
| 5787 | + } | |
| 5788 | + }, this); | |
| 5789 | + | |
| 5790 | + while (i < len) { | |
| 5791 | + this.addLayer(new Klass(latlngs[i++], this._options)); | |
| 5792 | + } | |
| 5793 | + | |
| 5794 | + return this; | |
| 5795 | + }, | |
| 5796 | + | |
| 5797 | + getLatLngs: function () { | |
| 5798 | + var latlngs = []; | |
| 5799 | + | |
| 5800 | + this.eachLayer(function (layer) { | |
| 5801 | + latlngs.push(layer.getLatLngs()); | |
| 5802 | + }); | |
| 5803 | + | |
| 5804 | + return latlngs; | |
| 5805 | + } | |
| 5806 | + }); | |
| 5807 | + } | |
| 5808 | + | |
| 5809 | + L.MultiPolyline = createMulti(L.Polyline); | |
| 5810 | + L.MultiPolygon = createMulti(L.Polygon); | |
| 5811 | + | |
| 5812 | + L.multiPolyline = function (latlngs, options) { | |
| 5813 | + return new L.MultiPolyline(latlngs, options); | |
| 5814 | + }; | |
| 5815 | + | |
| 5816 | + L.multiPolygon = function (latlngs, options) { | |
| 5817 | + return new L.MultiPolygon(latlngs, options); | |
| 5818 | + }; | |
| 5819 | +}()); | |
| 5820 | + | |
| 5821 | + | |
| 5822 | +/* | |
| 5823 | + * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object. | |
| 5824 | + */ | |
| 5825 | + | |
| 5826 | +L.Rectangle = L.Polygon.extend({ | |
| 5827 | + initialize: function (latLngBounds, options) { | |
| 5828 | + L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options); | |
| 5829 | + }, | |
| 5830 | + | |
| 5831 | + setBounds: function (latLngBounds) { | |
| 5832 | + this.setLatLngs(this._boundsToLatLngs(latLngBounds)); | |
| 5833 | + }, | |
| 5834 | + | |
| 5835 | + _boundsToLatLngs: function (latLngBounds) { | |
| 5836 | + latLngBounds = L.latLngBounds(latLngBounds); | |
| 5837 | + return [ | |
| 5838 | + latLngBounds.getSouthWest(), | |
| 5839 | + latLngBounds.getNorthWest(), | |
| 5840 | + latLngBounds.getNorthEast(), | |
| 5841 | + latLngBounds.getSouthEast() | |
| 5842 | + ]; | |
| 5843 | + } | |
| 5844 | +}); | |
| 5845 | + | |
| 5846 | +L.rectangle = function (latLngBounds, options) { | |
| 5847 | + return new L.Rectangle(latLngBounds, options); | |
| 5848 | +}; | |
| 5849 | + | |
| 5850 | + | |
| 5851 | +/* | |
| 5852 | + * L.Circle is a circle overlay (with a certain radius in meters). | |
| 5853 | + */ | |
| 5854 | + | |
| 5855 | +L.Circle = L.Path.extend({ | |
| 5856 | + initialize: function (latlng, radius, options) { | |
| 5857 | + L.Path.prototype.initialize.call(this, options); | |
| 5858 | + | |
| 5859 | + this._latlng = L.latLng(latlng); | |
| 5860 | + this._mRadius = radius; | |
| 5861 | + }, | |
| 5862 | + | |
| 5863 | + options: { | |
| 5864 | + fill: true | |
| 5865 | + }, | |
| 5866 | + | |
| 5867 | + setLatLng: function (latlng) { | |
| 5868 | + this._latlng = L.latLng(latlng); | |
| 5869 | + return this.redraw(); | |
| 5870 | + }, | |
| 5871 | + | |
| 5872 | + setRadius: function (radius) { | |
| 5873 | + this._mRadius = radius; | |
| 5874 | + return this.redraw(); | |
| 5875 | + }, | |
| 5876 | + | |
| 5877 | + projectLatlngs: function () { | |
| 5878 | + var lngRadius = this._getLngRadius(), | |
| 5879 | + latlng = this._latlng, | |
| 5880 | + pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]); | |
| 5881 | + | |
| 5882 | + this._point = this._map.latLngToLayerPoint(latlng); | |
| 5883 | + this._radius = Math.max(this._point.x - pointLeft.x, 1); | |
| 5884 | + }, | |
| 5885 | + | |
| 5886 | + getBounds: function () { | |
| 5887 | + var lngRadius = this._getLngRadius(), | |
| 5888 | + latRadius = (this._mRadius / 40075017) * 360, | |
| 5889 | + latlng = this._latlng; | |
| 5890 | + | |
| 5891 | + return new L.LatLngBounds( | |
| 5892 | + [latlng.lat - latRadius, latlng.lng - lngRadius], | |
| 5893 | + [latlng.lat + latRadius, latlng.lng + lngRadius]); | |
| 5894 | + }, | |
| 5895 | + | |
| 5896 | + getLatLng: function () { | |
| 5897 | + return this._latlng; | |
| 5898 | + }, | |
| 5899 | + | |
| 5900 | + getPathString: function () { | |
| 5901 | + var p = this._point, | |
| 5902 | + r = this._radius; | |
| 5903 | + | |
| 5904 | + if (this._checkIfEmpty()) { | |
| 5905 | + return ''; | |
| 5906 | + } | |
| 5907 | + | |
| 5908 | + if (L.Browser.svg) { | |
| 5909 | + return 'M' + p.x + ',' + (p.y - r) + | |
| 5910 | + 'A' + r + ',' + r + ',0,1,1,' + | |
| 5911 | + (p.x - 0.1) + ',' + (p.y - r) + ' z'; | |
| 5912 | + } else { | |
| 5913 | + p._round(); | |
| 5914 | + r = Math.round(r); | |
| 5915 | + return 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r + ' 0,' + (65535 * 360); | |
| 5916 | + } | |
| 5917 | + }, | |
| 5918 | + | |
| 5919 | + getRadius: function () { | |
| 5920 | + return this._mRadius; | |
| 5921 | + }, | |
| 5922 | + | |
| 5923 | + // TODO Earth hardcoded, move into projection code! | |
| 5924 | + | |
| 5925 | + _getLatRadius: function () { | |
| 5926 | + return (this._mRadius / 40075017) * 360; | |
| 5927 | + }, | |
| 5928 | + | |
| 5929 | + _getLngRadius: function () { | |
| 5930 | + return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat); | |
| 5931 | + }, | |
| 5932 | + | |
| 5933 | + _checkIfEmpty: function () { | |
| 5934 | + if (!this._map) { | |
| 5935 | + return false; | |
| 5936 | + } | |
| 5937 | + var vp = this._map._pathViewport, | |
| 5938 | + r = this._radius, | |
| 5939 | + p = this._point; | |
| 5940 | + | |
| 5941 | + return p.x - r > vp.max.x || p.y - r > vp.max.y || | |
| 5942 | + p.x + r < vp.min.x || p.y + r < vp.min.y; | |
| 5943 | + } | |
| 5944 | +}); | |
| 5945 | + | |
| 5946 | +L.circle = function (latlng, radius, options) { | |
| 5947 | + return new L.Circle(latlng, radius, options); | |
| 5948 | +}; | |
| 5949 | + | |
| 5950 | + | |
| 5951 | +/* | |
| 5952 | + * L.CircleMarker is a circle overlay with a permanent pixel radius. | |
| 5953 | + */ | |
| 5954 | + | |
| 5955 | +L.CircleMarker = L.Circle.extend({ | |
| 5956 | + options: { | |
| 5957 | + radius: 10, | |
| 5958 | + weight: 2 | |
| 5959 | + }, | |
| 5960 | + | |
| 5961 | + initialize: function (latlng, options) { | |
| 5962 | + L.Circle.prototype.initialize.call(this, latlng, null, options); | |
| 5963 | + this._radius = this.options.radius; | |
| 5964 | + }, | |
| 5965 | + | |
| 5966 | + projectLatlngs: function () { | |
| 5967 | + this._point = this._map.latLngToLayerPoint(this._latlng); | |
| 5968 | + }, | |
| 5969 | + | |
| 5970 | + _updateStyle : function () { | |
| 5971 | + L.Circle.prototype._updateStyle.call(this); | |
| 5972 | + this.setRadius(this.options.radius); | |
| 5973 | + }, | |
| 5974 | + | |
| 5975 | + setLatLng: function (latlng) { | |
| 5976 | + L.Circle.prototype.setLatLng.call(this, latlng); | |
| 5977 | + if (this._popup && this._popup._isOpen) { | |
| 5978 | + this._popup.setLatLng(latlng); | |
| 5979 | + } | |
| 5980 | + return this; | |
| 5981 | + }, | |
| 5982 | + | |
| 5983 | + setRadius: function (radius) { | |
| 5984 | + this.options.radius = this._radius = radius; | |
| 5985 | + return this.redraw(); | |
| 5986 | + }, | |
| 5987 | + | |
| 5988 | + getRadius: function () { | |
| 5989 | + return this._radius; | |
| 5990 | + } | |
| 5991 | +}); | |
| 5992 | + | |
| 5993 | +L.circleMarker = function (latlng, options) { | |
| 5994 | + return new L.CircleMarker(latlng, options); | |
| 5995 | +}; | |
| 5996 | + | |
| 5997 | + | |
| 5998 | +/* | |
| 5999 | + * Extends L.Polyline to be able to manually detect clicks on Canvas-rendered polylines. | |
| 6000 | + */ | |
| 6001 | + | |
| 6002 | +L.Polyline.include(!L.Path.CANVAS ? {} : { | |
| 6003 | + _containsPoint: function (p, closed) { | |
| 6004 | + var i, j, k, len, len2, dist, part, | |
| 6005 | + w = this.options.weight / 2; | |
| 6006 | + | |
| 6007 | + if (L.Browser.touch) { | |
| 6008 | + w += 10; // polyline click tolerance on touch devices | |
| 6009 | + } | |
| 6010 | + | |
| 6011 | + for (i = 0, len = this._parts.length; i < len; i++) { | |
| 6012 | + part = this._parts[i]; | |
| 6013 | + for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { | |
| 6014 | + if (!closed && (j === 0)) { | |
| 6015 | + continue; | |
| 6016 | + } | |
| 6017 | + | |
| 6018 | + dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]); | |
| 6019 | + | |
| 6020 | + if (dist <= w) { | |
| 6021 | + return true; | |
| 6022 | + } | |
| 6023 | + } | |
| 6024 | + } | |
| 6025 | + return false; | |
| 6026 | + } | |
| 6027 | +}); | |
| 6028 | + | |
| 6029 | + | |
| 6030 | +/* | |
| 6031 | + * Extends L.Polygon to be able to manually detect clicks on Canvas-rendered polygons. | |
| 6032 | + */ | |
| 6033 | + | |
| 6034 | +L.Polygon.include(!L.Path.CANVAS ? {} : { | |
| 6035 | + _containsPoint: function (p) { | |
| 6036 | + var inside = false, | |
| 6037 | + part, p1, p2, | |
| 6038 | + i, j, k, | |
| 6039 | + len, len2; | |
| 6040 | + | |
| 6041 | + // TODO optimization: check if within bounds first | |
| 6042 | + | |
| 6043 | + if (L.Polyline.prototype._containsPoint.call(this, p, true)) { | |
| 6044 | + // click on polygon border | |
| 6045 | + return true; | |
| 6046 | + } | |
| 6047 | + | |
| 6048 | + // ray casting algorithm for detecting if point is in polygon | |
| 6049 | + | |
| 6050 | + for (i = 0, len = this._parts.length; i < len; i++) { | |
| 6051 | + part = this._parts[i]; | |
| 6052 | + | |
| 6053 | + for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { | |
| 6054 | + p1 = part[j]; | |
| 6055 | + p2 = part[k]; | |
| 6056 | + | |
| 6057 | + if (((p1.y > p.y) !== (p2.y > p.y)) && | |
| 6058 | + (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { | |
| 6059 | + inside = !inside; | |
| 6060 | + } | |
| 6061 | + } | |
| 6062 | + } | |
| 6063 | + | |
| 6064 | + return inside; | |
| 6065 | + } | |
| 6066 | +}); | |
| 6067 | + | |
| 6068 | + | |
| 6069 | +/* | |
| 6070 | + * Extends L.Circle with Canvas-specific code. | |
| 6071 | + */ | |
| 6072 | + | |
| 6073 | +L.Circle.include(!L.Path.CANVAS ? {} : { | |
| 6074 | + _drawPath: function () { | |
| 6075 | + var p = this._point; | |
| 6076 | + this._ctx.beginPath(); | |
| 6077 | + this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2, false); | |
| 6078 | + }, | |
| 6079 | + | |
| 6080 | + _containsPoint: function (p) { | |
| 6081 | + var center = this._point, | |
| 6082 | + w2 = this.options.stroke ? this.options.weight / 2 : 0; | |
| 6083 | + | |
| 6084 | + return (p.distanceTo(center) <= this._radius + w2); | |
| 6085 | + } | |
| 6086 | +}); | |
| 6087 | + | |
| 6088 | + | |
| 6089 | +/* | |
| 6090 | + * CircleMarker canvas specific drawing parts. | |
| 6091 | + */ | |
| 6092 | + | |
| 6093 | +L.CircleMarker.include(!L.Path.CANVAS ? {} : { | |
| 6094 | + _updateStyle: function () { | |
| 6095 | + L.Path.prototype._updateStyle.call(this); | |
| 6096 | + } | |
| 6097 | +}); | |
| 6098 | + | |
| 6099 | + | |
| 6100 | +/* | |
| 6101 | + * L.GeoJSON turns any GeoJSON data into a Leaflet layer. | |
| 6102 | + */ | |
| 6103 | + | |
| 6104 | +L.GeoJSON = L.FeatureGroup.extend({ | |
| 6105 | + | |
| 6106 | + initialize: function (geojson, options) { | |
| 6107 | + L.setOptions(this, options); | |
| 6108 | + | |
| 6109 | + this._layers = {}; | |
| 6110 | + | |
| 6111 | + if (geojson) { | |
| 6112 | + this.addData(geojson); | |
| 6113 | + } | |
| 6114 | + }, | |
| 6115 | + | |
| 6116 | + addData: function (geojson) { | |
| 6117 | + var features = L.Util.isArray(geojson) ? geojson : geojson.features, | |
| 6118 | + i, len, feature; | |
| 6119 | + | |
| 6120 | + if (features) { | |
| 6121 | + for (i = 0, len = features.length; i < len; i++) { | |
| 6122 | + // Only add this if geometry or geometries are set and not null | |
| 6123 | + feature = features[i]; | |
| 6124 | + if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { | |
| 6125 | + this.addData(features[i]); | |
| 6126 | + } | |
| 6127 | + } | |
| 6128 | + return this; | |
| 6129 | + } | |
| 6130 | + | |
| 6131 | + var options = this.options; | |
| 6132 | + | |
| 6133 | + if (options.filter && !options.filter(geojson)) { return; } | |
| 6134 | + | |
| 6135 | + var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options); | |
| 6136 | + layer.feature = L.GeoJSON.asFeature(geojson); | |
| 6137 | + | |
| 6138 | + layer.defaultOptions = layer.options; | |
| 6139 | + this.resetStyle(layer); | |
| 6140 | + | |
| 6141 | + if (options.onEachFeature) { | |
| 6142 | + options.onEachFeature(geojson, layer); | |
| 6143 | + } | |
| 6144 | + | |
| 6145 | + return this.addLayer(layer); | |
| 6146 | + }, | |
| 6147 | + | |
| 6148 | + resetStyle: function (layer) { | |
| 6149 | + var style = this.options.style; | |
| 6150 | + if (style) { | |
| 6151 | + // reset any custom styles | |
| 6152 | + L.Util.extend(layer.options, layer.defaultOptions); | |
| 6153 | + | |
| 6154 | + this._setLayerStyle(layer, style); | |
| 6155 | + } | |
| 6156 | + }, | |
| 6157 | + | |
| 6158 | + setStyle: function (style) { | |
| 6159 | + this.eachLayer(function (layer) { | |
| 6160 | + this._setLayerStyle(layer, style); | |
| 6161 | + }, this); | |
| 6162 | + }, | |
| 6163 | + | |
| 6164 | + _setLayerStyle: function (layer, style) { | |
| 6165 | + if (typeof style === 'function') { | |
| 6166 | + style = style(layer.feature); | |
| 6167 | + } | |
| 6168 | + if (layer.setStyle) { | |
| 6169 | + layer.setStyle(style); | |
| 6170 | + } | |
| 6171 | + } | |
| 6172 | +}); | |
| 6173 | + | |
| 6174 | +L.extend(L.GeoJSON, { | |
| 6175 | + geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) { | |
| 6176 | + var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, | |
| 6177 | + coords = geometry.coordinates, | |
| 6178 | + layers = [], | |
| 6179 | + latlng, latlngs, i, len; | |
| 6180 | + | |
| 6181 | + coordsToLatLng = coordsToLatLng || this.coordsToLatLng; | |
| 6182 | + | |
| 6183 | + switch (geometry.type) { | |
| 6184 | + case 'Point': | |
| 6185 | + latlng = coordsToLatLng(coords); | |
| 6186 | + return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng); | |
| 6187 | + | |
| 6188 | + case 'MultiPoint': | |
| 6189 | + for (i = 0, len = coords.length; i < len; i++) { | |
| 6190 | + latlng = coordsToLatLng(coords[i]); | |
| 6191 | + layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng)); | |
| 6192 | + } | |
| 6193 | + return new L.FeatureGroup(layers); | |
| 6194 | + | |
| 6195 | + case 'LineString': | |
| 6196 | + latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng); | |
| 6197 | + return new L.Polyline(latlngs, vectorOptions); | |
| 6198 | + | |
| 6199 | + case 'Polygon': | |
| 6200 | + if (coords.length === 2 && !coords[1].length) { | |
| 6201 | + throw new Error('Invalid GeoJSON object.'); | |
| 6202 | + } | |
| 6203 | + latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); | |
| 6204 | + return new L.Polygon(latlngs, vectorOptions); | |
| 6205 | + | |
| 6206 | + case 'MultiLineString': | |
| 6207 | + latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); | |
| 6208 | + return new L.MultiPolyline(latlngs, vectorOptions); | |
| 6209 | + | |
| 6210 | + case 'MultiPolygon': | |
| 6211 | + latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng); | |
| 6212 | + return new L.MultiPolygon(latlngs, vectorOptions); | |
| 6213 | + | |
| 6214 | + case 'GeometryCollection': | |
| 6215 | + for (i = 0, len = geometry.geometries.length; i < len; i++) { | |
| 6216 | + | |
| 6217 | + layers.push(this.geometryToLayer({ | |
| 6218 | + geometry: geometry.geometries[i], | |
| 6219 | + type: 'Feature', | |
| 6220 | + properties: geojson.properties | |
| 6221 | + }, pointToLayer, coordsToLatLng, vectorOptions)); | |
| 6222 | + } | |
| 6223 | + return new L.FeatureGroup(layers); | |
| 6224 | + | |
| 6225 | + default: | |
| 6226 | + throw new Error('Invalid GeoJSON object.'); | |
| 6227 | + } | |
| 6228 | + }, | |
| 6229 | + | |
| 6230 | + coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng | |
| 6231 | + return new L.LatLng(coords[1], coords[0], coords[2]); | |
| 6232 | + }, | |
| 6233 | + | |
| 6234 | + coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array | |
| 6235 | + var latlng, i, len, | |
| 6236 | + latlngs = []; | |
| 6237 | + | |
| 6238 | + for (i = 0, len = coords.length; i < len; i++) { | |
| 6239 | + latlng = levelsDeep ? | |
| 6240 | + this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) : | |
| 6241 | + (coordsToLatLng || this.coordsToLatLng)(coords[i]); | |
| 6242 | + | |
| 6243 | + latlngs.push(latlng); | |
| 6244 | + } | |
| 6245 | + | |
| 6246 | + return latlngs; | |
| 6247 | + }, | |
| 6248 | + | |
| 6249 | + latLngToCoords: function (latlng) { | |
| 6250 | + var coords = [latlng.lng, latlng.lat]; | |
| 6251 | + | |
| 6252 | + if (latlng.alt !== undefined) { | |
| 6253 | + coords.push(latlng.alt); | |
| 6254 | + } | |
| 6255 | + return coords; | |
| 6256 | + }, | |
| 6257 | + | |
| 6258 | + latLngsToCoords: function (latLngs) { | |
| 6259 | + var coords = []; | |
| 6260 | + | |
| 6261 | + for (var i = 0, len = latLngs.length; i < len; i++) { | |
| 6262 | + coords.push(L.GeoJSON.latLngToCoords(latLngs[i])); | |
| 6263 | + } | |
| 6264 | + | |
| 6265 | + return coords; | |
| 6266 | + }, | |
| 6267 | + | |
| 6268 | + getFeature: function (layer, newGeometry) { | |
| 6269 | + return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry); | |
| 6270 | + }, | |
| 6271 | + | |
| 6272 | + asFeature: function (geoJSON) { | |
| 6273 | + if (geoJSON.type === 'Feature') { | |
| 6274 | + return geoJSON; | |
| 6275 | + } | |
| 6276 | + | |
| 6277 | + return { | |
| 6278 | + type: 'Feature', | |
| 6279 | + properties: {}, | |
| 6280 | + geometry: geoJSON | |
| 6281 | + }; | |
| 6282 | + } | |
| 6283 | +}); | |
| 6284 | + | |
| 6285 | +var PointToGeoJSON = { | |
| 6286 | + toGeoJSON: function () { | |
| 6287 | + return L.GeoJSON.getFeature(this, { | |
| 6288 | + type: 'Point', | |
| 6289 | + coordinates: L.GeoJSON.latLngToCoords(this.getLatLng()) | |
| 6290 | + }); | |
| 6291 | + } | |
| 6292 | +}; | |
| 6293 | + | |
| 6294 | +L.Marker.include(PointToGeoJSON); | |
| 6295 | +L.Circle.include(PointToGeoJSON); | |
| 6296 | +L.CircleMarker.include(PointToGeoJSON); | |
| 6297 | + | |
| 6298 | +L.Polyline.include({ | |
| 6299 | + toGeoJSON: function () { | |
| 6300 | + return L.GeoJSON.getFeature(this, { | |
| 6301 | + type: 'LineString', | |
| 6302 | + coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs()) | |
| 6303 | + }); | |
| 6304 | + } | |
| 6305 | +}); | |
| 6306 | + | |
| 6307 | +L.Polygon.include({ | |
| 6308 | + toGeoJSON: function () { | |
| 6309 | + var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())], | |
| 6310 | + i, len, hole; | |
| 6311 | + | |
| 6312 | + coords[0].push(coords[0][0]); | |
| 6313 | + | |
| 6314 | + if (this._holes) { | |
| 6315 | + for (i = 0, len = this._holes.length; i < len; i++) { | |
| 6316 | + hole = L.GeoJSON.latLngsToCoords(this._holes[i]); | |
| 6317 | + hole.push(hole[0]); | |
| 6318 | + coords.push(hole); | |
| 6319 | + } | |
| 6320 | + } | |
| 6321 | + | |
| 6322 | + return L.GeoJSON.getFeature(this, { | |
| 6323 | + type: 'Polygon', | |
| 6324 | + coordinates: coords | |
| 6325 | + }); | |
| 6326 | + } | |
| 6327 | +}); | |
| 6328 | + | |
| 6329 | +(function () { | |
| 6330 | + function multiToGeoJSON(type) { | |
| 6331 | + return function () { | |
| 6332 | + var coords = []; | |
| 6333 | + | |
| 6334 | + this.eachLayer(function (layer) { | |
| 6335 | + coords.push(layer.toGeoJSON().geometry.coordinates); | |
| 6336 | + }); | |
| 6337 | + | |
| 6338 | + return L.GeoJSON.getFeature(this, { | |
| 6339 | + type: type, | |
| 6340 | + coordinates: coords | |
| 6341 | + }); | |
| 6342 | + }; | |
| 6343 | + } | |
| 6344 | + | |
| 6345 | + L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')}); | |
| 6346 | + L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')}); | |
| 6347 | + | |
| 6348 | + L.LayerGroup.include({ | |
| 6349 | + toGeoJSON: function () { | |
| 6350 | + | |
| 6351 | + var geometry = this.feature && this.feature.geometry, | |
| 6352 | + jsons = [], | |
| 6353 | + json; | |
| 6354 | + | |
| 6355 | + if (geometry && geometry.type === 'MultiPoint') { | |
| 6356 | + return multiToGeoJSON('MultiPoint').call(this); | |
| 6357 | + } | |
| 6358 | + | |
| 6359 | + var isGeometryCollection = geometry && geometry.type === 'GeometryCollection'; | |
| 6360 | + | |
| 6361 | + this.eachLayer(function (layer) { | |
| 6362 | + if (layer.toGeoJSON) { | |
| 6363 | + json = layer.toGeoJSON(); | |
| 6364 | + jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json)); | |
| 6365 | + } | |
| 6366 | + }); | |
| 6367 | + | |
| 6368 | + if (isGeometryCollection) { | |
| 6369 | + return L.GeoJSON.getFeature(this, { | |
| 6370 | + geometries: jsons, | |
| 6371 | + type: 'GeometryCollection' | |
| 6372 | + }); | |
| 6373 | + } | |
| 6374 | + | |
| 6375 | + return { | |
| 6376 | + type: 'FeatureCollection', | |
| 6377 | + features: jsons | |
| 6378 | + }; | |
| 6379 | + } | |
| 6380 | + }); | |
| 6381 | +}()); | |
| 6382 | + | |
| 6383 | +L.geoJson = function (geojson, options) { | |
| 6384 | + return new L.GeoJSON(geojson, options); | |
| 6385 | +}; | |
| 6386 | + | |
| 6387 | + | |
| 6388 | +/* | |
| 6389 | + * L.DomEvent contains functions for working with DOM events. | |
| 6390 | + */ | |
| 6391 | + | |
| 6392 | +L.DomEvent = { | |
| 6393 | + /* inspired by John Resig, Dean Edwards and YUI addEvent implementations */ | |
| 6394 | + addListener: function (obj, type, fn, context) { // (HTMLElement, String, Function[, Object]) | |
| 6395 | + | |
| 6396 | + var id = L.stamp(fn), | |
| 6397 | + key = '_leaflet_' + type + id, | |
| 6398 | + handler, originalHandler, newType; | |
| 6399 | + | |
| 6400 | + if (obj[key]) { return this; } | |
| 6401 | + | |
| 6402 | + handler = function (e) { | |
| 6403 | + return fn.call(context || obj, e || L.DomEvent._getEvent()); | |
| 6404 | + }; | |
| 6405 | + | |
| 6406 | + if (L.Browser.pointer && type.indexOf('touch') === 0) { | |
| 6407 | + return this.addPointerListener(obj, type, handler, id); | |
| 6408 | + } | |
| 6409 | + if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) { | |
| 6410 | + this.addDoubleTapListener(obj, handler, id); | |
| 6411 | + } | |
| 6412 | + | |
| 6413 | + if ('addEventListener' in obj) { | |
| 6414 | + | |
| 6415 | + if (type === 'mousewheel') { | |
| 6416 | + obj.addEventListener('DOMMouseScroll', handler, false); | |
| 6417 | + obj.addEventListener(type, handler, false); | |
| 6418 | + | |
| 6419 | + } else if ((type === 'mouseenter') || (type === 'mouseleave')) { | |
| 6420 | + | |
| 6421 | + originalHandler = handler; | |
| 6422 | + newType = (type === 'mouseenter' ? 'mouseover' : 'mouseout'); | |
| 6423 | + | |
| 6424 | + handler = function (e) { | |
| 6425 | + if (!L.DomEvent._checkMouse(obj, e)) { return; } | |
| 6426 | + return originalHandler(e); | |
| 6427 | + }; | |
| 6428 | + | |
| 6429 | + obj.addEventListener(newType, handler, false); | |
| 6430 | + | |
| 6431 | + } else if (type === 'click' && L.Browser.android) { | |
| 6432 | + originalHandler = handler; | |
| 6433 | + handler = function (e) { | |
| 6434 | + return L.DomEvent._filterClick(e, originalHandler); | |
| 6435 | + }; | |
| 6436 | + | |
| 6437 | + obj.addEventListener(type, handler, false); | |
| 6438 | + } else { | |
| 6439 | + obj.addEventListener(type, handler, false); | |
| 6440 | + } | |
| 6441 | + | |
| 6442 | + } else if ('attachEvent' in obj) { | |
| 6443 | + obj.attachEvent('on' + type, handler); | |
| 6444 | + } | |
| 6445 | + | |
| 6446 | + obj[key] = handler; | |
| 6447 | + | |
| 6448 | + return this; | |
| 6449 | + }, | |
| 6450 | + | |
| 6451 | + removeListener: function (obj, type, fn) { // (HTMLElement, String, Function) | |
| 6452 | + | |
| 6453 | + var id = L.stamp(fn), | |
| 6454 | + key = '_leaflet_' + type + id, | |
| 6455 | + handler = obj[key]; | |
| 6456 | + | |
| 6457 | + if (!handler) { return this; } | |
| 6458 | + | |
| 6459 | + if (L.Browser.pointer && type.indexOf('touch') === 0) { | |
| 6460 | + this.removePointerListener(obj, type, id); | |
| 6461 | + } else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) { | |
| 6462 | + this.removeDoubleTapListener(obj, id); | |
| 6463 | + | |
| 6464 | + } else if ('removeEventListener' in obj) { | |
| 6465 | + | |
| 6466 | + if (type === 'mousewheel') { | |
| 6467 | + obj.removeEventListener('DOMMouseScroll', handler, false); | |
| 6468 | + obj.removeEventListener(type, handler, false); | |
| 6469 | + | |
| 6470 | + } else if ((type === 'mouseenter') || (type === 'mouseleave')) { | |
| 6471 | + obj.removeEventListener((type === 'mouseenter' ? 'mouseover' : 'mouseout'), handler, false); | |
| 6472 | + } else { | |
| 6473 | + obj.removeEventListener(type, handler, false); | |
| 6474 | + } | |
| 6475 | + } else if ('detachEvent' in obj) { | |
| 6476 | + obj.detachEvent('on' + type, handler); | |
| 6477 | + } | |
| 6478 | + | |
| 6479 | + obj[key] = null; | |
| 6480 | + | |
| 6481 | + return this; | |
| 6482 | + }, | |
| 6483 | + | |
| 6484 | + stopPropagation: function (e) { | |
| 6485 | + | |
| 6486 | + if (e.stopPropagation) { | |
| 6487 | + e.stopPropagation(); | |
| 6488 | + } else { | |
| 6489 | + e.cancelBubble = true; | |
| 6490 | + } | |
| 6491 | + L.DomEvent._skipped(e); | |
| 6492 | + | |
| 6493 | + return this; | |
| 6494 | + }, | |
| 6495 | + | |
| 6496 | + disableScrollPropagation: function (el) { | |
| 6497 | + var stop = L.DomEvent.stopPropagation; | |
| 6498 | + | |
| 6499 | + return L.DomEvent | |
| 6500 | + .on(el, 'mousewheel', stop) | |
| 6501 | + .on(el, 'MozMousePixelScroll', stop); | |
| 6502 | + }, | |
| 6503 | + | |
| 6504 | + disableClickPropagation: function (el) { | |
| 6505 | + var stop = L.DomEvent.stopPropagation; | |
| 6506 | + | |
| 6507 | + for (var i = L.Draggable.START.length - 1; i >= 0; i--) { | |
| 6508 | + L.DomEvent.on(el, L.Draggable.START[i], stop); | |
| 6509 | + } | |
| 6510 | + | |
| 6511 | + return L.DomEvent | |
| 6512 | + .on(el, 'click', L.DomEvent._fakeStop) | |
| 6513 | + .on(el, 'dblclick', stop); | |
| 6514 | + }, | |
| 6515 | + | |
| 6516 | + preventDefault: function (e) { | |
| 6517 | + | |
| 6518 | + if (e.preventDefault) { | |
| 6519 | + e.preventDefault(); | |
| 6520 | + } else { | |
| 6521 | + e.returnValue = false; | |
| 6522 | + } | |
| 6523 | + return this; | |
| 6524 | + }, | |
| 6525 | + | |
| 6526 | + stop: function (e) { | |
| 6527 | + return L.DomEvent | |
| 6528 | + .preventDefault(e) | |
| 6529 | + .stopPropagation(e); | |
| 6530 | + }, | |
| 6531 | + | |
| 6532 | + getMousePosition: function (e, container) { | |
| 6533 | + if (!container) { | |
| 6534 | + return new L.Point(e.clientX, e.clientY); | |
| 6535 | + } | |
| 6536 | + | |
| 6537 | + var rect = container.getBoundingClientRect(); | |
| 6538 | + | |
| 6539 | + return new L.Point( | |
| 6540 | + e.clientX - rect.left - container.clientLeft, | |
| 6541 | + e.clientY - rect.top - container.clientTop); | |
| 6542 | + }, | |
| 6543 | + | |
| 6544 | + getWheelDelta: function (e) { | |
| 6545 | + | |
| 6546 | + var delta = 0; | |
| 6547 | + | |
| 6548 | + if (e.wheelDelta) { | |
| 6549 | + delta = e.wheelDelta / 120; | |
| 6550 | + } | |
| 6551 | + if (e.detail) { | |
| 6552 | + delta = -e.detail / 3; | |
| 6553 | + } | |
| 6554 | + return delta; | |
| 6555 | + }, | |
| 6556 | + | |
| 6557 | + _skipEvents: {}, | |
| 6558 | + | |
| 6559 | + _fakeStop: function (e) { | |
| 6560 | + // fakes stopPropagation by setting a special event flag, checked/reset with L.DomEvent._skipped(e) | |
| 6561 | + L.DomEvent._skipEvents[e.type] = true; | |
| 6562 | + }, | |
| 6563 | + | |
| 6564 | + _skipped: function (e) { | |
| 6565 | + var skipped = this._skipEvents[e.type]; | |
| 6566 | + // reset when checking, as it's only used in map container and propagates outside of the map | |
| 6567 | + this._skipEvents[e.type] = false; | |
| 6568 | + return skipped; | |
| 6569 | + }, | |
| 6570 | + | |
| 6571 | + // check if element really left/entered the event target (for mouseenter/mouseleave) | |
| 6572 | + _checkMouse: function (el, e) { | |
| 6573 | + | |
| 6574 | + var related = e.relatedTarget; | |
| 6575 | + | |
| 6576 | + if (!related) { return true; } | |
| 6577 | + | |
| 6578 | + try { | |
| 6579 | + while (related && (related !== el)) { | |
| 6580 | + related = related.parentNode; | |
| 6581 | + } | |
| 6582 | + } catch (err) { | |
| 6583 | + return false; | |
| 6584 | + } | |
| 6585 | + return (related !== el); | |
| 6586 | + }, | |
| 6587 | + | |
| 6588 | + _getEvent: function () { // evil magic for IE | |
| 6589 | + /*jshint noarg:false */ | |
| 6590 | + var e = window.event; | |
| 6591 | + if (!e) { | |
| 6592 | + var caller = arguments.callee.caller; | |
| 6593 | + while (caller) { | |
| 6594 | + e = caller['arguments'][0]; | |
| 6595 | + if (e && window.Event === e.constructor) { | |
| 6596 | + break; | |
| 6597 | + } | |
| 6598 | + caller = caller.caller; | |
| 6599 | + } | |
| 6600 | + } | |
| 6601 | + return e; | |
| 6602 | + }, | |
| 6603 | + | |
| 6604 | + // this is a horrible workaround for a bug in Android where a single touch triggers two click events | |
| 6605 | + _filterClick: function (e, handler) { | |
| 6606 | + var timeStamp = (e.timeStamp || e.originalEvent.timeStamp), | |
| 6607 | + elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick); | |
| 6608 | + | |
| 6609 | + // are they closer together than 500ms yet more than 100ms? | |
| 6610 | + // Android typically triggers them ~300ms apart while multiple listeners | |
| 6611 | + // on the same event should be triggered far faster; | |
| 6612 | + // or check if click is simulated on the element, and if it is, reject any non-simulated events | |
| 6613 | + | |
| 6614 | + if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { | |
| 6615 | + L.DomEvent.stop(e); | |
| 6616 | + return; | |
| 6617 | + } | |
| 6618 | + L.DomEvent._lastClick = timeStamp; | |
| 6619 | + | |
| 6620 | + return handler(e); | |
| 6621 | + } | |
| 6622 | +}; | |
| 6623 | + | |
| 6624 | +L.DomEvent.on = L.DomEvent.addListener; | |
| 6625 | +L.DomEvent.off = L.DomEvent.removeListener; | |
| 6626 | + | |
| 6627 | + | |
| 6628 | +/* | |
| 6629 | + * L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too. | |
| 6630 | + */ | |
| 6631 | + | |
| 6632 | +L.Draggable = L.Class.extend({ | |
| 6633 | + includes: L.Mixin.Events, | |
| 6634 | + | |
| 6635 | + statics: { | |
| 6636 | + START: L.Browser.touch ? ['touchstart', 'mousedown'] : ['mousedown'], | |
| 6637 | + END: { | |
| 6638 | + mousedown: 'mouseup', | |
| 6639 | + touchstart: 'touchend', | |
| 6640 | + pointerdown: 'touchend', | |
| 6641 | + MSPointerDown: 'touchend' | |
| 6642 | + }, | |
| 6643 | + MOVE: { | |
| 6644 | + mousedown: 'mousemove', | |
| 6645 | + touchstart: 'touchmove', | |
| 6646 | + pointerdown: 'touchmove', | |
| 6647 | + MSPointerDown: 'touchmove' | |
| 6648 | + } | |
| 6649 | + }, | |
| 6650 | + | |
| 6651 | + initialize: function (element, dragStartTarget) { | |
| 6652 | + this._element = element; | |
| 6653 | + this._dragStartTarget = dragStartTarget || element; | |
| 6654 | + }, | |
| 6655 | + | |
| 6656 | + enable: function () { | |
| 6657 | + if (this._enabled) { return; } | |
| 6658 | + | |
| 6659 | + for (var i = L.Draggable.START.length - 1; i >= 0; i--) { | |
| 6660 | + L.DomEvent.on(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); | |
| 6661 | + } | |
| 6662 | + | |
| 6663 | + this._enabled = true; | |
| 6664 | + }, | |
| 6665 | + | |
| 6666 | + disable: function () { | |
| 6667 | + if (!this._enabled) { return; } | |
| 6668 | + | |
| 6669 | + for (var i = L.Draggable.START.length - 1; i >= 0; i--) { | |
| 6670 | + L.DomEvent.off(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); | |
| 6671 | + } | |
| 6672 | + | |
| 6673 | + this._enabled = false; | |
| 6674 | + this._moved = false; | |
| 6675 | + }, | |
| 6676 | + | |
| 6677 | + _onDown: function (e) { | |
| 6678 | + this._moved = false; | |
| 6679 | + | |
| 6680 | + if (e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } | |
| 6681 | + | |
| 6682 | + L.DomEvent.stopPropagation(e); | |
| 6683 | + | |
| 6684 | + if (L.Draggable._disabled) { return; } | |
| 6685 | + | |
| 6686 | + L.DomUtil.disableImageDrag(); | |
| 6687 | + L.DomUtil.disableTextSelection(); | |
| 6688 | + | |
| 6689 | + if (this._moving) { return; } | |
| 6690 | + | |
| 6691 | + var first = e.touches ? e.touches[0] : e; | |
| 6692 | + | |
| 6693 | + this._startPoint = new L.Point(first.clientX, first.clientY); | |
| 6694 | + this._startPos = this._newPos = L.DomUtil.getPosition(this._element); | |
| 6695 | + | |
| 6696 | + L.DomEvent | |
| 6697 | + .on(document, L.Draggable.MOVE[e.type], this._onMove, this) | |
| 6698 | + .on(document, L.Draggable.END[e.type], this._onUp, this); | |
| 6699 | + }, | |
| 6700 | + | |
| 6701 | + _onMove: function (e) { | |
| 6702 | + if (e.touches && e.touches.length > 1) { | |
| 6703 | + this._moved = true; | |
| 6704 | + return; | |
| 6705 | + } | |
| 6706 | + | |
| 6707 | + var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), | |
| 6708 | + newPoint = new L.Point(first.clientX, first.clientY), | |
| 6709 | + offset = newPoint.subtract(this._startPoint); | |
| 6710 | + | |
| 6711 | + if (!offset.x && !offset.y) { return; } | |
| 6712 | + if (L.Browser.touch && Math.abs(offset.x) + Math.abs(offset.y) < 3) { return; } | |
| 6713 | + | |
| 6714 | + L.DomEvent.preventDefault(e); | |
| 6715 | + | |
| 6716 | + if (!this._moved) { | |
| 6717 | + this.fire('dragstart'); | |
| 6718 | + | |
| 6719 | + this._moved = true; | |
| 6720 | + this._startPos = L.DomUtil.getPosition(this._element).subtract(offset); | |
| 6721 | + | |
| 6722 | + L.DomUtil.addClass(document.body, 'leaflet-dragging'); | |
| 6723 | + this._lastTarget = e.target || e.srcElement; | |
| 6724 | + L.DomUtil.addClass(this._lastTarget, 'leaflet-drag-target'); | |
| 6725 | + } | |
| 6726 | + | |
| 6727 | + this._newPos = this._startPos.add(offset); | |
| 6728 | + this._moving = true; | |
| 6729 | + | |
| 6730 | + L.Util.cancelAnimFrame(this._animRequest); | |
| 6731 | + this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget); | |
| 6732 | + }, | |
| 6733 | + | |
| 6734 | + _updatePosition: function () { | |
| 6735 | + this.fire('predrag'); | |
| 6736 | + L.DomUtil.setPosition(this._element, this._newPos); | |
| 6737 | + this.fire('drag'); | |
| 6738 | + }, | |
| 6739 | + | |
| 6740 | + _onUp: function () { | |
| 6741 | + L.DomUtil.removeClass(document.body, 'leaflet-dragging'); | |
| 6742 | + | |
| 6743 | + if (this._lastTarget) { | |
| 6744 | + L.DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target'); | |
| 6745 | + this._lastTarget = null; | |
| 6746 | + } | |
| 6747 | + | |
| 6748 | + for (var i in L.Draggable.MOVE) { | |
| 6749 | + L.DomEvent | |
| 6750 | + .off(document, L.Draggable.MOVE[i], this._onMove) | |
| 6751 | + .off(document, L.Draggable.END[i], this._onUp); | |
| 6752 | + } | |
| 6753 | + | |
| 6754 | + L.DomUtil.enableImageDrag(); | |
| 6755 | + L.DomUtil.enableTextSelection(); | |
| 6756 | + | |
| 6757 | + if (this._moved && this._moving) { | |
| 6758 | + // ensure drag is not fired after dragend | |
| 6759 | + L.Util.cancelAnimFrame(this._animRequest); | |
| 6760 | + | |
| 6761 | + this.fire('dragend', { | |
| 6762 | + distance: this._newPos.distanceTo(this._startPos) | |
| 6763 | + }); | |
| 6764 | + } | |
| 6765 | + | |
| 6766 | + this._moving = false; | |
| 6767 | + } | |
| 6768 | +}); | |
| 6769 | + | |
| 6770 | + | |
| 6771 | +/* | |
| 6772 | + L.Handler is a base class for handler classes that are used internally to inject | |
| 6773 | + interaction features like dragging to classes like Map and Marker. | |
| 6774 | +*/ | |
| 6775 | + | |
| 6776 | +L.Handler = L.Class.extend({ | |
| 6777 | + initialize: function (map) { | |
| 6778 | + this._map = map; | |
| 6779 | + }, | |
| 6780 | + | |
| 6781 | + enable: function () { | |
| 6782 | + if (this._enabled) { return; } | |
| 6783 | + | |
| 6784 | + this._enabled = true; | |
| 6785 | + this.addHooks(); | |
| 6786 | + }, | |
| 6787 | + | |
| 6788 | + disable: function () { | |
| 6789 | + if (!this._enabled) { return; } | |
| 6790 | + | |
| 6791 | + this._enabled = false; | |
| 6792 | + this.removeHooks(); | |
| 6793 | + }, | |
| 6794 | + | |
| 6795 | + enabled: function () { | |
| 6796 | + return !!this._enabled; | |
| 6797 | + } | |
| 6798 | +}); | |
| 6799 | + | |
| 6800 | + | |
| 6801 | +/* | |
| 6802 | + * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default. | |
| 6803 | + */ | |
| 6804 | + | |
| 6805 | +L.Map.mergeOptions({ | |
| 6806 | + dragging: true, | |
| 6807 | + | |
| 6808 | + inertia: !L.Browser.android23, | |
| 6809 | + inertiaDeceleration: 3400, // px/s^2 | |
| 6810 | + inertiaMaxSpeed: Infinity, // px/s | |
| 6811 | + inertiaThreshold: L.Browser.touch ? 32 : 18, // ms | |
| 6812 | + easeLinearity: 0.25, | |
| 6813 | + | |
| 6814 | + // TODO refactor, move to CRS | |
| 6815 | + worldCopyJump: false | |
| 6816 | +}); | |
| 6817 | + | |
| 6818 | +L.Map.Drag = L.Handler.extend({ | |
| 6819 | + addHooks: function () { | |
| 6820 | + if (!this._draggable) { | |
| 6821 | + var map = this._map; | |
| 6822 | + | |
| 6823 | + this._draggable = new L.Draggable(map._mapPane, map._container); | |
| 6824 | + | |
| 6825 | + this._draggable.on({ | |
| 6826 | + 'dragstart': this._onDragStart, | |
| 6827 | + 'drag': this._onDrag, | |
| 6828 | + 'dragend': this._onDragEnd | |
| 6829 | + }, this); | |
| 6830 | + | |
| 6831 | + if (map.options.worldCopyJump) { | |
| 6832 | + this._draggable.on('predrag', this._onPreDrag, this); | |
| 6833 | + map.on('viewreset', this._onViewReset, this); | |
| 6834 | + | |
| 6835 | + map.whenReady(this._onViewReset, this); | |
| 6836 | + } | |
| 6837 | + } | |
| 6838 | + this._draggable.enable(); | |
| 6839 | + }, | |
| 6840 | + | |
| 6841 | + removeHooks: function () { | |
| 6842 | + this._draggable.disable(); | |
| 6843 | + }, | |
| 6844 | + | |
| 6845 | + moved: function () { | |
| 6846 | + return this._draggable && this._draggable._moved; | |
| 6847 | + }, | |
| 6848 | + | |
| 6849 | + _onDragStart: function () { | |
| 6850 | + var map = this._map; | |
| 6851 | + | |
| 6852 | + if (map._panAnim) { | |
| 6853 | + map._panAnim.stop(); | |
| 6854 | + } | |
| 6855 | + | |
| 6856 | + map | |
| 6857 | + .fire('movestart') | |
| 6858 | + .fire('dragstart'); | |
| 6859 | + | |
| 6860 | + if (map.options.inertia) { | |
| 6861 | + this._positions = []; | |
| 6862 | + this._times = []; | |
| 6863 | + } | |
| 6864 | + }, | |
| 6865 | + | |
| 6866 | + _onDrag: function () { | |
| 6867 | + if (this._map.options.inertia) { | |
| 6868 | + var time = this._lastTime = +new Date(), | |
| 6869 | + pos = this._lastPos = this._draggable._newPos; | |
| 6870 | + | |
| 6871 | + this._positions.push(pos); | |
| 6872 | + this._times.push(time); | |
| 6873 | + | |
| 6874 | + if (time - this._times[0] > 200) { | |
| 6875 | + this._positions.shift(); | |
| 6876 | + this._times.shift(); | |
| 6877 | + } | |
| 6878 | + } | |
| 6879 | + | |
| 6880 | + this._map | |
| 6881 | + .fire('move') | |
| 6882 | + .fire('drag'); | |
| 6883 | + }, | |
| 6884 | + | |
| 6885 | + _onViewReset: function () { | |
| 6886 | + // TODO fix hardcoded Earth values | |
| 6887 | + var pxCenter = this._map.getSize()._divideBy(2), | |
| 6888 | + pxWorldCenter = this._map.latLngToLayerPoint([0, 0]); | |
| 6889 | + | |
| 6890 | + this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; | |
| 6891 | + this._worldWidth = this._map.project([0, 180]).x; | |
| 6892 | + }, | |
| 6893 | + | |
| 6894 | + _onPreDrag: function () { | |
| 6895 | + // TODO refactor to be able to adjust map pane position after zoom | |
| 6896 | + var worldWidth = this._worldWidth, | |
| 6897 | + halfWidth = Math.round(worldWidth / 2), | |
| 6898 | + dx = this._initialWorldOffset, | |
| 6899 | + x = this._draggable._newPos.x, | |
| 6900 | + newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, | |
| 6901 | + newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, | |
| 6902 | + newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2; | |
| 6903 | + | |
| 6904 | + this._draggable._newPos.x = newX; | |
| 6905 | + }, | |
| 6906 | + | |
| 6907 | + _onDragEnd: function (e) { | |
| 6908 | + var map = this._map, | |
| 6909 | + options = map.options, | |
| 6910 | + delay = +new Date() - this._lastTime, | |
| 6911 | + | |
| 6912 | + noInertia = !options.inertia || delay > options.inertiaThreshold || !this._positions[0]; | |
| 6913 | + | |
| 6914 | + map.fire('dragend', e); | |
| 6915 | + | |
| 6916 | + if (noInertia) { | |
| 6917 | + map.fire('moveend'); | |
| 6918 | + | |
| 6919 | + } else { | |
| 6920 | + | |
| 6921 | + var direction = this._lastPos.subtract(this._positions[0]), | |
| 6922 | + duration = (this._lastTime + delay - this._times[0]) / 1000, | |
| 6923 | + ease = options.easeLinearity, | |
| 6924 | + | |
| 6925 | + speedVector = direction.multiplyBy(ease / duration), | |
| 6926 | + speed = speedVector.distanceTo([0, 0]), | |
| 6927 | + | |
| 6928 | + limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), | |
| 6929 | + limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), | |
| 6930 | + | |
| 6931 | + decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), | |
| 6932 | + offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round(); | |
| 6933 | + | |
| 6934 | + if (!offset.x || !offset.y) { | |
| 6935 | + map.fire('moveend'); | |
| 6936 | + | |
| 6937 | + } else { | |
| 6938 | + offset = map._limitOffset(offset, map.options.maxBounds); | |
| 6939 | + | |
| 6940 | + L.Util.requestAnimFrame(function () { | |
| 6941 | + map.panBy(offset, { | |
| 6942 | + duration: decelerationDuration, | |
| 6943 | + easeLinearity: ease, | |
| 6944 | + noMoveStart: true | |
| 6945 | + }); | |
| 6946 | + }); | |
| 6947 | + } | |
| 6948 | + } | |
| 6949 | + } | |
| 6950 | +}); | |
| 6951 | + | |
| 6952 | +L.Map.addInitHook('addHandler', 'dragging', L.Map.Drag); | |
| 6953 | + | |
| 6954 | + | |
| 6955 | +/* | |
| 6956 | + * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default. | |
| 6957 | + */ | |
| 6958 | + | |
| 6959 | +L.Map.mergeOptions({ | |
| 6960 | + doubleClickZoom: true | |
| 6961 | +}); | |
| 6962 | + | |
| 6963 | +L.Map.DoubleClickZoom = L.Handler.extend({ | |
| 6964 | + addHooks: function () { | |
| 6965 | + this._map.on('dblclick', this._onDoubleClick, this); | |
| 6966 | + }, | |
| 6967 | + | |
| 6968 | + removeHooks: function () { | |
| 6969 | + this._map.off('dblclick', this._onDoubleClick, this); | |
| 6970 | + }, | |
| 6971 | + | |
| 6972 | + _onDoubleClick: function (e) { | |
| 6973 | + var map = this._map, | |
| 6974 | + zoom = map.getZoom() + (e.originalEvent.shiftKey ? -1 : 1); | |
| 6975 | + | |
| 6976 | + if (map.options.doubleClickZoom === 'center') { | |
| 6977 | + map.setZoom(zoom); | |
| 6978 | + } else { | |
| 6979 | + map.setZoomAround(e.containerPoint, zoom); | |
| 6980 | + } | |
| 6981 | + } | |
| 6982 | +}); | |
| 6983 | + | |
| 6984 | +L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom); | |
| 6985 | + | |
| 6986 | + | |
| 6987 | +/* | |
| 6988 | + * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map. | |
| 6989 | + */ | |
| 6990 | + | |
| 6991 | +L.Map.mergeOptions({ | |
| 6992 | + scrollWheelZoom: true | |
| 6993 | +}); | |
| 6994 | + | |
| 6995 | +L.Map.ScrollWheelZoom = L.Handler.extend({ | |
| 6996 | + addHooks: function () { | |
| 6997 | + L.DomEvent.on(this._map._container, 'mousewheel', this._onWheelScroll, this); | |
| 6998 | + L.DomEvent.on(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); | |
| 6999 | + this._delta = 0; | |
| 7000 | + }, | |
| 7001 | + | |
| 7002 | + removeHooks: function () { | |
| 7003 | + L.DomEvent.off(this._map._container, 'mousewheel', this._onWheelScroll); | |
| 7004 | + L.DomEvent.off(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); | |
| 7005 | + }, | |
| 7006 | + | |
| 7007 | + _onWheelScroll: function (e) { | |
| 7008 | + var delta = L.DomEvent.getWheelDelta(e); | |
| 7009 | + | |
| 7010 | + this._delta += delta; | |
| 7011 | + this._lastMousePos = this._map.mouseEventToContainerPoint(e); | |
| 7012 | + | |
| 7013 | + if (!this._startTime) { | |
| 7014 | + this._startTime = +new Date(); | |
| 7015 | + } | |
| 7016 | + | |
| 7017 | + var left = Math.max(40 - (+new Date() - this._startTime), 0); | |
| 7018 | + | |
| 7019 | + clearTimeout(this._timer); | |
| 7020 | + this._timer = setTimeout(L.bind(this._performZoom, this), left); | |
| 7021 | + | |
| 7022 | + L.DomEvent.preventDefault(e); | |
| 7023 | + L.DomEvent.stopPropagation(e); | |
| 7024 | + }, | |
| 7025 | + | |
| 7026 | + _performZoom: function () { | |
| 7027 | + var map = this._map, | |
| 7028 | + delta = this._delta, | |
| 7029 | + zoom = map.getZoom(); | |
| 7030 | + | |
| 7031 | + delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta); | |
| 7032 | + delta = Math.max(Math.min(delta, 4), -4); | |
| 7033 | + delta = map._limitZoom(zoom + delta) - zoom; | |
| 7034 | + | |
| 7035 | + this._delta = 0; | |
| 7036 | + this._startTime = null; | |
| 7037 | + | |
| 7038 | + if (!delta) { return; } | |
| 7039 | + | |
| 7040 | + if (map.options.scrollWheelZoom === 'center') { | |
| 7041 | + map.setZoom(zoom + delta); | |
| 7042 | + } else { | |
| 7043 | + map.setZoomAround(this._lastMousePos, zoom + delta); | |
| 7044 | + } | |
| 7045 | + } | |
| 7046 | +}); | |
| 7047 | + | |
| 7048 | +L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom); | |
| 7049 | + | |
| 7050 | + | |
| 7051 | +/* | |
| 7052 | + * Extends the event handling code with double tap support for mobile browsers. | |
| 7053 | + */ | |
| 7054 | + | |
| 7055 | +L.extend(L.DomEvent, { | |
| 7056 | + | |
| 7057 | + _touchstart: L.Browser.msPointer ? 'MSPointerDown' : L.Browser.pointer ? 'pointerdown' : 'touchstart', | |
| 7058 | + _touchend: L.Browser.msPointer ? 'MSPointerUp' : L.Browser.pointer ? 'pointerup' : 'touchend', | |
| 7059 | + | |
| 7060 | + // inspired by Zepto touch code by Thomas Fuchs | |
| 7061 | + addDoubleTapListener: function (obj, handler, id) { | |
| 7062 | + var last, | |
| 7063 | + doubleTap = false, | |
| 7064 | + delay = 250, | |
| 7065 | + touch, | |
| 7066 | + pre = '_leaflet_', | |
| 7067 | + touchstart = this._touchstart, | |
| 7068 | + touchend = this._touchend, | |
| 7069 | + trackedTouches = []; | |
| 7070 | + | |
| 7071 | + function onTouchStart(e) { | |
| 7072 | + var count; | |
| 7073 | + | |
| 7074 | + if (L.Browser.pointer) { | |
| 7075 | + trackedTouches.push(e.pointerId); | |
| 7076 | + count = trackedTouches.length; | |
| 7077 | + } else { | |
| 7078 | + count = e.touches.length; | |
| 7079 | + } | |
| 7080 | + if (count > 1) { | |
| 7081 | + return; | |
| 7082 | + } | |
| 7083 | + | |
| 7084 | + var now = Date.now(), | |
| 7085 | + delta = now - (last || now); | |
| 7086 | + | |
| 7087 | + touch = e.touches ? e.touches[0] : e; | |
| 7088 | + doubleTap = (delta > 0 && delta <= delay); | |
| 7089 | + last = now; | |
| 7090 | + } | |
| 7091 | + | |
| 7092 | + function onTouchEnd(e) { | |
| 7093 | + if (L.Browser.pointer) { | |
| 7094 | + var idx = trackedTouches.indexOf(e.pointerId); | |
| 7095 | + if (idx === -1) { | |
| 7096 | + return; | |
| 7097 | + } | |
| 7098 | + trackedTouches.splice(idx, 1); | |
| 7099 | + } | |
| 7100 | + | |
| 7101 | + if (doubleTap) { | |
| 7102 | + if (L.Browser.pointer) { | |
| 7103 | + // work around .type being readonly with MSPointer* events | |
| 7104 | + var newTouch = { }, | |
| 7105 | + prop; | |
| 7106 | + | |
| 7107 | + // jshint forin:false | |
| 7108 | + for (var i in touch) { | |
| 7109 | + prop = touch[i]; | |
| 7110 | + if (typeof prop === 'function') { | |
| 7111 | + newTouch[i] = prop.bind(touch); | |
| 7112 | + } else { | |
| 7113 | + newTouch[i] = prop; | |
| 7114 | + } | |
| 7115 | + } | |
| 7116 | + touch = newTouch; | |
| 7117 | + } | |
| 7118 | + touch.type = 'dblclick'; | |
| 7119 | + handler(touch); | |
| 7120 | + last = null; | |
| 7121 | + } | |
| 7122 | + } | |
| 7123 | + obj[pre + touchstart + id] = onTouchStart; | |
| 7124 | + obj[pre + touchend + id] = onTouchEnd; | |
| 7125 | + | |
| 7126 | + // on pointer we need to listen on the document, otherwise a drag starting on the map and moving off screen | |
| 7127 | + // will not come through to us, so we will lose track of how many touches are ongoing | |
| 7128 | + var endElement = L.Browser.pointer ? document.documentElement : obj; | |
| 7129 | + | |
| 7130 | + obj.addEventListener(touchstart, onTouchStart, false); | |
| 7131 | + endElement.addEventListener(touchend, onTouchEnd, false); | |
| 7132 | + | |
| 7133 | + if (L.Browser.pointer) { | |
| 7134 | + endElement.addEventListener(L.DomEvent.POINTER_CANCEL, onTouchEnd, false); | |
| 7135 | + } | |
| 7136 | + | |
| 7137 | + return this; | |
| 7138 | + }, | |
| 7139 | + | |
| 7140 | + removeDoubleTapListener: function (obj, id) { | |
| 7141 | + var pre = '_leaflet_'; | |
| 7142 | + | |
| 7143 | + obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false); | |
| 7144 | + (L.Browser.pointer ? document.documentElement : obj).removeEventListener( | |
| 7145 | + this._touchend, obj[pre + this._touchend + id], false); | |
| 7146 | + | |
| 7147 | + if (L.Browser.pointer) { | |
| 7148 | + document.documentElement.removeEventListener(L.DomEvent.POINTER_CANCEL, obj[pre + this._touchend + id], | |
| 7149 | + false); | |
| 7150 | + } | |
| 7151 | + | |
| 7152 | + return this; | |
| 7153 | + } | |
| 7154 | +}); | |
| 7155 | + | |
| 7156 | + | |
| 7157 | +/* | |
| 7158 | + * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. | |
| 7159 | + */ | |
| 7160 | + | |
| 7161 | +L.extend(L.DomEvent, { | |
| 7162 | + | |
| 7163 | + //static | |
| 7164 | + POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown', | |
| 7165 | + POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove', | |
| 7166 | + POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup', | |
| 7167 | + POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel', | |
| 7168 | + | |
| 7169 | + _pointers: [], | |
| 7170 | + _pointerDocumentListener: false, | |
| 7171 | + | |
| 7172 | + // Provides a touch events wrapper for (ms)pointer events. | |
| 7173 | + // Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019 | |
| 7174 | + //ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 | |
| 7175 | + | |
| 7176 | + addPointerListener: function (obj, type, handler, id) { | |
| 7177 | + | |
| 7178 | + switch (type) { | |
| 7179 | + case 'touchstart': | |
| 7180 | + return this.addPointerListenerStart(obj, type, handler, id); | |
| 7181 | + case 'touchend': | |
| 7182 | + return this.addPointerListenerEnd(obj, type, handler, id); | |
| 7183 | + case 'touchmove': | |
| 7184 | + return this.addPointerListenerMove(obj, type, handler, id); | |
| 7185 | + default: | |
| 7186 | + throw 'Unknown touch event type'; | |
| 7187 | + } | |
| 7188 | + }, | |
| 7189 | + | |
| 7190 | + addPointerListenerStart: function (obj, type, handler, id) { | |
| 7191 | + var pre = '_leaflet_', | |
| 7192 | + pointers = this._pointers; | |
| 7193 | + | |
| 7194 | + var cb = function (e) { | |
| 7195 | + | |
| 7196 | + L.DomEvent.preventDefault(e); | |
| 7197 | + | |
| 7198 | + var alreadyInArray = false; | |
| 7199 | + for (var i = 0; i < pointers.length; i++) { | |
| 7200 | + if (pointers[i].pointerId === e.pointerId) { | |
| 7201 | + alreadyInArray = true; | |
| 7202 | + break; | |
| 7203 | + } | |
| 7204 | + } | |
| 7205 | + if (!alreadyInArray) { | |
| 7206 | + pointers.push(e); | |
| 7207 | + } | |
| 7208 | + | |
| 7209 | + e.touches = pointers.slice(); | |
| 7210 | + e.changedTouches = [e]; | |
| 7211 | + | |
| 7212 | + handler(e); | |
| 7213 | + }; | |
| 7214 | + | |
| 7215 | + obj[pre + 'touchstart' + id] = cb; | |
| 7216 | + obj.addEventListener(this.POINTER_DOWN, cb, false); | |
| 7217 | + | |
| 7218 | + // need to also listen for end events to keep the _pointers list accurate | |
| 7219 | + // this needs to be on the body and never go away | |
| 7220 | + if (!this._pointerDocumentListener) { | |
| 7221 | + var internalCb = function (e) { | |
| 7222 | + for (var i = 0; i < pointers.length; i++) { | |
| 7223 | + if (pointers[i].pointerId === e.pointerId) { | |
| 7224 | + pointers.splice(i, 1); | |
| 7225 | + break; | |
| 7226 | + } | |
| 7227 | + } | |
| 7228 | + }; | |
| 7229 | + //We listen on the documentElement as any drags that end by moving the touch off the screen get fired there | |
| 7230 | + document.documentElement.addEventListener(this.POINTER_UP, internalCb, false); | |
| 7231 | + document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false); | |
| 7232 | + | |
| 7233 | + this._pointerDocumentListener = true; | |
| 7234 | + } | |
| 7235 | + | |
| 7236 | + return this; | |
| 7237 | + }, | |
| 7238 | + | |
| 7239 | + addPointerListenerMove: function (obj, type, handler, id) { | |
| 7240 | + var pre = '_leaflet_', | |
| 7241 | + touches = this._pointers; | |
| 7242 | + | |
| 7243 | + function cb(e) { | |
| 7244 | + | |
| 7245 | + // don't fire touch moves when mouse isn't down | |
| 7246 | + if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } | |
| 7247 | + | |
| 7248 | + for (var i = 0; i < touches.length; i++) { | |
| 7249 | + if (touches[i].pointerId === e.pointerId) { | |
| 7250 | + touches[i] = e; | |
| 7251 | + break; | |
| 7252 | + } | |
| 7253 | + } | |
| 7254 | + | |
| 7255 | + e.touches = touches.slice(); | |
| 7256 | + e.changedTouches = [e]; | |
| 7257 | + | |
| 7258 | + handler(e); | |
| 7259 | + } | |
| 7260 | + | |
| 7261 | + obj[pre + 'touchmove' + id] = cb; | |
| 7262 | + obj.addEventListener(this.POINTER_MOVE, cb, false); | |
| 7263 | + | |
| 7264 | + return this; | |
| 7265 | + }, | |
| 7266 | + | |
| 7267 | + addPointerListenerEnd: function (obj, type, handler, id) { | |
| 7268 | + var pre = '_leaflet_', | |
| 7269 | + touches = this._pointers; | |
| 7270 | + | |
| 7271 | + var cb = function (e) { | |
| 7272 | + for (var i = 0; i < touches.length; i++) { | |
| 7273 | + if (touches[i].pointerId === e.pointerId) { | |
| 7274 | + touches.splice(i, 1); | |
| 7275 | + break; | |
| 7276 | + } | |
| 7277 | + } | |
| 7278 | + | |
| 7279 | + e.touches = touches.slice(); | |
| 7280 | + e.changedTouches = [e]; | |
| 7281 | + | |
| 7282 | + handler(e); | |
| 7283 | + }; | |
| 7284 | + | |
| 7285 | + obj[pre + 'touchend' + id] = cb; | |
| 7286 | + obj.addEventListener(this.POINTER_UP, cb, false); | |
| 7287 | + obj.addEventListener(this.POINTER_CANCEL, cb, false); | |
| 7288 | + | |
| 7289 | + return this; | |
| 7290 | + }, | |
| 7291 | + | |
| 7292 | + removePointerListener: function (obj, type, id) { | |
| 7293 | + var pre = '_leaflet_', | |
| 7294 | + cb = obj[pre + type + id]; | |
| 7295 | + | |
| 7296 | + switch (type) { | |
| 7297 | + case 'touchstart': | |
| 7298 | + obj.removeEventListener(this.POINTER_DOWN, cb, false); | |
| 7299 | + break; | |
| 7300 | + case 'touchmove': | |
| 7301 | + obj.removeEventListener(this.POINTER_MOVE, cb, false); | |
| 7302 | + break; | |
| 7303 | + case 'touchend': | |
| 7304 | + obj.removeEventListener(this.POINTER_UP, cb, false); | |
| 7305 | + obj.removeEventListener(this.POINTER_CANCEL, cb, false); | |
| 7306 | + break; | |
| 7307 | + } | |
| 7308 | + | |
| 7309 | + return this; | |
| 7310 | + } | |
| 7311 | +}); | |
| 7312 | + | |
| 7313 | + | |
| 7314 | +/* | |
| 7315 | + * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers. | |
| 7316 | + */ | |
| 7317 | + | |
| 7318 | +L.Map.mergeOptions({ | |
| 7319 | + touchZoom: L.Browser.touch && !L.Browser.android23, | |
| 7320 | + bounceAtZoomLimits: true | |
| 7321 | +}); | |
| 7322 | + | |
| 7323 | +L.Map.TouchZoom = L.Handler.extend({ | |
| 7324 | + addHooks: function () { | |
| 7325 | + L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this); | |
| 7326 | + }, | |
| 7327 | + | |
| 7328 | + removeHooks: function () { | |
| 7329 | + L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this); | |
| 7330 | + }, | |
| 7331 | + | |
| 7332 | + _onTouchStart: function (e) { | |
| 7333 | + var map = this._map; | |
| 7334 | + | |
| 7335 | + if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } | |
| 7336 | + | |
| 7337 | + var p1 = map.mouseEventToLayerPoint(e.touches[0]), | |
| 7338 | + p2 = map.mouseEventToLayerPoint(e.touches[1]), | |
| 7339 | + viewCenter = map._getCenterLayerPoint(); | |
| 7340 | + | |
| 7341 | + this._startCenter = p1.add(p2)._divideBy(2); | |
| 7342 | + this._startDist = p1.distanceTo(p2); | |
| 7343 | + | |
| 7344 | + this._moved = false; | |
| 7345 | + this._zooming = true; | |
| 7346 | + | |
| 7347 | + this._centerOffset = viewCenter.subtract(this._startCenter); | |
| 7348 | + | |
| 7349 | + if (map._panAnim) { | |
| 7350 | + map._panAnim.stop(); | |
| 7351 | + } | |
| 7352 | + | |
| 7353 | + L.DomEvent | |
| 7354 | + .on(document, 'touchmove', this._onTouchMove, this) | |
| 7355 | + .on(document, 'touchend', this._onTouchEnd, this); | |
| 7356 | + | |
| 7357 | + L.DomEvent.preventDefault(e); | |
| 7358 | + }, | |
| 7359 | + | |
| 7360 | + _onTouchMove: function (e) { | |
| 7361 | + var map = this._map; | |
| 7362 | + | |
| 7363 | + if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } | |
| 7364 | + | |
| 7365 | + var p1 = map.mouseEventToLayerPoint(e.touches[0]), | |
| 7366 | + p2 = map.mouseEventToLayerPoint(e.touches[1]); | |
| 7367 | + | |
| 7368 | + this._scale = p1.distanceTo(p2) / this._startDist; | |
| 7369 | + this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter); | |
| 7370 | + | |
| 7371 | + if (this._scale === 1) { return; } | |
| 7372 | + | |
| 7373 | + if (!map.options.bounceAtZoomLimits) { | |
| 7374 | + if ((map.getZoom() === map.getMinZoom() && this._scale < 1) || | |
| 7375 | + (map.getZoom() === map.getMaxZoom() && this._scale > 1)) { return; } | |
| 7376 | + } | |
| 7377 | + | |
| 7378 | + if (!this._moved) { | |
| 7379 | + L.DomUtil.addClass(map._mapPane, 'leaflet-touching'); | |
| 7380 | + | |
| 7381 | + map | |
| 7382 | + .fire('movestart') | |
| 7383 | + .fire('zoomstart'); | |
| 7384 | + | |
| 7385 | + this._moved = true; | |
| 7386 | + } | |
| 7387 | + | |
| 7388 | + L.Util.cancelAnimFrame(this._animRequest); | |
| 7389 | + this._animRequest = L.Util.requestAnimFrame( | |
| 7390 | + this._updateOnMove, this, true, this._map._container); | |
| 7391 | + | |
| 7392 | + L.DomEvent.preventDefault(e); | |
| 7393 | + }, | |
| 7394 | + | |
| 7395 | + _updateOnMove: function () { | |
| 7396 | + var map = this._map, | |
| 7397 | + origin = this._getScaleOrigin(), | |
| 7398 | + center = map.layerPointToLatLng(origin), | |
| 7399 | + zoom = map.getScaleZoom(this._scale); | |
| 7400 | + | |
| 7401 | + map._animateZoom(center, zoom, this._startCenter, this._scale, this._delta, false, true); | |
| 7402 | + }, | |
| 7403 | + | |
| 7404 | + _onTouchEnd: function () { | |
| 7405 | + if (!this._moved || !this._zooming) { | |
| 7406 | + this._zooming = false; | |
| 7407 | + return; | |
| 7408 | + } | |
| 7409 | + | |
| 7410 | + var map = this._map; | |
| 7411 | + | |
| 7412 | + this._zooming = false; | |
| 7413 | + L.DomUtil.removeClass(map._mapPane, 'leaflet-touching'); | |
| 7414 | + L.Util.cancelAnimFrame(this._animRequest); | |
| 7415 | + | |
| 7416 | + L.DomEvent | |
| 7417 | + .off(document, 'touchmove', this._onTouchMove) | |
| 7418 | + .off(document, 'touchend', this._onTouchEnd); | |
| 7419 | + | |
| 7420 | + var origin = this._getScaleOrigin(), | |
| 7421 | + center = map.layerPointToLatLng(origin), | |
| 7422 | + | |
| 7423 | + oldZoom = map.getZoom(), | |
| 7424 | + floatZoomDelta = map.getScaleZoom(this._scale) - oldZoom, | |
| 7425 | + roundZoomDelta = (floatZoomDelta > 0 ? | |
| 7426 | + Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)), | |
| 7427 | + | |
| 7428 | + zoom = map._limitZoom(oldZoom + roundZoomDelta), | |
| 7429 | + scale = map.getZoomScale(zoom) / this._scale; | |
| 7430 | + | |
| 7431 | + map._animateZoom(center, zoom, origin, scale); | |
| 7432 | + }, | |
| 7433 | + | |
| 7434 | + _getScaleOrigin: function () { | |
| 7435 | + var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale); | |
| 7436 | + return this._startCenter.add(centerOffset); | |
| 7437 | + } | |
| 7438 | +}); | |
| 7439 | + | |
| 7440 | +L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom); | |
| 7441 | + | |
| 7442 | + | |
| 7443 | +/* | |
| 7444 | + * L.Map.Tap is used to enable mobile hacks like quick taps and long hold. | |
| 7445 | + */ | |
| 7446 | + | |
| 7447 | +L.Map.mergeOptions({ | |
| 7448 | + tap: true, | |
| 7449 | + tapTolerance: 15 | |
| 7450 | +}); | |
| 7451 | + | |
| 7452 | +L.Map.Tap = L.Handler.extend({ | |
| 7453 | + addHooks: function () { | |
| 7454 | + L.DomEvent.on(this._map._container, 'touchstart', this._onDown, this); | |
| 7455 | + }, | |
| 7456 | + | |
| 7457 | + removeHooks: function () { | |
| 7458 | + L.DomEvent.off(this._map._container, 'touchstart', this._onDown, this); | |
| 7459 | + }, | |
| 7460 | + | |
| 7461 | + _onDown: function (e) { | |
| 7462 | + if (!e.touches) { return; } | |
| 7463 | + | |
| 7464 | + L.DomEvent.preventDefault(e); | |
| 7465 | + | |
| 7466 | + this._fireClick = true; | |
| 7467 | + | |
| 7468 | + // don't simulate click or track longpress if more than 1 touch | |
| 7469 | + if (e.touches.length > 1) { | |
| 7470 | + this._fireClick = false; | |
| 7471 | + clearTimeout(this._holdTimeout); | |
| 7472 | + return; | |
| 7473 | + } | |
| 7474 | + | |
| 7475 | + var first = e.touches[0], | |
| 7476 | + el = first.target; | |
| 7477 | + | |
| 7478 | + this._startPos = this._newPos = new L.Point(first.clientX, first.clientY); | |
| 7479 | + | |
| 7480 | + // if touching a link, highlight it | |
| 7481 | + if (el.tagName && el.tagName.toLowerCase() === 'a') { | |
| 7482 | + L.DomUtil.addClass(el, 'leaflet-active'); | |
| 7483 | + } | |
| 7484 | + | |
| 7485 | + // simulate long hold but setting a timeout | |
| 7486 | + this._holdTimeout = setTimeout(L.bind(function () { | |
| 7487 | + if (this._isTapValid()) { | |
| 7488 | + this._fireClick = false; | |
| 7489 | + this._onUp(); | |
| 7490 | + this._simulateEvent('contextmenu', first); | |
| 7491 | + } | |
| 7492 | + }, this), 1000); | |
| 7493 | + | |
| 7494 | + L.DomEvent | |
| 7495 | + .on(document, 'touchmove', this._onMove, this) | |
| 7496 | + .on(document, 'touchend', this._onUp, this); | |
| 7497 | + }, | |
| 7498 | + | |
| 7499 | + _onUp: function (e) { | |
| 7500 | + clearTimeout(this._holdTimeout); | |
| 7501 | + | |
| 7502 | + L.DomEvent | |
| 7503 | + .off(document, 'touchmove', this._onMove, this) | |
| 7504 | + .off(document, 'touchend', this._onUp, this); | |
| 7505 | + | |
| 7506 | + if (this._fireClick && e && e.changedTouches) { | |
| 7507 | + | |
| 7508 | + var first = e.changedTouches[0], | |
| 7509 | + el = first.target; | |
| 7510 | + | |
| 7511 | + if (el && el.tagName && el.tagName.toLowerCase() === 'a') { | |
| 7512 | + L.DomUtil.removeClass(el, 'leaflet-active'); | |
| 7513 | + } | |
| 7514 | + | |
| 7515 | + // simulate click if the touch didn't move too much | |
| 7516 | + if (this._isTapValid()) { | |
| 7517 | + this._simulateEvent('click', first); | |
| 7518 | + } | |
| 7519 | + } | |
| 7520 | + }, | |
| 7521 | + | |
| 7522 | + _isTapValid: function () { | |
| 7523 | + return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance; | |
| 7524 | + }, | |
| 7525 | + | |
| 7526 | + _onMove: function (e) { | |
| 7527 | + var first = e.touches[0]; | |
| 7528 | + this._newPos = new L.Point(first.clientX, first.clientY); | |
| 7529 | + }, | |
| 7530 | + | |
| 7531 | + _simulateEvent: function (type, e) { | |
| 7532 | + var simulatedEvent = document.createEvent('MouseEvents'); | |
| 7533 | + | |
| 7534 | + simulatedEvent._simulated = true; | |
| 7535 | + e.target._simulatedClick = true; | |
| 7536 | + | |
| 7537 | + simulatedEvent.initMouseEvent( | |
| 7538 | + type, true, true, window, 1, | |
| 7539 | + e.screenX, e.screenY, | |
| 7540 | + e.clientX, e.clientY, | |
| 7541 | + false, false, false, false, 0, null); | |
| 7542 | + | |
| 7543 | + e.target.dispatchEvent(simulatedEvent); | |
| 7544 | + } | |
| 7545 | +}); | |
| 7546 | + | |
| 7547 | +if (L.Browser.touch && !L.Browser.pointer) { | |
| 7548 | + L.Map.addInitHook('addHandler', 'tap', L.Map.Tap); | |
| 7549 | +} | |
| 7550 | + | |
| 7551 | + | |
| 7552 | +/* | |
| 7553 | + * L.Handler.ShiftDragZoom is used to add shift-drag zoom interaction to the map | |
| 7554 | + * (zoom to a selected bounding box), enabled by default. | |
| 7555 | + */ | |
| 7556 | + | |
| 7557 | +L.Map.mergeOptions({ | |
| 7558 | + boxZoom: true | |
| 7559 | +}); | |
| 7560 | + | |
| 7561 | +L.Map.BoxZoom = L.Handler.extend({ | |
| 7562 | + initialize: function (map) { | |
| 7563 | + this._map = map; | |
| 7564 | + this._container = map._container; | |
| 7565 | + this._pane = map._panes.overlayPane; | |
| 7566 | + this._moved = false; | |
| 7567 | + }, | |
| 7568 | + | |
| 7569 | + addHooks: function () { | |
| 7570 | + L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this); | |
| 7571 | + }, | |
| 7572 | + | |
| 7573 | + removeHooks: function () { | |
| 7574 | + L.DomEvent.off(this._container, 'mousedown', this._onMouseDown); | |
| 7575 | + this._moved = false; | |
| 7576 | + }, | |
| 7577 | + | |
| 7578 | + moved: function () { | |
| 7579 | + return this._moved; | |
| 7580 | + }, | |
| 7581 | + | |
| 7582 | + _onMouseDown: function (e) { | |
| 7583 | + this._moved = false; | |
| 7584 | + | |
| 7585 | + if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; } | |
| 7586 | + | |
| 7587 | + L.DomUtil.disableTextSelection(); | |
| 7588 | + L.DomUtil.disableImageDrag(); | |
| 7589 | + | |
| 7590 | + this._startLayerPoint = this._map.mouseEventToLayerPoint(e); | |
| 7591 | + | |
| 7592 | + L.DomEvent | |
| 7593 | + .on(document, 'mousemove', this._onMouseMove, this) | |
| 7594 | + .on(document, 'mouseup', this._onMouseUp, this) | |
| 7595 | + .on(document, 'keydown', this._onKeyDown, this); | |
| 7596 | + }, | |
| 7597 | + | |
| 7598 | + _onMouseMove: function (e) { | |
| 7599 | + if (!this._moved) { | |
| 7600 | + this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane); | |
| 7601 | + L.DomUtil.setPosition(this._box, this._startLayerPoint); | |
| 7602 | + | |
| 7603 | + //TODO refactor: move cursor to styles | |
| 7604 | + this._container.style.cursor = 'crosshair'; | |
| 7605 | + this._map.fire('boxzoomstart'); | |
| 7606 | + } | |
| 7607 | + | |
| 7608 | + var startPoint = this._startLayerPoint, | |
| 7609 | + box = this._box, | |
| 7610 | + | |
| 7611 | + layerPoint = this._map.mouseEventToLayerPoint(e), | |
| 7612 | + offset = layerPoint.subtract(startPoint), | |
| 7613 | + | |
| 7614 | + newPos = new L.Point( | |
| 7615 | + Math.min(layerPoint.x, startPoint.x), | |
| 7616 | + Math.min(layerPoint.y, startPoint.y)); | |
| 7617 | + | |
| 7618 | + L.DomUtil.setPosition(box, newPos); | |
| 7619 | + | |
| 7620 | + this._moved = true; | |
| 7621 | + | |
| 7622 | + // TODO refactor: remove hardcoded 4 pixels | |
| 7623 | + box.style.width = (Math.max(0, Math.abs(offset.x) - 4)) + 'px'; | |
| 7624 | + box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px'; | |
| 7625 | + }, | |
| 7626 | + | |
| 7627 | + _finish: function () { | |
| 7628 | + if (this._moved) { | |
| 7629 | + this._pane.removeChild(this._box); | |
| 7630 | + this._container.style.cursor = ''; | |
| 7631 | + } | |
| 7632 | + | |
| 7633 | + L.DomUtil.enableTextSelection(); | |
| 7634 | + L.DomUtil.enableImageDrag(); | |
| 7635 | + | |
| 7636 | + L.DomEvent | |
| 7637 | + .off(document, 'mousemove', this._onMouseMove) | |
| 7638 | + .off(document, 'mouseup', this._onMouseUp) | |
| 7639 | + .off(document, 'keydown', this._onKeyDown); | |
| 7640 | + }, | |
| 7641 | + | |
| 7642 | + _onMouseUp: function (e) { | |
| 7643 | + | |
| 7644 | + this._finish(); | |
| 7645 | + | |
| 7646 | + var map = this._map, | |
| 7647 | + layerPoint = map.mouseEventToLayerPoint(e); | |
| 7648 | + | |
| 7649 | + if (this._startLayerPoint.equals(layerPoint)) { return; } | |
| 7650 | + | |
| 7651 | + var bounds = new L.LatLngBounds( | |
| 7652 | + map.layerPointToLatLng(this._startLayerPoint), | |
| 7653 | + map.layerPointToLatLng(layerPoint)); | |
| 7654 | + | |
| 7655 | + map.fitBounds(bounds); | |
| 7656 | + | |
| 7657 | + map.fire('boxzoomend', { | |
| 7658 | + boxZoomBounds: bounds | |
| 7659 | + }); | |
| 7660 | + }, | |
| 7661 | + | |
| 7662 | + _onKeyDown: function (e) { | |
| 7663 | + if (e.keyCode === 27) { | |
| 7664 | + this._finish(); | |
| 7665 | + } | |
| 7666 | + } | |
| 7667 | +}); | |
| 7668 | + | |
| 7669 | +L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom); | |
| 7670 | + | |
| 7671 | + | |
| 7672 | +/* | |
| 7673 | + * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default. | |
| 7674 | + */ | |
| 7675 | + | |
| 7676 | +L.Map.mergeOptions({ | |
| 7677 | + keyboard: true, | |
| 7678 | + keyboardPanOffset: 80, | |
| 7679 | + keyboardZoomOffset: 1 | |
| 7680 | +}); | |
| 7681 | + | |
| 7682 | +L.Map.Keyboard = L.Handler.extend({ | |
| 7683 | + | |
| 7684 | + keyCodes: { | |
| 7685 | + left: [37], | |
| 7686 | + right: [39], | |
| 7687 | + down: [40], | |
| 7688 | + up: [38], | |
| 7689 | + zoomIn: [187, 107, 61, 171], | |
| 7690 | + zoomOut: [189, 109, 173] | |
| 7691 | + }, | |
| 7692 | + | |
| 7693 | + initialize: function (map) { | |
| 7694 | + this._map = map; | |
| 7695 | + | |
| 7696 | + this._setPanOffset(map.options.keyboardPanOffset); | |
| 7697 | + this._setZoomOffset(map.options.keyboardZoomOffset); | |
| 7698 | + }, | |
| 7699 | + | |
| 7700 | + addHooks: function () { | |
| 7701 | + var container = this._map._container; | |
| 7702 | + | |
| 7703 | + // make the container focusable by tabbing | |
| 7704 | + if (container.tabIndex === -1) { | |
| 7705 | + container.tabIndex = '0'; | |
| 7706 | + } | |
| 7707 | + | |
| 7708 | + L.DomEvent | |
| 7709 | + .on(container, 'focus', this._onFocus, this) | |
| 7710 | + .on(container, 'blur', this._onBlur, this) | |
| 7711 | + .on(container, 'mousedown', this._onMouseDown, this); | |
| 7712 | + | |
| 7713 | + this._map | |
| 7714 | + .on('focus', this._addHooks, this) | |
| 7715 | + .on('blur', this._removeHooks, this); | |
| 7716 | + }, | |
| 7717 | + | |
| 7718 | + removeHooks: function () { | |
| 7719 | + this._removeHooks(); | |
| 7720 | + | |
| 7721 | + var container = this._map._container; | |
| 7722 | + | |
| 7723 | + L.DomEvent | |
| 7724 | + .off(container, 'focus', this._onFocus, this) | |
| 7725 | + .off(container, 'blur', this._onBlur, this) | |
| 7726 | + .off(container, 'mousedown', this._onMouseDown, this); | |
| 7727 | + | |
| 7728 | + this._map | |
| 7729 | + .off('focus', this._addHooks, this) | |
| 7730 | + .off('blur', this._removeHooks, this); | |
| 7731 | + }, | |
| 7732 | + | |
| 7733 | + _onMouseDown: function () { | |
| 7734 | + if (this._focused) { return; } | |
| 7735 | + | |
| 7736 | + var body = document.body, | |
| 7737 | + docEl = document.documentElement, | |
| 7738 | + top = body.scrollTop || docEl.scrollTop, | |
| 7739 | + left = body.scrollLeft || docEl.scrollLeft; | |
| 7740 | + | |
| 7741 | + this._map._container.focus(); | |
| 7742 | + | |
| 7743 | + window.scrollTo(left, top); | |
| 7744 | + }, | |
| 7745 | + | |
| 7746 | + _onFocus: function () { | |
| 7747 | + this._focused = true; | |
| 7748 | + this._map.fire('focus'); | |
| 7749 | + }, | |
| 7750 | + | |
| 7751 | + _onBlur: function () { | |
| 7752 | + this._focused = false; | |
| 7753 | + this._map.fire('blur'); | |
| 7754 | + }, | |
| 7755 | + | |
| 7756 | + _setPanOffset: function (pan) { | |
| 7757 | + var keys = this._panKeys = {}, | |
| 7758 | + codes = this.keyCodes, | |
| 7759 | + i, len; | |
| 7760 | + | |
| 7761 | + for (i = 0, len = codes.left.length; i < len; i++) { | |
| 7762 | + keys[codes.left[i]] = [-1 * pan, 0]; | |
| 7763 | + } | |
| 7764 | + for (i = 0, len = codes.right.length; i < len; i++) { | |
| 7765 | + keys[codes.right[i]] = [pan, 0]; | |
| 7766 | + } | |
| 7767 | + for (i = 0, len = codes.down.length; i < len; i++) { | |
| 7768 | + keys[codes.down[i]] = [0, pan]; | |
| 7769 | + } | |
| 7770 | + for (i = 0, len = codes.up.length; i < len; i++) { | |
| 7771 | + keys[codes.up[i]] = [0, -1 * pan]; | |
| 7772 | + } | |
| 7773 | + }, | |
| 7774 | + | |
| 7775 | + _setZoomOffset: function (zoom) { | |
| 7776 | + var keys = this._zoomKeys = {}, | |
| 7777 | + codes = this.keyCodes, | |
| 7778 | + i, len; | |
| 7779 | + | |
| 7780 | + for (i = 0, len = codes.zoomIn.length; i < len; i++) { | |
| 7781 | + keys[codes.zoomIn[i]] = zoom; | |
| 7782 | + } | |
| 7783 | + for (i = 0, len = codes.zoomOut.length; i < len; i++) { | |
| 7784 | + keys[codes.zoomOut[i]] = -zoom; | |
| 7785 | + } | |
| 7786 | + }, | |
| 7787 | + | |
| 7788 | + _addHooks: function () { | |
| 7789 | + L.DomEvent.on(document, 'keydown', this._onKeyDown, this); | |
| 7790 | + }, | |
| 7791 | + | |
| 7792 | + _removeHooks: function () { | |
| 7793 | + L.DomEvent.off(document, 'keydown', this._onKeyDown, this); | |
| 7794 | + }, | |
| 7795 | + | |
| 7796 | + _onKeyDown: function (e) { | |
| 7797 | + var key = e.keyCode, | |
| 7798 | + map = this._map; | |
| 7799 | + | |
| 7800 | + if (key in this._panKeys) { | |
| 7801 | + | |
| 7802 | + if (map._panAnim && map._panAnim._inProgress) { return; } | |
| 7803 | + | |
| 7804 | + map.panBy(this._panKeys[key]); | |
| 7805 | + | |
| 7806 | + if (map.options.maxBounds) { | |
| 7807 | + map.panInsideBounds(map.options.maxBounds); | |
| 7808 | + } | |
| 7809 | + | |
| 7810 | + } else if (key in this._zoomKeys) { | |
| 7811 | + map.setZoom(map.getZoom() + this._zoomKeys[key]); | |
| 7812 | + | |
| 7813 | + } else { | |
| 7814 | + return; | |
| 7815 | + } | |
| 7816 | + | |
| 7817 | + L.DomEvent.stop(e); | |
| 7818 | + } | |
| 7819 | +}); | |
| 7820 | + | |
| 7821 | +L.Map.addInitHook('addHandler', 'keyboard', L.Map.Keyboard); | |
| 7822 | + | |
| 7823 | + | |
| 7824 | +/* | |
| 7825 | + * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. | |
| 7826 | + */ | |
| 7827 | + | |
| 7828 | +L.Handler.MarkerDrag = L.Handler.extend({ | |
| 7829 | + initialize: function (marker) { | |
| 7830 | + this._marker = marker; | |
| 7831 | + }, | |
| 7832 | + | |
| 7833 | + addHooks: function () { | |
| 7834 | + var icon = this._marker._icon; | |
| 7835 | + if (!this._draggable) { | |
| 7836 | + this._draggable = new L.Draggable(icon, icon); | |
| 7837 | + } | |
| 7838 | + | |
| 7839 | + this._draggable | |
| 7840 | + .on('dragstart', this._onDragStart, this) | |
| 7841 | + .on('drag', this._onDrag, this) | |
| 7842 | + .on('dragend', this._onDragEnd, this); | |
| 7843 | + this._draggable.enable(); | |
| 7844 | + L.DomUtil.addClass(this._marker._icon, 'leaflet-marker-draggable'); | |
| 7845 | + }, | |
| 7846 | + | |
| 7847 | + removeHooks: function () { | |
| 7848 | + this._draggable | |
| 7849 | + .off('dragstart', this._onDragStart, this) | |
| 7850 | + .off('drag', this._onDrag, this) | |
| 7851 | + .off('dragend', this._onDragEnd, this); | |
| 7852 | + | |
| 7853 | + this._draggable.disable(); | |
| 7854 | + L.DomUtil.removeClass(this._marker._icon, 'leaflet-marker-draggable'); | |
| 7855 | + }, | |
| 7856 | + | |
| 7857 | + moved: function () { | |
| 7858 | + return this._draggable && this._draggable._moved; | |
| 7859 | + }, | |
| 7860 | + | |
| 7861 | + _onDragStart: function () { | |
| 7862 | + this._marker | |
| 7863 | + .closePopup() | |
| 7864 | + .fire('movestart') | |
| 7865 | + .fire('dragstart'); | |
| 7866 | + }, | |
| 7867 | + | |
| 7868 | + _onDrag: function () { | |
| 7869 | + var marker = this._marker, | |
| 7870 | + shadow = marker._shadow, | |
| 7871 | + iconPos = L.DomUtil.getPosition(marker._icon), | |
| 7872 | + latlng = marker._map.layerPointToLatLng(iconPos); | |
| 7873 | + | |
| 7874 | + // update shadow position | |
| 7875 | + if (shadow) { | |
| 7876 | + L.DomUtil.setPosition(shadow, iconPos); | |
| 7877 | + } | |
| 7878 | + | |
| 7879 | + marker._latlng = latlng; | |
| 7880 | + | |
| 7881 | + marker | |
| 7882 | + .fire('move', {latlng: latlng}) | |
| 7883 | + .fire('drag'); | |
| 7884 | + }, | |
| 7885 | + | |
| 7886 | + _onDragEnd: function (e) { | |
| 7887 | + this._marker | |
| 7888 | + .fire('moveend') | |
| 7889 | + .fire('dragend', e); | |
| 7890 | + } | |
| 7891 | +}); | |
| 7892 | + | |
| 7893 | + | |
| 7894 | +/* | |
| 7895 | + * L.Control is a base class for implementing map controls. Handles positioning. | |
| 7896 | + * All other controls extend from this class. | |
| 7897 | + */ | |
| 7898 | + | |
| 7899 | +L.Control = L.Class.extend({ | |
| 7900 | + options: { | |
| 7901 | + position: 'topright' | |
| 7902 | + }, | |
| 7903 | + | |
| 7904 | + initialize: function (options) { | |
| 7905 | + L.setOptions(this, options); | |
| 7906 | + }, | |
| 7907 | + | |
| 7908 | + getPosition: function () { | |
| 7909 | + return this.options.position; | |
| 7910 | + }, | |
| 7911 | + | |
| 7912 | + setPosition: function (position) { | |
| 7913 | + var map = this._map; | |
| 7914 | + | |
| 7915 | + if (map) { | |
| 7916 | + map.removeControl(this); | |
| 7917 | + } | |
| 7918 | + | |
| 7919 | + this.options.position = position; | |
| 7920 | + | |
| 7921 | + if (map) { | |
| 7922 | + map.addControl(this); | |
| 7923 | + } | |
| 7924 | + | |
| 7925 | + return this; | |
| 7926 | + }, | |
| 7927 | + | |
| 7928 | + getContainer: function () { | |
| 7929 | + return this._container; | |
| 7930 | + }, | |
| 7931 | + | |
| 7932 | + addTo: function (map) { | |
| 7933 | + this._map = map; | |
| 7934 | + | |
| 7935 | + var container = this._container = this.onAdd(map), | |
| 7936 | + pos = this.getPosition(), | |
| 7937 | + corner = map._controlCorners[pos]; | |
| 7938 | + | |
| 7939 | + L.DomUtil.addClass(container, 'leaflet-control'); | |
| 7940 | + | |
| 7941 | + if (pos.indexOf('bottom') !== -1) { | |
| 7942 | + corner.insertBefore(container, corner.firstChild); | |
| 7943 | + } else { | |
| 7944 | + corner.appendChild(container); | |
| 7945 | + } | |
| 7946 | + | |
| 7947 | + return this; | |
| 7948 | + }, | |
| 7949 | + | |
| 7950 | + removeFrom: function (map) { | |
| 7951 | + var pos = this.getPosition(), | |
| 7952 | + corner = map._controlCorners[pos]; | |
| 7953 | + | |
| 7954 | + corner.removeChild(this._container); | |
| 7955 | + this._map = null; | |
| 7956 | + | |
| 7957 | + if (this.onRemove) { | |
| 7958 | + this.onRemove(map); | |
| 7959 | + } | |
| 7960 | + | |
| 7961 | + return this; | |
| 7962 | + }, | |
| 7963 | + | |
| 7964 | + _refocusOnMap: function () { | |
| 7965 | + if (this._map) { | |
| 7966 | + this._map.getContainer().focus(); | |
| 7967 | + } | |
| 7968 | + } | |
| 7969 | +}); | |
| 7970 | + | |
| 7971 | +L.control = function (options) { | |
| 7972 | + return new L.Control(options); | |
| 7973 | +}; | |
| 7974 | + | |
| 7975 | + | |
| 7976 | +// adds control-related methods to L.Map | |
| 7977 | + | |
| 7978 | +L.Map.include({ | |
| 7979 | + addControl: function (control) { | |
| 7980 | + control.addTo(this); | |
| 7981 | + return this; | |
| 7982 | + }, | |
| 7983 | + | |
| 7984 | + removeControl: function (control) { | |
| 7985 | + control.removeFrom(this); | |
| 7986 | + return this; | |
| 7987 | + }, | |
| 7988 | + | |
| 7989 | + _initControlPos: function () { | |
| 7990 | + var corners = this._controlCorners = {}, | |
| 7991 | + l = 'leaflet-', | |
| 7992 | + container = this._controlContainer = | |
| 7993 | + L.DomUtil.create('div', l + 'control-container', this._container); | |
| 7994 | + | |
| 7995 | + function createCorner(vSide, hSide) { | |
| 7996 | + var className = l + vSide + ' ' + l + hSide; | |
| 7997 | + | |
| 7998 | + corners[vSide + hSide] = L.DomUtil.create('div', className, container); | |
| 7999 | + } | |
| 8000 | + | |
| 8001 | + createCorner('top', 'left'); | |
| 8002 | + createCorner('top', 'right'); | |
| 8003 | + createCorner('bottom', 'left'); | |
| 8004 | + createCorner('bottom', 'right'); | |
| 8005 | + }, | |
| 8006 | + | |
| 8007 | + _clearControlPos: function () { | |
| 8008 | + this._container.removeChild(this._controlContainer); | |
| 8009 | + } | |
| 8010 | +}); | |
| 8011 | + | |
| 8012 | + | |
| 8013 | +/* | |
| 8014 | + * L.Control.Zoom is used for the default zoom buttons on the map. | |
| 8015 | + */ | |
| 8016 | + | |
| 8017 | +L.Control.Zoom = L.Control.extend({ | |
| 8018 | + options: { | |
| 8019 | + position: 'topleft', | |
| 8020 | + zoomInText: '+', | |
| 8021 | + zoomInTitle: 'Zoom in', | |
| 8022 | + zoomOutText: '-', | |
| 8023 | + zoomOutTitle: 'Zoom out' | |
| 8024 | + }, | |
| 8025 | + | |
| 8026 | + onAdd: function (map) { | |
| 8027 | + var zoomName = 'leaflet-control-zoom', | |
| 8028 | + container = L.DomUtil.create('div', zoomName + ' leaflet-bar'); | |
| 8029 | + | |
| 8030 | + this._map = map; | |
| 8031 | + | |
| 8032 | + this._zoomInButton = this._createButton( | |
| 8033 | + this.options.zoomInText, this.options.zoomInTitle, | |
| 8034 | + zoomName + '-in', container, this._zoomIn, this); | |
| 8035 | + this._zoomOutButton = this._createButton( | |
| 8036 | + this.options.zoomOutText, this.options.zoomOutTitle, | |
| 8037 | + zoomName + '-out', container, this._zoomOut, this); | |
| 8038 | + | |
| 8039 | + this._updateDisabled(); | |
| 8040 | + map.on('zoomend zoomlevelschange', this._updateDisabled, this); | |
| 8041 | + | |
| 8042 | + return container; | |
| 8043 | + }, | |
| 8044 | + | |
| 8045 | + onRemove: function (map) { | |
| 8046 | + map.off('zoomend zoomlevelschange', this._updateDisabled, this); | |
| 8047 | + }, | |
| 8048 | + | |
| 8049 | + _zoomIn: function (e) { | |
| 8050 | + this._map.zoomIn(e.shiftKey ? 3 : 1); | |
| 8051 | + }, | |
| 8052 | + | |
| 8053 | + _zoomOut: function (e) { | |
| 8054 | + this._map.zoomOut(e.shiftKey ? 3 : 1); | |
| 8055 | + }, | |
| 8056 | + | |
| 8057 | + _createButton: function (html, title, className, container, fn, context) { | |
| 8058 | + var link = L.DomUtil.create('a', className, container); | |
| 8059 | + link.innerHTML = html; | |
| 8060 | + link.href = '#'; | |
| 8061 | + link.title = title; | |
| 8062 | + | |
| 8063 | + var stop = L.DomEvent.stopPropagation; | |
| 8064 | + | |
| 8065 | + L.DomEvent | |
| 8066 | + .on(link, 'click', stop) | |
| 8067 | + .on(link, 'mousedown', stop) | |
| 8068 | + .on(link, 'dblclick', stop) | |
| 8069 | + .on(link, 'click', L.DomEvent.preventDefault) | |
| 8070 | + .on(link, 'click', fn, context) | |
| 8071 | + .on(link, 'click', this._refocusOnMap, context); | |
| 8072 | + | |
| 8073 | + return link; | |
| 8074 | + }, | |
| 8075 | + | |
| 8076 | + _updateDisabled: function () { | |
| 8077 | + var map = this._map, | |
| 8078 | + className = 'leaflet-disabled'; | |
| 8079 | + | |
| 8080 | + L.DomUtil.removeClass(this._zoomInButton, className); | |
| 8081 | + L.DomUtil.removeClass(this._zoomOutButton, className); | |
| 8082 | + | |
| 8083 | + if (map._zoom === map.getMinZoom()) { | |
| 8084 | + L.DomUtil.addClass(this._zoomOutButton, className); | |
| 8085 | + } | |
| 8086 | + if (map._zoom === map.getMaxZoom()) { | |
| 8087 | + L.DomUtil.addClass(this._zoomInButton, className); | |
| 8088 | + } | |
| 8089 | + } | |
| 8090 | +}); | |
| 8091 | + | |
| 8092 | +L.Map.mergeOptions({ | |
| 8093 | + zoomControl: true | |
| 8094 | +}); | |
| 8095 | + | |
| 8096 | +L.Map.addInitHook(function () { | |
| 8097 | + if (this.options.zoomControl) { | |
| 8098 | + this.zoomControl = new L.Control.Zoom(); | |
| 8099 | + this.addControl(this.zoomControl); | |
| 8100 | + } | |
| 8101 | +}); | |
| 8102 | + | |
| 8103 | +L.control.zoom = function (options) { | |
| 8104 | + return new L.Control.Zoom(options); | |
| 8105 | +}; | |
| 8106 | + | |
| 8107 | + | |
| 8108 | + | |
| 8109 | +/* | |
| 8110 | + * L.Control.Attribution is used for displaying attribution on the map (added by default). | |
| 8111 | + */ | |
| 8112 | + | |
| 8113 | +L.Control.Attribution = L.Control.extend({ | |
| 8114 | + options: { | |
| 8115 | + position: 'bottomright', | |
| 8116 | + prefix: '<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>' | |
| 8117 | + }, | |
| 8118 | + | |
| 8119 | + initialize: function (options) { | |
| 8120 | + L.setOptions(this, options); | |
| 8121 | + | |
| 8122 | + this._attributions = {}; | |
| 8123 | + }, | |
| 8124 | + | |
| 8125 | + onAdd: function (map) { | |
| 8126 | + this._container = L.DomUtil.create('div', 'leaflet-control-attribution'); | |
| 8127 | + L.DomEvent.disableClickPropagation(this._container); | |
| 8128 | + | |
| 8129 | + for (var i in map._layers) { | |
| 8130 | + if (map._layers[i].getAttribution) { | |
| 8131 | + this.addAttribution(map._layers[i].getAttribution()); | |
| 8132 | + } | |
| 8133 | + } | |
| 8134 | + | |
| 8135 | + map | |
| 8136 | + .on('layeradd', this._onLayerAdd, this) | |
| 8137 | + .on('layerremove', this._onLayerRemove, this); | |
| 8138 | + | |
| 8139 | + this._update(); | |
| 8140 | + | |
| 8141 | + return this._container; | |
| 8142 | + }, | |
| 8143 | + | |
| 8144 | + onRemove: function (map) { | |
| 8145 | + map | |
| 8146 | + .off('layeradd', this._onLayerAdd) | |
| 8147 | + .off('layerremove', this._onLayerRemove); | |
| 8148 | + | |
| 8149 | + }, | |
| 8150 | + | |
| 8151 | + setPrefix: function (prefix) { | |
| 8152 | + this.options.prefix = prefix; | |
| 8153 | + this._update(); | |
| 8154 | + return this; | |
| 8155 | + }, | |
| 8156 | + | |
| 8157 | + addAttribution: function (text) { | |
| 8158 | + if (!text) { return; } | |
| 8159 | + | |
| 8160 | + if (!this._attributions[text]) { | |
| 8161 | + this._attributions[text] = 0; | |
| 8162 | + } | |
| 8163 | + this._attributions[text]++; | |
| 8164 | + | |
| 8165 | + this._update(); | |
| 8166 | + | |
| 8167 | + return this; | |
| 8168 | + }, | |
| 8169 | + | |
| 8170 | + removeAttribution: function (text) { | |
| 8171 | + if (!text) { return; } | |
| 8172 | + | |
| 8173 | + if (this._attributions[text]) { | |
| 8174 | + this._attributions[text]--; | |
| 8175 | + this._update(); | |
| 8176 | + } | |
| 8177 | + | |
| 8178 | + return this; | |
| 8179 | + }, | |
| 8180 | + | |
| 8181 | + _update: function () { | |
| 8182 | + if (!this._map) { return; } | |
| 8183 | + | |
| 8184 | + var attribs = []; | |
| 8185 | + | |
| 8186 | + for (var i in this._attributions) { | |
| 8187 | + if (this._attributions[i]) { | |
| 8188 | + attribs.push(i); | |
| 8189 | + } | |
| 8190 | + } | |
| 8191 | + | |
| 8192 | + var prefixAndAttribs = []; | |
| 8193 | + | |
| 8194 | + if (this.options.prefix) { | |
| 8195 | + prefixAndAttribs.push(this.options.prefix); | |
| 8196 | + } | |
| 8197 | + if (attribs.length) { | |
| 8198 | + prefixAndAttribs.push(attribs.join(', ')); | |
| 8199 | + } | |
| 8200 | + | |
| 8201 | + this._container.innerHTML = prefixAndAttribs.join(' | '); | |
| 8202 | + }, | |
| 8203 | + | |
| 8204 | + _onLayerAdd: function (e) { | |
| 8205 | + if (e.layer.getAttribution) { | |
| 8206 | + this.addAttribution(e.layer.getAttribution()); | |
| 8207 | + } | |
| 8208 | + }, | |
| 8209 | + | |
| 8210 | + _onLayerRemove: function (e) { | |
| 8211 | + if (e.layer.getAttribution) { | |
| 8212 | + this.removeAttribution(e.layer.getAttribution()); | |
| 8213 | + } | |
| 8214 | + } | |
| 8215 | +}); | |
| 8216 | + | |
| 8217 | +L.Map.mergeOptions({ | |
| 8218 | + attributionControl: true | |
| 8219 | +}); | |
| 8220 | + | |
| 8221 | +L.Map.addInitHook(function () { | |
| 8222 | + if (this.options.attributionControl) { | |
| 8223 | + this.attributionControl = (new L.Control.Attribution()).addTo(this); | |
| 8224 | + } | |
| 8225 | +}); | |
| 8226 | + | |
| 8227 | +L.control.attribution = function (options) { | |
| 8228 | + return new L.Control.Attribution(options); | |
| 8229 | +}; | |
| 8230 | + | |
| 8231 | + | |
| 8232 | +/* | |
| 8233 | + * L.Control.Scale is used for displaying metric/imperial scale on the map. | |
| 8234 | + */ | |
| 8235 | + | |
| 8236 | +L.Control.Scale = L.Control.extend({ | |
| 8237 | + options: { | |
| 8238 | + position: 'bottomleft', | |
| 8239 | + maxWidth: 100, | |
| 8240 | + metric: true, | |
| 8241 | + imperial: true, | |
| 8242 | + updateWhenIdle: false | |
| 8243 | + }, | |
| 8244 | + | |
| 8245 | + onAdd: function (map) { | |
| 8246 | + this._map = map; | |
| 8247 | + | |
| 8248 | + var className = 'leaflet-control-scale', | |
| 8249 | + container = L.DomUtil.create('div', className), | |
| 8250 | + options = this.options; | |
| 8251 | + | |
| 8252 | + this._addScales(options, className, container); | |
| 8253 | + | |
| 8254 | + map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); | |
| 8255 | + map.whenReady(this._update, this); | |
| 8256 | + | |
| 8257 | + return container; | |
| 8258 | + }, | |
| 8259 | + | |
| 8260 | + onRemove: function (map) { | |
| 8261 | + map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); | |
| 8262 | + }, | |
| 8263 | + | |
| 8264 | + _addScales: function (options, className, container) { | |
| 8265 | + if (options.metric) { | |
| 8266 | + this._mScale = L.DomUtil.create('div', className + '-line', container); | |
| 8267 | + } | |
| 8268 | + if (options.imperial) { | |
| 8269 | + this._iScale = L.DomUtil.create('div', className + '-line', container); | |
| 8270 | + } | |
| 8271 | + }, | |
| 8272 | + | |
| 8273 | + _update: function () { | |
| 8274 | + var bounds = this._map.getBounds(), | |
| 8275 | + centerLat = bounds.getCenter().lat, | |
| 8276 | + halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180), | |
| 8277 | + dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180, | |
| 8278 | + | |
| 8279 | + size = this._map.getSize(), | |
| 8280 | + options = this.options, | |
| 8281 | + maxMeters = 0; | |
| 8282 | + | |
| 8283 | + if (size.x > 0) { | |
| 8284 | + maxMeters = dist * (options.maxWidth / size.x); | |
| 8285 | + } | |
| 8286 | + | |
| 8287 | + this._updateScales(options, maxMeters); | |
| 8288 | + }, | |
| 8289 | + | |
| 8290 | + _updateScales: function (options, maxMeters) { | |
| 8291 | + if (options.metric && maxMeters) { | |
| 8292 | + this._updateMetric(maxMeters); | |
| 8293 | + } | |
| 8294 | + | |
| 8295 | + if (options.imperial && maxMeters) { | |
| 8296 | + this._updateImperial(maxMeters); | |
| 8297 | + } | |
| 8298 | + }, | |
| 8299 | + | |
| 8300 | + _updateMetric: function (maxMeters) { | |
| 8301 | + var meters = this._getRoundNum(maxMeters); | |
| 8302 | + | |
| 8303 | + this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px'; | |
| 8304 | + this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; | |
| 8305 | + }, | |
| 8306 | + | |
| 8307 | + _updateImperial: function (maxMeters) { | |
| 8308 | + var maxFeet = maxMeters * 3.2808399, | |
| 8309 | + scale = this._iScale, | |
| 8310 | + maxMiles, miles, feet; | |
| 8311 | + | |
| 8312 | + if (maxFeet > 5280) { | |
| 8313 | + maxMiles = maxFeet / 5280; | |
| 8314 | + miles = this._getRoundNum(maxMiles); | |
| 8315 | + | |
| 8316 | + scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px'; | |
| 8317 | + scale.innerHTML = miles + ' mi'; | |
| 8318 | + | |
| 8319 | + } else { | |
| 8320 | + feet = this._getRoundNum(maxFeet); | |
| 8321 | + | |
| 8322 | + scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px'; | |
| 8323 | + scale.innerHTML = feet + ' ft'; | |
| 8324 | + } | |
| 8325 | + }, | |
| 8326 | + | |
| 8327 | + _getScaleWidth: function (ratio) { | |
| 8328 | + return Math.round(this.options.maxWidth * ratio) - 10; | |
| 8329 | + }, | |
| 8330 | + | |
| 8331 | + _getRoundNum: function (num) { | |
| 8332 | + var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), | |
| 8333 | + d = num / pow10; | |
| 8334 | + | |
| 8335 | + d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1; | |
| 8336 | + | |
| 8337 | + return pow10 * d; | |
| 8338 | + } | |
| 8339 | +}); | |
| 8340 | + | |
| 8341 | +L.control.scale = function (options) { | |
| 8342 | + return new L.Control.Scale(options); | |
| 8343 | +}; | |
| 8344 | + | |
| 8345 | + | |
| 8346 | +/* | |
| 8347 | + * L.Control.Layers is a control to allow users to switch between different layers on the map. | |
| 8348 | + */ | |
| 8349 | + | |
| 8350 | +L.Control.Layers = L.Control.extend({ | |
| 8351 | + options: { | |
| 8352 | + collapsed: true, | |
| 8353 | + position: 'topright', | |
| 8354 | + autoZIndex: true | |
| 8355 | + }, | |
| 8356 | + | |
| 8357 | + initialize: function (baseLayers, overlays, options) { | |
| 8358 | + L.setOptions(this, options); | |
| 8359 | + | |
| 8360 | + this._layers = {}; | |
| 8361 | + this._lastZIndex = 0; | |
| 8362 | + this._handlingClick = false; | |
| 8363 | + | |
| 8364 | + for (var i in baseLayers) { | |
| 8365 | + this._addLayer(baseLayers[i], i); | |
| 8366 | + } | |
| 8367 | + | |
| 8368 | + for (i in overlays) { | |
| 8369 | + this._addLayer(overlays[i], i, true); | |
| 8370 | + } | |
| 8371 | + }, | |
| 8372 | + | |
| 8373 | + onAdd: function (map) { | |
| 8374 | + this._initLayout(); | |
| 8375 | + this._update(); | |
| 8376 | + | |
| 8377 | + map | |
| 8378 | + .on('layeradd', this._onLayerChange, this) | |
| 8379 | + .on('layerremove', this._onLayerChange, this); | |
| 8380 | + | |
| 8381 | + return this._container; | |
| 8382 | + }, | |
| 8383 | + | |
| 8384 | + onRemove: function (map) { | |
| 8385 | + map | |
| 8386 | + .off('layeradd', this._onLayerChange, this) | |
| 8387 | + .off('layerremove', this._onLayerChange, this); | |
| 8388 | + }, | |
| 8389 | + | |
| 8390 | + addBaseLayer: function (layer, name) { | |
| 8391 | + this._addLayer(layer, name); | |
| 8392 | + this._update(); | |
| 8393 | + return this; | |
| 8394 | + }, | |
| 8395 | + | |
| 8396 | + addOverlay: function (layer, name) { | |
| 8397 | + this._addLayer(layer, name, true); | |
| 8398 | + this._update(); | |
| 8399 | + return this; | |
| 8400 | + }, | |
| 8401 | + | |
| 8402 | + removeLayer: function (layer) { | |
| 8403 | + var id = L.stamp(layer); | |
| 8404 | + delete this._layers[id]; | |
| 8405 | + this._update(); | |
| 8406 | + return this; | |
| 8407 | + }, | |
| 8408 | + | |
| 8409 | + _initLayout: function () { | |
| 8410 | + var className = 'leaflet-control-layers', | |
| 8411 | + container = this._container = L.DomUtil.create('div', className); | |
| 8412 | + | |
| 8413 | + //Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released | |
| 8414 | + container.setAttribute('aria-haspopup', true); | |
| 8415 | + | |
| 8416 | + if (!L.Browser.touch) { | |
| 8417 | + L.DomEvent | |
| 8418 | + .disableClickPropagation(container) | |
| 8419 | + .disableScrollPropagation(container); | |
| 8420 | + } else { | |
| 8421 | + L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation); | |
| 8422 | + } | |
| 8423 | + | |
| 8424 | + var form = this._form = L.DomUtil.create('form', className + '-list'); | |
| 8425 | + | |
| 8426 | + if (this.options.collapsed) { | |
| 8427 | + if (!L.Browser.android) { | |
| 8428 | + L.DomEvent | |
| 8429 | + .on(container, 'mouseover', this._expand, this) | |
| 8430 | + .on(container, 'mouseout', this._collapse, this); | |
| 8431 | + } | |
| 8432 | + var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container); | |
| 8433 | + link.href = '#'; | |
| 8434 | + link.title = 'Layers'; | |
| 8435 | + | |
| 8436 | + if (L.Browser.touch) { | |
| 8437 | + L.DomEvent | |
| 8438 | + .on(link, 'click', L.DomEvent.stop) | |
| 8439 | + .on(link, 'click', this._expand, this); | |
| 8440 | + } | |
| 8441 | + else { | |
| 8442 | + L.DomEvent.on(link, 'focus', this._expand, this); | |
| 8443 | + } | |
| 8444 | + //Work around for Firefox android issue https://github.com/Leaflet/Leaflet/issues/2033 | |
| 8445 | + L.DomEvent.on(form, 'click', function () { | |
| 8446 | + setTimeout(L.bind(this._onInputClick, this), 0); | |
| 8447 | + }, this); | |
| 8448 | + | |
| 8449 | + this._map.on('click', this._collapse, this); | |
| 8450 | + // TODO keyboard accessibility | |
| 8451 | + } else { | |
| 8452 | + this._expand(); | |
| 8453 | + } | |
| 8454 | + | |
| 8455 | + this._baseLayersList = L.DomUtil.create('div', className + '-base', form); | |
| 8456 | + this._separator = L.DomUtil.create('div', className + '-separator', form); | |
| 8457 | + this._overlaysList = L.DomUtil.create('div', className + '-overlays', form); | |
| 8458 | + | |
| 8459 | + container.appendChild(form); | |
| 8460 | + }, | |
| 8461 | + | |
| 8462 | + _addLayer: function (layer, name, overlay) { | |
| 8463 | + var id = L.stamp(layer); | |
| 8464 | + | |
| 8465 | + this._layers[id] = { | |
| 8466 | + layer: layer, | |
| 8467 | + name: name, | |
| 8468 | + overlay: overlay | |
| 8469 | + }; | |
| 8470 | + | |
| 8471 | + if (this.options.autoZIndex && layer.setZIndex) { | |
| 8472 | + this._lastZIndex++; | |
| 8473 | + layer.setZIndex(this._lastZIndex); | |
| 8474 | + } | |
| 8475 | + }, | |
| 8476 | + | |
| 8477 | + _update: function () { | |
| 8478 | + if (!this._container) { | |
| 8479 | + return; | |
| 8480 | + } | |
| 8481 | + | |
| 8482 | + this._baseLayersList.innerHTML = ''; | |
| 8483 | + this._overlaysList.innerHTML = ''; | |
| 8484 | + | |
| 8485 | + var baseLayersPresent = false, | |
| 8486 | + overlaysPresent = false, | |
| 8487 | + i, obj; | |
| 8488 | + | |
| 8489 | + for (i in this._layers) { | |
| 8490 | + obj = this._layers[i]; | |
| 8491 | + this._addItem(obj); | |
| 8492 | + overlaysPresent = overlaysPresent || obj.overlay; | |
| 8493 | + baseLayersPresent = baseLayersPresent || !obj.overlay; | |
| 8494 | + } | |
| 8495 | + | |
| 8496 | + this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; | |
| 8497 | + }, | |
| 8498 | + | |
| 8499 | + _onLayerChange: function (e) { | |
| 8500 | + var obj = this._layers[L.stamp(e.layer)]; | |
| 8501 | + | |
| 8502 | + if (!obj) { return; } | |
| 8503 | + | |
| 8504 | + if (!this._handlingClick) { | |
| 8505 | + this._update(); | |
| 8506 | + } | |
| 8507 | + | |
| 8508 | + var type = obj.overlay ? | |
| 8509 | + (e.type === 'layeradd' ? 'overlayadd' : 'overlayremove') : | |
| 8510 | + (e.type === 'layeradd' ? 'baselayerchange' : null); | |
| 8511 | + | |
| 8512 | + if (type) { | |
| 8513 | + this._map.fire(type, obj); | |
| 8514 | + } | |
| 8515 | + }, | |
| 8516 | + | |
| 8517 | + // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) | |
| 8518 | + _createRadioElement: function (name, checked) { | |
| 8519 | + | |
| 8520 | + var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"'; | |
| 8521 | + if (checked) { | |
| 8522 | + radioHtml += ' checked="checked"'; | |
| 8523 | + } | |
| 8524 | + radioHtml += '/>'; | |
| 8525 | + | |
| 8526 | + var radioFragment = document.createElement('div'); | |
| 8527 | + radioFragment.innerHTML = radioHtml; | |
| 8528 | + | |
| 8529 | + return radioFragment.firstChild; | |
| 8530 | + }, | |
| 8531 | + | |
| 8532 | + _addItem: function (obj) { | |
| 8533 | + var label = document.createElement('label'), | |
| 8534 | + input, | |
| 8535 | + checked = this._map.hasLayer(obj.layer); | |
| 8536 | + | |
| 8537 | + if (obj.overlay) { | |
| 8538 | + input = document.createElement('input'); | |
| 8539 | + input.type = 'checkbox'; | |
| 8540 | + input.className = 'leaflet-control-layers-selector'; | |
| 8541 | + input.defaultChecked = checked; | |
| 8542 | + } else { | |
| 8543 | + input = this._createRadioElement('leaflet-base-layers', checked); | |
| 8544 | + } | |
| 8545 | + | |
| 8546 | + input.layerId = L.stamp(obj.layer); | |
| 8547 | + | |
| 8548 | + L.DomEvent.on(input, 'click', this._onInputClick, this); | |
| 8549 | + | |
| 8550 | + var name = document.createElement('span'); | |
| 8551 | + name.innerHTML = ' ' + obj.name; | |
| 8552 | + | |
| 8553 | + label.appendChild(input); | |
| 8554 | + label.appendChild(name); | |
| 8555 | + | |
| 8556 | + var container = obj.overlay ? this._overlaysList : this._baseLayersList; | |
| 8557 | + container.appendChild(label); | |
| 8558 | + | |
| 8559 | + return label; | |
| 8560 | + }, | |
| 8561 | + | |
| 8562 | + _onInputClick: function () { | |
| 8563 | + var i, input, obj, | |
| 8564 | + inputs = this._form.getElementsByTagName('input'), | |
| 8565 | + inputsLen = inputs.length; | |
| 8566 | + | |
| 8567 | + this._handlingClick = true; | |
| 8568 | + | |
| 8569 | + for (i = 0; i < inputsLen; i++) { | |
| 8570 | + input = inputs[i]; | |
| 8571 | + obj = this._layers[input.layerId]; | |
| 8572 | + | |
| 8573 | + if (input.checked && !this._map.hasLayer(obj.layer)) { | |
| 8574 | + this._map.addLayer(obj.layer); | |
| 8575 | + | |
| 8576 | + } else if (!input.checked && this._map.hasLayer(obj.layer)) { | |
| 8577 | + this._map.removeLayer(obj.layer); | |
| 8578 | + } | |
| 8579 | + } | |
| 8580 | + | |
| 8581 | + this._handlingClick = false; | |
| 8582 | + | |
| 8583 | + this._refocusOnMap(); | |
| 8584 | + }, | |
| 8585 | + | |
| 8586 | + _expand: function () { | |
| 8587 | + L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded'); | |
| 8588 | + }, | |
| 8589 | + | |
| 8590 | + _collapse: function () { | |
| 8591 | + this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', ''); | |
| 8592 | + } | |
| 8593 | +}); | |
| 8594 | + | |
| 8595 | +L.control.layers = function (baseLayers, overlays, options) { | |
| 8596 | + return new L.Control.Layers(baseLayers, overlays, options); | |
| 8597 | +}; | |
| 8598 | + | |
| 8599 | + | |
| 8600 | +/* | |
| 8601 | + * L.PosAnimation is used by Leaflet internally for pan animations. | |
| 8602 | + */ | |
| 8603 | + | |
| 8604 | +L.PosAnimation = L.Class.extend({ | |
| 8605 | + includes: L.Mixin.Events, | |
| 8606 | + | |
| 8607 | + run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) | |
| 8608 | + this.stop(); | |
| 8609 | + | |
| 8610 | + this._el = el; | |
| 8611 | + this._inProgress = true; | |
| 8612 | + this._newPos = newPos; | |
| 8613 | + | |
| 8614 | + this.fire('start'); | |
| 8615 | + | |
| 8616 | + el.style[L.DomUtil.TRANSITION] = 'all ' + (duration || 0.25) + | |
| 8617 | + 's cubic-bezier(0,0,' + (easeLinearity || 0.5) + ',1)'; | |
| 8618 | + | |
| 8619 | + L.DomEvent.on(el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); | |
| 8620 | + L.DomUtil.setPosition(el, newPos); | |
| 8621 | + | |
| 8622 | + // toggle reflow, Chrome flickers for some reason if you don't do this | |
| 8623 | + L.Util.falseFn(el.offsetWidth); | |
| 8624 | + | |
| 8625 | + // there's no native way to track value updates of transitioned properties, so we imitate this | |
| 8626 | + this._stepTimer = setInterval(L.bind(this._onStep, this), 50); | |
| 8627 | + }, | |
| 8628 | + | |
| 8629 | + stop: function () { | |
| 8630 | + if (!this._inProgress) { return; } | |
| 8631 | + | |
| 8632 | + // if we just removed the transition property, the element would jump to its final position, | |
| 8633 | + // so we need to make it stay at the current position | |
| 8634 | + | |
| 8635 | + L.DomUtil.setPosition(this._el, this._getPos()); | |
| 8636 | + this._onTransitionEnd(); | |
| 8637 | + L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation | |
| 8638 | + }, | |
| 8639 | + | |
| 8640 | + _onStep: function () { | |
| 8641 | + var stepPos = this._getPos(); | |
| 8642 | + if (!stepPos) { | |
| 8643 | + this._onTransitionEnd(); | |
| 8644 | + return; | |
| 8645 | + } | |
| 8646 | + // jshint camelcase: false | |
| 8647 | + // make L.DomUtil.getPosition return intermediate position value during animation | |
| 8648 | + this._el._leaflet_pos = stepPos; | |
| 8649 | + | |
| 8650 | + this.fire('step'); | |
| 8651 | + }, | |
| 8652 | + | |
| 8653 | + // you can't easily get intermediate values of properties animated with CSS3 Transitions, | |
| 8654 | + // we need to parse computed style (in case of transform it returns matrix string) | |
| 8655 | + | |
| 8656 | + _transformRe: /([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/, | |
| 8657 | + | |
| 8658 | + _getPos: function () { | |
| 8659 | + var left, top, matches, | |
| 8660 | + el = this._el, | |
| 8661 | + style = window.getComputedStyle(el); | |
| 8662 | + | |
| 8663 | + if (L.Browser.any3d) { | |
| 8664 | + matches = style[L.DomUtil.TRANSFORM].match(this._transformRe); | |
| 8665 | + if (!matches) { return; } | |
| 8666 | + left = parseFloat(matches[1]); | |
| 8667 | + top = parseFloat(matches[2]); | |
| 8668 | + } else { | |
| 8669 | + left = parseFloat(style.left); | |
| 8670 | + top = parseFloat(style.top); | |
| 8671 | + } | |
| 8672 | + | |
| 8673 | + return new L.Point(left, top, true); | |
| 8674 | + }, | |
| 8675 | + | |
| 8676 | + _onTransitionEnd: function () { | |
| 8677 | + L.DomEvent.off(this._el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); | |
| 8678 | + | |
| 8679 | + if (!this._inProgress) { return; } | |
| 8680 | + this._inProgress = false; | |
| 8681 | + | |
| 8682 | + this._el.style[L.DomUtil.TRANSITION] = ''; | |
| 8683 | + | |
| 8684 | + // jshint camelcase: false | |
| 8685 | + // make sure L.DomUtil.getPosition returns the final position value after animation | |
| 8686 | + this._el._leaflet_pos = this._newPos; | |
| 8687 | + | |
| 8688 | + clearInterval(this._stepTimer); | |
| 8689 | + | |
| 8690 | + this.fire('step').fire('end'); | |
| 8691 | + } | |
| 8692 | + | |
| 8693 | +}); | |
| 8694 | + | |
| 8695 | + | |
| 8696 | +/* | |
| 8697 | + * Extends L.Map to handle panning animations. | |
| 8698 | + */ | |
| 8699 | + | |
| 8700 | +L.Map.include({ | |
| 8701 | + | |
| 8702 | + setView: function (center, zoom, options) { | |
| 8703 | + | |
| 8704 | + zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom); | |
| 8705 | + center = this._limitCenter(L.latLng(center), zoom, this.options.maxBounds); | |
| 8706 | + options = options || {}; | |
| 8707 | + | |
| 8708 | + if (this._panAnim) { | |
| 8709 | + this._panAnim.stop(); | |
| 8710 | + } | |
| 8711 | + | |
| 8712 | + if (this._loaded && !options.reset && options !== true) { | |
| 8713 | + | |
| 8714 | + if (options.animate !== undefined) { | |
| 8715 | + options.zoom = L.extend({animate: options.animate}, options.zoom); | |
| 8716 | + options.pan = L.extend({animate: options.animate}, options.pan); | |
| 8717 | + } | |
| 8718 | + | |
| 8719 | + // try animating pan or zoom | |
| 8720 | + var animated = (this._zoom !== zoom) ? | |
| 8721 | + this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) : | |
| 8722 | + this._tryAnimatedPan(center, options.pan); | |
| 8723 | + | |
| 8724 | + if (animated) { | |
| 8725 | + // prevent resize handler call, the view will refresh after animation anyway | |
| 8726 | + clearTimeout(this._sizeTimer); | |
| 8727 | + return this; | |
| 8728 | + } | |
| 8729 | + } | |
| 8730 | + | |
| 8731 | + // animation didn't start, just reset the map view | |
| 8732 | + this._resetView(center, zoom); | |
| 8733 | + | |
| 8734 | + return this; | |
| 8735 | + }, | |
| 8736 | + | |
| 8737 | + panBy: function (offset, options) { | |
| 8738 | + offset = L.point(offset).round(); | |
| 8739 | + options = options || {}; | |
| 8740 | + | |
| 8741 | + if (!offset.x && !offset.y) { | |
| 8742 | + return this; | |
| 8743 | + } | |
| 8744 | + | |
| 8745 | + if (!this._panAnim) { | |
| 8746 | + this._panAnim = new L.PosAnimation(); | |
| 8747 | + | |
| 8748 | + this._panAnim.on({ | |
| 8749 | + 'step': this._onPanTransitionStep, | |
| 8750 | + 'end': this._onPanTransitionEnd | |
| 8751 | + }, this); | |
| 8752 | + } | |
| 8753 | + | |
| 8754 | + // don't fire movestart if animating inertia | |
| 8755 | + if (!options.noMoveStart) { | |
| 8756 | + this.fire('movestart'); | |
| 8757 | + } | |
| 8758 | + | |
| 8759 | + // animate pan unless animate: false specified | |
| 8760 | + if (options.animate !== false) { | |
| 8761 | + L.DomUtil.addClass(this._mapPane, 'leaflet-pan-anim'); | |
| 8762 | + | |
| 8763 | + var newPos = this._getMapPanePos().subtract(offset); | |
| 8764 | + this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity); | |
| 8765 | + } else { | |
| 8766 | + this._rawPanBy(offset); | |
| 8767 | + this.fire('move').fire('moveend'); | |
| 8768 | + } | |
| 8769 | + | |
| 8770 | + return this; | |
| 8771 | + }, | |
| 8772 | + | |
| 8773 | + _onPanTransitionStep: function () { | |
| 8774 | + this.fire('move'); | |
| 8775 | + }, | |
| 8776 | + | |
| 8777 | + _onPanTransitionEnd: function () { | |
| 8778 | + L.DomUtil.removeClass(this._mapPane, 'leaflet-pan-anim'); | |
| 8779 | + this.fire('moveend'); | |
| 8780 | + }, | |
| 8781 | + | |
| 8782 | + _tryAnimatedPan: function (center, options) { | |
| 8783 | + // difference between the new and current centers in pixels | |
| 8784 | + var offset = this._getCenterOffset(center)._floor(); | |
| 8785 | + | |
| 8786 | + // don't animate too far unless animate: true specified in options | |
| 8787 | + if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; } | |
| 8788 | + | |
| 8789 | + this.panBy(offset, options); | |
| 8790 | + | |
| 8791 | + return true; | |
| 8792 | + } | |
| 8793 | +}); | |
| 8794 | + | |
| 8795 | + | |
| 8796 | +/* | |
| 8797 | + * L.PosAnimation fallback implementation that powers Leaflet pan animations | |
| 8798 | + * in browsers that don't support CSS3 Transitions. | |
| 8799 | + */ | |
| 8800 | + | |
| 8801 | +L.PosAnimation = L.DomUtil.TRANSITION ? L.PosAnimation : L.PosAnimation.extend({ | |
| 8802 | + | |
| 8803 | + run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) | |
| 8804 | + this.stop(); | |
| 8805 | + | |
| 8806 | + this._el = el; | |
| 8807 | + this._inProgress = true; | |
| 8808 | + this._duration = duration || 0.25; | |
| 8809 | + this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); | |
| 8810 | + | |
| 8811 | + this._startPos = L.DomUtil.getPosition(el); | |
| 8812 | + this._offset = newPos.subtract(this._startPos); | |
| 8813 | + this._startTime = +new Date(); | |
| 8814 | + | |
| 8815 | + this.fire('start'); | |
| 8816 | + | |
| 8817 | + this._animate(); | |
| 8818 | + }, | |
| 8819 | + | |
| 8820 | + stop: function () { | |
| 8821 | + if (!this._inProgress) { return; } | |
| 8822 | + | |
| 8823 | + this._step(); | |
| 8824 | + this._complete(); | |
| 8825 | + }, | |
| 8826 | + | |
| 8827 | + _animate: function () { | |
| 8828 | + // animation loop | |
| 8829 | + this._animId = L.Util.requestAnimFrame(this._animate, this); | |
| 8830 | + this._step(); | |
| 8831 | + }, | |
| 8832 | + | |
| 8833 | + _step: function () { | |
| 8834 | + var elapsed = (+new Date()) - this._startTime, | |
| 8835 | + duration = this._duration * 1000; | |
| 8836 | + | |
| 8837 | + if (elapsed < duration) { | |
| 8838 | + this._runFrame(this._easeOut(elapsed / duration)); | |
| 8839 | + } else { | |
| 8840 | + this._runFrame(1); | |
| 8841 | + this._complete(); | |
| 8842 | + } | |
| 8843 | + }, | |
| 8844 | + | |
| 8845 | + _runFrame: function (progress) { | |
| 8846 | + var pos = this._startPos.add(this._offset.multiplyBy(progress)); | |
| 8847 | + L.DomUtil.setPosition(this._el, pos); | |
| 8848 | + | |
| 8849 | + this.fire('step'); | |
| 8850 | + }, | |
| 8851 | + | |
| 8852 | + _complete: function () { | |
| 8853 | + L.Util.cancelAnimFrame(this._animId); | |
| 8854 | + | |
| 8855 | + this._inProgress = false; | |
| 8856 | + this.fire('end'); | |
| 8857 | + }, | |
| 8858 | + | |
| 8859 | + _easeOut: function (t) { | |
| 8860 | + return 1 - Math.pow(1 - t, this._easeOutPower); | |
| 8861 | + } | |
| 8862 | +}); | |
| 8863 | + | |
| 8864 | + | |
| 8865 | +/* | |
| 8866 | + * Extends L.Map to handle zoom animations. | |
| 8867 | + */ | |
| 8868 | + | |
| 8869 | +L.Map.mergeOptions({ | |
| 8870 | + zoomAnimation: true, | |
| 8871 | + zoomAnimationThreshold: 4 | |
| 8872 | +}); | |
| 8873 | + | |
| 8874 | +if (L.DomUtil.TRANSITION) { | |
| 8875 | + | |
| 8876 | + L.Map.addInitHook(function () { | |
| 8877 | + // don't animate on browsers without hardware-accelerated transitions or old Android/Opera | |
| 8878 | + this._zoomAnimated = this.options.zoomAnimation && L.DomUtil.TRANSITION && | |
| 8879 | + L.Browser.any3d && !L.Browser.android23 && !L.Browser.mobileOpera; | |
| 8880 | + | |
| 8881 | + // zoom transitions run with the same duration for all layers, so if one of transitionend events | |
| 8882 | + // happens after starting zoom animation (propagating to the map pane), we know that it ended globally | |
| 8883 | + if (this._zoomAnimated) { | |
| 8884 | + L.DomEvent.on(this._mapPane, L.DomUtil.TRANSITION_END, this._catchTransitionEnd, this); | |
| 8885 | + } | |
| 8886 | + }); | |
| 8887 | +} | |
| 8888 | + | |
| 8889 | +L.Map.include(!L.DomUtil.TRANSITION ? {} : { | |
| 8890 | + | |
| 8891 | + _catchTransitionEnd: function (e) { | |
| 8892 | + if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) { | |
| 8893 | + this._onZoomTransitionEnd(); | |
| 8894 | + } | |
| 8895 | + }, | |
| 8896 | + | |
| 8897 | + _nothingToAnimate: function () { | |
| 8898 | + return !this._container.getElementsByClassName('leaflet-zoom-animated').length; | |
| 8899 | + }, | |
| 8900 | + | |
| 8901 | + _tryAnimatedZoom: function (center, zoom, options) { | |
| 8902 | + | |
| 8903 | + if (this._animatingZoom) { return true; } | |
| 8904 | + | |
| 8905 | + options = options || {}; | |
| 8906 | + | |
| 8907 | + // don't animate if disabled, not supported or zoom difference is too large | |
| 8908 | + if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || | |
| 8909 | + Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } | |
| 8910 | + | |
| 8911 | + // offset is the pixel coords of the zoom origin relative to the current center | |
| 8912 | + var scale = this.getZoomScale(zoom), | |
| 8913 | + offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale), | |
| 8914 | + origin = this._getCenterLayerPoint()._add(offset); | |
| 8915 | + | |
| 8916 | + // don't animate if the zoom origin isn't within one screen from the current center, unless forced | |
| 8917 | + if (options.animate !== true && !this.getSize().contains(offset)) { return false; } | |
| 8918 | + | |
| 8919 | + this | |
| 8920 | + .fire('movestart') | |
| 8921 | + .fire('zoomstart'); | |
| 8922 | + | |
| 8923 | + this._animateZoom(center, zoom, origin, scale, null, true); | |
| 8924 | + | |
| 8925 | + return true; | |
| 8926 | + }, | |
| 8927 | + | |
| 8928 | + _animateZoom: function (center, zoom, origin, scale, delta, backwards, forTouchZoom) { | |
| 8929 | + | |
| 8930 | + if (!forTouchZoom) { | |
| 8931 | + this._animatingZoom = true; | |
| 8932 | + } | |
| 8933 | + | |
| 8934 | + // put transform transition on all layers with leaflet-zoom-animated class | |
| 8935 | + L.DomUtil.addClass(this._mapPane, 'leaflet-zoom-anim'); | |
| 8936 | + | |
| 8937 | + // remember what center/zoom to set after animation | |
| 8938 | + this._animateToCenter = center; | |
| 8939 | + this._animateToZoom = zoom; | |
| 8940 | + | |
| 8941 | + // disable any dragging during animation | |
| 8942 | + if (L.Draggable) { | |
| 8943 | + L.Draggable._disabled = true; | |
| 8944 | + } | |
| 8945 | + | |
| 8946 | + L.Util.requestAnimFrame(function () { | |
| 8947 | + this.fire('zoomanim', { | |
| 8948 | + center: center, | |
| 8949 | + zoom: zoom, | |
| 8950 | + origin: origin, | |
| 8951 | + scale: scale, | |
| 8952 | + delta: delta, | |
| 8953 | + backwards: backwards | |
| 8954 | + }); | |
| 8955 | + }, this); | |
| 8956 | + }, | |
| 8957 | + | |
| 8958 | + _onZoomTransitionEnd: function () { | |
| 8959 | + | |
| 8960 | + this._animatingZoom = false; | |
| 8961 | + | |
| 8962 | + L.DomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim'); | |
| 8963 | + | |
| 8964 | + this._resetView(this._animateToCenter, this._animateToZoom, true, true); | |
| 8965 | + | |
| 8966 | + if (L.Draggable) { | |
| 8967 | + L.Draggable._disabled = false; | |
| 8968 | + } | |
| 8969 | + } | |
| 8970 | +}); | |
| 8971 | + | |
| 8972 | + | |
| 8973 | +/* | |
| 8974 | + Zoom animation logic for L.TileLayer. | |
| 8975 | +*/ | |
| 8976 | + | |
| 8977 | +L.TileLayer.include({ | |
| 8978 | + _animateZoom: function (e) { | |
| 8979 | + if (!this._animating) { | |
| 8980 | + this._animating = true; | |
| 8981 | + this._prepareBgBuffer(); | |
| 8982 | + } | |
| 8983 | + | |
| 8984 | + var bg = this._bgBuffer, | |
| 8985 | + transform = L.DomUtil.TRANSFORM, | |
| 8986 | + initialTransform = e.delta ? L.DomUtil.getTranslateString(e.delta) : bg.style[transform], | |
| 8987 | + scaleStr = L.DomUtil.getScaleString(e.scale, e.origin); | |
| 8988 | + | |
| 8989 | + bg.style[transform] = e.backwards ? | |
| 8990 | + scaleStr + ' ' + initialTransform : | |
| 8991 | + initialTransform + ' ' + scaleStr; | |
| 8992 | + }, | |
| 8993 | + | |
| 8994 | + _endZoomAnim: function () { | |
| 8995 | + var front = this._tileContainer, | |
| 8996 | + bg = this._bgBuffer; | |
| 8997 | + | |
| 8998 | + front.style.visibility = ''; | |
| 8999 | + front.parentNode.appendChild(front); // Bring to fore | |
| 9000 | + | |
| 9001 | + // force reflow | |
| 9002 | + L.Util.falseFn(bg.offsetWidth); | |
| 9003 | + | |
| 9004 | + this._animating = false; | |
| 9005 | + }, | |
| 9006 | + | |
| 9007 | + _clearBgBuffer: function () { | |
| 9008 | + var map = this._map; | |
| 9009 | + | |
| 9010 | + if (map && !map._animatingZoom && !map.touchZoom._zooming) { | |
| 9011 | + this._bgBuffer.innerHTML = ''; | |
| 9012 | + this._bgBuffer.style[L.DomUtil.TRANSFORM] = ''; | |
| 9013 | + } | |
| 9014 | + }, | |
| 9015 | + | |
| 9016 | + _prepareBgBuffer: function () { | |
| 9017 | + | |
| 9018 | + var front = this._tileContainer, | |
| 9019 | + bg = this._bgBuffer; | |
| 9020 | + | |
| 9021 | + // if foreground layer doesn't have many tiles but bg layer does, | |
| 9022 | + // keep the existing bg layer and just zoom it some more | |
| 9023 | + | |
| 9024 | + var bgLoaded = this._getLoadedTilesPercentage(bg), | |
| 9025 | + frontLoaded = this._getLoadedTilesPercentage(front); | |
| 9026 | + | |
| 9027 | + if (bg && bgLoaded > 0.5 && frontLoaded < 0.5) { | |
| 9028 | + | |
| 9029 | + front.style.visibility = 'hidden'; | |
| 9030 | + this._stopLoadingImages(front); | |
| 9031 | + return; | |
| 9032 | + } | |
| 9033 | + | |
| 9034 | + // prepare the buffer to become the front tile pane | |
| 9035 | + bg.style.visibility = 'hidden'; | |
| 9036 | + bg.style[L.DomUtil.TRANSFORM] = ''; | |
| 9037 | + | |
| 9038 | + // switch out the current layer to be the new bg layer (and vice-versa) | |
| 9039 | + this._tileContainer = bg; | |
| 9040 | + bg = this._bgBuffer = front; | |
| 9041 | + | |
| 9042 | + this._stopLoadingImages(bg); | |
| 9043 | + | |
| 9044 | + //prevent bg buffer from clearing right after zoom | |
| 9045 | + clearTimeout(this._clearBgBufferTimer); | |
| 9046 | + }, | |
| 9047 | + | |
| 9048 | + _getLoadedTilesPercentage: function (container) { | |
| 9049 | + var tiles = container.getElementsByTagName('img'), | |
| 9050 | + i, len, count = 0; | |
| 9051 | + | |
| 9052 | + for (i = 0, len = tiles.length; i < len; i++) { | |
| 9053 | + if (tiles[i].complete) { | |
| 9054 | + count++; | |
| 9055 | + } | |
| 9056 | + } | |
| 9057 | + return count / len; | |
| 9058 | + }, | |
| 9059 | + | |
| 9060 | + // stops loading all tiles in the background layer | |
| 9061 | + _stopLoadingImages: function (container) { | |
| 9062 | + var tiles = Array.prototype.slice.call(container.getElementsByTagName('img')), | |
| 9063 | + i, len, tile; | |
| 9064 | + | |
| 9065 | + for (i = 0, len = tiles.length; i < len; i++) { | |
| 9066 | + tile = tiles[i]; | |
| 9067 | + | |
| 9068 | + if (!tile.complete) { | |
| 9069 | + tile.onload = L.Util.falseFn; | |
| 9070 | + tile.onerror = L.Util.falseFn; | |
| 9071 | + tile.src = L.Util.emptyImageUrl; | |
| 9072 | + | |
| 9073 | + tile.parentNode.removeChild(tile); | |
| 9074 | + } | |
| 9075 | + } | |
| 9076 | + } | |
| 9077 | +}); | |
| 9078 | + | |
| 9079 | + | |
| 9080 | +/* | |
| 9081 | + * Provides L.Map with convenient shortcuts for using browser geolocation features. | |
| 9082 | + */ | |
| 9083 | + | |
| 9084 | +L.Map.include({ | |
| 9085 | + _defaultLocateOptions: { | |
| 9086 | + watch: false, | |
| 9087 | + setView: false, | |
| 9088 | + maxZoom: Infinity, | |
| 9089 | + timeout: 10000, | |
| 9090 | + maximumAge: 0, | |
| 9091 | + enableHighAccuracy: false | |
| 9092 | + }, | |
| 9093 | + | |
| 9094 | + locate: function (/*Object*/ options) { | |
| 9095 | + | |
| 9096 | + options = this._locateOptions = L.extend(this._defaultLocateOptions, options); | |
| 9097 | + | |
| 9098 | + if (!navigator.geolocation) { | |
| 9099 | + this._handleGeolocationError({ | |
| 9100 | + code: 0, | |
| 9101 | + message: 'Geolocation not supported.' | |
| 9102 | + }); | |
| 9103 | + return this; | |
| 9104 | + } | |
| 9105 | + | |
| 9106 | + var onResponse = L.bind(this._handleGeolocationResponse, this), | |
| 9107 | + onError = L.bind(this._handleGeolocationError, this); | |
| 9108 | + | |
| 9109 | + if (options.watch) { | |
| 9110 | + this._locationWatchId = | |
| 9111 | + navigator.geolocation.watchPosition(onResponse, onError, options); | |
| 9112 | + } else { | |
| 9113 | + navigator.geolocation.getCurrentPosition(onResponse, onError, options); | |
| 9114 | + } | |
| 9115 | + return this; | |
| 9116 | + }, | |
| 9117 | + | |
| 9118 | + stopLocate: function () { | |
| 9119 | + if (navigator.geolocation) { | |
| 9120 | + navigator.geolocation.clearWatch(this._locationWatchId); | |
| 9121 | + } | |
| 9122 | + if (this._locateOptions) { | |
| 9123 | + this._locateOptions.setView = false; | |
| 9124 | + } | |
| 9125 | + return this; | |
| 9126 | + }, | |
| 9127 | + | |
| 9128 | + _handleGeolocationError: function (error) { | |
| 9129 | + var c = error.code, | |
| 9130 | + message = error.message || | |
| 9131 | + (c === 1 ? 'permission denied' : | |
| 9132 | + (c === 2 ? 'position unavailable' : 'timeout')); | |
| 9133 | + | |
| 9134 | + if (this._locateOptions.setView && !this._loaded) { | |
| 9135 | + this.fitWorld(); | |
| 9136 | + } | |
| 9137 | + | |
| 9138 | + this.fire('locationerror', { | |
| 9139 | + code: c, | |
| 9140 | + message: 'Geolocation error: ' + message + '.' | |
| 9141 | + }); | |
| 9142 | + }, | |
| 9143 | + | |
| 9144 | + _handleGeolocationResponse: function (pos) { | |
| 9145 | + var lat = pos.coords.latitude, | |
| 9146 | + lng = pos.coords.longitude, | |
| 9147 | + latlng = new L.LatLng(lat, lng), | |
| 9148 | + | |
| 9149 | + latAccuracy = 180 * pos.coords.accuracy / 40075017, | |
| 9150 | + lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat), | |
| 9151 | + | |
| 9152 | + bounds = L.latLngBounds( | |
| 9153 | + [lat - latAccuracy, lng - lngAccuracy], | |
| 9154 | + [lat + latAccuracy, lng + lngAccuracy]), | |
| 9155 | + | |
| 9156 | + options = this._locateOptions; | |
| 9157 | + | |
| 9158 | + if (options.setView) { | |
| 9159 | + var zoom = Math.min(this.getBoundsZoom(bounds), options.maxZoom); | |
| 9160 | + this.setView(latlng, zoom); | |
| 9161 | + } | |
| 9162 | + | |
| 9163 | + var data = { | |
| 9164 | + latlng: latlng, | |
| 9165 | + bounds: bounds, | |
| 9166 | + timestamp: pos.timestamp | |
| 9167 | + }; | |
| 9168 | + | |
| 9169 | + for (var i in pos.coords) { | |
| 9170 | + if (typeof pos.coords[i] === 'number') { | |
| 9171 | + data[i] = pos.coords[i]; | |
| 9172 | + } | |
| 9173 | + } | |
| 9174 | + | |
| 9175 | + this.fire('locationfound', data); | |
| 9176 | + } | |
| 9177 | +}); | |
| 9178 | + | |
| 9179 | + | |
| 9180 | +}(window, document)); | |
| 0 | 9181 | \ No newline at end of file | ... | ... |
datalets/leafletjs-geojson-datalet/leafletsjs/leaflet.css
0 โ 100755
| 1 | +/* required styles */ | |
| 2 | + | |
| 3 | + .leaflet-map-pane, | |
| 4 | +.leaflet-tile, | |
| 5 | +.leaflet-marker-icon, | |
| 6 | +.leaflet-marker-shadow, | |
| 7 | +.leaflet-tile-pane, | |
| 8 | +.leaflet-tile-container, | |
| 9 | +.leaflet-overlay-pane, | |
| 10 | +.leaflet-shadow-pane, | |
| 11 | +.leaflet-marker-pane, | |
| 12 | +.leaflet-popup-pane, | |
| 13 | +.leaflet-overlay-pane svg, | |
| 14 | +.leaflet-zoom-box, | |
| 15 | +.leaflet-image-layer, | |
| 16 | +.leaflet-layer { | |
| 17 | + position: absolute; | |
| 18 | + left: 0; | |
| 19 | + top: 0; | |
| 20 | + } | |
| 21 | + .leaflet-container { | |
| 22 | + overflow: hidden; | |
| 23 | + -ms-touch-action: none; | |
| 24 | + } | |
| 25 | +.leaflet-tile, | |
| 26 | +.leaflet-marker-icon, | |
| 27 | +.leaflet-marker-shadow { | |
| 28 | + -webkit-user-select: none; | |
| 29 | + -moz-user-select: none; | |
| 30 | + user-select: none; | |
| 31 | + -webkit-user-drag: none; | |
| 32 | + } | |
| 33 | +.leaflet-marker-icon, | |
| 34 | +.leaflet-marker-shadow { | |
| 35 | + display: block; | |
| 36 | + } | |
| 37 | +/* map is broken in FF if you have max-width: 100% on tiles */ | |
| 38 | +.leaflet-container img { | |
| 39 | + max-width: none !important; | |
| 40 | + } | |
| 41 | +/* stupid Android 2 doesn't understand "max-width: none" properly */ | |
| 42 | +.leaflet-container img.leaflet-image-layer { | |
| 43 | + max-width: 15000px !important; | |
| 44 | + } | |
| 45 | +.leaflet-tile { | |
| 46 | + filter: inherit; | |
| 47 | + visibility: hidden; | |
| 48 | + } | |
| 49 | +.leaflet-tile-loaded { | |
| 50 | + visibility: inherit; | |
| 51 | + } | |
| 52 | +.leaflet-zoom-box { | |
| 53 | + width: 0; | |
| 54 | + height: 0; | |
| 55 | + } | |
| 56 | +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ | |
| 57 | +.leaflet-overlay-pane svg { | |
| 58 | + -moz-user-select: none; | |
| 59 | + } | |
| 60 | +.leaflet-tile-pane { z-index: 2; } | |
| 61 | +.leaflet-objects-pane { z-index: 3; } | |
| 62 | +.leaflet-overlay-pane { z-index: 4; } | |
| 63 | +.leaflet-shadow-pane { z-index: 5; } | |
| 64 | +.leaflet-marker-pane { z-index: 6; } | |
| 65 | +.leaflet-popup-pane { z-index: 7; } | |
| 66 | + | |
| 67 | +.leaflet-vml-shape { | |
| 68 | + width: 1px; | |
| 69 | + height: 1px; | |
| 70 | + } | |
| 71 | +.lvml { | |
| 72 | + behavior: url(#default#VML); | |
| 73 | + display: inline-block; | |
| 74 | + position: absolute; | |
| 75 | + } | |
| 76 | + | |
| 77 | + | |
| 78 | +/* control positioning */ | |
| 79 | + | |
| 80 | +.leaflet-control { | |
| 81 | + position: relative; | |
| 82 | + z-index: 7; | |
| 83 | + pointer-events: auto; | |
| 84 | + } | |
| 85 | +.leaflet-top, | |
| 86 | +.leaflet-bottom { | |
| 87 | + position: absolute; | |
| 88 | + /*z-index: 1000;*/ | |
| 89 | + pointer-events: none; | |
| 90 | + } | |
| 91 | +.leaflet-top { | |
| 92 | + top: 0; | |
| 93 | + } | |
| 94 | +.leaflet-right { | |
| 95 | + right: 0; | |
| 96 | + } | |
| 97 | +.leaflet-bottom { | |
| 98 | + bottom: 0; | |
| 99 | + } | |
| 100 | +.leaflet-left { | |
| 101 | + left: 0; | |
| 102 | + } | |
| 103 | +.leaflet-control { | |
| 104 | + float: left; | |
| 105 | + clear: both; | |
| 106 | + } | |
| 107 | +.leaflet-right .leaflet-control { | |
| 108 | + float: right; | |
| 109 | + } | |
| 110 | +.leaflet-top .leaflet-control { | |
| 111 | + margin-top: 10px; | |
| 112 | + } | |
| 113 | +.leaflet-bottom .leaflet-control { | |
| 114 | + margin-bottom: 10px; | |
| 115 | + } | |
| 116 | +.leaflet-left .leaflet-control { | |
| 117 | + margin-left: 10px; | |
| 118 | + } | |
| 119 | +.leaflet-right .leaflet-control { | |
| 120 | + margin-right: 10px; | |
| 121 | + } | |
| 122 | + | |
| 123 | + | |
| 124 | +/* zoom and fade animations */ | |
| 125 | + | |
| 126 | +.leaflet-fade-anim .leaflet-tile, | |
| 127 | +.leaflet-fade-anim .leaflet-popup { | |
| 128 | + opacity: 0; | |
| 129 | + -webkit-transition: opacity 0.2s linear; | |
| 130 | + -moz-transition: opacity 0.2s linear; | |
| 131 | + -o-transition: opacity 0.2s linear; | |
| 132 | + transition: opacity 0.2s linear; | |
| 133 | + } | |
| 134 | +.leaflet-fade-anim .leaflet-tile-loaded, | |
| 135 | +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { | |
| 136 | + opacity: 1; | |
| 137 | + } | |
| 138 | + | |
| 139 | +.leaflet-zoom-anim .leaflet-zoom-animated { | |
| 140 | + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); | |
| 141 | + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); | |
| 142 | + -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); | |
| 143 | + transition: transform 0.25s cubic-bezier(0,0,0.25,1); | |
| 144 | + } | |
| 145 | +.leaflet-zoom-anim .leaflet-tile, | |
| 146 | +.leaflet-pan-anim .leaflet-tile, | |
| 147 | +.leaflet-touching .leaflet-zoom-animated { | |
| 148 | + -webkit-transition: none; | |
| 149 | + -moz-transition: none; | |
| 150 | + -o-transition: none; | |
| 151 | + transition: none; | |
| 152 | + } | |
| 153 | + | |
| 154 | +.leaflet-zoom-anim .leaflet-zoom-hide { | |
| 155 | + visibility: hidden; | |
| 156 | + } | |
| 157 | + | |
| 158 | + | |
| 159 | +/* cursors */ | |
| 160 | + | |
| 161 | +.leaflet-clickable { | |
| 162 | + cursor: pointer; | |
| 163 | + } | |
| 164 | +.leaflet-container { | |
| 165 | + cursor: -webkit-grab; | |
| 166 | + cursor: -moz-grab; | |
| 167 | + } | |
| 168 | +.leaflet-popup-pane, | |
| 169 | +.leaflet-control { | |
| 170 | + cursor: auto; | |
| 171 | + } | |
| 172 | +.leaflet-dragging .leaflet-container, | |
| 173 | +.leaflet-dragging .leaflet-clickable { | |
| 174 | + cursor: move; | |
| 175 | + cursor: -webkit-grabbing; | |
| 176 | + cursor: -moz-grabbing; | |
| 177 | + } | |
| 178 | + | |
| 179 | + | |
| 180 | +/* visual tweaks */ | |
| 181 | + | |
| 182 | +.leaflet-container { | |
| 183 | + background: #ddd; | |
| 184 | + outline: 0; | |
| 185 | + } | |
| 186 | +.leaflet-container a { | |
| 187 | + color: #0078A8; | |
| 188 | + } | |
| 189 | +.leaflet-container a.leaflet-active { | |
| 190 | + outline: 2px solid orange; | |
| 191 | + } | |
| 192 | +.leaflet-zoom-box { | |
| 193 | + border: 2px dotted #38f; | |
| 194 | + background: rgba(255,255,255,0.5); | |
| 195 | + } | |
| 196 | + | |
| 197 | + | |
| 198 | +/* general typography */ | |
| 199 | +.leaflet-container { | |
| 200 | + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; | |
| 201 | + } | |
| 202 | + | |
| 203 | + | |
| 204 | +/* general toolbar styles */ | |
| 205 | + | |
| 206 | +.leaflet-bar { | |
| 207 | + box-shadow: 0 1px 5px rgba(0,0,0,0.65); | |
| 208 | + border-radius: 4px; | |
| 209 | + } | |
| 210 | +.leaflet-bar a, | |
| 211 | +.leaflet-bar a:hover { | |
| 212 | + background-color: #fff; | |
| 213 | + border-bottom: 1px solid #ccc; | |
| 214 | + width: 26px; | |
| 215 | + height: 26px; | |
| 216 | + line-height: 26px; | |
| 217 | + display: block; | |
| 218 | + text-align: center; | |
| 219 | + text-decoration: none; | |
| 220 | + color: black; | |
| 221 | + } | |
| 222 | +.leaflet-bar a, | |
| 223 | +.leaflet-control-layers-toggle { | |
| 224 | + background-position: 50% 50%; | |
| 225 | + background-repeat: no-repeat; | |
| 226 | + display: block; | |
| 227 | + } | |
| 228 | +.leaflet-bar a:hover { | |
| 229 | + background-color: #f4f4f4; | |
| 230 | + } | |
| 231 | +.leaflet-bar a:first-child { | |
| 232 | + border-top-left-radius: 4px; | |
| 233 | + border-top-right-radius: 4px; | |
| 234 | + } | |
| 235 | +.leaflet-bar a:last-child { | |
| 236 | + border-bottom-left-radius: 4px; | |
| 237 | + border-bottom-right-radius: 4px; | |
| 238 | + border-bottom: none; | |
| 239 | + } | |
| 240 | +.leaflet-bar a.leaflet-disabled { | |
| 241 | + cursor: default; | |
| 242 | + background-color: #f4f4f4; | |
| 243 | + color: #bbb; | |
| 244 | + } | |
| 245 | + | |
| 246 | +.leaflet-touch .leaflet-bar a { | |
| 247 | + width: 30px; | |
| 248 | + height: 30px; | |
| 249 | + line-height: 30px; | |
| 250 | + } | |
| 251 | + | |
| 252 | + | |
| 253 | +/* zoom control */ | |
| 254 | + | |
| 255 | +.leaflet-control-zoom-in, | |
| 256 | +.leaflet-control-zoom-out { | |
| 257 | + font: bold 18px 'Lucida Console', Monaco, monospace; | |
| 258 | + text-indent: 1px; | |
| 259 | + } | |
| 260 | +.leaflet-control-zoom-out { | |
| 261 | + font-size: 20px; | |
| 262 | + } | |
| 263 | + | |
| 264 | +.leaflet-touch .leaflet-control-zoom-in { | |
| 265 | + font-size: 22px; | |
| 266 | + } | |
| 267 | +.leaflet-touch .leaflet-control-zoom-out { | |
| 268 | + font-size: 24px; | |
| 269 | + } | |
| 270 | + | |
| 271 | + | |
| 272 | +/* layers control */ | |
| 273 | + | |
| 274 | +.leaflet-control-layers { | |
| 275 | + box-shadow: 0 1px 5px rgba(0,0,0,0.4); | |
| 276 | + background: #fff; | |
| 277 | + border-radius: 5px; | |
| 278 | + } | |
| 279 | +.leaflet-control-layers-toggle { | |
| 280 | + background-image: url(images/layers.png); | |
| 281 | + width: 36px; | |
| 282 | + height: 36px; | |
| 283 | + } | |
| 284 | +.leaflet-retina .leaflet-control-layers-toggle { | |
| 285 | + background-image: url(images/layers-2x.png); | |
| 286 | + background-size: 26px 26px; | |
| 287 | + } | |
| 288 | +.leaflet-touch .leaflet-control-layers-toggle { | |
| 289 | + width: 44px; | |
| 290 | + height: 44px; | |
| 291 | + } | |
| 292 | +.leaflet-control-layers .leaflet-control-layers-list, | |
| 293 | +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { | |
| 294 | + display: none; | |
| 295 | + } | |
| 296 | +.leaflet-control-layers-expanded .leaflet-control-layers-list { | |
| 297 | + display: block; | |
| 298 | + position: relative; | |
| 299 | + } | |
| 300 | +.leaflet-control-layers-expanded { | |
| 301 | + padding: 6px 10px 6px 6px; | |
| 302 | + color: #333; | |
| 303 | + background: #fff; | |
| 304 | + } | |
| 305 | +.leaflet-control-layers-selector { | |
| 306 | + margin-top: 2px; | |
| 307 | + position: relative; | |
| 308 | + top: 1px; | |
| 309 | + } | |
| 310 | +.leaflet-control-layers label { | |
| 311 | + display: block; | |
| 312 | + } | |
| 313 | +.leaflet-control-layers-separator { | |
| 314 | + height: 0; | |
| 315 | + border-top: 1px solid #ddd; | |
| 316 | + margin: 5px -10px 5px -6px; | |
| 317 | + } | |
| 318 | + | |
| 319 | + | |
| 320 | +/* attribution and scale controls */ | |
| 321 | + | |
| 322 | +.leaflet-container .leaflet-control-attribution { | |
| 323 | + background: #fff; | |
| 324 | + background: rgba(255, 255, 255, 0.7); | |
| 325 | + margin: 0; | |
| 326 | + } | |
| 327 | +.leaflet-control-attribution, | |
| 328 | +.leaflet-control-scale-line { | |
| 329 | + padding: 0 5px; | |
| 330 | + color: #333; | |
| 331 | + } | |
| 332 | +.leaflet-control-attribution a { | |
| 333 | + text-decoration: none; | |
| 334 | + } | |
| 335 | +.leaflet-control-attribution a:hover { | |
| 336 | + text-decoration: underline; | |
| 337 | + } | |
| 338 | +.leaflet-container .leaflet-control-attribution, | |
| 339 | +.leaflet-container .leaflet-control-scale { | |
| 340 | + font-size: 11px; | |
| 341 | + } | |
| 342 | +.leaflet-left .leaflet-control-scale { | |
| 343 | + margin-left: 5px; | |
| 344 | + } | |
| 345 | +.leaflet-bottom .leaflet-control-scale { | |
| 346 | + margin-bottom: 5px; | |
| 347 | + } | |
| 348 | +.leaflet-control-scale-line { | |
| 349 | + border: 2px solid #777; | |
| 350 | + border-top: none; | |
| 351 | + line-height: 1.1; | |
| 352 | + padding: 2px 5px 1px; | |
| 353 | + font-size: 11px; | |
| 354 | + white-space: nowrap; | |
| 355 | + overflow: hidden; | |
| 356 | + -moz-box-sizing: content-box; | |
| 357 | + box-sizing: content-box; | |
| 358 | + | |
| 359 | + background: #fff; | |
| 360 | + background: rgba(255, 255, 255, 0.5); | |
| 361 | + } | |
| 362 | +.leaflet-control-scale-line:not(:first-child) { | |
| 363 | + border-top: 2px solid #777; | |
| 364 | + border-bottom: none; | |
| 365 | + margin-top: -2px; | |
| 366 | + } | |
| 367 | +.leaflet-control-scale-line:not(:first-child):not(:last-child) { | |
| 368 | + border-bottom: 2px solid #777; | |
| 369 | + } | |
| 370 | + | |
| 371 | +.leaflet-touch .leaflet-control-attribution, | |
| 372 | +.leaflet-touch .leaflet-control-layers, | |
| 373 | +.leaflet-touch .leaflet-bar { | |
| 374 | + box-shadow: none; | |
| 375 | + } | |
| 376 | +.leaflet-touch .leaflet-control-layers, | |
| 377 | +.leaflet-touch .leaflet-bar { | |
| 378 | + border: 2px solid rgba(0,0,0,0.2); | |
| 379 | + background-clip: padding-box; | |
| 380 | + } | |
| 381 | + | |
| 382 | + | |
| 383 | +/* popup */ | |
| 384 | + | |
| 385 | +.leaflet-popup { | |
| 386 | + position: absolute; | |
| 387 | + text-align: center; | |
| 388 | + } | |
| 389 | +.leaflet-popup-content-wrapper { | |
| 390 | + padding: 1px; | |
| 391 | + text-align: left; | |
| 392 | + border-radius: 12px; | |
| 393 | + } | |
| 394 | +.leaflet-popup-content { | |
| 395 | + margin: 13px 19px; | |
| 396 | + line-height: 1.4; | |
| 397 | + } | |
| 398 | +.leaflet-popup-content p { | |
| 399 | + margin: 18px 0; | |
| 400 | + } | |
| 401 | +.leaflet-popup-tip-container { | |
| 402 | + margin: 0 auto; | |
| 403 | + width: 40px; | |
| 404 | + height: 20px; | |
| 405 | + position: relative; | |
| 406 | + overflow: hidden; | |
| 407 | + } | |
| 408 | +.leaflet-popup-tip { | |
| 409 | + width: 17px; | |
| 410 | + height: 17px; | |
| 411 | + padding: 1px; | |
| 412 | + | |
| 413 | + margin: -10px auto 0; | |
| 414 | + | |
| 415 | + -webkit-transform: rotate(45deg); | |
| 416 | + -moz-transform: rotate(45deg); | |
| 417 | + -ms-transform: rotate(45deg); | |
| 418 | + -o-transform: rotate(45deg); | |
| 419 | + transform: rotate(45deg); | |
| 420 | + } | |
| 421 | +.leaflet-popup-content-wrapper, | |
| 422 | +.leaflet-popup-tip { | |
| 423 | + background: white; | |
| 424 | + | |
| 425 | + box-shadow: 0 3px 14px rgba(0,0,0,0.4); | |
| 426 | + } | |
| 427 | +.leaflet-container a.leaflet-popup-close-button { | |
| 428 | + position: absolute; | |
| 429 | + top: 0; | |
| 430 | + right: 0; | |
| 431 | + padding: 4px 4px 0 0; | |
| 432 | + text-align: center; | |
| 433 | + width: 18px; | |
| 434 | + height: 14px; | |
| 435 | + font: 16px/14px Tahoma, Verdana, sans-serif; | |
| 436 | + color: #c3c3c3; | |
| 437 | + text-decoration: none; | |
| 438 | + font-weight: bold; | |
| 439 | + background: transparent; | |
| 440 | + } | |
| 441 | +.leaflet-container a.leaflet-popup-close-button:hover { | |
| 442 | + color: #999; | |
| 443 | + } | |
| 444 | +.leaflet-popup-scrolled { | |
| 445 | + overflow: auto; | |
| 446 | + border-bottom: 1px solid #ddd; | |
| 447 | + border-top: 1px solid #ddd; | |
| 448 | + } | |
| 449 | + | |
| 450 | +.leaflet-oldie .leaflet-popup-content-wrapper { | |
| 451 | + zoom: 1; | |
| 452 | + } | |
| 453 | +.leaflet-oldie .leaflet-popup-tip { | |
| 454 | + width: 24px; | |
| 455 | + margin: 0 auto; | |
| 456 | + | |
| 457 | + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; | |
| 458 | + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); | |
| 459 | + } | |
| 460 | +.leaflet-oldie .leaflet-popup-tip-container { | |
| 461 | + margin-top: -1px; | |
| 462 | + } | |
| 463 | + | |
| 464 | +.leaflet-oldie .leaflet-control-zoom, | |
| 465 | +.leaflet-oldie .leaflet-control-layers, | |
| 466 | +.leaflet-oldie .leaflet-popup-content-wrapper, | |
| 467 | +.leaflet-oldie .leaflet-popup-tip { | |
| 468 | + border: 1px solid #999; | |
| 469 | + } | |
| 470 | + | |
| 471 | + | |
| 472 | +/* div icon */ | |
| 473 | + | |
| 474 | +.leaflet-div-icon { | |
| 475 | + background: #fff; | |
| 476 | + border: 1px solid #666; | |
| 477 | + } | |
| 0 | 478 | \ No newline at end of file | ... | ... |
datalets/leafletjs-geojson-datalet/leafletsjs/leaflet.js
0 โ 100755
| 1 | +/* | |
| 2 | + Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com | |
| 3 | + (c) 2010-2013, Vladimir Agafonkin | |
| 4 | + (c) 2010-2011, CloudMade | |
| 5 | +*/ | |
| 6 | +!function(t,e,i){var n=t.L,o={};o.version="0.7.3","object"==typeof module&&"object"==typeof module.exports?module.exports=o:"function"==typeof define&&define.amd&&define(o),o.noConflict=function(){return t.L=n,this},t.L=o,o.Util={extend:function(t){var e,i,n,o,s=Array.prototype.slice.call(arguments,1);for(i=0,n=s.length;n>i;i++){o=s[i]||{};for(e in o)o.hasOwnProperty(e)&&(t[e]=o[e])}return t},bind:function(t,e){var i=arguments.length>2?Array.prototype.slice.call(arguments,2):null;return function(){return t.apply(e,i||arguments)}},stamp:function(){var t=0,e="_leaflet_id";return function(i){return i[e]=i[e]||++t,i[e]}}(),invokeEach:function(t,e,i){var n,o;if("object"==typeof t){o=Array.prototype.slice.call(arguments,3);for(n in t)e.apply(i,[n,t[n]].concat(o));return!0}return!1},limitExecByInterval:function(t,e,i){var n,o;return function s(){var a=arguments;return n?void(o=!0):(n=!0,setTimeout(function(){n=!1,o&&(s.apply(i,a),o=!1)},e),void t.apply(i,a))}},falseFn:function(){return!1},formatNum:function(t,e){var i=Math.pow(10,e||5);return Math.round(t*i)/i},trim:function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")},splitWords:function(t){return o.Util.trim(t).split(/\s+/)},setOptions:function(t,e){return t.options=o.extend({},t.options,e),t.options},getParamString:function(t,e,i){var n=[];for(var o in t)n.push(encodeURIComponent(i?o.toUpperCase():o)+"="+encodeURIComponent(t[o]));return(e&&-1!==e.indexOf("?")?"&":"?")+n.join("&")},template:function(t,e){return t.replace(/\{ *([\w_]+) *\}/g,function(t,n){var o=e[n];if(o===i)throw new Error("No value provided for variable "+t);return"function"==typeof o&&(o=o(e)),o})},isArray:Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},emptyImageUrl:"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="},function(){function e(e){var i,n,o=["webkit","moz","o","ms"];for(i=0;i<o.length&&!n;i++)n=t[o[i]+e];return n}function i(e){var i=+new Date,o=Math.max(0,16-(i-n));return n=i+o,t.setTimeout(e,o)}var n=0,s=t.requestAnimationFrame||e("RequestAnimationFrame")||i,a=t.cancelAnimationFrame||e("CancelAnimationFrame")||e("CancelRequestAnimationFrame")||function(e){t.clearTimeout(e)};o.Util.requestAnimFrame=function(e,n,a,r){return e=o.bind(e,n),a&&s===i?void e():s.call(t,e,r)},o.Util.cancelAnimFrame=function(e){e&&a.call(t,e)}}(),o.extend=o.Util.extend,o.bind=o.Util.bind,o.stamp=o.Util.stamp,o.setOptions=o.Util.setOptions,o.Class=function(){},o.Class.extend=function(t){var e=function(){this.initialize&&this.initialize.apply(this,arguments),this._initHooks&&this.callInitHooks()},i=function(){};i.prototype=this.prototype;var n=new i;n.constructor=e,e.prototype=n;for(var s in this)this.hasOwnProperty(s)&&"prototype"!==s&&(e[s]=this[s]);t.statics&&(o.extend(e,t.statics),delete t.statics),t.includes&&(o.Util.extend.apply(null,[n].concat(t.includes)),delete t.includes),t.options&&n.options&&(t.options=o.extend({},n.options,t.options)),o.extend(n,t),n._initHooks=[];var a=this;return e.__super__=a.prototype,n.callInitHooks=function(){if(!this._initHooksCalled){a.prototype.callInitHooks&&a.prototype.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=n._initHooks.length;e>t;t++)n._initHooks[t].call(this)}},e},o.Class.include=function(t){o.extend(this.prototype,t)},o.Class.mergeOptions=function(t){o.extend(this.prototype.options,t)},o.Class.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i)};var s="_leaflet_events";o.Mixin={},o.Mixin.Events={addEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d=this[s]=this[s]||{},p=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)r={action:e,context:i||this},h=t[n],p?(l=h+"_idx",u=l+"_len",c=d[l]=d[l]||{},c[p]||(c[p]=[],d[u]=(d[u]||0)+1),c[p].push(r)):(d[h]=d[h]||[],d[h].push(r));return this},hasEventListeners:function(t){var e=this[s];return!!e&&(t in e&&e[t].length>0||t+"_idx"in e&&e[t+"_idx_len"]>0)},removeEventListener:function(t,e,i){if(!this[s])return this;if(!t)return this.clearAllEventListeners();if(o.Util.invokeEach(t,this.removeEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d,p,_=this[s],m=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)if(r=t[n],u=r+"_idx",c=u+"_len",d=_[u],e){if(h=m&&d?d[m]:_[r]){for(l=h.length-1;l>=0;l--)h[l].action!==e||i&&h[l].context!==i||(p=h.splice(l,1),p[0].action=o.Util.falseFn);i&&d&&0===h.length&&(delete d[m],_[c]--)}}else delete _[r],delete _[u],delete _[c];return this},clearAllEventListeners:function(){return delete this[s],this},fireEvent:function(t,e){if(!this.hasEventListeners(t))return this;var i,n,a,r,h,l=o.Util.extend({},e,{type:t,target:this}),u=this[s];if(u[t])for(i=u[t].slice(),n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);r=u[t+"_idx"];for(h in r)if(i=r[h].slice())for(n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);return this},addOneTimeEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addOneTimeEventListener,this,e,i))return this;var n=o.bind(function(){this.removeEventListener(t,e,i).removeEventListener(t,n,i)},this);return this.addEventListener(t,e,i).addEventListener(t,n,i)}},o.Mixin.Events.on=o.Mixin.Events.addEventListener,o.Mixin.Events.off=o.Mixin.Events.removeEventListener,o.Mixin.Events.once=o.Mixin.Events.addOneTimeEventListener,o.Mixin.Events.fire=o.Mixin.Events.fireEvent,function(){var n="ActiveXObject"in t,s=n&&!e.addEventListener,a=navigator.userAgent.toLowerCase(),r=-1!==a.indexOf("webkit"),h=-1!==a.indexOf("chrome"),l=-1!==a.indexOf("phantom"),u=-1!==a.indexOf("android"),c=-1!==a.search("android [23]"),d=-1!==a.indexOf("gecko"),p=typeof orientation!=i+"",_=t.navigator&&t.navigator.msPointerEnabled&&t.navigator.msMaxTouchPoints&&!t.PointerEvent,m=t.PointerEvent&&t.navigator.pointerEnabled&&t.navigator.maxTouchPoints||_,f="devicePixelRatio"in t&&t.devicePixelRatio>1||"matchMedia"in t&&t.matchMedia("(min-resolution:144dpi)")&&t.matchMedia("(min-resolution:144dpi)").matches,g=e.documentElement,v=n&&"transition"in g.style,y="WebKitCSSMatrix"in t&&"m11"in new t.WebKitCSSMatrix&&!c,P="MozPerspective"in g.style,L="OTransition"in g.style,x=!t.L_DISABLE_3D&&(v||y||P||L)&&!l,w=!t.L_NO_TOUCH&&!l&&function(){var t="ontouchstart";if(m||t in g)return!0;var i=e.createElement("div"),n=!1;return i.setAttribute?(i.setAttribute(t,"return;"),"function"==typeof i[t]&&(n=!0),i.removeAttribute(t),i=null,n):!1}();o.Browser={ie:n,ielt9:s,webkit:r,gecko:d&&!r&&!t.opera&&!n,android:u,android23:c,chrome:h,ie3d:v,webkit3d:y,gecko3d:P,opera3d:L,any3d:x,mobile:p,mobileWebkit:p&&r,mobileWebkit3d:p&&y,mobileOpera:p&&t.opera,touch:w,msPointer:_,pointer:m,retina:f}}(),o.Point=function(t,e,i){this.x=i?Math.round(t):t,this.y=i?Math.round(e):e},o.Point.prototype={clone:function(){return new o.Point(this.x,this.y)},add:function(t){return this.clone()._add(o.point(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(o.point(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},distanceTo:function(t){t=o.point(t);var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},equals:function(t){return t=o.point(t),t.x===this.x&&t.y===this.y},contains:function(t){return t=o.point(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+o.Util.formatNum(this.x)+", "+o.Util.formatNum(this.y)+")"}},o.point=function(t,e,n){return t instanceof o.Point?t:o.Util.isArray(t)?new o.Point(t[0],t[1]):t===i||null===t?t:new o.Point(t,e,n)},o.Bounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.Bounds.prototype={extend:function(t){return t=o.point(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new o.Point((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new o.Point(this.min.x,this.max.y)},getTopRight:function(){return new o.Point(this.max.x,this.min.y)},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,i;return t="number"==typeof t[0]||t instanceof o.Point?o.point(t):o.bounds(t),t instanceof o.Bounds?(e=t.min,i=t.max):e=i=t,e.x>=this.min.x&&i.x<=this.max.x&&e.y>=this.min.y&&i.y<=this.max.y},intersects:function(t){t=o.bounds(t);var e=this.min,i=this.max,n=t.min,s=t.max,a=s.x>=e.x&&n.x<=i.x,r=s.y>=e.y&&n.y<=i.y;return a&&r},isValid:function(){return!(!this.min||!this.max)}},o.bounds=function(t,e){return!t||t instanceof o.Bounds?t:new o.Bounds(t,e)},o.Transformation=function(t,e,i,n){this._a=t,this._b=e,this._c=i,this._d=n},o.Transformation.prototype={transform:function(t,e){return this._transform(t.clone(),e)},_transform:function(t,e){return e=e||1,t.x=e*(this._a*t.x+this._b),t.y=e*(this._c*t.y+this._d),t},untransform:function(t,e){return e=e||1,new o.Point((t.x/e-this._b)/this._a,(t.y/e-this._d)/this._c)}},o.DomUtil={get:function(t){return"string"==typeof t?e.getElementById(t):t},getStyle:function(t,i){var n=t.style[i];if(!n&&t.currentStyle&&(n=t.currentStyle[i]),(!n||"auto"===n)&&e.defaultView){var o=e.defaultView.getComputedStyle(t,null);n=o?o[i]:null}return"auto"===n?null:n},getViewportOffset:function(t){var i,n=0,s=0,a=t,r=e.body,h=e.documentElement;do{if(n+=a.offsetTop||0,s+=a.offsetLeft||0,n+=parseInt(o.DomUtil.getStyle(a,"borderTopWidth"),10)||0,s+=parseInt(o.DomUtil.getStyle(a,"borderLeftWidth"),10)||0,i=o.DomUtil.getStyle(a,"position"),a.offsetParent===r&&"absolute"===i)break;if("fixed"===i){n+=r.scrollTop||h.scrollTop||0,s+=r.scrollLeft||h.scrollLeft||0;break}if("relative"===i&&!a.offsetLeft){var l=o.DomUtil.getStyle(a,"width"),u=o.DomUtil.getStyle(a,"max-width"),c=a.getBoundingClientRect();("none"!==l||"none"!==u)&&(s+=c.left+a.clientLeft),n+=c.top+(r.scrollTop||h.scrollTop||0);break}a=a.offsetParent}while(a);a=t;do{if(a===r)break;n-=a.scrollTop||0,s-=a.scrollLeft||0,a=a.parentNode}while(a);return new o.Point(s,n)},documentIsLtr:function(){return o.DomUtil._docIsLtrCached||(o.DomUtil._docIsLtrCached=!0,o.DomUtil._docIsLtr="ltr"===o.DomUtil.getStyle(e.body,"direction")),o.DomUtil._docIsLtr},create:function(t,i,n){var o=e.createElement(t);return o.className=i,n&&n.appendChild(o),o},hasClass:function(t,e){if(t.classList!==i)return t.classList.contains(e);var n=o.DomUtil._getClass(t);return n.length>0&&new RegExp("(^|\\s)"+e+"(\\s|$)").test(n)},addClass:function(t,e){if(t.classList!==i)for(var n=o.Util.splitWords(e),s=0,a=n.length;a>s;s++)t.classList.add(n[s]);else if(!o.DomUtil.hasClass(t,e)){var r=o.DomUtil._getClass(t);o.DomUtil._setClass(t,(r?r+" ":"")+e)}},removeClass:function(t,e){t.classList!==i?t.classList.remove(e):o.DomUtil._setClass(t,o.Util.trim((" "+o.DomUtil._getClass(t)+" ").replace(" "+e+" "," ")))},_setClass:function(t,e){t.className.baseVal===i?t.className=e:t.className.baseVal=e},_getClass:function(t){return t.className.baseVal===i?t.className:t.className.baseVal},setOpacity:function(t,e){if("opacity"in t.style)t.style.opacity=e;else if("filter"in t.style){var i=!1,n="DXImageTransform.Microsoft.Alpha";try{i=t.filters.item(n)}catch(o){if(1===e)return}e=Math.round(100*e),i?(i.Enabled=100!==e,i.Opacity=e):t.style.filter+=" progid:"+n+"(opacity="+e+")"}},testProp:function(t){for(var i=e.documentElement.style,n=0;n<t.length;n++)if(t[n]in i)return t[n];return!1},getTranslateString:function(t){var e=o.Browser.webkit3d,i="translate"+(e?"3d":"")+"(",n=(e?",0":"")+")";return i+t.x+"px,"+t.y+"px"+n},getScaleString:function(t,e){var i=o.DomUtil.getTranslateString(e.add(e.multiplyBy(-1*t))),n=" scale("+t+") ";return i+n},setPosition:function(t,e,i){t._leaflet_pos=e,!i&&o.Browser.any3d?t.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(e):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){return t._leaflet_pos}},o.DomUtil.TRANSFORM=o.DomUtil.testProp(["transform","WebkitTransform","OTransform","MozTransform","msTransform"]),o.DomUtil.TRANSITION=o.DomUtil.testProp(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),o.DomUtil.TRANSITION_END="webkitTransition"===o.DomUtil.TRANSITION||"OTransition"===o.DomUtil.TRANSITION?o.DomUtil.TRANSITION+"End":"transitionend",function(){if("onselectstart"in e)o.extend(o.DomUtil,{disableTextSelection:function(){o.DomEvent.on(t,"selectstart",o.DomEvent.preventDefault)},enableTextSelection:function(){o.DomEvent.off(t,"selectstart",o.DomEvent.preventDefault)}});else{var i=o.DomUtil.testProp(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);o.extend(o.DomUtil,{disableTextSelection:function(){if(i){var t=e.documentElement.style;this._userSelect=t[i],t[i]="none"}},enableTextSelection:function(){i&&(e.documentElement.style[i]=this._userSelect,delete this._userSelect)}})}o.extend(o.DomUtil,{disableImageDrag:function(){o.DomEvent.on(t,"dragstart",o.DomEvent.preventDefault)},enableImageDrag:function(){o.DomEvent.off(t,"dragstart",o.DomEvent.preventDefault)}})}(),o.LatLng=function(t,e,n){if(t=parseFloat(t),e=parseFloat(e),isNaN(t)||isNaN(e))throw new Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=t,this.lng=e,n!==i&&(this.alt=parseFloat(n))},o.extend(o.LatLng,{DEG_TO_RAD:Math.PI/180,RAD_TO_DEG:180/Math.PI,MAX_MARGIN:1e-9}),o.LatLng.prototype={equals:function(t){if(!t)return!1;t=o.latLng(t);var e=Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng));return e<=o.LatLng.MAX_MARGIN},toString:function(t){return"LatLng("+o.Util.formatNum(this.lat,t)+", "+o.Util.formatNum(this.lng,t)+")"},distanceTo:function(t){t=o.latLng(t);var e=6378137,i=o.LatLng.DEG_TO_RAD,n=(t.lat-this.lat)*i,s=(t.lng-this.lng)*i,a=this.lat*i,r=t.lat*i,h=Math.sin(n/2),l=Math.sin(s/2),u=h*h+l*l*Math.cos(a)*Math.cos(r);return 2*e*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))},wrap:function(t,e){var i=this.lng;return t=t||-180,e=e||180,i=(i+e)%(e-t)+(t>i||i===e?e:t),new o.LatLng(this.lat,i)}},o.latLng=function(t,e){return t instanceof o.LatLng?t:o.Util.isArray(t)?"number"==typeof t[0]||"string"==typeof t[0]?new o.LatLng(t[0],t[1],t[2]):null:t===i||null===t?t:"object"==typeof t&&"lat"in t?new o.LatLng(t.lat,"lng"in t?t.lng:t.lon):e===i?null:new o.LatLng(t,e)},o.LatLngBounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.LatLngBounds.prototype={extend:function(t){if(!t)return this;var e=o.latLng(t);return t=null!==e?e:o.latLngBounds(t),t instanceof o.LatLng?this._southWest||this._northEast?(this._southWest.lat=Math.min(t.lat,this._southWest.lat),this._southWest.lng=Math.min(t.lng,this._southWest.lng),this._northEast.lat=Math.max(t.lat,this._northEast.lat),this._northEast.lng=Math.max(t.lng,this._northEast.lng)):(this._southWest=new o.LatLng(t.lat,t.lng),this._northEast=new o.LatLng(t.lat,t.lng)):t instanceof o.LatLngBounds&&(this.extend(t._southWest),this.extend(t._northEast)),this},pad:function(t){var e=this._southWest,i=this._northEast,n=Math.abs(e.lat-i.lat)*t,s=Math.abs(e.lng-i.lng)*t;return new o.LatLngBounds(new o.LatLng(e.lat-n,e.lng-s),new o.LatLng(i.lat+n,i.lng+s))},getCenter:function(){return new o.LatLng((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new o.LatLng(this.getNorth(),this.getWest())},getSouthEast:function(){return new o.LatLng(this.getSouth(),this.getEast())},getWest:function(){return this._southWest.lng},getSouth:function(){return this._southWest.lat},getEast:function(){return this._northEast.lng},getNorth:function(){return this._northEast.lat},contains:function(t){t="number"==typeof t[0]||t instanceof o.LatLng?o.latLng(t):o.latLngBounds(t);var e,i,n=this._southWest,s=this._northEast;return t instanceof o.LatLngBounds?(e=t.getSouthWest(),i=t.getNorthEast()):e=i=t,e.lat>=n.lat&&i.lat<=s.lat&&e.lng>=n.lng&&i.lng<=s.lng},intersects:function(t){t=o.latLngBounds(t);var e=this._southWest,i=this._northEast,n=t.getSouthWest(),s=t.getNorthEast(),a=s.lat>=e.lat&&n.lat<=i.lat,r=s.lng>=e.lng&&n.lng<=i.lng;return a&&r},toBBoxString:function(){return[this.getWest(),this.getSouth(),this.getEast(),this.getNorth()].join(",")},equals:function(t){return t?(t=o.latLngBounds(t),this._southWest.equals(t.getSouthWest())&&this._northEast.equals(t.getNorthEast())):!1},isValid:function(){return!(!this._southWest||!this._northEast)}},o.latLngBounds=function(t,e){return!t||t instanceof o.LatLngBounds?t:new o.LatLngBounds(t,e)},o.Projection={},o.Projection.SphericalMercator={MAX_LATITUDE:85.0511287798,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=t.lng*e,a=n*e;return a=Math.log(Math.tan(Math.PI/4+a/2)),new o.Point(s,a)},unproject:function(t){var e=o.LatLng.RAD_TO_DEG,i=t.x*e,n=(2*Math.atan(Math.exp(t.y))-Math.PI/2)*e;return new o.LatLng(n,i)}},o.Projection.LonLat={project:function(t){return new o.Point(t.lng,t.lat)},unproject:function(t){return new o.LatLng(t.y,t.x)}},o.CRS={latLngToPoint:function(t,e){var i=this.projection.project(t),n=this.scale(e);return this.transformation._transform(i,n)},pointToLatLng:function(t,e){var i=this.scale(e),n=this.transformation.untransform(t,i);return this.projection.unproject(n)},project:function(t){return this.projection.project(t)},scale:function(t){return 256*Math.pow(2,t)},getSize:function(t){var e=this.scale(t);return o.point(e,e)}},o.CRS.Simple=o.extend({},o.CRS,{projection:o.Projection.LonLat,transformation:new o.Transformation(1,0,-1,0),scale:function(t){return Math.pow(2,t)}}),o.CRS.EPSG3857=o.extend({},o.CRS,{code:"EPSG:3857",projection:o.Projection.SphericalMercator,transformation:new o.Transformation(.5/Math.PI,.5,-.5/Math.PI,.5),project:function(t){var e=this.projection.project(t),i=6378137;return e.multiplyBy(i)}}),o.CRS.EPSG900913=o.extend({},o.CRS.EPSG3857,{code:"EPSG:900913"}),o.CRS.EPSG4326=o.extend({},o.CRS,{code:"EPSG:4326",projection:o.Projection.LonLat,transformation:new o.Transformation(1/360,.5,-1/360,.5)}),o.Map=o.Class.extend({includes:o.Mixin.Events,options:{crs:o.CRS.EPSG3857,fadeAnimation:o.DomUtil.TRANSITION&&!o.Browser.android23,trackResize:!0,markerZoomAnimation:o.DomUtil.TRANSITION&&o.Browser.any3d},initialize:function(t,e){e=o.setOptions(this,e),this._initContainer(t),this._initLayout(),this._onResize=o.bind(this._onResize,this),this._initEvents(),e.maxBounds&&this.setMaxBounds(e.maxBounds),e.center&&e.zoom!==i&&this.setView(o.latLng(e.center),e.zoom,{reset:!0}),this._handlers=[],this._layers={},this._zoomBoundLayers={},this._tileLayersNum=0,this.callInitHooks(),this._addLayers(e.layers)},setView:function(t,e){return e=e===i?this.getZoom():e,this._resetView(o.latLng(t),this._limitZoom(e)),this},setZoom:function(t,e){return this._loaded?this.setView(this.getCenter(),t,{zoom:e}):(this._zoom=this._limitZoom(t),this)},zoomIn:function(t,e){return this.setZoom(this._zoom+(t||1),e)},zoomOut:function(t,e){return this.setZoom(this._zoom-(t||1),e)},setZoomAround:function(t,e,i){var n=this.getZoomScale(e),s=this.getSize().divideBy(2),a=t instanceof o.Point?t:this.latLngToContainerPoint(t),r=a.subtract(s).multiplyBy(1-1/n),h=this.containerPointToLatLng(s.add(r));return this.setView(h,e,{zoom:i})},fitBounds:function(t,e){e=e||{},t=t.getBounds?t.getBounds():o.latLngBounds(t);var i=o.point(e.paddingTopLeft||e.padding||[0,0]),n=o.point(e.paddingBottomRight||e.padding||[0,0]),s=this.getBoundsZoom(t,!1,i.add(n)),a=n.subtract(i).divideBy(2),r=this.project(t.getSouthWest(),s),h=this.project(t.getNorthEast(),s),l=this.unproject(r.add(h).divideBy(2).add(a),s);return s=e&&e.maxZoom?Math.min(e.maxZoom,s):s,this.setView(l,s,e)},fitWorld:function(t){return this.fitBounds([[-90,-180],[90,180]],t)},panTo:function(t,e){return this.setView(t,this._zoom,{pan:e})},panBy:function(t){return this.fire("movestart"),this._rawPanBy(o.point(t)),this.fire("move"),this.fire("moveend")},setMaxBounds:function(t){return t=o.latLngBounds(t),this.options.maxBounds=t,t?(this._loaded&&this._panInsideMaxBounds(),this.on("moveend",this._panInsideMaxBounds,this)):this.off("moveend",this._panInsideMaxBounds,this)},panInsideBounds:function(t,e){var i=this.getCenter(),n=this._limitCenter(i,this._zoom,t);return i.equals(n)?this:this.panTo(n,e)},addLayer:function(t){var e=o.stamp(t);return this._layers[e]?this:(this._layers[e]=t,!t.options||isNaN(t.options.maxZoom)&&isNaN(t.options.minZoom)||(this._zoomBoundLayers[e]=t,this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum++,this._tileLayersToLoad++,t.on("load",this._onTileLayerLoad,this)),this._loaded&&this._layerAdd(t),this)},removeLayer:function(t){var e=o.stamp(t);return this._layers[e]?(this._loaded&&t.onRemove(this),delete this._layers[e],this._loaded&&this.fire("layerremove",{layer:t}),this._zoomBoundLayers[e]&&(delete this._zoomBoundLayers[e],this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum--,this._tileLayersToLoad--,t.off("load",this._onTileLayerLoad,this)),this):this},hasLayer:function(t){return t?o.stamp(t)in this._layers:!1},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},invalidateSize:function(t){if(!this._loaded)return this;t=o.extend({animate:!1,pan:!0},t===!0?{animate:!0}:t);var e=this.getSize();this._sizeChanged=!0,this._initialCenter=null;var i=this.getSize(),n=e.divideBy(2).round(),s=i.divideBy(2).round(),a=n.subtract(s);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(o.bind(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:e,newSize:i})):this},addHandler:function(t,e){if(!e)return this;var i=this[t]=new e(this);return this._handlers.push(i),this.options[t]&&i.enable(),this},remove:function(){this._loaded&&this.fire("unload"),this._initEvents("off");try{delete this._container._leaflet}catch(t){this._container._leaflet=i}return this._clearPanes(),this._clearControlPos&&this._clearControlPos(),this._clearHandlers(),this},getCenter:function(){return this._checkIfLoaded(),this._initialCenter&&!this._moved()?this._initialCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds(),e=this.unproject(t.getBottomLeft()),i=this.unproject(t.getTopRight());return new o.LatLngBounds(e,i)},getMinZoom:function(){return this.options.minZoom===i?this._layersMinZoom===i?0:this._layersMinZoom:this.options.minZoom},getMaxZoom:function(){return this.options.maxZoom===i?this._layersMaxZoom===i?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,e,i){t=o.latLngBounds(t);var n,s=this.getMinZoom()-(e?1:0),a=this.getMaxZoom(),r=this.getSize(),h=t.getNorthWest(),l=t.getSouthEast(),u=!0;i=o.point(i||[0,0]);do s++,n=this.project(l,s).subtract(this.project(h,s)).add(i),u=e?n.x<r.x||n.y<r.y:r.contains(n);while(u&&a>=s);return u&&e?null:e?s:s-1},getSize:function(){return(!this._size||this._sizeChanged)&&(this._size=new o.Point(this._container.clientWidth,this._container.clientHeight),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(){var t=this._getTopLeftPoint();return new o.Bounds(t,t.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._initialTopLeftPoint},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t){var e=this.options.crs;return e.scale(t)/e.scale(this._zoom)},getScaleZoom:function(t){return this._zoom+Math.log(t)/Math.LN2},project:function(t,e){return e=e===i?this._zoom:e,this.options.crs.latLngToPoint(o.latLng(t),e)},unproject:function(t,e){return e=e===i?this._zoom:e,this.options.crs.pointToLatLng(o.point(t),e)},layerPointToLatLng:function(t){var e=o.point(t).add(this.getPixelOrigin());return this.unproject(e)},latLngToLayerPoint:function(t){var e=this.project(o.latLng(t))._round();return e._subtract(this.getPixelOrigin())},containerPointToLayerPoint:function(t){return o.point(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return o.point(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var e=this.containerPointToLayerPoint(o.point(t));return this.layerPointToLatLng(e)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(o.latLng(t)))},mouseEventToContainerPoint:function(t){return o.DomEvent.getMousePosition(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var e=this._container=o.DomUtil.get(t);if(!e)throw new Error("Map container not found.");if(e._leaflet)throw new Error("Map container is already initialized.");e._leaflet=!0},_initLayout:function(){var t=this._container;o.DomUtil.addClass(t,"leaflet-container"+(o.Browser.touch?" leaflet-touch":"")+(o.Browser.retina?" leaflet-retina":"")+(o.Browser.ielt9?" leaflet-oldie":"")+(this.options.fadeAnimation?" leaflet-fade-anim":""));var e=o.DomUtil.getStyle(t,"position");"absolute"!==e&&"relative"!==e&&"fixed"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._mapPane=t.mapPane=this._createPane("leaflet-map-pane",this._container),this._tilePane=t.tilePane=this._createPane("leaflet-tile-pane",this._mapPane),t.objectsPane=this._createPane("leaflet-objects-pane",this._mapPane),t.shadowPane=this._createPane("leaflet-shadow-pane"),t.overlayPane=this._createPane("leaflet-overlay-pane"),t.markerPane=this._createPane("leaflet-marker-pane"),t.popupPane=this._createPane("leaflet-popup-pane");var e=" leaflet-zoom-hide";this.options.markerZoomAnimation||(o.DomUtil.addClass(t.markerPane,e),o.DomUtil.addClass(t.shadowPane,e),o.DomUtil.addClass(t.popupPane,e))},_createPane:function(t,e){return o.DomUtil.create("div",t,e||this._panes.objectsPane)},_clearPanes:function(){this._container.removeChild(this._mapPane)},_addLayers:function(t){t=t?o.Util.isArray(t)?t:[t]:[];for(var e=0,i=t.length;i>e;e++)this.addLayer(t[e])},_resetView:function(t,e,i,n){var s=this._zoom!==e;n||(this.fire("movestart"),s&&this.fire("zoomstart")),this._zoom=e,this._initialCenter=t,this._initialTopLeftPoint=this._getNewTopLeftPoint(t),i?this._initialTopLeftPoint._add(this._getMapPanePos()):o.DomUtil.setPosition(this._mapPane,new o.Point(0,0)),this._tileLayersToLoad=this._tileLayersNum;var a=!this._loaded;this._loaded=!0,this.fire("viewreset",{hard:!i}),a&&(this.fire("load"),this.eachLayer(this._layerAdd,this)),this.fire("move"),(s||n)&&this.fire("zoomend"),this.fire("moveend",{hard:!i})},_rawPanBy:function(t){o.DomUtil.setPosition(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_updateZoomLevels:function(){var t,e=1/0,n=-1/0,o=this._getZoomSpan();for(t in this._zoomBoundLayers){var s=this._zoomBoundLayers[t];isNaN(s.options.minZoom)||(e=Math.min(e,s.options.minZoom)),isNaN(s.options.maxZoom)||(n=Math.max(n,s.options.maxZoom))}t===i?this._layersMaxZoom=this._layersMinZoom=i:(this._layersMaxZoom=n,this._layersMinZoom=e),o!==this._getZoomSpan()&&this.fire("zoomlevelschange")},_panInsideMaxBounds:function(){this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(e){if(o.DomEvent){e=e||"on",o.DomEvent[e](this._container,"click",this._onMouseClick,this);var i,n,s=["dblclick","mousedown","mouseup","mouseenter","mouseleave","mousemove","contextmenu"];for(i=0,n=s.length;n>i;i++)o.DomEvent[e](this._container,s[i],this._fireMouseEvent,this);this.options.trackResize&&o.DomEvent[e](t,"resize",this._onResize,this)}},_onResize:function(){o.Util.cancelAnimFrame(this._resizeRequest),this._resizeRequest=o.Util.requestAnimFrame(function(){this.invalidateSize({debounceMoveend:!0})},this,!1,this._container)},_onMouseClick:function(t){!this._loaded||!t._simulated&&(this.dragging&&this.dragging.moved()||this.boxZoom&&this.boxZoom.moved())||o.DomEvent._skipped(t)||(this.fire("preclick"),this._fireMouseEvent(t))},_fireMouseEvent:function(t){if(this._loaded&&!o.DomEvent._skipped(t)){var e=t.type;if(e="mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,this.hasEventListeners(e)){"contextmenu"===e&&o.DomEvent.preventDefault(t);var i=this.mouseEventToContainerPoint(t),n=this.containerPointToLayerPoint(i),s=this.layerPointToLatLng(n);this.fire(e,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t})}}},_onTileLayerLoad:function(){this._tileLayersToLoad--,this._tileLayersNum&&!this._tileLayersToLoad&&this.fire("tilelayersload")},_clearHandlers:function(){for(var t=0,e=this._handlers.length;e>t;t++)this._handlers[t].disable()},whenReady:function(t,e){return this._loaded?t.call(e||this,this):this.on("load",t,e),this},_layerAdd:function(t){t.onAdd(this),this.fire("layeradd",{layer:t})},_getMapPanePos:function(){return o.DomUtil.getPosition(this._mapPane)},_moved:function(){var t=this._getMapPanePos();return t&&!t.equals([0,0])},_getTopLeftPoint:function(){return this.getPixelOrigin().subtract(this._getMapPanePos())},_getNewTopLeftPoint:function(t,e){var i=this.getSize()._divideBy(2);return this.project(t,e)._subtract(i)._round()},_latLngToNewLayerPoint:function(t,e,i){var n=this._getNewTopLeftPoint(i,e).add(this._getMapPanePos());return this.project(t,e)._subtract(n)},_getCenterLayerPoint:function(){return this.containerPointToLayerPoint(this.getSize()._divideBy(2))},_getCenterOffset:function(t){return this.latLngToLayerPoint(t).subtract(this._getCenterLayerPoint())},_limitCenter:function(t,e,i){if(!i)return t;var n=this.project(t,e),s=this.getSize().divideBy(2),a=new o.Bounds(n.subtract(s),n.add(s)),r=this._getBoundsOffset(a,i,e);return this.unproject(n.add(r),e)},_limitOffset:function(t,e){if(!e)return t;var i=this.getPixelBounds(),n=new o.Bounds(i.min.add(t),i.max.add(t));return t.add(this._getBoundsOffset(n,e))},_getBoundsOffset:function(t,e,i){var n=this.project(e.getNorthWest(),i).subtract(t.min),s=this.project(e.getSouthEast(),i).subtract(t.max),a=this._rebound(n.x,-s.x),r=this._rebound(n.y,-s.y);return new o.Point(a,r)},_rebound:function(t,e){return t+e>0?Math.round(t-e)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(e))},_limitZoom:function(t){var e=this.getMinZoom(),i=this.getMaxZoom();return Math.max(e,Math.min(i,t))}}),o.map=function(t,e){return new o.Map(t,e)},o.Projection.Mercator={MAX_LATITUDE:85.0840591556,R_MINOR:6356752.314245179,R_MAJOR:6378137,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=this.R_MAJOR,a=this.R_MINOR,r=t.lng*e*s,h=n*e,l=a/s,u=Math.sqrt(1-l*l),c=u*Math.sin(h);c=Math.pow((1-c)/(1+c),.5*u);var d=Math.tan(.5*(.5*Math.PI-h))/c;return h=-s*Math.log(d),new o.Point(r,h)},unproject:function(t){for(var e,i=o.LatLng.RAD_TO_DEG,n=this.R_MAJOR,s=this.R_MINOR,a=t.x*i/n,r=s/n,h=Math.sqrt(1-r*r),l=Math.exp(-t.y/n),u=Math.PI/2-2*Math.atan(l),c=15,d=1e-7,p=c,_=.1;Math.abs(_)>d&&--p>0;)e=h*Math.sin(u),_=Math.PI/2-2*Math.atan(l*Math.pow((1-e)/(1+e),.5*h))-u,u+=_; | |
| 7 | +return new o.LatLng(u*i,a)}},o.CRS.EPSG3395=o.extend({},o.CRS,{code:"EPSG:3395",projection:o.Projection.Mercator,transformation:function(){var t=o.Projection.Mercator,e=t.R_MAJOR,i=.5/(Math.PI*e);return new o.Transformation(i,.5,-i,.5)}()}),o.TileLayer=o.Class.extend({includes:o.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",zoomOffset:0,opacity:1,unloadInvisibleTiles:o.Browser.mobile,updateWhenIdle:o.Browser.mobile},initialize:function(t,e){e=o.setOptions(this,e),e.detectRetina&&o.Browser.retina&&e.maxZoom>0&&(e.tileSize=Math.floor(e.tileSize/2),e.zoomOffset++,e.minZoom>0&&e.minZoom--,this.options.maxZoom--),e.bounds&&(e.bounds=o.latLngBounds(e.bounds)),this._url=t;var i=this.options.subdomains;"string"==typeof i&&(this.options.subdomains=i.split(""))},onAdd:function(t){this._map=t,this._animated=t._zoomAnimated,this._initContainer(),t.on({viewreset:this._reset,moveend:this._update},this),this._animated&&t.on({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||(this._limitedUpdate=o.Util.limitExecByInterval(this._update,150,this),t.on("move",this._limitedUpdate,this)),this._reset(),this._update()},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._container.parentNode.removeChild(this._container),t.off({viewreset:this._reset,moveend:this._update},this),this._animated&&t.off({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||t.off("move",this._limitedUpdate,this),this._container=null,this._map=null},bringToFront:function(){var t=this._map._panes.tilePane;return this._container&&(t.appendChild(this._container),this._setAutoZIndex(t,Math.max)),this},bringToBack:function(){var t=this._map._panes.tilePane;return this._container&&(t.insertBefore(this._container,t.firstChild),this._setAutoZIndex(t,Math.min)),this},getAttribution:function(){return this.options.attribution},getContainer:function(){return this._container},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},setUrl:function(t,e){return this._url=t,e||this.redraw(),this},redraw:function(){return this._map&&(this._reset({hard:!0}),this._update()),this},_updateZIndex:function(){this._container&&this.options.zIndex!==i&&(this._container.style.zIndex=this.options.zIndex)},_setAutoZIndex:function(t,e){var i,n,o,s=t.children,a=-e(1/0,-1/0);for(n=0,o=s.length;o>n;n++)s[n]!==this._container&&(i=parseInt(s[n].style.zIndex,10),isNaN(i)||(a=e(a,i)));this.options.zIndex=this._container.style.zIndex=(isFinite(a)?a:0)+e(1,-1)},_updateOpacity:function(){var t,e=this._tiles;if(o.Browser.ielt9)for(t in e)o.DomUtil.setOpacity(e[t],this.options.opacity);else o.DomUtil.setOpacity(this._container,this.options.opacity)},_initContainer:function(){var t=this._map._panes.tilePane;if(!this._container){if(this._container=o.DomUtil.create("div","leaflet-layer"),this._updateZIndex(),this._animated){var e="leaflet-tile-container";this._bgBuffer=o.DomUtil.create("div",e,this._container),this._tileContainer=o.DomUtil.create("div",e,this._container)}else this._tileContainer=this._container;t.appendChild(this._container),this.options.opacity<1&&this._updateOpacity()}},_reset:function(t){for(var e in this._tiles)this.fire("tileunload",{tile:this._tiles[e]});this._tiles={},this._tilesToLoad=0,this.options.reuseTiles&&(this._unusedTiles=[]),this._tileContainer.innerHTML="",this._animated&&t&&t.hard&&this._clearBgBuffer(),this._initContainer()},_getTileSize:function(){var t=this._map,e=t.getZoom()+this.options.zoomOffset,i=this.options.maxNativeZoom,n=this.options.tileSize;return i&&e>i&&(n=Math.round(t.getZoomScale(e)/t.getZoomScale(i)*n)),n},_update:function(){if(this._map){var t=this._map,e=t.getPixelBounds(),i=t.getZoom(),n=this._getTileSize();if(!(i>this.options.maxZoom||i<this.options.minZoom)){var s=o.bounds(e.min.divideBy(n)._floor(),e.max.divideBy(n)._floor());this._addTilesFromCenterOut(s),(this.options.unloadInvisibleTiles||this.options.reuseTiles)&&this._removeOtherTiles(s)}}},_addTilesFromCenterOut:function(t){var i,n,s,a=[],r=t.getCenter();for(i=t.min.y;i<=t.max.y;i++)for(n=t.min.x;n<=t.max.x;n++)s=new o.Point(n,i),this._tileShouldBeLoaded(s)&&a.push(s);var h=a.length;if(0!==h){a.sort(function(t,e){return t.distanceTo(r)-e.distanceTo(r)});var l=e.createDocumentFragment();for(this._tilesToLoad||this.fire("loading"),this._tilesToLoad+=h,n=0;h>n;n++)this._addTile(a[n],l);this._tileContainer.appendChild(l)}},_tileShouldBeLoaded:function(t){if(t.x+":"+t.y in this._tiles)return!1;var e=this.options;if(!e.continuousWorld){var i=this._getWrapTileNum();if(e.noWrap&&(t.x<0||t.x>=i.x)||t.y<0||t.y>=i.y)return!1}if(e.bounds){var n=e.tileSize,o=t.multiplyBy(n),s=o.add([n,n]),a=this._map.unproject(o),r=this._map.unproject(s);if(e.continuousWorld||e.noWrap||(a=a.wrap(),r=r.wrap()),!e.bounds.intersects([a,r]))return!1}return!0},_removeOtherTiles:function(t){var e,i,n,o;for(o in this._tiles)e=o.split(":"),i=parseInt(e[0],10),n=parseInt(e[1],10),(i<t.min.x||i>t.max.x||n<t.min.y||n>t.max.y)&&this._removeTile(o)},_removeTile:function(t){var e=this._tiles[t];this.fire("tileunload",{tile:e,url:e.src}),this.options.reuseTiles?(o.DomUtil.removeClass(e,"leaflet-tile-loaded"),this._unusedTiles.push(e)):e.parentNode===this._tileContainer&&this._tileContainer.removeChild(e),o.Browser.android||(e.onload=null,e.src=o.Util.emptyImageUrl),delete this._tiles[t]},_addTile:function(t,e){var i=this._getTilePos(t),n=this._getTile();o.DomUtil.setPosition(n,i,o.Browser.chrome),this._tiles[t.x+":"+t.y]=n,this._loadTile(n,t),n.parentNode!==this._tileContainer&&e.appendChild(n)},_getZoomForUrl:function(){var t=this.options,e=this._map.getZoom();return t.zoomReverse&&(e=t.maxZoom-e),e+=t.zoomOffset,t.maxNativeZoom?Math.min(e,t.maxNativeZoom):e},_getTilePos:function(t){var e=this._map.getPixelOrigin(),i=this._getTileSize();return t.multiplyBy(i).subtract(e)},getTileUrl:function(t){return o.Util.template(this._url,o.extend({s:this._getSubdomain(t),z:t.z,x:t.x,y:t.y},this.options))},_getWrapTileNum:function(){var t=this._map.options.crs,e=t.getSize(this._map.getZoom());return e.divideBy(this._getTileSize())._floor()},_adjustTilePoint:function(t){var e=this._getWrapTileNum();this.options.continuousWorld||this.options.noWrap||(t.x=(t.x%e.x+e.x)%e.x),this.options.tms&&(t.y=e.y-t.y-1),t.z=this._getZoomForUrl()},_getSubdomain:function(t){var e=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[e]},_getTile:function(){if(this.options.reuseTiles&&this._unusedTiles.length>0){var t=this._unusedTiles.pop();return this._resetTile(t),t}return this._createTile()},_resetTile:function(){},_createTile:function(){var t=o.DomUtil.create("img","leaflet-tile");return t.style.width=t.style.height=this._getTileSize()+"px",t.galleryimg="no",t.onselectstart=t.onmousemove=o.Util.falseFn,o.Browser.ielt9&&this.options.opacity!==i&&o.DomUtil.setOpacity(t,this.options.opacity),o.Browser.mobileWebkit3d&&(t.style.WebkitBackfaceVisibility="hidden"),t},_loadTile:function(t,e){t._layer=this,t.onload=this._tileOnLoad,t.onerror=this._tileOnError,this._adjustTilePoint(e),t.src=this.getTileUrl(e),this.fire("tileloadstart",{tile:t,url:t.src})},_tileLoaded:function(){this._tilesToLoad--,this._animated&&o.DomUtil.addClass(this._tileContainer,"leaflet-zoom-animated"),this._tilesToLoad||(this.fire("load"),this._animated&&(clearTimeout(this._clearBgBufferTimer),this._clearBgBufferTimer=setTimeout(o.bind(this._clearBgBuffer,this),500)))},_tileOnLoad:function(){var t=this._layer;this.src!==o.Util.emptyImageUrl&&(o.DomUtil.addClass(this,"leaflet-tile-loaded"),t.fire("tileload",{tile:this,url:this.src})),t._tileLoaded()},_tileOnError:function(){var t=this._layer;t.fire("tileerror",{tile:this,url:this.src});var e=t.options.errorTileUrl;e&&(this.src=e),t._tileLoaded()}}),o.tileLayer=function(t,e){return new o.TileLayer(t,e)},o.TileLayer.WMS=o.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(t,e){this._url=t;var i=o.extend({},this.defaultWmsParams),n=e.tileSize||this.options.tileSize;i.width=i.height=e.detectRetina&&o.Browser.retina?2*n:n;for(var s in e)this.options.hasOwnProperty(s)||"crs"===s||(i[s]=e[s]);this.wmsParams=i,o.setOptions(this,e)},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var e=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[e]=this._crs.code,o.TileLayer.prototype.onAdd.call(this,t)},getTileUrl:function(t){var e=this._map,i=this.options.tileSize,n=t.multiplyBy(i),s=n.add([i,i]),a=this._crs.project(e.unproject(n,t.z)),r=this._crs.project(e.unproject(s,t.z)),h=this._wmsVersion>=1.3&&this._crs===o.CRS.EPSG4326?[r.y,a.x,a.y,r.x].join(","):[a.x,r.y,r.x,a.y].join(","),l=o.Util.template(this._url,{s:this._getSubdomain(t)});return l+o.Util.getParamString(this.wmsParams,l,!0)+"&BBOX="+h},setParams:function(t,e){return o.extend(this.wmsParams,t),e||this.redraw(),this}}),o.tileLayer.wms=function(t,e){return new o.TileLayer.WMS(t,e)},o.TileLayer.Canvas=o.TileLayer.extend({options:{async:!1},initialize:function(t){o.setOptions(this,t)},redraw:function(){this._map&&(this._reset({hard:!0}),this._update());for(var t in this._tiles)this._redrawTile(this._tiles[t]);return this},_redrawTile:function(t){this.drawTile(t,t._tilePoint,this._map._zoom)},_createTile:function(){var t=o.DomUtil.create("canvas","leaflet-tile");return t.width=t.height=this.options.tileSize,t.onselectstart=t.onmousemove=o.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t._tilePoint=e,this._redrawTile(t),this.options.async||this.tileDrawn(t)},drawTile:function(){},tileDrawn:function(t){this._tileOnLoad.call(t)}}),o.tileLayer.canvas=function(t){return new o.TileLayer.Canvas(t)},o.ImageOverlay=o.Class.extend({includes:o.Mixin.Events,options:{opacity:1},initialize:function(t,e,i){this._url=t,this._bounds=o.latLngBounds(e),o.setOptions(this,i)},onAdd:function(t){this._map=t,this._image||this._initImage(),t._panes.overlayPane.appendChild(this._image),t.on("viewreset",this._reset,this),t.options.zoomAnimation&&o.Browser.any3d&&t.on("zoomanim",this._animateZoom,this),this._reset()},onRemove:function(t){t.getPanes().overlayPane.removeChild(this._image),t.off("viewreset",this._reset,this),t.options.zoomAnimation&&t.off("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},setOpacity:function(t){return this.options.opacity=t,this._updateOpacity(),this},bringToFront:function(){return this._image&&this._map._panes.overlayPane.appendChild(this._image),this},bringToBack:function(){var t=this._map._panes.overlayPane;return this._image&&t.insertBefore(this._image,t.firstChild),this},setUrl:function(t){this._url=t,this._image.src=this._url},getAttribution:function(){return this.options.attribution},_initImage:function(){this._image=o.DomUtil.create("img","leaflet-image-layer"),this._map.options.zoomAnimation&&o.Browser.any3d?o.DomUtil.addClass(this._image,"leaflet-zoom-animated"):o.DomUtil.addClass(this._image,"leaflet-zoom-hide"),this._updateOpacity(),o.extend(this._image,{galleryimg:"no",onselectstart:o.Util.falseFn,onmousemove:o.Util.falseFn,onload:o.bind(this._onImageLoad,this),src:this._url})},_animateZoom:function(t){var e=this._map,i=this._image,n=e.getZoomScale(t.zoom),s=this._bounds.getNorthWest(),a=this._bounds.getSouthEast(),r=e._latLngToNewLayerPoint(s,t.zoom,t.center),h=e._latLngToNewLayerPoint(a,t.zoom,t.center)._subtract(r),l=r._add(h._multiplyBy(.5*(1-1/n)));i.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(l)+" scale("+n+") "},_reset:function(){var t=this._image,e=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),i=this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(e);o.DomUtil.setPosition(t,e),t.style.width=i.x+"px",t.style.height=i.y+"px"},_onImageLoad:function(){this.fire("load")},_updateOpacity:function(){o.DomUtil.setOpacity(this._image,this.options.opacity)}}),o.imageOverlay=function(t,e,i){return new o.ImageOverlay(t,e,i)},o.Icon=o.Class.extend({options:{className:""},initialize:function(t){o.setOptions(this,t)},createIcon:function(t){return this._createIcon("icon",t)},createShadow:function(t){return this._createIcon("shadow",t)},_createIcon:function(t,e){var i=this._getIconUrl(t);if(!i){if("icon"===t)throw new Error("iconUrl not set in Icon options (see the docs).");return null}var n;return n=e&&"IMG"===e.tagName?this._createImg(i,e):this._createImg(i),this._setIconStyles(n,t),n},_setIconStyles:function(t,e){var i,n=this.options,s=o.point(n[e+"Size"]);i=o.point("shadow"===e?n.shadowAnchor||n.iconAnchor:n.iconAnchor),!i&&s&&(i=s.divideBy(2,!0)),t.className="leaflet-marker-"+e+" "+n.className,i&&(t.style.marginLeft=-i.x+"px",t.style.marginTop=-i.y+"px"),s&&(t.style.width=s.x+"px",t.style.height=s.y+"px")},_createImg:function(t,i){return i=i||e.createElement("img"),i.src=t,i},_getIconUrl:function(t){return o.Browser.retina&&this.options[t+"RetinaUrl"]?this.options[t+"RetinaUrl"]:this.options[t+"Url"]}}),o.icon=function(t){return new o.Icon(t)},o.Icon.Default=o.Icon.extend({options:{iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],shadowSize:[41,41]},_getIconUrl:function(t){var e=t+"Url";if(this.options[e])return this.options[e];o.Browser.retina&&"icon"===t&&(t+="-2x");var i=o.Icon.Default.imagePath;if(!i)throw new Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");return i+"/marker-"+t+".png"}}),o.Icon.Default.imagePath=function(){var t,i,n,o,s,a=e.getElementsByTagName("script"),r=/[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/;for(t=0,i=a.length;i>t;t++)if(n=a[t].src,o=n.match(r))return s=n.split(r)[0],(s?s+"/":"")+"images"}(),o.Marker=o.Class.extend({includes:o.Mixin.Events,options:{icon:new o.Icon.Default,title:"",alt:"",clickable:!0,draggable:!1,keyboard:!0,zIndexOffset:0,opacity:1,riseOnHover:!1,riseOffset:250},initialize:function(t,e){o.setOptions(this,e),this._latlng=o.latLng(t)},onAdd:function(t){this._map=t,t.on("viewreset",this.update,this),this._initIcon(),this.update(),this.fire("add"),t.options.zoomAnimation&&t.options.markerZoomAnimation&&t.on("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this.dragging&&this.dragging.disable(),this._removeIcon(),this._removeShadow(),this.fire("remove"),t.off({viewreset:this.update,zoomanim:this._animateZoom},this),this._map=null},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this.update(),this.fire("move",{latlng:this._latlng})},setZIndexOffset:function(t){return this.options.zIndexOffset=t,this.update(),this},setIcon:function(t){return this.options.icon=t,this._map&&(this._initIcon(),this.update()),this._popup&&this.bindPopup(this._popup),this},update:function(){if(this._icon){var t=this._map.latLngToLayerPoint(this._latlng).round();this._setPos(t)}return this},_initIcon:function(){var t=this.options,e=this._map,i=e.options.zoomAnimation&&e.options.markerZoomAnimation,n=i?"leaflet-zoom-animated":"leaflet-zoom-hide",s=t.icon.createIcon(this._icon),a=!1;s!==this._icon&&(this._icon&&this._removeIcon(),a=!0,t.title&&(s.title=t.title),t.alt&&(s.alt=t.alt)),o.DomUtil.addClass(s,n),t.keyboard&&(s.tabIndex="0"),this._icon=s,this._initInteraction(),t.riseOnHover&&o.DomEvent.on(s,"mouseover",this._bringToFront,this).on(s,"mouseout",this._resetZIndex,this);var r=t.icon.createShadow(this._shadow),h=!1;r!==this._shadow&&(this._removeShadow(),h=!0),r&&o.DomUtil.addClass(r,n),this._shadow=r,t.opacity<1&&this._updateOpacity();var l=this._map._panes;a&&l.markerPane.appendChild(this._icon),r&&h&&l.shadowPane.appendChild(this._shadow)},_removeIcon:function(){this.options.riseOnHover&&o.DomEvent.off(this._icon,"mouseover",this._bringToFront).off(this._icon,"mouseout",this._resetZIndex),this._map._panes.markerPane.removeChild(this._icon),this._icon=null},_removeShadow:function(){this._shadow&&this._map._panes.shadowPane.removeChild(this._shadow),this._shadow=null},_setPos:function(t){o.DomUtil.setPosition(this._icon,t),this._shadow&&o.DomUtil.setPosition(this._shadow,t),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},_updateZIndex:function(t){this._icon.style.zIndex=this._zIndex+t},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center).round();this._setPos(e)},_initInteraction:function(){if(this.options.clickable){var t=this._icon,e=["dblclick","mousedown","mouseover","mouseout","contextmenu"];o.DomUtil.addClass(t,"leaflet-clickable"),o.DomEvent.on(t,"click",this._onMouseClick,this),o.DomEvent.on(t,"keypress",this._onKeyPress,this);for(var i=0;i<e.length;i++)o.DomEvent.on(t,e[i],this._fireMouseEvent,this);o.Handler.MarkerDrag&&(this.dragging=new o.Handler.MarkerDrag(this),this.options.draggable&&this.dragging.enable())}},_onMouseClick:function(t){var e=this.dragging&&this.dragging.moved();(this.hasEventListeners(t.type)||e)&&o.DomEvent.stopPropagation(t),e||(this.dragging&&this.dragging._enabled||!this._map.dragging||!this._map.dragging.moved())&&this.fire(t.type,{originalEvent:t,latlng:this._latlng})},_onKeyPress:function(t){13===t.keyCode&&this.fire("click",{originalEvent:t,latlng:this._latlng})},_fireMouseEvent:function(t){this.fire(t.type,{originalEvent:t,latlng:this._latlng}),"contextmenu"===t.type&&this.hasEventListeners(t.type)&&o.DomEvent.preventDefault(t),"mousedown"!==t.type?o.DomEvent.stopPropagation(t):o.DomEvent.preventDefault(t)},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},_updateOpacity:function(){o.DomUtil.setOpacity(this._icon,this.options.opacity),this._shadow&&o.DomUtil.setOpacity(this._shadow,this.options.opacity)},_bringToFront:function(){this._updateZIndex(this.options.riseOffset)},_resetZIndex:function(){this._updateZIndex(0)}}),o.marker=function(t,e){return new o.Marker(t,e)},o.DivIcon=o.Icon.extend({options:{iconSize:[12,12],className:"leaflet-div-icon",html:!1},createIcon:function(t){var i=t&&"DIV"===t.tagName?t:e.createElement("div"),n=this.options;return i.innerHTML=n.html!==!1?n.html:"",n.bgPos&&(i.style.backgroundPosition=-n.bgPos.x+"px "+-n.bgPos.y+"px"),this._setIconStyles(i,"icon"),i},createShadow:function(){return null}}),o.divIcon=function(t){return new o.DivIcon(t)},o.Map.mergeOptions({closePopupOnClick:!0}),o.Popup=o.Class.extend({includes:o.Mixin.Events,options:{minWidth:50,maxWidth:300,autoPan:!0,closeButton:!0,offset:[0,7],autoPanPadding:[5,5],keepInView:!1,className:"",zoomAnimation:!0},initialize:function(t,e){o.setOptions(this,t),this._source=e,this._animated=o.Browser.any3d&&this.options.zoomAnimation,this._isOpen=!1},onAdd:function(t){this._map=t,this._container||this._initLayout();var e=t.options.fadeAnimation;e&&o.DomUtil.setOpacity(this._container,0),t._panes.popupPane.appendChild(this._container),t.on(this._getEvents(),this),this.update(),e&&o.DomUtil.setOpacity(this._container,1),this.fire("open"),t.fire("popupopen",{popup:this}),this._source&&this._source.fire("popupopen",{popup:this})},addTo:function(t){return t.addLayer(this),this},openOn:function(t){return t.openPopup(this),this},onRemove:function(t){t._panes.popupPane.removeChild(this._container),o.Util.falseFn(this._container.offsetWidth),t.off(this._getEvents(),this),t.options.fadeAnimation&&o.DomUtil.setOpacity(this._container,0),this._map=null,this.fire("close"),t.fire("popupclose",{popup:this}),this._source&&this._source.fire("popupclose",{popup:this})},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this._map&&(this._updatePosition(),this._adjustPan()),this},getContent:function(){return this._content},setContent:function(t){return this._content=t,this.update(),this},update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updateLayout(),this._updatePosition(),this._container.style.visibility="",this._adjustPan())},_getEvents:function(){var t={viewreset:this._updatePosition};return this._animated&&(t.zoomanim=this._zoomAnimation),("closeOnClick"in this.options?this.options.closeOnClick:this._map.options.closePopupOnClick)&&(t.preclick=this._close),this.options.keepInView&&(t.moveend=this._adjustPan),t},_close:function(){this._map&&this._map.closePopup(this)},_initLayout:function(){var t,e="leaflet-popup",i=e+" "+this.options.className+" leaflet-zoom-"+(this._animated?"animated":"hide"),n=this._container=o.DomUtil.create("div",i);this.options.closeButton&&(t=this._closeButton=o.DomUtil.create("a",e+"-close-button",n),t.href="#close",t.innerHTML="×",o.DomEvent.disableClickPropagation(t),o.DomEvent.on(t,"click",this._onCloseButtonClick,this));var s=this._wrapper=o.DomUtil.create("div",e+"-content-wrapper",n);o.DomEvent.disableClickPropagation(s),this._contentNode=o.DomUtil.create("div",e+"-content",s),o.DomEvent.disableScrollPropagation(this._contentNode),o.DomEvent.on(s,"contextmenu",o.DomEvent.stopPropagation),this._tipContainer=o.DomUtil.create("div",e+"-tip-container",n),this._tip=o.DomUtil.create("div",e+"-tip",this._tipContainer)},_updateContent:function(){if(this._content){if("string"==typeof this._content)this._contentNode.innerHTML=this._content;else{for(;this._contentNode.hasChildNodes();)this._contentNode.removeChild(this._contentNode.firstChild);this._contentNode.appendChild(this._content)}this.fire("contentupdate")}},_updateLayout:function(){var t=this._contentNode,e=t.style;e.width="",e.whiteSpace="nowrap";var i=t.offsetWidth;i=Math.min(i,this.options.maxWidth),i=Math.max(i,this.options.minWidth),e.width=i+1+"px",e.whiteSpace="",e.height="";var n=t.offsetHeight,s=this.options.maxHeight,a="leaflet-popup-scrolled";s&&n>s?(e.height=s+"px",o.DomUtil.addClass(t,a)):o.DomUtil.removeClass(t,a),this._containerWidth=this._container.offsetWidth},_updatePosition:function(){if(this._map){var t=this._map.latLngToLayerPoint(this._latlng),e=this._animated,i=o.point(this.options.offset);e&&o.DomUtil.setPosition(this._container,t),this._containerBottom=-i.y-(e?0:t.y),this._containerLeft=-Math.round(this._containerWidth/2)+i.x+(e?0:t.x),this._container.style.bottom=this._containerBottom+"px",this._container.style.left=this._containerLeft+"px"}},_zoomAnimation:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);o.DomUtil.setPosition(this._container,e)},_adjustPan:function(){if(this.options.autoPan){var t=this._map,e=this._container.offsetHeight,i=this._containerWidth,n=new o.Point(this._containerLeft,-e-this._containerBottom);this._animated&&n._add(o.DomUtil.getPosition(this._container));var s=t.layerPointToContainerPoint(n),a=o.point(this.options.autoPanPadding),r=o.point(this.options.autoPanPaddingTopLeft||a),h=o.point(this.options.autoPanPaddingBottomRight||a),l=t.getSize(),u=0,c=0;s.x+i+h.x>l.x&&(u=s.x+i-l.x+h.x),s.x-u-r.x<0&&(u=s.x-r.x),s.y+e+h.y>l.y&&(c=s.y+e-l.y+h.y),s.y-c-r.y<0&&(c=s.y-r.y),(u||c)&&t.fire("autopanstart").panBy([u,c])}},_onCloseButtonClick:function(t){this._close(),o.DomEvent.stop(t)}}),o.popup=function(t,e){return new o.Popup(t,e)},o.Map.include({openPopup:function(t,e,i){if(this.closePopup(),!(t instanceof o.Popup)){var n=t;t=new o.Popup(i).setLatLng(e).setContent(n)}return t._isOpen=!0,this._popup=t,this.addLayer(t)},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&(this.removeLayer(t),t._isOpen=!1),this}}),o.Marker.include({openPopup:function(){return this._popup&&this._map&&!this._map.hasLayer(this._popup)&&(this._popup.setLatLng(this._latlng),this._map.openPopup(this._popup)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(){return this._popup&&(this._popup._isOpen?this.closePopup():this.openPopup()),this},bindPopup:function(t,e){var i=o.point(this.options.icon.options.popupAnchor||[0,0]);return i=i.add(o.Popup.prototype.options.offset),e&&e.offset&&(i=i.add(e.offset)),e=o.extend({offset:i},e),this._popupHandlersAdded||(this.on("click",this.togglePopup,this).on("remove",this.closePopup,this).on("move",this._movePopup,this),this._popupHandlersAdded=!0),t instanceof o.Popup?(o.setOptions(t,e),this._popup=t):this._popup=new o.Popup(e,this).setContent(t),this},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this.togglePopup,this).off("remove",this.closePopup,this).off("move",this._movePopup,this),this._popupHandlersAdded=!1),this},getPopup:function(){return this._popup},_movePopup:function(t){this._popup.setLatLng(t.latlng)}}),o.LayerGroup=o.Class.extend({initialize:function(t){this._layers={};var e,i;if(t)for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},addLayer:function(t){var e=this.getLayerId(t);return this._layers[e]=t,this._map&&this._map.addLayer(t),this},removeLayer:function(t){var e=t in this._layers?t:this.getLayerId(t);return this._map&&this._layers[e]&&this._map.removeLayer(this._layers[e]),delete this._layers[e],this},hasLayer:function(t){return t?t in this._layers||this.getLayerId(t)in this._layers:!1},clearLayers:function(){return this.eachLayer(this.removeLayer,this),this},invoke:function(t){var e,i,n=Array.prototype.slice.call(arguments,1);for(e in this._layers)i=this._layers[e],i[t]&&i[t].apply(i,n);return this},onAdd:function(t){this._map=t,this.eachLayer(t.addLayer,t)},onRemove:function(t){this.eachLayer(t.removeLayer,t),this._map=null},addTo:function(t){return t.addLayer(this),this},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},getLayer:function(t){return this._layers[t]},getLayers:function(){var t=[];for(var e in this._layers)t.push(this._layers[e]);return t},setZIndex:function(t){return this.invoke("setZIndex",t)},getLayerId:function(t){return o.stamp(t)}}),o.layerGroup=function(t){return new o.LayerGroup(t)},o.FeatureGroup=o.LayerGroup.extend({includes:o.Mixin.Events,statics:{EVENTS:"click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose"},addLayer:function(t){return this.hasLayer(t)?this:("on"in t&&t.on(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.addLayer.call(this,t),this._popupContent&&t.bindPopup&&t.bindPopup(this._popupContent,this._popupOptions),this.fire("layeradd",{layer:t}))},removeLayer:function(t){return this.hasLayer(t)?(t in this._layers&&(t=this._layers[t]),t.off(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.removeLayer.call(this,t),this._popupContent&&this.invoke("unbindPopup"),this.fire("layerremove",{layer:t})):this},bindPopup:function(t,e){return this._popupContent=t,this._popupOptions=e,this.invoke("bindPopup",t,e)},openPopup:function(t){for(var e in this._layers){this._layers[e].openPopup(t);break}return this},setStyle:function(t){return this.invoke("setStyle",t)},bringToFront:function(){return this.invoke("bringToFront")},bringToBack:function(){return this.invoke("bringToBack")},getBounds:function(){var t=new o.LatLngBounds;return this.eachLayer(function(e){t.extend(e instanceof o.Marker?e.getLatLng():e.getBounds())}),t},_propagateEvent:function(t){t=o.extend({layer:t.target,target:this},t),this.fire(t.type,t)}}),o.featureGroup=function(t){return new o.FeatureGroup(t)},o.Path=o.Class.extend({includes:[o.Mixin.Events],statics:{CLIP_PADDING:function(){var e=o.Browser.mobile?1280:2e3,i=(e/Math.max(t.outerWidth,t.outerHeight)-1)/2;return Math.max(0,Math.min(.5,i))}()},options:{stroke:!0,color:"#0033ff",dashArray:null,lineCap:null,lineJoin:null,weight:5,opacity:.5,fill:!1,fillColor:null,fillOpacity:.2,clickable:!0},initialize:function(t){o.setOptions(this,t)},onAdd:function(t){this._map=t,this._container||(this._initElements(),this._initEvents()),this.projectLatlngs(),this._updatePath(),this._container&&this._map._pathRoot.appendChild(this._container),this.fire("add"),t.on({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){t._pathRoot.removeChild(this._container),this.fire("remove"),this._map=null,o.Browser.vml&&(this._container=null,this._stroke=null,this._fill=null),t.off({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},projectLatlngs:function(){},setStyle:function(t){return o.setOptions(this,t),this._container&&this._updateStyle(),this},redraw:function(){return this._map&&(this.projectLatlngs(),this._updatePath()),this}}),o.Map.include({_updatePathViewport:function(){var t=o.Path.CLIP_PADDING,e=this.getSize(),i=o.DomUtil.getPosition(this._mapPane),n=i.multiplyBy(-1)._subtract(e.multiplyBy(t)._round()),s=n.add(e.multiplyBy(1+2*t)._round());this._pathViewport=new o.Bounds(n,s)}}),o.Path.SVG_NS="http://www.w3.org/2000/svg",o.Browser.svg=!(!e.createElementNS||!e.createElementNS(o.Path.SVG_NS,"svg").createSVGRect),o.Path=o.Path.extend({statics:{SVG:o.Browser.svg},bringToFront:function(){var t=this._map._pathRoot,e=this._container;return e&&t.lastChild!==e&&t.appendChild(e),this},bringToBack:function(){var t=this._map._pathRoot,e=this._container,i=t.firstChild;return e&&i!==e&&t.insertBefore(e,i),this},getPathString:function(){},_createElement:function(t){return e.createElementNS(o.Path.SVG_NS,t)},_initElements:function(){this._map._initPathRoot(),this._initPath(),this._initStyle()},_initPath:function(){this._container=this._createElement("g"),this._path=this._createElement("path"),this.options.className&&o.DomUtil.addClass(this._path,this.options.className),this._container.appendChild(this._path)},_initStyle:function(){this.options.stroke&&(this._path.setAttribute("stroke-linejoin","round"),this._path.setAttribute("stroke-linecap","round")),this.options.fill&&this._path.setAttribute("fill-rule","evenodd"),this.options.pointerEvents&&this._path.setAttribute("pointer-events",this.options.pointerEvents),this.options.clickable||this.options.pointerEvents||this._path.setAttribute("pointer-events","none"),this._updateStyle()},_updateStyle:function(){this.options.stroke?(this._path.setAttribute("stroke",this.options.color),this._path.setAttribute("stroke-opacity",this.options.opacity),this._path.setAttribute("stroke-width",this.options.weight),this.options.dashArray?this._path.setAttribute("stroke-dasharray",this.options.dashArray):this._path.removeAttribute("stroke-dasharray"),this.options.lineCap&&this._path.setAttribute("stroke-linecap",this.options.lineCap),this.options.lineJoin&&this._path.setAttribute("stroke-linejoin",this.options.lineJoin)):this._path.setAttribute("stroke","none"),this.options.fill?(this._path.setAttribute("fill",this.options.fillColor||this.options.color),this._path.setAttribute("fill-opacity",this.options.fillOpacity)):this._path.setAttribute("fill","none")},_updatePath:function(){var t=this.getPathString();t||(t="M0 0"),this._path.setAttribute("d",t)},_initEvents:function(){if(this.options.clickable){(o.Browser.svg||!o.Browser.vml)&&o.DomUtil.addClass(this._path,"leaflet-clickable"),o.DomEvent.on(this._container,"click",this._onMouseClick,this);for(var t=["dblclick","mousedown","mouseover","mouseout","mousemove","contextmenu"],e=0;e<t.length;e++)o.DomEvent.on(this._container,t[e],this._fireMouseEvent,this)}},_onMouseClick:function(t){this._map.dragging&&this._map.dragging.moved()||this._fireMouseEvent(t)},_fireMouseEvent:function(t){if(this.hasEventListeners(t.type)){var e=this._map,i=e.mouseEventToContainerPoint(t),n=e.containerPointToLayerPoint(i),s=e.layerPointToLatLng(n);this.fire(t.type,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t}),"contextmenu"===t.type&&o.DomEvent.preventDefault(t),"mousemove"!==t.type&&o.DomEvent.stopPropagation(t)}}}),o.Map.include({_initPathRoot:function(){this._pathRoot||(this._pathRoot=o.Path.prototype._createElement("svg"),this._panes.overlayPane.appendChild(this._pathRoot),this.options.zoomAnimation&&o.Browser.any3d?(o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-animated"),this.on({zoomanim:this._animatePathZoom,zoomend:this._endPathZoom})):o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-hide"),this.on("moveend",this._updateSvgViewport),this._updateSvgViewport()) | |
| 8 | +},_animatePathZoom:function(t){var e=this.getZoomScale(t.zoom),i=this._getCenterOffset(t.center)._multiplyBy(-e)._add(this._pathViewport.min);this._pathRoot.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(i)+" scale("+e+") ",this._pathZooming=!0},_endPathZoom:function(){this._pathZooming=!1},_updateSvgViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max,n=i.x-e.x,s=i.y-e.y,a=this._pathRoot,r=this._panes.overlayPane;o.Browser.mobileWebkit&&r.removeChild(a),o.DomUtil.setPosition(a,e),a.setAttribute("width",n),a.setAttribute("height",s),a.setAttribute("viewBox",[e.x,e.y,n,s].join(" ")),o.Browser.mobileWebkit&&r.appendChild(a)}}}),o.Path.include({bindPopup:function(t,e){return t instanceof o.Popup?this._popup=t:((!this._popup||e)&&(this._popup=new o.Popup(e,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on("click",this._openPopup,this).on("remove",this.closePopup,this),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this._openPopup).off("remove",this.closePopup),this._popupHandlersAdded=!1),this},openPopup:function(t){return this._popup&&(t=t||this._latlng||this._latlngs[Math.floor(this._latlngs.length/2)],this._openPopup({latlng:t})),this},closePopup:function(){return this._popup&&this._popup._close(),this},_openPopup:function(t){this._popup.setLatLng(t.latlng),this._map.openPopup(this._popup)}}),o.Browser.vml=!o.Browser.svg&&function(){try{var t=e.createElement("div");t.innerHTML='<v:shape adj="1"/>';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(n){return!1}}(),o.Path=o.Browser.svg||!o.Browser.vml?o.Path:o.Path.extend({statics:{VML:!0,CLIP_PADDING:.02},_createElement:function(){try{return e.namespaces.add("lvml","urn:schemas-microsoft-com:vml"),function(t){return e.createElement("<lvml:"+t+' class="lvml">')}}catch(t){return function(t){return e.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),_initPath:function(){var t=this._container=this._createElement("shape");o.DomUtil.addClass(t,"leaflet-vml-shape"+(this.options.className?" "+this.options.className:"")),this.options.clickable&&o.DomUtil.addClass(t,"leaflet-clickable"),t.coordsize="1 1",this._path=this._createElement("path"),t.appendChild(this._path),this._map._pathRoot.appendChild(t)},_initStyle:function(){this._updateStyle()},_updateStyle:function(){var t=this._stroke,e=this._fill,i=this.options,n=this._container;n.stroked=i.stroke,n.filled=i.fill,i.stroke?(t||(t=this._stroke=this._createElement("stroke"),t.endcap="round",n.appendChild(t)),t.weight=i.weight+"px",t.color=i.color,t.opacity=i.opacity,t.dashStyle=i.dashArray?o.Util.isArray(i.dashArray)?i.dashArray.join(" "):i.dashArray.replace(/( *, *)/g," "):"",i.lineCap&&(t.endcap=i.lineCap.replace("butt","flat")),i.lineJoin&&(t.joinstyle=i.lineJoin)):t&&(n.removeChild(t),this._stroke=null),i.fill?(e||(e=this._fill=this._createElement("fill"),n.appendChild(e)),e.color=i.fillColor||i.color,e.opacity=i.fillOpacity):e&&(n.removeChild(e),this._fill=null)},_updatePath:function(){var t=this._container.style;t.display="none",this._path.v=this.getPathString()+" ",t.display=""}}),o.Map.include(o.Browser.svg||!o.Browser.vml?{}:{_initPathRoot:function(){if(!this._pathRoot){var t=this._pathRoot=e.createElement("div");t.className="leaflet-vml-container",this._panes.overlayPane.appendChild(t),this.on("moveend",this._updatePathViewport),this._updatePathViewport()}}}),o.Browser.canvas=function(){return!!e.createElement("canvas").getContext}(),o.Path=o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?o.Path:o.Path.extend({statics:{CANVAS:!0,SVG:!1},redraw:function(){return this._map&&(this.projectLatlngs(),this._requestUpdate()),this},setStyle:function(t){return o.setOptions(this,t),this._map&&(this._updateStyle(),this._requestUpdate()),this},onRemove:function(t){t.off("viewreset",this.projectLatlngs,this).off("moveend",this._updatePath,this),this.options.clickable&&(this._map.off("click",this._onClick,this),this._map.off("mousemove",this._onMouseMove,this)),this._requestUpdate(),this.fire("remove"),this._map=null},_requestUpdate:function(){this._map&&!o.Path._updateRequest&&(o.Path._updateRequest=o.Util.requestAnimFrame(this._fireMapMoveEnd,this._map))},_fireMapMoveEnd:function(){o.Path._updateRequest=null,this.fire("moveend")},_initElements:function(){this._map._initPathRoot(),this._ctx=this._map._canvasCtx},_updateStyle:function(){var t=this.options;t.stroke&&(this._ctx.lineWidth=t.weight,this._ctx.strokeStyle=t.color),t.fill&&(this._ctx.fillStyle=t.fillColor||t.color)},_drawPath:function(){var t,e,i,n,s,a;for(this._ctx.beginPath(),t=0,i=this._parts.length;i>t;t++){for(e=0,n=this._parts[t].length;n>e;e++)s=this._parts[t][e],a=(0===e?"move":"line")+"To",this._ctx[a](s.x,s.y);this instanceof o.Polygon&&this._ctx.closePath()}},_checkIfEmpty:function(){return!this._parts.length},_updatePath:function(){if(!this._checkIfEmpty()){var t=this._ctx,e=this.options;this._drawPath(),t.save(),this._updateStyle(),e.fill&&(t.globalAlpha=e.fillOpacity,t.fill()),e.stroke&&(t.globalAlpha=e.opacity,t.stroke()),t.restore()}},_initEvents:function(){this.options.clickable&&(this._map.on("mousemove",this._onMouseMove,this),this._map.on("click",this._onClick,this))},_onClick:function(t){this._containsPoint(t.layerPoint)&&this.fire("click",t)},_onMouseMove:function(t){this._map&&!this._map._animatingZoom&&(this._containsPoint(t.layerPoint)?(this._ctx.canvas.style.cursor="pointer",this._mouseInside=!0,this.fire("mouseover",t)):this._mouseInside&&(this._ctx.canvas.style.cursor="",this._mouseInside=!1,this.fire("mouseout",t)))}}),o.Map.include(o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?{}:{_initPathRoot:function(){var t,i=this._pathRoot;i||(i=this._pathRoot=e.createElement("canvas"),i.style.position="absolute",t=this._canvasCtx=i.getContext("2d"),t.lineCap="round",t.lineJoin="round",this._panes.overlayPane.appendChild(i),this.options.zoomAnimation&&(this._pathRoot.className="leaflet-zoom-animated",this.on("zoomanim",this._animatePathZoom),this.on("zoomend",this._endPathZoom)),this.on("moveend",this._updateCanvasViewport),this._updateCanvasViewport())},_updateCanvasViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max.subtract(e),n=this._pathRoot;o.DomUtil.setPosition(n,e),n.width=i.x,n.height=i.y,n.getContext("2d").translate(-e.x,-e.y)}}}),o.LineUtil={simplify:function(t,e){if(!e||!t.length)return t.slice();var i=e*e;return t=this._reducePoints(t,i),t=this._simplifyDP(t,i)},pointToSegmentDistance:function(t,e,i){return Math.sqrt(this._sqClosestPointOnSegment(t,e,i,!0))},closestPointOnSegment:function(t,e,i){return this._sqClosestPointOnSegment(t,e,i)},_simplifyDP:function(t,e){var n=t.length,o=typeof Uint8Array!=i+""?Uint8Array:Array,s=new o(n);s[0]=s[n-1]=1,this._simplifyDPStep(t,s,e,0,n-1);var a,r=[];for(a=0;n>a;a++)s[a]&&r.push(t[a]);return r},_simplifyDPStep:function(t,e,i,n,o){var s,a,r,h=0;for(a=n+1;o-1>=a;a++)r=this._sqClosestPointOnSegment(t[a],t[n],t[o],!0),r>h&&(s=a,h=r);h>i&&(e[s]=1,this._simplifyDPStep(t,e,i,n,s),this._simplifyDPStep(t,e,i,s,o))},_reducePoints:function(t,e){for(var i=[t[0]],n=1,o=0,s=t.length;s>n;n++)this._sqDist(t[n],t[o])>e&&(i.push(t[n]),o=n);return s-1>o&&i.push(t[s-1]),i},clipSegment:function(t,e,i,n){var o,s,a,r=n?this._lastCode:this._getBitCode(t,i),h=this._getBitCode(e,i);for(this._lastCode=h;;){if(!(r|h))return[t,e];if(r&h)return!1;o=r||h,s=this._getEdgeIntersection(t,e,o,i),a=this._getBitCode(s,i),o===r?(t=s,r=a):(e=s,h=a)}},_getEdgeIntersection:function(t,e,i,n){var s=e.x-t.x,a=e.y-t.y,r=n.min,h=n.max;return 8&i?new o.Point(t.x+s*(h.y-t.y)/a,h.y):4&i?new o.Point(t.x+s*(r.y-t.y)/a,r.y):2&i?new o.Point(h.x,t.y+a*(h.x-t.x)/s):1&i?new o.Point(r.x,t.y+a*(r.x-t.x)/s):void 0},_getBitCode:function(t,e){var i=0;return t.x<e.min.x?i|=1:t.x>e.max.x&&(i|=2),t.y<e.min.y?i|=4:t.y>e.max.y&&(i|=8),i},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n},_sqClosestPointOnSegment:function(t,e,i,n){var s,a=e.x,r=e.y,h=i.x-a,l=i.y-r,u=h*h+l*l;return u>0&&(s=((t.x-a)*h+(t.y-r)*l)/u,s>1?(a=i.x,r=i.y):s>0&&(a+=h*s,r+=l*s)),h=t.x-a,l=t.y-r,n?h*h+l*l:new o.Point(a,r)}},o.Polyline=o.Path.extend({initialize:function(t,e){o.Path.prototype.initialize.call(this,e),this._latlngs=this._convertLatLngs(t)},options:{smoothFactor:1,noClip:!1},projectLatlngs:function(){this._originalPoints=[];for(var t=0,e=this._latlngs.length;e>t;t++)this._originalPoints[t]=this._map.latLngToLayerPoint(this._latlngs[t])},getPathString:function(){for(var t=0,e=this._parts.length,i="";e>t;t++)i+=this._getPathPartStr(this._parts[t]);return i},getLatLngs:function(){return this._latlngs},setLatLngs:function(t){return this._latlngs=this._convertLatLngs(t),this.redraw()},addLatLng:function(t){return this._latlngs.push(o.latLng(t)),this.redraw()},spliceLatLngs:function(){var t=[].splice.apply(this._latlngs,arguments);return this._convertLatLngs(this._latlngs,!0),this.redraw(),t},closestLayerPoint:function(t){for(var e,i,n=1/0,s=this._parts,a=null,r=0,h=s.length;h>r;r++)for(var l=s[r],u=1,c=l.length;c>u;u++){e=l[u-1],i=l[u];var d=o.LineUtil._sqClosestPointOnSegment(t,e,i,!0);n>d&&(n=d,a=o.LineUtil._sqClosestPointOnSegment(t,e,i))}return a&&(a.distance=Math.sqrt(n)),a},getBounds:function(){return new o.LatLngBounds(this.getLatLngs())},_convertLatLngs:function(t,e){var i,n,s=e?t:[];for(i=0,n=t.length;n>i;i++){if(o.Util.isArray(t[i])&&"number"!=typeof t[i][0])return;s[i]=o.latLng(t[i])}return s},_initEvents:function(){o.Path.prototype._initEvents.call(this)},_getPathPartStr:function(t){for(var e,i=o.Path.VML,n=0,s=t.length,a="";s>n;n++)e=t[n],i&&e._round(),a+=(n?"L":"M")+e.x+" "+e.y;return a},_clipPoints:function(){var t,e,i,n=this._originalPoints,s=n.length;if(this.options.noClip)return void(this._parts=[n]);this._parts=[];var a=this._parts,r=this._map._pathViewport,h=o.LineUtil;for(t=0,e=0;s-1>t;t++)i=h.clipSegment(n[t],n[t+1],r,t),i&&(a[e]=a[e]||[],a[e].push(i[0]),(i[1]!==n[t+1]||t===s-2)&&(a[e].push(i[1]),e++))},_simplifyPoints:function(){for(var t=this._parts,e=o.LineUtil,i=0,n=t.length;n>i;i++)t[i]=e.simplify(t[i],this.options.smoothFactor)},_updatePath:function(){this._map&&(this._clipPoints(),this._simplifyPoints(),o.Path.prototype._updatePath.call(this))}}),o.polyline=function(t,e){return new o.Polyline(t,e)},o.PolyUtil={},o.PolyUtil.clipPolygon=function(t,e){var i,n,s,a,r,h,l,u,c,d=[1,4,2,8],p=o.LineUtil;for(n=0,l=t.length;l>n;n++)t[n]._code=p._getBitCode(t[n],e);for(a=0;4>a;a++){for(u=d[a],i=[],n=0,l=t.length,s=l-1;l>n;s=n++)r=t[n],h=t[s],r._code&u?h._code&u||(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)):(h._code&u&&(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)),i.push(r));t=i}return t},o.Polygon=o.Polyline.extend({options:{fill:!0},initialize:function(t,e){o.Polyline.prototype.initialize.call(this,t,e),this._initWithHoles(t)},_initWithHoles:function(t){var e,i,n;if(t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0])for(this._latlngs=this._convertLatLngs(t[0]),this._holes=t.slice(1),e=0,i=this._holes.length;i>e;e++)n=this._holes[e]=this._convertLatLngs(this._holes[e]),n[0].equals(n[n.length-1])&&n.pop();t=this._latlngs,t.length>=2&&t[0].equals(t[t.length-1])&&t.pop()},projectLatlngs:function(){if(o.Polyline.prototype.projectLatlngs.call(this),this._holePoints=[],this._holes){var t,e,i,n;for(t=0,i=this._holes.length;i>t;t++)for(this._holePoints[t]=[],e=0,n=this._holes[t].length;n>e;e++)this._holePoints[t][e]=this._map.latLngToLayerPoint(this._holes[t][e])}},setLatLngs:function(t){return t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0]?(this._initWithHoles(t),this.redraw()):o.Polyline.prototype.setLatLngs.call(this,t)},_clipPoints:function(){var t=this._originalPoints,e=[];if(this._parts=[t].concat(this._holePoints),!this.options.noClip){for(var i=0,n=this._parts.length;n>i;i++){var s=o.PolyUtil.clipPolygon(this._parts[i],this._map._pathViewport);s.length&&e.push(s)}this._parts=e}},_getPathPartStr:function(t){var e=o.Polyline.prototype._getPathPartStr.call(this,t);return e+(o.Browser.svg?"z":"x")}}),o.polygon=function(t,e){return new o.Polygon(t,e)},function(){function t(t){return o.FeatureGroup.extend({initialize:function(t,e){this._layers={},this._options=e,this.setLatLngs(t)},setLatLngs:function(e){var i=0,n=e.length;for(this.eachLayer(function(t){n>i?t.setLatLngs(e[i++]):this.removeLayer(t)},this);n>i;)this.addLayer(new t(e[i++],this._options));return this},getLatLngs:function(){var t=[];return this.eachLayer(function(e){t.push(e.getLatLngs())}),t}})}o.MultiPolyline=t(o.Polyline),o.MultiPolygon=t(o.Polygon),o.multiPolyline=function(t,e){return new o.MultiPolyline(t,e)},o.multiPolygon=function(t,e){return new o.MultiPolygon(t,e)}}(),o.Rectangle=o.Polygon.extend({initialize:function(t,e){o.Polygon.prototype.initialize.call(this,this._boundsToLatLngs(t),e)},setBounds:function(t){this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=o.latLngBounds(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}}),o.rectangle=function(t,e){return new o.Rectangle(t,e)},o.Circle=o.Path.extend({initialize:function(t,e,i){o.Path.prototype.initialize.call(this,i),this._latlng=o.latLng(t),this._mRadius=e},options:{fill:!0},setLatLng:function(t){return this._latlng=o.latLng(t),this.redraw()},setRadius:function(t){return this._mRadius=t,this.redraw()},projectLatlngs:function(){var t=this._getLngRadius(),e=this._latlng,i=this._map.latLngToLayerPoint([e.lat,e.lng-t]);this._point=this._map.latLngToLayerPoint(e),this._radius=Math.max(this._point.x-i.x,1)},getBounds:function(){var t=this._getLngRadius(),e=this._mRadius/40075017*360,i=this._latlng;return new o.LatLngBounds([i.lat-e,i.lng-t],[i.lat+e,i.lng+t])},getLatLng:function(){return this._latlng},getPathString:function(){var t=this._point,e=this._radius;return this._checkIfEmpty()?"":o.Browser.svg?"M"+t.x+","+(t.y-e)+"A"+e+","+e+",0,1,1,"+(t.x-.1)+","+(t.y-e)+" z":(t._round(),e=Math.round(e),"AL "+t.x+","+t.y+" "+e+","+e+" 0,23592600")},getRadius:function(){return this._mRadius},_getLatRadius:function(){return this._mRadius/40075017*360},_getLngRadius:function(){return this._getLatRadius()/Math.cos(o.LatLng.DEG_TO_RAD*this._latlng.lat)},_checkIfEmpty:function(){if(!this._map)return!1;var t=this._map._pathViewport,e=this._radius,i=this._point;return i.x-e>t.max.x||i.y-e>t.max.y||i.x+e<t.min.x||i.y+e<t.min.y}}),o.circle=function(t,e,i){return new o.Circle(t,e,i)},o.CircleMarker=o.Circle.extend({options:{radius:10,weight:2},initialize:function(t,e){o.Circle.prototype.initialize.call(this,t,null,e),this._radius=this.options.radius},projectLatlngs:function(){this._point=this._map.latLngToLayerPoint(this._latlng)},_updateStyle:function(){o.Circle.prototype._updateStyle.call(this),this.setRadius(this.options.radius)},setLatLng:function(t){return o.Circle.prototype.setLatLng.call(this,t),this._popup&&this._popup._isOpen&&this._popup.setLatLng(t),this},setRadius:function(t){return this.options.radius=this._radius=t,this.redraw()},getRadius:function(){return this._radius}}),o.circleMarker=function(t,e){return new o.CircleMarker(t,e)},o.Polyline.include(o.Path.CANVAS?{_containsPoint:function(t,e){var i,n,s,a,r,h,l,u=this.options.weight/2;for(o.Browser.touch&&(u+=10),i=0,a=this._parts.length;a>i;i++)for(l=this._parts[i],n=0,r=l.length,s=r-1;r>n;s=n++)if((e||0!==n)&&(h=o.LineUtil.pointToSegmentDistance(t,l[s],l[n]),u>=h))return!0;return!1}}:{}),o.Polygon.include(o.Path.CANVAS?{_containsPoint:function(t){var e,i,n,s,a,r,h,l,u=!1;if(o.Polyline.prototype._containsPoint.call(this,t,!0))return!0;for(s=0,h=this._parts.length;h>s;s++)for(e=this._parts[s],a=0,l=e.length,r=l-1;l>a;r=a++)i=e[a],n=e[r],i.y>t.y!=n.y>t.y&&t.x<(n.x-i.x)*(t.y-i.y)/(n.y-i.y)+i.x&&(u=!u);return u}}:{}),o.Circle.include(o.Path.CANVAS?{_drawPath:function(){var t=this._point;this._ctx.beginPath(),this._ctx.arc(t.x,t.y,this._radius,0,2*Math.PI,!1)},_containsPoint:function(t){var e=this._point,i=this.options.stroke?this.options.weight/2:0;return t.distanceTo(e)<=this._radius+i}}:{}),o.CircleMarker.include(o.Path.CANVAS?{_updateStyle:function(){o.Path.prototype._updateStyle.call(this)}}:{}),o.GeoJSON=o.FeatureGroup.extend({initialize:function(t,e){o.setOptions(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,i,n,s=o.Util.isArray(t)?t:t.features;if(s){for(e=0,i=s.length;i>e;e++)n=s[e],(n.geometries||n.geometry||n.features||n.coordinates)&&this.addData(s[e]);return this}var a=this.options;if(!a.filter||a.filter(t)){var r=o.GeoJSON.geometryToLayer(t,a.pointToLayer,a.coordsToLatLng,a);return r.feature=o.GeoJSON.asFeature(t),r.defaultOptions=r.options,this.resetStyle(r),a.onEachFeature&&a.onEachFeature(t,r),this.addLayer(r)}},resetStyle:function(t){var e=this.options.style;e&&(o.Util.extend(t.options,t.defaultOptions),this._setLayerStyle(t,e))},setStyle:function(t){this.eachLayer(function(e){this._setLayerStyle(e,t)},this)},_setLayerStyle:function(t,e){"function"==typeof e&&(e=e(t.feature)),t.setStyle&&t.setStyle(e)}}),o.extend(o.GeoJSON,{geometryToLayer:function(t,e,i,n){var s,a,r,h,l="Feature"===t.type?t.geometry:t,u=l.coordinates,c=[];switch(i=i||this.coordsToLatLng,l.type){case"Point":return s=i(u),e?e(t,s):new o.Marker(s);case"MultiPoint":for(r=0,h=u.length;h>r;r++)s=i(u[r]),c.push(e?e(t,s):new o.Marker(s));return new o.FeatureGroup(c);case"LineString":return a=this.coordsToLatLngs(u,0,i),new o.Polyline(a,n);case"Polygon":if(2===u.length&&!u[1].length)throw new Error("Invalid GeoJSON object.");return a=this.coordsToLatLngs(u,1,i),new o.Polygon(a,n);case"MultiLineString":return a=this.coordsToLatLngs(u,1,i),new o.MultiPolyline(a,n);case"MultiPolygon":return a=this.coordsToLatLngs(u,2,i),new o.MultiPolygon(a,n);case"GeometryCollection":for(r=0,h=l.geometries.length;h>r;r++)c.push(this.geometryToLayer({geometry:l.geometries[r],type:"Feature",properties:t.properties},e,i,n));return new o.FeatureGroup(c);default:throw new Error("Invalid GeoJSON object.")}},coordsToLatLng:function(t){return new o.LatLng(t[1],t[0],t[2])},coordsToLatLngs:function(t,e,i){var n,o,s,a=[];for(o=0,s=t.length;s>o;o++)n=e?this.coordsToLatLngs(t[o],e-1,i):(i||this.coordsToLatLng)(t[o]),a.push(n);return a},latLngToCoords:function(t){var e=[t.lng,t.lat];return t.alt!==i&&e.push(t.alt),e},latLngsToCoords:function(t){for(var e=[],i=0,n=t.length;n>i;i++)e.push(o.GeoJSON.latLngToCoords(t[i]));return e},getFeature:function(t,e){return t.feature?o.extend({},t.feature,{geometry:e}):o.GeoJSON.asFeature(e)},asFeature:function(t){return"Feature"===t.type?t:{type:"Feature",properties:{},geometry:t}}});var a={toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"Point",coordinates:o.GeoJSON.latLngToCoords(this.getLatLng())})}};o.Marker.include(a),o.Circle.include(a),o.CircleMarker.include(a),o.Polyline.include({toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"LineString",coordinates:o.GeoJSON.latLngsToCoords(this.getLatLngs())})}}),o.Polygon.include({toGeoJSON:function(){var t,e,i,n=[o.GeoJSON.latLngsToCoords(this.getLatLngs())];if(n[0].push(n[0][0]),this._holes)for(t=0,e=this._holes.length;e>t;t++)i=o.GeoJSON.latLngsToCoords(this._holes[t]),i.push(i[0]),n.push(i);return o.GeoJSON.getFeature(this,{type:"Polygon",coordinates:n})}}),function(){function t(t){return function(){var e=[];return this.eachLayer(function(t){e.push(t.toGeoJSON().geometry.coordinates)}),o.GeoJSON.getFeature(this,{type:t,coordinates:e})}}o.MultiPolyline.include({toGeoJSON:t("MultiLineString")}),o.MultiPolygon.include({toGeoJSON:t("MultiPolygon")}),o.LayerGroup.include({toGeoJSON:function(){var e,i=this.feature&&this.feature.geometry,n=[];if(i&&"MultiPoint"===i.type)return t("MultiPoint").call(this);var s=i&&"GeometryCollection"===i.type;return this.eachLayer(function(t){t.toGeoJSON&&(e=t.toGeoJSON(),n.push(s?e.geometry:o.GeoJSON.asFeature(e)))}),s?o.GeoJSON.getFeature(this,{geometries:n,type:"GeometryCollection"}):{type:"FeatureCollection",features:n}}})}(),o.geoJson=function(t,e){return new o.GeoJSON(t,e)},o.DomEvent={addListener:function(t,e,i,n){var s,a,r,h=o.stamp(i),l="_leaflet_"+e+h;return t[l]?this:(s=function(e){return i.call(n||t,e||o.DomEvent._getEvent())},o.Browser.pointer&&0===e.indexOf("touch")?this.addPointerListener(t,e,s,h):(o.Browser.touch&&"dblclick"===e&&this.addDoubleTapListener&&this.addDoubleTapListener(t,s,h),"addEventListener"in t?"mousewheel"===e?(t.addEventListener("DOMMouseScroll",s,!1),t.addEventListener(e,s,!1)):"mouseenter"===e||"mouseleave"===e?(a=s,r="mouseenter"===e?"mouseover":"mouseout",s=function(e){return o.DomEvent._checkMouse(t,e)?a(e):void 0},t.addEventListener(r,s,!1)):"click"===e&&o.Browser.android?(a=s,s=function(t){return o.DomEvent._filterClick(t,a)},t.addEventListener(e,s,!1)):t.addEventListener(e,s,!1):"attachEvent"in t&&t.attachEvent("on"+e,s),t[l]=s,this))},removeListener:function(t,e,i){var n=o.stamp(i),s="_leaflet_"+e+n,a=t[s];return a?(o.Browser.pointer&&0===e.indexOf("touch")?this.removePointerListener(t,e,n):o.Browser.touch&&"dblclick"===e&&this.removeDoubleTapListener?this.removeDoubleTapListener(t,n):"removeEventListener"in t?"mousewheel"===e?(t.removeEventListener("DOMMouseScroll",a,!1),t.removeEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?t.removeEventListener("mouseenter"===e?"mouseover":"mouseout",a,!1):t.removeEventListener(e,a,!1):"detachEvent"in t&&t.detachEvent("on"+e,a),t[s]=null,this):this},stopPropagation:function(t){return t.stopPropagation?t.stopPropagation():t.cancelBubble=!0,o.DomEvent._skipped(t),this},disableScrollPropagation:function(t){var e=o.DomEvent.stopPropagation;return o.DomEvent.on(t,"mousewheel",e).on(t,"MozMousePixelScroll",e)},disableClickPropagation:function(t){for(var e=o.DomEvent.stopPropagation,i=o.Draggable.START.length-1;i>=0;i--)o.DomEvent.on(t,o.Draggable.START[i],e);return o.DomEvent.on(t,"click",o.DomEvent._fakeStop).on(t,"dblclick",e)},preventDefault:function(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,this},stop:function(t){return o.DomEvent.preventDefault(t).stopPropagation(t)},getMousePosition:function(t,e){if(!e)return new o.Point(t.clientX,t.clientY);var i=e.getBoundingClientRect();return new o.Point(t.clientX-i.left-e.clientLeft,t.clientY-i.top-e.clientTop)},getWheelDelta:function(t){var e=0;return t.wheelDelta&&(e=t.wheelDelta/120),t.detail&&(e=-t.detail/3),e},_skipEvents:{},_fakeStop:function(t){o.DomEvent._skipEvents[t.type]=!0},_skipped:function(t){var e=this._skipEvents[t.type];return this._skipEvents[t.type]=!1,e},_checkMouse:function(t,e){var i=e.relatedTarget;if(!i)return!0;try{for(;i&&i!==t;)i=i.parentNode}catch(n){return!1}return i!==t},_getEvent:function(){var e=t.event;if(!e)for(var i=arguments.callee.caller;i&&(e=i.arguments[0],!e||t.Event!==e.constructor);)i=i.caller;return e},_filterClick:function(t,e){var i=t.timeStamp||t.originalEvent.timeStamp,n=o.DomEvent._lastClick&&i-o.DomEvent._lastClick;return n&&n>100&&500>n||t.target._simulatedClick&&!t._simulated?void o.DomEvent.stop(t):(o.DomEvent._lastClick=i,e(t))}},o.DomEvent.on=o.DomEvent.addListener,o.DomEvent.off=o.DomEvent.removeListener,o.Draggable=o.Class.extend({includes:o.Mixin.Events,statics:{START:o.Browser.touch?["touchstart","mousedown"]:["mousedown"],END:{mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},MOVE:{mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"}},initialize:function(t,e){this._element=t,this._dragStartTarget=e||t},enable:function(){if(!this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.on(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!0}},disable:function(){if(this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.off(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!1,this._moved=!1}},_onDown:function(t){if(this._moved=!1,!(t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(o.DomEvent.stopPropagation(t),o.Draggable._disabled||(o.DomUtil.disableImageDrag(),o.DomUtil.disableTextSelection(),this._moving)))){var i=t.touches?t.touches[0]:t;this._startPoint=new o.Point(i.clientX,i.clientY),this._startPos=this._newPos=o.DomUtil.getPosition(this._element),o.DomEvent.on(e,o.Draggable.MOVE[t.type],this._onMove,this).on(e,o.Draggable.END[t.type],this._onUp,this)}},_onMove:function(t){if(t.touches&&t.touches.length>1)return void(this._moved=!0);var i=t.touches&&1===t.touches.length?t.touches[0]:t,n=new o.Point(i.clientX,i.clientY),s=n.subtract(this._startPoint);(s.x||s.y)&&(o.Browser.touch&&Math.abs(s.x)+Math.abs(s.y)<3||(o.DomEvent.preventDefault(t),this._moved||(this.fire("dragstart"),this._moved=!0,this._startPos=o.DomUtil.getPosition(this._element).subtract(s),o.DomUtil.addClass(e.body,"leaflet-dragging"),this._lastTarget=t.target||t.srcElement,o.DomUtil.addClass(this._lastTarget,"leaflet-drag-target")),this._newPos=this._startPos.add(s),this._moving=!0,o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updatePosition,this,!0,this._dragStartTarget)))},_updatePosition:function(){this.fire("predrag"),o.DomUtil.setPosition(this._element,this._newPos),this.fire("drag")},_onUp:function(){o.DomUtil.removeClass(e.body,"leaflet-dragging"),this._lastTarget&&(o.DomUtil.removeClass(this._lastTarget,"leaflet-drag-target"),this._lastTarget=null);for(var t in o.Draggable.MOVE)o.DomEvent.off(e,o.Draggable.MOVE[t],this._onMove).off(e,o.Draggable.END[t],this._onUp);o.DomUtil.enableImageDrag(),o.DomUtil.enableTextSelection(),this._moved&&this._moving&&(o.Util.cancelAnimFrame(this._animRequest),this.fire("dragend",{distance:this._newPos.distanceTo(this._startPos)})),this._moving=!1}}),o.Handler=o.Class.extend({initialize:function(t){this._map=t},enable:function(){this._enabled||(this._enabled=!0,this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks())},enabled:function(){return!!this._enabled}}),o.Map.mergeOptions({dragging:!0,inertia:!o.Browser.android23,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,inertiaThreshold:o.Browser.touch?32:18,easeLinearity:.25,worldCopyJump:!1}),o.Map.Drag=o.Handler.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new o.Draggable(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDrag,this),t.on("viewreset",this._onViewReset,this),t.whenReady(this._onViewReset,this))}this._draggable.enable()},removeHooks:function(){this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){var t=this._map;t._panAnim&&t._panAnim.stop(),t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(){if(this._map.options.inertia){var t=this._lastTime=+new Date,e=this._lastPos=this._draggable._newPos;this._positions.push(e),this._times.push(t),t-this._times[0]>200&&(this._positions.shift(),this._times.shift())}this._map.fire("move").fire("drag")},_onViewReset:function(){var t=this._map.getSize()._divideBy(2),e=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=e.subtract(t).x,this._worldWidth=this._map.project([0,180]).x},_onPreDrag:function(){var t=this._worldWidth,e=Math.round(t/2),i=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-e+i)%t+e-i,s=(n+e+i)%t-e-i,a=Math.abs(o+i)<Math.abs(s+i)?o:s;this._draggable._newPos.x=a},_onDragEnd:function(t){var e=this._map,i=e.options,n=+new Date-this._lastTime,s=!i.inertia||n>i.inertiaThreshold||!this._positions[0];if(e.fire("dragend",t),s)e.fire("moveend");else{var a=this._lastPos.subtract(this._positions[0]),r=(this._lastTime+n-this._times[0])/1e3,h=i.easeLinearity,l=a.multiplyBy(h/r),u=l.distanceTo([0,0]),c=Math.min(i.inertiaMaxSpeed,u),d=l.multiplyBy(c/u),p=c/(i.inertiaDeceleration*h),_=d.multiplyBy(-p/2).round();_.x&&_.y?(_=e._limitOffset(_,e.options.maxBounds),o.Util.requestAnimFrame(function(){e.panBy(_,{duration:p,easeLinearity:h,noMoveStart:!0})})):e.fire("moveend")}}}),o.Map.addInitHook("addHandler","dragging",o.Map.Drag),o.Map.mergeOptions({doubleClickZoom:!0}),o.Map.DoubleClickZoom=o.Handler.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var e=this._map,i=e.getZoom()+(t.originalEvent.shiftKey?-1:1);"center"===e.options.doubleClickZoom?e.setZoom(i):e.setZoomAround(t.containerPoint,i)}}),o.Map.addInitHook("addHandler","doubleClickZoom",o.Map.DoubleClickZoom),o.Map.mergeOptions({scrollWheelZoom:!0}),o.Map.ScrollWheelZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"mousewheel",this._onWheelScroll,this),o.DomEvent.on(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault),this._delta=0},removeHooks:function(){o.DomEvent.off(this._map._container,"mousewheel",this._onWheelScroll),o.DomEvent.off(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault)},_onWheelScroll:function(t){var e=o.DomEvent.getWheelDelta(t);this._delta+=e,this._lastMousePos=this._map.mouseEventToContainerPoint(t),this._startTime||(this._startTime=+new Date);var i=Math.max(40-(+new Date-this._startTime),0);clearTimeout(this._timer),this._timer=setTimeout(o.bind(this._performZoom,this),i),o.DomEvent.preventDefault(t),o.DomEvent.stopPropagation(t)},_performZoom:function(){var t=this._map,e=this._delta,i=t.getZoom();e=e>0?Math.ceil(e):Math.floor(e),e=Math.max(Math.min(e,4),-4),e=t._limitZoom(i+e)-i,this._delta=0,this._startTime=null,e&&("center"===t.options.scrollWheelZoom?t.setZoom(i+e):t.setZoomAround(this._lastMousePos,i+e))}}),o.Map.addInitHook("addHandler","scrollWheelZoom",o.Map.ScrollWheelZoom),o.extend(o.DomEvent,{_touchstart:o.Browser.msPointer?"MSPointerDown":o.Browser.pointer?"pointerdown":"touchstart",_touchend:o.Browser.msPointer?"MSPointerUp":o.Browser.pointer?"pointerup":"touchend",addDoubleTapListener:function(t,i,n){function s(t){var e;if(o.Browser.pointer?(_.push(t.pointerId),e=_.length):e=t.touches.length,!(e>1)){var i=Date.now(),n=i-(r||i);h=t.touches?t.touches[0]:t,l=n>0&&u>=n,r=i}}function a(t){if(o.Browser.pointer){var e=_.indexOf(t.pointerId);if(-1===e)return;_.splice(e,1)}if(l){if(o.Browser.pointer){var n,s={};for(var a in h)n=h[a],s[a]="function"==typeof n?n.bind(h):n;h=s}h.type="dblclick",i(h),r=null}}var r,h,l=!1,u=250,c="_leaflet_",d=this._touchstart,p=this._touchend,_=[];t[c+d+n]=s,t[c+p+n]=a;var m=o.Browser.pointer?e.documentElement:t;return t.addEventListener(d,s,!1),m.addEventListener(p,a,!1),o.Browser.pointer&&m.addEventListener(o.DomEvent.POINTER_CANCEL,a,!1),this},removeDoubleTapListener:function(t,i){var n="_leaflet_";return t.removeEventListener(this._touchstart,t[n+this._touchstart+i],!1),(o.Browser.pointer?e.documentElement:t).removeEventListener(this._touchend,t[n+this._touchend+i],!1),o.Browser.pointer&&e.documentElement.removeEventListener(o.DomEvent.POINTER_CANCEL,t[n+this._touchend+i],!1),this}}),o.extend(o.DomEvent,{POINTER_DOWN:o.Browser.msPointer?"MSPointerDown":"pointerdown",POINTER_MOVE:o.Browser.msPointer?"MSPointerMove":"pointermove",POINTER_UP:o.Browser.msPointer?"MSPointerUp":"pointerup",POINTER_CANCEL:o.Browser.msPointer?"MSPointerCancel":"pointercancel",_pointers:[],_pointerDocumentListener:!1,addPointerListener:function(t,e,i,n){switch(e){case"touchstart":return this.addPointerListenerStart(t,e,i,n);case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return this.addPointerListenerMove(t,e,i,n);default:throw"Unknown touch event type"}},addPointerListenerStart:function(t,i,n,s){var a="_leaflet_",r=this._pointers,h=function(t){o.DomEvent.preventDefault(t);for(var e=!1,i=0;i<r.length;i++)if(r[i].pointerId===t.pointerId){e=!0; | |
| 9 | +break}e||r.push(t),t.touches=r.slice(),t.changedTouches=[t],n(t)};if(t[a+"touchstart"+s]=h,t.addEventListener(this.POINTER_DOWN,h,!1),!this._pointerDocumentListener){var l=function(t){for(var e=0;e<r.length;e++)if(r[e].pointerId===t.pointerId){r.splice(e,1);break}};e.documentElement.addEventListener(this.POINTER_UP,l,!1),e.documentElement.addEventListener(this.POINTER_CANCEL,l,!1),this._pointerDocumentListener=!0}return this},addPointerListenerMove:function(t,e,i,n){function o(t){if(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons){for(var e=0;e<a.length;e++)if(a[e].pointerId===t.pointerId){a[e]=t;break}t.touches=a.slice(),t.changedTouches=[t],i(t)}}var s="_leaflet_",a=this._pointers;return t[s+"touchmove"+n]=o,t.addEventListener(this.POINTER_MOVE,o,!1),this},addPointerListenerEnd:function(t,e,i,n){var o="_leaflet_",s=this._pointers,a=function(t){for(var e=0;e<s.length;e++)if(s[e].pointerId===t.pointerId){s.splice(e,1);break}t.touches=s.slice(),t.changedTouches=[t],i(t)};return t[o+"touchend"+n]=a,t.addEventListener(this.POINTER_UP,a,!1),t.addEventListener(this.POINTER_CANCEL,a,!1),this},removePointerListener:function(t,e,i){var n="_leaflet_",o=t[n+e+i];switch(e){case"touchstart":t.removeEventListener(this.POINTER_DOWN,o,!1);break;case"touchmove":t.removeEventListener(this.POINTER_MOVE,o,!1);break;case"touchend":t.removeEventListener(this.POINTER_UP,o,!1),t.removeEventListener(this.POINTER_CANCEL,o,!1)}return this}}),o.Map.mergeOptions({touchZoom:o.Browser.touch&&!o.Browser.android23,bounceAtZoomLimits:!0}),o.Map.TouchZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var n=i.mouseEventToLayerPoint(t.touches[0]),s=i.mouseEventToLayerPoint(t.touches[1]),a=i._getCenterLayerPoint();this._startCenter=n.add(s)._divideBy(2),this._startDist=n.distanceTo(s),this._moved=!1,this._zooming=!0,this._centerOffset=a.subtract(this._startCenter),i._panAnim&&i._panAnim.stop(),o.DomEvent.on(e,"touchmove",this._onTouchMove,this).on(e,"touchend",this._onTouchEnd,this),o.DomEvent.preventDefault(t)}},_onTouchMove:function(t){var e=this._map;if(t.touches&&2===t.touches.length&&this._zooming){var i=e.mouseEventToLayerPoint(t.touches[0]),n=e.mouseEventToLayerPoint(t.touches[1]);this._scale=i.distanceTo(n)/this._startDist,this._delta=i._add(n)._divideBy(2)._subtract(this._startCenter),1!==this._scale&&(e.options.bounceAtZoomLimits||!(e.getZoom()===e.getMinZoom()&&this._scale<1||e.getZoom()===e.getMaxZoom()&&this._scale>1))&&(this._moved||(o.DomUtil.addClass(e._mapPane,"leaflet-touching"),e.fire("movestart").fire("zoomstart"),this._moved=!0),o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updateOnMove,this,!0,this._map._container),o.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e),n=t.getScaleZoom(this._scale);t._animateZoom(i,n,this._startCenter,this._scale,this._delta,!1,!0)},_onTouchEnd:function(){if(!this._moved||!this._zooming)return void(this._zooming=!1);var t=this._map;this._zooming=!1,o.DomUtil.removeClass(t._mapPane,"leaflet-touching"),o.Util.cancelAnimFrame(this._animRequest),o.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),n=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r),l=t.getZoomScale(h)/this._scale;t._animateZoom(n,h,i,l)},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),o.Map.addInitHook("addHandler","touchZoom",o.Map.TouchZoom),o.Map.mergeOptions({tap:!0,tapTolerance:15}),o.Map.Tap=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(o.DomEvent.preventDefault(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new o.Point(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.addClass(n,"leaflet-active"),this._holdTimeout=setTimeout(o.bind(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),o.DomEvent.on(e,"touchmove",this._onMove,this).on(e,"touchend",this._onUp,this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),o.DomEvent.off(e,"touchmove",this._onMove,this).off(e,"touchend",this._onUp,this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],n=i.target;n&&n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.removeClass(n,"leaflet-active"),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var e=t.touches[0];this._newPos=new o.Point(e.clientX,e.clientY)},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o._simulated=!0,n.target._simulatedClick=!0,o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),o.Browser.touch&&!o.Browser.pointer&&o.Map.addInitHook("addHandler","tap",o.Map.Tap),o.Map.mergeOptions({boxZoom:!0}),o.Map.BoxZoom=o.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._moved=!1},addHooks:function(){o.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){o.DomEvent.off(this._container,"mousedown",this._onMouseDown),this._moved=!1},moved:function(){return this._moved},_onMouseDown:function(t){return this._moved=!1,!t.shiftKey||1!==t.which&&1!==t.button?!1:(o.DomUtil.disableTextSelection(),o.DomUtil.disableImageDrag(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),void o.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).on(e,"keydown",this._onKeyDown,this))},_onMouseMove:function(t){this._moved||(this._box=o.DomUtil.create("div","leaflet-zoom-box",this._pane),o.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",this._map.fire("boxzoomstart"));var e=this._startLayerPoint,i=this._box,n=this._map.mouseEventToLayerPoint(t),s=n.subtract(e),a=new o.Point(Math.min(n.x,e.x),Math.min(n.y,e.y));o.DomUtil.setPosition(i,a),this._moved=!0,i.style.width=Math.max(0,Math.abs(s.x)-4)+"px",i.style.height=Math.max(0,Math.abs(s.y)-4)+"px"},_finish:function(){this._moved&&(this._pane.removeChild(this._box),this._container.style.cursor=""),o.DomUtil.enableTextSelection(),o.DomUtil.enableImageDrag(),o.DomEvent.off(e,"mousemove",this._onMouseMove).off(e,"mouseup",this._onMouseUp).off(e,"keydown",this._onKeyDown)},_onMouseUp:function(t){this._finish();var e=this._map,i=e.mouseEventToLayerPoint(t);if(!this._startLayerPoint.equals(i)){var n=new o.LatLngBounds(e.layerPointToLatLng(this._startLayerPoint),e.layerPointToLatLng(i));e.fitBounds(n),e.fire("boxzoomend",{boxZoomBounds:n})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}}),o.Map.addInitHook("addHandler","boxZoom",o.Map.BoxZoom),o.Map.mergeOptions({keyboard:!0,keyboardPanOffset:80,keyboardZoomOffset:1}),o.Map.Keyboard=o.Handler.extend({keyCodes:{left:[37],right:[39],down:[40],up:[38],zoomIn:[187,107,61,171],zoomOut:[189,109,173]},initialize:function(t){this._map=t,this._setPanOffset(t.options.keyboardPanOffset),this._setZoomOffset(t.options.keyboardZoomOffset)},addHooks:function(){var t=this._map._container;-1===t.tabIndex&&(t.tabIndex="0"),o.DomEvent.on(t,"focus",this._onFocus,this).on(t,"blur",this._onBlur,this).on(t,"mousedown",this._onMouseDown,this),this._map.on("focus",this._addHooks,this).on("blur",this._removeHooks,this)},removeHooks:function(){this._removeHooks();var t=this._map._container;o.DomEvent.off(t,"focus",this._onFocus,this).off(t,"blur",this._onBlur,this).off(t,"mousedown",this._onMouseDown,this),this._map.off("focus",this._addHooks,this).off("blur",this._removeHooks,this)},_onMouseDown:function(){if(!this._focused){var i=e.body,n=e.documentElement,o=i.scrollTop||n.scrollTop,s=i.scrollLeft||n.scrollLeft;this._map._container.focus(),t.scrollTo(s,o)}},_onFocus:function(){this._focused=!0,this._map.fire("focus")},_onBlur:function(){this._focused=!1,this._map.fire("blur")},_setPanOffset:function(t){var e,i,n=this._panKeys={},o=this.keyCodes;for(e=0,i=o.left.length;i>e;e++)n[o.left[e]]=[-1*t,0];for(e=0,i=o.right.length;i>e;e++)n[o.right[e]]=[t,0];for(e=0,i=o.down.length;i>e;e++)n[o.down[e]]=[0,t];for(e=0,i=o.up.length;i>e;e++)n[o.up[e]]=[0,-1*t]},_setZoomOffset:function(t){var e,i,n=this._zoomKeys={},o=this.keyCodes;for(e=0,i=o.zoomIn.length;i>e;e++)n[o.zoomIn[e]]=t;for(e=0,i=o.zoomOut.length;i>e;e++)n[o.zoomOut[e]]=-t},_addHooks:function(){o.DomEvent.on(e,"keydown",this._onKeyDown,this)},_removeHooks:function(){o.DomEvent.off(e,"keydown",this._onKeyDown,this)},_onKeyDown:function(t){var e=t.keyCode,i=this._map;if(e in this._panKeys){if(i._panAnim&&i._panAnim._inProgress)return;i.panBy(this._panKeys[e]),i.options.maxBounds&&i.panInsideBounds(i.options.maxBounds)}else{if(!(e in this._zoomKeys))return;i.setZoom(i.getZoom()+this._zoomKeys[e])}o.DomEvent.stop(t)}}),o.Map.addInitHook("addHandler","keyboard",o.Map.Keyboard),o.Handler.MarkerDrag=o.Handler.extend({initialize:function(t){this._marker=t},addHooks:function(){var t=this._marker._icon;this._draggable||(this._draggable=new o.Draggable(t,t)),this._draggable.on("dragstart",this._onDragStart,this).on("drag",this._onDrag,this).on("dragend",this._onDragEnd,this),this._draggable.enable(),o.DomUtil.addClass(this._marker._icon,"leaflet-marker-draggable")},removeHooks:function(){this._draggable.off("dragstart",this._onDragStart,this).off("drag",this._onDrag,this).off("dragend",this._onDragEnd,this),this._draggable.disable(),o.DomUtil.removeClass(this._marker._icon,"leaflet-marker-draggable")},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){this._marker.closePopup().fire("movestart").fire("dragstart")},_onDrag:function(){var t=this._marker,e=t._shadow,i=o.DomUtil.getPosition(t._icon),n=t._map.layerPointToLatLng(i);e&&o.DomUtil.setPosition(e,i),t._latlng=n,t.fire("move",{latlng:n}).fire("drag")},_onDragEnd:function(t){this._marker.fire("moveend").fire("dragend",t)}}),o.Control=o.Class.extend({options:{position:"topright"},initialize:function(t){o.setOptions(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this._map=t;var e=this._container=this.onAdd(t),i=this.getPosition(),n=t._controlCorners[i];return o.DomUtil.addClass(e,"leaflet-control"),-1!==i.indexOf("bottom")?n.insertBefore(e,n.firstChild):n.appendChild(e),this},removeFrom:function(t){var e=this.getPosition(),i=t._controlCorners[e];return i.removeChild(this._container),this._map=null,this.onRemove&&this.onRemove(t),this},_refocusOnMap:function(){this._map&&this._map.getContainer().focus()}}),o.control=function(t){return new o.Control(t)},o.Map.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.removeFrom(this),this},_initControlPos:function(){function t(t,s){var a=i+t+" "+i+s;e[t+s]=o.DomUtil.create("div",a,n)}var e=this._controlCorners={},i="leaflet-",n=this._controlContainer=o.DomUtil.create("div",i+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){this._container.removeChild(this._controlContainer)}}),o.Control.Zoom=o.Control.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"-",zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",i=o.DomUtil.create("div",e+" leaflet-bar");return this._map=t,this._zoomInButton=this._createButton(this.options.zoomInText,this.options.zoomInTitle,e+"-in",i,this._zoomIn,this),this._zoomOutButton=this._createButton(this.options.zoomOutText,this.options.zoomOutTitle,e+"-out",i,this._zoomOut,this),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),i},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},_zoomIn:function(t){this._map.zoomIn(t.shiftKey?3:1)},_zoomOut:function(t){this._map.zoomOut(t.shiftKey?3:1)},_createButton:function(t,e,i,n,s,a){var r=o.DomUtil.create("a",i,n);r.innerHTML=t,r.href="#",r.title=e;var h=o.DomEvent.stopPropagation;return o.DomEvent.on(r,"click",h).on(r,"mousedown",h).on(r,"dblclick",h).on(r,"click",o.DomEvent.preventDefault).on(r,"click",s,a).on(r,"click",this._refocusOnMap,a),r},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";o.DomUtil.removeClass(this._zoomInButton,e),o.DomUtil.removeClass(this._zoomOutButton,e),t._zoom===t.getMinZoom()&&o.DomUtil.addClass(this._zoomOutButton,e),t._zoom===t.getMaxZoom()&&o.DomUtil.addClass(this._zoomInButton,e)}}),o.Map.mergeOptions({zoomControl:!0}),o.Map.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new o.Control.Zoom,this.addControl(this.zoomControl))}),o.control.zoom=function(t){return new o.Control.Zoom(t)},o.Control.Attribution=o.Control.extend({options:{position:"bottomright",prefix:'<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'},initialize:function(t){o.setOptions(this,t),this._attributions={}},onAdd:function(t){this._container=o.DomUtil.create("div","leaflet-control-attribution"),o.DomEvent.disableClickPropagation(this._container);for(var e in t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return t.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this),this._update(),this._container},onRemove:function(t){t.off("layeradd",this._onLayerAdd).off("layerremove",this._onLayerRemove)},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):void 0},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):void 0},_update:function(){if(this._map){var t=[];for(var e in this._attributions)this._attributions[e]&&t.push(e);var i=[];this.options.prefix&&i.push(this.options.prefix),t.length&&i.push(t.join(", ")),this._container.innerHTML=i.join(" | ")}},_onLayerAdd:function(t){t.layer.getAttribution&&this.addAttribution(t.layer.getAttribution())},_onLayerRemove:function(t){t.layer.getAttribution&&this.removeAttribution(t.layer.getAttribution())}}),o.Map.mergeOptions({attributionControl:!0}),o.Map.addInitHook(function(){this.options.attributionControl&&(this.attributionControl=(new o.Control.Attribution).addTo(this))}),o.control.attribution=function(t){return new o.Control.Attribution(t)},o.Control.Scale=o.Control.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0,updateWhenIdle:!1},onAdd:function(t){this._map=t;var e="leaflet-control-scale",i=o.DomUtil.create("div",e),n=this.options;return this._addScales(n,e,i),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,i){t.metric&&(this._mScale=o.DomUtil.create("div",e+"-line",i)),t.imperial&&(this._iScale=o.DomUtil.create("div",e+"-line",i))},_update:function(){var t=this._map.getBounds(),e=t.getCenter().lat,i=6378137*Math.PI*Math.cos(e*Math.PI/180),n=i*(t.getNorthEast().lng-t.getSouthWest().lng)/180,o=this._map.getSize(),s=this.options,a=0;o.x>0&&(a=n*(s.maxWidth/o.x)),this._updateScales(s,a)},_updateScales:function(t,e){t.metric&&e&&this._updateMetric(e),t.imperial&&e&&this._updateImperial(e)},_updateMetric:function(t){var e=this._getRoundNum(t);this._mScale.style.width=this._getScaleWidth(e/t)+"px",this._mScale.innerHTML=1e3>e?e+" m":e/1e3+" km"},_updateImperial:function(t){var e,i,n,o=3.2808399*t,s=this._iScale;o>5280?(e=o/5280,i=this._getRoundNum(e),s.style.width=this._getScaleWidth(i/e)+"px",s.innerHTML=i+" mi"):(n=this._getRoundNum(o),s.style.width=this._getScaleWidth(n/o)+"px",s.innerHTML=n+" ft")},_getScaleWidth:function(t){return Math.round(this.options.maxWidth*t)-10},_getRoundNum:function(t){var e=Math.pow(10,(Math.floor(t)+"").length-1),i=t/e;return i=i>=10?10:i>=5?5:i>=3?3:i>=2?2:1,e*i}}),o.control.scale=function(t){return new o.Control.Scale(t)},o.Control.Layers=o.Control.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0},initialize:function(t,e,i){o.setOptions(this,i),this._layers={},this._lastZIndex=0,this._handlingClick=!1;for(var n in t)this._addLayer(t[n],n);for(n in e)this._addLayer(e[n],n,!0)},onAdd:function(t){return this._initLayout(),this._update(),t.on("layeradd",this._onLayerChange,this).on("layerremove",this._onLayerChange,this),this._container},onRemove:function(t){t.off("layeradd",this._onLayerChange,this).off("layerremove",this._onLayerChange,this)},addBaseLayer:function(t,e){return this._addLayer(t,e),this._update(),this},addOverlay:function(t,e){return this._addLayer(t,e,!0),this._update(),this},removeLayer:function(t){var e=o.stamp(t);return delete this._layers[e],this._update(),this},_initLayout:function(){var t="leaflet-control-layers",e=this._container=o.DomUtil.create("div",t);e.setAttribute("aria-haspopup",!0),o.Browser.touch?o.DomEvent.on(e,"click",o.DomEvent.stopPropagation):o.DomEvent.disableClickPropagation(e).disableScrollPropagation(e);var i=this._form=o.DomUtil.create("form",t+"-list");if(this.options.collapsed){o.Browser.android||o.DomEvent.on(e,"mouseover",this._expand,this).on(e,"mouseout",this._collapse,this);var n=this._layersLink=o.DomUtil.create("a",t+"-toggle",e);n.href="#",n.title="Layers",o.Browser.touch?o.DomEvent.on(n,"click",o.DomEvent.stop).on(n,"click",this._expand,this):o.DomEvent.on(n,"focus",this._expand,this),o.DomEvent.on(i,"click",function(){setTimeout(o.bind(this._onInputClick,this),0)},this),this._map.on("click",this._collapse,this)}else this._expand();this._baseLayersList=o.DomUtil.create("div",t+"-base",i),this._separator=o.DomUtil.create("div",t+"-separator",i),this._overlaysList=o.DomUtil.create("div",t+"-overlays",i),e.appendChild(i)},_addLayer:function(t,e,i){var n=o.stamp(t);this._layers[n]={layer:t,name:e,overlay:i},this.options.autoZIndex&&t.setZIndex&&(this._lastZIndex++,t.setZIndex(this._lastZIndex))},_update:function(){if(this._container){this._baseLayersList.innerHTML="",this._overlaysList.innerHTML="";var t,e,i=!1,n=!1;for(t in this._layers)e=this._layers[t],this._addItem(e),n=n||e.overlay,i=i||!e.overlay;this._separator.style.display=n&&i?"":"none"}},_onLayerChange:function(t){var e=this._layers[o.stamp(t.layer)];if(e){this._handlingClick||this._update();var i=e.overlay?"layeradd"===t.type?"overlayadd":"overlayremove":"layeradd"===t.type?"baselayerchange":null;i&&this._map.fire(i,e)}},_createRadioElement:function(t,i){var n='<input type="radio" class="leaflet-control-layers-selector" name="'+t+'"';i&&(n+=' checked="checked"'),n+="/>";var o=e.createElement("div");return o.innerHTML=n,o.firstChild},_addItem:function(t){var i,n=e.createElement("label"),s=this._map.hasLayer(t.layer);t.overlay?(i=e.createElement("input"),i.type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=s):i=this._createRadioElement("leaflet-base-layers",s),i.layerId=o.stamp(t.layer),o.DomEvent.on(i,"click",this._onInputClick,this);var a=e.createElement("span");a.innerHTML=" "+t.name,n.appendChild(i),n.appendChild(a);var r=t.overlay?this._overlaysList:this._baseLayersList;return r.appendChild(n),n},_onInputClick:function(){var t,e,i,n=this._form.getElementsByTagName("input"),o=n.length;for(this._handlingClick=!0,t=0;o>t;t++)e=n[t],i=this._layers[e.layerId],e.checked&&!this._map.hasLayer(i.layer)?this._map.addLayer(i.layer):!e.checked&&this._map.hasLayer(i.layer)&&this._map.removeLayer(i.layer);this._handlingClick=!1,this._refocusOnMap()},_expand:function(){o.DomUtil.addClass(this._container,"leaflet-control-layers-expanded")},_collapse:function(){this._container.className=this._container.className.replace(" leaflet-control-layers-expanded","")}}),o.control.layers=function(t,e,i){return new o.Control.Layers(t,e,i)},o.PosAnimation=o.Class.extend({includes:o.Mixin.Events,run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._newPos=e,this.fire("start"),t.style[o.DomUtil.TRANSITION]="all "+(i||.25)+"s cubic-bezier(0,0,"+(n||.5)+",1)",o.DomEvent.on(t,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),o.DomUtil.setPosition(t,e),o.Util.falseFn(t.offsetWidth),this._stepTimer=setInterval(o.bind(this._onStep,this),50)},stop:function(){this._inProgress&&(o.DomUtil.setPosition(this._el,this._getPos()),this._onTransitionEnd(),o.Util.falseFn(this._el.offsetWidth))},_onStep:function(){var t=this._getPos();return t?(this._el._leaflet_pos=t,void this.fire("step")):void this._onTransitionEnd()},_transformRe:/([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,_getPos:function(){var e,i,n,s=this._el,a=t.getComputedStyle(s);if(o.Browser.any3d){if(n=a[o.DomUtil.TRANSFORM].match(this._transformRe),!n)return;e=parseFloat(n[1]),i=parseFloat(n[2])}else e=parseFloat(a.left),i=parseFloat(a.top);return new o.Point(e,i,!0)},_onTransitionEnd:function(){o.DomEvent.off(this._el,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),this._inProgress&&(this._inProgress=!1,this._el.style[o.DomUtil.TRANSITION]="",this._el._leaflet_pos=this._newPos,clearInterval(this._stepTimer),this.fire("step").fire("end"))}}),o.Map.include({setView:function(t,e,n){if(e=e===i?this._zoom:this._limitZoom(e),t=this._limitCenter(o.latLng(t),e,this.options.maxBounds),n=n||{},this._panAnim&&this._panAnim.stop(),this._loaded&&!n.reset&&n!==!0){n.animate!==i&&(n.zoom=o.extend({animate:n.animate},n.zoom),n.pan=o.extend({animate:n.animate},n.pan));var s=this._zoom!==e?this._tryAnimatedZoom&&this._tryAnimatedZoom(t,e,n.zoom):this._tryAnimatedPan(t,n.pan);if(s)return clearTimeout(this._sizeTimer),this}return this._resetView(t,e),this},panBy:function(t,e){if(t=o.point(t).round(),e=e||{},!t.x&&!t.y)return this;if(this._panAnim||(this._panAnim=new o.PosAnimation,this._panAnim.on({step:this._onPanTransitionStep,end:this._onPanTransitionEnd},this)),e.noMoveStart||this.fire("movestart"),e.animate!==!1){o.DomUtil.addClass(this._mapPane,"leaflet-pan-anim");var i=this._getMapPanePos().subtract(t);this._panAnim.run(this._mapPane,i,e.duration||.25,e.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){o.DomUtil.removeClass(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,e){var i=this._getCenterOffset(t)._floor();return(e&&e.animate)===!0||this.getSize().contains(i)?(this.panBy(i,e),!0):!1}}),o.PosAnimation=o.DomUtil.TRANSITION?o.PosAnimation:o.PosAnimation.extend({run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=i||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=o.DomUtil.getPosition(t),this._offset=e.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(),this._complete())},_animate:function(){this._animId=o.Util.requestAnimFrame(this._animate,this),this._step()},_step:function(){var t=+new Date-this._startTime,e=1e3*this._duration;e>t?this._runFrame(this._easeOut(t/e)):(this._runFrame(1),this._complete())},_runFrame:function(t){var e=this._startPos.add(this._offset.multiplyBy(t));o.DomUtil.setPosition(this._el,e),this.fire("step")},_complete:function(){o.Util.cancelAnimFrame(this._animId),this._inProgress=!1,this.fire("end")},_easeOut:function(t){return 1-Math.pow(1-t,this._easeOutPower)}}),o.Map.mergeOptions({zoomAnimation:!0,zoomAnimationThreshold:4}),o.DomUtil.TRANSITION&&o.Map.addInitHook(function(){this._zoomAnimated=this.options.zoomAnimation&&o.DomUtil.TRANSITION&&o.Browser.any3d&&!o.Browser.android23&&!o.Browser.mobileOpera,this._zoomAnimated&&o.DomEvent.on(this._mapPane,o.DomUtil.TRANSITION_END,this._catchTransitionEnd,this)}),o.Map.include(o.DomUtil.TRANSITION?{_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,e,i){if(this._animatingZoom)return!0;if(i=i||{},!this._zoomAnimated||i.animate===!1||this._nothingToAnimate()||Math.abs(e-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(e),o=this._getCenterOffset(t)._divideBy(1-1/n),s=this._getCenterLayerPoint()._add(o);return i.animate===!0||this.getSize().contains(o)?(this.fire("movestart").fire("zoomstart"),this._animateZoom(t,e,s,n,null,!0),!0):!1},_animateZoom:function(t,e,i,n,s,a,r){r||(this._animatingZoom=!0),o.DomUtil.addClass(this._mapPane,"leaflet-zoom-anim"),this._animateToCenter=t,this._animateToZoom=e,o.Draggable&&(o.Draggable._disabled=!0),o.Util.requestAnimFrame(function(){this.fire("zoomanim",{center:t,zoom:e,origin:i,scale:n,delta:s,backwards:a})},this)},_onZoomTransitionEnd:function(){this._animatingZoom=!1,o.DomUtil.removeClass(this._mapPane,"leaflet-zoom-anim"),this._resetView(this._animateToCenter,this._animateToZoom,!0,!0),o.Draggable&&(o.Draggable._disabled=!1)}}:{}),o.TileLayer.include({_animateZoom:function(t){this._animating||(this._animating=!0,this._prepareBgBuffer());var e=this._bgBuffer,i=o.DomUtil.TRANSFORM,n=t.delta?o.DomUtil.getTranslateString(t.delta):e.style[i],s=o.DomUtil.getScaleString(t.scale,t.origin);e.style[i]=t.backwards?s+" "+n:n+" "+s},_endZoomAnim:function(){var t=this._tileContainer,e=this._bgBuffer;t.style.visibility="",t.parentNode.appendChild(t),o.Util.falseFn(e.offsetWidth),this._animating=!1},_clearBgBuffer:function(){var t=this._map;!t||t._animatingZoom||t.touchZoom._zooming||(this._bgBuffer.innerHTML="",this._bgBuffer.style[o.DomUtil.TRANSFORM]="")},_prepareBgBuffer:function(){var t=this._tileContainer,e=this._bgBuffer,i=this._getLoadedTilesPercentage(e),n=this._getLoadedTilesPercentage(t);return e&&i>.5&&.5>n?(t.style.visibility="hidden",void this._stopLoadingImages(t)):(e.style.visibility="hidden",e.style[o.DomUtil.TRANSFORM]="",this._tileContainer=e,e=this._bgBuffer=t,this._stopLoadingImages(e),void clearTimeout(this._clearBgBufferTimer))},_getLoadedTilesPercentage:function(t){var e,i,n=t.getElementsByTagName("img"),o=0;for(e=0,i=n.length;i>e;e++)n[e].complete&&o++;return o/i},_stopLoadingImages:function(t){var e,i,n,s=Array.prototype.slice.call(t.getElementsByTagName("img"));for(e=0,i=s.length;i>e;e++)n=s[e],n.complete||(n.onload=o.Util.falseFn,n.onerror=o.Util.falseFn,n.src=o.Util.emptyImageUrl,n.parentNode.removeChild(n))}}),o.Map.include({_defaultLocateOptions:{watch:!1,setView:!1,maxZoom:1/0,timeout:1e4,maximumAge:0,enableHighAccuracy:!1},locate:function(t){if(t=this._locateOptions=o.extend(this._defaultLocateOptions,t),!navigator.geolocation)return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var e=o.bind(this._handleGeolocationResponse,this),i=o.bind(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e=t.code,i=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+i+"."})},_handleGeolocationResponse:function(t){var e=t.coords.latitude,i=t.coords.longitude,n=new o.LatLng(e,i),s=180*t.coords.accuracy/40075017,a=s/Math.cos(o.LatLng.DEG_TO_RAD*e),r=o.latLngBounds([e-s,i-a],[e+s,i+a]),h=this._locateOptions;if(h.setView){var l=Math.min(this.getBoundsZoom(r),h.maxZoom);this.setView(n,l)}var u={latlng:n,bounds:r,timestamp:t.timestamp};for(var c in t.coords)"number"==typeof t.coords[c]&&(u[c]=t.coords[c]);this.fire("locationfound",u)}})}(window,document); | |
| 0 | 10 | \ No newline at end of file | ... | ... |
locales/controllet_ln.js
| ... | ... | @@ -77,6 +77,7 @@ ln["scatterchart_en"] = "Scatter"; |
| 77 | 77 | ln["bubblechart_en"] = "Bubble"; |
| 78 | 78 | ln["treemap_en"] = "Tree Map"; |
| 79 | 79 | ln["leafletjs_en"] = "Map"; |
| 80 | +ln["leafletjs-geojson_en"] = "Map Geojson"; | |
| 80 | 81 | |
| 81 | 82 | //inputs |
| 82 | 83 | ln["expertGroupBy_en"] = "EXPERT : GROUP BY"; |
| ... | ... | @@ -107,6 +108,7 @@ ln["SliceSizes_en"] = "SIZE [num]"; |
| 107 | 108 | ln["Latitude_en"] = "LATITUDE"; |
| 108 | 109 | ln["Longitude_en"] = "LONGITUDE"; |
| 109 | 110 | ln["BalloonContent_en"] = "BALLOON CONTENT";// [opt] |
| 111 | +ln["GEOJSON_en"] = "GEOJSON"; | |
| 110 | 112 | ln["BubbleContent_en"] = "BUBBLE CONTENT"; |
| 111 | 113 | ln["BubbleSize_en"] = "BUBBLE SIZE [num]"; |
| 112 | 114 | ln["Categories_en"] = "CATEGORY [opt]"; |
| ... | ... | @@ -201,6 +203,7 @@ ln["scatterchart_it"] = "Grafico a dispersione"; |
| 201 | 203 | ln["bubblechart_it"] = "Grafico a bolle"; |
| 202 | 204 | ln["treemap_it"] = "Grafico ad albero"; |
| 203 | 205 | ln["leafletjs_it"] = "Mappa"; |
| 206 | +ln["leafletjs-geojson_it"] = "Mappa geojson"; | |
| 204 | 207 | |
| 205 | 208 | //inputs |
| 206 | 209 | ln["expertGroupBy_it"] = "ESPERTO : RAGGRUPPA"; |
| ... | ... | @@ -231,6 +234,7 @@ ln["SliceSizes_it"] = "DIMENSIONE [num]"; |
| 231 | 234 | ln["Latitude_it"] = "LATITUDINE"; |
| 232 | 235 | ln["Longitude_it"] = "LONGITUDINE"; |
| 233 | 236 | ln["BalloonContent_it"] = "CONTENUTO"; |
| 237 | +ln["GEOJSON_it"] = "GEOJSON"; | |
| 234 | 238 | ln["BubbleContent_it"] = "CONTENUTO BOLLA"; |
| 235 | 239 | ln["BubbleSize_it"] = "DIMENSIONE BOLLA [num]"; |
| 236 | 240 | ln["Categories_it"] = "CATEGORIA [opt]"; |
| ... | ... | @@ -325,6 +329,7 @@ ln["scatterchart_fr"] = "Scatter"; |
| 325 | 329 | ln["bubblechart_fr"] = "Bubble"; |
| 326 | 330 | ln["treemap_fr"] = "Tree Map"; |
| 327 | 331 | ln["leafletjs_fr"] = "Map"; |
| 332 | +ln["leafletjs-geojson_fr"] = "Map Geojson"; | |
| 328 | 333 | |
| 329 | 334 | //inputs |
| 330 | 335 | ln["expertGroupBy_fr"] = "EXPERT : GROUP BY"; |
| ... | ... | @@ -355,6 +360,7 @@ ln["SliceSizes_fr"] = "SIZE [num]"; |
| 355 | 360 | ln["Latitude_fr"] = "LATITUDE"; |
| 356 | 361 | ln["Longitude_fr"] = "LONGITUDE"; |
| 357 | 362 | ln["BalloonContent_fr"] = "BALLOON CONTENT";// [opt] |
| 363 | +ln["GEOJSON_fr"] = "GEOJSON"; | |
| 358 | 364 | ln["BubbleContent_fr"] = "BUBBLE CONTENT"; |
| 359 | 365 | ln["BubbleSize_fr"] = "BUBBLE SIZE [num]"; |
| 360 | 366 | ln["Categories_fr"] = "CATEGORY [opt]"; |
| ... | ... | @@ -449,6 +455,7 @@ ln["scatterchart_nl"] = "Scatter"; |
| 449 | 455 | ln["bubblechart_nl"] = "Bubble"; |
| 450 | 456 | ln["treemap_nl"] = "Tree Map"; |
| 451 | 457 | ln["leafletjs_nl"] = "Map"; |
| 458 | +ln["leafletjs-geojson_nl"] = "Map Geojson"; | |
| 452 | 459 | |
| 453 | 460 | //inputs |
| 454 | 461 | ln["expertGroupBy_nl"] = "EXPERT : GROUP BY"; |
| ... | ... | @@ -479,6 +486,7 @@ ln["SliceSizes_nl"] = "SIZE [num]"; |
| 479 | 486 | ln["Latitude_nl"] = "LATITUDE"; |
| 480 | 487 | ln["Longitude_nl"] = "LONGITUDE"; |
| 481 | 488 | ln["BalloonContent_nl"] = "BALLOON CONTENT";// [opt] |
| 489 | +ln["GEOJSON_nl"] = "GEOJSON"; | |
| 482 | 490 | ln["BubbleContent_nl"] = "BUBBLE CONTENT"; |
| 483 | 491 | ln["BubbleSize_nl"] = "BUBBLE SIZE [num]"; |
| 484 | 492 | ln["Categories_nl"] = "CATEGORY [opt]"; | ... | ... |