我有定期进行活动的JavaScript。当用户不看站点时(即窗口或选项卡没有焦点),最好不要运行。

有没有办法使用JavaScript做到这一点? br />
我的参考点:如果您使用的窗口未激活,Gmail聊天会播放声音。

评论

对于那些对以下答案不满意的人,请查看requestAnimationFrame API,或使用现代功能,即当窗口不可见时(例如,在Chrome中为1秒),可以降低setTimeout / setInterval的频率。

document.body.onblur = function(e){console.log('lama');}适用于非重点元素。

有关使用W3C Page Visibility API的跨浏览器兼容解决方案,并回退到不支持该浏览器的浏览器,请参见此答案。

以下80%的答案不是此问题的答案。该问题询问当前是否不活跃,但下面的大量答案却不可见,这不是该问题的答案。可以说它们应该被标记为“不是答案”

大多数人在谈到不活跃且不可见时谈论不活跃。根本不活动很容易-仅仅处理窗口模糊/焦点事件...虽然用途有限,因为窗口可能是不活动的,但部分或全部可见(人们期望某些任务栏中也有“预览”图标)继续更新)。

#1 楼

自从最初编写此答案以来,由于有了W3C,新的规范已达到推荐状态。现在,页面可见性API(在MDN上)使我们能够更准确地检测用户何时隐藏页面。

document.addEventListener("visibilitychange", onchange);


当前的浏览器支持:


Chrome 13+
Internet Explorer 10+
Firefox 10+
Opera 12.10+ [阅读说明]


以下内容在不兼容的浏览器中,代码会退回到不太可靠的模糊/聚焦方法:

(function() {
  var hidden = "hidden";

  // Standards:
  if (hidden in document)
    document.addEventListener("visibilitychange", onchange);
  else if ((hidden = "mozHidden") in document)
    document.addEventListener("mozvisibilitychange", onchange);
  else if ((hidden = "webkitHidden") in document)
    document.addEventListener("webkitvisibilitychange", onchange);
  else if ((hidden = "msHidden") in document)
    document.addEventListener("msvisibilitychange", onchange);
  // IE 9 and lower:
  else if ("onfocusin" in document)
    document.onfocusin = document.onfocusout = onchange;
  // All others:
  else
    window.onpageshow = window.onpagehide
    = window.onfocus = window.onblur = onchange;

  function onchange (evt) {
    var v = "visible", h = "hidden",
        evtMap = {
          focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
        };

    evt = evt || window.event;
    if (evt.type in evtMap)
      document.body.className = evtMap[evt.type];
    else
      document.body.className = this[hidden] ? "hidden" : "visible";
  }

  // set the initial state (but only if browser supports the Page Visibility API)
  if( document[hidden] !== undefined )
    onchange({type: document[hidden] ? "blur" : "focus"});
})();


IE 9及更低版本需要onfocusinonfocusout,而所有其他版本都使用onfocusonblur(iOS除外)使用了onpageshowonpagehide

评论


@bellpeace:IE应该将iframe中的focusin和focusout传播到上部窗口。对于较新的浏览器,您只需处理每个iframe窗口对象上的焦点并模糊事件。您应该使用我刚刚添加的更新代码,这至少会涵盖较新的浏览器中的情况。

– Andy E
2012年5月30日23:13

@JulienKronegg:这就是为什么我的答案特别提到页面可见性API的原因,该页面在我最初编写答案后进入工作草案状态。焦点/模糊方法为较旧的浏览器提供了有限的功能。如您所回答的那样,绑定到其他事件并不能涵盖太多,并且更有可能出现行为差异(例如,当光标在光标下方弹出窗口时,IE不会触发鼠标退出)。我建议一个更适当的操作是显示一条消息或图标,以指示用户由于页面不活动而导致更新频率降低。

– Andy E
2012年9月7日在16:12

@AndyE我在铬上尝试了此解决方案。如果更改选项卡,它将起作用,但是,如果更改窗口(ALT +选项卡),则不会起作用。应该是?这是一个小提琴-jsfiddle.net/8a9N6/17

–托尼·兰帕达(TonyLâmpada)
2013年9月16日21:25



@Heliodor:我想暂时保持答案中的代码最少。从来没有打算将它作为剪切和粘贴的完整解决方案,因为实现者可能希望避免在主体上设置类并完全采取完全不同的动作(例如停止和启动计时器)。

