Pomodoro Timer: Variable value goes to 'NaN' - javascript

I'm trying to build a Pomodoro clock like http://codepen.io/GeoffStorbeck/full/RPbGxZ/. The value of seconds goes to NaN randomly and then returns to normal after starting 'break'.
$('#circle a').click(function() {
var timer = $('.time > span').html();
timer = timer.split(':');
var minutes = timer[0]; //Value of minutes
var seconds = timer[1]; //Value of seconds
var settimer = setInterval(function() {
seconds -= 1;
console.log(seconds);
if (seconds < 0 && minutes != 0) {
minutes -= 1;
minutes = String(minutes);
seconds = 59;
} else if (seconds < 10 && seconds.length != 2)
seconds = '0' + seconds;
if (minutes < 10 && minutes.length < 2)
minutes = '0' + minutes;
$('.time > span').html(minutes + ':' + seconds);
//Start break when session is completed
if (minutes == 0 && seconds == 0) {
$('.upper').find('h1').text('BREAK');
var time = $('#break').find('span').text();
$('.time > span').html('0' + time + ':00');
$('#circle a').trigger("click"); //Start timer for break
}
}, 1000);
});
Here's the link to the codepen
http://codepen.io/ibrahimjarif/pen/wMKJWN
How do I fix the NaN issue?
And is there any better way to implement this?

The code $('#circle a').trigger("click"); //Start timer for break recursively calls the function that was executing originally. This call starts a new timer while the original one was in progress.
The seconds value for the original timer went to NaN when the new timer was executing. There were two values for second due to two timers. The value of seconds in the original timer caused the unexplained appearance of NaN.
NOTE: Both the timers were running simultaneously all the time.
The simplest fix was to stop the current timer before starting a new one.
Here's the updated code
$('#circle a').click(function() {
var timer = $('.time > span').html().split(':');;
var minutes = Number(timer[0]),
seconds = Number(timer[1]);
var settimer = setInterval(function() {
seconds -= 1;
if (seconds < 0 && minutes != 0) {
minutes -= 1;
seconds = 59;
} else if (seconds < 10 && seconds.length != 2)
seconds = '0' + seconds;
if (minutes < 10 && minutes.toString().length < 2)
minutes = '0' + minutes;
$('.time > span').html(minutes + ':' + seconds);
if (minutes == 0 && seconds == 0) {
clearInterval(settimer); //Stop the current timer
var upper_text = $('.upper').find('h1');
var time;
if (upper_text.text() == 'BREAK') {
upper_text.text('Session');
time = $('#session').find('span').text();
} else {
upper_text.text('BREAK');
time = $('#break').find('span').text();
}
$('.time > span').html(time + ':00');
$('#circle a').trigger("click"); //Start new timer
}
}, 1000);
});

Related

How do I add clearInterval to my JS timer?

I've made a timer in JavaScript, but when the start button is repeatedly clicked it keeps getting faster. I know clearInterval is used to stop this, but depending on where I put it in the code it either stops the timer from working completely or makes no difference. This is the code, I put it on the fourth line but it's not doing anything:
var minutes;
var seconds;
function PomodoroBreak(x){
clearInterval(interval)
minutes = x;
seconds = 0;
var interval = setInterval(
function(){
var el = document.getElementById("timer")
if(seconds ==0 && minutes==0){
clearInterval(interval)
el.innerHTML = "00:00"
}
else if(seconds == 0){
minutes = minutes -1;
seconds = 59
el.innerHTML = minutes + ":" + seconds
}else if(seconds > 0){
seconds = seconds -1;
el.innerHTML = minutes + ":" + seconds
document.title = minutes + ":" + seconds
}
},
1000
)
}
Where am I supposed to put it instead, or have I done something else wrong? Thank you!
I'm seeing some adjustments to be done here. I believe returning clearInterval with the startTimer declared above should do the work.
Hope this helps.
function PomodoroBreak(x){
var minutes = x;
var seconds = 0;
let startTimer = setInterval(...,1000)
return clearInterval(startTimer)
}
I think you should declare the variable “interval“ outside the function. And remove the var in the function.
var minutes;
var seconds;
var interval;
function PomodoroBreak(x){
clearInterval(interval)
minutes = x;
seconds = 0;
interval = setInterval(
function(){
var el = document.getElementById("timer")
if(seconds ==0 && minutes==0){
clearInterval(interval)
el.innerHTML = "00:00"
}
else if(seconds == 0){
minutes = minutes -1;
seconds = 59
el.innerHTML = minutes + ":" + seconds
}else if(seconds > 0){
seconds = seconds -1;
el.innerHTML = minutes + ":" + seconds
document.title = minutes + ":" + seconds
}
},
1000
)
}

