From 80b55732e7cc0879acf6d98e69a82ad6fd786f0c Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Thu, 15 Dec 2022 13:47:23 +0100
Subject: [PATCH] Move all click events to `Component.js`

---
 src/index.html            | 11 ------
 src/js/Components.js      | 82 +++++++++++++++++++++++++++++++++++++--
 src/js/connect4-winner.js | 69 --------------------------------
 src/js/main.js            | 42 --------------------
 4 files changed, 79 insertions(+), 125 deletions(-)
 delete mode 100644 src/js/connect4-winner.js

diff --git a/src/index.html b/src/index.html
index bc4a5da..360cbb0 100644
--- a/src/index.html
+++ b/src/index.html
@@ -9,16 +9,5 @@
     <body>
         <div id="game">
         </div>
-        <form class="menu-bar">
-            <button class="button new-game">
-                New Game
-            </button>
-            <button class="button save">
-                Save Game
-            </button>
-            <button class="button load">
-                Load Game
-            </button>
-        </form>
     </body>
 </html>
diff --git a/src/js/Components.js b/src/js/Components.js
index f4162d1..e89db15 100644
--- a/src/js/Components.js
+++ b/src/js/Components.js
@@ -1,5 +1,7 @@
 import { Constants } from "./Constants.js";
 
+const saveGameKey = "connect-force-save";
+
 /**
  * Gets a component which represents the specified {@link game `game`}.
  *
@@ -46,9 +48,10 @@ export function App(game)
             "div",
             { className: "log" },
             game.winner ?
-                    `Player ${Constants.PLAYER_NAMES[game.winner]} wins!` :
-                    `It's player "${Constants.PLAYER_NAMES[game.currentPlayer]}"s turn`
-        ]
+                `Player ${Constants.PLAYER_NAMES[game.winner]} wins!` :
+                `It's player "${Constants.PLAYER_NAMES[game.currentPlayer]}"s turn`
+        ],
+        [MenuBar, game]
     ];
 }
 
@@ -103,3 +106,76 @@ export function Field(field)
                 [])
     ];
 }
+
+/**
+ * Renders a menu bar.
+ *
+ * @param {import("./Game.js").Game} game
+ * The game controlled by the menu bar.
+ *
+ * @returns {NodeDescriptor}
+ * The rendered element.
+ */
+export function MenuBar(game)
+{
+    return [
+        "div",
+        { className: "menu-bar" },
+        [
+            Button,
+            {
+                text: "New Game",
+                attributes: {
+                    onclick: () =>
+                    {
+                        game.reset();
+                    }
+                }
+            }
+        ],
+        [
+            Button,
+            {
+                text: "Save Game",
+                attributes: {
+                    onclick: () =>
+                    {
+                        localStorage.setItem(
+                            saveGameKey,
+                            JSON.stringify(game.dump()));
+                    }
+                }
+            }
+        ],
+        [
+            Button,
+            {
+                text: "Load Game",
+                attributes: {
+                    onclick: () =>
+                    {
+                        game.load(JSON.parse(localStorage.getItem(saveGameKey)));
+                    }
+                }
+            }
+        ]
+    ];
+}
+
+/**
+ * Renders a button.
+ *
+ * @param {{text: string, attributes: (Partial<HTMLElement> & Record<string, any>)}} data
+ * The settings of the button.
+ *
+ * @returns {NodeDescriptor}
+ * The rendered element.
+ */
+export function Button(data)
+{
+    return [
+        "button",
+        data.attributes,
+        data.text
+    ];
+}
diff --git a/src/js/connect4-winner.js b/src/js/connect4-winner.js
deleted file mode 100644
index 87b8d0f..0000000
--- a/src/js/connect4-winner.js
+++ /dev/null
@@ -1,69 +0,0 @@
-let testBoard = [
-    ["_", "_", "_", "_", "_", "_", "_"],
-    ["_", "_", "_", "_", "_", "_", "_"],
-    ["_", "_", "_", "_", "r", "_", "_"],
-    ["_", "_", "_", "r", "r", "b", "b"],
-    ["_", "_", "r", "b", "r", "r", "b"],
-    ["b", "b", "b", "r", "r", "b", "b"]
-];
-
-/**
- * Checks whether the specified {@link player `player`} is a winner according to the specified {@link board `board`}.
- *
- * @param {string} player
- * The player to check for.
- *
- * @param {string[][]} board
- * The board to check.
- *
- * @param {number} count
- * The number of chips which need to be set in a row.
- *
- * @param {number} width
- * The width of the board.
- *
- * @param {number} height
- * The height of the board.
- *
- * @returns {boolean}
- * A value indicating whether the specified {@link player `player`} did win.
- */
-function connect4Winner(player, board, count = 4, width = 7, height = 6)
-{
-    for (let yOffset = 0; yOffset <= 1; yOffset++)
-    {
-        for (let xOffset = (-1 * yOffset) + (1 - yOffset); xOffset <= 1; xOffset++)
-        {
-            let lowerBound = Math.max(0, xOffset * (count - 1) * -1);
-            let upperBound = Math.min(width, width - (xOffset * (count - 1)));
-
-            for (let y = 0; y < (height - yOffset * (count - 1)); y++)
-            {
-                for (let x = lowerBound; x < upperBound; x++)
-                {
-                    /**
-                     * @type {string[]}
-                     */
-                    let tokens = [];
-
-                    for (let index = 0; index < count; index++)
-                    {
-                        tokens.push(board[y + index * yOffset][x + index * xOffset]);
-                    }
-
-                    if (tokens.every((token) => token === player))
-                    {
-                        return true;
-                    }
-                }
-            }
-        }
-    }
-
-    return false;
-}
-
-module.exports = { connect4Winner };
-
-console.log(connect4Winner("r", testBoard));
-console.log(connect4Winner("b", testBoard));
diff --git a/src/js/main.js b/src/js/main.js
index 3168a6f..9c786cd 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -7,30 +7,6 @@ import { Game } from "./Game.js";
  */
 let game;
 
-const saveGameKey = "connect-force-save";
-
-/**
- * Gets the save button.
- *
- * @returns {HTMLButtonElement}
- * The save button.
- */
-function getSaveButton()
-{
-    return document.querySelector(".save");
-}
-
-/**
- * Gets the load button.
- *
- * @returns {HTMLButtonElement}
- * The load button.
- */
-function getLoadButton()
-{
-    return document.querySelector(".load");
-}
-
 /**
  * Initializes the board.
  */
@@ -38,24 +14,6 @@ function initialize()
 {
     game = new Game("game");
     game.initialize();
-
-    (/** @type {HTMLElement} */ (document.querySelector(".new-game"))).onclick = (event) =>
-    {
-        event.preventDefault();
-        game.reset();
-    };
-
-    getSaveButton().onclick = async (event) =>
-    {
-        event.preventDefault();
-        localStorage.setItem(saveGameKey, JSON.stringify(game.dump()));
-    };
-
-    getLoadButton().onclick = async (event) =>
-    {
-        event.preventDefault();
-        game.load(JSON.parse(localStorage.getItem(saveGameKey)));
-    };
 }
 
 initialize();