skip to Main Content

I am currently programing an app as a project. While doing so I just got into Javascript yesterday and I am having an issue to stop my count.

What is my program doing:
You can see an image, which you have to click on. With every click the count gets +1. While doing so, a time of 30sec is running down and showing on the screen as well.

What do I want to reach:
I got everything working so far. The timer is working perfectly, the count is working while I am clicking on the image. But what I can’t get to work is that the image should not be click-able anymore after the timer hits 00:00 and the count should stay at the last reached number, so I can put it into a highscore list.

It’s especially about this part:

function blobPress() {
            if (timeLeft > 0) {
                count++;
                document.getElementById("count").innerHTML = count;
            } else {
                blob.style.display = "block";
            }
        }
let alarm = new Audio('alarm.mp3');
let finish = new Audio('finish.mp3');
let timerStarted = false;
let count = 0;


function startTimer() {
  if (!timerStarted) {
    let startTime = new Date().getTime();
    let thirtySeconds = 1000 * 30;
    let endTime = startTime + thirtySeconds;
    alarm.play();


    let refreshInterval = setInterval(function() {
      let timeLeft = endTime - new Date().getTime();


      if (timeLeft > 0) {
        let minutes = timeLeft / (1000 * 60);
        minutes = Math.floor(minutes);
        let seconds = (timeLeft / 1000) % 60;
        seconds = Math.round(seconds);
        seconds = ('0' + seconds).slice(-2);
        let text = '0'  +  minutes  +  ' : '  +  seconds;
        timer.innerHTML = text;
      } else {
        finish.play();
        timer.innerHTML = '00 : 00';
        clearInterval(refreshInterval);
      }
    }, 1000);
    timerStarted = true;
  }
}

function showCount() {
  if (timerStarted) {
    document.getElementById('count').style.color = "white";
  } else {
    document.getElementById('count').style.color = "#262626";
  }
}

function hideButton() {
  if (button.style.display === "none") {
    button.style.display = "block";
  } else {
    button.style.display = "none";
  }
}