Enabling Button after certain time frame in Jquery html?

I want to enable button after certain time frame and again if I click on this button it should disable for this time frame .How to achieve this...
var timer2 = "00:30";
var interval = setInterval(function() {
var timer = timer2.split(':');
//by parsing integer, I avoid all extra string processing
var minutes = parseInt(timer[0], 10);
var seconds = parseInt(timer[1], 10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
//minutes = (minutes < 10) ? minutes : minutes;
$('.countdown').html(minutes + ':' + seconds);
timer2 = minutes + ':' + seconds;
}, 500);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="countdown"></div>
<button type="button" id="demo">click</button>
You can just wrap your code in a function and call that function on event click and at the beginning of your code run, and inside the function I added a check for the time to clear the interval and reset the timer, and using .setAttribute() and removeAttribute() to disable/enable the button:
function enableButton() {
var timer2 = "00:30";
var interval = setInterval(function() {
var timer = timer2.split(':');
//by parsing integer, I avoid all extra string processing
var minutes = parseInt(timer[0], 10);
var seconds = parseInt(timer[1], 10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
//minutes = (minutes < 10) ? minutes : minutes;
$('.countdown').html(minutes + ':' + seconds);
timer2 = minutes + ':' + seconds;
if( minutes === 0 && seconds === 0) {
clearInterval(interval);
document.getElementById('demo').removeAttribute('disabled');
}
else {
document.getElementById('demo').setAttribute('disabled', true);
}
}, 100);
}
document.getElementById('demo').addEventListener('click', function() {
enableButton();
});
enableButton();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="countdown"></div>
<button type="button" id="demo" disabled>click</button>

javascript timer keeps reseting too soon (not working)

// This timer keeps reseting back to 2:00 after it reaches 1 minute. Also i do not get a notification that says times up at the right time. Can someone please correct the code. Also the stop/resume timer button also has to stay functional.
var isRunning = false;
var ticker; //this will hold our setTimeout
var seconds,
minutes;
function countdown(mins, secs) {
//i made these global, so we can restart the timer later
seconds = secs || 60; //if user put in a number of minutes, use that. Otherwise, use 60
minutes = mins;
console.log('time stuff',mins,secs,minutes,seconds)
function tick() {
var counter = document.getElementById("timer");
var current_minutes = mins - 1
seconds--;
counter.innerHTML =
current_minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
if (seconds < 1 && minutes) {
//seconds reached 0, and still minutes left;
seconds=60;
minutes--;
}
if ((seconds > 0 || minutes > 0) && isRunning) {
ticker = setTimeout(tick, 1000);
} else if(isRunning){
console.log(seconds,minutes,isRunning)
alert('Time\'s up, brah!')
}
}
tick();
}
function timeToggle() {
isRunning = !isRunning; //if it's false, set it true. If it's true, set it false.
if (!isRunning) {
clearTimeout(ticker); //or whatever else you set the initial timeOut to.
} else {
//not running! and time is defined;
var sec = seconds||60;
console.log('def!',minutes, sec)
countdown(minutes, sec);
}
}
isRunning = true;
countdown(2);
<div id="timer">2:00</div>
<button onclick="timeToggle()">Stop time</button>
There is a small flaw in your logic.
During the countdown initialization your doing
seconds = secs || 60;
Which effectively add 60 seconds to the time you want if you don't initialize the seconds. see:
function countdownInit(mins, secs) {
seconds = secs || 60;
minutes = mins;
console.log(mins + 'min ' + seconds + 'sec');
}
countdownInit(1, 30) // ok
// 1min 30sec
countdownInit(1) // not ok
// 1min 60sec
// thats 2 minutes
The second issue here is that you use a var current_minutes that equals minutes - 1 to display the time. So you are not showing the real counter.
the fix is as follow:
function countdown(mins, secs) {
seconds = secs;
minutes = mins;
// if secs is 0 or uninitialized we set seconds to 60 and decrement the minutes
if(!secs) {
minutes--;
seconds = 60;
}
function tick() {
var counter = document.getElementById("timer");
seconds--;
// we use minutes instead of current_minutes in order to show what's really in our variables
counter.innerHTML =
minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
// rest of code
}
// rest of code
}
I tried to keep as much as your code as possible.

javascript/jquery countdown timer with JSfiddle example?

I am building a few things and one of them is a countdown timer, the countdown will never be over an hour so all I need to do is countdown minutes and seconds.
I have it partially working, but the problem is with the leading zeros. I got it to work in the seconds but not with the minutes.
Check out my example http://jsfiddle.net/cgweb87/GHNtk/
JavaScript
setInterval(function() {
var timer = $('span').html();
timer = timer.split(':');
var minutes = timer[0];
var seconds = timer[1];
seconds -= 1;
if (minutes < 0) return;
if (minutes < 10 && length.minutes != 2) minutes = '0' + minutes;
if (seconds < 0 && minutes != 0) {
minutes -= 1;
seconds = 59;
}
else if (seconds < 10 && length.seconds != 2) seconds = '0' + seconds;
$('span').html(minutes + ':' + seconds);
}, 1000);
HTML
<span>10:10</span>
What I want to happen is the countdown timer can begin anywhere under 1 hour, it will count down with leading zeros ie in this format;
08:49
46:09
And when it reaches the countdown to simply just display:
00:00
Thanks for any input, and I don't want to use plugins, I want to learn it.
setInterval returns an identity you can use later to clearInterval:
var interval = setInterval(function() {
/* snip */
$('span').html(minutes + ':' + seconds);
if (parseInt(minutes, 10) == 0 && parseInt(seconds, 10) == 0)
clearInterval(interval);
}, 1000);
And, to avoid the ever-increasing minutes -- 00000001:42 -- either:
change length.minutes to minutes.length in your prefix test.
cast the values to Numbers when retrieving -- var minutes = parseInt(timer[0], 10); -- and just test if (minutes < 10) ....
Taking option #2, here's an update: http://jsfiddle.net/BH8q9/
to check the length of a string, it is not
length.minutes
length.seconds
it is
minutes.length
seconds.length
Made a few simple changes to your code and it works as you'd like:
setInterval(function() {
var timer = $('span').html();
timer = timer.split(':');
var minutes = timer[0];
var seconds = timer[1];
seconds -= 1;
if (minutes < 0) return;
if (seconds < 0 && minutes != 0) {
minutes -= 1;
seconds = 59;
}
else if (seconds < 10 && length.seconds != 2) seconds = '0' + seconds;
if ((minutes < 10) && ((minutes+'').length < 2)) minutes = '0' + minutes;
$('span').html(minutes + ':' + seconds);
}, 1000);
I moved the if ((minutes < 10).... line down to happen after the minutes -= 1; otherwise at 9:59, you won't get the extra 0. Also length.minutes is the wrong way around, it'd need to be minutes.length -- but to make sure it's being treated as a string (which has a length, whereas a number doesn't), I added a blank string to it and then took the length of that.. This is what ((minutes+'').length < 2 does (checks that you have the leading zero).. This is really the best way to accomplish it, but it's the closest to your existing code.
I understand that an answer has already being accepted but would like to throw in my 2c: I like to avoid extra coding whenever possible. Using Jonathan Lonowski's approach, I would improve it like:
var interval = setInterval(function() {
var timer = $('span').html().split(':');
//by parsing integer, I avoid all extra string processing
var minutes = parseInt(timer[0],10);
var seconds = parseInt(timer[1],10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
seconds = (seconds < 10) ? '0' + seconds : seconds;
minutes = (minutes < 10) ? '0' + minutes : minutes;
$('span').html(minutes + ':' + seconds);
}, 1000);

Using JQuery replaceWith with a JavaScript Variable

Here's my html:
<div class="timer">Not Started</div>
And JS/JQ:
var seconds = 10;
var minutes = 0;
setTimeout("updateTimer()", 1000);
function updateTimer() {
if (seconds == 0 && minutes != 0) {
minutes -= minutes;
seconds = 59;
alert (seconds);
} else if (seconds == 1 && minutes == 0) {
alert ('done');
} else {
seconds = seconds - 1;
//alert (seconds);
$(".timer").replaceWith(seconds);
}
setTimeout("updateTimer()", 1000);
}
Instead of replacing Not Started with 10, 9, 8..., Not Started disappears.
$(".timer").text(seconds);
You can't replace a DOM node with a string.
See an example.
You could simplify your logic further by making use of setInterval instead of setTimeout, and use total seconds for easier calculations and remove minutes.
var seconds = 10, minutes = 0;
var totalSeconds = (minutes * 60) + seconds;
var timerId = setInterval(updateTimer, 1000);
function updateTimer() {
$('.timer').text(totalSeconds % 60);
if (totalSeconds == 0) {
alert("done");
clearInterval(timerId);
}
totalSeconds--;
}
replaceWith will replace the entire div, not just the contents. Try this instead:
$(".timer").html(seconds);

Categories