Na verdade, há uma API de visibilidade de página, documentada no MDN .
No entanto, ele só funciona quando o usuário alterna as guias dentro da janela do navegador. Se a janela do navegador em si perder o foco (enquanto sua guia estiver selecionada), a API de visibilidade da página não dirá que você perdeu o foco! Isso pode ser visto nesta página de demonstração para a API de visibilidade . Veja o que acontece quando alterna entre as guias e quando você alterna para outra janela.
Por outro lado, temos uma função genérica, document.hasFocus
que pode nos dizer se a guia está focada ou não, neste momento.
Também temos eventos de “desfoque” e “foco” anexados ao window
objeto, que são disparados quando o navegador entra ou sai de foco.
A API de visibilidade expõe outro evento, “visibilitychange”, que é disparado quando a guia atual sai de foco (dentro do contexto da janela do navegador).
Precisamos combinar esses dois mecanismos. Usarei o knockout porque nos dá observáveis que podemos “assinar” quando eles mudam; que usaremos para detectar eventos de foco.
var page_has_focus = ko.observable();
var checkFocus = function() {
page_has_focus(document.hasFocus());
}
Em seguida, nos inscrevemos em todos os eventos que mudam o foco:
document.addEventListener("visibilitychange", checkFocus);
window.addEventListener("focus", checkFocus);
window.addEventListener("blur", checkFocus);
Mas espere, há um problema. Nem todos os navegadores expõem o evento de alteração de visibilidade como “alteração de visibilidade”. Consulte novamente os documentos MDN para isso.
Então, nós o tornamos cross-browser:
var visibilityChange;
if (typeof document.hidden !== "undefined") {
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
visibilityChange = "webkitvisibilitychange";
}
document.addEventListener(visibilityChange, checkFocus);
window.addEventListener("focus", checkFocus);
window.addEventListener("blur", checkFocus);
E para tornar o código mais limpo, envolvemos tudo em um IIFE (função imediatamente invocada) e para torná-lo extra robusto, retornaremos uma versão somente leitura do observável, envolvendo-o em um cálculo simples.
Então, aqui está o resultado:
var page_has_focus = (function() {
var page_has_focus = ko.observable();
var checkFocus = function() {
page_has_focus(document.hasFocus());
}
checkFocus(); // init
var visibilityChange;
if (typeof document.hidden !== "undefined") {
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
visibilityChange = "webkitvisibilitychange";
}
document.addEventListener(visibilityChange, checkFocus);
window.addEventListener("focus", checkFocus);
window.addEventListener("blur", checkFocus);
return ko.computed(function() {
return page_has_focus();
});
})();
Agora vamos testar!
Digite o seguinte no console:
page_has_focus.subscribe(function(yes) {
if(yes) {
console.log("Page got focus");
} else {
console.log("Page lost focus");
}
});
Agora, se você alternar as guias e voltar, verá “A página perdeu o foco” seguido por uma mensagem “A página obteve o foco” no console.
Se você mudar para outro aplicativo e voltar, verá o mesmo.
Você também pode tentar alternar para outro aplicativo de forma que o console ainda esteja visível; e você ainda verá o mesmo resultado.
Observação: o próprio console conta como outra guia; então, depois de digitar o código no console, clique dentro do documento para focalizá-lo.