Contexto : Objetivo: Imitar el botón de cancelar correo electrónico enviado en gmail. Problema actual: tengo que hacer clic dos veces en el botón Cancel para que funcione.
Detalle : el siguiente código crea un botón Send . Después de hacer clic, se mostrará un párrafo de cuenta regresiva y comenzará a contar regresivamente de 10 a 0 y el botón cambiará de Send a Cancel . Se supone que el botón Cancel muestra un mensaje ( Sent email has been recalled! ) inmediatamente después de hacer clic en el botón. Sin embargo, actualmente, tengo que hacer clic en el botón Cancel dos veces para que aparezca el mensaje de recuperación. Me pregunto qué línea de código causa el problema.
Código a continuación
<!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>El problema es que no se actúa sobre el usuario haciendo clic en Cancelar de inmediato. En su lugar, crea un nuevo detector de eventos para que el sistema no haga nada hasta que el usuario vuelva a hacer clic y se invoque ese detector de eventos.
Elimine la creación de un nuevo detector de eventos y, en su lugar, llame a la función de cancelación de inmediato. Tenga en cuenta que también debe restablecer sec a su valor inicial; de lo contrario, el usuario obtiene una cantidad de tiempo decreciente para decidir cancelar el envío.
<!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><!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>