PageSourceSearch

https://goodwillng.org/wp-content/themes/voltron/assets-new/js/locations.js?ver=6.9.9

js goodwillng.org collected 2026-10-03 21:37:20 UTC 23,466 bytes, 760 lines download raw bytes

1var locationsFull;
2
3var Locations = {
4
5    locationType: getParameterByName('location_type') ? getParameterByName('location_type').split(',') : [],
6    zip: getParameterByName('zip') || '',
7    distance: parseInt(getParameterByName('distance')) || 25,
8
9    // this is set for location subpages
10    locationsOfType: false,
11
12    zipCoords: null,
13    filterChange: true,
14
15    locations: null,
16    locationsFiltered: null,
17    map: null,
18    markers: [],
19    geocoder: null,
20    locationId: false,
21    infoWindow: null,
22    apiUrl: null,
23
24    page: 0,
25    resultsPerPage: 9,
26
27    container: null,
28
29    defaults: {
30        hours: {
31            store: null,
32            dc: null,
33            cc: null
34        }
35    },
36
37    // set this for individual location pages
38    locationId: null,
39    currentLocation: null,
40
41
42    init: function(){
43
44        // setup page for individual location types
45        if( document.location.pathname.indexOf("locations/donation-centers") !== -1 ){
46            this.locationType = ["donation-center"];
47            this.locationsOfType = true;
48        }
49
50        if( document.location.pathname.indexOf("locations/career-centers") !== -1 ){
51            this.locationType = ["career-center"];
52            this.locationsOfType = true;
53        }
54
55        if( document.location.pathname.indexOf("locations/stores") !== -1 ){
56            this.locationType = ["store"];
57            this.locationsOfType = true;
58        }
59
60
61        if( this.zip ){
62            $('input[name=location-zip]').val(this.zip);
63        }
64
65        if( this.distance !== 25 ){
66            $('select[name=distance]').val(this.distance);
67        }
68
69        for( var i = 0; i < this.locationType.length; i ++ ){
70            $('.location-type-filters input[value=' + this.locationType[i] + ']').prop("checked", true);
71        }
72
73
74        this.locationId = $('#locations-app').attr('location-id');
75
76        var maxZoom = 12;
77
78        if( this.locationId ){
79            maxZoom = 18;
80        }
81
82
83        if( !this.locationsOfType ){
84            this.map = new google.maps.Map(document.getElementById('locations-map'), {
85    			center: new google.maps.LatLng(33.753746, -84.386330),
86    			zoom: 8,
87                maxZoom: maxZoom,
88    			disableDefaultUI: true,
89    			styles: [
90    				{
91    					"featureType": "landscape",
92    					"elementType": "geometry.fill",
93    					"stylers": [
94    						{
95    							"color": "#e8f5ff"
96    						}
97    					]
98    				},
99    				{
100    					"featureType": "road.highway",
101    					"elementType": "geometry.fill",
102    					"stylers": [
103    						{
104    							"color": "#0068b3"
105    						}
106    					]
107    				}
108    			]
109    		});
110
111
112        }
113
114        this.geocoder = new google.maps.Geocoder();
115
116        this.apiUrl = $('#locations-app').data('apiurl');
117
118
119        if( this.locationId ){
120            this.page = 0;
121            this.resultsPerPage = 3;
122            //this.container = $('.nearby-locations-grid');
123
124            this.markerHandler(this.getCurrentLocationInfo());
125        } else {
126            this.container = $('.locations-grid .row');
127        }
128
129
130        var that = this;
131
132        $.post(
133            that.apiUrl,
134            {},
135            function(data) {
136                that.locations = data;
137                that.locationsFiltered = data;
138                that.loadDefaults();
139
140                if( !that.locationId ){
141                    that.checkGeocoding();
142                } else {
143                    that.setCurrentLocation();
144                }
145            }
146        );
147    },
148
149    getCurrentLocationInfo: function(){
150        var el = $('.location-information-hidden');
151
152        var obj = {
153            post_title: $('.hero-content h1').text(),
154            acf: {
155                latitude: el.attr('data-latitude'),
156                longitude: el.attr('data-longitude'),
157                address_line_1: el.attr('data-address1'),
158                address_line_2: el.attr('data-address2'),
159                city: el.attr('data-city'),
160                state: el.attr('data-state'),
161                zip: el.attr('data-zip'),
162                phone_number: $('.hours .location-hours-item').first().find('phone a').text(),
163            }
164        };
165
166
167        return obj;
168    },
169
170    setCurrentLocation: function(){
171        for( var i = 0; i < this.locations.length; i++ ){
172            if( this.locations[i].ID == this.locationId ){
173                this.currentLocation = this.locations[i];
174                this.zip = this.currentLocation.acf.zip;
175                break;
176            }
177        }
178
179        this.checkGeocoding();
180    },
181
182    checkGeocoding: function(){
183        var that = this;
184
185        if( this.zip && !this.zipCoords ){
186            var zip = this.zip.toLowerCase();
187			if(String.prototype.endsWith && !zip.endsWith('ga') && !zip.endsWith('georgia')) {
188				zip += ' GA';
189			}
190
191            this.geocoder.geocode(
192                { 'address': zip },
193                function(results, status){
194                    if( status == "OK" ){
195                        that.zipCoords = results[0].geometry.location.toJSON();
196                        that.filter();
197                    } else {
198                        if( status === "ZERO_RESULTS" ){
199                            //console.log('handling zero results');
200                            that.zipCoords = "none";
201                            that.filter();
202                        } else {
203                            console.log("geocoding error: " + status)
204                        }
205                    }
206                }
207            )
208        } else {
209            this.filter();
210        }
211    },
212
213    filter: function(){
214
215        if( this.zipCoords === "none" ){
216            this.locationsFiltered = [];
217        } else if( this.zipCoords || this.locationType.length > 0 ){
218            var locTemp = [];
219
220            if( this.zipCoords ){
221                // console.log('filtering by distance');
222            }
223
224            if( this.locationType.length > 0 ){
225                // console.log('filtering by location type');
226            }
227
228            for( var i = 0; i < this.locations.length; i++ ){
229                var err = 0;
230                var loc = this.locations[i];
231                var locLatLong = {
232                    lat: loc.acf.latitude,
233                    lng: loc.acf.longitude
234                }
235
236                // if individual location page check that we aren't including current location in results
237                if( this.locationId ){
238                    if( this.locationId == loc.ID ){
239                        err++;
240                    }
241                }
242
243                if( this.zipCoords ){
244                    var distanceCheck = distance(this.zipCoords, locLatLong);
245                    if( distanceCheck > this.distance ){
246                        err++;
247                    } else {
248                        loc.distance = distanceCheck;
249                    }
250                }
251
252                if( this.locationType.length > 0 && this.locationType.length < 3 ){
253                    var match = 0;
254
255                    for( var j = 0; j < this.locationType.length; j++ ){
256                        if( loc.location_type.indexOf(this.locationType[j]) !== -1 ){
257                            match++;
258                        }
259                    }
260
261                    if( match === 0 ){
262                        err++;
263                    }
264                }
265
266                if( err === 0 ){
267                    locTemp.push(this.locations[i]);
268                }
269            }
270
271            this.locationsFiltered = locTemp;
272        } else {
273            this.locationsFiltered = this.locations;
274        }
275
276        if( this.zipCoords ){
277            this.locationsFiltered.sort(function(a, b){
278                if( a.distance < b.distance ){
279                    return -1;
280                }
281
282                if( a.distance > b.distance ){
283                    return 1;
284                }
285
286                return 0;
287            });
288        }
289
290        this.build();
291    },
292
293
294
295    build: function(){
296        if( this.filterChange ){
297            this.page = 0;
298
299            $('.locations-grid').addClass('loading');
300        }
301
302        var start = this.page * this.resultsPerPage;
303        var end = (this.page * this.resultsPerPage) + this.resultsPerPage;
304
305        if( end >= this.locationsFiltered.length ){
306            end = this.locationsFiltered.length;
307            $('.locations-button-bar').removeClass('active');
308        } else {
309            $('.locations-button-bar').addClass('active');
310        }
311
312        var html = "";
313
314        if( this.locationsFiltered.length > 0 ){
315            for( var i = start; i < end; i++ ){
316                var loc = this.locationsFiltered[i];
317                html += '' +
318                    '<div class="col-12 col-md-6 col-lg-4">' +
319                        '<div class="location-panel">' +
320                            '<div class="title-banner">';
321
322
323                html += '<p><a class="store-name" href="/locations/' + loc.post_name + '/">' + loc.post_title + '</a>';
324
325                if( loc.distance ){
326                    var dist = Math.round( loc.distance * 10 ) /  10;
327                    html += '<span class="distance">(' + dist + ' miles away)</span>'
328                }
329
330                html += '<span class="tags">';
331
332                if( loc.location_type.indexOf('store') !== -1 ){
333                    html += '<i class="fa-regular fa-shop"></i>';
334                }
335
336                if( loc.location_type.indexOf('donation-center') !== -1 ){
337                    html += '<i class="fa-light fa-box-open-full"></i>';
338                }
339
340                if( loc.location_type.indexOf('career-center') !== -1 ){
341                    html += '<i class="fa-light fa-briefcase"></i>';
342                }
343
344                html += '</span></p></div>';
345
346                var address = loc.acf.address_line_1 + ", " + loc.acf.city + " " + loc.acf.state + " " + loc.acf.zip;
347                var addressEncoded = encodeURIComponent(address);
348
349                html += '<a href="https://www.google.com/maps/dir//' + addressEncoded + '" class="store-ad
349dress">' + address + '</a>';
350
351                var currentDay = new Date().getDay();
352
353                // console.log(loc.post_title + " : " + i);
354
355                var phoneDefault = loc.acf.phone_number;
356                var phoneDefaultStripped = phoneDefault.replaceAll("-", "");
357
358                // get store hours/phone
359                if( loc.location_type.indexOf('store') !== -1 ){
360
361                    var hoursTemp = loc.acf.store_hours;
362
363                    if( loc.acf.override_hours && hoursTemp ){
364                        hoursTemp = parseStoreHours(hoursTemp);
365                    } else {
366                        hoursTemp = Locations.defaults.hours.store;
367                    }
368
369                    html += '<p class="info-string">Store:<a href="tel:' + phoneDefaultStripped + '">' + phoneDefault + '</a><span>' + hoursTemp[currentDay] + '</span></p>';
370                }
371
372                // get career center hours/phone
373                if( loc.location_type.indexOf('career-center') !== -1 ){
374
375                    var hoursTemp = loc.acf.career_center_hours;
376
377                    if( loc.acf.override_hours && hoursTemp ){
378                        hoursTemp = parseStoreHours(hoursTemp);
379                    } else {
380                        hoursTemp = Locations.defaults.hours.cc;
381                    }
382
383                    var phoneTemp = loc.acf.career_center_phone_number || phoneDefault;
384                    var stripped = phoneTemp.replaceAll("-", "");
385
386                    html += '<p class="info-string">Career Center:<a href="tel:' + stripped + '">' + phoneTemp + '</a><span>' + hoursTemp[currentDay] + '</span></p>';
387                }
388
389                // get donation center hours/phone
390                if( loc.location_type.indexOf('donation-center') !== -1 ){
391
392                    var hoursTemp = null;
393                    var phoneTemp = null;
394
395
396                    // check if adc
397                    if( loc.location_type.length === 1 ){
398                        hoursTemp = loc.acf.adc_hours;
399
400                        if( loc.acf.override_hours && hoursTemp ){
401                            hoursTemp = parseStoreHours(hoursTemp);
402                        } else {
403                            hoursTemp = Locations.defaults.hours.dc;
404                        }
405
406                    } else {
407                        hoursTemp = loc.acf.store_hours;
408
409                        if( loc.acf.override_hours && hoursTemp ){
410                            hoursTemp = parseStoreHours(hoursTemp);
411                        } else {
412                            hoursTemp = Locations.defaults.hours.store;
413                        }
414                    }
415
416                    phoneTemp = loc.acf.donation_center_phone_number || phoneDefault;
417                    var stripped = phoneTemp.replaceAll("-", "");
418
419                    html += '<p class="info-string">Donation Center:<a href="tel:' + stripped + '">' + phoneTemp + '</a><span>' + hoursTemp[currentDay] + '</span></p>';
420
421
422                    if( loc.acf.home_pickup ){
423                        html += '<p class="instore-pickup"><a href="https://resupply.app.link/e/goodwillnorthgeorgia" target="_blank">Donation Pickups Available</a></p>';
424                    }
425                }
426
427
428
429
430                html += '<a href="/locations/' + loc.post_name + '/" class="btn btn-border">View Details</a>';
431
432                html +=  "</div></div>";
433            }
434        } else {
435            html = "<p><strong>No locations found!</strong></p>";
436        }
437
438        if( this.filterChange ){
439            this.container.empty();
440            this.filterChange = false;
441        }
442
443        if( !this.locationsOfType && !this.locationId ){
444            this.setMarkers();
445        }
446
447        if( this.locationId ){
448            $('.nearby-locations-grid').removeClass('loading');
449        } else {
450            $('.locations-grid').removeClass('loading');
451        }
452
453
454        this.container.append(html);
455    },
456
457
458    markerHandler: function(element){
459        that = Locations;
460
461        var lat_lng = new google.maps.LatLng(element.acf.latitude, element.acf.longitude);
462
463        var marker = new google.maps.Marker({
464            position: lat_lng,
465            title: element.post_title,
466            icon: '/wp-content/themes/voltron/img/locations-marker.png'
467        });
468
469        marker.setMap(that.map);
470        that.markers.push(marker);
471
472        google.maps.event.addListener(marker,"click",function(){
473            if (that.infoWindow) {
474                that.infoWindow.close();
475            }
476
477            if (that.locationId) {
478                address  = element.acf.address_line_1 + ', ';
479                if (element.acf.address_line_2) {
480                    address += element.acf.address_line_2 + ', ';
481                }
482                address += element.acf.city + ', ';
483                address += element.acf.state + ' ';
484                address += element.acf.zip;
485
486                that.infoWindow = new google.maps.InfoWindow({
487                    content: '<div class="locations-map-tooltip">' +
488                        '<a href="https://www.google.com/maps/dir//' + address + '/" target="_blank" class="locations-map-tooltip-name">' + element.post_title + '</a>' +
489                        element.acf.address_line_1 + '<br />' +
490                        element.acf.city + ', ' + element.acf.state + ' ' + element.acf.zip + '<br />' +
491                        element.acf.phone_number +
492                        '<a href="https://www.google.com/maps/dir//' + address + '/" target="_blank">Get Directions</a>' +
493                        '</div>'
494                });
495            } else {
496                that.infoWindow = new google.maps.InfoWindow({
497                    content: '<div class="locations-map-tooltip">' +
498                        '<a href="/location/' + element.post_name + '/" class="locations-map-tooltip-name">' + element.post_title + '</a>' +
499                        element.acf.address_line_1 + '<br />' +
500                        element.acf.city + ', ' + element.acf.state + ' ' + element.acf.zip + '<br />' +
501                        element.acf.phone_number +
502                        '<a href="/location/' + element.post_name + '/">View Details</a>' +
503                        '</div>'
504                });
505            }
506
507            that.infoWindow.open(that.map, marker);
508        });
509
510        if (that.locationId) {
511            that.map.setZoom(16);
512            that.map.setCenter(marker.getPosition());
513        }
514    },
515
516
517    setMarkers: function() {
518		that = this;
519		this.clearMarkers();
520        this.locationsFiltered.forEach(that.markerHandler);
521
522
523        if( !that.locationId ){
524            var bounds = new google.maps.LatLngBounds();
525            for( var i = 0; i < that.markers.length; i++ ){
526                bounds.extend(that.markers[i].position);
527            }
528
529            that.map.fitBounds(bounds);
530        }
531	},
532
533    clearMarkers: function() {
534		var that = this;
535		for (var i = 0; i < that.markers.length; i++ ) {
536			that.markers[i].setMap(null);
537		}
538		that.markers.length = 0;
539	},
540
541    loadMore: function(){
542        this.page++;
543        this.build();
544    },
545
546    setZip: function(zip, distance){
547        this.zip = zip;
548        this.distance = distance;
549        this.zipCoords = null;
550        this.filterChange = true;
551        this.checkGeocoding();
552    },
553
554    clearZip: function(){
555        this.zip = "";
556        this.distance = 25;
557        this.zipCoords = null;
558        this.filterChange = true;
559
560        for( var i = 0; i < this.locations.length; i++ ){
561            this.locations[i].distance = null;
562        }
563
564        this.checkGeocoding();
565    },
566
567    setLocationType: function(loc){
568        this.locationType = loc;
569        this.filterChange = true;
570        this.checkGeocoding();
571    },
572
573    loadDefaults: function(){
574        var s = $('.defaults .store-hours').text();
575        var cc = $('.defaults .cc-hours').text();
576        var dc = $('.defaults .dc-hours').text();
577
578        this.defaults.hours.store =  parseStoreHours(s.replaceAll("\n", ","));
579        this.defaults.hours.cc =  parseStoreHours(cc.replaceAll("\n", ","));
580        this.defaults.hours.dc =  parseStoreHours(dc.replaceAll("\n", ","));
581    }
582}
583
584function getParameterByName(name, url) {
585    if (!url) url = window.location.href;
586    name = name.replace(/[\[\]]/g, "\\$&");
587    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
588        results = regex.exec(url);
589    if (!results) return null;
590    if (!results[2]) return '';
591    return decodeURIComponent(results[2].replace(/\+/g, " "));
592}
593
594function distance(a, b)
595{
596    var lat1 = a.lat;
597    var lon1 = a.lng;
598
599    var lat2 = b.lat;
600    var lon2 = b.lng;
601
602    var theta = lon1 - lon2;
603    var dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
604    dist = Math.acos(dist);
605    dist = rad2deg(dist);
606    var miles = dist * 60 * 1.1515;
607    return miles;
608}
609
610function deg2rad(degrees){
611    var pi = Math.PI;
612    return degrees * (pi/180);
613}
614
615function rad2deg(radians){
616    var pi = Math.PI;
617    return radians * (180/pi);
618}
619
620function parseStoreHours(h){
621    var hoursNew = ["", "", "", "", "", "", ""];
622
623    // normalize text from text area fields
624    h = h.replaceAll("<strong>", "").replaceAll("</strong>", "").replaceAll("<br />\r\n", ",");
625
626    // check for "," at end and remove (this happens when there were extra newlines)
627    while( h[h.length-1] === "," ){
628        h = h.substring(h,h.length-1);
629    }
630
631
632    // split each line into its own string
633    var stringArray = h.split(",");
634
635    // loop through each entry to assign to new array
636    for( var i = 0; i < stringArray.length; i++ ){
637        var temp = stringArray[i].split(":");
638
639        var days = temp[0].replace(" ", "");
640
641        var hours = temp.slice(1).join(":");
642
643        // check if string applies to multiple days
644        if( days.indexOf("-") !== -1){
645            var dayArray = days.split("-");
646            var startDay = getDayIndex(dayArray[0]);
647            var endDay = getDayIndex(dayArray[1]);
648
649            var done = false;
650            var dex = startDay;
651
652            while( !done ){
653                hoursNew[dex] = hours;
654
655                if( dex === endDay ){
656                    done = true;
657                }
658
659                dex++;
660                if( dex === 7 ) dex = 0;
661            }
662
663
664        } else {
665            hoursNew[getDayIndex(days)] = hours;
666        }
667    }
668
669    // check for days that don't have hours defined. trim others
670    for( var i = 0; i < hoursNew.length; i++ ){
671        if( hoursNew[i] === "" ){
672            hoursNew[i] = "Closed";
673        } else {
674            hoursNew[i] = hoursNew[i].trim();
675        }
676    }
677
678    return hoursNew;
679}
680
681function getDayIndex(day){
682    var cDay = day.toLowerCase();
683
684    switch(cDay){
685        case "sun":
686        case "sunday":
687            return 0;
688        case "mon":
689        case "monday":
690            return 1;
691        case "tue":
692        case "tues":
693        case "tuesday":
694            return 2;
695        case "wed":
696        case "wednesday":
697            return 3;
698        case "thu":
699        case "thur":
700        case "thurs":
701        case "thursday":
702            return 4;
703        case "fri":
704        case "friday":
705            return 5;
706        case "sat":
707        case "saturday":
708            return 6;
709        default:
710            // console.log("day error:" + day);
711            return 0;
712    }
713}
714
715
716
717$(document).ready(function(){
718    if( $('#locations-app').length ){
719        Locations.init();
720    }
721
722    $('.load-more-locations').on('click', function(e){
723        e.preventDefault();
724        Locations.loadMore();
725    });
726
727    $('.apply-location-filter').on('click', function(e){
728        e.preventDefault();
729        var zip = $('input[name=location-zip]').val();
730        var distance = parseInt($('select[name=distance]').val());
731
732        if( zip && distance ){
733            Locations.setZip(zip, distance);
734        } else {
735            Locations.clearZip();
736        }
737
738    });
739
740    $('.clear-location-filter').on('click', function(e){
741        e.preventDefault();
742
743        var zip = $('input[name=location-zip]').val("");
744        var distance = $('select[name=distance]').val(25);
745
746        Locations.clearZip();
747    });
748
749    $('.location-type-filters input').on('change', function(e){
750        var locTypes = [];
751
752        $('.location-type-filters input').each(function(){
753            if( $(this).is(":checked") ){
754                locTypes.push($(this).val());
755            }
756        })
757
758        Locations.setLocationType(locTypes);
759    });
760});

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.