Search code examples
javascripttimer

How to stop timer when the 'space' is pressed and start if do it again?


Cant get, why it doesn't work; I added new boolean 'keyPressed' to check if the key space was pressed. When it pressed, it's going to start the timer and, doing it again, stop the timer. But in my code this boolean doesn't help and only one part of my 'if' works: i can only stop or start by pressing space

const timeDisplay = document.querySelector("#timeDisplay");
const startBtn = document.querySelector("#startBtn");
const pauseBtn = document.querySelector("#pauseBtn");
const resetBtn = document.querySelector("#resetBtn");

let startTime = 0;
let elapsedTime = 0;
let currentTime = 0;
let paused = true;
let intervalId;
let hrs = 0;
let mins = 0;
let secs = 0;
let keyPressed = false;

document.addEventListener('keydown', function(event) {
  if (event.code == 'Space') {
    if (keyPressed) {
      if (paused) {
        paused = false;
        keyPressed = true;
        startTime = Date.now() - elapsedTime;
        intervalId = setInterval(updateTime, 1000);
      }
    }
  }
});

document.addEventListener('keydown', function(event) {
  if (event.code == 'Space') {
    if (!keyPressed) {
      if (!paused) {
        paused = true;
        keyPressed = false;
        elapsedTime = Date.now() - startTime;
        clearInterval(intervalId);
      }
    }
  }
});



startBtn.addEventListener("click", () => {

  if (paused) {
    paused = false;
    keyPressed = true;
    startTime = Date.now() - elapsedTime;
    intervalId = setInterval(updateTime, 1000);
  }
});
pauseBtn.addEventListener("click", () => {
  if (!paused) {
    paused = true;
    keyPressed = false;
    elapsedTime = Date.now() - startTime;
    clearInterval(intervalId);
  }
});
resetBtn.addEventListener("click", () => {
  paused = true;
  clearInterval(intervalId);
  startTime = 0;
  elapsedTime = 0;
  currentTime = 0;
  hrs = 0;
  mins = 0;
  secs = 0;
  timeDisplay.textContent = "00:00:00";
});

function updateTime() {
  elapsedTime = Date.now() - startTime;

  secs = Math.floor((elapsedTime / 1000) % 60);
  mins = Math.floor((elapsedTime / (1000 * 60)) % 60);
  hrs = Math.floor((elapsedTime / (1000 * 60 * 60)) % 60);

  secs = pad(secs);
  mins = pad(mins);
  hrs = pad(hrs);

  timeDisplay.textContent = `${hrs}:${mins}:${secs}`;

  function pad(unit) {
    return (("0") + unit).length > 2 ? unit : "0" + unit;
  }
}
<span id="timeDisplay"></span><br />
<button type="button" id="startBtn">Start</button>
<button type="button" id="pauseBtn">Pause</button>
<button type="button" id="resetBtn">Reset</button>


Solution

  • You shouldn't have two handlers for the same event because they will produce unpredictable behavior due to unpredictable order of execution.

    Additionally, I would recommend avoiding duplicated code in multiple handlers because it is hard to keep them consistent. It also makes it hard to track state changes performed in multiple places.

    The final thing is that I would recommend to use keyup instead of keydown. There could be many keydowns but only one keyup :)

    Here is how I would improve your code to fix the problem. Please let me know if this helps.

    const timeDisplay = document.querySelector("#timeDisplay");
    const startBtn = document.querySelector("#startBtn");
    const pauseBtn = document.querySelector("#pauseBtn");
    const resetBtn = document.querySelector("#resetBtn");
    
    let startTime = 0;
    let elapsedTime = 0;
    let currentTime = 0;
    let paused = true;
    let intervalId;
    let hrs = 0;
    let mins = 0;
    let secs = 0;
    let keyPressed = false;
    
    const start = () => {
      if (!paused) return;
      paused = false;
      startTime = Date.now() - elapsedTime;
      intervalId = setInterval(updateTime, 1000);
    };
    
    const pause = () => {
      if (paused) return;
      paused = true;
      elapsedTime = Date.now() - startTime;
      clearInterval(intervalId);
    };
    
    const reset = () => {
      paused = true;
      clearInterval(intervalId);
      startTime = 0;
      elapsedTime = 0;
      currentTime = 0;
      hrs = 0;
      mins = 0;
      secs = 0;
      timeDisplay.textContent = "00:00:00";
    };
    
    document.addEventListener('keyup', (event) => {
      if (event.code == 'Space') {
        if (paused) {
          start();
        } else {
          pause();
        }
      }
    });
    
    startBtn.addEventListener("click", start);
    pauseBtn.addEventListener("click", pause);
    resetBtn.addEventListener("click", reset);
    
    function updateTime() {
      elapsedTime = Date.now() - startTime;
    
      secs = Math.floor((elapsedTime / 1000) % 60);
      mins = Math.floor((elapsedTime / (1000 * 60)) % 60);
      hrs = Math.floor((elapsedTime / (1000 * 60 * 60)) % 60);
    
      secs = pad(secs);
      mins = pad(mins);
      hrs = pad(hrs);
    
      timeDisplay.textContent = `${hrs}:${mins}:${secs}`;
    
      function pad(unit) {
        return (("0") + unit).length > 2 ? unit : "0" + unit;
      }
    }
    <span id="timeDisplay"></span><br />
    <button type="button" id="startBtn">Start</button>
    <button type="button" id="pauseBtn">Pause</button>
    <button type="button" id="resetBtn">Reset</button>