// Inisialisasi Peta const map = L.map("map", { zoomControl: false }).setView( [-0.0263, 109.3425], 13, ); // ===== Toast Notification ===== window.showToast = function (message, type = "success", duration = 3500) { const icons = { success: "✅", error: "❌", info: "ℹ️", warning: "⚠️" }; const container = document.getElementById("toastContainer"); if (!container) return; const toast = document.createElement("div"); toast.className = `toast toast-${type}`; toast.innerHTML = `${icons[type] || "ℹ️"}${message}`; container.appendChild(toast); setTimeout(() => { toast.classList.add("hiding"); toast.addEventListener("animationend", () => toast.remove()); }, duration); }; // Custom Zoom Control Logic document.getElementById("zoomInBtn").addEventListener("click", function () { map.zoomIn(); }); document.getElementById("zoomOutBtn").addEventListener("click", function () { map.zoomOut(); }); // Base Map dari OpenStreetMap L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: '© OpenStreetMap contributors', }).addTo(map); // Inisialisasi FeatureGroups untuk masing-masing layer const parsilLayer = L.featureGroup().addTo(map); const searchInput = document.getElementById("searchInput"); const searchClear = document.getElementById("searchClear"); if (searchInput) { searchInput.addEventListener("focus", function () { if (typeof window.deactivateAddMode === "function") window.deactivateAddMode(); }); searchInput.addEventListener("input", function () { const val = this.value.toLowerCase(); if (val.length > 0) { searchClear.style.visibility = "visible"; window.showSearchResults(val); } else { searchClear.style.visibility = "hidden"; document.getElementById("searchResults").style.display = "none"; } }); } if (searchClear) { searchClear.addEventListener("click", function () { searchInput.value = ""; searchClear.style.visibility = "hidden"; document.getElementById("searchResults").style.display = "none"; searchInput.focus(); }); } window.showSearchResults = function (query) { const resultsContainer = document.getElementById("searchResults"); if (!resultsContainer) return; resultsContainer.innerHTML = ""; let results = []; if (typeof parsilLayer !== "undefined") { parsilLayer.eachLayer((layer) => { if ( layer.parsilData && layer.parsilData.nama && layer.parsilData.nama.toLowerCase().includes(query) ) { results.push({ type: "Parsil", nama: layer.parsilData.nama, layer: layer, }); } }); } if (results.length === 0) { resultsContainer.innerHTML = '
Tidak ada hasil
'; } else { results.forEach((res) => { const item = document.createElement("div"); item.style.padding = "10px 15px"; item.style.cursor = "pointer"; item.style.borderBottom = "1px solid #eee"; item.style.fontSize = "14px"; item.innerHTML = `${res.type}: ${res.nama}`; item.addEventListener( "mouseenter", () => (item.style.backgroundColor = "#f8f9fa"), ); item.addEventListener( "mouseleave", () => (item.style.backgroundColor = "white"), ); item.addEventListener("click", () => { if (res.layer instanceof L.Marker) { map.setView(res.layer.getLatLng(), 17); } else if (res.layer.getBounds) { map.fitBounds(res.layer.getBounds()); } res.layer.openPopup(); resultsContainer.style.display = "none"; }); resultsContainer.appendChild(item); }); } resultsContainer.style.display = "block"; }; // UI Logic: Custom Layer Control Toggle const layerBtn = document.getElementById("layerBtn"); const layerPanel = document.getElementById("layerPanel"); if (layerBtn && layerPanel) { layerBtn.addEventListener("click", function () { if (typeof window.deactivateAddMode === "function") window.deactivateAddMode(); layerPanel.style.display = layerPanel.style.display === "block" ? "none" : "block"; }); } // Sembunyikan layer panel saat klik di peta map.on("click", function () { if (layerPanel) layerPanel.style.display = "none"; }); // Logic untuk Toggle Layer Visibility const setupLayerToggle = (id, layer) => { const el = document.getElementById(id); if (el) { el.addEventListener("change", function (e) { e.target.checked ? map.addLayer(layer) : map.removeLayer(layer); }); } }; setupLayerToggle("layerParsil", parsilLayer); // --- Sub-layer Toggle (expand/collapse) --- window.toggleSubLayer = function (subId, iconEl) { const sub = document.getElementById(subId); if (!sub) return; const isHidden = sub.style.display === "none"; sub.style.display = isHidden ? "" : "none"; iconEl.classList.toggle("collapsed", !isHidden); }; // --- Sub-layer Filter --- window.applySubFilter = function (type) { if (type === "spbu") { const checked = [...document.querySelectorAll(".sub-spbu:checked")].map( (el) => el.value === "1", ); spbuLayer.eachLayer((layer) => { if (layer.spbuData === undefined) return; if (checked.includes(layer.spbuData.is_24_jam)) { layer.getElement && layer.getElement() && (layer.getElement().style.display = ""); } else { layer.getElement && layer.getElement() && (layer.getElement().style.display = "none"); } }); } else if (type === "jalan") { const checked = [...document.querySelectorAll(".sub-jalan:checked")].map( (el) => el.value, ); jalanLayer.eachLayer((layer) => { if (!layer.jalanData) return; if (checked.includes(layer.jalanData.status)) { layer.getElement && layer.getElement() && (layer.getElement().style.display = ""); } else { layer.getElement && layer.getElement() && (layer.getElement().style.display = "none"); } }); } else if (type === "parsil") { const checked = [...document.querySelectorAll(".sub-parsil:checked")].map( (el) => el.value, ); parsilLayer.eachLayer((layer) => { if (!layer.parsilData) return; if (checked.includes(layer.parsilData.status)) { layer.getElement && layer.getElement() && (layer.getElement().style.display = ""); } else { layer.getElement && layer.getElement() && (layer.getElement().style.display = "none"); } }); } }; // --- Modal Logic --- const unifiedModal = document.getElementById("unifiedModal"); const modalTitle = document.getElementById("modalTitle"); const modalBody = document.getElementById("modalBody"); window.openModal = function (title, bodyHTML, saveCallback) { if (!unifiedModal) return; modalTitle.textContent = title; modalBody.innerHTML = bodyHTML; unifiedModal.classList.add("show"); const currentSaveBtn = document.getElementById("modalSaveBtn"); if (currentSaveBtn) { const newSaveBtn = currentSaveBtn.cloneNode(true); currentSaveBtn.parentNode.replaceChild(newSaveBtn, currentSaveBtn); newSaveBtn.addEventListener("click", saveCallback); } }; window.closeModal = function () { if (unifiedModal) unifiedModal.classList.remove("show"); }; const confirmModal = document.getElementById("confirmModal"); const confirmMessage = document.getElementById("confirmMessage"); window.openConfirmModal = function (msg, confirmCallback) { if (!confirmModal) return; confirmMessage.textContent = msg; confirmModal.classList.add("show"); const currentYesBtn = document.getElementById("confirmYesBtn"); if (currentYesBtn) { const newYesBtn = currentYesBtn.cloneNode(true); currentYesBtn.parentNode.replaceChild(newYesBtn, currentYesBtn); newYesBtn.addEventListener("click", function () { confirmModal.classList.remove("show"); confirmCallback(); }); } }; window.closeConfirmModal = function () { if (confirmModal) confirmModal.classList.remove("show"); }; window.currentAddMode = null; // 'spbu', 'jalan', 'parsil' window.activateAddMode = function (mode) { if (window.currentAddMode === mode) { window.deactivateAddMode(); return; } window.currentAddMode = mode; document.getElementById("map").style.cursor = "crosshair"; }; window.deactivateAddMode = function () { window.currentAddMode = null; document.getElementById("map").style.cursor = ""; };