Forum Moderators: open

Message Too Old, No Replies

Javascript timer

countdown from 60 seconds to 0 and display message

         

Adam5000

4:24 pm on May 24, 2007 (gmt 0)

10+ Year Member



Hello Dr Doc and everyone.

I'm trying to make a simple javascript timer. I did it once before and I can't remember how. Somehow it involved the setTimeout command and the clearTimeout command, but I can't remember how I did it.

What I'm trying to do is display a timer on the screen that starts at 60 seconds. And then create a function, when called, will start a countdown from 60 seconds to zero. Then, when it gets to zero, display a message that reads something like "Time has ended." Help!

Dabrowski

4:49 pm on May 24, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This sounds like an idea use for my progress bar!

Try this code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>

<head>
<title>Test Page</title>
<style>

* { font-family: "Arial", sans-serif; }

#wrap { margin-top: 50px;text-align: center; }

#barwrap {
position: relative; /* to contain outer */
margin: 0 auto; /* to centre */
width: 250px;height: 20px; /* size of our bar - required */
text-align: left;
font-weight: bold;
border: 1px solid black;
}

#barwrap P { /* to contain text */
margin: 0; /* FF needs this or text drops below bar */
width: 250px; /* use this node to position text */
text-align: center;
}

#barwrap #outer { /* bar 'background' */
position: absolute;
width: 100%; height: 100%; /* match parent size */
background: lightgreen;
color: green; /* original colour of text */
}

#barwrap #inner {
position: relative; /* otherwise outer hides us */
width: 0; height: 100%; /* match parent */
overflow: hidden; /* to hide new text/prevent it wrapping */
background: green;
color: lightgreen; /* colour of changed text */
}

</style>

<script>

var time = 10000; // 10 secs
var steps = 50; // Five per second
var step = 1;

function progress() {
var bar = document.getElementById( "barwrap");
var aStep = (bar.offsetWidth -2) /steps;// 2px border removed from width
var x = Math.round( aStep *step);
var outer = document.getElementById( "outer");
var inner = document.getElementById( "inner");

// Work out seconds based on % progress from current step
var secs = (( time /1000) -Math.floor( ( step /steps) *10));

inner.style.width = x +"px";
step++;

// If 0 seconds, display waiting message instead
outer.firstChild.innerHTML = ( secs? secs +" seconds...": "Please Wait...");
// Match text
inner.firstChild.innerHTML = outer.firstChild.innerHTML;

if( step > steps) redir();
else setTimeout( "progress();", time /steps);
}

function redir() {
alert( "Redirecting now!");
}

</script>
</head>

<body>

<div id='wrap'>
Progress:
<div id='barwrap'> <!-- P wrappers for text positioning -->
<div id='outer'><p></p></div> <!-- original colour/text -->
<div id='inner'><p></p></div> <!-- new colour/text -->
</div>

