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, puterSelection) {
if (playerSelection === "Paper".toLowerCase() && puterSelection.toLowerCase() === "Rock".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} player wins !`);
} else if (playerSelection === "Scissor".toLowerCase() && puterSelection.toLowerCase() === "Paper".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} player wins !`);
} else if (playerSelection === "Rock".toLowerCase() && puterSelection.toLowerCase() === "Scissor".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} player wins !`);
} else if (playerSelection === puterSelection.toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} game is draw !`);
} else {
console.log(`Player choose ${playerSelection}, puter plays ${puterSelection}, puter wins !`);
}
}
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, puterSelection) {
if (playerSelection === "Paper".toLowerCase() && puterSelection.toLowerCase() === "Rock".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} player wins !`);
} else if (playerSelection === "Scissor".toLowerCase() && puterSelection.toLowerCase() === "Paper".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} player wins !`);
} else if (playerSelection === "Rock".toLowerCase() && puterSelection.toLowerCase() === "Scissor".toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} player wins !`);
} else if (playerSelection === puterSelection.toLowerCase() ) {
console.log(`Player choose ${playerSelection} and puter plays ${puterSelection} game is draw !`);
} else {
console.log(`Player choose ${playerSelection}, puter plays ${puterSelection}, puter wins !`);
}
}
Share
Improve this question
asked Jul 23, 2022 at 9:21
Jabri JuhininJabri Juhinin
471 silver badge7 bronze badges
3
-
You seem to have confused what is passed to an event callback, which is not the element that triggered the event, but rather an
event
object with properties describing the event (including the element which triggered it asevent.target
). Your second problem is that even if you handled the event correctly you would simply be adding new listeners on every click, rather than handling the click itself. – pilchard Commented Jul 23, 2022 at 9:27 -
I think it should be
function(ev) { ... }
instead offunction(selection) { ... }
and then when you pare the source of the event you should useev.target === startGame
instead ofselection === startGame
. And last but not least I would register all click listeners at once and never inside an event listener. If the game is started a second time, all buttons would have multiple event handlers. not tested – Michael Commented Jul 23, 2022 at 9:28 - Does this answer your question? What is DOM Event delegation? – pilchard Commented Jul 23, 2022 at 9:29
3 Answers
Reset to default 3you 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 paring 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/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 puterSelection () {
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.puter = document.createElement('fieldset');
scoreboard.puter.className = 'score';
scoreboard.puter.style.display = 'inline';
scoreboard.puter.innerHTML = `<legend>Computer</legend>`;
scoreboard.puter.score = document.createElement('span');
scoreboard.puter.score.innerHTML = '0';
scoreboard.puter.appendChild(scoreboard.puter.score);
scoreboard.appendChild( scoreboard.puter );
scoreboard.result = document.createElement('span');
scoreboard.appendChild(scoreboard.result);
return scoreboard;
}
function score ( playerSelect ) {
let puterSelect = puterSelection();
switch ( playerSelect ) {
case 0: switch ( puterSelect ) {
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.puter.score.innerHTML = parseInt(scoreboard.puter.score.innerHTML) + 1;
return;
}
case 1: switch ( puterSelect ) {
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.puter.score.innerHTML = parseInt(scoreboard.puter.score.innerHTML) + 1;
return;
}
case 2: switch ( puterSelect ) {
case 0:
scoreboard.result.innerHTML = `Scissors vs. Rock: Computer wins!`;
scoreboard.puter.score.innerHTML = parseInt(scoreboard.puter.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 puter to remember player selections and timestamps to try to intuit the player's choice. Saved to a server and you could pare heuristics across many players to try to make it even more petitive and requiring players to intuit and defy instincts.
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 matchstartgame
or any of the others. The event object'starget
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 thestrong
element, not thebutton
element, so you'd have to handle that, perhaps withclosest
).You're returning
item.toString()
from your inner event handlers, but that doesn't do anything useful. The return value from anaddEventListener
event handler is pletely 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.
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)