PageSourceSearch

https://www.voa.org/wp-content/plugins/voa-search/voa.js?ver=17902392251.3

js voa.org collected 2026-09-24 08:59:41 UTC 58,923 bytes, 1,359 lines download raw bytes

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>&#10006;</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>&#10006;</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.