0

I'm using the countdown timer from here: The simplest possible JavaScript countdown timer?

I'm adding the reset, pause and resume functionalities to the code.

  //=================== Timer class ==============================
function CountDownTimer(duration, granularity) {
  this.duration = duration
  this.granularity = granularity || 1000;
  this.tickFtns = [];
  this.running = false;
  this.resetFlag = false;
}

CountDownTimer.prototype.start = function() {
  console.log('calling start');

  if (this.running) {
    return;
  }
  this.running = true;
  var start = Date.now(),
      that = this,
      diff, obj,
      timeoutID;

  (function timer() {
    diff = that.duration - (((Date.now() - start) / 1000) | 0);

    if (that.resetFlag) {
        console.log('Reset inside closure');
        clearTimeout(timeoutID);
        diff = 0;
        that.resetFlag = false;
        that.running = false;
        return;
    }

    console.log(diff);

    if (diff > 0) {
      timeoutID = setTimeout(timer, that.granularity);
    } else {
      diff = 0;
      that.running = false;
    }

    obj = CountDownTimer.parse(diff);
    that.tickFtns.forEach(function(ftn) {
      ftn.call(this, obj.minutes, obj.seconds);
    }, that);
  }());
};

CountDownTimer.prototype.onTick = function(ftn) {
  if (typeof ftn === 'function') {
    this.tickFtns.push(ftn);
  }
  return this;
};

CountDownTimer.prototype.expired = function() {
  return !this.running;
};

CountDownTimer.prototype.setTime = function(secs) {
    this.duration = secs;
}

CountDownTimer.prototype.reset = function() {
    this.resetFlag = true;
}

CountDownTimer.parse = function(seconds) {
  return {
    'minutes': (seconds / 60) | 0,
    'seconds': (seconds % 60) | 0
  };
};

window.onload = function () {

    timer = new CountDownTimer(25);
    timer.start();

    $('#button').click(function() {
         console.log("before reset");
         console.log(timer);
         console.log("after reset");
         timer.reset();
         console.log(timer);
         // timer.setTime(10);
         timer.start();
    })
}

HTML for testing, check the output at console.

<script src="main.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<button id='button'> </button>

1) Is function timer() in start a closure?

2) I added a resetFlag, the reset method, and the check for resetFlag in the start function. I'm able to stop the timer immediately, but can't start it after that. How do I fix the error?

25
24
23
main.js:64 Reset inside closure

(it supposed to countdown from 25 to 0, and when I press #button, the timer reset and should count from 10 to 0.

================================EDITS==========================================:

After adding running = false, it's still not working.

before reset
main.js:128 CountDownTimer {duration: 25, granularity: 1000, tickFtns: Array[0], running: true, resetFlag: false}
main.js:129 after reset
main.js:131 CountDownTimer {duration: 25, granularity: 1000, tickFtns: Array[0], running: true, resetFlag: true}
calling start
main.js:64 Reset inside closure

It seems that there's some lag after resetting the timer? (The reset inside closure suppposed to appear before the after reset.

Community
  • 1
  • 1
Dzung Nguyen
  • 3,794
  • 9
  • 48
  • 86
  • 1
    *timer* has a closure to the variables in outer execution contexts, so it can access *that*, *diff*, etc. after *start* has finished running. Note the first line of *start*, the *reset* function also needs to set the *running* variable to false otherwise *start* doesn't do anything. – RobG Aug 19 '16 at 00:09
  • Thanks for the suggestions. Please find my edits. – Dzung Nguyen Aug 19 '16 at 00:16
  • The problem is that the reset doesn't end the timer() right away. I put cleartimeout in reset function, and it still has some lags. – Dzung Nguyen Aug 19 '16 at 00:34

0 Answers0