Wie kann man mit Javascript erkennen, ob ein Tab in Chrome fokussiert ist oder nicht?

75

Ich muss wissen, ob der Nutzer gerade einen Tab in Google Chrome anzeigt oder nicht. Ich habe versucht, die an das Fenster gebundene Ereignisunschärfe und den Fokus zu verwenden, aber nur die Unschärfe scheint korrekt zu funktionieren.

window.addEventListener('focus', function() {
  document.title = 'focused';
});

window.addEventListener('blur', function() {
  document.title = 'not focused';
});

Das Fokusereignis funktioniert nur manchmal seltsam. Wenn ich zu einer anderen Registerkarte und zurück wechsle, wird das Fokusereignis nicht aktiviert. Aber wenn ich auf die Adressleiste und dann wieder auf die Seite klicke, wird es. Wenn ich zu einem anderen Programm und dann zurück zu Chrome wechsle, wird es aktiviert, wenn die Registerkarte derzeit fokussiert ist.

fent
quelle
Haben Sie versucht, diese Ereignisse docmentanstelle von anzuhängen window?
Crozin
Ich bin nicht sicher, ob es die Ereigniserkennung beeinflusst, aber die window.focusAktion ist in Chrome deaktiviert (oder zumindest fehlerhaft). Weitere Informationen finden Sie hier und hier .
Brahn
Funktioniert auch nicht mit Dokumenten und dies gilt für das Fokusereignis, nicht für die Fokusaktion. Ich denke, ich werde meinen Ansatz ändern und das Ereignis entweder in Mouseover oder Fenster-Scrollen ändern. Für dieses Szenario ist es angemessen.
Fent
Der Code, den Sie in der Frage haben, funktioniert ab 2011 perfekt in Chrome. Die Lösung funktioniert nicht.
Ninjagecko

Antworten:

129

Update 2015: Der neue HTML5-Weg mit Sichtbarkeits-API (entnommen aus Blowsies Kommentar):

document.addEventListener('visibilitychange', function(){
    document.title = document.hidden; // change tab text for demo
})

Der Code, den das Originalplakat (in der Frage) enthält, funktioniert ab 2011:

window.addEventListener('focus', function() {
    document.title = 'focused';
});

window.addEventListener('blur', function() {
    document.title = 'not focused';
});

Bearbeiten : Ab einigen Monaten in Chrome 14 funktioniert dies immer noch, aber der Benutzer muss mit der Seite interagiert haben, indem er mindestens einmal auf eine beliebige Stelle im Fenster geklickt hat. Das bloße Scrollen und dergleichen reicht nicht aus, damit dies funktioniert. Dadurch window.focus()funktioniert dies auch nicht automatisch. Wenn jemand eine Problemumgehung kennt, erwähnen Sie diese bitte.

Ninjagecko
quelle
1
Um dies zum Laufen zu bringen, ohne dass der Benutzer zuerst auf eine Stelle klicken muss, fügen Sie dem window.onload-Ereignis "window.focus ()" hinzu. Der Nebeneffekt davon ist, dass wenn das Fenster das Ziel eines Links ist und bereits hinter dem aktuellen Fenster geöffnet war, es nach vorne gebracht wird. Beachten Sie, dass diese Lösung nur einen Fokusverlust erkennt, nicht jedoch durch das Wechseln der Registerkarten. Wenn der Fokus beispielsweise darauf zurückzuführen ist, dass der Benutzer in einen
Iframe
<iframe ... onmouseover = "iframeMouse (true)" onmouseout = "iframeMouse (false)"> </ iframe>
SPitBalls.com
Funktion iframeMouse (over) {oif = over; } window.addEventListener ('blur', function () {document.title = oif? "iframe fokussiert": "nicht fokussiert";});
SPitBalls.com
5
Eine ausführlichere und zuverlässigere Antwort finden Sie hier. forums.greensock.com/topic/…
Blowsie
2
Verwenden Sie document.visibilityState, um den aktuellen Sichtbarkeitsstatus zu erhalten
Oleg
2

Es könnte doch funktionieren, ich wurde neugierig und schrieb diesen Code:

...
setInterval ( updateSize, 500 );
function updateSize(){
  if(window.outerHeight == window.innerHeight){
    document.title = 'not focused';             
  } else {
    document.title = 'focused';
  }

  document.getElementById("arthur").innerHTML = window.outerHeight + " - " + window.innerHeight;
}
...
<div id="arthur">
  dent
</div>

Dieser Code macht genau das, was Sie wollen, aber auf hässliche Weise. Die Sache ist, Chrome scheint die Titeländerung von Zeit zu Zeit zu ignorieren (wenn Sie zum Tab wechseln und die Maus 1 Sekunde lang gedrückt halten, scheint dies immer zu bewirken).

Sie erhalten unterschiedliche Werte auf Ihrem Bildschirm, Ihr Titel ändert sich jedoch nicht.

Fazit: Was auch immer Sie tun, vertrauen Sie dem Ergebnis beim Testen nicht!

Bastiaan Linders
quelle
Der Titel ändert sich sofort für mich. Wenn ich die Ereignisse auf Mouseover und Mouseout ändere, erhalte ich sofort Ergebnisse.
Fent
Wie auch immer, danke für den Teil (window.outerHeight == window.innerHeight). Für dieses spezielle Projekt muss ich nur wissen, ob der Benutzer derzeit fokussiert ist oder nicht. Sie müssen nicht ständig nachsehen, und Ihr Code funktioniert.
Fent
2

Für alle, die Seitentitel bei Unschärfe austauschen und dann im Fokus zum ursprünglichen Seitentitel zurückkehren möchten:

// Swapping page titles on blur
var originalPageTitle = document.title;

window.addEventListener('blur', function(){
    document.title = 'Don\'t forget to read this...';
});

window.addEventListener('focus', function(){
    document.title = originalPageTitle;
});
stacigh
quelle
0

Ich fand heraus, dass das Hinzufügen von onblur = und onfocus = Ereignissen zu Inline das Problem umging:

Trass Vasston
quelle
0

Dies könnte mit JQuery funktionieren

$(function() {
    $(window).focus(function() {
        console.log('Focus');
    });

    $(window).blur(function() {
        console.log('Blur');
    });
});
Konga Raju
quelle
Ich denke, das wird nicht helfen, da der Browser, wie er berichtet hat, KEINE Ereignisfunktion auslöst, die Sie in "Unschärfe" angehängt haben. So wie in Ihrem Beispiel und Code console.log('Blur');wird in einigen Situationen NICHT aufgerufen.
Psulek
-2

In Chrome können Sie ein Hintergrundskript mit einer Zeitüberschreitung von weniger als 1 Sekunde ausführen. Wenn die Registerkarte keinen Fokus hat, wird Chrome nur jede Sekunde ausgeführt. Beispiel;

Dies funktioniert nicht in Firefox oder Opera. Ich weiß nichts über andere Browser, aber ich bezweifle, dass es auch dort funktioniert.

var currentDate = new Date();
var a = currentDate.getTime();

function test() {
    var currentDate = new Date();
    var b = currentDate.getTime();
var c = b - a;
    if (c > 900) {
        //Tab does not have focus.
    } else {
        //It does
    }
    a = b;
    setTimeout("test()",800);
}



setTimeout("test()",1);
Ben Vail
quelle
2
Ich mag die Idee nicht, Intervalle für etwas zu verwenden, das ereignisreich sein sollte. Und beachten Sie, dass Sie verwenden sollten setTimeout(test, 800). Wenn Sie ihm eine Zeichenfolge geben, wird eval()es, was viel viel langsamer ist.
Fent