all repos — onyx @ 30766accd61c704d72399bcfdc2591155ae25e53

minimal map annotation and location data sharing tool

add web manifest, favicon; implement edit modal - just need import/export
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmMAZV8ACgkQO3+8IhRO
Y5jeLg//YtHF+NeiQOcSe6tKwe17+FFfRTGzWPCewwY+OLD8/d+rkk7FHU/RrWO8
wsIgOBSeRJHn4C3DZc875A4Rce6LOsS3DhBlgpRc/pMfhCbjIFePrMR6Z6irUKru
Hzo16RCAl9F3O9WIS9MaNfah008uVe3sN3etWHiwnYCJWEVUwhcE1h43Cmyzb3CA
kltofdQODGRSBlYpTBtrFqVLtFAqCnBnxzPHnapceQwd1SGYQE0SN9KmRib571Ay
GSMycvmFdzrd7kk9EvhbBk+anDTX1bJWC+JjSP9rdfMSE5ahuKHjQhMVkjCSeOPQ
WEid/Pka+cHuLOG1EXQXYqEvSLJCyaUmu/0n1mK+VihkF79KMmcYXoxIIQiwglce
HZjjI12xZTlwATH3IlC3oHCAQ8e+Mu2Gc0owDF5JWOx5jf+07sLZQhb/xp38YQd+
+GFEENhC7rvMb9J3MvcvFFH66HqNVo67zgmkBvjSyF+7JdocdpjVvymQhtPCsKJB
04v4D+Gzrvc/Kx1izkuk2PXPDmwtOSlNsJ989W3yOfX4hYpj9KwBfwNPEw075tkW
NFOKybYiO6lssJMhuQwvn4vyT2zxDLBpwA+auXlfnuTl4byMmG5qZXAGU9Iuj3UR
uzrzZ0BIrBTh7xDO3AYNIWP1j8iS4BFdp3n2m76isCksn1WDHlI=
=w2ye
-----END PGP SIGNATURE-----
commit

30766accd61c704d72399bcfdc2591155ae25e53

parent

7ef255c556f3cf4d7889d58120319550a9bea53e

M src/10-overlay.tssrc/10-overlay.ts

@@ -7,6 +7,11 @@ enum OverlayType {

POINT = 0, CIRCLE = 1, POLYGON = 2, + POLYLINE = 3, +} + +interface OverlayMap { + [listName: string]: OverlayType; } interface Overlay {

@@ -46,12 +51,49 @@ this.points = points;

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)}&deg;${eastWest}, ${String(lat).substring(0,7)}&deg;${northSouth}</span>`; + } + + setPopupContent(content: string): void { + this.self.bindPopup(content); + } + abstract add(map: L.Map): void; abstract remove(map: L.Map): void; 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) { const list = document.getElementById(listName); if (list) {

@@ -61,7 +103,7 @@ if (li && a) {

a.innerText = self.name; a.href = "#"; a.onclick = (e: any) => { - //show EditOverlayModal with this overlay's data + MapHandler.editOverlay(self, OverlayBase.overlayTypeMap[OverlayBase.classSanitize(listName)]); }; li.appendChild(a); list.appendChild(li);

@@ -129,6 +171,10 @@ super(name, desc, points, options);

this.self = L.polygon(points, options); this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`); } + + center(): Point { + return this.self.getCenter(); + } add(map: L.Map) { this.self.addTo(map);

@@ -161,6 +207,10 @@ }

