diff --git a/htmlpage/static/js/address-suggestion.js b/htmlpage/static/js/address-suggestion.js index 8b63b3df..29a1ce91 100644 --- a/htmlpage/static/js/address-suggestion.js +++ b/htmlpage/static/js/address-suggestion.js @@ -197,30 +197,3 @@ class AddressInput extends HTMLElement { } customElements.define('address-input', AddressInput); - -function setLocationInputs(suggestion) { - let address = document.getElementById('address'); - let country = document.getElementById('address-country'); - let latitude = document.getElementById('latitude'); - let longitude = document.getElementById('longitude'); - let latlngAccuracyType = document.getElementById('latlng-accuracy-type'); - let postcode = document.getElementById('address-postcode'); - let place = document.getElementById('address-place'); - let region = document.getElementById('address-region'); - let street = document.getElementById('address-street'); - - // Extract context data from properties - const props = suggestion.properties; - const context = props.context || {}; - - // Populate structured fields - address.value = props.full_address; - country.value = context.country.name; - latitude.value = props.coordinates.latitude; - longitude.value = props.coordinates.longitude; - latlngAccuracyType.value = props.coordinates.accuracy; - postcode.value = context.postcode.name; - place.value = context.place.name; - region.value = context.region.name; - street.value = context.country.name; -} diff --git a/htmlpage/static/js/map-locator.js b/htmlpage/static/js/map-locator.js new file mode 100644 index 00000000..d9c362b2 --- /dev/null +++ b/htmlpage/static/js/map-locator.js @@ -0,0 +1,215 @@ +var map = null; +// A map that can be used to locate a single point by setting its location explicitly +// or by allowing the user to move a marker. +class MapLocator extends HTMLElement { + constructor() { + super(); + + // Create a shadow DOM + this.attachShadow({mode: "open" }); + + // Initial render + this.render(); + + // 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 === 'api-key') { + this._apiKey = newValue; + } + + 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() { + console.log("Setting up the map..."); + const lat = Number(this.getAttribute('latitude') || 36.2); + const lng = Number(this.getAttribute('longitude') || -119.2); + const zoom = Number(this.getAttribute('zoom') || 15); + + mapboxgl.accessToken = this._apiKey; + map = new mapboxgl.Map({ + container: "map", + center: { + lat: lat, + lng: lng, + }, + style: 'mapbox://styles/mapbox/streets-v12', // style URL + zoom: zoom, + }); + map.addControl(new mapboxgl.GeolocateControl({ + positionOptions: { + enableHighAccuracy: true + }, + trackUserLocation: true, + showUserHeading: true + })); + map.addControl(new mapboxgl.NavigationControl()); + map.on("load", function() { + 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 ` +