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.