implement menu that keeps track of overlays, sets home
This commit is contained in:
parent
d42b5fcd3d
commit
7ef255c556
13 changed files with 387 additions and 81 deletions
|
@ -46,44 +46,104 @@ abstract class OverlayBase implements Overlay {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(map: L.Map): void {
|
abstract add(map: L.Map): void;
|
||||||
this.self.addTo(map);
|
|
||||||
|
abstract remove(map: L.Map): void;
|
||||||
|
|
||||||
|
abstract menuItem: Node | null;
|
||||||
|
|
||||||
|
static listAdd(self: OverlayBase, listName: string) {
|
||||||
|
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: any) => {
|
||||||
|
//show EditOverlayModal with this overlay's data
|
||||||
|
};
|
||||||
|
li.appendChild(a);
|
||||||
|
list.appendChild(li);
|
||||||
|
self.menuItem = li;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(map: L.Map): void {
|
static listRemove(self: OverlayBase, listName: string) {
|
||||||
this.self.removeFrom(map);
|
const list = document.getElementById(listName);
|
||||||
|
if (list && self.menuItem) {
|
||||||
|
list.removeChild(self.menuItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Marker extends OverlayBase {
|
class Marker extends OverlayBase {
|
||||||
|
|
||||||
|
menuItem: Node | null = null;
|
||||||
|
|
||||||
constructor(name: string, desc: string, point: Point, options: any) {
|
constructor(name: string, desc: string, point: Point, options: any) {
|
||||||
super(name, desc, [ point ], options);
|
super(name, desc, [ point ], options);
|
||||||
this.self = L.marker(point);
|
this.self = L.marker(point);
|
||||||
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(map: L.Map) {
|
||||||
|
this.self.addTo(map);
|
||||||
|
OverlayBase.listAdd(this, "markers-list");
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(map: L.Map) {
|
||||||
|
this.self.removeFrom(map);
|
||||||
|
OverlayBase.listRemove(this, "markers-list");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Circle extends OverlayBase {
|
class Circle extends OverlayBase {
|
||||||
|
|
||||||
|
menuItem: Node | null = null;
|
||||||
|
|
||||||
constructor(name: string, desc: string, point: Point, options: any) {
|
constructor(name: string, desc: string, point: Point, options: any) {
|
||||||
super(name, desc, [ point ], options);
|
super(name, desc, [ point ], options);
|
||||||
this.self = L.circle(point, options);
|
this.self = L.circle(point, options);
|
||||||
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(map: L.Map) {
|
||||||
|
this.self.addTo(map);
|
||||||
|
OverlayBase.listAdd(this, "circles-list");
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(map: L.Map) {
|
||||||
|
this.self.removeFrom(map);
|
||||||
|
OverlayBase.listRemove(this, "circles-list");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Polygon extends OverlayBase {
|
class Polygon extends OverlayBase {
|
||||||
|
|
||||||
|
menuItem: Node | null = null;
|
||||||
|
|
||||||
constructor(name: string, desc: string, points: Point[], options: any) {
|
constructor(name: string, desc: string, points: Point[], options: any) {
|
||||||
super(name, desc, points, options);
|
super(name, desc, points, options);
|
||||||
this.self = L.polygon(points, options);
|
this.self = L.polygon(points, options);
|
||||||
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(map: L.Map) {
|
||||||
|
this.self.addTo(map);
|
||||||
|
OverlayBase.listAdd(this, "polygons-list");
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(map: L.Map) {
|
||||||
|
this.self.removeFrom(map);
|
||||||
|
OverlayBase.listRemove(this, "polygons-list");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Polyline extends OverlayBase {
|
class Polyline extends OverlayBase {
|
||||||
|
menuItem: Node | null = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("", "", [ ], {});
|
super("", "", [ ], {});
|
||||||
this.self = L.polyline([]);
|
this.self = L.polyline([]);
|
||||||
|
@ -102,6 +162,14 @@ class Polyline extends OverlayBase {
|
||||||
numPoints(): number {
|
numPoints(): number {
|
||||||
return this.self.getLatLngs().length;
|
return this.self.getLatLngs().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(map: L.Map) {
|
||||||
|
this.self.addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(map: L.Map) {
|
||||||
|
this.self.removeFrom(map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverlayState {
|
class OverlayState {
|
||||||
|
|
5
src/19-modal.ts
Normal file
5
src/19-modal.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
interface Modal {
|
||||||
|
self(): HTMLElement | null;
|
||||||
|
visible(): boolean;
|
||||||
|
setVisible(v: boolean): void;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
class CreateOverlayModal {
|
class CreateOverlayModal implements Modal {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
@ -6,6 +6,12 @@ class CreateOverlayModal {
|
||||||
if (closeBtn) {
|
if (closeBtn) {
|
||||||
closeBtn.onclick = ()=>{_this.setVisible(false)};
|
closeBtn.onclick = ()=>{_this.setVisible(false)};
|
||||||
}
|
}
|
||||||
|
const s = this.self();
|
||||||
|
if (s) {
|
||||||
|
s.onsubmit = (e: any): void => {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self(): HTMLElement | null {
|
self(): HTMLElement | null {
|
||||||
|
@ -89,7 +95,7 @@ class CreateOverlayModal {
|
||||||
submitBtn.onclick = () => {
|
submitBtn.onclick = () => {
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
if (name.trim().length < 1 || desc.trim().length < 1) {
|
if (name.trim().length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const point = new Marker(name, desc, args.latlng, {title: name, alt: name});
|
const point = new Marker(name, desc, args.latlng, {title: name, alt: name});
|
||||||
|
@ -108,7 +114,7 @@ class CreateOverlayModal {
|
||||||
const radius = _this.radiusField();
|
const radius = _this.radiusField();
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
if (name.trim().length < 1 || desc.trim().length < 1) {
|
if (name.trim().length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const circle = new Circle(name, desc, args.latlng, {radius: Number(radius) || 500});
|
const circle = new Circle(name, desc, args.latlng, {radius: Number(radius) || 500});
|
||||||
|
@ -126,7 +132,7 @@ class CreateOverlayModal {
|
||||||
submitBtn.onclick = () => {
|
submitBtn.onclick = () => {
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
if (name.trim().length < 1 || desc.trim().length < 1) {
|
if (name.trim().length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const polygon = new Polygon(name, desc, args.points, {});
|
const polygon = new Polygon(name, desc, args.points, {});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class CancelModal {
|
class CancelModal implements Modal {
|
||||||
self(): HTMLElement | null {
|
self(): HTMLElement | null {
|
||||||
return document.getElementById("cancel-container");
|
return document.getElementById("cancel-container");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class OKCancelModal {
|
class OKCancelModal implements Modal {
|
||||||
self(): HTMLElement | null {
|
self(): HTMLElement | null {
|
||||||
return document.getElementById("confirm-container");
|
return document.getElementById("confirm-container");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class InfoModal {
|
class InfoModal implements Modal {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
|
20
src/25-overlayManagerModal.ts
Normal file
20
src/25-overlayManagerModal.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class OverlayManagementModal implements Modal {
|
||||||
|
self(): HTMLElement | null {
|
||||||
|
return document.getElementById("overlays-menu-container");
|
||||||
|
}
|
||||||
|
|
||||||
|
visible(): boolean {
|
||||||
|
return this.self()?.style.display !== "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisible(v: boolean): void {
|
||||||
|
const modal = this.self();
|
||||||
|
if (modal) {
|
||||||
|
modal.style.display = v ? "grid" : "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,22 +3,26 @@ class ModalCollection {
|
||||||
cancel: CancelModal;
|
cancel: CancelModal;
|
||||||
okCancel: OKCancelModal;
|
okCancel: OKCancelModal;
|
||||||
info: InfoModal;
|
info: InfoModal;
|
||||||
|
overlayMgr: OverlayManagementModal;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
createOverlay: CreateOverlayModal,
|
createOverlay: CreateOverlayModal,
|
||||||
cancel: CancelModal,
|
cancel: CancelModal,
|
||||||
okCancel: OKCancelModal,
|
okCancel: OKCancelModal,
|
||||||
info: InfoModal
|
info: InfoModal,
|
||||||
|
overlayMgr: OverlayManagementModal
|
||||||
) {
|
) {
|
||||||
this.createOverlay = createOverlay;
|
this.createOverlay = createOverlay;
|
||||||
this.cancel = cancel;
|
this.cancel = cancel;
|
||||||
this.okCancel = okCancel;
|
this.okCancel = okCancel;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
|
this.overlayMgr = overlayMgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeAll(): void {
|
closeAll(): void {
|
||||||
this.createOverlay.setVisible(false);
|
this.createOverlay.setVisible(false);
|
||||||
this.cancel.setVisible(false);
|
this.cancel.setVisible(false);
|
||||||
this.okCancel.setVisible(false);
|
this.okCancel.setVisible(false);
|
||||||
|
this.overlayMgr.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -74,6 +74,7 @@ class MapHandler {
|
||||||
menuBtn.classList.remove("activeBtn");
|
menuBtn.classList.remove("activeBtn");
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
self.overlays.polyline.clearPoints();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +314,26 @@ class MapHandler {
|
||||||
static setHome(e: any): void {
|
static setHome(e: any): void {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
if (self) {
|
||||||
localStorage.setItem("home", JSON.stringify(self.map.getCenter()));
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,4 +349,17 @@ class MapHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -33,7 +33,8 @@ function init(): void {
|
||||||
new CreateOverlayModal(),
|
new CreateOverlayModal(),
|
||||||
new CancelModal(),
|
new CancelModal(),
|
||||||
new OKCancelModal(),
|
new OKCancelModal(),
|
||||||
new InfoModal());
|
new InfoModal(),
|
||||||
|
new OverlayManagementModal());
|
||||||
|
|
||||||
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
||||||
|
|
||||||
|
@ -45,27 +46,13 @@ function init(): void {
|
||||||
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
|
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
|
||||||
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);
|
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);
|
||||||
MapHandler.setButtonClick("restore-btn", MapHandler.overlayReset);
|
MapHandler.setButtonClick("restore-btn", MapHandler.overlayReset);
|
||||||
MapHandler.setButtonClick("menu-btn", ()=>{});
|
MapHandler.setButtonClick("menu-btn", MapHandler.toggleMenu);
|
||||||
|
|
||||||
|
MapHandler.setButtonClick("set-home-btn", MapHandler.setHome);
|
||||||
|
|
||||||
MapHandler.setButtonClick("tiles-btn", MapHandler.swapTiles);
|
MapHandler.setButtonClick("tiles-btn", MapHandler.swapTiles);
|
||||||
|
|
||||||
map.on("locationfound", ()=> {
|
map.on("locationfound", MapHandler.setHome);
|
||||||
const okCancel = modals.okCancel;
|
|
||||||
okCancel.setMsg("Set Home to current location?");
|
|
||||||
const okBtn = okCancel.okBtn();
|
|
||||||
if (okBtn) {
|
|
||||||
okBtn.onclick = (e: any) => {
|
|
||||||
okCancel.setVisible(false);
|
|
||||||
MapHandler.setHome(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const cancelBtn = okCancel.cancelBtn();
|
|
||||||
if (cancelBtn) {
|
|
||||||
cancelBtn.onclick = () => {
|
|
||||||
okCancel.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
map.on("locationerror", ()=> {
|
map.on("locationerror", ()=> {
|
||||||
const info = modals.info;
|
const info = modals.info;
|
||||||
|
@ -80,6 +67,8 @@ function init(): void {
|
||||||
} else {
|
} else {
|
||||||
map.locate({setView: true, maxZoom: 13});
|
map.locate({setView: true, maxZoom: 13});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modals.closeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<label for="createOverlay-name">Name</label><br/>
|
<label for="createOverlay-name">Name</label><br/>
|
||||||
<input type="text" id="createOverlay-name" required ><br/>
|
<input type="text" id="createOverlay-name" required ><br/>
|
||||||
<label for="createOverlay-desc">Description</label><br/>
|
<label for="createOverlay-desc">Description</label><br/>
|
||||||
<textarea id="createOverlay-desc" required></textarea><br/>
|
<textarea id="createOverlay-desc"></textarea><br/>
|
||||||
<div id="radius-container">
|
<div id="radius-container">
|
||||||
<label for="createOverlay-radius">Radius (meters)</label><br/>
|
<label for="createOverlay-radius">Radius (meters)</label><br/>
|
||||||
<input type="number" step="1" id="createOverlay-radius" value="500" required><br/>
|
<input type="number" step="1" id="createOverlay-radius" value="500" required><br/>
|
||||||
|
@ -75,22 +75,24 @@
|
||||||
<h2></h2>
|
<h2></h2>
|
||||||
<textarea id="import-export-textarea"></textarea>
|
<textarea id="import-export-textarea"></textarea>
|
||||||
<div class="multiBtn-container">
|
<div class="multiBtn-container">
|
||||||
<button id="import-export-ok-btn">OK</button>
|
<button class="positive-btn" id="import-export-ok-btn">OK</button>
|
||||||
<button id="import-export-cancel-btn">Cancel</button>
|
<button class="negative-btn" id="import-export-cancel-btn">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="overlays-menu-container">
|
<div id="overlays-menu-container">
|
||||||
<button class="closeBtn" id="overlys-closeBtn">x</button>
|
<div id="overlays-list">
|
||||||
<details id="markers-wrapper"><summary>Markers</summary><ul id="markers-list"></ul></details>
|
<details id="markers-wrapper"><summary>Markers</summary><ul id="markers-list"></ul></details>
|
||||||
<details id="circles-wrapper"><summary>Circles</summary><ul id="circles-list"></ul></details>
|
<details id="circles-wrapper"><summary>Circles</summary><ul id="circles-list"></ul></details>
|
||||||
<details id="polygons-wrapper"><summary>Polygons</summary><ul id="polygons-list"></ul></details>
|
<details id="polygons-wrapper"><summary>Polygons</summary><ul id="polygons-list"></ul></details>
|
||||||
|
</div>
|
||||||
<div class="multiBtn-container">
|
<div class="multiBtn-container">
|
||||||
|
<button id="set-home-btn">Set Home</button>
|
||||||
<button id="import-btn">Import</button>
|
<button id="import-btn">Import</button>
|
||||||
<button id="export-all-btn">Export All</button>
|
<button id="export-all-btn">Export All</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--</div>-->
|
|
||||||
</body>
|
</body>
|
||||||
<link rel='stylesheet' type="text/css" href="./leaflet.css">
|
<link rel='stylesheet' type="text/css" href="./leaflet.css">
|
||||||
<script src="./leaflet.js"></script>
|
<script src="./leaflet.js"></script>
|
||||||
|
|
|
@ -27,37 +27,82 @@ class OverlayBase {
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
add(map) {
|
static listAdd(self, listName) {
|
||||||
this.self.addTo(map);
|
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) => {
|
||||||
|
//show EditOverlayModal with this overlay's data
|
||||||
|
};
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
remove(map) {
|
|
||||||
this.self.removeFrom(map);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Marker extends OverlayBase {
|
class Marker extends OverlayBase {
|
||||||
constructor(name, desc, point, options) {
|
constructor(name, desc, point, options) {
|
||||||
super(name, desc, [point], options);
|
super(name, desc, [point], options);
|
||||||
|
this.menuItem = null;
|
||||||
this.self = L.marker(point);
|
this.self = L.marker(point);
|
||||||
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
|
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 {
|
class Circle extends OverlayBase {
|
||||||
constructor(name, desc, point, options) {
|
constructor(name, desc, point, options) {
|
||||||
super(name, desc, [point], options);
|
super(name, desc, [point], options);
|
||||||
|
this.menuItem = null;
|
||||||
this.self = L.circle(point, options);
|
this.self = L.circle(point, options);
|
||||||
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
|
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 {
|
class Polygon extends OverlayBase {
|
||||||
constructor(name, desc, points, options) {
|
constructor(name, desc, points, options) {
|
||||||
super(name, desc, points, options);
|
super(name, desc, points, options);
|
||||||
|
this.menuItem = null;
|
||||||
this.self = L.polygon(points, options);
|
this.self = L.polygon(points, options);
|
||||||
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
|
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 {
|
class Polyline extends OverlayBase {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("", "", [], {});
|
super("", "", [], {});
|
||||||
|
this.menuItem = null;
|
||||||
this.self = L.polyline([]);
|
this.self = L.polyline([]);
|
||||||
}
|
}
|
||||||
insertPoint(pt) {
|
insertPoint(pt) {
|
||||||
|
@ -71,6 +116,12 @@ class Polyline extends OverlayBase {
|
||||||
numPoints() {
|
numPoints() {
|
||||||
return this.self.getLatLngs().length;
|
return this.self.getLatLngs().length;
|
||||||
}
|
}
|
||||||
|
add(map) {
|
||||||
|
this.self.addTo(map);
|
||||||
|
}
|
||||||
|
remove(map) {
|
||||||
|
this.self.removeFrom(map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class OverlayState {
|
class OverlayState {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -182,6 +233,12 @@ class CreateOverlayModal {
|
||||||
if (closeBtn) {
|
if (closeBtn) {
|
||||||
closeBtn.onclick = () => { _this.setVisible(false); };
|
closeBtn.onclick = () => { _this.setVisible(false); };
|
||||||
}
|
}
|
||||||
|
const s = this.self();
|
||||||
|
if (s) {
|
||||||
|
s.onsubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self() {
|
self() {
|
||||||
return document.getElementById("createOverlay-container");
|
return document.getElementById("createOverlay-container");
|
||||||
|
@ -252,7 +309,7 @@ class CreateOverlayModal {
|
||||||
submitBtn.onclick = () => {
|
submitBtn.onclick = () => {
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
if (name.trim().length < 1 || desc.trim().length < 1) {
|
if (name.trim().length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const point = new Marker(name, desc, args.latlng, { title: name, alt: name });
|
const point = new Marker(name, desc, args.latlng, { title: name, alt: name });
|
||||||
|
@ -271,7 +328,7 @@ class CreateOverlayModal {
|
||||||
const radius = _this.radiusField();
|
const radius = _this.radiusField();
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
if (name.trim().length < 1 || desc.trim().length < 1) {
|
if (name.trim().length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const circle = new Circle(name, desc, args.latlng, { radius: Number(radius) || 500 });
|
const circle = new Circle(name, desc, args.latlng, { radius: Number(radius) || 500 });
|
||||||
|
@ -289,7 +346,7 @@ class CreateOverlayModal {
|
||||||
submitBtn.onclick = () => {
|
submitBtn.onclick = () => {
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
if (name.trim().length < 1 || desc.trim().length < 1) {
|
if (name.trim().length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const polygon = new Polygon(name, desc, args.points, {});
|
const polygon = new Polygon(name, desc, args.points, {});
|
||||||
|
@ -390,17 +447,37 @@ class InfoModal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 {
|
class ModalCollection {
|
||||||
constructor(createOverlay, cancel, okCancel, info) {
|
constructor(createOverlay, cancel, okCancel, info, overlayMgr) {
|
||||||
this.createOverlay = createOverlay;
|
this.createOverlay = createOverlay;
|
||||||
this.cancel = cancel;
|
this.cancel = cancel;
|
||||||
this.okCancel = okCancel;
|
this.okCancel = okCancel;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
|
this.overlayMgr = overlayMgr;
|
||||||
}
|
}
|
||||||
closeAll() {
|
closeAll() {
|
||||||
this.createOverlay.setVisible(false);
|
this.createOverlay.setVisible(false);
|
||||||
this.cancel.setVisible(false);
|
this.cancel.setVisible(false);
|
||||||
this.okCancel.setVisible(false);
|
this.okCancel.setVisible(false);
|
||||||
|
this.overlayMgr.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class MapHandler {
|
class MapHandler {
|
||||||
|
@ -476,6 +553,7 @@ class MapHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (_g) { }
|
catch (_g) { }
|
||||||
|
self.overlays.polyline.clearPoints();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static addMarker(e) {
|
static addMarker(e) {
|
||||||
|
@ -695,7 +773,26 @@ class MapHandler {
|
||||||
static setHome(e) {
|
static setHome(e) {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
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()));
|
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) {
|
static goHome(e) {
|
||||||
|
@ -710,6 +807,18 @@ class MapHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MapHandler.instance = null;
|
MapHandler.instance = null;
|
||||||
function init() {
|
function init() {
|
||||||
|
@ -730,7 +839,7 @@ function init() {
|
||||||
overlays.circles.forEach(m => m.add(map));
|
overlays.circles.forEach(m => m.add(map));
|
||||||
overlays.polygons.forEach(m => m.add(map));
|
overlays.polygons.forEach(m => m.add(map));
|
||||||
overlays.polyline.add(map);
|
overlays.polyline.add(map);
|
||||||
const modals = new ModalCollection(new CreateOverlayModal(), new CancelModal(), new OKCancelModal(), new InfoModal());
|
const modals = new ModalCollection(new CreateOverlayModal(), new CancelModal(), new OKCancelModal(), new InfoModal(), new OverlayManagementModal());
|
||||||
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
||||||
MapHandler.setButtonClick("home-btn", MapHandler.goHome);
|
MapHandler.setButtonClick("home-btn", MapHandler.goHome);
|
||||||
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
|
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
|
||||||
|
@ -739,25 +848,10 @@ function init() {
|
||||||
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
|
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
|
||||||
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);
|
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);
|
||||||
MapHandler.setButtonClick("restore-btn", MapHandler.overlayReset);
|
MapHandler.setButtonClick("restore-btn", MapHandler.overlayReset);
|
||||||
MapHandler.setButtonClick("menu-btn", () => { });
|
MapHandler.setButtonClick("menu-btn", MapHandler.toggleMenu);
|
||||||
|
MapHandler.setButtonClick("set-home-btn", MapHandler.setHome);
|
||||||
MapHandler.setButtonClick("tiles-btn", MapHandler.swapTiles);
|
MapHandler.setButtonClick("tiles-btn", MapHandler.swapTiles);
|
||||||
map.on("locationfound", () => {
|
map.on("locationfound", MapHandler.setHome);
|
||||||
const okCancel = modals.okCancel;
|
|
||||||
okCancel.setMsg("Set Home to current location?");
|
|
||||||
const okBtn = okCancel.okBtn();
|
|
||||||
if (okBtn) {
|
|
||||||
okBtn.onclick = (e) => {
|
|
||||||
okCancel.setVisible(false);
|
|
||||||
MapHandler.setHome(null);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const cancelBtn = okCancel.cancelBtn();
|
|
||||||
if (cancelBtn) {
|
|
||||||
cancelBtn.onclick = () => {
|
|
||||||
okCancel.setVisible(false);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
map.on("locationerror", () => {
|
map.on("locationerror", () => {
|
||||||
const info = modals.info;
|
const info = modals.info;
|
||||||
info.setMsg("Could not get location data");
|
info.setMsg("Could not get location data");
|
||||||
|
@ -771,5 +865,6 @@ function init() {
|
||||||
else {
|
else {
|
||||||
map.locate({ setView: true, maxZoom: 13 });
|
map.locate({ setView: true, maxZoom: 13 });
|
||||||
}
|
}
|
||||||
|
modals.closeAll();
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
|
|
108
static/style.css
108
static/style.css
|
@ -57,14 +57,21 @@ body {
|
||||||
font-size: 5vh;
|
font-size: 5vh;
|
||||||
padding-left: 0.5ch;
|
padding-left: 0.5ch;
|
||||||
padding-right: 0.5ch;
|
padding-right: 0.5ch;
|
||||||
|
border: solid 1px black;
|
||||||
border-bottom: solid 0.1em black;
|
border-bottom: solid 0.1em black;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mapControls button.activeBtn, #mapControls button:hover {
|
#mapControls .activeBtn,
|
||||||
|
#mapControls button:hover {
|
||||||
color: white;
|
color: white;
|
||||||
border-bottom: solid 0.1em #1f9b92;
|
border-bottom: solid 0.1em #1f9b92;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#mapControls button:focus {
|
||||||
|
border: dotted 1px #1f9b92;
|
||||||
|
border-bottom: solid 0.1em #1f9b92;
|
||||||
|
}
|
||||||
|
|
||||||
#subControls {
|
#subControls {
|
||||||
backgorund: transparent;
|
backgorund: transparent;
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -154,7 +161,7 @@ body {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.closeBtn {
|
.closeBtn {
|
||||||
float: right;
|
float: right;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
font-size: 200%;
|
font-size: 200%;
|
||||||
|
@ -165,11 +172,17 @@ button.closeBtn {
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.closeBtn:hover {
|
.closeBtn:hover,
|
||||||
|
.closeBtn:focus {
|
||||||
color: crimson;
|
color: crimson;
|
||||||
}
|
}
|
||||||
|
|
||||||
button#createOverlay-submitBtn, button.positive-btn, button.negative-btn {
|
#createOverlay-submitBtn,
|
||||||
|
.positive-btn,
|
||||||
|
.negative-btn,
|
||||||
|
#set-home-btn,
|
||||||
|
#import-btn,
|
||||||
|
#export-all-btn {
|
||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -180,32 +193,41 @@ button#createOverlay-submitBtn, button.positive-btn, button.negative-btn {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
button#createOverlay-submitBtn:hover {
|
#createOverlay-submitBtn:hover,
|
||||||
|
#createOverlay-submitBtn:focus,
|
||||||
|
#set-home-btn:hover,
|
||||||
|
#set-home-btn:focus,
|
||||||
|
#import-btn:hover,
|
||||||
|
#import-btn:focus,
|
||||||
|
#export-all-btn:hover,
|
||||||
|
#export-all-btn:focus {
|
||||||
background: white;
|
background: white;
|
||||||
color: black;
|
color: black;
|
||||||
border: solid 2px white;
|
border: solid 2px white;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.positive-btn, button.negative-btn {
|
.positive-btn, .negative-btn {
|
||||||
font-size: 66.66%;
|
font-size: 66.66%;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.positive-btn {
|
.positive-btn {
|
||||||
border: solid 2px #1f9b92;
|
border: solid 2px #1f9b92;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.positive-btn:hover {
|
.positive-btn:hover,
|
||||||
|
.positive-btn:focus {
|
||||||
color: black;
|
color: black;
|
||||||
background: #1f9b92;
|
background: #1f9b92;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.negative-btn {
|
.negative-btn {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.negative-btn:hover {
|
.negative-btn:hover,
|
||||||
|
.negative-btn:focus {
|
||||||
color: black;
|
color: black;
|
||||||
background: crimson;
|
background: crimson;
|
||||||
border: solid 2px crimson;
|
border: solid 2px crimson;
|
||||||
|
@ -231,7 +253,7 @@ button.negative-btn:hover {
|
||||||
line-height: 200%;
|
line-height: 200%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#info-container button.closeBtn {
|
#info-container .closeBtn {
|
||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-left: 1ch;
|
margin-left: 1ch;
|
||||||
|
@ -252,9 +274,71 @@ button.negative-btn:hover {
|
||||||
|
|
||||||
#overlays-menu-container {
|
#overlays-menu-container {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: calc(100vh - 2.5em);
|
height: 100vh;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
background: black;
|
background: black;
|
||||||
|
color: white;
|
||||||
|
z-index:2;
|
||||||
|
display: none;
|
||||||
|
padding: 1em;
|
||||||
|
font-size: 150%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
grid-template-rows: 1fr auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-menu-container .multiBtn-container {
|
||||||
|
text-align: center;
|
||||||
|
grid-row: 2;
|
||||||
|
margin-bottom: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list {
|
||||||
|
font-size: 200%;
|
||||||
|
grid-row: 1;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list details summary {
|
||||||
|
outline-style: none;
|
||||||
|
border-bottom: solid 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list details summary:hover {
|
||||||
|
color: #1f9b92;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list details summary:focus {
|
||||||
|
border-bottom: dotted 1px #1f9b92;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list a {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
outline-style: none;
|
||||||
|
border-bottom: solid 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list a:hover {
|
||||||
|
color: #1f9b92;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlays-list a:focus {
|
||||||
|
border-bottom: dotted 1px #1f9b92;
|
||||||
|
}
|
||||||
|
#overlays-list details {
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#import-export-container {
|
||||||
|
display: none;
|
||||||
}
|
}
|
Loading…
Reference in a new issue