通过纯JavaScript停止并再次运行计时器

时间:2016-02-21 08:04:30

标签: javascript

我想制作一个简单的倒计时器,可以通过+或 - 设置,也可以通过点击自己来停止和运行。 我的问题是当它停止然后运行它显示NAN为第一个数字。 我想这是因为setTimer功能,但我不知道如何解决这个问题。这是我的代码:



var x = document.getElementsByClassName('session');
var seconds = 60;
var session;
var t;
var on = true;
var minutes = 1;

for (var i = 0; i < x.length; i++) {
  x[i].innerHTML = minutes;
}

function increase() {
  minutes++;
  for (var i = 0; i < x.length; i++) {
    x[i].innerHTML = minutes;
  }
}

function decrease() {
  minutes--;
  for (var i = 0; i < x.length; i++) {
    if (x[i].innerHTML > 0) {
      x[i].innerHTML = minutes;
    }
  }
}

function setSession() {
  session = x[1].innerHTML - 1;
}

function timer() {
  if (seconds > 0) {
    seconds--;
    if (seconds == 0 && session > 0) {
      session--;
      seconds = 60;
    }
  }
  x[1].innerHTML = session + ':' + seconds;
}


function stoptimer() {
  clearInterval(t);
}


function general() {
  if (on) {
    on = false;
    t = setInterval(timer, 100);
  } else {
    on = true;
    stoptimer();
  }
}
&#13;
<div class='session'></div>
<div id='increase' onclick='decrease()'>-</div>
<div id='increase' onclick='increase()'>+</div>
<div class='session' onclick='setSession();general()'></div>
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:0)

你设置

x[1].innerHTML = session + ':' + seconds;

然后尝试将其计算为

session = x[1].innerHTML - 1;

您需要将会话:秒放在其他地方或执行

session = parseInt(x[1].innerHTML,10) - 1;

答案 1 :(得分:0)

您不应该从html实体设置会话。基本上这会产生解析问题,并可能会破坏您的代码。此外,每次获得此值时减去一个,将扳手投入工作中。

我重新整理了你的代码并添加了一些注释,看看:

var x = document.getElementsByClassName('session');
var seconds = 0;
var session;
var timer; // give this a useful name
var timerRunning = false; // give this a useful name
var minutes = 1;



function updateMinutes(newMinutes){

    if (timerRunning){
        return; // do not allow updating of countdown while count down is running
    }

    if(newMinutes !== undefined){ // allow this function to be called without any parameters
        minutes = newMinutes; 
    }

    if(minutes < 1){
        minutes = 1; //set your minimum allowed value
    }
    if(minutes > 99999){
        minutes = 99999; //could also have some sort of maximum;
    }

    for (var i = 0; i < x.length; i++) {
      x[i].innerHTML = minutes;
    }

    session = minutes; // now this can only be set while timer is not running, so no need to get it from the html
    //also, i would let this start at the exact same value as minutes, and have seconds start at zero
}

updateMinutes(); // call this now to initialise the display

function increase() {
  updateMinutes(minutes + 1);
}

function decrease() {
  updateMinutes(minutes - 1);
}

function timer_tick() {
  if (seconds > 0) {
    seconds--;
    if (seconds == -1 && session > 0) { //because of where you've positioned your logic, this should check for negative one, no zero, otherwise you'll never display a zero seconds value
      session--;
      seconds = 59; //when a timer clocks over it goes to 59
    }
  }
  if (session > 0 || seconds > 0){
      x[1].innerHTML = session + ':' + seconds;
  }
  else{// you need to detect the ending
      x[1].innerHTML = "Finished!!";
  }
}

function timer_stop() {
    clearInterval(timer);
}

function timer_start(){
    timer = setInterval(timer_tick, 1000);
}

function timer_toggle() { //give these timer functions consistent names
  if (!timerRunning) {
    timer_start();
  } else {
    timer_stop();
  }
  timerRunning = !timerRunning; //just flip the boolean
}

答案 2 :(得分:0)

好的,我会提出另一种方法。为您的计时器使用 { "timestamp": 1456043810789, "status": 400, "error": "Bad Request", "exception": "org.springframework.http.converter.HttpMessageNotReadableException", "message": "Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@eaa3acb; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@eaa3acb; line: 1, column: 1]", "path": "/app/loginuser" } ,如下所示:

