// lazyflat — Leaflet flat map // A single Leaflet map instance; re-initialised after every HTMX swap of // the Wohnungen body. Also flushes size when the view toggle flips from // list to map (Leaflet needs invalidateSize on a hidden-then-shown map). let mapInstance = null; const BERLIN_CENTER = [52.52, 13.405]; const BERLIN_ZOOM = 11; function initFlatsMap() { const el = document.getElementById("flats-map"); if (!el || typeof L === "undefined") return; if (mapInstance) { try { mapInstance.remove(); } catch (e) {} mapInstance = null; } mapInstance = L.map(el, { zoomControl: false, scrollWheelZoom: false, doubleClickZoom: false, boxZoom: false, touchZoom: false, keyboard: false, }).setView(BERLIN_CENTER, BERLIN_ZOOM); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: "© OpenStreetMap", maxZoom: 18, }).addTo(mapInstance); let data = []; try { data = JSON.parse(el.dataset.flats || "[]"); } catch (e) { console.warn("flats-map: bad JSON in data-flats", e); } const bounds = []; data.forEach((f) => { if (typeof f.lat !== "number" || typeof f.lng !== "number") return; const m = L.marker([f.lat, f.lng]).addTo(mapInstance); const rent = f.rent ? Math.round(f.rent) + " €" : ""; const rooms = f.rooms ? f.rooms + " Zi" : ""; const size = f.size ? Math.round(f.size) + " m²" : ""; const meta = [rooms, size, rent].filter(Boolean).join(" · "); const safeAddr = (f.address || "").replace(/${safeAddr}` + (meta ? `
${meta}` : "") + `
Zur Anzeige →`, ); bounds.push([f.lat, f.lng]); }); if (bounds.length === 1) { mapInstance.setView(bounds[0], 14); } else if (bounds.length > 1) { mapInstance.fitBounds(bounds, { padding: [30, 30] }); } } function flushMapSize() { if (mapInstance) { setTimeout(() => mapInstance.invalidateSize(), 50); } } function wireViewToggle() { document.querySelectorAll('input[name="view_mode"]').forEach((r) => { if (r.dataset.wired === "1") return; r.dataset.wired = "1"; r.addEventListener("change", (e) => { try { localStorage.setItem("lazyflat_view_mode", e.target.value); } catch (err) {} flushMapSize(); }); }); } function restoreView() { let stored = null; try { stored = localStorage.getItem("lazyflat_view_mode"); } catch (err) {} if (!stored) return; const el = document.querySelector( `input[name="view_mode"][value="${stored}"]`, ); if (el && !el.checked) { el.checked = true; flushMapSize(); } } function onReady() { initFlatsMap(); wireViewToggle(); restoreView(); } document.addEventListener("DOMContentLoaded", onReady); document.body && document.body.addEventListener("htmx:afterSwap", onReady);