Files
CWC/static/js/modules/ContactInfoMap.js
T
Keith Solomon 01c6fb7831
Deploy to Dreamhost (dev) / build (push) Successful in 34s
Sync TODOs with Issues / sync_todos (push) Successful in 7s
feature: Set up contact info block and map
2026-07-04 19:22:26 -05:00

99 lines
2.9 KiB
JavaScript

/**
* Contact Info map module.
*/
const MAP_SELECTOR = '.contact-info__map[data-lat][data-lng]';
const DEFAULT_ZOOM = 14;
const MARKER_SIZE = [62, 68];
let leafletModulePromise;
function loadLeaflet() {
if (!leafletModulePromise) {
leafletModulePromise = import('https://unpkg.com/leaflet@1.9.4/dist/leaflet-src.esm.js');
}
return leafletModulePromise;
}
function toFloat(value) {
const parsed = Number.parseFloat(value);
return Number.isFinite(parsed) ? parsed : null;
}
export async function initContactInfoMap() {
const mapContainers = document.querySelectorAll(MAP_SELECTOR);
if (!mapContainers.length) {
return;
}
let Leaflet;
try {
const module = await loadLeaflet();
Leaflet = module.default || module;
} catch (error) {
console.error('Leaflet failed to load for contact map.', error);
return;
}
mapContainers.forEach((container) => {
if (container.dataset.mapReady === 'true') {
return;
}
const latitude = toFloat(container.dataset.lat);
const longitude = toFloat(container.dataset.lng);
const zoom = toFloat(container.dataset.zoom) || DEFAULT_ZOOM;
if (latitude === null || longitude === null) {
return;
}
const map = Leaflet.map(container, {
zoomControl: false,
scrollWheelZoom: false,
dragging: false,
doubleClickZoom: false,
boxZoom: false,
keyboard: false,
tap: false,
attributionControl: true,
}).setView([latitude, longitude], zoom);
Leaflet.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
maxZoom: 19,
subdomains: 'abcd',
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
}).addTo(map);
const markerSvg = container.dataset.markerSvg;
const markerIcon = markerSvg
? Leaflet.divIcon({
className: 'contact-info__leaflet-pin',
html: markerSvg,
iconSize: MARKER_SIZE,
iconAnchor: [MARKER_SIZE[0] / 2, MARKER_SIZE[1]],
})
: Leaflet.icon({
iconUrl: container.dataset.marker || '',
iconSize: MARKER_SIZE,
iconAnchor: [MARKER_SIZE[0] / 2, MARKER_SIZE[1]],
popupAnchor: [0, -MARKER_SIZE[1] + 8],
className: 'contact-info__leaflet-pin'
});
const marker = Leaflet.marker([latitude, longitude], { icon: markerIcon }).addTo(map);
const popupText = container.dataset.popup;
if (popupText) {
marker.bindPopup(popupText);
}
container.dataset.mapReady = 'true';
});
}