1/** 2 * @namespace WPGMZA 3 * @module OLMap 4 * @requires WPGMZA.Map 5 * @pro-requires WPGMZA.ProMap 6 */ 7jQuery(function($) { 8 9 var Parent; 10 11 WPGMZA.OLMap = function(element, options) 12 { 13 var self = this; 14 15 Parent.call(this, element); 16 17 this.setOptions(options); 18 19 var viewOptions = this.settings.toOLViewOptions(); 20 21 this.mapType = viewOptions.mapType ? viewOptions.mapType : 'roadmap'; 22 this.tileLayers = this.getTileLayers(); 23 24 $(this.element).html(""); 25 26 viewOptions = this.extendNativeConfig(viewOptions); 27 28 let mapOptions = { 29 target: $(element)[0], 30 layers: this.tileLayers, 31 view: this.getTileView(viewOptions) 32 }; 33 34 if(!this.isLegacy()){ 35 /* Has V10 OpenLayers */ 36 const attributionOptions = { collapsible: true }; 37 if(typeof WPGMZA.tileServer !== 'undefined' && WPGMZA.tileServer instanceof Object){ 38 if(WPGMZA.tileServer.attribution && WPGMZA.tileServer.type === 'xyz'){ 39 attributionOptions.attributions = WPGMZA.tileServer.attribution; 40 } 41 } 42 const attribution = new ol.control.Attribution(attributionOptions); 43 mapOptions.controls = ol.control.defaults.defaults({attribution: false}).extend([attribution]); 44 } 45 46 47 this.olMap = new ol.Map(mapOptions); 48 49 if(this.customTileMode){ 50 /* The system is in custom tile view mode */ 51 if(!(ol.extent.containsCoordinate(this.customTileModeExtent, this.olMap.getView().getCenter()))){ 52 const view = this.olMap.getView(); 53 54 view.setCenter(ol.extent.getCenter(this.customTileModeExtent)); 55 this.wrapLongitude(); 56 this.onBoundsChanged(); 57 } 58 } 59 60 // NB: Handles legacy checkboxes as well as new, standard controls 61 function isSettingDisabled(value) 62 { 63 if(value === "yes") 64 return true; 65 66 return (value ? true : false); 67 } 68 69 // TODO: Re-implement using correct setting names 70 // Interactions 71 this.olMap.getInteractions().forEach(function(interaction) { 72 73 // NB: The true and false values are flipped because these settings represent the "disabled" state when true 74 if(interaction instanceof ol.interaction.DragPan) 75 interaction.setActive( 76 !isSettingDisabled(self.settings.wpgmza_settings_map_draggable) 77 ); 78 else if(interaction instanceof ol.interaction.DoubleClickZoom) 79 interaction.setActive( 80 !isSettingDisabled(self.settings.wpgmza_settings_map_clickzoom) 81 ); 82 else if(interaction instanceof ol.interaction.MouseWheelZoom) 83 interaction.setActive( 84 !isSettingDisabled(self.settings.wpgmza_settings_map_scroll) 85 ); 86 87 }, this); 88 89 // Cooperative gesture handling 90 if(!(this.settings.wpgmza_force_greedy_gestures == "greedy" || this.settings.wpgmza_force_greedy_gestures == "yes" || this.settings.wpgmza_force_greedy_gestures == true)) 91 { 92 this.gestureOverlay = $("<div class='wpgmza-gesture-overlay'></div>") 93 this.gestureOverlayTimeoutID = null; 94 95 if(WPGMZA.isTouchDevice()) 96 { 97 // On touch devices, require two fingers to drag and pan 98 // NB: Temporarily removed due to inconsistent behaviour 99 100 // Reintroduced: 9.0.0 -> We have made some changes to improve consistency 101 this.olMap.getInteractions().forEach(function(interaction) { 102 103 if(interaction instanceof ol.interaction.DragPan) 104 self.olMap.removeInteraction(interaction); 105 106 }); 107 108 this.olMap.addInteraction(new ol.interaction.DragPan({ 109 110 condition: function(olBrowserEvent) { 111 let allowed = false; 112 let originalEvent = olBrowserEvent.originalEvent; 113 if(originalEvent instanceof PointerEvent){ 114 /* Handle this as a pointer */ 115 if(this.targetPointers && this.targetPointers.length){ 116 allowed = this.targetPointers.length == 2; 117 } 118 } else if (originalEvent instanceof TouchEvent){ 119 if(originalEvent.touches && originalEvent.touches.length){ 120 allowed = originalEvent.touches.length == 2; 121 } 122 } 123 124 if(!allowed) 125 self.showGestureOverlay(); 126 127 return allowed; 128 } 129 130 })); 131 132 this.gestureOverlay.text(WPGMZA.localized_strings.use_two_fingers); 133 } 134 else 135 { 136 // On desktops, require Ctrl + zoom to zoom, show an overlay if that condition is not met 137 this.olMap.on("wheel", function(event) { 138 139 if(!ol.events.condition.platformModifierKeyOnly(event)) 140 { 141 self.showGestureOverlay(); 142 143 // Allow the page to scroll normally by commenting this out 144 //event.originalEvent.preventDefault(); 145 146 return false; 147 } 148 149 }); 150 151 let getstureString = WPGMZA.localized_strings.use_ctrl_scroll_to_zoom; 152 if(WPGMZA.isDeviceiOS()){ 153 getstureString = WPGMZA.localized_strings.use_ctrl_scroll_to_zoom_ios; 154 } 155 156 this.gestureOverlay.text(getstureString); 157 } 158 } 159 160 // Controls
161 this.olMap.getControls().forEach(function(control) { 162 163 // NB: The true and false values are flipped because these settings represent the "disabled" state when true 164 if(control instanceof ol.control.Zoom && WPGMZA.settings.wpgmza_settings_map_zoom == true) 165 self.olMap.removeControl(control); 166 167 }, this); 168 169 170 /* Layer control */ 171 const multiLayerConfig = this.settings.hasMutlilayerTileServer(); 172 if(multiLayerConfig){ 173 /* This map has more than one layer in it's tile server configuration */ 174 if(!isSettingDisabled(WPGMZA.settings.wpgmza_settings_map_type)){ 175 this.addMapTypeControl(multiLayerConfig, !isSettingDisabled(WPGMZA.settings.wpgmza_settings_map_full_screen_control)); 176 } 177 } 178 179 if(!isSettingDisabled(WPGMZA.settings.wpgmza_settings_map_full_screen_control)){ 180 this.olMap.addControl(new ol.control.FullScreen()); 181 } 182 183 if(this.settings.enable_scale_control){ 184 this.enableScaleControl(true); 185 } 186 187 if(WPGMZA.OLMarker.renderMode == WPGMZA.OLMarker.RENDER_MODE_VECTOR_LAYER) 188 { 189 // Marker layer 190 this.markerLayer = new ol.layer.Vector({ 191 source: new ol.source.Vector({ 192 features: [] 193 }) 194 }); 195 this.olMap.addLayer(this.markerLayer); 196 197 this.olMap.on("click", function(event) { 198 var features = self.olMap.getFeaturesAtPixel(event.pixel); 199 200 if(!features || !features.length) 201 return; 202 203 var marker = features[0].wpgmzaMarker; 204 205 if(!marker){ 206 return; 207 } 208 209 marker.trigger("click"); 210 marker.trigger("select"); 211 }); 212 } 213 214 // Listen for drag start 215 this.olMap.on("movestart", function(event) { 216 self.isBeingDragged = true; 217 }); 218 219 // Listen for end of pan so we can wrap longitude if needs be 220 this.olMap.on("moveend", function(event) { 221 self.wrapLongitude(); 222 223 self.isBeingDragged = false; 224 self.dispatchEvent("dragend"); 225 self.onIdle(); 226 }); 227 228 // Listen for zoom 229 this.olMap.getView().on("change:resolution", function(event) { 230 self.dispatchEvent("zoom_changed"); 231 self.dispatchEvent("zoomchanged"); 232 setTimeout(function() { 233 self.onIdle(); 234 }, 10); 235 }); 236 237 // Listen for bounds changing 238 this.olMap.getView().on("change", function() { 239 // Wrap longitude 240 self.onBoundsChanged(); 241 }); 242 self.onBoundsChanged(); 243 244 // Hover interaction 245 this._mouseoverNativeFeatures = []; 246 247 this.olMap.on("pointermove", function(event) { 248 249 if(event.dragging) 250 return; 251 252 try{ 253 var featuresUnderPixel = event.target.getFeaturesAtPixel(event.pixel); 254 }catch(e) { 255 // NB: Hacktacular.. An error is thrown when you mouse over a heatmap. See https://github.com/openlayers/openlayers/issues/10100. This was allegedly solved and merged in but seems to still be present in OpenLayers 6.4.3. 256 return; 257 } 258 259 if(!featuresUnderPixel) 260 featuresUnderPixel = []; 261 262 var nativeFeaturesUnderPixel = [], i, props; 263 264 for(i = 0; i < featuresUnderPixel.length; i++) 265 { 266 props = featuresUnderPixel[i].getProperties(); 267 268 if(!props.wpgmzaFeature) 269 continue; 270 271 nativeFeature = props.wpgmzaFeature; 272 nativeFeaturesUnderPixel.push(nativeFeature); 273 274 if(self._mouseoverNativeFeatures.indexOf(nativeFeature) == -1) 275 { 276 // Now hovering over this feature, when we weren't previously 277 nativeFeature.trigger("mouseover"); 278 self._mouseoverNativeFeatures.push(nativeFeature); 279 } 280 } 281
282 for(i = self._mouseoverNativeFeatures.length - 1; i >= 0; i--) 283 { 284 nativeFeature = self._mouseoverNativeFeatures[i]; 285 286 if(nativeFeaturesUnderPixel.indexOf(nativeFeature) == -1) 287 { 288 // No longer hovering over this feature, where we had been previously 289 nativeFeature.trigger("mouseout"); 290 self._mouseoverNativeFeatures.splice(i, 1); 291 } 292 } 293 294 }); 295 296 // Right click listener 297 $(this.element).on("click contextmenu", function(event) { 298 299 var isRight; 300 event = event || window.event; 301 302 var latLng = self.pixelsToLatLng(event.offsetX, event.offsetY); 303 304 if("which" in event) 305 isRight = event.which == 3; 306 else if("button" in event) 307 isRight = event.button == 2; 308 309 if(event.which == 1 || event.button == 1){ 310 if(self.isBeingDragged) 311 return; 312 313 // Left click 314 if($(event.target).closest(".ol-marker").length) 315 return; // A marker was clicked, not the map. Do nothing 316 317 /* 318 * User is clicking on the map, but looks like it was not a marker... 319 * 320 * Finding a light at the end of the tunnel 321 */ 322 try{ 323 if(self.element){ 324 const nestedCanvases = self.element.querySelectorAll('canvas'); 325 if(nestedCanvases.length > 1){ 326 const diff = (nestedCanvases[0].width / nestedCanvases[1].width); 327 event.offsetX *= diff; 328 event.offsetY *= diff; 329 } 330 } 331 332 var featuresUnderPixel = self.olMap.getFeaturesAtPixel([event.offsetX, event.offsetY]); 333 }catch(e) { 334 return; 335 } 336 337 if(!featuresUnderPixel) 338 featuresUnderPixel = []; 339 340 var nativeFeaturesUnderPixel = [], i, props; 341 for(i = 0; i < featuresUnderPixel.length; i++){ 342 props = featuresUnderPixel[i].getProperties(); 343 344 if(!props.wpgmzaFeature) 345 continue; 346 347 nativeFeature = props.wpgmzaFeature; 348 nativeFeaturesUnderPixel.push(nativeFeature); 349 let clickCoordinates = new WPGMZA.LatLng(latLng); 350 nativeFeature.trigger({type:"click", coordinates : clickCoordinates}); 351 } 352 353 if(featuresUnderPixel.length > 0){ 354 /* 355 * This is for a pixel interpolated feature, like polygons 356 * 357 * Let's return early, to avoid double event firing 358 */ 359 return; 360 } 361 362 if(event.target instanceof HTMLCanvasElement){ 363 /* Only trigger if this is the canvas element directly */ 364 self.trigger({ 365 type: "click", 366 latLng: latLng 367 }); 368 } 369 370 return; 371 } 372 373 if(!isRight){ 374 return; 375 } 376 377 return self.onRightClick(event); 378 }); 379 380 // Touch event support 381 $(this.element).on("touchstart", function (event) { 382 try{ 383 let offsetX; 384 let offsetY; 385 if(self.element){ 386 const nestedCanvases = self.element.querySelectorAll('canvas'); 387 388 const touch = event.originalEvent.changedTouches[0]; 389 const targetElement = event.originalEvent.target; 390 const rect = targetElement.getBoundingClientRect(); 391 392 offsetX = touch.clientX - rect.left; 393 offsetY = touch.clientY - rect.top; 394 395 if(nestedCanvases.length > 1){ 396 const diff = (nestedCanvases[0].width / nestedCanvases[1].width); 397 offsetX *= diff; 398 offsetY *= diff; 399 } 400 } 401 402 var featuresUnderPixel = self.olMap.getFeaturesAtPixel([offsetX, offsetY]); 403 }catch(e) { 404 return; 405 } 406 407 if(!featuresUnderPixel){ 408 featuresUnderPixel = []; 409 } 410 411 var nativeFeaturesUnderPixel = [], i, props; 412 for(i = 0; i < featuresUnderPixel.length; i++){ 413 props = featuresUnderPixel[i].getProperties(); 414 415 if(!props.wpgmzaFeature){ 416 continue; 417 } 418 419 nativeFeature = props.wpgmzaFeature; 420 nativeFeaturesUnderPixel.push(nativeFeature); 421 422 nativeFeature.trigger("click"); 423 } 424 }); 425 426 427 // Dispatch event 428 if(!WPGMZA.isProVersion()) 429 { 430 this.trigger("init"); 431 432 this.dispatchEvent("created"); 433 WPGMZA.events.dispatchEvent({type: "mapcreated", map: this}); 434 435 // Legacy event 436 $(this.element).trigger("wpgooglemaps_loaded"); 437 } 438 } 439 440 if(WPGMZA.isProVersion()) 441 Parent = WPGMZA.ProMap; 442 else
443 Parent = WPGMZA.Map; 444 445 WPGMZA.OLMap.prototype = Object.create(Parent.prototype); 446 WPGMZA.OLMap.prototype.constructor = WPGMZA.OLMap; 447 448 WPGMZA.OLMap.prototype.getTileLayers = function() { 449 let url = WPGMZA.settings.tile_server_url ? WPGMZA.settings.tile_server_url : "https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png"; 450 const config = this.settings.configureTileServer(url, { 451 authentication : WPGMZA.settings.open_layers_api_key ? WPGMZA.settings.open_layers_api_key : false, 452 map : this 453 }); 454 455 if(config && config.url){ 456 if(config.type && config.type === 'vector' && typeof olms !== 'undefined'){ 457 const layerGroup = new ol.layer.Group(); 458 olms.apply(layerGroup, config.url); 459 460 return [layerGroup]; 461 } else if(config.type && config.type === 'custom' && config.custom){ 462 /* Custom mode */ 463 const extent = [0, 0, config.custom.width, config.custom.height]; 464 465 const projection = new ol.proj.Projection({ 466 code: 'custom-tile-map', 467 units: 'pixels', 468 extent: extent 469 }); 470 471 return [new ol.layer.Image({ 472 source: new ol.source.ImageStatic({ 473 attributions: config.custom.attribution ? config.custom.attribution : '©', 474 url: config.url, 475 projection: projection, 476 imageExtent: extent, 477 imageSize: config.custom.dimensions ? config.custom.dimensions : null 478 }) 479 })]; 480 } 481 482 const layers = []; 483 484 if(config.dependencies){ 485 for(let dependency of config.dependencies){ 486 config.options.url = dependency.url; 487 layers.push( 488 new ol.layer.Tile({ 489 source: new ol.source.OSM(config.options) 490 }) 491 ); 492 } 493 } 494 495 config.options.url = config.url; 496 layers.push( 497 new ol.layer.Tile({ 498 source: new ol.source.OSM(config.options) 499 }) 500 ); 501 502 return layers; 503 } 504 505 /* Fallback */ 506 return [new ol.layer.Tile({ 507 source: new ol.source.OSM({url : url}) 508 })]; 509 } 510 511 WPGMZA.OLMap.prototype.getTileView = function(viewOptions){ 512 if(this.settings && this.settings.custom_tile_enabled){ 513 if(this.settings.custom_tile_image_width && this.settings.custom_tile_image_height){ 514 const width = parseInt(this.settings.custom_tile_image_width); 515 const height = parseInt(this.settings.custom_tile_image_height); 516 517 if(this.settings.custom_tile_image){ 518 const extent = [0, 0, width, height]; 519 520 const projection = new ol.proj.Projection({ 521 code: 'custom-tile-map', 522 units: 'pixels', 523 extent: extent 524 }); 525 526 viewOptions.projection = projection; 527 528 this.customTileModeExtent = extent; 529 this.customTileMode = true; 530 } 531 } 532 } 533 return new ol.View(viewOptions); 534 } 535 536 WPGMZA.OLMap.prototype.wrapLongitude = function() 537 { 538 var transformed = ol.proj.transform(this.olMap.getView().getCenter(), "EPSG:3857", "EPSG:4326"); 539 var center = { 540 lat: transformed[1], 541 lng: transformed[0] 542 }; 543 544 if(center.lng >= -180 && center.lng <= 180) 545 return; 546 547 center.lng = center.lng - 360 * Math.floor(center.lng / 360); 548 549 if(center.lng > 180) 550 center.lng -= 360; 551 552 this.setCenter(center); 553 } 554 555 WPGMZA.OLMap.prototype.getCenter = function() 556 { 557 var lonLat = ol.proj.toLonLat( 558 this.olMap.getView().getCenter() 559 ); 560 return { 561 lat: lonLat[1], 562 lng: lonLat[0] 563 }; 564 } 565 566 WPGMZA.OLMap.prototype.setCenter = function(latLng) 567 { 568 var view = this.olMap.getView(); 569 570 WPGMZA.Map.prototype.setCenter.call(this, latLng); 571 572 view.setCenter(ol.proj.fromLonLat([ 573 latLng.lng, 574 latLng.lat 575 ])); 576 577 this.wrapLongitude(); 578 579 this.onBoundsChanged(); 580 } 581 582 WPGMZA.OLMap.prototype.getBounds = function() 583 { 584 var bounds = this.olMap.getView().calculateExtent(this.olMap.getSize()); 585 var nativeBounds = new WPGMZA.LatLngBounds(); 586 587 var topLeft = ol.proj.toLonLat([bounds[0], bounds[1]]); 588 var bottomRight = ol.proj.toLonLat([bounds[2], bounds[3]]); 589 590 nativeBounds.north = topLeft[1]; 591 nativeBounds.south = bottomRight[1]; 592 593 nativeBounds.west = topLeft[0]; 594 nativeBounds.east = bottomRight[0]; 595 596 return nativeBounds; 597 } 598 599 /** 600 * Fit to given boundaries 601 * @return void 602 */ 603 WPGMZA.OLMap.prototype.fitBounds = function(southWest, northEast) 604 { 605 if(southWest instanceof WPGMZA.LatLng) 606 southWest = {lat: southWest.lat, lng: southWest.lng}; 607 if(northEast instanceof WPGMZA.LatLng) 608 northEast = {lat: northEast.lat, lng: northEast.lng}; 609 else if(southWest instanceof WPGMZA.LatLngBounds) 610 { 611 var bounds = southWest; 612 613 southWest = { 614 lat: bounds.south, 615 lng: bounds.west 616 }; 617 618 northEast = { 619 lat: bounds.north, 620 lng: bounds.east 621 }; 622 } 623 624 var view = this.olMap.getView(); 625 626 var extent = ol.extent.boundingExtent([ 627 ol.proj.fromLonLat([ 628 parseFloat(southWest.lng), 629 parseFloat(southWest.lat) 630 ]), 631 ol.proj.fromLonLat([ 632 parseFloat(northEast.lng), 633 parseFloat(northEast.lat) 634 ]) 635 ]); 636 view.fit(extent, { size : this.olMap.getSize(), padding : [60, 60, 60, 60] }); 637 } 638 639 WPGMZA.OLMap.prototype.panTo = function(latLng, zoom) 640 { 641 var view = this.olMap.getView(); 642 var options = { 643 center: ol.proj.fromLonLat([ 644 parseFloat(latLng.lng), 645 parseFloat(latLng.lat), 646 ]), 647 duration: 500 648 }; 649 650 if(arguments.length > 1) 651 options.zoom = parseInt(zoom); 652 653 view.animate(options); 654 } 655 656 WPGMZA.OLMap.prototype.getZoom = function() 657 { 658 return Math.round( this.olMap.getView().getZoom() ); 659 } 660 661 WPGMZA.OLMap.prototype.setZoom = function(value) 662 { 663 this.olMap.getView().setZoom(value); 664 } 665
666 WPGMZA.OLMap.prototype.getMinZoom = function() 667 { 668 return this.olMap.getView().getMinZoom(); 669 } 670 671 WPGMZA.OLMap.prototype.setMinZoom = function(value) 672 { 673 this.olMap.getView().setMinZoom(value); 674 } 675 676 WPGMZA.OLMap.prototype.getMaxZoom = function() 677 { 678 return this.olMap.getView().getMaxZoom(); 679 } 680 681 WPGMZA.OLMap.prototype.setMaxZoom = function(value) 682 { 683 this.olMap.getView().setMaxZoom(value); 684 } 685 686 WPGMZA.OLMap.prototype.setMapType = function(type){ 687 if(this.mapType !== type){ 688 this.mapType = type; 689 690 if(this.tileLayers){ 691 for(let layer of this.tileLayers){ 692 this.olMap.removeLayer(layer); 693 } 694 } 695 696 this.tileLayers = this.getTileLayers(); 697 const reversedLayers = this.tileLayers.slice().reverse(); 698 for(let layer of reversedLayers){ 699 this.olMap.getLayers().insertAt(0, layer); 700 } 701 702 $(this.element).find('.ol-layer-button[data-map-type]').removeClass('selected'); 703 $(this.element).find('.ol-layer-button[data-map-type="' + type + '"]').addClass('selected'); 704 } 705 } 706 707 WPGMZA.OLMap.prototype.getMapType = function(){ 708 return this.mapType ? this.mapType : 'roadmap'; 709 } 710 711 WPGMZA.OLMap.prototype.setOptions = function(options) 712 { 713 Parent.prototype.setOptions.call(this, options); 714 715 if(!this.olMap) 716 return; 717 718 this.olMap.getView().setProperties( this.settings.toOLViewOptions() ); 719 } 720 721 /** 722 * TODO: Consider moving all these functions to their respective classes, same on google map (DO IT!!! It's very misleading having them here) 723 */ 724 WPGMZA.OLMap.prototype.addMarker = function(marker) 725 { 726 if(WPGMZA.OLMarker.renderMode == WPGMZA.OLMarker.RENDER_MODE_HTML_ELEMENT){ 727 this.olMap.addOverlay(marker.overlay); 728 } else { 729 if(!marker.featureInSource){ 730 this.markerLayer.getSource().addFeature(marker.feature); 731 marker.featureInSource = true; 732 } 733 } 734 735 Parent.prototype.addMarker.call(this, marker); 736 } 737 738 WPGMZA.OLMap.prototype.removeMarker = function(marker) 739 { 740 if(WPGMZA.OLMarker.renderMode == WPGMZA.OLMarker.RENDER_MODE_HTML_ELEMENT) 741 this.olMap.removeOverlay(marker.overlay); 742 else 743 { 744 this.markerLayer.getSource().removeFeature(marker.feature); 745 marker.featureInSource = false; 746 } 747 748 Parent.prototype.removeMarker.call(this, marker); 749 } 750 751 WPGMZA.OLMap.prototype.addPolygon = function(polygon) 752 { 753 this.olMap.addLayer(polygon.layer); 754 755 Parent.prototype.addPolygon.call(this, polygon); 756 } 757 758 WPGMZA.OLMap.prototype.removePolygon = function(polygon) 759 { 760 this.olMap.removeLayer(polygon.layer); 761 762 Parent.prototype.removePolygon.call(this, polygon); 763 } 764 765 WPGMZA.OLMap.prototype.addPolyline = function(polyline) 766 { 767 this.olMap.addLayer(polyline.layer); 768 769 Parent.prototype.addPolyline.call(this, polyline); 770 } 771 772 WPGMZA.OLMap.prototype.removePolyline = function(polyline) 773 { 774 this.olMap.removeLayer(polyline.layer); 775 776 Parent.prototype.removePolyline.call(this, polyline); 777 } 778 779 WPGMZA.OLMap.prototype.addCircle = function(circle) 780 { 781 this.olMap.addLayer(circle.layer); 782 783 Parent.prototype.addCircle.call(this, circle); 784 } 785 786 WPGMZA.OLMap.prototype.removeCircle = function(circle) 787 { 788 this.olMap.removeLayer(circle.layer); 789 790 Parent.prototype.removeCircle.call(this, circle); 791 } 792 793 WPGMZA.OLMap.prototype.addRectangle = function(rectangle) 794 { 795 this.olMap.addLayer(rectangle.layer); 796 797 Parent.prototype.addRectangle.call(this, rectangle); 798 } 799 800 WPGMZA.OLMap.prototype.removeRectangle = function(rectangle) 801 { 802 this.olMap.removeLayer(rectangle.layer); 803 804 Parent.prototype.removeRectangle.call(this, rectangle); 805 } 806 807 WPGMZA.OLMap.prototype.pixelsToLatLng = function(x, y) 808 { 809 if(y == undefined) 810 { 811 if("x" in x && "y" in x) 812 { 813 y = x.y; 814 x = x.x; 815 } 816 else 817 console.warn("Y coordinate undefined in pixelsToLatLng (did you mean to pass 2 arguments?)"); 818 } 819 820 var coord = this.olMap.getCoordinateFromPixel([x, y]); 821 822 if(!coord) 823 return { 824 x: null, 825 y: null 826 }; 827 828 var lonLat = ol.proj.toLonLat(coord); 829 return { 830 lat: lonLat[1], 831 lng: lonLat[0] 832 }; 833 } 834 835 WPGMZA.OLMap.prototype.latLngToPixels = function(latLng) 836 { 837 var coord = ol.proj.fromLonLat([latLng.lng, latLng.lat]);
838 var pixel = this.olMap.getPixelFromCoordinate(coord); 839 840 if(!pixel) 841 return { 842 x: null, 843 y: null 844 }; 845 846 return { 847 x: pixel[0], 848 y: pixel[1] 849 }; 850 } 851 852 WPGMZA.OLMap.prototype.enableBicycleLayer = function(value) 853 { 854 if(value) 855 { 856 if(!this.bicycleLayer) 857 this.bicycleLayer = new ol.layer.Tile({ 858 source: new ol.source.OSM({ 859 url: "http://{a-c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png" 860 }) 861 }); 862 863 this.olMap.addLayer(this.bicycleLayer); 864 } 865 else 866 { 867 if(!this.bicycleLayer) 868 return; 869 870 this.olMap.removeLayer(this.bicycleLayer); 871 } 872 } 873 874 WPGMZA.OLMap.prototype.showGestureOverlay = function() 875 { 876 var self = this; 877 878 clearTimeout(this.gestureOverlayTimeoutID); 879 880 $(this.gestureOverlay).stop().animate({opacity: "100"}); 881 $(this.element).append(this.gestureOverlay); 882 883 $(this.gestureOverlay).css({ 884 "line-height": $(this.element).height() + "px", 885 "opacity": "1.0" 886 }); 887 $(this.gestureOverlay).show(); 888 889 this.gestureOverlayTimeoutID = setTimeout(function() { 890 self.gestureOverlay.fadeOut(2000); 891 }, 2000); 892 } 893 894 WPGMZA.OLMap.prototype.onElementResized = function(event) 895 { 896 this.olMap.updateSize(); 897 } 898 899 WPGMZA.OLMap.prototype.resetBounds = function() { 900 var latlng = new WPGMZA.LatLng(this.settings.map_start_lat, this.settings.map_start_lng); 901 this.panTo(latlng, this.settings.map_start_zoom); 902 } 903 904 WPGMZA.OLMap.prototype.onRightClick = function(event) 905 { 906 if($(event.target).closest(".ol-marker, .wpgmza_modern_infowindow, .wpgmza-modern-store-locator").length) 907 return true; 908 909 var parentOffset = $(this.element).offset(); 910 var relX = event.pageX - parentOffset.left; 911 var relY = event.pageY - parentOffset.top; 912 var latLng = this.pixelsToLatLng(relX, relY); 913 914 this.trigger({type: "rightclick", latLng: latLng}); 915 916 // Legacy event compatibility 917 $(this.element).trigger({type: "rightclick", latLng: latLng}); 918 919 // Prevent menu 920 event.preventDefault(); 921 return false; 922 } 923 924 WPGMZA.OLMap.prototype.enableAllInteractions = function() 925 { 926 927 this.olMap.getInteractions().forEach(function(interaction) { 928 929 if(interaction instanceof ol.interaction.DragPan || interaction instanceof ol.interaction.DoubleClickZoom || interaction instanceof ol.interaction.MouseWheelZoom) 930 { 931 interaction.setActive(true); 932 } 933 934 }, this); 935 936 } 937 938 WPGMZA.OLMap.prototype.addMapTypeControl = function(config, hasFullscreen){ 939 if(this.olMap && config && config.layers && config.layers.length >= 2){ 940 const container = document.createElement('div'); 941 container.classList.add('ol-control'); 942 container.classList.add('ol-unselectable'); 943 container.classList.add('ol-control-layers'); 944 945 if(hasFullscreen){ 946 container.classList.add('ol-has-fullscreen'); 947 } 948 949 // .ol-full-screen { 950 // right: .5em; 951 // top: .5em; 952 // } 953 954 for(let index in config.layers){ 955 const layer = config.layers[index]; 956 let label = WPGMZA.localized_strings[`map_type_${layer}`] ? WPGMZA.localized_strings[`map_type_${layer}`] : WPGMZA.capitalizeWords(layer); 957 958 const button = document.createElement('button'); 959 button.innerText = label; 960 button.classList.add('ol-layer-button'); 961 button.classList.add('ol-layer-button'); 962 button.setAttribute('type', 'button'); 963 button.setAttribute('data-map-type', layer); 964 965 if(config.active && config.active === layer){ 966 button.classList.add('selected'); 967 } 968 969 container.append(button); 970 971 button.addEventListener('click', (event) => { 972 event.preventDefault(); 973 974 this.setMapType(layer); 975 }); 976 } 977 978 const layerController = new ol.control.Control({ 979 element : container, 980 }); 981 982 this.olMap.addControl(layerController); 983 } 984 } 985 986 /** 987 * Enables / disables the scale control bar 988 * @param enable boolean, enable or not 989 * @return void 990 */ 991 WPGMZA.OLMap.prototype.enableScaleControl = function(enable) 992 { 993 if(!this.olMap) 994 return; 995 996 if(this.scaleControl){ 997 this.olMap.removeControl(this.scaleControl); 998 this.scaleControl = null; 999 } 1000 1001 if(enable){ 1002 const units = (this.settings.store_locator_distance == WPGMZA.Distance.MILES) 1003 ? 'imperial' 1004 : 'metric'; 1005 1006 this.scaleControl = new ol.control.ScaleLine({ units: units }); 1007 this.olMap.addControl(this.scaleControl); 1008 } 1009 } 1010 1011 WPGMZA.OLMap.prototype.isLegacy = function(){ 1012 if(WPGMZA.settings && WPGMZA.settings.engine === 'open-layers'){ 1013 return true; // Using Legacy V6 OpenLayers 1014 } 1015 return false; 1016 } 1017 1018});
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.