document.addEventListener('DOMContentLoaded', function() { function geocode(query, callback) { fetch('https://nominatim.openstreetmap.org/search?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(`https://nominatim.openstreetmap.org/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 showSuggestions(inputId, suggestionsId, value) { var suggestionsBox = document.getElementById(suggestionsId); if (!value) { suggestionsBox.innerHTML = ''; suggestionsBox.style.display = 'none'; return; } fetch('https://nominatim.openstreetmap.org/search?format=json&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 = item.display_name; option.onclick = function() { var input = document.getElementById(inputId); input.value = item.display_name; 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; } }); } }); });