react-leaflet-deflate 2.2.0 → 3.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2866 +1,319 @@
1
- (function webpackUniversalModuleDefinition(root, factory) {
2
- if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("leaflet"), require("react-leaflet"));
4
- else if(typeof define === 'function' && define.amd)
5
- define(["leaflet", "react-leaflet"], factory);
6
- else if(typeof exports === 'object')
7
- exports["ReactLeafletDeflate"] = factory(require("leaflet"), require("react-leaflet"));
8
- else
9
- root["ReactLeafletDeflate"] = factory(root["L"], root["ReactLeaflet"]);
10
- })(this, function(__WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_4__) {
11
- return /******/ (function(modules) { // webpackBootstrap
12
- /******/ // The module cache
13
- /******/ var installedModules = {};
14
-
15
- /******/ // The require function
16
- /******/ function __webpack_require__(moduleId) {
17
-
18
- /******/ // Check if module is in cache
19
- /******/ if(installedModules[moduleId])
20
- /******/ return installedModules[moduleId].exports;
21
-
22
- /******/ // Create a new module (and put it into the cache)
23
- /******/ var module = installedModules[moduleId] = {
24
- /******/ exports: {},
25
- /******/ id: moduleId,
26
- /******/ loaded: false
27
- /******/ };
28
-
29
- /******/ // Execute the module function
30
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31
-
32
- /******/ // Flag the module as loaded
33
- /******/ module.loaded = true;
34
-
35
- /******/ // Return the exports of the module
36
- /******/ return module.exports;
37
- /******/ }
38
-
39
-
40
- /******/ // expose the modules object (__webpack_modules__)
41
- /******/ __webpack_require__.m = modules;
42
-
43
- /******/ // expose the module cache
44
- /******/ __webpack_require__.c = installedModules;
45
-
46
- /******/ // __webpack_public_path__
47
- /******/ __webpack_require__.p = "";
48
-
49
- /******/ // Load entry module and return exports
50
- /******/ return __webpack_require__(0);
51
- /******/ })
52
- /************************************************************************/
53
- /******/ ([
54
- /* 0 */
55
- /***/ (function(module, exports, __webpack_require__) {
56
-
57
- 'use strict';
58
-
59
- Object.defineProperty(exports, "__esModule", {
60
- value: true
61
- });
62
-
63
- var _Deflate = __webpack_require__(1);
64
-
65
- var _Deflate2 = _interopRequireDefault(_Deflate);
66
-
67
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
68
-
69
- exports.default = _Deflate2.default;
70
-
71
- /***/ }),
72
- /* 1 */
73
- /***/ (function(module, exports, __webpack_require__) {
74
-
75
- 'use strict';
76
-
77
- Object.defineProperty(exports, "__esModule", {
78
- value: true
79
- });
80
-
81
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
82
-
83
- var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
84
-
85
- var _leaflet = __webpack_require__(2);
86
-
87
- var _leaflet2 = _interopRequireDefault(_leaflet);
88
-
89
- var _Leaflet = __webpack_require__(3);
90
-
91
- var _reactLeaflet = __webpack_require__(4);
92
-
93
- __webpack_require__(5);
94
-
95
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
96
-
97
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
98
-
99
- function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
100
-
101
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
102
-
103
- var Deflate = function (_MapLayer) {
104
- _inherits(Deflate, _MapLayer);
105
-
106
- function Deflate() {
107
- _classCallCheck(this, Deflate);
108
-
109
- return _possibleConstructorReturn(this, (Deflate.__proto__ || Object.getPrototypeOf(Deflate)).apply(this, arguments));
110
- }
111
-
112
- _createClass(Deflate, [{
113
- key: 'createLeafletElement',
114
- value: function createLeafletElement(props) {
115
- return new _Leaflet.DeflatedFeatureGroup(props);
116
- }
117
- }, {
118
- key: 'componentDidMount',
119
- value: function componentDidMount() {
120
- var _ref = this.props.leaflet || this.context,
121
- map = _ref.map;
122
-
123
- var markerCluster = this.props.markerCluster;
124
- // This will add our DeflatedFeatureGroup (this.leafletElement) to the map--something that must happen BEFORE
125
- // we can add anything to DeflatedFeatureGroup itself.
126
-
127
- _get(Deflate.prototype.__proto__ || Object.getPrototypeOf(Deflate.prototype), 'componentDidMount', this).call(this);
128
- _leaflet2.default.geoJSON(this.props.data, this.props).addTo(this.leafletElement);
129
- if (markerCluster) map._container.className += ' leaflet-cluster-anim marker-cluster-styled marker-cluster-animated';
130
- }
131
- }, {
132
- key: 'updateLeafletElement',
133
- value: function updateLeafletElement(fromProps, toProps) {
134
- this.props.leaflet.layerContainer.removeLayer(this.leafletElement);
135
- this.leafletElement = new _Leaflet.DeflatedFeatureGroup(toProps);
136
- this.props.leaflet.layerContainer.addLayer(this.leafletElement);
137
- _leaflet2.default.geoJSON(toProps.data, toProps).addTo(this.leafletElement);
138
- }
139
- }]);
140
-
141
- return Deflate;
142
- }(_reactLeaflet.MapLayer);
143
-
144
- exports.default = Deflate;
145
-
146
- /***/ }),
147
- /* 2 */
148
- /***/ (function(module, exports) {
149
-
150
- module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
151
-
152
- /***/ }),
153
- /* 3 */
154
- /***/ (function(module, exports) {
155
-
156
- L.Deflate=L.FeatureGroup.extend({options:{minSize:10,markerCluster:false,markerOptions:{},markerClusterOptions:{}},initialize:function(options){L.Util.setOptions(this,options);this._allLayers=[];L.FeatureGroup.prototype.initialize.call(this,[],options);if(options.markerCluster){this.clusterLayer=L.markerClusterGroup(this.options.markerClusterOptions)}},_getBounds:function(path){if(path instanceof L.Circle){path.addTo(this._map);var bounds=path.getBounds();this._map.removeLayer(path);return bounds}return path.getBounds()},_isCollapsed:function(path,zoom){var bounds=path.computedBounds;var ne_px=this._map.project(bounds.getNorthEast(),zoom);var sw_px=this._map.project(bounds.getSouthWest(),zoom);var width=ne_px.x-sw_px.x;var height=sw_px.y-ne_px.y;return height<this.options.minSize||width<this.options.minSize},_getZoomThreshold:function(path){var zoomThreshold=null;var zoom=this._map.getZoom();if(this._isCollapsed(path,this._map.getZoom())){while(!zoomThreshold){zoom+=1;if(!this._isCollapsed(path,zoom)){zoomThreshold=zoom-1}}}else{while(!zoomThreshold){zoom-=1;if(this._isCollapsed(path,zoom)){zoomThreshold=zoom}}}return zoomThreshold},_bindInfoTools:function(marker,parentLayer){if(parentLayer._popupHandlersAdded){marker.bindPopup(parentLayer._popup._content,parentLayer._popup.options)}if(parentLayer._tooltipHandlersAdded){marker.bindTooltip(parentLayer._tooltip._content,parentLayer._tooltip.options)}},_bindEvents:function(marker,parentLayer){this._bindInfoTools(marker,parentLayer);var events=parentLayer._events;for(var event in events){if(events.hasOwnProperty(event)){var listeners=events[event];for(var i=0,len=listeners.length;i<len;i++){marker.on(event,listeners[i].fn)}}}if(!parentLayer._eventParents){return}for(var key in parentLayer._eventParents){if(parentLayer._eventParents.hasOwnProperty(key)){if(parentLayer._eventParents[key]._map){continue}this._bindEvents(marker,parentLayer._eventParents[key]);this._bindInfoTools(parentLayer,parentLayer._eventParents[key])}}},_makeMarker:function(layer){var markerOptions;if(typeof this.options.markerOptions==="function"){markerOptions=this.options.markerOptions(layer)}else{markerOptions=this.options.markerOptions}var marker=L.marker(layer.computedBounds.getCenter(),markerOptions);this._bindEvents(marker,layer);if(layer.feature){var markerFeature=marker.toGeoJSON();markerFeature.properties=layer.feature.properties;marker.feature=markerFeature}return marker},addLayer:function(layer){if(layer instanceof L.FeatureGroup){for(var i in layer._layers){this.addLayer(layer._layers[i])}}else{var layerToAdd=layer;if(layer.getBounds&&!layer.zoomThreshold&&!layer.marker){layer.computedBounds=this._getBounds(layer);var zoomThreshold=this._getZoomThreshold(layer);layer.zoomThreshold=zoomThreshold;layer.marker=this._makeMarker(layer);layer.zoomState=this._map.getZoom();if(this._map.getZoom()<=zoomThreshold){layerToAdd=layer.marker}this._allLayers.push(layer)}if(this.clusterLayer){this.clusterLayer.addLayer(layerToAdd)}else{L.FeatureGroup.prototype.addLayer.call(this,layerToAdd)}}},removeLayer:function(layer){if(layer instanceof L.FeatureGroup){for(var i in layer._layers){this.removeLayer(layer._layers[i])}}else{var markerLayer=this.clusterLayer?this.clusterLayer:this._map;markerLayer.removeLayer(layer);if(layer.marker){markerLayer.removeLayer(layer.marker)}var index=this._allLayers.indexOf(layer);if(index!==-1){this._allLayers.splice(index,1)}}},clearLayers:function(){if(this.clusterLayer){this.clusterLayer.clearLayers();this._allLayers=[]}else{L.FeatureGroup.prototype.clearLayers.call(this)}},_switchDisplay:function(layer,showMarker){var markerLayer=this.clusterLayer?this.clusterLayer:this._map;if(showMarker){markerLayer.addLayer(layer.marker);markerLayer.removeLayer(layer)}else{markerLayer.addLayer(layer);markerLayer.removeLayer(layer.marker)}},_deflate:function(){var bounds=this._map.getBounds();var endZoom=this._map.getZoom();for(var i=0,len=this._allLayers.length;i<len;i++){if(this._allLayers[i].marker&&this._allLayers[i].zoomState!==endZoom&&this._allLayers[i].computedBounds.intersects(bounds)){this._switchDisplay(this._allLayers[i],endZoom<=this._allLayers[i].zoomThreshold);this._allLayers[i].zoomState=endZoom}}},onAdd:function(map){if(this.clusterLayer){this.clusterLayer.addTo(map)}this._map.on("zoomend",this._deflate,this);this._map.on("moveend",this._deflate,this)},onRemove:function(map){if(this.clusterLayer){map.removeLayer(this.cluster)}this._map.off("zoomend",this._deflate,this);this._map.off("moveend",this._deflate,this)}});L.deflate=function(options){return new L.Deflate(options)};
157
-
158
- /*** EXPORTS FROM exports-loader ***/
159
- exports["DeflatedFeatureGroup"] = (L.Deflate);
160
-
161
- /***/ }),
162
- /* 4 */
163
- /***/ (function(module, exports) {
164
-
165
- module.exports = __WEBPACK_EXTERNAL_MODULE_4__;
166
-
167
- /***/ }),
168
- /* 5 */
169
- /***/ (function(module, exports, __webpack_require__) {
170
-
171
- /*
172
- * Leaflet.markercluster 1.4.1+master.94f9815,
173
- * Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps.
174
- * https://github.com/Leaflet/Leaflet.markercluster
175
- * (c) 2012-2017, Dave Leaver, smartrak
176
- */
177
- (function (global, factory) {
178
- true ? factory(exports) :
179
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
180
- (factory((global.Leaflet = global.Leaflet || {}, global.Leaflet.markercluster = global.Leaflet.markercluster || {})));
181
- }(this, (function (exports) { 'use strict';
182
-
183
- /*
184
- * L.MarkerClusterGroup extends L.FeatureGroup by clustering the markers contained within
185
- */
186
-
187
- var MarkerClusterGroup = L.MarkerClusterGroup = L.FeatureGroup.extend({
188
-
189
- options: {
190
- maxClusterRadius: 80, //A cluster will cover at most this many pixels from its center
191
- iconCreateFunction: null,
192
- clusterPane: L.Marker.prototype.options.pane,
193
-
194
- spiderfyOnMaxZoom: true,
195
- showCoverageOnHover: true,
196
- zoomToBoundsOnClick: true,
197
- singleMarkerMode: false,
198
-
199
- disableClusteringAtZoom: null,
200
-
201
- // Setting this to false prevents the removal of any clusters outside of the viewpoint, which
202
- // is the default behaviour for performance reasons.
203
- removeOutsideVisibleBounds: true,
204
-
205
- // Set to false to disable all animations (zoom and spiderfy).
206
- // If false, option animateAddingMarkers below has no effect.
207
- // If L.DomUtil.TRANSITION is falsy, this option has no effect.
208
- animate: true,
209
-
210
- //Whether to animate adding markers after adding the MarkerClusterGroup to the map
211
- // If you are adding individual markers set to true, if adding bulk markers leave false for massive performance gains.
212
- animateAddingMarkers: false,
213
-
214
- //Increase to increase the distance away that spiderfied markers appear from the center
215
- spiderfyDistanceMultiplier: 1,
216
-
217
- // Make it possible to specify a polyline options on a spider leg
218
- spiderLegPolylineOptions: { weight: 1.5, color: '#222', opacity: 0.5 },
219
-
220
- // When bulk adding layers, adds markers in chunks. Means addLayers may not add all the layers in the call, others will be loaded during setTimeouts
221
- chunkedLoading: false,
222
- chunkInterval: 200, // process markers for a maximum of ~ n milliseconds (then trigger the chunkProgress callback)
223
- chunkDelay: 50, // at the end of each interval, give n milliseconds back to system/browser
224
- chunkProgress: null, // progress callback: function(processed, total, elapsed) (e.g. for a progress indicator)
225
-
226
- //Options to pass to the L.Polygon constructor
227
- polygonOptions: {}
228
- },
229
-
230
- initialize: function (options) {
231
- L.Util.setOptions(this, options);
232
- if (!this.options.iconCreateFunction) {
233
- this.options.iconCreateFunction = this._defaultIconCreateFunction;
234
- }
235
-
236
- this._featureGroup = L.featureGroup();
237
- this._featureGroup.addEventParent(this);
238
-
239
- this._nonPointGroup = L.featureGroup();
240
- this._nonPointGroup.addEventParent(this);
241
-
242
- this._inZoomAnimation = 0;
243
- this._needsClustering = [];
244
- this._needsRemoving = []; //Markers removed while we aren't on the map need to be kept track of
245
- //The bounds of the currently shown area (from _getExpandedVisibleBounds) Updated on zoom/move
246
- this._currentShownBounds = null;
247
-
248
- this._queue = [];
249
-
250
- this._childMarkerEventHandlers = {
251
- 'dragstart': this._childMarkerDragStart,
252
- 'move': this._childMarkerMoved,
253
- 'dragend': this._childMarkerDragEnd,
254
- };
255
-
256
- // Hook the appropriate animation methods.
257
- var animate = L.DomUtil.TRANSITION && this.options.animate;
258
- L.extend(this, animate ? this._withAnimation : this._noAnimation);
259
- // Remember which MarkerCluster class to instantiate (animated or not).
260
- this._markerCluster = animate ? L.MarkerCluster : L.MarkerClusterNonAnimated;
261
- },
262
-
263
- addLayer: function (layer) {
264
-
265
- if (layer instanceof L.LayerGroup) {
266
- return this.addLayers([layer]);
267
- }
268
-
269
- //Don't cluster non point data
270
- if (!layer.getLatLng) {
271
- this._nonPointGroup.addLayer(layer);
272
- this.fire('layeradd', { layer: layer });
273
- return this;
274
- }
275
-
276
- if (!this._map) {
277
- this._needsClustering.push(layer);
278
- this.fire('layeradd', { layer: layer });
279
- return this;
280
- }
281
-
282
- if (this.hasLayer(layer)) {
283
- return this;
284
- }
285
-
286
-
287
- //If we have already clustered we'll need to add this one to a cluster
288
-
289
- if (this._unspiderfy) {
290
- this._unspiderfy();
291
- }
292
-
293
- this._addLayer(layer, this._maxZoom);
294
- this.fire('layeradd', { layer: layer });
295
-
296
- // Refresh bounds and weighted positions.
297
- this._topClusterLevel._recalculateBounds();
298
-
299
- this._refreshClustersIcons();
300
-
301
- //Work out what is visible
302
- var visibleLayer = layer,
303
- currentZoom = this._zoom;
304
- if (layer.__parent) {
305
- while (visibleLayer.__parent._zoom >= currentZoom) {
306
- visibleLayer = visibleLayer.__parent;
307
- }
308
- }
309
-
310
- if (this._currentShownBounds.contains(visibleLayer.getLatLng())) {
311
- if (this.options.animateAddingMarkers) {
312
- this._animationAddLayer(layer, visibleLayer);
313
- } else {
314
- this._animationAddLayerNonAnimated(layer, visibleLayer);
315
- }
316
- }
317
- return this;
318
- },
319
-
320
- removeLayer: function (layer) {
321
-
322
- if (layer instanceof L.LayerGroup) {
323
- return this.removeLayers([layer]);
324
- }
325
-
326
- //Non point layers
327
- if (!layer.getLatLng) {
328
- this._nonPointGroup.removeLayer(layer);
329
- this.fire('layerremove', { layer: layer });
330
- return this;
331
- }
332
-
333
- if (!this._map) {
334
- if (!this._arraySplice(this._needsClustering, layer) && this.hasLayer(layer)) {
335
- this._needsRemoving.push({ layer: layer, latlng: layer._latlng });
336
- }
337
- this.fire('layerremove', { layer: layer });
338
- return this;
339
- }
340
-
341
- if (!layer.__parent) {
342
- return this;
343
- }
344
-
345
- if (this._unspiderfy) {
346
- this._unspiderfy();
347
- this._unspiderfyLayer(layer);
348
- }
349
-
350
- //Remove the marker from clusters
351
- this._removeLayer(layer, true);
352
- this.fire('layerremove', { layer: layer });
353
-
354
- // Refresh bounds and weighted positions.
355
- this._topClusterLevel._recalculateBounds();
356
-
357
- this._refreshClustersIcons();
358
-
359
- layer.off(this._childMarkerEventHandlers, this);
360
-
361
- if (this._featureGroup.hasLayer(layer)) {
362
- this._featureGroup.removeLayer(layer);
363
- if (layer.clusterShow) {
364
- layer.clusterShow();
365
- }
366
- }
367
-
368
- return this;
369
- },
370
-
371
- //Takes an array of markers and adds them in bulk
372
- addLayers: function (layersArray, skipLayerAddEvent) {
373
- if (!L.Util.isArray(layersArray)) {
374
- return this.addLayer(layersArray);
375
- }
376
-
377
- var fg = this._featureGroup,
378
- npg = this._nonPointGroup,
379
- chunked = this.options.chunkedLoading,
380
- chunkInterval = this.options.chunkInterval,
381
- chunkProgress = this.options.chunkProgress,
382
- l = layersArray.length,
383
- offset = 0,
384
- originalArray = true,
385
- m;
386
-
387
- if (this._map) {
388
- var started = (new Date()).getTime();
389
- var process = L.bind(function () {
390
- var start = (new Date()).getTime();
391
- for (; offset < l; offset++) {
392
- if (chunked && offset % 200 === 0) {
393
- // every couple hundred markers, instrument the time elapsed since processing started:
394
- var elapsed = (new Date()).getTime() - start;
395
- if (elapsed > chunkInterval) {
396
- break; // been working too hard, time to take a break :-)
397
- }
398
- }
399
-
400
- m = layersArray[offset];
401
-
402
- // Group of layers, append children to layersArray and skip.
403
- // Side effects:
404
- // - Total increases, so chunkProgress ratio jumps backward.
405
- // - Groups are not included in this group, only their non-group child layers (hasLayer).
406
- // Changing array length while looping does not affect performance in current browsers:
407
- // http://jsperf.com/for-loop-changing-length/6
408
- if (m instanceof L.LayerGroup) {
409
- if (originalArray) {
410
- layersArray = layersArray.slice();
411
- originalArray = false;
412
- }
413
- this._extractNonGroupLayers(m, layersArray);
414
- l = layersArray.length;
415
- continue;
416
- }
417
-
418
- //Not point data, can't be clustered
419
- if (!m.getLatLng) {
420
- npg.addLayer(m);
421
- if (!skipLayerAddEvent) {
422
- this.fire('layeradd', { layer: m });
423
- }
424
- continue;
425
- }
426
-
427
- if (this.hasLayer(m)) {
428
- continue;
429
- }
430
-
431
- this._addLayer(m, this._maxZoom);
432
- if (!skipLayerAddEvent) {
433
- this.fire('layeradd', { layer: m });
434
- }
435
-
436
- //If we just made a cluster of size 2 then we need to remove the other marker from the map (if it is) or we never will
437
- if (m.__parent) {
438
- if (m.__parent.getChildCount() === 2) {
439
- var markers = m.__parent.getAllChildMarkers(),
440
- otherMarker = markers[0] === m ? markers[1] : markers[0];
441
- fg.removeLayer(otherMarker);
442
- }
443
- }
444
- }
445
-
446
- if (chunkProgress) {
447
- // report progress and time elapsed:
448
- chunkProgress(offset, l, (new Date()).getTime() - started);
449
- }
450
-
451
- // Completed processing all markers.
452
- if (offset === l) {
453
-
454
- // Refresh bounds and weighted positions.
455
- this._topClusterLevel._recalculateBounds();
456
-
457
- this._refreshClustersIcons();
458
-
459
- this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);
460
- } else {
461
- setTimeout(process, this.options.chunkDelay);
462
- }
463
- }, this);
464
-
465
- process();
466
- } else {
467
- var needsClustering = this._needsClustering;
468
-
469
- for (; offset < l; offset++) {
470
- m = layersArray[offset];
471
-
472
- // Group of layers, append children to layersArray and skip.
473
- if (m instanceof L.LayerGroup) {
474
- if (originalArray) {
475
- layersArray = layersArray.slice();
476
- originalArray = false;
477
- }
478
- this._extractNonGroupLayers(m, layersArray);
479
- l = layersArray.length;
480
- continue;
481
- }
482
-
483
- //Not point data, can't be clustered
484
- if (!m.getLatLng) {
485
- npg.addLayer(m);
486
- continue;
487
- }
488
-
489
- if (this.hasLayer(m)) {
490
- continue;
491
- }
492
-
493
- needsClustering.push(m);
494
- }
495
- }
496
- return this;
497
- },
498
-
499
- //Takes an array of markers and removes them in bulk
500
- removeLayers: function (layersArray) {
501
- var i, m,
502
- l = layersArray.length,
503
- fg = this._featureGroup,
504
- npg = this._nonPointGroup,
505
- originalArray = true;
506
-
507
- if (!this._map) {
508
- for (i = 0; i < l; i++) {
509
- m = layersArray[i];
510
-
511
- // Group of layers, append children to layersArray and skip.
512
- if (m instanceof L.LayerGroup) {
513
- if (originalArray) {
514
- layersArray = layersArray.slice();
515
- originalArray = false;
516
- }
517
- this._extractNonGroupLayers(m, layersArray);
518
- l = layersArray.length;
519
- continue;
520
- }
521
-
522
- this._arraySplice(this._needsClustering, m);
523
- npg.removeLayer(m);
524
- if (this.hasLayer(m)) {
525
- this._needsRemoving.push({ layer: m, latlng: m._latlng });
526
- }
527
- this.fire('layerremove', { layer: m });
528
- }
529
- return this;
530
- }
531
-
532
- if (this._unspiderfy) {
533
- this._unspiderfy();
534
-
535
- // Work on a copy of the array, so that next loop is not affected.
536
- var layersArray2 = layersArray.slice(),
537
- l2 = l;
538
- for (i = 0; i < l2; i++) {
539
- m = layersArray2[i];
540
-
541
- // Group of layers, append children to layersArray and skip.
542
- if (m instanceof L.LayerGroup) {
543
- this._extractNonGroupLayers(m, layersArray2);
544
- l2 = layersArray2.length;
545
- continue;
546
- }
547
-
548
- this._unspiderfyLayer(m);
549
- }
550
- }
551
-
552
- for (i = 0; i < l; i++) {
553
- m = layersArray[i];
554
-
555
- // Group of layers, append children to layersArray and skip.
556
- if (m instanceof L.LayerGroup) {
557
- if (originalArray) {
558
- layersArray = layersArray.slice();
559
- originalArray = false;
560
- }
561
- this._extractNonGroupLayers(m, layersArray);
562
- l = layersArray.length;
563
- continue;
564
- }
565
-
566
- if (!m.__parent) {
567
- npg.removeLayer(m);
568
- this.fire('layerremove', { layer: m });
569
- continue;
570
- }
571
-
572
- this._removeLayer(m, true, true);
573
- this.fire('layerremove', { layer: m });
574
-
575
- if (fg.hasLayer(m)) {
576
- fg.removeLayer(m);
577
- if (m.clusterShow) {
578
- m.clusterShow();
579
- }
580
- }
581
- }
582
-
583
- // Refresh bounds and weighted positions.
584
- this._topClusterLevel._recalculateBounds();
585
-
586
- this._refreshClustersIcons();
587
-
588
- //Fix up the clusters and markers on the map
589
- this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);
590
-
591
- return this;
592
- },
593
-
594
- //Removes all layers from the MarkerClusterGroup
595
- clearLayers: function () {
596
- //Need our own special implementation as the LayerGroup one doesn't work for us
597
-
598
- //If we aren't on the map (yet), blow away the markers we know of
599
- if (!this._map) {
600
- this._needsClustering = [];
601
- this._needsRemoving = [];
602
- delete this._gridClusters;
603
- delete this._gridUnclustered;
604
- }
605
-
606
- if (this._noanimationUnspiderfy) {
607
- this._noanimationUnspiderfy();
608
- }
609
-
610
- //Remove all the visible layers
611
- this._featureGroup.clearLayers();
612
- this._nonPointGroup.clearLayers();
613
-
614
- this.eachLayer(function (marker) {
615
- marker.off(this._childMarkerEventHandlers, this);
616
- delete marker.__parent;
617
- }, this);
618
-
619
- if (this._map) {
620
- //Reset _topClusterLevel and the DistanceGrids
621
- this._generateInitialClusters();
622
- }
623
-
624
- return this;
625
- },
626
-
627
- //Override FeatureGroup.getBounds as it doesn't work
628
- getBounds: function () {
629
- var bounds = new L.LatLngBounds();
630
-
631
- if (this._topClusterLevel) {
632
- bounds.extend(this._topClusterLevel._bounds);
633
- }
634
-
635
- for (var i = this._needsClustering.length - 1; i >= 0; i--) {
636
- bounds.extend(this._needsClustering[i].getLatLng());
637
- }
638
-
639
- bounds.extend(this._nonPointGroup.getBounds());
640
-
641
- return bounds;
642
- },
643
-
644
- //Overrides LayerGroup.eachLayer
645
- eachLayer: function (method, context) {
646
- var markers = this._needsClustering.slice(),
647
- needsRemoving = this._needsRemoving,
648
- thisNeedsRemoving, i, j;
649
-
650
- if (this._topClusterLevel) {
651
- this._topClusterLevel.getAllChildMarkers(markers);
652
- }
653
-
654
- for (i = markers.length - 1; i >= 0; i--) {
655
- thisNeedsRemoving = true;
656
-
657
- for (j = needsRemoving.length - 1; j >= 0; j--) {
658
- if (needsRemoving[j].layer === markers[i]) {
659
- thisNeedsRemoving = false;
660
- break;
661
- }
662
- }
663
-
664
- if (thisNeedsRemoving) {
665
- method.call(context, markers[i]);
666
- }
667
- }
668
-
669
- this._nonPointGroup.eachLayer(method, context);
670
- },
671
-
672
- //Overrides LayerGroup.getLayers
673
- getLayers: function () {
674
- var layers = [];
675
- this.eachLayer(function (l) {
676
- layers.push(l);
677
- });
678
- return layers;
679
- },
680
-
681
- //Overrides LayerGroup.getLayer, WARNING: Really bad performance
682
- getLayer: function (id) {
683
- var result = null;
684
-
685
- id = parseInt(id, 10);
686
-
687
- this.eachLayer(function (l) {
688
- if (L.stamp(l) === id) {
689
- result = l;
690
- }
691
- });
692
-
693
- return result;
694
- },
695
-
696
- //Returns true if the given layer is in this MarkerClusterGroup
697
- hasLayer: function (layer) {
698
- if (!layer) {
699
- return false;
700
- }
701
-
702
- var i, anArray = this._needsClustering;
703
-
704
- for (i = anArray.length - 1; i >= 0; i--) {
705
- if (anArray[i] === layer) {
706
- return true;
707
- }
708
- }
709
-
710
- anArray = this._needsRemoving;
711
- for (i = anArray.length - 1; i >= 0; i--) {
712
- if (anArray[i].layer === layer) {
713
- return false;
714
- }
715
- }
716
-
717
- return !!(layer.__parent && layer.__parent._group === this) || this._nonPointGroup.hasLayer(layer);
718
- },
719
-
720
- //Zoom down to show the given layer (spiderfying if necessary) then calls the callback
721
- zoomToShowLayer: function (layer, callback) {
722
-
723
- if (typeof callback !== 'function') {
724
- callback = function () {};
725
- }
726
-
727
- var showMarker = function () {
728
- if ((layer._icon || layer.__parent._icon) && !this._inZoomAnimation) {
729
- this._map.off('moveend', showMarker, this);
730
- this.off('animationend', showMarker, this);
731
-
732
- if (layer._icon) {
733
- callback();
734
- } else if (layer.__parent._icon) {
735
- this.once('spiderfied', callback, this);
736
- layer.__parent.spiderfy();
737
- }
738
- }
739
- };
740
-
741
- if (layer._icon && this._map.getBounds().contains(layer.getLatLng())) {
742
- //Layer is visible ond on screen, immediate return
743
- callback();
744
- } else if (layer.__parent._zoom < Math.round(this._map._zoom)) {
745
- //Layer should be visible at this zoom level. It must not be on screen so just pan over to it
746
- this._map.on('moveend', showMarker, this);
747
- this._map.panTo(layer.getLatLng());
748
- } else {
749
- this._map.on('moveend', showMarker, this);
750
- this.on('animationend', showMarker, this);
751
- layer.__parent.zoomToBounds();
752
- }
753
- },
754
-
755
- //Overrides FeatureGroup.onAdd
756
- onAdd: function (map) {
757
- this._map = map;
758
- var i, l, layer;
759
-
760
- if (!isFinite(this._map.getMaxZoom())) {
761
- throw "Map has no maxZoom specified";
762
- }
763
-
764
- this._featureGroup.addTo(map);
765
- this._nonPointGroup.addTo(map);
766
-
767
- if (!this._gridClusters) {
768
- this._generateInitialClusters();
769
- }
770
-
771
- this._maxLat = map.options.crs.projection.MAX_LATITUDE;
772
-
773
- //Restore all the positions as they are in the MCG before removing them
774
- for (i = 0, l = this._needsRemoving.length; i < l; i++) {
775
- layer = this._needsRemoving[i];
776
- layer.newlatlng = layer.layer._latlng;
777
- layer.layer._latlng = layer.latlng;
778
- }
779
- //Remove them, then restore their new positions
780
- for (i = 0, l = this._needsRemoving.length; i < l; i++) {
781
- layer = this._needsRemoving[i];
782
- this._removeLayer(layer.layer, true);
783
- layer.layer._latlng = layer.newlatlng;
784
- }
785
- this._needsRemoving = [];
786
-
787
- //Remember the current zoom level and bounds
788
- this._zoom = Math.round(this._map._zoom);
789
- this._currentShownBounds = this._getExpandedVisibleBounds();
790
-
791
- this._map.on('zoomend', this._zoomEnd, this);
792
- this._map.on('moveend', this._moveEnd, this);
793
-
794
- if (this._spiderfierOnAdd) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely
795
- this._spiderfierOnAdd();
796
- }
797
-
798
- this._bindEvents();
799
-
800
- //Actually add our markers to the map:
801
- l = this._needsClustering;
802
- this._needsClustering = [];
803
- this.addLayers(l, true);
804
- },
805
-
806
- //Overrides FeatureGroup.onRemove
807
- onRemove: function (map) {
808
- map.off('zoomend', this._zoomEnd, this);
809
- map.off('moveend', this._moveEnd, this);
810
-
811
- this._unbindEvents();
812
-
813
- //In case we are in a cluster animation
814
- this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', '');
815
-
816
- if (this._spiderfierOnRemove) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely
817
- this._spiderfierOnRemove();
818
- }
819
-
820
- delete this._maxLat;
821
-
822
- //Clean up all the layers we added to the map
823
- this._hideCoverage();
824
- this._featureGroup.remove();
825
- this._nonPointGroup.remove();
826
-
827
- this._featureGroup.clearLayers();
828
-
829
- this._map = null;
830
- },
831
-
832
- getVisibleParent: function (marker) {
833
- var vMarker = marker;
834
- while (vMarker && !vMarker._icon) {
835
- vMarker = vMarker.__parent;
836
- }
837
- return vMarker || null;
838
- },
839
-
840
- //Remove the given object from the given array
841
- _arraySplice: function (anArray, obj) {
842
- for (var i = anArray.length - 1; i >= 0; i--) {
843
- if (anArray[i] === obj) {
844
- anArray.splice(i, 1);
845
- return true;
846
- }
847
- }
848
- },
849
-
850
- /**
851
- * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom.
852
- * @param marker to be removed from _gridUnclustered.
853
- * @param z integer bottom start zoom level (included)
854
- * @private
855
- */
856
- _removeFromGridUnclustered: function (marker, z) {
857
- var map = this._map,
858
- gridUnclustered = this._gridUnclustered,
859
- minZoom = Math.floor(this._map.getMinZoom());
860
-
861
- for (; z >= minZoom; z--) {
862
- if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) {
863
- break;
864
- }
865
- }
866
- },
867
-
868
- _childMarkerDragStart: function (e) {
869
- e.target.__dragStart = e.target._latlng;
870
- },
871
-
872
- _childMarkerMoved: function (e) {
873
- if (!this._ignoreMove && !e.target.__dragStart) {
874
- var isPopupOpen = e.target._popup && e.target._popup.isOpen();
875
-
876
- this._moveChild(e.target, e.oldLatLng, e.latlng);
877
-
878
- if (isPopupOpen) {
879
- e.target.openPopup();
880
- }
881
- }
882
- },
883
-
884
- _moveChild: function (layer, from, to) {
885
- layer._latlng = from;
886
- this.removeLayer(layer);
887
-
888
- layer._latlng = to;
889
- this.addLayer(layer);
890
- },
891
-
892
- _childMarkerDragEnd: function (e) {
893
- var dragStart = e.target.__dragStart;
894
- delete e.target.__dragStart;
895
- if (dragStart) {
896
- this._moveChild(e.target, dragStart, e.target._latlng);
897
- }
898
- },
899
-
900
-
901
- //Internal function for removing a marker from everything.
902
- //dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions)
903
- _removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) {
904
- var gridClusters = this._gridClusters,
905
- gridUnclustered = this._gridUnclustered,
906
- fg = this._featureGroup,
907
- map = this._map,
908
- minZoom = Math.floor(this._map.getMinZoom());
909
-
910
- //Remove the marker from distance clusters it might be in
911
- if (removeFromDistanceGrid) {
912
- this._removeFromGridUnclustered(marker, this._maxZoom);
913
- }
914
-
915
- //Work our way up the clusters removing them as we go if required
916
- var cluster = marker.__parent,
917
- markers = cluster._markers,
918
- otherMarker;
919
-
920
- //Remove the marker from the immediate parents marker list
921
- this._arraySplice(markers, marker);
922
-
923
- while (cluster) {
924
- cluster._childCount--;
925
- cluster._boundsNeedUpdate = true;
926
-
927
- if (cluster._zoom < minZoom) {
928
- //Top level, do nothing
929
- break;
930
- } else if (removeFromDistanceGrid && cluster._childCount <= 1) { //Cluster no longer required
931
- //We need to push the other marker up to the parent
932
- otherMarker = cluster._markers[0] === marker ? cluster._markers[1] : cluster._markers[0];
933
-
934
- //Update distance grid
935
- gridClusters[cluster._zoom].removeObject(cluster, map.project(cluster._cLatLng, cluster._zoom));
936
- gridUnclustered[cluster._zoom].addObject(otherMarker, map.project(otherMarker.getLatLng(), cluster._zoom));
937
-
938
- //Move otherMarker up to parent
939
- this._arraySplice(cluster.__parent._childClusters, cluster);
940
- cluster.__parent._markers.push(otherMarker);
941
- otherMarker.__parent = cluster.__parent;
942
-
943
- if (cluster._icon) {
944
- //Cluster is currently on the map, need to put the marker on the map instead
945
- fg.removeLayer(cluster);
946
- if (!dontUpdateMap) {
947
- fg.addLayer(otherMarker);
948
- }
949
- }
950
- } else {
951
- cluster._iconNeedsUpdate = true;
952
- }
953
-
954
- cluster = cluster.__parent;
955
- }
956
-
957
- delete marker.__parent;
958
- },
959
-
960
- _isOrIsParent: function (el, oel) {
961
- while (oel) {
962
- if (el === oel) {
963
- return true;
964
- }
965
- oel = oel.parentNode;
966
- }
967
- return false;
968
- },
969
-
970
- //Override L.Evented.fire
971
- fire: function (type, data, propagate) {
972
- if (data && data.layer instanceof L.MarkerCluster) {
973
- //Prevent multiple clustermouseover/off events if the icon is made up of stacked divs (Doesn't work in ie <= 8, no relatedTarget)
974
- if (data.originalEvent && this._isOrIsParent(data.layer._icon, data.originalEvent.relatedTarget)) {
975
- return;
976
- }
977
- type = 'cluster' + type;
978
- }
979
-
980
- L.FeatureGroup.prototype.fire.call(this, type, data, propagate);
981
- },
982
-
983
- //Override L.Evented.listens
984
- listens: function (type, propagate) {
985
- return L.FeatureGroup.prototype.listens.call(this, type, propagate) || L.FeatureGroup.prototype.listens.call(this, 'cluster' + type, propagate);
986
- },
987
-
988
- //Default functionality
989
- _defaultIconCreateFunction: function (cluster) {
990
- var childCount = cluster.getChildCount();
991
-
992
- var c = ' marker-cluster-';
993
- if (childCount < 10) {
994
- c += 'small';
995
- } else if (childCount < 100) {
996
- c += 'medium';
997
- } else {
998
- c += 'large';
999
- }
1000
-
1001
- return new L.DivIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });
1002
- },
1003
-
1004
- _bindEvents: function () {
1005
- var map = this._map,
1006
- spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom,
1007
- showCoverageOnHover = this.options.showCoverageOnHover,
1008
- zoomToBoundsOnClick = this.options.zoomToBoundsOnClick;
1009
-
1010
- //Zoom on cluster click or spiderfy if we are at the lowest level
1011
- if (spiderfyOnMaxZoom || zoomToBoundsOnClick) {
1012
- this.on('clusterclick', this._zoomOrSpiderfy, this);
1013
- }
1014
-
1015
- //Show convex hull (boundary) polygon on mouse over
1016
- if (showCoverageOnHover) {
1017
- this.on('clustermouseover', this._showCoverage, this);
1018
- this.on('clustermouseout', this._hideCoverage, this);
1019
- map.on('zoomend', this._hideCoverage, this);
1020
- }
1021
- },
1022
-
1023
- _zoomOrSpiderfy: function (e) {
1024
- var cluster = e.layer,
1025
- bottomCluster = cluster;
1026
-
1027
- while (bottomCluster._childClusters.length === 1) {
1028
- bottomCluster = bottomCluster._childClusters[0];
1029
- }
1030
-
1031
- if (bottomCluster._zoom === this._maxZoom &&
1032
- bottomCluster._childCount === cluster._childCount &&
1033
- this.options.spiderfyOnMaxZoom) {
1034
-
1035
- // All child markers are contained in a single cluster from this._maxZoom to this cluster.
1036
- cluster.spiderfy();
1037
- } else if (this.options.zoomToBoundsOnClick) {
1038
- cluster.zoomToBounds();
1039
- }
1040
-
1041
- // Focus the map again for keyboard users.
1042
- if (e.originalEvent && e.originalEvent.keyCode === 13) {
1043
- this._map._container.focus();
1044
- }
1045
- },
1046
-
1047
- _showCoverage: function (e) {
1048
- var map = this._map;
1049
- if (this._inZoomAnimation) {
1050
- return;
1051
- }
1052
- if (this._shownPolygon) {
1053
- map.removeLayer(this._shownPolygon);
1054
- }
1055
- if (e.layer.getChildCount() > 2 && e.layer !== this._spiderfied) {
1056
- this._shownPolygon = new L.Polygon(e.layer.getConvexHull(), this.options.polygonOptions);
1057
- map.addLayer(this._shownPolygon);
1058
- }
1059
- },
1060
-
1061
- _hideCoverage: function () {
1062
- if (this._shownPolygon) {
1063
- this._map.removeLayer(this._shownPolygon);
1064
- this._shownPolygon = null;
1065
- }
1066
- },
1067
-
1068
- _unbindEvents: function () {
1069
- var spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom,
1070
- showCoverageOnHover = this.options.showCoverageOnHover,
1071
- zoomToBoundsOnClick = this.options.zoomToBoundsOnClick,
1072
- map = this._map;
1073
-
1074
- if (spiderfyOnMaxZoom || zoomToBoundsOnClick) {
1075
- this.off('clusterclick', this._zoomOrSpiderfy, this);
1076
- }
1077
- if (showCoverageOnHover) {
1078
- this.off('clustermouseover', this._showCoverage, this);
1079
- this.off('clustermouseout', this._hideCoverage, this);
1080
- map.off('zoomend', this._hideCoverage, this);
1081
- }
1082
- },
1083
-
1084
- _zoomEnd: function () {
1085
- if (!this._map) { //May have been removed from the map by a zoomEnd handler
1086
- return;
1087
- }
1088
- this._mergeSplitClusters();
1089
-
1090
- this._zoom = Math.round(this._map._zoom);
1091
- this._currentShownBounds = this._getExpandedVisibleBounds();
1092
- },
1093
-
1094
- _moveEnd: function () {
1095
- if (this._inZoomAnimation) {
1096
- return;
1097
- }
1098
-
1099
- var newBounds = this._getExpandedVisibleBounds();
1100
-
1101
- this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, newBounds);
1102
- this._topClusterLevel._recursivelyAddChildrenToMap(null, Math.round(this._map._zoom), newBounds);
1103
-
1104
- this._currentShownBounds = newBounds;
1105
- return;
1106
- },
1107
-
1108
- _generateInitialClusters: function () {
1109
- var maxZoom = Math.ceil(this._map.getMaxZoom()),
1110
- minZoom = Math.floor(this._map.getMinZoom()),
1111
- radius = this.options.maxClusterRadius,
1112
- radiusFn = radius;
1113
-
1114
- //If we just set maxClusterRadius to a single number, we need to create
1115
- //a simple function to return that number. Otherwise, we just have to
1116
- //use the function we've passed in.
1117
- if (typeof radius !== "function") {
1118
- radiusFn = function () { return radius; };
1119
- }
1120
-
1121
- if (this.options.disableClusteringAtZoom !== null) {
1122
- maxZoom = this.options.disableClusteringAtZoom - 1;
1123
- }
1124
- this._maxZoom = maxZoom;
1125
- this._gridClusters = {};
1126
- this._gridUnclustered = {};
1127
-
1128
- //Set up DistanceGrids for each zoom
1129
- for (var zoom = maxZoom; zoom >= minZoom; zoom--) {
1130
- this._gridClusters[zoom] = new L.DistanceGrid(radiusFn(zoom));
1131
- this._gridUnclustered[zoom] = new L.DistanceGrid(radiusFn(zoom));
1132
- }
1133
-
1134
- // Instantiate the appropriate L.MarkerCluster class (animated or not).
1135
- this._topClusterLevel = new this._markerCluster(this, minZoom - 1);
1136
- },
1137
-
1138
- //Zoom: Zoom to start adding at (Pass this._maxZoom to start at the bottom)
1139
- _addLayer: function (layer, zoom) {
1140
- var gridClusters = this._gridClusters,
1141
- gridUnclustered = this._gridUnclustered,
1142
- minZoom = Math.floor(this._map.getMinZoom()),
1143
- markerPoint, z;
1144
-
1145
- if (this.options.singleMarkerMode) {
1146
- this._overrideMarkerIcon(layer);
1147
- }
1148
-
1149
- layer.on(this._childMarkerEventHandlers, this);
1150
-
1151
- //Find the lowest zoom level to slot this one in
1152
- for (; zoom >= minZoom; zoom--) {
1153
- markerPoint = this._map.project(layer.getLatLng(), zoom); // calculate pixel position
1154
-
1155
- //Try find a cluster close by
1156
- var closest = gridClusters[zoom].getNearObject(markerPoint);
1157
- if (closest) {
1158
- closest._addChild(layer);
1159
- layer.__parent = closest;
1160
- return;
1161
- }
1162
-
1163
- //Try find a marker close by to form a new cluster with
1164
- closest = gridUnclustered[zoom].getNearObject(markerPoint);
1165
- if (closest) {
1166
- var parent = closest.__parent;
1167
- if (parent) {
1168
- this._removeLayer(closest, false);
1169
- }
1170
-
1171
- //Create new cluster with these 2 in it
1172
-
1173
- var newCluster = new this._markerCluster(this, zoom, closest, layer);
1174
- gridClusters[zoom].addObject(newCluster, this._map.project(newCluster._cLatLng, zoom));
1175
- closest.__parent = newCluster;
1176
- layer.__parent = newCluster;
1177
-
1178
- //First create any new intermediate parent clusters that don't exist
1179
- var lastParent = newCluster;
1180
- for (z = zoom - 1; z > parent._zoom; z--) {
1181
- lastParent = new this._markerCluster(this, z, lastParent);
1182
- gridClusters[z].addObject(lastParent, this._map.project(closest.getLatLng(), z));
1183
- }
1184
- parent._addChild(lastParent);
1185
-
1186
- //Remove closest from this zoom level and any above that it is in, replace with newCluster
1187
- this._removeFromGridUnclustered(closest, zoom);
1188
-
1189
- return;
1190
- }
1191
-
1192
- //Didn't manage to cluster in at this zoom, record us as a marker here and continue upwards
1193
- gridUnclustered[zoom].addObject(layer, markerPoint);
1194
- }
1195
-
1196
- //Didn't get in anything, add us to the top
1197
- this._topClusterLevel._addChild(layer);
1198
- layer.__parent = this._topClusterLevel;
1199
- return;
1200
- },
1201
-
1202
- /**
1203
- * Refreshes the icon of all "dirty" visible clusters.
1204
- * Non-visible "dirty" clusters will be updated when they are added to the map.
1205
- * @private
1206
- */
1207
- _refreshClustersIcons: function () {
1208
- this._featureGroup.eachLayer(function (c) {
1209
- if (c instanceof L.MarkerCluster && c._iconNeedsUpdate) {
1210
- c._updateIcon();
1211
- }
1212
- });
1213
- },
1214
-
1215
- //Enqueue code to fire after the marker expand/contract has happened
1216
- _enqueue: function (fn) {
1217
- this._queue.push(fn);
1218
- if (!this._queueTimeout) {
1219
- this._queueTimeout = setTimeout(L.bind(this._processQueue, this), 300);
1220
- }
1221
- },
1222
- _processQueue: function () {
1223
- for (var i = 0; i < this._queue.length; i++) {
1224
- this._queue[i].call(this);
1225
- }
1226
- this._queue.length = 0;
1227
- clearTimeout(this._queueTimeout);
1228
- this._queueTimeout = null;
1229
- },
1230
-
1231
- //Merge and split any existing clusters that are too big or small
1232
- _mergeSplitClusters: function () {
1233
- var mapZoom = Math.round(this._map._zoom);
1234
-
1235
- //In case we are starting to split before the animation finished
1236
- this._processQueue();
1237
-
1238
- if (this._zoom < mapZoom && this._currentShownBounds.intersects(this._getExpandedVisibleBounds())) { //Zoom in, split
1239
- this._animationStart();
1240
- //Remove clusters now off screen
1241
- this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, this._getExpandedVisibleBounds());
1242
-
1243
- this._animationZoomIn(this._zoom, mapZoom);
1244
-
1245
- } else if (this._zoom > mapZoom) { //Zoom out, merge
1246
- this._animationStart();
1247
-
1248
- this._animationZoomOut(this._zoom, mapZoom);
1249
- } else {
1250
- this._moveEnd();
1251
- }
1252
- },
1253
-
1254
- //Gets the maps visible bounds expanded in each direction by the size of the screen (so the user cannot see an area we do not cover in one pan)
1255
- _getExpandedVisibleBounds: function () {
1256
- if (!this.options.removeOutsideVisibleBounds) {
1257
- return this._mapBoundsInfinite;
1258
- } else if (L.Browser.mobile) {
1259
- return this._checkBoundsMaxLat(this._map.getBounds());
1260
- }
1261
-
1262
- return this._checkBoundsMaxLat(this._map.getBounds().pad(1)); // Padding expands the bounds by its own dimensions but scaled with the given factor.
1263
- },
1264
-
1265
- /**
1266
- * Expands the latitude to Infinity (or -Infinity) if the input bounds reach the map projection maximum defined latitude
1267
- * (in the case of Web/Spherical Mercator, it is 85.0511287798 / see https://en.wikipedia.org/wiki/Web_Mercator#Formulas).
1268
- * Otherwise, the removeOutsideVisibleBounds option will remove markers beyond that limit, whereas the same markers without
1269
- * this option (or outside MCG) will have their position floored (ceiled) by the projection and rendered at that limit,
1270
- * making the user think that MCG "eats" them and never displays them again.
1271
- * @param bounds L.LatLngBounds
1272
- * @returns {L.LatLngBounds}
1273
- * @private
1274
- */
1275
- _checkBoundsMaxLat: function (bounds) {
1276
- var maxLat = this._maxLat;
1277
-
1278
- if (maxLat !== undefined) {
1279
- if (bounds.getNorth() >= maxLat) {
1280
- bounds._northEast.lat = Infinity;
1281
- }
1282
- if (bounds.getSouth() <= -maxLat) {
1283
- bounds._southWest.lat = -Infinity;
1284
- }
1285
- }
1286
-
1287
- return bounds;
1288
- },
1289
-
1290
- //Shared animation code
1291
- _animationAddLayerNonAnimated: function (layer, newCluster) {
1292
- if (newCluster === layer) {
1293
- this._featureGroup.addLayer(layer);
1294
- } else if (newCluster._childCount === 2) {
1295
- newCluster._addToMap();
1296
-
1297
- var markers = newCluster.getAllChildMarkers();
1298
- this._featureGroup.removeLayer(markers[0]);
1299
- this._featureGroup.removeLayer(markers[1]);
1300
- } else {
1301
- newCluster._updateIcon();
1302
- }
1303
- },
1304
-
1305
- /**
1306
- * Extracts individual (i.e. non-group) layers from a Layer Group.
1307
- * @param group to extract layers from.
1308
- * @param output {Array} in which to store the extracted layers.
1309
- * @returns {*|Array}
1310
- * @private
1311
- */
1312
- _extractNonGroupLayers: function (group, output) {
1313
- var layers = group.getLayers(),
1314
- i = 0,
1315
- layer;
1316
-
1317
- output = output || [];
1318
-
1319
- for (; i < layers.length; i++) {
1320
- layer = layers[i];
1321
-
1322
- if (layer instanceof L.LayerGroup) {
1323
- this._extractNonGroupLayers(layer, output);
1324
- continue;
1325
- }
1326
-
1327
- output.push(layer);
1328
- }
1329
-
1330
- return output;
1331
- },
1332
-
1333
- /**
1334
- * Implements the singleMarkerMode option.
1335
- * @param layer Marker to re-style using the Clusters iconCreateFunction.
1336
- * @returns {L.Icon} The newly created icon.
1337
- * @private
1338
- */
1339
- _overrideMarkerIcon: function (layer) {
1340
- var icon = layer.options.icon = this.options.iconCreateFunction({
1341
- getChildCount: function () {
1342
- return 1;
1343
- },
1344
- getAllChildMarkers: function () {
1345
- return [layer];
1346
- }
1347
- });
1348
-
1349
- return icon;
1350
- }
1351
- });
1352
-
1353
- // Constant bounds used in case option "removeOutsideVisibleBounds" is set to false.
1354
- L.MarkerClusterGroup.include({
1355
- _mapBoundsInfinite: new L.LatLngBounds(new L.LatLng(-Infinity, -Infinity), new L.LatLng(Infinity, Infinity))
1356
- });
1357
-
1358
- L.MarkerClusterGroup.include({
1359
- _noAnimation: {
1360
- //Non Animated versions of everything
1361
- _animationStart: function () {
1362
- //Do nothing...
1363
- },
1364
- _animationZoomIn: function (previousZoomLevel, newZoomLevel) {
1365
- this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel);
1366
- this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
1367
-
1368
- //We didn't actually animate, but we use this event to mean "clustering animations have finished"
1369
- this.fire('animationend');
1370
- },
1371
- _animationZoomOut: function (previousZoomLevel, newZoomLevel) {
1372
- this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel);
1373
- this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
1374
-
1375
- //We didn't actually animate, but we use this event to mean "clustering animations have finished"
1376
- this.fire('animationend');
1377
- },
1378
- _animationAddLayer: function (layer, newCluster) {
1379
- this._animationAddLayerNonAnimated(layer, newCluster);
1380
- }
1381
- },
1382
-
1383
- _withAnimation: {
1384
- //Animated versions here
1385
- _animationStart: function () {
1386
- this._map._mapPane.className += ' leaflet-cluster-anim';
1387
- this._inZoomAnimation++;
1388
- },
1389
-
1390
- _animationZoomIn: function (previousZoomLevel, newZoomLevel) {
1391
- var bounds = this._getExpandedVisibleBounds(),
1392
- fg = this._featureGroup,
1393
- minZoom = Math.floor(this._map.getMinZoom()),
1394
- i;
1395
-
1396
- this._ignoreMove = true;
1397
-
1398
- //Add all children of current clusters to map and remove those clusters from map
1399
- this._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) {
1400
- var startPos = c._latlng,
1401
- markers = c._markers,
1402
- m;
1403
-
1404
- if (!bounds.contains(startPos)) {
1405
- startPos = null;
1406
- }
1407
-
1408
- if (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us
1409
- fg.removeLayer(c);
1410
- c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds);
1411
- } else {
1412
- //Fade out old cluster
1413
- c.clusterHide();
1414
- c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds);
1415
- }
1416
-
1417
- //Remove all markers that aren't visible any more
1418
- //TODO: Do we actually need to do this on the higher levels too?
1419
- for (i = markers.length - 1; i >= 0; i--) {
1420
- m = markers[i];
1421
- if (!bounds.contains(m._latlng)) {
1422
- fg.removeLayer(m);
1423
- }
1424
- }
1425
-
1426
- });
1427
-
1428
- this._forceLayout();
1429
-
1430
- //Update opacities
1431
- this._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel);
1432
- //TODO Maybe? Update markers in _recursivelyBecomeVisible
1433
- fg.eachLayer(function (n) {
1434
- if (!(n instanceof L.MarkerCluster) && n._icon) {
1435
- n.clusterShow();
1436
- }
1437
- });
1438
-
1439
- //update the positions of the just added clusters/markers
1440
- this._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) {
1441
- c._recursivelyRestoreChildPositions(newZoomLevel);
1442
- });
1443
-
1444
- this._ignoreMove = false;
1445
-
1446
- //Remove the old clusters and close the zoom animation
1447
- this._enqueue(function () {
1448
- //update the positions of the just added clusters/markers
1449
- this._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) {
1450
- fg.removeLayer(c);
1451
- c.clusterShow();
1452
- });
1453
-
1454
- this._animationEnd();
1455
- });
1456
- },
1457
-
1458
- _animationZoomOut: function (previousZoomLevel, newZoomLevel) {
1459
- this._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel);
1460
-
1461
- //Need to add markers for those that weren't on the map before but are now
1462
- this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
1463
- //Remove markers that were on the map before but won't be now
1464
- this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel, this._getExpandedVisibleBounds());
1465
- },
1466
-
1467
- _animationAddLayer: function (layer, newCluster) {
1468
- var me = this,
1469
- fg = this._featureGroup;
1470
-
1471
- fg.addLayer(layer);
1472
- if (newCluster !== layer) {
1473
- if (newCluster._childCount > 2) { //Was already a cluster
1474
-
1475
- newCluster._updateIcon();
1476
- this._forceLayout();
1477
- this._animationStart();
1478
-
1479
- layer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng()));
1480
- layer.clusterHide();
1481
-
1482
- this._enqueue(function () {
1483
- fg.removeLayer(layer);
1484
- layer.clusterShow();
1485
-
1486
- me._animationEnd();
1487
- });
1488
-
1489
- } else { //Just became a cluster
1490
- this._forceLayout();
1491
-
1492
- me._animationStart();
1493
- me._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._zoom);
1494
- }
1495
- }
1496
- }
1497
- },
1498
-
1499
- // Private methods for animated versions.
1500
- _animationZoomOutSingle: function (cluster, previousZoomLevel, newZoomLevel) {
1501
- var bounds = this._getExpandedVisibleBounds(),
1502
- minZoom = Math.floor(this._map.getMinZoom());
1503
-
1504
- //Animate all of the markers in the clusters to move to their cluster center point
1505
- cluster._recursivelyAnimateChildrenInAndAddSelfToMap(bounds, minZoom, previousZoomLevel + 1, newZoomLevel);
1506
-
1507
- var me = this;
1508
-
1509
- //Update the opacity (If we immediately set it they won't animate)
1510
- this._forceLayout();
1511
- cluster._recursivelyBecomeVisible(bounds, newZoomLevel);
1512
-
1513
- //TODO: Maybe use the transition timing stuff to make this more reliable
1514
- //When the animations are done, tidy up
1515
- this._enqueue(function () {
1516
-
1517
- //This cluster stopped being a cluster before the timeout fired
1518
- if (cluster._childCount === 1) {
1519
- var m = cluster._markers[0];
1520
- //If we were in a cluster animation at the time then the opacity and position of our child could be wrong now, so fix it
1521
- this._ignoreMove = true;
1522
- m.setLatLng(m.getLatLng());
1523
- this._ignoreMove = false;
1524
- if (m.clusterShow) {
1525
- m.clusterShow();
1526
- }
1527
- } else {
1528
- cluster._recursively(bounds, newZoomLevel, minZoom, function (c) {
1529
- c._recursivelyRemoveChildrenFromMap(bounds, minZoom, previousZoomLevel + 1);
1530
- });
1531
- }
1532
- me._animationEnd();
1533
- });
1534
- },
1535
-
1536
- _animationEnd: function () {
1537
- if (this._map) {
1538
- this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', '');
1539
- }
1540
- this._inZoomAnimation--;
1541
- this.fire('animationend');
1542
- },
1543
-
1544
- //Force a browser layout of stuff in the map
1545
- // Should apply the current opacity and location to all elements so we can update them again for an animation
1546
- _forceLayout: function () {
1547
- //In my testing this works, infact offsetWidth of any element seems to work.
1548
- //Could loop all this._layers and do this for each _icon if it stops working
1549
-
1550
- L.Util.falseFn(document.body.offsetWidth);
1551
- }
1552
- });
1553
-
1554
- L.markerClusterGroup = function (options) {
1555
- return new L.MarkerClusterGroup(options);
1556
- };
1557
-
1558
- var MarkerCluster = L.MarkerCluster = L.Marker.extend({
1559
- options: L.Icon.prototype.options,
1560
-
1561
- initialize: function (group, zoom, a, b) {
1562
-
1563
- L.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0),
1564
- { icon: this, pane: group.options.clusterPane });
1565
-
1566
- this._group = group;
1567
- this._zoom = zoom;
1568
-
1569
- this._markers = [];
1570
- this._childClusters = [];
1571
- this._childCount = 0;
1572
- this._iconNeedsUpdate = true;
1573
- this._boundsNeedUpdate = true;
1574
-
1575
- this._bounds = new L.LatLngBounds();
1576
-
1577
- if (a) {
1578
- this._addChild(a);
1579
- }
1580
- if (b) {
1581
- this._addChild(b);
1582
- }
1583
- },
1584
-
1585
- //Recursively retrieve all child markers of this cluster
1586
- getAllChildMarkers: function (storageArray, ignoreDraggedMarker) {
1587
- storageArray = storageArray || [];
1588
-
1589
- for (var i = this._childClusters.length - 1; i >= 0; i--) {
1590
- this._childClusters[i].getAllChildMarkers(storageArray);
1591
- }
1592
-
1593
- for (var j = this._markers.length - 1; j >= 0; j--) {
1594
- if (ignoreDraggedMarker && this._markers[j].__dragStart) {
1595
- continue;
1596
- }
1597
- storageArray.push(this._markers[j]);
1598
- }
1599
-
1600
- return storageArray;
1601
- },
1602
-
1603
- //Returns the count of how many child markers we have
1604
- getChildCount: function () {
1605
- return this._childCount;
1606
- },
1607
-
1608
- //Zoom to the minimum of showing all of the child markers, or the extents of this cluster
1609
- zoomToBounds: function (fitBoundsOptions) {
1610
- var childClusters = this._childClusters.slice(),
1611
- map = this._group._map,
1612
- boundsZoom = map.getBoundsZoom(this._bounds),
1613
- zoom = this._zoom + 1,
1614
- mapZoom = map.getZoom(),
1615
- i;
1616
-
1617
- //calculate how far we need to zoom down to see all of the markers
1618
- while (childClusters.length > 0 && boundsZoom > zoom) {
1619
- zoom++;
1620
- var newClusters = [];
1621
- for (i = 0; i < childClusters.length; i++) {
1622
- newClusters = newClusters.concat(childClusters[i]._childClusters);
1623
- }
1624
- childClusters = newClusters;
1625
- }
1626
-
1627
- if (boundsZoom > zoom) {
1628
- this._group._map.setView(this._latlng, zoom);
1629
- } else if (boundsZoom <= mapZoom) { //If fitBounds wouldn't zoom us down, zoom us down instead
1630
- this._group._map.setView(this._latlng, mapZoom + 1);
1631
- } else {
1632
- this._group._map.fitBounds(this._bounds, fitBoundsOptions);
1633
- }
1634
- },
1635
-
1636
- getBounds: function () {
1637
- var bounds = new L.LatLngBounds();
1638
- bounds.extend(this._bounds);
1639
- return bounds;
1640
- },
1641
-
1642
- _updateIcon: function () {
1643
- this._iconNeedsUpdate = true;
1644
- if (this._icon) {
1645
- this.setIcon(this);
1646
- }
1647
- },
1648
-
1649
- //Cludge for Icon, we pretend to be an icon for performance
1650
- createIcon: function () {
1651
- if (this._iconNeedsUpdate) {
1652
- this._iconObj = this._group.options.iconCreateFunction(this);
1653
- this._iconNeedsUpdate = false;
1654
- }
1655
- return this._iconObj.createIcon();
1656
- },
1657
- createShadow: function () {
1658
- return this._iconObj.createShadow();
1659
- },
1660
-
1661
-
1662
- _addChild: function (new1, isNotificationFromChild) {
1663
-
1664
- this._iconNeedsUpdate = true;
1665
-
1666
- this._boundsNeedUpdate = true;
1667
- this._setClusterCenter(new1);
1668
-
1669
- if (new1 instanceof L.MarkerCluster) {
1670
- if (!isNotificationFromChild) {
1671
- this._childClusters.push(new1);
1672
- new1.__parent = this;
1673
- }
1674
- this._childCount += new1._childCount;
1675
- } else {
1676
- if (!isNotificationFromChild) {
1677
- this._markers.push(new1);
1678
- }
1679
- this._childCount++;
1680
- }
1681
-
1682
- if (this.__parent) {
1683
- this.__parent._addChild(new1, true);
1684
- }
1685
- },
1686
-
1687
- /**
1688
- * Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position.
1689
- * @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet.
1690
- * @private
1691
- */
1692
- _setClusterCenter: function (child) {
1693
- if (!this._cLatLng) {
1694
- // when clustering, take position of the first point as the cluster center
1695
- this._cLatLng = child._cLatLng || child._latlng;
1696
- }
1697
- },
1698
-
1699
- /**
1700
- * Assigns impossible bounding values so that the next extend entirely determines the new bounds.
1701
- * This method avoids having to trash the previous L.LatLngBounds object and to create a new one, which is much slower for this class.
1702
- * As long as the bounds are not extended, most other methods would probably fail, as they would with bounds initialized but not extended.
1703
- * @private
1704
- */
1705
- _resetBounds: function () {
1706
- var bounds = this._bounds;
1707
-
1708
- if (bounds._southWest) {
1709
- bounds._southWest.lat = Infinity;
1710
- bounds._southWest.lng = Infinity;
1711
- }
1712
- if (bounds._northEast) {
1713
- bounds._northEast.lat = -Infinity;
1714
- bounds._northEast.lng = -Infinity;
1715
- }
1716
- },
1717
-
1718
- _recalculateBounds: function () {
1719
- var markers = this._markers,
1720
- childClusters = this._childClusters,
1721
- latSum = 0,
1722
- lngSum = 0,
1723
- totalCount = this._childCount,
1724
- i, child, childLatLng, childCount;
1725
-
1726
- // Case where all markers are removed from the map and we are left with just an empty _topClusterLevel.
1727
- if (totalCount === 0) {
1728
- return;
1729
- }
1730
-
1731
- // Reset rather than creating a new object, for performance.
1732
- this._resetBounds();
1733
-
1734
- // Child markers.
1735
- for (i = 0; i < markers.length; i++) {
1736
- childLatLng = markers[i]._latlng;
1737
-
1738
- this._bounds.extend(childLatLng);
1739
-
1740
- latSum += childLatLng.lat;
1741
- lngSum += childLatLng.lng;
1742
- }
1743
-
1744
- // Child clusters.
1745
- for (i = 0; i < childClusters.length; i++) {
1746
- child = childClusters[i];
1747
-
1748
- // Re-compute child bounds and weighted position first if necessary.
1749
- if (child._boundsNeedUpdate) {
1750
- child._recalculateBounds();
1751
- }
1752
-
1753
- this._bounds.extend(child._bounds);
1754
-
1755
- childLatLng = child._wLatLng;
1756
- childCount = child._childCount;
1757
-
1758
- latSum += childLatLng.lat * childCount;
1759
- lngSum += childLatLng.lng * childCount;
1760
- }
1761
-
1762
- this._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount);
1763
-
1764
- // Reset dirty flag.
1765
- this._boundsNeedUpdate = false;
1766
- },
1767
-
1768
- //Set our markers position as given and add it to the map
1769
- _addToMap: function (startPos) {
1770
- if (startPos) {
1771
- this._backupLatlng = this._latlng;
1772
- this.setLatLng(startPos);
1773
- }
1774
- this._group._featureGroup.addLayer(this);
1775
- },
1776
-
1777
- _recursivelyAnimateChildrenIn: function (bounds, center, maxZoom) {
1778
- this._recursively(bounds, this._group._map.getMinZoom(), maxZoom - 1,
1779
- function (c) {
1780
- var markers = c._markers,
1781
- i, m;
1782
- for (i = markers.length - 1; i >= 0; i--) {
1783
- m = markers[i];
1784
-
1785
- //Only do it if the icon is still on the map
1786
- if (m._icon) {
1787
- m._setPos(center);
1788
- m.clusterHide();
1789
- }
1790
- }
1791
- },
1792
- function (c) {
1793
- var childClusters = c._childClusters,
1794
- j, cm;
1795
- for (j = childClusters.length - 1; j >= 0; j--) {
1796
- cm = childClusters[j];
1797
- if (cm._icon) {
1798
- cm._setPos(center);
1799
- cm.clusterHide();
1800
- }
1801
- }
1802
- }
1803
- );
1804
- },
1805
-
1806
- _recursivelyAnimateChildrenInAndAddSelfToMap: function (bounds, mapMinZoom, previousZoomLevel, newZoomLevel) {
1807
- this._recursively(bounds, newZoomLevel, mapMinZoom,
1808
- function (c) {
1809
- c._recursivelyAnimateChildrenIn(bounds, c._group._map.latLngToLayerPoint(c.getLatLng()).round(), previousZoomLevel);
1810
-
1811
- //TODO: depthToAnimateIn affects _isSingleParent, if there is a multizoom we may/may not be.
1812
- //As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate
1813
- if (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) {
1814
- c.clusterShow();
1815
- c._recursivelyRemoveChildrenFromMap(bounds, mapMinZoom, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds
1816
- } else {
1817
- c.clusterHide();
1818
- }
1819
-
1820
- c._addToMap();
1821
- }
1822
- );
1823
- },
1824
-
1825
- _recursivelyBecomeVisible: function (bounds, zoomLevel) {
1826
- this._recursively(bounds, this._group._map.getMinZoom(), zoomLevel, null, function (c) {
1827
- c.clusterShow();
1828
- });
1829
- },
1830
-
1831
- _recursivelyAddChildrenToMap: function (startPos, zoomLevel, bounds) {
1832
- this._recursively(bounds, this._group._map.getMinZoom() - 1, zoomLevel,
1833
- function (c) {
1834
- if (zoomLevel === c._zoom) {
1835
- return;
1836
- }
1837
-
1838
- //Add our child markers at startPos (so they can be animated out)
1839
- for (var i = c._markers.length - 1; i >= 0; i--) {
1840
- var nm = c._markers[i];
1841
-
1842
- if (!bounds.contains(nm._latlng)) {
1843
- continue;
1844
- }
1845
-
1846
- if (startPos) {
1847
- nm._backupLatlng = nm.getLatLng();
1848
-
1849
- nm.setLatLng(startPos);
1850
- if (nm.clusterHide) {
1851
- nm.clusterHide();
1852
- }
1853
- }
1854
-
1855
- c._group._featureGroup.addLayer(nm);
1856
- }
1857
- },
1858
- function (c) {
1859
- c._addToMap(startPos);
1860
- }
1861
- );
1862
- },
1863
-
1864
- _recursivelyRestoreChildPositions: function (zoomLevel) {
1865
- //Fix positions of child markers
1866
- for (var i = this._markers.length - 1; i >= 0; i--) {
1867
- var nm = this._markers[i];
1868
- if (nm._backupLatlng) {
1869
- nm.setLatLng(nm._backupLatlng);
1870
- delete nm._backupLatlng;
1871
- }
1872
- }
1873
-
1874
- if (zoomLevel - 1 === this._zoom) {
1875
- //Reposition child clusters
1876
- for (var j = this._childClusters.length - 1; j >= 0; j--) {
1877
- this._childClusters[j]._restorePosition();
1878
- }
1879
- } else {
1880
- for (var k = this._childClusters.length - 1; k >= 0; k--) {
1881
- this._childClusters[k]._recursivelyRestoreChildPositions(zoomLevel);
1882
- }
1883
- }
1884
- },
1885
-
1886
- _restorePosition: function () {
1887
- if (this._backupLatlng) {
1888
- this.setLatLng(this._backupLatlng);
1889
- delete this._backupLatlng;
1890
- }
1891
- },
1892
-
1893
- //exceptBounds: If set, don't remove any markers/clusters in it
1894
- _recursivelyRemoveChildrenFromMap: function (previousBounds, mapMinZoom, zoomLevel, exceptBounds) {
1895
- var m, i;
1896
- this._recursively(previousBounds, mapMinZoom - 1, zoomLevel - 1,
1897
- function (c) {
1898
- //Remove markers at every level
1899
- for (i = c._markers.length - 1; i >= 0; i--) {
1900
- m = c._markers[i];
1901
- if (!exceptBounds || !exceptBounds.contains(m._latlng)) {
1902
- c._group._featureGroup.removeLayer(m);
1903
- if (m.clusterShow) {
1904
- m.clusterShow();
1905
- }
1906
- }
1907
- }
1908
- },
1909
- function (c) {
1910
- //Remove child clusters at just the bottom level
1911
- for (i = c._childClusters.length - 1; i >= 0; i--) {
1912
- m = c._childClusters[i];
1913
- if (!exceptBounds || !exceptBounds.contains(m._latlng)) {
1914
- c._group._featureGroup.removeLayer(m);
1915
- if (m.clusterShow) {
1916
- m.clusterShow();
1917
- }
1918
- }
1919
- }
1920
- }
1921
- );
1922
- },
1923
-
1924
- //Run the given functions recursively to this and child clusters
1925
- // boundsToApplyTo: a L.LatLngBounds representing the bounds of what clusters to recurse in to
1926
- // zoomLevelToStart: zoom level to start running functions (inclusive)
1927
- // zoomLevelToStop: zoom level to stop running functions (inclusive)
1928
- // runAtEveryLevel: function that takes an L.MarkerCluster as an argument that should be applied on every level
1929
- // runAtBottomLevel: function that takes an L.MarkerCluster as an argument that should be applied at only the bottom level
1930
- _recursively: function (boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel) {
1931
- var childClusters = this._childClusters,
1932
- zoom = this._zoom,
1933
- i, c;
1934
-
1935
- if (zoomLevelToStart <= zoom) {
1936
- if (runAtEveryLevel) {
1937
- runAtEveryLevel(this);
1938
- }
1939
- if (runAtBottomLevel && zoom === zoomLevelToStop) {
1940
- runAtBottomLevel(this);
1941
- }
1942
- }
1943
-
1944
- if (zoom < zoomLevelToStart || zoom < zoomLevelToStop) {
1945
- for (i = childClusters.length - 1; i >= 0; i--) {
1946
- c = childClusters[i];
1947
- if (c._boundsNeedUpdate) {
1948
- c._recalculateBounds();
1949
- }
1950
- if (boundsToApplyTo.intersects(c._bounds)) {
1951
- c._recursively(boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel);
1952
- }
1953
- }
1954
- }
1955
- },
1956
-
1957
- //Returns true if we are the parent of only one cluster and that cluster is the same as us
1958
- _isSingleParent: function () {
1959
- //Don't need to check this._markers as the rest won't work if there are any
1960
- return this._childClusters.length > 0 && this._childClusters[0]._childCount === this._childCount;
1961
- }
1962
- });
1963
-
1964
- /*
1965
- * Extends L.Marker to include two extra methods: clusterHide and clusterShow.
1966
- *
1967
- * They work as setOpacity(0) and setOpacity(1) respectively, but
1968
- * don't overwrite the options.opacity
1969
- *
1970
- */
1971
-
1972
- L.Marker.include({
1973
- clusterHide: function () {
1974
- var backup = this.options.opacity;
1975
- this.setOpacity(0);
1976
- this.options.opacity = backup;
1977
- return this;
1978
- },
1979
-
1980
- clusterShow: function () {
1981
- return this.setOpacity(this.options.opacity);
1982
- }
1983
- });
1984
-
1985
- L.DistanceGrid = function (cellSize) {
1986
- this._cellSize = cellSize;
1987
- this._sqCellSize = cellSize * cellSize;
1988
- this._grid = {};
1989
- this._objectPoint = { };
1990
- };
1991
-
1992
- L.DistanceGrid.prototype = {
1993
-
1994
- addObject: function (obj, point) {
1995
- var x = this._getCoord(point.x),
1996
- y = this._getCoord(point.y),
1997
- grid = this._grid,
1998
- row = grid[y] = grid[y] || {},
1999
- cell = row[x] = row[x] || [],
2000
- stamp = L.Util.stamp(obj);
2001
-
2002
- this._objectPoint[stamp] = point;
2003
-
2004
- cell.push(obj);
2005
- },
2006
-
2007
- updateObject: function (obj, point) {
2008
- this.removeObject(obj);
2009
- this.addObject(obj, point);
2010
- },
2011
-
2012
- //Returns true if the object was found
2013
- removeObject: function (obj, point) {
2014
- var x = this._getCoord(point.x),
2015
- y = this._getCoord(point.y),
2016
- grid = this._grid,
2017
- row = grid[y] = grid[y] || {},
2018
- cell = row[x] = row[x] || [],
2019
- i, len;
2020
-
2021
- delete this._objectPoint[L.Util.stamp(obj)];
2022
-
2023
- for (i = 0, len = cell.length; i < len; i++) {
2024
- if (cell[i] === obj) {
2025
-
2026
- cell.splice(i, 1);
2027
-
2028
- if (len === 1) {
2029
- delete row[x];
2030
- }
2031
-
2032
- return true;
2033
- }
2034
- }
2035
-
2036
- },
2037
-
2038
- eachObject: function (fn, context) {
2039
- var i, j, k, len, row, cell, removed,
2040
- grid = this._grid;
2041
-
2042
- for (i in grid) {
2043
- row = grid[i];
2044
-
2045
- for (j in row) {
2046
- cell = row[j];
2047
-
2048
- for (k = 0, len = cell.length; k < len; k++) {
2049
- removed = fn.call(context, cell[k]);
2050
- if (removed) {
2051
- k--;
2052
- len--;
2053
- }
2054
- }
2055
- }
2056
- }
2057
- },
2058
-
2059
- getNearObject: function (point) {
2060
- var x = this._getCoord(point.x),
2061
- y = this._getCoord(point.y),
2062
- i, j, k, row, cell, len, obj, dist,
2063
- objectPoint = this._objectPoint,
2064
- closestDistSq = this._sqCellSize,
2065
- closest = null;
2066
-
2067
- for (i = y - 1; i <= y + 1; i++) {
2068
- row = this._grid[i];
2069
- if (row) {
2070
-
2071
- for (j = x - 1; j <= x + 1; j++) {
2072
- cell = row[j];
2073
- if (cell) {
2074
-
2075
- for (k = 0, len = cell.length; k < len; k++) {
2076
- obj = cell[k];
2077
- dist = this._sqDist(objectPoint[L.Util.stamp(obj)], point);
2078
- if (dist < closestDistSq ||
2079
- dist <= closestDistSq && closest === null) {
2080
- closestDistSq = dist;
2081
- closest = obj;
2082
- }
2083
- }
2084
- }
2085
- }
2086
- }
2087
- }
2088
- return closest;
2089
- },
2090
-
2091
- _getCoord: function (x) {
2092
- var coord = Math.floor(x / this._cellSize);
2093
- return isFinite(coord) ? coord : x;
2094
- },
2095
-
2096
- _sqDist: function (p, p2) {
2097
- var dx = p2.x - p.x,
2098
- dy = p2.y - p.y;
2099
- return dx * dx + dy * dy;
2100
- }
2101
- };
2102
-
2103
- /* Copyright (c) 2012 the authors listed at the following URL, and/or
2104
- the authors of referenced articles or incorporated external code:
2105
- http://en.literateprograms.org/Quickhull_(Javascript)?action=history&offset=20120410175256
2106
-
2107
- Permission is hereby granted, free of charge, to any person obtaining
2108
- a copy of this software and associated documentation files (the
2109
- "Software"), to deal in the Software without restriction, including
2110
- without limitation the rights to use, copy, modify, merge, publish,
2111
- distribute, sublicense, and/or sell copies of the Software, and to
2112
- permit persons to whom the Software is furnished to do so, subject to
2113
- the following conditions:
2114
-
2115
- The above copyright notice and this permission notice shall be
2116
- included in all copies or substantial portions of the Software.
2117
-
2118
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2119
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2120
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2121
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2122
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2123
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2124
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2125
-
2126
- Retrieved from: http://en.literateprograms.org/Quickhull_(Javascript)?oldid=18434
2127
- */
2128
-
2129
- (function () {
2130
- L.QuickHull = {
2131
-
2132
- /*
2133
- * @param {Object} cpt a point to be measured from the baseline
2134
- * @param {Array} bl the baseline, as represented by a two-element
2135
- * array of latlng objects.
2136
- * @returns {Number} an approximate distance measure
2137
- */
2138
- getDistant: function (cpt, bl) {
2139
- var vY = bl[1].lat - bl[0].lat,
2140
- vX = bl[0].lng - bl[1].lng;
2141
- return (vX * (cpt.lat - bl[0].lat) + vY * (cpt.lng - bl[0].lng));
2142
- },
2143
-
2144
- /*
2145
- * @param {Array} baseLine a two-element array of latlng objects
2146
- * representing the baseline to project from
2147
- * @param {Array} latLngs an array of latlng objects
2148
- * @returns {Object} the maximum point and all new points to stay
2149
- * in consideration for the hull.
2150
- */
2151
- findMostDistantPointFromBaseLine: function (baseLine, latLngs) {
2152
- var maxD = 0,
2153
- maxPt = null,
2154
- newPoints = [],
2155
- i, pt, d;
2156
-
2157
- for (i = latLngs.length - 1; i >= 0; i--) {
2158
- pt = latLngs[i];
2159
- d = this.getDistant(pt, baseLine);
2160
-
2161
- if (d > 0) {
2162
- newPoints.push(pt);
2163
- } else {
2164
- continue;
2165
- }
2166
-
2167
- if (d > maxD) {
2168
- maxD = d;
2169
- maxPt = pt;
2170
- }
2171
- }
2172
-
2173
- return { maxPoint: maxPt, newPoints: newPoints };
2174
- },
2175
-
2176
-
2177
- /*
2178
- * Given a baseline, compute the convex hull of latLngs as an array
2179
- * of latLngs.
2180
- *
2181
- * @param {Array} latLngs
2182
- * @returns {Array}
2183
- */
2184
- buildConvexHull: function (baseLine, latLngs) {
2185
- var convexHullBaseLines = [],
2186
- t = this.findMostDistantPointFromBaseLine(baseLine, latLngs);
2187
-
2188
- if (t.maxPoint) { // if there is still a point "outside" the base line
2189
- convexHullBaseLines =
2190
- convexHullBaseLines.concat(
2191
- this.buildConvexHull([baseLine[0], t.maxPoint], t.newPoints)
2192
- );
2193
- convexHullBaseLines =
2194
- convexHullBaseLines.concat(
2195
- this.buildConvexHull([t.maxPoint, baseLine[1]], t.newPoints)
2196
- );
2197
- return convexHullBaseLines;
2198
- } else { // if there is no more point "outside" the base line, the current base line is part of the convex hull
2199
- return [baseLine[0]];
2200
- }
2201
- },
2202
-
2203
- /*
2204
- * Given an array of latlngs, compute a convex hull as an array
2205
- * of latlngs
2206
- *
2207
- * @param {Array} latLngs
2208
- * @returns {Array}
2209
- */
2210
- getConvexHull: function (latLngs) {
2211
- // find first baseline
2212
- var maxLat = false, minLat = false,
2213
- maxLng = false, minLng = false,
2214
- maxLatPt = null, minLatPt = null,
2215
- maxLngPt = null, minLngPt = null,
2216
- maxPt = null, minPt = null,
2217
- i;
2218
-
2219
- for (i = latLngs.length - 1; i >= 0; i--) {
2220
- var pt = latLngs[i];
2221
- if (maxLat === false || pt.lat > maxLat) {
2222
- maxLatPt = pt;
2223
- maxLat = pt.lat;
2224
- }
2225
- if (minLat === false || pt.lat < minLat) {
2226
- minLatPt = pt;
2227
- minLat = pt.lat;
2228
- }
2229
- if (maxLng === false || pt.lng > maxLng) {
2230
- maxLngPt = pt;
2231
- maxLng = pt.lng;
2232
- }
2233
- if (minLng === false || pt.lng < minLng) {
2234
- minLngPt = pt;
2235
- minLng = pt.lng;
2236
- }
2237
- }
2238
-
2239
- if (minLat !== maxLat) {
2240
- minPt = minLatPt;
2241
- maxPt = maxLatPt;
2242
- } else {
2243
- minPt = minLngPt;
2244
- maxPt = maxLngPt;
2245
- }
2246
-
2247
- var ch = [].concat(this.buildConvexHull([minPt, maxPt], latLngs),
2248
- this.buildConvexHull([maxPt, minPt], latLngs));
2249
- return ch;
2250
- }
2251
- };
2252
- }());
2253
-
2254
- L.MarkerCluster.include({
2255
- getConvexHull: function () {
2256
- var childMarkers = this.getAllChildMarkers(),
2257
- points = [],
2258
- p, i;
2259
-
2260
- for (i = childMarkers.length - 1; i >= 0; i--) {
2261
- p = childMarkers[i].getLatLng();
2262
- points.push(p);
2263
- }
2264
-
2265
- return L.QuickHull.getConvexHull(points);
2266
- }
2267
- });
2268
-
2269
- //This code is 100% based on https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet
2270
- //Huge thanks to jawj for implementing it first to make my job easy :-)
2271
-
2272
- L.MarkerCluster.include({
2273
-
2274
- _2PI: Math.PI * 2,
2275
- _circleFootSeparation: 25, //related to circumference of circle
2276
- _circleStartAngle: 0,
2277
-
2278
- _spiralFootSeparation: 28, //related to size of spiral (experiment!)
2279
- _spiralLengthStart: 11,
2280
- _spiralLengthFactor: 5,
2281
-
2282
- _circleSpiralSwitchover: 9, //show spiral instead of circle from this marker count upwards.
2283
- // 0 -> always spiral; Infinity -> always circle
2284
-
2285
- spiderfy: function () {
2286
- if (this._group._spiderfied === this || this._group._inZoomAnimation) {
2287
- return;
2288
- }
2289
-
2290
- var childMarkers = this.getAllChildMarkers(null, true),
2291
- group = this._group,
2292
- map = group._map,
2293
- center = map.latLngToLayerPoint(this._latlng),
2294
- positions;
2295
-
2296
- this._group._unspiderfy();
2297
- this._group._spiderfied = this;
2298
-
2299
- //TODO Maybe: childMarkers order by distance to center
2300
-
2301
- if (childMarkers.length >= this._circleSpiralSwitchover) {
2302
- positions = this._generatePointsSpiral(childMarkers.length, center);
2303
- } else {
2304
- center.y += 10; // Otherwise circles look wrong => hack for standard blue icon, renders differently for other icons.
2305
- positions = this._generatePointsCircle(childMarkers.length, center);
2306
- }
2307
-
2308
- this._animationSpiderfy(childMarkers, positions);
2309
- },
2310
-
2311
- unspiderfy: function (zoomDetails) {
2312
- /// <param Name="zoomDetails">Argument from zoomanim if being called in a zoom animation or null otherwise</param>
2313
- if (this._group._inZoomAnimation) {
2314
- return;
2315
- }
2316
- this._animationUnspiderfy(zoomDetails);
2317
-
2318
- this._group._spiderfied = null;
2319
- },
2320
-
2321
- _generatePointsCircle: function (count, centerPt) {
2322
- var circumference = this._group.options.spiderfyDistanceMultiplier * this._circleFootSeparation * (2 + count),
2323
- legLength = circumference / this._2PI, //radius from circumference
2324
- angleStep = this._2PI / count,
2325
- res = [],
2326
- i, angle;
2327
-
2328
- legLength = Math.max(legLength, 35); // Minimum distance to get outside the cluster icon.
2329
-
2330
- res.length = count;
2331
-
2332
- for (i = 0; i < count; i++) { // Clockwise, like spiral.
2333
- angle = this._circleStartAngle + i * angleStep;
2334
- res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();
2335
- }
2336
-
2337
- return res;
2338
- },
2339
-
2340
- _generatePointsSpiral: function (count, centerPt) {
2341
- var spiderfyDistanceMultiplier = this._group.options.spiderfyDistanceMultiplier,
2342
- legLength = spiderfyDistanceMultiplier * this._spiralLengthStart,
2343
- separation = spiderfyDistanceMultiplier * this._spiralFootSeparation,
2344
- lengthFactor = spiderfyDistanceMultiplier * this._spiralLengthFactor * this._2PI,
2345
- angle = 0,
2346
- res = [],
2347
- i;
2348
-
2349
- res.length = count;
2350
-
2351
- // Higher index, closer position to cluster center.
2352
- for (i = count; i >= 0; i--) {
2353
- // Skip the first position, so that we are already farther from center and we avoid
2354
- // being under the default cluster icon (especially important for Circle Markers).
2355
- if (i < count) {
2356
- res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();
2357
- }
2358
- angle += separation / legLength + i * 0.0005;
2359
- legLength += lengthFactor / angle;
2360
- }
2361
- return res;
2362
- },
2363
-
2364
- _noanimationUnspiderfy: function () {
2365
- var group = this._group,
2366
- map = group._map,
2367
- fg = group._featureGroup,
2368
- childMarkers = this.getAllChildMarkers(null, true),
2369
- m, i;
2370
-
2371
- group._ignoreMove = true;
2372
-
2373
- this.setOpacity(1);
2374
- for (i = childMarkers.length - 1; i >= 0; i--) {
2375
- m = childMarkers[i];
2376
-
2377
- fg.removeLayer(m);
2378
-
2379
- if (m._preSpiderfyLatlng) {
2380
- m.setLatLng(m._preSpiderfyLatlng);
2381
- delete m._preSpiderfyLatlng;
2382
- }
2383
- if (m.setZIndexOffset) {
2384
- m.setZIndexOffset(0);
2385
- }
2386
-
2387
- if (m._spiderLeg) {
2388
- map.removeLayer(m._spiderLeg);
2389
- delete m._spiderLeg;
2390
- }
2391
- }
2392
-
2393
- group.fire('unspiderfied', {
2394
- cluster: this,
2395
- markers: childMarkers
2396
- });
2397
- group._ignoreMove = false;
2398
- group._spiderfied = null;
2399
- }
2400
- });
2401
-
2402
- //Non Animated versions of everything
2403
- L.MarkerClusterNonAnimated = L.MarkerCluster.extend({
2404
- _animationSpiderfy: function (childMarkers, positions) {
2405
- var group = this._group,
2406
- map = group._map,
2407
- fg = group._featureGroup,
2408
- legOptions = this._group.options.spiderLegPolylineOptions,
2409
- i, m, leg, newPos;
2410
-
2411
- group._ignoreMove = true;
2412
-
2413
- // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.
2414
- // The reverse order trick no longer improves performance on modern browsers.
2415
- for (i = 0; i < childMarkers.length; i++) {
2416
- newPos = map.layerPointToLatLng(positions[i]);
2417
- m = childMarkers[i];
2418
-
2419
- // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.
2420
- leg = new L.Polyline([this._latlng, newPos], legOptions);
2421
- map.addLayer(leg);
2422
- m._spiderLeg = leg;
2423
-
2424
- // Now add the marker.
2425
- m._preSpiderfyLatlng = m._latlng;
2426
- m.setLatLng(newPos);
2427
- if (m.setZIndexOffset) {
2428
- m.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING
2429
- }
2430
-
2431
- fg.addLayer(m);
2432
- }
2433
- this.setOpacity(0.3);
2434
-
2435
- group._ignoreMove = false;
2436
- group.fire('spiderfied', {
2437
- cluster: this,
2438
- markers: childMarkers
2439
- });
2440
- },
2441
-
2442
- _animationUnspiderfy: function () {
2443
- this._noanimationUnspiderfy();
2444
- }
2445
- });
2446
-
2447
- //Animated versions here
2448
- L.MarkerCluster.include({
2449
-
2450
- _animationSpiderfy: function (childMarkers, positions) {
2451
- var me = this,
2452
- group = this._group,
2453
- map = group._map,
2454
- fg = group._featureGroup,
2455
- thisLayerLatLng = this._latlng,
2456
- thisLayerPos = map.latLngToLayerPoint(thisLayerLatLng),
2457
- svg = L.Path.SVG,
2458
- legOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation.
2459
- finalLegOpacity = legOptions.opacity,
2460
- i, m, leg, legPath, legLength, newPos;
2461
-
2462
- if (finalLegOpacity === undefined) {
2463
- finalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity;
2464
- }
2465
-
2466
- if (svg) {
2467
- // If the initial opacity of the spider leg is not 0 then it appears before the animation starts.
2468
- legOptions.opacity = 0;
2469
-
2470
- // Add the class for CSS transitions.
2471
- legOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg';
2472
- } else {
2473
- // Make sure we have a defined opacity.
2474
- legOptions.opacity = finalLegOpacity;
2475
- }
2476
-
2477
- group._ignoreMove = true;
2478
-
2479
- // Add markers and spider legs to map, hidden at our center point.
2480
- // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.
2481
- // The reverse order trick no longer improves performance on modern browsers.
2482
- for (i = 0; i < childMarkers.length; i++) {
2483
- m = childMarkers[i];
2484
-
2485
- newPos = map.layerPointToLatLng(positions[i]);
2486
-
2487
- // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.
2488
- leg = new L.Polyline([thisLayerLatLng, newPos], legOptions);
2489
- map.addLayer(leg);
2490
- m._spiderLeg = leg;
2491
-
2492
- // Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/
2493
- // In our case the transition property is declared in the CSS file.
2494
- if (svg) {
2495
- legPath = leg._path;
2496
- legLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox.
2497
- legPath.style.strokeDasharray = legLength; // Just 1 length is enough, it will be duplicated.
2498
- legPath.style.strokeDashoffset = legLength;
2499
- }
2500
-
2501
- // If it is a marker, add it now and we'll animate it out
2502
- if (m.setZIndexOffset) {
2503
- m.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING
2504
- }
2505
- if (m.clusterHide) {
2506
- m.clusterHide();
2507
- }
2508
-
2509
- // Vectors just get immediately added
2510
- fg.addLayer(m);
2511
-
2512
- if (m._setPos) {
2513
- m._setPos(thisLayerPos);
2514
- }
2515
- }
2516
-
2517
- group._forceLayout();
2518
- group._animationStart();
2519
-
2520
- // Reveal markers and spider legs.
2521
- for (i = childMarkers.length - 1; i >= 0; i--) {
2522
- newPos = map.layerPointToLatLng(positions[i]);
2523
- m = childMarkers[i];
2524
-
2525
- //Move marker to new position
2526
- m._preSpiderfyLatlng = m._latlng;
2527
- m.setLatLng(newPos);
2528
-
2529
- if (m.clusterShow) {
2530
- m.clusterShow();
2531
- }
2532
-
2533
- // Animate leg (animation is actually delegated to CSS transition).
2534
- if (svg) {
2535
- leg = m._spiderLeg;
2536
- legPath = leg._path;
2537
- legPath.style.strokeDashoffset = 0;
2538
- //legPath.style.strokeOpacity = finalLegOpacity;
2539
- leg.setStyle({opacity: finalLegOpacity});
2540
- }
2541
- }
2542
- this.setOpacity(0.3);
2543
-
2544
- group._ignoreMove = false;
2545
-
2546
- setTimeout(function () {
2547
- group._animationEnd();
2548
- group.fire('spiderfied', {
2549
- cluster: me,
2550
- markers: childMarkers
2551
- });
2552
- }, 200);
2553
- },
2554
-
2555
- _animationUnspiderfy: function (zoomDetails) {
2556
- var me = this,
2557
- group = this._group,
2558
- map = group._map,
2559
- fg = group._featureGroup,
2560
- thisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng),
2561
- childMarkers = this.getAllChildMarkers(null, true),
2562
- svg = L.Path.SVG,
2563
- m, i, leg, legPath, legLength, nonAnimatable;
2564
-
2565
- group._ignoreMove = true;
2566
- group._animationStart();
2567
-
2568
- //Make us visible and bring the child markers back in
2569
- this.setOpacity(1);
2570
- for (i = childMarkers.length - 1; i >= 0; i--) {
2571
- m = childMarkers[i];
2572
-
2573
- //Marker was added to us after we were spiderfied
2574
- if (!m._preSpiderfyLatlng) {
2575
- continue;
2576
- }
2577
-
2578
- //Close any popup on the marker first, otherwise setting the location of the marker will make the map scroll
2579
- m.closePopup();
2580
-
2581
- //Fix up the location to the real one
2582
- m.setLatLng(m._preSpiderfyLatlng);
2583
- delete m._preSpiderfyLatlng;
2584
-
2585
- //Hack override the location to be our center
2586
- nonAnimatable = true;
2587
- if (m._setPos) {
2588
- m._setPos(thisLayerPos);
2589
- nonAnimatable = false;
2590
- }
2591
- if (m.clusterHide) {
2592
- m.clusterHide();
2593
- nonAnimatable = false;
2594
- }
2595
- if (nonAnimatable) {
2596
- fg.removeLayer(m);
2597
- }
2598
-
2599
- // Animate the spider leg back in (animation is actually delegated to CSS transition).
2600
- if (svg) {
2601
- leg = m._spiderLeg;
2602
- legPath = leg._path;
2603
- legLength = legPath.getTotalLength() + 0.1;
2604
- legPath.style.strokeDashoffset = legLength;
2605
- leg.setStyle({opacity: 0});
2606
- }
2607
- }
2608
-
2609
- group._ignoreMove = false;
2610
-
2611
- setTimeout(function () {
2612
- //If we have only <= one child left then that marker will be shown on the map so don't remove it!
2613
- var stillThereChildCount = 0;
2614
- for (i = childMarkers.length - 1; i >= 0; i--) {
2615
- m = childMarkers[i];
2616
- if (m._spiderLeg) {
2617
- stillThereChildCount++;
2618
- }
2619
- }
2620
-
2621
-
2622
- for (i = childMarkers.length - 1; i >= 0; i--) {
2623
- m = childMarkers[i];
2624
-
2625
- if (!m._spiderLeg) { //Has already been unspiderfied
2626
- continue;
2627
- }
2628
-
2629
- if (m.clusterShow) {
2630
- m.clusterShow();
2631
- }
2632
- if (m.setZIndexOffset) {
2633
- m.setZIndexOffset(0);
2634
- }
2635
-
2636
- if (stillThereChildCount > 1) {
2637
- fg.removeLayer(m);
2638
- }
2639
-
2640
- map.removeLayer(m._spiderLeg);
2641
- delete m._spiderLeg;
2642
- }
2643
- group._animationEnd();
2644
- group.fire('unspiderfied', {
2645
- cluster: me,
2646
- markers: childMarkers
2647
- });
2648
- }, 200);
2649
- }
2650
- });
2651
-
2652
-
2653
- L.MarkerClusterGroup.include({
2654
- //The MarkerCluster currently spiderfied (if any)
2655
- _spiderfied: null,
2656
-
2657
- unspiderfy: function () {
2658
- this._unspiderfy.apply(this, arguments);
2659
- },
2660
-
2661
- _spiderfierOnAdd: function () {
2662
- this._map.on('click', this._unspiderfyWrapper, this);
2663
-
2664
- if (this._map.options.zoomAnimation) {
2665
- this._map.on('zoomstart', this._unspiderfyZoomStart, this);
2666
- }
2667
- //Browsers without zoomAnimation or a big zoom don't fire zoomstart
2668
- this._map.on('zoomend', this._noanimationUnspiderfy, this);
2669
-
2670
- if (!L.Browser.touch) {
2671
- this._map.getRenderer(this);
2672
- //Needs to happen in the pageload, not after, or animations don't work in webkit
2673
- // http://stackoverflow.com/questions/8455200/svg-animate-with-dynamically-added-elements
2674
- //Disable on touch browsers as the animation messes up on a touch zoom and isn't very noticable
2675
- }
2676
- },
2677
-
2678
- _spiderfierOnRemove: function () {
2679
- this._map.off('click', this._unspiderfyWrapper, this);
2680
- this._map.off('zoomstart', this._unspiderfyZoomStart, this);
2681
- this._map.off('zoomanim', this._unspiderfyZoomAnim, this);
2682
- this._map.off('zoomend', this._noanimationUnspiderfy, this);
2683
-
2684
- //Ensure that markers are back where they should be
2685
- // Use no animation to avoid a sticky leaflet-cluster-anim class on mapPane
2686
- this._noanimationUnspiderfy();
2687
- },
2688
-
2689
- //On zoom start we add a zoomanim handler so that we are guaranteed to be last (after markers are animated)
2690
- //This means we can define the animation they do rather than Markers doing an animation to their actual location
2691
- _unspiderfyZoomStart: function () {
2692
- if (!this._map) { //May have been removed from the map by a zoomEnd handler
2693
- return;
2694
- }
2695
-
2696
- this._map.on('zoomanim', this._unspiderfyZoomAnim, this);
2697
- },
2698
-
2699
- _unspiderfyZoomAnim: function (zoomDetails) {
2700
- //Wait until the first zoomanim after the user has finished touch-zooming before running the animation
2701
- if (L.DomUtil.hasClass(this._map._mapPane, 'leaflet-touching')) {
2702
- return;
2703
- }
2704
-
2705
- this._map.off('zoomanim', this._unspiderfyZoomAnim, this);
2706
- this._unspiderfy(zoomDetails);
2707
- },
2708
-
2709
- _unspiderfyWrapper: function () {
2710
- /// <summary>_unspiderfy but passes no arguments</summary>
2711
- this._unspiderfy();
2712
- },
2713
-
2714
- _unspiderfy: function (zoomDetails) {
2715
- if (this._spiderfied) {
2716
- this._spiderfied.unspiderfy(zoomDetails);
2717
- }
2718
- },
2719
-
2720
- _noanimationUnspiderfy: function () {
2721
- if (this._spiderfied) {
2722
- this._spiderfied._noanimationUnspiderfy();
2723
- }
2724
- },
2725
-
2726
- //If the given layer is currently being spiderfied then we unspiderfy it so it isn't on the map anymore etc
2727
- _unspiderfyLayer: function (layer) {
2728
- if (layer._spiderLeg) {
2729
- this._featureGroup.removeLayer(layer);
2730
-
2731
- if (layer.clusterShow) {
2732
- layer.clusterShow();
2733
- }
2734
- //Position will be fixed up immediately in _animationUnspiderfy
2735
- if (layer.setZIndexOffset) {
2736
- layer.setZIndexOffset(0);
2737
- }
2738
-
2739
- this._map.removeLayer(layer._spiderLeg);
2740
- delete layer._spiderLeg;
2741
- }
2742
- }
2743
- });
2744
-
2745
- /**
2746
- * Adds 1 public method to MCG and 1 to L.Marker to facilitate changing
2747
- * markers' icon options and refreshing their icon and their parent clusters
2748
- * accordingly (case where their iconCreateFunction uses data of childMarkers
2749
- * to make up the cluster icon).
2750
- */
2751
-
2752
-
2753
- L.MarkerClusterGroup.include({
2754
- /**
2755
- * Updates the icon of all clusters which are parents of the given marker(s).
2756
- * In singleMarkerMode, also updates the given marker(s) icon.
2757
- * @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)|
2758
- * L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent
2759
- * clusters need to be updated. If not provided, retrieves all child markers of this.
2760
- * @returns {L.MarkerClusterGroup}
2761
- */
2762
- refreshClusters: function (layers) {
2763
- if (!layers) {
2764
- layers = this._topClusterLevel.getAllChildMarkers();
2765
- } else if (layers instanceof L.MarkerClusterGroup) {
2766
- layers = layers._topClusterLevel.getAllChildMarkers();
2767
- } else if (layers instanceof L.LayerGroup) {
2768
- layers = layers._layers;
2769
- } else if (layers instanceof L.MarkerCluster) {
2770
- layers = layers.getAllChildMarkers();
2771
- } else if (layers instanceof L.Marker) {
2772
- layers = [layers];
2773
- } // else: must be an Array(L.Marker)|Map(L.Marker)
2774
- this._flagParentsIconsNeedUpdate(layers);
2775
- this._refreshClustersIcons();
2776
-
2777
- // In case of singleMarkerMode, also re-draw the markers.
2778
- if (this.options.singleMarkerMode) {
2779
- this._refreshSingleMarkerModeMarkers(layers);
2780
- }
2781
-
2782
- return this;
2783
- },
2784
-
2785
- /**
2786
- * Simply flags all parent clusters of the given markers as having a "dirty" icon.
2787
- * @param layers Array(L.Marker)|Map(L.Marker) list of markers.
2788
- * @private
2789
- */
2790
- _flagParentsIconsNeedUpdate: function (layers) {
2791
- var id, parent;
2792
-
2793
- // Assumes layers is an Array or an Object whose prototype is non-enumerable.
2794
- for (id in layers) {
2795
- // Flag parent clusters' icon as "dirty", all the way up.
2796
- // Dumb process that flags multiple times upper parents, but still
2797
- // much more efficient than trying to be smart and make short lists,
2798
- // at least in the case of a hierarchy following a power law:
2799
- // http://jsperf.com/flag-nodes-in-power-hierarchy/2
2800
- parent = layers[id].__parent;
2801
- while (parent) {
2802
- parent._iconNeedsUpdate = true;
2803
- parent = parent.__parent;
2804
- }
2805
- }
2806
- },
2807
-
2808
- /**
2809
- * Re-draws the icon of the supplied markers.
2810
- * To be used in singleMarkerMode only.
2811
- * @param layers Array(L.Marker)|Map(L.Marker) list of markers.
2812
- * @private
2813
- */
2814
- _refreshSingleMarkerModeMarkers: function (layers) {
2815
- var id, layer;
2816
-
2817
- for (id in layers) {
2818
- layer = layers[id];
2819
-
2820
- // Make sure we do not override markers that do not belong to THIS group.
2821
- if (this.hasLayer(layer)) {
2822
- // Need to re-create the icon first, then re-draw the marker.
2823
- layer.setIcon(this._overrideMarkerIcon(layer));
2824
- }
2825
- }
2826
- }
2827
- });
2828
-
2829
- L.Marker.include({
2830
- /**
2831
- * Updates the given options in the marker's icon and refreshes the marker.
2832
- * @param options map object of icon options.
2833
- * @param directlyRefreshClusters boolean (optional) true to trigger
2834
- * MCG.refreshClustersOf() right away with this single marker.
2835
- * @returns {L.Marker}
2836
- */
2837
- refreshIconOptions: function (options, directlyRefreshClusters) {
2838
- var icon = this.options.icon;
2839
-
2840
- L.setOptions(icon, options);
2841
-
2842
- this.setIcon(icon);
2843
-
2844
- // Shortcut to refresh the associated MCG clusters right away.
2845
- // To be used when refreshing a single marker.
2846
- // Otherwise, better use MCG.refreshClusters() once at the end with
2847
- // the list of modified markers.
2848
- if (directlyRefreshClusters && this.__parent) {
2849
- this.__parent._group.refreshClusters(this);
2850
- }
2851
-
2852
- return this;
2853
- }
2854
- });
2855
-
2856
- exports.MarkerClusterGroup = MarkerClusterGroup;
2857
- exports.MarkerCluster = MarkerCluster;
2858
-
2859
- })));
2860
- //# sourceMappingURL=leaflet.markercluster-src.js.map
2861
-
2862
-
2863
- /***/ })
2864
- /******/ ])
2865
- });
2866
- ;
1
+ /*
2
+ * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
3
+ * This devtool is neither made for production nor for readable output files.
4
+ * It uses "eval()" calls to create a separate source file in the browser devtools.
5
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
6
+ * or disable the default devtool with "devtool: false".
7
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
8
+ */
9
+ (function webpackUniversalModuleDefinition(root, factory) {
10
+ if(typeof exports === 'object' && typeof module === 'object')
11
+ module.exports = factory(require("react"));
12
+ else if(typeof define === 'function' && define.amd)
13
+ define([], factory);
14
+ else if(typeof exports === 'object')
15
+ exports["react-leaflet-deflate"] = factory(require("react"));
16
+ else
17
+ root["ReactLeafletDeflate"] = factory(root["React"]);
18
+ })(this, (__WEBPACK_EXTERNAL_MODULE_react__) => {
19
+ return /******/ (() => { // webpackBootstrap
20
+ /******/ var __webpack_modules__ = ({
21
+
22
+ /***/ "./node_modules/@react-leaflet/core/lib/attribution.js":
23
+ /*!*************************************************************!*\
24
+ !*** ./node_modules/@react-leaflet/core/lib/attribution.js ***!
25
+ \*************************************************************/
26
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
27
+
28
+ "use strict";
29
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useAttribution: () => (/* binding */ useAttribution)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n\nfunction useAttribution(map, attribution) {\n const attributionRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(attribution);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function updateAttribution() {\n if (attribution !== attributionRef.current && map.attributionControl != null) {\n if (attributionRef.current != null) {\n map.attributionControl.removeAttribution(attributionRef.current);\n }\n if (attribution != null) {\n map.attributionControl.addAttribution(attribution);\n }\n }\n attributionRef.current = attribution;\n }, [\n map,\n attribution\n ]);\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/attribution.js?\n}");
30
+
31
+ /***/ }),
32
+
33
+ /***/ "./node_modules/@react-leaflet/core/lib/component.js":
34
+ /*!***********************************************************!*\
35
+ !*** ./node_modules/@react-leaflet/core/lib/component.js ***!
36
+ \***********************************************************/
37
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
38
+
39
+ "use strict";
40
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createContainerComponent: () => (/* binding */ createContainerComponent),\n/* harmony export */ createDivOverlayComponent: () => (/* binding */ createDivOverlayComponent),\n/* harmony export */ createLeafComponent: () => (/* binding */ createLeafComponent)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom */ \"./node_modules/react-dom/index.js\");\n/* harmony import */ var _context_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./context.js */ \"./node_modules/@react-leaflet/core/lib/context.js\");\n\n\n\nfunction createContainerComponent(useElement) {\n function ContainerComponent(props, forwardedRef) {\n const { instance, context } = useElement(props).current;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useImperativeHandle)(forwardedRef, ()=>instance);\n const { children } = props;\n return children == null ? null : /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement(_context_js__WEBPACK_IMPORTED_MODULE_2__.LeafletContext, {\n value: context\n }, children);\n }\n return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(ContainerComponent);\n}\nfunction createDivOverlayComponent(useElement) {\n function OverlayComponent(props, forwardedRef) {\n const [isOpen, setOpen] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);\n const { instance } = useElement(props, setOpen).current;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useImperativeHandle)(forwardedRef, ()=>instance);\n // biome-ignore lint/correctness/useExhaustiveDependencies: update overlay when children change\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function updateOverlay() {\n if (isOpen) {\n instance.update();\n }\n }, [\n instance,\n isOpen,\n props.children\n ]);\n // @ts-ignore _contentNode missing in type definition\n const contentNode = instance._contentNode;\n return contentNode ? /*#__PURE__*/ (0,react_dom__WEBPACK_IMPORTED_MODULE_1__.createPortal)(props.children, contentNode) : null;\n }\n return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(OverlayComponent);\n}\nfunction createLeafComponent(useElement) {\n function LeafComponent(props, forwardedRef) {\n const { instance } = useElement(props).current;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useImperativeHandle)(forwardedRef, ()=>instance);\n return null;\n }\n return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(LeafComponent);\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/component.js?\n}");
41
+
42
+ /***/ }),
43
+
44
+ /***/ "./node_modules/@react-leaflet/core/lib/context.js":
45
+ /*!*********************************************************!*\
46
+ !*** ./node_modules/@react-leaflet/core/lib/context.js ***!
47
+ \*********************************************************/
48
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
49
+
50
+ "use strict";
51
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CONTEXT_VERSION: () => (/* binding */ CONTEXT_VERSION),\n/* harmony export */ LeafletContext: () => (/* binding */ LeafletContext),\n/* harmony export */ createLeafletContext: () => (/* binding */ createLeafletContext),\n/* harmony export */ extendContext: () => (/* binding */ extendContext),\n/* harmony export */ useLeafletContext: () => (/* binding */ useLeafletContext)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n\nconst CONTEXT_VERSION = 1;\nfunction createLeafletContext(map) {\n return Object.freeze({\n __version: CONTEXT_VERSION,\n map\n });\n}\nfunction extendContext(source, extra) {\n return Object.freeze({\n ...source,\n ...extra\n });\n}\nconst LeafletContext = (0,react__WEBPACK_IMPORTED_MODULE_0__.createContext)(null);\nfunction useLeafletContext() {\n const context = (0,react__WEBPACK_IMPORTED_MODULE_0__.use)(LeafletContext);\n if (context == null) {\n throw new Error('No context provided: useLeafletContext() can only be used in a descendant of <MapContainer>');\n }\n return context;\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/context.js?\n}");
52
+
53
+ /***/ }),
54
+
55
+ /***/ "./node_modules/@react-leaflet/core/lib/control.js":
56
+ /*!*********************************************************!*\
57
+ !*** ./node_modules/@react-leaflet/core/lib/control.js ***!
58
+ \*********************************************************/
59
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
60
+
61
+ "use strict";
62
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createControlHook: () => (/* binding */ createControlHook)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var _context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./context.js */ \"./node_modules/@react-leaflet/core/lib/context.js\");\n\n\nfunction createControlHook(useElement) {\n return function useLeafletControl(props) {\n const context = (0,_context_js__WEBPACK_IMPORTED_MODULE_1__.useLeafletContext)();\n const elementRef = useElement(props, context);\n const { instance } = elementRef.current;\n const positionRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(props.position);\n const { position } = props;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function addControl() {\n instance.addTo(context.map);\n return function removeControl() {\n instance.remove();\n };\n }, [\n context.map,\n instance\n ]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function updateControl() {\n if (position != null && position !== positionRef.current) {\n instance.setPosition(position);\n positionRef.current = position;\n }\n }, [\n instance,\n position\n ]);\n return elementRef;\n };\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/control.js?\n}");
63
+
64
+ /***/ }),
65
+
66
+ /***/ "./node_modules/@react-leaflet/core/lib/div-overlay.js":
67
+ /*!*************************************************************!*\
68
+ !*** ./node_modules/@react-leaflet/core/lib/div-overlay.js ***!
69
+ \*************************************************************/
70
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
71
+
72
+ "use strict";
73
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createDivOverlayHook: () => (/* binding */ createDivOverlayHook)\n/* harmony export */ });\n/* harmony import */ var _attribution_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./attribution.js */ \"./node_modules/@react-leaflet/core/lib/attribution.js\");\n/* harmony import */ var _context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./context.js */ \"./node_modules/@react-leaflet/core/lib/context.js\");\n/* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./events.js */ \"./node_modules/@react-leaflet/core/lib/events.js\");\n/* harmony import */ var _pane_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./pane.js */ \"./node_modules/@react-leaflet/core/lib/pane.js\");\n\n\n\n\nfunction createDivOverlayHook(useElement, useLifecycle) {\n return function useDivOverlay(props, setOpen) {\n const context = (0,_context_js__WEBPACK_IMPORTED_MODULE_1__.useLeafletContext)();\n const elementRef = useElement((0,_pane_js__WEBPACK_IMPORTED_MODULE_3__.withPane)(props, context), context);\n (0,_attribution_js__WEBPACK_IMPORTED_MODULE_0__.useAttribution)(context.map, props.attribution);\n (0,_events_js__WEBPACK_IMPORTED_MODULE_2__.useEventHandlers)(elementRef.current, props.eventHandlers);\n useLifecycle(elementRef.current, context, props, setOpen);\n return elementRef;\n };\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/div-overlay.js?\n}");
74
+
75
+ /***/ }),
76
+
77
+ /***/ "./node_modules/@react-leaflet/core/lib/element.js":
78
+ /*!*********************************************************!*\
79
+ !*** ./node_modules/@react-leaflet/core/lib/element.js ***!
80
+ \*********************************************************/
81
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
82
+
83
+ "use strict";
84
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createElementHook: () => (/* binding */ createElementHook),\n/* harmony export */ createElementObject: () => (/* binding */ createElementObject)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n\nfunction createElementObject(instance, context, container) {\n return Object.freeze({\n instance,\n context,\n container\n });\n}\nfunction createElementHook(createElement, updateElement) {\n if (updateElement == null) {\n return function useImmutableLeafletElement(props, context) {\n const elementRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(undefined);\n if (!elementRef.current) elementRef.current = createElement(props, context);\n return elementRef;\n };\n }\n return function useMutableLeafletElement(props, context) {\n const elementRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(undefined);\n if (!elementRef.current) elementRef.current = createElement(props, context);\n const propsRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(props);\n const { instance } = elementRef.current;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function updateElementProps() {\n if (propsRef.current !== props) {\n updateElement(instance, props, propsRef.current);\n propsRef.current = props;\n }\n }, [\n instance,\n props,\n updateElement\n ]);\n return elementRef;\n };\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/element.js?\n}");
85
+
86
+ /***/ }),
87
+
88
+ /***/ "./node_modules/@react-leaflet/core/lib/events.js":
89
+ /*!********************************************************!*\
90
+ !*** ./node_modules/@react-leaflet/core/lib/events.js ***!
91
+ \********************************************************/
92
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
93
+
94
+ "use strict";
95
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useEventHandlers: () => (/* binding */ useEventHandlers)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n\nfunction useEventHandlers(element, eventHandlers) {\n const eventHandlersRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(undefined);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function addEventHandlers() {\n if (eventHandlers != null) {\n element.instance.on(eventHandlers);\n }\n eventHandlersRef.current = eventHandlers;\n return function removeEventHandlers() {\n if (eventHandlersRef.current != null) {\n element.instance.off(eventHandlersRef.current);\n }\n eventHandlersRef.current = null;\n };\n }, [\n element,\n eventHandlers\n ]);\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/events.js?\n}");
96
+
97
+ /***/ }),
98
+
99
+ /***/ "./node_modules/@react-leaflet/core/lib/generic.js":
100
+ /*!*********************************************************!*\
101
+ !*** ./node_modules/@react-leaflet/core/lib/generic.js ***!
102
+ \*********************************************************/
103
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
104
+
105
+ "use strict";
106
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createControlComponent: () => (/* binding */ createControlComponent),\n/* harmony export */ createLayerComponent: () => (/* binding */ createLayerComponent),\n/* harmony export */ createOverlayComponent: () => (/* binding */ createOverlayComponent),\n/* harmony export */ createPathComponent: () => (/* binding */ createPathComponent),\n/* harmony export */ createTileLayerComponent: () => (/* binding */ createTileLayerComponent)\n/* harmony export */ });\n/* harmony import */ var _component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./component.js */ \"./node_modules/@react-leaflet/core/lib/component.js\");\n/* harmony import */ var _control_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./control.js */ \"./node_modules/@react-leaflet/core/lib/control.js\");\n/* harmony import */ var _div_overlay_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./div-overlay.js */ \"./node_modules/@react-leaflet/core/lib/div-overlay.js\");\n/* harmony import */ var _element_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./element.js */ \"./node_modules/@react-leaflet/core/lib/element.js\");\n/* harmony import */ var _layer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./layer.js */ \"./node_modules/@react-leaflet/core/lib/layer.js\");\n/* harmony import */ var _path_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./path.js */ \"./node_modules/@react-leaflet/core/lib/path.js\");\n\n\n\n\n\n\nfunction createControlComponent(createInstance) {\n function createElement(props, context) {\n return (0,_element_js__WEBPACK_IMPORTED_MODULE_3__.createElementObject)(createInstance(props), context);\n }\n const useElement = (0,_element_js__WEBPACK_IMPORTED_MODULE_3__.createElementHook)(createElement);\n const useControl = (0,_control_js__WEBPACK_IMPORTED_MODULE_1__.createControlHook)(useElement);\n return (0,_component_js__WEBPACK_IMPORTED_MODULE_0__.createLeafComponent)(useControl);\n}\nfunction createLayerComponent(createElement, updateElement) {\n const useElement = (0,_element_js__WEBPACK_IMPORTED_MODULE_3__.createElementHook)(createElement, updateElement);\n const useLayer = (0,_layer_js__WEBPACK_IMPORTED_MODULE_4__.createLayerHook)(useElement);\n return (0,_component_js__WEBPACK_IMPORTED_MODULE_0__.createContainerComponent)(useLayer);\n}\nfunction createOverlayComponent(createElement, useLifecycle) {\n const useElement = (0,_element_js__WEBPACK_IMPORTED_MODULE_3__.createElementHook)(createElement);\n const useOverlay = (0,_div_overlay_js__WEBPACK_IMPORTED_MODULE_2__.createDivOverlayHook)(useElement, useLifecycle);\n return (0,_component_js__WEBPACK_IMPORTED_MODULE_0__.createDivOverlayComponent)(useOverlay);\n}\nfunction createPathComponent(createElement, updateElement) {\n const useElement = (0,_element_js__WEBPACK_IMPORTED_MODULE_3__.createElementHook)(createElement, updateElement);\n const usePath = (0,_path_js__WEBPACK_IMPORTED_MODULE_5__.createPathHook)(useElement);\n return (0,_component_js__WEBPACK_IMPORTED_MODULE_0__.createContainerComponent)(usePath);\n}\nfunction createTileLayerComponent(createElement, updateElement) {\n const useElement = (0,_element_js__WEBPACK_IMPORTED_MODULE_3__.createElementHook)(createElement, updateElement);\n const useLayer = (0,_layer_js__WEBPACK_IMPORTED_MODULE_4__.createLayerHook)(useElement);\n return (0,_component_js__WEBPACK_IMPORTED_MODULE_0__.createLeafComponent)(useLayer);\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/generic.js?\n}");
107
+
108
+ /***/ }),
109
+
110
+ /***/ "./node_modules/@react-leaflet/core/lib/grid-layer.js":
111
+ /*!************************************************************!*\
112
+ !*** ./node_modules/@react-leaflet/core/lib/grid-layer.js ***!
113
+ \************************************************************/
114
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
115
+
116
+ "use strict";
117
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ updateGridLayer: () => (/* binding */ updateGridLayer)\n/* harmony export */ });\nfunction updateGridLayer(layer, props, prevProps) {\n const { opacity, zIndex } = props;\n if (opacity != null && opacity !== prevProps.opacity) {\n layer.setOpacity(opacity);\n }\n if (zIndex != null && zIndex !== prevProps.zIndex) {\n layer.setZIndex(zIndex);\n }\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/grid-layer.js?\n}");
118
+
119
+ /***/ }),
120
+
121
+ /***/ "./node_modules/@react-leaflet/core/lib/layer.js":
122
+ /*!*******************************************************!*\
123
+ !*** ./node_modules/@react-leaflet/core/lib/layer.js ***!
124
+ \*******************************************************/
125
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
126
+
127
+ "use strict";
128
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createLayerHook: () => (/* binding */ createLayerHook),\n/* harmony export */ useLayerLifecycle: () => (/* binding */ useLayerLifecycle)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var _attribution_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./attribution.js */ \"./node_modules/@react-leaflet/core/lib/attribution.js\");\n/* harmony import */ var _context_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./context.js */ \"./node_modules/@react-leaflet/core/lib/context.js\");\n/* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./events.js */ \"./node_modules/@react-leaflet/core/lib/events.js\");\n/* harmony import */ var _pane_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./pane.js */ \"./node_modules/@react-leaflet/core/lib/pane.js\");\n\n\n\n\n\nfunction useLayerLifecycle(element, context) {\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function addLayer() {\n const container = context.layerContainer ?? context.map;\n container.addLayer(element.instance);\n return function removeLayer() {\n context.layerContainer?.removeLayer(element.instance);\n context.map.removeLayer(element.instance);\n };\n }, [\n context,\n element\n ]);\n}\nfunction createLayerHook(useElement) {\n return function useLayer(props) {\n const context = (0,_context_js__WEBPACK_IMPORTED_MODULE_2__.useLeafletContext)();\n const elementRef = useElement((0,_pane_js__WEBPACK_IMPORTED_MODULE_4__.withPane)(props, context), context);\n (0,_attribution_js__WEBPACK_IMPORTED_MODULE_1__.useAttribution)(context.map, props.attribution);\n (0,_events_js__WEBPACK_IMPORTED_MODULE_3__.useEventHandlers)(elementRef.current, props.eventHandlers);\n useLayerLifecycle(elementRef.current, context);\n return elementRef;\n };\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/layer.js?\n}");
129
+
130
+ /***/ }),
131
+
132
+ /***/ "./node_modules/@react-leaflet/core/lib/pane.js":
133
+ /*!******************************************************!*\
134
+ !*** ./node_modules/@react-leaflet/core/lib/pane.js ***!
135
+ \******************************************************/
136
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
137
+
138
+ "use strict";
139
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ withPane: () => (/* binding */ withPane)\n/* harmony export */ });\nfunction withPane(props, context) {\n const pane = props.pane ?? context.pane;\n return pane ? {\n ...props,\n pane\n } : props;\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/pane.js?\n}");
140
+
141
+ /***/ }),
142
+
143
+ /***/ "./node_modules/@react-leaflet/core/lib/path.js":
144
+ /*!******************************************************!*\
145
+ !*** ./node_modules/@react-leaflet/core/lib/path.js ***!
146
+ \******************************************************/
147
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
148
+
149
+ "use strict";
150
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createPathHook: () => (/* binding */ createPathHook),\n/* harmony export */ usePathOptions: () => (/* binding */ usePathOptions)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var _context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./context.js */ \"./node_modules/@react-leaflet/core/lib/context.js\");\n/* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./events.js */ \"./node_modules/@react-leaflet/core/lib/events.js\");\n/* harmony import */ var _layer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./layer.js */ \"./node_modules/@react-leaflet/core/lib/layer.js\");\n/* harmony import */ var _pane_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./pane.js */ \"./node_modules/@react-leaflet/core/lib/pane.js\");\n\n\n\n\n\nfunction usePathOptions(element, props) {\n const optionsRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(undefined);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function updatePathOptions() {\n if (props.pathOptions !== optionsRef.current) {\n const options = props.pathOptions ?? {};\n element.instance.setStyle(options);\n optionsRef.current = options;\n }\n }, [\n element,\n props\n ]);\n}\nfunction createPathHook(useElement) {\n return function usePath(props) {\n const context = (0,_context_js__WEBPACK_IMPORTED_MODULE_1__.useLeafletContext)();\n const elementRef = useElement((0,_pane_js__WEBPACK_IMPORTED_MODULE_4__.withPane)(props, context), context);\n (0,_events_js__WEBPACK_IMPORTED_MODULE_2__.useEventHandlers)(elementRef.current, props.eventHandlers);\n (0,_layer_js__WEBPACK_IMPORTED_MODULE_3__.useLayerLifecycle)(elementRef.current, context);\n usePathOptions(elementRef.current, props);\n return elementRef;\n };\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/@react-leaflet/core/lib/path.js?\n}");
151
+
152
+ /***/ }),
153
+
154
+ /***/ "./node_modules/Leaflet.Deflate/dist/L.Deflate.js":
155
+ /*!********************************************************!*\
156
+ !*** ./node_modules/Leaflet.Deflate/dist/L.Deflate.js ***!
157
+ \********************************************************/
158
+ /***/ (() => {
159
+
160
+ "use strict";
161
+ eval("{L.Layer.include({_originalRemove:L.Layer.prototype.remove,remove:function(){if(this.marker){this.marker.remove()}return this._originalRemove()}});L.Map.include({_originalRemoveLayer:L.Map.prototype.removeLayer,removeLayer:function(layer){if(layer.marker){layer.marker.remove()}return this._originalRemoveLayer(layer)}});L.Deflate=L.FeatureGroup.extend({options:{minSize:10,markerOptions:{},markerType:L.marker,greedyCollapse:true},initialize:function(options){L.Util.setOptions(this,options);this._layers=[];this._needsPrepping=[];this._featureLayer=this._getFeatureLayer(options)},_getFeatureLayer:function(){if(this.options.markerLayer){return this.options.markerLayer}return L.featureGroup(this.options)},_getBounds:function(path){if(path instanceof L.Circle){path.addTo(this._map);const bounds=path.getBounds();this._map.removeLayer(path);return bounds}return path.getBounds()},_isCollapsed:function(path,zoom){const bounds=path.computedBounds;const northEastPixels=this._map.project(bounds.getNorthEast(),zoom);const southWestPixels=this._map.project(bounds.getSouthWest(),zoom);const width=Math.abs(northEastPixels.x-southWestPixels.x);const height=Math.abs(southWestPixels.y-northEastPixels.y);if(this.options.greedyCollapse){return height<this.options.minSize||width<this.options.minSize}return height<this.options.minSize&&width<this.options.minSize},_getZoomThreshold:function(path){let zoomThreshold;let zoom=this._map.getZoom();if(this._isCollapsed(path,this._map.getZoom())){while(!zoomThreshold){zoom+=1;if(!this._isCollapsed(path,zoom)){zoomThreshold=zoom-1}}}else{while(!zoomThreshold){zoom-=1;if(this._isCollapsed(path,zoom)){zoomThreshold=zoom}}}return zoomThreshold},_bindInfoTools:function(marker,parentLayer){if(parentLayer._popupHandlersAdded){marker.bindPopup(parentLayer._popup._content,parentLayer._popup.options)}if(parentLayer._tooltipHandlersAdded){marker.bindTooltip(parentLayer._tooltip._content,parentLayer._tooltip.options)}},_bindEvents:function _bindEvents(marker,parentLayer){const events=parentLayer._events;const eventKeys=events?Object.getOwnPropertyNames(events):[];const eventParents=parentLayer._eventParents;const eventParentKeys=eventParents?Object.getOwnPropertyNames(eventParents):[];this._bindInfoTools(marker,parentLayer);for(let i=0,lenI=eventKeys.length;i<lenI;i+=1){const listeners=events[eventKeys[i]];for(let j=0,lenJ=listeners.length;j<lenJ;j+=1){marker.on(eventKeys[i],listeners[j].fn)}}if(!parentLayer._eventParents){return}for(let i=0,lenI=eventParentKeys.length;i<lenI;i+=1){if(!parentLayer._eventParents[eventParentKeys[i]]._map){this._bindEvents(marker,parentLayer._eventParents[eventParentKeys[i]]);this._bindInfoTools(parentLayer,parentLayer._eventParents[eventParentKeys[i]])}}},_makeMarker:function(layer){const allowedMarkerTypes=[L.marker,L.circleMarker];if(allowedMarkerTypes.indexOf(this.options.markerType)===-1){throw new Error(\"Invalid markerType provided. Allowed markerTypes are: L.marker and L.circleMarker\")}const markerOptions=typeof this.options.markerOptions===\"function\"?this.options.markerOptions(layer):this.options.markerOptions;const marker=this.options.markerType(layer.computedBounds.getCenter(),markerOptions);const markerFeature=layer.feature?marker.toGeoJSON():undefined;this._bindEvents(marker,layer);if(markerFeature){markerFeature.properties=layer.feature.properties;marker.feature=markerFeature}return marker},prepLayer:function(layer){if(layer.getBounds){layer.computedBounds=this._getBounds(layer);layer.zoomThreshold=this._getZoomThreshold(layer);layer.marker=this._makeMarker(layer);layer.zoomState=this._map.getZoom()}},_addToMap:function(layer){const layerToAdd=this._map.getZoom()<=layer.zoomThreshold?layer.marker:layer;this._featureLayer.addLayer(layerToAdd)},addLayer:function(layer){const layers=layer instanceof L.FeatureGroup?Object.getOwnPropertyNames(layer._layers):[];if(layers.length){for(let i=0,len=layers.length;i<len;i+=1){this.addLayer(layer._layers[layers[i]])}}else{if(this._map){this.prepLayer(layer);this._addToMap(layer)}else{this._needsPrepping.push(layer)}this._layers[this.getLayerId(layer)]=layer}},removeLayer:function(layer){const layers=layer instanceof L.FeatureGroup?Object.getOwnPropertyNames(layer._layers):[];if(layers.length){for(let i=0,len=layers.length;i<len;i+=1){this.removeLayer(layer._layers[layers[i]])}}else{const layerId=layer in this._layers?layer:this.getLayerId(layer);this._featureLayer.removeLayer(this._layers[layerId]);if(this._layers[layerId].marker){this._featureLayer.removeLayer(this._layers[layerId].marker)}delete this._layers[layerId];const layerIndex=this._needsPrepping.indexOf(this._layers[layerId]);if(layerIndex!==-1){this._needsPrepping.splice(layerIndex,1)}}},clearLayers:function(){this._featureLayer.clearLayers();this._layers=[]},_switchDisplay:function(layer,showMarker){if(showMarker){this._featureLayer.removeLayer(layer);this._featureLayer.addLayer(layer.marker)}else{this._featureLayer.removeLayer(layer.marker);this._featureLayer.addLayer(layer)}},_deflate:function(){const bounds=this._map.getBounds();const endZoom=this._map.getZoom();this.eachLayer((function(layer){if(layer.marker&&layer.zoomState!==endZoom&&layer.computedBounds.intersects(bounds)){this._switchDisplay(layer,endZoom<=layer.zoomThreshold);layer.zoomState=endZoom}}),this)},onAdd:function(map){this._featureLayer.addTo(map);this._map.on(\"zoomend\",this._deflate,this);this._map.on(\"moveend\",this._deflate,this);for(let i=0,len=this._needsPrepping.length;i<len;i+=1){this.addLayer(this._needsPrepping[i])}this._needsPrepping=[];this._deflate()},onRemove:function(map){map.removeLayer(this._featureLayer);this._map.off(\"zoomend\",this._deflate,this);this._map.off(\"moveend\",this._deflate,this)}});L.deflate=function(options){return new L.Deflate(options)};\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/Leaflet.Deflate/dist/L.Deflate.js?\n}");
162
+
163
+ /***/ }),
164
+
165
+ /***/ "./node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.js":
166
+ /*!******************************************************************************!*\
167
+ !*** ./node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.js ***!
168
+ \******************************************************************************/
169
+ /***/ (function(__unused_webpack_module, exports) {
170
+
171
+ eval("{/*\n * Leaflet.markercluster 1.5.3+master.e5124b2,\n * Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps.\n * https://github.com/Leaflet/Leaflet.markercluster\n * (c) 2012-2017, Dave Leaver, smartrak\n */\n(function (global, factory) {\n\t true ? factory(exports) :\n\t0;\n}(this, function (exports) { 'use strict';\n\n\t/*\n\t * L.MarkerClusterGroup extends L.FeatureGroup by clustering the markers contained within\n\t */\n\n\tvar MarkerClusterGroup = L.MarkerClusterGroup = L.FeatureGroup.extend({\n\n\t\toptions: {\n\t\t\tmaxClusterRadius: 80, //A cluster will cover at most this many pixels from its center\n\t\t\ticonCreateFunction: null,\n\t\t\tclusterPane: L.Marker.prototype.options.pane,\n\n\t\t\tspiderfyOnEveryZoom: false,\n\t\t\tspiderfyOnMaxZoom: true,\n\t\t\tshowCoverageOnHover: true,\n\t\t\tzoomToBoundsOnClick: true,\n\t\t\tsingleMarkerMode: false,\n\n\t\t\tdisableClusteringAtZoom: null,\n\n\t\t\t// Setting this to false prevents the removal of any clusters outside of the viewpoint, which\n\t\t\t// is the default behaviour for performance reasons.\n\t\t\tremoveOutsideVisibleBounds: true,\n\n\t\t\t// Set to false to disable all animations (zoom and spiderfy).\n\t\t\t// If false, option animateAddingMarkers below has no effect.\n\t\t\t// If L.DomUtil.TRANSITION is falsy, this option has no effect.\n\t\t\tanimate: true,\n\n\t\t\t//Whether to animate adding markers after adding the MarkerClusterGroup to the map\n\t\t\t// If you are adding individual markers set to true, if adding bulk markers leave false for massive performance gains.\n\t\t\tanimateAddingMarkers: false,\n\n\t\t\t// Make it possible to provide custom function to calculate spiderfy shape positions\n\t\t\tspiderfyShapePositions: null,\n\n\t\t\t//Increase to increase the distance away that spiderfied markers appear from the center\n\t\t\tspiderfyDistanceMultiplier: 1,\n\n\t\t\t// Make it possible to specify a polyline options on a spider leg\n\t\t\tspiderLegPolylineOptions: { weight: 1.5, color: '#222', opacity: 0.5 },\n\n\t\t\t// When bulk adding layers, adds markers in chunks. Means addLayers may not add all the layers in the call, others will be loaded during setTimeouts\n\t\t\tchunkedLoading: false,\n\t\t\tchunkInterval: 200, // process markers for a maximum of ~ n milliseconds (then trigger the chunkProgress callback)\n\t\t\tchunkDelay: 50, // at the end of each interval, give n milliseconds back to system/browser\n\t\t\tchunkProgress: null, // progress callback: function(processed, total, elapsed) (e.g. for a progress indicator)\n\n\t\t\t//Options to pass to the L.Polygon constructor\n\t\t\tpolygonOptions: {}\n\t\t},\n\n\t\tinitialize: function (options) {\n\t\t\tL.Util.setOptions(this, options);\n\t\t\tif (!this.options.iconCreateFunction) {\n\t\t\t\tthis.options.iconCreateFunction = this._defaultIconCreateFunction;\n\t\t\t}\n\n\t\t\tthis._featureGroup = L.featureGroup();\n\t\t\tthis._featureGroup.addEventParent(this);\n\n\t\t\tthis._nonPointGroup = L.featureGroup();\n\t\t\tthis._nonPointGroup.addEventParent(this);\n\n\t\t\tthis._inZoomAnimation = 0;\n\t\t\tthis._needsClustering = [];\n\t\t\tthis._needsRemoving = []; //Markers removed while we aren't on the map need to be kept track of\n\t\t\t//The bounds of the currently shown area (from _getExpandedVisibleBounds) Updated on zoom/move\n\t\t\tthis._currentShownBounds = null;\n\n\t\t\tthis._queue = [];\n\n\t\t\tthis._childMarkerEventHandlers = {\n\t\t\t\t'dragstart': this._childMarkerDragStart,\n\t\t\t\t'move': this._childMarkerMoved,\n\t\t\t\t'dragend': this._childMarkerDragEnd,\n\t\t\t};\n\n\t\t\t// Hook the appropriate animation methods.\n\t\t\tvar animate = L.DomUtil.TRANSITION && this.options.animate;\n\t\t\tL.extend(this, animate ? this._withAnimation : this._noAnimation);\n\t\t\t// Remember which MarkerCluster class to instantiate (animated or not).\n\t\t\tthis._markerCluster = animate ? L.MarkerCluster : L.MarkerClusterNonAnimated;\n\t\t},\n\n\t\taddLayer: function (layer) {\n\n\t\t\tif (layer instanceof L.LayerGroup) {\n\t\t\t\treturn this.addLayers([layer]);\n\t\t\t}\n\n\t\t\t//Don't cluster non point data\n\t\t\tif (!layer.getLatLng) {\n\t\t\t\tthis._nonPointGroup.addLayer(layer);\n\t\t\t\tthis.fire('layeradd', { layer: layer });\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tif (!this._map) {\n\t\t\t\tthis._needsClustering.push(layer);\n\t\t\t\tthis.fire('layeradd', { layer: layer });\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tif (this.hasLayer(layer)) {\n\t\t\t\treturn this;\n\t\t\t}\n\n\n\t\t\t//If we have already clustered we'll need to add this one to a cluster\n\n\t\t\tif (this._unspiderfy) {\n\t\t\t\tthis._unspiderfy();\n\t\t\t}\n\n\t\t\tthis._addLayer(layer, this._maxZoom);\n\t\t\tthis.fire('layeradd', { layer: layer });\n\n\t\t\t// Refresh bounds and weighted positions.\n\t\t\tthis._topClusterLevel._recalculateBounds();\n\n\t\t\tthis._refreshClustersIcons();\n\n\t\t\t//Work out what is visible\n\t\t\tvar visibleLayer = layer,\n\t\t\t currentZoom = this._zoom;\n\t\t\tif (layer.__parent) {\n\t\t\t\twhile (visibleLayer.__parent._zoom >= currentZoom) {\n\t\t\t\t\tvisibleLayer = visibleLayer.__parent;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this._currentShownBounds.contains(visibleLayer.getLatLng())) {\n\t\t\t\tif (this.options.animateAddingMarkers) {\n\t\t\t\t\tthis._animationAddLayer(layer, visibleLayer);\n\t\t\t\t} else {\n\t\t\t\t\tthis._animationAddLayerNonAnimated(layer, visibleLayer);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tremoveLayer: function (layer) {\n\n\t\t\tif (layer instanceof L.LayerGroup) {\n\t\t\t\treturn this.removeLayers([layer]);\n\t\t\t}\n\n\t\t\t//Non point layers\n\t\t\tif (!layer.getLatLng) {\n\t\t\t\tthis._nonPointGroup.removeLayer(layer);\n\t\t\t\tthis.fire('layerremove', { layer: layer });\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tif (!this._map) {\n\t\t\t\tif (!this._arraySplice(this._needsClustering, layer) && this.hasLayer(layer)) {\n\t\t\t\t\tthis._needsRemoving.push({ layer: layer, latlng: layer._latlng });\n\t\t\t\t}\n\t\t\t\tthis.fire('layerremove', { layer: layer });\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tif (!layer.__parent) {\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tif (this._unspiderfy) {\n\t\t\t\tthis._unspiderfy();\n\t\t\t\tthis._unspiderfyLayer(layer);\n\t\t\t}\n\n\t\t\t//Remove the marker from clusters\n\t\t\tthis._removeLayer(layer, true);\n\t\t\tthis.fire('layerremove', { layer: layer });\n\n\t\t\t// Refresh bounds and weighted positions.\n\t\t\tthis._topClusterLevel._recalculateBounds();\n\n\t\t\tthis._refreshClustersIcons();\n\n\t\t\tlayer.off(this._childMarkerEventHandlers, this);\n\n\t\t\tif (this._featureGroup.hasLayer(layer)) {\n\t\t\t\tthis._featureGroup.removeLayer(layer);\n\t\t\t\tif (layer.clusterShow) {\n\t\t\t\t\tlayer.clusterShow();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\t//Takes an array of markers and adds them in bulk\n\t\taddLayers: function (layersArray, skipLayerAddEvent) {\n\t\t\tif (!L.Util.isArray(layersArray)) {\n\t\t\t\treturn this.addLayer(layersArray);\n\t\t\t}\n\n\t\t\tvar fg = this._featureGroup,\n\t\t\t npg = this._nonPointGroup,\n\t\t\t chunked = this.options.chunkedLoading,\n\t\t\t chunkInterval = this.options.chunkInterval,\n\t\t\t chunkProgress = this.options.chunkProgress,\n\t\t\t l = layersArray.length,\n\t\t\t offset = 0,\n\t\t\t originalArray = true,\n\t\t\t m;\n\n\t\t\tif (this._map) {\n\t\t\t\tvar started = (new Date()).getTime();\n\t\t\t\tvar process = L.bind(function () {\n\t\t\t\t\tvar start = (new Date()).getTime();\n\n\t\t\t\t\t// Make sure to unspiderfy before starting to add some layers\n\t\t\t\t\tif (this._map && this._unspiderfy) {\n\t\t\t\t\t\tthis._unspiderfy();\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (; offset < l; offset++) {\n\t\t\t\t\t\tif (chunked && offset % 200 === 0) {\n\t\t\t\t\t\t\t// every couple hundred markers, instrument the time elapsed since processing started:\n\t\t\t\t\t\t\tvar elapsed = (new Date()).getTime() - start;\n\t\t\t\t\t\t\tif (elapsed > chunkInterval) {\n\t\t\t\t\t\t\t\tbreak; // been working too hard, time to take a break :-)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tm = layersArray[offset];\n\n\t\t\t\t\t\t// Group of layers, append children to layersArray and skip.\n\t\t\t\t\t\t// Side effects:\n\t\t\t\t\t\t// - Total increases, so chunkProgress ratio jumps backward.\n\t\t\t\t\t\t// - Groups are not included in this group, only their non-group child layers (hasLayer).\n\t\t\t\t\t\t// Changing array length while looping does not affect performance in current browsers:\n\t\t\t\t\t\t// http://jsperf.com/for-loop-changing-length/6\n\t\t\t\t\t\tif (m instanceof L.LayerGroup) {\n\t\t\t\t\t\t\tif (originalArray) {\n\t\t\t\t\t\t\t\tlayersArray = layersArray.slice();\n\t\t\t\t\t\t\t\toriginalArray = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\n\t\t\t\t\t\t\tl = layersArray.length;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//Not point data, can't be clustered\n\t\t\t\t\t\tif (!m.getLatLng) {\n\t\t\t\t\t\t\tnpg.addLayer(m);\n\t\t\t\t\t\t\tif (!skipLayerAddEvent) {\n\t\t\t\t\t\t\t\tthis.fire('layeradd', { layer: m });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (this.hasLayer(m)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis._addLayer(m, this._maxZoom);\n\t\t\t\t\t\tif (!skipLayerAddEvent) {\n\t\t\t\t\t\t\tthis.fire('layeradd', { layer: m });\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//If we just made a cluster of size 2 then we need to remove the other marker from the map (if it is) or we never will\n\t\t\t\t\t\tif (m.__parent) {\n\t\t\t\t\t\t\tif (m.__parent.getChildCount() === 2) {\n\t\t\t\t\t\t\t\tvar markers = m.__parent.getAllChildMarkers(),\n\t\t\t\t\t\t\t\t otherMarker = markers[0] === m ? markers[1] : markers[0];\n\t\t\t\t\t\t\t\tfg.removeLayer(otherMarker);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (chunkProgress) {\n\t\t\t\t\t\t// report progress and time elapsed:\n\t\t\t\t\t\tchunkProgress(offset, l, (new Date()).getTime() - started);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Completed processing all markers.\n\t\t\t\t\tif (offset === l) {\n\n\t\t\t\t\t\t// Refresh bounds and weighted positions.\n\t\t\t\t\t\tthis._topClusterLevel._recalculateBounds();\n\n\t\t\t\t\t\tthis._refreshClustersIcons();\n\n\t\t\t\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetTimeout(process, this.options.chunkDelay);\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\n\t\t\t\tprocess();\n\t\t\t} else {\n\t\t\t\tvar needsClustering = this._needsClustering;\n\n\t\t\t\tfor (; offset < l; offset++) {\n\t\t\t\t\tm = layersArray[offset];\n\n\t\t\t\t\t// Group of layers, append children to layersArray and skip.\n\t\t\t\t\tif (m instanceof L.LayerGroup) {\n\t\t\t\t\t\tif (originalArray) {\n\t\t\t\t\t\t\tlayersArray = layersArray.slice();\n\t\t\t\t\t\t\toriginalArray = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\n\t\t\t\t\t\tl = layersArray.length;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t//Not point data, can't be clustered\n\t\t\t\t\tif (!m.getLatLng) {\n\t\t\t\t\t\tnpg.addLayer(m);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.hasLayer(m)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tneedsClustering.push(m);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\t//Takes an array of markers and removes them in bulk\n\t\tremoveLayers: function (layersArray) {\n\t\t\tvar i, m,\n\t\t\t l = layersArray.length,\n\t\t\t fg = this._featureGroup,\n\t\t\t npg = this._nonPointGroup,\n\t\t\t originalArray = true;\n\n\t\t\tif (!this._map) {\n\t\t\t\tfor (i = 0; i < l; i++) {\n\t\t\t\t\tm = layersArray[i];\n\n\t\t\t\t\t// Group of layers, append children to layersArray and skip.\n\t\t\t\t\tif (m instanceof L.LayerGroup) {\n\t\t\t\t\t\tif (originalArray) {\n\t\t\t\t\t\t\tlayersArray = layersArray.slice();\n\t\t\t\t\t\t\toriginalArray = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\n\t\t\t\t\t\tl = layersArray.length;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._arraySplice(this._needsClustering, m);\n\t\t\t\t\tnpg.removeLayer(m);\n\t\t\t\t\tif (this.hasLayer(m)) {\n\t\t\t\t\t\tthis._needsRemoving.push({ layer: m, latlng: m._latlng });\n\t\t\t\t\t}\n\t\t\t\t\tthis.fire('layerremove', { layer: m });\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tif (this._unspiderfy) {\n\t\t\t\tthis._unspiderfy();\n\n\t\t\t\t// Work on a copy of the array, so that next loop is not affected.\n\t\t\t\tvar layersArray2 = layersArray.slice(),\n\t\t\t\t l2 = l;\n\t\t\t\tfor (i = 0; i < l2; i++) {\n\t\t\t\t\tm = layersArray2[i];\n\n\t\t\t\t\t// Group of layers, append children to layersArray and skip.\n\t\t\t\t\tif (m instanceof L.LayerGroup) {\n\t\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray2);\n\t\t\t\t\t\tl2 = layersArray2.length;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._unspiderfyLayer(m);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (i = 0; i < l; i++) {\n\t\t\t\tm = layersArray[i];\n\n\t\t\t\t// Group of layers, append children to layersArray and skip.\n\t\t\t\tif (m instanceof L.LayerGroup) {\n\t\t\t\t\tif (originalArray) {\n\t\t\t\t\t\tlayersArray = layersArray.slice();\n\t\t\t\t\t\toriginalArray = false;\n\t\t\t\t\t}\n\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\n\t\t\t\t\tl = layersArray.length;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!m.__parent) {\n\t\t\t\t\tnpg.removeLayer(m);\n\t\t\t\t\tthis.fire('layerremove', { layer: m });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthis._removeLayer(m, true, true);\n\t\t\t\tthis.fire('layerremove', { layer: m });\n\n\t\t\t\tif (fg.hasLayer(m)) {\n\t\t\t\t\tfg.removeLayer(m);\n\t\t\t\t\tif (m.clusterShow) {\n\t\t\t\t\t\tm.clusterShow();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Refresh bounds and weighted positions.\n\t\t\tthis._topClusterLevel._recalculateBounds();\n\n\t\t\tthis._refreshClustersIcons();\n\n\t\t\t//Fix up the clusters and markers on the map\n\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);\n\n\t\t\treturn this;\n\t\t},\n\n\t\t//Removes all layers from the MarkerClusterGroup\n\t\tclearLayers: function () {\n\t\t\t//Need our own special implementation as the LayerGroup one doesn't work for us\n\n\t\t\t//If we aren't on the map (yet), blow away the markers we know of\n\t\t\tif (!this._map) {\n\t\t\t\tthis._needsClustering = [];\n\t\t\t\tthis._needsRemoving = [];\n\t\t\t\tdelete this._gridClusters;\n\t\t\t\tdelete this._gridUnclustered;\n\t\t\t}\n\n\t\t\tif (this._noanimationUnspiderfy) {\n\t\t\t\tthis._noanimationUnspiderfy();\n\t\t\t}\n\n\t\t\t//Remove all the visible layers\n\t\t\tthis._featureGroup.clearLayers();\n\t\t\tthis._nonPointGroup.clearLayers();\n\n\t\t\tthis.eachLayer(function (marker) {\n\t\t\t\tmarker.off(this._childMarkerEventHandlers, this);\n\t\t\t\tdelete marker.__parent;\n\t\t\t}, this);\n\n\t\t\tif (this._map) {\n\t\t\t\t//Reset _topClusterLevel and the DistanceGrids\n\t\t\t\tthis._generateInitialClusters();\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\t//Override FeatureGroup.getBounds as it doesn't work\n\t\tgetBounds: function () {\n\t\t\tvar bounds = new L.LatLngBounds();\n\n\t\t\tif (this._topClusterLevel) {\n\t\t\t\tbounds.extend(this._topClusterLevel._bounds);\n\t\t\t}\n\n\t\t\tfor (var i = this._needsClustering.length - 1; i >= 0; i--) {\n\t\t\t\tbounds.extend(this._needsClustering[i].getLatLng());\n\t\t\t}\n\n\t\t\tbounds.extend(this._nonPointGroup.getBounds());\n\n\t\t\treturn bounds;\n\t\t},\n\n\t\t//Overrides LayerGroup.eachLayer\n\t\teachLayer: function (method, context) {\n\t\t\tvar markers = this._needsClustering.slice(),\n\t\t\t\tneedsRemoving = this._needsRemoving,\n\t\t\t\tthisNeedsRemoving, i, j;\n\n\t\t\tif (this._topClusterLevel) {\n\t\t\t\tthis._topClusterLevel.getAllChildMarkers(markers);\n\t\t\t}\n\n\t\t\tfor (i = markers.length - 1; i >= 0; i--) {\n\t\t\t\tthisNeedsRemoving = true;\n\n\t\t\t\tfor (j = needsRemoving.length - 1; j >= 0; j--) {\n\t\t\t\t\tif (needsRemoving[j].layer === markers[i]) {\n\t\t\t\t\t\tthisNeedsRemoving = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (thisNeedsRemoving) {\n\t\t\t\t\tmethod.call(context, markers[i]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._nonPointGroup.eachLayer(method, context);\n\t\t},\n\n\t\t//Overrides LayerGroup.getLayers\n\t\tgetLayers: function () {\n\t\t\tvar layers = [];\n\t\t\tthis.eachLayer(function (l) {\n\t\t\t\tlayers.push(l);\n\t\t\t});\n\t\t\treturn layers;\n\t\t},\n\n\t\t//Overrides LayerGroup.getLayer, WARNING: Really bad performance\n\t\tgetLayer: function (id) {\n\t\t\tvar result = null;\n\n\t\t\tid = parseInt(id, 10);\n\n\t\t\tthis.eachLayer(function (l) {\n\t\t\t\tif (L.stamp(l) === id) {\n\t\t\t\t\tresult = l;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn result;\n\t\t},\n\n\t\t//Returns true if the given layer is in this MarkerClusterGroup\n\t\thasLayer: function (layer) {\n\t\t\tif (!layer) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar i, anArray = this._needsClustering;\n\n\t\t\tfor (i = anArray.length - 1; i >= 0; i--) {\n\t\t\t\tif (anArray[i] === layer) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tanArray = this._needsRemoving;\n\t\t\tfor (i = anArray.length - 1; i >= 0; i--) {\n\t\t\t\tif (anArray[i].layer === layer) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn !!(layer.__parent && layer.__parent._group === this) || this._nonPointGroup.hasLayer(layer);\n\t\t},\n\n\t\t//Zoom down to show the given layer (spiderfying if necessary) then calls the callback\n\t\tzoomToShowLayer: function (layer, callback) {\n\n\t\t\tvar map = this._map;\n\n\t\t\tif (typeof callback !== 'function') {\n\t\t\t\tcallback = function () {};\n\t\t\t}\n\n\t\t\tvar showMarker = function () {\n\t\t\t\t// Assumes that map.hasLayer checks for direct appearance on map, not recursively calling\n\t\t\t\t// hasLayer on Layer Groups that are on map (typically not calling this MarkerClusterGroup.hasLayer, which would always return true)\n\t\t\t\tif ((map.hasLayer(layer) || map.hasLayer(layer.__parent)) && !this._inZoomAnimation) {\n\t\t\t\t\tthis._map.off('moveend', showMarker, this);\n\t\t\t\t\tthis.off('animationend', showMarker, this);\n\n\t\t\t\t\tif (map.hasLayer(layer)) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if (layer.__parent._icon) {\n\t\t\t\t\t\tthis.once('spiderfied', callback, this);\n\t\t\t\t\t\tlayer.__parent.spiderfy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (layer._icon && this._map.getBounds().contains(layer.getLatLng())) {\n\t\t\t\t//Layer is visible ond on screen, immediate return\n\t\t\t\tcallback();\n\t\t\t} else if (layer.__parent._zoom < Math.round(this._map._zoom)) {\n\t\t\t\t//Layer should be visible at this zoom level. It must not be on screen so just pan over to it\n\t\t\t\tthis._map.on('moveend', showMarker, this);\n\t\t\t\tthis._map.panTo(layer.getLatLng());\n\t\t\t} else {\n\t\t\t\tthis._map.on('moveend', showMarker, this);\n\t\t\t\tthis.on('animationend', showMarker, this);\n\t\t\t\tlayer.__parent.zoomToBounds();\n\t\t\t}\n\t\t},\n\n\t\t//Overrides FeatureGroup.onAdd\n\t\tonAdd: function (map) {\n\t\t\tthis._map = map;\n\t\t\tvar i, l, layer;\n\n\t\t\tif (!isFinite(this._map.getMaxZoom())) {\n\t\t\t\tthrow \"Map has no maxZoom specified\";\n\t\t\t}\n\n\t\t\tthis._featureGroup.addTo(map);\n\t\t\tthis._nonPointGroup.addTo(map);\n\n\t\t\tif (!this._gridClusters) {\n\t\t\t\tthis._generateInitialClusters();\n\t\t\t}\n\n\t\t\tthis._maxLat = map.options.crs.projection.MAX_LATITUDE;\n\n\t\t\t//Restore all the positions as they are in the MCG before removing them\n\t\t\tfor (i = 0, l = this._needsRemoving.length; i < l; i++) {\n\t\t\t\tlayer = this._needsRemoving[i];\n\t\t\t\tlayer.newlatlng = layer.layer._latlng;\n\t\t\t\tlayer.layer._latlng = layer.latlng;\n\t\t\t}\n\t\t\t//Remove them, then restore their new positions\n\t\t\tfor (i = 0, l = this._needsRemoving.length; i < l; i++) {\n\t\t\t\tlayer = this._needsRemoving[i];\n\t\t\t\tthis._removeLayer(layer.layer, true);\n\t\t\t\tlayer.layer._latlng = layer.newlatlng;\n\t\t\t}\n\t\t\tthis._needsRemoving = [];\n\n\t\t\t//Remember the current zoom level and bounds\n\t\t\tthis._zoom = Math.round(this._map._zoom);\n\t\t\tthis._currentShownBounds = this._getExpandedVisibleBounds();\n\n\t\t\tthis._map.on('zoomend', this._zoomEnd, this);\n\t\t\tthis._map.on('moveend', this._moveEnd, this);\n\n\t\t\tif (this._spiderfierOnAdd) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely\n\t\t\t\tthis._spiderfierOnAdd();\n\t\t\t}\n\n\t\t\tthis._bindEvents();\n\n\t\t\t//Actually add our markers to the map:\n\t\t\tl = this._needsClustering;\n\t\t\tthis._needsClustering = [];\n\t\t\tthis.addLayers(l, true);\n\t\t},\n\n\t\t//Overrides FeatureGroup.onRemove\n\t\tonRemove: function (map) {\n\t\t\tmap.off('zoomend', this._zoomEnd, this);\n\t\t\tmap.off('moveend', this._moveEnd, this);\n\n\t\t\tthis._unbindEvents();\n\n\t\t\t//In case we are in a cluster animation\n\t\t\tthis._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', '');\n\n\t\t\tif (this._spiderfierOnRemove) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely\n\t\t\t\tthis._spiderfierOnRemove();\n\t\t\t}\n\n\t\t\tdelete this._maxLat;\n\n\t\t\t//Clean up all the layers we added to the map\n\t\t\tthis._hideCoverage();\n\t\t\tthis._featureGroup.remove();\n\t\t\tthis._nonPointGroup.remove();\n\n\t\t\tthis._featureGroup.clearLayers();\n\n\t\t\tthis._map = null;\n\t\t},\n\n\t\tgetVisibleParent: function (marker) {\n\t\t\tvar vMarker = marker;\n\t\t\twhile (vMarker && !vMarker._icon) {\n\t\t\t\tvMarker = vMarker.__parent;\n\t\t\t}\n\t\t\treturn vMarker || null;\n\t\t},\n\n\t\t//Remove the given object from the given array\n\t\t_arraySplice: function (anArray, obj) {\n\t\t\tfor (var i = anArray.length - 1; i >= 0; i--) {\n\t\t\t\tif (anArray[i] === obj) {\n\t\t\t\t\tanArray.splice(i, 1);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom.\n\t\t * @param marker to be removed from _gridUnclustered.\n\t\t * @param z integer bottom start zoom level (included)\n\t\t * @private\n\t\t */\n\t\t_removeFromGridUnclustered: function (marker, z) {\n\t\t\tvar map = this._map,\n\t\t\t gridUnclustered = this._gridUnclustered,\n\t\t\t\tminZoom = Math.floor(this._map.getMinZoom());\n\n\t\t\tfor (; z >= minZoom; z--) {\n\t\t\t\tif (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_childMarkerDragStart: function (e) {\n\t\t\te.target.__dragStart = e.target._latlng;\n\t\t},\n\n\t\t_childMarkerMoved: function (e) {\n\t\t\tif (!this._ignoreMove && !e.target.__dragStart) {\n\t\t\t\tvar isPopupOpen = e.target._popup && e.target._popup.isOpen();\n\n\t\t\t\tthis._moveChild(e.target, e.oldLatLng, e.latlng);\n\n\t\t\t\tif (isPopupOpen) {\n\t\t\t\t\te.target.openPopup();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_moveChild: function (layer, from, to) {\n\t\t\tlayer._latlng = from;\n\t\t\tthis.removeLayer(layer);\n\n\t\t\tlayer._latlng = to;\n\t\t\tthis.addLayer(layer);\n\t\t},\n\n\t\t_childMarkerDragEnd: function (e) {\n\t\t\tvar dragStart = e.target.__dragStart;\n\t\t\tdelete e.target.__dragStart;\n\t\t\tif (dragStart) {\n\t\t\t\tthis._moveChild(e.target, dragStart, e.target._latlng);\n\t\t\t}\t\t\n\t\t},\n\n\n\t\t//Internal function for removing a marker from everything.\n\t\t//dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions)\n\t\t_removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) {\n\t\t\tvar gridClusters = this._gridClusters,\n\t\t\t\tgridUnclustered = this._gridUnclustered,\n\t\t\t\tfg = this._featureGroup,\n\t\t\t\tmap = this._map,\n\t\t\t\tminZoom = Math.floor(this._map.getMinZoom());\n\n\t\t\t//Remove the marker from distance clusters it might be in\n\t\t\tif (removeFromDistanceGrid) {\n\t\t\t\tthis._removeFromGridUnclustered(marker, this._maxZoom);\n\t\t\t}\n\n\t\t\t//Work our way up the clusters removing them as we go if required\n\t\t\tvar cluster = marker.__parent,\n\t\t\t\tmarkers = cluster._markers,\n\t\t\t\totherMarker;\n\n\t\t\t//Remove the marker from the immediate parents marker list\n\t\t\tthis._arraySplice(markers, marker);\n\n\t\t\twhile (cluster) {\n\t\t\t\tcluster._childCount--;\n\t\t\t\tcluster._boundsNeedUpdate = true;\n\n\t\t\t\tif (cluster._zoom < minZoom) {\n\t\t\t\t\t//Top level, do nothing\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (removeFromDistanceGrid && cluster._childCount <= 1) { //Cluster no longer required\n\t\t\t\t\t//We need to push the other marker up to the parent\n\t\t\t\t\totherMarker = cluster._markers[0] === marker ? cluster._markers[1] : cluster._markers[0];\n\n\t\t\t\t\t//Update distance grid\n\t\t\t\t\tgridClusters[cluster._zoom].removeObject(cluster, map.project(cluster._cLatLng, cluster._zoom));\n\t\t\t\t\tgridUnclustered[cluster._zoom].addObject(otherMarker, map.project(otherMarker.getLatLng(), cluster._zoom));\n\n\t\t\t\t\t//Move otherMarker up to parent\n\t\t\t\t\tthis._arraySplice(cluster.__parent._childClusters, cluster);\n\t\t\t\t\tcluster.__parent._markers.push(otherMarker);\n\t\t\t\t\totherMarker.__parent = cluster.__parent;\n\n\t\t\t\t\tif (cluster._icon) {\n\t\t\t\t\t\t//Cluster is currently on the map, need to put the marker on the map instead\n\t\t\t\t\t\tfg.removeLayer(cluster);\n\t\t\t\t\t\tif (!dontUpdateMap) {\n\t\t\t\t\t\t\tfg.addLayer(otherMarker);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcluster._iconNeedsUpdate = true;\n\t\t\t\t}\n\n\t\t\t\tcluster = cluster.__parent;\n\t\t\t}\n\n\t\t\tdelete marker.__parent;\n\t\t},\n\n\t\t_isOrIsParent: function (el, oel) {\n\t\t\twhile (oel) {\n\t\t\t\tif (el === oel) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\toel = oel.parentNode;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\n\t\t//Override L.Evented.fire\n\t\tfire: function (type, data, propagate) {\n\t\t\tif (data && data.layer instanceof L.MarkerCluster) {\n\t\t\t\t//Prevent multiple clustermouseover/off events if the icon is made up of stacked divs (Doesn't work in ie <= 8, no relatedTarget)\n\t\t\t\tif (data.originalEvent && this._isOrIsParent(data.layer._icon, data.originalEvent.relatedTarget)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttype = 'cluster' + type;\n\t\t\t}\n\n\t\t\tL.FeatureGroup.prototype.fire.call(this, type, data, propagate);\n\t\t},\n\n\t\t//Override L.Evented.listens\n\t\tlistens: function (type, propagate) {\n\t\t\treturn L.FeatureGroup.prototype.listens.call(this, type, propagate) || L.FeatureGroup.prototype.listens.call(this, 'cluster' + type, propagate);\n\t\t},\n\n\t\t//Default functionality\n\t\t_defaultIconCreateFunction: function (cluster) {\n\t\t\tvar childCount = cluster.getChildCount();\n\n\t\t\tvar c = ' marker-cluster-';\n\t\t\tif (childCount < 10) {\n\t\t\t\tc += 'small';\n\t\t\t} else if (childCount < 100) {\n\t\t\t\tc += 'medium';\n\t\t\t} else {\n\t\t\t\tc += 'large';\n\t\t\t}\n\n\t\t\treturn new L.DivIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });\n\t\t},\n\n\t\t_bindEvents: function () {\n\t\t\tvar map = this._map,\n\t\t\t spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom,\n\t\t\t showCoverageOnHover = this.options.showCoverageOnHover,\n\t\t\t zoomToBoundsOnClick = this.options.zoomToBoundsOnClick,\n\t\t\t spiderfyOnEveryZoom = this.options.spiderfyOnEveryZoom;\n\n\t\t\t//Zoom on cluster click or spiderfy if we are at the lowest level\n\t\t\tif (spiderfyOnMaxZoom || zoomToBoundsOnClick || spiderfyOnEveryZoom) {\n\t\t\t\tthis.on('clusterclick clusterkeypress', this._zoomOrSpiderfy, this);\n\t\t\t}\n\n\t\t\t//Show convex hull (boundary) polygon on mouse over\n\t\t\tif (showCoverageOnHover) {\n\t\t\t\tthis.on('clustermouseover', this._showCoverage, this);\n\t\t\t\tthis.on('clustermouseout', this._hideCoverage, this);\n\t\t\t\tmap.on('zoomend', this._hideCoverage, this);\n\t\t\t}\n\t\t},\n\n\t\t_zoomOrSpiderfy: function (e) {\n\t\t\tvar cluster = e.layer,\n\t\t\t bottomCluster = cluster;\n\n\t\t\tif (e.type === 'clusterkeypress' && e.originalEvent && e.originalEvent.keyCode !== 13) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twhile (bottomCluster._childClusters.length === 1) {\n\t\t\t\tbottomCluster = bottomCluster._childClusters[0];\n\t\t\t}\n\n\t\t\tif (bottomCluster._zoom === this._maxZoom &&\n\t\t\t\tbottomCluster._childCount === cluster._childCount &&\n\t\t\t\tthis.options.spiderfyOnMaxZoom) {\n\n\t\t\t\t// All child markers are contained in a single cluster from this._maxZoom to this cluster.\n\t\t\t\tcluster.spiderfy();\n\t\t\t} else if (this.options.zoomToBoundsOnClick) {\n\t\t\t\tcluster.zoomToBounds();\n\t\t\t}\n\n\t\t\tif (this.options.spiderfyOnEveryZoom) {\n\t\t\t\tcluster.spiderfy();\n\t\t\t}\n\n\t\t\t// Focus the map again for keyboard users.\n\t\t\tif (e.originalEvent && e.originalEvent.keyCode === 13) {\n\t\t\t\tthis._map._container.focus();\n\t\t\t}\n\t\t},\n\n\t\t_showCoverage: function (e) {\n\t\t\tvar map = this._map;\n\t\t\tif (this._inZoomAnimation) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._shownPolygon) {\n\t\t\t\tmap.removeLayer(this._shownPolygon);\n\t\t\t}\n\t\t\tif (e.layer.getChildCount() > 2 && e.layer !== this._spiderfied) {\n\t\t\t\tthis._shownPolygon = new L.Polygon(e.layer.getConvexHull(), this.options.polygonOptions);\n\t\t\t\tmap.addLayer(this._shownPolygon);\n\t\t\t}\n\t\t},\n\n\t\t_hideCoverage: function () {\n\t\t\tif (this._shownPolygon) {\n\t\t\t\tthis._map.removeLayer(this._shownPolygon);\n\t\t\t\tthis._shownPolygon = null;\n\t\t\t}\n\t\t},\n\n\t\t_unbindEvents: function () {\n\t\t\tvar spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom,\n\t\t\t\tshowCoverageOnHover = this.options.showCoverageOnHover,\n\t\t\t\tzoomToBoundsOnClick = this.options.zoomToBoundsOnClick,\n\t\t\t\tspiderfyOnEveryZoom = this.options.spiderfyOnEveryZoom,\n\t\t\t\tmap = this._map;\n\n\t\t\tif (spiderfyOnMaxZoom || zoomToBoundsOnClick || spiderfyOnEveryZoom) {\n\t\t\t\tthis.off('clusterclick clusterkeypress', this._zoomOrSpiderfy, this);\n\t\t\t}\n\t\t\tif (showCoverageOnHover) {\n\t\t\t\tthis.off('clustermouseover', this._showCoverage, this);\n\t\t\t\tthis.off('clustermouseout', this._hideCoverage, this);\n\t\t\t\tmap.off('zoomend', this._hideCoverage, this);\n\t\t\t}\n\t\t},\n\n\t\t_zoomEnd: function () {\n\t\t\tif (!this._map) { //May have been removed from the map by a zoomEnd handler\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._mergeSplitClusters();\n\n\t\t\tthis._zoom = Math.round(this._map._zoom);\n\t\t\tthis._currentShownBounds = this._getExpandedVisibleBounds();\n\t\t},\n\n\t\t_moveEnd: function () {\n\t\t\tif (this._inZoomAnimation) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar newBounds = this._getExpandedVisibleBounds();\n\n\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, newBounds);\n\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, Math.round(this._map._zoom), newBounds);\n\n\t\t\tthis._currentShownBounds = newBounds;\n\t\t\treturn;\n\t\t},\n\n\t\t_generateInitialClusters: function () {\n\t\t\tvar maxZoom = Math.ceil(this._map.getMaxZoom()),\n\t\t\t\tminZoom = Math.floor(this._map.getMinZoom()),\n\t\t\t\tradius = this.options.maxClusterRadius,\n\t\t\t\tradiusFn = radius;\n\n\t\t\t//If we just set maxClusterRadius to a single number, we need to create\n\t\t\t//a simple function to return that number. Otherwise, we just have to\n\t\t\t//use the function we've passed in.\n\t\t\tif (typeof radius !== \"function\") {\n\t\t\t\tradiusFn = function () { return radius; };\n\t\t\t}\n\n\t\t\tif (this.options.disableClusteringAtZoom !== null) {\n\t\t\t\tmaxZoom = this.options.disableClusteringAtZoom - 1;\n\t\t\t}\n\t\t\tthis._maxZoom = maxZoom;\n\t\t\tthis._gridClusters = {};\n\t\t\tthis._gridUnclustered = {};\n\n\t\t\t//Set up DistanceGrids for each zoom\n\t\t\tfor (var zoom = maxZoom; zoom >= minZoom; zoom--) {\n\t\t\t\tthis._gridClusters[zoom] = new L.DistanceGrid(radiusFn(zoom));\n\t\t\t\tthis._gridUnclustered[zoom] = new L.DistanceGrid(radiusFn(zoom));\n\t\t\t}\n\n\t\t\t// Instantiate the appropriate L.MarkerCluster class (animated or not).\n\t\t\tthis._topClusterLevel = new this._markerCluster(this, minZoom - 1);\n\t\t},\n\n\t\t//Zoom: Zoom to start adding at (Pass this._maxZoom to start at the bottom)\n\t\t_addLayer: function (layer, zoom) {\n\t\t\tvar gridClusters = this._gridClusters,\n\t\t\t gridUnclustered = this._gridUnclustered,\n\t\t\t\tminZoom = Math.floor(this._map.getMinZoom()),\n\t\t\t markerPoint, z;\n\n\t\t\tif (this.options.singleMarkerMode) {\n\t\t\t\tthis._overrideMarkerIcon(layer);\n\t\t\t}\n\n\t\t\tlayer.on(this._childMarkerEventHandlers, this);\n\n\t\t\t//Find the lowest zoom level to slot this one in\n\t\t\tfor (; zoom >= minZoom; zoom--) {\n\t\t\t\tmarkerPoint = this._map.project(layer.getLatLng(), zoom); // calculate pixel position\n\n\t\t\t\t//Try find a cluster close by\n\t\t\t\tvar closest = gridClusters[zoom].getNearObject(markerPoint);\n\t\t\t\tif (closest) {\n\t\t\t\t\tclosest._addChild(layer);\n\t\t\t\t\tlayer.__parent = closest;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t//Try find a marker close by to form a new cluster with\n\t\t\t\tclosest = gridUnclustered[zoom].getNearObject(markerPoint);\n\t\t\t\tif (closest) {\n\t\t\t\t\tvar parent = closest.__parent;\n\t\t\t\t\tif (parent) {\n\t\t\t\t\t\tthis._removeLayer(closest, false);\n\t\t\t\t\t}\n\n\t\t\t\t\t//Create new cluster with these 2 in it\n\n\t\t\t\t\tvar newCluster = new this._markerCluster(this, zoom, closest, layer);\n\t\t\t\t\tgridClusters[zoom].addObject(newCluster, this._map.project(newCluster._cLatLng, zoom));\n\t\t\t\t\tclosest.__parent = newCluster;\n\t\t\t\t\tlayer.__parent = newCluster;\n\n\t\t\t\t\t//First create any new intermediate parent clusters that don't exist\n\t\t\t\t\tvar lastParent = newCluster;\n\t\t\t\t\tfor (z = zoom - 1; z > parent._zoom; z--) {\n\t\t\t\t\t\tlastParent = new this._markerCluster(this, z, lastParent);\n\t\t\t\t\t\tgridClusters[z].addObject(lastParent, this._map.project(closest.getLatLng(), z));\n\t\t\t\t\t}\n\t\t\t\t\tparent._addChild(lastParent);\n\n\t\t\t\t\t//Remove closest from this zoom level and any above that it is in, replace with newCluster\n\t\t\t\t\tthis._removeFromGridUnclustered(closest, zoom);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t//Didn't manage to cluster in at this zoom, record us as a marker here and continue upwards\n\t\t\t\tgridUnclustered[zoom].addObject(layer, markerPoint);\n\t\t\t}\n\n\t\t\t//Didn't get in anything, add us to the top\n\t\t\tthis._topClusterLevel._addChild(layer);\n\t\t\tlayer.__parent = this._topClusterLevel;\n\t\t\treturn;\n\t\t},\n\n\t\t/**\n\t\t * Refreshes the icon of all \"dirty\" visible clusters.\n\t\t * Non-visible \"dirty\" clusters will be updated when they are added to the map.\n\t\t * @private\n\t\t */\n\t\t_refreshClustersIcons: function () {\n\t\t\tthis._featureGroup.eachLayer(function (c) {\n\t\t\t\tif (c instanceof L.MarkerCluster && c._iconNeedsUpdate) {\n\t\t\t\t\tc._updateIcon();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\t//Enqueue code to fire after the marker expand/contract has happened\n\t\t_enqueue: function (fn) {\n\t\t\tthis._queue.push(fn);\n\t\t\tif (!this._queueTimeout) {\n\t\t\t\tthis._queueTimeout = setTimeout(L.bind(this._processQueue, this), 300);\n\t\t\t}\n\t\t},\n\t\t_processQueue: function () {\n\t\t\tfor (var i = 0; i < this._queue.length; i++) {\n\t\t\t\tthis._queue[i].call(this);\n\t\t\t}\n\t\t\tthis._queue.length = 0;\n\t\t\tclearTimeout(this._queueTimeout);\n\t\t\tthis._queueTimeout = null;\n\t\t},\n\n\t\t//Merge and split any existing clusters that are too big or small\n\t\t_mergeSplitClusters: function () {\n\t\t\tvar mapZoom = Math.round(this._map._zoom);\n\n\t\t\t//In case we are starting to split before the animation finished\n\t\t\tthis._processQueue();\n\n\t\t\tif (this._zoom < mapZoom && this._currentShownBounds.intersects(this._getExpandedVisibleBounds())) { //Zoom in, split\n\t\t\t\tthis._animationStart();\n\t\t\t\t//Remove clusters now off screen\n\t\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, this._getExpandedVisibleBounds());\n\n\t\t\t\tthis._animationZoomIn(this._zoom, mapZoom);\n\n\t\t\t} else if (this._zoom > mapZoom) { //Zoom out, merge\n\t\t\t\tthis._animationStart();\n\n\t\t\t\tthis._animationZoomOut(this._zoom, mapZoom);\n\t\t\t} else {\n\t\t\t\tthis._moveEnd();\n\t\t\t}\n\t\t},\n\n\t\t//Gets the maps visible bounds expanded in each direction by the size of the screen (so the user cannot see an area we do not cover in one pan)\n\t\t_getExpandedVisibleBounds: function () {\n\t\t\tif (!this.options.removeOutsideVisibleBounds) {\n\t\t\t\treturn this._mapBoundsInfinite;\n\t\t\t} else if (L.Browser.mobile) {\n\t\t\t\treturn this._checkBoundsMaxLat(this._map.getBounds());\n\t\t\t}\n\n\t\t\treturn this._checkBoundsMaxLat(this._map.getBounds().pad(1)); // Padding expands the bounds by its own dimensions but scaled with the given factor.\n\t\t},\n\n\t\t/**\n\t\t * Expands the latitude to Infinity (or -Infinity) if the input bounds reach the map projection maximum defined latitude\n\t\t * (in the case of Web/Spherical Mercator, it is 85.0511287798 / see https://en.wikipedia.org/wiki/Web_Mercator#Formulas).\n\t\t * Otherwise, the removeOutsideVisibleBounds option will remove markers beyond that limit, whereas the same markers without\n\t\t * this option (or outside MCG) will have their position floored (ceiled) by the projection and rendered at that limit,\n\t\t * making the user think that MCG \"eats\" them and never displays them again.\n\t\t * @param bounds L.LatLngBounds\n\t\t * @returns {L.LatLngBounds}\n\t\t * @private\n\t\t */\n\t\t_checkBoundsMaxLat: function (bounds) {\n\t\t\tvar maxLat = this._maxLat;\n\n\t\t\tif (maxLat !== undefined) {\n\t\t\t\tif (bounds.getNorth() >= maxLat) {\n\t\t\t\t\tbounds._northEast.lat = Infinity;\n\t\t\t\t}\n\t\t\t\tif (bounds.getSouth() <= -maxLat) {\n\t\t\t\t\tbounds._southWest.lat = -Infinity;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn bounds;\n\t\t},\n\n\t\t//Shared animation code\n\t\t_animationAddLayerNonAnimated: function (layer, newCluster) {\n\t\t\tif (newCluster === layer) {\n\t\t\t\tthis._featureGroup.addLayer(layer);\n\t\t\t} else if (newCluster._childCount === 2) {\n\t\t\t\tnewCluster._addToMap();\n\n\t\t\t\tvar markers = newCluster.getAllChildMarkers();\n\t\t\t\tthis._featureGroup.removeLayer(markers[0]);\n\t\t\t\tthis._featureGroup.removeLayer(markers[1]);\n\t\t\t} else {\n\t\t\t\tnewCluster._updateIcon();\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Extracts individual (i.e. non-group) layers from a Layer Group.\n\t\t * @param group to extract layers from.\n\t\t * @param output {Array} in which to store the extracted layers.\n\t\t * @returns {*|Array}\n\t\t * @private\n\t\t */\n\t\t_extractNonGroupLayers: function (group, output) {\n\t\t\tvar layers = group.getLayers(),\n\t\t\t i = 0,\n\t\t\t layer;\n\n\t\t\toutput = output || [];\n\n\t\t\tfor (; i < layers.length; i++) {\n\t\t\t\tlayer = layers[i];\n\n\t\t\t\tif (layer instanceof L.LayerGroup) {\n\t\t\t\t\tthis._extractNonGroupLayers(layer, output);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\toutput.push(layer);\n\t\t\t}\n\n\t\t\treturn output;\n\t\t},\n\n\t\t/**\n\t\t * Implements the singleMarkerMode option.\n\t\t * @param layer Marker to re-style using the Clusters iconCreateFunction.\n\t\t * @returns {L.Icon} The newly created icon.\n\t\t * @private\n\t\t */\n\t\t_overrideMarkerIcon: function (layer) {\n\t\t\tvar icon = layer.options.icon = this.options.iconCreateFunction({\n\t\t\t\tgetChildCount: function () {\n\t\t\t\t\treturn 1;\n\t\t\t\t},\n\t\t\t\tgetAllChildMarkers: function () {\n\t\t\t\t\treturn [layer];\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn icon;\n\t\t}\n\t});\n\n\t// Constant bounds used in case option \"removeOutsideVisibleBounds\" is set to false.\n\tL.MarkerClusterGroup.include({\n\t\t_mapBoundsInfinite: new L.LatLngBounds(new L.LatLng(-Infinity, -Infinity), new L.LatLng(Infinity, Infinity))\n\t});\n\n\tL.MarkerClusterGroup.include({\n\t\t_noAnimation: {\n\t\t\t//Non Animated versions of everything\n\t\t\t_animationStart: function () {\n\t\t\t\t//Do nothing...\n\t\t\t},\n\t\t\t_animationZoomIn: function (previousZoomLevel, newZoomLevel) {\n\t\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel);\n\t\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());\n\n\t\t\t\t//We didn't actually animate, but we use this event to mean \"clustering animations have finished\"\n\t\t\t\tthis.fire('animationend');\n\t\t\t},\n\t\t\t_animationZoomOut: function (previousZoomLevel, newZoomLevel) {\n\t\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel);\n\t\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());\n\n\t\t\t\t//We didn't actually animate, but we use this event to mean \"clustering animations have finished\"\n\t\t\t\tthis.fire('animationend');\n\t\t\t},\n\t\t\t_animationAddLayer: function (layer, newCluster) {\n\t\t\t\tthis._animationAddLayerNonAnimated(layer, newCluster);\n\t\t\t}\n\t\t},\n\n\t\t_withAnimation: {\n\t\t\t//Animated versions here\n\t\t\t_animationStart: function () {\n\t\t\t\tthis._map._mapPane.className += ' leaflet-cluster-anim';\n\t\t\t\tthis._inZoomAnimation++;\n\t\t\t},\n\n\t\t\t_animationZoomIn: function (previousZoomLevel, newZoomLevel) {\n\t\t\t\tvar bounds = this._getExpandedVisibleBounds(),\n\t\t\t\t fg = this._featureGroup,\n\t\t\t\t\tminZoom = Math.floor(this._map.getMinZoom()),\n\t\t\t\t i;\n\n\t\t\t\tthis._ignoreMove = true;\n\n\t\t\t\t//Add all children of current clusters to map and remove those clusters from map\n\t\t\t\tthis._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) {\n\t\t\t\t\tvar startPos = c._latlng,\n\t\t\t\t\t markers = c._markers,\n\t\t\t\t\t m;\n\n\t\t\t\t\tif (!bounds.contains(startPos)) {\n\t\t\t\t\t\tstartPos = null;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us\n\t\t\t\t\t\tfg.removeLayer(c);\n\t\t\t\t\t\tc._recursivelyAddChildrenToMap(null, newZoomLevel, bounds);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//Fade out old cluster\n\t\t\t\t\t\tc.clusterHide();\n\t\t\t\t\t\tc._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds);\n\t\t\t\t\t}\n\n\t\t\t\t\t//Remove all markers that aren't visible any more\n\t\t\t\t\t//TODO: Do we actually need to do this on the higher levels too?\n\t\t\t\t\tfor (i = markers.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tm = markers[i];\n\t\t\t\t\t\tif (!bounds.contains(m._latlng)) {\n\t\t\t\t\t\t\tfg.removeLayer(m);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t});\n\n\t\t\t\tthis._forceLayout();\n\n\t\t\t\t//Update opacities\n\t\t\t\tthis._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel);\n\t\t\t\t//TODO Maybe? Update markers in _recursivelyBecomeVisible\n\t\t\t\tfg.eachLayer(function (n) {\n\t\t\t\t\tif (!(n instanceof L.MarkerCluster) && n._icon) {\n\t\t\t\t\t\tn.clusterShow();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t//update the positions of the just added clusters/markers\n\t\t\t\tthis._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) {\n\t\t\t\t\tc._recursivelyRestoreChildPositions(newZoomLevel);\n\t\t\t\t});\n\n\t\t\t\tthis._ignoreMove = false;\n\n\t\t\t\t//Remove the old clusters and close the zoom animation\n\t\t\t\tthis._enqueue(function () {\n\t\t\t\t\t//update the positions of the just added clusters/markers\n\t\t\t\t\tthis._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) {\n\t\t\t\t\t\tfg.removeLayer(c);\n\t\t\t\t\t\tc.clusterShow();\n\t\t\t\t\t});\n\n\t\t\t\t\tthis._animationEnd();\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t_animationZoomOut: function (previousZoomLevel, newZoomLevel) {\n\t\t\t\tthis._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel);\n\n\t\t\t\t//Need to add markers for those that weren't on the map before but are now\n\t\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());\n\t\t\t\t//Remove markers that were on the map before but won't be now\n\t\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel, this._getExpandedVisibleBounds());\n\t\t\t},\n\n\t\t\t_animationAddLayer: function (layer, newCluster) {\n\t\t\t\tvar me = this,\n\t\t\t\t fg = this._featureGroup;\n\n\t\t\t\tfg.addLayer(layer);\n\t\t\t\tif (newCluster !== layer) {\n\t\t\t\t\tif (newCluster._childCount > 2) { //Was already a cluster\n\n\t\t\t\t\t\tnewCluster._updateIcon();\n\t\t\t\t\t\tthis._forceLayout();\n\t\t\t\t\t\tthis._animationStart();\n\n\t\t\t\t\t\tlayer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng()));\n\t\t\t\t\t\tlayer.clusterHide();\n\n\t\t\t\t\t\tthis._enqueue(function () {\n\t\t\t\t\t\t\tfg.removeLayer(layer);\n\t\t\t\t\t\t\tlayer.clusterShow();\n\n\t\t\t\t\t\t\tme._animationEnd();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t} else { //Just became a cluster\n\t\t\t\t\t\tthis._forceLayout();\n\n\t\t\t\t\t\tme._animationStart();\n\t\t\t\t\t\tme._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._zoom);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Private methods for animated versions.\n\t\t_animationZoomOutSingle: function (cluster, previousZoomLevel, newZoomLevel) {\n\t\t\tvar bounds = this._getExpandedVisibleBounds(),\n\t\t\t\tminZoom = Math.floor(this._map.getMinZoom());\n\n\t\t\t//Animate all of the markers in the clusters to move to their cluster center point\n\t\t\tcluster._recursivelyAnimateChildrenInAndAddSelfToMap(bounds, minZoom, previousZoomLevel + 1, newZoomLevel);\n\n\t\t\tvar me = this;\n\n\t\t\t//Update the opacity (If we immediately set it they won't animate)\n\t\t\tthis._forceLayout();\n\t\t\tcluster._recursivelyBecomeVisible(bounds, newZoomLevel);\n\n\t\t\t//TODO: Maybe use the transition timing stuff to make this more reliable\n\t\t\t//When the animations are done, tidy up\n\t\t\tthis._enqueue(function () {\n\n\t\t\t\t//This cluster stopped being a cluster before the timeout fired\n\t\t\t\tif (cluster._childCount === 1) {\n\t\t\t\t\tvar m = cluster._markers[0];\n\t\t\t\t\t//If we were in a cluster animation at the time then the opacity and position of our child could be wrong now, so fix it\n\t\t\t\t\tthis._ignoreMove = true;\n\t\t\t\t\tm.setLatLng(m.getLatLng());\n\t\t\t\t\tthis._ignoreMove = false;\n\t\t\t\t\tif (m.clusterShow) {\n\t\t\t\t\t\tm.clusterShow();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcluster._recursively(bounds, newZoomLevel, minZoom, function (c) {\n\t\t\t\t\t\tc._recursivelyRemoveChildrenFromMap(bounds, minZoom, previousZoomLevel + 1);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tme._animationEnd();\n\t\t\t});\n\t\t},\n\n\t\t_animationEnd: function () {\n\t\t\tif (this._map) {\n\t\t\t\tthis._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', '');\n\t\t\t}\n\t\t\tthis._inZoomAnimation--;\n\t\t\tthis.fire('animationend');\n\t\t},\n\n\t\t//Force a browser layout of stuff in the map\n\t\t// Should apply the current opacity and location to all elements so we can update them again for an animation\n\t\t_forceLayout: function () {\n\t\t\t//In my testing this works, infact offsetWidth of any element seems to work.\n\t\t\t//Could loop all this._layers and do this for each _icon if it stops working\n\n\t\t\tL.Util.falseFn(document.body.offsetWidth);\n\t\t}\n\t});\n\n\tL.markerClusterGroup = function (options) {\n\t\treturn new L.MarkerClusterGroup(options);\n\t};\n\n\tvar MarkerCluster = L.MarkerCluster = L.Marker.extend({\n\t\toptions: L.Icon.prototype.options,\n\n\t\tinitialize: function (group, zoom, a, b) {\n\n\t\t\tL.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0),\n\t { icon: this, pane: group.options.clusterPane });\n\n\t\t\tthis._group = group;\n\t\t\tthis._zoom = zoom;\n\n\t\t\tthis._markers = [];\n\t\t\tthis._childClusters = [];\n\t\t\tthis._childCount = 0;\n\t\t\tthis._iconNeedsUpdate = true;\n\t\t\tthis._boundsNeedUpdate = true;\n\n\t\t\tthis._bounds = new L.LatLngBounds();\n\n\t\t\tif (a) {\n\t\t\t\tthis._addChild(a);\n\t\t\t}\n\t\t\tif (b) {\n\t\t\t\tthis._addChild(b);\n\t\t\t}\n\t\t},\n\n\t\t//Recursively retrieve all child markers of this cluster\n\t\tgetAllChildMarkers: function (storageArray, ignoreDraggedMarker) {\n\t\t\tstorageArray = storageArray || [];\n\n\t\t\tfor (var i = this._childClusters.length - 1; i >= 0; i--) {\n\t\t\t\tthis._childClusters[i].getAllChildMarkers(storageArray, ignoreDraggedMarker);\n\t\t\t}\n\n\t\t\tfor (var j = this._markers.length - 1; j >= 0; j--) {\n\t\t\t\tif (ignoreDraggedMarker && this._markers[j].__dragStart) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tstorageArray.push(this._markers[j]);\n\t\t\t}\n\n\t\t\treturn storageArray;\n\t\t},\n\n\t\t//Returns the count of how many child markers we have\n\t\tgetChildCount: function () {\n\t\t\treturn this._childCount;\n\t\t},\n\n\t\t//Zoom to the minimum of showing all of the child markers, or the extents of this cluster\n\t\tzoomToBounds: function (fitBoundsOptions) {\n\t\t\tvar childClusters = this._childClusters.slice(),\n\t\t\t\tmap = this._group._map,\n\t\t\t\tboundsZoom = map.getBoundsZoom(this._bounds),\n\t\t\t\tzoom = this._zoom + 1,\n\t\t\t\tmapZoom = map.getZoom(),\n\t\t\t\ti;\n\n\t\t\t//calculate how far we need to zoom down to see all of the markers\n\t\t\twhile (childClusters.length > 0 && boundsZoom > zoom) {\n\t\t\t\tzoom++;\n\t\t\t\tvar newClusters = [];\n\t\t\t\tfor (i = 0; i < childClusters.length; i++) {\n\t\t\t\t\tnewClusters = newClusters.concat(childClusters[i]._childClusters);\n\t\t\t\t}\n\t\t\t\tchildClusters = newClusters;\n\t\t\t}\n\n\t\t\tif (boundsZoom > zoom) {\n\t\t\t\tthis._group._map.setView(this._latlng, zoom);\n\t\t\t} else if (boundsZoom <= mapZoom) { //If fitBounds wouldn't zoom us down, zoom us down instead\n\t\t\t\tthis._group._map.setView(this._latlng, mapZoom + 1);\n\t\t\t} else {\n\t\t\t\tthis._group._map.fitBounds(this._bounds, fitBoundsOptions);\n\t\t\t}\n\t\t},\n\n\t\tgetBounds: function () {\n\t\t\tvar bounds = new L.LatLngBounds();\n\t\t\tbounds.extend(this._bounds);\n\t\t\treturn bounds;\n\t\t},\n\n\t\t_updateIcon: function () {\n\t\t\tthis._iconNeedsUpdate = true;\n\t\t\tif (this._icon) {\n\t\t\t\tthis.setIcon(this);\n\t\t\t}\n\t\t},\n\n\t\t//Cludge for Icon, we pretend to be an icon for performance\n\t\tcreateIcon: function () {\n\t\t\tif (this._iconNeedsUpdate) {\n\t\t\t\tthis._iconObj = this._group.options.iconCreateFunction(this);\n\t\t\t\tthis._iconNeedsUpdate = false;\n\t\t\t}\n\t\t\treturn this._iconObj.createIcon();\n\t\t},\n\t\tcreateShadow: function () {\n\t\t\treturn this._iconObj.createShadow();\n\t\t},\n\n\n\t\t_addChild: function (new1, isNotificationFromChild) {\n\n\t\t\tthis._iconNeedsUpdate = true;\n\n\t\t\tthis._boundsNeedUpdate = true;\n\t\t\tthis._setClusterCenter(new1);\n\n\t\t\tif (new1 instanceof L.MarkerCluster) {\n\t\t\t\tif (!isNotificationFromChild) {\n\t\t\t\t\tthis._childClusters.push(new1);\n\t\t\t\t\tnew1.__parent = this;\n\t\t\t\t}\n\t\t\t\tthis._childCount += new1._childCount;\n\t\t\t} else {\n\t\t\t\tif (!isNotificationFromChild) {\n\t\t\t\t\tthis._markers.push(new1);\n\t\t\t\t}\n\t\t\t\tthis._childCount++;\n\t\t\t}\n\n\t\t\tif (this.__parent) {\n\t\t\t\tthis.__parent._addChild(new1, true);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position.\n\t\t * @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet.\n\t\t * @private\n\t\t */\n\t\t_setClusterCenter: function (child) {\n\t\t\tif (!this._cLatLng) {\n\t\t\t\t// when clustering, take position of the first point as the cluster center\n\t\t\t\tthis._cLatLng = child._cLatLng || child._latlng;\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Assigns impossible bounding values so that the next extend entirely determines the new bounds.\n\t\t * This method avoids having to trash the previous L.LatLngBounds object and to create a new one, which is much slower for this class.\n\t\t * As long as the bounds are not extended, most other methods would probably fail, as they would with bounds initialized but not extended.\n\t\t * @private\n\t\t */\n\t\t_resetBounds: function () {\n\t\t\tvar bounds = this._bounds;\n\n\t\t\tif (bounds._southWest) {\n\t\t\t\tbounds._southWest.lat = Infinity;\n\t\t\t\tbounds._southWest.lng = Infinity;\n\t\t\t}\n\t\t\tif (bounds._northEast) {\n\t\t\t\tbounds._northEast.lat = -Infinity;\n\t\t\t\tbounds._northEast.lng = -Infinity;\n\t\t\t}\n\t\t},\n\n\t\t_recalculateBounds: function () {\n\t\t\tvar markers = this._markers,\n\t\t\t childClusters = this._childClusters,\n\t\t\t latSum = 0,\n\t\t\t lngSum = 0,\n\t\t\t totalCount = this._childCount,\n\t\t\t i, child, childLatLng, childCount;\n\n\t\t\t// Case where all markers are removed from the map and we are left with just an empty _topClusterLevel.\n\t\t\tif (totalCount === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Reset rather than creating a new object, for performance.\n\t\t\tthis._resetBounds();\n\n\t\t\t// Child markers.\n\t\t\tfor (i = 0; i < markers.length; i++) {\n\t\t\t\tchildLatLng = markers[i]._latlng;\n\n\t\t\t\tthis._bounds.extend(childLatLng);\n\n\t\t\t\tlatSum += childLatLng.lat;\n\t\t\t\tlngSum += childLatLng.lng;\n\t\t\t}\n\n\t\t\t// Child clusters.\n\t\t\tfor (i = 0; i < childClusters.length; i++) {\n\t\t\t\tchild = childClusters[i];\n\n\t\t\t\t// Re-compute child bounds and weighted position first if necessary.\n\t\t\t\tif (child._boundsNeedUpdate) {\n\t\t\t\t\tchild._recalculateBounds();\n\t\t\t\t}\n\n\t\t\t\tthis._bounds.extend(child._bounds);\n\n\t\t\t\tchildLatLng = child._wLatLng;\n\t\t\t\tchildCount = child._childCount;\n\n\t\t\t\tlatSum += childLatLng.lat * childCount;\n\t\t\t\tlngSum += childLatLng.lng * childCount;\n\t\t\t}\n\n\t\t\tthis._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount);\n\n\t\t\t// Reset dirty flag.\n\t\t\tthis._boundsNeedUpdate = false;\n\t\t},\n\n\t\t//Set our markers position as given and add it to the map\n\t\t_addToMap: function (startPos) {\n\t\t\tif (startPos) {\n\t\t\t\tthis._backupLatlng = this._latlng;\n\t\t\t\tthis.setLatLng(startPos);\n\t\t\t}\n\t\t\tthis._group._featureGroup.addLayer(this);\n\t\t},\n\n\t\t_recursivelyAnimateChildrenIn: function (bounds, center, maxZoom) {\n\t\t\tthis._recursively(bounds, this._group._map.getMinZoom(), maxZoom - 1,\n\t\t\t\tfunction (c) {\n\t\t\t\t\tvar markers = c._markers,\n\t\t\t\t\t\ti, m;\n\t\t\t\t\tfor (i = markers.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tm = markers[i];\n\n\t\t\t\t\t\t//Only do it if the icon is still on the map\n\t\t\t\t\t\tif (m._icon) {\n\t\t\t\t\t\t\tm._setPos(center);\n\t\t\t\t\t\t\tm.clusterHide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tfunction (c) {\n\t\t\t\t\tvar childClusters = c._childClusters,\n\t\t\t\t\t\tj, cm;\n\t\t\t\t\tfor (j = childClusters.length - 1; j >= 0; j--) {\n\t\t\t\t\t\tcm = childClusters[j];\n\t\t\t\t\t\tif (cm._icon) {\n\t\t\t\t\t\t\tcm._setPos(center);\n\t\t\t\t\t\t\tcm.clusterHide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t},\n\n\t\t_recursivelyAnimateChildrenInAndAddSelfToMap: function (bounds, mapMinZoom, previousZoomLevel, newZoomLevel) {\n\t\t\tthis._recursively(bounds, newZoomLevel, mapMinZoom,\n\t\t\t\tfunction (c) {\n\t\t\t\t\tc._recursivelyAnimateChildrenIn(bounds, c._group._map.latLngToLayerPoint(c.getLatLng()).round(), previousZoomLevel);\n\n\t\t\t\t\t//TODO: depthToAnimateIn affects _isSingleParent, if there is a multizoom we may/may not be.\n\t\t\t\t\t//As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate\n\t\t\t\t\tif (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) {\n\t\t\t\t\t\tc.clusterShow();\n\t\t\t\t\t\tc._recursivelyRemoveChildrenFromMap(bounds, mapMinZoom, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds\n\t\t\t\t\t} else {\n\t\t\t\t\t\tc.clusterHide();\n\t\t\t\t\t}\n\n\t\t\t\t\tc._addToMap();\n\t\t\t\t}\n\t\t\t);\n\t\t},\n\n\t\t_recursivelyBecomeVisible: function (bounds, zoomLevel) {\n\t\t\tthis._recursively(bounds, this._group._map.getMinZoom(), zoomLevel, null, function (c) {\n\t\t\t\tc.clusterShow();\n\t\t\t});\n\t\t},\n\n\t\t_recursivelyAddChildrenToMap: function (startPos, zoomLevel, bounds) {\n\t\t\tthis._recursively(bounds, this._group._map.getMinZoom() - 1, zoomLevel,\n\t\t\t\tfunction (c) {\n\t\t\t\t\tif (zoomLevel === c._zoom) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t//Add our child markers at startPos (so they can be animated out)\n\t\t\t\t\tfor (var i = c._markers.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tvar nm = c._markers[i];\n\n\t\t\t\t\t\tif (!bounds.contains(nm._latlng)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (startPos) {\n\t\t\t\t\t\t\tnm._backupLatlng = nm.getLatLng();\n\n\t\t\t\t\t\t\tnm.setLatLng(startPos);\n\t\t\t\t\t\t\tif (nm.clusterHide) {\n\t\t\t\t\t\t\t\tnm.clusterHide();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tc._group._featureGroup.addLayer(nm);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tfunction (c) {\n\t\t\t\t\tc._addToMap(startPos);\n\t\t\t\t}\n\t\t\t);\n\t\t},\n\n\t\t_recursivelyRestoreChildPositions: function (zoomLevel) {\n\t\t\t//Fix positions of child markers\n\t\t\tfor (var i = this._markers.length - 1; i >= 0; i--) {\n\t\t\t\tvar nm = this._markers[i];\n\t\t\t\tif (nm._backupLatlng) {\n\t\t\t\t\tnm.setLatLng(nm._backupLatlng);\n\t\t\t\t\tdelete nm._backupLatlng;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (zoomLevel - 1 === this._zoom) {\n\t\t\t\t//Reposition child clusters\n\t\t\t\tfor (var j = this._childClusters.length - 1; j >= 0; j--) {\n\t\t\t\t\tthis._childClusters[j]._restorePosition();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (var k = this._childClusters.length - 1; k >= 0; k--) {\n\t\t\t\t\tthis._childClusters[k]._recursivelyRestoreChildPositions(zoomLevel);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_restorePosition: function () {\n\t\t\tif (this._backupLatlng) {\n\t\t\t\tthis.setLatLng(this._backupLatlng);\n\t\t\t\tdelete this._backupLatlng;\n\t\t\t}\n\t\t},\n\n\t\t//exceptBounds: If set, don't remove any markers/clusters in it\n\t\t_recursivelyRemoveChildrenFromMap: function (previousBounds, mapMinZoom, zoomLevel, exceptBounds) {\n\t\t\tvar m, i;\n\t\t\tthis._recursively(previousBounds, mapMinZoom - 1, zoomLevel - 1,\n\t\t\t\tfunction (c) {\n\t\t\t\t\t//Remove markers at every level\n\t\t\t\t\tfor (i = c._markers.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tm = c._markers[i];\n\t\t\t\t\t\tif (!exceptBounds || !exceptBounds.contains(m._latlng)) {\n\t\t\t\t\t\t\tc._group._featureGroup.removeLayer(m);\n\t\t\t\t\t\t\tif (m.clusterShow) {\n\t\t\t\t\t\t\t\tm.clusterShow();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tfunction (c) {\n\t\t\t\t\t//Remove child clusters at just the bottom level\n\t\t\t\t\tfor (i = c._childClusters.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tm = c._childClusters[i];\n\t\t\t\t\t\tif (!exceptBounds || !exceptBounds.contains(m._latlng)) {\n\t\t\t\t\t\t\tc._group._featureGroup.removeLayer(m);\n\t\t\t\t\t\t\tif (m.clusterShow) {\n\t\t\t\t\t\t\t\tm.clusterShow();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t},\n\n\t\t//Run the given functions recursively to this and child clusters\n\t\t// boundsToApplyTo: a L.LatLngBounds representing the bounds of what clusters to recurse in to\n\t\t// zoomLevelToStart: zoom level to start running functions (inclusive)\n\t\t// zoomLevelToStop: zoom level to stop running functions (inclusive)\n\t\t// runAtEveryLevel: function that takes an L.MarkerCluster as an argument that should be applied on every level\n\t\t// runAtBottomLevel: function that takes an L.MarkerCluster as an argument that should be applied at only the bottom level\n\t\t_recursively: function (boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel) {\n\t\t\tvar childClusters = this._childClusters,\n\t\t\t zoom = this._zoom,\n\t\t\t i, c;\n\n\t\t\tif (zoomLevelToStart <= zoom) {\n\t\t\t\tif (runAtEveryLevel) {\n\t\t\t\t\trunAtEveryLevel(this);\n\t\t\t\t}\n\t\t\t\tif (runAtBottomLevel && zoom === zoomLevelToStop) {\n\t\t\t\t\trunAtBottomLevel(this);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (zoom < zoomLevelToStart || zoom < zoomLevelToStop) {\n\t\t\t\tfor (i = childClusters.length - 1; i >= 0; i--) {\n\t\t\t\t\tc = childClusters[i];\n\t\t\t\t\tif (c._boundsNeedUpdate) {\n\t\t\t\t\t\tc._recalculateBounds();\n\t\t\t\t\t}\n\t\t\t\t\tif (boundsToApplyTo.intersects(c._bounds)) {\n\t\t\t\t\t\tc._recursively(boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t//Returns true if we are the parent of only one cluster and that cluster is the same as us\n\t\t_isSingleParent: function () {\n\t\t\t//Don't need to check this._markers as the rest won't work if there are any\n\t\t\treturn this._childClusters.length > 0 && this._childClusters[0]._childCount === this._childCount;\n\t\t}\n\t});\n\n\t/*\n\t* Extends L.Marker to include two extra methods: clusterHide and clusterShow.\n\t* \n\t* They work as setOpacity(0) and setOpacity(1) respectively, but\n\t* don't overwrite the options.opacity\n\t* \n\t*/\n\n\tL.Marker.include({\n\t\tclusterHide: function () {\n\t\t\tvar backup = this.options.opacity;\n\t\t\tthis.setOpacity(0);\n\t\t\tthis.options.opacity = backup;\n\t\t\treturn this;\n\t\t},\n\t\t\n\t\tclusterShow: function () {\n\t\t\treturn this.setOpacity(this.options.opacity);\n\t\t}\n\t});\n\n\tL.DistanceGrid = function (cellSize) {\n\t\tthis._cellSize = cellSize;\n\t\tthis._sqCellSize = cellSize * cellSize;\n\t\tthis._grid = {};\n\t\tthis._objectPoint = { };\n\t};\n\n\tL.DistanceGrid.prototype = {\n\n\t\taddObject: function (obj, point) {\n\t\t\tvar x = this._getCoord(point.x),\n\t\t\t y = this._getCoord(point.y),\n\t\t\t grid = this._grid,\n\t\t\t row = grid[y] = grid[y] || {},\n\t\t\t cell = row[x] = row[x] || [],\n\t\t\t stamp = L.Util.stamp(obj);\n\n\t\t\tthis._objectPoint[stamp] = point;\n\n\t\t\tcell.push(obj);\n\t\t},\n\n\t\tupdateObject: function (obj, point) {\n\t\t\tthis.removeObject(obj);\n\t\t\tthis.addObject(obj, point);\n\t\t},\n\n\t\t//Returns true if the object was found\n\t\tremoveObject: function (obj, point) {\n\t\t\tvar x = this._getCoord(point.x),\n\t\t\t y = this._getCoord(point.y),\n\t\t\t grid = this._grid,\n\t\t\t row = grid[y] = grid[y] || {},\n\t\t\t cell = row[x] = row[x] || [],\n\t\t\t i, len;\n\n\t\t\tdelete this._objectPoint[L.Util.stamp(obj)];\n\n\t\t\tfor (i = 0, len = cell.length; i < len; i++) {\n\t\t\t\tif (cell[i] === obj) {\n\n\t\t\t\t\tcell.splice(i, 1);\n\n\t\t\t\t\tif (len === 1) {\n\t\t\t\t\t\tdelete row[x];\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t},\n\n\t\teachObject: function (fn, context) {\n\t\t\tvar i, j, k, len, row, cell, removed,\n\t\t\t grid = this._grid;\n\n\t\t\tfor (i in grid) {\n\t\t\t\trow = grid[i];\n\n\t\t\t\tfor (j in row) {\n\t\t\t\t\tcell = row[j];\n\n\t\t\t\t\tfor (k = 0, len = cell.length; k < len; k++) {\n\t\t\t\t\t\tremoved = fn.call(context, cell[k]);\n\t\t\t\t\t\tif (removed) {\n\t\t\t\t\t\t\tk--;\n\t\t\t\t\t\t\tlen--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgetNearObject: function (point) {\n\t\t\tvar x = this._getCoord(point.x),\n\t\t\t y = this._getCoord(point.y),\n\t\t\t i, j, k, row, cell, len, obj, dist,\n\t\t\t objectPoint = this._objectPoint,\n\t\t\t closestDistSq = this._sqCellSize,\n\t\t\t closest = null;\n\n\t\t\tfor (i = y - 1; i <= y + 1; i++) {\n\t\t\t\trow = this._grid[i];\n\t\t\t\tif (row) {\n\n\t\t\t\t\tfor (j = x - 1; j <= x + 1; j++) {\n\t\t\t\t\t\tcell = row[j];\n\t\t\t\t\t\tif (cell) {\n\n\t\t\t\t\t\t\tfor (k = 0, len = cell.length; k < len; k++) {\n\t\t\t\t\t\t\t\tobj = cell[k];\n\t\t\t\t\t\t\t\tdist = this._sqDist(objectPoint[L.Util.stamp(obj)], point);\n\t\t\t\t\t\t\t\tif (dist < closestDistSq ||\n\t\t\t\t\t\t\t\t\tdist <= closestDistSq && closest === null) {\n\t\t\t\t\t\t\t\t\tclosestDistSq = dist;\n\t\t\t\t\t\t\t\t\tclosest = obj;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn closest;\n\t\t},\n\n\t\t_getCoord: function (x) {\n\t\t\tvar coord = Math.floor(x / this._cellSize);\n\t\t\treturn isFinite(coord) ? coord : x;\n\t\t},\n\n\t\t_sqDist: function (p, p2) {\n\t\t\tvar dx = p2.x - p.x,\n\t\t\t dy = p2.y - p.y;\n\t\t\treturn dx * dx + dy * dy;\n\t\t}\n\t};\n\n\t/* Copyright (c) 2012 the authors listed at the following URL, and/or\n\tthe authors of referenced articles or incorporated external code:\n\thttp://en.literateprograms.org/Quickhull_(Javascript)?action=history&offset=20120410175256\n\n\tPermission is hereby granted, free of charge, to any person obtaining\n\ta copy of this software and associated documentation files (the\n\t\"Software\"), to deal in the Software without restriction, including\n\twithout limitation the rights to use, copy, modify, merge, publish,\n\tdistribute, sublicense, and/or sell copies of the Software, and to\n\tpermit persons to whom the Software is furnished to do so, subject to\n\tthe following conditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n\tMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n\tIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n\tCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n\tTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n\tSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\tRetrieved from: http://en.literateprograms.org/Quickhull_(Javascript)?oldid=18434\n\t*/\n\n\t(function () {\n\t\tL.QuickHull = {\n\n\t\t\t/*\n\t\t\t * @param {Object} cpt a point to be measured from the baseline\n\t\t\t * @param {Array} bl the baseline, as represented by a two-element\n\t\t\t * array of latlng objects.\n\t\t\t * @returns {Number} an approximate distance measure\n\t\t\t */\n\t\t\tgetDistant: function (cpt, bl) {\n\t\t\t\tvar vY = bl[1].lat - bl[0].lat,\n\t\t\t\t\tvX = bl[0].lng - bl[1].lng;\n\t\t\t\treturn (vX * (cpt.lat - bl[0].lat) + vY * (cpt.lng - bl[0].lng));\n\t\t\t},\n\n\t\t\t/*\n\t\t\t * @param {Array} baseLine a two-element array of latlng objects\n\t\t\t * representing the baseline to project from\n\t\t\t * @param {Array} latLngs an array of latlng objects\n\t\t\t * @returns {Object} the maximum point and all new points to stay\n\t\t\t * in consideration for the hull.\n\t\t\t */\n\t\t\tfindMostDistantPointFromBaseLine: function (baseLine, latLngs) {\n\t\t\t\tvar maxD = 0,\n\t\t\t\t\tmaxPt = null,\n\t\t\t\t\tnewPoints = [],\n\t\t\t\t\ti, pt, d;\n\n\t\t\t\tfor (i = latLngs.length - 1; i >= 0; i--) {\n\t\t\t\t\tpt = latLngs[i];\n\t\t\t\t\td = this.getDistant(pt, baseLine);\n\n\t\t\t\t\tif (d > 0) {\n\t\t\t\t\t\tnewPoints.push(pt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (d > maxD) {\n\t\t\t\t\t\tmaxD = d;\n\t\t\t\t\t\tmaxPt = pt;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn { maxPoint: maxPt, newPoints: newPoints };\n\t\t\t},\n\n\n\t\t\t/*\n\t\t\t * Given a baseline, compute the convex hull of latLngs as an array\n\t\t\t * of latLngs.\n\t\t\t *\n\t\t\t * @param {Array} latLngs\n\t\t\t * @returns {Array}\n\t\t\t */\n\t\t\tbuildConvexHull: function (baseLine, latLngs) {\n\t\t\t\tvar convexHullBaseLines = [],\n\t\t\t\t\tt = this.findMostDistantPointFromBaseLine(baseLine, latLngs);\n\n\t\t\t\tif (t.maxPoint) { // if there is still a point \"outside\" the base line\n\t\t\t\t\tconvexHullBaseLines =\n\t\t\t\t\t\tconvexHullBaseLines.concat(\n\t\t\t\t\t\t\tthis.buildConvexHull([baseLine[0], t.maxPoint], t.newPoints)\n\t\t\t\t\t\t);\n\t\t\t\t\tconvexHullBaseLines =\n\t\t\t\t\t\tconvexHullBaseLines.concat(\n\t\t\t\t\t\t\tthis.buildConvexHull([t.maxPoint, baseLine[1]], t.newPoints)\n\t\t\t\t\t\t);\n\t\t\t\t\treturn convexHullBaseLines;\n\t\t\t\t} else { // if there is no more point \"outside\" the base line, the current base line is part of the convex hull\n\t\t\t\t\treturn [baseLine[0]];\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/*\n\t\t\t * Given an array of latlngs, compute a convex hull as an array\n\t\t\t * of latlngs\n\t\t\t *\n\t\t\t * @param {Array} latLngs\n\t\t\t * @returns {Array}\n\t\t\t */\n\t\t\tgetConvexHull: function (latLngs) {\n\t\t\t\t// find first baseline\n\t\t\t\tvar maxLat = false, minLat = false,\n\t\t\t\t\tmaxLng = false, minLng = false,\n\t\t\t\t\tmaxLatPt = null, minLatPt = null,\n\t\t\t\t\tmaxLngPt = null, minLngPt = null,\n\t\t\t\t\tmaxPt = null, minPt = null,\n\t\t\t\t\ti;\n\n\t\t\t\tfor (i = latLngs.length - 1; i >= 0; i--) {\n\t\t\t\t\tvar pt = latLngs[i];\n\t\t\t\t\tif (maxLat === false || pt.lat > maxLat) {\n\t\t\t\t\t\tmaxLatPt = pt;\n\t\t\t\t\t\tmaxLat = pt.lat;\n\t\t\t\t\t}\n\t\t\t\t\tif (minLat === false || pt.lat < minLat) {\n\t\t\t\t\t\tminLatPt = pt;\n\t\t\t\t\t\tminLat = pt.lat;\n\t\t\t\t\t}\n\t\t\t\t\tif (maxLng === false || pt.lng > maxLng) {\n\t\t\t\t\t\tmaxLngPt = pt;\n\t\t\t\t\t\tmaxLng = pt.lng;\n\t\t\t\t\t}\n\t\t\t\t\tif (minLng === false || pt.lng < minLng) {\n\t\t\t\t\t\tminLngPt = pt;\n\t\t\t\t\t\tminLng = pt.lng;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (minLat !== maxLat) {\n\t\t\t\t\tminPt = minLatPt;\n\t\t\t\t\tmaxPt = maxLatPt;\n\t\t\t\t} else {\n\t\t\t\t\tminPt = minLngPt;\n\t\t\t\t\tmaxPt = maxLngPt;\n\t\t\t\t}\n\n\t\t\t\tvar ch = [].concat(this.buildConvexHull([minPt, maxPt], latLngs),\n\t\t\t\t\t\t\t\t\tthis.buildConvexHull([maxPt, minPt], latLngs));\n\t\t\t\treturn ch;\n\t\t\t}\n\t\t};\n\t}());\n\n\tL.MarkerCluster.include({\n\t\tgetConvexHull: function () {\n\t\t\tvar childMarkers = this.getAllChildMarkers(),\n\t\t\t\tpoints = [],\n\t\t\t\tp, i;\n\n\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\n\t\t\t\tp = childMarkers[i].getLatLng();\n\t\t\t\tpoints.push(p);\n\t\t\t}\n\n\t\t\treturn L.QuickHull.getConvexHull(points);\n\t\t}\n\t});\n\n\t//This code is 100% based on https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet\n\t//Huge thanks to jawj for implementing it first to make my job easy :-)\n\n\tL.MarkerCluster.include({\n\n\t\t_2PI: Math.PI * 2,\n\t\t_circleFootSeparation: 25, //related to circumference of circle\n\t\t_circleStartAngle: 0,\n\n\t\t_spiralFootSeparation: 28, //related to size of spiral (experiment!)\n\t\t_spiralLengthStart: 11,\n\t\t_spiralLengthFactor: 5,\n\n\t\t_circleSpiralSwitchover: 9, //show spiral instead of circle from this marker count upwards.\n\t\t\t\t\t\t\t\t\t// 0 -> always spiral; Infinity -> always circle\n\n\t\tspiderfy: function () {\n\t\t\tif (this._group._spiderfied === this || this._group._inZoomAnimation) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar childMarkers = this.getAllChildMarkers(null, true),\n\t\t\t\tgroup = this._group,\n\t\t\t\tmap = group._map,\n\t\t\t\tcenter = map.latLngToLayerPoint(this._latlng),\n\t\t\t\tpositions;\n\n\t\t\tthis._group._unspiderfy();\n\t\t\tthis._group._spiderfied = this;\n\n\t\t\t//TODO Maybe: childMarkers order by distance to center\n\n\t\t\tif (this._group.options.spiderfyShapePositions) {\n\t\t\t\tpositions = this._group.options.spiderfyShapePositions(childMarkers.length, center);\n\t\t\t} else if (childMarkers.length >= this._circleSpiralSwitchover) {\n\t\t\t\tpositions = this._generatePointsSpiral(childMarkers.length, center);\n\t\t\t} else {\n\t\t\t\tcenter.y += 10; // Otherwise circles look wrong => hack for standard blue icon, renders differently for other icons.\n\t\t\t\tpositions = this._generatePointsCircle(childMarkers.length, center);\n\t\t\t}\n\n\t\t\tthis._animationSpiderfy(childMarkers, positions);\n\t\t},\n\n\t\tunspiderfy: function (zoomDetails) {\n\t\t\t/// <param Name=\"zoomDetails\">Argument from zoomanim if being called in a zoom animation or null otherwise</param>\n\t\t\tif (this._group._inZoomAnimation) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._animationUnspiderfy(zoomDetails);\n\n\t\t\tthis._group._spiderfied = null;\n\t\t},\n\n\t\t_generatePointsCircle: function (count, centerPt) {\n\t\t\tvar circumference = this._group.options.spiderfyDistanceMultiplier * this._circleFootSeparation * (2 + count),\n\t\t\t\tlegLength = circumference / this._2PI, //radius from circumference\n\t\t\t\tangleStep = this._2PI / count,\n\t\t\t\tres = [],\n\t\t\t\ti, angle;\n\n\t\t\tlegLength = Math.max(legLength, 35); // Minimum distance to get outside the cluster icon.\n\n\t\t\tres.length = count;\n\n\t\t\tfor (i = 0; i < count; i++) { // Clockwise, like spiral.\n\t\t\t\tangle = this._circleStartAngle + i * angleStep;\n\t\t\t\tres[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();\n\t\t\t}\n\n\t\t\treturn res;\n\t\t},\n\n\t\t_generatePointsSpiral: function (count, centerPt) {\n\t\t\tvar spiderfyDistanceMultiplier = this._group.options.spiderfyDistanceMultiplier,\n\t\t\t\tlegLength = spiderfyDistanceMultiplier * this._spiralLengthStart,\n\t\t\t\tseparation = spiderfyDistanceMultiplier * this._spiralFootSeparation,\n\t\t\t\tlengthFactor = spiderfyDistanceMultiplier * this._spiralLengthFactor * this._2PI,\n\t\t\t\tangle = 0,\n\t\t\t\tres = [],\n\t\t\t\ti;\n\n\t\t\tres.length = count;\n\n\t\t\t// Higher index, closer position to cluster center.\n\t\t\tfor (i = count; i >= 0; i--) {\n\t\t\t\t// Skip the first position, so that we are already farther from center and we avoid\n\t\t\t\t// being under the default cluster icon (especially important for Circle Markers).\n\t\t\t\tif (i < count) {\n\t\t\t\t\tres[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();\n\t\t\t\t}\n\t\t\t\tangle += separation / legLength + i * 0.0005;\n\t\t\t\tlegLength += lengthFactor / angle;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\n\t\t_noanimationUnspiderfy: function () {\n\t\t\tvar group = this._group,\n\t\t\t\tmap = group._map,\n\t\t\t\tfg = group._featureGroup,\n\t\t\t\tchildMarkers = this.getAllChildMarkers(null, true),\n\t\t\t\tm, i;\n\n\t\t\tgroup._ignoreMove = true;\n\n\t\t\tthis.setOpacity(1);\n\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\n\t\t\t\tm = childMarkers[i];\n\n\t\t\t\tfg.removeLayer(m);\n\n\t\t\t\tif (m._preSpiderfyLatlng) {\n\t\t\t\t\tm.setLatLng(m._preSpiderfyLatlng);\n\t\t\t\t\tdelete m._preSpiderfyLatlng;\n\t\t\t\t}\n\t\t\t\tif (m.setZIndexOffset) {\n\t\t\t\t\tm.setZIndexOffset(0);\n\t\t\t\t}\n\n\t\t\t\tif (m._spiderLeg) {\n\t\t\t\t\tmap.removeLayer(m._spiderLeg);\n\t\t\t\t\tdelete m._spiderLeg;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgroup.fire('unspiderfied', {\n\t\t\t\tcluster: this,\n\t\t\t\tmarkers: childMarkers\n\t\t\t});\n\t\t\tgroup._ignoreMove = false;\n\t\t\tgroup._spiderfied = null;\n\t\t}\n\t});\n\n\t//Non Animated versions of everything\n\tL.MarkerClusterNonAnimated = L.MarkerCluster.extend({\n\t\t_animationSpiderfy: function (childMarkers, positions) {\n\t\t\tvar group = this._group,\n\t\t\t\tmap = group._map,\n\t\t\t\tfg = group._featureGroup,\n\t\t\t\tlegOptions = this._group.options.spiderLegPolylineOptions,\n\t\t\t\ti, m, leg, newPos;\n\n\t\t\tgroup._ignoreMove = true;\n\n\t\t\t// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.\n\t\t\t// The reverse order trick no longer improves performance on modern browsers.\n\t\t\tfor (i = 0; i < childMarkers.length; i++) {\n\t\t\t\tnewPos = map.layerPointToLatLng(positions[i]);\n\t\t\t\tm = childMarkers[i];\n\n\t\t\t\t// Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.\n\t\t\t\tleg = new L.Polyline([this._latlng, newPos], legOptions);\n\t\t\t\tmap.addLayer(leg);\n\t\t\t\tm._spiderLeg = leg;\n\n\t\t\t\t// Now add the marker.\n\t\t\t\tm._preSpiderfyLatlng = m._latlng;\n\t\t\t\tm.setLatLng(newPos);\n\t\t\t\tif (m.setZIndexOffset) {\n\t\t\t\t\tm.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING\n\t\t\t\t}\n\n\t\t\t\tfg.addLayer(m);\n\t\t\t}\n\t\t\tthis.setOpacity(0.3);\n\n\t\t\tgroup._ignoreMove = false;\n\t\t\tgroup.fire('spiderfied', {\n\t\t\t\tcluster: this,\n\t\t\t\tmarkers: childMarkers\n\t\t\t});\n\t\t},\n\n\t\t_animationUnspiderfy: function () {\n\t\t\tthis._noanimationUnspiderfy();\n\t\t}\n\t});\n\n\t//Animated versions here\n\tL.MarkerCluster.include({\n\n\t\t_animationSpiderfy: function (childMarkers, positions) {\n\t\t\tvar me = this,\n\t\t\t\tgroup = this._group,\n\t\t\t\tmap = group._map,\n\t\t\t\tfg = group._featureGroup,\n\t\t\t\tthisLayerLatLng = this._latlng,\n\t\t\t\tthisLayerPos = map.latLngToLayerPoint(thisLayerLatLng),\n\t\t\t\tsvg = L.Path.SVG,\n\t\t\t\tlegOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation.\n\t\t\t\tfinalLegOpacity = legOptions.opacity,\n\t\t\t\ti, m, leg, legPath, legLength, newPos;\n\n\t\t\tif (finalLegOpacity === undefined) {\n\t\t\t\tfinalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity;\n\t\t\t}\n\n\t\t\tif (svg) {\n\t\t\t\t// If the initial opacity of the spider leg is not 0 then it appears before the animation starts.\n\t\t\t\tlegOptions.opacity = 0;\n\n\t\t\t\t// Add the class for CSS transitions.\n\t\t\t\tlegOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg';\n\t\t\t} else {\n\t\t\t\t// Make sure we have a defined opacity.\n\t\t\t\tlegOptions.opacity = finalLegOpacity;\n\t\t\t}\n\n\t\t\tgroup._ignoreMove = true;\n\n\t\t\t// Add markers and spider legs to map, hidden at our center point.\n\t\t\t// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.\n\t\t\t// The reverse order trick no longer improves performance on modern browsers.\n\t\t\tfor (i = 0; i < childMarkers.length; i++) {\n\t\t\t\tm = childMarkers[i];\n\n\t\t\t\tnewPos = map.layerPointToLatLng(positions[i]);\n\n\t\t\t\t// Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.\n\t\t\t\tleg = new L.Polyline([thisLayerLatLng, newPos], legOptions);\n\t\t\t\tmap.addLayer(leg);\n\t\t\t\tm._spiderLeg = leg;\n\n\t\t\t\t// Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/\n\t\t\t\t// In our case the transition property is declared in the CSS file.\n\t\t\t\tif (svg) {\n\t\t\t\t\tlegPath = leg._path;\n\t\t\t\t\tlegLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox.\n\t\t\t\t\tlegPath.style.strokeDasharray = legLength; // Just 1 length is enough, it will be duplicated.\n\t\t\t\t\tlegPath.style.strokeDashoffset = legLength;\n\t\t\t\t}\n\n\t\t\t\t// If it is a marker, add it now and we'll animate it out\n\t\t\t\tif (m.setZIndexOffset) {\n\t\t\t\t\tm.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING\n\t\t\t\t}\n\t\t\t\tif (m.clusterHide) {\n\t\t\t\t\tm.clusterHide();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Vectors just get immediately added\n\t\t\t\tfg.addLayer(m);\n\n\t\t\t\tif (m._setPos) {\n\t\t\t\t\tm._setPos(thisLayerPos);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgroup._forceLayout();\n\t\t\tgroup._animationStart();\n\n\t\t\t// Reveal markers and spider legs.\n\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\n\t\t\t\tnewPos = map.layerPointToLatLng(positions[i]);\n\t\t\t\tm = childMarkers[i];\n\n\t\t\t\t//Move marker to new position\n\t\t\t\tm._preSpiderfyLatlng = m._latlng;\n\t\t\t\tm.setLatLng(newPos);\n\t\t\t\t\n\t\t\t\tif (m.clusterShow) {\n\t\t\t\t\tm.clusterShow();\n\t\t\t\t}\n\n\t\t\t\t// Animate leg (animation is actually delegated to CSS transition).\n\t\t\t\tif (svg) {\n\t\t\t\t\tleg = m._spiderLeg;\n\t\t\t\t\tlegPath = leg._path;\n\t\t\t\t\tlegPath.style.strokeDashoffset = 0;\n\t\t\t\t\t//legPath.style.strokeOpacity = finalLegOpacity;\n\t\t\t\t\tleg.setStyle({opacity: finalLegOpacity});\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.setOpacity(0.3);\n\n\t\t\tgroup._ignoreMove = false;\n\n\t\t\tsetTimeout(function () {\n\t\t\t\tgroup._animationEnd();\n\t\t\t\tgroup.fire('spiderfied', {\n\t\t\t\t\tcluster: me,\n\t\t\t\t\tmarkers: childMarkers\n\t\t\t\t});\n\t\t\t}, 200);\n\t\t},\n\n\t\t_animationUnspiderfy: function (zoomDetails) {\n\t\t\tvar me = this,\n\t\t\t\tgroup = this._group,\n\t\t\t\tmap = group._map,\n\t\t\t\tfg = group._featureGroup,\n\t\t\t\tthisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng),\n\t\t\t\tchildMarkers = this.getAllChildMarkers(null, true),\n\t\t\t\tsvg = L.Path.SVG,\n\t\t\t\tm, i, leg, legPath, legLength, nonAnimatable;\n\n\t\t\tgroup._ignoreMove = true;\n\t\t\tgroup._animationStart();\n\n\t\t\t//Make us visible and bring the child markers back in\n\t\t\tthis.setOpacity(1);\n\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\n\t\t\t\tm = childMarkers[i];\n\n\t\t\t\t//Marker was added to us after we were spiderfied\n\t\t\t\tif (!m._preSpiderfyLatlng) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t//Close any popup on the marker first, otherwise setting the location of the marker will make the map scroll\n\t\t\t\tm.closePopup();\n\n\t\t\t\t//Fix up the location to the real one\n\t\t\t\tm.setLatLng(m._preSpiderfyLatlng);\n\t\t\t\tdelete m._preSpiderfyLatlng;\n\n\t\t\t\t//Hack override the location to be our center\n\t\t\t\tnonAnimatable = true;\n\t\t\t\tif (m._setPos) {\n\t\t\t\t\tm._setPos(thisLayerPos);\n\t\t\t\t\tnonAnimatable = false;\n\t\t\t\t}\n\t\t\t\tif (m.clusterHide) {\n\t\t\t\t\tm.clusterHide();\n\t\t\t\t\tnonAnimatable = false;\n\t\t\t\t}\n\t\t\t\tif (nonAnimatable) {\n\t\t\t\t\tfg.removeLayer(m);\n\t\t\t\t}\n\n\t\t\t\t// Animate the spider leg back in (animation is actually delegated to CSS transition).\n\t\t\t\tif (svg) {\n\t\t\t\t\tleg = m._spiderLeg;\n\t\t\t\t\tlegPath = leg._path;\n\t\t\t\t\tlegLength = legPath.getTotalLength() + 0.1;\n\t\t\t\t\tlegPath.style.strokeDashoffset = legLength;\n\t\t\t\t\tleg.setStyle({opacity: 0});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgroup._ignoreMove = false;\n\n\t\t\tsetTimeout(function () {\n\t\t\t\t//If we have only <= one child left then that marker will be shown on the map so don't remove it!\n\t\t\t\tvar stillThereChildCount = 0;\n\t\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\n\t\t\t\t\tm = childMarkers[i];\n\t\t\t\t\tif (m._spiderLeg) {\n\t\t\t\t\t\tstillThereChildCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\n\t\t\t\t\tm = childMarkers[i];\n\n\t\t\t\t\tif (!m._spiderLeg) { //Has already been unspiderfied\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m.clusterShow) {\n\t\t\t\t\t\tm.clusterShow();\n\t\t\t\t\t}\n\t\t\t\t\tif (m.setZIndexOffset) {\n\t\t\t\t\t\tm.setZIndexOffset(0);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (stillThereChildCount > 1) {\n\t\t\t\t\t\tfg.removeLayer(m);\n\t\t\t\t\t}\n\n\t\t\t\t\tmap.removeLayer(m._spiderLeg);\n\t\t\t\t\tdelete m._spiderLeg;\n\t\t\t\t}\n\t\t\t\tgroup._animationEnd();\n\t\t\t\tgroup.fire('unspiderfied', {\n\t\t\t\t\tcluster: me,\n\t\t\t\t\tmarkers: childMarkers\n\t\t\t\t});\n\t\t\t}, 200);\n\t\t}\n\t});\n\n\n\tL.MarkerClusterGroup.include({\n\t\t//The MarkerCluster currently spiderfied (if any)\n\t\t_spiderfied: null,\n\n\t\tunspiderfy: function () {\n\t\t\tthis._unspiderfy.apply(this, arguments);\n\t\t},\n\n\t\t_spiderfierOnAdd: function () {\n\t\t\tthis._map.on('click', this._unspiderfyWrapper, this);\n\n\t\t\tif (this._map.options.zoomAnimation) {\n\t\t\t\tthis._map.on('zoomstart', this._unspiderfyZoomStart, this);\n\t\t\t}\n\t\t\t//Browsers without zoomAnimation or a big zoom don't fire zoomstart\n\t\t\tthis._map.on('zoomend', this._noanimationUnspiderfy, this);\n\n\t\t\tif (!L.Browser.touch) {\n\t\t\t\tthis._map.getRenderer(this);\n\t\t\t\t//Needs to happen in the pageload, not after, or animations don't work in webkit\n\t\t\t\t// http://stackoverflow.com/questions/8455200/svg-animate-with-dynamically-added-elements\n\t\t\t\t//Disable on touch browsers as the animation messes up on a touch zoom and isn't very noticable\n\t\t\t}\n\t\t},\n\n\t\t_spiderfierOnRemove: function () {\n\t\t\tthis._map.off('click', this._unspiderfyWrapper, this);\n\t\t\tthis._map.off('zoomstart', this._unspiderfyZoomStart, this);\n\t\t\tthis._map.off('zoomanim', this._unspiderfyZoomAnim, this);\n\t\t\tthis._map.off('zoomend', this._noanimationUnspiderfy, this);\n\n\t\t\t//Ensure that markers are back where they should be\n\t\t\t// Use no animation to avoid a sticky leaflet-cluster-anim class on mapPane\n\t\t\tthis._noanimationUnspiderfy();\n\t\t},\n\n\t\t//On zoom start we add a zoomanim handler so that we are guaranteed to be last (after markers are animated)\n\t\t//This means we can define the animation they do rather than Markers doing an animation to their actual location\n\t\t_unspiderfyZoomStart: function () {\n\t\t\tif (!this._map) { //May have been removed from the map by a zoomEnd handler\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._map.on('zoomanim', this._unspiderfyZoomAnim, this);\n\t\t},\n\n\t\t_unspiderfyZoomAnim: function (zoomDetails) {\n\t\t\t//Wait until the first zoomanim after the user has finished touch-zooming before running the animation\n\t\t\tif (L.DomUtil.hasClass(this._map._mapPane, 'leaflet-touching')) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._map.off('zoomanim', this._unspiderfyZoomAnim, this);\n\t\t\tthis._unspiderfy(zoomDetails);\n\t\t},\n\n\t\t_unspiderfyWrapper: function () {\n\t\t\t/// <summary>_unspiderfy but passes no arguments</summary>\n\t\t\tthis._unspiderfy();\n\t\t},\n\n\t\t_unspiderfy: function (zoomDetails) {\n\t\t\tif (this._spiderfied) {\n\t\t\t\tthis._spiderfied.unspiderfy(zoomDetails);\n\t\t\t}\n\t\t},\n\n\t\t_noanimationUnspiderfy: function () {\n\t\t\tif (this._spiderfied) {\n\t\t\t\tthis._spiderfied._noanimationUnspiderfy();\n\t\t\t}\n\t\t},\n\n\t\t//If the given layer is currently being spiderfied then we unspiderfy it so it isn't on the map anymore etc\n\t\t_unspiderfyLayer: function (layer) {\n\t\t\tif (layer._spiderLeg) {\n\t\t\t\tthis._featureGroup.removeLayer(layer);\n\n\t\t\t\tif (layer.clusterShow) {\n\t\t\t\t\tlayer.clusterShow();\n\t\t\t\t}\n\t\t\t\t\t//Position will be fixed up immediately in _animationUnspiderfy\n\t\t\t\tif (layer.setZIndexOffset) {\n\t\t\t\t\tlayer.setZIndexOffset(0);\n\t\t\t\t}\n\n\t\t\t\tthis._map.removeLayer(layer._spiderLeg);\n\t\t\t\tdelete layer._spiderLeg;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Adds 1 public method to MCG and 1 to L.Marker to facilitate changing\n\t * markers' icon options and refreshing their icon and their parent clusters\n\t * accordingly (case where their iconCreateFunction uses data of childMarkers\n\t * to make up the cluster icon).\n\t */\n\n\n\tL.MarkerClusterGroup.include({\n\t\t/**\n\t\t * Updates the icon of all clusters which are parents of the given marker(s).\n\t\t * In singleMarkerMode, also updates the given marker(s) icon.\n\t\t * @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)|\n\t\t * L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent\n\t\t * clusters need to be updated. If not provided, retrieves all child markers of this.\n\t\t * @returns {L.MarkerClusterGroup}\n\t\t */\n\t\trefreshClusters: function (layers) {\n\t\t\tif (!layers) {\n\t\t\t\tlayers = this._topClusterLevel.getAllChildMarkers();\n\t\t\t} else if (layers instanceof L.MarkerClusterGroup) {\n\t\t\t\tlayers = layers._topClusterLevel.getAllChildMarkers();\n\t\t\t} else if (layers instanceof L.LayerGroup) {\n\t\t\t\tlayers = layers._layers;\n\t\t\t} else if (layers instanceof L.MarkerCluster) {\n\t\t\t\tlayers = layers.getAllChildMarkers();\n\t\t\t} else if (layers instanceof L.Marker) {\n\t\t\t\tlayers = [layers];\n\t\t\t} // else: must be an Array(L.Marker)|Map(L.Marker)\n\t\t\tthis._flagParentsIconsNeedUpdate(layers);\n\t\t\tthis._refreshClustersIcons();\n\n\t\t\t// In case of singleMarkerMode, also re-draw the markers.\n\t\t\tif (this.options.singleMarkerMode) {\n\t\t\t\tthis._refreshSingleMarkerModeMarkers(layers);\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Simply flags all parent clusters of the given markers as having a \"dirty\" icon.\n\t\t * @param layers Array(L.Marker)|Map(L.Marker) list of markers.\n\t\t * @private\n\t\t */\n\t\t_flagParentsIconsNeedUpdate: function (layers) {\n\t\t\tvar id, parent;\n\n\t\t\t// Assumes layers is an Array or an Object whose prototype is non-enumerable.\n\t\t\tfor (id in layers) {\n\t\t\t\t// Flag parent clusters' icon as \"dirty\", all the way up.\n\t\t\t\t// Dumb process that flags multiple times upper parents, but still\n\t\t\t\t// much more efficient than trying to be smart and make short lists,\n\t\t\t\t// at least in the case of a hierarchy following a power law:\n\t\t\t\t// http://jsperf.com/flag-nodes-in-power-hierarchy/2\n\t\t\t\tparent = layers[id].__parent;\n\t\t\t\twhile (parent) {\n\t\t\t\t\tparent._iconNeedsUpdate = true;\n\t\t\t\t\tparent = parent.__parent;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Re-draws the icon of the supplied markers.\n\t\t * To be used in singleMarkerMode only.\n\t\t * @param layers Array(L.Marker)|Map(L.Marker) list of markers.\n\t\t * @private\n\t\t */\n\t\t_refreshSingleMarkerModeMarkers: function (layers) {\n\t\t\tvar id, layer;\n\n\t\t\tfor (id in layers) {\n\t\t\t\tlayer = layers[id];\n\n\t\t\t\t// Make sure we do not override markers that do not belong to THIS group.\n\t\t\t\tif (this.hasLayer(layer)) {\n\t\t\t\t\t// Need to re-create the icon first, then re-draw the marker.\n\t\t\t\t\tlayer.setIcon(this._overrideMarkerIcon(layer));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tL.Marker.include({\n\t\t/**\n\t\t * Updates the given options in the marker's icon and refreshes the marker.\n\t\t * @param options map object of icon options.\n\t\t * @param directlyRefreshClusters boolean (optional) true to trigger\n\t\t * MCG.refreshClustersOf() right away with this single marker.\n\t\t * @returns {L.Marker}\n\t\t */\n\t\trefreshIconOptions: function (options, directlyRefreshClusters) {\n\t\t\tvar icon = this.options.icon;\n\n\t\t\tL.setOptions(icon, options);\n\n\t\t\tthis.setIcon(icon);\n\n\t\t\t// Shortcut to refresh the associated MCG clusters right away.\n\t\t\t// To be used when refreshing a single marker.\n\t\t\t// Otherwise, better use MCG.refreshClusters() once at the end with\n\t\t\t// the list of modified markers.\n\t\t\tif (directlyRefreshClusters && this.__parent) {\n\t\t\t\tthis.__parent._group.refreshClusters(this);\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t});\n\n\texports.MarkerClusterGroup = MarkerClusterGroup;\n\texports.MarkerCluster = MarkerCluster;\n\n\tObject.defineProperty(exports, '__esModule', { value: true });\n\n}));\n//# sourceMappingURL=leaflet.markercluster-src.js.map\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.js?\n}");
172
+
173
+ /***/ }),
174
+
175
+ /***/ "./node_modules/react-dom/cjs/react-dom.development.js":
176
+ /*!*************************************************************!*\
177
+ !*** ./node_modules/react-dom/cjs/react-dom.development.js ***!
178
+ \*************************************************************/
179
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
180
+
181
+ "use strict";
182
+ eval("{/**\n * @license React\n * react-dom.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\n true &&\n (function () {\n function noop() {}\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function createPortal$1(children, containerInfo, implementation) {\n var key =\n 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;\n try {\n testStringCoercion(key);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n JSCompiler_inline_result &&\n (console.error(\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n key[Symbol.toStringTag]) ||\n key.constructor.name ||\n \"Object\"\n ),\n testStringCoercion(key));\n return {\n $$typeof: REACT_PORTAL_TYPE,\n key: null == key ? null : \"\" + key,\n children: children,\n containerInfo: containerInfo,\n implementation: implementation\n };\n }\n function getCrossOriginStringAs(as, input) {\n if (\"font\" === as) return \"\";\n if (\"string\" === typeof input)\n return \"use-credentials\" === input ? input : \"\";\n }\n function getValueDescriptorExpectingObjectForWarning(thing) {\n return null === thing\n ? \"`null`\"\n : void 0 === thing\n ? \"`undefined`\"\n : \"\" === thing\n ? \"an empty string\"\n : 'something with type \"' + typeof thing + '\"';\n }\n function getValueDescriptorExpectingEnumForWarning(thing) {\n return null === thing\n ? \"`null`\"\n : void 0 === thing\n ? \"`undefined`\"\n : \"\" === thing\n ? \"an empty string\"\n : \"string\" === typeof thing\n ? JSON.stringify(thing)\n : \"number\" === typeof thing\n ? \"`\" + thing + \"`\"\n : 'something with type \"' + typeof thing + '\"';\n }\n function resolveDispatcher() {\n var dispatcher = ReactSharedInternals.H;\n null === dispatcher &&\n console.error(\n \"Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\\n1. You might have mismatching versions of React and the renderer (such as React DOM)\\n2. You might be breaking the Rules of Hooks\\n3. You might have more than one copy of React in the same app\\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.\"\n );\n return dispatcher;\n }\n \"undefined\" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&\n \"function\" ===\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());\n var React = __webpack_require__(/*! react */ \"react\"),\n Internals = {\n d: {\n f: noop,\n r: function () {\n throw Error(\n \"Invalid form element. requestFormReset must be passed a form that was rendered by React.\"\n );\n },\n D: noop,\n C: noop,\n L: noop,\n m: noop,\n X: noop,\n S: noop,\n M: noop\n },\n p: 0,\n findDOMNode: null\n },\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n (\"function\" === typeof Map &&\n null != Map.prototype &&\n \"function\" === typeof Map.prototype.forEach &&\n \"function\" === typeof Set &&\n null != Set.prototype &&\n \"function\" === typeof Set.prototype.clear &&\n \"function\" === typeof Set.prototype.forEach) ||\n console.error(\n \"React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills\"\n );\n exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE =\n Internals;\n exports.createPortal = function (children, container) {\n var key =\n 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;\n if (\n !container ||\n (1 !== container.nodeType &&\n 9 !== container.nodeType &&\n 11 !== container.nodeType)\n )\n throw Error(\"Target container is not a DOM element.\");\n return createPortal$1(children, container, null, key);\n };\n exports.flushSync = function (fn) {\n var previousTransition = ReactSharedInternals.T,\n previousUpdatePriority = Internals.p;\n try {\n if (((ReactSharedInternals.T = null), (Internals.p = 2), fn))\n return fn();\n } finally {\n (ReactSharedInternals.T = previousTransition),\n (Internals.p = previousUpdatePriority),\n Internals.d.f() &&\n console.error(\n \"flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task.\"\n );\n }\n };\n exports.preconnect = function (href, options) {\n \"string\" === typeof href && href\n ? null != options && \"object\" !== typeof options\n ? console.error(\n \"ReactDOM.preconnect(): Expected the `options` argument (second) to be an object but encountered %s instead. The only supported option at this time is `crossOrigin` which accepts a string.\",\n getValueDescriptorExpectingEnumForWarning(options)\n )\n : null != options &&\n \"string\" !== typeof options.crossOrigin &&\n console.error(\n \"ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered %s instead. Try removing this option or passing a string value instead.\",\n getValueDescriptorExpectingObjectForWarning(options.crossOrigin)\n )\n : console.error(\n \"ReactDOM.preconnect(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.\",\n getValueDescriptorExpectingObjectForWarning(href)\n );\n \"string\" === typeof href &&\n (options\n ? ((options = options.crossOrigin),\n (options =\n \"string\" === typeof options\n ? \"use-credentials\" === options\n ? options\n : \"\"\n : void 0))\n : (options = null),\n Internals.d.C(href, options));\n };\n exports.prefetchDNS = function (href) {\n if (\"string\" !== typeof href || !href)\n console.error(\n \"ReactDOM.prefetchDNS(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.\",\n getValueDescriptorExpectingObjectForWarning(href)\n );\n else if (1 < arguments.length) {\n var options = arguments[1];\n \"object\" === typeof options && options.hasOwnProperty(\"crossOrigin\")\n ? console.error(\n \"ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.\",\n getValueDescriptorExpectingEnumForWarning(options)\n )\n : console.error(\n \"ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.\",\n getValueDescriptorExpectingEnumForWarning(options)\n );\n }\n \"string\" === typeof href && Internals.d.D(href);\n };\n exports.preinit = function (href, options) {\n \"string\" === typeof href && href\n ? null == options || \"object\" !== typeof options\n ? console.error(\n \"ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.\",\n getValueDescriptorExpectingEnumForWarning(options)\n )\n : \"style\" !== options.as &&\n \"script\" !== options.as &&\n console.error(\n 'ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are \"style\" and \"script\".',\n getValueDescriptorExpectingEnumForWarning(options.as)\n )\n : console.error(\n \"ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.\",\n getValueDescriptorExpectingObjectForWarning(href)\n );\n if (\n \"string\" === typeof href &&\n options &&\n \"string\" === typeof options.as\n ) {\n var as = options.as,\n crossOrigin = getCrossOriginStringAs(as, options.crossOrigin),\n integrity =\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n fetchPriority =\n \"string\" === typeof options.fetchPriority\n ? options.fetchPriority\n : void 0;\n \"style\" === as\n ? Internals.d.S(\n href,\n \"string\" === typeof options.precedence\n ? options.precedence\n : void 0,\n {\n crossOrigin: crossOrigin,\n integrity: integrity,\n fetchPriority: fetchPriority\n }\n )\n : \"script\" === as &&\n Internals.d.X(href, {\n crossOrigin: crossOrigin,\n integrity: integrity,\n fetchPriority: fetchPriority,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0\n });\n }\n };\n exports.preinitModule = function (href, options) {\n var encountered = \"\";\n (\"string\" === typeof href && href) ||\n (encountered +=\n \" The `href` argument encountered was \" +\n getValueDescriptorExpectingObjectForWarning(href) +\n \".\");\n void 0 !== options && \"object\" !== typeof options\n ? (encountered +=\n \" The `options` argument encountered was \" +\n getValueDescriptorExpectingObjectForWarning(options) +\n \".\")\n : options &&\n \"as\" in options &&\n \"script\" !== options.as &&\n (encountered +=\n \" The `as` option encountered was \" +\n getValueDescriptorExpectingEnumForWarning(options.as) +\n \".\");\n if (encountered)\n console.error(\n \"ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s\",\n encountered\n );\n else\n switch (\n ((encountered =\n options && \"string\" === typeof options.as ? options.as : \"script\"),\n encountered)\n ) {\n case \"script\":\n break;\n default:\n (encountered =\n getValueDescriptorExpectingEnumForWarning(encountered)),\n console.error(\n 'ReactDOM.preinitModule(): Currently the only supported \"as\" type for this function is \"script\" but received \"%s\" instead. This warning was generated for `href` \"%s\". In the future other module types will be supported, aligning with the import-attributes proposal. Learn more here: (https://github.com/tc39/proposal-import-attributes)',\n encountered,\n href\n );\n }\n if (\"string\" === typeof href)\n if (\"object\" === typeof options && null !== options) {\n if (null == options.as || \"script\" === options.as)\n (encountered = getCrossOriginStringAs(\n options.as,\n options.crossOrigin\n )),\n Internals.d.M(href, {\n crossOrigin: encountered,\n integrity:\n \"string\" === typeof options.integrity\n ? options.integrity\n : void 0,\n nonce:\n \"string\" === typeof options.nonce ? options.nonce : void 0\n });\n } else null == options && Internals.d.M(href);\n };\n exports.preload = function (href, options) {\n var encountered = \"\";\n (\"string\" === typeof href && href) ||\n (encountered +=\n \" The `href` argument encountered was \" +\n getValueDescriptorExpectingObjectForWarning(href) +\n \".\");\n null == options || \"object\" !== typeof options\n ? (encountered +=\n \" The `options` argument encountered was \" +\n getValueDescriptorExpectingObjectForWarning(options) +\n \".\")\n : (\"string\" === typeof options.as && options.as) ||\n (encountered +=\n \" The `as` option encountered was \" +\n getValueDescriptorExpectingObjectForWarning(options.as) +\n \".\");\n encountered &&\n console.error(\n 'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an `options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag.%s',\n encountered\n );\n if (\n \"string\" === typeof href &&\n \"object\" === typeof options &&\n null !== options &&\n \"string\" === typeof options.as\n ) {\n encountered = options.as;\n var crossOrigin = getCrossOriginStringAs(\n encountered,\n options.crossOrigin\n );\n Internals.d.L(href, encountered, {\n crossOrigin: crossOrigin,\n integrity:\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0,\n type: \"string\" === typeof options.type ? options.type : void 0,\n fetchPriority:\n \"string\" === typeof options.fetchPriority\n ? options.fetchPriority\n : void 0,\n referrerPolicy:\n \"string\" === typeof options.referrerPolicy\n ? options.referrerPolicy\n : void 0,\n imageSrcSet:\n \"string\" === typeof options.imageSrcSet\n ? options.imageSrcSet\n : void 0,\n imageSizes:\n \"string\" === typeof options.imageSizes\n ? options.imageSizes\n : void 0,\n media: \"string\" === typeof options.media ? options.media : void 0\n });\n }\n };\n exports.preloadModule = function (href, options) {\n var encountered = \"\";\n (\"string\" === typeof href && href) ||\n (encountered +=\n \" The `href` argument encountered was \" +\n getValueDescriptorExpectingObjectForWarning(href) +\n \".\");\n void 0 !== options && \"object\" !== typeof options\n ? (encountered +=\n \" The `options` argument encountered was \" +\n getValueDescriptorExpectingObjectForWarning(options) +\n \".\")\n : options &&\n \"as\" in options &&\n \"string\" !== typeof options.as &&\n (encountered +=\n \" The `as` option encountered was \" +\n getValueDescriptorExpectingObjectForWarning(options.as) +\n \".\");\n encountered &&\n console.error(\n 'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag.%s',\n encountered\n );\n \"string\" === typeof href &&\n (options\n ? ((encountered = getCrossOriginStringAs(\n options.as,\n options.crossOrigin\n )),\n Internals.d.m(href, {\n as:\n \"string\" === typeof options.as && \"script\" !== options.as\n ? options.as\n : void 0,\n crossOrigin: encountered,\n integrity:\n \"string\" === typeof options.integrity\n ? options.integrity\n : void 0\n }))\n : Internals.d.m(href));\n };\n exports.requestFormReset = function (form) {\n Internals.d.r(form);\n };\n exports.unstable_batchedUpdates = function (fn, a) {\n return fn(a);\n };\n exports.useFormState = function (action, initialState, permalink) {\n return resolveDispatcher().useFormState(action, initialState, permalink);\n };\n exports.useFormStatus = function () {\n return resolveDispatcher().useHostTransitionStatus();\n };\n exports.version = \"19.2.0\";\n \"undefined\" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&\n \"function\" ===\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());\n })();\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/react-dom/cjs/react-dom.development.js?\n}");
183
+
184
+ /***/ }),
185
+
186
+ /***/ "./node_modules/react-dom/index.js":
187
+ /*!*****************************************!*\
188
+ !*** ./node_modules/react-dom/index.js ***!
189
+ \*****************************************/
190
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
191
+
192
+ "use strict";
193
+ eval("{\n\nfunction checkDCE() {\n /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n if (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n ) {\n return;\n }\n if (true) {\n // This branch is unreachable because this function is only called\n // in production, but the condition is true only in development.\n // Therefore if the branch is still here, dead code elimination wasn't\n // properly applied.\n // Don't change the message. React DevTools relies on it. Also make sure\n // this message doesn't occur elsewhere in this function, or it will cause\n // a false positive.\n throw new Error('^_^');\n }\n // removed by dead control flow\n\n}\n\nif (false) // removed by dead control flow\n{} else {\n module.exports = __webpack_require__(/*! ./cjs/react-dom.development.js */ \"./node_modules/react-dom/cjs/react-dom.development.js\");\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/react-dom/index.js?\n}");
194
+
195
+ /***/ }),
196
+
197
+ /***/ "./node_modules/react-leaflet/lib/hooks.js":
198
+ /*!*************************************************!*\
199
+ !*** ./node_modules/react-leaflet/lib/hooks.js ***!
200
+ \*************************************************/
201
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
202
+
203
+ "use strict";
204
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useMap: () => (/* binding */ useMap),\n/* harmony export */ useMapEvent: () => (/* binding */ useMapEvent),\n/* harmony export */ useMapEvents: () => (/* binding */ useMapEvents)\n/* harmony export */ });\n/* harmony import */ var _react_leaflet_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @react-leaflet/core */ \"./node_modules/@react-leaflet/core/lib/context.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n\n\nfunction useMap() {\n return (0,_react_leaflet_core__WEBPACK_IMPORTED_MODULE_0__.useLeafletContext)().map;\n}\nfunction useMapEvent(type, handler) {\n const map = useMap();\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(function addMapEventHandler() {\n // @ts-ignore event type\n map.on(type, handler);\n return function removeMapEventHandler() {\n // @ts-ignore event type\n map.off(type, handler);\n };\n }, [\n map,\n type,\n handler\n ]);\n return map;\n}\nfunction useMapEvents(handlers) {\n const map = useMap();\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(function addMapEventHandlers() {\n map.on(handlers);\n return function removeMapEventHandlers() {\n map.off(handlers);\n };\n }, [\n map,\n handlers\n ]);\n return map;\n}\n\n\n//# sourceURL=webpack://ReactLeafletDeflate/./node_modules/react-leaflet/lib/hooks.js?\n}");
205
+
206
+ /***/ }),
207
+
208
+ /***/ "./src/Deflate.jsx":
209
+ /*!*************************!*\
210
+ !*** ./src/Deflate.jsx ***!
211
+ \*************************/
212
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
213
+
214
+ "use strict";
215
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react_leaflet_hooks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react-leaflet/hooks */ \"./node_modules/react-leaflet/lib/hooks.js\");\n/* harmony import */ var _react_leaflet_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @react-leaflet/core */ \"./node_modules/@react-leaflet/core/lib/element.js\");\n/* harmony import */ var _react_leaflet_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @react-leaflet/core */ \"./node_modules/@react-leaflet/core/lib/generic.js\");\n/* harmony import */ var _react_leaflet_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @react-leaflet/core */ \"./node_modules/@react-leaflet/core/lib/grid-layer.js\");\n/* harmony import */ var leaflet_markercluster__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! leaflet.markercluster */ \"./node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.js\");\n/* harmony import */ var leaflet_markercluster__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(leaflet_markercluster__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var Leaflet_Deflate__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! Leaflet.Deflate */ \"./node_modules/Leaflet.Deflate/dist/L.Deflate.js\");\n/* harmony import */ var Leaflet_Deflate__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(Leaflet_Deflate__WEBPACK_IMPORTED_MODULE_5__);\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\nvar initMapClasses = function initMapClasses() {\n var map = (0,react_leaflet_hooks__WEBPACK_IMPORTED_MODULE_0__.useMap)();\n var mapClassName = map.getContainer().className;\n var isAnimClassApplied = mapClassName.indexOf('leaflet-cluster-anim') !== -1;\n var isStyledClassApplied = mapClassName.indexOf('marker-cluster-styled') !== -1;\n var isAnimatedClassApplied = mapClassName.indexOf('marker-cluster-animated') !== -1;\n !isAnimClassApplied && (map.getContainer().className += ' leaflet-cluster-anim');\n !isStyledClassApplied && (map.getContainer().className += ' marker-cluster-styled');\n !isAnimatedClassApplied && (map.getContainer().className += ' marker-cluster-animated');\n};\nvar createDeflateLayer = function createDeflateLayer(props, context) {\n var markerCluster = props.markerCluster,\n data = props.data;\n // This will add our Leaflet.Deflate (this.leafletElement) to the map--something that must happen BEFORE\n // we can add anything to Leaflet.Deflate itself.\n\n var deflateProps = _objectSpread({}, props);\n if (markerCluster) {\n initMapClasses();\n var markerLayer = L.markerClusterGroup();\n deflateProps.markerLayer = markerLayer;\n }\n var layer = new L.Deflate(deflateProps);\n L.geoJSON(data, props).addTo(layer);\n return (0,_react_leaflet_core__WEBPACK_IMPORTED_MODULE_1__.createElementObject)(layer, context);\n};\nvar updateDeflateLayer = function updateDeflateLayer(layer, props, prevProps) {\n (0,_react_leaflet_core__WEBPACK_IMPORTED_MODULE_3__.updateGridLayer)(layer, props, prevProps);\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((0,_react_leaflet_core__WEBPACK_IMPORTED_MODULE_2__.createLayerComponent)(createDeflateLayer, updateDeflateLayer));\n\n//# sourceURL=webpack://ReactLeafletDeflate/./src/Deflate.jsx?\n}");
216
+
217
+ /***/ }),
218
+
219
+ /***/ "./src/index.jsx":
220
+ /*!***********************!*\
221
+ !*** ./src/index.jsx ***!
222
+ \***********************/
223
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
224
+
225
+ "use strict";
226
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _Deflate__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Deflate */ \"./src/Deflate.jsx\");\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_Deflate__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n\n//# sourceURL=webpack://ReactLeafletDeflate/./src/index.jsx?\n}");
227
+
228
+ /***/ }),
229
+
230
+ /***/ "react":
231
+ /*!************************************************************************!*\
232
+ !*** external {"commonjs":"react","commonjs2":"react","root":"React"} ***!
233
+ \************************************************************************/
234
+ /***/ ((module) => {
235
+
236
+ "use strict";
237
+ module.exports = __WEBPACK_EXTERNAL_MODULE_react__;
238
+
239
+ /***/ })
240
+
241
+ /******/ });
242
+ /************************************************************************/
243
+ /******/ // The module cache
244
+ /******/ var __webpack_module_cache__ = {};
245
+ /******/
246
+ /******/ // The require function
247
+ /******/ function __webpack_require__(moduleId) {
248
+ /******/ // Check if module is in cache
249
+ /******/ var cachedModule = __webpack_module_cache__[moduleId];
250
+ /******/ if (cachedModule !== undefined) {
251
+ /******/ return cachedModule.exports;
252
+ /******/ }
253
+ /******/ // Create a new module (and put it into the cache)
254
+ /******/ var module = __webpack_module_cache__[moduleId] = {
255
+ /******/ // no module.id needed
256
+ /******/ // no module.loaded needed
257
+ /******/ exports: {}
258
+ /******/ };
259
+ /******/
260
+ /******/ // Execute the module function
261
+ /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
262
+ /******/
263
+ /******/ // Return the exports of the module
264
+ /******/ return module.exports;
265
+ /******/ }
266
+ /******/
267
+ /************************************************************************/
268
+ /******/ /* webpack/runtime/compat get default export */
269
+ /******/ (() => {
270
+ /******/ // getDefaultExport function for compatibility with non-harmony modules
271
+ /******/ __webpack_require__.n = (module) => {
272
+ /******/ var getter = module && module.__esModule ?
273
+ /******/ () => (module['default']) :
274
+ /******/ () => (module);
275
+ /******/ __webpack_require__.d(getter, { a: getter });
276
+ /******/ return getter;
277
+ /******/ };
278
+ /******/ })();
279
+ /******/
280
+ /******/ /* webpack/runtime/define property getters */
281
+ /******/ (() => {
282
+ /******/ // define getter functions for harmony exports
283
+ /******/ __webpack_require__.d = (exports, definition) => {
284
+ /******/ for(var key in definition) {
285
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
286
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
287
+ /******/ }
288
+ /******/ }
289
+ /******/ };
290
+ /******/ })();
291
+ /******/
292
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
293
+ /******/ (() => {
294
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
295
+ /******/ })();
296
+ /******/
297
+ /******/ /* webpack/runtime/make namespace object */
298
+ /******/ (() => {
299
+ /******/ // define __esModule on exports
300
+ /******/ __webpack_require__.r = (exports) => {
301
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
302
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
303
+ /******/ }
304
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
305
+ /******/ };
306
+ /******/ })();
307
+ /******/
308
+ /************************************************************************/
309
+ /******/
310
+ /******/ // startup
311
+ /******/ // Load entry module and return exports
312
+ /******/ // This entry module can't be inlined because the eval devtool is used.
313
+ /******/ var __webpack_exports__ = __webpack_require__("./src/index.jsx");
314
+ /******/ __webpack_exports__ = __webpack_exports__["default"];
315
+ /******/
316
+ /******/ return __webpack_exports__;
317
+ /******/ })()
318
+ ;
319
+ });