let doorLeft = document.getElementById("left");
let doorMiddle = document.getElementById("middle");
let doorRight = document.getElementById("right");
let resetButton = document.getElementById("reset");
let numberOfClicks = 0;
function incrementClicks() {
numberOfClicks++;
console.log('Number of clicks: ' + numberOfClicks)
}
/* -------------------------------------------------------------------------- */
/* handle click door only once */
/* -------------------------------------------------------------------------- */
const revealDoorColour = () => {
doorLeft.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorMiddle.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorRight.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
};
/* -------------------------------------------------------------------------- */
const reset = () => {
doorLeft.style.backgroundColor = "paleturquoise";
doorRight.style.backgroundColor = "paleturquoise";
doorMiddle.style.backgroundColor = "paleturquoise";
revealDoorColour();
resetButton.innerHTML = "Let's play";
};
resetButton.addEventListener("click", function() {
reset();
numberOfClicks = 0;
});
.container.main {
display: flex;
justify-content: space-around;
padding: 0 20%;
}
.door {
height: 500px;
width: 300px;
margin: 10px;
}
#left {
background-color: paleturquoise;
}
#middle {
background-color: paleturquoise;
}
#right {
background-color: paleturquoise;
}
.score {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<title>Door guesser</title>
<script src="./js/main.js" async></script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container main">
<div class="door" id="left">
</div>
<div class="door" id="middle">
</div>
<div class="door" id="right">
</div>
</div>
<div class="container score">
<div class="currentScoreGroup">
<div>Current score: </div>
<div id="currentScore">0</div>
</div>
<div class="bestScoreGroup">
<div>Best score: </div>
<div id="bestScore">0</div>
</div>
<button class="reset" id='reset'>Let's play </button>
</div>
</body>
</html>
let doorLeft = document.getElementById("left");
let doorMiddle = document.getElementById("middle");
let doorRight = document.getElementById("right");
let resetButton = document.getElementById("reset");
let numberOfClicks = 0;
function incrementClicks() {
numberOfClicks++;
console.log('Number of clicks: ' + numberOfClicks)
}
/* -------------------------------------------------------------------------- */
/* handle click door only once */
/* -------------------------------------------------------------------------- */
const revealDoorColour = () => {
doorLeft.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorMiddle.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorRight.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
};
/* -------------------------------------------------------------------------- */
const reset = () => {
doorLeft.style.backgroundColor = "paleturquoise";
doorRight.style.backgroundColor = "paleturquoise";
doorMiddle.style.backgroundColor = "paleturquoise";
revealDoorColour();
resetButton.innerHTML = "Let's play";
};
resetButton.addEventListener("click", function() {
reset();
numberOfClicks = 0;
});
.container.main {
display: flex;
justify-content: space-around;
padding: 0 20%;
}
.door {
height: 500px;
width: 300px;
margin: 10px;
}
#left {
background-color: paleturquoise;
}
#middle {
background-color: paleturquoise;
}
#right {
background-color: paleturquoise;
}
.score {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<title>Door guesser</title>
<script src="./js/main.js" async></script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container main">
<div class="door" id="left">
</div>
<div class="door" id="middle">
</div>
<div class="door" id="right">
</div>
</div>
<div class="container score">
<div class="currentScoreGroup">
<div>Current score: </div>
<div id="currentScore">0</div>
</div>
<div class="bestScoreGroup">
<div>Best score: </div>
<div id="bestScore">0</div>
</div>
<button class="reset" id='reset'>Let's play </button>
</div>
</body>
</html>
Following Extract function from addEventListener I've added the {once:true} parameter which seems to work fine most of the time. However, when clicking on the div in question, it randomly gets fired multiple times (at the same x/y coordinates). How is this possible? I set a breakpoint in the anonymous function and it runs through it multiple times. Any ideas?
To replicate the issue
- Click Let's play
- Click any card
- click Let's play once again
- Click a different card
- Now you should see 2 entries (clicks) in the console
-
2
Hi! Please update your question with a minimal reproducible example demonstrating the problem, ideally a runnable one using Stack Snippets (the
[<>]
toolbar button); here's how to do one. Perhaps these elements are nested within one another? – T.J. Crowder Commented May 25, 2021 at 15:34 - Done :) Sorry for the minimal info provided at first. – gabe Commented May 25, 2021 at 15:48
- 1 Hi! I'm afraid you've gone the other way. Please do read through the link above for details. – T.J. Crowder Commented May 25, 2021 at 15:52
- Oops. I think this is the bare minimum I can strip it to so it still misbehaves – gabe Commented May 25, 2021 at 16:13
-
If I click "Let's play" and then click Door 1, I get a message. If I clidk Door 1 again, I don't; I do if I click a different door, but that's a different handler entirely. That's what
{once: true}
does. What are you expecting intead? – T.J. Crowder Commented May 25, 2021 at 16:20
1 Answer
Reset to default 5The once
option of addEventListener work like this:
once
A Boolean indicating that the listener should be invoked at most once after being added.
If true, the listener would be automatically removed when invoked.
So if a div is not clicked, its handler still stay there. When you click play again, you basically add more event listener to the div. What why it randomly gets fired multiple times (at the same x/y coordinates)
To fix that, just remove the event listener in reset
let doorLeft = document.getElementById("left");
let doorMiddle = document.getElementById("middle");
let doorRight = document.getElementById("right");
let resetButton = document.getElementById("reset");
let numberOfClicks = 0;
function incrementClicks() {
numberOfClicks++;
console.log('Number of clicks: ' + numberOfClicks)
}
/* -------------------------------------------------------------------------- */
/* handle click door only once */
/* -------------------------------------------------------------------------- */
const revealDoorColour = () => {
doorLeft.removeEventListener("click", incrementClicks);
doorMiddle.removeEventListener("click", incrementClicks);
doorRight.removeEventListener("click", incrementClicks);
//
doorLeft.addEventListener("click", incrementClicks, { once: true });
doorMiddle.addEventListener("click", incrementClicks, { once: true });
doorRight.addEventListener("click", incrementClicks, { once: true });
};
/* -------------------------------------------------------------------------- */
const reset = () => {
doorLeft.style.backgroundColor = "paleturquoise";
doorRight.style.backgroundColor = "paleturquoise";
doorMiddle.style.backgroundColor = "paleturquoise";
revealDoorColour();
resetButton.innerHTML = "Let's play";
};
resetButton.addEventListener("click", function() {
reset();
numberOfClicks = 0;
});
.container.main {
display: flex;
justify-content: space-around;
padding: 0 20%;
}
.door {
height: 500px;
width: 300px;
margin: 10px;
}
#left {
background-color: paleturquoise;
}
#middle {
background-color: paleturquoise;
}
#right {
background-color: paleturquoise;
}
.score {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<title>Door guesser</title>
<script src="./js/main.js" async></script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container main">
<div class="door" id="left">
</div>
<div class="door" id="middle">
</div>
<div class="door" id="right">
</div>
</div>
<div class="container score">
<div class="currentScoreGroup">
<div>Current score: </div>
<div id="currentScore">0</div>
</div>
<div class="bestScoreGroup">
<div>Best score: </div>
<div id="bestScore">0</div>
</div>
<button class="reset" id='reset'>Let's play </button>
</div>
</body>
</html>