web-dev-qa-db-fra.com

Détecter si l'onglet du navigateur a le focus

Existe-t-il un moyen fiable, multi-navigateur, de détecter qu'un onglet est actif?.

Le scénario est que nous avons une application qui interroge régulièrement les cours des actions et si la page n’est pas ciblée, nous pouvons arrêter le sondage et épargner le bruit de la circulation pour tout le monde, d’autant plus que les utilisateurs sont fans d’ouvrir plusieurs onglets avec différents portefeuilles.

Est window.onblur et window.onfocus une option pour cela?

127
Fenton

Oui, window.onfocus et window.onblur devrait fonctionner pour votre scénario:

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

109
Ryan Wright

Important Modifier: Cette réponse est obsolète. Depuis son écriture, l'API de visibilité ( mdn , exemple , spec ) a été introduit. C'est le meilleur moyen de résoudre ce problème.


var focused = true;

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

Autant que je sache, focus et blur sont tous pris en charge sur ... tout. (voir http://www.quirksmode.org/dom/events/index.html )

46
Zirak

En cherchant sur ce problème, j'ai trouvé une recommandation selon laquelle API de visibilité de la page devrait être utilisé. La plupart des navigateurs modernes prennent en charge cette API conformément à Puis-je utiliser: http://caniuse.com/#feat=pagevisibility .

Voici un exemple de travail (dérivé de cet extrait ):

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

Mise à jour: L'exemple ci-dessus avait des propriétés préfixées pour les navigateurs Gecko et WebKit, mais j'ai supprimé cette implémentation, car ces navigateurs offraient une API de visibilité des pages sans préfixe depuis un moment maintenant. J'ai gardé le préfixe spécifique à Microsoft afin de rester compatible avec IE10.

41
Ilija

Oui, ceux-ci devraient fonctionner pour vous. Vous venez de me rappeler de ce lien que j'ai découvert qui exploite ces techniques. lecture intéressante

29
Brian Glaz

Surprenant de ne voir personne mentionné document.hasFocus

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

MDN a plus d'informations.

21
aleclarson

Je le ferais de cette façon (référence 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
        }

    };  
4
confile

Solution jQuery croisée sur le navigateur!  Raw disponible sur GitHub

Fun & Facile à utiliser!

Le plug-in suivant passera par votre test standard pour différentes versions d'IE, Chrome, Firefox, Safari, etc. et établira vos méthodes déclarées en conséquence. Il traite également de questions telles que:

  • onblur | .blur/onfocus | .focus " dupliquer" appelle
  • fenêtre perdant le focus en sélectionnant une autre application, comme Word
    • Cela a tendance à être indésirable simplement parce que, si vous avez une page de banque ouverte et que c'est onblur l'événement lui dit de masquer la page, puis si vous ouvrez la calculatrice, vous ne pouvez plus voir la page. !
  • Ne pas déclencher au chargement de la page

L'utilisation est aussi simple que: Faites défiler vers le bas pour ' Exécuter l'extrait'

$.winFocus(function(event, isVisible) {
    console.log("Combo\t\t", event, isVisible);
});

//  OR Pass False boolean, and it will not trigger on load,
//  Instead, it will first trigger on first blur of current tab_window
$.winFocus(function(event, isVisible) {
    console.log("Combo\t\t", event, isVisible);
}, false);

//  OR Establish an object having methods "blur" & "focus", and/or "blurFocus"
//  (yes, you can set all 3, tho blurFocus is the only one with an 'isVisible' param)
$.winFocus({
    blur: function(event) {
        console.log("Blur\t\t", event);
    },
    focus: function(event) {
        console.log("Focus\t\t", event);
    }
});

