有没有办法检测浏览器窗口当前是否处于活动状态?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有没有办法检测浏览器窗口当前是否处于活动状态?相关的知识,希望对你有一定的参考价值。

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

有没有办法使用JavaScript?

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

答案

自从最初撰写此答案以来,由于W3C,新规范已达到推荐状态。 Page Visibility API(在MDN上)现在允许我们更准确地检测何时页面对用户隐藏。

目前的浏览器支持

  • Chrome 13+
  • Internet Explorer 10+
  • Firefox 10+
  • Opera 12.10+ [read notes]

以下代码使用API​​,回退到不兼容的浏览器中不太可靠的模糊/焦点方法。

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

onfocusinonfocusoutrequired for IE 9 and lower,而所有其他人都使用onfocusonblur,除了使用onpageshowonpagehideios

另一答案

你可以用:

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

})();
另一答案

html 5中,您还可以使用:

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

看到:

另一答案

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

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

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

另一答案

这是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);
}
另一答案

对于没有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)的后备也可用

另一答案

对于angular.js,这是一个指令(基于接受的答案),它将允许您的控制器对可见性的变化作出反应:

myApp.directive('reactOnWindowFocus', function($parse) {
    return {
        restrict: "A",
        link: function(scope, element, attrs) {
          

以上是关于有没有办法检测浏览器窗口当前是否处于活动状态?的主要内容,如果未能解决你的问题,请参考以下文章

检测会话当前是不是处于活动状态并加入而不是开始新的会话

有没有办法检查一个对象的所有孩子是不是都处于活动状态?

如何确定当前视图控制器是不是处于活动状态,如果处于活动状态则执行代码

如何判断浏览器/选项卡是不是处于活动状态[重复]

通过Swift中的触摸检测应用程序何时处于活动状态或非活动状态[重复]

如何监听浏览器当前页面是否处于活动页面(可见或未缩小)