document.addEventListener('DOMContentLoaded', function() { function geocode(query, callback) { fetch('/geocode?format=json&q=' + encodeURIComponent(query)) .then(response => response.json()) .then(data => { if (data && data.length > 0) { callback(data[0]); } else { callback(null); } }); } function setInputToCurrentLocation(inputId) { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { var lat = position.coords.latitude; var lon = position.coords.longitude; fetch(`/reverse?format=json&lat=${lat}&lon=${lon}`) .then(response => response.json()) .then(data => { document.getElementById(inputId).value = data.display_name || `${lat},${lon}`; document.getElementById(inputId).dataset.lat = lat; document.getElementById(inputId).dataset.lon = lon; }); }); } } function formatAddress(item) { if (!item.address) return item.display_name; const addr = item.address; let street = addr.road || addr.pedestrian || addr.cycleway || addr.footway || addr.street || ''; let number = addr.house_number || ''; let postcode = addr.postcode || ''; let city = addr.city || addr.town || addr.village || addr.hamlet || addr.municipality || addr.county || ''; // Build formatted string: Street Number, Postal code City let address = ''; if (street) address += street; if (number) address += (address ? ' ' : '') + number; if (postcode || city) { address += (address ? ', ' : ''); address += postcode; if (postcode && city) address += ' '; address += city; } return address; } function showSuggestions(inputId, suggestionsId, value) { var suggestionsBox = document.getElementById(suggestionsId); if (!value) { suggestionsBox.innerHTML = ''; suggestionsBox.style.display = 'none'; return; } fetch('/geocode?format=json&addressdetails=1&q=' + encodeURIComponent(value)) .then(response => response.json()) .then(data => { suggestionsBox.innerHTML = ''; if (data && data.length > 0) { data.slice(0, 5).forEach(function(item) { var option = document.createElement('button'); option.type = 'button'; option.className = 'list-group-item list-group-item-action'; option.textContent = formatAddress(item); option.title = item.display_name; // Show full address on hover option.onclick = function() { var input = document.getElementById(inputId); input.value = formatAddress(item); input.dataset.lat = item.lat; input.dataset.lon = item.lon; suggestionsBox.innerHTML = ''; suggestionsBox.style.display = 'none'; }; suggestionsBox.appendChild(option); }); suggestionsBox.style.display = 'block'; } else { suggestionsBox.style.display = 'none'; } }); } // Debounce helper function debounce(fn, delay) { let timer = null; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } function handleInput(e) { var val = e.target.value; if (val) { geocode(val, function(result) { if (result) { e.target.dataset.lat = result.lat; e.target.dataset.lon = result.lon; } else { delete e.target.dataset.lat; delete e.target.dataset.lon; } }); } else { delete e.target.dataset.lat; delete e.target.dataset.lon; } } document.getElementById('sourceInput').addEventListener('input', debounce(function(e) { showSuggestions('sourceInput', 'sourceSuggestions', e.target.value); }, 400)); document.getElementById('destInput').addEventListener('input', debounce(function(e) { showSuggestions('destInput', 'destSuggestions', e.target.value); }, 400)); // Hide suggestions when input loses focus (with a slight delay for click) document.getElementById('sourceInput').addEventListener('blur', function() { setTimeout(() => { document.getElementById('sourceSuggestions').style.display = 'none'; }, 200); }); document.getElementById('destInput').addEventListener('blur', function() { setTimeout(() => { document.getElementById('destSuggestions').style.display = 'none'; }, 200); }); document.getElementById('useCurrentSource').onclick = function() { setInputToCurrentLocation('sourceInput'); }; document.getElementById('useCurrentDest').onclick = function() { setInputToCurrentLocation('destInput'); }; document.getElementById('sourceInput').addEventListener('blur', function(e) { var val = e.target.value; if (val && !e.target.dataset.lat) { geocode(val, function(result) { if (result) { e.target.dataset.lat = result.lat; e.target.dataset.lon = result.lon; } }); } }); document.getElementById('destInput').addEventListener('blur', function(e) { var val = e.target.value; if (val && !e.target.dataset.lat) { geocode(val, function(result) { if (result) { e.target.dataset.lat = result.lat; e.target.dataset.lon = result.lon; } }); } }); });