– Andy E
14年8月14日在8:58

@AndyE您的解决方案似乎仅在用户更改选项卡或最小化/最大化窗口时才有效。但是,如果用户保持选项卡处于活动状态,则不会触发onchange事件,而是会从任务栏最大化该选项卡上的另一个程序。有针对这种情况的解决方案吗?谢谢!

–user1491636
2014年11月4日18:43

#2 楼

我会使用jQuery,因为您要做的就是:

$(window).blur(function(){
  //your code here
});
$(window).focus(function(){
  //your code
});


或者至少对我有用。

评论


对我来说,此呼叫在iframe中两次

–天使
2013年6月29日13:59

在Firefox中,如果您在Firebug控制台内部(在同一页面上)单击,则该窗口将失去焦点,这是正确的,但是取决于您的意图可能不是您所需要的。

–马吉德·弗拉德普尔
13年11月27日在7:31

这不适用于当前版本的现代浏览器,请参阅批准的答案(页面可见性API)

– Jon z
2014年2月25日在17:10

此解决方案在iPad上不起作用,请使用“ pageshow”事件

– ElizaS
2014年3月24日13:22

页面加载时,BLUR和FOCUS都会触发。当我从页面打开一个新窗口时,什么都没有发生,但是一旦新窗口关闭,两个事件都将触发:/(使用IE8)

– SearchForKnowledge
2014年8月21日在15:03



#3 楼

有3种典型的方法可用来确定用户是否可以看到HTML页面,但是它们都不完美:


W3C页面可见性API应该可以做到这一点(受支持的原因: Firefox 10,MSIE 10,Chrome 13)。但是,此API仅在完全覆盖浏览器标签时(例如,当用户从一个标签更改为另一个标签时)才会引发事件。当无法以100%的准确度确定可见性时,API不会引发事件(例如,使用Alt + Tab切换到另一个应用程序)。
使用基于焦点/模糊的方法会给您带来很多误报。例如,如果用户在浏览器窗口上方显示一个较小的窗口,则浏览器窗口将失去焦点(引发onblur),但用户仍然可以看到它(因此仍需要刷新)。另请参见http://javascript.info/tutorial/focus

依靠用户活动(鼠标移动,单击,键入的键)也会给您带来很多误报。考虑与上述相同的情况,或者用户正在观看视频。

为了改善上述不完美的行为,我使用了以下三种方法的组合:W3C Visibility API,然后进行聚焦/模糊处理和用户活动方法,以减少误报率。这样就可以管理以下事件:


将浏览器选项卡更改为另一个选项(由于W3C页面可见性API的原因,其准确性为100%)
页面可能被另一个窗口隐藏,例如由于Alt + Tab(概率=并非100%准确)
用户注意力可能未集中在HTML页面上(概率=并非100%准确)

