简体   繁体   中英

Is there a way to make a textContent stay permanent?

Sorry if it's a dumb question, currently making a tic tac toe game, I made the user able to click the board which are buttons. When clicked upon, it will place the players marker("X" or "O").

Problem: Once a player has pressed it, I do not want that textContent to change at all. Is there a way to achieve that result?

const playRound = (e) => {
    let playerInput = e.currentTarget.dataset.number
    placeMarker(playerInput, getActivePlayer().marker);
    e.currentTarget.textContent = getActivePlayer().marker;
    _switchPlayerTurn();

    printNewRound();
    console.log(`${board}`);
    console.log(typeof board);
    console.log(GameBoard.getBoard());
}

//Event Listener
const ScreenController = (function ScreenController() {
  const {
    playRound
  } = Game;
  const board = document.querySelectorAll('.square');
  board.forEach(element => {
    element.addEventListener('click', playRound);
  })
})();

Codepen: https://codepen.io/jimmyjimenez2400/pen/ZEjvrPq

I did try to look up of how I can make it stay permanent with no luck.

I did try to use innerHTML but knowing it can cause issues for security. I just avoid it.

Feeling that I probably have to make an if statement, where "If textContent changed, then somehow lock it". I'm expecting the textContent to not change on second click on the element.

I think setting the once option to true is the most concise:

element.addEventListener('click', playRound, { once: true });

Although it is not supported by IE: https://caniuse.com/once-event-listener

docs: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#parameters


Example:

 let count = 0; const playRound = (e) => { const letter = count++ % 2 == 0? "O": "X"; e.target.textContent = letter; console.log(`Turn ${count} complete`); } const board = document.querySelectorAll('.square'); board.forEach(element => { element.addEventListener('click', playRound, { once: true }); })
 .row { display: flex }.square { display: flex; cursor: pointer; width: 40px; height: 40px; border: 1px solid black; align-items: center; justify-content: center; } div.as-console-wrapper { max-height: 66px; }
 <div class="row"> <span class="square"></span> <span class="square"></span> <span class="square"></span> </div> <div class="row"> <span class="square"></span> <span class="square"></span> <span class="square"></span> </div> <div class="row"> <span class="square"></span> <span class="square"></span> <span class="square"></span> </div>


As suggested in the comments, here is a slightly less concise method that supports IE. It does the exact same thing as above, removes the event listener at the end of the callback function.

 let count = 0; const playRound = (e) => { const letter = count++ % 2 == 0? "O": "X"; e.target.textContent = letter; console.log(`Turn ${count} complete`); } const board = document.querySelectorAll('.square'); board.forEach(element => { const callback = (e) => { playRound(e); element.removeEventListener('click', callback); } element.addEventListener('click', callback); })
 .row { display: flex }.square { display: flex; cursor: pointer; width: 40px; height: 40px; border: 1px solid black; align-items: center; justify-content: center; } div.as-console-wrapper { max-height: 66px; }
 <div class="row"> <span class="square"></span> <span class="square"></span> <span class="square"></span> </div> <div class="row"> <span class="square"></span> <span class="square"></span> <span class="square"></span> </div> <div class="row"> <span class="square"></span> <span class="square"></span> <span class="square"></span> </div>

Simply add an if clause right at the beginning of your event listener function, like

const playRound = (e) => {
  if (e.currentTarget.textContent) return;
  ...
}

This will effectively "lock" any already filled out cell. An empty cell will have a .textContent of "" which in JavaScript will be seen as falsy.

Ok, if the initial content is numeric, then you should of course check differently, like:

if ("XO".includes(e.currentTarget.textContent)) return;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM