diff --git a/js/map.js b/js/map.js
index e69de29..190b295 100644
--- a/js/map.js
+++ b/js/map.js
@@ -0,0 +1,113 @@
+let map;
+let currentJourney = {
+ markers: [],
+ path: nullJustin // This will be the line feature (GeoJSON)
+};
+let currentMarkerBeingEdited = null;
+let isCreatingJourney = true;
+
+// Function to create a marker at a lngLat and add to the map
+function createMarker(lngLat) {
+ const markerElement = document.createElement('div');
+ markerElement.className = 'marker';
+ markerElement.innerHTML = '';
+
+ const marker = new maplibregl.Marker(markerElement)
+ .setLngLat(lngLat)
+ .addTo(map);
+
+ marker.id = Date.now();
+ marker.content = {
+ title: '',
+ date: '',
+ text: '',
+ images: [],
+ videoUrl: ''
+ };
+
+ // Add a popup
+ const popup = new maplibregl.Popup({ offset: 25 })
+ .setHTML('New Marker');
+ marker.setPopup(popup);
+
+ // When the marker is clicked, open the editor
+ markerElement.addEventListener('click', () => {
+ openMarkerEditor(marker);
+ });
+
+ return marker;
+}
+
+function openMarkerEditor(marker) {
+ currentMarkerBeingEdited = marker;
+ document.getElementById('marker-title').value = marker.content.title;
+ document.getElementById('marker-date').value = marker.content.date;
+ document.getElementById('marker-text').value = marker.content.text;
+ document.getElementById('video-url').value = marker.content.videoUrl;
+ document.getElementById('marker-coords').textContent =
+ `${marker.getLngLat().lng.toFixed(4)}, ${marker.getLngLat().lat.toFixed(4)}`;
+
+ // Show the modal
+ document.getElementById('marker-modal').style.display = 'block';
+}
+
+function closeMarkerEditor() {
+ document.getElementById('marker-modal').style.display = 'none';
+ currentMarkerBeingEdited = null;
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+ map = new maplibregl.Map({
+ container: 'map',
+ style: 'https://demotiles.maplibre.org/style.json',
+ center: [0, 20],
+ zoom: 2
+ });
+
+ // Close editor events
+ document.getElementById('close-modal').addEventListener('click', closeMarkerEditor);
+ document.getElementById('cancel-marker').addEventListener('click', closeMarkerEditor);
+
+ // Save marker event
+ document.getElementById('save-marker').addEventListener('click', function() {
+ if (!currentMarkerBeingEdited) return;
+
+ // Update marker content
+ currentMarkerBeingEdited.content.title = document.getElementById('marker-title').value;
+ currentMarkerBeingEdited.content.date = document.getElementById('marker-date').value;
+ currentMarkerBeingEdited.content.text = document.getElementById('marker-text').value;
+ currentMarkerBeingEdited.content.videoUrl = document.getElementById('video-url').value;
+
+ // Update the popup
+ currentMarkerBeingEdited.getPopup().setHTML(
+ `${currentMarkerBeingEdited.content.title || '袭刊Untitled'}`
+ );
+
+ closeMarkerEditor();
+ });
+
+ // Delete marker event
+ document.getElementById('delete-marker').addEventListener('click', function() {
+ if (!currentMarkerBeingEdited) return;
+
+ // Remove from map
+ currentMarkerBeingEdited.remove();
+
+ // Remove from currentJourney.markers
+ const index = currentJourney.markers.findIndex(m => m.id === currentMarkerBeingEdited.id);
+ if (index !== -1) {
+ currentJourney.markers.splice(index, 1);
+ }
+
+ closeMarkerEditor();
+ });
+
+ // Add marker on map click
+ map.on('click', (e) => {
+ if (isCreatingJourney) {
+ const marker = createMarker(e.lngLat);
+ currentJourney.markers.push(marker);
+ // TODO: update the path line
+ }
+ });
+});
\ No newline at end of file