它是这样工作的:当文档失去焦点时,将监视文档上的用户活动(例如鼠标移动),以确定该窗口是否可见。页面可见性概率与页面上最后一次用户活动的时间成反比:如果用户长时间未在文档上进行任何活动,则该页面很可能不可见。下面的代码模仿W3C页面可见性API:行为相同,但是误报率很小。它具有多浏览器的优势(在Firefox 5,Firefox 10,MSIE 9,MSIE 7,Safari 5,Chrome 9上测试)。


    <div id="x"></div>

    <script>
    /**
    Registers the handler to the event for the given object.
    @param obj the object which will raise the event
    @param evType the event type: click, keypress, mouseover, ...
    @param fn the event handler function
    @param isCapturing set the event mode (true = capturing event, false = bubbling event)
    @return true if the event handler has been attached correctly
    */
    function addEvent(obj, evType, fn, isCapturing){
      if (isCapturing==null) isCapturing=false; 
      if (obj.addEventListener){
        // Firefox
        obj.addEventListener(evType, fn, isCapturing);
        return true;
      } else if (obj.attachEvent){
        // MSIE
        var r = obj.attachEvent('on'+evType, fn);
        return r;
      } else {
        return false;
      }
    }

    // register to the potential page visibility change
    addEvent(document, "potentialvisilitychange", function(event) {
      document.getElementById("x").innerHTML+="potentialVisilityChange: potentialHidden="+document.potentialHidden+", document.potentiallyHiddenSince="+document.potentiallyHiddenSince+" s<br>";
    });

    // register to the W3C Page Visibility API
    var hidden=null;
    var visibilityChange=null;
    if (typeof document.mozHidden !== "undefined") {
      hidden="mozHidden";
      visibilityChange="mozvisibilitychange";
    } else if (typeof document.msHidden !== "undefined") {
      hidden="msHidden";
      visibilityChange="msvisibilitychange";
    } else if (typeof document.webkitHidden!=="undefined") {
      hidden="webkitHidden";
      visibilityChange="webkitvisibilitychange";
    } else if (typeof document.hidden !=="hidden") {
      hidden="hidden";
      visibilityChange="visibilitychange";
    }
    if (hidden!=null && visibilityChange!=null) {
      addEvent(document, visibilityChange, function(event) {
        document.getElementById("x").innerHTML+=visibilityChange+": "+hidden+"="+document[hidden]+"<br>";
      });
    }


    var potentialPageVisibility = {
      pageVisibilityChangeThreshold:3*3600, // in seconds
      init:function() {
        function setAsNotHidden() {
          var dispatchEventRequired=document.potentialHidden;
          document.potentialHidden=false;
          document.potentiallyHiddenSince=0;
          if (dispatchEventRequired) dispatchPageVisibilityChangeEvent();
        }

        function initPotentiallyHiddenDetection() {
          if (!hasFocusLocal) {
            // the window does not has the focus => check for  user activity in the window
            lastActionDate=new Date();
            if (timeoutHandler!=null) {
              clearTimeout(timeoutHandler);
            }
            timeoutHandler = setTimeout(checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold*1000+100); // +100 ms to avoid rounding issues under Firefox
          }
        }

        function dispatchPageVisibilityChangeEvent() {
          unifiedVisilityChangeEventDispatchAllowed=false;
          var evt = document.createEvent("Event");
          evt.initEvent("potentialvisilitychange", true, true);
          document.dispatchEvent(evt);
        }

        function checkPageVisibility() {
          var potentialHiddenDuration=(hasFocusLocal || lastActionDate==null?0:Math.floor((new Date().getTime()-lastActionDate.getTime())/1000));
                                        document.potentiallyHiddenSince=potentialHiddenDuration;
          if (potentialHiddenDuration>=potentialPageVisibility.pageVisibilityChangeThreshold && !document.potentialHidden) {
            // page visibility change threshold raiched => raise the even
            document.potentialHidden=true;
            dispatchPageVisibilityChangeEvent();
          }
        }

        var lastActionDate=null;
        var hasFocusLocal=true;
        var hasMouseOver=true;
        document.potentialHidden=false;
        document.potentiallyHiddenSince=0;
        var timeoutHandler = null;

        addEvent(document, "pageshow", function(event) {
          document.getElementById("x").innerHTML+="pageshow/doc:<br>";
        });
        addEvent(document, "pagehide", function(event) {
          document.getElementById("x").innerHTML+="pagehide/doc:<br>";
        });
        addEvent(window, "pageshow", function(event) {
          document.getElementById("x").innerHTML+="pageshow/win:<br>"; // raised when the page first shows
        });
        addEvent(window, "pagehide", function(event) {
          document.getElementById("x").innerHTML+="pagehide/win:<br>"; // not raised
        });
        addEvent(document, "mousemove", function(event) {
          lastActionDate=new Date();
        });
        addEvent(document, "mouseover", function(event) {
          hasMouseOver=true;
          setAsNotHidden();
        });
        addEvent(document, "mouseout", function(event) {
          hasMouseOver=false;
          initPotentiallyHiddenDetection();
        });
        addEvent(window, "blur", function(event) {
          hasFocusLocal=false;
          initPotentiallyHiddenDetection();
        });
        addEvent(window, "focus", function(event) {
          hasFocusLocal=true;
          setAsNotHidden();
        });
        setAsNotHidden();
      }
    }

    potentialPageVisibility.pageVisibilityChangeThreshold=4; // 4 seconds for testing
    potentialPageVisibility.init();
    </script>



没有假阳性就没有有效的跨浏览器解决方案,您最好对禁用网站上的定期活动进行三思。

评论


在字符串“ undefined”而不是undefined关键字上使用严格的比较运算符会不会在上述代码中导致误报?

–乔纳森
16年7月16日在0:23

