// Single source of truth for "where is the user" across the home hero map, // /map, and Browse Events' location filter — storage, place search, and // GPS lookup used to be copy-pasted across all three, which is exactly how // one of them (a Nominatim result not being saved) silently drifted out of // sync with the other two. Each page still owns what happens once a // location resolves (recenter a map vs. navigate to a new URL) — that part // genuinely differs per page — but the operations themselves live here once. (function (window) { var LAST_LOCATION_KEY = 'vindn:lastLocation'; function load() { try { var raw = window.localStorage && localStorage.getItem(LAST_LOCATION_KEY); if (!raw) return null; var parsed = JSON.parse(raw); if (typeof parsed.lat === 'number' && typeof parsed.lon === 'number' && isFinite(parsed.lat) && isFinite(parsed.lon)) { return parsed; } } catch (e) { /* localStorage disabled/unavailable, or corrupt value — just skip it */ } return null; } function save(lat, lon, name) { try { if (window.localStorage) localStorage.setItem(LAST_LOCATION_KEY, JSON.stringify({ lat: lat, lon: lon, name: name || null })); } catch (e) { /* localStorage disabled/unavailable — nothing to persist to */ } } function clear() { try { if (window.localStorage) localStorage.removeItem(LAST_LOCATION_KEY); } catch (e) { /* localStorage disabled/unavailable */ } } // Nominatim: explicit submit only, never as-you-type — required by its // usage policy (max ~1 req/s, no autocomplete-style querying). Every // "search a place" form on the site should call this instead of its own // fetch, so they all behave identically (and a fix here fixes all three). function searchPlace(query, callbacks) { callbacks = callbacks || {}; if (callbacks.onStart) callbacks.onStart(query); fetch('https://nominatim.openstreetmap.org/search?format=json&limit=1&q=' + encodeURIComponent(query)) .then(function (res) { return res.json(); }) .then(function (results) { if (!results || !results.length) { if (callbacks.onNotFound) callbacks.onNotFound(query); return; } if (callbacks.onFound) callbacks.onFound(parseFloat(results[0].lat), parseFloat(results[0].lon), results[0].display_name); }) .catch(function () { if (callbacks.onError) callbacks.onError(); }); } // "Use my location" — shared so every page reports the same fixed label // for a GPS-derived point (no reverse geocoding happens) and the same // error/unsupported messaging. function useMyLocation(callbacks) { callbacks = callbacks || {}; if (!navigator.geolocation) { if (callbacks.onUnsupported) callbacks.onUnsupported(); return; } if (callbacks.onStart) callbacks.onStart(); navigator.geolocation.getCurrentPosition(function (pos) { if (callbacks.onFound) callbacks.onFound(pos.coords.latitude, pos.coords.longitude, window.VindnI18n.t('location.yours')); }, function () { if (callbacks.onError) callbacks.onError(); }, { timeout: 8000 }); } window.VindnLocation = { load: load, save: save, clear: clear, searchPlace: searchPlace, useMyLocation: useMyLocation }; })(window);