I_love_vegetables
I_love_vegetables

Reputation: 1341

how to add minutes to stopwatch

i have this stopwatch code below which runs on SS:MS(seconds.milliseconds) format at first, and i want it to run on MM:SS.MS(minutes:seconds.milliseconds) format when it reaches above 60 seconds, here is my code

let sec = 0;
let min = 0;
let millisecond = 0;
const stopwatch = document.getElementById("stopwatch");
function stopwatchStart() {
    sec = parseInt(sec);
    min = parseInt(min);
    millisecond = parseInt(millisecond);

    millisecond = millisecond + 1;

    if (millisecond == 100) {
      sec = sec + 1;
      millisecond = 0;
    }

    stopwatch.innerHTML = sec + '.' + millisecond;

    if (sec === 60) {
      min = min + 1;
      sec = 0;
      // how do i make it run on MM:SS:MS format
    };

    setTimeout("stopwatchStart()", 10);
}

i tried this code but does not work (doesnt change the innerHTML of stopwatch)

 if (sec === 60) {
      min = min + 1;
      sec = 0;
      stopwatch.innerHTML = min  + ":" + sec + "." + millisecond;
    };

Upvotes: 0

Views: 630

Answers (2)

Wazeed
Wazeed

Reputation: 1280

function initStopWatch(hh, mm, ss, fff) {
    hh = +hh || 0;
    mm = +mm || 0;
    ss = +ss || 0;
    fff = +fff || 0;
    var timer = null, on = {
        hour: function (h) { },
        minute: function (m) { },
        second: function (s) { },
        milliSecond: function (f) { }
    }, last = 0, now = 0;
    function run() {
        now = Date.now();
        fff += (now - last);
        last = now;
        if (fff > 999) {
            fff -= 1000;
            ss++;
            if (ss > 59) {
                ss -= 60;
                mm++;
                if (mm > 59) {
                    mm -= 60;
                    hh++;
                    on.hour(hh);
                }
                on.minute(mm);
            }
            on.second(ss);
        }
        on.milliSecond(fff);
    }
    function start() {
        stop();
        last = now = Date.now();
        timer = setInterval(run, 10);
    }
    function stop() {
        clearInterval(timer);
    }
    function reset() {
        stop();
        hh = mm = ss = fff = last = now = 0;
        on.hour(hh);
        on.minute(mm);
        on.second(ss);
        on.milliSecond(fff);
    }
    return { start, stop, reset, on };
}

window.onload = function () {
    var hhElement = document.querySelector('.swatch .hh'),
        mmElement = document.querySelector('.swatch .mm'),
        ssElement = document.querySelector('.swatch .ss'),
        fffElement = document.querySelector('.swatch .fff');
    var stopWatch = initStopWatch();
    stopWatch.on.hour = function (h) {
        hhElement.textContent = (h + "").padStart(2, "0");
    }
    stopWatch.on.minute = function (m) {
        mmElement.textContent = (m + "").padStart(2, "0");
    }
    stopWatch.on.second = function (s) {
        ssElement.textContent = (s + "").padStart(2, "0");
    }
    stopWatch.on.milliSecond = function (f) {
        fffElement.textContent = (f + "").padStart(3, "0");
    }
    document.querySelector('.swatch').addEventListener('click', function (e) {
        var cls = e.target.classList;
        if (cls.contains('start')) {
            stopWatch.start();
            e.target.textContent = "Stop";
            cls.remove('start');
            cls.add('stop');
        } else if (cls.contains('stop')) {
            stopWatch.stop();
            e.target.textContent = "Start";
            cls.remove('stop');
            cls.add('start');
        } else if (cls.contains('reset')) {
            stopWatch.reset();
            var stopBtnElement = e.currentTarget.querySelector('.stop');
            if (stopBtnElement) {
                var cls2 = stopBtnElement.classList;
                stopBtnElement.textContent = "Start";
                cls2.remove('stop');
                cls2.add('start');
            }
        }
    });
}
.swatch {
  font-size: 32pt;
  font-weight: bold;
  color: green;
  font-family: Comic Sans MS, Comic Sans, cursive;
}

.swatch .fff {
  font-size: 24pt;
}

.swatch button {
  min-width: 100px;
  font-size: 12pt;
  padding: 10px;
  background-color: green;
  color: white;
  font-weight: bold;
}

.swatch button:hover {
  background-color: darkgreen;
}
<div class="swatch">
    <div>
        <span class="hh">00</span> :
        <span class="mm">00</span> :
        <span class="ss">00</span> .
        <span class="fff">000</span>
    </div>
    <div>
        <button type="button" class='start'>Start</button>
        <button type="button" class='reset'>Reset</button>
    </div>
</div>

Upvotes: 1

Kevin Verstraete
Kevin Verstraete

Reputation: 1463

You shouldn't trust setTimeout in this way, as you can never know when it will run. Easier method is to keep the starting datetime in a variable and make a difference from that. Even if there is a delay, your timer remains correct.

Using Intl.DateTimeFormat for formatting and setInterval instead of setTimeout also helps.

let startDate, 
    interval = null, 
    stopwatch = document.getElementById("stopwatch"),
    btn = document.getElementById("btn"),
    dateTimeFormat = new Intl.DateTimeFormat('default', { 
       minute: 'numeric',
       second: 'numeric',
       fractionalSecondDigits: 2});

function startStopWatch(){
  if(interval === null){
    startDate = Date.now();
    displayStopWatch();
    stopwatch.innerHTML= "test";
    interval = setInterval(displayStopWatch, 10);
  } else {
    clearInterval(interval);
    interval = null;
  }
}
function displayStopWatch(){
  let diff = Date.now() - startDate;
  stopwatch.innerHTML= dateTimeFormat.format(new Date(diff));
}
btn.addEventListener('click', function() {
  startStopWatch();
});
<button id="btn">start/stop</button>
<div id ="stopwatch">
</div>

Upvotes: 2

Related Questions