1/** 2 * @namespace WPGMZA 3 * @module LeafletMap 4 * @requires WPGMZA.Map 5 * @pro-requires WPGMZA.ProMap 6 */ 7jQuery(function($) { 8 9 var Parent; 10 11 WPGMZA.LeafletMap = function(element, options) 12 { 13 var self = this; 14 15 Parent.call(this, element); 16 17 this.setOptions(options); 18 19 $(this.element).html(""); 20 21 let mapOptions = this.settings.toLeafletViewOptions(); 22 mapOptions = mapOptions ? mapOptions : {}; 23 24 this.mapType = mapOptions.mapType ? mapOptions.mapType : 'roadmap'; 25 this.tileLayers = this.getTileLayers(); 26 27 mapOptions.layers = this.tileLayers; 28 29 if(this.customTileMode){ 30 mapOptions.crs = L.extend({}, L.CRS.Simple, { 31 scale: (zoom) => { 32 const initialScale = Math.min( 33 1000 / this.customTileDimensions.width, 34 1000 / this.customTileDimensions.height 35 ); 36 return initialScale * Math.pow(2, zoom); 37 } 38 }); 39 40 if(this.customTileBounds){ 41 const mapBounds = L.latLngBounds(this.customTileBounds); 42 if(!mapBounds.contains(mapOptions.center)){ 43 /* Starting location is out of bounds */ 44 mapOptions.center = mapBounds.getCenter(); 45 this.onBoundsChanged(); 46 } 47 } 48 } 49 50 mapOptions = this.extendNativeConfig(mapOptions); 51 52 this.leafletMap = L.map($(element)[0], mapOptions); 53 54 function isSettingDisabled(value) { 55 if(value === "yes"){ 56 return true; 57 } 58 return (value ? true : false); 59 } 60 61 /* Gesture Handling */ 62 if(!(this.settings.wpgmza_force_greedy_gestures == "greedy" || this.settings.wpgmza_force_greedy_gestures == "yes" || this.settings.wpgmza_force_greedy_gestures == true)){ 63 this.gestureOverlay = $("<div class='wpgmza-gesture-overlay'></div>") 64 this.gestureOverlayTimeoutID = null; 65 66 if(WPGMZA.isTouchDevice()) { 67 /* Touch : Two finger pan for drag events */ 68 if(this.leafletMap.dragging){ 69 this.leafletMap.dragging.disable(); 70 71 this.gestureState = { 72 touches : {}, 73 touchCount : 0, 74 midpoint : null, 75 center : null 76 }; 77 78 const leafletContainer = this.leafletMap.getContainer(); 79 80 L.DomEvent.on(leafletContainer, 'touchstart', (event) => { 81 Array.from(event.touches).forEach((touch) => { 82 this.gestureState.touches[touch.identifier] = { 83 x : touch.clientX, 84 y : touch.clientY 85 }; 86 }); 87 88 this.gestureState.touchCount = Object.keys(this.gestureState.touches).length; 89 if(this.gestureState.touchCount === 2){ 90 /* Two finger pan, track the gesture event for panning */ 91 L.DomEvent.preventDefault(event); 92 93 let touches = { 94 a : event.touches[0], 95 b : event.touches[1] 96 }; 97 98 this.gestureState.midpoint = L.point( 99 (touches.a.clientX + touches.b.clientX) / 2, 100 (touches.a.clientY + touches.b.clientY) / 2 101 ); 102 103 this.gestureState.center = this.leafletMap.getCenter(); 104 } else if(this.gestureState.touchCount === 1){ 105 /* If one touch, show the notice, if more we don't do anything */ 106 this.showGestureOverlay(); 107 } 108 }); 109 110 L.DomEvent.on(leafletContainer, 'touchmove', (event) => { 111 if(this.gestureState.touchCount === 2 && event.touches.length === 2){ 112 L.DomEvent.preventDefault(event); 113 114 let touches = { 115 a : event.touches[0], 116 b : event.touches[1] 117 }; 118 119 const midpoint = L.point( 120 (touches.a.clientX + touches.b.clientX) / 2, 121 (touches.a.clientY + touches.b.clientY) / 2 122 ); 123 124 const delta = { 125 x : midpoint.x - this.gestureState.midpoint.x, 126 y : midpoint.y - this.gestureState.midpoint.y 127 }; 128 129 const mapCenterPoint = this.leafletMap.latLngToContainerPoint(this.gestureState.center); 130 131 this.leafletMap.panTo( 132 this.leafletMap.containerPointToLatLng( 133 L.point( 134 mapCenterPoint.x - delta.x, 135 mapCenterPoint.y - delta.y 136 ) 137 ), 138 { 139 animate : false 140 } 141 ); 142 } 143 }); 144 145 L.DomEvent.on(leafletContainer, 'touchend', (event) => {
146 Array.from(event.changedTouches).forEach((touch) => { 147 delete this.gestureState.touches[touch.identifier]; 148 }); 149 150 if(Object.keys(this.gestureState.touches).length < 2){ 151 this.gestureState.midpoint = null; 152 this.gestureState.center = null; 153 } 154 }); 155 156 L.DomEvent.on(leafletContainer, 'touchcancel', (event) => { 157 this.gestureState.touches = {}; 158 this.gestureState.midpoint = null; 159 this.gestureState.center = null; 160 }); 161 162 this.gestureOverlay.text(WPGMZA.localized_strings.use_two_fingers); 163 } 164 } else { 165 /* Desktop : Require CTLR or CMD + Scroll to zoom, show overlay if not */ 166 if(this.leafletMap.scrollWheelZoom){ 167 this.leafletMap.scrollWheelZoom.disable(); 168 169 const leafletContainer = this.leafletMap.getContainer(); 170 L.DomEvent.on(leafletContainer, 'wheel', (event) => { 171 L.DomEvent.preventDefault(event); 172 173 if(event.ctrlKey || event.metaKey){ 174 const delta = L.DomEvent.getWheelDelta(event); 175 this.leafletMap.setZoom(this.leafletMap.getZoom() + (delta > 0 ? 1 : -1)); 176 } else { 177 this.showGestureOverlay(); 178 } 179 }); 180 181 let getstureString = WPGMZA.localized_strings.use_ctrl_scroll_to_zoom; 182 if(WPGMZA.isDeviceiOS()){ 183 getstureString = WPGMZA.localized_strings.use_ctrl_scroll_to_zoom_ios; 184 } 185 186 this.gestureOverlay.text(getstureString); 187 } 188 } 189 } 190 191 /* Layer control */ 192 const multiLayerConfig = this.settings.hasMutlilayerTileServer(); 193 if(multiLayerConfig && !this.customTileMode){ 194 /* This map has more than one layer in it's tile server configuration */ 195 196 if(!isSettingDisabled(WPGMZA.settings.wpgmza_settings_map_type)){ 197 this.addMapTypeControl(multiLayerConfig); 198 } 199 } 200 201 /* Fullscreen Controller */ 202 if(!isSettingDisabled(WPGMZA.settings.wpgmza_settings_map_full_screen_control)){ 203 this.addFullscreenControl(); 204 } 205 206 /* Scale Control */ 207 if(this.settings.enable_scale_control){ 208 this.enableScaleControl(true); 209 } 210 211 /* Click listener */ 212 this.leafletMap.on('click', (event) => { 213 this.dispatchEvent({ 214 type: "click", 215 map: this, 216 latLng : { 217 lat : event.latlng.lat, 218 lng : event.latlng.lng 219 } 220 }); 221 }) 222 223 /* Drag Start */ 224 this.leafletMap.on("movestart", (event) => { 225 this.isBeingDragged = true; 226 }); 227 228 /* Drag End */ 229 this.leafletMap.on("moveend", (event) => { 230 // this.wrapLongitude(); 231 232 if(this.isBeingDragged){ 233 this.dispatchEvent("dragend"); 234 this.isBeingDragged = false; 235 } 236 this.onIdle(); 237 }); 238 239 /* Zoom Event */ 240 this.leafletMap.on('zoomend', (event) => { 241 this.dispatchEvent("zoom_changed"); 242 this.dispatchEvent("zoomchanged"); 243 setTimeout(() => { 244 this.onIdle(); 245 }, 10); 246 }); 247 248 /* Bounds change */ 249 this.leafletMap.on("move", () => { 250 this.onBoundsChanged(); 251 }); 252 253 this.onBoundsChanged(); 254 255 /* Right click listener */ 256 this.leafletMap.on('click contextmenu', (event) => { 257 let isRight; 258 259 if("which" in event.originalEvent) 260 isRight = event.originalEvent.which == 3; 261 else if("button" in event.originalEvent) 262 isRight = event.originalEvent.button == 2; 263 264 if(event.originalEvent.which == 1 || event.originalEvent.button == 1){ 265 if(this.isBeingDragged){ 266 return; 267 } 268 } 269 270 if(!isRight){ 271 return; 272 } 273 274 return this.onRightClick(event); 275 }); 276 277 // Dispatch event 278 if(!WPGMZA.isProVersion()) { 279 this.trigger("init"); 280 281 this.dispatchEvent("created"); 282 WPGMZA.events.dispatchEvent({type: "mapcreated", map: this}); 283 284 // Legacy event 285 $(this.element).trigger("wpgooglemaps_loaded"); 286 } 287 288 if(this.innerStack && this.innerStack.length > 0){ 289 /* Disable inner stack components from allowing clicks through to the map surface */ 290 this.innerStack.each((index, element) => { 291 L.DomEvent.disableClickPropagation(element); 292 L.DomEvent.disableScrollPropagation(element); 293 L.DomEvent.on(element, 'mousedown', L.DomEvent.stopPropagation); 294 }); 295 } 296 } 297 298 if(WPGMZA.isProVersion()) 299 Parent = WPGMZA.ProMap; 300 else
301 Parent = WPGMZA.Map; 302 303 WPGMZA.LeafletMap.prototype = Object.create(Parent.prototype); 304 WPGMZA.LeafletMap.prototype.constructor = WPGMZA.LeafletMap; 305 306 WPGMZA.LeafletMap.prototype.getTileLayers = function(){ 307 let url = WPGMZA.settings.tile_server_url ? WPGMZA.settings.tile_server_url : "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"; 308 let tileKey = WPGMZA.settings.leaflet_api_key ? WPGMZA.settings.leaflet_api_key : false; 309 310 switch(WPGMZA.settings.engine){ 311 case 'leaflet-azure': 312 /* Remap to Azure settings */ 313 url = WPGMZA.settings.tile_server_url_leaflet_azure ? WPGMZA.settings.tile_server_url_leaflet_azure : url; 314 tileKey = WPGMZA.settings.wpgmza_leaflet_azure_key ? WPGMZA.settings.wpgmza_leaflet_azure_key : tileKey; 315 break; 316 case 'leaflet-stadia': 317 /* Remap to Stadia settings */ 318 url = WPGMZA.settings.tile_server_url_leaflet_stadia ? WPGMZA.settings.tile_server_url_leaflet_stadia : url; 319 tileKey = WPGMZA.settings.wpgmza_leaflet_stadia_key ? WPGMZA.settings.wpgmza_leaflet_stadia_key : tileKey; 320 break; 321 case 'leaflet-maptiler': 322 /* Remap to Maptiler settings */ 323 url = WPGMZA.settings.tile_server_url_leaflet_maptiler ? WPGMZA.settings.tile_server_url_leaflet_maptiler : url; 324 tileKey = WPGMZA.settings.wpgmza_leaflet_maptiler_key ? WPGMZA.settings.wpgmza_leaflet_maptiler_key : tileKey; 325 break; 326 case 'leaflet-locationiq': 327 /* Remap to LocationIQ settings */ 328 url = WPGMZA.settings.tile_server_url_leaflet_locationiq ? WPGMZA.settings.tile_server_url_leaflet_locationiq : url; 329 tileKey = WPGMZA.settings.wpgmza_leaflet_locationiq_key ? WPGMZA.settings.wpgmza_leaflet_locationiq_key : tileKey; 330 break; 331 case 'leaflet-zerocost': 332 /* Remap to zerocost settings */ 333 url = WPGMZA.settings.tile_server_url_leaflet_zerocost ? WPGMZA.settings.tile_server_url_leaflet_zerocost : url; 334 break; 335 } 336 337 const config = this.settings.configureTileServer(url, { 338 authentication : tileKey, 339 preferServerGlobals : true, 340 map : this 341 }); 342 343 if(config && config.url){ 344 if(config.type && config.type === 'vector' && typeof L.maplibreGL !== 'undefined'){ 345 /* Vector base layer, so we use MapLibreGL */ 346 let mapLibreOptions = {style : config.url}; 347 if(config.options){ 348 for(let key in config.options){ 349 if(key === 'url'){ 350 continue; 351 } 352 353 mapLibreOptions[key] = config.options[key]; 354 }; 355 } 356 357 return [L.maplibreGL(mapLibreOptions)]; 358 } else if (config.type && config.type === 'custom'){ 359 this.customTileDimensions = {width : config.custom.width, height : config.custom.height}; 360 this.customTileBounds = [[0,0], [this.customTileDimensions.height, this.customTileDimensions.width]]; 361 this.customTileMode = true; 362 return [L.imageOverlay(config.url, this.customTileBounds, { 363 attribution: config.custom.attribution ? config.custom.attribution : '©' 364 })]; 365 } 366 367 const layers = []; 368 369 if(config.dependencies){ 370 for(let dependency of config.dependencies){ 371 layers.push(new L.tileLayer(dependency.url, config.options ? config.options : {})); 372 } 373 } 374 375 layers.push(new L.tileLayer(config.url, config.options ? config.options : {})); 376 return layers; 377 } 378 379 /* Fallback */ 380 return [new L.tileLayer(url, {})]; 381 } 382 383 WPGMZA.LeafletMap.prototype.wrapLongitude = function(){ 384 let center = this.leafletMap.getCenter(); 385 if(center.lng >= -180 && center.lng <= 180){ 386 return; 387 } 388 389 center.lng = center.lng - 360 * Math.floor(center.lng / 360); 390 391 if(center.lng > 180){ 392 center.lng -= 360; 393 } 394 395 this.setCenter(center); 396 } 397 398 WPGMZA.LeafletMap.prototype.getCenter = function(){ 399 const center = this.leafletMap.getCenter(); 400 return { 401 lat: center.lat, 402 lng: center.lng 403 }; 404 } 405 406 WPGMZA.LeafletMap.prototype.setCenter = function(latLng) { 407 WPGMZA.Map.prototype.setCenter.call(this, latLng); 408 409 this.leafletMap.panTo(L.latLng({lat : latLng.lat, lng : latLng.lng}), {animate : false}); 410 // this.wrapLongitude(); 411 412 this.onBoundsChanged(); 413 } 414 415 WPGMZA.LeafletMap.prototype.getBounds = function() { 416 let bounds = this.leafletMap.getBounds(); 417 let nativeBounds = new WPGMZA.LatLngBounds(); 418 419 nativeBounds.north = bounds.getNorth(); 420 nativeBounds.south = bounds.getSouth(); 421 422 nativeBounds.west = bounds.getWest();
423 nativeBounds.east = bounds.getEast(); 424 425 return nativeBounds; 426 } 427 428 /** 429 * Fit to given boundaries 430 * @return void 431 */ 432 WPGMZA.LeafletMap.prototype.fitBounds = function(southWest, northEast) { 433 if(southWest instanceof WPGMZA.LatLng){ 434 southWest = {lat: southWest.lat, lng: southWest.lng}; 435 } 436 437 if(northEast instanceof WPGMZA.LatLng){ 438 northEast = {lat: northEast.lat, lng: northEast.lng}; 439 } else if(southWest instanceof WPGMZA.LatLngBounds) { 440 var bounds = southWest; 441 442 southWest = { 443 lat: bounds.south, 444 lng: bounds.west 445 }; 446 447 northEast = { 448 lat: bounds.north, 449 lng: bounds.east 450 }; 451 } 452 453 const leafletBounds = L.latLngBounds( 454 L.latLng({lat : northEast.lat, lng : northEast.lng}), 455 L.latLng({lat : southWest.lat, lng : southWest.lng}) 456 ); 457 458 this.leafletMap.fitBounds(leafletBounds, { padding : [60, 60]}); 459 } 460 461 WPGMZA.LeafletMap.prototype.panTo = function(latLng, zoom) { 462 if(arguments.length > 1){ 463 this.leafletMap.flyTo(L.latLng({lat: latLng.lat, lng: latLng.lng}), parseInt(zoom)); 464 } else { 465 this.leafletMap.flyTo(L.latLng({lat: latLng.lat, lng: latLng.lng})); 466 } 467 } 468 469 WPGMZA.LeafletMap.prototype.getZoom = function() { 470 return Math.round( this.leafletMap.getZoom() ); 471 } 472 473 WPGMZA.LeafletMap.prototype.setZoom = function(value) { 474 this.leafletMap.setZoom(value); 475 } 476 477 WPGMZA.LeafletMap.prototype.getMinZoom = function() { 478 return this.leafletMap.getMinZoom(); 479 } 480 481 WPGMZA.LeafletMap.prototype.setMinZoom = function(value) { 482 this.leafletMap.setMinZoom(value); 483 } 484 485 WPGMZA.LeafletMap.prototype.getMaxZoom = function() { 486 return this.leafletMap.getMaxZoom(); 487 } 488 489 WPGMZA.LeafletMap.prototype.setMaxZoom = function(value) { 490 this.leafletMap.setMaxZoom(value); 491 } 492 493 WPGMZA.LeafletMap.prototype.setMapType = function(type){ 494 if(this.mapType !== type){ 495 this.mapType = type; 496 497 if(this.tileLayers){ 498 for(let layer of this.tileLayers){ 499 if(this.leafletMap.hasLayer(layer)){ 500 this.leafletMap.removeLayer(layer); 501 } 502 } 503 } 504 505 this.tileLayers = this.getTileLayers(); 506 507 for(let layer of this.tileLayers){ 508 this.leafletMap.addLayer(layer); 509 } 510 511 $(this.element).find('.leaflet-layer-button[data-map-type]').removeClass('selected'); 512 $(this.element).find('.leaflet-layer-button[data-map-type="' + type + '"]').addClass('selected'); 513 } 514 } 515 516 WPGMZA.LeafletMap.prototype.getMapType = function(){ 517 return this.mapType ? this.mapType : 'roadmap'; 518 } 519 520 WPGMZA.LeafletMap.prototype.setOptions = function(options) { 521 Parent.prototype.setOptions.call(this, options); 522 523 if(!this.leafletMap){ 524 /* Hasn't been initialized yet */ 525 return; 526 } 527 528 /* Leaflet doesn't allow a bulk setter like other engines, we need to manage this internally */ 529 let mapOptions = this.settings.toLeafletViewOptions(); 530 for (const key in mapOptions) { 531 if (!mapOptions.hasOwnProperty(key)) { 532 continue; 533 } 534 535 const value = options[key]; 536 537 switch (key) { 538 case 'zoomControl': 539 if (value === false && this.leafletMap.zoomControl) { 540 this.leafletMap.removeControl(this.leafletMap.zoomControl); 541 } else if (value === true && !this.leafletMap.zoomControl) { 542 this.leafletMap.addControl(L.control.zoom()); 543 } 544 break; 545 case 'dragging': 546 case 'doubleClickZoom': 547 case 'scrollWheelZoom': 548 case 'boxZoom': 549 case 'keyboard': 550 case 'tap': 551 case 'touchZoom': 552 if (this.leafletMap[key]) { 553 if (value === true) { 554 this.leafletMap[key].enable(); 555 } else { 556 this.leafletMap[key].disable(); 557 } 558 } 559 break; 560 case 'minZoom': 561 this.setMinZoom(value); 562 break; 563 case 'maxZoom': 564 this.setMaxZoom(value); 565 break; 566 default: 567 break; 568 } 569 } 570 } 571 572 /** 573 * TODO: Consider moving all these functions to their respective classes, same on google map (DO IT!!! It's very misleading having them here) 574 */ 575 WPGMZA.LeafletMap.prototype.addMarker = function(marker) { 576 marker.leafletMarker.addTo(this.leafletMap); 577 Parent.prototype.addMarker.call(this, marker); 578 } 579 580 WPGMZA.LeafletMap.prototype.removeMarker = function(marker) { 581 marker.leafletMarker.removeFrom(this.leafletMap); 582 Parent.prototype.removeMarker.call(this, marker); 583 } 584 585 WPGMZA.LeafletMap.prototype.addPolygon = function(polygon) { 586 polygon.leafletFeature.addTo(this.leafletMap); 587 Parent.prototype.addPolygon.call(this, polygon); 588 } 589 590 WPGMZA.LeafletMap.prototype.removePolygon = function(polygon) { 591 polygon.leafletFeature.remove(); 592 Parent.prototype.removePolygon.call(this, polygon); 593 } 594 595 WPGMZA.LeafletMap.prototype.addPolyline = function(polyline) { 596 polyline.leafletFeature.addTo(this.leafletMap); 597 Parent.prototype.addPolyline.call(this, polyline); 598 } 599 600 WPGMZA.LeafletMap.prototype.removePolyline = function(polyline) { 601 polyline.leafletFeature.remove(); 602 Parent.prototype.removePolyline.call(this, polyline); 603 } 604 605 WPGMZA.LeafletMap.prototype.addCircle = function(circle) { 606 circle.leafletFeature.addTo(this.leafletMap); 607 Parent.prototype.addCircle.call(this, circle); 608 } 609 610 WPGMZA.LeafletMap.prototype.removeCircle = function(circle) { 611 circle.leafletFeature.remove(); 612 Parent.prototype.removeCircle.call(this, circle); 613 } 614 615 WPGMZA.LeafletMap.prototype.addRectangle = function(rectangle) { 616 rectangle.leafletFeature.addTo(this.leafletMap); 617 Parent.prototype.addRectangle.call(this, rectangle); 618 } 619 620 WPGMZA.LeafletMap.prototype.removeRectangle = function(rectangle) { 621 rectangle.leafletFeature.remove(); 622 Parent.prototype.removeRectangle.call(this, rectangle); 623 } 624 625 WPGMZA.LeafletMap.prototype.pixelsToLatLng = function(x, y) { 626 if(y == undefined) { 627 if("x" in x && "y" in x) { 628 y = x.y; 629 x = x.x; 630 } else { 631 console.warn("Y coordinate undefined in pixelsToLatLng (did you mean to pass 2 arguments?)"); 632 } 633 } 634 635 let coord = this.leafletMap.containerPointToLatLng(L.point(x, y)); 636 if(!coord){ 637 return { 638 x: null, 639 y: null 640 }; 641 } 642 643 return { 644 lat: coord.lat, 645 lng: coord.lng 646 }; 647 } 648 649 WPGMZA.LeafletMap.prototype.latLngToPixels = function(latLng) { 650 let pixel = this.leafletMap.latLngToContainerPoint(latLng); 651 if(!pixel){ 652 return { 653 x: null, 654 y: null 655 }; 656 } 657 658 return { 659 x: pixel.x, 660 y: pixel.y 661 }; 662 } 663 664 WPGMZA.LeafletMap.prototype.showGestureOverlay = function() { 665 clearTimeout(this.gestureOverlayTimeoutID); 666 667 $(this.gestureOverlay).stop().animate({opacity: "100"}); 668 $(this.element).append(this.gestureOverlay); 669 670 $(this.gestureOverlay).css({ 671 "line-height": $(this.element).height() + "px", 672 "opacity": "1.0" 673 }); 674 675 $(this.gestureOverlay).show(); 676 677 this.gestureOverlayTimeoutID = setTimeout(() => { 678 this.gestureOverlay.fadeOut(500); 679 }, 1000); 680 } 681 682 WPGMZA.LeafletMap.prototype.onRightClick = function(event) { 683 this.trigger({type: "rightclick", latLng: event.latlng}); 684 685 // Legacy event compatibility 686 $(this.element).trigger({type: "rightclick", latLng: event.latlng}); 687 688 // Prevent menu 689 event.originalEvent.preventDefault(); 690 return false; 691 } 692 693 WPGMZA.LeafletMap.prototype.addFullscreenControl = function(){ 694 if(this.leafletMap){
695 const fullscreenController = L.control({position : 'topright'}); 696 fullscreenController.onAdd = (map) => { 697 const container = L.DomUtil.create('div'); 698 container.classList.add('leaflet-bar'); 699 container.classList.add('leaflet-control'); 700 container.classList.add('leaflet-control-fullscreen'); 701 702 const button = L.DomUtil.create('a'); 703 button.classList.add('leaflet-control-button'); 704 button.classList.add('leaflet-fullscreen-button'); 705 button.href = '#'; 706 707 button.setAttribute('aria-label', "Fullscreen"); 708 709 const corners = ['tl' , 'tr' , 'bl', 'br']; 710 for(let corner of corners){ 711 const element = L.DomUtil.create('span'); 712 element.classList.add('leaflet-fullscreen-corner'); 713 element.classList.add('leaflet-fullscreen-corner-' + corner); 714 button.append(element); 715 } 716 717 container.append(button); 718 719 L.DomEvent.on(button, 'click', (event) => { 720 event.preventDefault(); 721 if(document.fullscreenElement){ 722 document.exitFullscreen(); 723 } else { 724 const mapContainer = this.element; 725 if (mapContainer.requestFullscreen) { 726 mapContainer.requestFullscreen(); 727 } else if (mapContainer.mozRequestFullScreen) { 728 mapContainer.mozRequestFullScreen(); 729 } else if (mapContainer.webkitRequestFullscreen) { 730 mapContainer.webkitRequestFullscreen(); 731 } else if (mapContainer.msRequestFullscreen) { 732 mapContainer.msRequestFullscreen(); 733 } 734 } 735 }); 736 737 return container; 738 } 739 740 fullscreenController.addTo(this.leafletMap); 741 } 742 } 743 744 WPGMZA.LeafletMap.prototype.addMapTypeControl = function(config){ 745 if(this.leafletMap && config && config.layers && config.layers.length >= 2){ 746 const layerController = L.control({position : 'topright'}); 747 layerController.onAdd = (map) => { 748 const container = L.DomUtil.create('div'); 749 container.classList.add('leaflet-bar'); 750 container.classList.add('leaflet-control'); 751 container.classList.add('leaflet-control-layers'); 752 753 for(let index in config.layers){ 754 const layer = config.layers[index]; 755 756 let label = WPGMZA.localized_strings[`map_type_${layer}`] ? WPGMZA.localized_strings[`map_type_${layer}`] : WPGMZA.capitalizeWords(layer); 757 758 const button = L.DomUtil.create('a'); 759 button.innerText = label; 760 button.classList.add('leaflet-control-button'); 761 button.classList.add('leaflet-layer-button'); 762 button.href = '#'; 763 764 button.setAttribute('data-map-type', layer); 765 766 if(config.active && config.active === layer){ 767 button.classList.add('selected'); 768 } 769 770 container.append(button); 771 772 L.DomEvent.on(button, 'click', (event) => { 773 event.preventDefault(); 774 this.setMapType(layer); 775 }); 776 } 777 778 779 return container; 780 } 781 782 layerController.addTo(this.leafletMap); 783 } 784 } 785 786 /** 787 * Enables / disables the scale control bar 788 * @param enable boolean, enable or not 789 * @return void 790 */ 791 WPGMZA.LeafletMap.prototype.enableScaleControl = function(enable) 792 { 793 if(!this.leafletMap) 794 return; 795 796 if(this.scaleControl){ 797 this.scaleControl.remove(); 798 this.scaleControl = null; 799 } 800 801 if(enable){ 802 const imperial = (this.settings.store_locator_distance == WPGMZA.Distance.MILES); 803 804 this.scaleControl = L.control.scale({ 805 imperial: imperial, 806 metric: !imperial, 807 position: 'bottomleft' 808 }).addTo(this.leafletMap); 809 } 810 } 811 812 WPGMZA.LeafletMap.prototype.getLayerGroupPane = function(pane, layer, basePane){ 813 basePane = typeof basePane === 'undefined' || !basePane ? 'overlayPane' : basePane; 814 if(this.leafletMap){ 815 let nativePane = this.leafletMap.getPane(`${pane}${layer}`); 816 if(!nativePane){ 817 nativePane = this.leafletMap.createPane(`${pane}${layer}`, this.leafletMap.getPane(basePane)); 818 nativePane.style.zIndex = layer; 819 } 820 821 return `${pane}${layer}`; 822 } 823 return false; 824 } 825 826 WPGMZA.LeafletMap.prototype.resetBounds = function() { 827 var latlng = new WPGMZA.LatLng(this.settings.map_start_lat, this.settings.map_start_lng); 828 this.panTo(latlng, this.settings.map_start_zoom); 829 } 830});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.