// Initialize the map const map = new maplibregl.Map({ container: 'map', style: 'https://tiles.openfreemap.org/styles/liberty', center: [2.3522, 48.8566], // Default center (Paris) zoom: 4 }); // Add navigation controls map.addControl(new maplibregl.NavigationControl()); // Add attribution control with OpenStreetMap attribution map.addControl(new maplibregl.AttributionControl({ customAttribution: '© OpenStreetMap contributors' })); // Store all events and their types let allEvents = null; let eventTypes = new Set(); let eventsByType = {}; let markersByType = {}; let colorsByType = {}; // Generate a color for each event type function getColorForType(type, index) { // Predefined colors for better visual distinction const colors = [ '#FF5722', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800' ]; return colors[index % colors.length]; } // Fetch events when the map is loaded map.on('load', function() { fetchEvents(); }); // Function to fetch events from the API function fetchEvents() { // Update event info document.getElementById('event-info').innerHTML = '
Loading events...
'; // Fetch events from the public API - using limit=1000 to get more events fetch('https://api.openeventdatabase.org/event?limit=1000') .then(response => response.json()) .then(data => { if (data.features && data.features.length > 0) { // Store all events allEvents = data; // Process events by type processEventsByType(data); // Create filter UI createFilterUI(); // Add all events to the map initially addAllEventsToMap(); // Fit map to events bounds fitMapToBounds(data); // Update event info document.getElementById('event-info').innerHTML = `Found ${data.features.length} events across ${eventTypes.size} different types.
`; } else { document.getElementById('event-info').innerHTML = 'No events found.
'; document.getElementById('filter-list').innerHTML = 'Error loading events: ${error.message}
`; }); } // Process events by their "what" type function processEventsByType(data) { eventTypes = new Set(); eventsByType = {}; // Group events by their "what" type data.features.forEach(feature => { const properties = feature.properties; const what = properties.what || 'Unknown'; // Add to set of event types eventTypes.add(what); // Add to events by type if (!eventsByType[what]) { eventsByType[what] = []; } eventsByType[what].push(feature); }); // Assign colors to each type let index = 0; eventTypes.forEach(type => { colorsByType[type] = getColorForType(type, index); index++; }); } // Create the filter UI function createFilterUI() { const filterList = document.getElementById('filter-list'); filterList.innerHTML = ''; // Sort event types alphabetically const sortedTypes = Array.from(eventTypes).sort(); // Create a checkbox for each event type sortedTypes.forEach(type => { const count = eventsByType[type].length; const color = colorsByType[type]; const li = document.createElement('li'); li.className = 'filter-item'; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.id = `filter-${type}`; checkbox.checked = true; checkbox.addEventListener('change', () => { toggleEventType(type, checkbox.checked); }); const colorDot = document.createElement('span'); colorDot.className = 'color-dot'; colorDot.style.backgroundColor = color; const label = document.createElement('label'); label.htmlFor = `filter-${type}`; label.appendChild(colorDot); label.appendChild(document.createTextNode(type)); const countSpan = document.createElement('span'); countSpan.className = 'filter-count'; countSpan.textContent = `(${count})`; label.appendChild(countSpan); li.appendChild(checkbox); li.appendChild(label); filterList.appendChild(li); }); // Add event listeners for select/deselect all buttons document.getElementById('select-all').addEventListener('click', selectAllEventTypes); document.getElementById('deselect-all').addEventListener('click', deselectAllEventTypes); } // Add all events to the map function addAllEventsToMap() { // Clear existing markers clearAllMarkers(); // Add markers for each event type Object.keys(eventsByType).forEach(type => { addEventsOfTypeToMap(type); }); } // Add events of a specific type to the map function addEventsOfTypeToMap(type) { if (!markersByType[type]) { markersByType[type] = []; } const events = eventsByType[type]; const color = colorsByType[type]; events.forEach(feature => { const coordinates = feature.geometry.coordinates.slice(); const properties = feature.properties; // Create popup content let popupContent = 'Type: ${type}
`; // Display all properties popupContent += '${key}: | ${displayValue} |