diff --git a/html/static/js/map-aggregate.js b/html/static/js/map-aggregate.js index 60881d97..e420f437 100644 --- a/html/static/js/map-aggregate.js +++ b/html/static/js/map-aggregate.js @@ -6,8 +6,9 @@ class MapAggregate extends HTMLElement { super(); // Create a shadow DOM - this.attachShadow({mode: "open" }); + this.attachShadow({ mode: "open" }); + this._markers = []; // Initial render this.render(); } @@ -26,156 +27,181 @@ class MapAggregate extends HTMLElement { // Lifecycle: watch these attributes for changes static get observedAttributes() { - return ["api-key", "latitude", "longitude", "organization-id", "tegola", "zoom"]; + return [ + "api-key", + "latitude", + "longitude", + "organization-id", + "tegola", + "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') { + + 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')); + + 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 === 'organization-id') { + if (name === "organization-id") { this._organizationID = newValue; } - if (name === 'tegola') { + if (name === "tegola") { this._tegola = newValue; } - if (name === 'zoom') { + 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 tegola = this.getAttribute("tegola"); const zoom = Number(this.getAttribute("zoom") || 15); mapboxgl.accessToken = apiKey; const mapElement = this.shadowRoot.querySelector("#map"); - map = new mapboxgl.Map({ + this._map = new mapboxgl.Map({ container: mapElement, center: { lat: lat, lng: lng, }, - style: 'mapbox://styles/mapbox/streets-v12', // style URL + style: "mapbox://styles/mapbox/streets-v12", // style URL zoom: zoom, }); - map.on("load", () => { - map.addSource('tegola', { - 'type': 'vector', - 'tiles': [ - `${tegola}maps/nidus/{z}/{x}/{y}?organization_id=${organization_id}` - ] + this._map.on("load", () => { + this._map.addSource("tegola", { + type: "vector", + tiles: [ + `${tegola}maps/nidus/{z}/{x}/{y}?organization_id=${organization_id}`, + ], }); - map.addInteraction('nidus-mouseenter-interaction', { - type: 'mouseenter', - target: { layerId: 'nidus' }, + this._map.addInteraction("nidus-mouseenter-interaction", { + type: "mouseenter", + target: { layerId: "nidus" }, handler: () => { - map.getCanvas().style.cursor = 'pointer'; - } + map.getCanvas().style.cursor = "pointer"; + }, }); - map.addInteraction('nidus-mouseleave-interaction', { - type: 'mouseleave', - target: { layerId: 'nidus' }, + this._map.addInteraction("nidus-mouseleave-interaction", { + type: "mouseleave", + target: { layerId: "nidus" }, handler: () => { - map.getCanvas().style.cursor = ''; - } + map.getCanvas().style.cursor = ""; + }, }); - map.addLayer({ - 'id': 'mosquito_source', - 'type': 'fill', - 'filter': ['==', ['zoom'], ['+', 2, ['to-number', ['get', 'resolution']]]], - 'source': 'tegola', - 'source-layer': 'mosquito_source', - 'paint': { - 'fill-opacity': 0.4, - 'fill-color': '#dc3545' - } + this._map.addLayer({ + id: "mosquito_source", + type: "fill", + filter: [ + "==", + ["zoom"], + ["+", 2, ["to-number", ["get", "resolution"]]], + ], + source: "tegola", + "source-layer": "mosquito_source", + paint: { + "fill-opacity": 0.4, + "fill-color": "#dc3545", + }, }); - map.addLayer({ - 'id': 'service_request', - 'type': 'fill', - 'filter': ['==', ['zoom'], ['+', 2, ['to-number', ['get', 'resolution']]]], - 'source': 'tegola', - 'source-layer': 'service_request', - 'paint': { - 'fill-opacity': 0.4, - 'fill-color': '#ffc107' - } + this._map.addLayer({ + id: "service_request", + type: "fill", + filter: [ + "==", + ["zoom"], + ["+", 2, ["to-number", ["get", "resolution"]]], + ], + source: "tegola", + "source-layer": "service_request", + paint: { + "fill-opacity": 0.4, + "fill-color": "#ffc107", + }, }); - map.addLayer({ - 'id': 'trap', - 'type': 'fill', - 'filter': ['==', ['zoom'], ['+', 2, ['to-number', ['get', 'resolution']]]], - 'source': 'tegola', - 'source-layer': 'trap', - 'paint': { - 'fill-opacity': 0.4, - 'fill-color': '#0dcaf0' - } + this._map.addLayer({ + id: "trap", + type: "fill", + filter: [ + "==", + ["zoom"], + ["+", 2, ["to-number", ["get", "resolution"]]], + ], + source: "tegola", + "source-layer": "trap", + paint: { + "fill-opacity": 0.4, + "fill-color": "#0dcaf0", + }, }); - map.addInteraction("tegola-click-mosquito-source", { + this._map.addInteraction("tegola-click-mosquito-source", { type: "click", target: { layerId: "mosquito_source" }, handler: (e) => { const coordinates = e.feature.geometry.coordinates.slice(); const properties = e.feature.properties; - this.dispatchEvent(new CustomEvent("cell-click", { - bubbles: true, - composed: true, // Allows event to cross shadow DOM boundary - detail: { - cell: properties.cell - } - })); - } + this.dispatchEvent( + new CustomEvent("cell-click", { + bubbles: true, + composed: true, // Allows event to cross shadow DOM boundary + detail: { + cell: properties.cell, + }, + }), + ); + }, }); - map.addInteraction("tegola-click-service-request", { + this._map.addInteraction("tegola-click-service-request", { type: "click", target: { layerId: "service_request" }, handler: (e) => { const coordinates = e.feature.geometry.coordinates.slice(); const properties = e.feature.properties; - this.dispatchEvent(new CustomEvent("cell-click", { - bubbles: true, - composed: true, // Allows event to cross shadow DOM boundary - detail: { - cell: properties.cell - } - })); - } + this.dispatchEvent( + new CustomEvent("cell-click", { + bubbles: true, + composed: true, // Allows event to cross shadow DOM boundary + detail: { + cell: properties.cell, + }, + }), + ); + }, }); - map.addInteraction("tegola-click-trap", { + this._map.addInteraction("tegola-click-trap", { type: "click", target: { layerId: "trap" }, handler: (e) => { const coordinates = e.feature.geometry.coordinates.slice(); const properties = e.feature.properties; - this.dispatchEvent(new CustomEvent("cell-click", { - bubbles: true, - composed: true, // Allows event to cross shadow DOM boundary - detail: { - cell: properties.cell - } - })); - } + this.dispatchEvent( + new CustomEvent("cell-click", { + bubbles: true, + composed: true, // Allows event to cross shadow DOM boundary + detail: { + cell: properties.cell, + }, + }), + ); + }, }); }); } @@ -184,25 +210,23 @@ class MapAggregate extends HTMLElement { render() { this.shadowRoot.innerHTML = ` @@ -226,13 +250,15 @@ class MapAggregate extends HTMLElement { const marker = new mapboxgl.Marker({ color: "#FF0000", - draggable: true - }).setLngLat(coords).addTo(map); - marker.on('dragend', function(e) { + draggable: true, + }) + .setLngLat(coords) + .addTo(this._map); + marker.on("dragend", function (e) { const markerDraggedEvent = new CustomEvent("markerdragend", { detail: { - marker: marker - } + marker: marker, + }, }); mapContainer.dispatchEvent(markerDraggedEvent); }); @@ -240,4 +266,4 @@ class MapAggregate extends HTMLElement { } } -customElements.define('map-aggregate', MapAggregate); +customElements.define("map-aggregate", MapAggregate);