Reputation: 47
I am doing a project on paper-rock-scissor that has UI. So, I have four buttons, Start game, rock, paper and scissor. Previously I write the code separately and it works. But right now because I want the result from clicking the button to be an input to another function. So I tried to group all the buttons altogether in my code below. However, it seems like the button doesnt seem to work but there are no errors. I have no idea why? Below are my code :
------------- HTML ---------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Project Rock Paper Scissors</title>
<script src = "javascript.js" defer> </script>
</head>
<body>
<div class="btn-group">
<button id="startgame"> Start game </button>
<button id="rock"> Rock </button>
<button id="paper"> Paper </button>
<button id="scissor"> Scissor </button>
</div>
</body>
</html>
------------ Javascript ---------------
const button = document.querySelector(".btn-group");
const startGame = document.querySelector('#startgame');
const rock = document.querySelector('#rock');
const paper = document.querySelector('#paper');
const scissor = document.querySelector('#scissor');
button.addEventListener('click', function(selection) {
if (selection === startGame) {
startGame.addEventListener('click', () => {
alert("Choose Rock, Paper or Scissor");
})
} else if (selection === rock) {
rock.addEventListener('click', () => {
let item = "rock";
return item.toLowerCase();
})
} else if (selection === paper) {
paper.addEventListener('click', () => {
let item2 = "paper";
return item2.toLowerCase();
})
} else if (selection === scissor) {
scissor.addEventListener('click', () => {
let item3 = "scissor";
return item3.toLowerCase();
})
}
})
----------- Js code above to be used as argument to function playRound(.... , ....) below ------------
function playRound(playerSelection, computerSelection) {
if (playerSelection === "Paper".toLowerCase() && computerSelection.toLowerCase() === "Rock".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and computer plays ${computerSelection} player wins !`);
} else if (playerSelection === "Scissor".toLowerCase() && computerSelection.toLowerCase() === "Paper".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and computer plays ${computerSelection} player wins !`);
} else if (playerSelection === "Rock".toLowerCase() && computerSelection.toLowerCase() === "Scissor".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and computer plays ${computerSelection} player wins !`);
} else if (playerSelection === computerSelection.toLowerCase() ) {
console.log(`Player choose ${playerSelection} and computer plays ${computerSelection} game is draw !`);
} else {
console.log(`Player choose ${playerSelection}, computer plays ${computerSelection}, computer wins !`);
}
}
Upvotes: 1
Views: 7457
Reputation: 2581
you have a bug in your code where selection
is an event object, and not the element which generated the event:
button.addEventListener('click', function(selection) { ...
Your if
statements are comparing selection
(the event object) to strongly equal the elements that were clicked, which is where it is getting skipped. On the event object selection
you'll find the target
property: see https://developer.mozilla.org/en-US/docs/Web/API/Event/target
So you might write your if statments this way:
if ( selection.target == startgame ) { ....
Finally, the event listener is on the outer div and not on each button themselves.
Perhaps an example might help showing one of many ways it is possible to script this:
function computerSelection () {
return Date.now() % 3;
}
function resetScoreBoard( parent ) {
console.log('reset ccoreboard');
scoreboard = document.querySelector('#scoreboard');
if ( scoreboard ) {
scoreboard.textContent = ''; // reset the contents
} else {
scoreboard = document.createElement('div');
parent.appendChild( scoreboard );
}
scoreboard.id = 'scoreboard';
scoreboard.player = document.createElement('fieldset');
scoreboard.player.className = 'score';
scoreboard.player.style.display = 'inline';
scoreboard.player.innerHTML = `<legend>Player</legend>`;
scoreboard.player.score = document.createElement('span');
scoreboard.player.score.innerHTML = '0';
scoreboard.player.appendChild(scoreboard.player.score);
scoreboard.appendChild( scoreboard.player );
scoreboard.computer = document.createElement('fieldset');
scoreboard.computer.className = 'score';
scoreboard.computer.style.display = 'inline';
scoreboard.computer.innerHTML = `<legend>Computer</legend>`;
scoreboard.computer.score = document.createElement('span');
scoreboard.computer.score.innerHTML = '0';
scoreboard.computer.appendChild(scoreboard.computer.score);
scoreboard.appendChild( scoreboard.computer );
scoreboard.result = document.createElement('span');
scoreboard.appendChild(scoreboard.result);
return scoreboard;
}
function score ( playerSelect ) {
let computerSelect = computerSelection();
switch ( playerSelect ) {
case 0: switch ( computerSelect ) {
case 0:
scoreboard.result.innerHTML = `Rock vs. Rock: draw!`;
return;
case 1:
scoreboard.result.innerHTML = `Rock vs. Scissors: Player wins!`;
scoreboard.player.score.innerHTML = parseInt(scoreboard.player.score.innerHTML) + 1;
return;
case 2:
scoreboard.result.innerHTML = `Rock vs. Paper: Computer wins!`;
scoreboard.computer.score.innerHTML = parseInt(scoreboard.computer.score.innerHTML) + 1;
return;
}
case 1: switch ( computerSelect ) {
case 0:
scoreboard.result.innerHTML = `Paper vs. Rock: Player wins!`;
scoreboard.player.score.innerHTML = parseInt(scoreboard.player.score.innerHTML) + 1;
return;
case 1:
scoreboard.result.innerHTML = `Paper vs. Paper: draw!`;
return;
case 2:
scoreboard.result.innerHTML = `Paper vs. Scissors: Computer wins!`;
scoreboard.computer.score.innerHTML = parseInt(scoreboard.computer.score.innerHTML) + 1;
return;
}
case 2: switch ( computerSelect ) {
case 0:
scoreboard.result.innerHTML = `Scissors vs. Rock: Computer wins!`;
scoreboard.computer.score.innerHTML = parseInt(scoreboard.computer.score.innerHTML) + 1;
return;
case 1:
scoreboard.result.innerHTML = `Scissors vs. Paper: Player wins!`;
scoreboard.player.score.innerHTML = parseInt(scoreboard.player.score.innerHTML) + 1;
return;
case 2:
scoreboard.result.innerHTML = `Scissors vs. Scissors: draw!`;
return;
}
}
}
function play ( event ) {
let selection = event.target.id;
switch ( selection ) {
case "startgame":
scoreboard = resetScoreBoard( event.target.parentElement );
return alert("Choose Rock, Paper or Scissor");
case "rock": return score(0);
case "paper": return score(1);
case "scissor": return score(2);
default: console.error(`Unhandled button ${ event.target.id }`);
}
}
let scoreboard;
const buttons = document.querySelectorAll(".btn-group > button");
buttons.forEach( function( button ) {
button.addEventListener('click', play );
});
You can check out the jsfiddle
It might be fun to allow the computer to remember player selections and timestamps to try to intuit the player's choice. Saved to a server and you could compare heuristics across many players to try to make it even more competitive and requiring players to intuit and defy instincts.
Upvotes: 3
Reputation: 127
If you want to add events when .btn-group
is clicked:
const button = document.querySelector(".btn-group");
const startGame = document.querySelector('#startgame');
const rock = document.querySelector('#rock');
const paper = document.querySelector('#paper');
const scissor = document.querySelector('#scissor');
function addEvents(){
startGame.addEventListener('click', () => {
alert("Choose Rock, Paper or Scissor");
})
rock.addEventListener('click', () => {
let item = "rock";
return item.toLowerCase();
})
paper.addEventListener('click', () => {
let item2 = "paper";
return item2.toLowerCase();
})
scissor.addEventListener('click', () => {
let item3 = "scissor";
return item3.toLowerCase();
})
}
button.addEventListener('click', addEvents)
Upvotes: 0
Reputation: 1073988
There are a few of issues there:
You're waiting until a click occurs anywhere within .btn-group
before you add click handlers to the buttons themselves. That doesn't make any sense. You would either use an overall click handler on .btn-group
and use event delegation to determine what button was pressed, or use event handlers on the individual buttons (probably simpler in this specific case).
An event handler receives an event object, not an element, so selection
will never match startgame
or any of the others. The event object's target
property refers to the element where the event was targeted, so with your markup that would match one of your buttons (but beware that if you had <button><strong>xyz</strong></button>
, it would be the strong
element, not the button
element, so you'd have to handle that, perhaps with closest
).
You're returning item.toString()
from your inner event handlers, but that doesn't do anything useful. The return value from an addEventListener
event handler is completely ignored.
The simple way to fix #1 and #2 is (in this case) to remove the .btn-group
handler entirely and just hook up the buttons directly. To fix #3, you have to provide yourself some way of showing that information in the DOM. There are dozens of ways of doing that, so I won't go into specifics here, but you can't just return it and have anything useful happen.
Upvotes: 2