TheOdinProject – Tic Tac Toe: DOM update

We’ve reached the last article from TheOdinProject Curriculum TicTacToe Game series.


In this article I will write about the updateDOM function, the factory function that manages the display of information from the game in the web interface and finally, the event listeners and the methods in them, responsible for starting and controlling a round.

JavaScript code:
const updateDOM = () => {
const gameInfo = document.getElementById("info-panel");
const player1NameInfoContainer = document.getElementById("player1-name");
const player1ScoreInfoContainer = document.getElementById("player1-score");
const player2NameInfoContainer = document.getElementById("player2-name");
const player2ScoreInfoContainer = document.getElementById("player2-score");
const gameUpdates = document.getElementById("game-updates");
const drawCount = document.getElementById("draws");

  const board = game.getBoard();

  playGrid.innerHTML = "";

  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board[i].length; j++) {
      let cellValue = board[i][j].getValue();
      let cellRow = i;
      let cellColumn = j;

      if (cellValue === 0) {
        cellValue = '';
      } 

      const cellElement = document.createElement("div");
      cellElement.classList.add("cell");
      cellElement.setAttribute("row-id", cellRow)
      cellElement.setAttribute("coll-id", cellColumn)
      
      cellElement.textContent = cellValue;

      playGrid.appendChild(cellElement);      
    }
  }
  
  gameUpdates.innerHTML = `${game.getActivePlayer().userName}'s turn.`;
  player1NameInfoContainer.innerHTML = `${game.getPlayerOneName()}`;
  player1ScoreInfoContainer.innerHTML = `Wins: ${game.getPlayerOneWins()}`;
  player2NameInfoContainer.innerHTML = `${game.getPlayerTwoName()}`;
  player2ScoreInfoContainer.innerHTML = `Wins: ${game.getPlayerTwoWins()}`;
  drawCount.innerHTML = `Draws: ${game.getDraws()}`;
  gameInfo.style.visibility = "visible"
};

startBtn.addEventListener("click", function(e) {
  e.preventDefault();
  const player1 = player1Input.value;
  const player2 = player2Input.value;

    if(player1.length > 0 || player2.length > 0 ) {
      game = GameController(player1, player2);
      game.playRound(); 
    }
  });

playGrid.addEventListener("click", function(e) {
  e.preventDefault();
  if (e.target && e.target.nodeName == "DIV" && e.target.classList.contains("cell")) {
    const rowId = e.target.getAttribute("row-id");
    const colId = e.target.getAttribute("coll-id");
    game.playRound(rowId, colId); 
    updateDOM();
  }
});

restartBtn.addEventListener("click", function(e) {
  const modal = modalControl(); 
  modal.closeModal();
  updateDOM();
});

1. Lines 1-42:

In the updateDOM function, responsible for updating the UI, we have between lines 2 and 8 a series of constants in which we store the elements taken from the DOM.

  • On lines 10 and 12 we store an instance of the game board and empty the game table content.
  • Between lines 14 and 33, I implemented an if check that iterates over the array and extracts the data of the cell that was clicked, starting with the value in cellValue and then the row and column in cellRow, respectively cellColumn.
  • If the value of the cell is stict 0, as it appears in array 2d, the content of the cell is replaced with an empty string.
  • Then we create a div, in the cellEment constant, to which we set the cell class with JS (for styling reasons) and  then set the attributes for the row and column.
  • On line 29, we set the mark it contains and append it to the game board.
  • Starting with lines 35, up to 41 the script manages the messages displayed in the info container, like: the active player, the name of player 1 and 2, how many wins each player has and how many tie results were recorded.
  • In the last line of the function, we set style.visibility = “visible”, because the module is hidden from css until the beginning of a round.

 

2. Lines 44-53:The first Event Listener listens to a click on the start button:

It takes the names of the 2 players from the DOM inputs, then in the if inside function, checks that their length is not 0, then creates a new GameController game instance with the names of the 2 players and call the playRound() method on the instance of game, to play a round.

3. Lines 55-63: Here we find the Event Listener that reacts to the click on the game board.

It checks if a cell with the cell class has been clicked, stores the id of the column and the row in rowId and colId, then calls playRound from the game instance. After all that, call the updateDOM() function to display the result of the round in the DOM.

4. Lines 65-69: The last Event Listener, attached to the round reset button from the modal that opens at the end of a round.

Closes the modal with the closeModal() method which resets the score / info board and updates the DOM to display a empty game board, ready for a new round to play.


If you want to see an index with all the articles for this application, go to Articles by projects.

Github page / Live version.

Leave a Reply

Your email address will not be published. Required fields are marked *