diff --git a/static/app.js b/static/app.js index 0d62e2b..8ea1965 100644 --- a/static/app.js +++ b/static/app.js @@ -802,7 +802,7 @@ function updateHash() { } // Start where you left off: an explicit link (hash) wins, otherwise the last -// place you looked at (remembered across views), otherwise the default US map. +// place you looked at (remembered across views), otherwise the default world map. function restoreFromHash() { const loc = window.Thermograph.loadLastLocation(); if (!loc) return; diff --git a/static/calendar.js b/static/calendar.js index f16f391..aba08fd 100644 --- a/static/calendar.js +++ b/static/calendar.js @@ -135,8 +135,11 @@ let data = null; // last /api/v2/calendar response let metric = localStorage.getItem("thermograph:calMetric") || "tmax"; // tmax|tmin|feels|wind|gust|precip|dsr // Season/year filters: only months whose season AND year are checked are shown. -const SEASONS = [["winter", "Winter"], ["spring", "Spring"], ["summer", "Summer"], ["fall", "Fall"]]; +// Keys group months (Dec–Feb = "winter", etc.); in the southern hemisphere those +// same months are the opposite season, so only the display label flips (s[2]). +const SEASONS = [["winter", "Winter", "Summer"], ["spring", "Spring", "Fall"], ["summer", "Summer", "Winter"], ["fall", "Fall", "Spring"]]; const seasonOf = (m) => (m === 11 || m <= 1) ? "winter" : m <= 4 ? "spring" : m <= 7 ? "summer" : "fall"; +const seasonLabel = (s) => (selected && selected.lat < 0 ? s[2] : s[1]); let checkedSeasons = new Set(SEASONS.map((s) => s[0])); // persists across reloads let checkedYears = null; // reset to all available on each fetch @@ -264,7 +267,7 @@ let filterYears = []; // the year set behind the Years dropdown (for its summa function seasonSummaryText() { if (checkedSeasons.size === SEASONS.length) return "All seasons"; if (checkedSeasons.size === 0) return "None"; - return SEASONS.filter((s) => checkedSeasons.has(s[0])).map((s) => s[1]).join(", "); + return SEASONS.filter((s) => checkedSeasons.has(s[0])).map(seasonLabel).join(", "); } function yearSummaryText() { const n = checkedYears ? checkedYears.size : 0; @@ -335,7 +338,7 @@ function renderFilters() { // the span (the weather sets survive the rebuild — they're module state). seasonYearEl.innerHTML = filterDropdown("season", "Seasons", "season", - SEASONS.map((s) => [s[0], s[1], checkedSeasons.has(s[0])]), seasonSummaryText()) + + SEASONS.map((s) => [s[0], seasonLabel(s), checkedSeasons.has(s[0])]), seasonSummaryText()) + filterDropdown("year", "Years", "year", years.map((y) => [y, y, checkedYears.has(y)]), yearSummaryText()) + weatherDropdown(); diff --git a/static/mappicker.js b/static/mappicker.js index bea750a..75b2151 100644 --- a/static/mappicker.js +++ b/static/mappicker.js @@ -25,7 +25,7 @@ @@ -70,8 +70,7 @@ } function renderSug(list) { - const usca = list.filter((r) => ["US", "CA"].includes(r.country_code)); - const shown = usca.length ? usca : list; + const shown = list; sugEl.innerHTML = ""; if (!shown.length) { sugEl.hidden = true; return; } shown.forEach((r) => { @@ -117,7 +116,7 @@ overlay.hidden = false; if (!map) { - map = L.map(mapEl, { worldCopyJump: true, zoomControl: true }).setView([44.5, -95], 4); + map = L.map(mapEl, { worldCopyJump: true, zoomControl: true }).setView([25, 0], 2); // Colorful CARTO "Voyager" basemap (no key needed), split into two raster // layers so road weight and label size can be tuned independently: // • the label-free base is requested one zoom lower and drawn at 512px diff --git a/static/nav.js b/static/nav.js index e7f217d..7e5a9f1 100644 --- a/static/nav.js +++ b/static/nav.js @@ -3,7 +3,7 @@ // (map, calendar, day) before that page's own script. It remembers the most // recently selected spot in localStorage and keeps the header's view links // (Map · Calendar · Day) pointing at that spot — so switching views, or coming -// back to the map, lands you where you were instead of an empty US-wide map. +// back to the map, lands you where you were instead of an empty world map. const LOC_KEY = "thermograph:loc"; @@ -327,10 +327,13 @@ function prefetchNeighbors(lat, lon) { for (const di of [-1, 0, 1]) { for (const dj of [-1, 0, 1]) { if (!di && !dj) continue; + const nLat = centerLat + di * latStep; + if (Math.abs(nLat) > 90) continue; // no rows past the poles + const nLon = ((centerLon + dj * lonStep + 540) % 360) - 180; // wrap across the antimeridian const cellTag = `${i + di}_${j + dj}`; if (_warmedCells.has(cellTag)) continue; _warmedCells.add(cellTag); - const nq = `lat=${(centerLat + di * latStep).toFixed(5)}&lon=${(centerLon + dj * lonStep).toFixed(5)}`; + const nq = `lat=${nLat.toFixed(5)}&lon=${nLon.toFixed(5)}`; setTimeout(() => { fetch(`api/v2/cell?${nq}&prefetch=1`).catch(() => {}); }, 1500 + 1100 * k++); } }