PageSourceSearch

https://www.galpinlincoln.com/content/plugins/jzl-core/core/visito…/js/geolocation3.js?ver=20231208-0000

js galpinlincoln.com collected 2026-10-08 06:33:20 UTC 14,317 bytes, 370 lines download raw bytes

1(function() {
2
3    // See readme.md
4
5    var settings = window['geolocation3_settings'];
6    // geolocationEndpoint - endpoint we get geolocation
7    // version - VERSION that is passed in. If this does not match saved value then
8    //           it is treated as though the value does not exist.
9
10    var LOCALSTORAGE_PREFIX = 'jzl-geolocation3-';
11    function saveLocalStorage( obj, expiresInDays ) {
12
13        var json = JSON.stringify(obj);
14        window.localStorage.setItem( LOCALSTORAGE_PREFIX + 'data', json );
15        window.localStorage.setItem( LOCALSTORAGE_PREFIX + 'version', settings.version );
16
17        var now = (new Date()).getTime();
18        var expires = now + 24 * 60 * 60 * 1000 * expiresInDays;
19        window.localStorage.setItem( LOCALSTORAGE_PREFIX + 'expiration', String(expires) );
20
21    }
22
23    function loadLocalStorage() {
24
25        if( window.localStorage.getItem(LOCALSTORAGE_PREFIX + 'version') !== settings.version ){
26            return null;
27        }
28        var expires = window.localStorage.getItem( LOCALSTORAGE_PREFIX + 'expiration' );
29        if( expires == null ) {
30            return null;
31        }
32        expires = parseInt( expires, 10 );
33        var now = (new Date()).getTime();
34        if( now > expires ) {
35            return null;
36        }
37
38        var json = window.localStorage.getItem( LOCALSTORAGE_PREFIX + 'data' );
39        if( json == null ) {
40            return null;
41        }
42        var obj;
43        try {
44            obj = JSON.parse(json);
45        } catch( ex ) {
46            obj = null;
47        }
48        return obj;
49
50    }
51
52    var _currentData = null; // current in-memory copy
53
54    function saveGeolocation( updatedData ) {
55        if( updatedData !== _currentData ) {
56            _currentData = updatedData;
57            var expiresInDays = 7;
58            console.log( 'Saving', updatedData, 'to localstorage for', expiresInDays, 'days' );
59            saveLocalStorage( updatedData, expiresInDays );
60        }
61    }
62    function loadGeolocation() {
63        var data = loadLocalStorage();
64        // copy over just the fields we care about
65        data = data != null ? {
66            latlng: {
67                lat: (data.latlng != null && data.latlng.lat != null ) ? data.latlng.lat : null,
68                lng: (data.latlng != null && data.latlng.lng != null ) ? data.latlng.lng : null,
69            },
70            countryName: data.countryName != null ? data.countryName : null,
71            countryNameShort: data.countryNameShort != null ? data.countryNameShort : null,
72            postalCode: data.postalCode != null ? data.postalCode : null,
73            state: data.state != null ? data.state : null,
74            stateShort: data.stateShort != null ? data.stateShort : null,
75            city: data.city != null ? data.city : null,
76            nearestRooftop: data.nearestRooftop != null ? data.nearestRooftop : null,
77            nearestRooftopsByDrivetime: data.nearestRooftopsByDrivetime != null ? data.nearestRooftopsByDrivetime : null,
78            overrideType: data.overrideType != null ? data.overrideType : null,
79            timestamp: data.timestamp != null ? data.timestamp : null,
80        } : null;
81        _currentData = data;
82        return data;
83    }
84
85    var _currentGeolocation = undefined;
86    var _currentGeolocationResolve = undefined;
87    var _currentGeolocationResolved = false;
88    var _currentGeolocationWaiting = new Promise(function(resolve) {
89        _currentGeolocationResolve = resolve;
90    });
91
92    function getCurrentGeolocation() {
93        return _currentGeolocationWaiting
94            .then(function() {
95                return _currentGeolocation;
96            });
97    }
98    function setCurrentGeolocation(data) {
99        data = data != null ? data : {};
100        _currentGeolocation = data;
101        if(!_currentGeolocationResolved) {
102            _currentGeolocationResolved = true;
103            _currentGeolocationResolve();
104        }
105    }
106
107    function cloneJsObject(obj) {
108        return JSON.parse( JSON.stringify(obj) );
109    }
110
111    function dispatchEvent( obj, initialLoad, changed ) {
112        // This used to be called jzl_set_zip_code
113        console.log( 'Dispatching jzl_set_geolocation event', _currentData, initialLoad ? '[INITIAL]' : '' );
114        var customEvent = new CustomEvent('jzl_set_geolocation', {
115            detail: {
116                geolocationData: obj != null ? cloneJsObject( obj ) : {},
117                initialLoad: initialLoad,
118                changed: changed != null ? changed : {},
119            },
120        });
121        window.dispatchEvent(customEvent);
122    }
123
124    function getPostalCodeAndNearestRooftopId(geolocationData) {
125        var postalCode = geolocationData != null ? geolocationData.postalCode : null;
126        var isRooftopInfoAvailable = geolocationData != null &&
127            geolocationData.nearestRooftop != null &&
128            geolocationData.nearestRooftop.storeInfo != null;
129        var nearestRooftopId = isRooftopInfoAvailable ?
130            geolocationData.nearestRooftop.storeInfo.Id : null;
131
132        return { postalCode: postalCode, nearestRooftopId: nearestRooftopId };
133    }
134
135    function doGeolocationPostalCode(countryName, postalCode) {
136
137        var promise = new Promise(function(resolve, reject) {
138            if( countryName == null || countryName === '' ) {
139                reject('MISSING_COUNTRY_NAME');
140                return;
141            }
142            if( postalCode == null || postalCode === '' ) {
143                reject('MISSING_POSTAL_CODE');
144                return;
145            }
146
147            getCurrentGeolocation()
148                .then(function(currentData) {
149                    var postalCodeAndNearestRooftopID = getPostalCodeAndNearestRooftopId(currentData);
150                    var params = {
151                        currentPostalCode: postalCodeAndNearestRooftopID.postalCode,
152                        currentNearestRooftopId: postalCodeAndNearestRooftopID.nearestRooftopId,
153                        countryName: countryName,
154                        postalCode: postalCode,
155                        overrideType: 'country+postal_code',
156                    };
157
158                    resolve(params);
159                });
160        });
161
162        return promise
163            .then(function(params) {
164                return applyGeolocation(params);
165            });
166    }
167
168    function doGeolocationBrowserLatLng() {
169
170        var promise = new Promise(function(resolve, reject) {
171            if (!("geolocation" in window.navigator)) {
172                reject('NOT_AVAILABLE');
173                return;
174            }
175            getCurrentGeolocation()
176                .then(function(currentData) {
177                    var timeoutId = setTimeout(function() {
178                        reject('TIMEOUT');
179                    }, 10000);
180
181                    window.navigator
182                        .geolocation
183                        .getCurrentPosition(function(position) {
184                            clearTimeout(timeoutId);
185
186                            var postalCodeAndNearestRooftopID = getPostalCodeAndNearestRooftopId(currentData);
187                            var params = {
188                                currentPostalCode: postalCodeAndNearestRooftopID.postalCode,
189                                currentNearestRooftopId: postalCodeAndNearestRooftopID.nearestRooftopId,
190                                latlng: {
191                                    lat: position.coords.latitude,
192                                    lng: position.coords.longitude,
193                                },
194                                overrideType: 'latlng',
195                            };
196
197                            resolve(params);
198                        }, function(error) {
199                            console.log('Error from geolocation', error);
200                            reject('GEOLOCATION_ERROR');
201                        });
202                });
203        });
204
205        return promise
206            .then(function(params) {
207                return applyGeolocation(params);
208            });
209
210    }
211
212    function applyGeolocation( params, initialLoad ) {
213        return doGeolocation( params )
214            .then(function( result ) {
215                var updatedData = result.geolocationData;
216                var changed = result.changed;
217                saveGeolocation( updatedData );
218                setCurrentGeolocation( updatedData );
219                dispatchEvent( updatedData, initialLoad, changed );
220            });
221    }
222
223    function checkRefresh( currentData ) {
224
225        var now = (new Date()).getTime();
226
227        // Localstorage and its overrides are valid for 7 days, but
228        // we will refresh the data from the server if it is more than 6 hours old.
229        var age = now - currentData.timestamp;
230        var maxHours = 6;
231        if( age > maxHours * 60 * 60 * 1000 ) {
232            console.log( 'timestamp older than ' + maxHours + ' hours, refreshing all.' );
233            return true;
234        }
235
236        console.log( 'current data not expired, using as is.' );
237        return false;
238
239    }
240
241    jazelReady(function() {
242
243        var params = null;
244
245        // When the page loads, first try the cookie to see if we have
246        // anything.
247        var currentData = loadGeolocation();
248
249        // If we are going to be forced to apply an override zip code
250        if( settings.overridePostalCode != null ) {
251            if( currentData == null || currentData.overrideType == null ) {
252                params = {
253                    countryName: 'United States',
254                    postalCode: settings.overridePostalCode,
255                    overrideType: 'country+postal_code',
256                };
257                if( currentData != null ) {
258                    var postalCodeAndNearestRooftopID = getPostalCodeAndNearestRooftopId(currentData);
259                    params.currentPostalCode = postalCodeAndNearestRooftopID.postalCode;
260                    params.currentNearestRooftopId = postalCodeAndNearestRooftopID.nearestRooftopId;
261                }
262            }
263        }
264
265        if( params == null ) {
266            if( currentData != null ) {
267                console.log("previously saved GeoLocation", currentData);
268                var postalCodeAndNearestRooftopID = getPostalCodeAndNearestRooftopId(currentData);
269
270                params = {
271                    currentPostalCode: postalCodeAndNearestRooftopID.postalCode,
272                    currentNearestRooftopId: postalCodeAndNearestRooftopID.nearestRooftopId,
273                    currentData: currentData,
274                    needRefresh: checkRefresh( currentData ),
275                };
276
277            } else {
278                console.log("no previously saved GeoLocation");
279                // and we try to detect it based on CF/IP-proxy
280            }
281        }
282
283        applyGeolocation( params, true )
284            .catch(function() {
285                // If this fails, then notify everyone of it anyway
286                setCurrentGeolocation( currentData );
287                dispatchEvent( currentData, true, null );
288            });
289
290    });
291
292    function doGeolocation( params ) {
293        if (params == null) {
294            params = {};
295        }
296        return new Promise(function(resolve, reject) {
297            var currentData = params.currentData;
298            if( currentData != null ) {
299                if( !params.needRefresh ) {
300                    resolve({geolocationData: currentData, changed: null});
301                    return;
302                }
303                params.overrideType = currentData.overrideType;
304                if( currentData.overrideType === 'country+postal_code' ) {
305                    params.postalCode = currentData.postalCode;
306                    params.countryName = currentData.countryName;
307                } else if( currentData.overrideType === 'latlng' ) {
308                    params.latlng = {
309                        lat: currentData.latlng.lat,
310                        lng: currentData.latlng.lng,
311                    };
312                }
313            }
314
315            setTimeout(function() {
316                reject('TIMEOUT');
317            }, 15000);
318            var endpoint = settings.geolocationEndpoint;
319            jQuery
320                .post(endpoint, {
321                    params: JSON.stringify( params ),
322                })
323                .done(function(result) {
324                    if( result.error ) {
325                        reject( result.message );
326                        return;
327                    }
328                    var geolocationData = result.geolocationData;
329                    geolocationData.timestamp = (new Date()).getTime();
330                    var changed = result.changed;
331                    resolve({geolocationData: geolocationData, changed: changed});
332                })
333                .fail(function( jqxhr, textStatus, error ) {
334                    reject('AJAX_ERROR');
335                });
336        });
337    }
338
339    var errorMessages = {
340        'TIMEOUT': 'Connection timed out. Try again later.',
341        'AJAX_ERROR': 'Something went wrong with the Ajax connection.  Try again later.',
342        'NOT_AVAILABLE': 'Geolocation not available in this browser.',
343        'GEOLOCATION_ERROR': 'Browser did not provide Geolocation data.',
344        'MISSING_COUNTRY_NAME': 'Country name must be provided.',
345        'MISSING_POSTAL_CODE': 'Zip Code must be provided.',
346        'UNKNOWN_COUNTRY_NAME': 'Provided Country name is unknown.',
347        'UNKNOWN_POSTAL_CODE': 'Provided Zip Code is unknown.',
348        'MISSING_LATLNG': 'Latitude/Longitude must be provided.',
349        'MISSING_LATITUDE': 'Latitude must be provided.',
350        'MISSING_LONGITUDE': 'Longitude must be provided.',
351        'REV_GEOCODE_FAILED': 'Your location could not be resolved to a supported address.',
352        'DEFAULT_GEOCODE_FAILED': 'Your location could not be detected.',
353    };
354
355    function getErrorMessageText( key ) {
356        var msg = errorMessages[key];
357        if( msg == null ) {
358            msg = 'Unknown error.';
359        }
360        return msg;
361    }
362
363    window.geolocation3 = {
364        getCurrentGeolocation: getCurrentGeolocation,
365        doGeolocationPostalCode: doGeolocationPostalCode,
366        doGeolocationBrowserLatLng: doGeolocationBrowserLatLng,
367        getErrorMessageText: getErrorMessageText,
368    };
369
370})();

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.