@kiran:实际上它与Alt + Tab一起使用。当您执行Alt + Tab键时,您无法确定页面是否被隐藏,因为您可能会切换到一个较小的窗口,因此不能保证页面被完全隐藏。这就是为什么我使用“潜在隐藏”的概念的原因(在示例中,阈值设置为4秒,因此您至少需要使用Alt + Tab切换到另一个窗口至少4秒)。但是,您的评论表明答案不是很清楚,所以我改了字。

–朱利恩·克朗格(Julien Kronegg)
16年1月1日在21:14

@JulienKronegg我认为这是最好的解决方案。但是,以上代码非常需要一些重构和抽象。您为什么不将其上传到GitHub并让社区对其进行重构?

–雅各布
17年4月20日在11:24

@Jacob很高兴您喜欢我的解决方案。随意将其自己推广到GitHub项目。我通过Creativecommons.org/licenses/by/4.0提供了具有创用CC许可的代码

–朱利恩·克朗格(Julien Kronegg)
17年4月20日在14:17

#4 楼

GitHub上有一个整洁的库:

https://github.com/serkanyersen/ifvisible.js

示例:

// If page is visible right now
if( ifvisible.now() ){
  // Display pop-up
  openPopUp();
}


我已经在所有浏览器上测试了1.0.1版,并且可以确认它可以与以下浏览器一起使用:


IE9,IE10
Chrome 34.0

...以及可能所有较新的版本。

不能完全与以下版本配合使用:


IE8 -始终指示选项卡/窗口当前处于活动状态(.now()始终为我返回true


评论


接受的答案在IE9中引起了问题。这个图书馆很棒。

–汤姆·特曼(Tom Teman)
15年1月14日在15:59

#5 楼

使用:页面可见性API

document.addEventListener( 'visibilitychange' , function() {
    if (document.hidden) {
        console.log('bye');
    } else {
        console.log('well back');
    }
}, false );


我可以使用吗? http://caniuse.com/#feat=pagevisibility

评论


问题不在于页面可见性。关于不活跃/活跃

– gman
18年8月31日在7:24

我认为OP并不是在谈论ide的功能

–l2aelba
18年8月31日在7:42

我也不是在谈论ide。我说的是alt-tabbing / cmd-tab另一个应用程序。突然页面未激活。页面可见性api不能帮助我知道页面是否处于非活动状态,它只能帮助我知道页面是否可能不可见。

– gman
18年8月31日在8:23

#6 楼

我为我的应用程序创建了Comet Chat,当我收到其他用户的消息时,我使用:

if(new_message){
    if(!document.hasFocus()){
        audio.play();
        document.title="Have new messages";
    }
    else{
        audio.stop();
        document.title="Application Name";
    } 
}


评论


支持IE6的最干净的解决方案

– Paul Cooper
2015年3月3日,9:34

document.hasFocus()是最干净的方法。使用基于可见性api或事件或查找各种级别的用户活动/缺乏活动的所有其他方式变得过于复杂,并且充满了边缘情况和漏洞。将其放在一个简单的时间间隔上,并在结果更改时引发自定义事件。示例:jsfiddle.net/59utucz6/1

– danatcofo
17 Mar 29 '17 at 18:17

高效且与其他解决方案不同的是,当您切换到另一个浏览器选项卡或窗口,甚至另一个应用程序时,都能提供正确的反馈。

–ow3n
17年7月17日在9:20

毫无疑问,这是最干净的方法,但是在Firefox中不起作用

– Hardik chugh
19年6月7日在16:44

如果我打开Chrome Dev工具,则document.hasFocus()等于false。或者即使您单击浏览器的顶部面板,也会发生同样的情况。我不确定此解决方案是否适合暂停视频,动画等

– tylik
19年7月10日在15:05

#7 楼

我开始使用社区Wiki答案,但意识到它没有在Chrome中检测到alt-tab事件。这是因为它使用了第一个可用的事件源,在这种情况下,它是页面可见性API,在Chrome中似乎不跟踪alt-tabbing。

我决定稍微修改一下脚本以保留跟踪页面焦点更改的所有可能事件。您可以使用以下功能:

function onVisibilityChange(callback) {
    var visible = true;

    if (!callback) {
        throw new Error('no callback given');
    }

    function focused() {
        if (!visible) {
            callback(visible = true);
        }
    }

    function unfocused() {
        if (visible) {
            callback(visible = false);
        }
    }

    // Standards:
    if ('hidden' in document) {
        document.addEventListener('visibilitychange',
            function() {(document.hidden ? unfocused : focused)()});
    }
    if ('mozHidden' in document) {
        document.addEventListener('mozvisibilitychange',
            function() {(document.mozHidden ? unfocused : focused)()});
    }
    if ('webkitHidden' in document) {
        document.addEventListener('webkitvisibilitychange',
            function() {(document.webkitHidden ? unfocused : focused)()});
    }
    if ('msHidden' in document) {
        document.addEventListener('msvisibilitychange',
            function() {(document.msHidden ? unfocused : focused)()});
    }
    // IE 9 and lower:
    if ('onfocusin' in document) {
        document.onfocusin = focused;
        document.onfocusout = unfocused;
    }
    // All others:
    window.onpageshow = window.onfocus = focused;
    window.onpagehide = window.onblur = unfocused;
};


像这样使用它:

onVisibilityChange(function(visible) {
    console.log('the page is now', visible ? 'focused' : 'unfocused');
});


此版本听针对所有不同的可见性事件,并在其中任何一个引起更改的情况下触发回调。如果多个API捕获到相同的可见性更改,则focusedunfocused处理程序可确保不会多次调用该回调。

评论


例如,Chrome浏览器同时具有document.hidden和document.webkitHidden。如果在if构造中没有else,我们会得到2个回调调用吗?

–克里斯蒂安·韦斯特贝克(Christiaan Westerbeek)
18年8月23日在15:28

@ChristiaanWesterbeek很好,我没想到!如果您可以编辑这篇文章,请继续,我会接受:)

