¿Cómo detectar el tiempo de inactividad en JavaScript de forma elegante?

¿Es posible detectar el tiempoinactivo ” en JavaScript?
Mi caso de uso principal probablemente sea precargar o precargar contenido.

Tiempo de inactividad : Periodo de inactividad del usuario o sin uso de CPU

Aquí hay un script simple usando JQuery que maneja los eventos mousemove y keypress. Si el tiempo expira, la página se recarga.

 

Sin usar jQuery, solo JavaScript:

 var inactivityTime = function () { var t; window.onload = resetTimer; // DOM Events document.onmousemove = resetTimer; document.onkeypress = resetTimer; function logout() { alert("You are now logged out.") //location.href = 'logout.php' } function resetTimer() { clearTimeout(t); t = setTimeout(logout, 3000) // 1000 milisec = 1 sec } }; 

Créditos: http://forums.devshed.com/javascript-development-115/alert-time-inactivity-click-logout-501444.html

Puede agregar más eventos DOM si lo necesita. Los más utilizados son:

 document.onload = resetTimer; document.onmousemove = resetTimer; document.onmousedown = resetTimer; // touchscreen presses document.ontouchstart = resetTimer; document.onclick = resetTimer; // touchpad clicks document.onscroll = resetTimer; // scrolling with arrow keys document.onkeypress = resetTimer; 

Lista de eventos DOM : http://www.w3schools.com/jsref/dom_obj_event.asp

Recuerde usar window , o document según sus necesidades. Aquí puede ver las diferencias entre ellos: ¿Cuál es la diferencia entre ventana, pantalla y documento en Javascript?

Mejorando la respuesta de Equiman:

 function idleLogout() { var t; window.onload = resetTimer; window.onmousemove = resetTimer; window.onmousedown = resetTimer; // catches touchscreen presses as well window.ontouchstart = resetTimer; // catches touchscreen swipes as well window.onclick = resetTimer; // catches touchpad clicks as well window.onkeypress = resetTimer; window.addEventListener('scroll', resetTimer, true); // improved; see comments function yourFunction() { // your function for too long inactivity goes here // eg window.location.href = 'logout.php'; } function resetTimer() { clearTimeout(t); t = setTimeout(yourFunction, 10000); // time is in milliseconds } } idleLogout(); 

.
Además de las mejoras relacionadas con la detección de actividades y el cambio de un document a otro, este script realmente llama a la función, en lugar de dejarla inactiva.

No detecta el uso de CPU cero directamente, pero eso es imposible, porque la ejecución de una función provoca el uso de la CPU. Y la inactividad del usuario lleva finalmente a un uso cero de la CPU, por lo que indirectamente no detecta el uso de la CPU.

Creé una lib pequeña que hace esto hace un año:

https://github.com/shawnmclean/Idle.js

Descripción:

Tiny javascript library para informar la actividad del usuario en el navegador (lejos, inactivo, sin mirar la página web, en una pestaña diferente, etc.). eso es independiente de cualquier otra librería javascript como jquery.

Los usuarios de Visual Studio pueden obtenerlo de NuGet por: PM> Install-Package Idle.js

Aquí hay una implementación aproximada de jQuery de la idea de tvanfosson:

 $(document).ready(function(){ idleTime = 0; //Increment the idle time counter every second. var idleInterval = setInterval(timerIncrement, 1000); function timerIncrement() { idleTime++; if (idleTime > 2) { doPreload(); } } //Zero the idle timer on mouse movement. $(this).mousemove(function(e){ idleTime = 0; }); function doPreload() { //Preload images, etc. } }) 

Similar a la solución de Iconic anterior (con evento personalizado jQuery) …

 // use jquery-idle-detect.js script below $(window).on('idle:start', function(){ //start your prefetch etc here... }); $(window).on('idle:stop', function(){ //stop your prefetch etc here... }); 

 //jquery-idle-detect.js (function($,$w){ // expose configuration option // idle is triggered when no events for 2 seconds $.idleTimeout = 2000; // currently in idle state var idle = false; // handle to idle timer for detection var idleTimer = null; //start idle timer and bind events on load (not dom-ready) $w.on('load', function(){ startIdleTimer(); $w.on('focus resize mousemove keyup', startIdleTimer) .on('blur',idleStart) //force idle when in a different tab/window ; ]); function startIdleTimer() { clearTimeout(idleTimer); //clear prior timer if (idle) $w.trigger('idle:stop'); //if idle, send stop event idle = false; //not idle var timeout = ~~$.idleTimeout; // option to integer if (timeout < = 100) timeout = 100; // min 100ms if (timeout > 300000) timeout = 300000; // max 5 minutes idleTimer = setTimeout(idleStart, timeout); //new timer } function idleStart() { if (!idle) $w.trigger('idle:start'); idle = true; } }(window.jQuery, window.jQuery(window))) 

Puedes hacerlo de forma más elegante con guión bajo y jquery –

 $('body').on("click mousemove keyup", _.debounce(function(){ // do preload here }, 1200000)) // 20 minutes debounce 

Sé que es una pregunta relativamente vieja, pero tuve el mismo problema y encontré una solución bastante buena.

Utilicé: jquery.idle y solo tuve que hacer:

 $(document).idle({ onIdle: function(){ alert('You did nothing for 5 seconds'); }, idle: 5000 }) 

Vea la demostración de JsFiddle .

(Solo para obtener información: vea esto para el seguimiento de eventos de back-end lleva a la carga del navegador )

Mi respuesta fue inspirada por la respuesta de vijay , pero es una solución más corta y general que pensé que compartiría para cualquiera que pudiera ser útil.

 (function () { var minutes = true; // change to false if you'd rather use seconds var interval = minutes ? 60000 : 1000; var IDLE_TIMEOUT = 3; // 3 minutes in this example var idleCounter = 0; document.onmousemove = document.onkeypress = function () { idleCounter = 0; }; window.setInterval(function () { if (++idleCounter >= IDLE_TIMEOUT) { window.location.reload(); // or whatever you want to do } }, interval); }()); 

Tal como está actualmente, este código se ejecutará inmediatamente y volverá a cargar su página actual después de 3 minutos sin movimiento del mouse ni pulsación de teclas.

Esto utiliza JavaScript normal sin formato y una expresión de función invocada inmediatamente para manejar los tiempos de espera inactivos de una manera limpia y autónoma.

Probablemente puedas hackear algo juntos al detectar el movimiento del mouse en el cuerpo del formulario y al actualizar una variable global con el último tiempo de movimiento. Entonces necesitaría tener un temporizador de intervalo en funcionamiento que verifique periódicamente el último tiempo de movimiento y haga algo si ha sido lo suficientemente largo desde que se detectó el último movimiento del mouse.

Prueba esto es perfecto trabajo ..

 var IDLE_TIMEOUT = 10; //seconds var _idleSecondsCounter = 0; document.onclick = function () { _idleSecondsCounter = 0; }; document.onmousemove = function () { _idleSecondsCounter = 0; }; document.onkeypress = function () { _idleSecondsCounter = 0; }; window.setInterval(CheckIdleTime, 1000); function CheckIdleTime() { _idleSecondsCounter++; var oPanel = document.getElementById("SecondsUntilExpire"); if (oPanel) oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + ""; if (_idleSecondsCounter >= IDLE_TIMEOUT) { alert("Time expired!"); document.location.href = "SessionExpired.aspx"; } } 
  

¡Creo que este código jquery es perfecto, aunque copiado y modificado a partir de las respuestas anteriores! ¡no olvide incluir la biblioteca jquery en su archivo!

Todas las respuestas anteriores tienen un controlador de movimiento de mouse siempre activo. Si el manejador es jQuery, el procesamiento adicional que realiza jQuery puede sumr. Especialmente si el usuario usa un mouse para juegos, pueden ocurrir hasta 500 eventos por segundo.

Esta solución evita el manejo de cada evento mousemove. Esto da como resultado un pequeño error de tiempo, pero que puede ajustar a su necesidad.

 function setIdleTimeout(millis, onIdle, onUnidle) { var timeout = 0; $(startTimer); function startTimer() { timeout = setTimeout(onExpires, millis); $(document).on("mousemove keypress", onActivity); } function onExpires() { timeout = 0; onIdle(); } function onActivity() { if (timeout) clearTimeout(timeout); else onUnidle(); //since the mouse is moving, we turn off our event hooks for 1 second $(document).off("mousemove keypress", onActivity); setTimeout(startTimer, 1000); } } 

http://jsfiddle.net/q8wLuLbw/

Escribí un plugin jQuery simple que hará lo que estás buscando.

https://github.com/afklondon/jquery.inactivity

 $(document).inactivity( { interval: 1000, // the timeout until the inactivity event fire [default: 3000] mouse: true, // listen for mouse inactivity [default: true] keyboard: false, // listen for keyboard inactivity [default: true] touch: false, // listen for touch inactivity [default: true] customEvents: "customEventName", // listen for custom events [default: ""] triggerAll: true, // if set to false only the first "activity" event will be fired [default: false] }); 

El script escuchará el mouse, el teclado, el tacto y otros eventos personalizados inactivos (inactivos) y activará eventos globales de “actividad” e “inactividad”.

Espero que esto ayude 🙂

Si su objective es Chrome, puede experimentar con requestIdleCallback

JavaScript puro con tiempo de reinicio y enlaces correctamente establecidos mediante addEventListener

 (function() { var t, timeout = 5000; function resetTimer() { console.log("reset: " + new Date().toLocaleString()); if (t) { window.clearTimeout(t); } t = window.setTimeout(logout, timeout); } function logout() { console.log("done: " + new Date().toLocaleString()); } resetTimer(); //And bind the events to call `resetTimer()` ["click", "mousemove", "keypress"].forEach(function(name) { console.log(name); document.addEventListener(name, resetTimer); }); }()); 

He probado este código de archivo de trabajo:

 var timeout = null; var timee = '4000'; // default time for session time out. $(document).bind('click keyup mousemove', function(event) { if (timeout !== null) { clearTimeout(timeout); } timeout = setTimeout(function() { timeout = null; console.log('Document Idle since '+timee+' ms'); alert("idle window"); }, timee); }); 

El problema con todas estas soluciones, aunque correctas, no es práctico, al tener en cuenta el valioso set de tiempo de espera de sesión, utilizando PHP, .NET o en el archivo Application.cfc para los desarrolladores de Coldfusion. El tiempo establecido por la solución anterior debe sincronizarse con el tiempo de espera de la sesión del lado del servidor. Si los dos no se sincronizan, puede encontrarse con problemas que simplemente frustrarán y confundirán a los usuarios. Por ejemplo, el tiempo de espera de la sesión del servidor puede establecerse en 60 minutos, pero el usuario puede creer que está seguro, porque la captura de tiempo inactiva de JavaScript ha aumentado la cantidad total de tiempo que un usuario puede pasar en una sola página. El usuario puede haber pasado tiempo rellenando un formulario largo, y luego va a enviarlo. El tiempo de espera de la sesión puede iniciarse antes de que se procese el envío del formulario. Tiendo a solo dar 180 minutos a mis usuarios y luego uso JavaScript para registrar automáticamente al usuario. Básicamente, utilizando parte del código anterior, para crear un temporizador simple, pero sin la captura de la parte del evento del mouse. De esta forma, mi lado del lado del cliente y del servidor se sincroniza perfectamente. No hay confusión, si le muestra el tiempo al usuario en su UI, ya que reduce. Cada vez que se accede a una nueva página en el CMS, se restablecen la sesión del lado del servidor y el temporizador de JavaScript. Simple y elegante. Si un usuario permanece en una sola página durante más de 180 minutos, en primer lugar, creo que hay algún problema con la página.

Aquí está la mejor solución que he encontrado: http://css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/

Aquí está el JS:

 idleTimer = null; idleState = false; idleWait = 2000; (function ($) { $(document).ready(function () { $('*').bind('mousemove keydown scroll', function () { clearTimeout(idleTimer); if (idleState == true) { // Reactivated event $("body").append("

Welcome Back.

"); } idleState = false; idleTimer = setTimeout(function () { // Idle Event $("body").append("

You've been idle for " + idleWait/1000 + " seconds.

"); idleState = true; }, idleWait); }); $("body").trigger("mousemove"); }); }) (jQuery)

Puedes usar la solución mencionada a continuación

 var idleTime; $(document).ready(function () { reloadPage(); $('html').bind('mousemove click mouseup mousedown keydown keypress keyup submit change mouseenter scroll resize dblclick', function () { clearTimeout(idleTime); reloadPage(); }); }); function reloadPage() { clearTimeout(idleTime); idleTime = setTimeout(function () { location.reload(); }, 3000); } 

Utilizo este enfoque, ya que no necesita reiniciar constantemente la hora cuando se activa un evento, sino que simplemente registramos el tiempo, esto genera el punto de inicio inactivo.

  function idle(WAIT_FOR_MINS, cb_isIdle) { var self = this, idle, ms = (WAIT_FOR_MINS || 1) * 60000, lastDigest = new Date(), watch; //document.onmousemove = digest; document.onkeypress = digest; document.onclick = digest; function digest() { lastDigest = new Date(); } // 1000 milisec = 1 sec watch = setInterval(function(){ if (new Date() - lastDigest > ms && cb_isIdel) { clearInterval(watch); cb_isIdle(); } }, 1000*60); }, 

Probablemente pueda detectar la inactividad en su página web utilizando los trucos de mousemove enumerados, pero eso no le dirá que el usuario no está en otra página en otra ventana o pestaña, o que el usuario está en Word o Photoshop, o WOW y simplemente no está mirando tu página en este momento. En general, simplemente hago la captación previa y confío en la multitarea del cliente. Si realmente necesita esta funcionalidad, puede hacer algo con un control activex en Windows, pero en el mejor de los casos es feo.

Para otros usuarios con el mismo problema. Aquí hay una función que acabo de inventar.

NO se ejecuta en cada movimiento del mouse que hace el usuario, o borra un temporizador cada vez que se mueve el mouse.

  

Aquí hay un servicio AngularJS para lograr en Angular.

 /* Tracks now long a user has been idle. secondsIdle can be polled at any time to know how long user has been idle. */ fuelServices.factory('idleChecker',['$interval', function($interval){ var self = { secondsIdle: 0, init: function(){ $(document).mousemove(function (e) { self.secondsIdle = 0; }); $(document).keypress(function (e) { self.secondsIdle = 0; }); $interval(function(){ self.secondsIdle += 1; }, 1000) } } return self; }]); 

Tenga en cuenta que este comprobador inactivo se ejecutará para todas las rutas, por lo que debe inicializarse en .run() al cargar la aplicación angular. Luego puede usar idleChecker.secondsIdle dentro de cada ruta.

 myApp.run(['idleChecker',function(idleChecker){ idleChecker.init(); }]); 

(Parcialmente inspirado por la buena lógica central de Equiman anteriormente en este hilo).

sessionExpiration.js


sessionExpiration.js es liviano pero efectivo y personalizable. Una vez implementado, utilícelo en una sola fila:

 sessionExpiration(idleMinutes, warningMinutes, logoutUrl); 
  • Afecta a todas las tabs del navegador, no solo a una.
  • Escrito en JavaScript puro , sin dependencias. Totalmente del lado del cliente.
  • (Si así lo desea.) Tiene una pancarta de advertencia y un reloj de cuenta atrás , que se cancela por la interacción del usuario.
  • Simplemente incluya la sesiónExpiration.js y llame a la función, con argumentos [1] cantidad de minutos inactivos (en todas las tabs) hasta que el usuario cierre sesión, [2] número de minutos inactivos hasta que se muestre la advertencia y la cuenta atrás, y [3] logout url.
  • Coloque el CSS en su hoja de estilo. Personalízalo si quieres. (O salte y elimine el banner si no lo desea).
  • Sin embargo, si desea el letrero de advertencia, debe colocar un div vacío con ID sessExpirDiv en su página (una sugerencia es ponerlo en el pie de página) .
  • Ahora el usuario se cerrará automáticamente si todas las tabs han estado inactivas durante la duración dada.

Este es un ejemplo de cómo se ve en acción, si no cambia el CSS.

demo_image

Escribí una pequeña clase de ES6 para detectar actividad y, de lo contrario, desencadenar eventos en tiempo de espera inactivo. Cubre teclado, mouse y tacto , se puede activar y desactivar y tiene una API muy pobre:

 const timer = new IdleTimer(() => alert('idle for 1 minute'), 1000 * 60 * 1); timer.activate(); 

No depende de jQuery, aunque es posible que deba ejecutarlo a través de Babel para admitir navegadores más antiguos.

https://gist.github.com/4547ef5718fd2d31e5cdcafef0208096

Podría publicarlo como un paquete npm una vez que reciba algún comentario.

Solo algunos pensamientos, una avenida o dos para explorar.

¿Es posible tener una función ejecutada cada 10 segundos y hacer que marque una variable “contador”? Si eso es posible, puede tener un mouseover para la página, ¿no es así? Si es así, use el evento mouseover para restablecer la variable “contador”. Si se llama a su función, y el contador está por encima del rango que usted determina previamente, entonces realice su acción.

De nuevo, solo algunos pensamientos … Espero que ayude.

Bien, podría adjuntar un evento de clic o mousemove al cuerpo del documento que restablece un temporizador. Tenga una función a la que llame a intervalos de tiempo que comprueben si el temporizador está en un tiempo determinado (como 1000 milisegundos) e inicie su precarga.

Intenté la solución @freddoo pero no funcionó durante 1 minuto, así que la cambié ligeramente para registrar la fecha y la hora en que el usuario hizo clic por última vez en la página y en mi función timerIncrement calculo la diferencia entre la hora actual y la hora actual. la última vez que se hizo clic y si el valor es mayor o igual al valor de tiempo de espera, entonces redirijo:

 var clickedDate = new Date(); var idleTime = 1;// function timerIncrement() { var nowDate = new Date(); var diffMs = (nowDate - clickedDate); //Milliseconds between now & the last time a user clicked somewhere on the page var diffMins = Math.round(((diffMs % 86400000) % 3600000) / 60000); //Convert ms to minutes if (diffMins >= idleTime) { //Redirect user to home page etc... } } $(document).ready(function () { var idleInterval = setInterval(timerIncrement, 60000); // 1 minute $(this).click(function (e) { clickedDate = new Date(); }); }); 

Javascript no tiene forma de decir el uso de la CPU. Esto rompería el sandbox que javascript ejecuta dentro.

Aparte de eso, conectar los eventos onmouseover y onkeydown de la página probablemente funcione.

También podría establecer el uso de setTimeout en el evento onload para progtwigr una función a la que llamar después de un retraso.

 // Call aFunction after 1 second window.setTimeout(aFunction, 1000);