Upload seluruh tugas SIG Point Line dan Polygon
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
let map;
|
||||
let markers = {};
|
||||
let markerCount = 0;
|
||||
let currentMapClickCoords = null;
|
||||
|
||||
// Layer groups for organizing SPBU by operation hours
|
||||
let spbu24HoursLayer;
|
||||
let spbuLimitedHoursLayer;
|
||||
let layerControl;
|
||||
|
||||
// Initialize map and load markers
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initMap();
|
||||
loadMarkers();
|
||||
setupModal();
|
||||
});
|
||||
|
||||
function setupModal() {
|
||||
const modal = document.getElementById('point-modal');
|
||||
const addBtn = document.getElementById('add-point-btn');
|
||||
const closeBtn = document.querySelector('.close');
|
||||
const form = document.getElementById('point-form');
|
||||
|
||||
addBtn.onclick = function() {
|
||||
openPointModal(null);
|
||||
}
|
||||
|
||||
closeBtn.onclick = function() {
|
||||
closePointModal();
|
||||
}
|
||||
|
||||
window.onclick = function(event) {
|
||||
if (event.target === modal) {
|
||||
closePointModal();
|
||||
}
|
||||
}
|
||||
|
||||
form.onsubmit = function(e) {
|
||||
e.preventDefault();
|
||||
submitPointForm();
|
||||
}
|
||||
}
|
||||
|
||||
function openPointModal(coords) {
|
||||
const modal = document.getElementById('point-modal');
|
||||
const form = document.getElementById('point-form');
|
||||
const latInput = document.getElementById('point-latitude');
|
||||
const lngInput = document.getElementById('point-longitude');
|
||||
const nameInput = document.getElementById('point-name');
|
||||
const formInfo = document.getElementById('form-info');
|
||||
const modalTitle = document.getElementById('modal-title');
|
||||
|
||||
form.reset();
|
||||
currentMapClickCoords = coords;
|
||||
|
||||
if (coords) {
|
||||
latInput.value = coords.lat.toFixed(6);
|
||||
lngInput.value = coords.lng.toFixed(6);
|
||||
latInput.readOnly = true;
|
||||
lngInput.readOnly = true;
|
||||
modalTitle.textContent = 'Create Point';
|
||||
formInfo.textContent = '✓ Coordinates auto-filled from map click. Just add a name!';
|
||||
formInfo.classList.add('show');
|
||||
nameInput.focus();
|
||||
} else {
|
||||
latInput.value = '';
|
||||
lngInput.value = '';
|
||||
latInput.readOnly = false;
|
||||
lngInput.readOnly = false;
|
||||
modalTitle.textContent = 'Add New Point';
|
||||
formInfo.classList.remove('show');
|
||||
nameInput.focus();
|
||||
}
|
||||
|
||||
modal.classList.add('show');
|
||||
}
|
||||
|
||||
function closePointModal() {
|
||||
const modal = document.getElementById('point-modal');
|
||||
modal.classList.remove('show');
|
||||
currentMapClickCoords = null;
|
||||
}
|
||||
|
||||
function submitPointForm() {
|
||||
const name = document.getElementById('point-name').value.trim();
|
||||
const latitude = parseFloat(document.getElementById('point-latitude').value);
|
||||
const longitude = parseFloat(document.getElementById('point-longitude').value);
|
||||
const open_24_hours = document.getElementById('point-24hours').checked ? 1 : 0;
|
||||
|
||||
// Validate inputs
|
||||
if (!name) {
|
||||
showNotification('Please enter a name for the point', true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNaN(latitude) || latitude < -90 || latitude > 90) {
|
||||
showNotification('Please enter a valid latitude (-90 to 90)', true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNaN(longitude) || longitude < -180 || longitude > 180) {
|
||||
showNotification('Please enter a valid longitude (-180 to 180)', true);
|
||||
return;
|
||||
}
|
||||
|
||||
addMarker(name, latitude, longitude, open_24_hours);
|
||||
}
|
||||
|
||||
function initMap() {
|
||||
// Create map centered on a default location (San Francisco)
|
||||
map = L.map('map').setView([37.7749, -122.4194], 13);
|
||||
|
||||
// Add OpenStreetMap tile layer
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© OpenStreetMap contributors',
|
||||
maxZoom: 19
|
||||
}).addTo(map);
|
||||
|
||||
// Create layer groups for SPBU categorization
|
||||
spbu24HoursLayer = L.layerGroup();
|
||||
spbuLimitedHoursLayer = L.layerGroup();
|
||||
|
||||
// Add both layer groups to map by default
|
||||
spbu24HoursLayer.addTo(map);
|
||||
spbuLimitedHoursLayer.addTo(map);
|
||||
|
||||
// Create layers control with custom styling
|
||||
const baseLayers = {};
|
||||
const overlayLayers = {
|
||||
'🕐 SPBU 24 Jam': spbu24HoursLayer,
|
||||
'⏰ SPBU Limited Hours': spbuLimitedHoursLayer
|
||||
};
|
||||
|
||||
layerControl = L.control.layers(baseLayers, overlayLayers, {
|
||||
position: 'topright',
|
||||
collapsed: false
|
||||
}).addTo(map);
|
||||
|
||||
// Handle map click to add marker with auto-filled coordinates
|
||||
map.on('click', function(e) {
|
||||
openPointModal({
|
||||
lat: e.latlng.lat,
|
||||
lng: e.latlng.lng
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function addMarker(name, lat, lng, open_24_hours) {
|
||||
// Save to database
|
||||
fetch('api/save_point.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: name,
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
open_24_hours: open_24_hours
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
displayMarker(data.id, data.name, data.latitude, data.longitude, data.open_24_hours);
|
||||
updateMarkerCount();
|
||||
showNotification('✓ Point added successfully');
|
||||
closePointModal();
|
||||
} else {
|
||||
showNotification('Error adding point: ' + data.error, true);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
showNotification('Error adding point', true);
|
||||
});
|
||||
}
|
||||
|
||||
function displayMarker(id, name, lat, lng, open_24_hours) {
|
||||
const marker = L.marker([lat, lng]);
|
||||
|
||||
const hoursText = open_24_hours ? '🕐 Open 24 Hours' : '⏰ Limited Hours';
|
||||
const popupContent = `
|
||||
<div class="marker-popup">
|
||||
<div class="marker-popup-name">${escapeHtml(name)}</div>
|
||||
<div class="marker-popup-hours">${hoursText}</div>
|
||||
<div class="marker-popup-info">
|
||||
<span>Lat: ${lat.toFixed(4)}</span><br>
|
||||
<span>Lng: ${lng.toFixed(4)}</span>
|
||||
</div>
|
||||
<button onclick="deleteMarker(${id})">Delete</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
marker.bindPopup(popupContent);
|
||||
|
||||
// Add marker to appropriate layer group based on operation hours
|
||||
if (open_24_hours) {
|
||||
spbu24HoursLayer.addLayer(marker);
|
||||
} else {
|
||||
spbuLimitedHoursLayer.addLayer(marker);
|
||||
}
|
||||
|
||||
markers[id] = {
|
||||
marker: marker,
|
||||
open_24_hours: open_24_hours
|
||||
};
|
||||
markerCount++;
|
||||
}
|
||||
|
||||
function loadMarkers() {
|
||||
fetch('api/get_points.php')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.markers) {
|
||||
data.markers.forEach(marker => {
|
||||
displayMarker(
|
||||
marker.id,
|
||||
marker.name,
|
||||
marker.latitude,
|
||||
marker.longitude,
|
||||
marker.open_24_hours
|
||||
);
|
||||
});
|
||||
updateMarkerCount();
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error loading markers:', error));
|
||||
}
|
||||
|
||||
function deleteMarker(id) {
|
||||
if (!confirm('Are you sure you want to delete this point?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('api/delete_point.php', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ id: id })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
if (markers[id]) {
|
||||
const markerData = markers[id];
|
||||
|
||||
// Remove from appropriate layer group
|
||||
if (markerData.open_24_hours) {
|
||||
spbu24HoursLayer.removeLayer(markerData.marker);
|
||||
} else {
|
||||
spbuLimitedHoursLayer.removeLayer(markerData.marker);
|
||||
}
|
||||
|
||||
delete markers[id];
|
||||
markerCount--;
|
||||
updateMarkerCount();
|
||||
showNotification('✓ Point deleted');
|
||||
}
|
||||
} else {
|
||||
showNotification('Error deleting point: ' + data.error, true);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
showNotification('Error deleting point', true);
|
||||
});
|
||||
}
|
||||
|
||||
function updateMarkerCount() {
|
||||
const count = Object.keys(markers).length;
|
||||
const countElement = document.getElementById('marker-count');
|
||||
if (countElement) {
|
||||
countElement.textContent = count;
|
||||
}
|
||||
}
|
||||
|
||||
function showNotification(message, isError = false) {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = 'notification' + (isError ? ' error' : '');
|
||||
notification.textContent = message;
|
||||
document.body.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.remove();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
const map = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
return text.replace(/[&<>"']/g, m => map[m]);
|
||||
}
|
||||
Reference in New Issue
Block a user