有没有一种方法可以检测浏览器窗口当前是否未激活?

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

有没有办法使用JavaScript做到这一点?

我的参考点:如果您使用的窗口未激活,则Gmail聊天会播放声音。

猴子神乐2020/03/12 12:36:47

If you want to act on whole browser blur: As I commented, if browser loose focus none of the suggested events fire. My idea is to count up in a loop and reset the counter if an event fire. If the counter reach a limit I do a location.href to an other page. This also fire if you work on dev-tools.

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();

This is a draft successful tested on FF.

神无伽罗阳光2020/03/12 12:36:47

Here is a solid, modern solution. (Short a sweet 👌🏽)

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

This will setup a listener to trigger when any visibility event is fired which could be a focus or blur.

Tom老丝Pro2020/03/12 12:36:47

For a solution without jQuery check out Visibility.js which provides information about three page states

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

and also convenience-wrappers for 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();
});

A fallback for older browsers (IE < 10; iOS < 7) is also available

YOC715882172020/03/12 12:36:47

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

  • onpageshow:窗口可见时要运行的脚本
  • onpagehide:隐藏窗口时运行的脚本

看到:

神无StafanTom2020/03/12 12:36:47

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

if(!document.hasFocus()) {
    // do stuff
}
JinJin宝儿2020/03/12 12:36:47
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/

斯丁前端2020/03/12 12:36:47

这真的很棘手。鉴于以下要求,似乎没有解决方案。

  • 该页面包含您无法控制的iframe
  • 无论跟踪是由TAB更改(ctrl + tab)还是由窗口更改(alt + tab)触发的,您都希望跟踪可见性状态更改

发生这种情况是因为:

  • 页面Visibility API可以可靠地告诉您选项卡的更改(即使使用iframe也是如此),但是它不能告诉您用户何时更改窗口。
  • 只要iframe没有焦点,聆听窗口模糊/焦点事件就可以检测alt + tab和ctrl + tab。

鉴于这些限制,可以实现一个结合以下解决方案的解决方案-页面可见性API-窗口模糊/焦点-document.activeElement

能够:

  • 1)父页面具有焦点时按Ctrl + Tab:是
  • 2)当iframe具有焦点时,按ctrl + tab:是
  • 3)当父页面具有焦点时,按alt + tab:是
  • 4)当iframe具有焦点时,按alt + tab: <-讨厌

当iframe具有焦点时,根本不会调用您的模糊/焦点事件,并且页面可见性API不会在alt + tab上触发。

我以@AndyE的解决方案为基础,并在此处实现了这个(几乎是很好的)解决方案:https : //dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test1.html(对不起,我在JSFiddle上遇到了一些麻烦)。

这也可以在Github上获得:https : //github.com/qmagico/estante-components

这适用于铬/铬。除了不加载iframe内容(知道为什么?)以外,它在Firefox上都可以使用

无论如何,要解决最后一个问题(4),唯一的方法是在iframe上监听模糊/聚焦事件。如果您对iframe有所控制,则可以使用postMessage API来执行此操作。

https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test2.html

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

米亚Near2020/03/12 12:36:46

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
  • FF 26.0
  • 镀铬34.0

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

不能与以下产品完全配合使用:

  • IE8-始终指示选项卡/窗口当前处于活动状态(.now()始终true为我返回
梅十三Near2020/03/12 12:36:46

我为我的应用创建了彗星聊天,当我收到其他用户的消息时,我使用:

if(new_message){
    if(!document.hasFocus()){
        audio.play();
        document.title="Have new messages";
    }
    else{
        audio.stop();
        document.title="Application Name";
    } 
}
米亚凯2020/03/12 12:36:46

我将使用jQuery,因为那么您要做的就是:

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

或者至少对我有用。

古一Mandy2020/03/12 12:36:46

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

document.addEventListener("visibilitychange", onchange);

当前的浏览器支持:

  • 铬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"});
})();

onfocusinIE 9及更低版本onfocusout必需的,而其他所有语言都使用onfocusonblur(iOS除外,后者使用onpageshow和)onpagehide