–丹尼尔·巴克马斯特(Daniel Buckmaster)
18年8月27日在1:14



嘿,等等:编辑由ChristiaanWesterbeek建议并由@ 1.21Gigawatts实际添加的“ else”似乎不是一个好主意:它击败了Daniel最初购买的想法,即尝试所有受支持的方法并行方法。而且没有回调被调用两次的风险,因为focused()和unfocused()在没有任何变化的情况下会抑制额外的调用。看来我们应该恢复到第一次转速。

–路易·森普里尼(Louis Semprini)
19年6月16日在3:35

@LouisSemprini很棒。我忘记了代码的初衷!我已经恢复了原件并添加了解释!

–丹尼尔·巴克马斯特(Daniel Buckmaster)
19-6-27在7:36



从今天开始进行检查,至少在Chrome 78 + macOS上未检测到alt + tab

–Hugo Gresse
19年12月11日在17:07

#8 楼

var visibilityChange = (function (window) {
    var inView = false;
    return function (fn) {
        window.onfocus = window.onblur = window.onpageshow = window.onpagehide = function (e) {
            if ({focus:1, pageshow:1}[e.type]) {
                if (inView) return;
                fn("visible");
                inView = true;
            } else if (inView) {
                fn("hidden");
                inView = false;
            }
        };
    };
}(this));

visibilityChange(function (state) {
    console.log(state);
});


http://jsfiddle.net/ARTsinn/JTxQY/

#9 楼

我仍然没有在足够多的浏览器上对此进行测试。
如果您可以找到有关此功能无效的更多信息,请在下面的评论中告诉我。

评论


在我的测试中,它还适用于IE9,IE10和Android上的Chrome。

–托尼·兰帕达(TonyLâmpada)
2013年9月17日18:31

看来IPAD需要一个完全不同的解决方案-stackoverflow.com/questions/4940657/…

–托尼·兰帕达(TonyLâmpada)
2013年9月17日18:50

