Reputation: 97
I have this web page with a textarea
and 3 buttons
. The textarea
receives a number. The first button
starts the coutdown from the number to 0, with a delayed output (one number per second, so if N is 10 it'll take 10 seconds). The second button
pauses the countdown, and the third button
resumes it (without starting over). Pressing the first button
at any time during the execution restarts the coutdown with whatever number is in the textarea
. This is the code I have so far:
<!DOCTYPE html>
<html>
<body>
<h2>Insert a number:</h2>
<textarea id="input"></textarea>
<br/>
<button id="start" onclick="begin()">BEGIN</button>
<button id="pause" onclick="pause()">PAUSE</button>
<button id="resume" onclick="resume()">RESUME</button>
<h1 id="result"></h1>
<script>
var isCounting=true,
input=document.getElementById("input"),
countSec;
function begin() {
countSec=input.value;
if (isNaN(countSec)) alert("NaN");
count();
}
function pause() {
isCounting=false;
}
function resume() {
isCounting=true;
count();
}
function count() {
var i,
bck=countSec;
for (i=0; i<=bck; i++) {
document.getElementById("result").innerHTML=countSec;
countSec--;
}
}
</script>
</body>
</html>
Is there a way to stop the execution for 1 second after countSec--
? I've been trying for 2 hours to do something with Date objects and setTimeout but I just can't figure out how to pause after every for
iteration
Upvotes: 2
Views: 1306
Reputation: 15827
Here is an option:
<script>
var input=document.getElementById("input"),
countSec,
timer = null;
function begin() {
countSec=input.value;
if (isNaN(countSec)) alert("NaN");
if( timer === null ) {
timer = setTimeout( count, 1000 );
}
}
function pause() {
clearTimeout( timer );
timer = null;
}
function resume() {
if( timer === null ) {
timer = setTimeout( count, 1000 );
}
}
function count() {
if( countSec > 0 ) {
countSec--;
}
document.getElementById("result").innerHTML = countSec;
if( countSec > 0 ) {
timer = setTimeout( count, 1000 );
}
}
</script>
As begin
is called it sets a timer on count
after 1 second.
When later count
is invoked it decreases the counter, updates the html and schedules itself to be recalled after 1 second with setTimeout()
(unless -of course- the counter reached zero)
The scheduled task is stored into timer
so it can be canceled with clearTimeout()
(see pause()
)
To resume the countdown just call count()
again.
timer
is set to null
when the counter is not running and is checked before starting it to ensure only one counter is running.
Upvotes: 1
Reputation: 278
What you want is for your count
function to contain a self invoking timer, like this:
var timer;
function count() {
var result = document.getElementById("result");
step();
function step() {
result.innerHTML=countSec;
countSec--;
if (countSec > 0) {
timer = setTimeout(step, 1000);
}
}
}
But know that the timeout doesn't really count 1000ms. If you want to be accurate you'll have to compare to the time where it all began. and lower the interval:
var timer,
start,
moment,
input = document.getElementById("input"),
result = document.getElementById("result");
function begin() {
var from = ((parseInt(input.value) + 1) * 1000);
start = Date.now() + from;
setTimeout(count, 40);
}
function pause() {
clearTimeout(timer);
}
function resume() {
start = Date.now() + (moment * 1000);
count();
}
function count() {
moment = parseInt((start - Date.now()) / 1000);
result.innerHTML = moment;
if (moment > 0) {
timer = setTimeout(count, 200);
}
}
Upvotes: 1
Reputation: 1930
Heres another solution
<!DOCTYPE html>
<html>
<body>
<h2>Insert a number:</h2>
<textarea id="input"></textarea>
<br/>
<button id="start" onclick="begin()">BEGIN</button>
<button id="pause" onclick="pause()">PAUSE</button>
<button id="resume" onclick="resume()">RESUME</button>
<h1 id="result"></h1>
<script>
let isCounting = true;
let input = document.getElementById("input");
let countSec = 0;
let countDownInterval = false;
function begin() {
countSec = input.value;
if (isNaN(countSec)) alert("NaN");
count();
}
function pause() {
isCounting = false;
}
function resume() {
isCounting = true;
}
function count() {
// Let's check we're doing a restart
if (countDownInterval) {
clearInterval(countDownInterval);
}
countDownInterval = setInterval(function() {
if (isCounting) {
document.getElementById("result").innerHTML = countSec;
countSec -= 1;
// Times up ??
if (countSec == -1) {
clearInterval(countDownInterval);
countDownInterval = null;
}
}
}, 1000);
}
</script>
</body>
</html>
Upvotes: 0
Reputation: 386578
You could use setInterval
, an intervalID and clearInterval
, when the count reaches zero.
var isCounting = true,
input = document.getElementById("input"),
countSec,
intervalID;
function begin() {
countSec = +input.value;
if (isNaN(countSec)) {
alert("NaN");
return;
}
document.getElementById("result").innerHTML = countSec;
intervalID = setInterval(count, 1000);
}
function pause() {
isCounting = false;
}
function resume() {
isCounting = true;
}
function count() {
if (countSec === 0) {
clearInterval(intervalID);
return;
}
if (isCounting) {
countSec--;
document.getElementById("result").innerHTML = countSec;
}
}
<h2>Insert a number:</h2>
<textarea id="input"></textarea><br/>
<button id="start" onclick="begin()">BEGIN</button>
<button id="pause" onclick="pause()">PAUSE</button>
<button id="resume" onclick="resume()">RESUME</button>
<h1 id="result"></h1>
Upvotes: 0
Reputation: 55740
I think most of the solutions have already answered your question. It is a better idea to involve interval operations in your solution as that is more apt and JS already provides it.
HTML
<h2>Insert a number:</h2>
<textarea id="input"></textarea>
<br/>
<button id="start">BEGIN</button>
<button id="pause">PAUSE</button>
<button id="resume">RESUME</button>
<h1 id="result"></h1>
JS
// Bind the click events
document.getElementById('start').addEventListener('click', begin);
document.getElementById('pause').addEventListener('click', pause);
document.getElementById('resume').addEventListener('click', resume);
var input = document.getElementById("input");
var countSec;
var timer;
function begin() {
debugger;
countSec = input.value;
if (isNaN(countSec)) alert("NaN");
count();
enableTimer();
}
function pause() {
clearInterval(timer);
}
function resume() {
enableTimer();
}
function count() {
if (countSec >= 0) {
document.getElementById("result").innerHTML = countSec;
} else {
clearInterval(timer);
}
countSec--;
}
// enable the timer again
function enableTimer() {
timer = setInterval(function() {
count();
}, 1000);
}
Upvotes: 1
Reputation: 8876
This sounds like the perfect scenario to implement Javascript's built-in asynchronous interval operations.
Your timer should center around setInterval
( https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval ). Basically, you'll set up your interval to fire every second, which will increment your counter.
To pause your countdown, you'll want to use clearInterval
( https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearInterval ). You can also use the intervalID to determine whether the setInterval timer is running or not.
These building blocks should get you going. If you require more information, just ask.
Upvotes: 1
Reputation: 2590
If you need a delay between each subtraction of countSec, then I recommend you use the setInterval
function. I've modified your code as follows:
var isCounting=true,
input=document.getElementById("input"),
countSec
interval;
function begin() {
countSec=input.value;
if (isNaN(countSec)) alert("NaN");
count();
}
function pause() {
isCounting=false;
clearInterval(interval);
}
function resume() {
isCounting=true;
count();
}
function count() {
var i,
bck=countSec;
document.getElementById("result").innerHTML=bck;
interval = setInterval(function() {
countSec--;
document.getElementById("result").innerHTML=countSec;
}, 1000);
}
Specifically, I created a global interval
variable, which will keep a reference to the interval. I set the interval in count(), and then I update the #result
ID at every tick of the interval (which has a delay of 1000ms). To pause, I clear the interval. I left a lot of your code in tact even though some of it isn't being used (like isCounting);
Here's the code in action: https://jsfiddle.net/exex7jh0/
Upvotes: 1