2

I'm trying to display a progress bar on a html page using javascript. However, when the browser tab containing the code becomes inactive, the progress bar stops updating, being resumed when the tab is active again.

How can I prevent the browser from stopping/pausing the execution of javascript code when the window is inactive?

Although it may be irrelevant, here is the code:

Object.progressBar = function(){
$( "#question-progress-bar" ).progressbar({
    value: false,
    complete: function(event, ui) { ... }
});

var seconds = 15.0,
progressbar = $("#question-progress-bar"),
progressbarValue = progressbar.find(".ui-progressbar-value");

progressbarValue.css({
    "background": '#c5b100',
    "opacity" : '0.8'
})

var int = setInterval(function() {
    var percent = (15-seconds)/15*100; 
    seconds=seconds-0.1;
    progressbar.progressbar( "option", {
        value: Math.ceil(percent)
    });

    $("#question-progress-bar-seconds").html((seconds).toFixed(1)+"s");

    if (seconds <= 0.1) {
        clearInterval(int);
    }
}, 100);
}
Catalin
  • 112
  • 1
  • 13
  • 1
    [Possibly related](http://stackoverflow.com/questions/7977170/ios-5-pauses-javascript-when-tab-is-not-active), if not essentially a duplicate. What browser are you seeing this in? – ajp15243 Apr 22 '13 at 15:34
  • You can't. Modern browsers all slow down interval timers when pages are not active, and they do so unconditionally. – Pointy Apr 22 '13 at 15:35
  • Have you considered instead setting an interval that checks the time since the page has loaded? That way the frequency of the interval timer doesn't matter. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date – Sandy Gifford Apr 22 '13 at 15:36
  • The time elapsed since page was loaded is not an option for my application. I could store the local time in ms when the timer was started and "correct" the progress bar, but I need to send something to a server when time is up. – Catalin Apr 22 '13 at 15:43
  • I think I understand what you mean, I'll update my answer below to reflect that – Sandy Gifford Apr 22 '13 at 15:51
  • I've updated my answer. Hope it's what you were looking for. – Sandy Gifford Apr 22 '13 at 16:09

1 Answers1

1

Instead of using setInterval and assuming a certain amount of time has passed between calls (even when it's up front, setInterval has hit or miss accuracy) use the Date object to get a time when the bar starts, and compare that to the current time at each iteration.

<html>
    <head>
        <script>
            function go()
            {
                var pb = new ProgressBar(5, "targ");
            }

            window.onload = go;

            function ProgressBar(l, t)
            {
                var start = Date.now();
                var length = l * 1000;
                var targ = document.getElementById(t);

                var it = window.setInterval(interval, 10);

                function interval()
                {
                    var p = 100 * (Date.now() - start) / length;

                    if(p > 100)
                    {
                        p = 100;

                        window.clearInterval(it);

                        alert("DONE"); // alternatively send an AJAX request here to alert the server
                    }

                    targ.value = (Math.round(p) + "%");
                }
            }
        </script>
    </head>
    <body>
        <input type="text" id="targ" />
    </body>
</html>

I've made an example object, here, that immediately starts a countdown when instantiated and calls an alert and kills the interval timer when done. Alternatively an AJAX call, or any other sort of call can be done upon completion.

It should be noted that this will NOT complete the call if the browser stops Javascript all together. It will, however, complete it as soon as the tab has been given focus again if enough time has passed in the interim. There is no way for a website to alter this sort of browser behavior from the scripting side.

Hope that helps!

Sandy Gifford
  • 7,219
  • 3
  • 35
  • 65
  • Thank you for your response. What I was looking for was something to prevent the browser from stopping the javascript, which seams impossible. – Catalin Apr 22 '13 at 20:08
  • Yeah, it's a hard coded feature in most browsers. Some will continue to run code in the background, some won't. Chrome, for example, will finish this call; iOS 5.0 Safari will not. This is the closest you'll get, though, as it will at least execute as soon as possible whereas the original solution will just pick up from where it left off. – Sandy Gifford Apr 22 '13 at 20:51
  • After implementing the progress bar in the way you suggested I noticed the browser doesn't interrupt the javascript code when the tab is out of focus. – Catalin Apr 28 '13 at 17:26
  • Fantastic! Although you should check across multiple browsers. I'm 90% sure that most mobile browsers WILL stop it, but ya gotta take what you can get sometimes I guess. Be sure to select this answer if you felt it was satisfactory! – Sandy Gifford Apr 29 '13 at 15:15