window.SpotNotes = window.SpotNotes || {};
window.SpotNotes.initMap = function() {
// Default view (e.g., Oklahoma area if geolocation fails)
window.SpotNotes.map = L.map('map').setView([35.6528, -97.4781], 10);
// Ask for location
if (navigator.geolocation) {
navigator.geolocation.watchPosition((position) => {
const { latitude, longitude } = position.coords;
window.SpotNotes.userLocation = { lat: latitude, lng: longitude };
const centerBtn = document.getElementById('btn-center-user');
if (centerBtn) centerBtn.style.display = 'block';
if (window.SpotNotes.isTracking) {
window.SpotNotes.map.setView([latitude, longitude]);
} else if (!window.SpotNotes.userMarker && !new URLSearchParams(window.location.search).has('pad') && !new URLSearchParams(window.location.search).has('note')) {
window.SpotNotes.map.setView([latitude, longitude], 13);
console.log("Map centered on user location:", latitude, longitude);
}
// Add User Location Dot
if (window.SpotNotes.userMarker) {
window.SpotNotes.userMarker.setLatLng([latitude, longitude]);
} else {
window.SpotNotes.userMarker = L.circleMarker([latitude, longitude], {
radius: 8,
fillColor: "#3388ff",
color: "#fff",
weight: 2,
opacity: 1,
fillOpacity: 0.8
}).addTo(window.SpotNotes.map).bindPopup("You are here");
}
// Location-Based Browser Alerts
const userLatLng = L.latLng(latitude, longitude);
if (window.SpotNotes.activeNotes && window.SpotNotes.activeNotes.length > 0) {
window.SpotNotes.activeNotes.forEach(note => {
const noteLatLng = L.latLng(note.lat, note.lng);
if (userLatLng.distanceTo(noteLatLng) <= 50) {
if (!window.SpotNotes.notifiedNoteIds.has(note.id)) {
window.SpotNotes.notifiedNoteIds.add(note.id);
alert(`You are near a note!\n\n${note.title}\n${note.content}`);
}
}
});
}
}, (err) => {
console.warn("Geolocation error:", err);
}, {
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
});
}
// Add OpenStreetMap tiles
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(window.SpotNotes.map);
// Listen for zoom changes to toggle note display
window.SpotNotes.map.on('zoomend', () => {
if (window.SpotNotes.activeNotes.length > 0) {
window.SpotNotes.renderMapMarkers();
}
});
window.SpotNotes.map.on('dragstart', window.SpotNotes.stopTracking);
window.SpotNotes.map.on('popupopen', window.SpotNotes.stopTracking);
// Initialize MarkerClusterGroup
window.SpotNotes.markerClusterGroup = L.markerClusterGroup({
disableClusteringAtZoom: 16
});
window.SpotNotes.map.addLayer(window.SpotNotes.markerClusterGroup);
};
window.SpotNotes.renderMapMarkers = function() {
// Clear existing
if (window.SpotNotes.markerClusterGroup) {
window.SpotNotes.markerClusterGroup.clearLayers();
}
// Also remove from map directly just in case (fallback)
window.SpotNotes.currentMarkers.forEach(marker => window.SpotNotes.map.removeLayer(marker));
window.SpotNotes.currentMarkers = [];
const zoom = window.SpotNotes.map.getZoom();
const showFull = zoom >= 14; // Zoom threshold
window.SpotNotes.activeNotes.forEach(note => {
if (!note || note.lat === undefined || note.lng === undefined || (note.lat === 0 && note.lng === 0)) {
return;
}
let marker;
let actionBtns = '';
// Determine permissions
const isOwner = window.SpotNotes.currentUser && (note.owner_id ? note.owner_id === window.SpotNotes.currentUser.id : window.SpotNotes.activePadOwnerId === window.SpotNotes.currentUser.id);
const isPublic = note.is_public !== undefined ? note.is_public : window.SpotNotes.activePadIsPublic;
const canWrite = (note.notepad && note.notepad.can_write !== undefined) ? note.notepad.can_write : window.SpotNotes.activePadCanWrite;
if (canWrite) {
const escapedTitle = window.SpotNotes.escapeHtml(note.title).replace(/'/g, "\\'").replace(/"/g, '"');
const escapedContent = window.SpotNotes.escapeHtml(note.content).replace(/'/g, "\\'").replace(/"/g, '"').replace(/\n/g, '\\n');
actionBtns = `
`;
} else if (isPublic) {
actionBtns = `
`;
}
const shareToken = note.share_token || '';
const shareBtn = ``;
const dateStr = new Date(note.created_at).toLocaleString();
const padColor = (note.notepad && note.notepad.color) ? note.notepad.color : '#3388ff';
const lockPrefix = note.is_encrypted ? 'π ' : '';
const directionsBtn = `πΊοΈ Directions`;
if (showFull) {
const icon = L.divIcon({
className: '',
html: `