(function () { 'use strict'; var label = document.getElementById('weather-label'); var results = document.getElementById('weather-location-results'); var latitude = document.getElementById('weather-latitude'); var longitude = document.getElementById('weather-longitude'); var latitudeValue = document.getElementById('weather-latitude-value'); var longitudeValue = document.getElementById('weather-longitude-value'); var timezone = document.getElementById('weather-timezone'); var manualCoordinates = document.getElementById('weather-manual-coordinates'); var timer; var requestId = 0; if (!label || !results || !latitude || !longitude || !timezone) { return; } function clearResults() { results.replaceChildren(); results.classList.add('d-none'); } function selectResult(result) { label.value = result.label; latitude.value = result.latitude; longitude.value = result.longitude; timezone.value = result.timezone; latitudeValue.value = result.latitude; longitudeValue.value = result.longitude; latitude.disabled = true; longitude.disabled = true; latitude.removeAttribute('name'); longitude.removeAttribute('name'); latitudeValue.name = 'latitude'; longitudeValue.name = 'longitude'; manualCoordinates.classList.remove('d-none'); clearResults(); } function enableManualCoordinates() { latitude.disabled = false; longitude.disabled = false; latitude.name = 'latitude'; longitude.name = 'longitude'; latitudeValue.removeAttribute('name'); longitudeValue.removeAttribute('name'); manualCoordinates.classList.add('d-none'); } function renderResults(items) { results.replaceChildren(); if (!items.length) { clearResults(); return; } items.forEach(function (item) { var button = document.createElement('button'); button.type = 'button'; button.className = 'list-group-item list-group-item-action'; button.textContent = item.label; button.addEventListener('click', function () { selectResult(item); }); results.appendChild(button); }); results.classList.remove('d-none'); } label.addEventListener('input', function () { enableManualCoordinates(); window.clearTimeout(timer); var query = label.value.trim(); if (query.length < 2) { clearResults(); return; } timer = window.setTimeout(function () { var currentRequestId = ++requestId; fetch('/data-sources/weather/geocode?q=' + encodeURIComponent(query), { credentials: 'same-origin' }) .then(function (response) { if (!response.ok) throw new Error('Lookup failed'); return response.json(); }) .then(function (data) { if (currentRequestId === requestId) renderResults(data.results || []); }) .catch(function () { if (currentRequestId === requestId) clearResults(); }); }, 300); }); manualCoordinates.addEventListener('click', enableManualCoordinates); if (latitude.value && longitude.value) { selectResult({ label: label.value, latitude: latitude.value, longitude: longitude.value, timezone: timezone.value }); } var refreshButton = document.querySelector('[data-weather-refresh-url]'); if (refreshButton) { refreshButton.addEventListener('click', function () { refreshButton.disabled = true; fetch(refreshButton.getAttribute('data-weather-refresh-url'), { method: 'POST', credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(function (response) { if (!response.ok) throw new Error('Refresh failed'); window.location.assign(response.url); }) .catch(function () { refreshButton.disabled = false; }); }); } var forecastButtons = document.querySelectorAll('[data-weather-forecast-mode]'); var dailyForecast = document.getElementById('weather-daily-forecast'); var hourlyForecast = document.getElementById('weather-hourly-forecast'); forecastButtons.forEach(function (button) { button.addEventListener('click', function () { var hourly = button.getAttribute('data-weather-forecast-mode') === 'hourly'; dailyForecast.classList.toggle('d-none', hourly); hourlyForecast.classList.toggle('d-none', !hourly); forecastButtons.forEach(function (item) { var selected = item === button; item.classList.toggle('btn-primary', selected); item.classList.toggle('btn-outline-secondary', !selected); item.setAttribute('aria-pressed', selected ? 'true' : 'false'); }); }); }); document.addEventListener('click', function (event) { if (!results.contains(event.target) && event.target !== label) { clearResults(); } }); }());