Unable to cancel setInterval - javascript

I am making a Javascript timed quiz with 10 questions to be answered in 60 seconds. It works fine if the contestant attempts the question in 50 to 60 seconds, but if he does it in a shorter time and restarts the quiz the timer runs at double the speed. Possibly the earlier timer isn't getting cleared. Here is the script:
$(window).ready(function() {
$('#fblock').hide();
$('#sblock').show();
$('#qblock').hide();
$('.startquiz').click(function() {
qsi = 0;
score = 0;
showq(0);
$('#fblock').hide();
$('#sblock').hide();
$('#qblock').show();
var secs = 0;
var id = setInterval(function() {
secs++;
console.log(secs);
document.getElementById("timer").innerHTML++;
if (secs > 60) {
clearInterval(id);
$('#result').html(score);
$('#qblock').hide();
$('#fblock').show();
}
}, 1000);
});
$('.restartquiz').click(function() {
$('#fblock').hide();
$('#sblock').show();
$('#qblock').hide();
document.getElementById("timer").innerHTML = 0;
});
});

For me it looks like the only time the interval gets canceled is, when the "timer" (secs) actually exeeds the number of 60.
The doubled speed could be explained by secs++ which (after restarting the quiz) gets executed two times (once per started interval).
Try canceling the interval in the function that gets executed when pressing the .restartquiz-Button.
This could look like something like that (untested):
var interval = null;
$(window).ready(function() {
$('#fblock').hide();
$('#sblock').show();
$('#qblock').hide();
$('.startquiz').click(function() {
qsi = 0;
score = 0;
showq(0);
$('#fblock').hide();
$('#sblock').hide();
$('#qblock').show();
var secs = 0;
interval = setInterval(function() {
secs++;
console.log(secs);
document.getElementById("timer").innerHTML++;
if (secs > 60) {
clearInterval(interval);
$('#result').html(score);
$('#qblock').hide();
$('#fblock').show();
}
}, 1000);
});
$('.restartquiz').click(function() {
$('#fblock').hide();
$('#sblock').show();
$('#qblock').hide();
clearInterval(interval);
document.getElementById("timer").innerHTML = 0;
});
});

Related

Why is my interval calling my function even though its in a variable?

I have a stopwatch that has buttons to start, stop, and reset the time. I assigned an interval to a variable to pause it using clearInterval every time I click the stop button, but my interval is calling the function even though I clicked no button. How do I fix this?
const startButton = document.getElementById('start');
const stopButton = document.getElementById('stop');
const resetButton = document.getElementById('reset');
const myInterval = setInterval(setTime, 10);
startButton.addEventListener('click', () => {
setInterval(setTime, 10);
})
stopButton.addEventListener('click', ()=> {
clearInterval(myInterval);
})
const timeUnits = ['00', '00', '00', '00'];
milliSeconds = 0;
seconds = 0;
minutes = 0;
hours = 0;
function setTime() {
if (minutes == 60) {
hours++;
minutes = 0;
timeUnits[0] = hours;
timeUnits[1] = 0;
} else if (seconds == 60) {
minutes++;
seconds = 0;
timeUnits[1] = minutes;
timeUnits[3] = 0;
} else if (milliSeconds == 100) {
seconds++;
milliSeconds = 0;
timeUnits[2] = seconds
timeUnits[3] = 0;
document.getElementById('para').innerHTML = timeUnits.join(':');
} else {
milliSeconds++;
timeUnits[3] = milliSeconds;
document.getElementById('para').innerHTML = timeUnits.join(':');
};
}
<p id="para">00:00:00:00</p>
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="reset">Reset</button>
You set up the interval in two places:
const myInterval = setInterval(setTime, 10); // <-- Here (A)
startButton.addEventListener('click', () => {
setInterval(setTime, 10); // <-- and here (B)
})
In spot A (auto-start on page load) you save the interval ID into myInterval so that you can later do clearInterval(myInterval).
However, in spot B (on-demand start on "start" button click), you do not do that, so the interval set by clicking the "start" button can never be cleared.
This can be fixed by saving the interval into myInterval in both places:
let myInterval = setInterval(setTime, 10)
startButton.addEventListener('click', () => {
myInterval = setInterval(setTime, 10)
})
Now, this created a bit of duplicate code, which is not ideal, and also there is still the problem that just clicking "start" multiple times would create multiple intervals running in parallel, overwriting the previous interval ID with the new one, making the old intervals again unclearable.
My suggestion for solving both of these issues is to create functions startInterval and stopInterval, where startInterval would also first call stopInterval before setting up a new interval, and stopInterval clearing the old one if it exists. Then you can call startInterval both on page load and on "start" button click, and stopInterval on "stop" button click:
let myInterval = null
function startInterval () {
stopInterval()
myInterval = setInterval(setTime, 10)
}
function stopInterval () {
if (!myInterval) return
clearInterval(myInterval)
myInterval = null
}
startInterval()
startButton.addEventListener('click', startInterval)
stopButton.addEventListener('click', stopInterval)
From the wording of the question I'm not sure whether you really want to auto-start the timer though. In case you don't, you can simply remove the startInterval() line from my example (or in case of the original code, change the first assignment to let myInterval = null like in the second example).
This line:
const myInterval = setInterval(setTime, 10);
actually starts the interval.
You need to change it to this:
let myInterval;
startButton.addEventListener('click', () => {
myInterval = setInterval(setTime, 10);
})
This ensures that everytime you press the start button the interval will be assigned to the myInterval variable again which can then be cleared by the stop button

