import { Controller } from 'stimulus' require("leaflet/dist/leaflet.css") import L from 'leaflet' delete L.Icon.Default.prototype._getIconUrl L.Icon.Default.mergeOptions({ iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'), iconUrl: require('leaflet/dist/images/marker-icon.png'), shadowUrl: require('leaflet/dist/images/marker-shadow.png'), }) export default class extends Controller { static targets = [ 'lat', 'lng', 'map', 'overlay' ] async connect () { const res = await fetch(this.element.dataset.map); this.overlayTarget.innerHTML = await res.text(); this.marker() this.latTarget.addEventListener('change', event => this.marker()) this.lngTarget.addEventListener('change', event => this.marker()) window.addEventListener('resize', event => this.map.invalidateSize()) this.map.on('click', event => { this.latTarget.value = event.latlng.lat this.lngTarget.value = event.latlng.lng this.latTarget.dispatchEvent(new Event('change')) }) } marker () { if (this._marker) this.map.removeLayer(this._marker) this._marker = L.marker(this.coords).addTo(this.map) return this._marker } get lat () { const lat = parseFloat(this.latTarget.value) return isNaN(lat) ? 0 : lat } get lng () { const lng = parseFloat(this.lngTarget.value) return isNaN(lng) ? 0 : lng } get coords () { return [this.lat, this.lng] } get svgOverlay () { return this.overlayTarget.querySelector('svg'); } get bounds () { return [ [0, 0], [ this.svgOverlay.viewBox.baseVal.height, this.svgOverlay.viewBox.baseVal.width, ] ]; } get map () { if (!this._map) { this._map = L.map(this.mapTarget).setView(this.coords, 13); L.svgOverlay(this.svgOverlay, this.bounds).addTo(this._map); this._map.fitBounds(bounds); this._map.setMaxBounds(bounds); } return this._map } }