1jQuery( document ).ready(function() { 2 (function($) { 3 let map; 4 5 //check if affiliate site to add extra text below service navigator.. 6 if(js_globals.affiliate_site){ 7 $('#affiliateContent').html("<a href='https://voa.org/service-navigator' target='_blank' class='affiliateContentAnchor' rel='noopener noreferrer'>See all VOA locations</a>"); 8 } 9 10 //check if params are in the url 11 var searchParams = new URLSearchParams(window.location.search) 12 13 if ($('#map').length > 0 ) { 14 initMap(); 15 } 16 setTimeout(function(){ 17 18 if ( searchParams.has('zipCode') && searchParams.has('serviceGroup') && searchParams.has('distance') && searchParams.has('service') ) { 19 20 var ZC = searchParams.get('zipCode'); 21 22 //update check for indexOf to -1 not false 23 if( ZC.indexOf(', USA') !== -1 ){ 24 ZC = ZC.substring(0, ZC.indexOf(', USA')); 25 } 26 //let locationName = searchParams.get('hiddenLocationName'); 27 $('#searchMAIN').click(); 28 $('#searchMAIN').val(ZC); 29 30 //set blur to make search run.. 31 $('#searchMAIN').blur(); 32 } 33 },600); 34 35 36 37 //set map marks are global array 38 var markers = []; 39 var validResponse = ''; 40 //clear markers if needed 41 function clearOverlays() { 42 if (markers) { 43 for (i in markers) { 44 markers[i].setMap(null); 45 } 46 } 47 } 48 // Attach your callback function to the `window` object 49 //window.initMap = function() { 50 // JS API is loaded and available 51 //}; 52 53 // default map without searching 54 function initMap() { 55 56 let map = returnDefaultMap(); 57 58 // The marker, positioned at Anoka 59 // const marker = new google.maps.Marker({ 60 // position: anoka, 61 // map: map, 62 // }); 63 const infowindow = new google.maps.InfoWindow(); 64 65 } 66 67 function returnDefaultMap(){ 68 //set default map 69 let map; 70 71 // The location of Anoka 72 const anoka = { lat:45.21, lng: -93.38 }; 73 // The map, centered at Anoka 74 map = new google.maps.Map(document.getElementById("map"), { 75 zoom: 9, 76 center: anoka, 77 }); 78 79 return map; 80 } 81 82 //this is default search map with all valid locations 83 function resetMap(validResponse){ 84 85 const infowindow = new google.maps.InfoWindow(); 86 var bounds = new google.maps.LatLngBounds(); 87 88 clearOverlays(); 89 90 map = returnDefaultMap(); 91 92 if( validResponse['pins'] == "No Pins" ) { 93 94 return false; 95 96 } 97 98 map.setCenter({lat: parseFloat(validResponse['pins'][0]['lat']),lng: parseFloat(validResponse['pins'][0]['lng'])}); 99 100 if(js_globals.site == 'VOA'){ 101 102 var image_marker = js_globals.image_marker; 103 104 }else { 105 106 var image_marker = js_globals.image_marker_VOANS; 107 108 } 109 110 for(let i = 0; i < validResponse['pins'].length;i++){ 111 112 var marker = new google.maps.Marker({ 113 position: { 114 lat: parseFloat(validResponse['pins'][i]['lat']), 115 lng: parseFloat(validResponse['pins'][i]['lng']) 116 }, 117 label: { color:'#fff', 118 fontSize: '18px', 119 text: `${validResponse['pins'][i]['position'] + 1} `, 120 className: 'marker-position' 121 }, 122 icon: image_marker, 123 map: map, 124 title: '', 125 }); 126 bounds.extend(marker.getPosition()); 127 google.maps.event.addListener(marker, 'click', (function(marker, i) { 128 return function() { 129 infowindow.setContent(validResponse['pins'][i]['content']); 130 infowindow.open(map, marker); 131 } 132 })(marker,i)); 133 markers.push(marker); 134 map.fitBounds(bounds); 135 } 136 if( document.getElementById('serviceModal').style.display == "block" ) { 137 138 //hide the service checkboxes.. 139 $('#serviceModalClose').toggle(); 140 //hide the modal close background.. 141 $('#serviceModal').toggle(); 142 143 144 } 145 var url = new URL(window.location.href); 146 if(url.searchParams.has('zipCode') && url.searchParams.has('serviceGroup') && url.searchParams.has('distance') && url.searchParams.has('service')){ 147 window.history.pushState({}, document.title, "/" + "service-navigator/"); 148 }else { 149 $('#serviceGroup').text('I NEED SERVICES FOR...'); 150 if( !$('#services').hasClass('disabled') ){ 151 $('#services').addClass('disabled'); 152 } 153 } 154 155 } 156 157 //Handle Check for zipcode or city 158 function isValidUSZip(sZip) { 159 return /^\d{5}
159(-\d{4})?$/.test(sZip); 160 } 161 162 //HANDLE FORM SUBMIT WITH AJAX ON KEYPRESS ENTER EVENT 163 $('#searchMAIN').keyup(function(event){ 164 if(event.key === "Enter"){ 165 $('#searchMAIN').blur(); 166 } 167 }); 168 169 //HANDLE FORM SUBMIT WITH AJAX with BLUR 170 $('#searchMAIN').blur( function() { 171 172 var search = $('#searchMAIN').val().trim(); 173 174 var distance = "250"; 175 176 //check if valid zip code 177 if ( isValidUSZip(search) ) { 178 179 var zipRequest = JSON.stringify(search); 180 181 } else{ 182 //check if search is length of 2 for state specific search 183 if ( search.trim().length == 2 ) { 184 185 var stateOnlyRequest = JSON.stringify(search.trim().toUpperCase()); 186 187 $('#Error').html('<p></p>'); 188 189 } else { 190 191 //if comma is not found.. 192 var comma = search.indexOf(','); 193 194 if ( comma == -1 && search.trim().length !== 2 ) { 195 196 var locationNameOnlyRequest = JSON.stringify( search.trim().toUpperCase() ); 197 198 } else { 199 200 var cityState = search.trim().toLowerCase(); 201 202 if( cityState.indexOf(',') ){ 203 204 var comma = cityState.indexOf(','); 205 206 var city = cityState.slice( 0, comma ).toUpperCase(); 207 var state = cityState.substring(comma + 1).trim().toUpperCase(); 208 209 var cityRequest = JSON.stringify( city ); 210 var stateRequest = JSON.stringify( state ); 211 212 //stringify adds quotes to string value 213 if( stateRequest.length !== 4 ){ 214 215 $('#Error').html('<p>State needs to be abbreviated using two letters: AZ </p>'); 216 return false; 217 218 }else{ 219 220 $('#Error').html('<p></p>'); 221 222 } 223 } 224 225 226 227 } 228 } 229 230 } 231 if(search.trim() !== "") { 232 233 $('#Error').html('<p></p>'); 234 var searchDistance = JSON.stringify(distance); 235 var api_url = `${website_url}/api/SN/`; 236 $.ajax({ 237 url: `${api_url}`, 238 type: "POST", 239 data : { 240 action: 'run_ajax', 241 zip: zipRequest, 242 city: cityRequest, 243 state: stateRequest, 244 stateOnly: stateOnlyRequest, 245 locationName: locationNameOnlyRequest, 246 distance: searchDistance 247 }, 248 beforeSend: function(){ 249 $('#loading').show(); 250 }, 251 success: function(response){ 252 253 console.log(response); 254 255 $('#loading').hide(); 256 if(response['pins'] !== 'No Pins'){ 257 $('#map').show(); 258 259 validResponse = response; 260 //display the locations 261 //set the url each time for checking.. 262 var url = new URL(window.location.href); 263 $('#locations').html(validResponse['locations']); 264 265 // unhide tabs section.. 266 $("#tabs").removeClass('d-none'); 267 $("#localTab").addClass('d-none'); 268 $("#localTab, #virtualTab").removeClass('active'); 269 $("#locationTab").addClass('active'); 270 $("#local, #virtual").addClass('d-none'); 271 $("#location").removeClass('d-none'); 272
273 // If no Zip, keep local tab hidden, if there is a zip and valid results, display local tab and render the content 274 if( typeof zipRequest === "undefined" ) { 275 276 // do nothing 277 278 } else { 279 280 if ( validResponse['inHouseServices'].length > 0 ) { 281 $("#localTab").removeClass('d-none'); 282 $('#local_services').html(validResponse['inHouseServices']); 283 } 284 285 } 286 287 //check if search params are in the url.. 288 if(url.searchParams.has('zipCode') && url.searchParams.has('serviceGroup') && url.searchParams.has('distance') && url.searchParams.has('service')){ 289 let zip = url.searchParams.get('zipCode'); 290 let SG = url.searchParams.get('serviceGroup'); 291 let Serv = url.searchParams.get('service'); 292 if(SG !== ""){ 293 //set the service 294 Serv = Serv.replace(/-/g, ' '); 295 //update certain services that have parentheses CCRC and PACE 296 if(Serv == "CONTINUUM OF CARE RETIREMENT COMMUNITY CCRC"){ 297 Serv = "CONTINUUM OF CARE RETIREMENT COMMUNITY (CCRC)"; 298 } 299 if(Serv == "PACE PROGRAM OF INCLUSIVE CARE FOR THE ELDERLY"){ 300 Serv = "PACE (PROGRAM OF INCLUSIVE CARE FOR THE ELDERLY)"; 301 } 302 303 serv_text = Serv.toLowerCase(); 304 //this is for not found text for service group, it can have commas 305 sg_text = SG.replace(/-/g, ' ').toLowerCase(); 306 //once its successful for the search do the rest of the search params.. 307 $('#serviceGroup').removeClass('disabled'); 308 $('#serviceGroup').click(); 309 var foundValue = 0; 310 $('.serviceGroup').each(function(){ 311 if($(this).val() == SG.toUpperCase().trim()){ 312 $(this).click(); 313 foundValue++; 314 } 315 }); 316 317 //if there is no service group match, hide the map, set error 318 if(!foundValue){ 319 $('#serviceGroup').click(); 320 $('#locations').html(`<h5> No locations with ${serv_text} services for ${sg_text} near ${zip}. Please search another Location Name | City, ST | ST (abbv) | Zip Code.</h5>`); 321 $('#searchMAIN').val(""); 322 $('#map').hide(); 323 $('#serviceGroup').text('I NEED SERVICES FOR...'); 324 $('#serviceGroup').addClass('disabled'); 325 if( !$('#services').hasClass('disabled') ){ 326 $('#services').addClass('disabled'); 327 } 328 $('.pill').each(function(){ 329 $(this).remove(); 330 }); 331 window.history.pushState({}, document.title, "/" + "service-navigator/"); 332 }else { 333 var foundValue = 0; 334 $('.pill').each(function(){ 335 //update dynamically the service to remove parenteses 336 if($(this).data('filterval') === Serv){ 337 foundValue++; 338 339 }else{ 340 $(this).click(); 341 } 342 }); 343 344 if(!foundValue){ 345 $('#locations').html(`<h5> No locations with ${serv_text} services for ${sg_text} near ${zip}. Please search another: Location Name | City, ST | ST (abbv) | Zip Code.</h5>`); 346 $('#searchMAIN').val(""); 347 $('#map').hide(); 348 $('#serviceGroup').text('I NEED SERVICES FOR...'); 349 $('.pill').each(function(){ 350 $(this).remove(); 351 }); 352 353 $('#serviceGroup').addClass('disabled'); 354 $('#services').addClass('disabled'); 355 window.history.pushState({}, document.title, "/" + "service-navigator/"); 356 }else { 357 $('#serviceGroup').removeClass('disabled'); 358 } 359 } 360 } else { 361 $('#serviceGroup').removeClass('disabled'); 362 } 363 }else { 364 //reset serviceGroup 365 $('#serviceGroup').text('I NEED SERVICES FOR...'); 366 //clear out pills 367 $('.pill').each(function(){ 368 $(this).remove(); 369 }); 370 $('#serviceGroup').removeClass('disabled'); 371 } 372 resetMap(validResponse); 373 var pills = $('.pill'); 374 if(pills.length !== 0){ 375 filterLocations(); 376 } 377 } 378 //no locations match 379 else { 380 //set url every time.. 381 var url = new URL(window.location.href); 382 383 $("#tabs").removeClass('d-none'); 384 $("#localTab").addClass('d-none'); 385 $("#localTab, #virtualTab").removeClass('active'); 386 $("#locationTab").addClass('active'); 387 $("#local, #virtual").addClass('d-none'); 388 $("#location").removeClass('d-none'); 389
390 // If no Zip, keep local tab hidden, if there is a zip, display local tab and render the content 391 if( typeof zipRequest === "undefined" ) { 392 393 // do nothing 394 395 } else { 396 397 if ( response['inHouseServices'].length > 0 ) { 398 $("#localTab").removeClass('d-none'); 399 $('#local_services').html(response['inHouseServices']); 400 } 401 402 } 403 404 //check if params are in url when no locations are found 405 if(url.searchParams.has('zipCode') && url.searchParams.has('serviceGroup') && url.searchParams.has('distance') && url.searchParams.has('service')){ 406 window.history.pushState({}, document.title, "/" + "service-navigator/"); 407 } 408 //remove pins 409 clearOverlays(); 410 $('#locations').html(response['locations']); 411 //hide the map 412 $('#map').hide(); 413 //clear the pins 414 $('.pill').each(function(){ 415 $(this).remove(); 416 }); 417 418 //reset service group text and disable buttons 419 //reset serviceGroup 420 $('#serviceGroup').text('I NEED SERVICES FOR...'); 421 $('#serviceGroup').addClass('disabled'); 422 if( !$('#services').hasClass('disabled') ){ 423 $('#services').addClass('disabled'); 424 } 425 426 } 427 }, 428 error: function(error){ 429 $('#loading').hide(); 430 console.log('error: ', error); 431 } 432 }) 433 } 434 }); 435 436 437 438 //handle service group button being clicked 439 $('#serviceGroup').click(function(){ 440 if(!$(this).hasClass('disabled')){ 441 var serviceGroupPosition = $('#serviceGroup').position(); 442 var left = serviceGroupPosition.left; 443 var top = serviceGroupPosition.top; 444 $('#serviceGroupModalClose').toggle(); 445 $('#serviceGroupModal').toggleClass('hidden'); 446 $('#serviceGroupModal').toggleClass('flex'); 447 $('#serviceGroupModal').css('left',left); 448 $('#serviceGroupModal').css('top',top); 449 //create Servicecheckboxes 450 createServiceCheckboxes(); 451 //remove disable for service button 452 $('#services').prop( 'disabled' , false ); 453 //create service Groups 454 createServiceGroups(validResponse); 455 456 } 457 }); 458 459 //function to create all service checkboxes to reference in createServiceGroup function 460 function createServiceCheckboxes(){ 461 //set services as response data 462 //used to get each object item 463 var services = validResponse['uniqueServices']; 464 $('#serviceModal .grid').html(''); 465 for(const service in services){ 466 //clear out the inner html of serviceModal 467 if(service['service'] !== ""){ 468 $('#serviceModal .grid').append(`<div class='flex justify-start items-center px-2'><input type='checkbox' class='mr-2 serviceCheckbox' name='service' title='${services[service].toUpperCase()}' value='${services[service].toUpperCase()}' aria-label='${services[service].toUpperCase()}'><label for='service'>${services[service]}</label></div>`); 469 } 470 } 471 } 472 //create serviceGroups, create serviceCheckboxes with Service Group Class 473 function createServiceGroups(validResponse){ 474 var locations = validResponse['results']; 475 var serviceGroups = []; 476 var services_Arr = []; 477 //go through each object location 478 locations.forEach(function(item,index){ 479 var service_groups = JSON.parse(item['service_groups']); 480 for(var i = 0; i < service_groups.length;i++){ 481 serviceGroups.push(service_groups[i]['name']); 482 if(service_groups[i]['services'].length !== 0){ 483 services_Arr.push([service_groups[i]['name'], service_groups[i]['services']]); 484 } 485 } 486 }); 487 var services = document.querySelectorAll('.serviceCheckbox'); 488 var uniqueServices = []; 489 //push all services 490 for(var j = 0; j < services.length;j++){ 491 uniqueServices.push(services[j].value); 492 } 493 //filter out duplicates 494 var uniqueServiceGroups = [...new Set(serviceGroups)]; 495 var uniqueServices = [...new Set(uniqueServices)]; 496 //go through all services and add classes based on the SG 497 for(var i = 0; i < services_Arr.length;i++){ 498 //REMOVE ALL SPACES AND COMMAS FROM SERVICE GROUPS ARRAY 499 const SG = services_Arr[i][0].replace(/[, ]+/g, '-').toUpperCase(); 500 for(var j = 0; j < services_Arr[i][1].length;j++){ 501 for(var z = 0; z < services.length;z++){ 502 if(services_Arr[i][1][j].toUpperCase() == services[z].value){ 503 if(!services[z].classList.contains(`${SG}`)){ 504 services[z].classList.add(`${SG}`); 505 }else{ 506 continue; 507 } 508 } 509 } 510 } 511 } 512 //empty out service groups 513 $('#serviceGroupModal').html(''); 514 uniqueServiceGroups.forEach(function(item){ 515 //REMOVE ALL SPACES AND COMMAS FROM SERVICE GROUPS ARRAY 516 $('#serviceGroupModal').append(`<button value="${item.replace(/[, ]+/g, '-').toUpperCase()}" class="serviceGroup">${item.toUpperCase()}</button>`); 517 }); 518 } 519 //handle service group inner button being clicked 520 $(document).on('click','.serviceGroup',function(){ 521 var serviceGroup = $(this).val(); 522 var serviceGroupText = $(this).text(); 523 524 $('#serviceGroup').val(serviceGroup); 525 $('#serviceGroup').text(serviceGroupText); 526 //disable services before checking 527 $('#services').removeClass('disabled'); 528 createServiceMessage(serviceGroupText); 529 530 handleServiceGroup(serviceGroup); 531 532 if ( serviceGroupText !== "I NEED SERVICES FOR...") { 533 sendInteraction('Service Group', serviceGroupText); 534 } 535 536 //hide modal and bg modal 537 $('#serviceGroupModalClose').toggle(); 538 $('#serviceGroupModal').toggleClass('hidden'); 539 $('#serviceGroupModal').toggleClass('flex'); 540 541 }); 542 //create service message above service checkboxes 543 function createServiceMessage(serviceGroupText){ 544 545 if(isValidUSZip($('#searchMAIN').val().trim())){ 546 547 $('#serviceMessage').html(`<div class='col-span-full mb-2 px-2'>Current ${serviceGroupText.toLowerCase()} services available ${validResponse['distance']}
547 miles from ${validResponse['zip']}:</div>`); 548 549 }else { 550 551 //check if searching for city,ST 552 if($('#searchMAIN').val().indexOf(",") > -1){ 553 554 $('#serviceMessage').html(`<div class='col-span-full mb-2 px-2'>Current ${serviceGroupText.toLowerCase()} services available ${validResponse['distance']} miles from ${ $('#searchMAIN').val() }:</div>`); 555 556 }else { 557 558 //check for ST 559 if($('#searchMAIN').val().length == 2 ){ 560 561 $('#serviceMessage').html(`<div class='col-span-full mb-2 px-2'>Current ${serviceGroupText.toLowerCase()} services available in ${ $('#searchMAIN').val() }:</div>`); 562 563 }else { 564 565 $('#serviceMessage').html(`<div class='col-span-full mb-2 px-2'>Current ${serviceGroupText.toLowerCase()} services available for ${ $('#searchMAIN').val() }:</div>`); 566 567 } 568 } 569 570 } 571 } 572 //filter all locations 573 function filterLocations() { 574 575 var filterData = []; 576 var count = 0; 577 $('.pill').each(function(){ 578 filterData.push($(this).data('filterval').trim()); 579 }); 580 if(filterData.length > 0){ 581 //reset map then go through locations and remove pins.. 582 clearOverlays(); 583 $('#map').show(); 584 $('#notFound').remove(); 585 $('.location').each(function(){ 586 //get each location filter data 587 var locationFilter = $(this).data('filter'); 588 //split strings into array 589 var locationData = locationFilter.split(','); 590 //variable used to break out of outter for loop 591 var exit = false; 592 //loop through the location data 593 for(var j = 0; j < locationData.length;j++){ 594 //loop through filter data 595 for(var i = 0; i < filterData.length;i++){ 596 //if location data at index j == filter data at index i 597 //keep showing the location div, exit both loops 598 if(locationData[j] == filterData[i]){ 599 600 //set breakout to true 601 exit = true; 602 //show the location div 603 count += 1; 604 $(this).show(); 605 //exit for loop 606 return exit; 607 } 608 else { 609 $(this).hide(); 610 } 611 }//end inner for loop 612 //exit loop 613 if(exit == true){ 614 break; 615 } 616 }//end outer for loop 617 }); 618 //always filter service groups after filtering the services 619 filterLocationServiceGroups(); 620 mapFilterUpdate(); 621 } 622 else { 623 //remove just incase the previous search was not found 624 $('#notFound').remove(); 625 //hide all locations 626 $('.location').each(function(){ 627 $(this).hide(); 628 }); 629 $('#locations').append("<div id='notFound'><h5>No locations found.</h5></div>"); 630 $('#map').hide(); 631 clearOverlays(); 632 resetMap(validResponse); 633 } 634 635 } 636 //handle filtering the location service group 637 function filterLocationServiceGroups(){ 638 var locationsShown = 0; 639 $('.location').each(function(){ 640 //get each location service group 641 var locationServiceGroups = $(this).data('location-service-groups'); 642 var locationServiceGroupData = locationServiceGroups.split(','); 643 var hide = true; 644 //check if location group data is empty 645 if(locationServiceGroupData.length > 0){ 646 for( var i = 0; i < locationServiceGroupData.length; i++ ){ 647 if( $('#serviceGroup').val() == locationServiceGroupData[i] ) { 648 hide = false;
649 locationsShown++; 650 break; 651 }else { 652 continue; 653 } 654 } 655 }else { 656 hide = false; 657 } 658 if(hide) { 659 //hide the location 660 $(this).hide(); 661 } 662 }); 663 664 //check if no locations match the service group filtering.. 665 if(locationsShown == 0){ 666 //remove just incase the previous search was not found 667 $('#notFound').remove(); 668 //hide all locations 669 $('.location').each(function(){ 670 $(this).hide(); 671 }); 672 //remove all pills 673 $('.pill').each(function(){ 674 $(this).remove(); 675 }); 676 //set no locations found 677 $('#locations').append("<div id='notFound'><h5>No locations found.</h5></div>"); 678 $('#map').hide(); 679 resetMap(validResponse); 680 } else { 681 //set location array and checkbox array to empty array 682 var locationDataArr = []; 683 var checkboxValues = []; 684 685 //only loop through locations that have that service group 686 $('.location:visible').each(function(){ 687 //get the filter data 688 var filterData = $(this).data('filter'); 689 //set it to an array 690 var locationData = filterData.split(','); 691 //removing VOA/VOANS 692 locationData.shift(); 693 for(var i = 0;i < locationData.length;i++){ 694 locationDataArr.push(locationData[i]); 695 } 696 697 $('.serviceCheckbox').each(function(){ 698 checkboxValues.push($(this).val()); 699 }); 700 }); 701 //getting all unique location services 702 var uniqueLocationServices = [...new Set(locationDataArr)]; 703 //compare location checkboxValues to services to see if there is not a match 704 for(var j = 0; j < checkboxValues.length;j++){ 705 //current checkbox value to compare to services 706 var valueToCheck = checkboxValues[j]; 707 //if there is a match do nothing 708 if(uniqueLocationServices.includes(valueToCheck)){ 709 } 710 //remove checkbox and hide pill if there is not a match 711 else { 712 //hide the service checkbox 713 $('.serviceCheckbox').each(function(){ 714 if( $(this).val() == valueToCheck ){ 715 $(this).parent().hide(); 716 } 717 }); 718 //remove the pill 719 $('.pill').each(function(){ 720 if($(this).data('filterval') == valueToCheck){ 721 $(this).click(); 722 } 723 }); 724 } 725 } 726 } 727 } 728 //handle creating the bounds and new map markers 729 function mapFilterUpdate(){ 730 731 const infowindow = new google.maps.InfoWindow(); 732 var bounds = new google.maps.LatLngBounds(); 733 734 let map = returnDefaultMap(); 735 736 map.setCenter({lat: parseFloat(validResponse['pins'][0]['lat']),lng: parseFloat(validResponse['pins'][0]['lng'])}); 737 const image_marker = js_globals.image_marker; 738 const image_marker_VOANS = js_globals.image_marker_VOANS; 739 $('.location').each(function(i){ 740 if($(this).css('display') !== 'none'){ 741 if( js_globals.site == 'VOA' ){ 742 var marker = new google.maps.Marker({ 743 position: { 744 lat: parseFloat($(this).data('lat')), 745 lng: parseFloat($(this).data('lng')) 746 }, 747 label: { color:'#fff', 748 fontSize: '18px', 749 text: `${$(this).data('id')} `, 750 className: 'marker-position' 751 }, 752 753 icon: image_marker, 754 map: map, 755 title: '', 756 }); 757 } 758 else { 759 var marker = new google.maps.Marker({ 760 position: { 761 lat: parseFloat($(this).data('lat')), 762 lng: parseFloat($(this).data('lng')) 763 }, 764 label: { color:'#fff', 765 fontSize: '18px', 766 text: `${$(this).data('id')} `, 767 className: 'marker-position' 768 }, 769 770 icon: image_marker_VOANS, 771 map: map, 772 title: '', 773 }); 774 } 775 bounds.extend(marker.getPosition()); 776 var content = 777 `<div> 778 <a href='${$(this).data('href')}'> 779 <h5 class='location-heading'> ${$(this).data('name')} > </h5> 780 </a> 781 <br> 782 <p class='location-info'>${$(this).data('address')}</p> 783 <p class='location-info'>${$(this).data('city-info')}</p> 784 <br> 785 <p class='location-info mb-2'>${$(this).data('phone')}</p> 786 <br> 787 </div>`; 788 google.maps.event.addListener(marker, 'click', (function(marker, i) { 789 return function() { 790 infowindow.setContent(content); 791 infowindow.open(map, marker); 792 } 793 })(marker,i)); 794 markers.push(marker); 795 map.fitBounds(bounds); 796 } 797 }); 798 } 799 //handle service group being changed 800 function handleServiceGroup(serviceGroup){ 801 var selectedVal = serviceGroup; 802 //reset pills 803 $('#pills').html(''); 804 //reset service checkboxes
805 $('.serviceCheckbox').prop('checked',false); 806 //set only ones that match the service group to true 807 $(`.${selectedVal}`).prop('checked',true); 808 809 //go through each checkbox 810 $('.serviceCheckbox').each(function(){ 811 //create each pill based on each service checked.. 812 if($(this).is(':checked')){ 813 var newPill = "<a href='#' class='p-2 rounded-lg mx-2 my-2 text-xs pill' data-filterVal='" + $(this).val() + "'>" + $(this).val() + " <span>✖</span>"; 814 $('#pills').append(newPill); 815 }else { 816 $(this).parent().hide(); 817 } 818 }); 819 filterLocations(); 820 } 821 822 //handle service button being clicked 823 $('#services').click(function(){ 824 //set the top of the modal to below the serivces// 825 //set modal to display grid 826 if( !$(this).hasClass('disabled')){ 827 $('#serviceModalClose').toggle(); 828 $('#serviceModal').toggle(); 829 var serviceGroupPosition = $('#services').position(); 830 var right = $(document).width() - ($('#services').offset().left + $('#services').width()); 831 var top = serviceGroupPosition.top; 832 var left = serviceGroupPosition.left; 833 $('#serviceModal').toggleClass('flex'); 834 if($(document).width() < '767') { 835 $('#serviceModal').css('left',left); 836 837 } 838 else { 839 $('#serviceModal').css('right',right); 840 } 841 $('#serviceModal').css('top',top); 842 } 843 }); 844 845 //handle services being clicked 846 $(document).on('change','.serviceCheckbox',function(){ 847 var checkBoxVal = $(this).val(); 848 849 sendInteraction('Checkbox', checkBoxVal); 850 851 if($(this).is(':checked')){ 852 //active 853 var newPill = "<a href='#' class='p-2 rounded-lg mx-2 my-2 text-xs pill' data-filterVal='" + checkBoxVal + "'>" + checkBoxVal + " <span>✖</span>"; 854 //check if pills already exist 855 var exit = false; 856 $('.pill').each(function(){ 857 if($(this).data('filterval').trim() === checkBoxVal.trim()){ 858 exit = true; 859 return false; 860 } 861 }); 862 if(exit){ 863 return false; 864 } 865 $('#pills').append(newPill); 866 filterLocations(); 867 return false; 868 } 869 else{ 870 //remove the inactive pill 871 $('.pill').each(function(){ 872 if($(this).data('filterval').trim() == checkBoxVal.trim()){ 873 $(this).remove(); 874 if($('#pills').children().length == 0){ 875 //show all locations again 876 $('.location').show(); 877 resetMap(validResponse); 878 } 879 else{ 880 //filter location check 881 filterLocations(); 882 } 883 } 884 }); 885 } 886 887 }); 888 889 //handle pills being clicked 890 $(document).on('click', '.pill', function(){ 891 //remove the pill 892 var pill = $(this); 893 894 var text = pill[0].text.replace('â',''); 895 896 sendInteraction('Pill',text); 897 898 $(this).remove(); 899 //check services 900 checkServices(pill); 901 if($('#pills').children().length == 0){ 902 //show all locations again 903 $('.location').show(); 904 resetMap(validResponse); 905 }else{ 906 //filter location check 907 filterLocations(); 908 } 909 return false; 910 }); 911 912 //uncheck services when a pill is removed 913 function checkServices(pill){
914 var serviceCheck = pill.data('filterval'); 915 var services = document.querySelectorAll('.serviceCheckbox'); 916 var servicesArr = []; 917 //push all services 918 for(var j = 0; j < services.length;j++){ 919 servicesArr.push(services[j].value); 920 } 921 for(var i = 0; i < services.length;i++){ 922 if(servicesArr[i].toUpperCase().trim() == serviceCheck){ 923 services[i].checked = false; 924 } 925 } 926 } 927 928 //handle div behind modal being clicked 929 $('#serviceGroupModalClose').click(function(){ 930 $('#serviceGroupModalClose').toggle(); 931 $('#serviceGroupModal').toggleClass('hidden'); 932 $('#serviceGroupModal').toggleClass('flex'); 933 }); 934 935 //handle div behind serviceModal being clicked 936 $('#serviceModalClose').click(function(){ 937 $('#serviceModalClose').toggle(); 938 $('#serviceModal').toggle(); 939 }); 940 941 //handle div behind modal being clicked 942 $('#amenityModalClose').click(function(){ 943 $('#amenityModalClose').toggle(); 944 $('#amenityModal').toggle(); 945 }); 946 947 //handle div behind modal being clicked 948 $('#affiliateModalClose').click(function(){ 949 $('#affiliateModalClose').toggle(); 950 $('#affiliateModal').toggle(); 951 }); 952 953 954 955 956 // VOA SEARCH BLOCK JS ONLY =============== 957 958 //handle zip code being entered and leaving the zip code input box 959 $('#zipCodeSF').blur(function(event){ 960 event.preventDefault(); 961 //when unfocusing after input 962 // if($('#searchByLocationName').prop('checked')){ 963 // var locationNameRequest = JSON.stringify($('#zipCodeSF').val().trim().toUpperCase()); 964 // $('#serviceGroupSF').removeClass("disabled"); 965 // $('#serviceGroupSFServ').removeClass("disabled"); 966 // }else { 967 968 //first need to check if state abbreviation 969 if($('#zipCodeSF').val().trim().length == 2){ 970 var stateOnlyRequest = JSON.stringify($('#zipCodeSF').val().trim().toUpperCase()); 971 $('#hiddenLocationName').val('false'); 972 $('#serviceGroupSF').removeClass("disabled"); 973 $('#serviceGroupSFServ').removeClass("disabled"); 974 975 }else { 976 //search request that might be either: Zip Code , City, ST / or Location Name 977 if($('#zipCodeSF').val().length > 2) { 978 var search = $('#zipCodeSF').val(); 979 var cityState = search.trim().toUpperCase(); 980 var length = cityState.length; 981 var comma = cityState.indexOf(','); 982 var cityRequest = JSON.stringify(cityState.slice(0, comma)); 983 var afterComma = cityState.substring(comma + 1); 984 var stateRequest = JSON.stringify(afterComma.slice(afterComma, length).trim()); 985 //checking if it is a valid zip code.. 986 if(isValidUSZip( search.trim() ) ){ 987 $('#serviceGroupSF').removeClass("disabled"); 988 $('#serviceGroupSFServ').removeClass("disabled"); 989 $('#hiddenLocationName').val('false'); 990 $('#Error').html('<p></p>'); 991 //regular search, not a State abbreviated and not a zip code 992 }else{ 993 //if comma is missing then it will default to location name search.. 994 if(comma == -1){ 995 var locationNameRequest = JSON.stringify($('#zipCodeSF').val().trim().toUpperCase()); 996 //set it as a location name search.. 997 $('#hiddenLocationName').val('true'); 998 //have ability to click on service groups and services dropdowns 999 // $('#serviceGroupSF').removeClass("disabled"); 1000 // $('#serviceGroupSFServ').removeClass("disabled");
1001 //set hidden inputs as empty strings to not filter location name 1002 $("input[name=service]").val(""); 1003 $("input[name=serviceGroup]").val(""); 1004 $('#searchCTA').submit(); 1005 1006 }else { 1007 if(stateRequest.length != 4){ 1008 $('#Error').html('<p>State needs to be abbreviated using two letters: AZ </p>'); 1009 $('#servicesSF').removeClass("disabled"); 1010 $('#serviceGroupSF').removeClass("disabled"); 1011 $('#serviceGroupSFServ').removeClass("disabled"); 1012 $('#servicesSF').addClass("disabled"); 1013 $('#serviceGroupSF').addClass("disabled"); 1014 return false; 1015 }else { 1016 $('#hiddenLocationName').val('false'); 1017 $('#Error').html('<p></p>'); 1018 } 1019 } 1020 $('#serviceGroupSF').removeClass("disabled"); 1021 $('#serviceGroupSFServ').removeClass("disabled"); 1022 } 1023 } 1024 //disable all buttons if the length is less than 3 1025 else { 1026 $('#servicesSF').removeClass("disabled"); 1027 $('#serviceGroupSF').removeClass("disabled"); 1028 $('#serviceGroupSFServ').removeClass("disabled"); 1029 $('#servicesSF').addClass("disabled"); 1030 $('#serviceGroupSF').addClass("disabled"); 1031 } 1032 } 1033 return false; 1034 }); 1035 1036 //remove error on focus when typing 1037 $('#zipCodeSF').focus(function(){ 1038 $('#Error').html('<p></p>'); 1039 }); 1040 1041 // //remove error when checking location checkbox and allow select options to work when its checked.. 1042 // $('#searchByLocationName').click(function(){ 1043 // if($(this).is(':checked')){ 1044 1045 // $('#Error').html('<p></p>'); 1046 // $('#serviceGroupSF').removeClass("disabled"); 1047 // $('#serviceGroupSFServ').removeClass("disabled"); 1048 // document.querySelector('input[name="hiddenLocationName"]').value = 'true'; 1049 1050 // }else { 1051 // //disable buttons and show error message if there is improper formatting 1052 // $('#serviceGroupSF').removeClass("disabled"); 1053 // $('#serviceGroupSFServ').removeClass("disabled"); 1054 // $('#servicesSF').addClass("disabled"); 1055 // $('#serviceGroupSF').addClass("disabled"); 1056 // $('#zipCodeSF').blur(); 1057 // document.querySelector('input[name="hiddenLocationName"]').value = 'true'; 1058 // } 1059 1060 // }); 1061 1062 //handle displaying modal window 1063 $('#serviceGroupSF').click(function(event){ 1064 event.preventDefault(); 1065 if($('#serviceGroupSF').hasClass('disabled')){ 1066 return false; 1067 } 1068 else { 1069 var serviceGroupPosition = $('#serviceGroupSF').position(); 1070 var left = serviceGroupPosition.left; 1071 var top = serviceGroupPosition.top; 1072 $('#serviceGroupModalCloseSF').toggle(); 1073 $('#serviceGroupModalSF').toggleClass('hidden'); 1074 $('#serviceGroupModalSF').toggleClass('flex'); 1075 $('#serviceGroupModalSF').css('left',left); 1076 $('#serviceGroupModalSF').css('top',top); 1077 return false; 1078 } 1079 }); 1080 1081 //handle displaying modal window 1082 $('#servicesSF').click(function(event){ 1083 event.preventDefault(); 1084 if($('#servicesSF').hasClass('disabled')){ 1085 return false;
1086 } 1087 else { 1088 var distancePosition = $('#servicesSF').position(); 1089 var left = distancePosition.left; 1090 var top = distancePosition.top; 1091 $('#servicesModalCloseSF').toggle(); 1092 $('#servicesModalSF').toggleClass('hidden'); 1093 $('#servicesModalSF').toggleClass('flex'); 1094 $('#servicesModalSF').css('left',left); 1095 $('#servicesModalSF').css('top',top); 1096 return false; 1097 } 1098 }); 1099 //handle div behind modal being clicked 1100 $('#servicesModalCloseSF').click(function(){ 1101 $('#servicesModalCloseSF').toggle(); 1102 $('#servicesModalSF').toggleClass('hidden'); 1103 $('#servicesModalSF').toggleClass('flex'); 1104 }); 1105 1106 //handle div behind modal being clicked 1107 $('#serviceGroupModalCloseSF').click(function(){ 1108 $('#serviceGroupModalCloseSF').toggle(); 1109 $('#serviceGroupModalSF').toggleClass('hidden'); 1110 $('#serviceGroupModalSF').toggleClass('flex'); 1111 }); 1112 1113 //handle serviceGroup modal option selection 1114 $('.serviceGroupSF').click(function(event){ 1115 event.preventDefault(); 1116 $('#serviceGroupModalCloseSF').toggle(); 1117 $('#serviceGroupModalSF').toggleClass('hidden'); 1118 $('#serviceGroupModalSF').toggleClass('flex'); 1119 $('#serviceGroupSF').text($(this).text()); 1120 $("input[name=serviceGroup]").val($(this).val()); 1121 $('#serviceGroupSF').val($(this).val()); 1122 //enable the services dropdown 1123 $('#servicesSF').removeClass('disabled'); 1124 var service_id = $(this).attr('data-id'); 1125 var ajax_url = `${website_url}/wp-json/voa-search/v1/services/${service_id}`; 1126 $.ajax({ 1127 url: `${ajax_url}`, 1128 type: "POST", 1129 data : { 1130 action: 'run_ajax', 1131 id: service_id, 1132 }, 1133 success: function(response){ 1134 //locations have matched 1135 var markup = JSON.parse(response); 1136 $('#servicesModalSF').html(markup); 1137 }, 1138 error: function(error){ 1139 console.log('error: ', error); 1140 } 1141 }); 1142 1143 return false; 1144 }); 1145 //handle services modal option selection 1146 $(document).on('click', '.servicesSF',function(event){ 1147 event.preventDefault(); 1148 $('#servicesModalCloseSF').toggle(); 1149 $('#servicesModalSF').toggleClass('hidden'); 1150 $('#servicesModalSF').toggleClass('flex'); 1151 $('#servicesSF').text($(this).text()); 1152 $('#servicesSF').val($(this).val()); 1153 $("input[name=service]").val($(this).val()); 1154 1155 //form check then submit.. 1156 if($('#zipCodeSF').val() !== "" && $('#serviceGroupSF').val() !== "" && $('#servicesSF').val() !== ""){ 1157 $('#searchCTA').submit(); 1158 } 1159 }); 1160 1161 //tabs show/hide stuff 1162 $('.tabs').on('click',function(e){ 1163 e.preventDefault(); 1164 $('.tabs').removeClass('active'); 1165 $(this).addClass('active'); 1166 let showTab = $(this).data('panel'); 1167 $('#virtual').removeClass('d-none'); 1168 $('#local').removeClass('d-none'); 1169 $('#location').removeClass('d-none'); 1170 $('#virtual').addClass('d-none'); 1171 $('#local').addClass('d-none'); 1172 $('#location').addClass('d-none'); 1173 $(`#${showTab}`).removeClass('d-none'); 1174 }); 1175 1176 // PLACES AUTO COMPLETE RELATED JS ============ 1177 1178 //search input for main service navigator 1179 var searchMain = document.getElementById('searchMAIN'); 1180 var gac_servNav_main = searchMain; 1181 1182 if ( $('#searchMAIN').length ) { 1183 1184 //autocompelte for main service navigator
1185/* 1186 var autocomplete_main = new google.maps.places.Autocomplete(gac_servNav_main, { 1187 componentRestrictions: { country: ["us"] }, 1188 fields: ["address_components"], 1189 types: ["(cities)"], 1190 }); 1191 1192 autocomplete_main.addListener("place_changed", fillInMainServNavAddress); 1193*/ 1194 1195 function fillInMainServNavAddress(){ 1196 1197 //get the updated address from selection 1198 let updatedAddress = gac_servNav_main.value; 1199 1200 if ( updatedAddress.indexOf(', USA') > -1 ) { 1201 //remove the ,USA from string 1202 const gac_results = updatedAddress.slice(0,-5); 1203 1204 document.getElementById('searchMAIN').value = `${gac_results}`; 1205 1206 }else { 1207 1208 if ( updatedAddress.indexOf(',USA') > -1 ) { 1209 1210 const gac_results = updatedAddress.slice(0,-4); 1211 1212 document.getElementById('searchMAIN').value = `${gac_results}`; 1213 1214 } else { 1215 const gac_results = updatedAddress; 1216 1217 document.getElementById('searchMAIN').value = `${gac_results}`; 1218 1219 } 1220 } 1221 $('#searchMAIN').blur(); 1222 } 1223 } 1224 1225 //search input for CTA service navigator 1226 var searchCTA = document.getElementById('zipCodeSF'); 1227 var gac_servNav_CTA = searchCTA; 1228 1229 if( $('#zipCodeSF').length ) { 1230 //autocompelte for main service navigator 1231/* 1232 var autocomplete_CTA = new google.maps.places.Autocomplete(gac_servNav_CTA, { 1233 componentRestrictions: { country: ["us"] }, 1234 fields: ["address_components"], 1235 types: ["(cities)"], 1236 }); 1237 1238 autocomplete_CTA.addListener("place_changed", fillInCTAServNavAddress); 1239*/ 1240 1241 function fillInCTAServNavAddress(){ 1242 //get the updated address from selection 1243 let updatedAddress = gac_servNav_CTA.value; 1244 1245 if ( gac_servNav_CTA.value.indexOf(', USA') > -1 ) { 1246 //remove the ,USA from string 1247 const gac_results = updatedAddress.slice(0,-5); 1248 document.getElementById('zipCodeSF').value = gac_results; 1249 1250 //focus out of the input 1251 gac_servNav_CTA.blur(); 1252 1253 //clear out the error message 1254 $('#Error').html('<p></p>'); 1255 1256 //remove disabled from the service group and service dropdowns 1257 $('#serviceGroupSF').removeClass("disabled"); 1258 $('#serviceGroupSFServ').removeClass("disabled"); 1259 1260 } else { 1261 const gac_results = updatedAddress; 1262 document.getElementById('zipCodeSF').value = gac_results; 1263 } 1264 $('#searchMAIN').blur(); 1265 } 1266 } 1267 1268 //window resize event for service modal and service group modal 1269 1270 $( window ).resize(function(){ 1271 //service modal 1272 if( $('#services').length > 0 ){ 1273 var servicePosition = $('#services').position(); 1274 var right = $( this ).width() - ($('#services').offset().left + $('#services').width()); 1275 var top = servicePosition.top; 1276 var left = servicePosition.left; 1277 if($( this ).width() < '767') { 1278 $('#serviceModal').css('left',left); 1279 $('#serviceModal').css('right','auto'); 1280 } 1281 else { 1282 $('#serviceModal').css('right',right); 1283 $('#serviceModal').css('left','auto') 1284 } 1285 $('#serviceModal').css('top',top); 1286 } 1287 //service group modal 1288 if( $("#serviceGroup").length > 0 ){ 1289 var serviceGroupPosition = $('#serviceGroup').position(); 1290 var left = serviceGroupPosition.left; 1291 var top = serviceGroupPosition.top; 1292 $('#serviceGroupModal').css('left',left); 1293 $('#serviceGroupModal').css('top',top); 1294 } 1295 }); 1296 1297 //custom submenu JS needed to show and hide content 1298 //set non mega menu sub menus to display none 1299 $('.dropdown-regular .submenu-item-has-children .sub-menu').css('display','none'); 1300 1301 1302 1303 //handle all sub-menu parent li's being clicked 1304 $('.dropdown-regular .submenu-item-has-children').on('click',function(){ 1305 1306 if($(this).hasClass('show')){ 1307 $(this).toggleClass('show'); 1308 $(this).children('ul').slideUp(); 1309 } 1310 else { 1311 $(this).toggleClass('show'); 1312 $(this).children('ul').slideDown(); 1313 } 1314 }); 1315 1316 function sendInteraction( type, text ) { 1317 1318 var api_url = `${website_url}/api/SN/interactions.php`; 1319 1320 $.ajax({ 1321 url: `${api_url}`, 1322 type: "POST", 1323 data : { 1324 action: 'run_ajax', 1325 type: JSON.stringify(type), 1326 text: JSON.stringify(text), 1327 }, 1328 success: function(response){ 1329 1330 console.log('file updated'); 1331 1332 }, 1333 error: function(error){ 1334 console.log('error: ', error); 1335 } 1336 }) 1337 1338 } 1339 1340 //handle external links for testing VOANS only.. 1341 if( js_globals.site !== 'VOA' && !js_globals.affiliate_site ){ 1342 $('a').filter(function() { 1343 //check if donate link to not show pop up.. 1344 // if( this.hostname == "donate.voa.org" ){ 1345 // return this.hostname; 1346 // }else { 1347 return this.hostname && this.hostname !== location.hostname; 1348 // } 1349 }).click(function(e) { 1350 if(!confirm("You are leaving this site. Proceed to external site?")) 1351 { 1352 // if user clicks 'no' then dont proceed to link. 1353 e.preventDefault(); 1354 }; 1355 }); 1356 } 1357 })(jQuery); 1358 1359 });
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.