Created
October 13, 2025 03:34
-
-
Save maxwofford/5cd3e642493c447808fe32502c64319b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Airtable Locations Map</title> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | |
| <style> | |
| body { | |
| margin: 0; | |
| padding: 20px; | |
| font-family: Arial, sans-serif; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| } | |
| #map { | |
| height: 500px; | |
| width: 100%; | |
| border: 1px solid #ccc; | |
| margin-bottom: 20px; | |
| } | |
| .locations-list { | |
| max-height: 400px; | |
| overflow-y: auto; | |
| border: 1px solid #ddd; | |
| padding: 10px; | |
| } | |
| .location-item { | |
| margin-bottom: 10px; | |
| padding: 8px; | |
| border-bottom: 1px solid #eee; | |
| } | |
| .location-item:last-child { | |
| border-bottom: none; | |
| } | |
| .location-name { | |
| font-weight: bold; | |
| cursor: pointer; | |
| } | |
| .location-name:hover { | |
| color: #007cba; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="map"></div> | |
| <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | |
| <script> | |
| // Initialize the map centered on the world (it will auto-zoom to fit points) | |
| const map = L.map('map').setView([0, 0], 2); | |
| // Add OpenStreetMap tiles | |
| L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |
| attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | |
| }).addTo(map); | |
| // Airtable config - Replace BASE_ID and TABLE_NAME with yours | |
| const AIRTABLE_PAT = 'patkDeTklC7FkfuDl.f4c50991508eff765c7ca4952b363fecca32a31b0b4599aa88001778d55715d1'; | |
| const BASE_ID = 'appdOWEJZEtL8lanH'; | |
| const TABLE_NAME = 'tblg7SJpuCpj5PNMP'; | |
| let markers = L.featureGroup(); // Group to auto-fit bounds and manage markers | |
| let locationsData = []; // Store data for the list | |
| // Fetch data from Airtable API | |
| fetch(`https://api.airtable.com/v0/${BASE_ID}/${TABLE_NAME}`, { | |
| headers: { | |
| 'Authorization': `Bearer ${AIRTABLE_PAT}` | |
| } | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| console.log({ data }) | |
| locationsData = data.records; | |
| locationsData.forEach(record => { | |
| const fields = record.fields; | |
| const lat = fields.lat; | |
| const lng = fields.lng; | |
| // const name = fields.Name || 'Unnamed Location'; // Adjust field name if different | |
| // const description = fields.Description || ''; // Adjust field name if different | |
| if (lat && lng && !isNaN(lat) && !isNaN(lng)) { | |
| const marker = L.marker([lat, lng]) | |
| // .bindPopup(`<b>${name}</b><br>${description}`) | |
| .addTo(markers); | |
| // Store marker reference for list clicks | |
| record.marker = marker; | |
| } | |
| }); | |
| markers.addTo(map); | |
| if (markers.getLayers().length > 0) { | |
| map.fitBounds(markers.getBounds(), { padding: [20, 20] }); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error fetching Airtable data:', error); | |
| }); | |
| // Function to pan map to a specific marker when list item is clicked | |
| function panToMarker(recordId) { | |
| const record = locationsData.find(r => r.id === recordId); | |
| if (record && record.marker) { | |
| map.panTo(record.marker.getLatLng(), { animate: true, duration: 0.5 }); | |
| record.marker.openPopup(); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment