Tarayıcı Sekmesinin Odaklanıp Odaklanmadığını Algıla


154

Bir sekmenin odaklandığını algılamanın güvenilir bir çapraz tarayıcı yolu var mı?

Senaryo, hisse senedi fiyatları için düzenli olarak anket yapan bir uygulamamız olması ve eğer sayfanın odak noktası yoksa, oylamayı durdurabilir ve herkesi trafik gürültüsünden kurtarabiliriz, özellikle de insanlar farklı portföylere sahip birkaç sekme açmanın hayranları olduklarından.

window.onblurve window.onfocusbunun için bir seçenek?


Evet bunlar sizin için çalışmalı. Bana bu teknikleri kullanan, karşılaştığım bu bağlantıyı hatırlattın. ilginç okuma
Brian Glaz

Yanıtlar:


136

Evet window.onfocusve window.onblursenaryonuz için çalışmalıdır:

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


3
Bunun odak dışı / odak dışı yönü ve ayrıca kullanıcıya duraklattığınızı söylemeyle ilgili not gerçekten iyi notlardır. Teşekkürler.
Fenton

7
Lütfen bu şekilde sayfa yüklenirken sayfanın etkin olup olmadığını ayırt edemeyeceğinizi unutmayın.
pimvdb

@SteveFenton - onfocusbahsettiğiniz olayların yalnızca IE'ye yönelik olduğu çapraz tarayıcıdır , bunun neden sizin tarafınızdan iyi bir not olarak kabul edildiğini anlayamıyorum ..
vsync

1
@vsync - bağlantılı makaleyi okuyun, hem 'onfocusin' hem de 'onfocus' kullandığını göreceksiniz .
Fenton

En azından ikisi arasındaki farktan bahsedebilir misiniz?
Lenar Hoyt

58

Önemli Düzenleme: Bu cevap güncel değildir. Yazıldığından beri Görünürlük API'si ( mdn , örnek , spesifikasyon ) tanıtıldı. Bu sorunu çözmenin daha iyi yolu budur.


var focused = true;

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

