diff --git a/htmlpage/static/js/map-locator.js b/htmlpage/static/js/map-locator.js index d9c362b2..5c641110 100644 --- a/htmlpage/static/js/map-locator.js +++ b/htmlpage/static/js/map-locator.js @@ -206,10 +206,3 @@ class MapLocator extends HTMLElement { } customElements.define('map-locator', MapLocator); - - - -function mapLoad(MAPBOX_ACCESS_TOKEN) { - return new Promise((resolve, reject) => { - }); -} diff --git a/htmlpage/static/js/map-multipoint.js b/htmlpage/static/js/map-multipoint.js new file mode 100644 index 00000000..1e15b108 --- /dev/null +++ b/htmlpage/static/js/map-multipoint.js @@ -0,0 +1,220 @@ +var map = null; +// A map that shows multiple single point locations. +// Points have additional detail popups. +class MapMultipoint extends HTMLElement { + constructor() { + super(); + + // Create a shadow DOM + this.attachShadow({mode: "open" }); + + // Initial render + this.render(); + + this._map = null; + // markers shown on the map. Should be none or 1, generally. + this._markers = null; + } + + // Lifecycle: when element is added to the DOM + connectedCallback() { + // Initialize the map when the element is added to the DOM + setTimeout(() => this._initializeMap(), 0); + } + + disconnectedCallback() { + if (this._map) { + this._map.remove(); + } + } + + // Lifecycle: watch these attributes for changes + static get observedAttributes() { + return ['api-key', 'latitude', 'longitude', 'zoom']; + } + + // Lifecycle: respond to attribute changes + attributeChangedCallback(name, oldValue, newValue) { + // Only handle if map exists and values actually changed + if (!this._map || oldValue === newValue) return; + + if (name === 'latitude' || name === 'longitude') { + if (this.hasAttribute('latitude') && this.hasAttribute('longitude')) { + const lat = Number(this.getAttribute('latitude')); + const lng = Number(this.getAttribute('longitude')); + this._map.setCenter([lat, lng]); + } + } + + if (name === 'zoom') { + this._map.setZoom(Number(newValue)); + } + } + + _initializeMap() { + const apiKey = this.getAttribute("api-key"); + const lat = Number(this.getAttribute('latitude') || 36.2); + const lng = Number(this.getAttribute('longitude') || -119.2); + const organization_id = Number(this.getAttribute("organization-id") || 0); + const tegola = this.getAttribute("tegola") + const zoom = Number(this.getAttribute('zoom') || 15); + + mapboxgl.accessToken = apiKey; + const mapElement = this.shadowRoot.querySelector("#map"); + this._map = new mapboxgl.Map({ + container: mapElement, + center: { + lat: lat, + lng: lng, + }, + style: 'mapbox://styles/mapbox/streets-v12', // style URL + zoom: zoom, + }); + this._map.addControl(new mapboxgl.GeolocateControl({ + positionOptions: { + enableHighAccuracy: true + }, + trackUserLocation: true, + showUserHeading: true + })); + this._map.addControl(new mapboxgl.NavigationControl()); + this._map.on("load", () => { + this.dispatchEvent(new CustomEvent('load'), { + bubbles: true, + composed: true, // Allows event to cross shadow DOM boundary + detail: { + map: this + } + }); + }); + } + + async _fetchAddressSuggestions(text) { + try { + const url = `https://api.mapbox.com/search/geocode/v6/forward?q=${encodeURIComponent(text)}&access_token=${this._apiKey}`; + + const response = await fetch(url); + const data = await response.json(); + return data; + } catch (error) { + console.error('Error fetching geocoding suggestions:', error); + } + } + + _renderSuggestions(suggestions) { + console.log("Rendering suggestions", suggestions); + this._suggestions.innerHTML = suggestions.map((item, index) => { + if (item.properties.place_formatted != "") { + return ` +