import maplibregl from "maplibre-gl" const defaultStyle = { version: 8, sources: { osm: { type: "raster", tiles: [document.documentElement.dataset.mapTileUrl], tileSize: 256, attribution: "© OpenStreetMap contributors" } }, layers: [{id: "osm", type: "raster", source: "osm"}] } export const Hooks = { AidMap: { mounted() { this.markers = [] this.map = new maplibregl.Map({ container: this.el, style: defaultStyle, center: [30.5234, 50.4501], zoom: 5 }) this.map.addControl(new maplibregl.NavigationControl(), "top-right") this.markLoading = () => { this.el.dataset.mapReady = "false" } this.markReady = () => { this.el.dataset.mapReady = "true" } this.map.on("dataloading", this.markLoading) this.map.on("idle", this.markReady) this.renderMarkers() }, updated() { this.renderMarkers() }, destroyed() { this.map?.off("dataloading", this.markLoading) this.map?.off("idle", this.markReady) this.map?.remove() }, renderMarkers() { if (!this.map) return this.markers.forEach(marker => marker.remove()) this.markers = [] const points = JSON.parse(this.el.dataset.markers || "[]") points.forEach(point => { const popup = new maplibregl.Popup({offset: 18}).setHTML( `${escapeHtml(point.title)}
${escapeHtml(point.location)}` ) const marker = new maplibregl.Marker({color: point.exact ? "#d6573b" : "#278467"}) .setLngLat([point.longitude, point.latitude]) .setPopup(popup) .addTo(this.map) this.markers.push(marker) }) if (points.length === 1) { this.map.flyTo({center: [points[0].longitude, points[0].latitude], zoom: 12}) } else if (points.length > 1) { const bounds = new maplibregl.LngLatBounds() points.forEach(point => bounds.extend([point.longitude, point.latitude])) this.map.fitBounds(bounds, {padding: 52, maxZoom: 13}) } } }, LocationPicker: { mounted() { this.el.addEventListener("click", () => { navigator.geolocation.getCurrentPosition( position => { document.querySelector("#request-latitude").value = position.coords.latitude document.querySelector("#request-longitude").value = position.coords.longitude this.el.textContent = "Location added" this.el.classList.add("btn-success") }, () => { this.el.textContent = "Location permission denied" this.el.classList.add("btn-error") }, {enableHighAccuracy: true, timeout: 10000} ) }) } }, LiveTracking: { mounted() { this.destroying = false if (window.WhoNeedHelpAndroid) { this.nativeError = () => { this.pushEvent("location-error", {}) this.pushEvent("stop-tracking", {}) } window.addEventListener("wnh:native-tracking-error", this.nativeError) return } this.watchId = navigator.geolocation.watchPosition( position => this.pushEvent("location-update", { latitude: position.coords.latitude, longitude: position.coords.longitude, accuracy_meters: position.coords.accuracy }), () => { if (!this.destroying) this.pushEvent("location-error", {}) }, {enableHighAccuracy: true, maximumAge: 5000, timeout: 15000} ) }, destroyed() { this.destroying = true if (this.nativeError) { window.removeEventListener("wnh:native-tracking-error", this.nativeError) } if (this.watchId !== undefined) navigator.geolocation.clearWatch(this.watchId) } } } function escapeHtml(value) { const node = document.createElement("div") node.textContent = value || "" return node.innerHTML }