37

I have a simple slideshow that I've made on a client's homepage, using setInterval to time the rotations.

To prevent browsers from screwing up setInterval when the page isn't in focus (another tab is being viewed, or another programme), I'm using:

function onBlur() {
            clearInterval(play);
        };

        function onFocus() {

            mySlideRotateFunction();

        };

        if (/*@cc_on!@*/false) { 
            document.onfocusin = onFocus;
            document.onfocusout = onBlur;
        } else {
            window.onfocus = onFocus;
            window.onblur = onBlur;
        }

Where mySlideRotateFunction sets the setInterval and runs some jQuery. While this works the majority of the time, I find that, on occasion, it appears as though onBlur hasn't run, and when I return to the page the timings have 'built up' and the rotations go crazy.

I can't quite determine a cause as to why this happens on occasion, and not on others.

My question- is there a problem with my code, and does anyone have a better suggestion for 'pausing' setInterval when browser window is out of focus?

Thanks

Michael Watson
  • 1,079
  • 3
  • 14
  • 26
  • I run into the same issue as I was working on a project some time ago - we tried to fix that annoying "bug" .. but in the end we used the code as it was .. because we can't reproduce when this strange behavious happens :( +1 hopefully there is someone out there with a solution :) – Walialu Sep 20 '11 at 14:35

2 Answers2

31

Immediately inside setInterval, place a check to see if the document is focused. The interval will continue firing as usual, but the code inside will only execute if the document is focused. If the window is blurred and later refocused, the interval will have continued keeping time but document.hasFocus() was false during that time, so there's no need for the browser to "catch up" by executing the code block a bunch of times when focus is restored.

var timePerInterval = 7000;
$(document).ready(function() {
    setInterval(function(){
        if ( document.hasFocus() ) {
            // code to be run every 7 seconds, but only when tab is focused
        }
    }, timePerInterval );
});
Jacob Ford
  • 4,553
  • 5
  • 27
  • 42
21

Try something like this:

var myInterval;
var interval_delay = 500;
var is_interval_running = false; //Optional

$(document).ready(function () {
    $(window).focus(function () {
        clearInterval(myInterval); // Clearing interval if for some reason it has not been cleared yet
        if  (!is_interval_running) //Optional
            myInterval = setInterval(interval_function, interval_delay);
    }).blur(function () {
        clearInterval(myInterval); // Clearing interval on window blur
        is_interval_running = false; //Optional
    });
});

interval_function = function () {
     is_interval_running = true; //Optional
     // Code running while window is in focus
}

Some testing done in IE9 and FF6

Linus Jäderlund
  • 515
  • 5
  • 13
  • So basically adding a second clearInterval just in case? Seems sensible, if clearInterval is indeed being missed. I'll test your idea out a bit, see if it resolves the bug. – Michael Watson Sep 20 '11 at 16:32
  • @MichaelWatson added some additional code, marked it "Optional". That code might give some extra security (at least it might prevent several intervals running at the same time) – Linus Jäderlund Sep 20 '11 at 17:17
  • i like it. Let me give it a day or so of testing and I'll let you know if the silly bug still sneaks through. – Michael Watson Sep 20 '11 at 22:25
  • Hey Linus- I can confirm, it works! No dramatic over testing, but seems great on ie7+, chrome, safari & firefox. – Michael Watson Sep 28 '11 at 08:58
  • In Chrome (at least Chrome 52), it seems the code contained in `$(window).focus(function () {}` doesn't run until the window has been blurred, then refocused. – Jacob Ford Jun 06 '16 at 23:26
  • 1
    @JacobFord you probably need to set interval on init, clear it on blue then set interval again on focus. Guessing "focus" never happens if window is already in focus then loading the page. Sorry about the late answer! – Linus Jäderlund Jun 21 '16 at 10:17