检测浏览器标签是否有焦点

IT技术 javascript optimization polling
2021-01-22 02:03:33

是否有可靠的跨浏览器方式来检测选项卡是否具有焦点。

场景是我们有一个应用程序定期轮询股票价格,如果页面没有焦点,我们可以停止轮询并为每个人节省交通噪音,特别是当人们喜欢打开具有不同投资组合的多个标签时。

window.onblurwindow.onfocus这个选项?

6个回答

是的,window.onfocus并且window.onblur应该为您的方案的工作:

http://www.thefutureoftheweb.com/blog/detect-browser-window-focus

@SteveFenton -onfocus是跨浏览器,你提到的事件仅限于 IE,我不明白为什么你会认为这是一个很好的笔记..
2021-03-21 02:03:33
你能不能至少提一下两者之间的区别?
2021-03-23 02:03:33
@vsync - 阅读链接的文章,您会看到它同时使用“onfocusin”和“onfocus”。
2021-03-28 02:03:33
请注意,您无法通过这种方式在页面加载时区分页面处于活动状态还是非活动状态。
2021-04-03 02:03:33
这方面的 onfocusin/onfocusout 方面,以及关于告诉用户您已暂停的注释都是非常好的注释。谢谢。
2021-04-04 02:03:33

重要编辑:此答案已过时。自从编写它以来,已经引入了 Visibility API( mdn example spec)。这是解决这个问题的更好方法。


var focused = true;

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

AFAIK,focus并且blur都支持......一切。(见http://www.quirksmode.org/dom/events/index.html

请注意,使用所有这些解决方案,您可能会冒着用户在 javascript 完全加载之前更改选项卡的风险,从而将错误的值分配给focused。不确定有没有好的解决方法。
2021-03-14 02:03:33
问题具体是检测页面是否有焦点,这与检测页面是否可见是不同的。多个页面可以同时可见(在不同的窗口中),而只有一个可以有焦点。使用适合您需要的任何技术,但要知道其中的区别。
2021-03-22 02:03:33
这是一个危险的解决方案,因为它冒着在更大的应用程序中覆盖其他一些事件侦听器的风险。你应该按照这个答案:stackoverflow.com/a/21935031/549503
2021-04-03 02:03:33
更新链接正是我正在寻找的。感谢您添加它们!
2021-04-06 02:03:33

令人惊讶的是没有人提到 document.hasFocus

if (document.hasFocus()) console.log('Tab is active')

MDN 有更多信息。

真的,这不是完美的答案吗?有没有人看到任何缺点?
2021-03-22 02:03:33
唯一的缺点是,如果您尝试从 iframe 中确定选项卡是否处于焦点状态,那么如果在父页面仍处于焦点之外时加载 iframe,它就会失败。为了涵盖这一点,您必须使用页面可见性 api。
2021-03-25 02:03:33
对我有用(在 Chrome 和 Firefox 上测试过)。接受的答案(的onfocus /的onblur)做工作
2021-03-26 02:03:33
正确答案再次出现在最底部。去 StackOverflow 的方式!
2021-04-06 02:03:33
如果您只是单击选项卡标题,则 document.hasFocus() 值不会更改,因为它在文档上,您必须单击文档才能看到更改。这是一个缺点。
2021-04-07 02:03:33

在搜索这个问题时,我发现应该使用Page Visibility API的建议根据 Can I Use:http : //caniuse.com/#feat=pagevisibility ,大多数现代浏览器都支持此 API

这是一个工作示例(源自此代码段):

$(document).ready(function() {
  var hidden, visibilityState, visibilityChange;

  if (typeof document.hidden !== "undefined") {
    hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
  } else if (typeof document.msHidden !== "undefined") {
    hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
  }

  var document_hidden = document[hidden];

  document.addEventListener(visibilityChange, function() {
    if(document_hidden != document[hidden]) {
      if(document[hidden]) {
        // Document hidden
      } else {
        // Document shown
      }

      document_hidden = document[hidden];
    }
  });
});

更新:上面的例子曾经有 Gecko 和 WebKit 浏览器的前缀属性,但我删除了这个实现,因为这些浏览器已经提供了一段时间没有前缀的页面可见性 API。为了与 IE10 保持兼容,我保留了 Microsoft 特定的前缀。

@Ajedi32 谢谢。我需要做一些测试和挖掘以查看它仍然相关的内容,以及现在可以忽略的内容。
2021-03-16 02:03:33
这是对所有现代浏览器执行此操作的正确方法。+1
2021-03-22 02:03:33
当供应商前缀从这里开始时,我可能会切换!
2021-03-24 02:03:33
唯一真正的问题不是供应商前缀,因为有官方的 W3C 建议(日期为 2013 年 10 月 29 日)。某些情况下的问题是 IE10 及更新版本支持页面可见性 API。如果你需要支持 IE9,你应该寻找不同的方法......
2021-03-31 02:03:33
您确定这些供应商前缀甚至是必需的吗?根据 MDN 和 CanIUse 的说法,Chrome 自 32 版以来就不再需要它们,自 17 版以来在 Firefox 上就不再需要它们,并且它们在 IE 上也不再需要了。
2021-04-01 02:03:33

我会这样做(参考http://www.w3.org/TR/page-visibility/):

    window.onload = function() {

        // check the visiblility of the page
        var hidden, visibilityState, visibilityChange;

        if (typeof document.hidden !== "undefined") {
            hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
        }
        else if (typeof document.mozHidden !== "undefined") {
            hidden = "mozHidden", visibilityChange = "mozvisibilitychange", visibilityState = "mozVisibilityState";
        }
        else if (typeof document.msHidden !== "undefined") {
            hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
        }
        else if (typeof document.webkitHidden !== "undefined") {
            hidden = "webkitHidden", visibilityChange = "webkitvisibilitychange", visibilityState = "webkitVisibilityState";
        }


        if (typeof document.addEventListener === "undefined" || typeof hidden === "undefined") {
            // not supported
        }
        else {
            document.addEventListener(visibilityChange, function() {
                console.log("hidden: " + document[hidden]);
                console.log(document[visibilityState]);

                switch (document[visibilityState]) {
                case "visible":
                    // visible
                    break;
                case "hidden":
                    // hidden
                    break;
                }
            }, false);
        }

        if (document[visibilityState] === "visible") {
            // visible
        }

    };  
谢谢@confile!该代码是不言自明且易于使用的。将此作为一个函数来实现,它就像一个魅力——跨浏览器和跨平台,包括移动浏览器!
2021-03-29 02:03:33
您能解释一下这个答案与@Ilija 给出的答案有何不同-可能存在差异,但很微妙-因此对它是什么以及为什么应该不同的解释将不胜感激。
2021-03-31 02:03:33