JavaScript:clear setInterval on blur和resume on focus

I have a very basic slideshow cycling some div containers. This is my code:

function cycle(){
    var $first = $('.panes .pane1');
    var $active = $('.panes .active');
    var $next = $active.next();
    if($next.length != 0){
        $active.removeClass('active').addClass('inactive');
        $('.panes').animate({left: "-=430px"}, 400);
        setTimeout(function(){
            $next.removeClass('inactive').addClass('active');
        }, 400);
    } else {
        $active.removeClass('active').addClass('inactive');
        $('.panes').animate({left: "0px"}, 400);
        setTimeout(function(){
            $first.removeClass('inactive').addClass('active');
        }, 400);
    }

}

$(window).blur(function(){window.clearInterval(cycling)});
$(window).focus(function(){cycling = setInterval('cycle()', 5001);});

Then in my document.ready function, I'm calling the above with cycling = setInterval('cycle()', 5001);

When the page become inactive, the setInterval should clear, then resume when the page regains focus. This works correctly in Chrome, but not IE. I'm not really concerned about IE because it doesn't need to be cleared there.

In Firefox, with the above code, the div container just switches back and forth with each interval, or sometimes it slides to the left twice as far as it is supposed to.

When I remove the $(window).focus(function(){cycling = setInterval('cycle()', 5001);}); line, then it behaves correctly with the exception of that it does not resume when the page regains focus.

What is causing this and how do I resolve the issue?

#0

You are calling setInterval twice, once on focus and once on document ready. The blur handler only clears whichever of those happened second. So the cycle() function gets called twice as often as you expect.

One way to get around that is to initialise cycling to null, assign cycling = null in the blur handler, and then in the ready and focus handlers only create a new interval if cycling === null.

Another way is to only call setInterval from document ready and just leave it running forever (i.e. until the user navigates away from your page), but add an "infocus" flag that you set and clear from the focus and blur handlers:

var infocus = false;
$(window).focus(function(){ infocus = true; })
        .blur(function (){ infocus = false; });

Then check the flag:

function cycle() {
   if (!infocus)
      return;

   // rest of your code here...
}