This commit is contained in:
envicy
2026-06-11 22:29:16 +07:00
parent 503e9421a9
commit ce26f9fac6
15 changed files with 1933 additions and 2015 deletions
+81 -99
View File
@@ -1,5 +1,8 @@
// ============================================================
// WebGIS Kemiskinan Pontianak — map.js (Redesign)
// ============================================================
// Inisialisasi Peta
// Koordinat awal: [-0.0263, 109.3425] (Pontianak)
const map = L.map('map', { zoomControl: false }).setView([-0.0263, 109.3425], 13);
// ===== Toast Notification =====
@@ -7,86 +10,94 @@ 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 = `<span class="toast-icon">${icons[type] || '️'}</span><span>${message}</span>`;
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(); });
// ===== Zoom Controls =====
document.getElementById('zoomInBtn').addEventListener('click', () => map.zoomIn());
document.getElementById('zoomOutBtn').addEventListener('click', () => map.zoomOut());
// Base Map dari OpenStreetMap
// ===== Base Map =====
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
// Inisialisasi FeatureGroups untuk masing-masing layer
const rumahIbadahLayer = L.featureGroup().addTo(map);
// ===== Feature Groups =====
const rumahIbadahLayer = L.featureGroup().addTo(map);
const pendudukMiskinLayer = L.featureGroup().addTo(map);
const geoJsonLayer = L.featureGroup().addTo(map);
const geoJsonLayer = L.featureGroup().addTo(map);
// ===== Sidebar Collapse =====
const collapseBtn = document.getElementById('sidebarCollapseBtn');
const collapseIcon = document.getElementById('collapseIcon');
if (collapseBtn) {
collapseBtn.addEventListener('click', function() {
const collapsed = document.body.classList.toggle('sidebar-collapsed');
if (collapseIcon) collapseIcon.className = collapsed ? 'fas fa-chevron-right' : 'fas fa-chevron-left';
setTimeout(() => map.invalidateSize(), 320);
});
}
// ===== Search =====
const searchInput = document.getElementById('searchInput');
const searchClear = document.getElementById('searchClear');
const searchResultsEl = document.getElementById('searchResults');
searchInput.addEventListener('focus', function() {
searchInput.addEventListener('focus', () => {
if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode();
});
searchInput.addEventListener('input', function() {
const val = this.value.toLowerCase();
const val = this.value.toLowerCase().trim();
if (val.length > 0) {
searchClear.style.visibility = 'visible';
window.showSearchResults(val);
} else {
searchClear.style.visibility = 'hidden';
document.getElementById('searchResults').style.display = 'none';
searchResultsEl.style.display = 'none';
}
});
searchClear.addEventListener('click', function() {
searchInput.value = '';
searchClear.style.visibility = 'hidden';
document.getElementById('searchResults').style.display = 'none';
searchResultsEl.style.display = 'none';
searchInput.focus();
});
window.showSearchResults = function(query) {
const resultsContainer = document.getElementById('searchResults');
resultsContainer.innerHTML = '';
let results = [];
document.addEventListener('click', function(e) {
if (!e.target.closest('.search-bar') && !e.target.closest('#searchResults')) {
searchResultsEl.style.display = 'none';
}
});
window.showSearchResults = function(query) {
searchResultsEl.innerHTML = '';
let results = [];
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 (layer.ibadahData?.nama?.toLowerCase().includes(query) && layer instanceof L.Marker) {
results.push({ type: 'Rumah Ibadah', icon: '🕌', nama: layer.ibadahData.nama, layer });
}
});
}
if (results.length === 0) {
resultsContainer.innerHTML = '<div style="padding: 10px 15px; color: #666; font-size: 14px;">Tidak ada hasil</div>';
searchResultsEl.innerHTML = '<div class="search-result-item" style="color:#94a3b8;">Tidak ada hasil ditemukan</div>';
} 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 = `<strong>${res.type}:</strong> ${res.nama}`;
item.addEventListener('mouseenter', () => item.style.backgroundColor = '#f8f9fa');
item.addEventListener('mouseleave', () => item.style.backgroundColor = 'white');
item.className = 'search-result-item';
item.innerHTML = `<span>${res.icon}</span><span><strong style="font-size:10px; color:#94a3b8; text-transform:uppercase;">${res.type}</strong><br>${res.nama}</span>`;
item.addEventListener('click', () => {
if (res.layer instanceof L.Marker) {
map.setView(res.layer.getLatLng(), 17);
@@ -94,38 +105,40 @@ window.showSearchResults = function(query) {
map.fitBounds(res.layer.getBounds());
}
res.layer.openPopup();
resultsContainer.style.display = 'none';
searchResultsEl.style.display = 'none';
searchInput.value = res.nama;
searchClear.style.visibility = 'visible';
});
resultsContainer.appendChild(item);
searchResultsEl.appendChild(item);
});
}
resultsContainer.style.display = 'block';
searchResultsEl.style.display = 'block';
};
// UI Logic: Custom Layer Control Toggle
// ===== Layer Panel Toggle =====
const layerBtn = document.getElementById('layerBtn');
const layerPanel = document.getElementById('layerPanel');
layerBtn.addEventListener('click', function() {
if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode();
layerPanel.style.display = layerPanel.style.display === 'block' ? 'none' : 'block';
const isOpen = layerPanel.classList.toggle('show');
layerBtn.classList.toggle('active', isOpen);
});
// Sembunyikan layer panel saat klik di peta
map.on('click', function() {
layerPanel.style.display = 'none';
layerPanel.classList.remove('show');
layerBtn.classList.remove('active');
});
// Logic untuk Toggle Layer Visibility
// ===== Layer Visibility =====
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;
@@ -134,87 +147,58 @@ window.toggleSubLayer = function(subId, iconEl) {
iconEl.classList.toggle('collapsed', !isHidden);
};
// --- Sub-layer Filter ---
window.applySubFilter = function(type) {
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');
}
const el = layer.getElement?.();
if (el) el.style.display = checked.includes(layer.miskinData.kategori_bantuan) ? '' : 'none';
});
}
};
// --- Modal Logic ---
// ===== 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;
document.getElementById('modalTitle').textContent = title;
document.getElementById('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);
const oldBtn = document.getElementById('modalSaveBtn');
const newBtn = oldBtn.cloneNode(true);
oldBtn.parentNode.replaceChild(newBtn, oldBtn);
newBtn.addEventListener('click', saveCallback);
};
window.closeModal = function() {
unifiedModal.classList.remove('show');
};
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;
document.getElementById('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() {
const oldBtn = document.getElementById('confirmYesBtn');
const newBtn = oldBtn.cloneNode(true);
oldBtn.parentNode.replaceChild(newBtn, oldBtn);
newBtn.addEventListener('click', function() {
confirmModal.classList.remove('show');
confirmCallback();
});
};
window.closeConfirmModal = function() {
confirmModal.classList.remove('show');
};
window.closeConfirmModal = function() { confirmModal.classList.remove('show'); };
// --- Action Menu Logic (replaced by left sidebar) ---
window.currentAddMode = null; // 'rumah_ibadah' atau 'miskin_click'
// ===== Add Mode =====
window.currentAddMode = null;
window.activateAddMode = function(mode) {
// Toggle: jika mode yang sama diklik lagi, batalkan
if (window.currentAddMode === mode) {
window.deactivateAddMode();
return;
}
if (window.currentAddMode === mode) { window.deactivateAddMode(); return; }
window.currentAddMode = mode;
// Tooltip
const tooltips = {
'rumah_ibadah': 'Klik untuk Tambah Rumah Ibadah'
};
const tooltips = { 'rumah_ibadah': 'Klik peta 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';
};
@@ -224,18 +208,16 @@ window.deactivateAddMode = function() {
if (window.cursorTooltip) window.cursorTooltip.style.display = 'none';
};
// --- Custom Tooltip Cursor ---
// ===== Cursor Tooltip =====
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.cursorTooltip.style.display = 'block';
window.cursorTooltip.style.left = e.pageX + 15 + 'px';
window.cursorTooltip.style.top = e.pageY + 15 + 'px';
window.cursorTooltip.style.top = e.pageY + 15 + 'px';
} else {
window.cursorTooltip.style.display = 'none';
}