diff --git a/index.html b/index.html
index 59cace12..ab832725 100644
--- a/index.html
+++ b/index.html
@@ -7716,7 +7716,7 @@
-
+
diff --git a/src/layers/index.js b/src/layers/index.ts
similarity index 100%
rename from src/layers/index.js
rename to src/layers/index.ts
diff --git a/src/layers/init.ts b/src/layers/init.ts
index b0027531..7735a2c5 100644
--- a/src/layers/init.ts
+++ b/src/layers/init.ts
@@ -1,5 +1,9 @@
+import {getInputValue, setInputValue} from "utils/nodeUtils";
import {stored, byId, store} from "utils/shorthands";
+import {renderLayer} from "./renderers";
+import {toggleLayerOnClick} from "./toggles";
import {layerIsOn} from "./utils";
+import {prompt} from "scripts/prompt";
export function initLayers() {
restoreCustomPresets();
@@ -7,7 +11,7 @@ export function initLayers() {
addLayerListeners();
}
-let presets = {};
+let presets: Dict = {};
const defaultPresets = {
political: [
@@ -86,23 +90,23 @@ function restoreCustomPresets() {
for (const preset in storedPresets) {
if (presets[preset]) continue;
- byId("layersPreset").add(new Option(preset, preset));
+ (byId("layersPreset") as HTMLSelectElement)?.add(new Option(preset, preset));
}
presets = storedPresets;
}
function addLayerListeners() {
- byId("mapLayers").on("click", toggleLayerOnClick);
- byId("savePresetButton").on("click", savePreset);
- byId("removePresetButton").on("click", removePreset);
+ byId("mapLayers")?.on("click", toggleLayerOnClick);
+ byId("savePresetButton")?.on("click", savePreset);
+ byId("removePresetButton")?.on("click", removePreset);
// allow to move layers by dragging layer button (jquery)
$("#mapLayers").sortable({items: "li:not(.solid)", containment: "parent", cancel: ".solid", update: moveLayer});
}
// connection between option layer buttons and actual svg groups to move the element
-const layerButtonToElementMap = {
+const layerButtonToElementMap: Dict = {
toggleBiomes: "biomes",
toggleBorders: "borders",
toggleCells: "cells",
@@ -131,34 +135,28 @@ const layerButtonToElementMap = {
toggleZones: "zones"
};
-function moveLayer(event, $layerButton) {
- const getLayer = buttonId => $("#" + layerButtonToElementMap[buttonId]);
- const layer = getLayer($layerButton.item.attr("id"));
- if (!layer) return;
+function moveLayer(_event: Event, layer: JQueryUI.SortableUIParams) {
+ const getLayer = (buttonId: string) => $("#" + layerButtonToElementMap[buttonId]);
+ const layerId = getLayer(layer.item.attr("id") || "");
+ if (!layerId) return;
- const prev = getLayer($layerButton.item.prev().attr("id"));
- const next = getLayer($layerButton.item.next().attr("id"));
+ const prev = getLayer(layer.item.prev().attr("id") || "");
+ const next = getLayer(layer.item.next().attr("id") || "");
- if (prev) layer.insertAfter(prev);
- else if (next) layer.insertBefore(next);
-}
-
-function toggleLayerOnClick(event) {
- const targetId = event.target.id;
- if (!targetId || targetId === "mapLayers" || !layerTogglesMap[targetId]) return;
- layerTogglesMap[targetId]();
+ if (prev) layer.item.insertAfter(prev);
+ else if (next) layer.item.insertBefore(next);
}
// run on map generation
function applyPreset() {
- const preset = stored("preset") || byId("layersPreset")?.value || "political";
+ const preset = stored("preset") || getInputValue("layersPreset") || "political";
changePreset(preset);
}
// toggle layers on preset change
-function changePreset(preset) {
+function changePreset(preset: string) {
const layers = presets[preset]; // layers to be turned on
- const $layerButtons = byId("mapLayers").querySelectorAll("li");
+ const $layerButtons = byId("mapLayers")?.querySelectorAll("li")!;
$layerButtons.forEach(function ($layerButton) {
const {id} = $layerButton;
@@ -166,36 +164,45 @@ function changePreset(preset) {
else if (!layers.includes(id) && layerIsOn(id)) $layerButton.click();
});
- byId("layersPreset").value = preset;
+ setInputValue("layersPreset", preset);
store("preset", preset);
- const isDefault = defaultPresets[preset];
- byId("removePresetButton").style.display = isDefault ? "none" : "inline-block";
- byId("savePresetButton").style.display = "none";
- if (byId("canvas3d")) setTimeout(ThreeD.update(), 400);
+ const isDefault = preset in defaultPresets;
+
+ const $removeButton = byId("removePresetButton")!;
+ const $saveButton = byId("savePresetButton")!;
+
+ $removeButton.style.display = isDefault ? "none" : "inline-block";
+ $saveButton.style.display = "none";
+
+ if (byId("canvas3d")) setTimeout(window.ThreeD.update(), 400);
}
function savePreset() {
- prompt("Please provide a preset name", {default: ""}, preset => {
- presets[preset] = Array.from(byId("mapLayers").querySelectorAll("li:not(.buttonoff)"))
+ prompt("Please provide a preset name", {default: ""}, returned => {
+ const preset = String(returned);
+ presets[preset] = Array.from(byId("mapLayers")?.querySelectorAll("li:not(.buttonoff)") || [])
.map(node => node.id)
.sort();
- layersPreset.add(new Option(preset, preset, false, true));
+
+ (byId("layersPreset") as HTMLSelectElement)?.add(new Option(preset, preset, false, true));
localStorage.setItem("presets", JSON.stringify(presets));
localStorage.setItem("preset", preset);
- removePresetButton.style.display = "inline-block";
- savePresetButton.style.display = "none";
+ byId("removePresetButton")!.style.display = "inline-block";
+ byId("savePresetButton")!.style.display = "none";
});
}
function removePreset() {
- const preset = layersPreset.value;
+ const $layersPreset = byId("layersPreset") as HTMLSelectElement;
+ const preset = $layersPreset.value;
delete presets[preset];
- const index = Array.from(layersPreset.options).findIndex(o => o.value === preset);
- layersPreset.options.remove(index);
- layersPreset.value = "custom";
- removePresetButton.style.display = "none";
- savePresetButton.style.display = "inline-block";
+ const index = Array.from($layersPreset.options).findIndex(option => option.value === preset);
+ $layersPreset.options.remove(index);
+ $layersPreset.value = "custom";
+
+ byId("removePresetButton")!.style.display = "none";
+ byId("savePresetButton")!.style.display = "inline-block";
store("presets", JSON.stringify(presets));
localStorage.removeItem("preset");
@@ -203,22 +210,22 @@ function removePreset() {
// run on map regeneration
export function restoreLayers() {
- if (layerIsOn("toggleHeight")) drawHeightmap();
- if (layerIsOn("toggleCells")) drawCells();
- if (layerIsOn("toggleGrid")) drawGrid();
- if (layerIsOn("toggleCoordinates")) drawCoordinates();
+ if (layerIsOn("toggleHeight")) renderLayer("heightmap");
+ if (layerIsOn("toggleCells")) renderLayer("cells");
+ if (layerIsOn("toggleGrid")) renderLayer("grid");
+ if (layerIsOn("toggleCoordinates")) renderLayer("coordinates");
if (layerIsOn("toggleCompass")) compass.style("display", "block");
- if (layerIsOn("toggleTemp")) drawTemp();
- if (layerIsOn("togglePrec")) drawPrec();
- if (layerIsOn("togglePopulation")) drawPopulation();
- if (layerIsOn("toggleBiomes")) drawBiomes();
- if (layerIsOn("toggleRelief")) ReliefIcons();
- if (layerIsOn("toggleCultures")) drawCultures();
- if (layerIsOn("toggleProvinces")) drawProvinces();
- if (layerIsOn("toggleReligions")) drawReligions();
- if (layerIsOn("toggleIce")) drawIce();
- if (layerIsOn("toggleEmblems")) drawEmblems();
- if (layerIsOn("toggleMarkers")) drawMarkers();
+ if (layerIsOn("toggleTemp")) renderLayer("temperature");
+ if (layerIsOn("togglePrec")) renderLayer("precipitation");
+ if (layerIsOn("togglePopulation")) renderLayer("population");
+ if (layerIsOn("toggleBiomes")) renderLayer("biomes");
+ if (layerIsOn("toggleRelief")) window.ReliefIcons();
+ if (layerIsOn("toggleCultures")) renderLayer("cultures");
+ if (layerIsOn("toggleProvinces")) renderLayer("provinces");
+ if (layerIsOn("toggleReligions")) renderLayer("religions");
+ if (layerIsOn("toggleIce")) renderLayer("ice");
+ if (layerIsOn("toggleEmblems")) renderLayer("emblems");
+ if (layerIsOn("toggleMarkers")) renderLayer("markers");
// some layers are rendered each time, remove them if they are not on
if (!layerIsOn("toggleBorders")) borders.selectAll("path").remove();
@@ -227,21 +234,21 @@ export function restoreLayers() {
}
export function updatePresetInput() {
- const $toggledOnLayers = byId("mapLayers").querySelectorAll("li:not(.buttonoff)");
- const currentLayers = Array.from($toggledOnLayers)
+ const $toggledOnLayers = byId("mapLayers")?.querySelectorAll("li:not(.buttonoff)");
+ const currentLayers = Array.from($toggledOnLayers || [])
.map(node => node.id)
.sort();
for (const preset in presets) {
if (JSON.stringify(presets[preset].sort()) !== JSON.stringify(currentLayers)) continue;
- byId("layersPreset").value = preset;
- byId("removePresetButton").style.display = defaultPresets[preset] ? "none" : "inline-block";
- byId("savePresetButton").style.display = "none";
+ setInputValue("layersPreset", preset);
+ byId("removePresetButton")!.style.display = preset in defaultPresets ? "none" : "inline-block";
+ byId("savePresetButton")!.style.display = "none";
return;
}
- byId("layersPreset").value = "custom";
- byId("removePresetButton").style.display = "none";
- byId("savePresetButton").style.display = "inline-block";
+ setInputValue("layersPreset", "custom");
+ byId("removePresetButton")!.style.display = "none";
+ byId("savePresetButton")!.style.display = "inline-block";
}
diff --git a/src/layers/renderers/index.js b/src/layers/renderers/index.ts
similarity index 95%
rename from src/layers/renderers/index.js
rename to src/layers/renderers/index.ts
index d85b1567..6ddd94a0 100644
--- a/src/layers/renderers/index.js
+++ b/src/layers/renderers/index.ts
@@ -38,7 +38,7 @@ const layerRenderersMap = {
temperature: drawTemperature
};
-export function renderLayer(layerName) {
+export function renderLayer(layerName: keyof typeof layerRenderersMap) {
const rendered = layerRenderersMap[layerName];
TIME && console.time(rendered.name);
rendered();
diff --git a/src/layers/toggles.js b/src/layers/toggles.ts
similarity index 64%
rename from src/layers/toggles.js
rename to src/layers/toggles.ts
index b9730dde..543f20c1 100644
--- a/src/layers/toggles.js
+++ b/src/layers/toggles.ts
@@ -1,8 +1,11 @@
import {tip} from "scripts/tooltips";
import {getBase64} from "utils/functionUtils";
-import {isCtrlClick} from "utils/keyboardUtils";
+import {isCtrlPressed} from "utils/keyboardUtils";
+// @ts-expect-error js module
+import {editStyle, calculateFriendlyGridSize, shiftCompass} from "modules/ui/style";
import {turnLayerButtonOn, turnLayerButtonOff, layerIsOn} from "./utils";
import {renderLayer} from "./renderers";
+import {getInputNumber, getInputValue} from "utils/nodeUtils";
const layerTogglesMap = {
toggleBiomes,
@@ -34,11 +37,19 @@ const layerTogglesMap = {
toggleZones
};
-export function toggleLayer(toggleId) {
+type TLayerToggle = keyof typeof layerTogglesMap;
+
+export function toggleLayer(toggleId: TLayerToggle) {
layerTogglesMap[toggleId]();
}
-function toggleHeight(event) {
+export function toggleLayerOnClick(event: Event) {
+ const targetId = (event.target as HTMLButtonElement)?.id;
+ if (!targetId || targetId === "mapLayers" || !(targetId in layerTogglesMap)) return;
+ layerTogglesMap[targetId as TLayerToggle](event as MouseEvent);
+}
+
+function toggleHeight(event?: MouseEvent) {
if (customization === 1) {
tip("You cannot turn off the layer when heightmap is in edit mode", false, "error");
return;
@@ -47,9 +58,9 @@ function toggleHeight(event) {
if (!terrs.selectAll("*").size()) {
turnLayerButtonOn("toggleHeight");
renderLayer("heightmap");
- if (event && isCtrlClick(event)) editStyle("terrs");
+ if (isCtrlPressed(event)) editStyle("terrs");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("terrs");
return;
}
@@ -58,13 +69,13 @@ function toggleHeight(event) {
}
}
-function toggleTemp(event) {
+function toggleTemp(event?: MouseEvent) {
if (!temperature.selectAll("*").size()) {
turnLayerButtonOn("toggleTemp");
renderLayer("temperature");
- if (event && isCtrlClick(event)) editStyle("temperature");
+ if (isCtrlPressed(event)) editStyle("temperature");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("temperature");
return;
}
@@ -73,13 +84,13 @@ function toggleTemp(event) {
}
}
-function toggleBiomes(event) {
+function toggleBiomes(event?: MouseEvent) {
if (!biomes.selectAll("path").size()) {
turnLayerButtonOn("toggleBiomes");
renderLayer("biomes");
- if (event && isCtrlClick(event)) editStyle("biomes");
+ if (isCtrlPressed(event)) editStyle("biomes");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("biomes");
return;
}
@@ -88,13 +99,13 @@ function toggleBiomes(event) {
}
}
-function togglePrec(event) {
+function togglePrec(event?: MouseEvent) {
if (!prec.selectAll("circle").size()) {
turnLayerButtonOn("togglePrec");
renderLayer("precipitation");
- if (event && isCtrlClick(event)) editStyle("prec");
+ if (isCtrlPressed(event)) editStyle("prec");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("prec");
return;
}
@@ -106,13 +117,13 @@ function togglePrec(event) {
}
}
-function togglePopulation(event) {
+function togglePopulation(event?: MouseEvent) {
if (!population.selectAll("line").size()) {
turnLayerButtonOn("togglePopulation");
renderLayer("population");
- if (event && isCtrlClick(event)) editStyle("population");
+ if (isCtrlPressed(event)) editStyle("population");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("population");
return;
}
@@ -141,13 +152,13 @@ function togglePopulation(event) {
}
}
-function toggleCells(event) {
+function toggleCells(event?: MouseEvent) {
if (!cells.selectAll("path").size()) {
turnLayerButtonOn("toggleCells");
renderLayer("cells");
- if (event && isCtrlClick(event)) editStyle("cells");
+ if (isCtrlPressed(event)) editStyle("cells");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("cells");
return;
}
@@ -156,14 +167,14 @@ function toggleCells(event) {
}
}
-function toggleIce(event) {
+function toggleIce(event?: MouseEvent) {
if (!layerIsOn("toggleIce")) {
turnLayerButtonOn("toggleIce");
$("#ice").fadeIn();
if (!ice.selectAll("*").size()) renderLayer("ice");
- if (event && isCtrlClick(event)) editStyle("ice");
+ if (isCtrlPressed(event)) editStyle("ice");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("ice");
return;
}
@@ -172,15 +183,15 @@ function toggleIce(event) {
}
}
-function toggleCultures(event) {
- const cultures = pack.cultures.filter(c => c.i && !c.removed);
+function toggleCultures(event?: MouseEvent) {
+ const cultures = pack.cultures.filter(({i, removed}) => i && !removed);
const empty = !cults.selectAll("path").size();
if (empty && cultures.length) {
turnLayerButtonOn("toggleCultures");
renderLayer("cultures");
- if (event && isCtrlClick(event)) editStyle("cults");
+ if (isCtrlPressed(event)) editStyle("cults");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("cults");
return;
}
@@ -189,14 +200,14 @@ function toggleCultures(event) {
}
}
-function toggleReligions(event) {
- const religions = pack.religions.filter(r => r.i && !r.removed);
+function toggleReligions(event?: MouseEvent) {
+ const religions = pack.religions.filter(({i, removed}) => i && !removed);
if (!relig.selectAll("path").size() && religions.length) {
turnLayerButtonOn("toggleReligions");
renderLayer("religions");
- if (event && isCtrlClick(event)) editStyle("relig");
+ if (isCtrlPressed(event)) editStyle("relig");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("relig");
return;
}
@@ -205,14 +216,14 @@ function toggleReligions(event) {
}
}
-function toggleStates(event) {
+function toggleStates(event?: MouseEvent) {
if (!layerIsOn("toggleStates")) {
turnLayerButtonOn("toggleStates");
regions.style("display", null);
renderLayer("states");
- if (event && isCtrlClick(event)) editStyle("regions");
+ if (isCtrlPressed(event)) editStyle("regions");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("regions");
return;
}
@@ -221,13 +232,13 @@ function toggleStates(event) {
}
}
-function toggleBorders(event) {
+function toggleBorders(event?: MouseEvent) {
if (!layerIsOn("toggleBorders")) {
turnLayerButtonOn("toggleBorders");
renderLayer("borders");
- if (event && isCtrlClick(event)) editStyle("borders");
+ if (isCtrlPressed(event)) editStyle("borders");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("borders");
return;
}
@@ -236,13 +247,13 @@ function toggleBorders(event) {
}
}
-function toggleProvinces(event) {
+function toggleProvinces(event?: MouseEvent) {
if (!layerIsOn("toggleProvinces")) {
turnLayerButtonOn("toggleProvinces");
renderLayer("provinces");
- if (event && isCtrlClick(event)) editStyle("provs");
+ if (isCtrlPressed(event)) editStyle("provs");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("provs");
return;
}
@@ -251,15 +262,15 @@ function toggleProvinces(event) {
}
}
-function toggleGrid(event) {
+function toggleGrid(event?: MouseEvent) {
if (!gridOverlay.selectAll("*").size()) {
turnLayerButtonOn("toggleGrid");
renderLayer("grid");
calculateFriendlyGridSize();
- if (event && isCtrlClick(event)) editStyle("gridOverlay");
+ if (isCtrlPressed(event)) editStyle("gridOverlay");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("gridOverlay");
return;
}
@@ -268,13 +279,13 @@ function toggleGrid(event) {
}
}
-function toggleCoordinates(event) {
+function toggleCoordinates(event?: MouseEvent) {
if (!coordinates.selectAll("*").size()) {
turnLayerButtonOn("toggleCoordinates");
renderLayer("coordinates");
- if (event && isCtrlClick(event)) editStyle("coordinates");
+ if (isCtrlPressed(event)) editStyle("coordinates");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("coordinates");
return;
}
@@ -283,7 +294,7 @@ function toggleCoordinates(event) {
}
}
-function toggleCompass(event) {
+function toggleCompass(event?: MouseEvent) {
if (!layerIsOn("toggleCompass")) {
turnLayerButtonOn("toggleCompass");
$("#compass").fadeIn();
@@ -291,9 +302,9 @@ function toggleCompass(event) {
compass.append("use").attr("xlink:href", "#rose");
shiftCompass();
}
- if (event && isCtrlClick(event)) editStyle("compass");
+ if (isCtrlPressed(event)) editStyle("compass");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("compass");
return;
}
@@ -302,14 +313,14 @@ function toggleCompass(event) {
}
}
-function toggleRelief(event) {
+function toggleRelief(event?: MouseEvent) {
if (!layerIsOn("toggleRelief")) {
turnLayerButtonOn("toggleRelief");
- if (!terrain.selectAll("*").size()) ReliefIcons();
+ if (!terrain.selectAll("*").size()) window.ReliefIcons();
$("#terrain").fadeIn();
- if (event && isCtrlClick(event)) editStyle("terrain");
+ if (isCtrlPressed(event)) editStyle("terrain");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("terrain");
return;
}
@@ -318,13 +329,14 @@ function toggleRelief(event) {
}
}
-function toggleTexture(event) {
+function toggleTexture(event?: MouseEvent) {
if (!layerIsOn("toggleTexture")) {
turnLayerButtonOn("toggleTexture");
// append default texture image selected by default. Don't append on load to not harm performance
if (!texture.selectAll("*").size()) {
- const x = +styleTextureShiftX.value;
- const y = +styleTextureShiftY.value;
+ const x = getInputNumber("styleTextureShiftX");
+ const y = getInputNumber("styleTextureShiftY");
+
const image = texture
.append("image")
.attr("id", "textureImage")
@@ -333,37 +345,37 @@ function toggleTexture(event) {
.attr("width", graphWidth - x)
.attr("height", graphHeight - y)
.attr("preserveAspectRatio", "xMidYMid slice");
- getBase64(styleTextureInput.value, base64 => image.attr("xlink:href", base64));
+ getBase64(getInputValue("styleTextureInput"), base64 => image.attr("xlink:href", base64));
}
$("#texture").fadeIn();
- zoom.scaleBy(svg, 1.00001); // enforce browser re-draw
- if (event && isCtrlClick(event)) editStyle("texture");
+ window.Zoom.force;
+ if (isCtrlPressed(event)) editStyle("texture");
} else {
- if (event && isCtrlClick(event)) return editStyle("texture");
+ if (isCtrlPressed(event)) return editStyle("texture");
$("#texture").fadeOut();
turnLayerButtonOff("toggleTexture");
}
}
-function toggleRivers(event) {
+function toggleRivers(event?: MouseEvent) {
if (!layerIsOn("toggleRivers")) {
turnLayerButtonOn("toggleRivers");
renderLayer("rivers");
- if (event && isCtrlClick(event)) editStyle("rivers");
+ if (isCtrlPressed(event)) editStyle("rivers");
} else {
- if (event && isCtrlClick(event)) return editStyle("rivers");
+ if (isCtrlPressed(event)) return editStyle("rivers");
rivers.selectAll("*").remove();
turnLayerButtonOff("toggleRivers");
}
}
-function toggleRoutes(event) {
+function toggleRoutes(event?: MouseEvent) {
if (!layerIsOn("toggleRoutes")) {
turnLayerButtonOn("toggleRoutes");
$("#routes").fadeIn();
- if (event && isCtrlClick(event)) editStyle("routes");
+ if (isCtrlPressed(event)) editStyle("routes");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("routes");
return;
}
@@ -372,13 +384,13 @@ function toggleRoutes(event) {
}
}
-function toggleMilitary(event) {
+function toggleMilitary(event?: MouseEvent) {
if (!layerIsOn("toggleMilitary")) {
turnLayerButtonOn("toggleMilitary");
$("#armies").fadeIn();
- if (event && isCtrlClick(event)) editStyle("armies");
+ if (isCtrlPressed(event)) editStyle("armies");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("armies");
return;
}
@@ -387,26 +399,26 @@ function toggleMilitary(event) {
}
}
-function toggleMarkers(event) {
+function toggleMarkers(event?: MouseEvent) {
if (!layerIsOn("toggleMarkers")) {
turnLayerButtonOn("toggleMarkers");
renderLayer("markers");
- if (event && isCtrlClick(event)) editStyle("markers");
+ if (isCtrlPressed(event)) editStyle("markers");
} else {
- if (event && isCtrlClick(event)) return editStyle("markers");
+ if (isCtrlPressed(event)) return editStyle("markers");
markers.selectAll("*").remove();
turnLayerButtonOff("toggleMarkers");
}
}
-function toggleLabels(event) {
+function toggleLabels(event?: MouseEvent) {
if (!layerIsOn("toggleLabels")) {
turnLayerButtonOn("toggleLabels");
labels.style("display", null);
- Zoom.invoke();
- if (event && isCtrlClick(event)) editStyle("labels");
+ window.Zoom.invoke();
+ if (isCtrlPressed(event)) editStyle("labels");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("labels");
return;
}
@@ -415,13 +427,13 @@ function toggleLabels(event) {
}
}
-function toggleIcons(event) {
+function toggleIcons(event?: MouseEvent) {
if (!layerIsOn("toggleIcons")) {
turnLayerButtonOn("toggleIcons");
$("#icons").fadeIn();
- if (event && isCtrlClick(event)) editStyle("burgIcons");
+ if (isCtrlPressed(event)) editStyle("burgIcons");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("burgIcons");
return;
}
@@ -430,14 +442,14 @@ function toggleIcons(event) {
}
}
-function toggleRulers(event) {
+function toggleRulers(event?: MouseEvent) {
if (!layerIsOn("toggleRulers")) {
turnLayerButtonOn("toggleRulers");
- if (event && isCtrlClick(event)) editStyle("ruler");
+ if (isCtrlPressed(event)) editStyle("ruler");
rulers.draw();
ruler.style("display", null);
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("ruler");
return;
}
@@ -447,28 +459,33 @@ function toggleRulers(event) {
}
}
-function toggleScaleBar(event) {
+function toggleScaleBar(event?: MouseEvent) {
if (!layerIsOn("toggleScaleBar")) {
turnLayerButtonOn("toggleScaleBar");
$("#scaleBar").fadeIn();
- if (event && isCtrlClick(event)) editUnits();
+ if (isCtrlPressed(event)) openUnitsEditor();
} else {
- if (event && isCtrlClick(event)) {
- editUnits();
- return;
+ if (isCtrlPressed(event)) openUnitsEditor();
+ else {
+ $("#scaleBar").fadeOut();
+ turnLayerButtonOff("toggleScaleBar");
}
- $("#scaleBar").fadeOut();
- turnLayerButtonOff("toggleScaleBar");
+ }
+
+ async function openUnitsEditor() {
+ // @ts-ignore fix dynamic import
+ const {editUnits} = await import("./../modules/ui/unitsEditor.js");
+ editUnits();
}
}
-function toggleZones(event) {
+function toggleZones(event?: MouseEvent) {
if (!layerIsOn("toggleZones")) {
turnLayerButtonOn("toggleZones");
$("#zones").fadeIn();
- if (event && isCtrlClick(event)) editStyle("zones");
+ if (isCtrlPressed(event)) editStyle("zones");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("zones");
return;
}
@@ -477,14 +494,14 @@ function toggleZones(event) {
}
}
-function toggleEmblems(event) {
+function toggleEmblems(event?: MouseEvent) {
if (!layerIsOn("toggleEmblems")) {
turnLayerButtonOn("toggleEmblems");
if (!emblems.selectAll("use").size()) renderLayer("emblems");
$("#emblems").fadeIn();
- if (event && isCtrlClick(event)) editStyle("emblems");
+ if (isCtrlPressed(event)) editStyle("emblems");
} else {
- if (event && isCtrlClick(event)) {
+ if (isCtrlPressed(event)) {
editStyle("emblems");
return;
}
diff --git a/src/modules/ui/style.js b/src/modules/ui/style.js
index 9e8355a3..ab7985e0 100644
--- a/src/modules/ui/style.js
+++ b/src/modules/ui/style.js
@@ -24,7 +24,7 @@ styleElements.addEventListener("change", function (ev) {
});
// select element to be edited
-function editStyle(element, group) {
+export function editStyle(element, group) {
showOptions();
styleTab.click();
styleElementSelect.value = element;
@@ -403,7 +403,7 @@ styleGridScale.addEventListener("input", function () {
calculateFriendlyGridSize();
});
-function calculateFriendlyGridSize() {
+export function calculateFriendlyGridSize() {
const size = styleGridScale.value * 25;
const friendly = `${rn(size * distanceScaleInput.value, 2)} ${distanceUnitInput.value}`;
styleGridSizeFriendly.value = friendly;
@@ -537,7 +537,7 @@ styleCompassSizeInput.addEventListener("input", function () {
styleCompassShiftX.addEventListener("input", shiftCompass);
styleCompassShiftY.addEventListener("input", shiftCompass);
-function shiftCompass() {
+export function shiftCompass() {
const tr = `translate(${styleCompassShiftX.value} ${styleCompassShiftY.value}) scale(${styleCompassSizeInput.value})`;
compass.select("use").attr("transform", tr);
}
diff --git a/src/modules/ui/3d.js b/src/modules/ui/threeD.js
similarity index 100%
rename from src/modules/ui/3d.js
rename to src/modules/ui/threeD.js
diff --git a/src/modules/ui/tools.js b/src/modules/ui/tools.js
index 3ea66a61..c9db8b04 100644
--- a/src/modules/ui/tools.js
+++ b/src/modules/ui/tools.js
@@ -3,7 +3,7 @@ import {findCell} from "utils/graphUtils";
import {last} from "utils/arrayUtils";
import {tip, clearMainTip} from "scripts/tooltips";
import {rn} from "utils/numberUtils";
-import {isCtrlClick} from "utils/keyboardUtils";
+import {isCtrlPressed} from "utils/keyboardUtils";
import {prompt} from "scripts/prompt";
import {getNextId} from "utils/nodeUtils";
import {P, generateSeed} from "utils/probabilityUtils";
@@ -444,7 +444,7 @@ function regenerateMarkers() {
}
function regenerateZones(event) {
- if (isCtrlClick(event))
+ if (isCtrlPressed(event))
prompt("Please provide zones number multiplier", {default: 1, step: 0.01, min: 0, max: 100}, v =>
addNumberOfZones(v)
);
diff --git a/src/modules/zoom.js b/src/modules/zoom.js
index eb064207..59fff8eb 100644
--- a/src/modules/zoom.js
+++ b/src/modules/zoom.js
@@ -33,6 +33,10 @@ window.Zoom = (function () {
invokeActiveZooming();
}
+ function force() {
+ zoom.scaleBy(svg, 1.00001); // enforce browser re-draw;
+ }
+
// zoom to a specific point
function to(x, y, z = 8, d = 2000) {
const transform = d3.zoomIdentity.translate(x * -z + graphWidth / 2, y * -z + graphHeight / 2).scale(z);
@@ -59,5 +63,5 @@ window.Zoom = (function () {
zoom.scaleTo(element, scale);
}
- return {setZoomBehavior, invoke, to, reset, scaleExtent, translateExtent, scaleTo};
+ return {setZoomBehavior, invoke, force, to, reset, scaleExtent, translateExtent, scaleTo};
})();
diff --git a/src/scripts/prompt.ts b/src/scripts/prompt.ts
index 06df1aeb..362d138e 100644
--- a/src/scripts/prompt.ts
+++ b/src/scripts/prompt.ts
@@ -1,5 +1,21 @@
import {ERROR} from "../config/logging";
+interface IPromptStringOptions {
+ default: string;
+ required?: boolean;
+}
+
+interface IPromptNumberOptions {
+ default: number;
+ step?: number;
+ min?: number;
+ max?: number;
+ required?: boolean;
+}
+
+const isNumerical = (options: {default: number | string}): options is IPromptNumberOptions =>
+ typeof options.default === "number";
+
// prompt replacer (prompt does not work in Electron)
const $prompt: HTMLElement = document.getElementById("prompt")!;
const $form: HTMLFormElement = $prompt.querySelector("#promptForm")!;
@@ -10,16 +26,23 @@ const $cancel: HTMLButtonElement = $prompt.querySelector("#promptCancel")!;
const defaultText = "Please provide an input";
const defaultOptions = {default: 1, step: 0.01, min: 0, max: 100, required: true};
-export function prompt(promptText = defaultText, options = defaultOptions, callback: (value: number | string) => void) {
- if (options.default === undefined)
- return ERROR && console.error("Prompt: options object does not have default value defined");
+export function prompt(
+ promptText: string = defaultText,
+ options: IPromptStringOptions | IPromptNumberOptions = defaultOptions,
+ callback?: (value: string | number) => void
+): void {
+ const numerical = isNumerical(options);
+ if (numerical) {
+ $input.type = "number";
+ if (options.step !== undefined) $input.step = String(options.step);
+ if (options.min !== undefined) $input.min = String(options.min);
+ if (options.max !== undefined) $input.max = String(options.max);
+ if (callback) callback("rw");
+ } else {
+ $input.type = "text";
+ }
$text.innerHTML = promptText;
- $input.type = typeof options.default === "number" ? "number" : "text";
-
- if (options.step !== undefined) $input.step = String(options.step);
- if (options.min !== undefined) $input.min = String(options.min);
- if (options.max !== undefined) $input.max = String(options.max);
$input.required = options.required === false ? false : true;
$input.placeholder = "type a " + $input.type;
@@ -32,8 +55,15 @@ export function prompt(promptText = defaultText, options = defaultOptions, callb
event.preventDefault();
$prompt.style.display = "none";
- const value = $input.type === "number" ? Number($input.value) : $input.value;
- if (callback) callback(value);
+ if (callback) {
+ if (isNumerical(options)) {
+ const value = Number($input.value);
+ callback(value);
+ } else {
+ const value = $input.value;
+ callback(value);
+ }
+ }
},
{once: true}
);
diff --git a/src/types/globals.d.ts b/src/types/globals.d.ts
index 9f3f7249..30d5093c 100644
--- a/src/types/globals.d.ts
+++ b/src/types/globals.d.ts
@@ -34,16 +34,54 @@ declare let distanceScale: number;
declare let urbanDensity: number;
declare let statesNeutral: number;
-declare let scaleBar: Selection;
-declare let legend: Selection;
-
declare const defineSvg: (graphWidth: number, graphHeight: number) => void;
-// old modules
-declare const Biomes: {
- getDefault: () => IBiomesData;
-};
-
-declare const Names: {
- getNameBases: () => INamebase[];
-};
+let svg: Selection;
+let defs: Selection;
+let viewbox: Selection;
+let scaleBar: Selection;
+let legend: Selection;
+let ocean: Selection;
+let oceanLayers: Selection;
+let oceanPattern: Selection;
+let lakes: Selection;
+let landmass: Selection;
+let texture: Selection;
+let terrs: Selection;
+let biomes: Selection;
+let cells: Selection;
+let gridOverlay: Selection;
+let coordinates: Selection;
+let compass: Selection;
+let rivers: Selection;
+let terrain: Selection;
+let relig: Selection;
+let cults: Selection;
+let regions: Selection;
+let statesBody: Selection;
+let statesHalo: Selection;
+let provs: Selection;
+let zones: Selection;
+let borders: Selection;
+let stateBorders: Selection;
+let provinceBorders: Selection;
+let routes: Selection;
+let roads: Selection;
+let trails: Selection;
+let searoutes: Selection;
+let temperature: Selection;
+let coastline: Selection;
+let ice: Selection;
+let prec: Selection;
+let population: Selection;
+let emblems: Selection;
+let labels: Selection;
+let icons: Selection;
+let burgLabels: Selection;
+let burgIcons: Selection;
+let anchors: Selection;
+let armies: Selection;
+let markers: Selection;
+let fogging: Selection;
+let ruler: Selection;
+let debug: Selection;
diff --git a/src/types/overrides.d.ts b/src/types/overrides.d.ts
index 1a00cca7..231de2a4 100644
--- a/src/types/overrides.d.ts
+++ b/src/types/overrides.d.ts
@@ -10,9 +10,15 @@ interface Window {
[key: string]: boolean;
};
};
- d3: typeof d3;
- $: typeof $;
mapCoordinates: IMapCoordinates;
+ // untyped IIFE modules
+ $: typeof $;
+ d3: typeof d3;
+ Biomes: typeof Biomes;
+ Names: typeof Names;
+ ThreeD: typeof ThreeD;
+ ReliefIcons: typeof ReliefIcons;
+ Zoom: typeof Zoom;
}
interface Node {
diff --git a/src/types/pack.d.ts b/src/types/pack.d.ts
index ea522f30..9fdd34cd 100644
--- a/src/types/pack.d.ts
+++ b/src/types/pack.d.ts
@@ -6,11 +6,29 @@ interface IPack {
pop: number[];
burg: number[];
};
- states: [];
- cultures: [];
- provinces: [];
+ states: IState[];
+ cultures: ICulture[];
+ provinces: IProvince[];
burgs: IBurg[];
- religions: [];
+ religions: IReligion[];
+}
+
+interface IState {
+ i: number;
+ name: string;
+ removed?: boolean;
+}
+
+interface ICulture {
+ i: number;
+ name: string;
+ removed?: boolean;
+}
+
+interface IProvince {
+ i: number;
+ name: string;
+ removed?: boolean;
}
interface IBurg {
@@ -20,4 +38,11 @@ interface IBurg {
x: number;
y: number;
population: number;
+ removed?: boolean;
+}
+
+interface IReligion {
+ i: number;
+ name: string;
+ removed?: boolean;
}
diff --git a/src/utils/keyboardUtils.ts b/src/utils/keyboardUtils.ts
index cadd4a5c..f4503c6a 100644
--- a/src/utils/keyboardUtils.ts
+++ b/src/utils/keyboardUtils.ts
@@ -1,3 +1,3 @@
-export function isCtrlClick(event: MouseEvent) {
- return event.ctrlKey || event.metaKey;
+export function isCtrlPressed(event?: MouseEvent) {
+ return event && (event.ctrlKey || event.metaKey);
}
diff --git a/src/utils/nodeUtils.ts b/src/utils/nodeUtils.ts
index c927ea17..27ffed0e 100644
--- a/src/utils/nodeUtils.ts
+++ b/src/utils/nodeUtils.ts
@@ -7,13 +7,29 @@ export function getNextId(core: string, index = 1) {
}
export function getInputValue(id: string) {
+ const $element = byId(id);
+ if (!$element) throw new Error(`Element ${id} not found`);
+ if (!("value" in $element)) throw new Error(`Element ${id} is not an input`);
+
return (byId(id) as HTMLInputElement)?.value;
}
export function getInputNumber(id: string) {
+ const $element = byId(id);
+ if (!$element) throw new Error(`Element ${id} not found`);
+ if (!("value" in $element)) throw new Error(`Element ${id} is not an input`);
+
return (byId(id) as HTMLInputElement)?.valueAsNumber;
}
+export function setInputValue(id: string, value: string | number | boolean) {
+ const $element = byId(id);
+ if (!$element) throw new Error(`Element ${id} not found`);
+ if (!("value" in $element)) throw new Error(`Element ${id} is not an input`);
+
+ ($element as HTMLInputElement).value = String(value);
+}
+
// apply drop-down menu option. If the value is not in options, add it
export function applyDropdownOption($select: HTMLSelectElement, value: string, name = value) {
const isExisting = Array.from($select.options).some(o => o.value === value);