cabralpinto
cabralpinto

Reputation: 2098

Javascript: function working sometimes, and other times just not doing anything

I'm really confused about this but I'm sure there's an explanation. I'm working on a personal training webapp and I have a timer that, every time it reaches 00:00, it should go to 00:10 and stop. The timer works using this function I wrote:

//timer object function
function Timer(element, callback) {

  var ac, minutes, seconds, finalTimeInSeconds, displayMinutes, displaySeconds, interval = 1000,
    self = this,
    timeLeftToNextSecond = 1000,
    running = false;

  this.set = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds = inputMinutes * 60 + inputSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.add = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds += inputMinutes * 60 + inputSeconds;
    finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.subtract = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds -= inputMinutes * 60 + inputSeconds;
    if (finalTimeInSeconds < 0) {
      callback()
    }
    finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;
    this.print();
  }

  this.reset = function() {

    this.set(0, 0);
  }

  this.print = function() {

    displayMinutes = (minutes.toString().length == 1) ? "0" + minutes : minutes; //ternary operator: adds a zero to the beggining 
    displaySeconds = (seconds.toString().length == 1) ? "0" + seconds : seconds; //of the number if it has only one caracter.

    $(element).text(displayMinutes + ":" + displaySeconds);
  }

  this.run = function() {

    if (running == false) {
      running = true;

      var _f = function() {
        secondStarted = new Date;
        self.subtract(0, 1);
        interval = 1000;

        ac = setTimeout(_f, interval);


      }
      ac = setTimeout(_f, interval);


    }
  }

  this.stop = function() {

    if (running == true) {
      running = false;
      console.log(this + "(" + element + ") was stopped");
      stopped = new Date;
      interval = 1000 - (stopped - secondStarted);
      clearTimeout(ac);
    }
  }

  this.getTotalTimeInSeconds = function() {


    return finalTimeInSeconds;
  }

  this.reset();

}

What I did was create a timer like this:

globalTimer = new Timer("#globalTimer", function() {
            globalTimer.stop();
            globalTimer.set(0,10);
        });

And then I set it to 00:15 and ran it:

globalTimer.set(0,15);
globalTimer.run();

And for some reason, when the timer reaches zero, it sets to 00:10, but it doesn't stop. The thing is, before it reaches 00:00, I can stop it with the console and it works perfectly; but when the timer gets to zero the .stop() function just doesn't work anymore. Click here for a demo I made. Why does this happen? Is there something wrong with the Timer function? Thank you so much.

Upvotes: 0

Views: 787

Answers (2)

domii
domii

Reputation: 169

The reason is the variable running is still set to false, just add the following line after closing the if statement in the stop function.

running = true;

Here is the code extract.

this.stop = function() {
    if (running == true) {
        running = false;
        console.log(this + "(" + element + ") was stopped");
        stopped = new Date;
        interval = 1000 - (stopped - secondStarted);
        clearTimeout(ac);
    }
    running = true;
}

Upvotes: 0

Anthony Sherratt
Anthony Sherratt

Reputation: 475

Adding a simple check to your 'running' variable in your setTimeout callback function should be enough here. I think you may possibly be getting slightly confused with the difference between setTimeout and setInterval.

I simply removed the clearTimeout from your 'stop' function as it wasn't required and changed your 'run' function to check if your 'globalTimer' was 'running' and it worked as you described.

this.run = function() 
{
    var _f = function() {
        secondStarted = new Date;
        self.subtract(0, 1);
        interval = 1000;

        var theColorIs = $(element).css("color");
        if (running == true)
        {
            ac = setTimeout(_f, interval);
        }
    }

    if (running == false) 
    {
        running = true;
        ac = setTimeout(_f, interval);
    }
}

Upvotes: 1

Related Questions