<br>
<a href='#' onClick='progress();'>Click here to start bar (only once please, you'll break it)</a>
</div>

</body>

</html>

Fotiman

5:27 pm on May 24, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Here's one way you could do it:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset:utf-8">
<title>Countdown Timer</title>
<script type="text/javascript">
var CountdownTimer = function() {
this.s = null; // The seconds left in the timer
this.reset = null; // The seconds to reset the timer to
this.el = null; // The element container used to draw the timer
this.timerId = null; // The timerId as provided by setTimeout
return {
/**
* Initialize the timer with the number of seconds and the element that
* will be used to draw the timer.
* @param {Integer} s The number of seconds in the timer
* @param {HTMLElement} el The element whose contents will be replaced
*/
init : function(s, el) {
CountdownTimer.s = s;
CountdownTimer.reset = s;
CountdownTimer.el = document.getElementById(el);
},
/**
* Draw the timer and then start the countdown
*/
start : function() {
CountdownTimer.draw();
if (CountdownTimer.s > 0) {
CountdownTimer.timerId = setTimeout(CountdownTimer.step, 1000);
}
},
/**
* If the counter is counting down, stop it
*/
stop : function() {
if(CountdownTimer.timerId) {
clearTimeout(CountdownTimer.timerId);
}
},
/**
* Stop the counter if it's counting down, then reset to the initialized
* value, and redraw the timer.
*/
resetTimer : function() {
if(CountdownTimer.timerId) {
CountdownTimer.stop();
}
CountdownTimer.s = CountdownTimer.reset;
CountdownTimer.draw();
},
/**
* If the timer has reached zero, notify the user. Otherwise, decrement
* it, draw it, and call this method again in 1 second.
*/
step : function() {
if (CountdownTimer.s > 0) {
CountdownTimer.s--;
CountdownTimer.draw();
CountdownTimer.timerId = setTimeout(CountdownTimer.step, 1000);
}
else {
alert("Time's up!");
}
},
/**
* Draw the value of the timer in the container element.
*/
draw : function() {
CountdownTimer.el.innerHTML = CountdownTimer.s;
}
};
}();
window.onload = function() {
CountdownTimer.init(60,'countdown');
CountdownTimer.start();
document.getElementById("stopClock").onclick = function() {
CountdownTimer.stop();
};
document.getElementById("startClock").onclick = function() {
CountdownTimer.start();
};
document.getElementById("resetClock").onclick = function() {
CountdownTimer.resetTimer();
};
}
</script>
</head>
<body>
<div id="countdown"></div>
<input type="button" id="stopClock" value="Stop Timer">
<input type="button" id="startClock" value="Start Timer">
<input type="button" id="resetClock" value="Reset Timer">
</body>
</html>

Fotiman

5:44 pm on May 24, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I made a minor tweak in the start method. This will prevent you from being able to "start" the timer more than once:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset:utf-8">
<title>Countdown Timer</title>
<script type="text/javascript">
var CountdownTimer = function() {
this.s = null; // The seconds left in the timer
this.reset = null; // The seconds to reset the timer to
this.el = null; // The element container used to draw the timer
this.timerId = null; // The timerId as provided by setTimeout
return {
/**
* Initialize the timer with the number of seconds and the element that
* will be used to draw the timer.
* @param {Integer} s The number of seconds in the timer
* @param {HTMLElement} el The element whose contents will be replaced
*/
init : function(s, el) {
CountdownTimer.s = s;
CountdownTimer.reset = s;
CountdownTimer.el = document.getElementById(el);
},
/**
* Draw the timer and then start the countdown
*/
start : function() {
CountdownTimer.draw();
if (CountdownTimer.s > 0 &&!CountdownTimer.timerId) {
CountdownTimer.timerId = setTimeout(CountdownTimer.step, 1000);
}
},
/**
* If the counter is counting down, stop it
*/
stop : function() {
if(CountdownTimer.timerId) {
clearTimeout(CountdownTimer.timerId);
}
},
/**
* Stop the counter if it's counting down, then reset to the initialized
* value, and redraw the timer.
*/
resetTimer : function() {
if(CountdownTimer.timerId) {
CountdownTimer.stop();
}
CountdownTimer.s = CountdownTimer.reset;
CountdownTimer.draw();
},
/**
* If the timer has reached zero, notify the user. Otherwise, decrement
* it, draw it, and call this method again in 1 second.
*/
step : function() {
if (CountdownTimer.s > 0) {
CountdownTimer.s--;
CountdownTimer.draw();
CountdownTimer.timerId = setTimeout(CountdownTimer.step, 1000);
}
else {
alert("Time's up!");
}
},
/**
* Draw the value of the timer in the container element.
*/
draw : function() {
CountdownTimer.el.innerHTML = CountdownTimer.s;
}
};
}();
window.onload = function() {
CountdownTimer.init(60,'countdown');
CountdownTimer.start();
document.getElementById("stopClock").onclick = function() {
CountdownTimer.stop();
};
document.getElementById("startClock").onclick = function() {
CountdownTimer.start();
};
document.getElementById("resetClock").onclick = function() {
CountdownTimer.resetTimer();
};
}
</script>
</head>
<body>
<div id="countdown"></div>
<input type="button" id="stopClock" value="Stop Timer">
<input type="button" id="startClock" value="Start Timer">
<input type="button" id="resetClock" value="Reset Timer">
</body>
</html>

Adam5000

7:15 pm on May 24, 2007 (gmt 0)

10+ Year Member



Dab Foti

Dab. That progress bar looks great. It has definite applications. The message pops up at the end just like I wanted it too.

Foti. You're looks good too. I'm having to work with it a bit though. For some reason I can't get the display on the screen. But the code looks great and I like the idea of being able to start it only once.

Fotiman

7:25 pm on May 24, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Here's another small bug fix so you can resart it once it's been stopped. Also fixed a mistake in the comments for init.

Also, what part are you having problems with? This should work if you just cut and paste it.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset:utf-8">
<title>Countdown Timer</title>
<script type="text/javascript">
var CountdownTimer = function() {
this.s = null; // The seconds left in the timer
this.reset = null; // The seconds to reset the timer to
this.el = null; // The element container used to draw the timer
this.timerId = null; // The timerId as provided by setTimeout
return {
/**
* Initialize the timer with the number of seconds and the element that
* will be used to draw the timer.
* @param {Integer} s The number of seconds in the timer
* @param {String} el The id of the element whose contents will be replaced
*/
init : function(s, el) {
CountdownTimer.s = s;
CountdownTimer.reset = s;
CountdownTimer.el = document.getElementById(el);
},
/**
* Draw the timer and then start the countdown
*/
start : function() {
CountdownTimer.draw();
if (CountdownTimer.s > 0 &&!CountdownTimer.timerId) {
CountdownTimer.timerId = setTimeout(CountdownTimer.step, 1000);
}
},
/**
* If the counter is counting down, stop it
*/
stop : function() {
if(CountdownTimer.timerId) {
clearTimeout(CountdownTimer.timerId);
CountdownTimer.timerId = null;
}
},
/**
* Stop the counter if it's counting down, then reset to the initialized
* value, and redraw the timer.
*/
resetTimer : function() {
if(CountdownTimer.timerId) {
CountdownTimer.stop();
}
CountdownTimer.s = CountdownTimer.reset;
CountdownTimer.draw();
},
/**
* If the timer has reached zero, notify the user. Otherwise, decrement
* it, draw it, and call this method again in 1 second.
*/
step : function() {
if (CountdownTimer.s > 0) {
CountdownTimer.s--;
CountdownTimer.draw();
CountdownTimer.timerId = setTimeout(CountdownTimer.step, 1000);
}
else {
alert("Time's up!");
}
},
/**
* Draw the value of the timer in the container element.
*/
draw : function() {
CountdownTimer.el.innerHTML = CountdownTimer.s;
}
};
}();
window.onload = function() {
CountdownTimer.init(60,'countdown');
CountdownTimer.start();
document.getElementById("stopClock").onclick = function() {
CountdownTimer.stop();
};
document.getElementById("startClock").onclick = function() {
CountdownTimer.start();
};
document.getElementById("resetClock").onclick = function() {
CountdownTimer.resetTimer();
};
}
</script>
</head>
<body>
<div id="countdown"></div>
<input type="button" id="stopClock" value="Stop Timer">
<input type="button" id="startClock" value="Start Timer">
<input type="button" id="resetClock" value="Reset Timer">
</body>
</html>

[edited by: Fotiman at 7:34 pm (utc) on May 24, 2007]

Dabrowski

7:53 pm on May 24, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This will prevent you from being able to "start" the timer more than once:

Here's another small bug fix so you can resart it once it's been stopped

This was just a test case, I could have done that. I just didn't because I assumed it would be started from an event, which you wouldn't call twice cos that would just be stupid. ;)

