add polygon support and use cancel/okCancel modals
This commit is contained in:
parent
c80313085e
commit
fbd1d515d3
11 changed files with 524 additions and 30 deletions
|
@ -79,17 +79,28 @@ class Polygon extends OverlayBase {
|
||||||
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>`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Path extends OverlayBase {
|
class Polyline extends OverlayBase {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("", "", [ ], {});
|
super("", "", [ ], {});
|
||||||
this.self = L.polyline([]);
|
this.self = L.polyline([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
insertPoint(pt: Point) {
|
insertPoint(pt: Point): void {
|
||||||
this.self.addLatLng(pt);
|
this.self.addLatLng(pt);
|
||||||
|
this.points.push(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearPoints(): void {
|
||||||
|
this.points = [];
|
||||||
|
this.self.setLatLngs([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
numPoints(): number {
|
||||||
|
return this.self.getLatLngs().length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,11 +108,13 @@ class OverlayState {
|
||||||
markers: Marker[];
|
markers: Marker[];
|
||||||
circles: Circle[];
|
circles: Circle[];
|
||||||
polygons: Polygon[];
|
polygons: Polygon[];
|
||||||
|
polyline: Polyline;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.markers = [];
|
this.markers = [];
|
||||||
this.circles = [];
|
this.circles = [];
|
||||||
this.polygons = [];
|
this.polygons = [];
|
||||||
|
this.polyline = new Polyline();
|
||||||
}
|
}
|
||||||
|
|
||||||
static load(): OverlayState {
|
static load(): OverlayState {
|
||||||
|
@ -112,6 +125,7 @@ class OverlayState {
|
||||||
markers: model.markers.map((m: OverlayData) => OverlayState.fromData(m)),
|
markers: model.markers.map((m: OverlayData) => OverlayState.fromData(m)),
|
||||||
circles: model.circles.map((c: OverlayData) => OverlayState.fromData(c)),
|
circles: model.circles.map((c: OverlayData) => OverlayState.fromData(c)),
|
||||||
polygons: model.polygons.map((p: OverlayData) => OverlayState.fromData(p)),
|
polygons: model.polygons.map((p: OverlayData) => OverlayState.fromData(p)),
|
||||||
|
polyline: new Polyline(),
|
||||||
} as OverlayState
|
} as OverlayState
|
||||||
} else {
|
} else {
|
||||||
return new OverlayState();
|
return new OverlayState();
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
class TextUtils {
|
class TextUtils {
|
||||||
static decodeHTML(text: string): string {
|
static decodeHTML(text: string): string {
|
||||||
|
return text;
|
||||||
const textArea = document.createElement('textarea');
|
const textArea = document.createElement('textarea');
|
||||||
textArea.innerHTML = text;
|
textArea.innerHTML = text;
|
||||||
return textArea.value;
|
return textArea.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static encodeHTML(text: string): string {
|
static encodeHTML(text: string): string {
|
||||||
|
return text;
|
||||||
const textArea = document.createElement('textarea');
|
const textArea = document.createElement('textarea');
|
||||||
textArea.innerText = text;
|
textArea.innerText = text;
|
||||||
return textArea.innerHTML;
|
return textArea.innerHTML;
|
||||||
|
|
|
@ -89,6 +89,9 @@ 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) {
|
||||||
|
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});
|
||||||
point.add(args.map);
|
point.add(args.map);
|
||||||
args.overlays.markers.push(point);
|
args.overlays.markers.push(point);
|
||||||
|
@ -105,6 +108,9 @@ 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) {
|
||||||
|
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});
|
||||||
circle.add(args.map);
|
circle.add(args.map);
|
||||||
args.overlays.circles.push(circle);
|
args.overlays.circles.push(circle);
|
||||||
|
@ -113,6 +119,22 @@ class CreateOverlayModal {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OverlayType.POLYGON:
|
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 || desc.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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
src/21-cancelModal.ts
Normal file
31
src/21-cancelModal.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
class CancelModal {
|
||||||
|
self(): HTMLElement | null {
|
||||||
|
return document.getElementById("cancel-container");
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelMsg(): HTMLElement | null {
|
||||||
|
return document.getElementById("cancel-msg");
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelBtn(): HTMLElement | null {
|
||||||
|
return document.getElementById("cancel-btn");
|
||||||
|
}
|
||||||
|
|
||||||
|
visible(): boolean {
|
||||||
|
return this.self()?.style.display != "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisible(v: boolean): void {
|
||||||
|
const modal = this.self();
|
||||||
|
if (modal) {
|
||||||
|
modal.style.display = v ? "block" : "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setMsg(s: string): void {
|
||||||
|
const msg = this.cancelMsg();
|
||||||
|
if (msg) {
|
||||||
|
msg.innerText = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/22-okCancelModal.ts
Normal file
35
src/22-okCancelModal.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
class OKCancelModal {
|
||||||
|
self(): HTMLElement | null {
|
||||||
|
return document.getElementById("confirm-container");
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmMsg(): HTMLElement | null {
|
||||||
|
return document.getElementById("confirm-msg");
|
||||||
|
}
|
||||||
|
|
||||||
|
okBtn(): HTMLElement | null {
|
||||||
|
return document.getElementById("yes-btn");
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelBtn(): HTMLElement | null {
|
||||||
|
return document.getElementById("no-btn");
|
||||||
|
}
|
||||||
|
|
||||||
|
visible(): boolean {
|
||||||
|
return this.self()?.style.display != "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisible(v: boolean): void {
|
||||||
|
const modal = this.self();
|
||||||
|
if (modal) {
|
||||||
|
modal.style.display = v ? "block" : "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setMsg(s: string): void {
|
||||||
|
const msg = this.confirmMsg();
|
||||||
|
if (msg) {
|
||||||
|
msg.innerText = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,21 @@
|
||||||
class ModalCollection {
|
class ModalCollection {
|
||||||
createOverlay: CreateOverlayModal;
|
createOverlay: CreateOverlayModal;
|
||||||
|
cancel: CancelModal;
|
||||||
|
okCancel: OKCancelModal;
|
||||||
|
|
||||||
constructor(createOverlay: CreateOverlayModal) {
|
constructor(
|
||||||
|
createOverlay: CreateOverlayModal,
|
||||||
|
cancel: CancelModal,
|
||||||
|
okCancel: OKCancelModal
|
||||||
|
) {
|
||||||
this.createOverlay = createOverlay;
|
this.createOverlay = createOverlay;
|
||||||
|
this.cancel = cancel;
|
||||||
|
this.okCancel = okCancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeAll(): void {
|
closeAll(): void {
|
||||||
this.createOverlay.setVisible(false);
|
this.createOverlay.setVisible(false);
|
||||||
|
this.cancel.setVisible(false);
|
||||||
|
this.okCancel.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,14 +34,21 @@ class MapHandler {
|
||||||
if (addPointBtn) {
|
if (addPointBtn) {
|
||||||
addPointBtn.classList.remove("activeBtn");
|
addPointBtn.classList.remove("activeBtn");
|
||||||
}
|
}
|
||||||
self.map.off("click", this.addMarker);
|
self.map.off("click", MapHandler.addMarker);
|
||||||
} catch {}
|
} catch {}
|
||||||
try {
|
try {
|
||||||
const addCircleBtn = document.getElementById("addCircle-btn");
|
const addCircleBtn = document.getElementById("addCircle-btn");
|
||||||
if (addCircleBtn) {
|
if (addCircleBtn) {
|
||||||
addCircleBtn.classList.remove("activeBtn");
|
addCircleBtn.classList.remove("activeBtn");
|
||||||
}
|
}
|
||||||
self.map.off("click", this.addCircle);
|
self.map.off("click", MapHandler.addCircle);
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
const addPolygonBtn = document.getElementById("addPolygon-btn");
|
||||||
|
if (addPolygonBtn) {
|
||||||
|
addPolygonBtn.classList.remove("activeBtn");
|
||||||
|
}
|
||||||
|
self.map.off("click", MapHandler.polygonAddPoint);
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,26 +56,43 @@ class MapHandler {
|
||||||
static addMarker(e: any): void {
|
static addMarker(e: any): void {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
if (self) {
|
||||||
self.modals.createOverlay.setVisible(true);
|
self.modals.cancel.setVisible(false);
|
||||||
self.modals.createOverlay.setState(OverlayType.POINT, {
|
self.modals.createOverlay.setState(OverlayType.POINT, {
|
||||||
latlng: e.latlng,
|
latlng: e.latlng,
|
||||||
map: self.map,
|
map: self.map,
|
||||||
overlays: self.overlays,
|
overlays: self.overlays,
|
||||||
});
|
});
|
||||||
MapHandler.resetMapClick();
|
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) {
|
||||||
self.modals.createOverlay.setVisible(true);
|
self.modals.cancel.setVisible(false);
|
||||||
self.modals.createOverlay.setState(OverlayType.CIRCLE, {
|
self.modals.createOverlay.setState(OverlayType.CIRCLE, {
|
||||||
latlng: e.latlng,
|
latlng: e.latlng,
|
||||||
map: self.map,
|
map: self.map,
|
||||||
overlays: self.overlays,
|
overlays: self.overlays,
|
||||||
});
|
});
|
||||||
MapHandler.resetMapClick();
|
MapHandler.resetMapClick();
|
||||||
|
self.modals.createOverlay.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static addPolygon(e: any): void {
|
||||||
|
const self = MapHandler.instance;
|
||||||
|
if (self) {
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
self.modals.createOverlay.setState(OverlayType.POLYGON, {
|
||||||
|
points: self.overlays.polyline.points,
|
||||||
|
map: self.map,
|
||||||
|
overlays: self.overlays,
|
||||||
|
});
|
||||||
|
MapHandler.resetMapClick();
|
||||||
|
self.overlays.polyline.clearPoints();
|
||||||
|
self.modals.createOverlay.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +103,16 @@ class MapHandler {
|
||||||
MapHandler.resetMapClick();
|
MapHandler.resetMapClick();
|
||||||
(e.target as HTMLElement).classList.add("activeBtn");
|
(e.target as HTMLElement).classList.add("activeBtn");
|
||||||
self.map.on("click", MapHandler.addCircle);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,20 +123,116 @@ class MapHandler {
|
||||||
MapHandler.resetMapClick();
|
MapHandler.resetMapClick();
|
||||||
(e.target as HTMLElement).classList.add("activeBtn");
|
(e.target as HTMLElement).classList.add("activeBtn");
|
||||||
self.map.on("click", MapHandler.addMarker);
|
self.map.on("click", MapHandler.addMarker);
|
||||||
|
|
||||||
|
const cancelBtn = self.modals.cancel.cancelBtn();
|
||||||
|
if (cancelBtn) {
|
||||||
|
cancelBtn.onclick = ()=> {
|
||||||
|
self.modals.closeAll();
|
||||||
|
MapHandler.resetMapClick();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
self.modals.cancel.setMsg("Placing marker");
|
||||||
|
self.modals.cancel.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static polygonCollect(e: any): void {
|
||||||
|
const self = MapHandler.instance;
|
||||||
|
if (self) {
|
||||||
|
self.modals.closeAll();
|
||||||
|
MapHandler.resetMapClick();
|
||||||
|
(e.target as HTMLElement).classList.add("activeBtn");
|
||||||
|
|
||||||
|
// show cancel -- on cancel, clear polyline and reset map handling
|
||||||
|
const cancelBtn = self.modals.cancel.cancelBtn();
|
||||||
|
if (cancelBtn) {
|
||||||
|
cancelBtn.onclick = MapHandler.polygonClearPoints;
|
||||||
|
}
|
||||||
|
self.modals.cancel.setMsg("Creating polygon");
|
||||||
|
self.modals.cancel.setVisible(true);
|
||||||
|
|
||||||
|
self.map.on("click", MapHandler.polygonAddPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static polygonClearPoints(e: any): void {
|
||||||
|
const self = MapHandler.instance;
|
||||||
|
if (self) {
|
||||||
|
self.modals.closeAll();
|
||||||
|
self.overlays.polyline.clearPoints();
|
||||||
|
MapHandler.resetMapClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static polygonAddPoint(e: any): void {
|
||||||
|
const self = MapHandler.instance;
|
||||||
|
if (self) {
|
||||||
|
self.overlays.polyline.insertPoint(e.latlng);
|
||||||
|
if (self.overlays.polyline.numPoints() >= 3) {
|
||||||
|
self.modals.cancel.setVisible(false);
|
||||||
|
|
||||||
|
const okBtn = self.modals.okCancel.okBtn();
|
||||||
|
if (okBtn) {
|
||||||
|
okBtn.onclick = MapHandler.addPolygon;
|
||||||
|
}
|
||||||
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
||||||
|
if (cancelBtn) {
|
||||||
|
cancelBtn.onclick = MapHandler.polygonClearPoints;
|
||||||
|
}
|
||||||
|
self.modals.okCancel.setMsg("Creating polygon");
|
||||||
|
self.modals.okCancel.setVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static overlaySave(e: any): void {
|
static overlaySave(e: any): void {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
if (self) {
|
||||||
|
self.modals.closeAll();
|
||||||
|
MapHandler.resetMapClick();
|
||||||
|
(e.target as HTMLElement).classList.add("activeBtn");
|
||||||
|
self.modals.okCancel.setMsg("Save current map overlays?");
|
||||||
|
|
||||||
|
const okBtn = self.modals.okCancel.okBtn();
|
||||||
|
if (okBtn) {
|
||||||
|
okBtn.onclick = ()=> {
|
||||||
OverlayState.save(self.overlays);
|
OverlayState.save(self.overlays);
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
// show info modal "Save complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
||||||
|
if (cancelBtn) {
|
||||||
|
cancelBtn.onclick = () => {
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.modals.okCancel.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static overlayClear(e: any): void {
|
static overlayClear(e: any): void {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
if (self) {
|
||||||
|
self.modals.closeAll();
|
||||||
|
MapHandler.resetMapClick();
|
||||||
|
(e.target as HTMLElement).classList.add("activeBtn");
|
||||||
|
self.modals.okCancel.setMsg("Clear all map overlays (will not affect saved data)?");
|
||||||
|
|
||||||
|
const okBtn = self.modals.okCancel.okBtn();
|
||||||
|
if (okBtn) {
|
||||||
|
okBtn.onclick = ()=> {
|
||||||
self.overlays = OverlayState.clear(self.overlays, self.map);
|
self.overlays = OverlayState.clear(self.overlays, self.map);
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
||||||
|
if (cancelBtn) {
|
||||||
|
cancelBtn.onclick = () => {
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.modals.okCancel.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,18 @@ function init(): void {
|
||||||
overlays.markers.forEach(m=>m.add(map));
|
overlays.markers.forEach(m=>m.add(map));
|
||||||
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));
|
||||||
const createOverlayModal = new CreateOverlayModal();
|
overlays.polyline.add(map);
|
||||||
|
|
||||||
const modals = new ModalCollection(
|
const modals = new ModalCollection(
|
||||||
createOverlayModal);
|
new CreateOverlayModal(),
|
||||||
|
new CancelModal(),
|
||||||
|
new OKCancelModal());
|
||||||
|
|
||||||
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
||||||
|
|
||||||
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
|
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
|
||||||
MapHandler.setButtonClick("addCircle-btn", MapHandler.circleCollect);
|
MapHandler.setButtonClick("addCircle-btn", MapHandler.circleCollect);
|
||||||
|
MapHandler.setButtonClick("addPolygon-btn", MapHandler.polygonCollect);
|
||||||
|
|
||||||
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
|
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
|
||||||
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);
|
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
<button id="addCircle-btn">∘</button>
|
<button id="addCircle-btn">∘</button>
|
||||||
<button id="addPolygon-btn">⋄</button>
|
<button id="addPolygon-btn">⋄</button>
|
||||||
<div id="subControls">
|
<div id="subControls">
|
||||||
<button id="save-btn">↓</button>
|
|
||||||
<button id="tiles-btn">∷</button>
|
<button id="tiles-btn">∷</button>
|
||||||
|
<button id="save-btn">↓</button>
|
||||||
<button id="clear-btn">↺</button>
|
<button id="clear-btn">↺</button>
|
||||||
<button id="menu-btn">≡</button>
|
<button id="menu-btn">≡</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -49,20 +49,23 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="cancel-container">
|
<div id="cancel-container">
|
||||||
|
<span id="cancel-msg"></span>
|
||||||
|
<div class="multiBtn-container">
|
||||||
<button class="negative-btn" id="cancel-btn">Cancel</button>
|
<button class="negative-btn" id="cancel-btn">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="info-container">
|
<div id="info-container">
|
||||||
<button class="closeBtn" id="info-closeBtn">x</button>
|
<button class="closeBtn" id="info-closeBtn">x</button>
|
||||||
<div class="info-content>
|
<div class="info-content">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="confirm-container">
|
<div id="confirm-container">
|
||||||
<span id="confirm-msg"></span>
|
<span id="confirm-msg"></span>
|
||||||
<div class="multiBtn-container">
|
<div class="multiBtn-container">
|
||||||
<button class="positive-btn" id="yes-btn">Yes</button>
|
<button class="positive-btn" id="yes-btn">OK</button>
|
||||||
<button class="negative-btn" id="no-btn">No</button>
|
<button class="negative-btn" id="no-btn">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -52,15 +52,24 @@ 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.self = L.polygon(points, options);
|
this.self = L.polygon(points, options);
|
||||||
|
this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Path extends OverlayBase {
|
class Polyline extends OverlayBase {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("", "", [], {});
|
super("", "", [], {});
|
||||||
this.self = L.polyline([]);
|
this.self = L.polyline([]);
|
||||||
}
|
}
|
||||||
insertPoint(pt) {
|
insertPoint(pt) {
|
||||||
this.self.addLatLng(pt);
|
this.self.addLatLng(pt);
|
||||||
|
this.points.push(pt);
|
||||||
|
}
|
||||||
|
clearPoints() {
|
||||||
|
this.points = [];
|
||||||
|
this.self.setLatLngs([]);
|
||||||
|
}
|
||||||
|
numPoints() {
|
||||||
|
return this.self.getLatLngs().length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class OverlayState {
|
class OverlayState {
|
||||||
|
@ -68,6 +77,7 @@ class OverlayState {
|
||||||
this.markers = [];
|
this.markers = [];
|
||||||
this.circles = [];
|
this.circles = [];
|
||||||
this.polygons = [];
|
this.polygons = [];
|
||||||
|
this.polyline = new Polyline();
|
||||||
}
|
}
|
||||||
static load() {
|
static load() {
|
||||||
const store = localStorage.getItem("overlay_state");
|
const store = localStorage.getItem("overlay_state");
|
||||||
|
@ -77,6 +87,7 @@ class OverlayState {
|
||||||
markers: model.markers.map((m) => OverlayState.fromData(m)),
|
markers: model.markers.map((m) => OverlayState.fromData(m)),
|
||||||
circles: model.circles.map((c) => OverlayState.fromData(c)),
|
circles: model.circles.map((c) => OverlayState.fromData(c)),
|
||||||
polygons: model.polygons.map((p) => OverlayState.fromData(p)),
|
polygons: model.polygons.map((p) => OverlayState.fromData(p)),
|
||||||
|
polyline: new Polyline(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -239,6 +250,9 @@ 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) {
|
||||||
|
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 });
|
||||||
point.add(args.map);
|
point.add(args.map);
|
||||||
args.overlays.markers.push(point);
|
args.overlays.markers.push(point);
|
||||||
|
@ -255,6 +269,9 @@ 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) {
|
||||||
|
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 });
|
||||||
circle.add(args.map);
|
circle.add(args.map);
|
||||||
args.overlays.circles.push(circle);
|
args.overlays.circles.push(circle);
|
||||||
|
@ -263,16 +280,93 @@ class CreateOverlayModal {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OverlayType.POLYGON:
|
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 || desc.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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 ModalCollection {
|
class ModalCollection {
|
||||||
constructor(createOverlay) {
|
constructor(createOverlay, cancel, okCancel) {
|
||||||
this.createOverlay = createOverlay;
|
this.createOverlay = createOverlay;
|
||||||
|
this.cancel = cancel;
|
||||||
|
this.okCancel = okCancel;
|
||||||
}
|
}
|
||||||
closeAll() {
|
closeAll() {
|
||||||
this.createOverlay.setVisible(false);
|
this.createOverlay.setVisible(false);
|
||||||
|
this.cancel.setVisible(false);
|
||||||
|
this.okCancel.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class MapHandler {
|
class MapHandler {
|
||||||
|
@ -301,7 +395,7 @@ class MapHandler {
|
||||||
if (addPointBtn) {
|
if (addPointBtn) {
|
||||||
addPointBtn.classList.remove("activeBtn");
|
addPointBtn.classList.remove("activeBtn");
|
||||||
}
|
}
|
||||||
self.map.off("click", this.addMarker);
|
self.map.off("click", MapHandler.addMarker);
|
||||||
}
|
}
|
||||||
catch (_a) { }
|
catch (_a) { }
|
||||||
try {
|
try {
|
||||||
|
@ -309,33 +403,57 @@ class MapHandler {
|
||||||
if (addCircleBtn) {
|
if (addCircleBtn) {
|
||||||
addCircleBtn.classList.remove("activeBtn");
|
addCircleBtn.classList.remove("activeBtn");
|
||||||
}
|
}
|
||||||
self.map.off("click", this.addCircle);
|
self.map.off("click", MapHandler.addCircle);
|
||||||
}
|
}
|
||||||
catch (_b) { }
|
catch (_b) { }
|
||||||
|
try {
|
||||||
|
const addPolygonBtn = document.getElementById("addPolygon-btn");
|
||||||
|
if (addPolygonBtn) {
|
||||||
|
addPolygonBtn.classList.remove("activeBtn");
|
||||||
|
}
|
||||||
|
self.map.off("click", MapHandler.polygonAddPoint);
|
||||||
|
}
|
||||||
|
catch (_c) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static addMarker(e) {
|
static addMarker(e) {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
if (self) {
|
||||||
self.modals.createOverlay.setVisible(true);
|
self.modals.cancel.setVisible(false);
|
||||||
self.modals.createOverlay.setState(OverlayType.POINT, {
|
self.modals.createOverlay.setState(OverlayType.POINT, {
|
||||||
latlng: e.latlng,
|
latlng: e.latlng,
|
||||||
map: self.map,
|
map: self.map,
|
||||||
overlays: self.overlays,
|
overlays: self.overlays,
|
||||||
});
|
});
|
||||||
MapHandler.resetMapClick();
|
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) {
|
||||||
self.modals.createOverlay.setVisible(true);
|
self.modals.cancel.setVisible(false);
|
||||||
self.modals.createOverlay.setState(OverlayType.CIRCLE, {
|
self.modals.createOverlay.setState(OverlayType.CIRCLE, {
|
||||||
latlng: e.latlng,
|
latlng: e.latlng,
|
||||||
map: self.map,
|
map: self.map,
|
||||||
overlays: self.overlays,
|
overlays: self.overlays,
|
||||||
});
|
});
|
||||||
MapHandler.resetMapClick();
|
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) {
|
static circleCollect(e) {
|
||||||
|
@ -345,6 +463,15 @@ class MapHandler {
|
||||||
MapHandler.resetMapClick();
|
MapHandler.resetMapClick();
|
||||||
e.target.classList.add("activeBtn");
|
e.target.classList.add("activeBtn");
|
||||||
self.map.on("click", MapHandler.addCircle);
|
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) {
|
static markerCollect(e) {
|
||||||
|
@ -354,18 +481,105 @@ class MapHandler {
|
||||||
MapHandler.resetMapClick();
|
MapHandler.resetMapClick();
|
||||||
e.target.classList.add("activeBtn");
|
e.target.classList.add("activeBtn");
|
||||||
self.map.on("click", MapHandler.addMarker);
|
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 polygon");
|
||||||
|
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 polygon");
|
||||||
|
self.modals.okCancel.setVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static overlaySave(e) {
|
static overlaySave(e) {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
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);
|
OverlayState.save(self.overlays);
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
// show info modal "Save complete"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
||||||
|
if (cancelBtn) {
|
||||||
|
cancelBtn.onclick = () => {
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
self.modals.okCancel.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static overlayClear(e) {
|
static overlayClear(e) {
|
||||||
const self = MapHandler.instance;
|
const self = MapHandler.instance;
|
||||||
if (self) {
|
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);
|
self.overlays = OverlayState.clear(self.overlays, self.map);
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const cancelBtn = self.modals.okCancel.cancelBtn();
|
||||||
|
if (cancelBtn) {
|
||||||
|
cancelBtn.onclick = () => {
|
||||||
|
self.modals.okCancel.setVisible(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
self.modals.okCancel.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static swapTiles(e) {
|
static swapTiles(e) {
|
||||||
|
@ -397,11 +611,12 @@ function init() {
|
||||||
overlays.markers.forEach(m => m.add(map));
|
overlays.markers.forEach(m => m.add(map));
|
||||||
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));
|
||||||
const createOverlayModal = new CreateOverlayModal();
|
overlays.polyline.add(map);
|
||||||
const modals = new ModalCollection(createOverlayModal);
|
const modals = new ModalCollection(new CreateOverlayModal(), new CancelModal(), new OKCancelModal());
|
||||||
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
|
||||||
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
|
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
|
||||||
MapHandler.setButtonClick("addCircle-btn", MapHandler.circleCollect);
|
MapHandler.setButtonClick("addCircle-btn", MapHandler.circleCollect);
|
||||||
|
MapHandler.setButtonClick("addPolygon-btn", MapHandler.polygonCollect);
|
||||||
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("tiles-btn", MapHandler.swapTiles);
|
MapHandler.setButtonClick("tiles-btn", MapHandler.swapTiles);
|
||||||
|
|
|
@ -169,9 +169,9 @@ button.closeBtn:hover {
|
||||||
color: crimson;
|
color: crimson;
|
||||||
}
|
}
|
||||||
|
|
||||||
button#createOverlay-submitBtn {
|
button#createOverlay-submitBtn, button.positive-btn, button.negative-btn {
|
||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
background: transparent;;
|
background: transparent;
|
||||||
color: white;
|
color: white;
|
||||||
border: solid 2px dimgray;
|
border: solid 2px dimgray;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -186,14 +186,42 @@ button#createOverlay-submitBtn:hover {
|
||||||
border: solid 2px white;
|
border: solid 2px white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.positive-btn, button.negative-btn {
|
||||||
|
font-size: 66.66%;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.positive-btn {
|
||||||
|
border: solid 2px #1f9b92;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.positive-btn:hover {
|
||||||
|
color: black;
|
||||||
|
background: #1f9b92;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.negative-btn {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.negative-btn:hover {
|
||||||
|
color: black;
|
||||||
|
background: crimson;
|
||||||
|
border: solid 2px crimson;
|
||||||
|
}
|
||||||
|
|
||||||
#cancel-container, #confirm-container, #info-container {
|
#cancel-container, #confirm-container, #info-container {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
font-size: 200%;
|
font-size: 250%;
|
||||||
bottom: 1.5em;
|
bottom: 5em;
|
||||||
display: none;
|
display: none;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateX(-50%);
|
||||||
background: black;
|
background: black;
|
||||||
|
z-index: 10;
|
||||||
|
color: white;
|
||||||
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#import-export-container {
|
#import-export-container {
|
||||||
|
|
Loading…
Reference in a new issue