"use strict"; class Point { constructor() { this.lat = 0.00; this.lng = 0.00; } } var OverlayType; (function (OverlayType) { OverlayType[OverlayType["POINT"] = 0] = "POINT"; OverlayType[OverlayType["CIRCLE"] = 1] = "CIRCLE"; OverlayType[OverlayType["POLYGON"] = 2] = "POLYGON"; OverlayType[OverlayType["POLYLINE"] = 3] = "POLYLINE"; })(OverlayType || (OverlayType = {})); class OverlayData { constructor(type, name, desc, points, options) { this.type = type; this.name = name; this.desc = desc; this.points = points; this.options = options; } } class OverlayBase { constructor(name, desc, points, options) { this.name = name; this.desc = desc; this.points = points; this.options = options; } center() { return this.points[0]; } static centerAsString(pt) { let eastWest = ""; let northSouth = ""; const lat = pt.lat; const long = pt.lng; if (lat > 0) { northSouth = "N"; } else if (lat < 0) { northSouth = "S"; } if (long > 0) { eastWest = "E"; } else if (long < 0) { eastWest = "W"; } return `${String(long).substring(0, 7)}°${eastWest}, ${String(lat).substring(0, 7)}°${northSouth}`; } setPopupContent(content) { this.self.bindPopup(content); } static classSanitize(input) { return input.replace(/\-/g, "_"); } static listAdd(self, listName) { const list = document.getElementById(listName); if (list) { const li = document.createElement("li"); const a = document.createElement("a"); if (li && a) { a.innerText = self.name; a.href = "#"; a.onclick = (e) => { MapHandler.editOverlay(self, OverlayBase.overlayTypeMap[OverlayBase.classSanitize(listName)]); }; li.appendChild(a); list.appendChild(li); self.menuItem = li; } } } static listRemove(self, listName) { const list = document.getElementById(listName); if (list && self.menuItem) { list.removeChild(self.menuItem); } } } OverlayBase.overlayTypeMap = { markers_list: OverlayType.POINT, circles_list: OverlayType.CIRCLE, polygons_list: OverlayType.POLYGON, }; class Marker extends OverlayBase { constructor(name, desc, point, options) { super(name, desc, [point], options); this.menuItem = null; this.self = L.marker(point); this.self.bindPopup(`

${name}

${desc}

`); } add(map) { this.self.addTo(map); OverlayBase.listAdd(this, "markers-list"); } remove(map) { this.self.removeFrom(map); OverlayBase.listRemove(this, "markers-list"); } } class Circle extends OverlayBase { constructor(name, desc, point, options) { super(name, desc, [point], options); this.menuItem = null; this.self = L.circle(point, options); this.self.bindPopup(`

${name}

${desc}

`); } add(map) { this.self.addTo(map); OverlayBase.listAdd(this, "circles-list"); } remove(map) { this.self.removeFrom(map); OverlayBase.listRemove(this, "circles-list"); } } class Polygon extends OverlayBase { constructor(name, desc, points, options) { super(name, desc, points, options); this.menuItem = null; if (options.closed) { this.self = L.polygon(points, options); } else { this.self = L.polyline(points, options); } this.self.bindPopup(`

${name}

${desc}

`); } center() { return this.self.getCenter(); } add(map) { this.self.addTo(map); OverlayBase.listAdd(this, "polygons-list"); } remove(map) { this.self.removeFrom(map); OverlayBase.listRemove(this, "polygons-list"); } } class Polyline extends OverlayBase { constructor() { super("", "", [], {}); this.menuItem = null; this.self = L.polyline([]); } insertPoint(pt) { this.self.addLatLng(pt); this.points.push(pt); } clearPoints() { this.points = []; this.self.setLatLngs([]); } numPoints() { return this.self.getLatLngs().length; } center() { return this.self.getCenter(); } add(map) { this.self.addTo(map); } remove(map) { this.self.removeFrom(map); } } class OverlayState { constructor() { this.markers = []; this.circles = []; this.paths = []; this.polyline = new Polyline(); } static load() { const store = localStorage.getItem("overlay_state"); return store ? OverlayState.import(store) : new OverlayState; } static import(overlayData) { const model = JSON.parse(overlayData); return { markers: model.markers.map((m) => OverlayState.fromData(m)), circles: model.circles.map((c) => OverlayState.fromData(c)), paths: model.paths.map((p) => OverlayState.fromData(p)), polyline: new Polyline(), }; } static exportSingle(overlay) { return JSON.stringify(OverlayState.toData(overlay), null, 2); } static export(overlayState) { return JSON.stringify({ markers: overlayState.markers.map((m) => OverlayState.toData(m)), circles: overlayState.circles.map((c) => OverlayState.toData(c)), paths: overlayState.paths.map((p) => OverlayState.toData(p)), }, null, 2); } static save(overlayState) { localStorage.setItem("overlay_state", OverlayState.export(overlayState)); } static clear(overlayState, map) { overlayState.markers.forEach((m) => m.remove(map)); overlayState.circles.forEach((c) => c.remove(map)); overlayState.paths.forEach((p) => p.remove(map)); const self = new OverlayState(); self.polyline.add(map); return self; } static toData(source) { let type = OverlayType.POINT; if (source.points.length > 1) { if (source.options.closed) { type = OverlayType.POLYGON; } else { type = OverlayType.POLYLINE; } } else if (source.options.radius) { type = OverlayType.CIRCLE; } return new OverlayData(type, source.name, source.desc, source.points, source.options); } static fromData(data) { switch (data.type) { case OverlayType.POINT: default: return new Marker(data.name, data.desc, data.points[0], data.options); case OverlayType.CIRCLE: return new Circle(data.name, data.desc, data.points[0], data.options); case OverlayType.POLYGON: case OverlayType.POLYLINE: return new Polygon(data.name, data.desc, data.points, data.options); } } static importWrapper(data, overlayState, map) { try { const singleData = JSON.parse(data); const overlay = OverlayState.fromData(singleData); switch (singleData.type) { case OverlayType.POINT: overlayState.markers.push(overlay); break; case OverlayType.CIRCLE: overlayState.circles.push(overlay); break; case OverlayType.POLYGON: case OverlayType.POLYLINE: overlayState.paths.push(overlay); break; } overlay.add(map); return true; } catch (_a) { } try { const self = OverlayState.import(data); self.markers.forEach((m) => { overlayState.markers.push(m); m.add(map); }); self.circles.forEach((c) => { overlayState.circles.push(c); c.add(map); }); self.paths.forEach((p) => { overlayState.paths.push(p); p.add(map); }); return true; } catch (_b) { } return false; } } class TileLayerWrapper { constructor(name, self) { this.visible = false; this.self = self; this.name = name; } static constructLayer(name, self) { const wrapper = new TileLayerWrapper(name, self); TileLayerWrapper.layers.push(wrapper); return wrapper; } static getActiveLayer() { for (const l of TileLayerWrapper.layers) { if (l.visible == true) { return l.name; } } return null; } static enableOnly(self, map) { for (const l of TileLayerWrapper.layers) { if (l.visible) { l.self.removeFrom(map); l.visible = false; } if (l.name == self) { l.self.addTo(map); l.visible = true; } } } } TileLayerWrapper.layers = new Array(); class TextUtils { static decodeHTML(text) { return text; const textArea = document.createElement('textarea'); textArea.innerHTML = text; return textArea.value; } static encodeHTML(text) { return text; const textArea = document.createElement('textarea'); textArea.innerText = text; return textArea.innerHTML; } } class CreateOverlayModal { constructor() { const _this = this; const closeBtn = document.getElementById("createOverlay-closeBtn"); if (closeBtn) { closeBtn.onclick = () => { _this.setVisible(false); }; } const s = this.self(); if (s) { s.onsubmit = (e) => { e.preventDefault(); }; } } self() { return document.getElementById("createOverlay-container"); } title() { return document.getElementById("createOverlay-title"); } content() { return document.getElementById("createOverlay-content"); } submitBtn() { return document.getElementById("createOverlay-submitBtn"); } radiusContainer() { return document.getElementById("radius-container"); } closePolyContainer() { return document.getElementById("close-poly-container"); } closePolyCheckbox() { return document.getElementById("close-poly-checkbox"); } setClosePoly(v) { const checkbox = this.closePolyCheckbox(); if (checkbox) { checkbox.checked = v; } } setName(name) { const self = document.getElementById("createOverlay-name"); if (self) { self.value = name; } } setDesc(desc) { const self = document.getElementById("createOverlay-desc"); if (self) { self.value = desc; } } setRadius(radius) { const self = document.getElementById("createOverlay-radius"); if (self) { self.value = String(radius); } } nameField() { var _a, _b; return (_b = (_a = document.getElementById("createOverlay-name")) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ""; } descField() { var _a, _b; return (_b = (_a = document.getElementById("createOverlay-desc")) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ""; } radiusField() { var _a, _b; return (_b = (_a = document.getElementById("createOverlay-radius")) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ""; } visible() { var _a; return ((_a = this.self()) === null || _a === void 0 ? void 0 : _a.style.display) != "none"; } setVisible(v) { const modal = this.self(); if (modal) { modal.style.display = v ? "block" : "none"; } } setExtraButtonsVisible(v) { const extraBtns = document.getElementById("edit-extra-btns"); if (extraBtns) { extraBtns.style.display = v ? "inline" : "none"; } } gotoBtn() { return document.getElementById("goto-btn"); } exportBtn() { return document.getElementById("export-btn"); } deleteBtn() { return document.getElementById("delete-btn"); } clearInputs() { const name = document.getElementById("createOverlay-name"); const desc = document.getElementById("createOverlay-desc"); const radius = document.getElementById("createOverlay-radius"); if (name === null || name === void 0 ? void 0 : name.value) { name.value = ""; } if (desc === null || desc === void 0 ? void 0 : desc.value) { desc.value = ""; } if (Number(radius === null || radius === void 0 ? void 0 : radius.value) != 500) { radius.value = "500"; } this.setClosePoly(false); } setState(state, args) { const _this = this; const title = this.title(); const radiusContainer = _this.radiusContainer(); const closePolyContainer = _this.closePolyContainer(); const closePoly = _this.closePolyCheckbox(); const submitBtn = _this.submitBtn(); const editing = args.self ? true : false; _this.clearInputs(); if (radiusContainer) { radiusContainer.style.display = state == OverlayType.CIRCLE ? "block" : "none"; } if (closePolyContainer) { closePolyContainer.style.display = (state == OverlayType.POLYGON && !editing) ? "block" : "none"; } this.setExtraButtonsVisible(editing); if (editing) { const gotoBtn = this.gotoBtn(); const exportBtn = this.exportBtn(); const deleteBtn = this.deleteBtn(); if (title) { switch (state) { case OverlayType.POINT: title.innerHTML = "Edit Marker "; break; case OverlayType.CIRCLE: title.innerHTML = "Edit Circle "; break; case OverlayType.POLYGON: title.innerHTML = "Edit Path "; break; } } if (gotoBtn) { gotoBtn.onclick = () => { _this.setVisible(false); args.map.setView(args.self.center()); }; } if (exportBtn) { exportBtn.onclick = () => { MapHandler.exportSingle(args.self); }; } if (deleteBtn) { deleteBtn.onclick = () => { MapHandler.confirmDelete(args.self); }; } this.setName(args.self.name); this.setDesc(args.self.desc); if (state == OverlayType.CIRCLE) { this.setRadius(args.self.options.radius); } if (submitBtn) { submitBtn.onclick = () => { const name = TextUtils.encodeHTML(_this.nameField()); const desc = TextUtils.encodeHTML(_this.descField()); if (name.trim().length < 1) { return; } args.self.name = name; args.self.desc = desc; args.self.setPopupContent(`

${name}

${desc}

`); _this.setVisible(false); }; } } else { switch (state) { case OverlayType.POINT: if (title) { title.innerHTML = "Add Marker "; } if (submitBtn) { submitBtn.onclick = () => { const name = TextUtils.encodeHTML(_this.nameField()); const desc = TextUtils.encodeHTML(_this.descField()); if (name.trim().length < 1) { return; } const point = new Marker(name, desc, args.latlng, { title: name, alt: name }); point.add(args.map); args.overlays.markers.push(point); _this.setVisible(false); }; } break; case OverlayType.CIRCLE: if (title) { title.innerHTML = "Add Circle "; } if (submitBtn) { submitBtn.onclick = () => { const radius = _this.radiusField(); const name = TextUtils.encodeHTML(_this.nameField()); const desc = TextUtils.encodeHTML(_this.descField()); if (name.trim().length < 1) { return; } const circle = new Circle(name, desc, args.latlng, { radius: Number(radius) || 500 }); circle.add(args.map); args.overlays.circles.push(circle); _this.setVisible(false); }; } break; case OverlayType.POLYGON: if (title) { title.innerHTML = "Add Path "; } if (submitBtn) { submitBtn.onclick = () => { var _a; const name = TextUtils.encodeHTML(_this.nameField()); const desc = TextUtils.encodeHTML(_this.descField()); if (name.trim().length < 1) { return; } const polygon = new Polygon(name, desc, args.points, { closed: (_a = closePoly === null || closePoly === void 0 ? void 0 : closePoly.checked) !== null && _a !== void 0 ? _a : false, weight: 5 }); polygon.add(args.map); args.overlays.paths.push(polygon); _this.setVisible(false); }; } break; } } if (title) { title.innerHTML += OverlayBase.centerAsString(args.self ? args.self.center() : (state === OverlayType.POLYGON ? args.overlays.polyline.center() : args.latlng)); } } } class CancelModal { self() { return document.getElementById("cancel-container"); } cancelMsg() { return document.getElementById("cancel-msg"); } cancelBtn() { return document.getElementById("cancel-btn"); } visible() { var _a; return ((_a = this.self()) === null || _a === void 0 ? void 0 : _a.style.display) != "none"; } setVisible(v) { const modal = this.self(); if (modal) { modal.style.display = v ? "block" : "none"; } } setMsg(s) { const msg = this.cancelMsg(); if (msg) { msg.innerText = s; } } } class OKCancelModal { self() { return document.getElementById("confirm-container"); } confirmMsg() { return document.getElementById("confirm-msg"); } okBtn() { return document.getElementById("yes-btn"); } cancelBtn() { return document.getElementById("no-btn"); } visible() { var _a; return ((_a = this.self()) === null || _a === void 0 ? void 0 : _a.style.display) != "none"; } setVisible(v) { const modal = this.self(); if (modal) { modal.style.display = v ? "block" : "none"; } } setMsg(s) { const msg = this.confirmMsg(); if (msg) { msg.innerText = s; } } } class InfoModal { constructor() { const _this = this; const closeBtn = document.getElementById("info-closeBtn"); if (closeBtn) { closeBtn.onclick = () => { _this.setVisible(false); }; } } self() { return document.getElementById("info-container"); } visible() { var _a; return ((_a = this.self()) === null || _a === void 0 ? void 0 : _a.style.display) != "none"; } infoMsg() { return document.getElementById("info-content"); } setMsg(s) { const infoMsg = this.infoMsg(); if (infoMsg) { infoMsg.innerText = s; } } setVisible(v) { const modal = this.self(); if (modal) { modal.style.display = v ? "block" : "none"; } } } class ImportExportModal { self() { return document.getElementById("import-export-container"); } visible() { var _a; return ((_a = this.self()) === null || _a === void 0 ? void 0 : _a.style.display) != "none"; } setVisible(v) { const modal = this.self(); if (modal) { modal.style.display = v ? "block" : "none"; } } setTitle(title) { const modalH2 = document.getElementById("import-export-title"); if (modalH2) { modalH2.innerHTML = title; } } setTextArea(text, readonly) { const textarea = document.getElementById("import-export-textarea"); if (textarea) { textarea.value = text; textarea.readOnly = readonly; } } setErrMsg(text, visible) { const errMsg = document.getElementById("import-export-error"); if (errMsg) { errMsg.innerHTML = text; errMsg.style.display = visible ? "unset" : "none"; } } copyTextArea() { const textarea = document.getElementById("import-export-textarea"); if (textarea) { textarea.select(); textarea.setSelectionRange(0, 9999999); navigator.clipboard.writeText(textarea.value); } } getText() { const textarea = document.getElementById("import-export-textarea"); if (textarea) { return textarea.value; } return ""; } okBtn() { return document.getElementById("import-export-ok-btn"); } cancelBtn() { return document.getElementById("import-export-cancel-btn"); } } class OverlayManagementModal { self() { return document.getElementById("overlays-menu-container"); } visible() { var _a; return ((_a = this.self()) === null || _a === void 0 ? void 0 : _a.style.display) !== "none"; } setVisible(v) { const modal = this.self(); if (modal) { modal.style.display = v ? "grid" : "none"; } } constructor() { this.setVisible(false); } } class ModalCollection { constructor(createOverlay, cancel, okCancel, info, overlayMgr, importExport) { this.createOverlay = createOverlay; this.cancel = cancel; this.okCancel = okCancel; this.info = info; this.overlayMgr = overlayMgr; this.importExport = importExport; } closeAll() { this.createOverlay.setVisible(false); this.cancel.setVisible(false); this.okCancel.setVisible(false); this.info.setVisible(false); this.overlayMgr.setVisible(false); this.importExport.setVisible(false); } } class MapHandler { constructor(map, overlays, layers, modals) { this.map = map; this.overlays = overlays; this.layers = layers; this.modals = modals; } static init(map, overlays, layers, modals) { if (!MapHandler.instance) { MapHandler.instance = new MapHandler(map, overlays, layers, modals); } } static setButtonClick(btnId, handler) { const button = document.getElementById(btnId); if (button) { button.onclick = handler; } } static resetMapClick() { 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 (_a) { } try { const addCircleBtn = document.getElementById("addCircle-btn"); if (addCircleBtn) { addCircleBtn.classList.remove("activeBtn"); } self.map.off("click", MapHandler.addCircle); } catch (_b) { } try { const addPolygonBtn = document.getElementById("addPolygon-btn"); if (addPolygonBtn) { addPolygonBtn.classList.remove("activeBtn"); } self.map.off("click", MapHandler.polygonAddPoint); } catch (_c) { } try { const saveBtn = document.getElementById("save-btn"); if (saveBtn) { saveBtn.classList.remove("activeBtn"); } } catch (_d) { } try { const clearBtn = document.getElementById("clear-btn"); if (clearBtn) { clearBtn.classList.remove("activeBtn"); } } catch (_e) { } try { const resetBtn = document.getElementById("restore-btn"); if (resetBtn) { resetBtn.classList.remove("activeBtn"); } } catch (_f) { } try { const menuBtn = document.getElementById("menu-btn"); if (menuBtn) { menuBtn.classList.remove("activeBtn"); } } catch (_g) { } self.overlays.polyline.clearPoints(); } } static addMarker(e) { 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, type) { 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) { 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) { 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) { const self = MapHandler.instance; if (self) { self.modals.closeAll(); MapHandler.resetMapClick(); e.target.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) { const self = MapHandler.instance; if (self) { self.modals.closeAll(); MapHandler.resetMapClick(); e.target.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) { const self = MapHandler.instance; if (self) { self.modals.closeAll(); MapHandler.resetMapClick(); e.target.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) { const self = MapHandler.instance; if (self) { self.modals.closeAll(); self.overlays.polyline.clearPoints(); MapHandler.resetMapClick(); } } static polygonAddPoint(e) { 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) { const self = MapHandler.instance; if (self) { self.modals.closeAll(); MapHandler.resetMapClick(); e.target.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) { const self = MapHandler.instance; if (self) { self.modals.closeAll(); MapHandler.resetMapClick(); e.target.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) { const self = MapHandler.instance; if (self) { self.modals.closeAll(); MapHandler.resetMapClick(); e.target.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) { const self = MapHandler.instance; if (self) { if (TileLayerWrapper.getActiveLayer() == "satelliteLayer") { TileLayerWrapper.enableOnly("streetLayer", self.map); } else { TileLayerWrapper.enableOnly("satelliteLayer", self.map); } } } static setHome(e) { 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) => { okCancel.setVisible(false); localStorage.setItem("home", JSON.stringify(self.map.getCenter())); 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) { const self = MapHandler.instance; if (self) { const homeData = localStorage.getItem("home"); if (homeData) { const home = JSON.parse(homeData); if (home) { self.map.setView(home, 13); } } } } static toggleMenu(e) { 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.classList.add("activeBtn"); } } } static confirmDelete(overlay) { 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) { 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() { 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() { 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) { 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() { const self = MapHandler.instance; if (self) { self.modals.closeAll(); } } } MapHandler.instance = null; const helpLink = "
ONYX v0.3.0 [ license | manual ]"; function init() { let overlays = new OverlayState(); try { overlays = OverlayState.load(); } catch (_a) { alert("Error reading saved data; initializing with empty data."); } const map = L.map('map').fitWorld(); const streetLayer = TileLayerWrapper.constructLayer("streetLayer", L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: "street map data © OpenStreetMap contributors" + helpLink })); const satelliteLayer = TileLayerWrapper.constructLayer("satelliteLayer", L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { maxZoom: 19, attribution: "satellite data © Esri" + helpLink })); TileLayerWrapper.enableOnly("streetLayer", map); overlays.markers.forEach(m => m.add(map)); overlays.circles.forEach(m => m.add(map)); overlays.paths.forEach(m => m.add(map)); overlays.polyline.add(map); const modals = new ModalCollection(new CreateOverlayModal(), new CancelModal(), new OKCancelModal(), new InfoModal(), new OverlayManagementModal(), new ImportExportModal()); MapHandler.init(map, overlays, TileLayerWrapper.layers, modals); MapHandler.setButtonClick("home-btn", MapHandler.goHome); MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect); MapHandler.setButtonClick("addCircle-btn", MapHandler.circleCollect); MapHandler.setButtonClick("addPolygon-btn", MapHandler.polygonCollect); MapHandler.setButtonClick("tiles-btn", MapHandler.swapTiles); MapHandler.setButtonClick("save-btn", MapHandler.overlaySave); MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear); MapHandler.setButtonClick("restore-btn", MapHandler.overlayReset); MapHandler.setButtonClick("menu-btn", MapHandler.toggleMenu); MapHandler.setButtonClick("set-home-btn", MapHandler.setHome); MapHandler.setButtonClick("export-all-btn", MapHandler.exportAll); MapHandler.setButtonClick("import-export-cancel-btn", MapHandler.closeImportExport); MapHandler.setButtonClick("import-btn", MapHandler.import); map.on("locationfound", MapHandler.setHome); map.on("locationerror", () => { const info = modals.info; info.setMsg("Could not get location data"); info.setVisible(true); }); // the menu doesn't open on the first click unless we do this first... not sure why modals.closeAll(); const homeData = localStorage.getItem("home"); if (homeData) { const home = JSON.parse(homeData); map.setView(home, 13); } else { const okCancel = modals.okCancel; const okBtn = okCancel.okBtn(); if (okBtn) { okBtn.onclick = () => { modals.closeAll(); map.locate({ setView: true, maxZoom: 13 }); }; } const cancelBtn = okCancel.cancelBtn(); if (cancelBtn) { cancelBtn.onclick = () => { modals.closeAll(); }; } okCancel.setMsg("Would you like to use location data to set Home?"); okCancel.setVisible(true); } } init();