numPoints(): number { return this.self.getLatLngs().length; + } + + center(): Point { + return this.self.getCenter(); } add(map: L.Map) {

@@ -229,6 +279,7 @@

private static fromData(data: OverlayData): OverlayBase { switch(data.type) { case OverlayType.POINT: + default: return new Marker(data.name, data.desc, data.points[0], data.options); case OverlayType.CIRCLE: return new Circle(data.name, data.desc, data.points[0], data.options);
M src/20-createOverlayModal.tssrc/20-createOverlayModal.ts

@@ -34,6 +34,27 @@ radiusContainer(): HTMLElement | null {

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 { return (document.getElementById("createOverlay-name") as HTMLInputElement)?.value ?? ""; }

@@ -57,6 +78,25 @@ modal.style.display = v ? "block" : "none";

} } + 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 { const name = document.getElementById("createOverlay-name") as HTMLInputElement; const desc = document.getElementById("createOverlay-desc") as HTMLInputElement;

@@ -80,15 +120,73 @@ const radiusContainer = _this.radiusContainer();

const submitBtn = _this.submitBtn(); _this.clearInputs(); - if (radiusContainer) { 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) { case OverlayType.POINT: if (title) { - title.innerHTML = "Add Marker"; + title.innerHTML = "Add Marker "; } if (submitBtn) {

@@ -107,7 +205,7 @@ }

break; case OverlayType.CIRCLE: if (title) { - title.innerHTML = "Add Circle"; + title.innerHTML = "Add Circle "; } if (submitBtn) { submitBtn.onclick = () => {

@@ -126,7 +224,7 @@ }

break; case OverlayType.POLYGON: if (title) { - title.innerHTML = "Add Polygon"; + title.innerHTML = "Add Polygon "; } if (submitBtn) { submitBtn.onclick = () => {

@@ -142,6 +240,10 @@ _this.setVisible(false);

} } break; + } + } + if (title) { + title.innerHTML += OverlayBase.centerAsString(args.self ? args.self.center() : (state === OverlayType.POLYGON ? args.overlays.polyline.center() : args.latlng)); } } }
M src/40-handlers.tssrc/40-handlers.ts

@@ -92,6 +92,20 @@ self.modals.createOverlay.setVisible(true);

} } + 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 { const self = MapHandler.instance; if (self) {

@@ -360,6 +374,30 @@ self.modals.overlayMgr.setVisible(!visible);

if (!visible) { (e.target as HTMLElement).classList.add("activeBtn"); } + } + } + + 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); } } }
M src/build.shsrc/build.sh

@@ -8,6 +8,10 @@ if [ ! -z "$1" ]; then

progname=$1 fi +if [ -e ${progname}.ts ]; then + rm ${progname}.ts +fi + # build the source map and concatenate the source srcmap=$(mktemp) for f in *.ts; do

@@ -25,10 +29,14 @@

# 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} +# if sourcemapper panics you can uncomment this +# cat ${errorOut} + # 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 rm ${errorOut} -rm ${progname}.ts + rm ${progname}.ts rm ${srcmap}
M static/index.htmlstatic/index.html

@@ -5,7 +5,9 @@ <meta charset='utf-8'>

<meta name='description' content='map annotation tool'/> <meta name='viewport' content='width=device-width,initial-scale=1'> <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> </head> <body>

@@ -45,8 +47,12 @@ <div id="radius-container">

<label for="createOverlay-radius">Radius (meters)</label><br/> <input type="number" step="1" id="createOverlay-radius" value="500" required><br/> </div> - - <button type="submit" id="createOverlay-submitBtn">OK</button> + <div class="multiBtn-container" id="edit-extra-btns"> + <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> </div>
A static/manifest.json

@@ -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" +}
M static/onyx-scry.jsstatic/onyx-scry.js

