I'm having an issue with event listeners in JS. I have a sort of chessboard on my display (i.e. a box containing 25 squared divs). When I click on one of those divs, I want an 'A' to show up on that div. When I click a second time, I want a 'B' to show up. If I have another try, I want an 'A' again, and then a 'B', and then an 'A'. And so on, until my chessboard is filled with As and Bs.
My code now resembles this one:
const showA = () => {
chessBoard.addEventListener('click', function() {
//code that makes an A show up
});
}
const showB = () => {
chessBoard.addEventListener('click', function() {
//code that makes a B show up
});
}
These functions work properly if I call only one of them:
showA(); /*works*/
//showB();
When I call them both, as my code is supposed to work in order to fill up the chessboard with both letters, only the second event will fire.
showA();
showB();
//Only Bs will show up on my chessboard!
I already tried to put the listeners on the individual divs that build the chessboard, but it produced the same result.
I'm sorry if this issue has already been raised in older threads, but I didn't manage to find anything helpful. Thanks in advance!
You need only one event listener and a condition within that listener that swaps the text content of the square from A to B when it's clicked.
In this example I've used CSS grid to create some squares.
// Cache the container element and add a handler to it
// This allows us to use event delegation. The handler will
// capture any event that "bubbles up" the DOM from its child
// elements - in this case the nested divs.
const container = document.querySelector('.container');
container.addEventListener('click', handler, false);
function handler(e) {
// Get the text content from the div that was clicked
const { textContent } = e.target;
// Reset the target content depending on that current content
if (textContent === '' || textContent === 'B') {
e.target.textContent = 'A';
} else {
e.target.textContent = 'B';
}
}
.container { display: grid; grid-template-columns: 1fr 1fr; width: 100px; }
.container div { font-size: 1.4rem; width: 50px; height: 50px; padding: 0.8em; background-color: #efefef; text-align: center; border: 1px solid #acacac; vertical-align: middle; line-height: 50px; }
.container div:hover { cursor: pointer; background-color: #dfdfdf; }
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
You can read more on event delegation here.
If I've well understood your question you want to alternate between A and B for each calls.
This can be simply done with a flag that is toggled at each calls, such as ATurn = !ATurn;
let ATurn = true;
document.getElementById("test").addEventListener('click', (e) => {
if (ATurn)
{
// code for A
console.log("It's A's turn ");
}
else
{
// code for B
console.log("It's B's turn ");
}
ATurn = !ATurn; // true becomes !true, which is false, or false becomes !false, which is true
});
<button type="button" id="test">Click me!</button>
You should handle switching between A and B in a single event listener; here is the code:
let turn = 'A';
chessboard.addEventListener('click', () => {
if(turn === 'A') {
//code that makes an A show up
turn = 'B'
} else if(turn === 'B') {
//code that makes an B show up
turn = 'A'
}
})