1/* global google */ 2( function( $ ) { 3 4 var map; 5 var mapInitialized = false; // Add this line 6 /** 7 * initMap 8 * 9 * Renders a Google Map onto the selected jQuery element 10 * 11 * @param {jQuery} $el The jQuery element. 12 */ 13 14 function initMap( $el ) { 15 if (!mapInitialized) { 16 // Find marker elements within map. 17 const $markers = $el.find( '.marker' ); 18 19 // Create gerenic map. 20 const mapArgs = { 21 zoom: $el.data( 'zoom' ) || 16, 22 mapTypeId: google.maps.MapTypeId.ROADMAP, 23 disableDefaultUI: true, 24 styles: [ 25 { 26 elementType: 'geometry', 27 stylers: [ 28 { 29 color: '#ffedd7', 30 }, 31 ], 32 }, 33 { 34 elementType: 'labels.icon', 35 stylers: [ 36 { 37 visibility: 'off', 38 }, 39 ], 40 }, 41 { 42 elementType: 'labels.text.fill', 43 stylers: [ 44 { 45 color: '#616161', 46 }, 47 ], 48 }, 49 { 50 elementType: 'labels.text.stroke', 51 stylers: [ 52 { 53 color: '#f5f5f5', 54 }, 55 ], 56 }, 57 { 58 featureType: 'administrative.land_parcel', 59 elementType: 'labels.text.fill', 60 stylers: [ 61 { 62 color: '#bdbdbd', 63 }, 64 ], 65 }, 66 { 67 featureType: 'poi', 68 elementType: 'geometry', 69 stylers: [ 70 { 71 color: '#eeeeee', 72 }, 73 ], 74 }, 75 { 76 featureType: 'poi', 77 elementType: 'labels.text.fill', 78 stylers: [ 79 { 80 color: '#757575', 81 }, 82 ], 83 }, 84 { 85 featureType: 'poi.park', 86 elementType: 'geometry', 87 stylers: [ 88 { 89 color: '#b4e49b', 90 }, 91 ], 92 }, 93 { 94 featureType: 'poi.business', 95 elementType: 'geometry', 96 stylers: [ 97 { 98 color: '#fff0ac', 99 }, 100 ], 101 }, 102 103 { 104 featureType: 'poi.park', 105 elementType: 'labels.text.fill', 106 stylers: [ 107 { 108 color: '#9e9e9e', 109 }, 110 ], 111 }, 112 { 113 featureType: 'road', 114 elementType: 'geometry', 115 stylers: [ 116 { 117 color: '#ffffff', 118 }, 119 ], 120 }, 121 { 122 featureType: 'road.arterial', 123 elementType: 'labels.text.fill', 124 stylers: [ 125 { 126 color: '#757575', 127 }, 128 ], 129 }, 130 { 131 featureType: 'road.highway', 132 elementType: 'geometry', 133 stylers: [ 134 { 135 color: '#dadada', 136 }, 137 ], 138 }, 139 { 140 featureType: 'road.highway', 141 elementType: 'labels.text.fill', 142 stylers: [ 143 { 144 color: '#616161', 145 }, 146 ], 147 }, 148 { 149 featureType: 'road.local', 150 elementType: 'labels.text.fill', 151 stylers: [ 152 { 153 color: '#9e9e9e', 154 }, 155 ], 156 }, 157 { 158 featureType: 'transit.line', 159 elementType: 'geometry', 160 stylers: [ 161 { 162 color: '#e5e5e5', 163 }, 164 ], 165 }, 166 { 167 featureType: 'transit.station', 168 elementType: 'geometry', 169 stylers: [ 170 { 171 color: '#eeeeee', 172 }, 173 ], 174 }, 175 { 176 featureType: 'water', 177 elementType: 'geometry', 178 stylers: [ 179 { 180 color: '#76cff0', 181 }, 182 ], 183 }, 184 { 185 featureType: 'water', 186 elementType: 'labels.text.fill', 187 stylers: [ 188 { 189 color: '#9e9e9e', 190 }, 191 ], 192 }, 193 ], 194 }; 195 map = new google.maps.Map( $el[ 0 ], mapArgs ); 196 197 // Add markers. 198 map.markers = []; 199 $markers.each( function() { 200 initMarker( $( this ), map ); 201 } ); 202 203 // Center map based on markers. 204 centerMap(map); 205 206 mapInitialized = true; 207 208 } 209 // render autocompletesearch 210 //autoCompleteSearch(); 211 212 // Return map instance. 213 return map; 214 } 215 216 /** 217 * initMarker 218 * 219 * Creates a marker for the given jQuery element and map. 220 * 221 * @param {Object} $marker The map instance. 222 * @param {Object} map The marker instance. 223 */ 224 function initMarker( $marker, map ) { 225 // Get position from marker. 226 const lat = $marker.data( 'lat' ); 227 const lng = $marker.data( 'lng' ); 228 const latLng = { 229 lat: parseFloat( lat ), 230 lng: parseFloat( lng ), 231 }; 232 const icon = $marker.attr( 'data-img' ); 233 234 // Create marker instance. 235 const marker = new google.maps.Marker( { 236 position: latLng, 237 map, 238 icon: {
239 url: '/wp-content/uploads/2023/11/new-single-pin-icon.svg', // Replace this with the path to your custom marker image 240 scaledSize: new google.maps.Size(32, 32), // Adjust the size as needed 241 }, 242 } ); 243 244 // Append to reference for later use. 245 map.markers.push( marker ); 246 247 // If marker contains HTML, add it to an infoWindow. 248 if ( $marker.html() ) { 249 // Create info window. 250 const infowindow = new google.maps.InfoWindow( { 251 content: $marker.html(), 252 pixelOffset: new google.maps.Size( 240, 96 ), 253 maxWidth: 442, 254 } ); 255 256 // Show info window when marker is clicked. 257 google.maps.event.addListener( marker, 'click', function() { 258 // infowindow.open( map, marker ); 259 260 if ( ! marker.open ) { 261 infowindow.open( map, marker ); 262 marker.open = true; 263 } else { 264 infowindow.close(); 265 marker.open = false; 266 } 267 google.maps.event.addListener( map, 'click', function() { 268 infowindow.close(); 269 marker.open = false; 270 } ); 271 } ); 272 } 273 } 274 275 /** 276 * centerMap 277 * 278 * Centers the map showing all markers in view. 279 * 280 * @param {Object} map The map instance. 281 */ 282 function centerMap( map ) { 283 // Create map boundaries from all map markers. 284 const bounds = new google.maps.LatLngBounds(); 285 map.markers.forEach( function( marker ) { 286 bounds.extend( { 287 lat: marker.position.lat(), 288 lng: marker.position.lng(), 289 } ); 290 } ); 291 292 // Case: Single marker. 293 if ( map.markers.length === 1 ) { 294 map.setCenter( bounds.getCenter() ); 295 296 // Case: Multiple markers. 297 } else { 298 map.fitBounds( bounds ); 299 } 300 } 301 302 // // Call this function when performing an AJAX search 303 // function centerMapAfterSearch(map) { 304 // if (map && map.markers) { 305 // // Sort the markers by distance 306 // map.markers.sort(function (a, b) { 307 // return a.distance - b.distance; 308 // }); 309 310 // // Zoom in on the nearest marker (assuming the nearest one is the first in the sorted array) 311 // const nearestMarker = map.markers[0]; 312 // const nearestLatLng = nearestMarker.getPosition(); 313 314 // // Set the center and zoom level of the map to focus on the nearest location 315 // map.setCenter(nearestLatLng); 316 // map.setZoom(12); // Adjust the zoom level as needed 317 // } 318 // } 319 320 function successCallback(curLat, curLng) { 321 var userLatitude = curLat; 322 var userLongitude = curLng; 323 324 // Call a function to find the nearest location 325 findNearestLocation(userLatitude, userLongitude, map); 326 327 // Call the centerMapAfterSearch function after finding the nearest location 328 // centerMapAfterSearch(map); 329 } 330 331 // Error callback function 332 function errorCallback(error) { 333 console.log("Error occurred while retrieving user's location:", error); 334 } 335 336 // Function to find the nearest location 337 function findNearestLocation(userLatitude, userLongitude, map) { 338 339 // Example loop to retrieve location data from custom post type 340 $.ajax({
341 type: 'post', 342 dataType: 'json', 343 url: myAjax.ajaxurl, 344 data: { action: 'get_all_locations_details' }, 345 beforeSend: function(){ 346 $('.new-location-items').css('opacity','0.5'); 347 }, 348 success: function(response) { 349 350 // Initialize variables to hold the nearest location details 351 var maxDistance = Number.POSITIVE_INFINITY; 352 var nearestDistance = 15; 353 var nearestLocation = []; 354 355 // Iterate over each location 356 response.forEach(function (location) { 357 358 p1 = new google.maps.LatLng(location.lat, location.lng); 359 p2 = new google.maps.LatLng(userLatitude, userLongitude); 360 361 location.distance = calcDistance(p1, p2); 362 363 if( location.distance < maxDistance ) { 364 nearestLocation.push(location); 365 } 366 367 }); 368 369 var nearest = nearestLocation.sort(compare); 370 371 console.log(nearestLocation); 372 373 // Clear existing content 374 //$('body').find('.acf_map').html(''); 375 $('body').find('.new-location-items').html(''); 376 377 if (nearestLocation.length > 0) { 378 nearestLocation.forEach(function(currentLocation) { 379 380 // Replace spaces with empty string in the phone number 381 var phoneWithoutSpaces = currentLocation.phone.replace(/\s/g, ''); 382 383 $('body').find('.acf_map').append(` 384 <div class="marker" data-lat="${currentLocation.lat}" data-lng="${currentLocation.lng}"> 385 <div class="inside-marker"> 386 <div class="facility-img" style="background-image:url(${currentLocation.image})"></div> 387 <div class="facility-info"> 388 <p class="map-title">${currentLocation.title}</p> 389 <p>${currentLocation.address}</p> 390 <ul> 391 <li><a href="tel:${phoneWithoutSpaces}" onclick="ga('send', 'event', 'Call', 'Click', 'Click to Call');">${currentLocation.phone}</a></li> 392 <li><a href="${currentLocation.permalink}">Visit facility</a></li> 393 </ul> 394 </div> 395 </div> 396 </div> 397 `); 398 399 $('body').find('.new-location-items').append(` 400 <div class="new-location-item"> 401 <div class="new-location-box"> 402 <p class="loc-distance"><strong>${currentLocation.distance}</strong> miles away</p> 403 <a class="new-location-img" href="${currentLocation.permalink}" style="background-image:url(${currentLocation.image})"></a> 404 <h3> 405 <a href="${currentLocation.permalink}" class="info-title">${currentLocation.title}</a> 406 </h3> 407 <p class="address">${currentLocation.address}</p> 408 <div class="separator"></div> 409 <p class="phone"><a href="tel:${phoneWithoutSpaces}" onclick="ga('send', 'event', 'Call', 'Click', 'Click to Call');">${currentLocation.phone}</a></p> 410 <p class="email"><a href="mailto:${currentLocation.email}" onclick="ga('send', 'event', 'Email', 'Click', 'Click to Email');">${currentLocation.email}</a></p> 411 <a href="${currentLocation.permalink}" class="btn-view">View Facility</a> 412 </div> 413 </div> 414 `).css('opacity','1'); 415 }); 416 417 //initMap( $('body').find('.location-map-main-container .acf_map') ); 418 //centerMapAfterSearch(map); 419 // Zoom in on the first location 420 centerMapOnFirstLocation(nearestLocation); 421 // Avoid reinitializing the map if it's already initialized 422 if (!mapInitialized) { 423 // Your map initialization logic (initMap) 424 mapInitialized = true; // Set a flag to indicate that the map has been initialized 425 } 426 427 } else { 428 // Display a message if no locations are found 429 $('body').find('.new-location-items').html(` 430 <h5 class="no-loc-found">
430Sorry, no locations found.</h5> 431 `); 432 } 433 434 } 435 }) 436 437 } 438 439 // Function to zoom in on the first location in the response 440 function centerMapOnFirstLocation(locations) { 441 if (locations.length > 0) { 442 var firstLocation = locations[0]; 443 444 // Use the latitude and longitude of the first location 445 var latLng = new google.maps.LatLng(firstLocation.lat, firstLocation.lng); 446 447 // Set the map center and zoom level 448 map.setCenter(latLng); 449 map.setZoom(12); // Adjust the zoom level as needed 450 451 // Iterate over each marker on the map 452 for (var i = 0; i < map.markers.length; i++) { 453 var marker = map.markers[i]; 454 455 // Reset styles and animations for all markers 456 marker.setOptions({ 457 icon: { 458 url: '/wp-content/uploads/2023/11/new-single-pin-icon.svg', // Replace this with the path to your custom marker image 459 scaledSize: new google.maps.Size(32, 32), // Adjust the size as needed 460 }, 461 }); 462 marker.setAnimation(null); // Remove any existing animations 463 marker.addListener('click', function () { 464 // Add your existing click function here 465 // var infowindow = new google.maps.InfoWindow({ 466 // content: firstLocation.title, // Adjust this to get the appropriate title or content for your marker 467 // }); 468 // infowindow.open(map, marker); 469 }); 470 471 // Add a class to the first marker for styling 472 if (marker.position.lat() === latLng.lat() && marker.position.lng() === latLng.lng()) { 473 marker.setOptions({ 474 icon: { 475 url: '/wp-content/uploads/2023/11/new-single-pin-icon.svg', // Replace this with the path to your custom marker image 476 scaledSize: new google.maps.Size(32, 32), // Adjust the size as needed 477 }, 478 }); 479 marker.setAnimation(google.maps.Animation.BOUNCE); // Add a bouncing animation for the first marker 480 marker.addListener('click', function () { 481 // Add your existing click function here 482 // var infowindow = new google.maps.InfoWindow({ 483 // content: firstLocation.title, // Adjust this to get the appropriate title or content for your marker 484 // }); 485 // infowindow.open(map, marker); 486 }); 487 488 } 489 } 490 491 } 492 } 493 494 // Function to convert degrees to radians 495 function degToRad(deg) { 496 return deg * (Math.PI / 180); 497 } 498 // Function to calculate distance between two coordinates using the Haversine formula 499 function calcDistance(p1, p2) { 500 const earthRadiusKm = 6371; // Radius of the Earth in kilometers 501 const dLat = degToRad(p2.lat() - p1.lat()); 502 const dLon = degToRad(p2.lng() - p1.lng()); 503 504 const a = 505 Math.sin(dLat / 2) * Math.sin(dLat / 2) + 506 Math.cos(degToRad(p1.lat())) * Math.cos(degToRad(p2.lat())) * Math.sin(dLon / 2) * Math.sin(dLon / 2); 507 508 const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 509 const distanceKm = earthRadiusKm * c; // Distance in kilometers 510 511 const milesPerKm = 0.621371; // Conversion factor from kilometers to miles 512 const distanceMiles = distanceKm * milesPerKm; // Distance in miles 513 514 return distanceMiles.toFixed(2); 515 } 516 517 function compare(a, b) { 518 if (parseFloat(a.distance) < parseFloat(b.distance)) { 519 return -1; 520 } 521 522 if (parseFloat(a.distance) > parseFloat(b.distance)) { 523 return 1; 524 } 525 526 return 0; 527 } 528 529 // // Function to convert degrees to radians 530 // function degToRad(deg) { 531 // return deg * (Math.PI / 180); 532 // } 533 // function renderMap(location) { 534 // // Assuming you have an ACF map field with the name 'location_map' to display the map 535 // var mapContainer = document.getElementsByClassName('.acf_map'); // Replace 'your_map_container_id' with the ID of the container element to render the map 536 // } 537
538 function geocodeLatLng(geocoder, lat, lng) { 539 const latlng = { 540 lat: parseFloat(lat), 541 lng: parseFloat(lng), 542 }; 543 544 geocoder 545 .geocode({ location: latlng }) 546 .then((response) => { 547 if (response.results[0]) { 548 $('body').find('input.pac-target-input').val(response.results[0].formatted_address); 549 } else { 550 window.alert("No results found"); 551 } 552 }) 553 .catch((e) => window.alert("Geocoder failed due to: " + e)); 554 } 555 556 var getUrlParameter = function getUrlParameter(sParam) { 557 var sPageURL = window.location.search.substring(1), 558 sURLVariables = sPageURL.split('&'), 559 sParameterName, 560 i; 561 562 for (i = 0; i < sURLVariables.length; i++) { 563 sParameterName = sURLVariables[i].split('='); 564 565 if (sParameterName[0] === sParam) { 566 return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]); 567 } 568 } 569 return false; 570 }; 571 572 // Render maps on page load. 573 $( document ).ready( function() { 574 575 var acOptions = { 576 types: ['(regions)'], 577 componentRestrictions: { 578 country: "UK" 579 } 580 }; 581 var ac = new window.google.maps.places.Autocomplete($('.autocomplete-search input.s')[0],acOptions ); 582 var curLat, 583 curLng; 584 585 if (typeof ac !== 'undefined') { 586 google.maps.event.addListener(ac,'place_changed', function(){ 587 var pos = {lat: ac.getPlace().geometry.location.lat(), lng: ac.getPlace().geometry.location.lng()} 588 curLat = pos.lat; 589 curLng = pos.lng; 590 }); 591 } 592 593 const geocoder = new google.maps.Geocoder(); 594 595 if (!navigator.geolocation) { 596 597 console.log('Not Supported!'); 598 599 } else { 600 601 $('body').on('click', '.current-location', function(e){ 602 603 e.preventDefault(); 604 605 navigator.geolocation.getCurrentPosition(function(position) { 606 607 // Get the coordinates of the current possition. 608 curLat = position.coords.latitude; 609 curLng = position.coords.longitude; 610 611 geocodeLatLng( geocoder, curLat, curLng ); 612 613 }); 614 615 }); 616 617 } 618 619 //onload location page with search params 620 var s_curLat = getUrlParameter('curLat'); 621 var s_curLng = getUrlParameter('curLng'); 622 623 //locations page 624 $('form#locationsearch').on('submit', function(e){ 625 e.preventDefault(); 626 successCallback( curLat, curLng ); 627 }); 628 629 //homepage search 630 $('form#locationhomesearch').on('submit', function(e){ 631 e.preventDefault(); 632 successCallback( curLat, curLng ); 633 console.log('triggered!'); 634 location.href = '/?page_id=4274&curLat='+curLat+'&curLng='+curLng; 635 }); 636 637 638 if( s_curLat && s_curLng ) { 639 $('html, body').animate({ 640 scrollTop: $("#locations").offset().top - 100 641 }, 2000); 642 findNearestLocation(s_curLat,s_curLng); 643 }else { 644 // $( '.acf_map' ).each( function() { 645 // initMap( $( this ) ); 646 // } ); 647 } 648 649 $( '.acf_map' ).each( function() { 650 initMap( $( this ) ); 651 } ); 652 653 } ); 654 655}( jQuery ) );
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.