Having issue resetting JS stopwatch - javascript

I made a little typing game that reveals some random text and you have to type the same in, so that you can test your typing speed. the users has the ability to play again and again, the issue is that when the user types play again, the stopwatch does not begin as it did the first time.
Can anyone help me with making the stopwatch restart everytime the user clicks on the play again button?
[ full code is here] (https://jsfiddle.net/kisho/ncbxd9o4/#&togetherjs=qD5bT8vLiw)
js portion-
const textDisplay = document.querySelector('#text-display');
const input = document.querySelector('#input');
const btn = document.querySelector('#btn');
const textBox = document.querySelector('#text-box');
const countdown = document.querySelector('#countdown');
const stopwatch = document.querySelector('#stopwatch');
const successMessege = document.querySelector('#success-messege');
const stopwatchTime = document.querySelector('#stopwatch-time');
btn.addEventListener('click', runGame);
function runGame() {
if ((btn.innerText = 'Play again')) {
playAgain();
fetchQuote();
countownTimer();
confirmQuote();
} else {
fetchQuote();
countownTimer();
confirmQuote();
}
}
function fetchQuote() {
fetch('https://api.quotable.io/random')
.then((res) => {
return res.json();
})
.then((data) => {
textDisplay.innerText = data.content;
});
}
function countownTimer() {
if (timer !== undefined) {
clearInterval(timer);
}
var timeleft = 2;
var downloadTimer = setInterval(function() {
if (timeleft <= 0) {
clearInterval(downloadTimer);
document.getElementById('countdown').innerHTML = 'Start Typing!';
input.classList.remove('displayNone');
runningStopwatch.classList.remove('displayNone');
begin();
} else {
document.getElementById('countdown').innerHTML = timeleft + ' seconds remaining';
}
timeleft -= 1;
}, 1000);
}
function confirmQuote() {
if ((countdown.innerHTML = 'Start typing!')) {
input.addEventListener('keyup', function(event) {
if (event.keyCode === 13) {
if (textDisplay.innerText === input.value) {
btn.innerText = 'Play again';
// textBox.classList.add('displayNone');
hold();
} else successMessege.innerText = 'Missed something there, try again!!';
}
});
}
}
function playAgain() {
textBox.classList.remove('displayNone');
input.classList.add('displayNone');
input;
input.value = '';
successMessege.innerText = '';
}
let ms = 0,
s = 0,
m = 0;
let timer;
let runningStopwatch = document.querySelector('.running-stopwatch');
function begin() {
timer = setInterval(run, 10);
}
function run() {
runningStopwatch.textContent =
(m < 10 ? '0' + m : m) + ': ' + (s < 10 ? '0' + s : s) + ': ' + (ms < 10 ? '0' + ms : ms);
ms++;
if (ms == 100) {
ms = 0;
s++;
}
if (s == 60) {
s = 0;
m++;
}
}
function hold() {
clearInterval(timer);
successMessege.innerText = `Nice job! You just typed in x seconds!`;
}
function stop() {
(ms = 0), (s = 0), (m = 0);
runningStopwatch.textContent =
(m < 10 ? '0' + m : m) + ': ' + (s < 10 ? '0' + s : s) + ': ' + (ms < 10 ? '0' + ms : ms);
}

You are not handling the clearInterval correctly.
You are clearing the interval only if one ends the game successfully.
My solution would be:
When calling the countownTimer() function, the first thing you should do, is to check if the interval timer is still running.
function countownTimer() {
if (timer !== undefined) {
clearInterval(timer);
}
// [...]
}
The next thing would be, to start the interval every time begin() gets called.
function begin() {
timer = setInterval(run, 10);
}

Related

JQuery - How to update variable after call function?

I have a timer function, I want to change the value of my variable after the timer reaches 0?
function countdown(minutes) {
var seconds = 60;
var mins = minutes
function tick() {
var counter = document.getElementById("timer");
current_minutes = mins - 1
seconds--;
counter.innerHTML =
current_minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
if (parseInt(current_minutes) === 0 && parseInt(seconds) === 00) {
sendAgain.show();
finalMin = parseInt(current_minutes);
finalSec = parseInt(seconds);
}
if (seconds > 0) {
timeoutHandle = setTimeout(tick, 1000);
} else {
if (mins > 1) {
// countdown(mins-1); never reach “00″ issue solved:Contributed by Victor Streithorst
setTimeout(function () { countdown(mins - 1); }, 1000);
}
}
}
tick();
}
variables :
let finalMin = null;
var finalSec = null;
I want the variables to be set after the following code is executed?
if (parseInt(current_minutes) === 0 && parseInt(seconds) === 00) {
sendAgain.show();
finalMin = parseInt(current_minutes);
finalSec = parseInt(seconds);
}
countdown(2);
console.log(finalMin); ===== show "0"

Why clearInterval is not stopping setInterval?

I'm trying to make a Timer for a project that record audios and while on the making, I've faced with this problem: setInterval is not stopping, why?
I have the following code:
/** Audio **/
var timerseconds = 0;
$('.audio-recorder-dialog-con').on('click', '#record', function() {
gotrecordval = document.getElementById("record").value;
//Crónometro
var timerseconds = setInterval(function() {
rseconds = parseInt(document.getElementById("r-seconds").value);
if (rseconds == 59) {
document.getElementById("r-seconds").value = "00";
}
rseconds = parseInt(document.getElementById("r-seconds").value);
rseconds += 1;
if (rseconds < 10) {
document.getElementById("r-seconds").value = ("00" + rseconds).substr(-2);
}
if (rseconds >= 10) {
document.getElementById("r-seconds").value = rseconds;
}
}, 1000);
//
if (gotrecordval == "Empezar a Grabar Audio") {
document.getElementById("record").value = "Detener/Subir";
}
if (gotrecordval == "Detener/Subir") {
document.getElementById("record").value = "Empezar a Grabar Audio";
$('.audio-recorder-dialog-con').fadeOut(500);
$(".contenido-dialog-new-d").fadeIn(500);
$("#aviaudio").fadeIn(500);
clearInterval(timerseconds);
}
});
--FIXED--
I've fixed it by adding this inside the setInterval:
//Crónometro
var timerseconds = setInterval(function(){
rseconds = parseInt(document.getElementById("r-seconds").value);
if(rseconds==59){document.getElementById("r-seconds").value = "00";}
rseconds = parseInt(document.getElementById("r-seconds").value);
rseconds+=1;
if(rseconds<10){document.getElementById("r-seconds").value = ("00" + rseconds).substr(-2);}
if(rseconds>=10){document.getElementById("r-seconds").value = rseconds;}
--Code added-
$('html, body').on('click', '.open-audio', function(){
clearInterval(timerseconds);
});
--
}, 1000);
//
".open-audio" is an image that opens the recording dialog for the user, so when you re-open it, the clearInterval works.
The solution you added to your question is not sound: this will create a new event handler at every 'tick' of the setInterval timer. That is not the right way to do it.
Instead, only execute setInterval in the case you need to start it, so put it inside the first if:
if (gotrecordval == "Empezar a Grabar Audio") {
//Crónometro
var timerseconds = setInterval(function() {
rseconds = parseInt(document.getElementById("r-seconds").value);
if (rseconds == 59) {
document.getElementById("r-seconds").value = "00";
}
rseconds = parseInt(document.getElementById("r-seconds").value);
rseconds += 1;
if (rseconds < 10) {
document.getElementById("r-seconds").value = ("00" + rseconds).substr(-2);
}
if (rseconds >= 10) {
document.getElementById("r-seconds").value = rseconds;
}
}, 1000);
//
document.getElementById("record").value = "Detener/Subir";
}

JavaScript timer in my program stops in unpredictable way

I'm a completely beginner and I write code in my free time. Can anyone explain me please why sometimes my Pomodore Clock is stuck when it hits 0 0 1. (hours, minutes, seconds)
I can start it in one tab in chrome and it will work for unpredictable amount of cycles and then for no reason it will stop at 0 0 1, just before starting next cycle. I want it to work continuous (work, break, work, break, etc.) until I hit reset button...
Is there better way to handle time in JS?
Code:
// Code wrapped in a closure to avoid global variables
(function () {
let countdown;
let timeIsRunnig = false;
let actionTypeSwitch = "Work";
const timerDisplay = document.querySelector(".display__time-left");
const infoDisplay = document.querySelector(".display__info");
const endTime = document.querySelector(".display__end-time");
const buttons = document.querySelectorAll("[data-time]");
const breakSettings = document.querySelectorAll(".settings__breakButton");
const workSettings = document.querySelectorAll(".settings__workButton");
const breakValue = document.querySelector("#valueBreak");
const workValue = document.querySelector("#valueWork");
const buttonMain = document.querySelector("#buttonMain");
let workValueSettings = 25; // Default work session value in min
let breakValueSettings = 5; // Default break session value in min
workValue.textContent = workValueSettings + ' min';
breakValue.textContent = breakValueSettings + ' min';
timerDisplay.textContent = `${ workValueSettings}:00`;
infoDisplay.textContent = "Are you ready?";
endTime.textContent = "Press START";
function timer(seconds) {
// Clear any existing timers
clearInterval(countdown);
// Current time in ms
const now = Date.now();
const future = now + seconds * 1000;
displayTimeLeft(seconds);
displayEndTime(future);
function timeCalc() {
const secondsLeft = Math.round((future - Date.now()) / 1000);
// Check if we should stop it
if (secondsLeft < 0) {
clearInterval(countdown);
return;
}
// Display it
displayTimeLeft(secondsLeft);
}
countdown = setInterval(timeCalc, 1000);
}
function startTimer() {
const seconds = workValueSettings * 60;
actionTypeSwitch = "Work";
infoDisplay.textContent = "Working hard!";
timer(seconds);
}
function startBreak() {
const seconds = breakValueSettings * 60;
actionTypeSwitch = "Break";
infoDisplay.textContent = "Short break!";
timer(seconds);
}
function resetTimer() {
const seconds = workValueSettings * 60;
// Clear any existing timers
clearInterval(countdown);
// Refresh display
displayTimeLeft(seconds);
infoDisplay.textContent = "Are you ready?";
endTime.textContent = "Press START";
}
function startAndReset() {
let name = "START";
if (timeIsRunnig === false) {
timeIsRunnig = true;
name = "RESET";
this.innerHTML = name;
startTimer();
} else {
timeIsRunnig = false;
name = "START";
this.innerHTML = name;
resetTimer();
}
}
function playSoundStartBreak() {
// Returns the first Element within the document
// that matches the specified group of selectors.
const audio = document.querySelector(`audio[data-sound="workDone"]`);
if(!audio) return; // Stop the function from running
audio.currentTime = 0; // Rewind to the start
audio.play();
}
function playSoundBackToWork() {
// Returns the first Element within the document
// that matches the specified group of selectors.
const audio = document.querySelector(`audio[data-sound="backToWork"]`);
if(!audio) return; // Stop the function from running
audio.currentTime = 0; // Rewind to the start
audio.play();
}
function displayTimeLeft(sec) {
const hours = parseFloat(Math.floor(sec / 3600));
const minutes = parseFloat(Math.floor(sec / 60));
const remainderMinutes = parseFloat(minutes % 60);
const remainderSeconds = parseFloat(sec % 60);
console.log(hours, remainderMinutes, remainderSeconds);
// Play sound when timer gets to 0
if (parseFloat(sec) === 0) {
if (actionTypeSwitch === "Work") {
playSoundStartBreak()
startBreak();
} else {
playSoundBackToWork();
startTimer();
}
}
// Hide hours when hours is 0
let hoursFirstStatement = hours < 10 ? "0" : "";
let hoursSecondStatement = hours;
let colon = ":";
if (hours === 0) {
hoursFirstStatement = "";
hoursSecondStatement = "";
colon = "";
}
// This `${}` allows adding javascript variables in strings
const display = `${hoursFirstStatement}${hoursSecondStatement}${colon}${
remainderMinutes < 10 ? "0" : ""}${remainderMinutes}:${
remainderSeconds < 10 ? "0" : ""}${remainderSeconds}`;
timerDisplay.textContent = display;
document.title = display + " " + "(" + actionTypeSwitch + ")";
}
function displayEndTime(timestamp) {
const end = new Date(timestamp);
const hours = end.getHours();
const minutes = end.getMinutes();
endTime.textContent = `This session ends at ${hours < 10 ? "0" : ""}${hours}:${
minutes < 10 ? "0" : ""}${minutes}`;
}
function changeBreakSettings() {
const breakChangeValue = parseInt(this.dataset.settings);
if ((breakValueSettings <= 1 && breakChangeValue === -1) ||
(breakValueSettings >= 30 && breakChangeValue === 1)) {
return; // Do nothing when this conditions are fulfilled
} else {
breakValueSettings = breakValueSettings + breakChangeValue;
breakValue.textContent = breakValueSettings + ' min';
}
}
function changeWorkSettings() {
const workChangeValue = parseInt(this.dataset.settings);
if ((workValueSettings <= 5 && workChangeValue === -1) ||
(workValueSettings >= 120 && workChangeValue === 1)) {
return; // Do nothing when this conditions are fulfilled
} else {
workValueSettings = workValueSettings + workChangeValue;
workValue.textContent = workValueSettings + ' min';
}
}
breakSettings.forEach(button => button.addEventListener("click", changeBreakSettings));
workSettings.forEach(button => button.addEventListener("click", changeWorkSettings));
buttonMain.addEventListener("click", startAndReset);
}());
You need to do clearInterval() against timeCalc & update the display on the case of secondsLeft < 0. Because when you do not clear it, when it is showing "1 second left", the call of timeCalc will goes into the if statement and return, and never update the display and timeCalc is never clear and you get into infinite loop.

Reset countdown interval with clearInterval doesn't work

I don't know how to reset ongoing counter. I have two counters on my page. It seems it works properly, but when I want to set new value to counter2 when it is still counting down, I see in my div two counting times. New and old one.
var interval1;
var interval2;
function countdown(element, minutes, seconds, timer) {
var el = document.getElementById(element);
clearInterval(timer);
timer = setInterval(function() {
if(seconds == 0) {
if(minutes == 0) {
(el.innerHTML = "---");
clearInterval(timer);
return;
}
else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
}
else {
var minute_text = '';
}
var second_text = seconds > 1 ? '' : '';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + '';
seconds--;
}, 1000);
}
function setCounter1(mins) {
countdown('timeLeft', mins, 00, interval1);
}
function setCounter2(mins) {
countdown('timeLeft2', mins, 00, interval2);
}
If for example I have set counter2 for 10mins, and after a minute I call setCounter2(3), I see in my timeLeft2 div two counters.
How can I reset ongoing counter?
Thanks for your help!
Reassigning an argument variable inside a function does not modify the argument outside of the function. You can see a demonstration of that fact here : http://jsfiddle.net/t6z5324y/
var outsideVariable = 0;
console.log('start', outsideVariable);
function foo(insideVariable) {
console.log('before', insideVariable);
insideVariable = 1;
console.log('before', insideVariable);
}
foo(outsideVariable);
console.log('end', outsideVariable);
But you can pass an object as an argument, and modify a member of that object inside the function. The solution will then be:
var intervalHolder1 = {timer: null};
var intervalHolder2 = {timer: null};
function countdown(element, minutes, seconds, timerHolder) {
//stuff
clearInterval(timerHolder.timer);
timerHolder.timer = setInterval(function() {
//stuff
}, 1000);
}
function setCounter1(mins) {
countdown('timeLeft', mins, 00, intervalHolder1);
}
function setCounter2(mins) {
countdown('timeLeft2', mins, 00, intervalHolder2);
}
I would do it by defining an array of Interval outside (how many you need) and making your function pass the Index of the Interval rather then the interval itself.
var interval1;
var interval2;
var arrayInterval = [interval1, interval2];
function countdown(element, minutes, seconds, timerId) {
var el = document.getElementById(element);
clearInterval(arrayInterval[timerId]);
arrayInterval[timerId] = setInterval(function() {
if (seconds == 0) {
if (minutes == 0) {
(el.value = "---");
clearInterval(arrayInterval[timerId]);
return;
} else {
minutes--;
seconds = 60;
}
}
if (minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? '' : '';
el.value = minute_text + ' ' + seconds + ' ' + second_text + '';
seconds--;
}, 1000);
}
function setCounter1(mins) {
countdown('timeLeft', mins, 00, 0);
}
function setCounter2(mins) {
countdown('timeLeft2', mins, 00, 1);
}

clearInterval is not clearing

Take a look at the function below, It purpose is to change the button text
to "Abort", "Abort 0", "Abort 1" and so on.
Once the counter reaches 10 another function should be executed, but if
the button is clicked, the counter should stop, and the button text should return
to it's original value ("Sync DB").
It seems I'm trying to clear out the interval in a wrong way.
Any assistance will be appreciated.
function sync_database(abort)
{
if (abort == true) { sync_db_btn.innerHTML = "Sync DB"; return false }
sync_db_btn.innerHTML = "Abort"
var i = 0;
sync_db_btn.addEventListener("click", function() { sync_database(true) } );
var x = setInterval(function() {
if (abort == true) {
clearInterval(x);
}
if (i < 10) {
sync_db_btn.innerHTML = "Abort " + i++;
}
}, 1000);
}
var x;
sync_db_btn.addEventListener("click", function() {
sync_database(true);
clearInterval(x);
} );
function sync_database(abort)
{
if (abort == true) { sync_db_btn.innerHTML = "Sync DB"; return false }
sync_db_btn.innerHTML = "Abort"
var i = 0;
x = setInterval(function() {
if (i < 10) {
sync_db_btn.innerHTML = "Abort " + i++;
}
}, 1000);
}
I think you need something like this:
var sync_db_btn = document.getElementById('but'),
abortSync = -1,
interval,
sync_database = function () {
var i = 0;
abortSync *= -1;
if (abortSync < 0) {
sync_db_btn.innerHTML = 'Sync DB';
clearInterval(interval);
return false;
}
sync_db_btn.innerHTML = 'Abort';
interval = setInterval(function () {
if (i < 10) {
sync_db_btn.innerHTML = 'Abort ' + i++;
} else {
sync_db_btn.innerHTML = 'Sync DB';
clearInterval(interval);
abortSync = -1;
}
}, 1000);
};
sync_db_btn.addEventListener('click', sync_database);
A live demo at jsFiddle.

Categories