Is there a way to detect if a browser window is not currently active?

前端 未结 19 2047
无人共我
无人共我 2020-11-21 04:40

I have JavaScript that is doing activity periodically. When the user is not looking at the site (i.e., the window or tab does not have focus), it\'d be nice to not run.

相关标签:
19条回答
  • 2020-11-21 04:44

    I started off using the community wiki answer, but realised that it wasn't detecting alt-tab events in Chrome. This is because it uses the first available event source, and in this case it's the page visibility API, which in Chrome seems to not track alt-tabbing.

    I decided to modify the script a bit to keep track of all possible events for page focus changes. Here's a function you can drop in:

    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;
    };
    

    Use it like this:

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

    This version listens for all the different visibility events and fires a callback if any of them causes a change. The focused and unfocused handlers make sure that the callback isn't called multiple times if multiple APIs catch the same visibility change.

    0 讨论(0)
  • 2020-11-21 04:47

    I create a Comet Chat for my app, and when I receive a message from another user I use:

    if(new_message){
        if(!document.hasFocus()){
            audio.play();
            document.title="Have new messages";
        }
        else{
            audio.stop();
            document.title="Application Name";
        } 
    }
    
    0 讨论(0)
  • 2020-11-21 04:48

    In HTML 5 you could also use:

    • onpageshow: Script to be run when the window becomes visible
    • onpagehide: Script to be run when the window is hidden

    See:

    • https://developer.mozilla.org/en-US/docs/Web/Events/pageshow
    • https://developer.mozilla.org/en-US/docs/Web/Events/pagehide
    0 讨论(0)
  • 2020-11-21 04:48

    If you want to act on whole browser blur: As I commented, if browser lose 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.

    0 讨论(0)
  • 2020-11-21 04:51

    Since originally writing this answer, a new specification has reached recommendation status thanks to the W3C. The Page Visibility API (on MDN) now allows us to more accurately detect when a page is hidden to the user.

    document.addEventListener("visibilitychange", onchange);
    

    Current browser support:

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

    The following code falls back to the less reliable blur/focus method in incompatible browsers:

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

    onfocusin and onfocusout are required for IE 9 and lower, while all others make use of onfocus and onblur, except for iOS, which uses onpageshow and onpagehide.

    0 讨论(0)
  • 2020-11-21 04:51

    Here is a solid, modern solution. (Short a sweet

    0 讨论(0)
提交回复
热议问题