function blobPress() {
  if (timeLeft > 0) {
    count++;
    document.getElementById("count").innerHTML = count;
  } else {
    blob.style.display = "block";
  }
}
body {background-color: #262626;} 

.background-dark {
  background-color: #262626;
}

.center {
  display: flex;
  justify-content: center;
}

.margin-top {
  margin-top: 60px;
}

.timer {
  font-size: 80px;
  color: white;
  font-family: 'Roboto', sans-serif;
}

.count {
  font-size: 50px;
  color: #262626;
  font-family: 'Roboto', sans-serif;
}
<div>
  <img src="img/menu.png">
</div>


<div class="center margin-top count" id="count">0</div>


<div class="center margin-top">
  <img id="blob" onclick="blobPress()" src="img/blob.png" style="transform: scale(0.9);">
</div>


<div class="center margin-top timer" id="timer">00 : 30</div>


<div class="center margin-top">
  <img id="button" onclick="startTimer(); showCount(); hideButton()" src="img/button.png" style="transform: scale(0.8);">
</div>

2

Answers


  1. The issues were:

    1. timeLeft was not defined inside blobPress().
    2. count was not handled correctly.

    I fixed the issues by doing the following changes:

    1. Removed onclick from #blob.
    2. Created a click event listener for the blob.
    3. Passed timeLeft to blobPress(timeLeft).
    4. Created a function parseTimeToSeconds(timeStr) to return timeLeft in integer as when you get it by innerHTML, it returns string.

    I also added alt attributes to the images. Rest of your code is untouched.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>Counter</title>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <style>
          body {
            background-color: #262626;
          }
    
          .background-dark {
            background-color: #262626;
          }
    
          .center {
            display: flex;
            justify-content: center;
          }
    
          .margin-top {
            margin-top: 60px;
          }
    
          .timer {
            font-size: 80px;
            color: white;
            font-family: "Roboto", sans-serif;
          }
    
          .count {
            font-size: 50px;
            color: #262626;
            font-family: "Roboto", sans-serif;
          }
        </style>
      </head>
      <body>
        <div>
          <img src="img/menu.png" alt="Menu Img" />
        </div>
    
        <div class="center margin-top count" id="count">0</div>
    
        <div class="center margin-top">
          <img
            id="blob"
            src="img/blob.png"
            style="transform: scale(0.9)"
            alt="Blob Img"
          />
        </div>
    
        <div class="center margin-top timer" id="timer">00 : 30</div>
    
        <div class="center margin-top">
          <img
            id="button"
            onclick="startTimer(); showCount(); hideButton()"
            src="img/button.png"
            style="transform: scale(0.8)"
            alt="Button Img"
          />
        </div>
    
        <script>
          let alarm = new Audio("alarm.mp3");
          let finish = new Audio("finish.mp3");
          let timerStarted = false;
          let count = 0;
    
          function startTimer() {
            if (!timerStarted) {
              let startTime = new Date().getTime();
              let thirtySeconds = 1000 * 30;
              let endTime = startTime + thirtySeconds;
              alarm.play();
    
              let refreshInterval = setInterval(function () {
                let timeLeft = endTime - new Date().getTime();
    
                if (timeLeft > 0) {
                  let minutes = timeLeft / (1000 * 60);
                  minutes = Math.floor(minutes);
                  let seconds = (timeLeft / 1000) % 60;
                  seconds = Math.round(seconds);
                  seconds = ("0" + seconds).slice(-2);
                  let text = "0" + minutes + " : " + seconds;
                  timer.innerHTML = text;
                } else {
                  finish.play();
                  timer.innerHTML = "00 : 00";
                  clearInterval(refreshInterval);
                }
              }, 1000);
              timerStarted = true;
            }
          }
    
          function showCount() {
            if (timerStarted) {
              document.getElementById("count").style.color = "white";
            } else {
              document.getElementById("count").style.color = "#262626";
            }
          }
    
          function hideButton() {
            if (button.style.display === "none") {
              button.style.display = "block";
            } else {
              button.style.display = "none";
            }
          }
    
          let blobBtn = document.getElementById("blob");
    
          blobBtn.addEventListener("click", function (event) {
            let timeLeft = document.getElementById("timer").innerHTML;
    
            // console.log("Time left: " + timeLeft);
    
            blobPress(timeLeft);
          });
    
          function blobPress(timeLeft) {
            let countElement = document.getElementById("count");
            let count = parseInt(countElement.innerHTML);
    
            // console.log("Count: " + count);
    
            let remainingTime = parseTimeToSeconds(timeLeft);
    
            if (remainingTime > 0) {
              count++;
              countElement.innerHTML = count;
            } else {
              blob.style.display = "block";
            }
          }
    
          function parseTimeToSeconds(timeStr) {
            let timeParts = timeStr.split(" : ");
            let minutes = parseInt(timeParts[0]);
            let seconds = parseInt(timeParts[1]);
    
            return minutes * 60 + seconds;
          }
        </script>
      </body>
    </html>
    
    Login or Signup to reply.
  2. It is generally not a good idea to use inline event handlers. Use addEventListener to handle events within the scripting.

    Muhammad Aleem Hashmi already explained the issues with your code.

    I took the liberty to create a timer factory. Maybe its useful for your project.

    To demonstrate its use here is a minimal reproducable example based on your code. The handling uses event delegation.

    document.addEventListener(`click`, handle);
    const myTimer = timerFactory(document.querySelector(`#timer`));
    
    // a factory to show a timer (counting backwards) in [timerDiv]
    function timerFactory(timerDiv) {
      let start, running;
    
      function runTimer(seconds) {
        const end = new Date(start);
        end.setSeconds(end.getSeconds() + seconds);
        const diff = new Date(end - start);
        const [min, sec] = [
          `${diff.getUTCMinutes()}`.padStart(2, `0`),
          `${diff.getUTCSeconds()}`.padStart(2, `0`)
        ];
    
        if (seconds >= 0) {
          timerDiv.textContent = `${min} : ${sec}`;
          return setTimeout(_ => runTimer(seconds - 1), 1000);
        }
    
        running = false;
      }
    
      return function(seconds) {
        if (!running) { 
          start = new Date();
          running = true;
          runTimer(seconds);
        }
      };
    }
    
    function handle(evt) {
      if (evt.target.id === `startTimer`) {
        return handleTimer();
      }
    }
    
    function handleTimer() {
      const inp = document.querySelector(`#nSeconds`);
      const seconds = +inp.value;
    
      if (seconds < +inp.min || seconds > inp.max) {
        return console.log(`${seconds} seconds not within limits (${
            inp.min} - ${inp.max} seconds)`);
      };
    
      return myTimer(seconds);
    }
    body {
      background-color: #262626;
    }
    
    input#nSeconds {
      width: 40px;
      margin-right: 0.3rem;
    }
    
    #startTimer {
      margin-left: 0.3rem;
    }
    
    .center {
      display: flex;
      justify-content: center;
      
      span.white {
        color: white
      }
    }
    
    .timer {
      color: white;
      margin-top: 30px;
      font-size: 80px;
      color: white;
      font-family: 'Roboto', sans-serif;
    }
    <div class="center margin-top timer" id="timer">00 : 00</div>
    <div class="center">
      <input type="number" value="10" min="5" max="120" id="nSeconds">
      <span class="white">seconds</span>
      <button id="startTimer">start timer</button>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search