所有这些链接都是404s :(

–丹尼尔·巴克马斯特(Daniel Buckmaster)
16年8月2日,0:24

#10 楼

这对我适用于chrome 67,firefox 67,

if(!document.hasFocus()) {
    // do stuff
}


#11 楼

您可以使用:

(function () {

    var requiredResolution = 10; // ms
    var checkInterval = 1000; // ms
    var tolerance = 20; // percent


    var counter = 0;
    var expected = checkInterval / requiredResolution;
    //console.log('expected:', expected);

    window.setInterval(function () {
        counter++;
    }, requiredResolution);

    window.setInterval(function () {
        var deviation = 100 * Math.abs(1 - counter / expected);
        // console.log('is:', counter, '(off by', deviation , '%)');
        if (deviation > tolerance) {
            console.warn('Timer resolution not sufficient!');
        }
        counter = 0;
    }, checkInterval);

})();


#12 楼

在HTML 5中,您还可以使用:



onpageshow:当窗口可见时运行的脚本

onpagehide:当窗口可见时运行的脚本窗口被隐藏

请参见:


https://developer.mozilla.org/zh-CN/docs/Web/Events/pageshow
https://developer.mozilla.org/zh-CN/docs/Web/Events/pagehide


评论


我认为这与BFCache有关:当用户单击“上一步”或“前进”时,它与计算机桌面顶部的页面无关。

–nonopolarity
13年7月11日在7:07

#13 楼

稍微复杂一点的方法是使用setInterval()检查鼠标位置并与上一次检查进行比较。如果鼠标没有在设定的时间内移动,则用户可能处于空闲状态。

这具有附加的优点,即告诉用户是否空闲,而不仅仅是检查窗口是否处于空闲状态。活跃。

正如许多人指出的那样,这并不总是一种检查用户或浏览器窗口是否空闲的好方法,因为用户甚至可能没有使用鼠标或正在观看视频。或类似内容。我只是建议一种检查空闲状态的方法。

评论


除非用户没有鼠标。

–user1686
09年6月29日在19:36

@Annan:现在是codinghorror.com/blog/2007/03/…。

–奇堡
2011年6月16日14:34

如果用户正在观看视频,这也不会玩骰子

– jamiew
2011-11-29 17:32

您可以使用onkeypress或其他类似事件重置计时器并解决非鼠标问题。当然,对于主动查看页面以观看视频,学习图像等的用户而言,它仍然行不通。

– joshuahedlund
2012年1月10日21:34

#14 楼

这是对Andy E.答案的改编。

这将完成一项任务,例如每30秒刷新一次页面,
,但仅当页面可见且焦点清晰时。

如果无法检测到可见性,则仅使用焦点。

如果用户将页面放在焦点上,那么它将立即更新

直到ajax调用后30秒,页面才会再次更新

var windowFocused = true;
var timeOut2 = null;

$(function(){
  $.ajaxSetup ({
    cache: false
  });
  $("#content").ajaxComplete(function(event,request, settings){
       set_refresh_page(); // ajax call has just been made, so page doesn't need updating again for 30 seconds
   });
  // check visibility and focus of window, so as not to keep updating unnecessarily
  (function() {
      var hidden, change, vis = {
              hidden: "visibilitychange",
              mozHidden: "mozvisibilitychange",
              webkitHidden: "webkitvisibilitychange",
              msHidden: "msvisibilitychange",
              oHidden: "ovisibilitychange" /* not currently supported */
          };
      for (hidden in vis) {
          if (vis.hasOwnProperty(hidden) && hidden in document) {
              change = vis[hidden];
              break;
          }
      }
      document.body.className="visible";
      if (change){     // this will check the tab visibility instead of window focus
          document.addEventListener(change, onchange,false);
      }

      if(navigator.appName == "Microsoft Internet Explorer")
         window.onfocus = document.onfocusin = document.onfocusout = onchangeFocus
      else
         window.onfocus = window.onblur = onchangeFocus;

      function onchangeFocus(evt){
        evt = evt || window.event;
        if (evt.type == "focus" || evt.type == "focusin"){
          windowFocused=true; 
        }
        else if (evt.type == "blur" || evt.type == "focusout"){
          windowFocused=false;
        }
        if (evt.type == "focus"){
          update_page();  // only update using window.onfocus, because document.onfocusin can trigger on every click
        }

      }

      function onchange () {
        document.body.className = this[hidden] ? "hidden" : "visible";
        update_page();
      }

      function update_page(){
        if(windowFocused&&(document.body.className=="visible")){
          set_refresh_page(1000);
        }
      }


  })();
  set_refresh_page();
})

function get_date_time_string(){
  var d = new Date();
  var dT = [];
  dT.push(d.getDate());
  dT.push(d.getMonth())
  dT.push(d.getFullYear());
  dT.push(d.getHours());
  dT.push(d.getMinutes());
  dT.push(d.getSeconds());
  dT.push(d.getMilliseconds());
  return dT.join('_');
}

function do_refresh_page(){

// do tasks here

// e.g. some ajax call to update part of the page.

// (date time parameter will probably force the server not to cache)

//      $.ajax({
//        type: "POST",
//        url: "someUrl.php",
//        data: "t=" + get_date_time_string()+"&task=update",
//        success: function(html){
//          $('#content').html(html);
//        }
//      });

}

function set_refresh_page(interval){
  interval = typeof interval !== 'undefined' ? interval : 30000; // default time = 30 seconds
  if(timeOut2 != null) clearTimeout(timeOut2);
  timeOut2 = setTimeout(function(){
    if((document.body.className=="visible")&&windowFocused){
      do_refresh_page();
    }
    set_refresh_page();
  }, interval);
}


评论


依靠焦点/模糊方法不起作用(它给您带来很多误报),请参阅stackoverflow.com/a/9502074/698168

–朱利恩·克朗格(Julien Kronegg)
2012年9月7日14:43在

#15 楼

对于没有jQuery的解决方案,请查看Visibility.js,其中提供了有关三个页面状态的信息

visible    ... page is visible
hidden     ... page is not visible
prerender  ... page is being prerendered by the browser


以及setInterval的便捷包装

/* Perform action every second if visible */
Visibility.every(1000, function () {
    action();
});

/* Perform action every second if visible, every 60 sec if not visible */
Visibility.every(1000, 60*1000, function () {
    action();
});


还提供了针对旧版浏览器(IE <10; iOS <7)的后备版本

评论


浏览器支持如何?目前,您可以使用Chrome,Safari和Firefox进行分叉。

–塞尔瓦·加纳帕蒂(Selva Ganapathi)
3月24日,11:11

#16 楼

对于angular.js,这是一条指令(基于公认的答案),它可使您的控制器对可见性的变化做出反应:

myApp.directive('reactOnWindowFocus', function($parse) {
    return {
        restrict: "A",
        link: function(scope, element, attrs) {
            var hidden = "hidden";
            var currentlyVisible = true;
            var functionOrExpression = $parse(attrs.reactOnWindowFocus);

          // Standards:
          if (hidden in document)
            document.addEventListener("visibilitychange", onchange);
          else if ((hidden = "mozHidden") in document)
            document.addEventListener("mozvisibilitychange", onchange);
          else if ((hidden = "webkitHidden") in document)
            document.addEventListener("webkitvisibilitychange", onchange);
          else if ((hidden = "msHidden") in document)
            document.addEventListener("msvisibilitychange", onchange);
          else if ("onfocusin" in document) {
                // IE 9 and lower:
            document.onfocusin = onshow;
                document.onfocusout = onhide;
          } else {
                // All others:
            window.onpageshow = window.onfocus = onshow;
                window.onpagehide = window.onblur = onhide;
            }

          function onchange (evt) {
                //occurs both on leaving and on returning
                currentlyVisible = !currentlyVisible;
                doSomethingIfAppropriate();
          }

            function onshow(evt) {
                //for older browsers
                currentlyVisible = true;
                doSomethingIfAppropriate();
            }

            function onhide(evt) {
                //for older browsers
                currentlyVisible = false;
                doSomethingIfAppropriate();
            }

            function doSomethingIfAppropriate() {
                if (currentlyVisible) {
                    //trigger angular digest cycle in this scope
                    scope.$apply(function() {
                        functionOrExpression(scope);
                    });
                }
            }
        }
    };

});


您可以使用它像这个例子:<div react-on-window-focus="refresh()">,其中refresh()是作用域中的作用域函数,无论控制器在作用域中是什么。

#17 楼

这对我有用
document.addEventListener("visibilitychange", function() {
      document.title = document.hidden ? "I'm away" : "I'm here";
});


#18 楼

这是一个可靠的现代解决方案。 (短小👌🏽)

document.addEventListener("visibilitychange", () => {
  console.log( document.hasFocus() )
})


这将设置侦听器,以在激发可见性事件(可能是焦点或模糊)时触发。

#19 楼

如果您想对整个浏览器进行模糊处理,请按照以下步骤操作:
我评论过,如果浏览器失去焦点,则不会触发任何建议的事件。我的想法是循环计数并在发生事件时重置计数器。如果计数器达到极限,我可以在location.href到另一页。如果您使用开发工具,这也会触发。

var iput=document.getElementById("hiddenInput");
   ,count=1
   ;
function check(){
         count++;
         if(count%2===0){
           iput.focus();
         }
         else{
           iput.blur();
         }
         iput.value=count;  
         if(count>3){
           location.href="http://Nirwana.com";
         }              
         setTimeout(function(){check()},1000);
}   
iput.onblur=function(){count=1}
iput.onfocus=function(){count=1}
check();


这是在FF上成功测试的草案。