I want the timer to begin counting down from 30 minutes immediately on page load and loop forever

For my site, I want the timer to begin counting down from 30 minutes immediately on page load and loop forever (until the user closes the page).
At the end of every 30 minute cycle, an alarm will go off. I have an mp3 file I will use. The alarm goes off, then the 30 minutes start again.
// I did it to solve the problem... Thanks all
window.loopingInterval = 30;
setInterval(loopingTimerMethod, 1000);
window.secondStart = 60;
window.loopingMinutes = loopingInterval - 1;
window.loopingSecond = secondStart;
function loopingStartTime(tim) {
var i = tim - 1;
return i;
}
function loopingTimerMethod()
{
loopingSecond = loopingStartTime(loopingSecond);
document.getElementById("timer-minutes").innerHTML = timeWithZero(loopingMinutes);
document.getElementById("timer-second").innerHTML = timeWithZero(loopingSecond);
if (loopingSecond == 0) {
if (loopingMinutes == 0 && loopingSecond == 0) {
var x = document.getElementById("myLoopingAudioPlayer");
LoopingPlayAudio(x);
window.loopingMinutes = loopingInterval;
}
loopingMinutes = loopingMinutes - 1;
loopingSecond = secondStart;
}
}
function LoopingPlayAudio(x) {
x.play();
}
function LoopingPauseAudio(x) {
x.pause();
}
function timeWithZero(i) {
if (i < 10) {
i = "0" + i
}
; // add zero in front of numbers < 10
return i;
}
/*END Timer Looping functionality*/

timer with delay, reset and restart? jQuery

