开发者

Run setTimeout only when tab is active

Is there a way to stop setTimeout("myfunction()",10000); from counting up when the page isn't active. For instance,开发者_开发百科

  1. A user arrives at a "some page" and stays there for 2000ms
  2. User goes to another tab, leaves "some page" open.
  3. myfunction() doesn't fire until they've come back for another 8000ms.


(function() {
  var time = 10000,
      delta = 100,
      tid;

  tid = setInterval(function() {
    if ( document.hidden ) { return; }    
    time -= delta;
    if ( time <= 0 ) {
      clearInterval(tid);
      myFunction(); // time passed - do your work
    }        
  }, delta);
})();

Live demo: https://jsbin.com/xaxodaw/quiet


Changelog:

  • June 9, 2019: I’ve switched to using document.hidden to detect when the page is not visible.


Great answer by Šime Vidas, it helped me with my own coding. For completeness sake I made an example for if you want to use setTimeout instead of setInterval:

(function() {

    function myFunction() {
        if(window.blurred) {
            setTimeout(myFunction, 100);
            return;
        }

        // What you normally want to happen

        setTimeout(myFunction, 10000);
    };
    setTimeout(myFunction, 10000);

    window.onblur = function() {window.blurred = true;};
    window.onfocus = function() {window.blurred = false;};

})();

You'll see that the window blurred check has a shorter time set than normal, so you can set this depending on how soon you require the rest of the function to be run when the window regains focus.


You can do something like:

$([window, document]).blur(function() {
  // Clear timeout here
}).focus(function() {
  // start timeout back up here
});

Window is for IE, document is for the rest of the browser world.


I use almost the same approach as Šime Vidas in my slider but my code is based on document.visibilityState for page visibility checking:

document.addEventListener("visibilitychange", () => {

  if ( document.visibilityState === "visible" ) {

    slideshow.play();

  } else {

    slideshow.pause();
  }
});
  • About Page Visibility API: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API


What you'd have to do is set up a mechanism to set timeouts at small intervals, keeping track of total elapsed time. You'd also track "mouseenter" and "mouseleave" on the whole page (the <body> or something). When the short-term timeouts expire, they can check the window state (in or out) and not restart the process when the window is not in focus. The "mouseenter" handler would start all paused timers.

edit — @Šime Vidas has posted an excellent example.


I've finally implemented a variation of @Šime Vidas' answer, because the interval was still running if I opened another program and the browser window was not visible, but the page executing the interval was the active browser tab. So, I've modified the condition to document.hidden || !document.hasFocus(). This way, if the document is hidden or the document doesn't have the focus, the interval function just returns.

(function() {
  var time = 10000,
      delta = 100,
      tid;

  tid = setInterval(function() {
    if ( document.hidden || !document.hasFocus() ) { return; }    
    time -= delta;
    if ( time <= 0 ) {
      clearInterval(tid);
      myFunction(); // time passed - do your work
    }        
  }, delta);
})();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