488 lines
No EOL
14 KiB
TypeScript
488 lines
No EOL
14 KiB
TypeScript
class MapHandler {
|
|
map: L.Map;
|
|
overlays: OverlayState;
|
|
layers: TileLayerWrapper[];
|
|
modals: ModalCollection;
|
|
|
|
static instance: MapHandler | null = null;
|
|
|
|
private constructor(map: L.Map, overlays: OverlayState, layers: TileLayerWrapper[], modals: ModalCollection) {
|
|
this.map = map;
|
|
this.overlays = overlays;
|
|
this.layers = layers;
|
|
this.modals = modals;
|
|
}
|
|
|
|
static init(map: L.Map, overlays: OverlayState, layers: TileLayerWrapper[], modals: ModalCollection): void {
|
|
if (!MapHandler.instance) {
|
|
MapHandler.instance = new MapHandler(map, overlays, layers, modals);
|
|
}
|
|
}
|
|
|
|
static setButtonClick(btnId: string, handler: any): void {
|
|
const button = document.getElementById(btnId);
|
|
if (button) {
|
|
button.onclick = handler;
|
|
}
|
|
}
|
|
|
|
static resetMapClick(): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
try {
|
|
const addPointBtn = document.getElementById("addPoint-btn");
|
|
if (addPointBtn) {
|
|
addPointBtn.classList.remove("activeBtn");
|
|
}
|
|
self.map.off("click", MapHandler.addMarker);
|
|
} catch {}
|
|
try {
|
|
const addCircleBtn = document.getElementById("addCircle-btn");
|
|
if (addCircleBtn) {
|
|
addCircleBtn.classList.remove("activeBtn");
|
|
}
|
|
self.map.off("click", MapHandler.addCircle);
|
|
} catch {}
|
|
try {
|
|
const addPolygonBtn = document.getElementById("addPolygon-btn");
|
|
if (addPolygonBtn) {
|
|
addPolygonBtn.classList.remove("activeBtn");
|
|
}
|
|
self.map.off("click", MapHandler.polygonAddPoint);
|
|
} catch {}
|
|
try {
|
|
const saveBtn = document.getElementById("save-btn");
|
|
if (saveBtn) {
|
|
saveBtn.classList.remove("activeBtn");
|
|
}
|
|
} catch {}
|
|
try {
|
|
const clearBtn = document.getElementById("clear-btn");
|
|
if (clearBtn) {
|
|
clearBtn.classList.remove("activeBtn");
|
|
}
|
|
} catch {}
|
|
try {
|
|
const resetBtn = document.getElementById("restore-btn");
|
|
if (resetBtn) {
|
|
resetBtn.classList.remove("activeBtn");
|
|
}
|
|
} catch {}
|
|
try {
|
|
const menuBtn = document.getElementById("menu-btn");
|
|
if (menuBtn) {
|
|
menuBtn.classList.remove("activeBtn");
|
|
}
|
|
} catch {}
|
|
self.overlays.polyline.clearPoints();
|
|
}
|
|
}
|
|
|
|
static addMarker(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.cancel.setVisible(false);
|
|
self.modals.createOverlay.setState(OverlayType.POINT, {
|
|
latlng: e.latlng,
|
|
map: self.map,
|
|
overlays: self.overlays,
|
|
});
|
|
MapHandler.resetMapClick();
|
|
self.modals.createOverlay.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static editOverlay(overlay: OverlayBase, type: OverlayType): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
self.modals.createOverlay.setState(type, {
|
|
self: overlay,
|
|
map: self.map,
|
|
overlays: self.overlays,
|
|
});
|
|
MapHandler.resetMapClick();
|
|
self.modals.createOverlay.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static addCircle(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.cancel.setVisible(false);
|
|
self.modals.createOverlay.setState(OverlayType.CIRCLE, {
|
|
latlng: e.latlng,
|
|
map: self.map,
|
|
overlays: self.overlays,
|
|
});
|
|
MapHandler.resetMapClick();
|
|
self.modals.createOverlay.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static addPolygon(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.okCancel.setVisible(false);
|
|
self.modals.createOverlay.setState(OverlayType.POLYGON, {
|
|
points: self.overlays.polyline.points,
|
|
map: self.map,
|
|
overlays: self.overlays,
|
|
});
|
|
MapHandler.resetMapClick();
|
|
self.overlays.polyline.clearPoints();
|
|
self.modals.createOverlay.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static circleCollect(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
(e.target as HTMLElement).classList.add("activeBtn");
|
|
self.map.on("click", MapHandler.addCircle);
|
|
|
|
const cancelBtn = self.modals.cancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = ()=> {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
};
|
|
}
|
|
self.modals.cancel.setMsg("Placing circle");
|
|
self.modals.cancel.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static markerCollect(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
(e.target as HTMLElement).classList.add("activeBtn");
|
|
self.map.on("click", MapHandler.addMarker);
|
|
|
|
const cancelBtn = self.modals.cancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = ()=> {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
};
|
|
}
|
|
self.modals.cancel.setMsg("Placing marker");
|
|
self.modals.cancel.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static polygonCollect(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
(e.target as HTMLElement).classList.add("activeBtn");
|
|
|
|
// show cancel -- on cancel, clear polyline and reset map handling
|
|
const cancelBtn = self.modals.cancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = MapHandler.polygonClearPoints;
|
|
}
|
|
self.modals.cancel.setMsg("Creating path");
|
|
self.modals.cancel.setVisible(true);
|
|
|
|
self.map.on("click", MapHandler.polygonAddPoint);
|
|
}
|
|
}
|
|
|
|
static polygonClearPoints(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
self.overlays.polyline.clearPoints();
|
|
MapHandler.resetMapClick();
|
|
}
|
|
}
|
|
|
|
static polygonAddPoint(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.overlays.polyline.insertPoint(e.latlng);
|
|
if (self.overlays.polyline.numPoints() >= 3) {
|
|
self.modals.cancel.setVisible(false);
|
|
|
|
const okBtn = self.modals.okCancel.okBtn();
|
|
if (okBtn) {
|
|
okBtn.onclick = MapHandler.addPolygon;
|
|
}
|
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = MapHandler.polygonClearPoints;
|
|
}
|
|
self.modals.okCancel.setMsg("Creating path");
|
|
self.modals.okCancel.setVisible(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
static overlaySave(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
(e.target as HTMLElement).classList.add("activeBtn");
|
|
self.modals.okCancel.setMsg("Save current map overlays?");
|
|
|
|
const okBtn = self.modals.okCancel.okBtn();
|
|
if (okBtn) {
|
|
okBtn.onclick = ()=> {
|
|
OverlayState.save(self.overlays);
|
|
self.modals.okCancel.setVisible(false);
|
|
MapHandler.resetMapClick();
|
|
self.modals.info.setMsg("Save complete");
|
|
self.modals.info.setVisible(true);
|
|
}
|
|
}
|
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = () => {
|
|
self.modals.okCancel.setVisible(false);
|
|
MapHandler.resetMapClick();
|
|
}
|
|
}
|
|
self.modals.okCancel.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static overlayReset(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
(e.target as HTMLElement).classList.add("activeBtn");
|
|
self.modals.okCancel.setMsg("Restore overlays from saved data?");
|
|
|
|
const okBtn = self.modals.okCancel.okBtn();
|
|
if (okBtn) {
|
|
okBtn.onclick = ()=> {
|
|
self.overlays = OverlayState.clear(self.overlays, self.map);
|
|
self.overlays = OverlayState.load();
|
|
self.overlays.markers.forEach(m=>m.add(self.map));
|
|
self.overlays.circles.forEach(m=>m.add(self.map));
|
|
self.overlays.paths.forEach(m=>m.add(self.map));
|
|
self.overlays.polyline.add(self.map);
|
|
self.modals.okCancel.setVisible(false);
|
|
MapHandler.resetMapClick();
|
|
self.modals.info.setMsg("Restored");
|
|
self.modals.info.setVisible(true);
|
|
}
|
|
}
|
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = () => {
|
|
self.modals.okCancel.setVisible(false);
|
|
MapHandler.resetMapClick();
|
|
}
|
|
}
|
|
self.modals.okCancel.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static overlayClear(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
(e.target as HTMLElement).classList.add("activeBtn");
|
|
self.modals.okCancel.setMsg("Clear all map overlays (will not affect saved data)?");
|
|
|
|
const okBtn = self.modals.okCancel.okBtn();
|
|
if (okBtn) {
|
|
okBtn.onclick = ()=> {
|
|
self.overlays = OverlayState.clear(self.overlays, self.map);
|
|
MapHandler.resetMapClick();
|
|
self.modals.okCancel.setVisible(false);
|
|
}
|
|
}
|
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = () => {
|
|
MapHandler.resetMapClick();
|
|
self.modals.okCancel.setVisible(false);
|
|
}
|
|
}
|
|
self.modals.okCancel.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static swapTiles(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
if (TileLayerWrapper.getActiveLayer() == "satelliteLayer") {
|
|
TileLayerWrapper.enableOnly("streetLayer", self.map);
|
|
} else {
|
|
TileLayerWrapper.enableOnly("satelliteLayer", self.map);
|
|
}
|
|
}
|
|
}
|
|
|
|
static setHome(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
const okCancel = self.modals.okCancel;
|
|
okCancel.setMsg("Set Home to current coordinates?");
|
|
const okBtn = okCancel.okBtn();
|
|
if (okBtn) {
|
|
okBtn.onclick = (e: any) => {
|
|
okCancel.setVisible(false);
|
|
localStorage.setItem("home", JSON.stringify(self.map.getCenter() as Point));
|
|
const info = self.modals.info;
|
|
info.setMsg("Home coordinates set");
|
|
info.setVisible(true);
|
|
}
|
|
}
|
|
const cancelBtn = okCancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = () => {
|
|
okCancel.setVisible(false);
|
|
}
|
|
}
|
|
okCancel.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static goHome(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
const homeData = localStorage.getItem("home");
|
|
if (homeData) {
|
|
const home = <Point>JSON.parse(homeData);
|
|
if (home) {
|
|
self.map.setView(home, 13);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static toggleMenu(e: any): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
const visible = self.modals.overlayMgr.visible();
|
|
self.modals.closeAll();
|
|
MapHandler.resetMapClick();
|
|
self.modals.overlayMgr.setVisible(!visible);
|
|
if (!visible) {
|
|
(e.target as HTMLElement).classList.add("activeBtn");
|
|
}
|
|
}
|
|
}
|
|
|
|
static confirmDelete(overlay: OverlayBase): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
self.modals.okCancel.setMsg(`Delete "${overlay.name}"?`);
|
|
const okBtn = self.modals.okCancel.okBtn();
|
|
if (okBtn) {
|
|
okBtn.onclick = () => {
|
|
self.modals.closeAll();
|
|
overlay.remove(self.map);
|
|
self.modals.info.setMsg(`"${overlay.name}" deleted`);
|
|
self.modals.info.setVisible(true);
|
|
}
|
|
}
|
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
|
if (cancelBtn) {
|
|
cancelBtn.onclick = () => {
|
|
self.modals.closeAll();
|
|
}
|
|
}
|
|
self.modals.okCancel.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static exportSingle(overlay: OverlayBase): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
self.modals.importExport.setTitle("Export Overlay");
|
|
self.modals.importExport.setErrMsg("", false);
|
|
|
|
const okBtn = self.modals.importExport.okBtn();
|
|
if (okBtn) {
|
|
okBtn.innerText = "Copy to clipboard";
|
|
okBtn.onclick = () => {
|
|
self.modals.importExport.copyTextArea();
|
|
self.modals.closeAll();
|
|
self.modals.info.setMsg("Copied the data to the clipboard");
|
|
self.modals.info.setVisible(true);
|
|
}
|
|
}
|
|
|
|
self.modals.importExport.setTextArea(OverlayState.exportSingle(overlay), true);
|
|
self.modals.importExport.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static exportAll(): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
self.modals.importExport.setTitle("Export All Overlays");
|
|
self.modals.importExport.setErrMsg("", false);
|
|
|
|
const okBtn = self.modals.importExport.okBtn();
|
|
if (okBtn) {
|
|
okBtn.innerText = "Copy to clipboard";
|
|
okBtn.onclick = () => {
|
|
self.modals.importExport.copyTextArea();
|
|
self.modals.closeAll();
|
|
self.modals.info.setMsg("Copied the data to the clipboard");
|
|
self.modals.info.setVisible(true);
|
|
}
|
|
}
|
|
|
|
self.modals.importExport.setTextArea(OverlayState.export(self.overlays), true);
|
|
self.modals.importExport.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static import(): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
self.modals.importExport.setTitle("Import Overlay Data");
|
|
self.modals.importExport.setErrMsg("", false);
|
|
self.modals.importExport.setTextArea("", false);
|
|
|
|
const okBtn = self.modals.importExport.okBtn();
|
|
if (okBtn) {
|
|
okBtn.innerText = "Import";
|
|
okBtn.onclick = () => {
|
|
MapHandler.doImport(self.modals.importExport.getText());
|
|
}
|
|
}
|
|
self.modals.importExport.setVisible(true);
|
|
}
|
|
}
|
|
|
|
static doImport(data: string): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
if (OverlayState.importWrapper(data, self.overlays, self.map)) {
|
|
self.modals.closeAll();
|
|
self.modals.info.setMsg("Import successful");
|
|
self.modals.info.setVisible(true);
|
|
} else {
|
|
self.modals.importExport.setErrMsg("The data was malformed — please check that it is valid JSON exported from ONYX/scry", true);
|
|
}
|
|
}
|
|
}
|
|
|
|
static closeImportExport(): void {
|
|
const self = MapHandler.instance;
|
|
if (self) {
|
|
self.modals.closeAll();
|
|
}
|
|
}
|
|
} |