Reputation: 11
Context: Goal: Mimic the cancel sent email button in gmail. Current problem: I have to click the Cancel
button twice for it to work.
Detail: The following code creates a Send
button. After it was clicked, a countdown paragraph will display and started to count down from 10 to 0 and the button will change from Send
to Cancel
. The Cancel
button is supposed to display a message (Sent email has been recalled!
) immediately after the button was clicked. However, currently, I have to click the Cancel
button twice for the recall message to show up. I wonder which line of code causes the problem?
Code below
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM Demo</title>
<link ref="icon" href="favicon.ico">
</head>
<body>
<main>
<div>
<button id="action-button">Send</button>
<p id="countdown-message"></p>
</div>
</main>
<script>
'use strict'
const button = document.getElementById('action-button');
button.addEventListener('click', changeButtonText)
const countdownMessage = document.getElementById('countdown-message');
let sec = 10;
let timeoutId = 0;
function changeButtonText() {
if (button.innerText === 'Send') {
button.innerText = 'Cancel';
countDown();
}
else if (button.innerText === 'Cancel') {
button.addEventListener('click',cancelSent);
}
}
function countDown() {
if (sec > 0) {
showCountdownMessage();
sec--;
timeoutId = setTimeout(countDown, 1000);
} else {
showSentMessage();
}
}
function cancelSent(){
clearTimeout(timeoutId);
countdownMessage.innerText = 'Sent email has been recalled!'
}
function showCountdownMessage() {
countdownMessage.innerText = `The email will be sent in ${sec} seconds`;
}
function showSentMessage() {
countdownMessage.innerText = 'Email has been sent!'
}
</script>
</body>
</html>
Upvotes: 0
Views: 159
Reputation: 451
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM Demo</title>
</head>
<body>
<main>
<div>
<button id="action-button">Send</button>
<p id="countdown-message"></p>
</div>
</main>
<script>
'use strict'
const button = document.getElementById('action-button');
button.addEventListener('click', changeButtonText)
const countdownMessage = document.getElementById('countdown-message');
let sec = 10;
let timeoutId = 0;
function changeButtonText() {
if (button.innerText === 'Send') {
button.innerText = 'Cancel';
countDown();
}
else if (button.innerText === 'Cancel') {
cancelSent()
}
// efficient way to do the same
// switch(button.innerText){
// case 'Send':
// button.innerText = 'Cancel';
// countDown();
// break;
// case 'Cancel':
// cancelSent()
// }
}
function countDown() {
if (sec > 0) {
showCountdownMessage();
sec--;
timeoutId = setTimeout(countDown, 1000);
} else {
showSentMessage();
}
}
function cancelSent(){
clearTimeout(timeoutId);
countdownMessage.innerText = 'Sent email has been recalled!'
}
function showCountdownMessage() {
countdownMessage.innerText = `The email will be sent in ${sec} seconds`;
}
function showSentMessage() {
countdownMessage.innerText = 'Email has been sent!'
}
</script>
</body>
</html>
Upvotes: 0
Reputation: 36456
The problem is that you don't act on the user clicking Cancel straightaway. Instead you create a new event listener so the system won't do anything until the user clicks again and that event listener is invoked.
Remove the creation of a new event listener and instead call the cancelling function straightaway. Note, you also need to reset sec to its initial value otherwise the user gets a decreasing amount of time in which to decide to cancel the send.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM Demo</title>
<link ref="icon" href="favicon.ico">
</head>
<body>
<main>
<div>
<button id="action-button">Send</button>
<p id="countdown-message"></p>
</div>
</main>
<script>
'use strict'
const button = document.getElementById('action-button');
button.addEventListener('click', changeButtonText)
const countdownMessage = document.getElementById('countdown-message');
let sec = 10;
let timeoutId = 0;
function changeButtonText() {
if (button.innerText === 'Send') {
button.innerText = 'Cancel';
countDown();
} else if (button.innerText === 'Cancel') {
// button.addEventListener('click',cancelSent);
cancelSent();
button.innerText = 'Send';
sec = 10;
}
}
function countDown() {
if (sec > 0) {
showCountdownMessage();
sec--;
timeoutId = setTimeout(countDown, 1000);
} else {
showSentMessage();
}
}
function cancelSent() {
clearTimeout(timeoutId);
countdownMessage.innerText = 'Sent email has been recalled!'
}
function showCountdownMessage() {
countdownMessage.innerText = `The email will be sent in ${sec} seconds`;
}
function showSentMessage() {
countdownMessage.innerText = 'Email has been sent!'
}
</script>
</body>
</html>
Upvotes: 1