So I'm working in a project recently it is about the rock paper scissor game. I'm stuck in a problem that when I click on one of the three buttons (which are rock, paper, or scissors) the addEventListener
does work but one of the actual parameters of a function that I'm passing as a parameter to the event listener "the console said it is undefined".
I just want when clicking the button to pass the value of that button to this parameter I'm talking about.
const rock = document.querySelector('.rock');
const paper = document.querySelector('.paper');
const scissors = document.querySelector('.scissors');
// there are some functions
let computerSelection = computerPlay();
rock.addEventListener('click', function(){
playRound(playerSelection, computerSelection);
});
paper.addEventListener('click', function(){
playRound(playerSelection, computerSelection);});
scissors.addEventListener('click', function(){
playRound(playerSelection, computerSelection);});
<button >ROCK</button>
<button >PAPER</button>
<button >SCISSORS</button>
CodePudding user response:
You have to read the event on each click listener and you can extract the value from the event by ev.target.value
:
anyButton.addEventListener('click', function(ev) {
playRound(playerSelection, computerSelection, ev.target.value);
}
This, of course, implies that your buttons all have a value
attribute set.
As an improvement, you could add add event listeners at once without going through each element:
const allButtons = document.querySelectorAll('button') // adjust this per your DOM
allButtons.forEach((button) => {
button.addEventListener('click', function(ev) {
playRound(playerSelection, computerSelection, ev.target.value);
})
})
CodePudding user response:
I think it would be most clean to use the dataset and event delegation.
// use event delegation to to reduce the number of event listeners
document.getElementById("game-inputs").onclick = ({ target }) => {
// if its not a game button, do nothing
if (!target.classList.contains("game-button")) {
return
}
// otherwise get the value from the dataset
const value = target.dataset.value
console.log(value);
};
<div id="game-inputs">
<button data-value="rock" >ROCK</button>
<button data-value="paper" >PAPER</button>
<button data-value="scissors" >SCISSORS</button>
</div>
CodePudding user response:
You have to pass playSelection according to wich button the player has clicked:
rock.addEventListener('click', function(){
playRound('rock', computerSelection);
});
paper.addEventListener('click', function(){
playRound('paper', computerSelection);});
scissors.addEventListener('click', function(){
playRound('scissors', computerSelection);
});
But I have a suggestion to do that with only one event handler. First you'll have to say in each button what choice it represents. Do that using data- attributtes (https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes):
<button data-choice="rock">ROCK</button>
<button data-choice="paper">PAPER</button>
<button data-choice="scissors">SCISSORS</button>
Note that I added a choice-button
class to each button, so you can access all three at once when adding the event:
// there are some functions
let computerSelection = computerPlay();
document.querySelectorAll('.choice-button')
.forEach(el => el.addEventListener('click', function(event) {
playRound(event.target.dataset.choice, computerSelection);
}));
First I use querySelectorAll
to find all elements that matches the choice-button
class, then i use forEach
function to iterate trought all 3 found buttons and add the same event listener to all of them.
Once the event listener is executed, I used 'event.target' to get access to the clicked button, and called the dataset property to get the value defined in the data-choice
attribute.
I know it might seem a bit overhead for only three choices, but since you seem to be learning javascript, its interesting to learn different approaches that might help you in a more complex situation.
CodePudding user response:
The undefined
error (and two more that follow it once the initial one is fixed) is caused because you are referencing a function that has not been declared:
let computerSelection = computerPlay();
// computerPlay() is not defined;
If you create the computerPlay()
function, the error will go away but a new one will appear because playRound()
is also not defined. Again, the function must be declared if it is referenced (although hoisting allows it to be declared after the call in this case).
When that is fixed, the last error arises by the reference to playerSelection
as, again, this has not been declared. Assuming the value of playerSelection
is to be rock, paper, or scissors, you have to extract it from the click event.
The event handler needs to extract the innerText
property value of the event's target
. Inside you're event listeners you need:
playerSelection = event.target.innerText;