Search code examples
javascripthtmltimercountdown

Javascript timer stopping at 1, not continuing to 0


I've been trying to get this javascript countdown working and have gotten it to countdown from 3 to 1, however I can't figure out why it doesnt go all the way down to 0?

Why does it stop at 1 and how do I make it count down fully?

<body>
<p>Time left: <span id="time">3</span> seconds.</p>
<p><a href="#" onclick="play()">Play</a> <a href="#" onclick="pause()">Pause</a></p>
<script>
var time = 3,
timeElement = document.getElementById('time'),
timer = null;
var updateTimer = function() {
  timeElement.innerHTML = time--;
  if (time === 0) {
    clearInterval(timer);
  }
}
function play() {
    timer = setInterval(updateTimer, 1000);
    return false;
}
function pause() {
    clearInterval(timer);
    return false;
}
</script>
</body>

You can also test the JsFiddle I made here: http://jsfiddle.net/Vg4kQ/ Thanks for your help!


Solution

  • Use prefix instead of postfix decrement:

    timeElement.innerHTML = --time;
    

    This has to do with the semantic differences between the prefix and postfix increment/decrement operators. They both increment/decrement the value of the variable, as expected, but they do not evaluate to the same value when used as expressions.

    Prefix increment/decrement both function the way most people would expect: they adjust the variable's value, then evaluate to the new value.

    var x = 5;
    console.log(++x); // 6
    console.log(x);   // 6
    

    Postfix operators are a little less intuitive. They still modify the value the same way, but when used as expressions, they evaluate to the variable's value before it was modified.

    var x = 5;
    console.log(x++); // 5
    console.log(x);   // 6
    

    In your code, when time reached 0, the postfix expression still yielded the previous value, 1, making timeElement's value still display 1, but still ending the loop. Converting the expression to use prefix decrement fixes that problem.

    Alternatively, you could always just split it up into two statements.

    time--;
    timeElement.innerHTML = time;