AFAIK focusve blurhepsi ... her şeyde destekleniyor. (bkz. http://www.quirksmode.org/dom/events/index.html )


2
Küçük bir not, tüm bu çözümlerle, javascript tam olarak yüklenmeden önce kullanıcının sekmeleri değiştirme riskini alırsınız, böylece odaklanmışa yanlış değeri atarsınız. Etrafında iyi bir yol olduğundan emin değilim.
JayD3e

Güncelleme bağlantıları tam olarak aradığım şey. Onları eklediğiniz için teşekkürler!
webLacky3rdClass

Soru, özellikle, sayfanın görünür olup olmadığını tespit etmekten farklı olarak, bir sayfanın odaklanıp odaklanmadığını tespit etmekle ilgilidir. Aynı anda birden fazla sayfa görülebilir (farklı pencerelerde), ancak yalnızca biri odaklanabilir. İhtiyaçlarınıza uyan tekniği kullanın, ancak farkı bilin.
jaredjacobs

1
Bu tehlikeli bir çözümdür çünkü daha büyük bir uygulamada başka bir olay dinleyicisini geçersiz kılma riskini taşır. Bunun yerine şu yanıtı izlemelisiniz: stackoverflow.com/a/21935031/549503
mmmeff

55

Bu sorunu araştırırken, Sayfa Görünürlüğü API'sinin kullanılması gerektiğine dair bir öneri buldum . Modern tarayıcıların çoğu, Kullanabilir miyim? Uyarınca bu API'yi destekler: http://caniuse.com/#feat=pagevisibility .

İşte çalışan bir örnek ( bu pasajdan türetilmiştir ):

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

Güncelleme: Yukarıdaki örnek, Gecko ve WebKit tarayıcıları için önekli özelliklere sahipti, ancak bu uygulamayı kaldırdım çünkü bu tarayıcılar bir süredir önek olmadan Sayfa Görünürlüğü API'si sunuyorlar. IE10 ile uyumlu kalabilmek için Microsoft'a özgü ön eki sakladım.


Satıcı önekleri bundan sonra, muhtemelen değiştireceğim!
Fenton

Bununla ilgili tek gerçek sorun, satıcı önekleri değildir, çünkü resmi bir W3C tavsiyesi vardır (29. Ekim 2013 tarihli). Bazı durumlarda sorun olan şey, sayfa görünürlük API'sinin IE10 ve daha yeni sürümlerde desteklenmesidir. IE9'u desteklemeniz gerekiyorsa, farklı bir yaklaşım
Ilija

Tüm modern tarayıcılar için bunu yapmanın doğru yolu budur. +1
Ajedi32

Bu satıcı öneklerinin gerekli olduğundan bile emin misiniz? MDN ve CanIUse'a göre, sürüm 32'den beri Chrome'da veya sürüm 17'den beri Firefox'ta gerekli olmadılar ve IE'de hiç gerekli olmadılar.
Ajedi32

@ Ajedi32 Teşekkürler. Neyin hala alakalı olduğunu ve şimdi neyin dışarıda bırakılabileceğini görmek için bazı testler yapmam ve kazmam gerekecek.
Ilija

46

Kimsenin bahsetmediğini görmek şaşırtıcı document.hasFocus

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

MDN daha fazla bilgiye sahiptir.


benim için çalışıyor (Chrome ve Firefox'ta test edildi). Kabul cevap (onfocus / Onblur) did not çalışmak
harmv

1
Doğru cevap yine en altta. StackOverflow'a gitmenin yolu!
Ekim

gerçekten, bu mükemmel cevap değil mi? herhangi bir olumsuzluk gören var mı?
gaspar

2
Bunun tek dezavantajı, sekmenin bir iframe içinden odakta olup olmadığını belirlemeye çalışıyorsanız, üst sayfa hala odak dışındayken iframe yüklenmesi durumunda başarısız olacaktır. Bunu da kapatmak için sayfa görünürlüğü API'sine gitmeniz gerekecek.
Ivan

4

Bunu şu şekilde yapardım (Referans 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
        }

    };  

Bu cevabın @Ilija tarafından verilen cevaptan nasıl farklı olduğunu açıklayabilir misiniz - bir fark olabilir, ancak ince - bu yüzden ne olduğu ve neden farklı olması gerektiğine dair bir açıklama takdir edilecektir.
Fenton

2

Çapraz Tarayıcı jQuery Çözümü! GitHub'da ham olarak mevcuttur

Eğlenceli ve Kullanımı Kolay!

Aşağıdaki eklenti, IE, Chrome, Firefox, Safari vb. Çeşitli sürümleri için standart testinizden geçecek ve buna göre beyan edilen yöntemlerinizi oluşturacaktır. Ayrıca aşağıdaki gibi konularla da ilgilenir:

  • onblur | .blur / onfocus | .focus " yinelenen " çağrılar
  • kelime gibi alternatif uygulama seçimiyle odağı kaybeden pencere
    • Bu istenmeyen bir durumdur çünkü eğer açık bir banka sayfanız varsa ve bu onblur olayı ona sayfayı maskelemesini söylerse, o zaman hesap makinesini açarsanız, artık sayfayı göremezsiniz!
  • Sayfa yüklemede tetiklenmiyor

: Kullanımı için basit gibidir 'gidin Aşağı Run Snippet'ine '

$.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>


Eklenti için kodu küçültmeden koymalısınız.
Patrick Desjardins

@PatrickDesjardins evet. Bunu bu hafta sonu diğer şeylerle birlikte yapmayı planlayın. BEN? Sahip olduğum bir sürü şey için bir öz oluştur. Github'da Jdmckinstry. Bunları
özüne ekledikçe

"Word" veya "Hesap Makinesi" gibi başka bir uygulamaya geçtiğimde sayfanın odağını kaybetmesini istersem ne olur?
Benas

@Benas Yanlış olabilir, ancak bunun jQuery(window).blur/focusbirçokları tarafından istenmeyen temel işlevinin temel işlevi olduğuna inanıyorum , bu yüzden bu eklentiyi yapmamın nedenlerinden biri. Eklenti,
jQuery'nin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.