JavaScript Timer
For my CS162 class we have to do a project requiring some AJAX. I’ve actually never used AJAX before, and really haven’t used javascript other than to manipulate already existing html information. However despite my inexperience with javascript I found this function to be pretty robust and perhaps helpful to many others. Anyways I found myself needing a javascript wait function which isn’t available and thus I came across a few solutions. The main way appears to be making use of the setTimeout function and use recursion to repeatedly call the current function. I personally see problems with this method however since people using a web browser don’t need updates every millisecond it’s fairly safe to assume the javascript stack wont grow to the point where it’s suffocating memory.
Update: After writing this I realized I was wrong about recursion and the setTimeout function. Thus this method really doesn’t have any flaws. Though for a more advanced timer please see my next post.
Please note that with all my sample scripts from this point on I require that my name and website be retained in the event of using the code. If you wish to use without my information please email me.
First the code for those that just want to use it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // Bryce Boe // Originally posted: http://www.bryceboe.com/2007/04/06/javascript-timer/ // // This is a pimp ass update function. It takes in // an interval in milliseconds, a count, a function name // and any number of arguments to pass to that function. // In this sense it should work with any function that // needs to be called at a specified interval. // The count specifies how many times to repeat. Any // negative value specifies to repeat forever. function timer(interval,count,someFunction) { args = []; for (i=3;i<arguments.length;i++) args[i-3]=arguments[i]; someFunction.apply(this,args); if (count > 0) tCount = count-1; else tCount = -1; command='timer('+interval+','+tCount+','+someFunction+','; for (i=3;i<arguments.length;i++) { if (typeof arguments[i]=='string') command+='\''+arguments[i]+'\''; else command+=arguments[i]; if(i+1<arguments.length) command+=','; } command+=')'; if (tCount != 0) setTimeout(command,interval); } |
Now what does this do? This function allows you to call any other function at a specified interval, and the key part is that the function you are calling can have any number of any type of arguments and still be passed through this function. This works by passing the function as an argument to another function in javascript.
Myself being a big python fan I was somewhat disappointed as the **kw functionality wasn’t easily available but in looking at line 13 one can see how I implemented this. This uses the javascript arguments array to get the undeclared parameters which are then passed into the function we wish to call by using the javascript apply function. This is essentially a trick because apply is used so that we can pass an array as the arguments to the function rather than using apply to modify the meaning of the keyword this in the callee as I understand apply is really used for.
Lines 17-24 recreate the same call we used to get into the timer function with the counter decremented by one if it is positive. Perhaps there is a better way to do this however this works as we need to have a string to pass to the setTimeout function. Also note on lines 19 and 20 I handled a special case for a string as an argument because otherwise the string will be evaluated rather before being passed. For other object types this may also need to be done to work properly.
A very simple demonstration of this script is a counter function that has a min value, max value, step size and default starting location. In my example I use -25 as the min, 25 as the max -25 as the default start and .5 as the step size with a time interval of .3 seconds. By entering in a value in the text field before running the start point can be adjusted.
Here is the code of the timer function:
1 2 3 4 5 6 7 8 | function myCounter(min,max,start,step,id) { curr = parseFloat(document.getElementById(id).value); if (isNaN(curr)) curr = start n = curr+step; if (min <= n && n <= max) { document.getElementById(id).value=n; } } |
And the code used to start the timer:
<input type="text" id="jsText1" value=""/> <input type="button" value="start timer" onclick="timer(300,100,myCounter,-25,25,-25,0.5,'jsText1');" />
Notice how I wrote the function to be passed the field which I wish to modify. This easily allows for more robustness as I can easily change my timer function to update any other html entity with a value field. With a bit more trickery this function could take another argument which will allow it to modify the innerHTML field if the element specified by the id doesn’t have a value, however I’ll leave that up to you to figure out.
One flaw I noticed while testing this post is that each time the start button is clicked a new timer is started thus making the counter go much faster. Feel free to correct that if needed, but it shouldn’t be a problem if you’re sure the timer will only be started once.
I think that’s it, feel free to email me, or comment with any questions you may have regarding this.
Related Entries
Comments
Comment from claudius
Time May 16, 2008 at 3:02 am
You have done an excellent job!
I just wonder if this class can be used for running the following sequence of JS functions:
function 1 for variable duration then
function 2 for variable duration then
function 3 for variable duration then
function 4 for variable duration then
function 5 for variable duration then
and repeating this cycle.
Thanks,
Claudius
Comment from Bryce Boe
Time May 16, 2008 at 10:27 am
Claudius,
This should work for what you’ve asked. Take this line:
command=’timer(’+interval+’,'+tCount+’,'+someFunction+’,';
and put some conditionals around it to change the count and function based on the current function’s name.
Such as:
if (someFunction == ‘function1′) command=’timer(’+duration2+’,'+tCount+’,'+function2+’,';
Comment from Adam
Time April 10, 2007 at 10:51 am
You should have just asked, we have all of TNG, DS9, Voyager, and TOS on DVD. You can borrow them anytime, and rip/copy/whatever them. I’m going to Netflix Enterprise one of these days, but it’s not really a priority because it sucks. We’re on the last few episodes of Voyager, then we’re going to start TOS.
Have you seen the twilight zone episodes with Shatner in them? He’s an amazingly good actor. I wonder if he started sucking on purpose during Trek.