// Inisialisasi Peta // Koordinat awal: [-0.0263, 109.3425] (Pontianak) const map = L.map('map', { zoomControl: false }).setView([-0.0263, 109.3425], 13); // 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 spbuLayer = L.featureGroup().addTo(map); const jalanLayer = L.featureGroup().addTo(map); const parsilLayer = L.featureGroup().addTo(map); const rumahIbadahLayer = L.featureGroup().addTo(map); const pendudukMiskinLayer = L.featureGroup().addTo(map); const geoJsonLayer = L.featureGroup().addTo(map); const searchInput = document.getElementById('searchInput'); const searchClear = document.getElementById('searchClear'); 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'; } }); 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'); resultsContainer.innerHTML = ''; let results = []; if (typeof spbuLayer !== 'undefined') { spbuLayer.eachLayer(layer => { if (layer.spbuData && layer.spbuData.nama && layer.spbuData.nama.toLowerCase().includes(query)) { results.push({ type: 'SPBU', nama: layer.spbuData.nama, layer: layer }); } }); } if (typeof jalanLayer !== 'undefined') { jalanLayer.eachLayer(layer => { if (layer.jalanData && layer.jalanData.nama && layer.jalanData.nama.toLowerCase().includes(query)) { results.push({ type: 'Jalan', nama: layer.jalanData.nama, layer: layer }); } }); } 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 (typeof rumahIbadahLayer !== 'undefined') { rumahIbadahLayer.eachLayer(layer => { if (layer.ibadahData && layer.ibadahData.nama && layer.ibadahData.nama.toLowerCase().includes(query)) { if(layer instanceof L.Marker) { results.push({ type: 'Rumah Ibadah', nama: layer.ibadahData.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'); layerBtn.addEventListener('click', function() { layerPanel.style.display = layerPanel.style.display === 'block' ? 'none' : 'block'; }); // Sembunyikan layer panel saat klik di peta map.on('click', function() { layerPanel.style.display = 'none'; }); // Logic untuk Toggle Layer Visibility document.getElementById('layerSpbu').addEventListener('change', function(e) { e.target.checked ? map.addLayer(spbuLayer) : map.removeLayer(spbuLayer); }); document.getElementById('layerJalan').addEventListener('change', function(e) { e.target.checked ? map.addLayer(jalanLayer) : map.removeLayer(jalanLayer); }); document.getElementById('layerParsil').addEventListener('change', function(e) { e.target.checked ? map.addLayer(parsilLayer) : map.removeLayer(parsilLayer); }); document.getElementById('layerRumahIbadah').addEventListener('change', function(e) { e.target.checked ? map.addLayer(rumahIbadahLayer) : map.removeLayer(rumahIbadahLayer); }); document.getElementById('layerMiskin').addEventListener('change', function(e) { e.target.checked ? map.addLayer(pendudukMiskinLayer) : map.removeLayer(pendudukMiskinLayer); }); // --- 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); spbuLayer.eachLayer(layer => { if (!layer.spbuData) return; const val = layer.spbuData.is_24_jam ? '1' : '0'; if (checked.includes(val)) { if (!spbuLayer.hasLayer(layer)) spbuLayer.addLayer(layer); layer.getElement && layer.getElement() && (layer.getElement().style.display = ''); } else { layer.getElement && layer.getElement() && (layer.getElement().style.display = 'none'); } }); } if (type === 'jalan') { const checked = [...document.querySelectorAll('.sub-jalan:checked')].map(el => el.value); jalanLayer.eachLayer(layer => { if (!layer.jalanData) return; const visible = checked.includes(layer.jalanData.status); const display = visible ? '' : 'none'; // Sembunyikan garis polyline if (layer._path) layer._path.style.display = display; // Sembunyikan label teks (leaflet-textpath simpan di _textNode) if (layer._textNode) layer._textNode.style.display = display; }); } 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._path && (layer._path.style.display = ''); } else { layer._path && (layer._path.style.display = 'none'); } }); } if (type === 'miskin') { const checked = [...document.querySelectorAll('.sub-miskin:checked')].map(el => el.value); pendudukMiskinLayer.eachLayer(layer => { if (!layer.miskinData) return; if (checked.includes(layer.miskinData.kategori_bantuan)) { 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) { modalTitle.textContent = title; modalBody.innerHTML = bodyHTML; unifiedModal.classList.add('show'); // Ambil elemen tombol save terbaru dari DOM const currentSaveBtn = document.getElementById('modalSaveBtn'); // Clone untuk menghapus semua event listener lama const newSaveBtn = currentSaveBtn.cloneNode(true); currentSaveBtn.parentNode.replaceChild(newSaveBtn, currentSaveBtn); newSaveBtn.addEventListener('click', saveCallback); }; window.closeModal = function() { unifiedModal.classList.remove('show'); }; const confirmModal = document.getElementById('confirmModal'); const confirmMessage = document.getElementById('confirmMessage'); window.openConfirmModal = function(msg, confirmCallback) { confirmMessage.textContent = msg; confirmModal.classList.add('show'); const currentYesBtn = document.getElementById('confirmYesBtn'); const newYesBtn = currentYesBtn.cloneNode(true); currentYesBtn.parentNode.replaceChild(newYesBtn, currentYesBtn); newYesBtn.addEventListener('click', function() { confirmModal.classList.remove('show'); confirmCallback(); }); }; window.closeConfirmModal = function() { confirmModal.classList.remove('show'); }; // --- Action Menu Logic (replaced by left sidebar) --- window.currentAddMode = null; // 'spbu' atau 'rumah_ibadah' window.currentDrawMode = null; // 'polyline' atau 'polygon' window.activateAddMode = function(mode) { // Toggle: jika mode yang sama diklik lagi, batalkan if (window.currentAddMode === mode) { window.deactivateAddMode(); return; } // Reset draw mode if active if (window.activeDrawHandler) { window.activeDrawHandler.disable(); window.activeDrawHandler = null; } window.currentAddMode = mode; window.currentDrawMode = null; // Tooltip const tooltips = { 'spbu': 'Klik untuk Tambah SPBU', 'rumah_ibadah': 'Klik untuk Tambah Rumah Ibadah' }; if (window.cursorTooltip && tooltips[mode]) window.cursorTooltip.textContent = tooltips[mode]; // Ubah kursor map menjadi crosshair document.getElementById('map').style.cursor = 'crosshair'; }; window.deactivateAddMode = function() { window.currentAddMode = null; window.currentDrawMode = null; if (window.activeDrawHandler) { window.activeDrawHandler.disable(); window.activeDrawHandler = null; } document.getElementById('map').style.cursor = ''; if (window.cursorTooltip) window.cursorTooltip.style.display = 'none'; }; // --- Custom Tooltip Cursor --- window.cursorTooltip = document.createElement('div'); window.cursorTooltip.className = 'custom-cursor-tooltip'; document.body.appendChild(window.cursorTooltip); // Gunakan document-level mousemove agar selalu terpicu // bahkan saat Leaflet Draw overlay aktif menangkap event map document.addEventListener('mousemove', function(e) { if (window.currentAddMode || window.currentDrawMode) { window.cursorTooltip.style.display = 'block'; window.cursorTooltip.style.left = e.pageX + 15 + 'px'; window.cursorTooltip.style.top = e.pageY + 15 + 'px'; } else { window.cursorTooltip.style.display = 'none'; } });