call-me
call-me

Reputation: 726

Javascript easy timer does not work

I am trying to make an easy countdown but it does not work the way I think it should work. This is the first time I use setInterval in Javascript and would be very happy if someone could find my mistake.

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <script type="text/javascript">
            function timer () {
                window.clearTimeout(clock)
                var seconds = 10;
                var clock = setInterval(function() {
                    if (seconds == 0) {

                    } else {
                        seconds = seconds-1;
                        document.getElementById('seconds').innerHTML = seconds;
                    };
                },1000);
            }
        </script>
        <button onclick="timer();">timer</button>
        <p id="seconds">10</p>
    </body>
</html>

I hoped the timer would start-over when you clicked the button, but there are 2 timers running at the same time.

Upvotes: 0

Views: 993

Answers (2)

Witiko
Witiko

Reputation: 3387

There are several problems with your code you need to address:

  1. You need to make the clock variable global. In your example, an empty new variable clock is created each time the timer() function is called.
  2. You are using the clearTimeout() function instead of the clearInterval() function.
  3. The setInterval() function may miss some ticks and your seconds counter will then be off. If you wish to avoid that, you should check the current time each time the interval function is called.
<!DOCTYPE html>
<html>
    <body>
        <script type="text/javascript">
            var clock;
            function timer () {
                clearInterval(clock);
                var start = new Date().getTime();
                clock = setInterval(function() {
                    var seconds = Math.round(10 - (new Date().getTime() - start) / 1000);
                    if (seconds > 0)
                        document.getElementById('seconds').innerHTML = seconds;
                    else 
                        clearInterval(clock);
                }, 1000);
            }
        </script>
        <button onclick="timer();">timer</button>
        <p id="seconds">10</p>
    </body>
</html>

A breakdown of Math.round(10 - (new Date().getTime() - start) / 1000):

  • new Date().getTime() returns the current time in milliseconds since the epoch.
  • (... - start) / 1000 returns the number of seconds since the start of the timer.
  • 10 - ... returns the number of remaining seconds.
  • Math.round(...) rounds the result to an integer.

Upvotes: 2

KooiInc
KooiInc

Reputation: 122906

Just using setTimeout simplifies things (you used setInterval, but clearTimeout to clear it), declare the necessary variables outside the timer function and add a reset argument to be able to reset the timer.

(function () {
  var report = document.querySelector('#seconds');
  var seconds = 10;
  var timed = null;
  
  document.querySelector('button')
    .addEventListener('click', function(e) { timer(true) });
  
  timer(true);

  function timer (reset) {
     seconds -= 1;
     if(reset) { 
       clearTimeout(timed); 
       seconds = 10; 
     }
     report.textContent = seconds;
     if (seconds > 0 ) {
      timed = setTimeout(timer, 1000);
     }
  }
}())
#seconds {
  font: 48px/70px bold verdana, arial;
  color: white;
  width: 70px;
  height: 70px;
  background: green;
  text-align: center;
  border-radius: 50%;
}
<button>start/reset timer</button>
<p id="seconds"></p>

Upvotes: 0

Related Questions