Eu tenho JavaScript que realiza atividades periodicamente. Quando o usuário não está vendo o site (por exemplo, a janela ou a guia não tem foco), seria bom não executar.
Existe uma maneira de fazer isso usando JavaScript?
Meu ponto de referência: o Bate-papo do Gmail emite um som se a janela que você está usando não estiver ativa.
javascript
browser
focus
window
Luke Francl
fonte
fonte
requestAnimationFrame
API ou use o recurso moderno de que a frequência desetTimeout
/setInterval
é reduzida quando a janela não está visível (1 segundo no Chrome, por exemplo).blur
/focus
em navegadores que não a suportam.Respostas:
Desde que escrevemos originalmente esta resposta, uma nova especificação alcançou o status de recomendação graças ao W3C. A API de visibilidade da página (no MDN ) agora nos permite detectar com mais precisão quando uma página está oculta para o usuário.
Suporte atual do navegador:
O código a seguir volta ao método menos desfocado / foco menos confiável em navegadores incompatíveis:
onfocusin
eonfocusout
são necessários para o IE 9 e inferior , enquanto todos os outros fazem uso deonfocus
eonblur
, exceto para iOS, que usaonpageshow
eonpagehide
.fonte
focusin
efocusout
do iframe para a janela superior. Para navegadores mais recentes, você precisaria lidar com os eventosfocus
eblur
em cadawindow
objeto do iframe . Você deve usar o código atualizado que acabei de adicionar, que abrangerá pelo menos esses casos em navegadores mais recentes.Eu usaria o jQuery porque tudo o que você precisa fazer é o seguinte:
Ou pelo menos funcionou para mim.
fonte
window
foco será perdido, o que é correto, mas dependendo de qual seja sua intenção, talvez não seja o que você precisa.Existem três métodos típicos usados para determinar se o usuário pode ver a página HTML, mas nenhum deles funciona perfeitamente:
A API do W3C Page Visibility deve fazer isso (suportada desde: Firefox 10, MSIE 10, Chrome 13). No entanto, essa API somente gera eventos quando a guia do navegador é totalmente substituída (por exemplo, quando o usuário muda de uma guia para outra). A API não gera eventos quando a visibilidade não pode ser determinada com 100% de precisão (por exemplo, Alt + Tab para alternar para outro aplicativo).
O uso de métodos baseados em foco / desfoque fornece muitos falsos positivos. Por exemplo, se o usuário exibir uma janela menor na parte superior da janela do navegador, ela perderá o foco (
onblur
aumentado), mas o usuário ainda poderá vê-lo (portanto, ainda precisará ser atualizado). Veja também http://javascript.info/tutorial/focusPara melhorar os comportamentos imperfeitos descritos acima, uso uma combinação dos 3 métodos: API de visibilidade do W3C, em seguida, foco / desfoque e métodos de atividade do usuário para reduzir a taxa de falsos positivos. Isso permite gerenciar os seguintes eventos:
É assim que funciona: quando o documento perde o foco, a atividade do usuário (como a movimentação do mouse) no documento é monitorada para determinar se a janela está visível ou não. A probabilidade de visibilidade da página é inversamente proporcional à hora da última atividade do usuário na página: se o usuário não faz atividade no documento por um longo tempo, é provável que a página não esteja visível. O código abaixo imita a API de visibilidade da página W3C: ela se comporta da mesma maneira, mas possui uma pequena taxa de falsos positivos. Tem a vantagem de ser multibrowser (testado no Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).
Como atualmente não existe uma solução que funcione em vários navegadores sem falso positivo, é melhor pensar duas vezes em desativar a atividade periódica em seu site.
fonte
Há uma biblioteca interessante disponível no GitHub:
https://github.com/serkanyersen/ifvisible.js
Exemplo:
Testei a versão 1.0.1 em todos os navegadores que tenho e posso confirmar que funciona com:
... e provavelmente todas as versões mais recentes.
Não funciona totalmente com:
.now()
sempre retornatrue
para mim)fonte
Usando: API de visibilidade da página
Eu posso usar ? http://caniuse.com/#feat=pagevisibility
fonte
Crio um Comet Chat para o meu aplicativo e, quando recebo uma mensagem de outro usuário, uso:
fonte
document.hasFocus()
é a maneira mais limpa de fazer isso. Todas as outras maneiras de usar a API de visibilidade ou evento baseado em ou procurar vários níveis de atividade do usuário / falta de atividade tornam-se complicadas demais e cheias de casos e falhas de borda. coloque-o em um intervalo simples e crie um evento personalizado quando os resultados forem alterados. Exemplo: jsfiddle.net/59utucz6/1Comecei a usar a resposta do wiki da comunidade, mas percebi que não estava detectando eventos com a tecla alt-tab no Chrome. Isso ocorre porque ele usa a primeira fonte de eventos disponível e, nesse caso, é a API de visibilidade da página, que no Chrome parece não rastrear as abas alternadas.
Decidi modificar um pouco o script para acompanhar todos os eventos possíveis para alterações no foco da página. Aqui está uma função que você pode incluir:
Use-o assim:
Esta versão escuta todos os diferentes eventos de visibilidade e aciona um retorno de chamada se algum deles causar uma alteração. Os manipuladores
focused
eunfocused
garantem que o retorno de chamada não seja chamado várias vezes se várias APIs capturarem a mesma alteração de visibilidade.fonte
document.hidden
edocument.webkitHidden
. Sem oelse
naif
construção obteríamos 2 chamadas de retorno de chamada certo?Isso é realmente complicado. Parece não haver solução, considerando os seguintes requisitos.
Isso acontece porque:
Dadas essas restrições, é possível implementar uma solução que combine - A página API de visibilidade - desfoque / foco da janela - document.activeElement
Que é capaz de:
Quando o iframe tem foco, seus eventos de desfoque / foco não são invocados e a API de visibilidade da página não é acionada na guia alt +.
Desenvolvi a solução da @ AndyE e implementei esta (quase boa) solução aqui: https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test1.html (desculpe, tive alguns problemas com o JSFiddle).
Isso também está disponível no Github: https://github.com/qmagico/estante-components
Isso funciona em cromo / cromo. Ele funciona no firefox, exceto pelo fato de não carregar o conteúdo do iframe (alguma ideia por que?)
De qualquer forma, para resolver o último problema (4), a única maneira de fazer isso é ouvir eventos de desfoque / foco no iframe. Se você tiver algum controle sobre os iframes, poderá usar a API postMessage para fazer isso.
https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test2.html
Ainda não testei isso com navegadores suficientes. Se você puder encontrar mais informações sobre onde isso não funciona, entre em contato nos comentários abaixo.
fonte
http://jsfiddle.net/ARTsinn/JTxQY/
fonte
isso funciona para mim no chrome 67, firefox 67,
fonte
você pode usar:
fonte
No HTML 5, você também pode usar:
onpageshow
: Script a ser executado quando a janela se tornar visívelonpagehide
: Script a ser executado quando a janela estiver ocultaVejo:
fonte
Esta é uma adaptação da resposta de Andy E.
Isso fará uma tarefa, por exemplo, atualizar a página a cada 30 segundos, mas apenas se a página estiver visível e focada.
Se a visibilidade não puder ser detectada, apenas o foco será usado.
Se o usuário focar a página, ele será atualizado imediatamente
A página não será atualizada novamente até 30 segundos após qualquer chamada ajax
fonte
Para uma solução sem jQuery, acesse Visibility.js, que fornece informações sobre três estados de página
e também wrappers de conveniência para setInterval
Também está disponível um fallback para navegadores mais antigos (IE <10; iOS <7)
fonte
Uma maneira um pouco mais complicada seria usar
setInterval()
para verificar a posição do mouse e comparar com a última verificação. Se o mouse não se mover em um período de tempo definido, o usuário provavelmente está ocioso.Isso tem a vantagem adicional de dizer se o usuário está ocioso, em vez de apenas verificar se a janela não está ativa.Como muitas pessoas apontaram, essa nem sempre é uma boa maneira de verificar se a janela do usuário ou do navegador está ociosa, pois o usuário pode nem estar usando o mouse ou assistindo a um vídeo ou semelhante. Estou apenas sugerindo uma maneira possível de verificar a ociosidade.
fonte
Para angular.js, aqui está uma diretiva (baseada na resposta aceita) que permitirá que seu controlador reaja a uma alteração na visibilidade:
Você pode usá-lo como este exemplo:,
<div react-on-window-focus="refresh()">
Onderefresh()
está uma função de escopo no escopo de qualquer Controller que esteja no escopo.fonte
Aqui está uma solução sólida e moderna. (Curto um doce 👌🏽)
Isso configurará um ouvinte para disparar quando qualquer evento de visibilidade for disparado, o que poderia ser um foco ou um borrão.
fonte
Se você deseja atuar em todo o borrão do navegador : Como comentei, se o navegador perder o foco, nenhum dos eventos sugeridos será acionado. Minha idéia é contar em um loop e redefinir o contador se um evento disparar. Se o contador atingir um limite, eu faço um location.href para outra página. Isso também dispara se você trabalha com dev-tools.
Este é um rascunho testado com sucesso no FF.
fonte