@@ -10,6 +10,7 @@ (function (OverlayType) {

OverlayType[OverlayType["POINT"] = 0] = "POINT"; OverlayType[OverlayType["CIRCLE"] = 1] = "CIRCLE"; OverlayType[OverlayType["POLYGON"] = 2] = "POLYGON"; + OverlayType[OverlayType["POLYLINE"] = 3] = "POLYLINE"; })(OverlayType || (OverlayType = {})); class OverlayData { constructor(type, name, desc, points, options) {

@@ -27,6 +28,34 @@ this.desc = desc;

this.points = points; this.options = options; } + center() { + return this.points[0]; + } + static centerAsString(pt) { + let eastWest = ""; + let northSouth = ""; + const lat = pt.lat; + const long = pt.lng; + if (lat > 0) { + northSouth = "N"; + } + else if (lat < 0) { + northSouth = "S"; + } + if (long > 0) { + eastWest = "E"; + } + else if (long < 0) { + eastWest = "W"; + } + return `<span class="tiny">${String(long).substring(0, 7)}&deg;${eastWest}, ${String(lat).substring(0, 7)}&deg;${northSouth}</span>`; + } + setPopupContent(content) { + this.self.bindPopup(content); + } + static classSanitize(input) { + return input.replace(/\-/g, "_"); + } static listAdd(self, listName) { const list = document.getElementById(listName); if (list) {

@@ -36,7 +65,7 @@ if (li && a) {

a.innerText = self.name; a.href = "#"; a.onclick = (e) => { - //show EditOverlayModal with this overlay's data + MapHandler.editOverlay(self, OverlayBase.overlayTypeMap[OverlayBase.classSanitize(listName)]); }; li.appendChild(a); list.appendChild(li);

@@ -51,6 +80,11 @@ list.removeChild(self.menuItem);

} } } +OverlayBase.overlayTypeMap = { + markers_list: OverlayType.POINT, + circles_list: OverlayType.CIRCLE, + polygons_list: OverlayType.POLYGON, +}; class Marker extends OverlayBase { constructor(name, desc, point, options) { super(name, desc, [point], options);

@@ -90,6 +124,9 @@ this.menuItem = null;

this.self = L.polygon(points, options); this.self.bindPopup(`<h3>${name}</h3><p>${desc}</p>`); } + center() { + return this.self.getCenter(); + } add(map) { this.self.addTo(map); OverlayBase.listAdd(this, "polygons-list");

@@ -116,6 +153,9 @@ }

numPoints() { return this.self.getLatLngs().length; } + center() { + return this.self.getCenter(); + } add(map) { this.self.addTo(map); }

@@ -171,6 +211,7 @@ }

static fromData(data) { switch (data.type) { case OverlayType.POINT: + default: return new Marker(data.name, data.desc, data.points[0], data.options); case OverlayType.CIRCLE: return new Circle(data.name, data.desc, data.points[0], data.options);

@@ -255,6 +296,24 @@ }

radiusContainer() { 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() { var _a, _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 @@ if (modal) {

modal.style.display = v ? "block" : "none"; } } + setExtraButtonsVisible(v) { + const extraBtns = document.getElementById("edit-extra-btns"); + if (extraBtns) { + extraBtns.style.display = v ? "inline" : "none"; + } + } + gotoBtn() { + return document.getElementById("goto-btn"); + } + exportBtn() { + return document.getElementById("export-btn"); + } + deleteBtn() { + return document.getElementById("delete-btn"); + } clearInputs() { const name = document.getElementById("createOverlay-name"); const desc = document.getElementById("createOverlay-desc");

@@ -300,62 +374,119 @@ _this.clearInputs();

if (radiusContainer) { radiusContainer.style.display = state == OverlayType.CIRCLE ? "block" : "none"; } - switch (state) { - case OverlayType.POINT: - if (title) { - title.innerHTML = "Add Marker"; + 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 (submitBtn) { - submitBtn.onclick = () => { - const name = TextUtils.encodeHTML(_this.nameField()); - const desc = TextUtils.encodeHTML(_this.descField()); - if (name.trim().length < 1) { - return; - } - const point = new Marker(name, desc, args.latlng, { title: name, alt: name }); - point.add(args.map); - args.overlays.markers.push(point); - _this.setVisible(false); - }; - } - break; - case OverlayType.CIRCLE: - if (title) { - title.innerHTML = "Add Circle"; - } - if (submitBtn) { - submitBtn.onclick = () => { - const radius = _this.radiusField(); - const name = TextUtils.encodeHTML(_this.nameField()); - const desc = TextUtils.encodeHTML(_this.descField()); - if (name.trim().length < 1) { - return; - } - const circle = new Circle(name, desc, args.latlng, { radius: Number(radius) || 500 }); - circle.add(args.map); - args.overlays.circles.push(circle); - _this.setVisible(false); - }; - } - break; - case OverlayType.POLYGON: - if (title) { - title.innerHTML = "Add 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 (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); + }; + } + 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) { + case OverlayType.POINT: + if (title) { + title.innerHTML = "Add Marker "; + } + if (submitBtn) { + submitBtn.onclick = () => { + const name = TextUtils.encodeHTML(_this.nameField()); + const desc = TextUtils.encodeHTML(_this.descField()); + if (name.trim().length < 1) { + return; + } + const point = new Marker(name, desc, args.latlng, { title: name, alt: name }); + point.add(args.map); + args.overlays.markers.push(point); + _this.setVisible(false); + }; + } + break; + case OverlayType.CIRCLE: + if (title) { + title.innerHTML = "Add Circle "; + } + if (submitBtn) { + submitBtn.onclick = () => { + const radius = _this.radiusField(); + const name = TextUtils.encodeHTML(_this.nameField()); + const desc = TextUtils.encodeHTML(_this.descField()); + if (name.trim().length < 1) { + return; + } + const circle = new Circle(name, desc, args.latlng, { radius: Number(radius) || 500 }); + circle.add(args.map); + args.overlays.circles.push(circle); + _this.setVisible(false); + }; + } + break; + case OverlayType.POLYGON: + if (title) { + title.innerHTML = "Add 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)); } } }

@@ -562,6 +693,19 @@ if (self) {

self.modals.cancel.setVisible(false); self.modals.createOverlay.setState(OverlayType.POINT, { latlng: e.latlng, + map: self.map, + overlays: self.overlays, + }); + MapHandler.resetMapClick(); + self.modals.createOverlay.setVisible(true); + } + } + static editOverlay(overlay, type) { + const self = MapHandler.instance; + if (self) { + self.modals.closeAll(); + self.modals.createOverlay.setState(type, { + self: overlay, map: self.map, overlays: self.overlays, });

@@ -817,6 +961,29 @@ self.modals.overlayMgr.setVisible(!visible);

if (!visible) { e.target.classList.add("activeBtn"); } + } + } + static confirmDelete(overlay) { + const self = MapHandler.instance; + if (self) { + self.modals.closeAll(); + self.modals.okCancel.setMsg(`Delete "${overlay.name}"?`); + const okBtn = self.modals.okCancel.okBtn(); + if (okBtn) { + okBtn.onclick = () => { + self.modals.closeAll(); + overlay.remove(self.map); + self.modals.info.setMsg(`"${overlay.name}" deleted`); + self.modals.info.setVisible(true); + }; + } + const cancelBtn = self.modals.okCancel.cancelBtn(); + if (cancelBtn) { + cancelBtn.onclick = () => { + self.modals.closeAll(); + }; + } + self.modals.okCancel.setVisible(true); } } }
M static/style.cssstatic/style.css

@@ -16,6 +16,11 @@ align: center;

position: relative; } +.tiny { + font-size: 33%; + vertical-align: top; +} + #noscript-container { position: absolute; top: 0;

