Tengo JavaScript que realiza actividad periódicamente. Cuando el usuario no está mirando el sitio (es decir, la ventana o pestaña no tiene el foco), sería bueno no ejecutarlo.
¿Hay alguna manera de hacer esto usando JavaScript?
Mi punto de referencia: Gmail Chat reproduce un sonido si la ventana que está utilizando no está activa.
javascript
browser
focus
window
Luke Francl
fuente
fuente
requestAnimationFrame
API o use la función moderna de que la frecuencia desetTimeout
/setInterval
se reduce cuando la ventana no es visible (1 segundo en Chrome, por ejemplo).blur
/focus
en los navegadores que no lo soportan.blur
/focus
eventos ... eso será de uso limitado, ya que una ventana puede estar inactiva pero total o parcialmente visible (también hay iconos de "vista previa" en algunas barras de tareas que la gente espera seguir siendo actualizado).Respuestas:
Desde que escribió originalmente esta respuesta, una nueva especificación ha alcanzado el estado de recomendación gracias al W3C. La API de visibilidad de página (en MDN ) ahora nos permite detectar con mayor precisión cuándo una página está oculta para el usuario.
Soporte actual del navegador:
El siguiente código recurre al método de desenfoque / enfoque menos confiable en navegadores incompatibles:
onfocusin
yonfocusout
son necesarios para IE 9 y versiones anteriores, mientras que todos los demás utilizanonfocus
yonblur
, a excepción de iOS, que utilizaonpageshow
yonpagehide
.fuente
focusin
yfocusout
desde el iframe a la ventana superior. Para los navegadores más nuevos, solo tendría que manejar los eventosfocus
yblur
en elwindow
objeto de cada iframe . Debe usar el código actualizado que acabo de agregar, que al menos cubrirá esos casos en los navegadores más nuevos.Usaría jQuery porque entonces todo lo que tienes que hacer es esto:
O al menos funcionó para mí.
fuente
window
foco se perderá, lo cual es correcto, pero dependiendo de cuál sea su intención, podría no ser lo que necesita.Hay 3 métodos típicos utilizados para determinar si el usuario puede ver la página HTML, sin embargo, ninguno de ellos funciona perfectamente:
Se supone que la API de visibilidad de página W3C debe hacer esto (compatible desde: Firefox 10, MSIE 10, Chrome 13). Sin embargo, esta API solo genera eventos cuando la pestaña del navegador se anula por completo (por ejemplo, cuando el usuario cambia de una pestaña a otra). La API no genera eventos cuando la visibilidad no se puede determinar con una precisión del 100% (por ejemplo, Alt + Tab para cambiar a otra aplicación).
El uso de métodos basados en enfoque / desenfoque le da muchos falsos positivos. Por ejemplo, si el usuario muestra una ventana más pequeña en la parte superior de la ventana del navegador, la ventana del navegador perderá el foco (
onblur
elevado) pero el usuario aún puede verlo (por lo que aún debe actualizarse). Ver también http://javascript.info/tutorial/focusPara mejorar los comportamientos imperfectos descritos anteriormente, utilizo una combinación de los 3 métodos: API de visibilidad W3C, luego enfoque / desenfoque y métodos de actividad del usuario para reducir la tasa de falsos positivos. Esto permite gestionar los siguientes eventos:
Así es como funciona: cuando el documento pierde el foco, la actividad del usuario (como el movimiento del mouse) en el documento se monitorea para determinar si la ventana es visible o no. La probabilidad de visibilidad de la página es inversamente proporcional al tiempo de la última actividad del usuario en la página: si el usuario no realiza actividad en el documento durante mucho tiempo, la página probablemente no sea visible. El siguiente código imita la API de visibilidad de página del W3C: se comporta de la misma manera pero tiene una pequeña tasa de falsos positivos. Tiene la ventaja de ser multi-navegador (probado en Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).
Como actualmente no existe una solución de navegador cruzado que funcione sin falsos positivos, es mejor que lo piense dos veces antes de deshabilitar la actividad periódica en su sitio web.
fuente
Hay una biblioteca ordenada disponible en GitHub:
https://github.com/serkanyersen/ifvisible.js
Ejemplo:
He probado la versión 1.0.1 en todos los navegadores que tengo y puedo confirmar que funciona con:
... y probablemente todas las versiones más nuevas.
No funciona completamente con:
.now()
siempre vuelvetrue
para mí)fuente
Uso: API de visibilidad de página
Puedo usar ? http://caniuse.com/#feat=pagevisibility
fuente
Creo un Chat Comet para mi aplicación, y cuando recibo un mensaje de otro usuario, uso:
fuente
document.hasFocus()
Es la forma más limpia de hacerlo. Todas las otras formas de usar la API de visibilidad o evento basado o buscar varios niveles de actividad del usuario / falta de actividad se vuelven demasiado complicadas y llenas de casos y agujeros. póngalo en un intervalo simple y genere un evento personalizado cuando cambien los resultados. Ejemplo: jsfiddle.net/59utucz6/1Comencé a usar la respuesta wiki de la comunidad, pero me di cuenta de que no estaba detectando eventos de pestaña alternativa en Chrome. Esto se debe a que utiliza la primera fuente de eventos disponible y, en este caso, es la API de visibilidad de la página, que en Chrome parece no rastrear la tabulación alternativa.
Decidí modificar un poco el script para realizar un seguimiento de todos los eventos posibles para los cambios de foco de la página. Aquí hay una función que puede colocar:
Úselo así:
Esta versión escucha todos los diferentes eventos de visibilidad y activa una devolución de llamada si alguno de ellos causa un cambio. Los controladores
focused
y seunfocused
aseguran de que la devolución de llamada no se llame varias veces si varias API detectan el mismo cambio de visibilidad.fuente
document.hidden
ydocument.webkitHidden
. Sin elelse
en laif
construcción tendríamos 2 llamadas de devolución de llamada ¿verdad?Esto es realmente complicado. Parece que no hay solución dados los siguientes requisitos.
Esto sucede porque:
Dadas estas restricciones, es posible implementar una solución que combine: la API de Visibilidad de la página - desenfoque / enfoque de la ventana - document.activeElement
Eso es capaz de:
Cuando el iframe tiene foco, sus eventos de desenfoque / foco no se invocan en absoluto, y la API de Visibilidad de la página no se activará en alt + tab.
Construí sobre la solución de @ AndyE e implementé esta (casi buena) solución aquí: https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test1.html (lo siento, tuve algunos problemas con JSFiddle).
Esto también está disponible en Github: https://github.com/qmagico/estante-components
Esto funciona en cromo / cromo. Funciona en Firefox, excepto que no carga el contenido del iframe (¿alguna idea de por qué?)
De todos modos, para resolver el último problema (4), la única forma de hacerlo es escuchar eventos de desenfoque / enfoque en el iframe. Si tiene algún control sobre los iframes, puede usar la API postMessage para hacerlo.
https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test2.html
Todavía no he probado esto con suficientes navegadores. Si puede encontrar más información sobre dónde esto no funciona, hágamelo saber en los comentarios a continuación.
fuente
http://jsfiddle.net/ARTsinn/JTxQY/
fuente
esto funciona para mí en Chrome 67, Firefox 67,
fuente
puedes usar:
fuente
En HTML 5 también puedes usar:
onpageshow
: Secuencia de comandos que se ejecutará cuando la ventana se vuelva visibleonpagehide
: Secuencia de comandos que se ejecutará cuando la ventana esté ocultaVer:
fuente
Esta es una adaptación de la respuesta de Andy E.
Esto hará una tarea, por ejemplo, actualizar la página cada 30 segundos, pero solo si la página está visible y enfocada.
Si no se puede detectar la visibilidad, solo se utilizará el foco.
Si el usuario enfoca la página, se actualizará inmediatamente
La página no se actualizará nuevamente hasta 30 segundos después de cualquier llamada ajax
fuente
Para una solución sin jQuery, visite Visibility.js que proporciona información sobre tres estados de página
y también envoltorios de conveniencia para setInterval
También está disponible un respaldo para navegadores antiguos (IE <10; iOS <7)
fuente
Una forma un poco más complicada sería usar
setInterval()
para verificar la posición del mouse y comparar con la última verificación. Si el mouse no se ha movido en un tiempo determinado, el usuario probablemente esté inactivo.Esto tiene la ventaja adicional de saber si el usuario está inactivo, en lugar de simplemente verificar si la ventana no está activa.Como muchas personas han señalado, esta no siempre es una buena manera de verificar si el usuario o la ventana del navegador están inactivos, ya que el usuario puede no estar usando el mouse o viendo un video o similar. Solo estoy sugiriendo una posible forma de verificar la inactividad.
fuente
Para angular.js, aquí hay una directiva (basada en la respuesta aceptada) que permitirá que su controlador reaccione ante un cambio de visibilidad:
Puede usarlo como este ejemplo:,
<div react-on-window-focus="refresh()">
donderefresh()
es una función de alcance en el alcance de cualquier controlador que esté en el alcance.fuente
Aquí hay una solución sólida y moderna. (Corto un dulce 👌🏽)
Esto configurará un oyente para que se active cuando se active cualquier evento de visibilidad que podría ser un foco o desenfoque.
fuente
Si desea actuar en todo el desenfoque del navegador : como comenté, si el navegador pierde el foco, ninguno de los eventos sugeridos se activa. Mi idea es contar en un bucle y restablecer el contador si se dispara un evento. Si el contador alcanza un límite, hago un location.href a otra página. Esto también se dispara si trabajas en herramientas de desarrollo.
Este es un borrador probado con éxito en FF.
fuente