{"version":3,"file":"app-799b5e97.9729664bca28a8e6916d.bundle.js","mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAYA;AAAA;AAEA;AAAA;AAwBA;AAAA;AApCA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBA;AAEA;AACA;AACA;AACA;AA2vBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAgEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAn4BA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAEA;AACA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA2CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AA0CA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAp9BA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;;;;;;;;;;;;;;;;;;;;ACxCA;AACA;AAEA;AASA;AAAA;AAPA;AACA;AAAA;AAOA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AA7DA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;;;;;;;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACPA;AACA;AACA;AACA;;;;;;;;;;;ACHA;AACA;AACA;AACA","sources":["webpack://www.zeusteam.com/./src/slippy-map/slippy-map.js","webpack://www.zeusteam.com/./src/slippy-map/us-county-selector.js","webpack://www.zeusteam.com/./src/slippy-map/slippy-map.scss","webpack://www.zeusteam.com/./src/slippy-map/us-county-selector.scss","webpack://www.zeusteam.com/./src/slippy-map/slippy-map.html","webpack://www.zeusteam.com/./src/slippy-map/us-county-selector.html"],"sourcesContent":["import { bindable, bindingMode, computedFrom } from 'aurelia-framework';\r\nimport { EventAggregator } from 'aurelia-event-aggregator';\r\nimport { Notifier } from 'common/ui';\r\nimport { Google } from 'services/google';\r\nimport { MarkerClusterer } from '@googlemaps/markerclusterer';\r\nimport { I18n } from 'common/i18n';\r\nimport { HttpClient } from 'aurelia-http-client';\r\nimport { Geography } from '../services/geography';\r\nimport * as topojson from 'topojson-client';\r\nimport turfCentroid from '@turf/centroid';\r\n\r\nexport class SlippyMap {\r\n static inject = [Element, EventAggregator, Notifier, Google, I18n, Geography];\r\n _ea;\r\n _notifier;\r\n _google;\r\n _i18n;\r\n _geography;\r\n\r\n @bindable markers;\r\n @bindable selectMarkers = false;\r\n @bindable popupCallback;\r\n @bindable hoverInfoCallback;\r\n @bindable({ defaultBindingMode: bindingMode.fromView }) visibleMarkers;\r\n _mapMarkers = [];\r\n @bindable({ defaultBindingMode: bindingMode.fromView }) currentLocation;\r\n @bindable highlightMarker;\r\n @bindable selectMarker\r\n @bindable allowFullScreen = false;\r\n @bindable streetView;\r\n @bindable topojson;\r\n @bindable resetTopojsonStyles;\r\n @bindable zoom = 6;\r\n @bindable heatmap;\r\n @bindable geojson;\r\n @bindable removeGeojsonIds;\r\n @bindable selectWithDrawingTools = false;\r\n @bindable clearSelected;\r\n @bindable selectWithCounties = false;\r\n @bindable selectedEventKey;\r\n @bindable sendSelectedEventKey;\r\n\r\n _domParser;\r\n\r\n _infoWindow;\r\n _topojsonLayers = [];\r\n _geojsonLabels = [];\r\n _handlers = [];\r\n\r\n constructor(element, ea, notifier, google, i18n, geography) {\r\n this._element = element;\r\n this._ea = ea;\r\n this._notifier = notifier;\r\n this._google = google;\r\n this._i18n = i18n;\r\n this._geography = geography;\r\n }\r\n\r\n attached() {\r\n if (this.selectedEventKey) this._handlers.push(this._ea.subscribe(this.selectedEventKey, (data) => this._onSelectedIdsChanged(data.ids)));\r\n this._domParser = new DOMParser();\r\n this._initializeMap();\r\n this._isAttached = true;\r\n }\r\n\r\n detached() {\r\n this._handlers.forEach(h => h.dispose());\r\n this._handlers = [];\r\n }\r\n\r\n @computedFrom('_isAttached', '_map')\r\n get isMapLoaded() {\r\n return this._map && this._isAttached;\r\n }\r\n\r\n streetViewChanged() {\r\n try {\r\n if (!this._map || !this._panorama) return;\r\n if (!this.streetView) {\r\n if (this._panorama.getVisible() === true) this._panorama.setVisible(false);\r\n return;\r\n }\r\n const streetViewPosition = { lat: this.streetView.latitude, lng: this.streetView.longitude };\r\n this._panorama.setPosition(streetViewPosition);\r\n this._panorama.setPov({ heading: 0, pitch: 0 });\r\n this._panorama.setVisible(true);\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n selectMarkerChanged() {\r\n try {\r\n if (this._onMarkerClicked) {\r\n this._onMarkerClicked = false;\r\n return;\r\n }\r\n if (!this._mapMarkers) return;\r\n if (this._mapMarkerPopup) {\r\n this._mapMarkerPopup.close();\r\n }\r\n if (!this.selectMarker) return;\r\n const selectedMarker = this._mapMarkers.find(x => x.locationId === this.selectMarker);\r\n if (!selectedMarker) return;\r\n this._onMarkerClick(selectedMarker, true, true);\r\n this._map.setOptions({\r\n center: selectedMarker.marker.position,\r\n zoom: Number(15)\r\n });\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _onSelectedIdsChanged(ids) {\r\n try {\r\n this._clearSelected(false);\r\n ids.forEach(id => {\r\n const mapMarker = this._mapMarkers.find(x => x.locationId === id);\r\n if (!mapMarker) return;\r\n this._onMarkerClick(mapMarker, false, false, true);\r\n });\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n async markersChanged() {\r\n try {\r\n if (!this._map) {\r\n this._loadMarkers = true;\r\n return;\r\n }\r\n if (this._mapMarkers.length) {\r\n // Remove the existing markers\r\n this._mapMarkers.forEach(m => {\r\n m.marker.setMap(null);\r\n });\r\n this._mapMarkers.length = 0;\r\n this._mapMarkers = [];\r\n }\r\n\r\n if (!this.markers) return;\r\n\r\n if (!this._mapMarkerPopup) {\r\n this._mapMarkerPopup = new google.maps.InfoWindow({ content: '', disableAutoPan: true });\r\n this._mapMarkerPopup.addListener('closeclick', () => this._onMarkerClosed());\r\n }\r\n if (!this._mapMarkerHover) {\r\n this._mapMarkerHover = new google.maps.InfoWindow({ content: '', disableAutoPan: true });\r\n }\r\n\r\n const markerBounds = new google.maps.LatLngBounds();\r\n this._mapMarkers = this.markers.map((m, i) => {\r\n if (!m.lat || !m.lng) return;\r\n const faPin = this._faPin(m.marker);\r\n let highlightFaPin;\r\n if (this.selectMarkers) {\r\n highlightFaPin = this._faPin(m.marker, '#00ff00', '#ff0000', '#00ff00');\r\n }\r\n const marker = new google.maps.marker.AdvancedMarkerElement({\r\n position: new google.maps.LatLng(m.lat, m.lng),\r\n content: m.selected && highlightFaPin ? highlightFaPin.element : faPin.element,\r\n });\r\n markerBounds.extend(marker.position);\r\n const mapMarker = { locationId: m.id, marker, faPin, highlightFaPin, selected: m.selected };\r\n marker.addListener('click', () => this._onMarkerClick(mapMarker));\r\n if (this.hoverInfoCallback) {\r\n marker.content.addEventListener('mouseenter', () => this._onMarkerMouseover(mapMarker));\r\n marker.content.addEventListener('mouseleave', () => this._onMarkerMouseout());\r\n }\r\n return mapMarker;\r\n });\r\n\r\n if (this.markers.length) {\r\n window.setTimeout(() => {\r\n this._map.fitBounds(markerBounds);\r\n }, 50);\r\n }\r\n\r\n this._setMarkerCluster();\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _faPin(iconClass, glyphColor = '#ffffff', background = '#ff0000', borderColor = '#cccccc') {\r\n const icon = document.createElement('div');\r\n icon.innerHTML = ``;\r\n return new google.maps.marker.PinElement({\r\n glyph: icon,\r\n glyphColor,\r\n background,\r\n borderColor,\r\n });\r\n }\r\n\r\n async _onMarkerMouseover(mapMarker) {\r\n try {\r\n let content = mapMarker.locationId;\r\n if (this.hoverInfoCallback) {\r\n content = await this.hoverInfoCallback(mapMarker.locationId);\r\n }\r\n if (content.header) {\r\n this._mapMarkerHover.setHeaderContent(content.header);\r\n this._mapMarkerHover.setContent(content.body);\r\n } else {\r\n this._mapMarkerHover.setContent(content);\r\n }\r\n this._mapMarkerHover.open(this._map, mapMarker.marker);\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _onMarkerMouseout() {\r\n if (this._mapMarkerHover) this._mapMarkerHover.close();\r\n }\r\n\r\n async _onMarkerClick(marker, publishEvent = true, ignoreSelectMarkers = false, fromDrawing = false) {\r\n try {\r\n this._onMarkerClicked = true;\r\n window.setTimeout(() => this._onMarkerClicked = false, 1000);\r\n this._element.dispatchEvent(new CustomEvent('marker-clicked', { bubbles: true, detail: { id: marker.locationId } }));\r\n\r\n if (this.selectMarkers && !ignoreSelectMarkers) {\r\n marker.selected = !marker.selected;\r\n if (marker.selected) {\r\n marker.marker.content = marker.highlightFaPin.element;\r\n } else {\r\n marker.marker.content = marker.faPin.element;\r\n }\r\n if (publishEvent) {\r\n this._publishMarkersSelected();\r\n }\r\n\r\n if (fromDrawing) return;\r\n\r\n if (!this.popupCallback) {\r\n return;\r\n }\r\n }\r\n\r\n let content = marker.locationId;\r\n if (this.popupCallback) {\r\n content = await this.popupCallback(marker.locationId);\r\n }\r\n if (content.header) {\r\n this._mapMarkerPopup.setHeaderContent(content.header);\r\n this._mapMarkerPopup.setContent(content.body);\r\n } else {\r\n this._mapMarkerPopup.setContent(content);\r\n }\r\n this._mapMarkerPopup.open(this._map, marker.marker);\r\n this._element.dispatchEvent(new CustomEvent('marker-opened', { bubbles: true, detail: { id: marker.locationId } }));\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _publishMarkersSelected() {\r\n const selectedIds = this._mapMarkers.filter(x => x.selected)?.map(x => x.locationId) ?? [];\r\n this._element.dispatchEvent(new CustomEvent('markers-selected', { bubbles: true, detail: { ids: selectedIds } }));\r\n if (this.sendSelectedEventKey) this._ea.publish(this.sendSelectedEventKey, { ids: selectedIds });\r\n }\r\n\r\n _onMarkerClosed() {\r\n this._element.dispatchEvent(new CustomEvent('marker-closed', { bubbles: true, detail: {} }));\r\n }\r\n\r\n clearSelectedChanged() {\r\n if (!this.clearSelected) return;\r\n this._clearSelected();\r\n }\r\n\r\n _clearSelected(publishEvent = true) {\r\n try {\r\n if (!this._mapMarkers.length) return;\r\n for (let i = 0; i < this._mapMarkers.length; i++) {\r\n this._mapMarkers[i].selected = true;\r\n let publish = i === this._mapMarkers.length - 1;\r\n if (!publishEvent) publish = false;\r\n this._onMarkerClick(this._mapMarkers[i], publish, false, true);\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n /**\r\n * Google map is super slow with rendering many markers\r\n * Only display the markers that are in the visible bounds\r\n */\r\n _setMarkerCluster() {\r\n if (!this._map || !this._mapMarkers) return;\r\n try {\r\n if (this._mapMarkerCluster) {\r\n this._mapMarkerCluster.setMap(null);\r\n this._mapMarkerCluster = null;\r\n }\r\n const mapBounds = this._map.getBounds();\r\n if (!mapBounds) return;\r\n this._mapMarkers.forEach(mm => {\r\n if (mm.marker.map === this._map) mm.marker.setMap(null);\r\n mm.marker.display = mapBounds.contains(mm.marker.position);\r\n });\r\n const displayMarkers = this._mapMarkers.filter(x => x.marker.display) || [];\r\n this.visibleMarkers = displayMarkers.map((m, i) => {\r\n return {\r\n id: m.locationId,\r\n position: {\r\n latitude: m.marker.position.lat,\r\n longitude: m.marker.position.lng\r\n }\r\n };\r\n });\r\n\r\n this._mapMarkerCluster = new MarkerClusterer({ markers: displayMarkers.map(x => x.marker), map: this._map });\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n /**\r\n * Google map is super slow with rendering many markers\r\n * This will clear the markers if there are too many when the map starts to change\r\n */\r\n _clearMarkerCluster() {\r\n try {\r\n if (!this._mapMarkerCluster) return;\r\n const displayedMarkers = (this._mapMarkers.filter(x => x.marker.display) || []).length;\r\n if (displayedMarkers < 100) return;\r\n this._mapMarkerCluster.setMap(null);\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n geojsonChanged() {\r\n if (!this.geojson || !this._map || !this._isAttached) return;\r\n this._addGeojson();\r\n }\r\n\r\n resetGeojsonStylesChanged() {\r\n if (!this._map) return;\r\n this._map.data.revertStyle();\r\n }\r\n\r\n removeGeojsonIdsChanged() {\r\n if (!this.removeGeojsonIds || !this.isMapLoaded) return;\r\n try {\r\n this.removeGeojsonIds.forEach(id => {\r\n const f = this._map.data.getFeatureById(id);\r\n if (f) {\r\n this._map.data.remove(f);\r\n }\r\n const label = this._geojsonLabels.find(x => x.id === id);\r\n if (label) {\r\n label.marker.setMap(null);\r\n label.el.remove();\r\n }\r\n });\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _zoomToFeature(feature) {\r\n try {\r\n if (!this.isMapLoaded || !feature) return;\r\n\r\n let bounds = new google.maps.LatLngBounds();\r\n feature.getGeometry().forEachLatLng((latlng) => {\r\n bounds.extend(latlng);\r\n });\r\n this._map.fitBounds(bounds, 10)\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n async _addGeojson() {\r\n try {\r\n this._map.data.setStyle(this.geojson.style);\r\n const listenersLoaded = google.maps.event.hasListeners(this._map.data, 'click');\r\n if (this.geojson.click && !listenersLoaded) {\r\n this._map.data.addListener('click', (event) => {\r\n if (this.geojson.click.callback) this.geojson.click.callback(event.feature);\r\n if (this.geojson.click.setStyle) {\r\n const style = this.geojson.click.setStyle(event.feature);\r\n if (style) {\r\n this._map.data.overrideStyle(event.feature, style);\r\n } else {\r\n this._map.data.revertStyle(event.feature);\r\n }\r\n }\r\n if (this.geojson.click.zoomTo) {\r\n this._zoomToFeature(event.feature);\r\n }\r\n });\r\n }\r\n if (this.geojson.label.minZoom && !listenersLoaded) {\r\n this._map.addListener('zoom_changed', () => {\r\n const zoom = this._map.getZoom();\r\n if (this.geojson.label.minZoom) {\r\n if (zoom < this.geojson.label.minZoom) {\r\n this._geojsonLabels.forEach(l => l.marker.setMap(null));\r\n } else {\r\n this._geojsonLabels.forEach(l => l.marker.setMap(this._map));\r\n }\r\n }\r\n });\r\n }\r\n if (this.geojson.label) {\r\n this.geojson.labels = [];\r\n // add a point with a label for each geojson feature\r\n this.geojson.data.features.forEach((f) => {\r\n const centroid = turfCentroid(f.geometry);\r\n const lat = centroid.geometry.coordinates[1];\r\n const lng = centroid.geometry.coordinates[0];\r\n const label = document.createElement('div');\r\n label.classList.add(this.geojson.label.cssClass)\r\n label.textContent = this.geojson.label.template(f);\r\n const featureLabelMarker = new google.maps.marker.AdvancedMarkerElement({\r\n map: this._map,\r\n position: { lat, lng },\r\n content: label,\r\n });\r\n this._geojsonLabels.push({ id: f.id, el: label, marker: featureLabelMarker });\r\n });\r\n }\r\n if (this.geojson.mouseover && !listenersLoaded) {\r\n this._map.data.addListener('mouseover', (event) => {\r\n if (this.geojson.mouseover.setStyle) {\r\n const style = this.geojson.mouseover.setStyle(event.feature);\r\n if (style) this._map.data.overrideStyle(event.feature, style);\r\n }\r\n });\r\n this._map.data.addListener('mouseout', (event) => {\r\n if (this.geojson.mouseover.setStyle) {\r\n const style = this.geojson.mouseover.setStyle(event.feature);\r\n if (style) this._map.data.revertStyle(event.feature);\r\n }\r\n });\r\n }\r\n this._map.data.addGeoJson(this.geojson.data);\r\n if (this.geojson.label.minZoom) {\r\n google.maps.event.trigger(this._map, 'zoom_changed');\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n topojsonChanged() {\r\n if (!this.topojson || !this.isMapLoaded) return;\r\n this._addTopoJson();\r\n }\r\n\r\n resetTopojsonStylesChanged() {\r\n if (!this._map) return;\r\n this._map.data.revertStyle();\r\n }\r\n\r\n _clearTopoJson(id) {\r\n if (!id || !this.isMapLoaded || !this._topojsonLayers) return;\r\n try {\r\n const idx = this._topojsonLayers.findIndex(x => x.id === id);\r\n if (idx < 0) return;\r\n this._topojsonLayers[idx].features.forEach(f => {\r\n this._map.data.remove(f);\r\n });\r\n this._topojsonLayers[idx].labels.forEach(l => {\r\n l.setMap(null);\r\n console.log(l);\r\n });\r\n this._topojsonLayers[idx].labelEls.forEach(el => {\r\n el.remove();\r\n });\r\n google.maps.event.clearInstanceListeners(this._map.data);\r\n this._topojsonLayers.splice(idx, 1);\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n async _addTopoJson() {\r\n try {\r\n if (this.topojson.clearOnReload) this._clearTopoJson(this.topojson.id);\r\n const idx = this._topojsonLayers.findIndex(x => x.id === this.topojson.id);\r\n if (idx < 0) this._topojsonLayers.push({ id: this.topojson.id, features: [], labels: [], labelEls: [] });\r\n const topojsonLayer = this._topojsonLayers.find(x => x.id === this.topojson.id);\r\n\r\n const httpClient = new HttpClient();\r\n const response = await httpClient.get(this.topojson.url);\r\n const data = JSON.parse(response.response);\r\n let geojson = topojson.feature(data, data.objects[this.topojson.objectName]);\r\n if (this.topojson.includeIds && this.topojson.includeIds.length) {\r\n geojson.features = geojson.features.filter(x => this.topojson.includeIds.includes(x.id));\r\n }\r\n this._map.data.setStyle(this.topojson.style);\r\n if (this.topojson.click) {\r\n this._map.data.addListener('click', (event) => {\r\n if (this.topojson.click.callback) this.topojson.click.callback(event.feature);\r\n if (this.topojson.click.setStyle) {\r\n const style = this.topojson.click.setStyle(event.feature);\r\n if (style) this._map.data.overrideStyle(event.feature, style);\r\n else this._map.data.revertStyle(event.feature);\r\n }\r\n });\r\n }\r\n // if (this.topojson.label.minZoom) {\r\n // this._map.addListener('zoom_changed', () => {\r\n // const zoom = this._map.getZoom();\r\n // if (this.topojson.label.minZoom) {\r\n // if (zoom < this.topojson.label.minZoom) {\r\n // topojsonLayer.labels.forEach(l => l.setMap(null));\r\n // } else {\r\n // topojsonLayer.labels.forEach(l => l.setMap(this._map));\r\n // }\r\n // }\r\n // });\r\n // }\r\n // if (this.topojson.label) {\r\n // // add a point with a label for each geojson feature\r\n // geojson.features.forEach((f) => {\r\n // const centroid = turfCentroid(f.geometry);\r\n // const label = document.createElement('div');\r\n // label.classList.add(this.topojson.label.cssClass)\r\n // label.textContent = this.topojson.label.template(f);\r\n // const featureLabelMarker = new google.maps.marker.AdvancedMarkerElement({\r\n // map: this._map,\r\n // position: { lat: centroid.geometry.coordinates[1], lng: centroid.geometry.coordinates[0] },\r\n // content: label,\r\n // });\r\n // topojsonLayer.labels.push(featureLabelMarker);\r\n // topojsonLayer.labelEls.push(label);\r\n // });\r\n // }\r\n // if (this.topojson.mouseover) {\r\n // this._map.data.addListener('mouseover', (event) => {\r\n // if (this.topojson.mouseover.setStyle) {\r\n // const style = this.topojson.mouseover.setStyle(event.feature);\r\n // if (style) this._map.data.overrideStyle(event.feature, this.topojson.mouseover.style);\r\n // }\r\n // });\r\n // const mouseoutListener = this._map.data.addListener('mouseout', (event) => {\r\n // if (this.topojson.mouseover.setStyle) {\r\n // const style = this.topojson.mouseover.setStyle(event.feature);\r\n // if (style) this._map.data.revertStyle(event.feature);\r\n // }\r\n // });\r\n // }\r\n topojsonLayer.features = this._map.data.addGeoJson(geojson);\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n heatmapChanged() {\r\n if (!this.heatmap || !this.isMapLoaded) return;\r\n this._addHeatmap();\r\n }\r\n\r\n async _addHeatmap() {\r\n try {\r\n const data = [];\r\n this.heatmap.forEach(x => data.push(new google.maps.LatLng(x[1], x[0])));\r\n if (this._heatmapLayer) {\r\n this._heatmapLayer.setData(data);\r\n } else {\r\n this._heatmapLayer = new google.maps.visualization.HeatmapLayer({\r\n data,\r\n opacity: 0.75,\r\n });\r\n this._map.addListener('zoom_changed', () => {\r\n const radius = this._heatmapZoomRadius();\r\n this._heatmapLayer.setOptions({ radius });\r\n });\r\n this._heatmapLayer.setMap(this._map);\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _heatmapZoomRadius() {\r\n if (!this._map) return 20;\r\n const zoom = this._map.getZoom();\r\n if (zoom <= 3) return 5;\r\n if (zoom <= 4) return 10;\r\n if (zoom <= 5) return 13;\r\n if (zoom <= 6) return 16;\r\n if (zoom <= 7) return 19;\r\n if (zoom <= 8) return 25;\r\n if (zoom <= 9) return 45;\r\n if (zoom <= 10) return 75;\r\n if (zoom <= 11) return 125;\r\n return 175;\r\n }\r\n\r\n async gotoCurrentLocation() {\r\n try {\r\n const position = await this._currentLocation();\r\n this._map.setCenter(position);\r\n } catch (err) {\r\n console.log(err);\r\n this._notifier.error('Geolocation service in the browser failed');\r\n }\r\n }\r\n\r\n _currentLocation() {\r\n return new Promise((resolve, reject) => {\r\n if (!navigator.geolocation) {\r\n resolve(null);\r\n return;\r\n }\r\n try {\r\n navigator.geolocation.getCurrentPosition((position) => {\r\n const pos = {\r\n lat: position.coords.latitude,\r\n lng: position.coords.longitude,\r\n };\r\n this.currentLocation = { latitude: pos.lat, longitude: pos.lng };\r\n resolve(pos);\r\n return;\r\n },\r\n () => {\r\n reject();\r\n },\r\n );\r\n } catch (err) {\r\n console.log(err);\r\n reject();\r\n }\r\n });\r\n }\r\n\r\n async _centerMapOnCurrentLocation(zoom = 14) {\r\n try {\r\n const position = await this._currentLocation();\r\n if (!position) return;\r\n this._map.setOptions({ center: position, zoom });\r\n\r\n if (this._currentLocationMarker) {\r\n this._currentLocationMarker.setMap(this._map);\r\n this._currentLocationMarker.position = position;\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _addCurrentLocationControls() {\r\n try {\r\n const controlDiv = document.createElement('div');\r\n controlDiv.className = 'zeus-map-button-container';\r\n\r\n const locationButton = document.createElement('button');\r\n locationButton.className = 'zeus-map-button';\r\n locationButton.title = this._i18n.tr('map-your-location');\r\n controlDiv.appendChild(locationButton);\r\n \r\n const secondChild = document.createElement('i');\r\n secondChild.className = 'fas fa-crosshairs';\r\n locationButton.appendChild(secondChild);\r\n \r\n google.maps.event.addListener(this._map, 'center_changed', function () {\r\n secondChild.style['background-position'] = '0 0';\r\n });\r\n \r\n locationButton.addEventListener('click', () => this._centerMapOnCurrentLocation());\r\n \r\n controlDiv.index = 1;\r\n this._map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);\r\n\r\n // Add pulsing marker\r\n const locationSvgString = ``;\r\n const locationSvg = this._domParser.parseFromString(locationSvgString, 'image/svg+xml').documentElement;\r\n\r\n this._currentLocationMarker = new google.maps.marker.AdvancedMarkerElement({\r\n position: new google.maps.LatLng(0, 0),\r\n draggable: false,\r\n content: locationSvg,\r\n });\r\n this._currentLocationMarker.content.style.transform = 'translate(10%, 10%)';\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n async _initializeMap() {\r\n try {\r\n await this._google.load();\r\n const center = { lat: 40.26114, lng: -99.30101 };\r\n const zoom = Number(this.zoom);\r\n const options = { mapId: 'LPFN_MAP', center, zoom, gestureHandling: 'greedy', fullscreenControl: this.allowFullScreen };\r\n this._map = new google.maps.Map(this.slippyMapEl, options);\r\n this._addCurrentLocationControls();\r\n this._centerMapOnCurrentLocation(zoom);\r\n this._map.addListener('idle', () => this._setMarkerCluster());\r\n this._map.addListener('center_changed', (e) => this._clearMarkerCluster(e));\r\n //this._map.addListener('zoom_changed', () => { console.log(this._map.getZoom()); });\r\n if (this._loadMarkers) this.markersChanged();\r\n if (this.topojson) this._addTopoJson();\r\n if (this.geojson) this._addGeojson();\r\n if (this.heatmap && this.heatmap.length) this._addHeatmap();\r\n this._panorama = this._map.getStreetView();\r\n this._panorama.addListener('position_changed', () => this._setStreetViewHeading());\r\n this._panorama.addListener('status_changed', () => this._streetViewStatusChanged());\r\n this._panorama.addListener('visible_changed', () => {\r\n if (this._panorama && !this._panorama.getVisible()) {\r\n this._element.dispatchEvent(new CustomEvent('streetview-closed', { bubbles: true, detail: { streetView: this.streetView } }));\r\n }\r\n });\r\n\r\n this._infoWindow = new google.maps.InfoWindow({});\r\n if (this.selectWithDrawingTools) {\r\n this._addDrawingTools();\r\n }\r\n if (this.selectWithCounties) {\r\n this._addCounties();\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _addDrawingTools() {\r\n this._drawingMgr = new google.maps.drawing.DrawingManager({\r\n drawingMode: null,\r\n drawingControl: true,\r\n drawingControlOptions: {\r\n position: google.maps.ControlPosition.TOP_CENTER,\r\n drawingModes: [\r\n google.maps.drawing.OverlayType.CIRCLE,\r\n google.maps.drawing.OverlayType.POLYGON,\r\n google.maps.drawing.OverlayType.RECTANGLE,\r\n ]\r\n },\r\n circleOptions: {\r\n fillColor: '#ffffff',\r\n fillOpacity: 0.2,\r\n strokeWeight: 1,\r\n clickable: false,\r\n draggable: true,\r\n editable: true,\r\n zIndex: 1,\r\n },\r\n polygonOptions: {\r\n fillColor: '#ffffff',\r\n fillOpacity: 0.2,\r\n strokeWeight: 1,\r\n clickable: false,\r\n draggable: true,\r\n editable: true,\r\n zIndex: 1,\r\n },\r\n rectangleOptions: {\r\n fillColor: '#ffffff',\r\n fillOpacity: 0.2,\r\n strokeWeight: 1,\r\n clickable: false,\r\n draggable: true,\r\n editable: true,\r\n zIndex: 1,\r\n }\r\n });\r\n this._drawingMgr.setMap(this._map);\r\n google.maps.event.addListener(this._drawingMgr, 'overlaycomplete', (event) => {\r\n if (this._drawing) {\r\n this._drawing.setMap(null);\r\n this._drawing = null;\r\n }\r\n this._drawing = event.overlay;\r\n this._drawing.type = event.type;\r\n this._drawingChanged();\r\n\r\n switch (event.type) {\r\n case 'polygon':\r\n google.maps.event.addListener(this._drawing, 'mouseup', this._drawingChanged);\r\n break;\r\n case 'rectangle':\r\n case 'circle':\r\n this._drawing.addListener('bounds_changed', this._drawingChanged);\r\n break;\r\n }\r\n this._drawingMgr.setOptions({\r\n drawingMode: null\r\n });\r\n });\r\n const clearBtn = document.createElement('button');\r\n clearBtn.classList.add('zeus-gmap-btn');\r\n clearBtn.classList.add('zeus-gmap-top');\r\n clearBtn.innerHTML = '';\r\n clearBtn.addEventListener('click', () => {\r\n if (!this._drawing) return;\r\n this._drawing.setMap(null);\r\n this._drawing = null;\r\n });\r\n this._map.controls[google.maps.ControlPosition.TOP_CENTER].push(clearBtn);\r\n }\r\n\r\n _drawingChanged = (ev) => {\r\n try {\r\n if (this._mapMarkers) {\r\n let polygon = new google.maps.Polygon();\r\n switch (this._drawing.type) {\r\n case 'circle':\r\n const numSides = 60;\r\n const circlePoints = [];\r\n const angleStep = 360 / numSides;\r\n \r\n for (let i = 0; i < numSides; i++) {\r\n const angle = i * angleStep;\r\n const radian = angle * (Math.PI / 180);\r\n const lat = this._drawing.center.lat() + (this._drawing.radius * Math.cos(radian)) / 111320; // 111320 meters per degree latitude\r\n const lng = this._drawing.center.lng() + (this._drawing.radius * Math.sin(radian)) / (111320 * Math.cos(this._drawing.center.lat() * (Math.PI / 180)));\r\n circlePoints.push(new google.maps.LatLng(lat, lng));\r\n }\r\n polygon.setPath(circlePoints);\r\n break;\r\n case 'polygon':\r\n polygon.setPaths(this._drawing.getPaths());\r\n break;\r\n case 'rectangle':\r\n const bounds = this._drawing.getBounds();\r\n const ne = bounds.getNorthEast();\r\n const sw = bounds.getSouthWest();\r\n const nw = new google.maps.LatLng(ne.lat(), sw.lng());\r\n const se = new google.maps.LatLng(sw.lat(), ne.lng());\r\n \r\n const polygonCoords = [nw, ne, se, sw];\r\n polygon.setPaths(polygonCoords);\r\n break;\r\n }\r\n\r\n this._selectMapMarkersWithinPolygon(polygon);\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n };\r\n\r\n _selectMapMarkersWithinPolygon(polygon) {\r\n for (let i = 0; i < this._mapMarkers.length; i++) {\r\n const isInside = google.maps.geometry.poly.containsLocation(this._mapMarkers[i].marker.position, polygon);\r\n if (!isInside) continue;\r\n this._mapMarkers[i].selected = false; // set to false, _onMarkerClick will set to true to select it\r\n this._onMarkerClick(this._mapMarkers[i], false, false, true);\r\n }\r\n this._publishMarkersSelected();\r\n }\r\n\r\n async _addCounties() {\r\n try {\r\n this._countiesVisibleStyle = {\r\n clickable: true,\r\n cursor: 'pointer',\r\n fillColor: '#ffffff',\r\n fillOpacity: 0.2,\r\n strokeColor: '#000000',\r\n strokeOpacity: 0.6,\r\n strokeWeight: 1,\r\n visible: true,\r\n };\r\n this._countiesHiddenStyle = {\r\n visible: false,\r\n };\r\n this._countiesData = new google.maps.Data({\r\n style: this._countiesHiddenStyle,\r\n });\r\n this._countiesData.addGeoJson(await this._geography.geojson.usCounties());\r\n this._countiesData.addListener('click', this._onCountyClick);\r\n this._countiesData.setMap(this._map);\r\n this._map.addListener('zoom_changed', this._countiesZoomChanged);\r\n\r\n this._countiesLabels = [];\r\n this._countiesData.forEach(f => {\r\n f.toGeoJson(gj => {\r\n try {\r\n const centroid = turfCentroid(gj);\r\n const lat = centroid.geometry.coordinates[1];\r\n const lng = centroid.geometry.coordinates[0];\r\n const label = document.createElement('div');\r\n label.classList.add('zeus-map-label');\r\n label.textContent = gj.properties.name;\r\n const featureLabelMarker = new google.maps.marker.AdvancedMarkerElement({\r\n map: null,\r\n position: { lat, lng },\r\n content: label,\r\n });\r\n this._countiesLabels.push({ id: f.id, el: label, marker: featureLabelMarker });\r\n } catch (iErr) {\r\n console.log(iErr);\r\n }\r\n });\r\n });\r\n\r\n this._countiesZoomChanged();\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _countiesZoomChanged = () => {\r\n try {\r\n const zoom = this._map.getZoom();\r\n const currentStyle = this._countiesData.getStyle();\r\n if (zoom >= 7) {\r\n if (!currentStyle.visible) {\r\n this._countiesData.setStyle(this._countiesVisibleStyle);\r\n }\r\n } else {\r\n if (currentStyle.visible) {\r\n this._countiesData.setStyle(this._countiesHiddenStyle);\r\n }\r\n }\r\n if (zoom >= 9) {\r\n if (this._countiesLabels.length && !this._countiesLabels[0].marker.map) {\r\n this._countiesLabels.forEach(l => l.marker.setMap(this._map));\r\n }\r\n } else {\r\n if (this._countiesLabels.length && this._countiesLabels[0].marker.map) {\r\n this._countiesLabels.forEach(l => l.marker.setMap(null));\r\n }\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _onCountyClick = (ev) => {\r\n try {\r\n const geometry = ev.feature.getGeometry();\r\n let polygon = new google.maps.Polygon();\r\n const latLngs = [];\r\n geometry.forEachLatLng(latLng => latLngs.push(latLng));\r\n polygon.setPath(latLngs);\r\n this._selectMapMarkersWithinPolygon(polygon);\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n async _createInfoWindow(event, content) {\r\n try {\r\n this._infoWindow.setContent(content);\r\n this._infoWindow.setPosition(event.latLng);\r\n this._infoWindow.open({ map: this._map, shouldFocus: false });\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _streetViewStatusChanged() {\r\n if (!this._panorama || !this.streetView) return;\r\n try {\r\n const status = this._panorama.getStatus();\r\n if (status === google.maps.StreetViewStatus.ZERO_RESULTS || status === google.maps.StreetViewStatus.UNKNOWN_ERROR) {\r\n this._notifier.info('map-street-view-not-found');\r\n }\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _setStreetViewHeading() {\r\n if (!this._panorama || !this.streetView) return;\r\n try {\r\n const panoramaPosition = this._panorama.getPosition().toJSON();\r\n const streetViewPosition = { lat: this.streetView.latitude, lng: this.streetView.longitude };\r\n const heading = this._getHeadingDegrees(panoramaPosition, streetViewPosition);\r\n this._panorama.setPov({ heading, pitch: 0 });\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n _getHeadingDegrees(gps1, gps2) {\r\n let dLon = (gps2.lng - gps1.lng) * Math.PI / 180;\r\n\r\n let lat1 = gps1.lat * Math.PI / 180;\r\n let lat2 = gps2.lat * Math.PI / 180;\r\n \r\n let y = Math.sin(dLon) * Math.cos(gps2.lat);\r\n let x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);\r\n \r\n let rad = Math.atan2(y, x);\r\n let deg = rad * 180 / Math.PI;\r\n\r\n return deg * -1;\r\n }\r\n}\r\n","import { bindable } from 'aurelia-framework';\r\nimport { Geography } from 'services/geography';\r\n\r\nexport class UsCountySelector {\r\n static inject = [Element, Geography];\r\n _element;\r\n _geography;\r\n\r\n @bindable type = 'counties';\r\n\r\n selectedUsCounties = [];\r\n\r\n constructor(element, geography) {\r\n this._element = element;\r\n this._geography = geography;\r\n this._initializeCounties();\r\n }\r\n\r\n _initializeCounties() {\r\n this.usCountiesTopo = this._geography.topojson.usCounties(\r\n {\r\n strokeColor: 'red',\r\n strokeOpacity: 1,\r\n strokeWeight: 1,\r\n fillColor: 'transparent',\r\n fillOpacity: 'transparent',\r\n },\r\n 8,\r\n (feature) => {\r\n // if the feature is selected, return null for the mouseover style so the map doesn't reset the style\r\n if (this.selectedUsCounties.includes(feature.getId())) return null;\r\n return { fillColor: 'red', fillOpacity: 0.25 };\r\n },\r\n (feature) => {\r\n if (this.selectedUsCounties.includes(feature.getId())) {\r\n return { fillColor: 'red', fillOpacity: 0.5 };\r\n }\r\n return null;\r\n },\r\n (feature) => {\r\n const fips = feature.getId();\r\n const idx = this.selectedUsCounties.indexOf(fips);\r\n if (idx >= 0) this.selectedUsCounties.splice(idx, 1);\r\n else this.selectedUsCounties.push(fips);\r\n },\r\n );\r\n console.log(this.usCountiesTopox);\r\n }\r\n\r\n async selectCounties() {\r\n try {\r\n let detail;\r\n if (this.type === 'zips') {\r\n detail = await this._geography.zips(this.selectedUsCounties);\r\n this.zips = detail;\r\n } else {\r\n detail = await this._geography.countiesByFips(this.selectedUsCounties);\r\n }\r\n this._element.dispatchEvent(new CustomEvent('selected', { bubbles: true, detail }));\r\n } catch (err) {\r\n console.log(err);\r\n }\r\n }\r\n\r\n clearCounties() {\r\n this.selectedUsCounties = [];\r\n this.resetTopojsonStyles = new Date().valueOf();\r\n this.zips = [];\r\n }\r\n}","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"slippy-map {\\n display: flex;\\n width: 100%;\\n height: 100%;\\n}\\n\\n.zeus-slippyMap {\\n display: flex;\\n width: 100%;\\n height: 100%;\\n}\\n\\n.zeus-map-label {\\n padding: 4px;\\n border-radius: 4px;\\n background-color: white;\\n color: black;\\n font-size: 0.9em;\\n}\\n\\n.zeus-map-button-container .zeus-map-button {\\n background-color: #fff;\\n border: none;\\n outline: none;\\n width: 40px;\\n height: 40px;\\n border-radius: 2px;\\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\\n cursor: pointer;\\n margin-right: 10px;\\n padding: 0;\\n font-size: 25px;\\n color: #777;\\n}\\n.zeus-map-button-container .zeus-map-button:hover {\\n color: #000;\\n}\\n\\n.zeus-current-location-pulse {\\n display: block;\\n border-radius: 50%;\\n cursor: pointer;\\n animation: currentLocationPulse 2s infinite;\\n}\\n\\n.zeus-gmap-btn {\\n width: 28px;\\n height: 28px;\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n border: 1px solid #cccccc;\\n background: white;\\n}\\n.zeus-gmap-btn.zeus-gmap-top {\\n margin-top: 5px;\\n}\\n\\n@keyframes currentLocationPulse {\\n 0% {\\n -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.4);\\n box-shadow: 0 0 0 0;\\n }\\n 70% {\\n -moz-box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);\\n box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);\\n }\\n 100% {\\n -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);\\n box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);\\n }\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/slippy-map/slippy-map.scss\"],\"names\":[],\"mappings\":\"AAAA;EACI,aAAA;EACA,WAAA;EACA,YAAA;AACJ;;AAEA;EACI,aAAA;EACA,WAAA;EACA,YAAA;AACJ;;AAEA;EACI,YAAA;EACA,kBAAA;EACA,uBAAA;EACA,YAAA;EACA,gBAAA;AACJ;;AAGI;EACI,sBAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;EACA,wCAAA;EACA,eAAA;EACA,kBAAA;EACA,UAAA;EACA,eAAA;EACA,WAAA;AAAR;AAEQ;EACI,WAAA;AAAZ;;AAKA;EACI,cAAA;EACA,kBAAA;EACA,eAAA;EACA,2CAAA;AAFJ;;AAKA;EACI,WAAA;EACA,YAAA;EACA,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,yBAAA;EACA,iBAAA;AAFJ;AAII;EACI,eAAA;AAFR;;AAMA;EACI;IACE,2CAAA;IACA,mBAAA;EAHJ;EAKE;IACE,4CAAA;IACC,uCAAA;EAHL;EAKE;IACE,yCAAA;IACC,oCAAA;EAHL;AACF\",\"sourcesContent\":[\"slippy-map {\\r\\n display: flex;\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n}\\r\\n\\r\\n.zeus-slippyMap {\\r\\n display: flex;\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n}\\r\\n\\r\\n.zeus-map-label {\\r\\n padding: 4px;\\r\\n border-radius: 4px;\\r\\n background-color: white;\\r\\n color: black;\\r\\n font-size: 0.9em;\\r\\n}\\r\\n\\r\\n.zeus-map-button-container {\\r\\n .zeus-map-button {\\r\\n background-color: #fff;\\r\\n border: none;\\r\\n outline: none;\\r\\n width: 40px;\\r\\n height: 40px;\\r\\n border-radius: 2px;\\r\\n box-shadow: 0 1px 4px rgba(0,0,0,0.3);\\r\\n cursor: pointer;\\r\\n margin-right: 10px;\\r\\n padding: 0;\\r\\n font-size: 25px;\\r\\n color: #777;\\r\\n\\r\\n &:hover {\\r\\n color: #000;\\r\\n }\\r\\n }\\r\\n}\\r\\n\\r\\n.zeus-current-location-pulse {\\r\\n display: block;\\r\\n border-radius: 50%;\\r\\n cursor: pointer;\\r\\n animation: currentLocationPulse 2s infinite;\\r\\n}\\r\\n\\r\\n.zeus-gmap-btn {\\r\\n width: 28px;\\r\\n height: 28px;\\r\\n display: flex;\\r\\n justify-content: center;\\r\\n align-items: center;\\r\\n border: 1px solid #cccccc;\\r\\n background: white;\\r\\n\\r\\n &.zeus-gmap-top {\\r\\n margin-top: 5px;\\r\\n }\\r\\n}\\r\\n \\r\\n@keyframes currentLocationPulse {\\r\\n 0% {\\r\\n -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.4);\\r\\n box-shadow: 0 0 0 0;\\r\\n }\\r\\n 70% {\\r\\n -moz-box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);\\r\\n box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);\\r\\n }\\r\\n 100% {\\r\\n -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);\\r\\n box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);\\r\\n }\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".zeus-county-map-container {\\n display: flex;\\n width: 100%;\\n height: 100%;\\n min-height: 250px;\\n margin-bottom: var(--zeus-space);\\n}\\n\\n.zeus-county-label {\\n padding: 4px;\\n border-radius: 4px;\\n background-color: white;\\n color: black;\\n font-size: 0.9em;\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/slippy-map/us-county-selector.scss\"],\"names\":[],\"mappings\":\"AAAA;EACI,aAAA;EACA,WAAA;EACA,YAAA;EACA,iBAAA;EACA,gCAAA;AACJ;;AAEA;EACI,YAAA;EACA,kBAAA;EACA,uBAAA;EACA,YAAA;EACA,gBAAA;AACJ\",\"sourcesContent\":[\".zeus-county-map-container {\\r\\n display: flex;\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n min-height: 250px;\\r\\n margin-bottom: var(--zeus-space);\\r\\n}\\r\\n\\r\\n.zeus-county-label {\\r\\n padding: 4px;\\r\\n border-radius: 4px;\\r\\n background-color: white;\\r\\n color: black;\\r\\n font-size: 0.9em;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Module\nvar code = \"\\r\\n \\r\\n \\r\\n\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n ${zip}\\r\\n\";\n// Exports\nexport default code;"],"names":[],"sourceRoot":""}