81 lines
3.2 KiB
JavaScript
81 lines
3.2 KiB
JavaScript
// 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, 'Your location');
|
|
}, function () {
|
|
if (callbacks.onError) callbacks.onError();
|
|
}, { timeout: 8000 });
|
|
}
|
|
|
|
window.VindnLocation = {
|
|
load: load,
|
|
save: save,
|
|
clear: clear,
|
|
searchPlace: searchPlace,
|
|
useMyLocation: useMyLocation
|
|
};
|
|
})(window);
|