Also didn't bother with restart. I wrote it originally for a guy who wanted his page to redirect after 10 seconds. The popup message was just to prove you could capture the endpoint, but it's exactly the ticket here.

Foti, I'm gonna start having a play with your OLN namespace method to simplify(?) some of my scripts. I'm going to assign the environment to the element in question, rather than have to keep track of x different elements. Might need your help, can I sticky you if I need to?

Dabrowski

7:53 pm on May 24, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



P.S. mine looks better! ;D

Fotiman

8:17 pm on May 24, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




Foti, I'm gonna start having a play with your OLN namespace method to simplify(?) some of my scripts. I'm going to assign the environment to the element in question, rather than have to keep track of x different elements. Might need your help, can I sticky you if I need to?

Absolutely. I can also give you some external references to some sites that give great examples and/or documentation about this method.


P.S. mine looks better! ;D

Definately. But whose code looks better? ;-) I was focusing on the functional portion. My example could easily be modified to incorporate your progress bar into it. You'd just need to modify the "draw" method in my example. But yes, your output certainly looks better. :-)

Adam5000

12:53 am on May 25, 2007 (gmt 0)

10+ Year Member



The code looks good Foit and when I paste it into notepad and run it, I get an error message "Line 1 expected '}' Also I have to have the numbers displayed in a text box or in some other way visible on the screen. But the code itself looks well done.

Adam5000

12:55 am on May 25, 2007 (gmt 0)

10+ Year Member



Oops. Scuse the typo Foti

Fotiman

3:13 pm on May 25, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




The code looks good Foit and when I paste it into notepad and run it, I get an error message "Line 1 expected '}'

I don't know what to say about that. I just tried copying the code from my post, pasting it into notepad, saving as test.htm (and changing the file type to All Files). I then pointed my browser at it and it worked just fine. I've tried both IE6 and Firefox with no problems. Did you perhaps miss some of it when you tried to copy and paste?


Also I have to have the numbers displayed in a text box or in some other way visible on the screen. But the code itself looks well done.

Just modify the draw method. Currently, it's just writing the value to the screen, but you could tweak it to put the value in a text box or whatever you wanted it to do.

Adam5000

10:15 pm on May 25, 2007 (gmt 0)

10+ Year Member



I don't know what to say either. I'm using IE 7 if that makes any difference. When I paste into notepad and save, then view it with the browser, there's an error message and just the buttons appear. The numbers don't have to be in a text box, and writing to the screen would work fine, but only the buttons are on the screen. Maybe it's one of the settings on my computer.

Fotiman

10:55 pm on May 25, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



If you're not viewing the file via a web server, then IE7 will try to block the JavaScript content by default. Usually, this means you'll see a small note near the top of the viewport that says:

To help protect your security, Internet Explorer has restricted this webpage from running scripts or ActiveX controls that could access your computer. Click here for options...

I just tried viewing it with IE7 and had no problem viewing from a webserver, and then I tried it locally and after clicking to allow the blocked content, it worked just fine.

Adam5000

4:55 pm on May 28, 2007 (gmt 0)

10+ Year Member



That did the trick. It works good now. You're a genius. Happy memorial day all.

Adam5000

6:00 pm on May 28, 2007 (gmt 0)

10+ Year Member



And you too Dab. The progress bar is good too.