So I basically have a timer which counts 1 number every 4 seconds.
It stops when it hits 10.
Q: How do i make it so that the timer stops at 10 for a couple of seconds, then starts counting again at 1?
var i = 8;
setInterval( increment, 4000);
function increment(){
if(i<=10)
{
console.log(i);
$('.increase').html('').append(i);
i++;
}
}
JSfiddle: http://jsfiddle.net/0t3s8erj/
Use the else!
var counter = 0
function increment () {
counter++
if (counter <= 10) {
console.log(counter)
} else {
clearInterval(incrementInterval)
setTimeout(function () {
incrementInterval = setInterval(increment, 4000)
}, 10000)
}
}
incrementInterval = setInterval(increment, 4000)
You can do it like this where you run an interval timer until you get to the max count, then you clear that timer and start a new timer for the amount of time you want to pause and then when that delay timer fires, you call your function again to start it all over.
Here's a working code snippet (I set the times short here for demo purposes, but you can set them to whatever you want):
function runTimer(selector, start, end, interval, delay) {
var cntr = start;
$(selector).html(cntr);
var timer = setInterval(function() {
++cntr;
$(selector).html(cntr);
if (cntr >= end) {
clearInterval(timer);
setTimeout(function() {
runTimer(selector, 1, end, interval, delay);
}, delay);
}
}, interval);
}
runTimer('.increase', 8, 10, 300, 2000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="increase">8</span>/10

How to speed up the count down?

I am working on a basic countdown using Javascript where, the countdown starts from 0 and then ends till 24 as thats the idea of the countdown, I want to end it at 24. Here's the code:
var count=0;
var counter=setInterval(timer, 50); //1000 will run it every 1 second
function timer()
{
count=count+1;
if (count >= 24)
{
clearInterval(counter);
//counter ended, do something here
document.getElementById("countdown").innerHTML=24 ;
return;
}
//Do code for showing the number of seconds here
document.getElementById("countdown").innerHTML=count ; // watch for spelling
}
Now the thing is that if you notice this, the countdown happens very fast, this is the intended effect. However the question is this, Is there a way to have a smooth easing type effect, where the countdown starts slowly and then speeds up by the end ? How to achieve that effect ?
Thanks for your response.
EDIT: Here is the fiddle, to see the countdown in action and to gain a deeper insight.
You'll need to use setTimeout instead of setInterval and another variable for setTimeout.
var count=0;
var speed = 1000;
timer();
function timer()
{
count++;
//Do code for showing the number of seconds here
document.getElementById("countdown").innerHTML=count ; // watch for spelling
if (count >= 24)
{
return;
}
speed = speed / 6 * 5; // or whatever
setTimeout(timer, speed);
}
Fiddle: http://jsfiddle.net/4nnms1gz/2/
Use a timeout which runs only once then add extra time and run the timeout again until you reach 24.
var count=0;
var ms = 200;
var step = 5;
var counter=setTimeout(timer, ms); //1000 will run it every 1 second
function timer()
{
count=count+1;
if (count <= 24)
{
//Do code for showing the number of seconds here
document.getElementById("countdown").innerHTML=count ; // watch for spelling
ms = ms - step;
counter = setTimeout(timer, ms);
}
}
Using setTimeout will give you more control on your counter.Here is a working example where you can handle the speed of your counter.It will give you a time increase of 30ms to 70ms to each call to time function
var count=0;
var loop=1000;
var interval;
var text=document.getElementById('countdown');
var range=document.getElementById('range');
var btn=document.getElementById('btn');
var span=document.getElementById('val');
range.addEventListener('change',function(e){
span.innerHTML=range.value+' ms';
});
btn.addEventListener('click',function(e){
timer(parseInt(range.value));
});
function timer(time)
{
console.log(time);
if (count < 24)
{
count=count+1;
text.value=count;
loop-=time;
interval=setTimeout(function(){
timer(time);
},loop);
if(count>=24){
clearTimeout(interval);
return;
}
}
}
<input type='text' id='countdown' value='0'></br>
<input type='range' id='range' max='70' min='30' value='30' >increase by:<span id='val'></span></br>
<input type='button' value='start' id='btn' ></br>

Timer counting faster on second run

I am working on a simple game right now. its almost done except for the timer has a glitch in it and I can't figure out whats doing it. when you push a button, an HTML5 text on the canvas starts to count down from 35 to 0. On the first run it's fine. But if you choose to play again with out refresh the timer starts to countdown faster. here is the code.
var timer = 35;
ctx.fillText("Countdown: " + timer, 320, 32);
function resetReggie(){
reggie.x = canvasWidth / 2;
reggie.y = canvasHeight / 2;
}
//Starts Timer for Timed Game
function timedMsg()
{
resetReggie();
ballsCaught = 0;
timer = 35;
alert('Pick up as many as you can in ' + timer + ' seconds');
countDown();
var t=setTimeout(function() {
var again = confirm("TIMES UP! You Gathered " + ballsCaught + " Balls! Play Again?");
if (again === true){
timedMsg();
resetReggie();
}
if (again === false){
resetReggie();
ballsCaught = 0;
timer = 35;
}
}, timer * 1000);
}
function countDown() {
if (timer != 0){
timer-=1;
setTimeout('countDown()', 1000);
}
}
I think the problem is in the line
}, timer * 1000);
where you have a value that is at most 34 at the time 'timer' is evaluated to set the timeout. Because you initialize it to 35 but then call countDown() which decreases it to 34, then you have a call to confirm() which might let 'timer' decrease even more. As a result the subsequent call to timedMsg() happens a little too soon causing countDown() to be called twice as often. Try the following (I ran it in node) and then change the 4 to 6.
function countDown() {
console.log("Countdown: " + timer, 320, 32);
if (timer != 0) {
timer -= 1;
setTimeout(countDown, 1000);
}
}
function timedMsg() {
timer = 5;
countDown();
var t=setTimeout(function() {
timedMsg();
}, 4 * 1000);
}
timedMsg();
As mentioned in my comment, each time you start a new game, it appears you are decreasing the timeout value. As a result, this reduces the time each time.
Try this:
var timeout = currentTime = 5;
var int = setInterval(function() {
​console.log(currentTime);
currentTime--;
if(currentTime < 0) {
var again = confirm('Play again?');
if(again) {
currentTime = timeout;
}
else {
clearInterval(int);
}
}
}, 1000);​
http://jsfiddle.net/gRoberts/CsyYx/
Look at your console (F12 in Chrome), or update the code to write to the browser to see it working ;)

Categories

Resources