Skip to content Skip to sidebar Skip to footer

Countdown Timer 'delays' When Tab Is Inactive?

Trying to build a very simple Javascript countdown. However, whenever the tab is inactive, the countdown begins to lag and holds an incorrect count. See jsfiddle here for example:

Solution 1:

For this you can use the HTML5 Visibility API for detecting if the browser tab is active or not. And use regular binding of event handlers for focus and blur for the browser window.

Basically you pause() the timeline when you blur out of the tab, and then play() when you give the tab refocus. Example of this in action:

http://codepen.io/jonathan/pen/sxgJl

// Set the name of the hidden property and the change event for visibilityvar hidden, visibilityChange; 
if (typeofdocument.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support 
   hidden = "hidden";
   visibilityChange = "visibilitychange";
} elseif (typeofdocument.mozHidden !== "undefined") {
    hidden = "mozHidden";
    visibilityChange = "mozvisibilitychange";
} elseif (typeofdocument.msHidden !== "undefined") {
    hidden = "msHidden";
    visibilityChange = "msvisibilitychange";
} elseif (typeofdocument.webkitHidden !== "undefined") {
    hidden = "webkitHidden";
    visibilityChange = "webkitvisibilitychange";
}

// If the page is hidden, pause the video;// if the page is shown, play the videofunctionhandleVisibilityChange() {
   if (document[hidden]) {
      tl.pause();
   } else {
      tl.play();
   }
}

// Warn if the browser doesn't support addEventListener or the Page Visibility APIif (typeofdocument.addEventListener === "undefined" || typeofdocument[hidden] === "undefined") {
   // do nothing or throw error via alert()alert("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
   // Handle page visibility change // Pause timeline  
   tl.pause();
}

HTML5 Visibility Docs:

https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

Regarding GreenSock Forum Topic:

http://forums.greensock.com/topic/9059-cross-browser-to-detect-tab-or-window-is-active-so-animations-stay-in-sync-using-html5-visibility-api/

Also in GSAP the equivalent for setTimeout() is delayedCall()

Provides a simple way to call a function after a set amount of time (or frames). You can optionally pass any number of parameters to the function too.

GSAP delayedCall(): http://greensock.com/docs/#/HTML5/GSAP/TweenMax/delayedCall/

//calls myFunction after 1 second and passes 2 parameters:TweenMax.delayedCall(1, myFunction, ["param1", "param2"]);

functionmyFunction(param1, param2) {
    //do stuff
}

I hope this helps!

Solution 2:

before all, i have to mention that, those countdown animation is truly outstanding and elegant dear sir! well done...

Now to the answers: as mentioned in many articles, and here is one of them:

setInterval(func, delay) does not guarantee a given delay between executions. There are cases when the real delay is more or less than given. In fact, it doesn’t guarantee that there be any delay at all.

Source: http://javascript.info/tutorial/settimeout-setinterval and..

Most browsers apply performance improvements by reducing the priority of several tasks on inactive tabs or even some portions of the page that aren't on screen. Sometimes these improvements affects the executions of Javascript intervals as well.

Source: How can I make setInterval also work when a tab is inactive in Chrome?

as you can see, they mentioned that setInterval does not guarantee a given delay between executions even when the tab is active, and lets just assume that setTimeout (the one that you used) is also the same because they are relatively is "the same"

so what is the solution to this problem? well, what you actually can do is check how many times has actually elapsed between the event, something like this Codepen

EDIT: as you have requested, here is a fiddle of your countdown with the fix, and i have //commented on the changes i made to the fiddle, so it would hopefully make it easier for you to understand. So now, when you paired the countdown to other timer (ex. your phone's timer) you should get the same result even when the tab is inactive or the frame rate slowdown.

if you have enjoyed my answer please consider mark it as "the answer" or at least up vote it ;)

Solution 3:

The simplest way to ensure the timer stays correct when a user moves off the tab and then returns is to use session storage - to store the original starting time:

on the first load - get the local current datetime and store into session storage (note that will only accept a string - so you will have to stringify the value and then parse it out again upon retrieval).

when the tab loses focus that set start time will still be stored as startTime in ss. When the tab regains focus - have a function that gets the new current datetime, gets the stored datedtime from session storage and calculates the difference. Then the timer can be updated to the new reduced time.

Eg if its 10:00 am on page load - set the startTime into ss. Then the user spends 1 minute on the site and goes offsite for 5 minutes. Upon returning - the above described process will determine the current time is 10:06 and determine that its 6 minutes later than the start time so can update the timer as such.

This avoids the need for intervals and timers etc. You can take the specificity down to ms if needed. And also - I like your fiddle too.

Solution 4:

You can use this code. Each time the tab changes, it calculates the end time again and updates the counter.

let interval;
let duration=timeDifference(endTime(),nowDate())
updateTime();
$(window).focus(function () {
    clearInterval(interval)
    updateTime();
});

functionupdateTime() {
     interval = setInterval(function () {
        var timer = duration.split(':');
        //by parsing integer, I avoid all extra string processingvar hours = parseInt(timer[0], 10);
        var minutes = parseInt(timer[1], 10);
        var seconds = parseInt(timer[2], 10);
        --seconds;
        minutes = (seconds < 0) ? --minutes : minutes;
        if (minutes < 0) clearInterval(interval);
        seconds = (seconds < 0) ? 59 : seconds;
        seconds = (seconds < 10) ? '0' + seconds : seconds;
        hours = (hours < 10) ? '0' + hours : hours;
        //minutes = (minutes < 10) ?  minutes : minutes;
        $('.countdown').html(hours + ':' + minutes + ':' + seconds);
         duration = hours + ':' + minutes + ':' + seconds;
    }, 1000);
}
functionnowDate() {
    let date = newDate()
    let time1 = newDate();
    date = date.toISOString().slice(0, 10);
    date = date.split('-');
    returnnewDate(date[2] + '/' + date[1] + '/' + date[0] + " " + time1.getHours() + ":" + time1.getMinutes() + ":" + time1.getSeconds());
}
functionendTime() {
    let endTime = $('input[name=end_date]').val();
    endTime = endTime.split(' ');
    let date = endTime[0].split('-');
    let time = endTime[1];
    returnnewDate(date[2] + '/' + date[1] + '/' + date[0] + " " + time);
}
functiontimeDifference(date1,date2) {
    var difference = date1.getTime() - date2.getTime();

    var daysDifference = Math.floor(difference/1000/60/60/24);
    difference -= daysDifference*1000*60*60*24var hoursDifference = Math.floor(difference/1000/60/60);
    difference -= hoursDifference*1000*60*60var minutesDifference = Math.floor(difference/1000/60);
    difference -= minutesDifference*1000*60var secondsDifference = Math.floor(difference/1000);

    return hoursDifference +":"+minutesDifference+":"+secondsDifference
}

Post a Comment for "Countdown Timer 'delays' When Tab Is Inactive?"