//  OR First method becoms a "blur", second method becoms "focus"!
$.winFocus(function(event) {
    console.log("Blur\t\t", event);
},
function(event) {
    console.log("Focus\t\t", event);
});
/*    Begin Plugin    */
;;(function($){$.winFocus||($.extend({winFocus:function(){var a=!0,b=[];$(document).data("winFocus")||$(document).data("winFocus",$.winFocus.init());for(x in arguments)"object"==typeof arguments[x]?(arguments[x].blur&&$.winFocus.methods.blur.Push(arguments[x].blur),arguments[x].focus&&$.winFocus.methods.focus.Push(arguments[x].focus),arguments[x].blurFocus&&$.winFocus.methods.blurFocus.Push(arguments[x].blurFocus),arguments[x].initRun&&(a=arguments[x].initRun)):"function"==typeof arguments[x]?b.Push(arguments[x]):
"boolean"==typeof arguments[x]&&(a=arguments[x]);b&&(1==b.length?$.winFocus.methods.blurFocus.Push(b[0]):($.winFocus.methods.blur.Push(b[0]),$.winFocus.methods.focus.Push(b[1])));if(a)$.winFocus.methods.onChange()}}),$.winFocus.init=function(){$.winFocus.props.hidden in document?document.addEventListener("visibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden="mozHidden")in document?document.addEventListener("mozvisibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden=
"webkitHidden")in document?document.addEventListener("webkitvisibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden="msHidden")in document?document.addEventListener("msvisibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden="onfocusin")in document?document.onfocusin=document.onfocusout=$.winFocus.methods.onChange:window.onpageshow=window.onpagehide=window.onfocus=window.onblur=$.winFocus.methods.onChange;return $.winFocus},$.winFocus.methods={blurFocus:[],blur:[],focus:[],
exeCB:function(a){$.winFocus.methods.blurFocus&&$.each($.winFocus.methods.blurFocus,function(b,c){this.apply($.winFocus,[a,!a.hidden])});a.hidden&&$.winFocus.methods.blur&&$.each($.winFocus.methods.blur,function(b,c){this.apply($.winFocus,[a])});!a.hidden&&$.winFocus.methods.focus&&$.each($.winFocus.methods.focus,function(b,c){this.apply($.winFocus,[a])})},onChange:function(a){var b={focus:!1,focusin:!1,pageshow:!1,blur:!0,focusout:!0,pagehide:!0};if(a=a||window.event)a.hidden=a.type in b?b[a.type]:
document[$.winFocus.props.hidden],$(window).data("visible",!a.hidden),$.winFocus.methods.exeCB(a);else try{$.winFocus.methods.onChange.call(document,new Event("visibilitychange"))}catch(c){}}},$.winFocus.props={hidden:"hidden"})})(jQuery);
/*    End Plugin      */

// Simple example
$(function() {
        $.winFocus(function(event, isVisible) {
                $('td tbody').empty();
                $.each(event, function(i) {
                        $('td tbody').append(
                                $('<tr />').append(
                                        $('<th />', { text: i }),
                                        $('<td />', { text: this.toString() })
                                )
                        )
                });
                if (isVisible) 
                        $("#isVisible").stop().delay(100).fadeOut('fast', function(e) {
                                $('body').addClass('visible');
                                $(this).stop().text('TRUE').fadeIn('slow');
                        });
                else {
                        $('body').removeClass('visible');
                        $("#isVisible").text('FALSE');
                }
        });
})
body { background: #AAF; }
table { width: 100%; }
table table { border-collapse: collapse; margin: 0 auto; width: auto; }
tbody > tr > th { text-align: right; }
td { width: 50%; }
th, td { padding: .1em .5em; }
td th, td td { border: 1px solid; }
.visible { background: #FFA; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h3>See Console for Event Object Returned</h3>
<table>
    <tr>
        <th><p>Is Visible?</p></th>
        <td><p id="isVisible">TRUE</p></td>
    </tr>
    <tr>
        <td colspan="2">
            <table>
                <thead>
                    <tr>
                        <th colspan="2">Event Data <span style="font-size: .8em;">{ See Console for More Details }</span></th>
                    </tr>
                </thead>
                <tbody></tbody>
            </table>
        </td>
    </tr>
</table>
2
SpYk3HH