1window.addEventListener('load', function(e) { 2 3 // Restore the extended L object (OUMLeaflet.L) to the global scope (prevents conflicts with other Leaflet instances) 4 window.L = window.OUMLeaflet.L; 5 6 // VARIABLES 7 const { __ } = wp.i18n; 8 9 // FUNCTIONS 10 11 function getParameterByName(name) { 12 name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); 13 const regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), 14 results = regex.exec(location.search); 15 return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 16 } 17 18 function latLngToBounds(lat, lng, zoom, width, height){ 19 const EARTH_CIR_METERS = 40075016.686; 20 const degreesPerMeter = 360 / EARTH_CIR_METERS; 21 const metersPerPixelEW = EARTH_CIR_METERS / Math.pow(2, zoom + 8); 22 const metersPerPixelNS = EARTH_CIR_METERS / Math.pow(2, zoom + 8) * Math.cos(lat * Math.PI / 180); 23 24 const shiftMetersEW = width/2 * metersPerPixelEW; 25 const shiftMetersNS = height/2 * metersPerPixelNS; 26 27 const shiftDegreesEW = shiftMetersEW * degreesPerMeter; 28 const shiftDegreesNS = shiftMetersNS * degreesPerMeter; 29 30 // [[south, west], [north, east]] 31 return [[lat-shiftDegreesNS, lng-shiftDegreesEW], [lat+shiftDegreesNS, lng+shiftDegreesEW]]; 32 } 33 34 function customAutoSuggestText(text,val) { 35 return '<div><img src="' + val.layer.options.icon.options.iconUrl + '" />' + val.layer.options.title + '</div>'; 36 } 37 38 function updatePreview() { 39 this.nextElementSibling.classList.add('active'); 40 this.nextElementSibling.querySelector('span').textContent = this.files[0].name; 41 } 42 43 function editLocation(post_id) { 44 // Trigger the Add Location button to open the form 45 document.getElementById('open-add-location-overlay').click(); 46 47 document.getElementById('add-location-overlay').classList.add('edit-location'); 48 49 // Wait for the form to be visible (use a small timeout if necessary) 50 setTimeout(function() { 51 // Retrieve the location data (this assumes the data is available in JavaScript, possibly as a global variable or via an AJAX call) 52 let locationData = oum_all_locations.find(location => location.post_id == post_id); 53 54 if (locationData) { 55 // Prefill the form fields with the location data 56 const titleField = document.querySelector('input[name="oum_location_title"]'); 57 if (titleField) titleField.value = locationData.title; 58 59 const textField = document.querySelector('textarea[name="oum_location_text"]'); 60 if (textField) textField.value = locationData.text; 61 62 const addressField = document.querySelector('input[name="oum_location_address"]'); 63 if (addressField) addressField.value = locationData.address; 64 65 const latField = document.querySelector('input[name="oum_location_lat"]'); 66 if (latField) latField.value = locationData.lat; 67 68 const lngField = document.querySelector('input[name="oum_location_lng"]'); 69 if (lngField) lngField.value = locationData.lng; 70 71 // Add the location marker to the map 72 const coords = L.latLng(locationData.lat, locationData.lng); 73 oumMap2.fire('click', { 74 latlng: coords 75 }); 76 77 // Set the map view to the location 78 oumMap2.setView(coords, oumMap2.getZoom()); 79 80 // Marker categories 81 if (locationData.types) { 82 locationData.types.forEach(type => { 83 const selectBox = document.querySelector(`select[name="oum_marker_icon[]"]`); 84 if (selectBox) { 85 selectBox.value = type; 86 } else { 87 const checkbox = document.querySelector(`input[name="oum_marker_icon[]"][value="${type}"]`); 88 if (checkbox) { 89 checkbox.checked = true; 90 } 91 } 92 }); 93 } 94 95 // Custom fields 96 if (locationData.custom_fields) { 97 locationData.custom_fields.forEach(custom_field => { 98 if(custom_field.val.length > 0) { 99 if(custom_field.fieldtype == 'checkbox') { 100 if(Array.isArray(custom_field.val)) { 101 custom_field.val.forEach(val => { 102 const checkbox = document.querySelector(`input[name="oum_location_custom_fields[${custom_field.index}][]"][value="${val}"]`); 103 if (checkbox) checkbox.checked = true; 104 }); 105 } 106 } else if(custom_field.fieldtype == 'radio') { 107 const radio = document.querySelector(`input[name="oum_location_custom_fields[${custom_field.index}]"][value="${custom_field.val}"]`); 108 if (radio) radio.checked = true; 109 } else if(custom_field.fieldtype == 'select') { 110 const select = document.querySelector(`select[name="oum_location_custom_fields[${custom_field.index}]"]`); 111 if (select) select.value = custom_field.val; 112 } else { 113 const input = document.querySelector(`input[name="oum_location_custom_fields[${custom_field.index}]"]`); 114 if (input) input.value = custom_field.val; 115 } 116 } 117 }); 118 } 119 120 // Image 121 if (locationData.image) { 122 const imageField = document.querySelector('input[name="oum_location_image"]'); 123 if (imageField) { 124 // Remove the required attribute (in case it was set) 125 imageField.required = false;
126 127 // Update the image preview 128 const label = imageField.nextElementSibling; 129 if (label) { 130 label.classList.add('active'); 131 label.querySelector('span').textContent = locationData.image.split('/').pop(); 132 } 133 } 134 135 const oum_remove_existing_image = document.getElementById('oum_remove_existing_image'); 136 if (oum_remove_existing_image) oum_remove_existing_image.value = '0'; 137 } 138 139 // Audio 140 if (locationData.audio) { 141 const audioField = document.querySelector('input[name="oum_location_audio"]'); 142 if (audioField) { 143 // Remove the required attribute (in case it was set) 144 audioField.required = false; 145 146 // Update the audio preview 147 const label = audioField.nextElementSibling; 148 if (label) { 149 label.classList.add('active'); 150 label.querySelector('span').textContent = locationData.audio.split('/').pop(); 151 } 152 } 153 154 const oum_remove_existing_audio = document.getElementById('oum_remove_existing_audio'); 155 if (oum_remove_existing_audio) oum_remove_existing_audio.value = '0'; 156 } 157 158 // Video 159 const videoField = document.querySelector('input[name="oum_location_video"]'); 160 if (videoField) videoField.value = decodeURIComponent(locationData.video.replace(/&/g, '&')); 161 162 // Set the form action or hidden input to indicate this is an edit and not a new submission 163 const postIdField = document.querySelector('input[name="oum_post_id"]'); 164 if (postIdField) postIdField.value = locationData.post_id; 165 } 166 }, 500); // Adjust timeout as needed 167 } 168 169 // Dynamic Filtering Function with Text and Category Filters 170 function filterMarkers() { 171 // Check if the text search input exists and get its value 172 const markerFilterInput = document.getElementById('oum_filter_markers'); 173 const filter = markerFilterInput ? markerFilterInput.value.toLowerCase() : ''; 174 175 // Check if category filters exist and get selected categories 176 const categoryInputs = document.querySelectorAll('.open-user-map .oum-filter-controls [name="type"]'); 177 const checkedCategories = categoryInputs.length > 0 178 ? Array.from(categoryInputs).filter(input => input.checked).map(input => input.value) 179 : []; 180 181 // Clear existing markers from the map 182 oumMarkersLayer.clearLayers(); 183 184 // Filter and re-add markers based on both text filter and selected categories 185 oumAllMarkers.forEach(marker => { 186 const contentText = marker.options.content.toLowerCase(); 187 const markerTypes = marker.options.types || []; 188 189 // Check if marker matches the text filter 190 const matchesTextFilter = !filter || contentText.includes(filter); 191 192 // Check if marker should be shown based on selected categories 193 const matchesCategoryFilter = markerTypes.length === 0 // Always show markers without categories 194 || (checkedCategories.length === 0 && markerTypes.length === 0) // Show uncategorized markers when no categories are selected 195 || markerTypes.some(type => checkedCategories.includes(type)); // Show markers matching any selected category 196 197 // Only add marker if it matches both filters 198 if (matchesTextFilter && matchesCategoryFilter) { 199 oumMarkersLayer.addLayer(marker); // Add the marker back to the map if it matches both filters 200 } 201 }); 202 } 203 204 // Create leaflet markers based on "oum_all_locations" json 205 function addMarkers() { 206 oum_all_locations.forEach(location => { 207 const contentText = (location.title + ' | ' + location.content.replace(/(<([^>]+)>)/gi, " ").replace(/\s\s+/g, " ")).toLowerCase(); 208 209 let marker = L.marker([location.lat, location.lng], { 210 title: location.title, 211 post_id: location.post_id, 212 content: contentText, 213 icon: L.icon({ 214 iconUrl: location.icon, 215 iconSize: [26, 41], 216 iconAnchor: [13, 41], 217 popupAnchor: [0, -25], 218 shadowUrl: marker_shadow_url, 219 shadowSize: [41, 41], 220 shadowAnchor: [13, 41] 221 }), 222 types: location.types || [] 223 }); 224 let popup = L.responsivePopup().setContent(location.content); 225 marker.bindPopup(popup); 226 oumAllMarkers.push(marker); // Add to the array for future filtering 227 }); 228 } 229 230 231 // Use this to initialize markers and add them to the map initially 232 function initializeMarkers() { 233 addMarkers(); // Fill the oumAllMarkers array
234 oumAllMarkers.forEach(marker => { 235 oumMarkersLayer.addLayer(marker); // Add all markers to the markers LayerGroup or ClusterGroup 236 }); 237 } 238 239 240 // VARIABLES 241 242 const POPUP_MARKER_ID = getParameterByName('markerid'); 243 const REGION_ID = getParameterByName('region'); 244 const enableFullscreen = oum_enable_fullscreen ? true : false; 245 const enableGestureHandlingMap = oum_enable_scrollwheel_zoom_map ? false : true; 246 247 // Handle "Add Location" popup DOM placement on fullscreen mode 248 const addLocationPopup = document.querySelector('#add-location-overlay'); 249 const originalContainer = addLocationPopup.parentElement; 250 const fullscreenContainer = document.querySelector('.open-user-map .map-wrap'); 251 252 // Handle Location Bubble on small screens (show in fullscreen) 253 const locationFullscreenContainer = document.querySelector('.open-user-map #location-fullscreen-container'); 254 255 // Handle "Locate My Position" service (should not run in parallel) 256 var map_locate_process = false; 257 var map2_locate_process = false; 258 259 // SETUP MAIN MAP 260 261 // Init Map 262 const map = L.map(map_el, { 263 gestureHandling: enableGestureHandlingMap, 264 zoomSnap: 0.5, 265 zoomDelta: 0.5, 266 attributionControl: true, 267 fullscreenControl: enableFullscreen, 268 fullscreenControlOptions: { 269 position: 'topleft', 270 fullscreenElement: fullscreenContainer, 271 } 272 }); 273 274 map.attributionControl.setPrefix(false); 275 276 // prevent moving/zoom outside main world bounds 277 let world_bounds = L.latLngBounds(L.latLng(-60, -190), L.latLng(80, 190)); 278 let world_min_zoom = (map.getBoundsZoom(world_bounds) > 0) ? map.getBoundsZoom(world_bounds) : 1; 279 map.setMaxBounds(world_bounds); 280 map.setMinZoom(Math.ceil(world_min_zoom)); 281 map.on('drag', function() { 282 map.panInsideBounds(world_bounds, { animate: false }); 283 }); 284 285 // make map reloadable (oumMap.invalidateSize()) after some preloader is ready 286 oumMap = map; 287 288 // Get Initial Map Bounds & Zoom 289 let start_bounds = latLngToBounds(parseFloat(start_lat), parseFloat(start_lng), parseFloat(start_zoom), 570, 372); 290 let start_bounds_zoom = map.getBoundsZoom(start_bounds); 291 292 oum_minimum_zoom_level = oum_minimum_zoom_level ? oum_minimum_zoom_level : 1; 293 294 if(oum_use_settings_start_location && !oum_has_regions) { 295 296 // START POSITION FROM SETTINGS AND REGIONS ARE DISABLED 297 298 // Make sure "Minimum zoom level" is lower than start zoom 299 if(oum_minimum_zoom_level > parseFloat(start_zoom)) { 300 oum_minimum_zoom_level = Math.floor(start_bounds_zoom); 301 } 302 303 // Set min zoom 304 map.setMinZoom(oum_minimum_zoom_level); 305 306 }else{ 307 308 // CUSTOM START POSITION 309 310 // Disable "Fixed Map Bounds" from Settings 311 oum_enable_fixed_map_bounds = false; 312 } 313 314 // Render Map 315 map.setView([start_lat, start_lng], start_bounds_zoom); 316 317 // Bound map to fixed position 318 if(oum_enable_fixed_map_bounds) { 319 map.setMaxBounds(map.getBounds().pad(0.1)); 320 } 321 322 // Create Bounds Object needed for Marker Search 323 let start_bounds_object = map.getBounds(); 324 325 // Set map style 326 if (mapStyle == 'Custom1') { 327 328 L.tileLayer('https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png').addTo(map); 329 L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png', { 330 tileSize: 512, 331 zoomOffset: -1 332 }).addTo(map); 333 334 } else if (mapStyle == 'Custom2') { 335 336 L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png').addTo(map); 337 L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png', { 338 tileSize: 512, 339 zoomOffset: -1 340 }).addTo(map); 341 342 } else if (mapStyle == 'Custom3') { 343 344 L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png').addTo(map); 345 L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png', { 346 tileSize: 512, 347 zoomOffset: -1 348 }).addTo(map); 349 350 } else if (mapStyle == 'MapBox.streets') { 351 352 L.tileLayer.provider('MapBox', { 353 id: 'mapbox/streets-v12',
354 accessToken: oum_tile_provider_mapbox_key 355 }).addTo(map); 356 357 } else if (mapStyle == 'MapBox.outdoors') { 358 359 L.tileLayer.provider('MapBox', { 360 id: 'mapbox/outdoors-v12', 361 accessToken: oum_tile_provider_mapbox_key 362 }).addTo(map); 363 364 } else if (mapStyle == 'MapBox.light') { 365 366 L.tileLayer.provider('MapBox', { 367 id: 'mapbox/light-v11', 368 accessToken: oum_tile_provider_mapbox_key 369 }).addTo(map); 370 371 } else if (mapStyle == 'MapBox.dark') { 372 373 L.tileLayer.provider('MapBox', { 374 id: 'mapbox/dark-v11', 375 accessToken: oum_tile_provider_mapbox_key 376 }).addTo(map); 377 378 } else if (mapStyle == 'MapBox.satellite') { 379 380 L.tileLayer.provider('MapBox', { 381 id: 'mapbox/satellite-v9', 382 accessToken: oum_tile_provider_mapbox_key 383 }).addTo(map); 384 385 } else if (mapStyle == 'MapBox.satellite-streets') { 386 387 L.tileLayer.provider('MapBox', { 388 id: 'mapbox/satellite-streets-v12', 389 accessToken: oum_tile_provider_mapbox_key 390 }).addTo(map); 391 392 } else { 393 // Default 394 L.tileLayer.provider(mapStyle).addTo(map); 395 } 396 397 398 // ADD LOCATIONS 399 400 let oumAllMarkers = []; // holds all markers 401 let oumMarkersLayer; // Marker parent layer 402 403 if (!oum_enable_cluster) { 404 // clustering disabled 405 oumMarkersLayer = L.layerGroup({ 406 chunkedLoading: true 407 }); 408 } else { 409 // clustering enabled 410 oumMarkersLayer = L.markerClusterGroup({ 411 showCoverageOnHover: false, 412 removeOutsideVisibleBounds: false, 413 maxClusterRadius: 40, 414 chunkedLoading: true 415 }); 416 } 417 418 // Add markers layer to map 419 oumMarkersLayer.addTo(map); 420 421 // Call this function initially to set up markers 422 initializeMarkers(); 423 424 425 426 427 // ADD MAP CONTROLS 428 429 // Control: search markers 430 if (oum_enable_searchmarkers_button && (!oum_enable_searchbar || oum_searchbar_type !== 'markers')) { 431 L.control.search({ 432 textPlaceholder: oum_searchmarkers_label, 433 layer: oumMarkersLayer, 434 propertyName: 'content', 435 initial: false, 436 buildTip: customAutoSuggestText, 437 firstTipSubmit: true, 438 autoCollapse: true, // resets search field 439 zoom: oum_searchmarkers_zoom, 440 }).addTo(map); 441 } 442 443 // Searchbar: search markers 444 if (oum_enable_searchbar && oum_searchbar_type == 'markers') { 445 L.control.search({ 446 container: 'oum_search_marker', 447 collapsed: false, 448 textPlaceholder: oum_searchmarkers_label, 449 layer: oumMarkersLayer, 450 propertyName: 'content', 451 initial: false, 452 buildTip: customAutoSuggestText, 453 firstTipSubmit: true, 454 autoCollapse: true, // resets search field 455 zoom: oum_searchmarkers_zoom, 456 }).addTo(map); 457 } 458 459 // Geosearch Provider 460 switch (oum_geosearch_provider) { 461 case 'osm': 462 oum_geosearch_selected_provider = new GeoSearch.OpenStreetMapProvider(); 463 break; 464 case 'geoapify': 465 oum_geosearch_selected_provider = new GeoSearch.GeoapifyProvider({ 466 params: { 467 apiKey: oum_geosearch_provider_geoapify_key 468 } 469 }); 470 break; 471 case 'here': 472 oum_geosearch_selected_provider = new GeoSearch.HereProvider({ 473 params: { 474 apiKey: oum_geosearch_provider_here_key 475 } 476 }); 477 break; 478 case 'mapbox': 479 oum_geosearch_selected_provider = new GeoSearch.MapBoxProvider({ 480 params: { 481 access_token: oum_geosearch_provider_mapbox_key 482 } 483 }); 484 break; 485 default: 486 oum_geosearch_selected_provider = new GeoSearch.OpenStreetMapProvider(); 487 break; 488 } 489 490 // Control: search address 491 if (oum_enable_searchaddress_button && (!oum_enable_searchbar || oum_searchbar_type !== 'address')) { 492 const searchControl = new GeoSearch.GeoSearchControl({ 493 style: 'button', //bar, button 494 showMarker: false, 495 provider: oum_geosearch_selected_provider, 496 notFoundMessage: 'Sorry, that address could not be found.', 497 searchLabel: oum_searchaddress_label, 498 updateMap: false, 499 autoComplete: true 500 }); 501 map.addControl(searchControl); 502 } 503 504 // Searchbar: search address 505 if (oum_enable_searchbar && oum_searchbar_type == 'address') { 506 const searchControl = new GeoSearch.GeoSearchControl({ 507 style: 'bar', //bar, button 508 showMarker: false, 509 provider: oum_geosearch_selected_provider, 510 searchLabel: oum_searchaddress_label, 511 updateMap: false, 512 }); 513 map.addControl(searchControl); 514 } 515 516 // Control: get current location 517 if (oum_enable_currentlocation) { 518 map_locate_process = L.control.locate({ 519 flyTo: true, 520 showPopup: false 521 }).addTo(map); 522 } 523 524 525 // EVENTS 526 527 // Event: Enter Fullscreen 528 map.on('enterFullscreen', function () { 529 fullscreenContainer.appendChild(addLocationPopup); 530 }); 531 532 // Event: Exit Fullscreen 533 map.on('exitFullscreen', function () { 534 originalContainer.appendChild(addLocationPopup); 535 }); 536 537 // Event: Open Location Bubble 538 map.on('popupopen', function(locationBubble){ 539 var el = locationFullscreenContainer; 540 el.querySelector('.location-content-wrap').innerHTML = locationBubble.popup.getContent(); 541 locationFullscreenContainer.classList.add('visible'); 542 document.querySelector('body').classList.add('oum-location-opened'); 543 }); 544 545 // Event: Close Location Bubble 546 map.on('popupclose', function(locationBubble){ 547 var el = locationFullscreenContainer; 548 el.classList.remove('visible'); 549 document.querySelector('body').classList.remove('oum-location-opened');
550 //map.setView(locationBubble.popup.getLatLng()); 551 }); 552 553 // Event: pan or zoom Map 554 map.on('moveend', function(ev) { 555 start_lat = map.getCenter().lat; 556 start_lng = map.getCenter().lng; 557 start_zoom = map.getZoom(); 558 }); 559 560 // Event: click on geosearch result 561 map.on('geosearch/showlocation', function(e) { 562 let coords = e.marker._latlng; 563 let isInBounds = start_bounds_object.contains(coords); 564 const searchBar = document.querySelector(`#${map_el} .leaflet-geosearch-bar form, #${map_el} .leaflet-geosearch-button form`); 565 566 if(!isInBounds && oum_enable_fixed_map_bounds) { 567 console.log('This search result is out of reach.'); 568 searchBar.style.boxShadow = "0 0 10px rgb(255, 111, 105)"; 569 setTimeout(function() { 570 searchBar.style.boxShadow = "0 1px 5px rgba(255, 255, 255, 0.65)"; 571 }, 2000); 572 }else{ 573 if(e.location.bounds !== null) { 574 // Bounds exist for this search result 575 map.flyToBounds(e.location.bounds); 576 }else{ 577 if(e.location.raw.mapView) { 578 // Here 579 map.flyToBounds([ 580 [e.location.raw.mapView.south,e.location.raw.mapView.west], 581 [e.location.raw.mapView.north,e.location.raw.mapView.east] 582 ]); 583 }else{ 584 // No Bounds available for this search result 585 map.flyTo([e.location.y, e.location.x], 17); 586 } 587 } 588 } 589 }); 590 591 // Event: automatically open popup on ?markerid=123 592 oumMarkersLayer.eachLayer(function(layer) { 593 594 if(layer.options.post_id && layer.options.post_id === POPUP_MARKER_ID){ 595
596 map.setView(layer.getLatLng(), oum_searchmarkers_zoom); 597 layer.openPopup(); 598 599 } 600 }); 601 602 // Event: Change Region 603 document.querySelectorAll('.open-user-map .change_region').forEach(function(btn) { 604 btn.onclick = function(event) { 605 let el = event.currentTarget; 606 let region_lat = el.getAttribute('data-lat'); 607 let region_lng = el.getAttribute('data-lng'); 608 let region_zoom = el.getAttribute('data-zoom'); 609 610 let region_bounds = latLngToBounds(parseFloat(region_lat), parseFloat(region_lng), parseFloat(region_zoom), 570, 372); 611 let region_bounds_zoom = map.getBoundsZoom(region_bounds); 612 613 // Center Map 614 map.flyTo([region_lat, region_lng], region_bounds_zoom); 615 616 document.querySelectorAll('.open-user-map .change_region').forEach(function(el) { 617 el.classList.remove('active'); 618 }); 619 el.classList.add('active'); 620 }; 621 622 // Event: Change Region on ?region=Europe 623 if(btn.textContent == REGION_ID) { 624 btn.click(); 625 } 626 }); 627 628 // Event: Filter markers on text input change (only if it exists) 629 const markerFilterInput = document.getElementById('oum_filter_markers'); 630 if (markerFilterInput) { 631 markerFilterInput.addEventListener('input', filterMarkers); 632 } 633 634 // Event: Filter markers on category change (only if categories exist) 635 const categoryInputs = document.querySelectorAll('.open-user-map .oum-filter-controls [name="type"]'); 636 if (categoryInputs.length > 0) { 637 categoryInputs.forEach(input => { 638 input.addEventListener('change', filterMarkers); 639 }); 640 } 641 642 // Event: Toggle Filter List 643 (function() { 644 // Cache the filter controls element 645 let filterControls = document.querySelector('.open-user-map .oum-filter-controls'); 646 647 if (!filterControls) return; // Exit if element is not found 648 649 // Function to show the filter list 650 function showFilterList() { 651 filterControls.classList.add('active'); 652 } 653 654 // Function to hide the filter list 655 function hideFilterList() { 656 filterControls.classList.remove('active'); 657 } 658 659 // Event: Open Filter List (mouseover for collapsed design) 660 if (filterControls.classList.contains('use-collapse')) { 661 filterControls.querySelector('.oum-filter-toggle').addEventListener('mouseover', showFilterList); 662 663 // Close on mouseleave 664 filterControls.querySelector('.oum-filter-list').addEventListener('mouseleave', hideFilterList); 665 } 666 667 // Event: Open Filter List (click) 668 filterControls.querySelector('.oum-filter-toggle').addEventListener('click', showFilterList); 669 670 // Event: Close Filter List (click on close button) 671 filterControls.querySelector('.oum-filter-list .close-filter-list').addEventListener('click', hideFilterList); 672 })(); 673 674 675 // ADD LOCATION 676 677 if (document.getElementById('open-add-location-overlay') != null) { 678 //init form map 679 const map2 = L.map('mapGetLocation', { 680 attributionControl: false, 681 gestureHandling: true, 682 zoomSnap: 1, 683 zoomDelta: 1, 684 fullscreenControl: enableFullscreen, 685 fullscreenControlOptions: { 686 position: 'topleft' 687 } 688 }); 689 690 // Activate Map inside overlay 691 (function() { 692 693 let markerIsVisible = false; 694 695 // Set map style 696 if (mapStyle == 'Custom1') { 697 698 L.tileLayer('https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png').addTo(map2); 699 L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png', { 700 tileSize: 512, 701 zoomOffset: -1 702 }).addTo(map2); 703 704 } else if (mapStyle == 'Custom2') { 705 706 L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png').addTo(map2); 707 L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png', { 708 tileSize: 512, 709 zoomOffset: -1 710 }).addTo(map2); 711 712 } else if (mapStyle == 'Custom3') { 713 714 L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png').addTo(map2); 715 L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}{r}.png', { 716 tileSize: 512, 717 zoomOffset: -1 718 }).addTo(map2); 719 720 } else if (mapStyle == 'MapBox.streets') { 721 722 L.tileLayer.provider('MapBox', { 723 id: 'mapbox/streets-v12',
724 accessToken: oum_tile_provider_mapbox_key 725 }).addTo(map2); 726 727 } else if (mapStyle == 'MapBox.outdoors') { 728 729 L.tileLayer.provider('MapBox', { 730 id: 'mapbox/outdoors-v12', 731 accessToken: oum_tile_provider_mapbox_key 732 }).addTo(map2); 733 734 } else if (mapStyle == 'MapBox.light') { 735 736 L.tileLayer.provider('MapBox', { 737 id: 'mapbox/light-v11', 738 accessToken: oum_tile_provider_mapbox_key 739 }).addTo(map2); 740 741 } else if (mapStyle == 'MapBox.dark') { 742 743 L.tileLayer.provider('MapBox', { 744 id: 'mapbox/dark-v11', 745 accessToken: oum_tile_provider_mapbox_key 746 }).addTo(map2); 747 748 } else if (mapStyle == 'MapBox.satellite') { 749 750 L.tileLayer.provider('MapBox', { 751 id: 'mapbox/satellite-v9', 752 accessToken: oum_tile_provider_mapbox_key 753 }).addTo(map2); 754 755 } else if (mapStyle == 'MapBox.satellite-streets') { 756 757 L.tileLayer.provider('MapBox', { 758 id: 'mapbox/satellite-streets-v12', 759 accessToken: oum_tile_provider_mapbox_key 760 }).addTo(map2); 761 762 } else { 763 // Default 764 L.tileLayer.provider(mapStyle).addTo(map2); 765 } 766 767 // Add searchbar: address 768 const search = new GeoSearch.GeoSearchControl({ 769 style: 'bar', 770 showMarker: false, 771 provider: oum_geosearch_selected_provider, 772 searchLabel: oum_searchaddress_label, 773 updateMap: false, 774 }); 775 map2.addControl(search); 776 777 // Add control: get current location 778 if (oum_enable_currentlocation) { 779 map2_locate_process = L.control.locate({ 780 flyTo: true, 781 showPopup: false 782 }).addTo(map2); 783 } 784 785 //define marker 786 787 // Marker Icon 788 let markerIcon = L.icon({ 789 iconUrl: marker_icon_url, 790 iconSize: [26, 41], 791 iconAnchor: [13, 41], 792 popupAnchor: [0, -25], 793 shadowUrl: marker_shadow_url, 794 shadowSize: [41, 41], 795 shadowAnchor: [13, 41] 796 }); 797 798 let locationMarker = L.marker([0, 0], { 799 icon: markerIcon 800 }, { 801 'draggable': true 802 }); 803 804 // move "Add Location"-Map to current Main map position 805 start_lat = map.getCenter().lat; 806 start_lng = map.getCenter().lng; 807 start_zoom = map.getZoom(); 808 809 let main_map_width = document.querySelector(`#${map_el}`).offsetWidth; 810 let main_map_height = document.querySelector(`#${map_el}`).offsetHeight; 811 let start_bounds = latLngToBounds(parseFloat(start_lat), parseFloat(start_lng), parseFloat(start_zoom), main_map_width, main_map_height); 812 let start_bounds_zoom = map2.getBoundsZoom(start_bounds); 813 814 map2.setView([start_lat, start_lng], start_bounds_zoom); 815 816 // prevent moving/zoom outside main world bounds 817 map2.setMaxBounds(world_bounds); 818 map2.setMinZoom(Math.ceil(world_min_zoom)); 819 map2.on('drag', function() { 820 map2.panInsideBounds(world_bounds, { animate: false }); 821 }); 822 823 // Bound map to fixed position 824 if(oum_enable_fixed_map_bounds) { 825 map2.setMaxBounds(map.getBounds()); 826 } 827 828 //Event: click on map to set marker OR location found 829 map2.on('click locationfound', function(e) { 830 let coords = e.latlng; 831 832 locationMarker.setLatLng(coords); 833 834 if (!markerIsVisible) { 835 locationMarker.addTo(map2); 836 markerIsVisible = true; 837 } 838 839 setLocationLatLng(coords); 840 }); 841 842 //Event: geosearch success 843 map2.on('geosearch/showlocation', function(e) { 844 let coords = e.marker._latlng; 845 let label = e.location.label; 846 let isInBounds = start_bounds_object.contains(coords); 847 const searchBar = document.querySelector(`#mapGetLocation .leaflet-geosearch-bar form`); 848 849 if(!isInBounds && oum_enable_fixed_map_bounds) { 850 console.log('This search result is out of reach.'); 851 searchBar.style.boxShadow = "0 0 10px rgb(255, 111, 105)"; 852 setTimeout(function() { 853 searchBar.style.boxShadow = "0 1px 5px rgba(255, 255, 255, 0.65)"; 854 }, 2000); 855 }else{ 856 if(e.location.bounds !== null) { 857 // Bounds exist for this search result 858 map2.flyToBounds(e.location.bounds); 859 }else{ 860 if(e.location.raw.mapView) { 861 // Here 862 map2.flyToBounds([ 863 [e.location.raw.mapView.south,e.location.raw.mapView.west], 864 [e.location.raw.mapView.north,e.location.raw.mapView.east] 865 ]); 866 }else{ 867 // No Bounds available for this search result 868 map2.flyTo([e.location.y, e.location.x], 17); 869 } 870 } 871 872 locationMarker.setLatLng(coords); 873 874 if (!markerIsVisible) { 875 locationMarker.addTo(map2); 876 markerIsVisible = true; 877 } 878 879 setLocationLatLng(coords); 880 881 //setAddress(label); 882 } 883 }); 884 885 oumMap2 = map2; 886 887 //Event: drag marker 888 locationMarker.on('dragend', function(e) { 889 setLocationLatLng(e.target.getLatLng()); 890 }); 891 892 //Validation for required checkbox groups 893 jQuery('#oum_add_location input[type="submit"]').on('click', function() { 894 let required_fieldsets = jQuery('#oum_add_location fieldset.is-required'); 895 896 required_fieldsets.each(function() {
897 $cbx_group = jQuery(this).find('input:checkbox'); 898 $cbx_group.prop('required', true); 899 if($cbx_group.is(":checked")){ 900 $cbx_group.prop('required', false); 901 } 902 }); 903 }); 904 905 //set lat & lng input fields 906 function setLocationLatLng(markerLatLng) { 907 console.log(markerLatLng); 908 909 jQuery('#oum_location_lat').val(markerLatLng.lat); 910 jQuery('#oum_location_lng').val(markerLatLng.lng); 911 } 912 913 //set address field 914 function setAddress(label) { 915 jQuery('#oum_location_address').val(label); 916 } 917 918 })(); 919 920 // Event: click on "+ Add Location" button 921 document.getElementById('open-add-location-overlay').addEventListener('click', function(event) { 922 923 // show overlay 924 document.getElementById('add-location-overlay').classList.add('active'); 925 926 // reset overlay 927 document.getElementById('oum_add_location_thankyou').style.display = 'none'; // hide thank you message 928 document.getElementById('oum_add_location').style.display = 'block'; 929 document.getElementById('oum_add_location').reset(); // clear form (except marker lat/lng) 930 document.getElementById('add-location-overlay').classList.remove('edit-location'); // remove edit class 931 if (document.querySelector('input[name="oum_post_id"]') != null) document.querySelector('input[name="oum_post_id"]').value = ''; // clear post_id 932 if (document.querySelector('input[name="oum_delete_location"]') != null) document.querySelector('input[name="oum_delete_location"]').value = ''; // clear delete_location 933 if (document.getElementById('oum_remove_image') != null) document.getElementById('oum_remove_image').click(); // remove image 934 if (document.getElementById('oum_remove_audio') != null) document.getElementById('oum_remove_audio').click(); 935 936 // prevent body scrolling 937 document.querySelector('body').classList.add('oum-add-location-opened'); 938 939 // scroll to top of overlay 940 window.scrollTo(0, document.getElementById('add-location-overlay').getBoundingClientRect().top + scrollY); 941 942 //recalculate map size (due to overlay opening) 943 map2.invalidateSize({animate: false}); 944 945 // stop locate process (main map) 946 if(map_locate_process) { 947 map_locate_process.stop(); 948 } 949 950 // move "Add Location"-Map to current Main map position 951 let main_map_width = document.querySelector(`#${map_el}`).offsetWidth; 952 let main_map_height = document.querySelector(`#${map_el}`).offsetHeight; 953 let start_bounds = latLngToBounds(parseFloat(start_lat), parseFloat(start_lng), parseFloat(start_zoom), main_map_width, main_map_height); 954 955 // reposition map (wait for invalidateSize() to be ready) 956 setTimeout(function() { 957 map2.fitBounds(start_bounds); 958 }, 300); 959 960 }); 961 962 // Event: click on "notify on publish" 963 if (document.getElementById('oum_location_notification') != null) { 964 document.getElementById('oum_location_notification').addEventListener('change', function(event) { 965 if (this.checked) { 966 document.getElementById('oum_author').classList.add('active'); 967 document.getElementById('oum_location_author_name').required = true; 968 document.getElementById('oum_location_author_email').required = true; 969 } else { 970 document.getElementById('oum_author').classList.remove('active'); 971 document.getElementById('oum_location_author_name').required = false; 972 document.getElementById('oum_location_author_email').required = false; 973 } 974 }); 975 } 976 977 // Events: close "Add location" overlay 978 if (document.getElementById('close-add-location-overlay') != null) { 979 980 // Event: Close "Add location" popup on X 981 document.getElementById('close-add-location-overlay').addEventListener('click', function(event) { 982 document.getElementById('add-location-overlay').classList.remove('active'); 983 984 // stop locate process (map2) 985 if(map2_locate_process) { 986 map2_locate_process.stop(); 987 } 988 989 // allow body scrolling 990 document.querySelector('body').classList.remove('oum-add-location-opened'); 991 }); 992 993 // Event: Close "Add location" popup on ESC key 994 document.onkeydown = function(evt) { 995 evt = evt || window.event; 996 if(evt.key === "Escape") { 997 document.getElementById('close-add-location-overlay').click(); 998 } 999 }; 1000 1001 // Event: Close "Add location" popup on click on backdrop 1002 document.getElementById('add-location-overlay').addEventListener('click', function(event) { 1003 if (event.target !== this) return; 1004 document.getElementById('close-add-location-overlay').click(); 1005 }); 1006 } 1007 1008 // Event: Remove uploaded image 1009 if (document.getElementById('oum_remove_image') != null) { 1010 document.getElementById('oum_remove_image').addEventListener('click', function() { 1011 document.getElementById('oum_location_image').value = ''; 1012 document.getElementById('oum_remove_existing_image').value = '1'; 1013 document.getElementById('oum_location_image').nextElementSibling.classList.remove('active'); 1014 document.getElementById('oum_location_image').nextElementSibling.querySelector('span').textContent = ''; 1015 }); 1016 } 1017 1018 // Event: Remove uploaded audio 1019 if (document.getElementById('oum_remove_audio') != null) { 1020 document.getElementById('oum_remove_audio').addEventListener('click', function() { 1021 document.getElementById('oum_location_audio').value = ''; 1022 document.getElementById('oum_remove_existing_audio').value = '1'; 1023 document.getElementById('oum_location_audio').nextElementSibling.classList.remove('active'); 1024 document.getElementById('oum_location_audio').nextElementSibling.querySelector('span').textContent = ''; 1025 }); 1026 } 1027 1028 // Event: add another location 1029 if (document.getElementById('oum_add_another_location') != null) { 1030 document.getElementById('oum_add_another_location').addEventListener('click', function() { 1031 document.getElementById('close-add-location-overlay').click(); // close current overlay 1032 document.getElementById('open-add-location-overlay').click(); // open new overlay 1033 }); 1034 } 1035 1036 if(document.getElementById('oum_location_image') != null) { 1037 document.getElementById('oum_location_image').addEventListener('change', updatePreview); 1038 } 1039 1040 if(document.getElementById('oum_location_audio') != null) { 1041 document.getElementById('oum_location_audio').addEventListener('change', updatePreview) 1042 } 1043 1044 // Event delegation for Edit and Delete Location buttons 1045 document.addEventListener('click', function(event) { 1046 // Edit Location button clicked 1047 if (event.target.classList.contains('edit-location-button')) { 1048 let post_id = event.target.getAttribute('data-post-id'); 1049 editLocation(post_id); // Call edit function 1050 } 1051 1052 // Delete Location button clicked 1053 if (event.target.matches('#oum_delete_location_btn span')) { 1054 const userConfirmed = confirm(__('Are you sure you want to delete this location?', 'open-u
1054ser-map')); 1055 1056 if (userConfirmed) { 1057 // Set delete flag to true and submit the form 1058 document.querySelector('input[name="oum_delete_location"]').value = 'true'; 1059 document.getElementById('oum_submit_btn').click(); 1060 } 1061 } 1062 }); 1063 1064 } 1065 1066 //execute custom JS from the settings here 1067 let oum_custom_js = Function(custom_js.snippet)(); 1068 1069}, false);
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.