add web manifest, favicon; implement edit modal - just need import/export
This commit is contained in:
parent
7ef255c556
commit
30766accd6
11 changed files with 479 additions and 74 deletions
|
@ -7,6 +7,11 @@ enum OverlayType {
|
||||||
POINT = 0,
|
POINT = 0,
|
||||||
CIRCLE = 1,
|
CIRCLE = 1,
|
||||||
POLYGON = 2,
|
POLYGON = 2,
|
||||||
|
POLYLINE = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OverlayMap {
|
||||||
|
[listName: string]: OverlayType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Overlay {
|
interface Overlay {
|
||||||
|
@ -46,12 +51,49 @@ abstract class OverlayBase implements Overlay {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
center(): Point {
|
||||||
|
return this.points[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static centerAsString(pt: Point): string {
|
||||||
|
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 `<span class="tiny">${String(long).substring(0, 7)}°${eastWest}, ${String(lat).substring(0,7)}°${northSouth}</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPopupContent(content: string): void {
|
||||||
|
this.self.bindPopup(content);
|
||||||
|
}
|
||||||
|
|
||||||
abstract add(map: L.Map): void;
|
abstract add(map: L.Map): void;
|
||||||
|
|
||||||
abstract remove(map: L.Map): void;
|
abstract remove(map: L.Map): void;
|
||||||
|
|
||||||
abstract menuItem: Node | null;
|
abstract menuItem: Node | null;
|
||||||
|
|
||||||
|
private static classSanitize(input: string): string {
|
||||||
|
return input.replace(/\-/g, "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static overlayTypeMap: OverlayMap = {
|
||||||
|
markers_list: OverlayType.POINT,
|
||||||
|
circles_list: OverlayType.CIRCLE,
|
||||||
|
polygons_list: OverlayType.POLYGON,
|
||||||
|
}
|
||||||
|
|
||||||
static listAdd(self: OverlayBase, listName: string) {
|
static listAdd(self: OverlayBase, listName: string) {
|
||||||
const list = document.getElementById(listName);
|
const list = document.getElementById(listName);
|
||||||
if (list) {
|
if (list) {
|
||||||
|
@ -61,7 +103,7 @@ abstract class OverlayBase implements Overlay {
|
||||||
a.innerText = self.name;
|
a.innerText = self.name;
|
||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = (e: any) => {
|
a.onclick = (e: any) => {
|
||||||
//show EditOverlayModal with this overlay's data
|
MapHandler.editOverlay(self, OverlayBase.overlayTypeMap[OverlayBase.classSanitize(listName)]);
|
||||||
};
|
};
|
||||||
li.appendChild(a);
|
li.appendChild(a);
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
|
@ -130,6 +172,10 @@ class Polygon extends OverlayBase {
|
||||||
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
center(): Point {
|
||||||
|
return this.self.getCenter();
|
||||||
|
}
|
||||||
|
|
||||||
add(map: L.Map) {
|
add(map: L.Map) {
|
||||||
this.self.addTo(map);
|
this.self.addTo(map);
|
||||||
OverlayBase.listAdd(this, "polygons-list");
|
OverlayBase.listAdd(this, "polygons-list");
|
||||||
|
@ -163,6 +209,10 @@ class Polyline extends OverlayBase {
|
||||||
return this.self.getLatLngs().length;
|
return this.self.getLatLngs().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
center(): Point {
|
||||||
|
return this.self.getCenter();
|
||||||
|
}
|
||||||
|
|
||||||
add(map: L.Map) {
|
add(map: L.Map) {
|
||||||
this.self.addTo(map);
|
this.self.addTo(map);
|
||||||
}
|
}
|
||||||
|
@ -229,6 +279,7 @@ class OverlayState {
|
||||||
private static fromData(data: OverlayData): OverlayBase {
|
private static fromData(data: OverlayData): OverlayBase {
|
||||||
switch(data.type) {
|
switch(data.type) {
|
||||||
case OverlayType.POINT:
|
case OverlayType.POINT:
|
||||||
|
default:
|
||||||
return new Marker(data.name, data.desc, data.points[0], data.options);
|
return new Marker(data.name, data.desc, data.points[0], data.options);
|
||||||
case OverlayType.CIRCLE:
|
case OverlayType.CIRCLE:
|
||||||
return new Circle(data.name, data.desc, data.points[0], data.options);
|
return new Circle(data.name, data.desc, data.points[0], data.options);
|
||||||
|
|
|
@ -34,6 +34,27 @@ class CreateOverlayModal implements Modal {
|
||||||
return document.getElementById("radius-container");
|
return document.getElementById("radius-container");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setName(name: string): void {
|
||||||
|
const self = document.getElementById("createOverlay-name") as HTMLInputElement;
|
||||||
|
if (self) {
|
||||||
|
self.value = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setDesc(desc: string): void {
|
||||||
|
const self = document.getElementById("createOverlay-desc") as HTMLInputElement;
|
||||||
|
if (self) {
|
||||||
|
self.value = desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setRadius(radius: Number) {
|
||||||
|
const self = document.getElementById("createOverlay-radius") as HTMLInputElement;
|
||||||
|
if (self) {
|
||||||
|
self.value = String(radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nameField(): string {
|
nameField(): string {
|
||||||
return (document.getElementById("createOverlay-name") as HTMLInputElement)?.value ?? "";
|
return (document.getElementById("createOverlay-name") as HTMLInputElement)?.value ?? "";
|
||||||
}
|
}
|
||||||
|
@ -57,6 +78,25 @@ class CreateOverlayModal implements Modal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setExtraButtonsVisible(v: boolean): void {
|
||||||
|
const extraBtns = document.getElementById("edit-extra-btns");
|
||||||
|
if (extraBtns) {
|
||||||
|
extraBtns.style.display = v ? "inline" : "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gotoBtn(): HTMLElement | null {
|
||||||
|
return document.getElementById("goto-btn");
|
||||||
|
}
|
||||||
|
|
||||||
|
exportBtn(): HTMLElement | null {
|
||||||
|
return document.getElementById("export-btn");
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteBtn(): HTMLElement | null {
|
||||||
|
return document.getElementById("delete-btn");
|
||||||
|
}
|
||||||
|
|
||||||
clearInputs(): void {
|
clearInputs(): void {
|
||||||
const name = document.getElementById("createOverlay-name") as HTMLInputElement;
|
const name = document.getElementById("createOverlay-name") as HTMLInputElement;
|
||||||
const desc = document.getElementById("createOverlay-desc") as HTMLInputElement;
|
const desc = document.getElementById("createOverlay-desc") as HTMLInputElement;
|
||||||
|
@ -80,15 +120,73 @@ class CreateOverlayModal implements Modal {
|
||||||
const submitBtn = _this.submitBtn();
|
const submitBtn = _this.submitBtn();
|
||||||
|
|
||||||
_this.clearInputs();
|
_this.clearInputs();
|
||||||
|
|
||||||
if (radiusContainer) {
|
if (radiusContainer) {
|
||||||
radiusContainer.style.display = state == OverlayType.CIRCLE ? "block" : "none";
|
radiusContainer.style.display = state == OverlayType.CIRCLE ? "block" : "none";
|
||||||
}
|
}
|
||||||
|
const editing = args.self ? true : false;
|
||||||
|
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 Polygon ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gotoBtn) {
|
||||||
|
gotoBtn.onclick = () => {
|
||||||
|
_this.setVisible(false);
|
||||||
|
args.map.setView(args.self.center());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exportBtn) {
|
||||||
|
// show export window with this Overlay's OverlayData
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deleteBtn) {
|
||||||
|
deleteBtn.onclick = () => {
|
||||||
|
MapHandler.confirmDelete(args.self as OverlayBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
|
_this.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case OverlayType.POINT:
|
case OverlayType.POINT:
|
||||||
if (title) {
|
if (title) {
|
||||||
title.innerHTML = "Add Marker";
|
title.innerHTML = "Add Marker ";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submitBtn) {
|
if (submitBtn) {
|
||||||
|
@ -107,7 +205,7 @@ class CreateOverlayModal implements Modal {
|
||||||
break;
|
break;
|
||||||
case OverlayType.CIRCLE:
|
case OverlayType.CIRCLE:
|
||||||
if (title) {
|
if (title) {
|
||||||
title.innerHTML = "Add Circle";
|
title.innerHTML = "Add Circle ";
|
||||||
}
|
}
|
||||||
if (submitBtn) {
|
if (submitBtn) {
|
||||||
submitBtn.onclick = () => {
|
submitBtn.onclick = () => {
|
||||||
|
@ -126,7 +224,7 @@ class CreateOverlayModal implements Modal {
|
||||||
break;
|
break;
|
||||||
case OverlayType.POLYGON:
|
case OverlayType.POLYGON:
|
||||||
if (title) {
|
if (title) {
|
||||||
title.innerHTML = "Add Polygon";
|
title.innerHTML = "Add Polygon ";
|
||||||
}
|
}
|
||||||
if (submitBtn) {
|
if (submitBtn) {
|
||||||
submitBtn.onclick = () => {
|
submitBtn.onclick = () => {
|
||||||
|
@ -143,5 +241,9 @@ class CreateOverlayModal implements Modal {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (title) {
|
||||||
|
title.innerHTML += OverlayBase.centerAsString(args.self ? args.self.center() : (state === OverlayType.POLYGON ? args.overlays.polyline.center() : args.latlng));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -92,6 +92,20 @@ class MapHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
static addCircle(e: any): void {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
if (self) {
|
||||||
|
@ -362,4 +376,28 @@ class MapHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
12
src/build.sh
12
src/build.sh
|
@ -8,6 +8,10 @@ if [ ! -z "$1" ]; then
|
||||||
progname=$1
|
progname=$1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -e ${progname}.ts ]; then
|
||||||
|
rm ${progname}.ts
|
||||||
|
fi
|
||||||
|
|
||||||
# build the source map and concatenate the source
|
# build the source map and concatenate the source
|
||||||
srcmap=$(mktemp)
|
srcmap=$(mktemp)
|
||||||
for f in *.ts; do
|
for f in *.ts; do
|
||||||
|
@ -25,10 +29,14 @@ errorOut=$(mktemp)
|
||||||
# compile and write output to temporary file
|
# compile and write output to temporary file
|
||||||
tsc --strict --target ES2015 --outFile ../static/${progname}.js ${progname}.ts | sed -e s/\(/:/ -e s/,/:/ -e s/\):// | nobs >> ${errorOut}
|
tsc --strict --target ES2015 --outFile ../static/${progname}.js ${progname}.ts | sed -e s/\(/:/ -e s/,/:/ -e s/\):// | nobs >> ${errorOut}
|
||||||
|
|
||||||
|
# if sourcemapper panics you can uncomment this
|
||||||
|
# cat ${errorOut}
|
||||||
|
|
||||||
# translate lines into original source with the source map and output to stdout
|
# translate lines into original source with the source map and output to stdout
|
||||||
../buildtools/sourcemapper ${errorOut} ${srcmap}
|
../buildtools/sourcemapper ${errorOut} ${srcmap}
|
||||||
|
|
||||||
|
|
||||||
# delete the temporary files
|
# delete the temporary files
|
||||||
rm ${errorOut}
|
rm ${errorOut}
|
||||||
rm ${progname}.ts
|
rm ${progname}.ts
|
||||||
rm ${srcmap}
|
rm ${srcmap}
|
BIN
static/favicon.png
Normal file
BIN
static/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
BIN
static/favicon_192.png
Normal file
BIN
static/favicon_192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
static/favicon_96.png
Normal file
BIN
static/favicon_96.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
|
@ -5,7 +5,9 @@
|
||||||
<meta name='description' content='map annotation tool'/>
|
<meta name='description' content='map annotation tool'/>
|
||||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||||
<link rel='stylesheet' type='text/css' href='./style.css'>
|
<link rel='stylesheet' type='text/css' href='./style.css'>
|
||||||
<!--<link rel='shortcut icon' href='/img/favicon.png'>-->
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
|
<link rel='shortcut icon' href='/favicon.png'>
|
||||||
<title>ONYX/scry</title>
|
<title>ONYX/scry</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -45,8 +47,12 @@
|
||||||
<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/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="multiBtn-container" id="edit-extra-btns">
|
||||||
<button type="submit" id="createOverlay-submitBtn">OK</button>
|
<button id="goto-btn">Go Here</button>
|
||||||
|
<button id="export-btn">Export</button>
|
||||||
|
<button id="delete-btn">Delete</button>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="positive-btn" id="createOverlay-submitBtn">OK</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
14
static/manifest.json
Normal file
14
static/manifest.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"short_name": "ONYX/scry",
|
||||||
|
"name": "ONYX/scru map annotation tool",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/favicon_192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": "/index.html",
|
||||||
|
"display": "standalone",
|
||||||
|
"orientation": "auto"
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ var OverlayType;
|
||||||
OverlayType[OverlayType["POINT"] = 0] = "POINT";
|
OverlayType[OverlayType["POINT"] = 0] = "POINT";
|
||||||
OverlayType[OverlayType["CIRCLE"] = 1] = "CIRCLE";
|
OverlayType[OverlayType["CIRCLE"] = 1] = "CIRCLE";
|
||||||
OverlayType[OverlayType["POLYGON"] = 2] = "POLYGON";
|
OverlayType[OverlayType["POLYGON"] = 2] = "POLYGON";
|
||||||
|
OverlayType[OverlayType["POLYLINE"] = 3] = "POLYLINE";
|
||||||
})(OverlayType || (OverlayType = {}));
|
})(OverlayType || (OverlayType = {}));
|
||||||
class OverlayData {
|
class OverlayData {
|
||||||
constructor(type, name, desc, points, options) {
|
constructor(type, name, desc, points, options) {
|
||||||
|
@ -27,6 +28,34 @@ class OverlayBase {
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.options = options;
|
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 `<span class="tiny">${String(long).substring(0, 7)}°${eastWest}, ${String(lat).substring(0, 7)}°${northSouth}</span>`;
|
||||||
|
}
|
||||||
|
setPopupContent(content) {
|
||||||
|
this.self.bindPopup(content);
|
||||||
|
}
|
||||||
|
static classSanitize(input) {
|
||||||
|
return input.replace(/\-/g, "_");
|
||||||
|
}
|
||||||
static listAdd(self, listName) {
|
static listAdd(self, listName) {
|
||||||
const list = document.getElementById(listName);
|
const list = document.getElementById(listName);
|
||||||
if (list) {
|
if (list) {
|
||||||
|
@ -36,7 +65,7 @@ class OverlayBase {
|
||||||
a.innerText = self.name;
|
a.innerText = self.name;
|
||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = (e) => {
|
a.onclick = (e) => {
|
||||||
//show EditOverlayModal with this overlay's data
|
MapHandler.editOverlay(self, OverlayBase.overlayTypeMap[OverlayBase.classSanitize(listName)]);
|
||||||
};
|
};
|
||||||
li.appendChild(a);
|
li.appendChild(a);
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
|
@ -51,6 +80,11 @@ class OverlayBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
OverlayBase.overlayTypeMap = {
|
||||||
|
markers_list: OverlayType.POINT,
|
||||||
|
circles_list: OverlayType.CIRCLE,
|
||||||
|
polygons_list: OverlayType.POLYGON,
|
||||||
|
};
|
||||||
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);
|
||||||
|
@ -90,6 +124,9 @@ class Polygon extends OverlayBase {
|
||||||
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>`);
|
||||||
}
|
}
|
||||||
|
center() {
|
||||||
|
return this.self.getCenter();
|
||||||
|
}
|
||||||
add(map) {
|
add(map) {
|
||||||
this.self.addTo(map);
|
this.self.addTo(map);
|
||||||
OverlayBase.listAdd(this, "polygons-list");
|
OverlayBase.listAdd(this, "polygons-list");
|
||||||
|
@ -116,6 +153,9 @@ class Polyline extends OverlayBase {
|
||||||
numPoints() {
|
numPoints() {
|
||||||
return this.self.getLatLngs().length;
|
return this.self.getLatLngs().length;
|
||||||
}
|
}
|
||||||
|
center() {
|
||||||
|
return this.self.getCenter();
|
||||||
|
}
|
||||||
add(map) {
|
add(map) {
|
||||||
this.self.addTo(map);
|
this.self.addTo(map);
|
||||||
}
|
}
|
||||||
|
@ -171,6 +211,7 @@ class OverlayState {
|
||||||
static fromData(data) {
|
static fromData(data) {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case OverlayType.POINT:
|
case OverlayType.POINT:
|
||||||
|
default:
|
||||||
return new Marker(data.name, data.desc, data.points[0], data.options);
|
return new Marker(data.name, data.desc, data.points[0], data.options);
|
||||||
case OverlayType.CIRCLE:
|
case OverlayType.CIRCLE:
|
||||||
return new Circle(data.name, data.desc, data.points[0], data.options);
|
return new Circle(data.name, data.desc, data.points[0], data.options);
|
||||||
|
@ -255,6 +296,24 @@ class CreateOverlayModal {
|
||||||
radiusContainer() {
|
radiusContainer() {
|
||||||
return document.getElementById("radius-container");
|
return document.getElementById("radius-container");
|
||||||
}
|
}
|
||||||
|
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() {
|
nameField() {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
return (_b = (_a = document.getElementById("createOverlay-name")) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "";
|
return (_b = (_a = document.getElementById("createOverlay-name")) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "";
|
||||||
|
@ -277,6 +336,21 @@ class CreateOverlayModal {
|
||||||
modal.style.display = v ? "block" : "none";
|
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() {
|
clearInputs() {
|
||||||
const name = document.getElementById("createOverlay-name");
|
const name = document.getElementById("createOverlay-name");
|
||||||
const desc = document.getElementById("createOverlay-desc");
|
const desc = document.getElementById("createOverlay-desc");
|
||||||
|
@ -300,62 +374,119 @@ class CreateOverlayModal {
|
||||||
if (radiusContainer) {
|
if (radiusContainer) {
|
||||||
radiusContainer.style.display = state == OverlayType.CIRCLE ? "block" : "none";
|
radiusContainer.style.display = state == OverlayType.CIRCLE ? "block" : "none";
|
||||||
}
|
}
|
||||||
switch (state) {
|
const editing = args.self ? true : false;
|
||||||
case OverlayType.POINT:
|
this.setExtraButtonsVisible(editing);
|
||||||
if (title) {
|
if (editing) {
|
||||||
title.innerHTML = "Add Marker";
|
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 Polygon ";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (submitBtn) {
|
}
|
||||||
submitBtn.onclick = () => {
|
if (gotoBtn) {
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
gotoBtn.onclick = () => {
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
_this.setVisible(false);
|
||||||
if (name.trim().length < 1) {
|
args.map.setView(args.self.center());
|
||||||
return;
|
};
|
||||||
}
|
}
|
||||||
const point = new Marker(name, desc, args.latlng, { title: name, alt: name });
|
if (exportBtn) {
|
||||||
point.add(args.map);
|
// show export window with this Overlay's OverlayData
|
||||||
args.overlays.markers.push(point);
|
}
|
||||||
_this.setVisible(false);
|
if (deleteBtn) {
|
||||||
};
|
deleteBtn.onclick = () => {
|
||||||
}
|
MapHandler.confirmDelete(args.self);
|
||||||
break;
|
};
|
||||||
case OverlayType.CIRCLE:
|
}
|
||||||
if (title) {
|
this.setName(args.self.name);
|
||||||
title.innerHTML = "Add Circle";
|
this.setDesc(args.self.desc);
|
||||||
}
|
if (state == OverlayType.CIRCLE) {
|
||||||
if (submitBtn) {
|
this.setRadius(args.self.options.radius);
|
||||||
submitBtn.onclick = () => {
|
}
|
||||||
const radius = _this.radiusField();
|
if (submitBtn) {
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
submitBtn.onclick = () => {
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
if (name.trim().length < 1) {
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
return;
|
if (name.trim().length < 1) {
|
||||||
}
|
return;
|
||||||
const circle = new Circle(name, desc, args.latlng, { radius: Number(radius) || 500 });
|
}
|
||||||
circle.add(args.map);
|
args.self.name = name;
|
||||||
args.overlays.circles.push(circle);
|
args.self.desc = desc;
|
||||||
_this.setVisible(false);
|
args.self.setPopupContent(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
};
|
_this.setVisible(false);
|
||||||
}
|
};
|
||||||
break;
|
}
|
||||||
case OverlayType.POLYGON:
|
}
|
||||||
if (title) {
|
else {
|
||||||
title.innerHTML = "Add Polygon";
|
switch (state) {
|
||||||
}
|
case OverlayType.POINT:
|
||||||
if (submitBtn) {
|
if (title) {
|
||||||
submitBtn.onclick = () => {
|
title.innerHTML = "Add Marker ";
|
||||||
const name = TextUtils.encodeHTML(_this.nameField());
|
}
|
||||||
const desc = TextUtils.encodeHTML(_this.descField());
|
if (submitBtn) {
|
||||||
if (name.trim().length < 1) {
|
submitBtn.onclick = () => {
|
||||||
return;
|
const name = TextUtils.encodeHTML(_this.nameField());
|
||||||
}
|
const desc = TextUtils.encodeHTML(_this.descField());
|
||||||
const polygon = new Polygon(name, desc, args.points, {});
|
if (name.trim().length < 1) {
|
||||||
polygon.add(args.map);
|
return;
|
||||||
args.overlays.polygons.push(polygon);
|
}
|
||||||
_this.setVisible(false);
|
const point = new Marker(name, desc, args.latlng, { title: name, alt: name });
|
||||||
};
|
point.add(args.map);
|
||||||
}
|
args.overlays.markers.push(point);
|
||||||
break;
|
_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 Polygon ";
|
||||||
|
}
|
||||||
|
if (submitBtn) {
|
||||||
|
submitBtn.onclick = () => {
|
||||||
|
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, {});
|
||||||
|
polygon.add(args.map);
|
||||||
|
args.overlays.polygons.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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -569,6 +700,19 @@ class MapHandler {
|
||||||
self.modals.createOverlay.setVisible(true);
|
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) {
|
static addCircle(e) {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
if (self) {
|
||||||
|
@ -819,6 +963,29 @@ class MapHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MapHandler.instance = null;
|
MapHandler.instance = null;
|
||||||
function init() {
|
function init() {
|
||||||
|
|
|
@ -16,6 +16,11 @@ body {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tiny {
|
||||||
|
font-size: 33%;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
#noscript-container {
|
#noscript-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -89,7 +94,7 @@ body {
|
||||||
|
|
||||||
#createOverlay-container {
|
#createOverlay-container {
|
||||||
background: #000000;
|
background: #000000;
|
||||||
color: #c9c9c9;
|
color: white;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
|
@ -114,12 +119,16 @@ body {
|
||||||
#createOverlay-container h2 {
|
#createOverlay-container h2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: 200%;
|
font-size: 200%;
|
||||||
font-wieght: normal;
|
font-weight: normal;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#createOverlay-container .multiBtn-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#createOverlay-content {
|
#createOverlay-content {
|
||||||
margin: 2em;
|
margin: 2em;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
@ -136,7 +145,9 @@ body {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createOverlay-content input[type="text"], #createOverlay-content textarea, #createOverlay-content input[type="number"] {
|
#createOverlay-content input[type="text"],
|
||||||
|
#createOverlay-content textarea,
|
||||||
|
#createOverlay-content input[type="number"] {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
|
@ -177,6 +188,7 @@ body {
|
||||||
color: crimson;
|
color: crimson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#createOverlay-container .multiBtn-container button,
|
||||||
#createOverlay-submitBtn,
|
#createOverlay-submitBtn,
|
||||||
.positive-btn,
|
.positive-btn,
|
||||||
.negative-btn,
|
.negative-btn,
|
||||||
|
@ -193,8 +205,10 @@ body {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createOverlay-submitBtn:hover,
|
#createOverlay-container .multiBtn-container button:hover,
|
||||||
#createOverlay-submitBtn:focus,
|
#createOverlay-container .multiBtn-container button:focus,
|
||||||
|
#createOverlay-container submitBtn:hover,
|
||||||
|
#createOverlay-container submitBtn:focus,
|
||||||
#set-home-btn:hover,
|
#set-home-btn:hover,
|
||||||
#set-home-btn:focus,
|
#set-home-btn:focus,
|
||||||
#import-btn:hover,
|
#import-btn:hover,
|
||||||
|
@ -212,14 +226,19 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.positive-btn {
|
.positive-btn {
|
||||||
border: solid 2px #1f9b92;
|
border: solid 2px #1f9b92 !important;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.positive-btn:hover,
|
.positive-btn:hover,
|
||||||
.positive-btn:focus {
|
.positive-btn:focus {
|
||||||
color: black;
|
color: black !important;
|
||||||
background: #1f9b92;
|
background: #1f9b92 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#createOverlay-submitBtn {
|
||||||
|
float: none;
|
||||||
|
font-size: 150%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.negative-btn {
|
.negative-btn {
|
||||||
|
|
Loading…
Reference in a new issue