OHello
OHello

Reputation: 97

Javascript Start/Stop button changes innerHTML and starts timer but doesn't fulfil any of the other part of function

I have a button which I am trying to use as a start and stop for an event which starts or stops a countdown timer. However it currently only starts and changes to the stop but will not change back to start or stop the timer from counting down.

Is there a better way of doing this? I've also included the reset button as I've tried to reset things when it it's pushed but it currently just changes back to the start, but the start won't fire again after I have done this.

((d) => {
  let btn = d.getElementById("btn");
  let reset = d.getElementById("reset");
  let countdown = d.getElementById("countdown");


  let counter;
  let startTime = 1500;

  let timerFormat = (s) => {
    return (s - (s %= 60)) / 60 + (9 < s ? ":" : ":0") + s;
  };

  countdown.innerHTML = timerFormat(startTime);

  let timer = () => {
    startTime--;
    countdown.innerHTML = timerFormat(startTime);
    if (startTime === 0) clearInterval(counter);
  };

  btn.addEventListener("click", () => {
    if (stop) {
      start();
      btn.innerHTML = "Stop";
    } else {
      stop();
      btn.innerHTML = "Start";
    }
  });

  let start = () => {
    counter = counter || setInterval(timer, 1000);
  };

  let stop = () => {
    clearInterval(counter);
    counter = undefined;
  };

  reset.onclick = () => {
    startTime = 1500;
    countdown.innerHTML = timerFormat(startTime);
    if (btn.innerHTML === "Stop") {
      btn.innerHTML = "Start";
    }
  };
})(document);
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="../styles/styles.css" />
    <script defer src="../JS/timer.js"></script>
  </head>
  <body>
    <div id="countdown"></div>
    <div class="btn__container">
      <button class="btn" id="btn">Start</button>
      <button class="btn" id="reset">Reset</button>
    </div>
  </body>
</html>

Upvotes: 0

Views: 246

Answers (1)

Scott Marcus
Scott Marcus

Reputation: 65808

Your problem is in how you are determining whether to start or stop:

if (stop) {

stop is a function, so it has a "truthy" value and your if statement will always evaluate to true. Instead, check the existence of counter.

Other:

  • Don't use .innerHTML if you can help it and certainly not when the string you are working with doesn't contain any HTML. .innerHTML has security and performance implications. Instead, use .textContent.
  • While a timer isn't going to be 100% accurate for timekeeping, you can make the counter a little bit more accurate by having the callback run just a little under every second. The reason being that running every second means you run the risk of possibly skipping over a second on the counter if the timer doesn't run exactly one second later.

((d) => {
  let btn = d.getElementById("btn");
  let reset = d.getElementById("reset");
  let countdown = d.getElementById("countdown");


  let counter;
  let startTime = 1500;

  let timerFormat = (s) => {
    return (s - (s %= 60)) / 60 + (9 < s ? ":" : ":0") + s;
  };

  countdown.textContent = timerFormat(startTime);

  let timer = () => {
    startTime--;
    countdown.textContent = timerFormat(startTime);
    if (startTime === 0) clearInterval(counter);
  };

  btn.addEventListener("click", () => {
    if (counter) {
      stop();
      btn.textContent = "Start";
    } else {
      start();
      btn.textContent = "Stop";
    }
  });

  let start = () => {
    counter = counter || setInterval(timer, 950);
  };

  let stop = () => {
    clearInterval(counter);
    counter = null;
  };

  reset.onclick = () => {
    startTime = 1500;
    countdown.textContent = timerFormat(startTime);
    if (btn.textContent === "Stop") {
      btn.textContent = "Start";
    }
  };
})(document);
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="../styles/styles.css" />
    <script defer src="../JS/timer.js"></script>
  </head>
  <body>
    <div id="countdown"></div>
    <div class="btn__container">
      <button class="btn" id="btn">Start</button>
      <button class="btn" id="reset">Reset</button>
    </div>
  </body>
</html>

Upvotes: 2

Related Questions