skip to Main Content

I can’t understand. Wrote code for 2 independent timers. But when you press the start button, both timers start. What am I doing wrong, tell me?

I tried with conditions, but it didn’t work. Maybe we can somehow solve this? I don’t have any ideas anymore.
Here is the code:

const res = document.getElementById('res'),
  btnStart = document.getElementById('start'),
  btnStop = document.getElementById('stop');

const res1 = document.getElementById('res1'),
  btnStart1 = document.getElementById('start1'),
  btnStop1 = document.getElementById('stop1');


function getCounter(el, startBtn, stopBtn) {
  let sec = 0;
  let min = 0;
  let hours = 0;
  let interval;
  let isAvtive = false;

  function updateCounter() {
    sec++;
    if (sec === 60) {
      min++;
      sec = 0;
    }
    if (min === 60) {
      hours++;
      min = 0;
    }
    if (hours === 24) {
      hours = 0;
    }
    el.textContent = sec;
    if (btnStart) {
      res.textContent = `${hours.toString().padStart(2,0)}:${min.toString().padStart(2,0)}:${sec.toString().padStart(2,0)}`;
    }
    if (btnStart1) {
      res1.textContent = `${hours.toString().padStart(2,0)}:${min.toString().padStart(2,0)}:${sec.toString().padStart(2,0)}`;
    }

  }

  startBtn.addEventListener('click', function() {
    if (btnStart)
      interval = setInterval(updateCounter, 1000);


  });
  stopBtn.addEventListener("click", function() {

    if (interval) {
      clearInterval(interval)
      interval = null;

    }
  })


}


getCounter(res, btnStart, btnStop);
getCounter(res1, btnStart1, btnStop1);
<input type="button" value="start" id="start" />
<input type="button" value="stop" id="stop" />
<span id="res"></span>

<br/>

<input type="button" value="start1" id="start1" />
<input type="button" value="stop1" id="stop1" />
<span id="res1"></span>

2

Answers


  1. const res = document.getElementById('res');
    const btnStart = document.getElementById('start');
    const btnStop = document.getElementById('stop');
    
    const res1 = document.getElementById('res1');
    const btnStart1 = document.getElementById('start1');
    const btnStop1 = document.getElementById('stop1');
    
    function getCounter(el, startBtn, stopBtn) {
      let sec = 0;
      let min = 0;
      let hours = 0;
      let interval;
      let isActive = false;
    
      function updateCounter() {
        sec++;
        if (sec === 60) {
          min++;
          sec = 0;
        }
        if (min === 60) {
          hours++;
          min = 0;
        }
        if (hours === 24) {
          hours = 0;
        }
        el.textContent = `${hours.toString().padStart(2, '0')}:${min.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`;
      }
    
      startBtn.addEventListener('click', function () {
        if (!isActive) {
          interval = setInterval(updateCounter, 1000);
          isActive = true;
        }
      });
    
      stopBtn.addEventListener('click', function () {
        if (interval) {
          clearInterval(interval);
          interval = null;
          isActive = false;
        }
      });
    }
    
    getCounter(res, btnStart, btnStop);
    getCounter(res1, btnStart1, btnStop1);
    <p>Result: <span id="res">00:00:00</span></p>
    <button id="start">Start</button>
    <button id="stop">Stop</button>
    
    <p>Result1: <span id="res1">00:00:00</span></p>
    <button id="start1">Start1</button>
    <button id="stop1">Stop1</button>

    Inside the updateCounter function, the isActive flag is used to determine whether the timer has started. The timer is only started if isActive is false. This allows each timer to be controlled independently of the other.

    Login or Signup to reply.
  2. Make a function to create a timer in a parent element, you can provide a HTML template and insert it instead of repeating it in HTML.

    Don’t use setInterval/setTimeout since they aren’t precise and throttled in inactive tabs. Just calculate difference between start and current time. For smooth display use requestAnimationFrame() so your display would be also precise:

    function createTimer(parent = document.body){
    
      parent.insertAdjacentHTML('beforeend', `<div class="timer">
        <h1 class="text" style="font-family:monospace"></h1>
        <button class="start">Start</button>
        <button class="stop">Stop</button>
      </div>`);
      
      const $timer = [...parent.children].at(-1);
    
      let start, today, running;
      
      const [$text, $start, $stop] = 'text start stop'.split(' ').map(name => $timer.querySelector('.' + name));
    
      $start.onclick = () => {
        start = new Date, today = new Date;
        today.setHours(0, 0, 0, 0);
        running = true;
        timer();
      };
      
      $stop.onclick = () => running = false;
      
      const format = new Intl.DateTimeFormat('en', {
        hourCycle: 'h23',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',  
        fractionalSecondDigits: 2
      });
    
      $text.textContent = '00:00:00.00';
    
      // add today's timestamp so the timezone would be properly handled
      const timer = () => requestAnimationFrame(() => {
        $text.textContent = format.format(new Date - start + +today);
        running && timer();
      });
    }
    
    const container = document.querySelector('.timers');
    
    createTimer(container);
    createTimer(container);
    createTimer(container);
    button{
      padding: 5px 10px;
      min-width: 80px;
      border-radius: 5px;
      cursor:pointer;
      background:lightblue;
      text-transform:uppercase;
      letter-spacing:3px;
    }
    .timers{
      display:flex;
    }
    .timers > *{
      text-align: center;
      flex: 1;
    }
    <div class="timers"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search