Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pause and resume a javascript timer [duplicate]

I have this timer which works fine, but i need to be able to pause and resume it after that. i would appreciate it if someone could help me.

<html>
<head>
<script>
function startTimer(m,s)
    {
        document.getElementById('timer').innerHTML= m+":"+s;
        if (s==0)
            {
               if (m == 0)
                {
                    return;
                }
                else if (m != 0)
                {
                    m = m-1;
                    s = 60;
                }
        }
    s = s-1;
    t=setTimeout(function(){startTimer(m,s)},1000);
}


</script>
</head>

<body>
<button onClick = "startTimer(5,0)">Start</button>

<p id = "timer">00:00</p>
</body>
</html>
like image 316
user2303981 Avatar asked Feb 16 '23 18:02

user2303981


2 Answers

I simply can't stand to see setTimeout(...,1000) and expecting it to be exactly 1,000 milliseconds. Newsflash: it's not. In fact, depending on your system it could be anywhere between 992 and 1008, and that difference will add up.

I'm going to show you a pausable timer with delta timing to ensure accuracy. The only way for this to not be accurate is if you change your computer's clock in the middle of it.

function startTimer(seconds, container, oncomplete) {
    var startTime, timer, obj, ms = seconds*1000,
        display = document.getElementById(container);
    obj = {};
    obj.resume = function() {
        startTime = new Date().getTime();
        timer = setInterval(obj.step,250); // adjust this number to affect granularity
                            // lower numbers are more accurate, but more CPU-expensive
    };
    obj.pause = function() {
        ms = obj.step();
        clearInterval(timer);
    };
    obj.step = function() {
        var now = Math.max(0,ms-(new Date().getTime()-startTime)),
            m = Math.floor(now/60000), s = Math.floor(now/1000)%60;
        s = (s < 10 ? "0" : "")+s;
        display.innerHTML = m+":"+s;
        if( now == 0) {
            clearInterval(timer);
            obj.resume = function() {};
            if( oncomplete) oncomplete();
        }
        return now;
    };
    obj.resume();
    return obj;
}

And use this to start/pause/resume:

// start:
var timer = startTimer(5*60, "timer", function() {alert("Done!");});
// pause:
timer.pause();
// resume:
timer.resume();
like image 100
Niet the Dark Absol Avatar answered Mar 03 '23 01:03

Niet the Dark Absol


<p id="timer">00:00</p>
<button id="start">Start</button>
<button id="pause">Pause</button>
<button id="resume">Resume</button>

var timer = document.getElementById("timer");
var start = document.getElementById("start");
var pause = document.getElementById("pause");
var resume = document.getElementById("resume");
var id;
var value = "00:00";

function startTimer(m, s) {
    timer.textContent = m + ":" + s;
    if (s == 0) {
        if (m == 0) {
            return;
        } else if (m != 0) {
            m = m - 1;
            s = 60;
        }
    }

    s = s - 1;
    id = setTimeout(function () {
        startTimer(m, s)
    }, 1000);
}

function pauseTimer() {
    value = timer.textContent;
    clearTimeout(id);
}

function resumeTimer() {
    var t = value.split(":");

    startTimer(parseInt(t[0], 10), parseInt(t[1], 10));
}

start.addEventListener("click", function () {
    startTimer(5, 0);
}, false);

pause.addEventListener("click", pauseTimer, false);

resume.addEventListener("click", resumeTimer, false);

on jsfiddle

There are a whole load of improvements that could be made but I'm sticking with the code that the OP posted for the OP's comprehension.

Here is an extended version to give you further ideas on jsfiddle

like image 32
Xotic750 Avatar answered Mar 03 '23 01:03

Xotic750