Forum Moderators: open
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!
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>
<!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>
<!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>
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.
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]
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?
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?
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. :-)
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.
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.