| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import { Utils } from "../../Utils" | 
					
						
							|  |  |  | import BaseUIElement from "../BaseUIElement" | 
					
						
							|  |  |  | import { UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  | import Loc from "../../Models/Loc" | 
					
						
							|  |  |  | import BaseLayer from "../../Models/BaseLayer" | 
					
						
							|  |  |  | import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" | 
					
						
							|  |  |  | import * as L from "leaflet" | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  | import { LeafletMouseEvent, Map } from "leaflet" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import Minimap, { MinimapObj, MinimapOptions } from "./Minimap" | 
					
						
							|  |  |  | import { BBox } from "../../Logic/BBox" | 
					
						
							|  |  |  | import "leaflet-polylineoffset" | 
					
						
							|  |  |  | import { SimpleMapScreenshoter } from "leaflet-simple-map-screenshoter" | 
					
						
							|  |  |  | import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" | 
					
						
							|  |  |  | import AvailableBaseLayersImplementation from "../../Logic/Actors/AvailableBaseLayersImplementation" | 
					
						
							|  |  |  | import ShowDataLayer from "../ShowDataLayer/ShowDataLayer" | 
					
						
							|  |  |  | import ShowDataLayerImplementation from "../ShowDataLayer/ShowDataLayerImplementation" | 
					
						
							| 
									
										
										
										
											2022-12-24 03:44:21 +01:00
										 |  |  | import FilteredLayer from "../../Models/FilteredLayer" | 
					
						
							|  |  |  | import ScrollableFullScreen from "./ScrollableFullScreen" | 
					
						
							|  |  |  | import Constants from "../../Models/Constants" | 
					
						
							|  |  |  | import StrayClickHandler from "../../Logic/Actors/StrayClickHandler" | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 03:44:21 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * The stray-click-hanlders adds a marker to the map if no feature was clicked. | 
					
						
							|  |  |  |  * Shows the given uiToShow-element in the messagebox | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export class StrayClickHandlerImplementation { | 
					
						
							|  |  |  |     private _lastMarker | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         state: { | 
					
						
							|  |  |  |             LastClickLocation: UIEventSource<{ lat: number; lon: number }> | 
					
						
							|  |  |  |             selectedElement: UIEventSource<string> | 
					
						
							|  |  |  |             filteredLayers: UIEventSource<FilteredLayer[]> | 
					
						
							|  |  |  |             leafletMap: UIEventSource<L.Map> | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         uiToShow: ScrollableFullScreen, | 
					
						
							|  |  |  |         iconToShow: BaseUIElement | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         const self = this | 
					
						
							|  |  |  |         const leafletMap = state.leafletMap | 
					
						
							|  |  |  |         state.filteredLayers.data.forEach((filteredLayer) => { | 
					
						
							|  |  |  |             filteredLayer.isDisplayed.addCallback((isEnabled) => { | 
					
						
							|  |  |  |                 if (isEnabled && self._lastMarker && leafletMap.data !== undefined) { | 
					
						
							|  |  |  |                     // When a layer is activated, we remove the 'last click location' in order to force the user to reclick
 | 
					
						
							|  |  |  |                     // This reclick might be at a location where a feature now appeared...
 | 
					
						
							|  |  |  |                     state.leafletMap.data.removeLayer(self._lastMarker) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         state.LastClickLocation.addCallback(function (lastClick) { | 
					
						
							|  |  |  |             if (self._lastMarker !== undefined) { | 
					
						
							|  |  |  |                 state.leafletMap.data?.removeLayer(self._lastMarker) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (lastClick === undefined) { | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             state.selectedElement.setData(undefined) | 
					
						
							|  |  |  |             const clickCoor: [number, number] = [lastClick.lat, lastClick.lon] | 
					
						
							|  |  |  |             self._lastMarker = L.marker(clickCoor, { | 
					
						
							|  |  |  |                 icon: L.divIcon({ | 
					
						
							|  |  |  |                     html: iconToShow.ConstructElement(), | 
					
						
							|  |  |  |                     iconSize: [50, 50], | 
					
						
							|  |  |  |                     iconAnchor: [25, 50], | 
					
						
							|  |  |  |                     popupAnchor: [0, -45], | 
					
						
							|  |  |  |                 }), | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self._lastMarker.addTo(leafletMap.data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self._lastMarker.on("click", () => { | 
					
						
							|  |  |  |                 if (leafletMap.data.getZoom() < Constants.userJourney.minZoomLevelToAddNewPoints) { | 
					
						
							|  |  |  |                     leafletMap.data.flyTo( | 
					
						
							|  |  |  |                         clickCoor, | 
					
						
							|  |  |  |                         Constants.userJourney.minZoomLevelToAddNewPoints | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 uiToShow.Activate() | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         state.selectedElement.addCallback(() => { | 
					
						
							|  |  |  |             if (self._lastMarker !== undefined) { | 
					
						
							|  |  |  |                 leafletMap.data.removeLayer(self._lastMarker) | 
					
						
							|  |  |  |                 this._lastMarker = undefined | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | export default class MinimapImplementation extends BaseUIElement implements MinimapObj { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private static _nextId = 0 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     public readonly leafletMap: UIEventSource<Map> | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public readonly location: UIEventSource<Loc> | 
					
						
							|  |  |  |     public readonly bounds: UIEventSource<BBox> | undefined | 
					
						
							|  |  |  |     private readonly _id: string | 
					
						
							|  |  |  |     private readonly _background: UIEventSource<BaseLayer> | 
					
						
							|  |  |  |     private _isInited = false | 
					
						
							|  |  |  |     private _allowMoving: boolean | 
					
						
							|  |  |  |     private readonly _leafletoptions: any | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     private readonly _onFullyLoaded: (leaflet: L.Map) => void | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _attribution: BaseUIElement | boolean | 
					
						
							|  |  |  |     private readonly _addLayerControl: boolean | 
					
						
							|  |  |  |     private readonly _options: MinimapOptions | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  |     private constructor(options?: MinimapOptions) { | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         super() | 
					
						
							|  |  |  |         options = options ?? {} | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._id = "minimap" + MinimapImplementation._nextId | 
					
						
							| 
									
										
										
										
											2022-06-29 16:22:33 +02:00
										 |  |  |         MinimapImplementation._nextId++ | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         this.leafletMap = options.leafletMap ?? new UIEventSource<Map>(undefined) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._background = | 
					
						
							|  |  |  |             options?.background ?? new UIEventSource<BaseLayer>(AvailableBaseLayers.osmCarto) | 
					
						
							|  |  |  |         this.location = options?.location ?? new UIEventSource<Loc>({ lat: 0, lon: 0, zoom: 1 }) | 
					
						
							|  |  |  |         this.bounds = options?.bounds | 
					
						
							|  |  |  |         this._allowMoving = options.allowMoving ?? true | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         this._leafletoptions = options.leafletOptions ?? {} | 
					
						
							|  |  |  |         this._onFullyLoaded = options.onFullyLoaded | 
					
						
							|  |  |  |         this._attribution = options.attribution | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |         this._addLayerControl = options.addLayerControl ?? false | 
					
						
							| 
									
										
										
										
											2022-01-08 20:02:07 +01:00
										 |  |  |         this._options = options | 
					
						
							| 
									
										
										
										
											2022-02-11 01:20:01 +01:00
										 |  |  |         this.SetClass("relative") | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public static initialize() { | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |         AvailableBaseLayers.implement(new AvailableBaseLayersImplementation()) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         Minimap.createMiniMap = (options) => new MinimapImplementation(options) | 
					
						
							|  |  |  |         ShowDataLayer.actualContstructor = (options) => new ShowDataLayerImplementation(options) | 
					
						
							| 
									
										
										
										
											2022-12-24 03:44:21 +01:00
										 |  |  |         StrayClickHandler.construct = ( | 
					
						
							|  |  |  |             state: { | 
					
						
							|  |  |  |                 LastClickLocation: UIEventSource<{ lat: number; lon: number }> | 
					
						
							|  |  |  |                 selectedElement: UIEventSource<string> | 
					
						
							|  |  |  |                 filteredLayers: UIEventSource<FilteredLayer[]> | 
					
						
							|  |  |  |                 leafletMap: UIEventSource<L.Map> | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             uiToShow: ScrollableFullScreen, | 
					
						
							|  |  |  |             iconToShow: BaseUIElement | 
					
						
							|  |  |  |         ) => { | 
					
						
							|  |  |  |             return new StrayClickHandlerImplementation(state, uiToShow, iconToShow) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |     public installBounds(factor: number | BBox, showRange?: boolean) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.leafletMap.addCallbackD((leaflet) => { | 
					
						
							|  |  |  |             let bounds: { getEast(); getNorth(); getWest(); getSouth() } | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |             if (typeof factor === "number") { | 
					
						
							| 
									
										
										
										
											2022-02-01 04:14:54 +01:00
										 |  |  |                 const lbounds = leaflet.getBounds().pad(factor) | 
					
						
							|  |  |  |                 leaflet.setMaxBounds(lbounds) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 bounds = lbounds | 
					
						
							| 
									
										
										
										
											2021-09-22 20:44:53 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 // @ts-ignore
 | 
					
						
							|  |  |  |                 leaflet.setMaxBounds(factor.toLeaflet()) | 
					
						
							| 
									
										
										
										
											2022-02-01 04:14:54 +01:00
										 |  |  |                 bounds = factor | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (showRange) { | 
					
						
							|  |  |  |                 const data = { | 
					
						
							|  |  |  |                     type: "FeatureCollection", | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     features: [ | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             type: "Feature", | 
					
						
							|  |  |  |                             geometry: { | 
					
						
							|  |  |  |                                 type: "LineString", | 
					
						
							|  |  |  |                                 coordinates: [ | 
					
						
							|  |  |  |                                     [bounds.getEast(), bounds.getNorth()], | 
					
						
							|  |  |  |                                     [bounds.getWest(), bounds.getNorth()], | 
					
						
							|  |  |  |                                     [bounds.getWest(), bounds.getSouth()], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                                     [bounds.getEast(), bounds.getSouth()], | 
					
						
							|  |  |  |                                     [bounds.getEast(), bounds.getNorth()], | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                                 ], | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             }, | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                     ], | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 // @ts-ignore
 | 
					
						
							|  |  |  |                 L.geoJSON(data, { | 
					
						
							|  |  |  |                     style: { | 
					
						
							| 
									
										
										
										
											2022-01-25 21:55:51 +01:00
										 |  |  |                         color: "#f44", | 
					
						
							|  |  |  |                         weight: 4, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         opacity: 0.7, | 
					
						
							|  |  |  |                     }, | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 }).addTo(leaflet) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |     Destroy() { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         super.Destroy() | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |         console.warn("Decomissioning minimap", this._id) | 
					
						
							|  |  |  |         const mp = this.leafletMap.data | 
					
						
							|  |  |  |         this.leafletMap.setData(null) | 
					
						
							|  |  |  |         mp.off() | 
					
						
							|  |  |  |         mp.remove() | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-12 20:14:03 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Takes a screenshot of the current map | 
					
						
							|  |  |  |      * @param format: image: give a base64 encoded png image; | 
					
						
							|  |  |  |      * @constructor | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |     public async TakeScreenshot(): Promise<string> | 
					
						
							|  |  |  |     public async TakeScreenshot(format: "image"): Promise<string> | 
					
						
							|  |  |  |     public async TakeScreenshot(format: "blob"): Promise<Blob> | 
					
						
							|  |  |  |     public async TakeScreenshot(format: "image" | "blob"): Promise<string | Blob> | 
					
						
							| 
									
										
										
										
											2022-09-12 20:14:03 +02:00
										 |  |  |     public async TakeScreenshot(format: "image" | "blob" = "image"): Promise<string | Blob> { | 
					
						
							| 
									
										
										
										
											2022-09-18 12:45:02 +02:00
										 |  |  |         console.log("Taking a screenshot...") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const screenshotter = new SimpleMapScreenshoter() | 
					
						
							|  |  |  |         screenshotter.addTo(this.leafletMap.data) | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         const result = <any>await screenshotter.takeScreen(<any>format ?? "image") | 
					
						
							|  |  |  |         if (format === "image" && typeof result === "string") { | 
					
						
							| 
									
										
										
										
											2022-09-12 20:14:03 +02:00
										 |  |  |             return result | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         if (format === "blob" && result instanceof Blob) { | 
					
						
							| 
									
										
										
										
											2022-09-12 20:14:03 +02:00
										 |  |  |             return result | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         throw "Something went wrong while creating the screenshot: " + result | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     protected InnerConstructElement(): HTMLElement { | 
					
						
							|  |  |  |         const div = document.createElement("div") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         div.id = this._id | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         div.style.height = "100%" | 
					
						
							|  |  |  |         div.style.width = "100%" | 
					
						
							|  |  |  |         div.style.minWidth = "40px" | 
					
						
							|  |  |  |         div.style.minHeight = "40px" | 
					
						
							|  |  |  |         div.style.position = "relative" | 
					
						
							|  |  |  |         const wrapper = document.createElement("div") | 
					
						
							|  |  |  |         wrapper.appendChild(div) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const resizeObserver = new ResizeObserver((_) => { | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |             if (wrapper.clientHeight === 0 || wrapper.clientWidth === 0) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             if ( | 
					
						
							|  |  |  |                 wrapper.offsetParent === null || | 
					
						
							|  |  |  |                 window.getComputedStyle(wrapper).display === "none" | 
					
						
							|  |  |  |             ) { | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |                 // Not visible
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-22 20:44:53 +02:00
										 |  |  |             try { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 self.InitMap() | 
					
						
							| 
									
										
										
										
											2021-09-22 20:44:53 +02:00
										 |  |  |             } catch (e) { | 
					
						
							| 
									
										
										
										
											2022-12-06 04:08:18 +01:00
										 |  |  |                 console.debug("Could not construct a minimap:", e) | 
					
						
							| 
									
										
										
										
											2021-09-22 20:44:53 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-06-29 16:22:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 self.leafletMap?.data?.invalidateSize() | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							| 
									
										
										
										
											2022-12-06 04:08:18 +01:00
										 |  |  |                 console.debug("Could not invalidate size of a minimap:", e) | 
					
						
							| 
									
										
										
										
											2022-06-29 16:22:33 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         resizeObserver.observe(div) | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (this._addLayerControl) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const switcher = new BackgroundMapSwitch( | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |                     locationControl: this.location, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     backgroundLayer: this._background, | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |                 }, | 
					
						
							|  |  |  |                 this._background | 
					
						
							|  |  |  |             ).SetClass("top-0 right-0 z-above-map absolute") | 
					
						
							|  |  |  |             wrapper.appendChild(switcher.ConstructElement()) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return wrapper | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private InitMap() { | 
					
						
							|  |  |  |         if (this._constructedHtmlElement === undefined) { | 
					
						
							|  |  |  |             // This element isn't initialized yet
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (document.getElementById(this._id) === null) { | 
					
						
							|  |  |  |             // not yet attached, we probably got some other event
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (this._isInited) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._isInited = true | 
					
						
							|  |  |  |         const location = this.location | 
					
						
							|  |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         let currentLayer = this._background.data.layer() | 
					
						
							| 
									
										
										
										
											2021-09-22 20:44:53 +02:00
										 |  |  |         let latLon = <[number, number]>[location.data?.lat ?? 0, location.data?.lon ?? 0] | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |         if (isNaN(latLon[0]) || isNaN(latLon[1])) { | 
					
						
							|  |  |  |             latLon = [0, 0] | 
					
						
							| 
									
										
										
										
											2021-09-22 20:44:53 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         const options = { | 
					
						
							| 
									
										
										
										
											2021-09-22 20:44:53 +02:00
										 |  |  |             center: latLon, | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             zoom: location.data?.zoom ?? 2, | 
					
						
							|  |  |  |             layers: [currentLayer], | 
					
						
							|  |  |  |             zoomControl: false, | 
					
						
							|  |  |  |             attributionControl: this._attribution !== undefined, | 
					
						
							|  |  |  |             dragging: this._allowMoving, | 
					
						
							|  |  |  |             scrollWheelZoom: this._allowMoving, | 
					
						
							|  |  |  |             doubleClickZoom: this._allowMoving, | 
					
						
							|  |  |  |             keyboard: this._allowMoving, | 
					
						
							|  |  |  |             touchZoom: this._allowMoving, | 
					
						
							|  |  |  |             // Disabling this breaks the geojson layer - don't ask me why!  zoomAnimation: this._allowMoving,
 | 
					
						
							|  |  |  |             fadeAnimation: this._allowMoving, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             maxZoom: 21, | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Utils.Merge(this._leafletoptions, options) | 
					
						
							| 
									
										
										
										
											2022-06-29 16:22:33 +02:00
										 |  |  |         /* | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |          * Somehow, the element gets '_leaflet_id' set on chrome. | 
					
						
							|  |  |  |          * When attempting to init this leaflet map, it'll throw an exception and the map won't show up. | 
					
						
							|  |  |  |          * Simply removing '_leaflet_id' fixes the issue. | 
					
						
							|  |  |  |          * See https://github.com/pietervdvn/MapComplete/issues/726
 | 
					
						
							|  |  |  |          * */ | 
					
						
							| 
									
										
										
										
											2022-06-29 16:22:33 +02:00
										 |  |  |         delete document.getElementById(this._id)["_leaflet_id"] | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const map = L.map(this._id, options) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         if (self._onFullyLoaded !== undefined) { | 
					
						
							|  |  |  |             currentLayer.on("load", () => { | 
					
						
							|  |  |  |                 console.log("Fully loaded all tiles!") | 
					
						
							|  |  |  |                 self._onFullyLoaded(map) | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Users are not allowed to zoom to the 'copies' on the left and the right, stuff goes wrong then
 | 
					
						
							|  |  |  |         // We give a bit of leeway for people on the edges
 | 
					
						
							|  |  |  |         // Also see: https://www.reddit.com/r/openstreetmap/comments/ih4zzc/mapcomplete_a_new_easytouse_editor/g31ubyv/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         map.setMaxBounds([ | 
					
						
							|  |  |  |             [-100, -200], | 
					
						
							|  |  |  |             [100, 200], | 
					
						
							|  |  |  |         ]) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (this._attribution !== undefined) { | 
					
						
							|  |  |  |             if (this._attribution === true) { | 
					
						
							|  |  |  |                 map.attributionControl.setPrefix(false) | 
					
						
							|  |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 map.attributionControl.setPrefix("<span id='leaflet-attribution'></span>") | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._background.addCallbackAndRun((layer) => { | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             const newLayer = layer.layer() | 
					
						
							|  |  |  |             if (currentLayer !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 map.removeLayer(currentLayer) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             currentLayer = newLayer | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             if (self._onFullyLoaded !== undefined) { | 
					
						
							|  |  |  |                 currentLayer.on("load", () => { | 
					
						
							|  |  |  |                     console.log("Fully loaded all tiles!") | 
					
						
							|  |  |  |                     self._onFullyLoaded(map) | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             map.addLayer(newLayer) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             if (self._attribution !== true && self._attribution !== false) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 self._attribution?.AttachTo("leaflet-attribution") | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let isRecursing = false | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         map.on("moveend", function () { | 
					
						
							|  |  |  |             if (isRecursing) { | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             if ( | 
					
						
							|  |  |  |                 map.getZoom() === location.data.zoom && | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |                 map.getCenter().lat === location.data.lat && | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 map.getCenter().lng === location.data.lon | 
					
						
							|  |  |  |             ) { | 
					
						
							|  |  |  |                 return | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             location.data.zoom = map.getZoom() | 
					
						
							|  |  |  |             location.data.lat = map.getCenter().lat | 
					
						
							|  |  |  |             location.data.lon = map.getCenter().lng | 
					
						
							|  |  |  |             isRecursing = true | 
					
						
							|  |  |  |             location.ping() | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |             if (self.bounds !== undefined) { | 
					
						
							|  |  |  |                 self.bounds.setData(BBox.fromLeafletBounds(map.getBounds())) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             isRecursing = false // This is ugly, I know
 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         location.addCallback((loc) => { | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             const mapLoc = map.getCenter() | 
					
						
							|  |  |  |             const dlat = Math.abs(loc.lat - mapLoc[0]) | 
					
						
							|  |  |  |             const dlon = Math.abs(loc.lon - mapLoc[1]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (dlat < 0.000001 && dlon < 0.000001 && map.getZoom() === loc.zoom) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             map.setView([loc.lat, loc.lon], loc.zoom) | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |         if (self.bounds !== undefined) { | 
					
						
							|  |  |  |             self.bounds.setData(BBox.fromLeafletBounds(map.getBounds())) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-08 20:02:07 +01:00
										 |  |  |         if (this._options.lastClickLocation) { | 
					
						
							|  |  |  |             const lastClickLocation = this._options.lastClickLocation | 
					
						
							| 
									
										
										
										
											2022-12-09 13:58:41 +01:00
										 |  |  |             map.on("click", function (e: LeafletMouseEvent) { | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  |                 if (e.originalEvent["dismissed"]) { | 
					
						
							| 
									
										
										
										
											2022-12-09 13:58:41 +01:00
										 |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 lastClickLocation?.setData({ lat: e.latlng.lat, lon: e.latlng.lng }) | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             map.on("contextmenu", function (e) { | 
					
						
							|  |  |  |                 // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 lastClickLocation?.setData({ lat: e.latlng.lat, lon: e.latlng.lng }) | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.leafletMap.setData(map) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |