diff --git a/package.json b/package.json index 103cfd5..e97e089 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minesweeper", - "version": "0.73.1", + "version": "0.74.0", "description": "Just Minesweeper!", "author": "Felix W. Dekker", "browser": "dist/bundle.js", diff --git a/src/main/index.html b/src/main/index.html index 2c111ac..0867ba4 100644 --- a/src/main/index.html +++ b/src/main/index.html @@ -46,7 +46,7 @@ -
+
@@ -105,6 +105,20 @@ + +
+
+
+ + + + +
+
+ +
+
+
diff --git a/src/main/js/Game.ts b/src/main/js/Game.ts index e21bdaa..b50e47c 100644 --- a/src/main/js/Game.ts +++ b/src/main/js/Game.ts @@ -7,6 +7,7 @@ import {customDifficulty, defaultDifficulty, difficulties} from "./Difficulty"; import {Display} from "./Display"; import {Field} from "./Field"; import {Solver} from "./Solver"; +import {Overlay} from "./UI"; /** @@ -15,14 +16,14 @@ import {Solver} from "./Solver"; export class Game { private readonly canvas: HTMLCanvasElement; private readonly difficultySelect: HTMLSelectElement; - private readonly customDifficultyOverlay: HTMLDivElement; - private readonly customDifficultyForm: HTMLFormElement; - private readonly customDifficultyCancelForm: HTMLFormElement; private readonly newGameForm: HTMLFormElement; private readonly restartForm: HTMLFormElement; - private readonly seedForm: HTMLFormElement; + private readonly seedOverlay: Overlay; + private readonly seedOpenForm: HTMLFormElement; + private readonly seedInput: HTMLFormElement; private readonly undoForm: HTMLFormElement; private readonly solveForm: HTMLFormElement; + private readonly customDifficultyOverlay: Overlay; private readonly widthInput: HTMLInputElement; private readonly heightInput: HTMLInputElement; private readonly minesInput: HTMLInputElement; @@ -81,7 +82,7 @@ export class Game { return; } - this.customDifficultyOverlay.style.visibility = "unset"; + this.customDifficultyOverlay.show(); this.widthInput.value = "" + (this.field?.width ?? defaultDifficulty.width); this.heightInput.value = "" + (this.field?.height ?? defaultDifficulty.height); this.minesInput.value = "" + (this.field?.mineCount ?? defaultDifficulty.mineCount); @@ -92,28 +93,11 @@ export class Game { ); // Custom difficulty - this.customDifficultyOverlay = $("#customDifficultyOverlay"); - this.customDifficultyOverlay.addEventListener( - "mousedown", - event => { - if (event.target === this.customDifficultyOverlay) - this.customDifficultyOverlay.style.visibility = "hidden"; - } - ); - this.customDifficultyOverlay.addEventListener( - "keydown", - event => { - if (event.key === "Escape") - this.customDifficultyOverlay.style.visibility = "hidden"; - } - ); - this.customDifficultyForm = $("#customDifficultyForm"); - this.customDifficultyForm.addEventListener( - "submit", - event => { - event.preventDefault(); - - this.customDifficultyOverlay.style.visibility = "hidden"; + this.customDifficultyOverlay = new Overlay( + $("#customDifficultyOverlay"), + $("#customDifficultyForm"), + $("#customDifficultyCancelForm"), + () => { this.initNewField( +this.widthInput.value, +this.heightInput.value, @@ -122,15 +106,6 @@ export class Game { ); } ); - this.customDifficultyCancelForm = $("#customDifficultyCancelForm"); - this.customDifficultyCancelForm.addEventListener( - "submit", - event => { - event.preventDefault(); - - this.customDifficultyOverlay.style.visibility = "hidden"; - } - ); this.widthInput = $("#settingsWidth"); this.widthInput.addEventListener("change", _ => this.setMineLimit()); @@ -162,21 +137,30 @@ export class Game { ); // Seed - this.seedForm = $("#seedForm"); - this.seedForm.addEventListener( + this.seedInput = $("#seed"); + this.seedOpenForm = $("#seedOpenForm"); + this.seedOpenForm.addEventListener( "submit", event => { event.preventDefault(); - const input = window.prompt("Enter seed", "" + this.seed); - if (input !== null) - this.initNewField( - this.field?.width, - this.field?.height, - this.field?.mineCount, - this.field?.solvable, - input - ); + this.seedOverlay.show(); + this.seedInput.value = this.seed; + this.seedInput.focus(); + } + ); + this.seedOverlay = new Overlay( + $("#seedOverlay"), + $("#seedForm"), + $("#seedCancelForm"), + () => { + this.initNewField( + this.field?.width, + this.field?.height, + this.field?.mineCount, + this.field?.solvable, + this.seedInput.value + ); } ); diff --git a/src/main/js/UI.ts b/src/main/js/UI.ts new file mode 100644 index 0000000..6dd2a7e --- /dev/null +++ b/src/main/js/UI.ts @@ -0,0 +1,76 @@ +/** + * An overlay displayed in HTML. + */ +export class Overlay { + private readonly overlay: HTMLDivElement; + private readonly submitForm: HTMLFormElement; + private readonly cancelForm: HTMLFormElement; + + + /** + * Constructs a new overlay. + * + * @param overlay the overlay element to show and hide + * @param submitForm the form that invokes `onSubmit` and closes the overlay when submitted + * @param cancelForm the form that closes the overlay when submitted + * @param onSubmit the callback to invoke when the form is submit + */ + constructor( + overlay: HTMLDivElement, + submitForm: HTMLFormElement, + cancelForm: HTMLFormElement, + onSubmit: () => void + ) { + this.overlay = overlay; + overlay.addEventListener( + "mousedown", + event => { + if (event.target === overlay) + this.hide(); + } + ); + overlay.addEventListener( + "keydown", + event => { + if (event.key === "Escape") + this.hide(); + } + ); + + this.submitForm = submitForm; + submitForm.addEventListener( + "submit", + event => { + event.preventDefault(); + + this.hide(); + onSubmit(); + } + ); + + this.cancelForm = cancelForm; + cancelForm.addEventListener( + "submit", + event => { + event.preventDefault(); + + this.hide(); + } + ); + } + + + /** + * Shows the overlay. + */ + show(): void { + this.overlay.style.visibility = "unset"; + } + + /** + * Hides the overlay. + */ + hide(): void { + this.overlay.style.visibility = "hidden"; + } +}