Countdown Timer in js, what's wrong?

54 views Asked by At

I'm in the middle of a countdown app project (Pomodoro) The app doesn't work for me, something in the calculation of the Math library may not be written correctly even though I think it is written correctly.

I am attaching the piece of code that does not work and also the complete code of the entire application

this is all my code, CSS is not necessary

hope for help :))

let timer;

function startTimer() {
    const hours = document.getElementById("hours").value;
    const minutes = document.getElementById("minutes").value;
    const seconds = document.getElementById("seconds").value;

    let totalTime = (hours * 3600) + (minutes * 60) + (seconds); // sum all seconds

    if (totalTime <= 0) {
        alert('Please set a valid time before starting.');
        return;
    }

    document.getElementById("input-section").style.display = 'none';
    document.getElementById("display-section").style.display = 'flex';
    console.log(timer);
    document.title = ('Time To Go ' + timer);
    
    if (timer) {
        clearInterval(timer);
    }
    
    timer = setInterval(
        function() {
            if (totalTime <= 0) {
                clearInterval(timer);
                alert("Time's Up!!");
                return;
            }

            const displayHours = Math.floor(totalTime / 3600);
            const displayMinutes = Math.floor((totalTime % 3600) / 60);
            const displaySeconds = totalTime % 60;

            document.getElementById("displayHours").textContent = String(displayHours).padStart(2, '0');
            document.getElementById("displayMinutes").textContent = String(displayMinutes).padStart(2, '0');
            document.getElementById("displaySeconds").textContent = String(displaySeconds).padStart(2, '0');
            
            totalTime--;
        }, 1000);
}

function stopTimer() {
    if (timer) {
        clearInterval(timer);
    }
    
    document.getElementById("inputSection").style.display = 'flex';
    document.getElementById("displaySection").style.display = 'none';
}
<div class="container">
    <div class="header">Countdown Timer</div>

    <div class="input-section" id="input-section">
        <input type="number" id="hours" placeholder="hours" min="0">
        <input type="number" id="minutes" placeholder="minutes" min="0" max="59">
        <input type="number" id="seconds" placeholder="seconds" min="0" max="59">
        <button onclick="startTimer()">Start</button>
    </div>
    
    <div class="display-section" id="display-section">
        <span id="displayHours">00</span>
        <span id="displayminutes">00</span>
        <span id="displaySeconds">00</span>
        <button onclick="stopTimer()">Stop</button>
    </div>
</div>

my problem is counting the time or something with the Math.floor

1

There are 1 answers

2
Scott Marcus On

In your HTML, you have an element with and id of: displayminutes, but in your JavaScript, you try to get a reference to: displayMinutes and that causes the textContent error you are currently getting. Fixing that error will at least get the timer running.

Beyond that, you are using some old techniques for setting up event handlers and you are using inline styles, which should always be avoided when possible. You also don't need separate start and stop buttons and separate functions for start and stop. You also aren't really using flex here, so that's not needed, just a single CSS class that can be applied when you want to hide something and removed when you want to show it.

See the re-worked code below and read the comments for details.

// Get all your DOM references just once, not every time the function runs
const hours = document.getElementById("hours");
const minutes = document.getElementById("minutes");
const seconds = document.getElementById("seconds");
const dispHours = document.getElementById("displayHours");
const dispMinutes = document.getElementById("displayMinutes");
const dispSeconds = document.getElementById("displaySeconds");
const inputSection = document.getElementById("input-section");
const outputSection = document.getElementById("output-section");
const toggleButton = document.querySelector("button");

let timer = null; // Always initialize your variables, even if its with null

// Set up your event handlers in JavaScript, not HTML
toggleButton.addEventListener("click", toggleTimer);

// This function will start and stop the timer
function toggleTimer() {   
    // Toggle the text on the button
    toggleButton.textContent = toggleButton.textContent === "Start" ? "Stop" : "Start";
    
    // If the clock is ticking, stop it
    if(toggleButton.textContent === "Start"){
      clearInterval(timer);
      inputSection.classList.remove("hidden");
      outputSection.classList.add("hidden"); 
      toggleButton.textContent = "Start";  
      
      // Reset the input and output
      hours.value = "00";
      minutes.value = "00";
      seconds.value = "00";      
      dispHours.textContent = "00";
      dispMinutes.textContent = "00";
      dispSeconds.textContent = "00";
      return;
    }

    let totalTime = (hours.value * 3600) + (minutes.value * 60) + (seconds.value); // sum all seconds

    if (totalTime <= 0) {
        alert('Please set a valid time before starting.');
        return;
    }

    // Don't use inline styles. Just add/remove classes
    inputSection.classList.add("hidden");
    outputSection.classList.remove("hidden");
    
    document.title = ('Time To Go ' + timer);
    
    if (timer) {
        clearInterval(timer);
    }
    
    timer = setInterval(function() {
            if (totalTime <= 0) {
                clearInterval(timer);
                alert("Time's Up!!");
                return;
            }

            const displayHours = Math.floor(totalTime / 3600).toString();
            const displayMinutes = Math.floor((totalTime % 3600) / 60).toString();
            const displaySeconds = (totalTime % 60).toString();

            dispHours.textContent = displayHours.padStart(2, '0');
            dispMinutes.textContent = displayMinutes.padStart(2, '0');
            dispSeconds.textContent = displaySeconds.padStart(2, '0');
            
            totalTime--;
        }, 1000);
}
/* Avoid inline styles when possible and use classes instead */
.hidden { display:none; }
<div class="container">
    <div class="header">Countdown Timer</div>

    <div class="input-section flex" id="input-section">
        <input type="number" id="hours" placeholder="hours" min="0">
        <input type="number" id="minutes" placeholder="minutes" min="0" max="59">
        <input type="number" id="seconds" placeholder="seconds" min="0" max="59">
    </div>
    <button>Start</button>
    <div class="display-section hidden" id="output-section">
        <span id="displayHours">00</span>
        <span id="displayMinutes">00</span>
        <span id="displaySeconds">00</span>
    </div>
</div>