Skip to content

Instantly share code, notes, and snippets.

@davidbgk
Forked from adactio/embedMap.js
Created December 16, 2024 15:33
Show Gist options
  • Save davidbgk/af9459cd65438b5f31e347551af7c854 to your computer and use it in GitHub Desktop.
Save davidbgk/af9459cd65438b5f31e347551af7c854 to your computer and use it in GitHub Desktop.

Revisions

  1. @adactio adactio created this gist Dec 16, 2024.
    152 changes: 152 additions & 0 deletions embedMap.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,152 @@
    class EmbedMap extends HTMLElement {
    constructor () {
    super();
    }
    loadScript(src, callback) {
    let script = document.createElement('script');
    script.src = src;
    script.addEventListener('load', callback);
    document.querySelector('head').appendChild(script);
    }
    loadLibrary () {
    caches.match('/js/leaflet/maplibre-gl.js')
    .then( responseFromCache => {
    if (responseFromCache) {
    let link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = '/js/leaflet/maplibre-gl.css';
    document.querySelector('head').appendChild(link);
    this.loadScript('/js/leaflet/leaflet.js', () => {
    this.loadScript('/js/leaflet/maplibre-gl.js', () => {
    this.loadScript('/js/leaflet/leaflet-maplibre-gl.js', () => {
    this.init();
    });
    });
    });
    } else {
    this.loadScript('/js/leaflet/leaflet.js', () => {
    this.init();
    });
    }
    });
    }
    setLocation (lat, lon) {
    this.location = L.latLng(lat, lon);
    }
    addMarker (lat, lon, overlay) {
    let marker = L.marker([lat, lon]).addTo(this.map);
    if (overlay) {
    marker.bindPopup(overlay);
    }
    this.pins.push(marker);
    }
    removePins () {
    this.pins.forEach( (pin) => {
    pin.remove();
    });
    this.pins = [];
    }
    dropPins () {
    let elements = document.querySelectorAll('[data-latlon]');
    if (elements.length < 1) {
    return;
    }
    let boundary = L.latLngBounds();
    let coords;
    elements.forEach( (element) => {
    coords = element.dataset.latlon.split(',');
    element.marker = this.addMarker(coords[0], coords[1], element.cloneNode(true));
    boundary.extend(L.latLng(coords[0], coords[1]));
    });
    this.map.setView(boundary.getCenter());
    if (elements.length > 1) {
    this.map.fitBounds(boundary);
    }
    }
    updatePins () {
    this.removePins();
    this.dropPins();
    }
    draw () {
    let mapOptions = {
    zoom: this.magnification
    };
    if (!this.map) {
    this.map = L.map(this.querySelector('.map'), mapOptions);
    if (L.maplibreGL) {
    L.maplibreGL({
    style: 'https://tiles.openfreemap.org/styles/bright',
    attribution: '&copy; <a href="https://www.openmaptiles.org/">OpenMapTiles</a> Data from <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
    }).addTo(this.map);
    } else {
    L.tileLayer('https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(this.map);
    }
    }
    if (this.location) {
    this.map.setView(this.location);
    }
    if (this.dataset.updates) {
    this.map.on('moveend', (ev) => {
    this.broadcastLocation();
    });
    this.map.on('zoomend', (ev) => {
    this.broadcastLocation();
    });
    }
    }
    broadcastLocation () {
    let detail = {};
    let location = this.map.getCenter();
    detail.latitude = parseFloat(location.lat).toFixed(6);
    detail.longitude = parseFloat(location.lng).toFixed(6);
    detail.zoom = this.map.getZoom();
    const locationUpdate = new CustomEvent('locationUpdate', { bubbles: true, detail: detail });
    document.dispatchEvent(locationUpdate);
    }
    init () {
    if (this.dataset.geolocate) {
    this.querySelector('.map').innerHTML = '<div style="text-align: center"><p>Getting location… please wait.<span class="loader loading"></span></p></div>';
    navigator.geolocation.getCurrentPosition(
    (position) => {
    this.magnification = 12;
    this.setLocation(position.coords.latitude, position.coords.longitude);
    this.draw();
    this.broadcastLocation();
    },
    (error) => {
    this.draw();
    }
    );
    }
    if (this.dataset.latitude && this.dataset.longitude) {
    this.setLocation(this.dataset.latitude, this.dataset.longitude);
    }
    this.draw();
    if (this.dataset.marker) {
    this.addMarker(this.dataset.latitude, this.dataset.longitude);
    } else {
    this.dropPins();
    document.addEventListener('updateMarkers', (ev) => {
    this.updatePins();
    });
    }
    }
    connectedCallback () {
    this.innerHTML = '<div class="map"></div>';
    this.magnification = 12;
    if (this.dataset.zoom) {
    this.magnification = this.dataset.zoom;
    }
    this.map = null;
    this.pins = [];
    this.location = null;
    if (window.L) {
    this.init();
    } else {
    this.loadLibrary();
    }
    }
    }
    customElements.define('embed-map', EmbedMap);