✨feature: Set up contact info block and map
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <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';
|
||||
});
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import GetHeaderHeight from './modules/GetHeaderHeight.js';
|
||||
import tagExternalLinks from './modules/TagExternalLinks.js';
|
||||
import Navigation from './modules/Navigation.js';
|
||||
import initRecentPostsCarousels from './modules/RecentPostsCarousel.js';
|
||||
import { initContactInfoMap } from './modules/ContactInfoMap.js';
|
||||
|
||||
// Add passive event listeners
|
||||
! function (e) {
|
||||
@@ -72,6 +73,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// Initialize mobile Recent Insights carousels.
|
||||
initRecentPostsCarousels();
|
||||
|
||||
// Initialize Contact Info Leaflet maps.
|
||||
initContactInfoMap();
|
||||
|
||||
// Add Back to Top button to body
|
||||
// const backToTop = document.createElement('x-back-to-top');
|
||||
// document.body.appendChild(backToTop);
|
||||
|
||||
Reference in New Issue
Block a user