diff --git a/LibreNMS/Util/Html.php b/LibreNMS/Util/Html.php new file mode 100644 index 0000000000..6a1399987c --- /dev/null +++ b/LibreNMS/Util/Html.php @@ -0,0 +1,98 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Util; + +use LibreNMS\Config; + +class Html +{ + /** + * Print or return a row of graphs + * + * @param array $graph_array + * @param bool $print + * @return array + */ + public static function graphRow($graph_array, $print = false) + { + if (session('widescreen')) { + if (!$graph_array['height']) { + $graph_array['height'] = '110'; + } + + if (!$graph_array['width']) { + $graph_array['width'] = '215'; + } + + $periods = Config::get('graphs.mini.widescreen'); + } else { + if (!$graph_array['height']) { + $graph_array['height'] = '100'; + } + + if (!$graph_array['width']) { + $graph_array['width'] = '215'; + } + + $periods = Config::get('graphs.mini.normal'); + } + + $screen_width = session('screen_width'); + if ($screen_width) { + if ($screen_width < 1024 && $screen_width > 700) { + $graph_array['width'] = round(($screen_width - 90) / 2, 0); + } elseif ($screen_width > 1024) { + $graph_array['width'] = round(($screen_width - 90) / count($periods) + 1, 0); + } else { + $graph_array['width'] = $screen_width - 70; + } + } + + $graph_array['height'] = round($graph_array['width'] / 2.15); + + $graph_data = []; + foreach ($periods as $period => $period_text) { + $graph_array['from'] = Config::get("time.$period"); + $graph_array_zoom = $graph_array; + $graph_array_zoom['height'] = '150'; + $graph_array_zoom['width'] = '400'; + + $link_array = $graph_array; + $link_array['page'] = 'graphs'; + unset($link_array['height'], $link_array['width']); + $link = Url::generate($link_array); + + $full_link = Url::overlibLink($link, Url::lazyGraphTag($graph_array), Url::graphTag($graph_array_zoom), null); + $graph_data[] = $full_link; + + if ($print) { + echo "
$full_link
"; + } + } + + return $graph_data; + } +} diff --git a/LibreNMS/Util/Url.php b/LibreNMS/Util/Url.php index 9cf2edbe98..d3b69cdfed 100644 --- a/LibreNMS/Util/Url.php +++ b/LibreNMS/Util/Url.php @@ -204,7 +204,23 @@ class Url $urlargs[] = $key . '=' . urlencode($arg); } - return ''; + return ''; + } + + public static function lazyGraphTag($args) + { + $urlargs = []; + + foreach ($args as $key => $arg) { + $urlargs[] = $key . "=" . urlencode($arg); + } + + + if (Config::get('enable_lazy_load', true)) { + return ''; + } + + return ''; } public static function overlibLink($url, $text, $contents, $class = null) diff --git a/app/ApiClients/GoogleMapsApi.php b/app/ApiClients/GoogleMapsApi.php index 45ba0ac894..e4cbdff027 100644 --- a/app/ApiClients/GoogleMapsApi.php +++ b/app/ApiClients/GoogleMapsApi.php @@ -92,6 +92,7 @@ class GoogleMapsApi extends BaseApi implements Geocoder * @param \Psr\Http\Message\ResponseInterface $response * @param array $data decoded response data * @return bool + * @throws Exception you may throw an Exception if validation fails */ protected function checkResponse($response, $data) { diff --git a/app/Http/Controllers/LocationController.php b/app/Http/Controllers/LocationController.php new file mode 100644 index 0000000000..461a11eeca --- /dev/null +++ b/app/Http/Controllers/LocationController.php @@ -0,0 +1,77 @@ + $maps_api, + 'maps_engine' => $maps_api ? Config::get('geoloc.engine') : '', + ]; + + + $data['graph_template'] = ''; + Config::set('enable_lazy_load', false); + $graph_array = [ + 'type' => 'location_bits', + 'height' => '100', + 'width' => '220', + 'legend' => 'no', + 'id' => '{{id}}', + ]; + foreach (Html::graphRow($graph_array) as $graph) { + $data['graph_template'] .= "
"; + $data['graph_template'] .= str_replace('%7B%7Bid%7D%7D', '{{id}}', $graph); // restore handlebars + $data['graph_template'] .= "
"; + } + + return view('locations', $data); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param Location $location + * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function update(Request $request, Location $location) + { + $this->authorize('admin', $request->user()); + + $this->validate($request, [ + 'lat' => 'required|numeric|max:90|min:-90', + 'lng' => 'required|numeric|max:180|min:-180', + ]); + + $location->fill($request->only(['lat', 'lng'])); + $location->save(); + + return response()->json(['status' => 'success']); + } + + /** + * Remove the specified resource from storage. + * + * @param Location $location + * @return \Illuminate\Http\Response + * @throws \Exception + */ + public function destroy(Request $request, Location $location) + { + $this->authorize('admin', $request->user()); + + $location->delete(); + + return response()->json(['status' => 'success']); + } +} diff --git a/app/Http/Controllers/PaginatedAjaxController.php b/app/Http/Controllers/PaginatedAjaxController.php index b813e176a3..9965017e33 100644 --- a/app/Http/Controllers/PaginatedAjaxController.php +++ b/app/Http/Controllers/PaginatedAjaxController.php @@ -69,6 +69,7 @@ abstract class PaginatedAjaxController extends Controller * * @param \Illuminate\Http\Request $request * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function searchFields($request) { diff --git a/app/Http/Controllers/Table/LocationController.php b/app/Http/Controllers/Table/LocationController.php new file mode 100644 index 0000000000..af9d457355 --- /dev/null +++ b/app/Http/Controllers/Table/LocationController.php @@ -0,0 +1,118 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace App\Http\Controllers\Table; + +use App\Models\Device; +use App\Models\Location; + +class LocationController extends TableController +{ + /** + * Defines search fields will be searched in order + * + * @param \Illuminate\Http\Request $request + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function searchFields($request) + { + return ['location', 'devices', 'down', 'network', 'servers', 'firewalls']; + } + + /** + * Defines the base query for this resource + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder + */ + public function baseQuery($request) + { + // joins are needed for device count sorts + $sort = $request->get('sort'); + $key = key($sort); + $join = $this->getJoinQuery($key); + + if ($join) { + return Location::hasAccess($request->user()) + ->select(['id', 'location', 'lat', 'lng', \DB::raw("COUNT(device_id) AS `$key`")]) + ->leftJoin('devices', $join) + ->groupBy(['id', 'location', 'lat', 'lng']); + } + + return Location::hasAccess($request->user()); + } + + /** + * @param Location $location + * @return array|\Illuminate\Database\Eloquent\Model|\Illuminate\Support\Collection + */ + public function formatItem($location) + { + return [ + 'id' => $location->id, + 'location' => $location->location, + 'lat' => $location->lat, + 'lng' => $location->lng, + 'down' => $location->devices()->isDown()->count(), + 'devices' => $location->devices()->count(), + 'network' => $location->devices()->where('type', 'network')->count(), + 'servers' => $location->devices()->where('type', 'server')->count(), + 'firewalls' => $location->devices()->where('type', 'firewall')->count(), + ]; + } + + private function getJoinQuery($field) + { + switch ($field) { + case 'devices': + return function ($query) { + $query->on('devices.location_id', 'locations.id'); + }; + case 'down': + return function ($query) { + $query->on('devices.location_id', 'locations.id'); + (new Device)->scopeIsDown($query); + }; + case 'network': + return function ($query) { + $query->on('devices.location_id', 'locations.id') + ->where('devices.type', 'network'); + }; + case 'servers': + return function ($query) { + $query->on('devices.location_id', 'locations.id') + ->where('devices.type', 'server'); + }; + case 'firewalls': + return function ($query) { + $query->on('devices.location_id', 'locations.id') + ->where('devices.type', 'firewall'); + }; + default: + return null; + } + } +} diff --git a/app/Http/Controllers/Table/TableController.php b/app/Http/Controllers/Table/TableController.php index 62bc04a804..731ae047c1 100644 --- a/app/Http/Controllers/Table/TableController.php +++ b/app/Http/Controllers/Table/TableController.php @@ -58,6 +58,10 @@ abstract class TableController extends PaginatedAjaxController $limit = $request->get('rowCount', 25); $page = $request->get('current', 1); + if ($limit < 0) { + $limit = $query->count(); + $page = null; + } $paginator = $query->paginate($limit, ['*'], 'page', $page); return $this->formatResponse($paginator); diff --git a/html/css/L.Control.Locate.min.css b/html/css/L.Control.Locate.min.css new file mode 100644 index 0000000000..567ced0ddb --- /dev/null +++ b/html/css/L.Control.Locate.min.css @@ -0,0 +1,2 @@ +.leaflet-control-locate a{font-size:1.4em;color:#444;cursor:pointer}.leaflet-control-locate.active a{color:#2074B6}.leaflet-control-locate.active.following a{color:#FC8428}.leafet-control-locate-location circle{animation:leaflet-control-locate-throb 4s ease infinite}@keyframes leaflet-control-locate-throb{0%{r:9;stroke-width:1}50%{r:7;stroke-width:3}100%{r:9;stroke-width:1}} +/*# sourceMappingURL=L.Control.Locate.min.css.map */ diff --git a/html/css/L.Control.Locate.min.css.map b/html/css/L.Control.Locate.min.css.map new file mode 100644 index 0000000000..bc6e5d491f --- /dev/null +++ b/html/css/L.Control.Locate.min.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAEE,yBAAE,CACA,SAAS,CAAE,KAAK,CAChB,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,OAAO,CAGf,gCAAE,CACA,KAAK,CAAE,OAAO,CAEhB,0CAAc,CACZ,KAAK,CAAE,OAAO,CAKpB,sCAAuC,CACrC,SAAS,CAAE,6CAA6C,CAG1D,uCAIC,CAHG,EAAG,CAAE,CAAC,CAAE,CAAC,CAAE,YAAY,CAAE,CAAC,CAC3B,GAAI,CAAE,CAAC,CAAE,CAAC,CAAE,YAAY,CAAE,CAAC,CAC5B,IAAK,CAAE,CAAC,CAAE,CAAC,CAAE,YAAY,CAAE,CAAC", +"sources": ["../src/L.Control.Locate.scss"], +"names": [], +"file": "L.Control.Locate.min.css" +} diff --git a/html/css/images/layers-2x.png b/html/css/images/layers-2x.png new file mode 100644 index 0000000000..200c333dca Binary files /dev/null and b/html/css/images/layers-2x.png differ diff --git a/html/css/images/layers.png b/html/css/images/layers.png new file mode 100644 index 0000000000..1a72e5784b Binary files /dev/null and b/html/css/images/layers.png differ diff --git a/html/css/images/marker-icon-2x.png b/html/css/images/marker-icon-2x.png new file mode 100644 index 0000000000..88f9e50188 Binary files /dev/null and b/html/css/images/marker-icon-2x.png differ diff --git a/html/css/images/marker-icon.png b/html/css/images/marker-icon.png new file mode 100644 index 0000000000..950edf2467 Binary files /dev/null and b/html/css/images/marker-icon.png differ diff --git a/html/css/images/marker-shadow.png b/html/css/images/marker-shadow.png new file mode 100644 index 0000000000..9fd2979532 Binary files /dev/null and b/html/css/images/marker-shadow.png differ diff --git a/html/css/leaflet.css b/html/css/leaflet.css index a13c778467..a0932d57ad 100644 --- a/html/css/leaflet.css +++ b/html/css/leaflet.css @@ -45,8 +45,10 @@ .leaflet-container .leaflet-marker-pane img, .leaflet-container .leaflet-shadow-pane img, .leaflet-container .leaflet-tile-pane img, -.leaflet-container img.leaflet-image-layer { +.leaflet-container img.leaflet-image-layer, +.leaflet-container .leaflet-tile { max-width: none !important; + max-height: none !important; } .leaflet-container.leaflet-touch-zoom { @@ -55,7 +57,10 @@ } .leaflet-container.leaflet-touch-drag { -ms-touch-action: pinch-zoom; - } + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} .leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { -ms-touch-action: none; touch-action: none; @@ -164,7 +169,6 @@ opacity: 0; -webkit-transition: opacity 0.2s linear; -moz-transition: opacity 0.2s linear; - -o-transition: opacity 0.2s linear; transition: opacity 0.2s linear; } .leaflet-fade-anim .leaflet-map-pane .leaflet-popup { @@ -181,14 +185,12 @@ .leaflet-zoom-anim .leaflet-zoom-animated { -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); - -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); transition: transform 0.25s cubic-bezier(0,0,0.25,1); } .leaflet-zoom-anim .leaflet-tile, .leaflet-pan-anim .leaflet-tile { -webkit-transition: none; -moz-transition: none; - -o-transition: none; transition: none; } @@ -205,6 +207,7 @@ .leaflet-grab { cursor: -webkit-grab; cursor: -moz-grab; + cursor: grab; } .leaflet-crosshair, .leaflet-crosshair .leaflet-interactive { @@ -220,6 +223,7 @@ cursor: move; cursor: -webkit-grabbing; cursor: -moz-grabbing; + cursor: grabbing; } /* marker & overlays interactivity */ @@ -490,7 +494,6 @@ -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); - -o-transform: rotate(45deg); transform: rotate(45deg); } .leaflet-popup-content-wrapper, diff --git a/html/css/styles.css b/html/css/styles.css index 628aa41c91..181ce1edcb 100644 --- a/html/css/styles.css +++ b/html/css/styles.css @@ -396,13 +396,14 @@ A.purple:visited, a.purple, .purple { color: #740074; } color: #cc0000; } -tr.device-overview:nth-child(odd) { - background: #ffffff; -} +.device-overview>.panel-body { padding-top: 0; padding-bottom: 0; } +.device-overview>.panel-body>.row:nth-child(odd) { background-color: #f9f9f9; } +.device-overview>.panel-body>.row:hover { background-color: #f5f5f5; } +.device-overview>.panel-body>.row>div { padding: 3px 5px; } +.device-overview>.panel-body>.row>div:first-child { font-weight: 500; } -tr.device-overview:nth-child(even) { - background: #eeeeee; -} +#coordinates-row { cursor: pointer; } +#location-map { padding: 15px; height: 400px; } a.list-device, a.list-device-ignored, a.list-device-down, a.list-device-ignored-up, a.list-device-disabled { font-weight: bold; diff --git a/html/includes/common/worldmap.inc.php b/html/includes/common/worldmap.inc.php index 5cd7673942..6fed0914e6 100644 --- a/html/includes/common/worldmap.inc.php +++ b/html/includes/common/worldmap.inc.php @@ -109,7 +109,7 @@ if ($config['map']['engine'] == 'leaflet') { } else { $temp_output = ' - +
'; +echo ''; $uptime = formatUptime($device['uptime']); $uptime_text = 'Uptime'; @@ -35,113 +39,140 @@ if ($device['features']) { $device['os_text'] = $config['os'][$device['os']]['text']; -echo ' - System Name - '.$device['sysName'].' - '; +echo '
+
System Name
+
'.$device['sysName'].'
+
'; if (!empty($device['ip'])) { - echo "Resolved IP{$device['ip']}"; + echo "
Resolved IP
{$device['ip']}
"; } elseif ($config['force_ip_to_sysname'] === true) { try { $ip = IP::parse($device['hostname']); - echo "IP Address$ip"; + echo "
IP Address
$ip
"; } catch (InvalidIpException $e) { // don't add an ip line } } if ($device['purpose']) { - echo ' - Description - '.display($device['purpose']).' - '; + echo '
+
Description
+
'.display($device['purpose']).'
+
'; } if ($device['hardware']) { - echo ' - Hardware - '.$device['hardware'].' - '; + echo '
+
Hardware
+
'.$device['hardware'].'
+
'; } -echo ' - Operating System - '.$device['os_text'].' '.$device['version'].' '.$device['features'].' - '; +echo '
+
Operating System
+
'.$device['os_text'].' '.$device['version'].' '.$device['features'].'
+
'; if ($device['serial']) { - echo ' - Serial - '.$device['serial'].' - '; + echo '
+
Serial
+
'.$device['serial'].'
+
'; } if ($device['sysObjectID']) { - echo ' - Object ID - '.$device['sysObjectID'].' - '; + echo '
+
Object ID
+
'.$device['sysObjectID'].'
+
'; } if ($device['sysContact']) { - echo ' - Contact'; + echo '
+
Contact
'; if (get_dev_attrib($device, 'override_sysContact_bool')) { echo ' - '.htmlspecialchars(get_dev_attrib($device, 'override_sysContact_string')).' - - - SNMP Contact'; +
'.htmlspecialchars(get_dev_attrib($device, 'override_sysContact_string')).'
+
+
+
SNMP Contact
'; } echo ' - '.htmlspecialchars($device['sysContact']).' - '; -} - -if ($device['location_id']) { - $location = \App\Models\Location::find($device['location_id']); - echo ' - Location - ' . $location->location . ' - '; - - if ($location->coordinatesValid()) { - echo ' - Lat / Lng - [' . $location->lat . ',' . $location->lng . '] - '; - } +
'.htmlspecialchars($device['sysContact']).'
+
'; } if ($uptime) { - echo " - $uptime_text - $uptime - "; -} - -echo ' - - - '; - -$perf_info = DevicePerf::where('device_id', $device['device_id'])->latest('timestamp')->first(); -$perf_debug = json_decode($perf_info['debug'], true); -if ($perf_debug['traceroute']) { echo "
-
-
-
-

Traceroute ({$perf_info['timestamp']})

-
-
-
{$perf_debug['traceroute']}
-
-
-
-
"; +
$uptime_text
+
$uptime
+ "; } -echo ''; +if ($device['location_id']) { + $maps_api = Config::get('geoloc.api_key'); + $maps_engine = $maps_api ? Config::get('geoloc.engine') : ''; + + $location = Location::find($device['location_id']); + $location_coords = $location->coordinatesValid() ? $location->lat . ', ' . $location->lng : 'N/A'; + + echo ' +
+
Location
+
' . $location->location . '
+
+
+
Lat / Lng
+
' . $location_coords . '
'; + + echo ''; + if ($location->coordinatesValid()) { + echo ' Map'; + } + echo '
+
+
+
+ + '; +} +?> + + + + diff --git a/html/includes/functions.inc.php b/html/includes/functions.inc.php index 222ddf530c..be273b1626 100644 --- a/html/includes/functions.inc.php +++ b/html/includes/functions.inc.php @@ -203,21 +203,10 @@ function generate_link($text, $vars, $new_vars = array()) }//end generate_link() -function generate_url($vars, $new_vars = array()) +function generate_url($vars, $new_vars = []) { - $vars = array_merge($vars, $new_vars); - - $url = $vars['page'] . '/'; - unset($vars['page']); - - foreach ($vars as $var => $value) { - if ($value == '0' || $value != '' && strstr($var, 'opt') === false && is_numeric($var) === false) { - $url .= $var . '=' . urlencode($value) . '/'; - } - } - - return ($url); -}//end generate_url() + return \LibreNMS\Util\Url::generate($vars, $new_vars); +} function escape_quotes($text) @@ -369,26 +358,8 @@ function generate_device_link($device, $text = null, $vars = array(), $start = 0 function overlib_link($url, $text, $contents, $class = null) { - global $config; - - $contents = "
" . $contents . '
'; - $contents = str_replace('"', "\'", $contents); - if ($class === null) { - $output = '"; - } - - $output .= $text . ''; - - return $output; -}//end overlib_link() + return \LibreNMS\Util\Url::overlibLink($url, $text, $contents, $class); +} function generate_graph_popup($graph_array) @@ -536,45 +507,13 @@ function print_graph_tag($args) function generate_graph_tag($args) { - $urlargs = array(); - foreach ($args as $key => $arg) { - $urlargs[] = $key . '=' . urlencode($arg); - } - - return ''; -}//end generate_graph_tag() + return \LibreNMS\Util\Url::graphTag($args); +} function generate_lazy_graph_tag($args) { - global $config; - $urlargs = array(); - $w = 0; - $h = 0; - foreach ($args as $key => $arg) { - switch (strtolower($key)) { - case 'width': - $w = $arg; - break; - case 'height': - $h = $arg; - break; - case 'lazy_w': - $lazy_w = $arg; - break; - } - $urlargs[] = $key . "=" . urlencode($arg); - } - - if (isset($lazy_w)) { - $w = $lazy_w; - } - - if ($config['enable_lazy_load'] === true) { - return ''; - } else { - return ''; - } -}//end generate_lazy_graph_tag() + return \LibreNMS\Util\Url::lazyGraphTag($args); +} function generate_dynamic_graph_tag($args) { diff --git a/html/includes/print-graphrow.inc.php b/html/includes/print-graphrow.inc.php index 800281ed0d..5013f9b226 100644 --- a/html/includes/print-graphrow.inc.php +++ b/html/includes/print-graphrow.inc.php @@ -1,63 +1,6 @@ 700) { - $graph_array['width'] = round(($_SESSION['screen_width'] - 90 )/2, 0); - } else { - if ($_SESSION['screen_width'] > 1024) { - $graph_array['width'] = round(($_SESSION['screen_width'] - 90 )/count($periods)+1, 0); - } else { - $graph_array['width'] = $_SESSION['screen_width'] - 70; - } - } -} - -$graph_array['height'] = round($graph_array['width'] /2.15); - -$graph_array['to'] = $config['time']['now']; - -$graph_data = array(); -foreach ($periods as $period => $period_tex) { - $graph_array['from'] = $config['time'][$period]; - $graph_array_zoom = $graph_array; - $graph_array_zoom['height'] = '150'; - $graph_array_zoom['width'] = '400'; - - $link_array = $graph_array; - $link_array['page'] = 'graphs'; - unset($link_array['height'], $link_array['width']); - $link = generate_url($link_array); - - if ($return_data === true) { - $graph_data[] = overlib_link($link, generate_lazy_graph_tag($graph_array), generate_graph_tag($graph_array_zoom), null); - } else { - echo "
"; - echo(overlib_link($link, generate_lazy_graph_tag($graph_array), generate_graph_tag($graph_array_zoom), null)); - echo "
"; - } -} unset($graph_array); diff --git a/html/js/L.Control.Locate.min.js b/html/js/L.Control.Locate.min.js new file mode 100644 index 0000000000..d8a3a41b75 --- /dev/null +++ b/html/js/L.Control.Locate.min.js @@ -0,0 +1,5 @@ +/*! Version: 0.65.1 +Copyright (c) 2016 Dominik Moritz */ + +!function(t,i){"function"==typeof define&&define.amd?define(["leaflet"],t):"object"==typeof exports&&(void 0!==i&&i.L?module.exports=t(L):module.exports=t(require("leaflet"))),void 0!==i&&i.L&&(i.L.Control.Locate=t(L))}(function(h){var o=function(i,o,t){(t=t.split(" ")).forEach(function(t){h.DomUtil[i].call(this,o,t)})},i=function(t,i){o("addClass",t,i)},s=function(t,i){o("removeClass",t,i)},t=h.Marker.extend({initialize:function(t,i){h.Util.setOptions(this,i),this._latlng=t,this.createIcon()},createIcon:function(){var t=this.options,i="";void 0!==t.color&&(i+="stroke:"+t.color+";"),void 0!==t.weight&&(i+="stroke-width:"+t.weight+";"),void 0!==t.fillColor&&(i+="fill:"+t.fillColor+";"),void 0!==t.fillOpacity&&(i+="fill-opacity:"+t.fillOpacity+";"),void 0!==t.opacity&&(i+="opacity:"+t.opacity+";");var o=this._getIconSVG(t,i);this._locationIcon=h.divIcon({className:o.className,html:o.svg,iconSize:[o.w,o.h]}),this.setIcon(this._locationIcon)},_getIconSVG:function(t,i){var o=t.radius,s=o+t.weight,e=2*s;return{className:"leafet-control-locate-location",svg:'',w:e,h:e}},setStyle:function(t){h.Util.setOptions(this,t),this.createIcon()}}),e=t.extend({initialize:function(t,i,o){h.Util.setOptions(this,o),this._latlng=t,this._heading=i,this.createIcon()},setHeading:function(t){this._heading=t},_getIconSVG:function(t,i){var o=t.radius,s=t.width+t.weight,e=2*(o+t.depth+t.weight),n="M0,0 l"+t.width/2+","+t.depth+" l-"+s+",0 z";return{className:"leafet-control-locate-heading",svg:'',w:s,h:e}}}),n=h.Control.extend({options:{position:"topleft",layer:void 0,setView:"untilPanOrZoom",keepCurrentZoomLevel:!1,getLocationBounds:function(t){return t.bounds},flyTo:!1,clickBehavior:{inView:"stop",outOfView:"setView"},returnToPrevBounds:!1,cacheLocation:!0,drawCircle:!0,drawMarker:!0,showCompass:!0,markerClass:t,compassClass:e,circleStyle:{className:"leaflet-control-locate-circle",color:"#136AEC",fillColor:"#136AEC",fillOpacity:.15,weight:0},markerStyle:{className:"leaflet-control-locate-marker",color:"#fff",fillColor:"#2A93EE",fillOpacity:1,weight:3,opacity:1,radius:9},compassStyle:{fillColor:"#2A93EE",fillOpacity:1,weight:0,color:"#fff",opacity:1,radius:9,width:9,depth:6},followCircleStyle:{},followMarkerStyle:{},followCompassStyle:{},icon:"fa fa-map-marker",iconLoading:"fa fa-spinner fa-spin",iconElementTag:"span",circlePadding:[0,0],metric:!0,createButtonCallback:function(t,i){var o=h.DomUtil.create("a","leaflet-bar-part leaflet-bar-part-single",t);return o.title=i.strings.title,{link:o,icon:h.DomUtil.create(i.iconElementTag,i.icon,o)}},onLocationError:function(t,i){alert(t.message)},onLocationOutsideMapBounds:function(t){t.stop(),alert(t.options.strings.outsideMapBoundsMsg)},showPopup:!0,strings:{title:"Show me where I am",metersUnit:"meters",feetUnit:"feet",popup:"You are within {distance} {unit} from this point",outsideMapBoundsMsg:"You seem located outside the boundaries of the map"},locateOptions:{maxZoom:1/0,watch:!0,setView:!1}},initialize:function(t){for(var i in t)"object"==typeof this.options[i]?h.extend(this.options[i],t[i]):this.options[i]=t[i];this.options.followMarkerStyle=h.extend({},this.options.markerStyle,this.options.followMarkerStyle),this.options.followCircleStyle=h.extend({},this.options.circleStyle,this.options.followCircleStyle),this.options.followCompassStyle=h.extend({},this.options.compassStyle,this.options.followCompassStyle)},onAdd:function(t){var i=h.DomUtil.create("div","leaflet-control-locate leaflet-bar leaflet-control");this._layer=this.options.layer||new h.LayerGroup,this._layer.addTo(t),this._event=void 0,this._compassHeading=null,this._prevBounds=null;var o=this.options.createButtonCallback(i,this.options);return this._link=o.link,this._icon=o.icon,h.DomEvent.on(this._link,"click",h.DomEvent.stopPropagation).on(this._link,"click",h.DomEvent.preventDefault).on(this._link,"click",this._onClick,this).on(this._link,"dblclick",h.DomEvent.stopPropagation),this._resetVariables(),this._map.on("unload",this._unload,this),i},_onClick:function(){if(this._justClicked=!0,this._userPanned=!1,this._userZoomed=!1,this._active&&!this._event)this.stop();else if(this._active&&void 0!==this._event){switch(this._map.getBounds().contains(this._event.latlng)?this.options.clickBehavior.inView:this.options.clickBehavior.outOfView){case"setView":this.setView();break;case"stop":if(this.stop(),this.options.returnToPrevBounds)(this.options.flyTo?this._map.flyToBounds:this._map.fitBounds).bind(this._map)(this._prevBounds)}}else this.options.returnToPrevBounds&&(this._prevBounds=this._map.getBounds()),this.start();this._updateContainerStyle()},start:function(){this._activate(),this._event&&(this._drawMarker(this._map),this.options.setView&&this.setView()),this._updateContainerStyle()},stop:function(){this._deactivate(),this._cleanClasses(),this._resetVariables(),this._removeMarker()},_activate:function(){this._active||(this._map.locate(this.options.locateOptions),this._active=!0,this._map.on("locationfound",this._onLocationFound,this),this._map.on("locationerror",this._onLocationError,this),this._map.on("dragstart",this._onDrag,this),this._map.on("zoomstart",this._onZoom,this),this._map.on("zoomend",this._onZoomEnd,this),this.options.showCompass&&("ondeviceorientationabsolute"in window?h.DomEvent.on(window,"deviceorientationabsolute",this._onDeviceOrientation,this):"ondeviceorientation"in window&&h.DomEvent.on(window,"deviceorientation",this._onDeviceOrientation,this)))},_deactivate:function(){this._map.stopLocate(),this._active=!1,this.options.cacheLocation||(this._event=void 0),this._map.off("locationfound",this._onLocationFound,this),this._map.off("locationerror",this._onLocationError,this),this._map.off("dragstart",this._onDrag,this),this._map.off("zoomstart",this._onZoom,this),this._map.off("zoomend",this._onZoomEnd,this),this.options.showCompass&&(this._compassHeading=null,"ondeviceorientationabsolute"in window?h.DomEvent.off(window,"deviceorientationabsolute",this._onDeviceOrientation,this):"ondeviceorientation"in window&&h.DomEvent.off(window,"deviceorientation",this._onDeviceOrientation,this))},setView:function(){if(this._drawMarker(),this._isOutsideMapBounds())this._event=void 0,this.options.onLocationOutsideMapBounds(this);else if(this.options.keepCurrentZoomLevel){(t=this.options.flyTo?this._map.flyTo:this._map.panTo).bind(this._map)([this._event.latitude,this._event.longitude])}else{var t=this.options.flyTo?this._map.flyToBounds:this._map.fitBounds;this._ignoreEvent=!0,t.bind(this._map)(this.options.getLocationBounds(this._event),{padding:this.options.circlePadding,maxZoom:this.options.locateOptions.maxZoom}),h.Util.requestAnimFrame(function(){this._ignoreEvent=!1},this)}},_drawCompass:function(){var t=this._event.latlng;if(this.options.showCompass&&t&&null!==this._compassHeading){var i=this._isFollowing()?this.options.followCompassStyle:this.options.compassStyle;this._compass?(this._compass.setLatLng(t),this._compass.setHeading(this._compassHeading),this._compass.setStyle&&this._compass.setStyle(i)):this._compass=new this.options.compassClass(t,this._compassHeading,i).addTo(this._layer)}!this._compass||this.options.showCompass&&null!==this._compassHeading||(this._compass.removeFrom(this._layer),this._compass=null)},_drawMarker:function(){void 0===this._event.accuracy&&(this._event.accuracy=0);var t,i,o=this._event.accuracy,s=this._event.latlng;if(this.options.drawCircle){var e=this._isFollowing()?this.options.followCircleStyle:this.options.circleStyle;this._circle?this._circle.setLatLng(s).setRadius(o).setStyle(e):this._circle=h.circle(s,o,e).addTo(this._layer)}if(i=this.options.metric?(t=o.toFixed(0),this.options.strings.metersUnit):(t=(3.2808399*o).toFixed(0),this.options.strings.feetUnit),this.options.drawMarker){var n=this._isFollowing()?this.options.followMarkerStyle:this.options.markerStyle;this._marker?(this._marker.setLatLng(s),this._marker.setStyle&&this._marker.setStyle(n)):this._marker=new this.options.markerClass(s,n).addTo(this._layer)}this._drawCompass();var a=this.options.strings.popup;this.options.showPopup&&a&&this._marker&&this._marker.bindPopup(h.Util.template(a,{distance:t,unit:i}))._popup.setLatLng(s),this.options.showPopup&&a&&this._compass&&this._compass.bindPopup(h.Util.template(a,{distance:t,unit:i}))._popup.setLatLng(s)},_removeMarker:function(){this._layer.clearLayers(),this._marker=void 0,this._circle=void 0},_unload:function(){this.stop(),this._map.off("unload",this._unload,this)},_setCompassHeading:function(t){!isNaN(parseFloat(t))&&isFinite(t)?(t=Math.round(t),this._compassHeading=t,h.Util.requestAnimFrame(this._drawCompass,this)):this._compassHeading=null},_onCompassNeedsCalibration:function(){this._setCompassHeading()},_onDeviceOrientation:function(t){this._active&&(t.webkitCompassHeading?this._setCompassHeading(t.webkitCompassHeading):t.absolute&&t.alpha&&this._setCompassHeading(360-t.alpha))},_onLocationError:function(t){3==t.code&&this.options.locateOptions.watch||(this.stop(),this.options.onLocationError(t,this))},_onLocationFound:function(t){if((!this._event||this._event.latlng.lat!==t.latlng.lat||this._event.latlng.lng!==t.latlng.lng||this._event.accuracy!==t.accuracy)&&this._active){switch(this._event=t,this._drawMarker(),this._updateContainerStyle(),this.options.setView){case"once":this._justClicked&&this.setView();break;case"untilPan":this._userPanned||this.setView();break;case"untilPanOrZoom":this._userPanned||this._userZoomed||this.setView();break;case"always":this.setView()}this._justClicked=!1}},_onDrag:function(){this._event&&!this._ignoreEvent&&(this._userPanned=!0,this._updateContainerStyle(),this._drawMarker())},_onZoom:function(){this._event&&!this._ignoreEvent&&(this._userZoomed=!0,this._updateContainerStyle(),this._drawMarker())},_onZoomEnd:function(){this._event&&this._drawCompass()},_isFollowing:function(){return!!this._active&&("always"===this.options.setView||("untilPan"===this.options.setView?!this._userPanned:"untilPanOrZoom"===this.options.setView?!this._userPanned&&!this._userZoomed:void 0))},_isOutsideMapBounds:function(){return void 0!==this._event&&(this._map.options.maxBounds&&!this._map.options.maxBounds.contains(this._event.latlng))},_updateContainerStyle:function(){this._container&&(this._active&&!this._event?this._setClasses("requesting"):this._isFollowing()?this._setClasses("following"):this._active?this._setClasses("active"):this._cleanClasses())},_setClasses:function(t){"requesting"==t?(s(this._container,"active following"),i(this._container,"requesting"),s(this._icon,this.options.icon),i(this._icon,this.options.iconLoading)):"active"==t?(s(this._container,"requesting following"),i(this._container,"active"),s(this._icon,this.options.iconLoading),i(this._icon,this.options.icon)):"following"==t&&(s(this._container,"requesting"),i(this._container,"active following"),s(this._icon,this.options.iconLoading),i(this._icon,this.options.icon))},_cleanClasses:function(){h.DomUtil.removeClass(this._container,"requesting"),h.DomUtil.removeClass(this._container,"active"),h.DomUtil.removeClass(this._container,"following"),s(this._icon,this.options.iconLoading),i(this._icon,this.options.icon)},_resetVariables:function(){this._active=!1,this._justClicked=!1,this._userPanned=!1,this._userZoomed=!1}});return h.control.locate=function(t){return new h.Control.Locate(t)},n},window); +//# sourceMappingURL=L.Control.Locate.min.js.map \ No newline at end of file diff --git a/html/js/L.Control.Locate.min.js.map b/html/js/L.Control.Locate.min.js.map new file mode 100644 index 0000000000..470b3d0e5d --- /dev/null +++ b/html/js/L.Control.Locate.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/L.Control.Locate.js"],"names":["factory","window","define","amd","exports","L","module","require","Control","Locate","LDomUtilApplyClassesMethod","method","element","classNames","split","forEach","className","DomUtil","call","this","addClasses","el","names","removeClasses","LocationMarker","Marker","extend","initialize","latlng","options","Util","setOptions","_latlng","createIcon","opt","style","undefined","color","weight","fillColor","fillOpacity","opacity","icon","_getIconSVG","_locationIcon","divIcon","html","svg","iconSize","w","h","setIcon","r","radius","s","s2","setStyle","CompassMarker","heading","_heading","setHeading","width","depth","path","LocateControl","position","layer","setView","keepCurrentZoomLevel","getLocationBounds","locationEvent","bounds","flyTo","clickBehavior","inView","outOfView","returnToPrevBounds","cacheLocation","drawCircle","drawMarker","showCompass","markerClass","compassClass","circleStyle","markerStyle","compassStyle","followCircleStyle","followMarkerStyle","followCompassStyle","iconLoading","iconElementTag","circlePadding","metric","createButtonCallback","container","link","create","title","strings","onLocationError","err","control","alert","message","onLocationOutsideMapBounds","stop","outsideMapBoundsMsg","showPopup","metersUnit","feetUnit","popup","locateOptions","maxZoom","Infinity","watch","i","onAdd","map","_layer","LayerGroup","addTo","_event","_compassHeading","_prevBounds","linkAndIcon","_link","_icon","DomEvent","on","stopPropagation","preventDefault","_onClick","_resetVariables","_map","_unload","_justClicked","_userPanned","_userZoomed","_active","getBounds","contains","flyToBounds","fitBounds","bind","f","start","_updateContainerStyle","_activate","_drawMarker","_deactivate","_cleanClasses","_removeMarker","locate","_onLocationFound","_onLocationError","_onDrag","_onZoom","_onZoomEnd","_onDeviceOrientation","stopLocate","off","_isOutsideMapBounds","panTo","latitude","longitude","_ignoreEvent","padding","requestAnimFrame","_drawCompass","cStyle","_isFollowing","_compass","setLatLng","removeFrom","accuracy","distance","unit","_circle","setRadius","circle","toFixed","mStyle","_marker","t","bindPopup","template","_popup","clearLayers","_setCompassHeading","angle","isNaN","parseFloat","isFinite","Math","round","_onCompassNeedsCalibration","e","webkitCompassHeading","absolute","alpha","code","lat","lng","maxBounds","_container","_setClasses","state","removeClass"],"mappings":";;;CAMC,SAAUA,EAASC,GAKM,mBAAXC,QAAyBA,OAAOC,IACvCD,OAAO,CAAC,WAAYF,GAGM,iBAAZI,eACQ,IAAXH,GAA0BA,EAAOI,EACxCC,OAAOF,QAAUJ,EAAQK,GAEzBC,OAAOF,QAAUJ,EAAQO,QAAQ,kBAKnB,IAAXN,GAA0BA,EAAOI,IACxCJ,EAAOI,EAAEG,QAAQC,OAAST,EAAQK,IAnB1C,CAqBG,SAAUA,GACT,IAAIK,EAA6B,SAASC,EAAQC,EAASC,IACvDA,EAAaA,EAAWC,MAAM,MACnBC,QAAQ,SAASC,GACxBX,EAAEY,QAAQN,GAAQO,KAAKC,KAAMP,EAASI,MAI1CI,EAAa,SAASC,EAAIC,GAASZ,EAA2B,WAAYW,EAAIC,IAC9EC,EAAgB,SAASF,EAAIC,GAASZ,EAA2B,cAAeW,EAAIC,IAKpFE,EAAiBnB,EAAEoB,OAAOC,OAAO,CACjCC,WAAY,SAAUC,EAAQC,GAC1BxB,EAAEyB,KAAKC,WAAWZ,KAAMU,GACxBV,KAAKa,QAAUJ,EACfT,KAAKc,cAMTA,WAAY,WACR,IAAIC,EAAMf,KAAKU,QAEXM,EAAQ,QAEMC,IAAdF,EAAIG,QACJF,GAAS,UAAUD,EAAIG,MAAM,UAEdD,IAAfF,EAAII,SACJH,GAAS,gBAAgBD,EAAII,OAAO,UAElBF,IAAlBF,EAAIK,YACJJ,GAAS,QAAQD,EAAIK,UAAU,UAEXH,IAApBF,EAAIM,cACJL,GAAS,gBAAgBD,EAAIM,YAAY,UAEzBJ,IAAhBF,EAAIO,UACJN,GAAS,WAAWD,EAAIO,QAAQ,KAGpC,IAAIC,EAAOvB,KAAKwB,YAAYT,EAAKC,GAEjChB,KAAKyB,cAAgBvC,EAAEwC,QAAQ,CAC3B7B,UAAW0B,EAAK1B,UAChB8B,KAAMJ,EAAKK,IACXC,SAAU,CAACN,EAAKO,EAAEP,EAAKQ,KAG3B/B,KAAKgC,QAAQhC,KAAKyB,gBAQtBD,YAAa,SAASd,EAASM,GAC3B,IAAIiB,EAAIvB,EAAQwB,OAEZC,EAAIF,EADAvB,EAAQS,OAEZiB,EAAS,EAAJD,EAIT,MAAO,CACHtC,UAAW,iCACX+B,IALM,kDAAkDQ,EAAG,aAAaA,EAAG,6BAA6BD,EAAE,KAAKA,EAAE,IAAIC,EAAG,IAAIA,EAAG,gBACrHH,EAAE,YAAYjB,EAAM,aAK9Bc,EAAGM,EACHL,EAAGK,IAIXC,SAAU,SAASrB,GACf9B,EAAEyB,KAAKC,WAAWZ,KAAMgB,GACxBhB,KAAKc,gBAITwB,EAAgBjC,EAAeE,OAAO,CACtCC,WAAY,SAAUC,EAAQ8B,EAAS7B,GACnCxB,EAAEyB,KAAKC,WAAWZ,KAAMU,GACxBV,KAAKa,QAAUJ,EACfT,KAAKwC,SAAWD,EAChBvC,KAAKc,cAGT2B,WAAY,SAASF,GACjBvC,KAAKwC,SAAWD,GAMpBf,YAAa,SAASd,EAASM,GAC3B,IAAIiB,EAAIvB,EAAQwB,OACZJ,EAAKpB,EAAQgC,MAAQhC,EAAQS,OAC7BY,EAAuC,GAAlCE,EAAEvB,EAAQiC,MAAQjC,EAAQS,QAC/ByB,EAAO,SAAUlC,EAAQgC,MAAM,EAAG,IAAIhC,EAAQiC,MAAM,MAAM,EAAI,OAKlE,MAAO,CACH9C,UAAW,gCACX+B,IALM,kDAAkD,EAAI,aAAaG,EAAE,6BAA8BD,EAAE,EAAG,MAAMA,EAAE,IAAIC,EAAE,aADjH,qBAAqB/B,KAAKwC,SAAS,QACmG,cACzII,EAAK,YAAY5B,EAAM,aAK/Bc,EAAGA,EACHC,EAAGA,MAMXc,EAAgB3D,EAAEG,QAAQkB,OAAO,CACjCG,QAAS,CAELoC,SAAU,UAEVC,WAAO9B,EAkBP+B,QAAS,iBAETC,sBAAsB,EAWtBC,kBAAmB,SAAUC,GACzB,OAAOA,EAAcC,QAGzBC,OAAO,EAQPC,cAAe,CAEXC,OAAQ,OAERC,UAAW,WAOfC,oBAAoB,EAKpBC,eAAe,EAEfC,YAAY,EAEZC,YAAY,EAEZC,aAAa,EAEbC,YAAazD,EAEb0D,aAAczB,EAEd0B,YAAa,CACTnE,UAAa,gCACbqB,MAAa,UACbE,UAAa,UACbC,YAAa,IACbF,OAAa,GAGjB8C,YAAa,CACTpE,UAAa,gCACbqB,MAAa,OACbE,UAAa,UACbC,YAAa,EACbF,OAAa,EACbG,QAAa,EACbY,OAAa,GAGjBgC,aAAc,CACV9C,UAAa,UACbC,YAAa,EACbF,OAAa,EACbD,MAAa,OACbI,QAAa,EACbY,OAAa,EACbQ,MAAa,EACbC,MAAa,GAMjBwB,kBAAmB,GACnBC,kBAAmB,GAInBC,mBAAoB,GAEpB9C,KAAM,mBACN+C,YAAa,wBAEbC,eAAgB,OAEhBC,cAAe,CAAC,EAAG,GAEnBC,QAAQ,EAMRC,qBAAsB,SAAUC,EAAWjE,GACvC,IAAIkE,EAAO1F,EAAEY,QAAQ+E,OAAO,IAAK,2CAA4CF,GAG7E,OAFAC,EAAKE,MAAQpE,EAAQqE,QAAQD,MAEtB,CAAEF,KAAMA,EAAMrD,KADVrC,EAAEY,QAAQ+E,OAAOnE,EAAQ6D,eAAgB7D,EAAQa,KAAMqD,KAItEI,gBAAiB,SAASC,EAAKC,GAC3BC,MAAMF,EAAIG,UAMdC,2BAA4B,SAASH,GACjCA,EAAQI,OACRH,MAAMD,EAAQxE,QAAQqE,QAAQQ,sBAGlCC,WAAW,EACXT,QAAS,CACLD,MAAO,qBACPW,WAAY,SACZC,SAAU,OACVC,MAAO,mDACPJ,oBAAqB,sDAGzBK,cAAe,CACXC,QAASC,EAAAA,EACTC,OAAO,EACP/C,SAAS,IAKjBxC,WAAY,SAAUE,GAElB,IAAK,IAAIsF,KAAKtF,EACqB,iBAApBV,KAAKU,QAAQsF,GACpB9G,EAAEqB,OAAOP,KAAKU,QAAQsF,GAAItF,EAAQsF,IAElChG,KAAKU,QAAQsF,GAAKtF,EAAQsF,GAKlChG,KAAKU,QAAQ0D,kBAAoBlF,EAAEqB,OAAO,GAAIP,KAAKU,QAAQuD,YAAajE,KAAKU,QAAQ0D,mBACrFpE,KAAKU,QAAQyD,kBAAoBjF,EAAEqB,OAAO,GAAIP,KAAKU,QAAQsD,YAAahE,KAAKU,QAAQyD,mBACrFnE,KAAKU,QAAQ2D,mBAAqBnF,EAAEqB,OAAO,GAAIP,KAAKU,QAAQwD,aAAclE,KAAKU,QAAQ2D,qBAM3F4B,MAAO,SAAUC,GACb,IAAIvB,EAAYzF,EAAEY,QAAQ+E,OAAO,MAC7B,sDAEJ7E,KAAKmG,OAASnG,KAAKU,QAAQqC,OAAS,IAAI7D,EAAEkH,WAC1CpG,KAAKmG,OAAOE,MAAMH,GAClBlG,KAAKsG,YAASrF,EACdjB,KAAKuG,gBAAkB,KACvBvG,KAAKwG,YAAc,KAEnB,IAAIC,EAAczG,KAAKU,QAAQgE,qBAAqBC,EAAW3E,KAAKU,SAcpE,OAbAV,KAAK0G,MAAQD,EAAY7B,KACzB5E,KAAK2G,MAAQF,EAAYlF,KAEzBrC,EAAE0H,SACGC,GAAG7G,KAAK0G,MAAO,QAASxH,EAAE0H,SAASE,iBACnCD,GAAG7G,KAAK0G,MAAO,QAASxH,EAAE0H,SAASG,gBACnCF,GAAG7G,KAAK0G,MAAO,QAAS1G,KAAKgH,SAAUhH,MACvC6G,GAAG7G,KAAK0G,MAAO,WAAYxH,EAAE0H,SAASE,iBAE3C9G,KAAKiH,kBAELjH,KAAKkH,KAAKL,GAAG,SAAU7G,KAAKmH,QAASnH,MAE9B2E,GAMXqC,SAAU,WAKN,GAJAhH,KAAKoH,cAAe,EACpBpH,KAAKqH,aAAc,EACnBrH,KAAKsH,aAAc,EAEftH,KAAKuH,UAAYvH,KAAKsG,OAEtBtG,KAAKsF,YACF,GAAItF,KAAKuH,cAA2BtG,IAAhBjB,KAAKsG,OAAsB,CAGlD,OAFetG,KAAKkH,KAAKM,YAAYC,SAASzH,KAAKsG,OAAO7F,QACtDT,KAAKU,QAAQ4C,cAAcC,OAASvD,KAAKU,QAAQ4C,cAAcE,WAE/D,IAAK,UACDxD,KAAKgD,UACL,MACJ,IAAK,OAED,GADAhD,KAAKsF,OACDtF,KAAKU,QAAQ+C,oBACLzD,KAAKU,QAAQ2C,MAAQrD,KAAKkH,KAAKQ,YAAc1H,KAAKkH,KAAKS,WAC7DC,KAAK5H,KAAKkH,KAAZW,CAAkB7H,KAAKwG,mBAK/BxG,KAAKU,QAAQ+C,qBACfzD,KAAKwG,YAAcxG,KAAKkH,KAAKM,aAE/BxH,KAAK8H,QAGT9H,KAAK+H,yBAQTD,MAAO,WACH9H,KAAKgI,YAEDhI,KAAKsG,SACLtG,KAAKiI,YAAYjI,KAAKkH,MAGlBlH,KAAKU,QAAQsC,SACbhD,KAAKgD,WAGbhD,KAAK+H,yBASTzC,KAAM,WACFtF,KAAKkI,cAELlI,KAAKmI,gBACLnI,KAAKiH,kBAELjH,KAAKoI,iBAYTJ,UAAW,WACFhI,KAAKuH,UACNvH,KAAKkH,KAAKmB,OAAOrI,KAAKU,QAAQkF,eAC9B5F,KAAKuH,SAAU,EAGfvH,KAAKkH,KAAKL,GAAG,gBAAiB7G,KAAKsI,iBAAkBtI,MACrDA,KAAKkH,KAAKL,GAAG,gBAAiB7G,KAAKuI,iBAAkBvI,MACrDA,KAAKkH,KAAKL,GAAG,YAAa7G,KAAKwI,QAASxI,MACxCA,KAAKkH,KAAKL,GAAG,YAAa7G,KAAKyI,QAASzI,MACxCA,KAAKkH,KAAKL,GAAG,UAAW7G,KAAK0I,WAAY1I,MACrCA,KAAKU,QAAQmD,cACT,gCAAiC/E,OACjCI,EAAE0H,SAASC,GAAG/H,OAAQ,4BAA6BkB,KAAK2I,qBAAsB3I,MACvE,wBAAyBlB,QAChCI,EAAE0H,SAASC,GAAG/H,OAAQ,oBAAqBkB,KAAK2I,qBAAsB3I,SAWtFkI,YAAa,WACTlI,KAAKkH,KAAK0B,aACV5I,KAAKuH,SAAU,EAEVvH,KAAKU,QAAQgD,gBACd1D,KAAKsG,YAASrF,GAIlBjB,KAAKkH,KAAK2B,IAAI,gBAAiB7I,KAAKsI,iBAAkBtI,MACtDA,KAAKkH,KAAK2B,IAAI,gBAAiB7I,KAAKuI,iBAAkBvI,MACtDA,KAAKkH,KAAK2B,IAAI,YAAa7I,KAAKwI,QAASxI,MACzCA,KAAKkH,KAAK2B,IAAI,YAAa7I,KAAKyI,QAASzI,MACzCA,KAAKkH,KAAK2B,IAAI,UAAW7I,KAAK0I,WAAY1I,MACtCA,KAAKU,QAAQmD,cACb7D,KAAKuG,gBAAkB,KACnB,gCAAiCzH,OACjCI,EAAE0H,SAASiC,IAAI/J,OAAQ,4BAA6BkB,KAAK2I,qBAAsB3I,MACxE,wBAAyBlB,QAChCI,EAAE0H,SAASiC,IAAI/J,OAAQ,oBAAqBkB,KAAK2I,qBAAsB3I,QAQnFgD,QAAS,WAEL,GADAhD,KAAKiI,cACDjI,KAAK8I,sBACL9I,KAAKsG,YAASrF,EACdjB,KAAKU,QAAQ2E,2BAA2BrF,WAExC,GAAIA,KAAKU,QAAQuC,qBAAsB,EAC/B4E,EAAI7H,KAAKU,QAAQ2C,MAAQrD,KAAKkH,KAAK7D,MAAQrD,KAAKkH,KAAK6B,OACvDnB,KAAK5H,KAAKkH,KAAZW,CAAkB,CAAC7H,KAAKsG,OAAO0C,SAAUhJ,KAAKsG,OAAO2C,gBAClD,CACH,IAAIpB,EAAI7H,KAAKU,QAAQ2C,MAAQrD,KAAKkH,KAAKQ,YAAc1H,KAAKkH,KAAKS,UAE/D3H,KAAKkJ,cAAe,EACpBrB,EAAED,KAAK5H,KAAKkH,KAAZW,CAAkB7H,KAAKU,QAAQwC,kBAAkBlD,KAAKsG,QAAS,CAC3D6C,QAASnJ,KAAKU,QAAQ8D,cACtBqB,QAAS7F,KAAKU,QAAQkF,cAAcC,UAExC3G,EAAEyB,KAAKyI,iBAAiB,WAEpBpJ,KAAKkJ,cAAe,GACrBlJ,QASfqJ,aAAc,WACV,IAAI5I,EAAST,KAAKsG,OAAO7F,OAEzB,GAAIT,KAAKU,QAAQmD,aAAepD,GAAmC,OAAzBT,KAAKuG,gBAA0B,CACrE,IAAI+C,EAAStJ,KAAKuJ,eAAiBvJ,KAAKU,QAAQ2D,mBAAqBrE,KAAKU,QAAQwD,aAC7ElE,KAAKwJ,UAGNxJ,KAAKwJ,SAASC,UAAUhJ,GACxBT,KAAKwJ,SAAS/G,WAAWzC,KAAKuG,iBAE1BvG,KAAKwJ,SAASnH,UACdrC,KAAKwJ,SAASnH,SAASiH,IAN3BtJ,KAAKwJ,SAAW,IAAIxJ,KAAKU,QAAQqD,aAAatD,EAAQT,KAAKuG,gBAAiB+C,GAAQjD,MAAMrG,KAAKmG,SAWnGnG,KAAKwJ,UAAcxJ,KAAKU,QAAQmD,aAAwC,OAAzB7D,KAAKuG,kBACpDvG,KAAKwJ,SAASE,WAAW1J,KAAKmG,QAC9BnG,KAAKwJ,SAAW,OASxBvB,YAAa,gBACoBhH,IAAzBjB,KAAKsG,OAAOqD,WACZ3J,KAAKsG,OAAOqD,SAAW,GAG3B,IAcIC,EAAUC,EAdV3H,EAASlC,KAAKsG,OAAOqD,SACrBlJ,EAAST,KAAKsG,OAAO7F,OAGzB,GAAIT,KAAKU,QAAQiD,WAAY,CACzB,IAAI3C,EAAQhB,KAAKuJ,eAAiBvJ,KAAKU,QAAQyD,kBAAoBnE,KAAKU,QAAQsD,YAE3EhE,KAAK8J,QAGN9J,KAAK8J,QAAQL,UAAUhJ,GAAQsJ,UAAU7H,GAAQG,SAASrB,GAF1DhB,KAAK8J,QAAU5K,EAAE8K,OAAOvJ,EAAQyB,EAAQlB,GAAOqF,MAAMrG,KAAKmG,QAgBlE,GAPI0D,EAFA7J,KAAKU,QAAQ+D,QACbmF,EAAW1H,EAAO+H,QAAQ,GAClBjK,KAAKU,QAAQqE,QAAQU,aAE7BmE,GAAqB,UAAT1H,GAAoB+H,QAAQ,GACjCjK,KAAKU,QAAQqE,QAAQW,UAI5B1F,KAAKU,QAAQkD,WAAY,CACzB,IAAIsG,EAASlK,KAAKuJ,eAAiBvJ,KAAKU,QAAQ0D,kBAAoBpE,KAAKU,QAAQuD,YAC5EjE,KAAKmK,SAGNnK,KAAKmK,QAAQV,UAAUhJ,GAEnBT,KAAKmK,QAAQ9H,UACbrC,KAAKmK,QAAQ9H,SAAS6H,IAL1BlK,KAAKmK,QAAU,IAAInK,KAAKU,QAAQoD,YAAYrD,EAAQyJ,GAAQ7D,MAAMrG,KAAKmG,QAU/EnG,KAAKqJ,eAEL,IAAIe,EAAIpK,KAAKU,QAAQqE,QAAQY,MACzB3F,KAAKU,QAAQ8E,WAAa4E,GAAKpK,KAAKmK,SACpCnK,KAAKmK,QACAE,UAAUnL,EAAEyB,KAAK2J,SAASF,EAAG,CAACR,SAAUA,EAAUC,KAAMA,KACxDU,OAAOd,UAAUhJ,GAEtBT,KAAKU,QAAQ8E,WAAa4E,GAAKpK,KAAKwJ,UACpCxJ,KAAKwJ,SACAa,UAAUnL,EAAEyB,KAAK2J,SAASF,EAAG,CAACR,SAAUA,EAAUC,KAAMA,KACxDU,OAAOd,UAAUhJ,IAO9B2H,cAAe,WACXpI,KAAKmG,OAAOqE,cACZxK,KAAKmK,aAAUlJ,EACfjB,KAAK8J,aAAU7I,GAOnBkG,QAAS,WACLnH,KAAKsF,OACLtF,KAAKkH,KAAK2B,IAAI,SAAU7I,KAAKmH,QAASnH,OAM1CyK,mBAAoB,SAASC,IACpBC,MAAMC,WAAWF,KAAWG,SAASH,IACtCA,EAAQI,KAAKC,MAAML,GAEnB1K,KAAKuG,gBAAkBmE,EACvBxL,EAAEyB,KAAKyI,iBAAiBpJ,KAAKqJ,aAAcrJ,OAE3CA,KAAKuG,gBAAkB,MAO/ByE,2BAA4B,WACxBhL,KAAKyK,sBAMT9B,qBAAsB,SAASsC,GACtBjL,KAAKuH,UAIN0D,EAAEC,qBAEFlL,KAAKyK,mBAAmBQ,EAAEC,sBACnBD,EAAEE,UAAYF,EAAEG,OAEvBpL,KAAKyK,mBAAmB,IAAMQ,EAAEG,SAOxC7C,iBAAkB,SAAStD,GAEP,GAAZA,EAAIoG,MAAarL,KAAKU,QAAQkF,cAAcG,QAIhD/F,KAAKsF,OACLtF,KAAKU,QAAQsE,gBAAgBC,EAAKjF,QAMtCsI,iBAAkB,SAAS2C,GAEvB,KAAIjL,KAAKsG,QACJtG,KAAKsG,OAAO7F,OAAO6K,MAAQL,EAAExK,OAAO6K,KACpCtL,KAAKsG,OAAO7F,OAAO8K,MAAQN,EAAExK,OAAO8K,KAChCvL,KAAKsG,OAAOqD,WAAasB,EAAEtB,WAI/B3J,KAAKuH,QAAV,CAUA,OALAvH,KAAKsG,OAAS2E,EAEdjL,KAAKiI,cACLjI,KAAK+H,wBAEG/H,KAAKU,QAAQsC,SACjB,IAAK,OACGhD,KAAKoH,cACLpH,KAAKgD,UAET,MACJ,IAAK,WACIhD,KAAKqH,aACNrH,KAAKgD,UAET,MACJ,IAAK,iBACIhD,KAAKqH,aAAgBrH,KAAKsH,aAC3BtH,KAAKgD,UAET,MACJ,IAAK,SACDhD,KAAKgD,UAObhD,KAAKoH,cAAe,IAMxBoB,QAAS,WAEDxI,KAAKsG,SAAWtG,KAAKkJ,eACrBlJ,KAAKqH,aAAc,EACnBrH,KAAK+H,wBACL/H,KAAKiI,gBAObQ,QAAS,WAEDzI,KAAKsG,SAAWtG,KAAKkJ,eACrBlJ,KAAKsH,aAAc,EACnBtH,KAAK+H,wBACL/H,KAAKiI,gBAObS,WAAY,WACJ1I,KAAKsG,QACLtG,KAAKqJ,gBAObE,aAAc,WACV,QAAKvJ,KAAKuH,UAImB,WAAzBvH,KAAKU,QAAQsC,UAEmB,aAAzBhD,KAAKU,QAAQsC,SACZhD,KAAKqH,YACmB,mBAAzBrH,KAAKU,QAAQsC,SACZhD,KAAKqH,cAAgBrH,KAAKsH,iBAD/B,KAQXwB,oBAAqB,WACjB,YAAoB7H,IAAhBjB,KAAKsG,SAGFtG,KAAKkH,KAAKxG,QAAQ8K,YACpBxL,KAAKkH,KAAKxG,QAAQ8K,UAAU/D,SAASzH,KAAKsG,OAAO7F,UAM1DsH,sBAAuB,WACd/H,KAAKyL,aAINzL,KAAKuH,UAAYvH,KAAKsG,OAEtBtG,KAAK0L,YAAY,cACV1L,KAAKuJ,eACZvJ,KAAK0L,YAAY,aACV1L,KAAKuH,QACZvH,KAAK0L,YAAY,UAEjB1L,KAAKmI,kBAObuD,YAAa,SAASC,GACL,cAATA,GACAvL,EAAcJ,KAAKyL,WAAY,oBAC/BxL,EAAWD,KAAKyL,WAAY,cAE5BrL,EAAcJ,KAAK2G,MAAO3G,KAAKU,QAAQa,MACvCtB,EAAWD,KAAK2G,MAAO3G,KAAKU,QAAQ4D,cACpB,UAATqH,GACPvL,EAAcJ,KAAKyL,WAAY,wBAC/BxL,EAAWD,KAAKyL,WAAY,UAE5BrL,EAAcJ,KAAK2G,MAAO3G,KAAKU,QAAQ4D,aACvCrE,EAAWD,KAAK2G,MAAO3G,KAAKU,QAAQa,OACpB,aAAToK,IACPvL,EAAcJ,KAAKyL,WAAY,cAC/BxL,EAAWD,KAAKyL,WAAY,oBAE5BrL,EAAcJ,KAAK2G,MAAO3G,KAAKU,QAAQ4D,aACvCrE,EAAWD,KAAK2G,MAAO3G,KAAKU,QAAQa,QAO5C4G,cAAe,WACXjJ,EAAEY,QAAQ8L,YAAY5L,KAAKyL,WAAY,cACvCvM,EAAEY,QAAQ8L,YAAY5L,KAAKyL,WAAY,UACvCvM,EAAEY,QAAQ8L,YAAY5L,KAAKyL,WAAY,aAEvCrL,EAAcJ,KAAK2G,MAAO3G,KAAKU,QAAQ4D,aACvCrE,EAAWD,KAAK2G,MAAO3G,KAAKU,QAAQa,OAMxC0F,gBAAiB,WAEbjH,KAAKuH,SAAU,EAIfvH,KAAKoH,cAAe,EAGpBpH,KAAKqH,aAAc,EAGnBrH,KAAKsH,aAAc,KAQ3B,OAJApI,EAAEgG,QAAQmD,OAAS,SAAU3H,GACzB,OAAO,IAAIxB,EAAEG,QAAQC,OAAOoB,IAGzBmC,GACR/D","file":"L.Control.Locate.min.js"} \ No newline at end of file diff --git a/html/js/Leaflet.GoogleMutant.js b/html/js/Leaflet.GoogleMutant.js new file mode 100644 index 0000000000..0ec19bb429 --- /dev/null +++ b/html/js/Leaflet.GoogleMutant.js @@ -0,0 +1,457 @@ +// Based on https://github.com/shramov/leaflet-plugins +// GridLayer like https://avinmathew.com/leaflet-and-google-maps/ , but using MutationObserver instead of jQuery + + +// 🍂class GridLayer.GoogleMutant +// 🍂extends GridLayer +L.GridLayer.GoogleMutant = L.GridLayer.extend({ + options: { + minZoom: 0, + maxZoom: 23, + tileSize: 256, + subdomains: 'abc', + errorTileUrl: '', + attribution: '', // The mutant container will add its own attribution anyways. + opacity: 1, + continuousWorld: false, + noWrap: false, + // 🍂option type: String = 'roadmap' + // Google's map type. Valid values are 'roadmap', 'satellite' or 'terrain'. 'hybrid' is not really supported. + type: 'roadmap', + maxNativeZoom: 21 + }, + + initialize: function (options) { + L.GridLayer.prototype.initialize.call(this, options); + + this._ready = !!window.google && !!window.google.maps && !!window.google.maps.Map; + + this._GAPIPromise = this._ready ? Promise.resolve(window.google) : new Promise(function (resolve, reject) { + var checkCounter = 0; + var intervalId = null; + intervalId = setInterval(function () { + if (checkCounter >= 10) { + clearInterval(intervalId); + return reject(new Error('window.google not found after 10 attempts')); + } + if (!!window.google && !!window.google.maps && !!window.google.maps.Map) { + clearInterval(intervalId); + return resolve(window.google); + } + checkCounter++; + }, 500); + }); + + // Couple data structures indexed by tile key + this._tileCallbacks = {}; // Callbacks for promises for tiles that are expected + this._freshTiles = {}; // Tiles from the mutant which haven't been requested yet + + this._imagesPerTile = (this.options.type === 'hybrid') ? 2 : 1; + + this._boundOnMutatedImage = this._onMutatedImage.bind(this); + }, + + onAdd: function (map) { + L.GridLayer.prototype.onAdd.call(this, map); + this._initMutantContainer(); + + this._GAPIPromise.then(function () { + this._ready = true; + this._map = map; + + this._initMutant(); + + map.on('viewreset', this._reset, this); + map.on('move', this._update, this); + map.on('zoomend', this._handleZoomAnim, this); + map.on('resize', this._resize, this); + + //handle layer being added to a map for which there are no Google tiles at the given zoom + google.maps.event.addListenerOnce(this._mutant, 'idle', function () { + this._checkZoomLevels(); + this._mutantIsReady = true; + }.bind(this)); + + //20px instead of 1em to avoid a slight overlap with google's attribution + map._controlCorners.bottomright.style.marginBottom = '20px'; + map._controlCorners.bottomleft.style.marginBottom = '20px'; + + this._reset(); + this._update(); + + if (this._subLayers) { + //restore previously added google layers + for (var layerName in this._subLayers) { + this._subLayers[layerName].setMap(this._mutant); + } + } + }.bind(this)); + }, + + onRemove: function (map) { + L.GridLayer.prototype.onRemove.call(this, map); + map._container.removeChild(this._mutantContainer); + this._mutantContainer = undefined; + + google.maps.event.clearListeners(map, 'idle'); + google.maps.event.clearListeners(this._mutant, 'idle'); + map.off('viewreset', this._reset, this); + map.off('move', this._update, this); + map.off('zoomend', this._handleZoomAnim, this); + map.off('resize', this._resize, this); + + if (map._controlCorners) { + map._controlCorners.bottomright.style.marginBottom = '0em'; + map._controlCorners.bottomleft.style.marginBottom = '0em'; + } + }, + + getAttribution: function () { + return this.options.attribution; + }, + + setOpacity: function (opacity) { + this.options.opacity = opacity; + if (opacity < 1) { + L.DomUtil.setOpacity(this._mutantContainer, opacity); + } + }, + + setElementSize: function (e, size) { + e.style.width = size.x + 'px'; + e.style.height = size.y + 'px'; + }, + + + addGoogleLayer: function (googleLayerName, options) { + if (!this._subLayers) this._subLayers = {}; + return this._GAPIPromise.then(function () { + var Constructor = google.maps[googleLayerName]; + var googleLayer = new Constructor(options); + googleLayer.setMap(this._mutant); + this._subLayers[googleLayerName] = googleLayer; + return googleLayer; + }.bind(this)); + }, + + removeGoogleLayer: function (googleLayerName) { + var googleLayer = this._subLayers && this._subLayers[googleLayerName]; + if (!googleLayer) return; + + googleLayer.setMap(null); + delete this._subLayers[googleLayerName]; + }, + + + _initMutantContainer: function () { + if (!this._mutantContainer) { + this._mutantContainer = L.DomUtil.create('div', 'leaflet-google-mutant leaflet-top leaflet-left'); + this._mutantContainer.id = '_MutantContainer_' + L.Util.stamp(this._mutantContainer); + this._mutantContainer.style.zIndex = '800'; //leaflet map pane at 400, controls at 1000 + this._mutantContainer.style.pointerEvents = 'none'; + + this._map.getContainer().appendChild(this._mutantContainer); + } + + this.setOpacity(this.options.opacity); + this.setElementSize(this._mutantContainer, this._map.getSize()); + + this._attachObserver(this._mutantContainer); + }, + + _initMutant: function () { + if (!this._ready || !this._mutantContainer) return; + this._mutantCenter = new google.maps.LatLng(0, 0); + + var map = new google.maps.Map(this._mutantContainer, { + center: this._mutantCenter, + zoom: 0, + tilt: 0, + mapTypeId: this.options.type, + disableDefaultUI: true, + keyboardShortcuts: false, + draggable: false, + disableDoubleClickZoom: true, + scrollwheel: false, + streetViewControl: false, + styles: this.options.styles || {}, + backgroundColor: 'transparent' + }); + + this._mutant = map; + + google.maps.event.addListenerOnce(map, 'idle', function () { + var nodes = this._mutantContainer.querySelectorAll('a'); + for (var i = 0; i < nodes.length; i++) { + nodes[i].style.pointerEvents = 'auto'; + } + }.bind(this)); + + // 🍂event spawned + // Fired when the mutant has been created. + this.fire('spawned', {mapObject: map}); + }, + + _attachObserver: function _attachObserver (node) { +// console.log('Gonna observe', node); + + var observer = new MutationObserver(this._onMutations.bind(this)); + + // pass in the target node, as well as the observer options + observer.observe(node, { childList: true, subtree: true }); + }, + + _onMutations: function _onMutations (mutations) { + for (var i = 0; i < mutations.length; ++i) { + var mutation = mutations[i]; + for (var j = 0; j < mutation.addedNodes.length; ++j) { + var node = mutation.addedNodes[j]; + + if (node instanceof HTMLImageElement) { + this._onMutatedImage(node); + } else if (node instanceof HTMLElement) { + Array.prototype.forEach.call( + node.querySelectorAll('img'), + this._boundOnMutatedImage + ); + + // Check for, and remove, the "Sorry, we have no imagery here" + // empty
s. The [style*="text-align: center"] selector + // avoids matching the attribution notice. + // This empty div doesn't have a reference to the tile + // coordinates, so it's not possible to mark the tile as + // failed. + Array.prototype.forEach.call( + node.querySelectorAll('div[draggable=false][style*="text-align: center"]'), + L.DomUtil.remove + ) + } + } + } + }, + + // Only images which 'src' attrib match this will be considered for moving around. + // Looks like some kind of string-based protobuf, maybe?? + // Only the roads (and terrain, and vector-based stuff) match this pattern + _roadRegexp: /!1i(\d+)!2i(\d+)!3i(\d+)!/, + + // On the other hand, raster imagery matches this other pattern + _satRegexp: /x=(\d+)&y=(\d+)&z=(\d+)/, + + // On small viewports, when zooming in/out, a static image is requested + // This will not be moved around, just removed from the DOM. + _staticRegExp: /StaticMapService\.GetMapImage/, + + _onMutatedImage: function _onMutatedImage (imgNode) { +// if (imgNode.src) { +// console.log('caught mutated image: ', imgNode.src); +// } + + var coords; + var match = imgNode.src.match(this._roadRegexp); + var sublayer = 0; + + if (match) { + coords = { + z: match[1], + x: match[2], + y: match[3] + }; + if (this._imagesPerTile > 1) { + imgNode.style.zIndex = 1; + sublayer = 1; + } + } else { + match = imgNode.src.match(this._satRegexp); + if (match) { + coords = { + x: match[1], + y: match[2], + z: match[3] + }; + } +// imgNode.style.zIndex = 0; + sublayer = 0; + } + + if (coords) { + var tileKey = this._tileCoordsToKey(coords); + imgNode.style.position = 'absolute'; + imgNode.style.visibility = 'hidden'; + + var key = tileKey + '/' + sublayer; + // console.log('mutation for tile', key) + //store img so it can also be used in subsequent tile requests + this._freshTiles[key] = imgNode; + + if (key in this._tileCallbacks && this._tileCallbacks[key]) { +// console.log('Fullfilling callback ', key); + //fullfill most recent tileCallback because there maybe callbacks that will never get a + //corresponding mutation (because map moved to quickly...) + this._tileCallbacks[key].pop()(imgNode); + if (!this._tileCallbacks[key].length) { delete this._tileCallbacks[key]; } + } else { + if (this._tiles[tileKey]) { + //we already have a tile in this position (mutation is probably a google layer being added) + //replace it + var c = this._tiles[tileKey].el; + var oldImg = (sublayer === 0) ? c.firstChild : c.firstChild.nextSibling; + var cloneImgNode = this._clone(imgNode); + c.replaceChild(cloneImgNode, oldImg); + } + } + } else if (imgNode.src.match(this._staticRegExp)) { + imgNode.style.visibility = 'hidden'; + } + }, + + + createTile: function (coords, done) { + var key = this._tileCoordsToKey(coords); + + var tileContainer = L.DomUtil.create('div'); + tileContainer.dataset.pending = this._imagesPerTile; + done = done.bind(this, null, tileContainer); + + for (var i = 0; i < this._imagesPerTile; i++) { + var key2 = key + '/' + i; + if (key2 in this._freshTiles) { + var imgNode = this._freshTiles[key2]; + tileContainer.appendChild(this._clone(imgNode)); + tileContainer.dataset.pending--; +// console.log('Got ', key2, ' from _freshTiles'); + } else { + this._tileCallbacks[key2] = this._tileCallbacks[key2] || []; + this._tileCallbacks[key2].push( (function (c/*, k2*/) { + return function (imgNode) { + c.appendChild(this._clone(imgNode)); + c.dataset.pending--; + if (!parseInt(c.dataset.pending)) { done(); } +// console.log('Sent ', k2, ' to _tileCallbacks, still ', c.dataset.pending, ' images to go'); + }.bind(this); + }.bind(this))(tileContainer/*, key2*/) ); + } + } + + if (!parseInt(tileContainer.dataset.pending)) { + L.Util.requestAnimFrame(done); + } + return tileContainer; + }, + + _clone: function (imgNode) { + var clonedImgNode = imgNode.cloneNode(true); + clonedImgNode.style.visibility = 'visible'; + return clonedImgNode; + }, + + _checkZoomLevels: function () { + //setting the zoom level on the Google map may result in a different zoom level than the one requested + //(it won't go beyond the level for which they have data). + var zoomLevel = this._map.getZoom(); + var gMapZoomLevel = this._mutant.getZoom(); + if (!zoomLevel || !gMapZoomLevel) return; + + + if ((gMapZoomLevel !== zoomLevel) || //zoom levels are out of sync, Google doesn't have data + (gMapZoomLevel > this.options.maxNativeZoom)) { //at current location, Google does have data (contrary to maxNativeZoom) + //Update maxNativeZoom + this._setMaxNativeZoom(gMapZoomLevel); + } + }, + + _setMaxNativeZoom: function (zoomLevel) { + if (zoomLevel != this.options.maxNativeZoom) { + this.options.maxNativeZoom = zoomLevel; + this._resetView(); + } + }, + + _reset: function () { + this._initContainer(); + }, + + _update: function () { + // zoom level check needs to happen before super's implementation (tile addition/creation) + // otherwise tiles may be missed if maxNativeZoom is not yet correctly determined + if (this._mutant) { + var center = this._map.getCenter(); + var _center = new google.maps.LatLng(center.lat, center.lng); + + this._mutant.setCenter(_center); + var zoom = this._map.getZoom(); + var fractionalLevel = zoom !== Math.round(zoom); + var mutantZoom = this._mutant.getZoom(); + + //ignore fractional zoom levels + if (!fractionalLevel && (zoom != mutantZoom)) { + this._mutant.setZoom(zoom); + + if (this._mutantIsReady) this._checkZoomLevels(); + //else zoom level check will be done later by 'idle' handler + } + } + + L.GridLayer.prototype._update.call(this); + }, + + _resize: function () { + var size = this._map.getSize(); + if (this._mutantContainer.style.width === size.x && + this._mutantContainer.style.height === size.y) + return; + this.setElementSize(this._mutantContainer, size); + if (!this._mutant) return; + google.maps.event.trigger(this._mutant, 'resize'); + }, + + _handleZoomAnim: function () { + if (!this._mutant) return; + var center = this._map.getCenter(); + var _center = new google.maps.LatLng(center.lat, center.lng); + + this._mutant.setCenter(_center); + this._mutant.setZoom(Math.round(this._map.getZoom())); + }, + + // Agressively prune _freshtiles when a tile with the same key is removed, + // this prevents a problem where Leaflet keeps a loaded tile longer than + // GMaps, so that GMaps makes two requests but Leaflet only consumes one, + // polluting _freshTiles with stale data. + _removeTile: function (key) { + if (!this._mutant) return; + + //give time for animations to finish before checking it tile should be pruned + setTimeout(this._pruneTile.bind(this, key), 1000); + + + return L.GridLayer.prototype._removeTile.call(this, key); + }, + + _pruneTile: function (key) { + var gZoom = this._mutant.getZoom(); + var tileZoom = key.split(':')[2]; + var googleBounds = this._mutant.getBounds(); + var sw = googleBounds.getSouthWest(); + var ne = googleBounds.getNorthEast(); + var gMapBounds = L.latLngBounds([[sw.lat(), sw.lng()], [ne.lat(), ne.lng()]]); + + for (var i=0; i=0}function I(t,i,e,n){return"touchstart"===i?O(t,e,n):"touchmove"===i?W(t,e,n):"touchend"===i&&H(t,e,n),this}function A(t,i,e){var n=t["_leaflet_"+i+e];return"touchstart"===i?t.removeEventListener(Xi,n,!1):"touchmove"===i?t.removeEventListener(Ji,n,!1):"touchend"===i&&(t.removeEventListener($i,n,!1),t.removeEventListener(Qi,n,!1)),this}function O(t,i,n){var o=e(function(t){if("mouse"!==t.pointerType&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(te.indexOf(t.target.tagName)<0))return;$(t)}j(t,i)});t["_leaflet_touchstart"+n]=o,t.addEventListener(Xi,o,!1),ee||(document.documentElement.addEventListener(Xi,R,!0),document.documentElement.addEventListener(Ji,D,!0),document.documentElement.addEventListener($i,N,!0),document.documentElement.addEventListener(Qi,N,!0),ee=!0)}function R(t){ie[t.pointerId]=t,ne++}function D(t){ie[t.pointerId]&&(ie[t.pointerId]=t)}function N(t){delete ie[t.pointerId],ne--}function j(t,i){t.touches=[];for(var e in ie)t.touches.push(ie[e]);t.changedTouches=[t],i(t)}function W(t,i,e){var n=function(t){(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons)&&j(t,i)};t["_leaflet_touchmove"+e]=n,t.addEventListener(Ji,n,!1)}function H(t,i,e){var n=function(t){j(t,i)};t["_leaflet_touchend"+e]=n,t.addEventListener($i,n,!1),t.addEventListener(Qi,n,!1)}function F(t,i,e){function n(t){var i;if(Wi){if(!Li||"mouse"===t.pointerType)return;i=ne}else i=t.touches.length;if(!(i>1)){var e=Date.now(),n=e-(s||e);r=t.touches?t.touches[0]:t,a=n>0&&n<=h,s=e}}function o(t){if(a&&!r.cancelBubble){if(Wi){if(!Li||"mouse"===t.pointerType)return;var e,n,o={};for(n in r)e=r[n],o[n]=e&&e.bind?e.bind(r):e;r=o}r.type="dblclick",i(r),s=null}}var s,r,a=!1,h=250;return t[re+oe+e]=n,t[re+se+e]=o,t[re+"dblclick"+e]=i,t.addEventListener(oe,n,!1),t.addEventListener(se,o,!1),t.addEventListener("dblclick",i,!1),this}function U(t,i){var e=t[re+oe+i],n=t[re+se+i],o=t[re+"dblclick"+i];return t.removeEventListener(oe,e,!1),t.removeEventListener(se,n,!1),Li||t.removeEventListener("dblclick",o,!1),this}function V(t,i,e,n){if("object"==typeof i)for(var o in i)q(t,o,i[o],e);else for(var s=0,r=(i=u(i)).length;s100&&n<500||t.target._simulatedClick&&!t._simulated?Q(t):(di=e,i(t))}function rt(t){return"string"==typeof t?document.getElementById(t):t}function at(t,i){var e=t.style[i]||t.currentStyle&&t.currentStyle[i];if((!e||"auto"===e)&&document.defaultView){var n=document.defaultView.getComputedStyle(t,null);e=n?n[i]:null}return"auto"===e?null:e}function ht(t,i,e){var n=document.createElement(t);return n.className=i||"",e&&e.appendChild(n),n}function ut(t){var i=t.parentNode;i&&i.removeChild(t)}function lt(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function ct(t){var i=t.parentNode;i.lastChild!==t&&i.appendChild(t)}function _t(t){var i=t.parentNode;i.firstChild!==t&&i.insertBefore(t,i.firstChild)}function dt(t,i){if(void 0!==t.classList)return t.classList.contains(i);var e=gt(t);return e.length>0&&new RegExp("(^|\\s)"+i+"(\\s|$)").test(e)}function pt(t,i){if(void 0!==t.classList)for(var e=u(i),n=0,o=e.length;nh&&(s=r,h=a);h>e&&(i[s]=1,St(t,i,e,n,s),St(t,i,e,s,o))}function kt(t,i){for(var e=[t[0]],n=1,o=0,s=t.length;ni&&(e.push(t[n]),o=n);return oi.max.x&&(e|=2),t.yi.max.y&&(e|=8),e}function Ot(t,i){var e=i.x-t.x,n=i.y-t.y;return e*e+n*n}function Rt(t,i,e,n){var o,s=i.x,r=i.y,a=e.x-s,h=e.y-r,u=a*a+h*h;return u>0&&((o=((t.x-s)*a+(t.y-r)*h)/u)>1?(s=e.x,r=e.y):o>0&&(s+=a*o,r+=h*o)),a=t.x-s,h=t.y-r,n?a*a+h*h:new x(s,r)}function Dt(t){return!ei(t[0])||"object"!=typeof t[0][0]&&void 0!==t[0][0]}function Nt(t){return console.warn("Deprecated use of _flat, please use L.LineUtil.isFlat instead."),Dt(t)}function jt(t,i,e){var n,o,s,r,a,h,u,l,c,_=[1,4,2,8];for(o=0,u=t.length;o=this.min.x&&e.x<=this.max.x&&i.y>=this.min.y&&e.y<=this.max.y},intersects:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>=i.x&&n.x<=e.x,r=o.y>=i.y&&n.y<=e.y;return s&&r},overlaps:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>i.x&&n.xi.y&&n.y=n.lat&&e.lat<=o.lat&&i.lng>=n.lng&&e.lng<=o.lng},intersects:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>=i.lat&&n.lat<=e.lat,r=o.lng>=i.lng&&n.lng<=e.lng;return s&&r},overlaps:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>i.lat&&n.lati.lng&&n.lng1,Gi=!!document.createElement("canvas").getContext,qi=!(!document.createElementNS||!S("svg").createSVGRect),Ki=!qi&&function(){try{var t=document.createElement("div");t.innerHTML='';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(t){return!1}}(),Yi=(Object.freeze||Object)({ie:xi,ielt9:wi,edge:Li,webkit:Pi,android:bi,android23:Ti,opera:zi,chrome:Mi,gecko:Ci,safari:Zi,phantom:Ei,opera12:Si,win:ki,ie3d:Bi,webkit3d:Ii,gecko3d:Ai,any3d:Oi,mobile:Ri,mobileWebkit:Di,mobileWebkit3d:Ni,msPointer:ji,pointer:Wi,touch:Hi,mobileOpera:Fi,mobileGecko:Ui,retina:Vi,canvas:Gi,svg:qi,vml:Ki}),Xi=ji?"MSPointerDown":"pointerdown",Ji=ji?"MSPointerMove":"pointermove",$i=ji?"MSPointerUp":"pointerup",Qi=ji?"MSPointerCancel":"pointercancel",te=["INPUT","SELECT","OPTION"],ie={},ee=!1,ne=0,oe=ji?"MSPointerDown":Wi?"pointerdown":"touchstart",se=ji?"MSPointerUp":Wi?"pointerup":"touchend",re="_leaflet_",ae="_leaflet_events",he=ki&&Mi?2*window.devicePixelRatio:Ci?window.devicePixelRatio:1,ue={},le=(Object.freeze||Object)({on:V,off:G,stopPropagation:Y,disableScrollPropagation:X,disableClickPropagation:J,preventDefault:$,stop:Q,getMousePosition:tt,getWheelDelta:it,fakeStop:et,skipped:nt,isExternalTarget:ot,addListener:V,removeListener:G}),ce=xt(["transform","WebkitTransform","OTransform","MozTransform","msTransform"]),_e=xt(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),de="webkitTransition"===_e||"OTransition"===_e?_e+"End":"transitionend";if("onselectstart"in document)pi=function(){V(window,"selectstart",$)},mi=function(){G(window,"selectstart",$)};else{var pe=xt(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);pi=function(){if(pe){var t=document.documentElement.style;fi=t[pe],t[pe]="none"}},mi=function(){pe&&(document.documentElement.style[pe]=fi,fi=void 0)}}var me,fe,ge=(Object.freeze||Object)({TRANSFORM:ce,TRANSITION:_e,TRANSITION_END:de,get:rt,getStyle:at,create:ht,remove:ut,empty:lt,toFront:ct,toBack:_t,hasClass:dt,addClass:pt,removeClass:mt,setClass:ft,getClass:gt,setOpacity:vt,testProp:xt,setTransform:wt,setPosition:Lt,getPosition:Pt,disableTextSelection:pi,enableTextSelection:mi,disableImageDrag:bt,enableImageDrag:Tt,preventOutline:zt,restoreOutline:Mt}),ve=ui.extend({run:function(t,i,e,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=e||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=Pt(t),this._offset=i.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(!0),this._complete())},_animate:function(){this._animId=f(this._animate,this),this._step()},_step:function(t){var i=+new Date-this._startTime,e=1e3*this._duration;ithis.options.maxZoom?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,z(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},invalidateSize:function(t){if(!this._loaded)return this;t=i({animate:!1,pan:!0},!0===t?{animate:!0}:t);var n=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var o=this.getSize(),s=n.divideBy(2).round(),r=o.divideBy(2).round(),a=s.subtract(r);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(e(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:n,newSize:o})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){if(t=this._locateOptions=i({timeout:1e4,watch:!1},t),!("geolocation"in navigator))return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var n=e(this._handleGeolocationResponse,this),o=e(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(n,o,t):navigator.geolocation.getCurrentPosition(n,o,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var i=t.code,e=t.message||(1===i?"permission denied":2===i?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:i,message:"Geolocation error: "+e+"."})},_handleGeolocationResponse:function(t){var i=new M(t.coords.latitude,t.coords.longitude),e=i.toBounds(t.coords.accuracy),n=this._locateOptions;if(n.setView){var o=this.getBoundsZoom(e);this.setView(i,n.maxZoom?Math.min(o,n.maxZoom):o)}var s={latlng:i,bounds:e,timestamp:t.timestamp};for(var r in t.coords)"number"==typeof t.coords[r]&&(s[r]=t.coords[r]);this.fire("locationfound",s)},addHandler:function(t,i){if(!i)return this;var e=this[t]=new i(this);return this._handlers.push(e),this.options[t]&&e.enable(),this},remove:function(){if(this._initEvents(!0),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}ut(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._clearHandlers(),this._loaded&&this.fire("unload");var t;for(t in this._layers)this._layers[t].remove();for(t in this._panes)ut(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,i){var e=ht("div","leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),i||this._mapPane);return t&&(this._panes[t]=e),e},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new T(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,i,e){t=z(t),e=w(e||[0,0]);var n=this.getZoom()||0,o=this.getMinZoom(),s=this.getMaxZoom(),r=t.getNorthWest(),a=t.getSouthEast(),h=this.getSize().subtract(e),u=b(this.project(a,n),this.project(r,n)).getSize(),l=Oi?this.options.zoomSnap:1,c=h.x/u.x,_=h.y/u.y,d=i?Math.max(c,_):Math.min(c,_);return n=this.getScaleZoom(d,n),l&&(n=Math.round(n/(l/100))*(l/100),n=i?Math.ceil(n/l)*l:Math.floor(n/l)*l),Math.max(o,Math.min(s,n))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new x(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,i){var e=this._getTopLeftPoint(t,i);return new P(e,e.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,i){var e=this.options.crs;return i=void 0===i?this._zoom:i,e.scale(t)/e.scale(i)},getScaleZoom:function(t,i){var e=this.options.crs;i=void 0===i?this._zoom:i;var n=e.zoom(t*e.scale(i));return isNaN(n)?1/0:n},project:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.latLngToPoint(C(t),i)},unproject:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.pointToLatLng(w(t),i)},layerPointToLatLng:function(t){var i=w(t).add(this.getPixelOrigin());return this.unproject(i)},latLngToLayerPoint:function(t){return this.project(C(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(C(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(z(t))},distance:function(t,i){return this.options.crs.distance(C(t),C(i))},containerPointToLayerPoint:function(t){return w(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return w(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var i=this.containerPointToLayerPoint(w(t));return this.layerPointToLatLng(i)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(C(t)))},mouseEventToContainerPoint:function(t){return tt(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var i=this._container=rt(t);if(!i)throw new Error("Map container not found.");if(i._leaflet_id)throw new Error("Map container is already initialized.");V(i,"scroll",this._onScroll,this),this._containerId=n(i)},_initLayout:function(){var t=this._container;this._fadeAnimated=this.options.fadeAnimation&&Oi,pt(t,"leaflet-container"+(Hi?" leaflet-touch":"")+(Vi?" leaflet-retina":"")+(wi?" leaflet-oldie":"")+(Zi?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":""));var i=at(t,"position");"absolute"!==i&&"relative"!==i&&"fixed"!==i&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),Lt(this._mapPane,new x(0,0)),this.createPane("tilePane"),this.createPane("shadowPane"),this.createPane("overlayPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(pt(t.markerPane,"leaflet-zoom-hide"),pt(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,i){Lt(this._mapPane,new x(0,0));var e=!this._loaded;this._loaded=!0,i=this._limitZoom(i),this.fire("viewprereset");var n=this._zoom!==i;this._moveStart(n)._move(t,i)._moveEnd(n),this.fire("viewreset"),e&&this.fire("load")},_moveStart:function(t){return t&&this.fire("zoomstart"),this.fire("movestart")},_move:function(t,i,e){void 0===i&&(i=this._zoom);var n=this._zoom!==i;return this._zoom=i,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),(n||e&&e.pinch)&&this.fire("zoom",e),this.fire("move",e)},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return g(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){Lt(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={},this._targets[n(this._container)]=this;var i=t?G:V;i(this._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress",this._handleDOMEvent,this),this.options.trackResize&&i(window,"resize",this._onResize,this),Oi&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){g(this._resizeRequest),this._resizeRequest=f(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,o=[],s="mouseout"===i||"mouseover"===i,r=t.target||t.srcElement,a=!1;r;){if((e=this._targets[n(r)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){a=!0;break}if(e&&e.listens(i,!0)){if(s&&!ot(r,t))break;if(o.push(e),s)break}if(r===this._container)break;r=r.parentNode}return o.length||a||s||!ot(r,t)||(o=[this]),o},_handleDOMEvent:function(t){if(this._loaded&&!nt(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i||zt(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,n){if("click"===t.type){var o=i({},t);o.type="preclick",this._fireDOMEvent(o,o.type,n)}if(!t._stopped&&(n=(n||[]).concat(this._findEventTargets(t,e))).length){var s=n[0];"contextmenu"===e&&s.listens(e,!0)&&$(t);var r={originalEvent:t};if("keypress"!==t.type){var a=s.options&&"icon"in s.options;r.containerPoint=a?this.latLngToContainerPoint(s.getLatLng()):this.mouseEventToContainerPoint(t),r.layerPoint=this.containerPointToLayerPoint(r.containerPoint),r.latlng=a?s.getLatLng():this.layerPointToLatLng(r.layerPoint)}for(var h=0;h0?Math.round(t-i)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(i))},_limitZoom:function(t){var i=this.getMinZoom(),e=this.getMaxZoom(),n=Oi?this.options.zoomSnap:1;return n&&(t=Math.round(t/n)*n),Math.max(i,Math.min(e,t))},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){mt(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,i){var e=this._getCenterOffset(t)._floor();return!(!0!==(i&&i.animate)&&!this.getSize().contains(e))&&(this.panBy(e,i),!0)},_createAnimProxy:function(){var t=this._proxy=ht("div","leaflet-proxy leaflet-zoom-animated");this._panes.mapPane.appendChild(t),this.on("zoomanim",function(t){var i=ce,e=this._proxy.style[i];wt(this._proxy,this.project(t.center,t.zoom),this.getZoomScale(t.zoom,1)),e===this._proxy.style[i]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on("load moveend",function(){var t=this.getCenter(),i=this.getZoom();wt(this._proxy,this.project(t,i),this.getZoomScale(i,1))},this),this._on("unload",this._destroyAnimProxy,this)},_destroyAnimProxy:function(){ut(this._proxy),delete this._proxy},_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,i,e){if(this._animatingZoom)return!0;if(e=e||{},!this._zoomAnimated||!1===e.animate||this._nothingToAnimate()||Math.abs(i-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o))&&(f(function(){this._moveStart(!0)._animateZoom(t,i,!0)},this),!0)},_animateZoom:function(t,i,n,o){n&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,pt(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:o}),setTimeout(e(this._onZoomTransitionEnd,this),250)},_onZoomTransitionEnd:function(){this._animatingZoom&&(mt(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),f(function(){this._moveEnd(!0)},this))}}),xe=v.extend({options:{position:"topright"},initialize:function(t){l(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return pt(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this},remove:function(){return this._map?(ut(this._container),this.onRemove&&this.onRemove(this._map),this._map=null,this):this},_refocusOnMap:function(t){this._map&&t&&t.screenX>0&&t.screenY>0&&this._map.getContainer().focus()}}),we=function(t){return new xe(t)};ye.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){function t(t,o){var s=e+t+" "+e+o;i[t+o]=ht("div",s,n)}var i=this._controlCorners={},e="leaflet-",n=this._controlContainer=ht("div",e+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){for(var t in this._controlCorners)ut(this._controlCorners[t]);ut(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var Le=xe.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,i,e,n){return e1,this._baseLayersList.style.display=t?"":"none"),this._separator.style.display=i&&t?"":"none",this},_onLayerChange:function(t){this._handlingClick||this._update();var i=this._getLayer(n(t.target)),e=i.overlay?"add"===t.type?"overlayadd":"overlayremove":"add"===t.type?"baselayerchange":null;e&&this._map.fire(e,i)},_createRadioElement:function(t,i){var e='",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),o=this._map.hasLayer(t.layer);t.overlay?((i=document.createElement("input")).type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=o):i=this._createRadioElement("leaflet-base-layers",o),this._layerControlInputs.push(i),i.layerId=n(t.layer),V(i,"click",this._onInputClick,this);var s=document.createElement("span");s.innerHTML=" "+t.name;var r=document.createElement("div");return e.appendChild(r),r.appendChild(i),r.appendChild(s),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e=this._layerControlInputs,n=[],o=[];this._handlingClick=!0;for(var s=e.length-1;s>=0;s--)t=e[s],i=this._getLayer(t.layerId).layer,t.checked?n.push(i):t.checked||o.push(i);for(s=0;s=0;o--)t=e[o],i=this._getLayer(t.layerId).layer,t.disabled=void 0!==i.options.minZoom&&ni.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),Pe=xe.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=ht("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=ht("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),J(s),V(s,"click",Q),V(s,"click",o,this),V(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";mt(this._zoomInButton,i),mt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMinZoom())&&pt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMaxZoom())&&pt(this._zoomInButton,i)}});ye.mergeOptions({zoomControl:!0}),ye.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new Pe,this.addControl(this.zoomControl))});var be=xe.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i=ht("div","leaflet-control-scale"),e=this.options;return this._addScales(e,"leaflet-control-scale-line",i),t.on(e.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=ht("div",i,e)),t.imperial&&(this._iScale=ht("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;o>5280?(i=o/5280,e=this._getRoundNum(i),this._updateScale(this._iScale,e+" mi",e/i)):(n=this._getRoundNum(o),this._updateScale(this._iScale,n+" ft",n/o))},_updateScale:function(t,i,e){t.style.width=Math.round(this.options.maxWidth*e)+"px",t.innerHTML=i},_getRoundNum:function(t){var i=Math.pow(10,(Math.floor(t)+"").length-1),e=t/i;return e=e>=10?10:e>=5?5:e>=3?3:e>=2?2:1,i*e}}),Te=xe.extend({options:{position:"bottomright",prefix:'Leaflet'},initialize:function(t){l(this,t),this._attributions={}},onAdd:function(t){t.attributionControl=this,this._container=ht("div","leaflet-control-attribution"),J(this._container);for(var i in t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):this},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});ye.mergeOptions({attributionControl:!0}),ye.addInitHook(function(){this.options.attributionControl&&(new Te).addTo(this)});xe.Layers=Le,xe.Zoom=Pe,xe.Scale=be,xe.Attribution=Te,we.layers=function(t,i,e){return new Le(t,i,e)},we.zoom=function(t){return new Pe(t)},we.scale=function(t){return new be(t)},we.attribution=function(t){return new Te(t)};var ze,Me=v.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}}),Ce={Events:hi},Ze=Hi?"touchstart mousedown":"mousedown",Ee={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},Se={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},ke=ui.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){l(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(V(this._dragStartTarget,Ze,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(ke._dragging===this&&this.finishDrag(),G(this._dragStartTarget,Ze,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!dt(this._element,"leaflet-zoom-anim")&&!(ke._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(ke._dragging=this,this._preventOutline&&zt(this._element),bt(),pi(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t;this._startPoint=new x(i.clientX,i.clientY),V(document,Se[t.type],this._onMove,this),V(document,Ee[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled)if(t.touches&&t.touches.length>1)this._moved=!0;else{var i=t.touches&&1===t.touches.length?t.touches[0]:t,e=new x(i.clientX,i.clientY).subtract(this._startPoint);(e.x||e.y)&&(Math.abs(e.x)+Math.abs(e.y)1e-7;h++)i=s*Math.sin(a),i=Math.pow((1-i)/(1+i),s/2),a+=u=Math.PI/2-2*Math.atan(r*i)-a;return new M(a*e,t.x*e/n)}},Re=(Object.freeze||Object)({LonLat:Ae,Mercator:Oe,SphericalMercator:_i}),De=i({},ci,{code:"EPSG:3395",projection:Oe,transformation:function(){var t=.5/(Math.PI*Oe.R);return E(t,.5,-t,.5)}()}),Ne=i({},ci,{code:"EPSG:4326",projection:Ae,transformation:E(1/180,1,-1/180,.5)}),je=i({},li,{projection:Ae,transformation:E(1,0,-1,0),scale:function(t){return Math.pow(2,t)},zoom:function(t){return Math.log(t)/Math.LN2},distance:function(t,i){var e=i.lng-t.lng,n=i.lat-t.lat;return Math.sqrt(e*e+n*n)},infinite:!0});li.Earth=ci,li.EPSG3395=De,li.EPSG3857=gi,li.EPSG900913=vi,li.EPSG4326=Ne,li.Simple=je;var We=ui.extend({options:{pane:"overlayPane",attribution:null,bubblingMouseEvents:!0},addTo:function(t){return t.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(t){return t&&t.removeLayer(this),this},getPane:function(t){return this._map.getPane(t?this.options[t]||t:this.options.pane)},addInteractiveTarget:function(t){return this._map._targets[n(t)]=this,this},removeInteractiveTarget:function(t){return delete this._map._targets[n(t)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(t){var i=t.target;if(i.hasLayer(this)){if(this._map=i,this._zoomAnimated=i._zoomAnimated,this.getEvents){var e=this.getEvents();i.on(e,this),this.once("remove",function(){i.off(e,this)},this)}this.onAdd(i),this.getAttribution&&i.attributionControl&&i.attributionControl.addAttribution(this.getAttribution()),this.fire("add"),i.fire("layeradd",{layer:this})}}});ye.include({addLayer:function(t){if(!t._layerAdd)throw new Error("The provided object is not a Layer.");var i=n(t);return this._layers[i]?this:(this._layers[i]=t,t._mapToAdd=this,t.beforeAdd&&t.beforeAdd(this),this.whenReady(t._layerAdd,t),this)},removeLayer:function(t){var i=n(t);return this._layers[i]?(this._loaded&&t.onRemove(this),t.getAttribution&&this.attributionControl&&this.attributionControl.removeAttribution(t.getAttribution()),delete this._layers[i],this._loaded&&(this.fire("layerremove",{layer:t}),t.fire("remove")),t._map=t._mapToAdd=null,this):this},hasLayer:function(t){return!!t&&n(t)in this._layers},eachLayer:function(t,i){for(var e in this._layers)t.call(i,this._layers[e]);return this},_addLayers:function(t){for(var i=0,e=(t=t?ei(t)?t:[t]:[]).length;ithis._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()i)return r=(n-i)/e,this._map.layerPointToLatLng([s.x-r*(s.x-o.x),s.y-r*(s.y-o.y)])},getBounds:function(){return this._bounds},addLatLng:function(t,i){return i=i||this._defaultShape(),t=C(t),i.push(t),this._bounds.extend(t),this.redraw()},_setLatLngs:function(t){this._bounds=new T,this._latlngs=this._convertLatLngs(t)},_defaultShape:function(){return Dt(this._latlngs)?this._latlngs:this._latlngs[0]},_convertLatLngs:function(t){for(var i=[],e=Dt(t),n=0,o=t.length;n=2&&i[0]instanceof M&&i[0].equals(i[e-1])&&i.pop(),i},_setLatLngs:function(t){Je.prototype._setLatLngs.call(this,t),Dt(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return Dt(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var t=this._renderer._bounds,i=this.options.weight,e=new x(i,i);if(t=new P(t.min.subtract(e),t.max.add(e)),this._parts=[],this._pxBounds&&this._pxBounds.intersects(t))if(this.options.noClip)this._parts=this._rings;else for(var n,o=0,s=this._rings.length;ot.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||Je.prototype._containsPoint.call(this,t,!0)}}),Qe=Fe.extend({initialize:function(t,i){l(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=ei(t)?t:t.features;if(o){for(i=0,e=o.length;io?(i.height=o+"px",pt(t,"leaflet-popup-scrolled")):mt(t,"leaflet-popup-scrolled"),this._containerWidth=this._container.offsetWidth},_animateZoom:function(t){var i=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center),e=this._getAnchor();Lt(this._container,i.add(e))},_adjustPan:function(){if(!(!this.options.autoPan||this._map._panAnim&&this._map._panAnim._inProgress)){var t=this._map,i=parseInt(at(this._container,"marginBottom"),10)||0,e=this._container.offsetHeight+i,n=this._containerWidth,o=new x(this._containerLeft,-e-this._containerBottom);o._add(Pt(this._container));var s=t.layerPointToContainerPoint(o),r=w(this.options.autoPanPadding),a=w(this.options.autoPanPaddingTopLeft||r),h=w(this.options.autoPanPaddingBottomRight||r),u=t.getSize(),l=0,c=0;s.x+n+h.x>u.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Q(t)},_getAnchor:function(){return w(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}});ye.mergeOptions({closePopupOnClick:!0}),ye.include({openPopup:function(t,i,e){return t instanceof rn||(t=new rn(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),We.include({bindPopup:function(t,i){return t instanceof rn?(l(t,i),this._popup=t,t._source=this):(this._popup&&!i||(this._popup=new rn(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){if(t instanceof We||(i=t,t=this),t instanceof Fe)for(var e in this._layers){t=this._layers[e];break}return i||(i=t.getCenter?t.getCenter():t.getLatLng()),this._popup&&this._map&&(this._popup._source=t,this._popup.update(),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;this._popup&&this._map&&(Q(t),i instanceof Ke?this.openPopup(t.layer||t.target,t.latlng):this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var an=sn.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){sn.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){sn.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=sn.prototype.getEvents.call(this);return Hi&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=ht("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=w(this.options.offset),u=this._getAnchor();"top"===s?t=t.add(w(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t=t.subtract(w(r/2-h.x,-h.y,!0)):"center"===s?t=t.subtract(w(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||en&&this._retainParent(o,s,r,n))},_retainChildren:function(t,i,e,n){for(var o=2*t;o<2*t+2;o++)for(var s=2*i;s<2*i+2;s++){var r=new x(o,s);r.z=e+1;var a=this._tileCoordsToKey(r),h=this._tiles[a];h&&h.active?h.retain=!0:(h&&h.loaded&&(h.retain=!0),e+1this.options.maxZoom||void 0!==this.options.minZoom&&o1)this._setView(t,e);else{for(var c=o.min.y;c<=o.max.y;c++)for(var _=o.min.x;_<=o.max.x;_++){var d=new x(_,c);d.z=this._tileZoom,this._isValidTile(d)&&(this._tiles[this._tileCoordsToKey(d)]||r.push(d))}if(r.sort(function(t,i){return t.distanceTo(s)-i.distanceTo(s)}),0!==r.length){this._loading||(this._loading=!0,this.fire("loading"));var p=document.createDocumentFragment();for(_=0;_e.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return z(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToBounds:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e),s=new T(i.unproject(n,t.z),i.unproject(o,t.z));return this.options.noWrap||i.wrapLatLngBounds(s),s},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new x(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(ut(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){pt(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=r,t.onmousemove=r,wi&&this.options.opacity<1&&vt(t,this.options.opacity),bi&&!Ti&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var n=this._getTilePos(t),o=this._tileCoordsToKey(t),s=this.createTile(this._wrapCoords(t),e(this._tileReady,this,t));this._initTile(s),this.createTile.length<2&&f(e(this._tileReady,this,t,null,s)),Lt(s,n),this._tiles[o]={el:s,coords:t,current:!0},i.appendChild(s),this.fire("tileloadstart",{tile:s,coords:t})},_tileReady:function(t,i,n){if(this._map){i&&this.fire("tileerror",{error:i,tile:n,coords:t});var o=this._tileCoordsToKey(t);(n=this._tiles[o])&&(n.loaded=+new Date,this._map._fadeAnimated?(vt(n.el,0),g(this._fadeFrame),this._fadeFrame=f(this._updateOpacity,this)):(n.active=!0,this._pruneTiles()),i||(pt(n.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:n.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),wi||!this._map._fadeAnimated?f(this._pruneTiles,this):setTimeout(e(this._pruneTiles,this),250)))}},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new x(this._wrapX?s(t.x,this._wrapX):t.x,this._wrapY?s(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new P(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}}),ln=un.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,(i=l(this,i)).detectRetina&&Vi&&i.maxZoom>0&&(i.tileSize=Math.floor(i.tileSize/2),i.zoomReverse?(i.zoomOffset--,i.minZoom++):(i.zoomOffset++,i.maxZoom--),i.minZoom=Math.max(0,i.minZoom)),"string"==typeof i.subdomains&&(i.subdomains=i.subdomains.split("")),bi||this.on("tileunload",this._onTileRemove)},setUrl:function(t,i){return this._url=t,i||this.redraw(),this},createTile:function(t,i){var n=document.createElement("img");return V(n,"load",e(this._tileOnLoad,this,i,n)),V(n,"error",e(this._tileOnError,this,i,n)),this.options.crossOrigin&&(n.crossOrigin=""),n.alt="",n.setAttribute("role","presentation"),n.src=this.getTileUrl(t),n},getTileUrl:function(t){var e={r:Vi?"@2x":"",s:this._getSubdomain(t),x:t.x,y:t.y,z:this._getZoomForUrl()};if(this._map&&!this._map.options.crs.infinite){var n=this._globalTileRange.max.y-t.y;this.options.tms&&(e.y=n),e["-y"]=n}return _(this._url,i(e,this.options))},_tileOnLoad:function(t,i){wi?setTimeout(e(t,this,null,i),0):t(null,i)},_tileOnError:function(t,i,e){var n=this.options.errorTileUrl;n&&i.src!==n&&(i.src=n),t(e,i)},_onTileRemove:function(t){t.tile.onload=null},_getZoomForUrl:function(){var t=this._tileZoom,i=this.options.maxZoom,e=this.options.zoomReverse,n=this.options.zoomOffset;return e&&(t=i-t),t+n},_getSubdomain:function(t){var i=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[i]},_abortLoading:function(){var t,i;for(t in this._tiles)this._tiles[t].coords.z!==this._tileZoom&&((i=this._tiles[t].el).onload=r,i.onerror=r,i.complete||(i.src=ni,ut(i)))}}),cn=ln.extend({defaultWmsParams:{service:"WMS",request:"GetMap",layers:"",styles:"",format:"image/jpeg",transparent:!1,version:"1.1.1"},options:{crs:null,uppercase:!1},initialize:function(t,e){this._url=t;var n=i({},this.defaultWmsParams);for(var o in e)o in this.options||(n[o]=e[o]);e=l(this,e),n.width=n.height=e.tileSize*(e.detectRetina&&Vi?2:1),this.wmsParams=n},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var i=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[i]=this._crs.code,ln.prototype.onAdd.call(this,t)},getTileUrl:function(t){var i=this._tileCoordsToBounds(t),e=this._crs.project(i.getNorthWest()),n=this._crs.project(i.getSouthEast()),o=(this._wmsVersion>=1.3&&this._crs===Ne?[n.y,e.x,e.y,n.x]:[e.x,n.y,n.x,e.y]).join(","),s=ln.prototype.getTileUrl.call(this,t);return s+c(this.wmsParams,s,this.options.uppercase)+(this.options.uppercase?"&BBOX=":"&bbox=")+o},setParams:function(t,e){return i(this.wmsParams,t),e||this.redraw(),this}});ln.WMS=cn,Yt.wms=function(t,i){return new cn(t,i)};var _n=We.extend({options:{padding:.1},initialize:function(t){l(this,t),n(this),this._layers=this._layers||{}},onAdd:function(){this._container||(this._initContainer(),this._zoomAnimated&&pt(this._container,"leaflet-zoom-animated")),this.getPane().appendChild(this._container),this._update(),this.on("update",this._updatePaths,this)},onRemove:function(){this.off("update",this._updatePaths,this),this._destroyContainer()},getEvents:function(){var t={viewreset:this._reset,zoom:this._onZoom,moveend:this._update,zoomend:this._onZoomEnd};return this._zoomAnimated&&(t.zoomanim=this._onAnimZoom),t},_onAnimZoom:function(t){this._updateTransform(t.center,t.zoom)},_onZoom:function(){this._updateTransform(this._map.getCenter(),this._map.getZoom())},_updateTransform:function(t,i){var e=this._map.getZoomScale(i,this._zoom),n=Pt(this._container),o=this._map.getSize().multiplyBy(.5+this.options.padding),s=this._map.project(this._center,i),r=this._map.project(t,i).subtract(s),a=o.multiplyBy(-e).add(n).add(o).subtract(r);Oi?wt(this._container,a,e):Lt(this._container,a)},_reset:function(){this._update(),this._updateTransform(this._center,this._zoom);for(var t in this._layers)this._layers[t]._reset()},_onZoomEnd:function(){for(var t in this._layers)this._layers[t]._project()},_updatePaths:function(){for(var t in this._layers)this._layers[t]._update()},_update:function(){var t=this.options.padding,i=this._map.getSize(),e=this._map.containerPointToLayerPoint(i.multiplyBy(-t)).round();this._bounds=new P(e,e.add(i.multiplyBy(1+2*t)).round()),this._center=this._map.getCenter(),this._zoom=this._map.getZoom()}}),dn=_n.extend({getEvents:function(){var t=_n.prototype.getEvents.call(this);return t.viewprereset=this._onViewPreReset,t},_onViewPreReset:function(){this._postponeUpdatePaths=!0},onAdd:function(){_n.prototype.onAdd.call(this),this._draw()},_initContainer:function(){var t=this._container=document.createElement("canvas");V(t,"mousemove",o(this._onMouseMove,32,this),this),V(t,"click dblclick mousedown mouseup contextmenu",this._onClick,this),V(t,"mouseout",this._handleMouseOut,this),this._ctx=t.getContext("2d")},_destroyContainer:function(){delete this._ctx,ut(this._container),G(this._container),delete this._container},_updatePaths:function(){if(!this._postponeUpdatePaths){this._redrawBounds=null;for(var t in this._layers)this._layers[t]._update();this._redraw()}},_update:function(){if(!this._map._animatingZoom||!this._bounds){this._drawnLayers={},_n.prototype._update.call(this);var t=this._bounds,i=this._container,e=t.getSize(),n=Vi?2:1;Lt(i,t.min),i.width=n*e.x,i.height=n*e.y,i.style.width=e.x+"px",i.style.height=e.y+"px",Vi&&this._ctx.scale(2,2),this._ctx.translate(-t.min.x,-t.min.y),this.fire("update")}},_reset:function(){_n.prototype._reset.call(this),this._postponeUpdatePaths&&(this._postponeUpdatePaths=!1,this._updatePaths())},_initPath:function(t){this._updateDashArray(t),this._layers[n(t)]=t;var i=t._order={layer:t,prev:this._drawLast,next:null};this._drawLast&&(this._drawLast.next=i),this._drawLast=i,this._drawFirst=this._drawFirst||this._drawLast},_addPath:function(t){this._requestRedraw(t)},_removePath:function(t){var i=t._order,e=i.next,n=i.prev;e?e.prev=n:this._drawLast=n,n?n.next=e:this._drawFirst=e,delete t._order,delete this._layers[L.stamp(t)],this._requestRedraw(t)},_updatePath:function(t){this._extendRedrawBounds(t),t._project(),t._update(),this._requestRedraw(t)},_updateStyle:function(t){this._updateDashArray(t),this._requestRedraw(t)},_updateDashArray:function(t){if(t.options.dashArray){var i,e=t.options.dashArray.split(","),n=[];for(i=0;i')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),mn={_initContainer:function(){this._container=ht("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(_n.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=pn("shape");pt(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=pn("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;ut(i),t.removeInteractiveTarget(i),delete this._layers[n(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=pn("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=ei(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=pn("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){ct(t._container)},_bringToBack:function(t){_t(t._container)}},fn=Ki?pn:S,gn=_n.extend({getEvents:function(){var t=_n.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=fn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=fn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){ut(this._container),G(this._container),delete this._container,delete this._rootGroup},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){_n.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),Lt(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=fn("path");t.options.className&&pt(i,t.options.className),t.options.interactive&&pt(i,"leaflet-interactive"),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){ut(t._path),t.removeInteractiveTarget(t._path),delete this._layers[n(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,k(t._parts,i))},_updateCircle:function(t){var i=t._point,e=t._radius,n="a"+e+","+(t._radiusY||e)+" 0 1,0 ",o=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+n+2*e+",0 "+n+2*-e+",0 ";this._setPath(t,o)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){ct(t._path)},_bringToBack:function(t){_t(t._path)}});Ki&&gn.include(mn),ye.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this.options.preferCanvas&&Xt()||Jt()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=gn&&Jt({pane:t})||dn&&Xt({pane:t}),this._paneRenderers[t]=i),i}});var vn=$e.extend({initialize:function(t,i){$e.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=z(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});gn.create=fn,gn.pointsToPath=k,Qe.geometryToLayer=Wt,Qe.coordsToLatLng=Ht,Qe.coordsToLatLngs=Ft,Qe.latLngToCoords=Ut,Qe.latLngsToCoords=Vt,Qe.getFeature=Gt,Qe.asFeature=qt,ye.mergeOptions({boxZoom:!0});var yn=Me.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){V(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){G(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){ut(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){if(!t.shiftKey||1!==t.which&&1!==t.button)return!1;this._clearDeferredResetState(),this._resetState(),pi(),bt(),this._startPoint=this._map.mouseEventToContainerPoint(t),V(document,{contextmenu:Q,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=ht("div","leaflet-zoom-box",this._container),pt(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new P(this._point,this._startPoint),e=i.getSize();Lt(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(ut(this._box),mt(this._container,"leaflet-crosshair")),mi(),Tt(),G(document,{contextmenu:Q,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(e(this._resetState,this),0);var i=new T(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});ye.addInitHook("addHandler","boxZoom",yn),ye.mergeOptions({doubleClickZoom:!0});var xn=Me.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});ye.addInitHook("addHandler","doubleClickZoom",xn),ye.mergeOptions({dragging:!0,inertia:!Ti,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var wn=Me.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new ke(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}pt(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){mt(this._map._container,"leaflet-grab"),mt(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=z(this._map.options.maxBounds);this._offsetLimit=b(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),i-this._times[0]>50&&(this._positions.shift(),this._times.shift())}this._map.fire("move",t).fire("drag",t)},_onZoomEnd:function(){var t=this._map.getSize().divideBy(2),i=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=i.subtract(t).x,this._worldWidth=this._map.getPixelWorldBounds().getSize().x},_viscousLimit:function(t,i){return t-(t-i)*this._viscosity},_onPreDragLimit:function(){if(this._viscosity&&this._offsetLimit){var t=this._draggable._newPos.subtract(this._draggable._startPos),i=this._offsetLimit;t.xi.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});ye.addInitHook("addHandler","scrollWheelZoom",Pn),ye.mergeOptions({tap:!0,tapTolerance:15});var bn=Me.extend({addHooks:function(){V(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){G(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if($(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&pt(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),V(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),G(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&mt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});Hi&&!Wi&&ye.addInitHook("addHandler","tap",bn),ye.mergeOptions({touchZoom:Hi&&!Ti,bounceAtZoomLimits:!0});var Tn=Me.extend({addHooks:function(){pt(this._map._container,"leaflet-touch-zoom"),V(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){mt(this._map._container,"leaflet-touch-zoom"),G(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),V(document,"touchmove",this._onTouchMove,this),V(document,"touchend",this._onTouchEnd,this),$(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),$(t)}},_onTouchEnd:function(){this._moved&&this._zooming?(this._zooming=!1,g(this._animRequest),G(document,"touchmove",this._onTouchMove),G(document,"touchend",this._onTouchEnd),this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom))):this._zooming=!1}});ye.addInitHook("addHandler","touchZoom",Tn),ye.BoxZoom=yn,ye.DoubleClickZoom=xn,ye.Drag=wn,ye.Keyboard=Ln,ye.ScrollWheelZoom=Pn,ye.Tap=bn,ye.TouchZoom=Tn;var zn=window.L;window.L=t,Object.freeze=$t,t.version="1.2.0",t.noConflict=function(){return window.L=zn,this},t.Control=xe,t.control=we,t.Browser=Yi,t.Evented=ui,t.Mixin=Ce,t.Util=ai,t.Class=v,t.Handler=Me,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=le,t.DomUtil=ge,t.PosAnimation=ve,t.Draggable=ke,t.LineUtil=Be,t.PolyUtil=Ie,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=Z,t.transformation=E,t.Projection=Re,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=li,t.GeoJSON=Qe,t.geoJSON=Kt,t.geoJson=en,t.Layer=We,t.LayerGroup=He,t.layerGroup=function(t){return new He(t)},t.FeatureGroup=Fe,t.featureGroup=function(t){return new Fe(t)},t.ImageOverlay=nn,t.imageOverlay=function(t,i,e){return new nn(t,i,e)},t.VideoOverlay=on,t.videoOverlay=function(t,i,e){return new on(t,i,e)},t.DivOverlay=sn,t.Popup=rn,t.popup=function(t,i){return new rn(t,i)},t.Tooltip=an,t.tooltip=function(t,i){return new an(t,i)},t.Icon=Ue,t.icon=function(t){return new Ue(t)},t.DivIcon=hn,t.divIcon=function(t){return new hn(t)},t.Marker=qe,t.marker=function(t,i){return new qe(t,i)},t.TileLayer=ln,t.tileLayer=Yt,t.GridLayer=un,t.gridLayer=function(t){return new un(t)},t.SVG=gn,t.svg=Jt,t.Renderer=_n,t.Canvas=dn,t.canvas=Xt,t.Path=Ke,t.CircleMarker=Ye,t.circleMarker=function(t,i){return new Ye(t,i)},t.Circle=Xe,t.circle=function(t,i,e){return new Xe(t,i,e)},t.Polyline=Je,t.polyline=function(t,i){return new Je(t,i)},t.Polygon=$e,t.polygon=function(t,i){return new $e(t,i)},t.Rectangle=vn,t.rectangle=function(t,i){return new vn(t,i)},t.Map=ye,t.map=function(t,i){return new ye(t,i)}}); \ No newline at end of file +!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i(t.L={})}(this,function(t){"use strict";function i(t){var i,e,n,o;for(e=1,n=arguments.length;e=0}function B(t,i,e,n){return"touchstart"===i?O(t,e,n):"touchmove"===i?W(t,e,n):"touchend"===i&&H(t,e,n),this}function I(t,i,e){var n=t["_leaflet_"+i+e];return"touchstart"===i?t.removeEventListener(te,n,!1):"touchmove"===i?t.removeEventListener(ie,n,!1):"touchend"===i&&(t.removeEventListener(ee,n,!1),t.removeEventListener(ne,n,!1)),this}function O(t,i,n){var o=e(function(t){if("mouse"!==t.pointerType&&t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(oe.indexOf(t.target.tagName)<0))return;Pt(t)}j(t,i)});t["_leaflet_touchstart"+n]=o,t.addEventListener(te,o,!1),re||(document.documentElement.addEventListener(te,R,!0),document.documentElement.addEventListener(ie,N,!0),document.documentElement.addEventListener(ee,D,!0),document.documentElement.addEventListener(ne,D,!0),re=!0)}function R(t){se[t.pointerId]=t,ae++}function N(t){se[t.pointerId]&&(se[t.pointerId]=t)}function D(t){delete se[t.pointerId],ae--}function j(t,i){t.touches=[];for(var e in se)t.touches.push(se[e]);t.changedTouches=[t],i(t)}function W(t,i,e){var n=function(t){(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons)&&j(t,i)};t["_leaflet_touchmove"+e]=n,t.addEventListener(ie,n,!1)}function H(t,i,e){var n=function(t){j(t,i)};t["_leaflet_touchend"+e]=n,t.addEventListener(ee,n,!1),t.addEventListener(ne,n,!1)}function F(t,i,e){function n(t){var i;if(Vi){if(!bi||"mouse"===t.pointerType)return;i=ae}else i=t.touches.length;if(!(i>1)){var e=Date.now(),n=e-(s||e);r=t.touches?t.touches[0]:t,a=n>0&&n<=h,s=e}}function o(t){if(a&&!r.cancelBubble){if(Vi){if(!bi||"mouse"===t.pointerType)return;var e,n,o={};for(n in r)e=r[n],o[n]=e&&e.bind?e.bind(r):e;r=o}r.type="dblclick",i(r),s=null}}var s,r,a=!1,h=250;return t[le+he+e]=n,t[le+ue+e]=o,t[le+"dblclick"+e]=i,t.addEventListener(he,n,!1),t.addEventListener(ue,o,!1),t.addEventListener("dblclick",i,!1),this}function U(t,i){var e=t[le+he+i],n=t[le+ue+i],o=t[le+"dblclick"+i];return t.removeEventListener(he,e,!1),t.removeEventListener(ue,n,!1),bi||t.removeEventListener("dblclick",o,!1),this}function V(t){return"string"==typeof t?document.getElementById(t):t}function q(t,i){var e=t.style[i]||t.currentStyle&&t.currentStyle[i];if((!e||"auto"===e)&&document.defaultView){var n=document.defaultView.getComputedStyle(t,null);e=n?n[i]:null}return"auto"===e?null:e}function G(t,i,e){var n=document.createElement(t);return n.className=i||"",e&&e.appendChild(n),n}function K(t){var i=t.parentNode;i&&i.removeChild(t)}function Y(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function X(t){var i=t.parentNode;i.lastChild!==t&&i.appendChild(t)}function J(t){var i=t.parentNode;i.firstChild!==t&&i.insertBefore(t,i.firstChild)}function $(t,i){if(void 0!==t.classList)return t.classList.contains(i);var e=et(t);return e.length>0&&new RegExp("(^|\\s)"+i+"(\\s|$)").test(e)}function Q(t,i){if(void 0!==t.classList)for(var e=u(i),n=0,o=e.length;n100&&n<500||t.target._simulatedClick&&!t._simulated?Lt(t):(ge=e,i(t))}function Zt(t,i){if(!i||!t.length)return t.slice();var e=i*i;return t=Bt(t,e),t=kt(t,e)}function Et(t,i,e){return Math.sqrt(Dt(t,i,e,!0))}function kt(t,i){var e=t.length,n=new(typeof Uint8Array!=void 0+""?Uint8Array:Array)(e);n[0]=n[e-1]=1,At(t,n,i,0,e-1);var o,s=[];for(o=0;oh&&(s=r,h=a);h>e&&(i[s]=1,At(t,i,e,n,s),At(t,i,e,s,o))}function Bt(t,i){for(var e=[t[0]],n=1,o=0,s=t.length;ni&&(e.push(t[n]),o=n);return oi.max.x&&(e|=2),t.yi.max.y&&(e|=8),e}function Nt(t,i){var e=i.x-t.x,n=i.y-t.y;return e*e+n*n}function Dt(t,i,e,n){var o,s=i.x,r=i.y,a=e.x-s,h=e.y-r,u=a*a+h*h;return u>0&&((o=((t.x-s)*a+(t.y-r)*h)/u)>1?(s=e.x,r=e.y):o>0&&(s+=a*o,r+=h*o)),a=t.x-s,h=t.y-r,n?a*a+h*h:new x(s,r)}function jt(t){return!oi(t[0])||"object"!=typeof t[0][0]&&void 0!==t[0][0]}function Wt(t){return console.warn("Deprecated use of _flat, please use L.LineUtil.isFlat instead."),jt(t)}function Ht(t,i,e){var n,o,s,r,a,h,u,l,c,_=[1,4,2,8];for(o=0,u=t.length;o0?Math.floor(t):Math.ceil(t)};x.prototype={clone:function(){return new x(this.x,this.y)},add:function(t){return this.clone()._add(w(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(w(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},scaleBy:function(t){return new x(this.x*t.x,this.y*t.y)},unscaleBy:function(t){return new x(this.x/t.x,this.y/t.y)},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.clone()._ceil()},_ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},trunc:function(){return this.clone()._trunc()},_trunc:function(){return this.x=_i(this.x),this.y=_i(this.y),this},distanceTo:function(t){var i=(t=w(t)).x-this.x,e=t.y-this.y;return Math.sqrt(i*i+e*e)},equals:function(t){return(t=w(t)).x===this.x&&t.y===this.y},contains:function(t){return t=w(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+a(this.x)+", "+a(this.y)+")"}},P.prototype={extend:function(t){return t=w(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new x((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new x(this.min.x,this.max.y)},getTopRight:function(){return new x(this.max.x,this.min.y)},getTopLeft:function(){return this.min},getBottomRight:function(){return this.max},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var i,e;return(t="number"==typeof t[0]||t instanceof x?w(t):b(t))instanceof P?(i=t.min,e=t.max):i=e=t,i.x>=this.min.x&&e.x<=this.max.x&&i.y>=this.min.y&&e.y<=this.max.y},intersects:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>=i.x&&n.x<=e.x,r=o.y>=i.y&&n.y<=e.y;return s&&r},overlaps:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>i.x&&n.xi.y&&n.y=n.lat&&e.lat<=o.lat&&i.lng>=n.lng&&e.lng<=o.lng},intersects:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>=i.lat&&n.lat<=e.lat,r=o.lng>=i.lng&&n.lng<=e.lng;return s&&r},overlaps:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>i.lat&&n.lati.lng&&n.lng1,Xi=!!document.createElement("canvas").getContext,Ji=!(!document.createElementNS||!E("svg").createSVGRect),$i=!Ji&&function(){try{var t=document.createElement("div");t.innerHTML='';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(t){return!1}}(),Qi=(Object.freeze||Object)({ie:Pi,ielt9:Li,edge:bi,webkit:Ti,android:zi,android23:Mi,androidStock:Si,opera:Zi,chrome:Ei,gecko:ki,safari:Ai,phantom:Bi,opera12:Ii,win:Oi,ie3d:Ri,webkit3d:Ni,gecko3d:Di,any3d:ji,mobile:Wi,mobileWebkit:Hi,mobileWebkit3d:Fi,msPointer:Ui,pointer:Vi,touch:qi,mobileOpera:Gi,mobileGecko:Ki,retina:Yi,canvas:Xi,svg:Ji,vml:$i}),te=Ui?"MSPointerDown":"pointerdown",ie=Ui?"MSPointerMove":"pointermove",ee=Ui?"MSPointerUp":"pointerup",ne=Ui?"MSPointerCancel":"pointercancel",oe=["INPUT","SELECT","OPTION"],se={},re=!1,ae=0,he=Ui?"MSPointerDown":Vi?"pointerdown":"touchstart",ue=Ui?"MSPointerUp":Vi?"pointerup":"touchend",le="_leaflet_",ce=st(["transform","webkitTransform","OTransform","MozTransform","msTransform"]),_e=st(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),de="webkitTransition"===_e||"OTransition"===_e?_e+"End":"transitionend";if("onselectstart"in document)fi=function(){mt(window,"selectstart",Pt)},gi=function(){ft(window,"selectstart",Pt)};else{var pe=st(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);fi=function(){if(pe){var t=document.documentElement.style;vi=t[pe],t[pe]="none"}},gi=function(){pe&&(document.documentElement.style[pe]=vi,vi=void 0)}}var me,fe,ge,ve=(Object.freeze||Object)({TRANSFORM:ce,TRANSITION:_e,TRANSITION_END:de,get:V,getStyle:q,create:G,remove:K,empty:Y,toFront:X,toBack:J,hasClass:$,addClass:Q,removeClass:tt,setClass:it,getClass:et,setOpacity:nt,testProp:st,setTransform:rt,setPosition:at,getPosition:ht,disableTextSelection:fi,enableTextSelection:gi,disableImageDrag:ut,enableImageDrag:lt,preventOutline:ct,restoreOutline:_t,getSizedParentNode:dt,getScale:pt}),ye="_leaflet_events",xe=Oi&&Ei?2*window.devicePixelRatio:ki?window.devicePixelRatio:1,we={},Pe=(Object.freeze||Object)({on:mt,off:ft,stopPropagation:yt,disableScrollPropagation:xt,disableClickPropagation:wt,preventDefault:Pt,stop:Lt,getMousePosition:bt,getWheelDelta:Tt,fakeStop:zt,skipped:Mt,isExternalTarget:Ct,addListener:mt,removeListener:ft}),Le=ci.extend({run:function(t,i,e,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=e||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=ht(t),this._offset=i.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(!0),this._complete())},_animate:function(){this._animId=f(this._animate,this),this._step()},_step:function(t){var i=+new Date-this._startTime,e=1e3*this._duration;ithis.options.maxZoom)?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,z(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},invalidateSize:function(t){if(!this._loaded)return this;t=i({animate:!1,pan:!0},!0===t?{animate:!0}:t);var n=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var o=this.getSize(),s=n.divideBy(2).round(),r=o.divideBy(2).round(),a=s.subtract(r);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(e(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:n,newSize:o})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){if(t=this._locateOptions=i({timeout:1e4,watch:!1},t),!("geolocation"in navigator))return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var n=e(this._handleGeolocationResponse,this),o=e(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(n,o,t):navigator.geolocation.getCurrentPosition(n,o,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var i=t.code,e=t.message||(1===i?"permission denied":2===i?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:i,message:"Geolocation error: "+e+"."})},_handleGeolocationResponse:function(t){var i=new M(t.coords.latitude,t.coords.longitude),e=i.toBounds(2*t.coords.accuracy),n=this._locateOptions;if(n.setView){var o=this.getBoundsZoom(e);this.setView(i,n.maxZoom?Math.min(o,n.maxZoom):o)}var s={latlng:i,bounds:e,timestamp:t.timestamp};for(var r in t.coords)"number"==typeof t.coords[r]&&(s[r]=t.coords[r]);this.fire("locationfound",s)},addHandler:function(t,i){if(!i)return this;var e=this[t]=new i(this);return this._handlers.push(e),this.options[t]&&e.enable(),this},remove:function(){if(this._initEvents(!0),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}void 0!==this._locationWatchId&&this.stopLocate(),this._stop(),K(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._resizeRequest&&(g(this._resizeRequest),this._resizeRequest=null),this._clearHandlers(),this._loaded&&this.fire("unload");var t;for(t in this._layers)this._layers[t].remove();for(t in this._panes)K(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,i){var e=G("div","leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),i||this._mapPane);return t&&(this._panes[t]=e),e},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new T(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,i,e){t=z(t),e=w(e||[0,0]);var n=this.getZoom()||0,o=this.getMinZoom(),s=this.getMaxZoom(),r=t.getNorthWest(),a=t.getSouthEast(),h=this.getSize().subtract(e),u=b(this.project(a,n),this.project(r,n)).getSize(),l=ji?this.options.zoomSnap:1,c=h.x/u.x,_=h.y/u.y,d=i?Math.max(c,_):Math.min(c,_);return n=this.getScaleZoom(d,n),l&&(n=Math.round(n/(l/100))*(l/100),n=i?Math.ceil(n/l)*l:Math.floor(n/l)*l),Math.max(o,Math.min(s,n))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new x(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,i){var e=this._getTopLeftPoint(t,i);return new P(e,e.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,i){var e=this.options.crs;return i=void 0===i?this._zoom:i,e.scale(t)/e.scale(i)},getScaleZoom:function(t,i){var e=this.options.crs;i=void 0===i?this._zoom:i;var n=e.zoom(t*e.scale(i));return isNaN(n)?1/0:n},project:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.latLngToPoint(C(t),i)},unproject:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.pointToLatLng(w(t),i)},layerPointToLatLng:function(t){var i=w(t).add(this.getPixelOrigin());return this.unproject(i)},latLngToLayerPoint:function(t){return this.project(C(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(C(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(z(t))},distance:function(t,i){return this.options.crs.distance(C(t),C(i))},containerPointToLayerPoint:function(t){return w(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return w(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var i=this.containerPointToLayerPoint(w(t));return this.layerPointToLatLng(i)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(C(t)))},mouseEventToContainerPoint:function(t){return bt(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var i=this._container=V(t);if(!i)throw new Error("Map container not found.");if(i._leaflet_id)throw new Error("Map container is already initialized.");mt(i,"scroll",this._onScroll,this),this._containerId=n(i)},_initLayout:function(){var t=this._container;this._fadeAnimated=this.options.fadeAnimation&&ji,Q(t,"leaflet-container"+(qi?" leaflet-touch":"")+(Yi?" leaflet-retina":"")+(Li?" leaflet-oldie":"")+(Ai?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":""));var i=q(t,"position");"absolute"!==i&&"relative"!==i&&"fixed"!==i&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),at(this._mapPane,new x(0,0)),this.createPane("tilePane"),this.createPane("shadowPane"),this.createPane("overlayPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(Q(t.markerPane,"leaflet-zoom-hide"),Q(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,i){at(this._mapPane,new x(0,0));var e=!this._loaded;this._loaded=!0,i=this._limitZoom(i),this.fire("viewprereset");var n=this._zoom!==i;this._moveStart(n,!1)._move(t,i)._moveEnd(n),this.fire("viewreset"),e&&this.fire("load")},_moveStart:function(t,i){return t&&this.fire("zoomstart"),i||this.fire("movestart"),this},_move:function(t,i,e){void 0===i&&(i=this._zoom);var n=this._zoom!==i;return this._zoom=i,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),(n||e&&e.pinch)&&this.fire("zoom",e),this.fire("move",e)},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return g(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){at(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={},this._targets[n(this._container)]=this;var i=t?ft:mt;i(this._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress",this._handleDOMEvent,this),this.options.trackResize&&i(window,"resize",this._onResize,this),ji&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){g(this._resizeRequest),this._resizeRequest=f(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,o=[],s="mouseout"===i||"mouseover"===i,r=t.target||t.srcElement,a=!1;r;){if((e=this._targets[n(r)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){a=!0;break}if(e&&e.listens(i,!0)){if(s&&!Ct(r,t))break;if(o.push(e),s)break}if(r===this._container)break;r=r.parentNode}return o.length||a||s||!Ct(r,t)||(o=[this]),o},_handleDOMEvent:function(t){if(this._loaded&&!Mt(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i||ct(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,n){if("click"===t.type){var o=i({},t);o.type="preclick",this._fireDOMEvent(o,o.type,n)}if(!t._stopped&&(n=(n||[]).concat(this._findEventTargets(t,e))).length){var s=n[0];"contextmenu"===e&&s.listens(e,!0)&&Pt(t);var r={originalEvent:t};if("keypress"!==t.type){var a=s.getLatLng&&(!s._radius||s._radius<=10);r.containerPoint=a?this.latLngToContainerPoint(s.getLatLng()):this.mouseEventToContainerPoint(t),r.layerPoint=this.containerPointToLayerPoint(r.containerPoint),r.latlng=a?s.getLatLng():this.layerPointToLatLng(r.layerPoint)}for(var h=0;h0?Math.round(t-i)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(i))},_limitZoom:function(t){var i=this.getMinZoom(),e=this.getMaxZoom(),n=ji?this.options.zoomSnap:1;return n&&(t=Math.round(t/n)*n),Math.max(i,Math.min(e,t))},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){tt(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,i){var e=this._getCenterOffset(t)._trunc();return!(!0!==(i&&i.animate)&&!this.getSize().contains(e))&&(this.panBy(e,i),!0)},_createAnimProxy:function(){var t=this._proxy=G("div","leaflet-proxy leaflet-zoom-animated");this._panes.mapPane.appendChild(t),this.on("zoomanim",function(t){var i=ce,e=this._proxy.style[i];rt(this._proxy,this.project(t.center,t.zoom),this.getZoomScale(t.zoom,1)),e===this._proxy.style[i]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on("load moveend",function(){var t=this.getCenter(),i=this.getZoom();rt(this._proxy,this.project(t,i),this.getZoomScale(i,1))},this),this._on("unload",this._destroyAnimProxy,this)},_destroyAnimProxy:function(){K(this._proxy),delete this._proxy},_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,i,e){if(this._animatingZoom)return!0;if(e=e||{},!this._zoomAnimated||!1===e.animate||this._nothingToAnimate()||Math.abs(i-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o))&&(f(function(){this._moveStart(!0,!1)._animateZoom(t,i,!0)},this),!0)},_animateZoom:function(t,i,n,o){this._mapPane&&(n&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,Q(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:o}),setTimeout(e(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&tt(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),f(function(){this._moveEnd(!0)},this))}}),Te=v.extend({options:{position:"topright"},initialize:function(t){l(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return Q(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this},remove:function(){return this._map?(K(this._container),this.onRemove&&this.onRemove(this._map),this._map=null,this):this},_refocusOnMap:function(t){this._map&&t&&t.screenX>0&&t.screenY>0&&this._map.getContainer().focus()}}),ze=function(t){return new Te(t)};be.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){function t(t,o){var s=e+t+" "+e+o;i[t+o]=G("div",s,n)}var i=this._controlCorners={},e="leaflet-",n=this._controlContainer=G("div",e+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){for(var t in this._controlCorners)K(this._controlCorners[t]);K(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var Me=Te.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,i,e,n){return e1,this._baseLayersList.style.display=t?"":"none"),this._separator.style.display=i&&t?"":"none",this},_onLayerChange:function(t){this._handlingClick||this._update();var i=this._getLayer(n(t.target)),e=i.overlay?"add"===t.type?"overlayadd":"overlayremove":"add"===t.type?"baselayerchange":null;e&&this._map.fire(e,i)},_createRadioElement:function(t,i){var e='",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),o=this._map.hasLayer(t.layer);t.overlay?((i=document.createElement("input")).type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=o):i=this._createRadioElement("leaflet-base-layers",o),this._layerControlInputs.push(i),i.layerId=n(t.layer),mt(i,"click",this._onInputClick,this);var s=document.createElement("span");s.innerHTML=" "+t.name;var r=document.createElement("div");return e.appendChild(r),r.appendChild(i),r.appendChild(s),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e=this._layerControlInputs,n=[],o=[];this._handlingClick=!0;for(var s=e.length-1;s>=0;s--)t=e[s],i=this._getLayer(t.layerId).layer,t.checked?n.push(i):t.checked||o.push(i);for(s=0;s=0;o--)t=e[o],i=this._getLayer(t.layerId).layer,t.disabled=void 0!==i.options.minZoom&&ni.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),Ce=Te.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=G("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=G("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),wt(s),mt(s,"click",Lt),mt(s,"click",o,this),mt(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";tt(this._zoomInButton,i),tt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMinZoom())&&Q(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMaxZoom())&&Q(this._zoomInButton,i)}});be.mergeOptions({zoomControl:!0}),be.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new Ce,this.addControl(this.zoomControl))});var Se=Te.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i=G("div","leaflet-control-scale"),e=this.options;return this._addScales(e,"leaflet-control-scale-line",i),t.on(e.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=G("div",i,e)),t.imperial&&(this._iScale=G("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;o>5280?(i=o/5280,e=this._getRoundNum(i),this._updateScale(this._iScale,e+" mi",e/i)):(n=this._getRoundNum(o),this._updateScale(this._iScale,n+" ft",n/o))},_updateScale:function(t,i,e){t.style.width=Math.round(this.options.maxWidth*e)+"px",t.innerHTML=i},_getRoundNum:function(t){var i=Math.pow(10,(Math.floor(t)+"").length-1),e=t/i;return e=e>=10?10:e>=5?5:e>=3?3:e>=2?2:1,i*e}}),Ze=Te.extend({options:{position:"bottomright",prefix:'Leaflet'},initialize:function(t){l(this,t),this._attributions={}},onAdd:function(t){t.attributionControl=this,this._container=G("div","leaflet-control-attribution"),wt(this._container);for(var i in t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):this},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});be.mergeOptions({attributionControl:!0}),be.addInitHook(function(){this.options.attributionControl&&(new Ze).addTo(this)});Te.Layers=Me,Te.Zoom=Ce,Te.Scale=Se,Te.Attribution=Ze,ze.layers=function(t,i,e){return new Me(t,i,e)},ze.zoom=function(t){return new Ce(t)},ze.scale=function(t){return new Se(t)},ze.attribution=function(t){return new Ze(t)};var Ee=v.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}});Ee.addTo=function(t,i){return t.addHandler(i,this),this};var ke,Ae={Events:li},Be=qi?"touchstart mousedown":"mousedown",Ie={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},Oe={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},Re=ci.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){l(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(mt(this._dragStartTarget,Be,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(Re._dragging===this&&this.finishDrag(),ft(this._dragStartTarget,Be,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!$(this._element,"leaflet-zoom-anim")&&!(Re._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(Re._dragging=this,this._preventOutline&&ct(this._element),ut(),fi(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t,e=dt(this._element);this._startPoint=new x(i.clientX,i.clientY),this._parentScale=pt(e),mt(document,Oe[t.type],this._onMove,this),mt(document,Ie[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled)if(t.touches&&t.touches.length>1)this._moved=!0;else{var i=t.touches&&1===t.touches.length?t.touches[0]:t,e=new x(i.clientX,i.clientY)._subtract(this._startPoint);(e.x||e.y)&&(Math.abs(e.x)+Math.abs(e.y)1e-7;h++)i=s*Math.sin(a),i=Math.pow((1-i)/(1+i),s/2),a+=u=Math.PI/2-2*Math.atan(r*i)-a;return new M(a*e,t.x*e/n)}},He=(Object.freeze||Object)({LonLat:je,Mercator:We,SphericalMercator:mi}),Fe=i({},pi,{code:"EPSG:3395",projection:We,transformation:function(){var t=.5/(Math.PI*We.R);return Z(t,.5,-t,.5)}()}),Ue=i({},pi,{code:"EPSG:4326",projection:je,transformation:Z(1/180,1,-1/180,.5)}),Ve=i({},di,{projection:je,transformation:Z(1,0,-1,0),scale:function(t){return Math.pow(2,t)},zoom:function(t){return Math.log(t)/Math.LN2},distance:function(t,i){var e=i.lng-t.lng,n=i.lat-t.lat;return Math.sqrt(e*e+n*n)},infinite:!0});di.Earth=pi,di.EPSG3395=Fe,di.EPSG3857=yi,di.EPSG900913=xi,di.EPSG4326=Ue,di.Simple=Ve;var qe=ci.extend({options:{pane:"overlayPane",attribution:null,bubblingMouseEvents:!0},addTo:function(t){return t.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(t){return t&&t.removeLayer(this),this},getPane:function(t){return this._map.getPane(t?this.options[t]||t:this.options.pane)},addInteractiveTarget:function(t){return this._map._targets[n(t)]=this,this},removeInteractiveTarget:function(t){return delete this._map._targets[n(t)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(t){var i=t.target;if(i.hasLayer(this)){if(this._map=i,this._zoomAnimated=i._zoomAnimated,this.getEvents){var e=this.getEvents();i.on(e,this),this.once("remove",function(){i.off(e,this)},this)}this.onAdd(i),this.getAttribution&&i.attributionControl&&i.attributionControl.addAttribution(this.getAttribution()),this.fire("add"),i.fire("layeradd",{layer:this})}}});be.include({addLayer:function(t){if(!t._layerAdd)throw new Error("The provided object is not a Layer.");var i=n(t);return this._layers[i]?this:(this._layers[i]=t,t._mapToAdd=this,t.beforeAdd&&t.beforeAdd(this),this.whenReady(t._layerAdd,t),this)},removeLayer:function(t){var i=n(t);return this._layers[i]?(this._loaded&&t.onRemove(this),t.getAttribution&&this.attributionControl&&this.attributionControl.removeAttribution(t.getAttribution()),delete this._layers[i],this._loaded&&(this.fire("layerremove",{layer:t}),t.fire("remove")),t._map=t._mapToAdd=null,this):this},hasLayer:function(t){return!!t&&n(t)in this._layers},eachLayer:function(t,i){for(var e in this._layers)t.call(i,this._layers[e]);return this},_addLayers:function(t){for(var i=0,e=(t=t?oi(t)?t:[t]:[]).length;ithis._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()i)return r=(n-i)/e,this._map.layerPointToLatLng([s.x-r*(s.x-o.x),s.y-r*(s.y-o.y)])},getBounds:function(){return this._bounds},addLatLng:function(t,i){return i=i||this._defaultShape(),t=C(t),i.push(t),this._bounds.extend(t),this.redraw()},_setLatLngs:function(t){this._bounds=new T,this._latlngs=this._convertLatLngs(t)},_defaultShape:function(){return jt(this._latlngs)?this._latlngs:this._latlngs[0]},_convertLatLngs:function(t){for(var i=[],e=jt(t),n=0,o=t.length;n=2&&i[0]instanceof M&&i[0].equals(i[e-1])&&i.pop(),i},_setLatLngs:function(t){nn.prototype._setLatLngs.call(this,t),jt(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return jt(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var t=this._renderer._bounds,i=this.options.weight,e=new x(i,i);if(t=new P(t.min.subtract(e),t.max.add(e)),this._parts=[],this._pxBounds&&this._pxBounds.intersects(t))if(this.options.noClip)this._parts=this._rings;else for(var n,o=0,s=this._rings.length;ot.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||nn.prototype._containsPoint.call(this,t,!0)}}),sn=Ke.extend({initialize:function(t,i){l(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=oi(t)?t:t.features;if(o){for(i=0,e=o.length;i0?o:[i.src]}else{oi(this._url)||(this._url=[this._url]),i.autoplay=!!this.options.autoplay,i.loop=!!this.options.loop;for(var a=0;ao?(i.height=o+"px",Q(t,"leaflet-popup-scrolled")):tt(t,"leaflet-popup-scrolled"),this._containerWidth=this._container.offsetWidth},_animateZoom:function(t){var i=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center),e=this._getAnchor();at(this._container,i.add(e))},_adjustPan:function(){if(!(!this.options.autoPan||this._map._panAnim&&this._map._panAnim._inProgress)){var t=this._map,i=parseInt(q(this._container,"marginBottom"),10)||0,e=this._container.offsetHeight+i,n=this._containerWidth,o=new x(this._containerLeft,-e-this._containerBottom);o._add(ht(this._container));var s=t.layerPointToContainerPoint(o),r=w(this.options.autoPanPadding),a=w(this.options.autoPanPaddingTopLeft||r),h=w(this.options.autoPanPaddingBottomRight||r),u=t.getSize(),l=0,c=0;s.x+n+h.x>u.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Lt(t)},_getAnchor:function(){return w(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}});be.mergeOptions({closePopupOnClick:!0}),be.include({openPopup:function(t,i,e){return t instanceof cn||(t=new cn(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),qe.include({bindPopup:function(t,i){return t instanceof cn?(l(t,i),this._popup=t,t._source=this):(this._popup&&!i||(this._popup=new cn(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){if(t instanceof qe||(i=t,t=this),t instanceof Ke)for(var e in this._layers){t=this._layers[e];break}return i||(i=t.getCenter?t.getCenter():t.getLatLng()),this._popup&&this._map&&(this._popup._source=t,this._popup.update(),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;this._popup&&this._map&&(Lt(t),i instanceof Qe?this.openPopup(t.layer||t.target,t.latlng):this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var _n=ln.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){ln.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){ln.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=ln.prototype.getEvents.call(this);return qi&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=G("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=w(this.options.offset),u=this._getAnchor();"top"===s?t=t.add(w(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t=t.subtract(w(r/2-h.x,-h.y,!0)):"center"===s?t=t.subtract(w(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||en&&this._retainParent(o,s,r,n))},_retainChildren:function(t,i,e,n){for(var o=2*t;o<2*t+2;o++)for(var s=2*i;s<2*i+2;s++){var r=new x(o,s);r.z=e+1;var a=this._tileCoordsToKey(r),h=this._tiles[a];h&&h.active?h.retain=!0:(h&&h.loaded&&(h.retain=!0),e+1this.options.maxZoom||void 0!==this.options.minZoom&&o1)this._setView(t,e);else{for(var c=o.min.y;c<=o.max.y;c++)for(var _=o.min.x;_<=o.max.x;_++){var d=new x(_,c);if(d.z=this._tileZoom,this._isValidTile(d)){var p=this._tiles[this._tileCoordsToKey(d)];p?p.current=!0:r.push(d)}}if(r.sort(function(t,i){return t.distanceTo(s)-i.distanceTo(s)}),0!==r.length){this._loading||(this._loading=!0,this.fire("loading"));var m=document.createDocumentFragment();for(_=0;_e.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return z(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToNwSe:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e);return[i.unproject(n,t.z),i.unproject(o,t.z)]},_tileCoordsToBounds:function(t){var i=this._tileCoordsToNwSe(t),e=new T(i[0],i[1]);return this.options.noWrap||(e=this._map.wrapLatLngBounds(e)),e},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new x(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(K(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){Q(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=r,t.onmousemove=r,Li&&this.options.opacity<1&&nt(t,this.options.opacity),zi&&!Mi&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var n=this._getTilePos(t),o=this._tileCoordsToKey(t),s=this.createTile(this._wrapCoords(t),e(this._tileReady,this,t));this._initTile(s),this.createTile.length<2&&f(e(this._tileReady,this,t,null,s)),at(s,n),this._tiles[o]={el:s,coords:t,current:!0},i.appendChild(s),this.fire("tileloadstart",{tile:s,coords:t})},_tileReady:function(t,i,n){i&&this.fire("tileerror",{error:i,tile:n,coords:t});var o=this._tileCoordsToKey(t);(n=this._tiles[o])&&(n.loaded=+new Date,this._map._fadeAnimated?(nt(n.el,0),g(this._fadeFrame),this._fadeFrame=f(this._updateOpacity,this)):(n.active=!0,this._pruneTiles()),i||(Q(n.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:n.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),Li||!this._map._fadeAnimated?f(this._pruneTiles,this):setTimeout(e(this._pruneTiles,this),250)))},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new x(this._wrapX?s(t.x,this._wrapX):t.x,this._wrapY?s(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new P(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}}),mn=pn.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,(i=l(this,i)).detectRetina&&Yi&&i.maxZoom>0&&(i.tileSize=Math.floor(i.tileSize/2),i.zoomReverse?(i.zoomOffset--,i.minZoom++):(i.zoomOffset++,i.maxZoom--),i.minZoom=Math.max(0,i.minZoom)),"string"==typeof i.subdomains&&(i.subdomains=i.subdomains.split("")),zi||this.on("tileunload",this._onTileRemove)},setUrl:function(t,i){return this._url=t,i||this.redraw(),this},createTile:function(t,i){var n=document.createElement("img");return mt(n,"load",e(this._tileOnLoad,this,i,n)),mt(n,"error",e(this._tileOnError,this,i,n)),(this.options.crossOrigin||""===this.options.crossOrigin)&&(n.crossOrigin=!0===this.options.crossOrigin?"":this.options.crossOrigin),n.alt="",n.setAttribute("role","presentation"),n.src=this.getTileUrl(t),n},getTileUrl:function(t){var e={r:Yi?"@2x":"",s:this._getSubdomain(t),x:t.x,y:t.y,z:this._getZoomForUrl()};if(this._map&&!this._map.options.crs.infinite){var n=this._globalTileRange.max.y-t.y;this.options.tms&&(e.y=n),e["-y"]=n}return _(this._url,i(e,this.options))},_tileOnLoad:function(t,i){Li?setTimeout(e(t,this,null,i),0):t(null,i)},_tileOnError:function(t,i,e){var n=this.options.errorTileUrl;n&&i.getAttribute("src")!==n&&(i.src=n),t(e,i)},_onTileRemove:function(t){t.tile.onload=null},_getZoomForUrl:function(){var t=this._tileZoom,i=this.options.maxZoom,e=this.options.zoomReverse,n=this.options.zoomOffset;return e&&(t=i-t),t+n},_getSubdomain:function(t){var i=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[i]},_abortLoading:function(){var t,i;for(t in this._tiles)this._tiles[t].coords.z!==this._tileZoom&&((i=this._tiles[t].el).onload=r,i.onerror=r,i.complete||(i.src=si,K(i),delete this._tiles[t]))},_removeTile:function(t){var i=this._tiles[t];if(i)return Si||i.el.setAttribute("src",si),pn.prototype._removeTile.call(this,t)},_tileReady:function(t,i,e){if(this._map&&(!e||e.getAttribute("src")!==si))return pn.prototype._tileReady.call(this,t,i,e)}}),fn=mn.extend({defaultWmsParams:{service:"WMS",request:"GetMap",layers:"",styles:"",format:"image/jpeg",transparent:!1,version:"1.1.1"},options:{crs:null,uppercase:!1},initialize:function(t,e){this._url=t;var n=i({},this.defaultWmsParams);for(var o in e)o in this.options||(n[o]=e[o]);var s=(e=l(this,e)).detectRetina&&Yi?2:1,r=this.getTileSize();n.width=r.x*s,n.height=r.y*s,this.wmsParams=n},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var i=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[i]=this._crs.code,mn.prototype.onAdd.call(this,t)},getTileUrl:function(t){var i=this._tileCoordsToNwSe(t),e=this._crs,n=b(e.project(i[0]),e.project(i[1])),o=n.min,s=n.max,r=(this._wmsVersion>=1.3&&this._crs===Ue?[o.y,o.x,s.y,s.x]:[o.x,o.y,s.x,s.y]).join(","),a=mn.prototype.getTileUrl.call(this,t);return a+c(this.wmsParams,a,this.options.uppercase)+(this.options.uppercase?"&BBOX=":"&bbox=")+r},setParams:function(t,e){return i(this.wmsParams,t),e||this.redraw(),this}});mn.WMS=fn,Jt.wms=function(t,i){return new fn(t,i)};var gn=qe.extend({options:{padding:.1,tolerance:0},initialize:function(t){l(this,t),n(this),this._layers=this._layers||{}},onAdd:function(){this._container||(this._initContainer(),this._zoomAnimated&&Q(this._container,"leaflet-zoom-animated")),this.getPane().appendChild(this._container),this._update(),this.on("update",this._updatePaths,this)},onRemove:function(){this.off("update",this._updatePaths,this),this._destroyContainer()},getEvents:function(){var t={viewreset:this._reset,zoom:this._onZoom,moveend:this._update,zoomend:this._onZoomEnd};return this._zoomAnimated&&(t.zoomanim=this._onAnimZoom),t},_onAnimZoom:function(t){this._updateTransform(t.center,t.zoom)},_onZoom:function(){this._updateTransform(this._map.getCenter(),this._map.getZoom())},_updateTransform:function(t,i){var e=this._map.getZoomScale(i,this._zoom),n=ht(this._container),o=this._map.getSize().multiplyBy(.5+this.options.padding),s=this._map.project(this._center,i),r=this._map.project(t,i).subtract(s),a=o.multiplyBy(-e).add(n).add(o).subtract(r);ji?rt(this._container,a,e):at(this._container,a)},_reset:function(){this._update(),this._updateTransform(this._center,this._zoom);for(var t in this._layers)this._layers[t]._reset()},_onZoomEnd:function(){for(var t in this._layers)this._layers[t]._project()},_updatePaths:function(){for(var t in this._layers)this._layers[t]._update()},_update:function(){var t=this.options.padding,i=this._map.getSize(),e=this._map.containerPointToLayerPoint(i.multiplyBy(-t)).round();this._bounds=new P(e,e.add(i.multiplyBy(1+2*t)).round()),this._center=this._map.getCenter(),this._zoom=this._map.getZoom()}}),vn=gn.extend({getEvents:function(){var t=gn.prototype.getEvents.call(this);return t.viewprereset=this._onViewPreReset,t},_onViewPreReset:function(){this._postponeUpdatePaths=!0},onAdd:function(){gn.prototype.onAdd.call(this),this._draw()},_initContainer:function(){var t=this._container=document.createElement("canvas");mt(t,"mousemove",o(this._onMouseMove,32,this),this),mt(t,"click dblclick mousedown mouseup contextmenu",this._onClick,this),mt(t,"mouseout",this._handleMouseOut,this),this._ctx=t.getContext("2d")},_destroyContainer:function(){g(this._redrawRequest),delete this._ctx,K(this._container),ft(this._container),delete this._container},_updatePaths:function(){if(!this._postponeUpdatePaths){this._redrawBounds=null;for(var t in this._layers)this._layers[t]._update();this._redraw()}},_update:function(){if(!this._map._animatingZoom||!this._bounds){this._drawnLayers={},gn.prototype._update.call(this);var t=this._bounds,i=this._container,e=t.getSize(),n=Yi?2:1;at(i,t.min),i.width=n*e.x,i.height=n*e.y,i.style.width=e.x+"px",i.style.height=e.y+"px",Yi&&this._ctx.scale(2,2),this._ctx.translate(-t.min.x,-t.min.y),this.fire("update")}},_reset:function(){gn.prototype._reset.call(this),this._postponeUpdatePaths&&(this._postponeUpdatePaths=!1,this._updatePaths())},_initPath:function(t){this._updateDashArray(t),this._layers[n(t)]=t;var i=t._order={layer:t,prev:this._drawLast,next:null};this._drawLast&&(this._drawLast.next=i),this._drawLast=i,this._drawFirst=this._drawFirst||this._drawLast},_addPath:function(t){this._requestRedraw(t)},_removePath:function(t){var i=t._order,e=i.next,o=i.prev;e?e.prev=o:this._drawLast=o,o?o.next=e:this._drawFirst=e,delete this._drawnLayers[t._leaflet_id],delete t._order,delete this._layers[n(t)],this._requestRedraw(t)},_updatePath:function(t){this._extendRedrawBounds(t),t._project(),t._update(),this._requestRedraw(t)},_updateStyle:function(t){this._updateDashArray(t),this._requestRedraw(t)},_updateDashArray:function(t){if("string"==typeof t.options.dashArray){var i,e=t.options.dashArray.split(/[, ]+/),n=[];for(i=0;i')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),xn={_initContainer:function(){this._container=G("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(gn.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=yn("shape");Q(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=yn("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;K(i),t.removeInteractiveTarget(i),delete this._layers[n(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=yn("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=oi(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=yn("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){X(t._container)},_bringToBack:function(t){J(t._container)}},wn=$i?yn:E,Pn=gn.extend({getEvents:function(){var t=gn.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=wn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=wn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){K(this._container),ft(this._container),delete this._container,delete this._rootGroup,delete this._svgSize},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){gn.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),at(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=wn("path");t.options.className&&Q(i,t.options.className),t.options.interactive&&Q(i,"leaflet-interactive"),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){K(t._path),t.removeInteractiveTarget(t._path),delete this._layers[n(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,k(t._parts,i))},_updateCircle:function(t){var i=t._point,e=Math.max(Math.round(t._radius),1),n="a"+e+","+(Math.max(Math.round(t._radiusY),1)||e)+" 0 1,0 ",o=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+n+2*e+",0 "+n+2*-e+",0 ";this._setPath(t,o)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){X(t._path)},_bringToBack:function(t){J(t._path)}});$i&&Pn.include(xn),be.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this._createRenderer()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=this._createRenderer({pane:t}),this._paneRenderers[t]=i),i},_createRenderer:function(t){return this.options.preferCanvas&&$t(t)||Qt(t)}});var Ln=on.extend({initialize:function(t,i){on.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=z(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});Pn.create=wn,Pn.pointsToPath=k,sn.geometryToLayer=Ft,sn.coordsToLatLng=Ut,sn.coordsToLatLngs=Vt,sn.latLngToCoords=qt,sn.latLngsToCoords=Gt,sn.getFeature=Kt,sn.asFeature=Yt,be.mergeOptions({boxZoom:!0});var bn=Ee.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){mt(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){ft(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){K(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){if(!t.shiftKey||1!==t.which&&1!==t.button)return!1;this._clearDeferredResetState(),this._resetState(),fi(),ut(),this._startPoint=this._map.mouseEventToContainerPoint(t),mt(document,{contextmenu:Lt,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=G("div","leaflet-zoom-box",this._container),Q(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new P(this._point,this._startPoint),e=i.getSize();at(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(K(this._box),tt(this._container,"leaflet-crosshair")),gi(),lt(),ft(document,{contextmenu:Lt,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(e(this._resetState,this),0);var i=new T(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});be.addInitHook("addHandler","boxZoom",bn),be.mergeOptions({doubleClickZoom:!0});var Tn=Ee.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});be.addInitHook("addHandler","doubleClickZoom",Tn),be.mergeOptions({dragging:!0,inertia:!Mi,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var zn=Ee.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new Re(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}Q(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){tt(this._map._container,"leaflet-grab"),tt(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=z(this._map.options.maxBounds);this._offsetLimit=b(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),this._prunePositions(i)}this._map.fire("move",t).fire("drag",t)},_prunePositions:function(t){for(;this._positions.length>1&&t-this._times[0]>50;)this._positions.shift(),this._times.shift()},_onZoomEnd:function(){var t=this._map.getSize().divideBy(2),i=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=i.subtract(t).x,this._worldWidth=this._map.getPixelWorldBounds().getSize().x},_viscousLimit:function(t,i){return t-(t-i)*this._viscosity},_onPreDragLimit:function(){if(this._viscosity&&this._offsetLimit){var t=this._draggable._newPos.subtract(this._draggable._startPos),i=this._offsetLimit;t.xi.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});be.addInitHook("addHandler","scrollWheelZoom",Cn),be.mergeOptions({tap:!0,tapTolerance:15});var Sn=Ee.extend({addHooks:function(){mt(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){ft(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(Pt(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&Q(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),mt(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),ft(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&tt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});qi&&!Vi&&be.addInitHook("addHandler","tap",Sn),be.mergeOptions({touchZoom:qi&&!Mi,bounceAtZoomLimits:!0});var Zn=Ee.extend({addHooks:function(){Q(this._map._container,"leaflet-touch-zoom"),mt(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){tt(this._map._container,"leaflet-touch-zoom"),ft(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),mt(document,"touchmove",this._onTouchMove,this),mt(document,"touchend",this._onTouchEnd,this),Pt(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0,!1),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),Pt(t)}},_onTouchEnd:function(){this._moved&&this._zooming?(this._zooming=!1,g(this._animRequest),ft(document,"touchmove",this._onTouchMove),ft(document,"touchend",this._onTouchEnd),this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom))):this._zooming=!1}});be.addInitHook("addHandler","touchZoom",Zn),be.BoxZoom=bn,be.DoubleClickZoom=Tn,be.Drag=zn,be.Keyboard=Mn,be.ScrollWheelZoom=Cn,be.Tap=Sn,be.TouchZoom=Zn,Object.freeze=ti,t.version="1.3.4+HEAD.0e566b2",t.Control=Te,t.control=ze,t.Browser=Qi,t.Evented=ci,t.Mixin=Ae,t.Util=ui,t.Class=v,t.Handler=Ee,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=Pe,t.DomUtil=ve,t.PosAnimation=Le,t.Draggable=Re,t.LineUtil=Ne,t.PolyUtil=De,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=S,t.transformation=Z,t.Projection=He,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=di,t.GeoJSON=sn,t.geoJSON=Xt,t.geoJson=an,t.Layer=qe,t.LayerGroup=Ge,t.layerGroup=function(t,i){return new Ge(t,i)},t.FeatureGroup=Ke,t.featureGroup=function(t){return new Ke(t)},t.ImageOverlay=hn,t.imageOverlay=function(t,i,e){return new hn(t,i,e)},t.VideoOverlay=un,t.videoOverlay=function(t,i,e){return new un(t,i,e)},t.DivOverlay=ln,t.Popup=cn,t.popup=function(t,i){return new cn(t,i)},t.Tooltip=_n,t.tooltip=function(t,i){return new _n(t,i)},t.Icon=Ye,t.icon=function(t){return new Ye(t)},t.DivIcon=dn,t.divIcon=function(t){return new dn(t)},t.Marker=$e,t.marker=function(t,i){return new $e(t,i)},t.TileLayer=mn,t.tileLayer=Jt,t.GridLayer=pn,t.gridLayer=function(t){return new pn(t)},t.SVG=Pn,t.svg=Qt,t.Renderer=gn,t.Canvas=vn,t.canvas=$t,t.Path=Qe,t.CircleMarker=tn,t.circleMarker=function(t,i){return new tn(t,i)},t.Circle=en,t.circle=function(t,i,e){return new en(t,i,e)},t.Polyline=nn,t.polyline=function(t,i){return new nn(t,i)},t.Polygon=on,t.polygon=function(t,i){return new on(t,i)},t.Rectangle=Ln,t.rectangle=function(t,i){return new Ln(t,i)},t.Map=be,t.map=function(t,i){return new be(t,i)};var En=window.L;t.noConflict=function(){return window.L=En,this},window.L=t}); \ No newline at end of file diff --git a/html/js/leaflet.markercluster-src.js b/html/js/leaflet.markercluster-src.js deleted file mode 100644 index 4c8adb2803..0000000000 --- a/html/js/leaflet.markercluster-src.js +++ /dev/null @@ -1,2677 +0,0 @@ -/* - Leaflet.markercluster, Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps. - https://github.com/Leaflet/Leaflet.markercluster - (c) 2012-2017, Dave Leaver -*/ -(function (window, document, undefined) {/* - * L.MarkerClusterGroup extends L.FeatureGroup by clustering the markers contained within - */ - -L.MarkerClusterGroup = L.FeatureGroup.extend({ - - options: { - maxClusterRadius: 80, //A cluster will cover at most this many pixels from its center - iconCreateFunction: null, - clusterPane: L.Marker.prototype.options.pane, - - spiderfyOnMaxZoom: true, - showCoverageOnHover: true, - zoomToBoundsOnClick: true, - singleMarkerMode: false, - - disableClusteringAtZoom: null, - - // Setting this to false prevents the removal of any clusters outside of the viewpoint, which - // is the default behaviour for performance reasons. - removeOutsideVisibleBounds: true, - - // Set to false to disable all animations (zoom and spiderfy). - // If false, option animateAddingMarkers below has no effect. - // If L.DomUtil.TRANSITION is falsy, this option has no effect. - animate: true, - - //Whether to animate adding markers after adding the MarkerClusterGroup to the map - // If you are adding individual markers set to true, if adding bulk markers leave false for massive performance gains. - animateAddingMarkers: false, - - //Increase to increase the distance away that spiderfied markers appear from the center - spiderfyDistanceMultiplier: 1, - - // Make it possible to specify a polyline options on a spider leg - spiderLegPolylineOptions: { weight: 1.5, color: '#222', opacity: 0.5 }, - - // 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 - chunkedLoading: false, - chunkInterval: 200, // process markers for a maximum of ~ n milliseconds (then trigger the chunkProgress callback) - chunkDelay: 50, // at the end of each interval, give n milliseconds back to system/browser - chunkProgress: null, // progress callback: function(processed, total, elapsed) (e.g. for a progress indicator) - - //Options to pass to the L.Polygon constructor - polygonOptions: {} - }, - - initialize: function (options) { - L.Util.setOptions(this, options); - if (!this.options.iconCreateFunction) { - this.options.iconCreateFunction = this._defaultIconCreateFunction; - } - - this._featureGroup = L.featureGroup(); - this._featureGroup.addEventParent(this); - - this._nonPointGroup = L.featureGroup(); - this._nonPointGroup.addEventParent(this); - - this._inZoomAnimation = 0; - this._needsClustering = []; - this._needsRemoving = []; //Markers removed while we aren't on the map need to be kept track of - //The bounds of the currently shown area (from _getExpandedVisibleBounds) Updated on zoom/move - this._currentShownBounds = null; - - this._queue = []; - - this._childMarkerEventHandlers = { - 'dragstart': this._childMarkerDragStart, - 'move': this._childMarkerMoved, - 'dragend': this._childMarkerDragEnd, - }; - - // Hook the appropriate animation methods. - var animate = L.DomUtil.TRANSITION && this.options.animate; - L.extend(this, animate ? this._withAnimation : this._noAnimation); - // Remember which MarkerCluster class to instantiate (animated or not). - this._markerCluster = animate ? L.MarkerCluster : L.MarkerClusterNonAnimated; - }, - - addLayer: function (layer) { - - if (layer instanceof L.LayerGroup) { - return this.addLayers([layer]); - } - - //Don't cluster non point data - if (!layer.getLatLng) { - this._nonPointGroup.addLayer(layer); - this.fire('layeradd', { layer: layer }); - return this; - } - - if (!this._map) { - this._needsClustering.push(layer); - this.fire('layeradd', { layer: layer }); - return this; - } - - if (this.hasLayer(layer)) { - return this; - } - - - //If we have already clustered we'll need to add this one to a cluster - - if (this._unspiderfy) { - this._unspiderfy(); - } - - this._addLayer(layer, this._maxZoom); - this.fire('layeradd', { layer: layer }); - - // Refresh bounds and weighted positions. - this._topClusterLevel._recalculateBounds(); - - this._refreshClustersIcons(); - - //Work out what is visible - var visibleLayer = layer, - currentZoom = this._zoom; - if (layer.__parent) { - while (visibleLayer.__parent._zoom >= currentZoom) { - visibleLayer = visibleLayer.__parent; - } - } - - if (this._currentShownBounds.contains(visibleLayer.getLatLng())) { - if (this.options.animateAddingMarkers) { - this._animationAddLayer(layer, visibleLayer); - } else { - this._animationAddLayerNonAnimated(layer, visibleLayer); - } - } - return this; - }, - - removeLayer: function (layer) { - - if (layer instanceof L.LayerGroup) { - return this.removeLayers([layer]); - } - - //Non point layers - if (!layer.getLatLng) { - this._nonPointGroup.removeLayer(layer); - this.fire('layerremove', { layer: layer }); - return this; - } - - if (!this._map) { - if (!this._arraySplice(this._needsClustering, layer) && this.hasLayer(layer)) { - this._needsRemoving.push({ layer: layer, latlng: layer._latlng }); - } - this.fire('layerremove', { layer: layer }); - return this; - } - - if (!layer.__parent) { - return this; - } - - if (this._unspiderfy) { - this._unspiderfy(); - this._unspiderfyLayer(layer); - } - - //Remove the marker from clusters - this._removeLayer(layer, true); - this.fire('layerremove', { layer: layer }); - - // Refresh bounds and weighted positions. - this._topClusterLevel._recalculateBounds(); - - this._refreshClustersIcons(); - - layer.off(this._childMarkerEventHandlers, this); - - if (this._featureGroup.hasLayer(layer)) { - this._featureGroup.removeLayer(layer); - if (layer.clusterShow) { - layer.clusterShow(); - } - } - - return this; - }, - - //Takes an array of markers and adds them in bulk - addLayers: function (layersArray, skipLayerAddEvent) { - if (!L.Util.isArray(layersArray)) { - return this.addLayer(layersArray); - } - - var fg = this._featureGroup, - npg = this._nonPointGroup, - chunked = this.options.chunkedLoading, - chunkInterval = this.options.chunkInterval, - chunkProgress = this.options.chunkProgress, - l = layersArray.length, - offset = 0, - originalArray = true, - m; - - if (this._map) { - var started = (new Date()).getTime(); - var process = L.bind(function () { - var start = (new Date()).getTime(); - for (; offset < l; offset++) { - if (chunked && offset % 200 === 0) { - // every couple hundred markers, instrument the time elapsed since processing started: - var elapsed = (new Date()).getTime() - start; - if (elapsed > chunkInterval) { - break; // been working too hard, time to take a break :-) - } - } - - m = layersArray[offset]; - - // Group of layers, append children to layersArray and skip. - // Side effects: - // - Total increases, so chunkProgress ratio jumps backward. - // - Groups are not included in this group, only their non-group child layers (hasLayer). - // Changing array length while looping does not affect performance in current browsers: - // http://jsperf.com/for-loop-changing-length/6 - if (m instanceof L.LayerGroup) { - if (originalArray) { - layersArray = layersArray.slice(); - originalArray = false; - } - this._extractNonGroupLayers(m, layersArray); - l = layersArray.length; - continue; - } - - //Not point data, can't be clustered - if (!m.getLatLng) { - npg.addLayer(m); - if (!skipLayerAddEvent) { - this.fire('layeradd', { layer: m }); - } - continue; - } - - if (this.hasLayer(m)) { - continue; - } - - this._addLayer(m, this._maxZoom); - if (!skipLayerAddEvent) { - this.fire('layeradd', { layer: m }); - } - - //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 - if (m.__parent) { - if (m.__parent.getChildCount() === 2) { - var markers = m.__parent.getAllChildMarkers(), - otherMarker = markers[0] === m ? markers[1] : markers[0]; - fg.removeLayer(otherMarker); - } - } - } - - if (chunkProgress) { - // report progress and time elapsed: - chunkProgress(offset, l, (new Date()).getTime() - started); - } - - // Completed processing all markers. - if (offset === l) { - - // Refresh bounds and weighted positions. - this._topClusterLevel._recalculateBounds(); - - this._refreshClustersIcons(); - - this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds); - } else { - setTimeout(process, this.options.chunkDelay); - } - }, this); - - process(); - } else { - var needsClustering = this._needsClustering; - - for (; offset < l; offset++) { - m = layersArray[offset]; - - // Group of layers, append children to layersArray and skip. - if (m instanceof L.LayerGroup) { - if (originalArray) { - layersArray = layersArray.slice(); - originalArray = false; - } - this._extractNonGroupLayers(m, layersArray); - l = layersArray.length; - continue; - } - - //Not point data, can't be clustered - if (!m.getLatLng) { - npg.addLayer(m); - continue; - } - - if (this.hasLayer(m)) { - continue; - } - - needsClustering.push(m); - } - } - return this; - }, - - //Takes an array of markers and removes them in bulk - removeLayers: function (layersArray) { - var i, m, - l = layersArray.length, - fg = this._featureGroup, - npg = this._nonPointGroup, - originalArray = true; - - if (!this._map) { - for (i = 0; i < l; i++) { - m = layersArray[i]; - - // Group of layers, append children to layersArray and skip. - if (m instanceof L.LayerGroup) { - if (originalArray) { - layersArray = layersArray.slice(); - originalArray = false; - } - this._extractNonGroupLayers(m, layersArray); - l = layersArray.length; - continue; - } - - this._arraySplice(this._needsClustering, m); - npg.removeLayer(m); - if (this.hasLayer(m)) { - this._needsRemoving.push({ layer: m, latlng: m._latlng }); - } - this.fire('layerremove', { layer: m }); - } - return this; - } - - if (this._unspiderfy) { - this._unspiderfy(); - - // Work on a copy of the array, so that next loop is not affected. - var layersArray2 = layersArray.slice(), - l2 = l; - for (i = 0; i < l2; i++) { - m = layersArray2[i]; - - // Group of layers, append children to layersArray and skip. - if (m instanceof L.LayerGroup) { - this._extractNonGroupLayers(m, layersArray2); - l2 = layersArray2.length; - continue; - } - - this._unspiderfyLayer(m); - } - } - - for (i = 0; i < l; i++) { - m = layersArray[i]; - - // Group of layers, append children to layersArray and skip. - if (m instanceof L.LayerGroup) { - if (originalArray) { - layersArray = layersArray.slice(); - originalArray = false; - } - this._extractNonGroupLayers(m, layersArray); - l = layersArray.length; - continue; - } - - if (!m.__parent) { - npg.removeLayer(m); - this.fire('layerremove', { layer: m }); - continue; - } - - this._removeLayer(m, true, true); - this.fire('layerremove', { layer: m }); - - if (fg.hasLayer(m)) { - fg.removeLayer(m); - if (m.clusterShow) { - m.clusterShow(); - } - } - } - - // Refresh bounds and weighted positions. - this._topClusterLevel._recalculateBounds(); - - this._refreshClustersIcons(); - - //Fix up the clusters and markers on the map - this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds); - - return this; - }, - - //Removes all layers from the MarkerClusterGroup - clearLayers: function () { - //Need our own special implementation as the LayerGroup one doesn't work for us - - //If we aren't on the map (yet), blow away the markers we know of - if (!this._map) { - this._needsClustering = []; - delete this._gridClusters; - delete this._gridUnclustered; - } - - if (this._noanimationUnspiderfy) { - this._noanimationUnspiderfy(); - } - - //Remove all the visible layers - this._featureGroup.clearLayers(); - this._nonPointGroup.clearLayers(); - - this.eachLayer(function (marker) { - marker.off(this._childMarkerEventHandlers, this); - delete marker.__parent; - }, this); - - if (this._map) { - //Reset _topClusterLevel and the DistanceGrids - this._generateInitialClusters(); - } - - return this; - }, - - //Override FeatureGroup.getBounds as it doesn't work - getBounds: function () { - var bounds = new L.LatLngBounds(); - - if (this._topClusterLevel) { - bounds.extend(this._topClusterLevel._bounds); - } - - for (var i = this._needsClustering.length - 1; i >= 0; i--) { - bounds.extend(this._needsClustering[i].getLatLng()); - } - - bounds.extend(this._nonPointGroup.getBounds()); - - return bounds; - }, - - //Overrides LayerGroup.eachLayer - eachLayer: function (method, context) { - var markers = this._needsClustering.slice(), - needsRemoving = this._needsRemoving, - thisNeedsRemoving, i, j; - - if (this._topClusterLevel) { - this._topClusterLevel.getAllChildMarkers(markers); - } - - for (i = markers.length - 1; i >= 0; i--) { - thisNeedsRemoving = true; - - for (j = needsRemoving.length - 1; j >= 0; j--) { - if (needsRemoving[j].layer === markers[i]) { - thisNeedsRemoving = false; - break; - } - } - - if (thisNeedsRemoving) { - method.call(context, markers[i]); - } - } - - this._nonPointGroup.eachLayer(method, context); - }, - - //Overrides LayerGroup.getLayers - getLayers: function () { - var layers = []; - this.eachLayer(function (l) { - layers.push(l); - }); - return layers; - }, - - //Overrides LayerGroup.getLayer, WARNING: Really bad performance - getLayer: function (id) { - var result = null; - - id = parseInt(id, 10); - - this.eachLayer(function (l) { - if (L.stamp(l) === id) { - result = l; - } - }); - - return result; - }, - - //Returns true if the given layer is in this MarkerClusterGroup - hasLayer: function (layer) { - if (!layer) { - return false; - } - - var i, anArray = this._needsClustering; - - for (i = anArray.length - 1; i >= 0; i--) { - if (anArray[i] === layer) { - return true; - } - } - - anArray = this._needsRemoving; - for (i = anArray.length - 1; i >= 0; i--) { - if (anArray[i].layer === layer) { - return false; - } - } - - return !!(layer.__parent && layer.__parent._group === this) || this._nonPointGroup.hasLayer(layer); - }, - - //Zoom down to show the given layer (spiderfying if necessary) then calls the callback - zoomToShowLayer: function (layer, callback) { - - if (typeof callback !== 'function') { - callback = function () {}; - } - - var showMarker = function () { - if ((layer._icon || layer.__parent._icon) && !this._inZoomAnimation) { - this._map.off('moveend', showMarker, this); - this.off('animationend', showMarker, this); - - if (layer._icon) { - callback(); - } else if (layer.__parent._icon) { - this.once('spiderfied', callback, this); - layer.__parent.spiderfy(); - } - } - }; - - if (layer._icon && this._map.getBounds().contains(layer.getLatLng())) { - //Layer is visible ond on screen, immediate return - callback(); - } else if (layer.__parent._zoom < Math.round(this._map._zoom)) { - //Layer should be visible at this zoom level. It must not be on screen so just pan over to it - this._map.on('moveend', showMarker, this); - this._map.panTo(layer.getLatLng()); - } else { - this._map.on('moveend', showMarker, this); - this.on('animationend', showMarker, this); - layer.__parent.zoomToBounds(); - } - }, - - //Overrides FeatureGroup.onAdd - onAdd: function (map) { - this._map = map; - var i, l, layer; - - if (!isFinite(this._map.getMaxZoom())) { - throw "Map has no maxZoom specified"; - } - - this._featureGroup.addTo(map); - this._nonPointGroup.addTo(map); - - if (!this._gridClusters) { - this._generateInitialClusters(); - } - - this._maxLat = map.options.crs.projection.MAX_LATITUDE; - - //Restore all the positions as they are in the MCG before removing them - for (i = 0, l = this._needsRemoving.length; i < l; i++) { - layer = this._needsRemoving[i]; - layer.newlatlng = layer.layer._latlng; - layer.layer._latlng = layer.latlng; - } - //Remove them, then restore their new positions - for (i = 0, l = this._needsRemoving.length; i < l; i++) { - layer = this._needsRemoving[i]; - this._removeLayer(layer.layer, true); - layer.layer._latlng = layer.newlatlng; - } - this._needsRemoving = []; - - //Remember the current zoom level and bounds - this._zoom = Math.round(this._map._zoom); - this._currentShownBounds = this._getExpandedVisibleBounds(); - - this._map.on('zoomend', this._zoomEnd, this); - this._map.on('moveend', this._moveEnd, this); - - if (this._spiderfierOnAdd) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely - this._spiderfierOnAdd(); - } - - this._bindEvents(); - - //Actually add our markers to the map: - l = this._needsClustering; - this._needsClustering = []; - this.addLayers(l, true); - }, - - //Overrides FeatureGroup.onRemove - onRemove: function (map) { - map.off('zoomend', this._zoomEnd, this); - map.off('moveend', this._moveEnd, this); - - this._unbindEvents(); - - //In case we are in a cluster animation - this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', ''); - - if (this._spiderfierOnRemove) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely - this._spiderfierOnRemove(); - } - - delete this._maxLat; - - //Clean up all the layers we added to the map - this._hideCoverage(); - this._featureGroup.remove(); - this._nonPointGroup.remove(); - - this._featureGroup.clearLayers(); - - this._map = null; - }, - - getVisibleParent: function (marker) { - var vMarker = marker; - while (vMarker && !vMarker._icon) { - vMarker = vMarker.__parent; - } - return vMarker || null; - }, - - //Remove the given object from the given array - _arraySplice: function (anArray, obj) { - for (var i = anArray.length - 1; i >= 0; i--) { - if (anArray[i] === obj) { - anArray.splice(i, 1); - return true; - } - } - }, - - /** - * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom. - * @param marker to be removed from _gridUnclustered. - * @param z integer bottom start zoom level (included) - * @private - */ - _removeFromGridUnclustered: function (marker, z) { - var map = this._map, - gridUnclustered = this._gridUnclustered, - minZoom = Math.floor(this._map.getMinZoom()); - - for (; z >= minZoom; z--) { - if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) { - break; - } - } - }, - - _childMarkerDragStart: function (e) { - e.target.__dragStart = e.target._latlng; - }, - - _childMarkerMoved: function (e) { - if (!this._ignoreMove && !e.target.__dragStart) { - var isPopupOpen = e.target._popup && e.target._popup.isOpen(); - - this._moveChild(e.target, e.oldLatLng, e.latlng); - - if (isPopupOpen) { - e.target.openPopup(); - } - } - }, - - _moveChild: function (layer, from, to) { - layer._latlng = from; - this.removeLayer(layer); - - layer._latlng = to; - this.addLayer(layer); - }, - - _childMarkerDragEnd: function (e) { - if (e.target.__dragStart) { - this._moveChild(e.target, e.target.__dragStart, e.target._latlng); - } - delete e.target.__dragStart; - }, - - - //Internal function for removing a marker from everything. - //dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions) - _removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) { - var gridClusters = this._gridClusters, - gridUnclustered = this._gridUnclustered, - fg = this._featureGroup, - map = this._map, - minZoom = Math.floor(this._map.getMinZoom()); - - //Remove the marker from distance clusters it might be in - if (removeFromDistanceGrid) { - this._removeFromGridUnclustered(marker, this._maxZoom); - } - - //Work our way up the clusters removing them as we go if required - var cluster = marker.__parent, - markers = cluster._markers, - otherMarker; - - //Remove the marker from the immediate parents marker list - this._arraySplice(markers, marker); - - while (cluster) { - cluster._childCount--; - cluster._boundsNeedUpdate = true; - - if (cluster._zoom < minZoom) { - //Top level, do nothing - break; - } else if (removeFromDistanceGrid && cluster._childCount <= 1) { //Cluster no longer required - //We need to push the other marker up to the parent - otherMarker = cluster._markers[0] === marker ? cluster._markers[1] : cluster._markers[0]; - - //Update distance grid - gridClusters[cluster._zoom].removeObject(cluster, map.project(cluster._cLatLng, cluster._zoom)); - gridUnclustered[cluster._zoom].addObject(otherMarker, map.project(otherMarker.getLatLng(), cluster._zoom)); - - //Move otherMarker up to parent - this._arraySplice(cluster.__parent._childClusters, cluster); - cluster.__parent._markers.push(otherMarker); - otherMarker.__parent = cluster.__parent; - - if (cluster._icon) { - //Cluster is currently on the map, need to put the marker on the map instead - fg.removeLayer(cluster); - if (!dontUpdateMap) { - fg.addLayer(otherMarker); - } - } - } else { - cluster._iconNeedsUpdate = true; - } - - cluster = cluster.__parent; - } - - delete marker.__parent; - }, - - _isOrIsParent: function (el, oel) { - while (oel) { - if (el === oel) { - return true; - } - oel = oel.parentNode; - } - return false; - }, - - //Override L.Evented.fire - fire: function (type, data, propagate) { - if (data && data.layer instanceof L.MarkerCluster) { - //Prevent multiple clustermouseover/off events if the icon is made up of stacked divs (Doesn't work in ie <= 8, no relatedTarget) - if (data.originalEvent && this._isOrIsParent(data.layer._icon, data.originalEvent.relatedTarget)) { - return; - } - type = 'cluster' + type; - } - - L.FeatureGroup.prototype.fire.call(this, type, data, propagate); - }, - - //Override L.Evented.listens - listens: function (type, propagate) { - return L.FeatureGroup.prototype.listens.call(this, type, propagate) || L.FeatureGroup.prototype.listens.call(this, 'cluster' + type, propagate); - }, - - //Default functionality - _defaultIconCreateFunction: function (cluster) { - var childCount = cluster.getChildCount(); - - var c = ' marker-cluster-'; - if (childCount < 10) { - c += 'small'; - } else if (childCount < 100) { - c += 'medium'; - } else { - c += 'large'; - } - - return new L.DivIcon({ html: '
' + childCount + '
', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) }); - }, - - _bindEvents: function () { - var map = this._map, - spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom, - showCoverageOnHover = this.options.showCoverageOnHover, - zoomToBoundsOnClick = this.options.zoomToBoundsOnClick; - - //Zoom on cluster click or spiderfy if we are at the lowest level - if (spiderfyOnMaxZoom || zoomToBoundsOnClick) { - this.on('clusterclick', this._zoomOrSpiderfy, this); - } - - //Show convex hull (boundary) polygon on mouse over - if (showCoverageOnHover) { - this.on('clustermouseover', this._showCoverage, this); - this.on('clustermouseout', this._hideCoverage, this); - map.on('zoomend', this._hideCoverage, this); - } - }, - - _zoomOrSpiderfy: function (e) { - var cluster = e.layer, - bottomCluster = cluster; - - while (bottomCluster._childClusters.length === 1) { - bottomCluster = bottomCluster._childClusters[0]; - } - - if (bottomCluster._zoom === this._maxZoom && - bottomCluster._childCount === cluster._childCount && - this.options.spiderfyOnMaxZoom) { - - // All child markers are contained in a single cluster from this._maxZoom to this cluster. - cluster.spiderfy(); - } else if (this.options.zoomToBoundsOnClick) { - cluster.zoomToBounds(); - } - - // Focus the map again for keyboard users. - if (e.originalEvent && e.originalEvent.keyCode === 13) { - this._map._container.focus(); - } - }, - - _showCoverage: function (e) { - var map = this._map; - if (this._inZoomAnimation) { - return; - } - if (this._shownPolygon) { - map.removeLayer(this._shownPolygon); - } - if (e.layer.getChildCount() > 2 && e.layer !== this._spiderfied) { - this._shownPolygon = new L.Polygon(e.layer.getConvexHull(), this.options.polygonOptions); - map.addLayer(this._shownPolygon); - } - }, - - _hideCoverage: function () { - if (this._shownPolygon) { - this._map.removeLayer(this._shownPolygon); - this._shownPolygon = null; - } - }, - - _unbindEvents: function () { - var spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom, - showCoverageOnHover = this.options.showCoverageOnHover, - zoomToBoundsOnClick = this.options.zoomToBoundsOnClick, - map = this._map; - - if (spiderfyOnMaxZoom || zoomToBoundsOnClick) { - this.off('clusterclick', this._zoomOrSpiderfy, this); - } - if (showCoverageOnHover) { - this.off('clustermouseover', this._showCoverage, this); - this.off('clustermouseout', this._hideCoverage, this); - map.off('zoomend', this._hideCoverage, this); - } - }, - - _zoomEnd: function () { - if (!this._map) { //May have been removed from the map by a zoomEnd handler - return; - } - this._mergeSplitClusters(); - - this._zoom = Math.round(this._map._zoom); - this._currentShownBounds = this._getExpandedVisibleBounds(); - }, - - _moveEnd: function () { - if (this._inZoomAnimation) { - return; - } - - var newBounds = this._getExpandedVisibleBounds(); - - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, newBounds); - this._topClusterLevel._recursivelyAddChildrenToMap(null, Math.round(this._map._zoom), newBounds); - - this._currentShownBounds = newBounds; - return; - }, - - _generateInitialClusters: function () { - var maxZoom = Math.ceil(this._map.getMaxZoom()), - minZoom = Math.floor(this._map.getMinZoom()), - radius = this.options.maxClusterRadius, - radiusFn = radius; - - //If we just set maxClusterRadius to a single number, we need to create - //a simple function to return that number. Otherwise, we just have to - //use the function we've passed in. - if (typeof radius !== "function") { - radiusFn = function () { return radius; }; - } - - if (this.options.disableClusteringAtZoom !== null) { - maxZoom = this.options.disableClusteringAtZoom - 1; - } - this._maxZoom = maxZoom; - this._gridClusters = {}; - this._gridUnclustered = {}; - - //Set up DistanceGrids for each zoom - for (var zoom = maxZoom; zoom >= minZoom; zoom--) { - this._gridClusters[zoom] = new L.DistanceGrid(radiusFn(zoom)); - this._gridUnclustered[zoom] = new L.DistanceGrid(radiusFn(zoom)); - } - - // Instantiate the appropriate L.MarkerCluster class (animated or not). - this._topClusterLevel = new this._markerCluster(this, minZoom - 1); - }, - - //Zoom: Zoom to start adding at (Pass this._maxZoom to start at the bottom) - _addLayer: function (layer, zoom) { - var gridClusters = this._gridClusters, - gridUnclustered = this._gridUnclustered, - minZoom = Math.floor(this._map.getMinZoom()), - markerPoint, z; - - if (this.options.singleMarkerMode) { - this._overrideMarkerIcon(layer); - } - - layer.on(this._childMarkerEventHandlers, this); - - //Find the lowest zoom level to slot this one in - for (; zoom >= minZoom; zoom--) { - markerPoint = this._map.project(layer.getLatLng(), zoom); // calculate pixel position - - //Try find a cluster close by - var closest = gridClusters[zoom].getNearObject(markerPoint); - if (closest) { - closest._addChild(layer); - layer.__parent = closest; - return; - } - - //Try find a marker close by to form a new cluster with - closest = gridUnclustered[zoom].getNearObject(markerPoint); - if (closest) { - var parent = closest.__parent; - if (parent) { - this._removeLayer(closest, false); - } - - //Create new cluster with these 2 in it - - var newCluster = new this._markerCluster(this, zoom, closest, layer); - gridClusters[zoom].addObject(newCluster, this._map.project(newCluster._cLatLng, zoom)); - closest.__parent = newCluster; - layer.__parent = newCluster; - - //First create any new intermediate parent clusters that don't exist - var lastParent = newCluster; - for (z = zoom - 1; z > parent._zoom; z--) { - lastParent = new this._markerCluster(this, z, lastParent); - gridClusters[z].addObject(lastParent, this._map.project(closest.getLatLng(), z)); - } - parent._addChild(lastParent); - - //Remove closest from this zoom level and any above that it is in, replace with newCluster - this._removeFromGridUnclustered(closest, zoom); - - return; - } - - //Didn't manage to cluster in at this zoom, record us as a marker here and continue upwards - gridUnclustered[zoom].addObject(layer, markerPoint); - } - - //Didn't get in anything, add us to the top - this._topClusterLevel._addChild(layer); - layer.__parent = this._topClusterLevel; - return; - }, - - /** - * Refreshes the icon of all "dirty" visible clusters. - * Non-visible "dirty" clusters will be updated when they are added to the map. - * @private - */ - _refreshClustersIcons: function () { - this._featureGroup.eachLayer(function (c) { - if (c instanceof L.MarkerCluster && c._iconNeedsUpdate) { - c._updateIcon(); - } - }); - }, - - //Enqueue code to fire after the marker expand/contract has happened - _enqueue: function (fn) { - this._queue.push(fn); - if (!this._queueTimeout) { - this._queueTimeout = setTimeout(L.bind(this._processQueue, this), 300); - } - }, - _processQueue: function () { - for (var i = 0; i < this._queue.length; i++) { - this._queue[i].call(this); - } - this._queue.length = 0; - clearTimeout(this._queueTimeout); - this._queueTimeout = null; - }, - - //Merge and split any existing clusters that are too big or small - _mergeSplitClusters: function () { - var mapZoom = Math.round(this._map._zoom); - - //In case we are starting to split before the animation finished - this._processQueue(); - - if (this._zoom < mapZoom && this._currentShownBounds.intersects(this._getExpandedVisibleBounds())) { //Zoom in, split - this._animationStart(); - //Remove clusters now off screen - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, this._getExpandedVisibleBounds()); - - this._animationZoomIn(this._zoom, mapZoom); - - } else if (this._zoom > mapZoom) { //Zoom out, merge - this._animationStart(); - - this._animationZoomOut(this._zoom, mapZoom); - } else { - this._moveEnd(); - } - }, - - //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) - _getExpandedVisibleBounds: function () { - if (!this.options.removeOutsideVisibleBounds) { - return this._mapBoundsInfinite; - } else if (L.Browser.mobile) { - return this._checkBoundsMaxLat(this._map.getBounds()); - } - - return this._checkBoundsMaxLat(this._map.getBounds().pad(1)); // Padding expands the bounds by its own dimensions but scaled with the given factor. - }, - - /** - * Expands the latitude to Infinity (or -Infinity) if the input bounds reach the map projection maximum defined latitude - * (in the case of Web/Spherical Mercator, it is 85.0511287798 / see https://en.wikipedia.org/wiki/Web_Mercator#Formulas). - * Otherwise, the removeOutsideVisibleBounds option will remove markers beyond that limit, whereas the same markers without - * this option (or outside MCG) will have their position floored (ceiled) by the projection and rendered at that limit, - * making the user think that MCG "eats" them and never displays them again. - * @param bounds L.LatLngBounds - * @returns {L.LatLngBounds} - * @private - */ - _checkBoundsMaxLat: function (bounds) { - var maxLat = this._maxLat; - - if (maxLat !== undefined) { - if (bounds.getNorth() >= maxLat) { - bounds._northEast.lat = Infinity; - } - if (bounds.getSouth() <= -maxLat) { - bounds._southWest.lat = -Infinity; - } - } - - return bounds; - }, - - //Shared animation code - _animationAddLayerNonAnimated: function (layer, newCluster) { - if (newCluster === layer) { - this._featureGroup.addLayer(layer); - } else if (newCluster._childCount === 2) { - newCluster._addToMap(); - - var markers = newCluster.getAllChildMarkers(); - this._featureGroup.removeLayer(markers[0]); - this._featureGroup.removeLayer(markers[1]); - } else { - newCluster._updateIcon(); - } - }, - - /** - * Extracts individual (i.e. non-group) layers from a Layer Group. - * @param group to extract layers from. - * @param output {Array} in which to store the extracted layers. - * @returns {*|Array} - * @private - */ - _extractNonGroupLayers: function (group, output) { - var layers = group.getLayers(), - i = 0, - layer; - - output = output || []; - - for (; i < layers.length; i++) { - layer = layers[i]; - - if (layer instanceof L.LayerGroup) { - this._extractNonGroupLayers(layer, output); - continue; - } - - output.push(layer); - } - - return output; - }, - - /** - * Implements the singleMarkerMode option. - * @param layer Marker to re-style using the Clusters iconCreateFunction. - * @returns {L.Icon} The newly created icon. - * @private - */ - _overrideMarkerIcon: function (layer) { - var icon = layer.options.icon = this.options.iconCreateFunction({ - getChildCount: function () { - return 1; - }, - getAllChildMarkers: function () { - return [layer]; - } - }); - - return icon; - } -}); - -// Constant bounds used in case option "removeOutsideVisibleBounds" is set to false. -L.MarkerClusterGroup.include({ - _mapBoundsInfinite: new L.LatLngBounds(new L.LatLng(-Infinity, -Infinity), new L.LatLng(Infinity, Infinity)) -}); - -L.MarkerClusterGroup.include({ - _noAnimation: { - //Non Animated versions of everything - _animationStart: function () { - //Do nothing... - }, - _animationZoomIn: function (previousZoomLevel, newZoomLevel) { - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel); - this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); - - //We didn't actually animate, but we use this event to mean "clustering animations have finished" - this.fire('animationend'); - }, - _animationZoomOut: function (previousZoomLevel, newZoomLevel) { - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel); - this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); - - //We didn't actually animate, but we use this event to mean "clustering animations have finished" - this.fire('animationend'); - }, - _animationAddLayer: function (layer, newCluster) { - this._animationAddLayerNonAnimated(layer, newCluster); - } - }, - - _withAnimation: { - //Animated versions here - _animationStart: function () { - this._map._mapPane.className += ' leaflet-cluster-anim'; - this._inZoomAnimation++; - }, - - _animationZoomIn: function (previousZoomLevel, newZoomLevel) { - var bounds = this._getExpandedVisibleBounds(), - fg = this._featureGroup, - minZoom = Math.floor(this._map.getMinZoom()), - i; - - this._ignoreMove = true; - - //Add all children of current clusters to map and remove those clusters from map - this._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) { - var startPos = c._latlng, - markers = c._markers, - m; - - if (!bounds.contains(startPos)) { - startPos = null; - } - - if (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us - fg.removeLayer(c); - c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds); - } else { - //Fade out old cluster - c.clusterHide(); - c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds); - } - - //Remove all markers that aren't visible any more - //TODO: Do we actually need to do this on the higher levels too? - for (i = markers.length - 1; i >= 0; i--) { - m = markers[i]; - if (!bounds.contains(m._latlng)) { - fg.removeLayer(m); - } - } - - }); - - this._forceLayout(); - - //Update opacities - this._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel); - //TODO Maybe? Update markers in _recursivelyBecomeVisible - fg.eachLayer(function (n) { - if (!(n instanceof L.MarkerCluster) && n._icon) { - n.clusterShow(); - } - }); - - //update the positions of the just added clusters/markers - this._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) { - c._recursivelyRestoreChildPositions(newZoomLevel); - }); - - this._ignoreMove = false; - - //Remove the old clusters and close the zoom animation - this._enqueue(function () { - //update the positions of the just added clusters/markers - this._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) { - fg.removeLayer(c); - c.clusterShow(); - }); - - this._animationEnd(); - }); - }, - - _animationZoomOut: function (previousZoomLevel, newZoomLevel) { - this._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel); - - //Need to add markers for those that weren't on the map before but are now - this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); - //Remove markers that were on the map before but won't be now - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel, this._getExpandedVisibleBounds()); - }, - - _animationAddLayer: function (layer, newCluster) { - var me = this, - fg = this._featureGroup; - - fg.addLayer(layer); - if (newCluster !== layer) { - if (newCluster._childCount > 2) { //Was already a cluster - - newCluster._updateIcon(); - this._forceLayout(); - this._animationStart(); - - layer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng())); - layer.clusterHide(); - - this._enqueue(function () { - fg.removeLayer(layer); - layer.clusterShow(); - - me._animationEnd(); - }); - - } else { //Just became a cluster - this._forceLayout(); - - me._animationStart(); - me._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._zoom); - } - } - } - }, - - // Private methods for animated versions. - _animationZoomOutSingle: function (cluster, previousZoomLevel, newZoomLevel) { - var bounds = this._getExpandedVisibleBounds(), - minZoom = Math.floor(this._map.getMinZoom()); - - //Animate all of the markers in the clusters to move to their cluster center point - cluster._recursivelyAnimateChildrenInAndAddSelfToMap(bounds, minZoom, previousZoomLevel + 1, newZoomLevel); - - var me = this; - - //Update the opacity (If we immediately set it they won't animate) - this._forceLayout(); - cluster._recursivelyBecomeVisible(bounds, newZoomLevel); - - //TODO: Maybe use the transition timing stuff to make this more reliable - //When the animations are done, tidy up - this._enqueue(function () { - - //This cluster stopped being a cluster before the timeout fired - if (cluster._childCount === 1) { - var m = cluster._markers[0]; - //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 - this._ignoreMove = true; - m.setLatLng(m.getLatLng()); - this._ignoreMove = false; - if (m.clusterShow) { - m.clusterShow(); - } - } else { - cluster._recursively(bounds, newZoomLevel, minZoom, function (c) { - c._recursivelyRemoveChildrenFromMap(bounds, minZoom, previousZoomLevel + 1); - }); - } - me._animationEnd(); - }); - }, - - _animationEnd: function () { - if (this._map) { - this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', ''); - } - this._inZoomAnimation--; - this.fire('animationend'); - }, - - //Force a browser layout of stuff in the map - // Should apply the current opacity and location to all elements so we can update them again for an animation - _forceLayout: function () { - //In my testing this works, infact offsetWidth of any element seems to work. - //Could loop all this._layers and do this for each _icon if it stops working - - L.Util.falseFn(document.body.offsetWidth); - } -}); - -L.markerClusterGroup = function (options) { - return new L.MarkerClusterGroup(options); -}; - - -L.MarkerCluster = L.Marker.extend({ - initialize: function (group, zoom, a, b) { - - L.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0), - { icon: this, pane: group.options.clusterPane }); - - this._group = group; - this._zoom = zoom; - - this._markers = []; - this._childClusters = []; - this._childCount = 0; - this._iconNeedsUpdate = true; - this._boundsNeedUpdate = true; - - this._bounds = new L.LatLngBounds(); - - if (a) { - this._addChild(a); - } - if (b) { - this._addChild(b); - } - }, - - //Recursively retrieve all child markers of this cluster - getAllChildMarkers: function (storageArray) { - storageArray = storageArray || []; - - for (var i = this._childClusters.length - 1; i >= 0; i--) { - this._childClusters[i].getAllChildMarkers(storageArray); - } - - for (var j = this._markers.length - 1; j >= 0; j--) { - storageArray.push(this._markers[j]); - } - - return storageArray; - }, - - //Returns the count of how many child markers we have - getChildCount: function () { - return this._childCount; - }, - - //Zoom to the minimum of showing all of the child markers, or the extents of this cluster - zoomToBounds: function (fitBoundsOptions) { - var childClusters = this._childClusters.slice(), - map = this._group._map, - boundsZoom = map.getBoundsZoom(this._bounds), - zoom = this._zoom + 1, - mapZoom = map.getZoom(), - i; - - //calculate how far we need to zoom down to see all of the markers - while (childClusters.length > 0 && boundsZoom > zoom) { - zoom++; - var newClusters = []; - for (i = 0; i < childClusters.length; i++) { - newClusters = newClusters.concat(childClusters[i]._childClusters); - } - childClusters = newClusters; - } - - if (boundsZoom > zoom) { - this._group._map.setView(this._latlng, zoom); - } else if (boundsZoom <= mapZoom) { //If fitBounds wouldn't zoom us down, zoom us down instead - this._group._map.setView(this._latlng, mapZoom + 1); - } else { - this._group._map.fitBounds(this._bounds, fitBoundsOptions); - } - }, - - getBounds: function () { - var bounds = new L.LatLngBounds(); - bounds.extend(this._bounds); - return bounds; - }, - - _updateIcon: function () { - this._iconNeedsUpdate = true; - if (this._icon) { - this.setIcon(this); - } - }, - - //Cludge for Icon, we pretend to be an icon for performance - createIcon: function () { - if (this._iconNeedsUpdate) { - this._iconObj = this._group.options.iconCreateFunction(this); - this._iconNeedsUpdate = false; - } - return this._iconObj.createIcon(); - }, - createShadow: function () { - return this._iconObj.createShadow(); - }, - - - _addChild: function (new1, isNotificationFromChild) { - - this._iconNeedsUpdate = true; - - this._boundsNeedUpdate = true; - this._setClusterCenter(new1); - - if (new1 instanceof L.MarkerCluster) { - if (!isNotificationFromChild) { - this._childClusters.push(new1); - new1.__parent = this; - } - this._childCount += new1._childCount; - } else { - if (!isNotificationFromChild) { - this._markers.push(new1); - } - this._childCount++; - } - - if (this.__parent) { - this.__parent._addChild(new1, true); - } - }, - - /** - * Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position. - * @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet. - * @private - */ - _setClusterCenter: function (child) { - if (!this._cLatLng) { - // when clustering, take position of the first point as the cluster center - this._cLatLng = child._cLatLng || child._latlng; - } - }, - - /** - * Assigns impossible bounding values so that the next extend entirely determines the new bounds. - * This method avoids having to trash the previous L.LatLngBounds object and to create a new one, which is much slower for this class. - * As long as the bounds are not extended, most other methods would probably fail, as they would with bounds initialized but not extended. - * @private - */ - _resetBounds: function () { - var bounds = this._bounds; - - if (bounds._southWest) { - bounds._southWest.lat = Infinity; - bounds._southWest.lng = Infinity; - } - if (bounds._northEast) { - bounds._northEast.lat = -Infinity; - bounds._northEast.lng = -Infinity; - } - }, - - _recalculateBounds: function () { - var markers = this._markers, - childClusters = this._childClusters, - latSum = 0, - lngSum = 0, - totalCount = this._childCount, - i, child, childLatLng, childCount; - - // Case where all markers are removed from the map and we are left with just an empty _topClusterLevel. - if (totalCount === 0) { - return; - } - - // Reset rather than creating a new object, for performance. - this._resetBounds(); - - // Child markers. - for (i = 0; i < markers.length; i++) { - childLatLng = markers[i]._latlng; - - this._bounds.extend(childLatLng); - - latSum += childLatLng.lat; - lngSum += childLatLng.lng; - } - - // Child clusters. - for (i = 0; i < childClusters.length; i++) { - child = childClusters[i]; - - // Re-compute child bounds and weighted position first if necessary. - if (child._boundsNeedUpdate) { - child._recalculateBounds(); - } - - this._bounds.extend(child._bounds); - - childLatLng = child._wLatLng; - childCount = child._childCount; - - latSum += childLatLng.lat * childCount; - lngSum += childLatLng.lng * childCount; - } - - this._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount); - - // Reset dirty flag. - this._boundsNeedUpdate = false; - }, - - //Set our markers position as given and add it to the map - _addToMap: function (startPos) { - if (startPos) { - this._backupLatlng = this._latlng; - this.setLatLng(startPos); - } - this._group._featureGroup.addLayer(this); - }, - - _recursivelyAnimateChildrenIn: function (bounds, center, maxZoom) { - this._recursively(bounds, this._group._map.getMinZoom(), maxZoom - 1, - function (c) { - var markers = c._markers, - i, m; - for (i = markers.length - 1; i >= 0; i--) { - m = markers[i]; - - //Only do it if the icon is still on the map - if (m._icon) { - m._setPos(center); - m.clusterHide(); - } - } - }, - function (c) { - var childClusters = c._childClusters, - j, cm; - for (j = childClusters.length - 1; j >= 0; j--) { - cm = childClusters[j]; - if (cm._icon) { - cm._setPos(center); - cm.clusterHide(); - } - } - } - ); - }, - - _recursivelyAnimateChildrenInAndAddSelfToMap: function (bounds, mapMinZoom, previousZoomLevel, newZoomLevel) { - this._recursively(bounds, newZoomLevel, mapMinZoom, - function (c) { - c._recursivelyAnimateChildrenIn(bounds, c._group._map.latLngToLayerPoint(c.getLatLng()).round(), previousZoomLevel); - - //TODO: depthToAnimateIn affects _isSingleParent, if there is a multizoom we may/may not be. - //As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate - if (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) { - c.clusterShow(); - c._recursivelyRemoveChildrenFromMap(bounds, mapMinZoom, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds - } else { - c.clusterHide(); - } - - c._addToMap(); - } - ); - }, - - _recursivelyBecomeVisible: function (bounds, zoomLevel) { - this._recursively(bounds, this._group._map.getMinZoom(), zoomLevel, null, function (c) { - c.clusterShow(); - }); - }, - - _recursivelyAddChildrenToMap: function (startPos, zoomLevel, bounds) { - this._recursively(bounds, this._group._map.getMinZoom() - 1, zoomLevel, - function (c) { - if (zoomLevel === c._zoom) { - return; - } - - //Add our child markers at startPos (so they can be animated out) - for (var i = c._markers.length - 1; i >= 0; i--) { - var nm = c._markers[i]; - - if (!bounds.contains(nm._latlng)) { - continue; - } - - if (startPos) { - nm._backupLatlng = nm.getLatLng(); - - nm.setLatLng(startPos); - if (nm.clusterHide) { - nm.clusterHide(); - } - } - - c._group._featureGroup.addLayer(nm); - } - }, - function (c) { - c._addToMap(startPos); - } - ); - }, - - _recursivelyRestoreChildPositions: function (zoomLevel) { - //Fix positions of child markers - for (var i = this._markers.length - 1; i >= 0; i--) { - var nm = this._markers[i]; - if (nm._backupLatlng) { - nm.setLatLng(nm._backupLatlng); - delete nm._backupLatlng; - } - } - - if (zoomLevel - 1 === this._zoom) { - //Reposition child clusters - for (var j = this._childClusters.length - 1; j >= 0; j--) { - this._childClusters[j]._restorePosition(); - } - } else { - for (var k = this._childClusters.length - 1; k >= 0; k--) { - this._childClusters[k]._recursivelyRestoreChildPositions(zoomLevel); - } - } - }, - - _restorePosition: function () { - if (this._backupLatlng) { - this.setLatLng(this._backupLatlng); - delete this._backupLatlng; - } - }, - - //exceptBounds: If set, don't remove any markers/clusters in it - _recursivelyRemoveChildrenFromMap: function (previousBounds, mapMinZoom, zoomLevel, exceptBounds) { - var m, i; - this._recursively(previousBounds, mapMinZoom - 1, zoomLevel - 1, - function (c) { - //Remove markers at every level - for (i = c._markers.length - 1; i >= 0; i--) { - m = c._markers[i]; - if (!exceptBounds || !exceptBounds.contains(m._latlng)) { - c._group._featureGroup.removeLayer(m); - if (m.clusterShow) { - m.clusterShow(); - } - } - } - }, - function (c) { - //Remove child clusters at just the bottom level - for (i = c._childClusters.length - 1; i >= 0; i--) { - m = c._childClusters[i]; - if (!exceptBounds || !exceptBounds.contains(m._latlng)) { - c._group._featureGroup.removeLayer(m); - if (m.clusterShow) { - m.clusterShow(); - } - } - } - } - ); - }, - - //Run the given functions recursively to this and child clusters - // boundsToApplyTo: a L.LatLngBounds representing the bounds of what clusters to recurse in to - // zoomLevelToStart: zoom level to start running functions (inclusive) - // zoomLevelToStop: zoom level to stop running functions (inclusive) - // runAtEveryLevel: function that takes an L.MarkerCluster as an argument that should be applied on every level - // runAtBottomLevel: function that takes an L.MarkerCluster as an argument that should be applied at only the bottom level - _recursively: function (boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel) { - var childClusters = this._childClusters, - zoom = this._zoom, - i, c; - - if (zoomLevelToStart <= zoom) { - if (runAtEveryLevel) { - runAtEveryLevel(this); - } - if (runAtBottomLevel && zoom === zoomLevelToStop) { - runAtBottomLevel(this); - } - } - - if (zoom < zoomLevelToStart || zoom < zoomLevelToStop) { - for (i = childClusters.length - 1; i >= 0; i--) { - c = childClusters[i]; - if (boundsToApplyTo.intersects(c._bounds)) { - c._recursively(boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel); - } - } - } - }, - - //Returns true if we are the parent of only one cluster and that cluster is the same as us - _isSingleParent: function () { - //Don't need to check this._markers as the rest won't work if there are any - return this._childClusters.length > 0 && this._childClusters[0]._childCount === this._childCount; - } -}); - - - -/* -* Extends L.Marker to include two extra methods: clusterHide and clusterShow. -* -* They work as setOpacity(0) and setOpacity(1) respectively, but -* they will remember the marker's opacity when hiding and showing it again. -* -*/ - - -L.Marker.include({ - - clusterHide: function () { - this.options.opacityWhenUnclustered = this.options.opacity || 1; - return this.setOpacity(0); - }, - - clusterShow: function () { - var ret = this.setOpacity(this.options.opacity || this.options.opacityWhenUnclustered); - delete this.options.opacityWhenUnclustered; - return ret; - } - -}); - - - - - -L.DistanceGrid = function (cellSize) { - this._cellSize = cellSize; - this._sqCellSize = cellSize * cellSize; - this._grid = {}; - this._objectPoint = { }; -}; - -L.DistanceGrid.prototype = { - - addObject: function (obj, point) { - var x = this._getCoord(point.x), - y = this._getCoord(point.y), - grid = this._grid, - row = grid[y] = grid[y] || {}, - cell = row[x] = row[x] || [], - stamp = L.Util.stamp(obj); - - this._objectPoint[stamp] = point; - - cell.push(obj); - }, - - updateObject: function (obj, point) { - this.removeObject(obj); - this.addObject(obj, point); - }, - - //Returns true if the object was found - removeObject: function (obj, point) { - var x = this._getCoord(point.x), - y = this._getCoord(point.y), - grid = this._grid, - row = grid[y] = grid[y] || {}, - cell = row[x] = row[x] || [], - i, len; - - delete this._objectPoint[L.Util.stamp(obj)]; - - for (i = 0, len = cell.length; i < len; i++) { - if (cell[i] === obj) { - - cell.splice(i, 1); - - if (len === 1) { - delete row[x]; - } - - return true; - } - } - - }, - - eachObject: function (fn, context) { - var i, j, k, len, row, cell, removed, - grid = this._grid; - - for (i in grid) { - row = grid[i]; - - for (j in row) { - cell = row[j]; - - for (k = 0, len = cell.length; k < len; k++) { - removed = fn.call(context, cell[k]); - if (removed) { - k--; - len--; - } - } - } - } - }, - - getNearObject: function (point) { - var x = this._getCoord(point.x), - y = this._getCoord(point.y), - i, j, k, row, cell, len, obj, dist, - objectPoint = this._objectPoint, - closestDistSq = this._sqCellSize, - closest = null; - - for (i = y - 1; i <= y + 1; i++) { - row = this._grid[i]; - if (row) { - - for (j = x - 1; j <= x + 1; j++) { - cell = row[j]; - if (cell) { - - for (k = 0, len = cell.length; k < len; k++) { - obj = cell[k]; - dist = this._sqDist(objectPoint[L.Util.stamp(obj)], point); - if (dist < closestDistSq || - dist <= closestDistSq && closest === null) { - closestDistSq = dist; - closest = obj; - } - } - } - } - } - } - return closest; - }, - - _getCoord: function (x) { - var coord = Math.floor(x / this._cellSize); - return isFinite(coord) ? coord : x; - }, - - _sqDist: function (p, p2) { - var dx = p2.x - p.x, - dy = p2.y - p.y; - return dx * dx + dy * dy; - } -}; - - -/* Copyright (c) 2012 the authors listed at the following URL, and/or -the authors of referenced articles or incorporated external code: -http://en.literateprograms.org/Quickhull_(Javascript)?action=history&offset=20120410175256 - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Retrieved from: http://en.literateprograms.org/Quickhull_(Javascript)?oldid=18434 -*/ - -(function () { - L.QuickHull = { - - /* - * @param {Object} cpt a point to be measured from the baseline - * @param {Array} bl the baseline, as represented by a two-element - * array of latlng objects. - * @returns {Number} an approximate distance measure - */ - getDistant: function (cpt, bl) { - var vY = bl[1].lat - bl[0].lat, - vX = bl[0].lng - bl[1].lng; - return (vX * (cpt.lat - bl[0].lat) + vY * (cpt.lng - bl[0].lng)); - }, - - /* - * @param {Array} baseLine a two-element array of latlng objects - * representing the baseline to project from - * @param {Array} latLngs an array of latlng objects - * @returns {Object} the maximum point and all new points to stay - * in consideration for the hull. - */ - findMostDistantPointFromBaseLine: function (baseLine, latLngs) { - var maxD = 0, - maxPt = null, - newPoints = [], - i, pt, d; - - for (i = latLngs.length - 1; i >= 0; i--) { - pt = latLngs[i]; - d = this.getDistant(pt, baseLine); - - if (d > 0) { - newPoints.push(pt); - } else { - continue; - } - - if (d > maxD) { - maxD = d; - maxPt = pt; - } - } - - return { maxPoint: maxPt, newPoints: newPoints }; - }, - - - /* - * Given a baseline, compute the convex hull of latLngs as an array - * of latLngs. - * - * @param {Array} latLngs - * @returns {Array} - */ - buildConvexHull: function (baseLine, latLngs) { - var convexHullBaseLines = [], - t = this.findMostDistantPointFromBaseLine(baseLine, latLngs); - - if (t.maxPoint) { // if there is still a point "outside" the base line - convexHullBaseLines = - convexHullBaseLines.concat( - this.buildConvexHull([baseLine[0], t.maxPoint], t.newPoints) - ); - convexHullBaseLines = - convexHullBaseLines.concat( - this.buildConvexHull([t.maxPoint, baseLine[1]], t.newPoints) - ); - return convexHullBaseLines; - } else { // if there is no more point "outside" the base line, the current base line is part of the convex hull - return [baseLine[0]]; - } - }, - - /* - * Given an array of latlngs, compute a convex hull as an array - * of latlngs - * - * @param {Array} latLngs - * @returns {Array} - */ - getConvexHull: function (latLngs) { - // find first baseline - var maxLat = false, minLat = false, - maxLng = false, minLng = false, - maxLatPt = null, minLatPt = null, - maxLngPt = null, minLngPt = null, - maxPt = null, minPt = null, - i; - - for (i = latLngs.length - 1; i >= 0; i--) { - var pt = latLngs[i]; - if (maxLat === false || pt.lat > maxLat) { - maxLatPt = pt; - maxLat = pt.lat; - } - if (minLat === false || pt.lat < minLat) { - minLatPt = pt; - minLat = pt.lat; - } - if (maxLng === false || pt.lng > maxLng) { - maxLngPt = pt; - maxLng = pt.lng; - } - if (minLng === false || pt.lng < minLng) { - minLngPt = pt; - minLng = pt.lng; - } - } - - if (minLat !== maxLat) { - minPt = minLatPt; - maxPt = maxLatPt; - } else { - minPt = minLngPt; - maxPt = maxLngPt; - } - - var ch = [].concat(this.buildConvexHull([minPt, maxPt], latLngs), - this.buildConvexHull([maxPt, minPt], latLngs)); - return ch; - } - }; -}()); - -L.MarkerCluster.include({ - getConvexHull: function () { - var childMarkers = this.getAllChildMarkers(), - points = [], - p, i; - - for (i = childMarkers.length - 1; i >= 0; i--) { - p = childMarkers[i].getLatLng(); - points.push(p); - } - - return L.QuickHull.getConvexHull(points); - } -}); - - -//This code is 100% based on https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet -//Huge thanks to jawj for implementing it first to make my job easy :-) - -L.MarkerCluster.include({ - - _2PI: Math.PI * 2, - _circleFootSeparation: 25, //related to circumference of circle - _circleStartAngle: Math.PI / 6, - - _spiralFootSeparation: 28, //related to size of spiral (experiment!) - _spiralLengthStart: 11, - _spiralLengthFactor: 5, - - _circleSpiralSwitchover: 9, //show spiral instead of circle from this marker count upwards. - // 0 -> always spiral; Infinity -> always circle - - spiderfy: function () { - if (this._group._spiderfied === this || this._group._inZoomAnimation) { - return; - } - - var childMarkers = this.getAllChildMarkers(), - group = this._group, - map = group._map, - center = map.latLngToLayerPoint(this._latlng), - positions; - - this._group._unspiderfy(); - this._group._spiderfied = this; - - //TODO Maybe: childMarkers order by distance to center - - if (childMarkers.length >= this._circleSpiralSwitchover) { - positions = this._generatePointsSpiral(childMarkers.length, center); - } else { - center.y += 10; // Otherwise circles look wrong => hack for standard blue icon, renders differently for other icons. - positions = this._generatePointsCircle(childMarkers.length, center); - } - - this._animationSpiderfy(childMarkers, positions); - }, - - unspiderfy: function (zoomDetails) { - /// Argument from zoomanim if being called in a zoom animation or null otherwise - if (this._group._inZoomAnimation) { - return; - } - this._animationUnspiderfy(zoomDetails); - - this._group._spiderfied = null; - }, - - _generatePointsCircle: function (count, centerPt) { - var circumference = this._group.options.spiderfyDistanceMultiplier * this._circleFootSeparation * (2 + count), - legLength = circumference / this._2PI, //radius from circumference - angleStep = this._2PI / count, - res = [], - i, angle; - - res.length = count; - - for (i = count - 1; i >= 0; i--) { - angle = this._circleStartAngle + i * angleStep; - res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round(); - } - - return res; - }, - - _generatePointsSpiral: function (count, centerPt) { - var spiderfyDistanceMultiplier = this._group.options.spiderfyDistanceMultiplier, - legLength = spiderfyDistanceMultiplier * this._spiralLengthStart, - separation = spiderfyDistanceMultiplier * this._spiralFootSeparation, - lengthFactor = spiderfyDistanceMultiplier * this._spiralLengthFactor * this._2PI, - angle = 0, - res = [], - i; - - res.length = count; - - // Higher index, closer position to cluster center. - for (i = count - 1; i >= 0; i--) { - angle += separation / legLength + i * 0.0005; - res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round(); - legLength += lengthFactor / angle; - } - return res; - }, - - _noanimationUnspiderfy: function () { - var group = this._group, - map = group._map, - fg = group._featureGroup, - childMarkers = this.getAllChildMarkers(), - m, i; - - group._ignoreMove = true; - - this.setOpacity(1); - for (i = childMarkers.length - 1; i >= 0; i--) { - m = childMarkers[i]; - - fg.removeLayer(m); - - if (m._preSpiderfyLatlng) { - m.setLatLng(m._preSpiderfyLatlng); - delete m._preSpiderfyLatlng; - } - if (m.setZIndexOffset) { - m.setZIndexOffset(0); - } - - if (m._spiderLeg) { - map.removeLayer(m._spiderLeg); - delete m._spiderLeg; - } - } - - group.fire('unspiderfied', { - cluster: this, - markers: childMarkers - }); - group._ignoreMove = false; - group._spiderfied = null; - } -}); - -//Non Animated versions of everything -L.MarkerClusterNonAnimated = L.MarkerCluster.extend({ - _animationSpiderfy: function (childMarkers, positions) { - var group = this._group, - map = group._map, - fg = group._featureGroup, - legOptions = this._group.options.spiderLegPolylineOptions, - i, m, leg, newPos; - - group._ignoreMove = true; - - // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition. - // The reverse order trick no longer improves performance on modern browsers. - for (i = 0; i < childMarkers.length; i++) { - newPos = map.layerPointToLatLng(positions[i]); - m = childMarkers[i]; - - // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it. - leg = new L.Polyline([this._latlng, newPos], legOptions); - map.addLayer(leg); - m._spiderLeg = leg; - - // Now add the marker. - m._preSpiderfyLatlng = m._latlng; - m.setLatLng(newPos); - if (m.setZIndexOffset) { - m.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING - } - - fg.addLayer(m); - } - this.setOpacity(0.3); - - group._ignoreMove = false; - group.fire('spiderfied', { - cluster: this, - markers: childMarkers - }); - }, - - _animationUnspiderfy: function () { - this._noanimationUnspiderfy(); - } -}); - -//Animated versions here -L.MarkerCluster.include({ - - _animationSpiderfy: function (childMarkers, positions) { - var me = this, - group = this._group, - map = group._map, - fg = group._featureGroup, - thisLayerLatLng = this._latlng, - thisLayerPos = map.latLngToLayerPoint(thisLayerLatLng), - svg = L.Path.SVG, - legOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation. - finalLegOpacity = legOptions.opacity, - i, m, leg, legPath, legLength, newPos; - - if (finalLegOpacity === undefined) { - finalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity; - } - - if (svg) { - // If the initial opacity of the spider leg is not 0 then it appears before the animation starts. - legOptions.opacity = 0; - - // Add the class for CSS transitions. - legOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg'; - } else { - // Make sure we have a defined opacity. - legOptions.opacity = finalLegOpacity; - } - - group._ignoreMove = true; - - // Add markers and spider legs to map, hidden at our center point. - // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition. - // The reverse order trick no longer improves performance on modern browsers. - for (i = 0; i < childMarkers.length; i++) { - m = childMarkers[i]; - - newPos = map.layerPointToLatLng(positions[i]); - - // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it. - leg = new L.Polyline([thisLayerLatLng, newPos], legOptions); - map.addLayer(leg); - m._spiderLeg = leg; - - // Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/ - // In our case the transition property is declared in the CSS file. - if (svg) { - legPath = leg._path; - legLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox. - legPath.style.strokeDasharray = legLength; // Just 1 length is enough, it will be duplicated. - legPath.style.strokeDashoffset = legLength; - } - - // If it is a marker, add it now and we'll animate it out - if (m.setZIndexOffset) { - m.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING - } - if (m.clusterHide) { - m.clusterHide(); - } - - // Vectors just get immediately added - fg.addLayer(m); - - if (m._setPos) { - m._setPos(thisLayerPos); - } - } - - group._forceLayout(); - group._animationStart(); - - // Reveal markers and spider legs. - for (i = childMarkers.length - 1; i >= 0; i--) { - newPos = map.layerPointToLatLng(positions[i]); - m = childMarkers[i]; - - //Move marker to new position - m._preSpiderfyLatlng = m._latlng; - m.setLatLng(newPos); - - if (m.clusterShow) { - m.clusterShow(); - } - - // Animate leg (animation is actually delegated to CSS transition). - if (svg) { - leg = m._spiderLeg; - legPath = leg._path; - legPath.style.strokeDashoffset = 0; - //legPath.style.strokeOpacity = finalLegOpacity; - leg.setStyle({opacity: finalLegOpacity}); - } - } - this.setOpacity(0.3); - - group._ignoreMove = false; - - setTimeout(function () { - group._animationEnd(); - group.fire('spiderfied', { - cluster: me, - markers: childMarkers - }); - }, 200); - }, - - _animationUnspiderfy: function (zoomDetails) { - var me = this, - group = this._group, - map = group._map, - fg = group._featureGroup, - thisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng), - childMarkers = this.getAllChildMarkers(), - svg = L.Path.SVG, - m, i, leg, legPath, legLength, nonAnimatable; - - group._ignoreMove = true; - group._animationStart(); - - //Make us visible and bring the child markers back in - this.setOpacity(1); - for (i = childMarkers.length - 1; i >= 0; i--) { - m = childMarkers[i]; - - //Marker was added to us after we were spiderfied - if (!m._preSpiderfyLatlng) { - continue; - } - - //Close any popup on the marker first, otherwise setting the location of the marker will make the map scroll - m.closePopup(); - - //Fix up the location to the real one - m.setLatLng(m._preSpiderfyLatlng); - delete m._preSpiderfyLatlng; - - //Hack override the location to be our center - nonAnimatable = true; - if (m._setPos) { - m._setPos(thisLayerPos); - nonAnimatable = false; - } - if (m.clusterHide) { - m.clusterHide(); - nonAnimatable = false; - } - if (nonAnimatable) { - fg.removeLayer(m); - } - - // Animate the spider leg back in (animation is actually delegated to CSS transition). - if (svg) { - leg = m._spiderLeg; - legPath = leg._path; - legLength = legPath.getTotalLength() + 0.1; - legPath.style.strokeDashoffset = legLength; - leg.setStyle({opacity: 0}); - } - } - - group._ignoreMove = false; - - setTimeout(function () { - //If we have only <= one child left then that marker will be shown on the map so don't remove it! - var stillThereChildCount = 0; - for (i = childMarkers.length - 1; i >= 0; i--) { - m = childMarkers[i]; - if (m._spiderLeg) { - stillThereChildCount++; - } - } - - - for (i = childMarkers.length - 1; i >= 0; i--) { - m = childMarkers[i]; - - if (!m._spiderLeg) { //Has already been unspiderfied - continue; - } - - if (m.clusterShow) { - m.clusterShow(); - } - if (m.setZIndexOffset) { - m.setZIndexOffset(0); - } - - if (stillThereChildCount > 1) { - fg.removeLayer(m); - } - - map.removeLayer(m._spiderLeg); - delete m._spiderLeg; - } - group._animationEnd(); - group.fire('unspiderfied', { - cluster: me, - markers: childMarkers - }); - }, 200); - } -}); - - -L.MarkerClusterGroup.include({ - //The MarkerCluster currently spiderfied (if any) - _spiderfied: null, - - unspiderfy: function () { - this._unspiderfy.apply(this, arguments); - }, - - _spiderfierOnAdd: function () { - this._map.on('click', this._unspiderfyWrapper, this); - - if (this._map.options.zoomAnimation) { - this._map.on('zoomstart', this._unspiderfyZoomStart, this); - } - //Browsers without zoomAnimation or a big zoom don't fire zoomstart - this._map.on('zoomend', this._noanimationUnspiderfy, this); - - if (!L.Browser.touch) { - this._map.getRenderer(this); - //Needs to happen in the pageload, not after, or animations don't work in webkit - // http://stackoverflow.com/questions/8455200/svg-animate-with-dynamically-added-elements - //Disable on touch browsers as the animation messes up on a touch zoom and isn't very noticable - } - }, - - _spiderfierOnRemove: function () { - this._map.off('click', this._unspiderfyWrapper, this); - this._map.off('zoomstart', this._unspiderfyZoomStart, this); - this._map.off('zoomanim', this._unspiderfyZoomAnim, this); - this._map.off('zoomend', this._noanimationUnspiderfy, this); - - //Ensure that markers are back where they should be - // Use no animation to avoid a sticky leaflet-cluster-anim class on mapPane - this._noanimationUnspiderfy(); - }, - - //On zoom start we add a zoomanim handler so that we are guaranteed to be last (after markers are animated) - //This means we can define the animation they do rather than Markers doing an animation to their actual location - _unspiderfyZoomStart: function () { - if (!this._map) { //May have been removed from the map by a zoomEnd handler - return; - } - - this._map.on('zoomanim', this._unspiderfyZoomAnim, this); - }, - - _unspiderfyZoomAnim: function (zoomDetails) { - //Wait until the first zoomanim after the user has finished touch-zooming before running the animation - if (L.DomUtil.hasClass(this._map._mapPane, 'leaflet-touching')) { - return; - } - - this._map.off('zoomanim', this._unspiderfyZoomAnim, this); - this._unspiderfy(zoomDetails); - }, - - _unspiderfyWrapper: function () { - /// _unspiderfy but passes no arguments - this._unspiderfy(); - }, - - _unspiderfy: function (zoomDetails) { - if (this._spiderfied) { - this._spiderfied.unspiderfy(zoomDetails); - } - }, - - _noanimationUnspiderfy: function () { - if (this._spiderfied) { - this._spiderfied._noanimationUnspiderfy(); - } - }, - - //If the given layer is currently being spiderfied then we unspiderfy it so it isn't on the map anymore etc - _unspiderfyLayer: function (layer) { - if (layer._spiderLeg) { - this._featureGroup.removeLayer(layer); - - if (layer.clusterShow) { - layer.clusterShow(); - } - //Position will be fixed up immediately in _animationUnspiderfy - if (layer.setZIndexOffset) { - layer.setZIndexOffset(0); - } - - this._map.removeLayer(layer._spiderLeg); - delete layer._spiderLeg; - } - } -}); - - -/** - * Adds 1 public method to MCG and 1 to L.Marker to facilitate changing - * markers' icon options and refreshing their icon and their parent clusters - * accordingly (case where their iconCreateFunction uses data of childMarkers - * to make up the cluster icon). - */ - - -L.MarkerClusterGroup.include({ - /** - * Updates the icon of all clusters which are parents of the given marker(s). - * In singleMarkerMode, also updates the given marker(s) icon. - * @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)| - * L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent - * clusters need to be updated. If not provided, retrieves all child markers of this. - * @returns {L.MarkerClusterGroup} - */ - refreshClusters: function (layers) { - if (!layers) { - layers = this._topClusterLevel.getAllChildMarkers(); - } else if (layers instanceof L.MarkerClusterGroup) { - layers = layers._topClusterLevel.getAllChildMarkers(); - } else if (layers instanceof L.LayerGroup) { - layers = layers._layers; - } else if (layers instanceof L.MarkerCluster) { - layers = layers.getAllChildMarkers(); - } else if (layers instanceof L.Marker) { - layers = [layers]; - } // else: must be an Array(L.Marker)|Map(L.Marker) - this._flagParentsIconsNeedUpdate(layers); - this._refreshClustersIcons(); - - // In case of singleMarkerMode, also re-draw the markers. - if (this.options.singleMarkerMode) { - this._refreshSingleMarkerModeMarkers(layers); - } - - return this; - }, - - /** - * Simply flags all parent clusters of the given markers as having a "dirty" icon. - * @param layers Array(L.Marker)|Map(L.Marker) list of markers. - * @private - */ - _flagParentsIconsNeedUpdate: function (layers) { - var id, parent; - - // Assumes layers is an Array or an Object whose prototype is non-enumerable. - for (id in layers) { - // Flag parent clusters' icon as "dirty", all the way up. - // Dumb process that flags multiple times upper parents, but still - // much more efficient than trying to be smart and make short lists, - // at least in the case of a hierarchy following a power law: - // http://jsperf.com/flag-nodes-in-power-hierarchy/2 - parent = layers[id].__parent; - while (parent) { - parent._iconNeedsUpdate = true; - parent = parent.__parent; - } - } - }, - - /** - * Re-draws the icon of the supplied markers. - * To be used in singleMarkerMode only. - * @param layers Array(L.Marker)|Map(L.Marker) list of markers. - * @private - */ - _refreshSingleMarkerModeMarkers: function (layers) { - var id, layer; - - for (id in layers) { - layer = layers[id]; - - // Make sure we do not override markers that do not belong to THIS group. - if (this.hasLayer(layer)) { - // Need to re-create the icon first, then re-draw the marker. - layer.setIcon(this._overrideMarkerIcon(layer)); - } - } - } -}); - -L.Marker.include({ - /** - * Updates the given options in the marker's icon and refreshes the marker. - * @param options map object of icon options. - * @param directlyRefreshClusters boolean (optional) true to trigger - * MCG.refreshClustersOf() right away with this single marker. - * @returns {L.Marker} - */ - refreshIconOptions: function (options, directlyRefreshClusters) { - var icon = this.options.icon; - - L.setOptions(icon, options); - - this.setIcon(icon); - - // Shortcut to refresh the associated MCG clusters right away. - // To be used when refreshing a single marker. - // Otherwise, better use MCG.refreshClusters() once at the end with - // the list of modified markers. - if (directlyRefreshClusters && this.__parent) { - this.__parent._group.refreshClusters(this); - } - - return this; - } -}); - - -}(window, document)); \ No newline at end of file diff --git a/html/js/leaflet.markercluster.js b/html/js/leaflet.markercluster.js new file mode 100644 index 0000000000..67c52dcd6b --- /dev/null +++ b/html/js/leaflet.markercluster.js @@ -0,0 +1,3 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e.Leaflet=e.Leaflet||{},e.Leaflet.markercluster=e.Leaflet.markercluster||{}))}(this,function(e){"use strict";var t=L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,clusterPane:L.Marker.prototype.options.pane,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animate:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,spiderLegPolylineOptions:{weight:1.5,color:"#222",opacity:.5},chunkedLoading:!1,chunkInterval:200,chunkDelay:50,chunkProgress:null,polygonOptions:{}},initialize:function(e){L.Util.setOptions(this,e),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),this._featureGroup=L.featureGroup(),this._featureGroup.addEventParent(this),this._nonPointGroup=L.featureGroup(),this._nonPointGroup.addEventParent(this),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null,this._queue=[],this._childMarkerEventHandlers={dragstart:this._childMarkerDragStart,move:this._childMarkerMoved,dragend:this._childMarkerDragEnd};var t=L.DomUtil.TRANSITION&&this.options.animate;L.extend(this,t?this._withAnimation:this._noAnimation),this._markerCluster=t?L.MarkerCluster:L.MarkerClusterNonAnimated},addLayer:function(e){if(e instanceof L.LayerGroup)return this.addLayers([e]);if(!e.getLatLng)return this._nonPointGroup.addLayer(e),this.fire("layeradd",{layer:e}),this;if(!this._map)return this._needsClustering.push(e),this.fire("layeradd",{layer:e}),this;if(this.hasLayer(e))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(e,this._maxZoom),this.fire("layeradd",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons();var t=e,i=this._zoom;if(e.__parent)for(;t.__parent._zoom>=i;)t=t.__parent;return this._currentShownBounds.contains(t.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(e,t):this._animationAddLayerNonAnimated(e,t)),this},removeLayer:function(e){return e instanceof L.LayerGroup?this.removeLayers([e]):e.getLatLng?this._map?e.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(e)),this._removeLayer(e,!0),this.fire("layerremove",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),e.off(this._childMarkerEventHandlers,this),this._featureGroup.hasLayer(e)&&(this._featureGroup.removeLayer(e),e.clusterShow&&e.clusterShow()),this):this:(!this._arraySplice(this._needsClustering,e)&&this.hasLayer(e)&&this._needsRemoving.push({layer:e,latlng:e._latlng}),this.fire("layerremove",{layer:e}),this):(this._nonPointGroup.removeLayer(e),this.fire("layerremove",{layer:e}),this)},addLayers:function(e,t){if(!L.Util.isArray(e))return this.addLayer(e);var i,n=this._featureGroup,r=this._nonPointGroup,s=this.options.chunkedLoading,o=this.options.chunkInterval,a=this.options.chunkProgress,h=e.length,l=0,u=!0;if(this._map){var _=(new Date).getTime(),d=L.bind(function(){for(var c=(new Date).getTime();h>l;l++){if(s&&0===l%200){var p=(new Date).getTime()-c;if(p>o)break}if(i=e[l],i instanceof L.LayerGroup)u&&(e=e.slice(),u=!1),this._extractNonGroupLayers(i,e),h=e.length;else if(i.getLatLng){if(!this.hasLayer(i)&&(this._addLayer(i,this._maxZoom),t||this.fire("layeradd",{layer:i}),i.__parent&&2===i.__parent.getChildCount())){var f=i.__parent.getAllChildMarkers(),m=f[0]===i?f[1]:f[0];n.removeLayer(m)}}else r.addLayer(i),t||this.fire("layeradd",{layer:i})}a&&a(l,h,(new Date).getTime()-_),l===h?(this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)):setTimeout(d,this.options.chunkDelay)},this);d()}else for(var c=this._needsClustering;h>l;l++)i=e[l],i instanceof L.LayerGroup?(u&&(e=e.slice(),u=!1),this._extractNonGroupLayers(i,e),h=e.length):i.getLatLng?this.hasLayer(i)||c.push(i):r.addLayer(i);return this},removeLayers:function(e){var t,i,n=e.length,r=this._featureGroup,s=this._nonPointGroup,o=!0;if(!this._map){for(t=0;n>t;t++)i=e[t],i instanceof L.LayerGroup?(o&&(e=e.slice(),o=!1),this._extractNonGroupLayers(i,e),n=e.length):(this._arraySplice(this._needsClustering,i),s.removeLayer(i),this.hasLayer(i)&&this._needsRemoving.push({layer:i,latlng:i._latlng}),this.fire("layerremove",{layer:i}));return this}if(this._unspiderfy){this._unspiderfy();var a=e.slice(),h=n;for(t=0;h>t;t++)i=a[t],i instanceof L.LayerGroup?(this._extractNonGroupLayers(i,a),h=a.length):this._unspiderfyLayer(i)}for(t=0;n>t;t++)i=e[t],i instanceof L.LayerGroup?(o&&(e=e.slice(),o=!1),this._extractNonGroupLayers(i,e),n=e.length):i.__parent?(this._removeLayer(i,!0,!0),this.fire("layerremove",{layer:i}),r.hasLayer(i)&&(r.removeLayer(i),i.clusterShow&&i.clusterShow())):(s.removeLayer(i),this.fire("layerremove",{layer:i}));return this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),this},clearLayers:function(){return this._map||(this._needsClustering=[],this._needsRemoving=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy(),this._featureGroup.clearLayers(),this._nonPointGroup.clearLayers(),this.eachLayer(function(e){e.off(this._childMarkerEventHandlers,this),delete e.__parent},this),this._map&&this._generateInitialClusters(),this},getBounds:function(){var e=new L.LatLngBounds;this._topClusterLevel&&e.extend(this._topClusterLevel._bounds);for(var t=this._needsClustering.length-1;t>=0;t--)e.extend(this._needsClustering[t].getLatLng());return e.extend(this._nonPointGroup.getBounds()),e},eachLayer:function(e,t){var i,n,r,s=this._needsClustering.slice(),o=this._needsRemoving;for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(s),n=s.length-1;n>=0;n--){for(i=!0,r=o.length-1;r>=0;r--)if(o[r].layer===s[n]){i=!1;break}i&&e.call(t,s[n])}this._nonPointGroup.eachLayer(e,t)},getLayers:function(){var e=[];return this.eachLayer(function(t){e.push(t)}),e},getLayer:function(e){var t=null;return e=parseInt(e,10),this.eachLayer(function(i){L.stamp(i)===e&&(t=i)}),t},hasLayer:function(e){if(!e)return!1;var t,i=this._needsClustering;for(t=i.length-1;t>=0;t--)if(i[t]===e)return!0;for(i=this._needsRemoving,t=i.length-1;t>=0;t--)if(i[t].layer===e)return!1;return!(!e.__parent||e.__parent._group!==this)||this._nonPointGroup.hasLayer(e)},zoomToShowLayer:function(e,t){"function"!=typeof t&&(t=function(){});var i=function(){!e._icon&&!e.__parent._icon||this._inZoomAnimation||(this._map.off("moveend",i,this),this.off("animationend",i,this),e._icon?t():e.__parent._icon&&(this.once("spiderfied",t,this),e.__parent.spiderfy()))};e._icon&&this._map.getBounds().contains(e.getLatLng())?t():e.__parent._zoomt;t++)n=this._needsRemoving[t],n.newlatlng=n.layer._latlng,n.layer._latlng=n.latlng;for(t=0,i=this._needsRemoving.length;i>t;t++)n=this._needsRemoving[t],this._removeLayer(n.layer,!0),n.layer._latlng=n.newlatlng;this._needsRemoving=[],this._zoom=Math.round(this._map._zoom),this._currentShownBounds=this._getExpandedVisibleBounds(),this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),i=this._needsClustering,this._needsClustering=[],this.addLayers(i,!0)},onRemove:function(e){e.off("zoomend",this._zoomEnd,this),e.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove(),delete this._maxLat,this._hideCoverage(),this._featureGroup.remove(),this._nonPointGroup.remove(),this._featureGroup.clearLayers(),this._map=null},getVisibleParent:function(e){for(var t=e;t&&!t._icon;)t=t.__parent;return t||null},_arraySplice:function(e,t){for(var i=e.length-1;i>=0;i--)if(e[i]===t)return e.splice(i,1),!0},_removeFromGridUnclustered:function(e,t){for(var i=this._map,n=this._gridUnclustered,r=Math.floor(this._map.getMinZoom());t>=r&&n[t].removeObject(e,i.project(e.getLatLng(),t));t--);},_childMarkerDragStart:function(e){e.target.__dragStart=e.target._latlng},_childMarkerMoved:function(e){if(!this._ignoreMove&&!e.target.__dragStart){var t=e.target._popup&&e.target._popup.isOpen();this._moveChild(e.target,e.oldLatLng,e.latlng),t&&e.target.openPopup()}},_moveChild:function(e,t,i){e._latlng=t,this.removeLayer(e),e._latlng=i,this.addLayer(e)},_childMarkerDragEnd:function(e){var t=e.target.__dragStart;delete e.target.__dragStart,t&&this._moveChild(e.target,t,e.target._latlng)},_removeLayer:function(e,t,i){var n=this._gridClusters,r=this._gridUnclustered,s=this._featureGroup,o=this._map,a=Math.floor(this._map.getMinZoom());t&&this._removeFromGridUnclustered(e,this._maxZoom);var h,l=e.__parent,u=l._markers;for(this._arraySplice(u,e);l&&(l._childCount--,l._boundsNeedUpdate=!0,!(l._zoomt?"small":100>t?"medium":"large",new L.DivIcon({html:"
"+t+"
",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var e=this._map,t=this.options.spiderfyOnMaxZoom,i=this.options.showCoverageOnHover,n=this.options.zoomToBoundsOnClick;(t||n)&&this.on("clusterclick",this._zoomOrSpiderfy,this),i&&(this.on("clustermouseover",this._showCoverage,this),this.on("clustermouseout",this._hideCoverage,this),e.on("zoomend",this._hideCoverage,this))},_zoomOrSpiderfy:function(e){for(var t=e.layer,i=t;1===i._childClusters.length;)i=i._childClusters[0];i._zoom===this._maxZoom&&i._childCount===t._childCount&&this.options.spiderfyOnMaxZoom?t.spiderfy():this.options.zoomToBoundsOnClick&&t.zoomToBounds(),e.originalEvent&&13===e.originalEvent.keyCode&&this._map._container.focus()},_showCoverage:function(e){var t=this._map;this._inZoomAnimation||(this._shownPolygon&&t.removeLayer(this._shownPolygon),e.layer.getChildCount()>2&&e.layer!==this._spiderfied&&(this._shownPolygon=new L.Polygon(e.layer.getConvexHull(),this.options.polygonOptions),t.addLayer(this._shownPolygon)))},_hideCoverage:function(){this._shownPolygon&&(this._map.removeLayer(this._shownPolygon),this._shownPolygon=null)},_unbindEvents:function(){var e=this.options.spiderfyOnMaxZoom,t=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(e||i)&&this.off("clusterclick",this._zoomOrSpiderfy,this),t&&(this.off("clustermouseover",this._showCoverage,this),this.off("clustermouseout",this._hideCoverage,this),n.off("zoomend",this._hideCoverage,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=Math.round(this._map._zoom),this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var e=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,Math.floor(this._map.getMinZoom()),this._zoom,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,Math.round(this._map._zoom),e),this._currentShownBounds=e}},_generateInitialClusters:function(){var e=Math.ceil(this._map.getMaxZoom()),t=Math.floor(this._map.getMinZoom()),i=this.options.maxClusterRadius,n=i;"function"!=typeof i&&(n=function(){return i}),null!==this.options.disableClusteringAtZoom&&(e=this.options.disableClusteringAtZoom-1),this._maxZoom=e,this._gridClusters={},this._gridUnclustered={};for(var r=e;r>=t;r--)this._gridClusters[r]=new L.DistanceGrid(n(r)),this._gridUnclustered[r]=new L.DistanceGrid(n(r));this._topClusterLevel=new this._markerCluster(this,t-1)},_addLayer:function(e,t){var i,n,r=this._gridClusters,s=this._gridUnclustered,o=Math.floor(this._map.getMinZoom());for(this.options.singleMarkerMode&&this._overrideMarkerIcon(e),e.on(this._childMarkerEventHandlers,this);t>=o;t--){i=this._map.project(e.getLatLng(),t);var a=r[t].getNearObject(i);if(a)return a._addChild(e),e.__parent=a,void 0;if(a=s[t].getNearObject(i)){var h=a.__parent;h&&this._removeLayer(a,!1);var l=new this._markerCluster(this,t,a,e);r[t].addObject(l,this._map.project(l._cLatLng,t)),a.__parent=l,e.__parent=l;var u=l;for(n=t-1;n>h._zoom;n--)u=new this._markerCluster(this,n,u),r[n].addObject(u,this._map.project(a.getLatLng(),n));return h._addChild(u),this._removeFromGridUnclustered(a,t),void 0}s[t].addObject(e,i)}this._topClusterLevel._addChild(e),e.__parent=this._topClusterLevel},_refreshClustersIcons:function(){this._featureGroup.eachLayer(function(e){e instanceof L.MarkerCluster&&e._iconNeedsUpdate&&e._updateIcon()})},_enqueue:function(e){this._queue.push(e),this._queueTimeout||(this._queueTimeout=setTimeout(L.bind(this._processQueue,this),300))},_processQueue:function(){for(var e=0;ee?(this._animationStart(),this._animationZoomOut(this._zoom,e)):this._moveEnd()},_getExpandedVisibleBounds:function(){return this.options.removeOutsideVisibleBounds?L.Browser.mobile?this._checkBoundsMaxLat(this._map.getBounds()):this._checkBoundsMaxLat(this._map.getBounds().pad(1)):this._mapBoundsInfinite},_checkBoundsMaxLat:function(e){var t=this._maxLat;return void 0!==t&&(e.getNorth()>=t&&(e._northEast.lat=1/0),e.getSouth()<=-t&&(e._southWest.lat=-1/0)),e},_animationAddLayerNonAnimated:function(e,t){if(t===e)this._featureGroup.addLayer(e);else if(2===t._childCount){t._addToMap();var i=t.getAllChildMarkers();this._featureGroup.removeLayer(i[0]),this._featureGroup.removeLayer(i[1])}else t._updateIcon()},_extractNonGroupLayers:function(e,t){var i,n=e.getLayers(),r=0;for(t=t||[];r=0;i--)o=h[i],n.contains(o._latlng)||r.removeLayer(o)}),this._forceLayout(),this._topClusterLevel._recursivelyBecomeVisible(n,t),r.eachLayer(function(e){e instanceof L.MarkerCluster||!e._icon||e.clusterShow()}),this._topClusterLevel._recursively(n,e,t,function(e){e._recursivelyRestoreChildPositions(t)}),this._ignoreMove=!1,this._enqueue(function(){this._topClusterLevel._recursively(n,e,s,function(e){r.removeLayer(e),e.clusterShow()}),this._animationEnd()})},_animationZoomOut:function(e,t){this._animationZoomOutSingle(this._topClusterLevel,e-1,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,t,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,Math.floor(this._map.getMinZoom()),e,this._getExpandedVisibleBounds())},_animationAddLayer:function(e,t){var i=this,n=this._featureGroup;n.addLayer(e),t!==e&&(t._childCount>2?(t._updateIcon(),this._forceLayout(),this._animationStart(),e._setPos(this._map.latLngToLayerPoint(t.getLatLng())),e.clusterHide(),this._enqueue(function(){n.removeLayer(e),e.clusterShow(),i._animationEnd()})):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(t,this._map.getMaxZoom(),this._zoom)))}},_animationZoomOutSingle:function(e,t,i){var n=this._getExpandedVisibleBounds(),r=Math.floor(this._map.getMinZoom());e._recursivelyAnimateChildrenInAndAddSelfToMap(n,r,t+1,i);var s=this;this._forceLayout(),e._recursivelyBecomeVisible(n,i),this._enqueue(function(){if(1===e._childCount){var o=e._markers[0];this._ignoreMove=!0,o.setLatLng(o.getLatLng()),this._ignoreMove=!1,o.clusterShow&&o.clusterShow()}else e._recursively(n,i,r,function(e){e._recursivelyRemoveChildrenFromMap(n,r,t+1)});s._animationEnd()})},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_forceLayout:function(){L.Util.falseFn(document.body.offsetWidth)}}),L.markerClusterGroup=function(e){return new L.MarkerClusterGroup(e)};var i=L.MarkerCluster=L.Marker.extend({options:L.Icon.prototype.options,initialize:function(e,t,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this,pane:e.options.clusterPane}),this._group=e,this._zoom=t,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(e,t){e=e||[];for(var i=this._childClusters.length-1;i>=0;i--)this._childClusters[i].getAllChildMarkers(e);for(var n=this._markers.length-1;n>=0;n--)t&&this._markers[n].__dragStart||e.push(this._markers[n]);return e},getChildCount:function(){return this._childCount},zoomToBounds:function(e){for(var t,i=this._childClusters.slice(),n=this._group._map,r=n.getBoundsZoom(this._bounds),s=this._zoom+1,o=n.getZoom();i.length>0&&r>s;){s++;var a=[];for(t=0;ts?this._group._map.setView(this._latlng,s):o>=r?this._group._map.setView(this._latlng,o+1):this._group._map.fitBounds(this._bounds,e)},getBounds:function(){var e=new L.LatLngBounds;return e.extend(this._bounds),e},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(e,t){this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._setClusterCenter(e),e instanceof L.MarkerCluster?(t||(this._childClusters.push(e),e.__parent=this),this._childCount+=e._childCount):(t||this._markers.push(e),this._childCount++),this.__parent&&this.__parent._addChild(e,!0)},_setClusterCenter:function(e){this._cLatLng||(this._cLatLng=e._cLatLng||e._latlng)},_resetBounds:function(){var e=this._bounds;e._southWest&&(e._southWest.lat=1/0,e._southWest.lng=1/0),e._northEast&&(e._northEast.lat=-1/0,e._northEast.lng=-1/0)},_recalculateBounds:function(){var e,t,i,n,r=this._markers,s=this._childClusters,o=0,a=0,h=this._childCount;if(0!==h){for(this._resetBounds(),e=0;e=0;i--)n=r[i],n._icon&&(n._setPos(t),n.clusterHide())},function(e){var i,n,r=e._childClusters;for(i=r.length-1;i>=0;i--)n=r[i],n._icon&&(n._setPos(t),n.clusterHide())})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(e,t,i,n){this._recursively(e,n,t,function(r){r._recursivelyAnimateChildrenIn(e,r._group._map.latLngToLayerPoint(r.getLatLng()).round(),i),r._isSingleParent()&&i-1===n?(r.clusterShow(),r._recursivelyRemoveChildrenFromMap(e,t,i)):r.clusterHide(),r._addToMap()})},_recursivelyBecomeVisible:function(e,t){this._recursively(e,this._group._map.getMinZoom(),t,null,function(e){e.clusterShow()})},_recursivelyAddChildrenToMap:function(e,t,i){this._recursively(i,this._group._map.getMinZoom()-1,t,function(n){if(t!==n._zoom)for(var r=n._markers.length-1;r>=0;r--){var s=n._markers[r];i.contains(s._latlng)&&(e&&(s._backupLatlng=s.getLatLng(),s.setLatLng(e),s.clusterHide&&s.clusterHide()),n._group._featureGroup.addLayer(s))}},function(t){t._addToMap(e)})},_recursivelyRestoreChildPositions:function(e){for(var t=this._markers.length-1;t>=0;t--){var i=this._markers[t];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(e-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var r=this._childClusters.length-1;r>=0;r--)this._childClusters[r]._recursivelyRestoreChildPositions(e)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(e,t,i,n){var r,s;this._recursively(e,t-1,i-1,function(e){for(s=e._markers.length-1;s>=0;s--)r=e._markers[s],n&&n.contains(r._latlng)||(e._group._featureGroup.removeLayer(r),r.clusterShow&&r.clusterShow())},function(e){for(s=e._childClusters.length-1;s>=0;s--)r=e._childClusters[s],n&&n.contains(r._latlng)||(e._group._featureGroup.removeLayer(r),r.clusterShow&&r.clusterShow())})},_recursively:function(e,t,i,n,r){var s,o,a=this._childClusters,h=this._zoom;if(h>=t&&(n&&n(this),r&&h===i&&r(this)),t>h||i>h)for(s=a.length-1;s>=0;s--)o=a[s],o._boundsNeedUpdate&&o._recalculateBounds(),e.intersects(o._bounds)&&o._recursively(e,t,i,n,r)},_isSingleParent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}});L.Marker.include({clusterHide:function(){var e=this.options.opacity;return this.setOpacity(0),this.options.opacity=e,this},clusterShow:function(){return this.setOpacity(this.options.opacity)}}),L.DistanceGrid=function(e){this._cellSize=e,this._sqCellSize=e*e,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(e,t){var i=this._getCoord(t.x),n=this._getCoord(t.y),r=this._grid,s=r[n]=r[n]||{},o=s[i]=s[i]||[],a=L.Util.stamp(e);this._objectPoint[a]=t,o.push(e)},updateObject:function(e,t){this.removeObject(e),this.addObject(e,t)},removeObject:function(e,t){var i,n,r=this._getCoord(t.x),s=this._getCoord(t.y),o=this._grid,a=o[s]=o[s]||{},h=a[r]=a[r]||[];for(delete this._objectPoint[L.Util.stamp(e)],i=0,n=h.length;n>i;i++)if(h[i]===e)return h.splice(i,1),1===n&&delete a[r],!0},eachObject:function(e,t){var i,n,r,s,o,a,h,l=this._grid;for(i in l){o=l[i];for(n in o)for(a=o[n],r=0,s=a.length;s>r;r++)h=e.call(t,a[r]),h&&(r--,s--)}},getNearObject:function(e){var t,i,n,r,s,o,a,h,l=this._getCoord(e.x),u=this._getCoord(e.y),_=this._objectPoint,d=this._sqCellSize,c=null;for(t=u-1;u+1>=t;t++)if(r=this._grid[t])for(i=l-1;l+1>=i;i++)if(s=r[i])for(n=0,o=s.length;o>n;n++)a=s[n],h=this._sqDist(_[L.Util.stamp(a)],e),(d>h||d>=h&&null===c)&&(d=h,c=a);return c},_getCoord:function(e){var t=Math.floor(e/this._cellSize);return isFinite(t)?t:e},_sqDist:function(e,t){var i=t.x-e.x,n=t.y-e.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(e,t){var i=t[1].lat-t[0].lat,n=t[0].lng-t[1].lng;return n*(e.lat-t[0].lat)+i*(e.lng-t[0].lng)},findMostDistantPointFromBaseLine:function(e,t){var i,n,r,s=0,o=null,a=[];for(i=t.length-1;i>=0;i--)n=t[i],r=this.getDistant(n,e),r>0&&(a.push(n),r>s&&(s=r,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(e,t){var i=[],n=this.findMostDistantPointFromBaseLine(e,t);return n.maxPoint?(i=i.concat(this.buildConvexHull([e[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,e[1]],n.newPoints))):[e[0]]},getConvexHull:function(e){var t,i=!1,n=!1,r=!1,s=!1,o=null,a=null,h=null,l=null,u=null,_=null;for(t=e.length-1;t>=0;t--){var d=e[t];(i===!1||d.lat>i)&&(o=d,i=d.lat),(n===!1||d.latr)&&(h=d,r=d.lng),(s===!1||d.lng=0;t--)e=i[t].getLatLng(),n.push(e);return L.QuickHull.getConvexHull(n)}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:0,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var e,t=this.getAllChildMarkers(null,!0),i=this._group,n=i._map,r=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,t.length>=this._circleSpiralSwitchover?e=this._generatePointsSpiral(t.length,r):(r.y+=10,e=this._generatePointsCircle(t.length,r)),this._animationSpiderfy(t,e)}},unspiderfy:function(e){this._group._inZoomAnimation||(this._animationUnspiderfy(e),this._group._spiderfied=null)},_generatePointsCircle:function(e,t){var i,n,r=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+e),s=r/this._2PI,o=this._2PI/e,a=[];for(s=Math.max(s,35),a.length=e,i=0;e>i;i++)n=this._circleStartAngle+i*o,a[i]=new L.Point(t.x+s*Math.cos(n),t.y+s*Math.sin(n))._round();return a},_generatePointsSpiral:function(e,t){var i,n=this._group.options.spiderfyDistanceMultiplier,r=n*this._spiralLengthStart,s=n*this._spiralFootSeparation,o=n*this._spiralLengthFactor*this._2PI,a=0,h=[];for(h.length=e,i=e;i>=0;i--)e>i&&(h[i]=new L.Point(t.x+r*Math.cos(a),t.y+r*Math.sin(a))._round()),a+=s/r+5e-4*i,r+=o/a;return h},_noanimationUnspiderfy:function(){var e,t,i=this._group,n=i._map,r=i._featureGroup,s=this.getAllChildMarkers(null,!0);for(i._ignoreMove=!0,this.setOpacity(1),t=s.length-1;t>=0;t--)e=s[t],r.removeLayer(e),e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng),e.setZIndexOffset&&e.setZIndexOffset(0),e._spiderLeg&&(n.removeLayer(e._spiderLeg),delete e._spiderLeg);i.fire("unspiderfied",{cluster:this,markers:s}),i._ignoreMove=!1,i._spiderfied=null}}),L.MarkerClusterNonAnimated=L.MarkerCluster.extend({_animationSpiderfy:function(e,t){var i,n,r,s,o=this._group,a=o._map,h=o._featureGroup,l=this._group.options.spiderLegPolylineOptions;for(o._ignoreMove=!0,i=0;i=0;i--)a=u.layerPointToLatLng(t[i]),n=e[i],n._preSpiderfyLatlng=n._latlng,n.setLatLng(a),n.clusterShow&&n.clusterShow(),p&&(r=n._spiderLeg,s=r._path,s.style.strokeDashoffset=0,r.setStyle({opacity:m}));this.setOpacity(.3),l._ignoreMove=!1,setTimeout(function(){l._animationEnd(),l.fire("spiderfied",{cluster:h,markers:e})},200)},_animationUnspiderfy:function(e){var t,i,n,r,s,o,a=this,h=this._group,l=h._map,u=h._featureGroup,_=e?l._latLngToNewLayerPoint(this._latlng,e.zoom,e.center):l.latLngToLayerPoint(this._latlng),d=this.getAllChildMarkers(null,!0),c=L.Path.SVG;for(h._ignoreMove=!0,h._animationStart(),this.setOpacity(1),i=d.length-1;i>=0;i--)t=d[i],t._preSpiderfyLatlng&&(t.closePopup(),t.setLatLng(t._preSpiderfyLatlng),delete t._preSpiderfyLatlng,o=!0,t._setPos&&(t._setPos(_),o=!1),t.clusterHide&&(t.clusterHide(),o=!1),o&&u.removeLayer(t),c&&(n=t._spiderLeg,r=n._path,s=r.getTotalLength()+.1,r.style.strokeDashoffset=s,n.setStyle({opacity:0})));h._ignoreMove=!1,setTimeout(function(){var e=0;for(i=d.length-1;i>=0;i--)t=d[i],t._spiderLeg&&e++;for(i=d.length-1;i>=0;i--)t=d[i],t._spiderLeg&&(t.clusterShow&&t.clusterShow(),t.setZIndexOffset&&t.setZIndexOffset(0),e>1&&u.removeLayer(t),l.removeLayer(t._spiderLeg),delete t._spiderLeg);h._animationEnd(),h.fire("unspiderfied",{cluster:a,markers:d})},200)}}),L.MarkerClusterGroup.include({_spiderfied:null,unspiderfy:function(){this._unspiderfy.apply(this,arguments)},_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation&&this._map.on("zoomstart",this._unspiderfyZoomStart,this),this._map.on("zoomend",this._noanimationUnspiderfy,this),L.Browser.touch||this._map.getRenderer(this)},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._map.off("zoomend",this._noanimationUnspiderfy,this),this._noanimationUnspiderfy() +},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(e){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy(e))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(e){this._spiderfied&&this._spiderfied.unspiderfy(e)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(e){e._spiderLeg&&(this._featureGroup.removeLayer(e),e.clusterShow&&e.clusterShow(),e.setZIndexOffset&&e.setZIndexOffset(0),this._map.removeLayer(e._spiderLeg),delete e._spiderLeg)}}),L.MarkerClusterGroup.include({refreshClusters:function(e){return e?e instanceof L.MarkerClusterGroup?e=e._topClusterLevel.getAllChildMarkers():e instanceof L.LayerGroup?e=e._layers:e instanceof L.MarkerCluster?e=e.getAllChildMarkers():e instanceof L.Marker&&(e=[e]):e=this._topClusterLevel.getAllChildMarkers(),this._flagParentsIconsNeedUpdate(e),this._refreshClustersIcons(),this.options.singleMarkerMode&&this._refreshSingleMarkerModeMarkers(e),this},_flagParentsIconsNeedUpdate:function(e){var t,i;for(t in e)for(i=e[t].__parent;i;)i._iconNeedsUpdate=!0,i=i.__parent},_refreshSingleMarkerModeMarkers:function(e){var t,i;for(t in e)i=e[t],this.hasLayer(i)&&i.setIcon(this._overrideMarkerIcon(i))}}),L.Marker.include({refreshIconOptions:function(e,t){var i=this.options.icon;return L.setOptions(i,e),this.setIcon(i),t&&this.__parent&&this.__parent._group.refreshClusters(this),this}}),e.MarkerClusterGroup=t,e.MarkerCluster=i}); +//# sourceMappingURL=leaflet.markercluster.js.map \ No newline at end of file diff --git a/html/js/librenms.js b/html/js/librenms.js index 2d4c32a4b4..313a573f36 100644 --- a/html/js/librenms.js +++ b/html/js/librenms.js @@ -298,3 +298,108 @@ $(document).ready(function () { }); }, 300000); }); + +function loadScript(src, callback) { + var script = document.createElement("script"); + script.type = "text/javascript"; + if(callback)script.onload=callback; + document.getElementsByTagName("head")[0].appendChild(script); + script.src = src; +} + +function init_map(id, engine, api_key) { + var leaflet = L.map(id); + var baseMaps = {}; + leaflet.setView([0, 0], 15); + + if (engine === 'google') { + var roads, satellite; + loadScript('https://maps.googleapis.com/maps/api/js?key=' + api_key, function () { + loadScript('js/Leaflet.GoogleMutant.js', function () { + roads = L.gridLayer.googleMutant({ + type: 'roadmap' // valid values are 'roadmap', 'satellite', 'terrain' and 'hybrid' + }); + satellite = L.gridLayer.googleMutant({ + type: 'satellite' + }); + + baseMaps = { + "Streets": roads, + "Satellite": satellite + }; + L.control.layers(baseMaps, null, {position: 'bottomleft'}).addTo(leaflet); + roads.addTo(leaflet); + }); + }); + } else { + var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap' + }); + + // var esri = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { + // attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' + // }); + // + // baseMaps = { + // "OpenStreetMap": osm, + // "Satellite": esri + // }; + // L.control.layers(baseMaps, null, {position: 'bottomleft'}).addTo(leaflet); + osm.addTo(leaflet); + } + + if (location.protocol === 'https:') { + // can't request location permission without https + L.control.locate().addTo(leaflet); + } + + return leaflet; +} + +function init_map_marker(leaflet, latlng) { + var marker = L.marker(latlng); + marker.addTo(leaflet); + leaflet.setView(latlng); + + // move marker on drag + leaflet.on('drag', function () { + marker.setLatLng(leaflet.getCenter()); + }); + // center map on zoom + leaflet.on('zoom', function () { + leaflet.setView(marker.getLatLng()); + }); + + return marker; +} + +function update_location(id, latlng, callback) { + $.ajax({ + method: 'PATCH', + url: "ajax/location/" + id, + data: {lat: latlng.lat, lng: latlng.lng} + }).success(function () { + toastr.success('Location updated'); + typeof callback === 'function' && callback(true); + }).error(function (e) { + var msg = 'Failed to update location: ' + e.statusText; + var data = e.responseJSON; + if (data) { + if (data.hasOwnProperty('lat')) { + msg = data.lat.join(' ') + '
'; + } + if (data.hasOwnProperty('lng')) { + if (!data.hasOwnProperty('lat')) { + msg = ''; + } + + msg += data.lng.join(' ') + } + } + + toastr.error(msg); + typeof callback === 'function' && callback(false); + + }); +} diff --git a/html/legacy_index.php b/html/legacy_index.php index 6e66699d6f..66ceb77354 100644 --- a/html/legacy_index.php +++ b/html/legacy_index.php @@ -97,11 +97,12 @@ if (empty($config['favicon'])) { + - + - +