-2

const DEFAULT_TIME = 0;
const TIMER_INTERVAL_MS = 1000;
const BLINK_CLASS = 'blink';
const BEEP_SOUND_URL = 'https://assets.mixkit.co/active_storage/sfx/1714/1714-preview.mp3';

let countdownInterval;
let initialTime = DEFAULT_TIME;
let timeLeft = initialTime;
let isRunning = false;


const timerDisplay = document.getElementById("timer");
const startPauseBtn = document.getElementById("start-button");
const resetBtn = document.getElementById("reset-button");
const timeInput = document.getElementById("time-input");

const formatTime = seconds => {
  const hrs = Math.floor(seconds / 3600);
  const mins = Math.floor((seconds % 3600) / 60);
  const secs = seconds % 60;
  return [hrs, mins, secs].map(unit => String(unit).padStart(2, '0')).join(':');
};

const updateDisplay = seconds => {
  const formatted = formatTime(seconds);
  timerDisplay.textContent = formatted;
  document.title = `Timer: ${formatted}`;
};

const playEndSound = () => {
  const beep = new Audio(BEEP_SOUND_URL);
  beep.play().catch(console.error);
};

const onTimeEnd = () => {
  isRunning = false;
  startPauseBtn.textContent = 'Start';
  startPauseBtn.disabled = false;
  playEndSound();
  timerDisplay.classList.add(BLINK_CLASS);

  // callback_time_end(); // hook for callback
};

const startCountdown = () => {
  isRunning = true;
  startPauseBtn.textContent = 'Pause';
  startPauseBtn.disabled = false;
  countdownInterval = setInterval(() => {
    if (timeLeft > 0) {
      timeLeft--;
      updateDisplay(timeLeft);
    } else {
      clearInterval(countdownInterval);
      onTimeEnd();
    }
  }, TIMER_INTERVAL_MS);
};

const pauseCountdown = () => {
  clearInterval(countdownInterval);
  isRunning = false;
  startPauseBtn.textContent = 'Resume';
};

const handleStartPause = () => {
  if (isRunning) {
    pauseCountdown();
  } else {
    if (timeInput?.value) {
      const newTime = parseInt(timeInput.value, 10);
      if (isNaN(newTime) || newTime <= 0) {
        alert("Please enter a valid time in seconds.");
        return;
      }
      initialTime = newTime;
      if (timeLeft === 0 || timeLeft === DEFAULT_TIME) {
        timeLeft = initialTime;
        updateDisplay(timeLeft);
      }
    }
    startCountdown();
  }
};

const resetCountdown = () => {
  clearInterval(countdownInterval);
  isRunning = false;
  timeLeft = initialTime;
  updateDisplay(timeLeft);
  startPauseBtn.textContent = 'Start';
  startPauseBtn.disabled = false;
  timerDisplay.classList.remove(BLINK_CLASS);
};

const handleTimeInputChange = () => {
  if (isRunning) return;
  const newTime = parseInt(timeInput.value, 10);
  if (!isNaN(newTime) && newTime > 0) {
    initialTime = newTime;
    timeLeft = initialTime;
    updateDisplay(timeLeft);
  }
};

updateDisplay(timeLeft);

startPauseBtn.addEventListener("click", handleStartPause);
resetBtn.addEventListener("click", resetCountdown);
timeInput.addEventListener("change", handleTimeInputChange);
<button id="start-button">Start</button>
<button id="reset-button">Reset</button>
<input id="time-input" type="number" min="1" placeholder="Set sec" value="">
<span id="timer">0</span>

3
  • 2
    Use <select> instead of <input> to create a dropdown. This is basic HTML that any tutorial should explain. Commented 4 hours ago
  • You could follow this post to retrieve the selected value in a dropdown: stackoverflow.com/questions/10659097/… Commented 4 hours ago
  • Alternatively replace the number input with the time input. This will display a dropdown that allows users to set your countdown timer. Commented 2 hours ago

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.