È possibile rilevare il tempo " inattivo " in JavaScript?
Il mio caso d'uso principale sarebbe probabilmente precaricare o precaricare il contenuto.
Tempo di inattività: periodo di inattività dell'utente o senza utilizzo della CPU
È possibile rilevare il tempo " inattivo " in JavaScript?
Il mio caso d'uso principale sarebbe probabilmente precaricare o precaricare il contenuto.
Tempo di inattività: periodo di inattività dell'utente o senza utilizzo della CPU
Risposte:
Ecco un semplice script che utilizza JQuery che gestisce gli eventi mousemove e keypress. Se il tempo scade, la pagina viene ricaricata.
<script type="text/javascript">
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
var idleInterval = setInterval(timerIncrement, 60000); // 1 minute
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
});
$(this).keypress(function (e) {
idleTime = 0;
});
});
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 19) { // 20 minutes
window.location.reload();
}
}
</script>
setInterval, che viene quindi valutata come JavaScript.
idleTime++;invece diidleTime = idleTime + 1;
'mousemove keydown click'usare bit flags ( Event.MOUSEMOVE | Event.KEYDOWN | Event.CLICK), poiché sono più veloci delle operazioni sulle stringhe. Ma vuoi davvero farlo?
Senza usare jQuery, solo JavaScript vaniglia:
var inactivityTime = function () {
var time;
window.onload = resetTimer;
// DOM Events
document.onmousemove = resetTimer;
document.onkeypress = resetTimer;
function logout() {
alert("You are now logged out.")
//location.href = 'logout.html'
}
function resetTimer() {
clearTimeout(time);
time = setTimeout(logout, 3000)
// 1000 milliseconds = 1 second
}
};
E avvia la funzione dove ti serve (ad esempio: onPageLoad).
window.onload = function() {
inactivityTime();
}
È possibile aggiungere più eventi DOM, se necessario. I più utilizzati sono:
document.onload = resetTimer;
document.onmousemove = resetTimer;
document.onmousedown = resetTimer; // touchscreen presses
document.ontouchstart = resetTimer;
document.onclick = resetTimer; // touchpad clicks
document.onkeypress = resetTimer;
document.addEventListener('scroll', resetTimer, true); // improved; see comments
Oppure registra gli eventi desiderati utilizzando un array
window.addEventListener('load', resetTimer, true);
var events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
events.forEach(function(name) {
document.addEventListener(name, resetTimer, true);
});
Elenco eventi DOM : http://www.w3schools.com/jsref/dom_obj_event.asp
Ricorda l'uso windowo in documentbase alle tue esigenze. Qui puoi vedere le differenze tra loro: Qual è la differenza tra finestra, schermo e documento in Javascript?
Il codice aggiornato con @ frank-conijn e @daxchen migliora: window.onscrollnon si attiva se lo scorrimento è all'interno di un elemento scorrevole, perché gli eventi di scorrimento non si gonfiano. window.addEventListener('scroll', resetTimer, true), il terzo argomento dice all'ascoltatore di catturare l'evento durante la fase di acquisizione anziché la fase di bolla.
document.onload = function () { inactivityTime(); }; document.onmousedown = function () { inactivityTime(); }; document.onkeypress = function () { inactivityTime(); }; document.ontouchstart = function () { inactivityTime(); };
Migliorare la risposta di 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
// e.g. window.location.href = 'logout.php';
}
function resetTimer() {
clearTimeout(t);
t = setTimeout(yourFunction, 10000); // time is in milliseconds
}
}
idleLogout();
.
A parte i miglioramenti riguardanti il rilevamento delle attività e la modifica da documenta window, questo script in realtà chiama la funzione, piuttosto che lasciarla inattiva.
Non rileva direttamente l'utilizzo della CPU pari a zero, ma ciò è impossibile, poiché l'esecuzione di una funzione provoca l'utilizzo della CPU. E l'inattività dell'utente alla fine porta a zero utilizzo della CPU, quindi indirettamente cattura zero utilizzo della CPU.
window.onscrollnon si attiva se lo scorrimento è all'interno di un elemento scorrevole, perché gli eventi di scorrimento non fanno bolle. Usando window.addEventListener('scroll', resetTimer, true), il terzo argomento dice all'ascoltatore di catturare l'evento durante la capturefase anziché la bubblefase (IE> 8), vedi questa risposta
document.onscrollha lo stesso problema, non sparare se lo scorrimento è all'interno di un bambino scorrevole?
addEventListenerposto di onscroll.
Ho creato una piccola libreria che lo fa un anno fa:
https://github.com/shawnmclean/Idle.js
Descrizione:
Minuscola libreria javascript per segnalare l'attività dell'utente nel browser (assente, inattivo, non guardando la pagina web, in un'altra scheda, ecc.). che è indipendente da qualsiasi altra libreria javascript come jquery.
Gli utenti di Visual Studio possono ottenerlo da NuGet: PM> Install-Package Idle.js
Ecco un'implementazione approssimativa di jQuery dell'idea di 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.
}
})
setIntervaluna stringa! Basta dare una funzione come variabile!
setInterval()valutare l'espressione nell'ambito globale e quindi non troverà la timerIncrement()funzione che si trova all'interno della funzione del gestore .ready. Questa è un'altra ragione per non passare MAI le stringhe setInterval(). Basta passare un riferimento effettivo alla funzione e non si avrà questo problema perché vengono valutati nell'ambito corrente.
Simile alla soluzione di Iconic sopra (con evento personalizzato 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)))
Puoi farlo in modo più elegante con underscore e jquery -
$('body').on("click mousemove keyup", _.debounce(function(){
// do preload here
}, 1200000)) // 20 minutes debounce
La mia risposta è stata ispirata dalla risposta di Vijay , ma è una soluzione più breve e più generale che pensavo di condividere per chiunque potesse aiutare.
(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);
}());
Allo stato attuale, questo codice verrà eseguito immediatamente e ricaricherà la pagina corrente dopo 3 minuti di inattività del mouse o della pressione dei tasti.
Questo utilizza JavaScript semplice alla vaniglia e un'espressione di funzione immediatamente invocata per gestire i timeout di inattività in modo pulito e autonomo.
onclickassegnazione poiché probabilmente non è necessario in aggiunta a onmousemove, ma ovviamente tutti questi eventi che sono attivati a livello di programmazione continueranno a reimpostarsi idleCounter. Non sono sicuro del motivo per cui simuleresti l'interazione dell'utente invece di chiamare semplicemente una funzione, ma se è qualcosa che devi fare per qualche motivo, questa risposta ovviamente non funzionerà per te, né la maggior parte delle altre risposte che ' ho esaminato questa domanda.
Conosco una domanda relativamente vecchia, ma ho avuto lo stesso problema e ho trovato una soluzione abbastanza buona.
Ho usato: jquery.idle e dovevo solo fare:
$(document).idle({
onIdle: function(){
alert('You did nothing for 5 seconds');
},
idle: 5000
})
Guarda la demo di JsFiddle .
(Solo per informazioni: vedere questo per il monitoraggio degli eventi back-end Lead download del browser )
keepTrackingopzione su false. Se si desidera ripristinare, è possibile provare a reinizializzare è. Ecco un esempio modificato che sparerebbe
Tutte le risposte precedenti hanno un gestore mousemove sempre attivo. Se il gestore è jQuery, è possibile aggiungere l'elaborazione aggiuntiva che jQuery esegue. Soprattutto se l'utente utilizza un mouse da gioco, possono verificarsi fino a 500 eventi al secondo.
Questa soluzione evita la gestione di ogni evento mousemove. Ciò si traduce in un piccolo errore di temporizzazione, ma che puoi adattare alle tue necessità.
function setIdleTimeout(millis, onIdle, onUnidle) {
var timeout = 0;
startTimer();
function startTimer() {
timeout = setTimeout(onExpires, millis);
document.addEventListener("mousemove", onActivity);
document.addEventListener("keydown", 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.removeEventListener("mousemove", onActivity);
document.removeEventListener("keydown", onActivity);
setTimeout(startTimer, 1000);
}
}
$(startTimer)è equivalente a $(document).ready(startTimer), assicura che il DOM è pronto prima di agganciare il mousemove ed eventi di pressione.
Probabilmente potresti hackerare qualcosa insieme rilevando il movimento del mouse sul corpo del modulo e aggiornando una variabile globale con l'ultimo tempo di movimento. Dovresti quindi avere un timer ad intervalli che controlla periodicamente l'ultimo tempo di movimento e fa qualcosa se è stato sufficientemente lungo da quando è stato rilevato l'ultimo movimento del mouse.
Ho scritto una piccola classe ES6 per rilevare attività e altrimenti generare eventi in timeout inattivo. Copre tastiera, mouse e touch , può essere attivato e disattivato e ha un'API molto snella:
const timer = new IdleTimer(() => alert('idle for 1 minute'), 1000 * 60 * 1);
timer.activate();
Essa non dipende da jQuery, anche se potrebbe essere necessario eseguire attraverso Babel per supportare i browser più vecchi.
https://gist.github.com/4547ef5718fd2d31e5cdcafef0208096
Potrei rilasciarlo come pacchetto npm una volta ricevuto un feedback.
Se stai scegliendo come target un browser supportato (Chrome o Firefox a dicembre 2018), puoi provare la richiestaIdleCallback e includere lo shim requestIdleCallback per i browser non supportati.
Prova questo codice, funziona perfettamente.
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";
}
}
<script type="text/javascript">
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
idleInterval = setInterval(timerIncrement, 60000); // 1 minute
//Zero the idle timer on mouse movement.
$('body').mousemove(function (e) {
//alert("mouse moved" + idleTime);
idleTime = 0;
});
$('body').keypress(function (e) {
//alert("keypressed" + idleTime);
idleTime = 0;
});
$('body').click(function() {
//alert("mouse moved" + idleTime);
idleTime = 0;
});
});
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 10) { // 10 minutes
window.location.assign("http://www.google.com");
}
}
</script>
Penso che questo codice jquery sia perfetto, anche se copiato e modificato dalle risposte sopra !! non hai dimenticato di includere la libreria jquery nel tuo file!
Il problema con tutte queste soluzioni, sebbene corrette, sono poco pratiche, se si tiene conto del prezioso set di timeout della sessione, utilizzando PHP, .NET o nel file Application.cfc per gli sviluppatori Coldfusion. Il tempo impostato dalla soluzione precedente deve essere sincronizzato con il timeout della sessione lato server. Se i due non si sincronizzano, puoi imbatterti in problemi che potrebbero frustrare e confondere i tuoi utenti. Ad esempio, il timeout della sessione lato server potrebbe essere impostato su 60 minuti, ma l'utente può ritenere che sia sicuro, poiché l'acquisizione del tempo di inattività JavaScript ha aumentato il tempo totale che un utente può trascorrere su una singola pagina. L'utente potrebbe aver trascorso del tempo a compilare un modulo lungo, quindi a inviarlo. Il timeout della sessione potrebbe essere avviato prima che l'elaborazione del modulo venga inviato. Tendo a dare ai miei utenti solo 180 minuti, e quindi utilizzare JavaScript per disconnettere automaticamente l'utente. In sostanza, usando parte del codice sopra, per creare un semplice timer, ma senza la parte di evento del mouse di acquisizione. In questo modo il mio lato client e lato server si sincronizza perfettamente. Non c'è confusione, se si mostra il tempo all'utente nell'interfaccia utente, in quanto riduce. Ogni volta che si accede a una nuova pagina nel CMS, la sessione lato server e il timer JavaScript vengono ripristinati. Semplice ed elegante Se un utente rimane su una singola pagina per più di 180 minuti, immagino che ci sia qualcosa di sbagliato nella pagina, in primo luogo. in quanto riduce. Ogni volta che si accede a una nuova pagina nel CMS, la sessione lato server e il timer JavaScript vengono ripristinati. Semplice ed elegante Se un utente rimane su una singola pagina per più di 180 minuti, immagino che ci sia qualcosa di sbagliato nella pagina, in primo luogo. in quanto riduce. Ogni volta che si accede a una nuova pagina nel CMS, la sessione lato server e il timer JavaScript vengono ripristinati. Semplice ed elegante Se un utente rimane su una singola pagina per più di 180 minuti, immagino che ci sia qualcosa di sbagliato nella pagina, in primo luogo.
JavaScript puro con tempo di reimpostazione e collegamenti impostati correttamente tramite 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);
});
}());
(In parte ispirato alla buona logica di base di Equiman all'inizio di questo thread.)
sessionExpiration.js è leggero ma efficace e personalizzabile. Una volta implementato, utilizzare in una sola riga:
sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
Questo è un esempio di come appare in azione, se non cambi il CSS.
Ho scritto un semplice plugin jQuery che farà quello che stai cercando.
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]
});
Lo script ascolterà l'inattività del mouse, della tastiera, del tocco e di altri eventi personalizzati (inattività) e genererà eventi "attività" e "inattività" globali.
Spero che sia di aiuto :)
Solo qualche pensiero, un viale o due da esplorare.
È possibile eseguire una funzione ogni 10 secondi e verificare che una variabile "counter"? Se è possibile, puoi avere un passaggio del mouse per la pagina, no? In tal caso, utilizzare l'evento mouseover per ripristinare la variabile "contatore". Se viene chiamata la tua funzione e il contatore è al di sopra dell'intervallo che hai predeterminato, allora fai la tua azione.
Ancora una volta, solo alcuni pensieri ... Spero che sia d'aiuto.
Ho testato questo file di lavoro del codice:
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);
});
Ecco la migliore soluzione che ho trovato: http://css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/
Ecco il 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("<p>Welcome Back.</p>");
}
idleState = false;
idleTimer = setTimeout(function () {
// Idle Event
$("body").append("<p>You've been idle for " + idleWait/1000 + " seconds.</p>");
idleState = true; }, idleWait);
});
$("body").trigger("mousemove");
});
}) (jQuery)
È possibile utilizzare la soluzione di seguito indicata
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);
}
Uso questo approccio, dal momento che non è necessario reimpostare costantemente l'ora in cui si verifica un evento, invece registriamo solo l'ora, questo genera il punto iniziale inattivo.
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);
},
Probabilmente potresti rilevare l'inattività sulla tua pagina web usando i trucchi mousemove elencati, ma ciò non ti dirà che l'utente non si trova su un'altra pagina in un'altra finestra o scheda, o che l'utente si trova in Word o Photoshop o WOW e semplicemente non sta guardando la tua pagina in questo momento. Generalmente farei semplicemente il prefetch e fare affidamento sul multi-tasking del cliente. Se hai davvero bisogno di questa funzionalità, fai qualcosa con un controllo activex in Windows, ma nella migliore delle ipotesi è brutto.
Ecco un servizio AngularJS per la realizzazione in 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;
}]);
Tieni presente che questo correttore di inattività verrà eseguito per tutti i percorsi, quindi dovrebbe essere inizializzato .run()al caricamento dell'app angolare. Quindi è possibile utilizzare idleChecker.secondsIdleall'interno di ogni percorso.
myApp.run(['idleChecker',function(idleChecker){
idleChecker.init();
}]);
Debounce in realtà un'ottima idea! Qui versione per progetti gratuiti jQuery:
const derivedLogout = createDerivedLogout(30);
derivedLogout(); // it could happen that user too idle)
window.addEventListener('click', derivedLogout, false);
window.addEventListener('mousemove', derivedLogout, false);
window.addEventListener('keyup', derivedLogout, false);
function createDerivedLogout (sessionTimeoutInMinutes) {
return _.debounce( () => {
window.location = this.logoutUrl;
}, sessionTimeoutInMinutes * 60 * 1000 )
}
Il più semplice possibile, rileva solo quando il mouse si sposta:
var idle = false;
document.querySelector('body').addEventListener('mousemove', function(e) {
if(idle!=false)idle = false;
});
var idleI = setInterval(function()
{
if(idle == 'inactive')
{
return;
}
if(idle == true)
{
idleFunction();
idle = 'inactive';
return;
}
idle = true;
}, 30000);// half the expected time, idle will trigger after 60s in this case.
function idleFuntion()
{
console.log('user is idle');
}
Bene, è possibile allegare un evento clic o mousemove al corpo del documento che reimposta un timer. Avere una funzione che si chiama a intervalli temporizzati che controlla se il timer è in un periodo di tempo specificato (come 1000 millis) e avviare il precaricamento.
Javascript non ha modo di dire l'utilizzo della CPU. Ciò spezzerebbe il sandbox javascript eseguito all'interno.
A parte questo, probabilmente agganciare gli eventi onmouseover e onkeydown della pagina funzionerebbe.
È inoltre possibile impostare utilizzare setTimeout nell'evento onload per pianificare una funzione da chiamare dopo un ritardo.
// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);