add polygon support and use cancel/okCancel modals

This commit is contained in:
Iris Lightshard 2022-08-14 20:44:00 -06:00
parent c80313085e
commit fbd1d515d3
Signed by: Iris Lightshard
GPG key ID: 3B7FBC22144E6398
11 changed files with 524 additions and 30 deletions

View file

@ -79,17 +79,28 @@ class Polygon extends OverlayBase {
constructor(name: string, desc: string, points: Point[], options: any) {
super(name, desc, 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() {
super("", "", [ ], {});
this.self = L.polyline([]);
}
insertPoint(pt: Point) {
insertPoint(pt: Point): void {
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[];
circles: Circle[];
polygons: Polygon[];
polyline: Polyline;
constructor() {
this.markers = [];
this.circles = [];
this.polygons = [];
this.polyline = new Polyline();
}
static load(): OverlayState {
@ -112,6 +125,7 @@ class OverlayState {
markers: model.markers.map((m: OverlayData) => OverlayState.fromData(m)),
circles: model.circles.map((c: OverlayData) => OverlayState.fromData(c)),
polygons: model.polygons.map((p: OverlayData) => OverlayState.fromData(p)),
polyline: new Polyline(),
} as OverlayState
} else {
return new OverlayState();

View file

@ -1,11 +1,13 @@
class TextUtils {
static decodeHTML(text: string): string {
return text;
const textArea = document.createElement('textarea');
textArea.innerHTML = text;
return textArea.value;
}
static encodeHTML(text: string): string {
return text;
const textArea = document.createElement('textarea');
textArea.innerText = text;
return textArea.innerHTML;

View file

@ -89,6 +89,9 @@ class CreateOverlayModal {
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 point = new Marker(name, desc, args.latlng, {title: name, alt: name});
point.add(args.map);
args.overlays.markers.push(point);
@ -105,6 +108,9 @@ class CreateOverlayModal {
const radius = _this.radiusField();
const name = TextUtils.encodeHTML(_this.nameField());
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});
circle.add(args.map);
args.overlays.circles.push(circle);
@ -113,6 +119,22 @@ class CreateOverlayModal {
}
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 || 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;
}
}

31
src/21-cancelModal.ts Normal file
View 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
View 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;
}
}
}

View file

@ -1,11 +1,21 @@
class ModalCollection {
createOverlay: CreateOverlayModal;
cancel: CancelModal;
okCancel: OKCancelModal;
constructor(createOverlay: CreateOverlayModal) {
constructor(
createOverlay: CreateOverlayModal,
cancel: CancelModal,
okCancel: OKCancelModal
) {
this.createOverlay = createOverlay;
this.cancel = cancel;
this.okCancel = okCancel;
}
closeAll(): void {
this.createOverlay.setVisible(false);
this.cancel.setVisible(false);
this.okCancel.setVisible(false);
}
}

View file

@ -34,14 +34,21 @@ class MapHandler {
if (addPointBtn) {
addPointBtn.classList.remove("activeBtn");
}
self.map.off("click", this.addMarker);
self.map.off("click", MapHandler.addMarker);
} catch {}
try {
const addCircleBtn = document.getElementById("addCircle-btn");
if (addCircleBtn) {
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 {}
}
}
@ -49,26 +56,43 @@ class MapHandler {
static addMarker(e: any): void {
const self = MapHandler.instance;
if (self) {
self.modals.createOverlay.setVisible(true);
self.modals.cancel.setVisible(false);
self.modals.createOverlay.setState(OverlayType.POINT, {
latlng: e.latlng,
map: self.map,
overlays: self.overlays,
});
MapHandler.resetMapClick();
self.modals.createOverlay.setVisible(true);
}
}
static addCircle(e: any): void {
const self = MapHandler.instance;
if (self) {
self.modals.createOverlay.setVisible(true);
self.modals.cancel.setVisible(false);
self.modals.createOverlay.setState(OverlayType.CIRCLE, {
latlng: e.latlng,
map: self.map,
overlays: self.overlays,
});
MapHandler.resetMapClick();
self.modals.createOverlay.setVisible(true);
}
}
static addPolygon(e: any): void {
const self = MapHandler.instance;
if (self) {
self.modals.okCancel.setVisible(false);
self.modals.createOverlay.setState(OverlayType.POLYGON, {
points: self.overlays.polyline.points,
map: self.map,
overlays: self.overlays,
});
MapHandler.resetMapClick();
self.overlays.polyline.clearPoints();
self.modals.createOverlay.setVisible(true);
}
}
@ -79,6 +103,16 @@ class MapHandler {
MapHandler.resetMapClick();
(e.target as HTMLElement).classList.add("activeBtn");
self.map.on("click", MapHandler.addCircle);
const cancelBtn = self.modals.cancel.cancelBtn();
if (cancelBtn) {
cancelBtn.onclick = ()=> {
self.modals.closeAll();
MapHandler.resetMapClick();
};
}
self.modals.cancel.setMsg("Placing circle");
self.modals.cancel.setVisible(true);
}
}
@ -89,20 +123,116 @@ class MapHandler {
MapHandler.resetMapClick();
(e.target as HTMLElement).classList.add("activeBtn");
self.map.on("click", MapHandler.addMarker);
const cancelBtn = self.modals.cancel.cancelBtn();
if (cancelBtn) {
cancelBtn.onclick = ()=> {
self.modals.closeAll();
MapHandler.resetMapClick();
};
}
self.modals.cancel.setMsg("Placing marker");
self.modals.cancel.setVisible(true);
}
}
static polygonCollect(e: any): void {
const self = MapHandler.instance;
if (self) {
self.modals.closeAll();
MapHandler.resetMapClick();
(e.target as HTMLElement).classList.add("activeBtn");
// show cancel -- on cancel, clear polyline and reset map handling
const cancelBtn = self.modals.cancel.cancelBtn();
if (cancelBtn) {
cancelBtn.onclick = MapHandler.polygonClearPoints;
}
self.modals.cancel.setMsg("Creating 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 {
const self = MapHandler.instance;
if (self) {
OverlayState.save(self.overlays);
self.modals.closeAll();
MapHandler.resetMapClick();
(e.target as HTMLElement).classList.add("activeBtn");
self.modals.okCancel.setMsg("Save current map overlays?");
const okBtn = self.modals.okCancel.okBtn();
if (okBtn) {
okBtn.onclick = ()=> {
OverlayState.save(self.overlays);
self.modals.okCancel.setVisible(false);
// 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 {
const self = MapHandler.instance;
if (self) {
self.overlays = OverlayState.clear(self.overlays, self.map);
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.modals.okCancel.setVisible(false);
}
}
const cancelBtn = self.modals.okCancel.cancelBtn();
if (cancelBtn) {
cancelBtn.onclick = () => {
self.modals.okCancel.setVisible(false);
}
}
self.modals.okCancel.setVisible(true);
}
}

View file

@ -26,14 +26,18 @@ function init(): void {
overlays.markers.forEach(m=>m.add(map));
overlays.circles.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);
new CreateOverlayModal(),
new CancelModal(),
new OKCancelModal());
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
MapHandler.setButtonClick("addCircle-btn", MapHandler.circleCollect);
MapHandler.setButtonClick("addPolygon-btn", MapHandler.polygonCollect);
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);

View file

@ -22,8 +22,8 @@
<button id="addCircle-btn">&compfn;</button>
<button id="addPolygon-btn">&diamond;</button>
<div id="subControls">
<button id="tiles-btn">&Colon;</button>
<button id="save-btn">&darr;</button>
<button id="tiles-btn">&Colon;</button>
<button id="clear-btn">&olarr;</button>
<button id="menu-btn">&equiv;</button>
</div>
@ -49,20 +49,23 @@
</div>
<div id="cancel-container">
<span id="cancel-msg"></span>
<div class="multiBtn-container">
<button class="negative-btn" id="cancel-btn">Cancel</button>
</div>
</div>
<div id="info-container">
<button class="closeBtn" id="info-closeBtn">x</button>
<div class="info-content>
<div class="info-content">
</div>
</div>
<div id="confirm-container">
<span id="confirm-msg"></span>
<div class="multiBtn-container">
<button class="positive-btn" id="yes-btn">Yes</button>
<button class="negative-btn" id="no-btn">No</button>
<button class="positive-btn" id="yes-btn">OK</button>
<button class="negative-btn" id="no-btn">Cancel</button>
</div>
</div>

View file

@ -52,15 +52,24 @@ class Polygon extends OverlayBase {
constructor(name, desc, points, options) {
super(name, desc, 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() {
super("", "", [], {});
this.self = L.polyline([]);
}
insertPoint(pt) {
this.self.addLatLng(pt);
this.points.push(pt);
}
clearPoints() {
this.points = [];
this.self.setLatLngs([]);
}
numPoints() {
return this.self.getLatLngs().length;
}
}
class OverlayState {
@ -68,6 +77,7 @@ class OverlayState {
this.markers = [];
this.circles = [];
this.polygons = [];
this.polyline = new Polyline();
}
static load() {
const store = localStorage.getItem("overlay_state");
@ -77,6 +87,7 @@ class OverlayState {
markers: model.markers.map((m) => OverlayState.fromData(m)),
circles: model.circles.map((c) => OverlayState.fromData(c)),
polygons: model.polygons.map((p) => OverlayState.fromData(p)),
polyline: new Polyline(),
};
}
else {
@ -239,6 +250,9 @@ class CreateOverlayModal {
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 point = new Marker(name, desc, args.latlng, { title: name, alt: name });
point.add(args.map);
args.overlays.markers.push(point);
@ -255,6 +269,9 @@ class CreateOverlayModal {
const radius = _this.radiusField();
const name = TextUtils.encodeHTML(_this.nameField());
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 });
circle.add(args.map);
args.overlays.circles.push(circle);
@ -263,16 +280,93 @@ class CreateOverlayModal {
}
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 || 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;
}
}
}
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 {
constructor(createOverlay) {
constructor(createOverlay, cancel, okCancel) {
this.createOverlay = createOverlay;
this.cancel = cancel;
this.okCancel = okCancel;
}
closeAll() {
this.createOverlay.setVisible(false);
this.cancel.setVisible(false);
this.okCancel.setVisible(false);
}
}
class MapHandler {
@ -301,7 +395,7 @@ class MapHandler {
if (addPointBtn) {
addPointBtn.classList.remove("activeBtn");
}
self.map.off("click", this.addMarker);
self.map.off("click", MapHandler.addMarker);
}
catch (_a) { }
try {
@ -309,33 +403,57 @@ class MapHandler {
if (addCircleBtn) {
addCircleBtn.classList.remove("activeBtn");
}
self.map.off("click", this.addCircle);
self.map.off("click", MapHandler.addCircle);
}
catch (_b) { }
try {
const addPolygonBtn = document.getElementById("addPolygon-btn");
if (addPolygonBtn) {
addPolygonBtn.classList.remove("activeBtn");
}
self.map.off("click", MapHandler.polygonAddPoint);
}
catch (_c) { }
}
}
static addMarker(e) {
const self = MapHandler.instance;
if (self) {
self.modals.createOverlay.setVisible(true);
self.modals.cancel.setVisible(false);
self.modals.createOverlay.setState(OverlayType.POINT, {
latlng: e.latlng,
map: self.map,
overlays: self.overlays,
});
MapHandler.resetMapClick();
self.modals.createOverlay.setVisible(true);
}
}
static addCircle(e) {
const self = MapHandler.instance;
if (self) {
self.modals.createOverlay.setVisible(true);
self.modals.cancel.setVisible(false);
self.modals.createOverlay.setState(OverlayType.CIRCLE, {
latlng: e.latlng,
map: self.map,
overlays: self.overlays,
});
MapHandler.resetMapClick();
self.modals.createOverlay.setVisible(true);
}
}
static addPolygon(e) {
const self = MapHandler.instance;
if (self) {
self.modals.okCancel.setVisible(false);
self.modals.createOverlay.setState(OverlayType.POLYGON, {
points: self.overlays.polyline.points,
map: self.map,
overlays: self.overlays,
});
MapHandler.resetMapClick();
self.overlays.polyline.clearPoints();
self.modals.createOverlay.setVisible(true);
}
}
static circleCollect(e) {
@ -345,6 +463,15 @@ class MapHandler {
MapHandler.resetMapClick();
e.target.classList.add("activeBtn");
self.map.on("click", MapHandler.addCircle);
const cancelBtn = self.modals.cancel.cancelBtn();
if (cancelBtn) {
cancelBtn.onclick = () => {
self.modals.closeAll();
MapHandler.resetMapClick();
};
}
self.modals.cancel.setMsg("Placing circle");
self.modals.cancel.setVisible(true);
}
}
static markerCollect(e) {
@ -354,18 +481,105 @@ class MapHandler {
MapHandler.resetMapClick();
e.target.classList.add("activeBtn");
self.map.on("click", MapHandler.addMarker);
const cancelBtn = self.modals.cancel.cancelBtn();
if (cancelBtn) {
cancelBtn.onclick = () => {
self.modals.closeAll();
MapHandler.resetMapClick();
};
}
self.modals.cancel.setMsg("Placing marker");
self.modals.cancel.setVisible(true);
}
}
static polygonCollect(e) {
const self = MapHandler.instance;
if (self) {
self.modals.closeAll();
MapHandler.resetMapClick();
e.target.classList.add("activeBtn");
// show cancel -- on cancel, clear polyline and reset map handling
const cancelBtn = self.modals.cancel.cancelBtn();
if (cancelBtn) {
cancelBtn.onclick = MapHandler.polygonClearPoints;
}
self.modals.cancel.setMsg("Creating 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) {
const self = MapHandler.instance;
if (self) {
OverlayState.save(self.overlays);
self.modals.closeAll();
MapHandler.resetMapClick();
e.target.classList.add("activeBtn");
self.modals.okCancel.setMsg("Save current map overlays?");
const okBtn = self.modals.okCancel.okBtn();
if (okBtn) {
okBtn.onclick = () => {
OverlayState.save(self.overlays);
self.modals.okCancel.setVisible(false);
// 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) {
const self = MapHandler.instance;
if (self) {
self.overlays = OverlayState.clear(self.overlays, self.map);
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.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) {
@ -397,11 +611,12 @@ function init() {
overlays.markers.forEach(m => m.add(map));
overlays.circles.forEach(m => m.add(map));
overlays.polygons.forEach(m => m.add(map));
const createOverlayModal = new CreateOverlayModal();
const modals = new ModalCollection(createOverlayModal);
overlays.polyline.add(map);
const modals = new ModalCollection(new CreateOverlayModal(), new CancelModal(), new OKCancelModal());
MapHandler.init(map, overlays, TileLayerWrapper.layers, modals);
MapHandler.setButtonClick("addPoint-btn", MapHandler.markerCollect);
MapHandler.setButtonClick("addCircle-btn", MapHandler.circleCollect);
MapHandler.setButtonClick("addPolygon-btn", MapHandler.polygonCollect);
MapHandler.setButtonClick("save-btn", MapHandler.overlaySave);
MapHandler.setButtonClick("clear-btn", MapHandler.overlayClear);
MapHandler.setButtonClick("tiles-btn", MapHandler.swapTiles);

View file

@ -169,9 +169,9 @@ button.closeBtn:hover {
color: crimson;
}
button#createOverlay-submitBtn {
button#createOverlay-submitBtn, button.positive-btn, button.negative-btn {
font-size: 150%;
background: transparent;;
background: transparent;
color: white;
border: solid 2px dimgray;
position: relative;
@ -186,14 +186,42 @@ button#createOverlay-submitBtn:hover {
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 {
position: fixed;
font-size: 200%;
bottom: 1.5em;
font-size: 250%;
bottom: 5em;
display: none;
left: 50%;
transform: translateY(-50%);
transform: translateX(-50%);
background: black;
z-index: 10;
color: white;
padding: 0.5em;
}
#import-export-container {