Hey everyone - the function discussed in this thread is at the bottom of this post.

What this function does is countdown the value of an HTML table-cell to zero (minus 1 every second) then stop counting that specific cell when it's finished. This works perfectly, the problem is that when it is called AGAIN for a different table-cell, the previous cell starts reducing its value by 2 every second instead of 1. This function supports the Hour:Minute:Second format.

So, how would i make this function so that i can call an infinite number of different table cells, and the previous table cells timers would not be affected (they would still countdown 1 per second as they should)?


Thank you so much. I have been stuck on this problem for 2 weeks and just left my project dormant because of it. This simple problem has struck me from behind and destroyed my passion for the project - please help me get back on track!

-Ollie

This is the code which CALLS the function, where $i is 1-5 inclusive, defined by PHP:

timer('ff".$i."', ". rand(1,100) .");

This is the BODY of the function itself, called by the above command

var running = new Array(50);
function timer(data, id)
{
	//clearTimeout(id[data]);
	var id=new Array(50);
	// usage: var id=new Array(50); timer('cq0');
	dat=document.getElementById(data);
	var time=(dat.innerHTML).split(":"); 
	var done=0;
	if(dat.innerHTML == null) {
		done = 1;
		alert('null');
	}
	if (time[2]>0) time[2]--;
	else
	{
		time[2]=59;
		if (time[1]>0) time[1]--;
		else
		{
			time[1]=59;
			if (time[0]>0) time[0]--;
			else { 
			clearTimeout(id[data]); 
			done=1;
			running[data] = 0;
			renderStack();
			}
			
		}
		
	}
	if (!done)
	{
		dat.innerHTML=time[0]+":"+time[1]+":"+time[2];
		id[data]=setTimeout("timer('"+data+"')", 1000);
		running[data] = 1;
	}
}

Your validation in your code is somewhat odd.
1.It is not a good idea to keep redeclaring new whole arrays just to clear only 1 event you set out using setTimeout().
2.Why would you check for dat.innerHTML==null if the 'dat' could be null itself before you can check for innerHTML value, or even dat.innerHTML.split() would already cause an error?
3.When you declare 'new Array(50)', you are declaring the 'id' as regular array. But when you use 'id[string]', it will be used as an associated array (hash). Remember, your 'data' is a string, not an integer (look at your setTimeout() and also any bare variable value passed through setTimeout() could become string regardless quotation mark). This could give you a side effect and should not be use that way.

The problem you get when the timer is going down faster than it should is because the event you expected fired the same function call more than one time (click on the same button more than 1 time). As a result, there are multiple event attempt to read and write your innerHTML at the same time.

I have modified your code and added some HTML for testing as below. It is just an example to prevent a user to click on the same button multiple time which cause the timer to go wild.

<html>
<head>
<script type="text/javascript">

var running = [];  // create an array for assoc array use

// This function will check whether the event for the 'data'
// has already been initiated. If it has, ignore it; otherwise,
// run the timer().
function runTimer(data) {
  if (!running[data]) {  // not running yet, go for it
    running[data] = 1;  // arbitrary value
    timer(data);
  }
}

// real count down (both read & write)
function timer(data) {
  dat=document.getElementById(data);
  if (dat) {
    var time=(dat.innerHTML).toString().split(":");
    var done=false;
    if(time.length!=3) {  // incorrect time format
      done = true;
      alert('null');
    }
    else {
      // convert string to integer
      time[0] = parseInt(time[0], 10)
      time[1] = parseInt(time[1], 10)
      time[2] = parseInt(time[2], 10)
      // attempt to decrease the time
      if (time[2]>0) { time[2]--; }
      else {
        time[2]=59;
        if (time[1]>0) { time[1]--; }
        else {
          time[1]=59;
          if (time[0]>0) { time[0]--; }
          else {
            done=true;
            running[data] = null;
            renderStack();
          }
        }
      }
    }
    if (!done) {
      var outTime = "" +((time[0]<10)? "0" : "")+time[0]
      outTime += ":" +((time[1]<10)? "0" : "")+time[1]
      outTime += ":" +((time[2]<10)? "0" : "")+time[2]
      dat.innerHTML=outTime
      setTimeout("timer('"+data+"')", 1000);
    }
    else { dat.innerHTML = "00:00:00" }
  }
}
</script>
</head>

<body>
<div id="box1">00:02:00</div>
<input type="button" value="Go 1" onclick="runTimer('box1')"><br /><br />
<div id="box2">00:00:07</div>
<input type="button" value="Go 2" onclick="runTimer('box2')"><br /><br />
<div id="box3">00:04:11</div>
<input type="button" value="Go 3" onclick="runTimer('box3')"><br /><br />
<div id="box4">00:07:45</div>
<input type="button" value="Go 4" onclick="runTimer('box4')"><br /><br />
<div id="box5">01:01:02</div>
<input type="button" value="Go 5" onclick="runTimer('box5')"><br /><br />
</body>
</html>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.