class Base
end

class A < Base
  Foo = true
end

class B < A
  Foo = false
end

class C < B
end

C.ancestors.find { |o| o.constants(false).include?(:Foo) }
  #=> B

然后,您可以像这样使用它:

class

html中唯一的变化是删除function MyTimer(htmlEl) { this.sec = 0; this.min = 0; this.elt = htmlEl; } MyTimer.prototype.set = function(m) { this.min = m; this.display(); var self = this; this._dec = function() { self.sec--; if (self.sec < 0) { if (self.min == 0) { self.stop(); } else { self.min -= 1; self.sec = 59; } } self.display(); } } MyTimer.prototype.display = function() { this.elt.innerHTML = this.min + ":" + this.sec; } MyTimer.prototype.toggle = function() { if (this.interval) { this.stop(); this.interval = undefined; } else this.start(); } MyTimer.prototype.start = function() { this.interval = setInterval(this._dec, 100); }; MyTimer.prototype.stop = function() { clearInterval(this.interval); }; 来电:

window.onload = init;

var minutes, x, timer;

function init() {
  x = document.getElementsByClassName('session');
  timer = new MyTimer(x[1]);
  minutes = 0;
}

function increase() {
  minutes += 1;
  x[0].innerHTML = minutes;
  timer.set(minutes);
}

function decrease() {
  minutes -= 1;
  x[0].innerHTML = minutes;
  timer.set(minutes);
}


function general() {
  timer.toggle();
}

此代码更清晰。您将逻辑和min / sec封装在一个可重用的对象中。这是一个工作小提琴:https://jsfiddle.net/Shitsu/zs7osc59/

答案 3 :(得分:0)

问题的根源在于代码

    session = x[1].innerHTML - 1;

让我们重新访问保持变量'session'的目的。我想这是保持最大值的值,分钟的上限,从哪里开始计数,对吧?另一方面,'minutes'变量是保持分钟的临时值。你在这里迷茫的是你用'分钟'代替它的上限(实际上是会话的角色),例如在这段代码中

    function increase() {
        minutes++;
        for (var i = 0; i < x.length; i++) {
           x[i].innerHTML = minutes;
        }
    }

请注意,您正在通过'minutes'的值更新html,之后您正在通过该恶意代码将该值读入'session':

    session = x[1].innerHTML - 1;

那么,为什么?为什么需要从html更新'your'变量的值?您应该只根据session var的值更新html,反之亦然。让我们继续,让生活更简单...... 让我们在'分钟'中保留分钟的临时值,让我们在变量会话中保持上限,并且,让我们将其重命名为maxMinutes。只有当用户点击“+”或“ - ”时才更新'maxMinutes'(绝不是来自html)。

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
</head>
<body>

<script>

var x = document.getElementsByClassName('session');
var maxMinutes = 0;
var minutes = maxMinutes;
var seconds = 0;
var timer;
var on = false;

function increase() {
  if(on) {
    return;
  }
  maxMinutes++;
  minutes = maxMinutes;
  x[0].innerHTML = maxMinutes;
  x[1].innerHTML = minutes;
 }

function decrease() {
  if(on) {
    return;
  }
  if(maxMinutes == 0)
  {
    return;
  }

  maxMinutes--;

  minutes=maxMinutes;

  x[0].innerHTML = maxMinutes;
  x[1].innerHTML = minutes;

}

function periodicRun() {
  if (seconds > 0) {
    seconds--;
  }
  else if(seconds == 0)
  {
   if(minutes > 0) {
      minutes--;
      seconds = 60;
    }
    else
    {
      stopTimer(timer);
      return;
    }
  }
  x[1].innerHTML = minutes + ':' + seconds;
}


function stoptimer() {
  clearInterval(timer);
}


function general() {
  if (on) {
    on = false;
    stoptimer();
  } else {
    on = true;
    timer = setInterval(periodicRun, 500);
  }
}

$(document).ready(function(){
  increase();
});

</script>

<div class='session'></div>
<div id='increase' onclick='decrease()'>-</div>
<div id='increase' onclick='increase()'>+</div>
<div class='session' onclick='general()'></div>

</body>
</html>

注意,maxLimits获得赋值的唯一位置是increase()和reduce()。 'minutes'和html依次根据maxMinutes进行更新。 祝好运!