@@ -89,7 +94,7 @@ }

#createOverlay-container { background: #000000; - color: #c9c9c9; + color: white; position: fixed; width: 100%; max-width: 800px;

@@ -114,12 +119,16 @@

#createOverlay-container h2 { text-align: left; font-size: 200%; - font-wieght: normal; + font-weight: normal; text-transform: uppercase; line-height: 2em; margin-left: 1em; } +#createOverlay-container .multiBtn-container { + display: none; +} + #createOverlay-content { margin: 2em; text-align: right;

@@ -136,7 +145,9 @@ #createOverlay-content #radius-container {

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; width: 100%; font-size: 150%;

@@ -177,6 +188,7 @@ .closeBtn:focus {

color: crimson; } +#createOverlay-container .multiBtn-container button, #createOverlay-submitBtn, .positive-btn, .negative-btn,

@@ -193,8 +205,10 @@ padding: 0.25em;

text-transform: uppercase; } -#createOverlay-submitBtn:hover, -#createOverlay-submitBtn:focus, +#createOverlay-container .multiBtn-container button:hover, +#createOverlay-container .multiBtn-container button:focus, +#createOverlay-container submitBtn:hover, +#createOverlay-container submitBtn:focus, #set-home-btn:hover, #set-home-btn:focus, #import-btn:hover,

@@ -212,14 +226,19 @@ margin-top: 1em;

} .positive-btn { - border: solid 2px #1f9b92; + border: solid 2px #1f9b92 !important; float: left; } .positive-btn:hover, .positive-btn:focus { - color: black; - background: #1f9b92; + color: black !important; + background: #1f9b92 !important; +} + +#createOverlay-submitBtn { + float: none; + font-size: 150%; } .negative-btn {