Comment détecter élégamment le temps d'inactivité en JavaScript?

479

Est-il possible de détecter le temps " inactif " en JavaScript?
Mon principal cas d'utilisation serait probablement de pré-récupérer ou de précharger du contenu.

Temps d'inactivité : période d'inactivité de l'utilisateur ou sans utilisation du processeur

Cherian
la source
7
Comment définissez-vous IDLE TIME?
Itay Moav -Malimovka
4
consultez github.com/kidh0/jquery.idle
apneadiving
74
Près de 50% des réponses ici ont utilisé jQuery pour une tâche aussi simple pour du Javascript pur. C'est au-delà de la stupidité, d'autant plus que l'OP voulait Javascript. Demandez de la glace à la fraise, mais achetez plutôt une grange mitoyenne.
TheCarver
4
c'est StackOverflow pour vous
robertmain
5
@TheCarver - Devoir installer une bibliothèque jQuery pour quelque chose d'aussi simple est en effet ridicule, et cela allonge le temps de rendu et augmente la consommation d'énergie. Les gens devraient faire défiler un peu plus loin. Il existe également une solution presque copier-coller en Javascript vanille.
Frank Conijn

Réponses:

439

Voici un script simple utilisant JQuery qui gère les événements mousemove et keypress. Si le délai expire, la page se recharge.

<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>   
freddoo
la source
16
Il manque un point-virgule après le corps de $ (document) .ready (function (). De plus, dans l'appel à setInterval, cela ne fonctionnera pas avec des guillemets autour du nom de la fonction et vous n'avez pas besoin des parenthèses après. Just: setInterval (timerIncrement, 60000)
Jesse Roper
9
@Jesse: Vos suggestions sont toutes bonnes, c'est ainsi que le code devrait être. Mais je voulais juste souligner que même sans ces changements, le code est entièrement fonctionnel. Les points-virgules à la fin d'une instruction d'expression sont facultatifs et vous pouvez en fait passer une chaîne à setInterval, qui est ensuite évaluée comme JavaScript.
Felix Kling
6
Vous pouvez simplement utiliser idleTime++;au lieu deidleTime = idleTime + 1;
Mike Causer
7
N'est-ce pas lourd sur le système d'un utilisateur? Disons qu'un utilisateur avec un navigateur assez ancien sur un PC pas si lourd, travaille dans une application javascript pendant une demi-journée, et il traite ces fonctions à chaque fois que l'utilisateur déplace sa souris ... Je me demande si cela a gagné '' t affecter l'expérience de l'utilisateur ...
Sander
5
@PietBinnenbocht De plus, si vous commencez à optimiser des choses comme celle-ci, vous pouvez aussi bien changer chaque fonction qui prend des chaînes comme 'mousemove keydown click'utiliser des indicateurs de bits ( Event.MOUSEMOVE | Event.KEYDOWN | Event.CLICK), car elles sont waaaaay plus rapides que les opérations de chaîne. Mais voulez-vous vraiment faire ça?
Killah
362

Sans utiliser jQuery, uniquement du vanilla JavaScript:

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
    }
};

Et lancez la fonction là où vous en avez besoin (par exemple: onPageLoad).

window.onload = function() {
  inactivityTime(); 
}

Vous pouvez ajouter plus d'événements DOM si vous en avez besoin. Les plus utilisés sont:

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

Ou enregistrez les événements souhaités à l'aide d'un tableau

window.addEventListener('load', resetTimer, true);
var events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
events.forEach(function(name) {
 document.addEventListener(name, resetTimer, true); 
});

Liste des événements DOM : http://www.w3schools.com/jsref/dom_obj_event.asp

N'oubliez pas d'utiliser windowou documentselon vos besoins. Ici vous pouvez voir les différences entre eux: Quelle est la différence entre la fenêtre, l'écran et le document en Javascript?

Le code mis à jour avec @ frank-conijn et @daxchen s'améliore: window.onscrollne se déclenche pas si le défilement est à l'intérieur d'un élément déroulant, car les événements de défilement ne bouillonnent pas. window.addEventListener('scroll', resetTimer, true), le troisième argument indique à l'auditeur d'attraper l'événement pendant la phase de capture au lieu de la phase de bulle.

equiman
la source
58
J'aime beaucoup l'approche javascript simple.
Manatax
4
Réinitialiser définitivement une minuterie est une approche plus directe / intuitive et précise que d'avoir un délai d'expiration, seulement pour garder un nombre entier d'une autre chose, lorsque la minuterie elle-même peut être le compteur (de haute précision).
Josh Sutterfield
2
@mpsbhat ajoutez simplement un fichier console.log ou une alerte et voyez si cela fonctionne. Ou enregistrez cet événement:document.onload = function () { inactivityTime(); }; document.onmousedown = function () { inactivityTime(); }; document.onkeypress = function () { inactivityTime(); }; document.ontouchstart = function () { inactivityTime(); };
equiman
2
Ouais ... ça marche. jsfiddle.net/mpsbhat/6b6mja5t/1 . Merci @equiman
mpsbhat
6
Ce serait bien mieux d'avoir un drapeau var notidle; définissez ce flag = true uniquement sur les événements. Ensuite, dans le test de la fonction resetTimer, si l'indicateur notidle est vrai, s'il est réinitialisé le minuteur, ou appelez la déconnexion. Cela supprimera la complexité de la réinitialisation constante de la minuterie.
MartinWebb
75

Amélioration de la réponse d'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();

.
Mis à part les améliorations concernant la détection d'activité et le changement de documentà window, ce script appelle en fait la fonction, plutôt que de la laisser inactive.

Il n'attrape pas directement l'utilisation du CPU, mais cela est impossible, car l'exécution d'une fonction provoque l'utilisation du CPU. Et l'inactivité des utilisateurs finit par entraîner une utilisation nulle du processeur, donc indirectement, elle n'attrape aucune utilisation du processeur.

Frank Conijn
la source
3
Je voulais juste souligner que window.onscrollcela ne se déclenchera pas si le défilement est à l'intérieur d'un élément déroulant, car les événements de défilement ne bouillonnent pas. En utilisant window.addEventListener('scroll', resetTimer, true), le troisième argument indique à l'auditeur d'attraper un événement pendant la capturephase au lieu de la bubblephase (IE> 8), voir cette réponse
DaxChen
@DaxChen - N'a pas document.onscrollle même problème, ne se déclenche pas si le défilement est à l'intérieur d'un enfant défilable?
Frank Conijn
2
Oui, le point que je disais est d'utiliser addEventListenerau lieu de onscroll.
DaxChen
@DaxChen - OK, je me demandais si vous vouliez dire ça, pour contourner cela, mais c'est clair maintenant. J'ai modifié la réponse en conséquence. Merci pour le commentaire.
Frank Conijn
Je mettrai à jour ma réponse avec ces informations importantes, pour avide d'autres copier et coller mon erreur. Merci @DaxChen et Frank
equiman
33

J'ai créé une petite bibliothèque qui fait ça il y a un an:

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

La description:

Petite bibliothèque javascript pour signaler l'activité de l'utilisateur dans le navigateur (absent, inactif, ne regardant pas la page Web, dans un onglet différent, etc.). qui est indépendante de toute autre bibliothèque javascript telle que jquery.

Les utilisateurs de Visual Studio peuvent l'obtenir auprès de NuGet en: PM> Install-Package Idle.js

Shawn Mclean
la source
32

Voici une implémentation jQuery approximative de l'idée 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.
   }

})
Peter J
la source
9
Cette solution ne prend pas en compte les événements de clavier.
Daniel Silveira
7
Ne passez jamais setIntervalune chaîne! Donnez juste une fonction comme variable!
Eric
1
Cela ne fonctionnera pas réellement car passer une chaîne pour setInterval()évaluer l'expression dans la portée globale et donc ne trouvera pas la timerIncrement()fonction qui est à l'intérieur de la fonction de gestionnaire .ready. C'est encore une autre raison de ne JAMAIS transmettre de chaînes setInterval(). Passez simplement une référence de fonction réelle et vous n'aurez pas ce problème car ils sont évalués dans la portée actuelle.
jfriend00
Merci, je n'étais pas conscient de la nécessité de ne JAMAIS passer de chaînes à setInterval. Mis à jour ma réponse.
Peter J
24

Similaire à la solution Iconic ci-dessus (avec événement personnalisé 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)))
Tracker1
la source
20

Vous pouvez le faire plus élégamment avec le soulignement et le jquery -

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

Ma réponse a été inspirée par la réponse de vijay , mais c'est une solution plus courte et plus générale que je pensais partager pour quiconque pourrait l'aider.

(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);
}());

Dans sa forme actuelle, ce code s'exécutera immédiatement et rechargera votre page actuelle après 3 minutes sans mouvement de la souris ni appui sur les touches.

Cela utilise du JavaScript vanilla simple et une expression de fonction immédiatement invoquée pour gérer les délais d'inactivité d'une manière propre et autonome.

johnnyRose
la source
document.onclick considère les fonctions javascript en utilisant .trigger («clic») que j'ai écrit comme automatisé. Ce n'est donc pas vraiment une interaction utilisateur, mais cela réinitialisera idleCounter dans ce cas
Carmela
@Carmela: Je ne sais pas pourquoi je viens de voir ça; J'ai du le manquer. Merci, j'ai supprimé l' onclickaffectation car elle n'est probablement pas nécessaire en plus de onmousemove, mais évidemment, l'un de ces événements qui sont déclenchés par programme continuera de se réinitialiser idleCounter. Je ne sais pas pourquoi vous simulez l'interaction utilisateur au lieu d'appeler simplement une fonction, mais si c'est quelque chose que vous devez faire pour une raison quelconque, cette réponse ne fonctionnera évidemment pas pour vous, pas plus que la plupart des autres réponses que je '' ai examiné cette question.
johnnyRose
15

Je sais que c'est une question relativement ancienne, mais j'ai eu le même problème et j'ai trouvé une assez bonne solution.

J'ai utilisé: jquery.idle et je n'avais qu'à faire:

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

Voir démo JsFiddle .

(Juste pour info: voir ceci pour le suivi des événements de back-end Leadload navigateur )

DDan
la source
Comment puis-je arrêter cette fonction, ils ont déclaré un événement inactif: arrêtez-vous, mais honnêtement, je ne sais pas comment l'utiliser. Je veux que si je passe à la page suivante (basée sur ajax, seul le fragment de page HTML est mis à jour), la fonction inactive s'arrête. Saviez-vous comment y parvenir?
Mubasher
Ici, il est dit: "idle: stop": arrêtera et supprimera le suivi des utilisateurs
DDan
J'ai déjà lu mais je n'ai pas compris comment l'utiliser. Pourriez-vous m'aider?
Mubasher
Si vous souhaitez qu'il ne se déclenche qu'une seule fois, vous pouvez définir l' keepTrackingoption sur false. Si vous souhaitez réinitialiser, vous pouvez essayer de le réinitialiser. Voici un exemple modifié qui ne se déclencherait qu'une seule fois: jsfiddle.net/f238hchm/12
DDan
Non, je ne tire pas une fois, keepTracking devrait être vrai, mais sur la navigation vers une autre page, je veux arrêter cela
Mubasher
15

Toutes les réponses précédentes ont un gestionnaire de déplacement de souris toujours actif. Si le gestionnaire est jQuery, le traitement supplémentaire effectué par jQuery peut s'additionner. Surtout si l'utilisateur utilise une souris de jeu, jusqu'à 500 événements par seconde peuvent se produire.

Cette solution évite de gérer chaque événement de déplacement de souris. Il en résulte une petite erreur de synchronisation, mais que vous pouvez ajuster à votre besoin.

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);
    }
}

http://jsfiddle.net/jndxq51o/

Salsepareille
la source
1
Cela fonctionnera-t-il automatiquement s'il est placé sur une page, ou doit-il être dans un wrapper $ (document) .ready ()? Je vous remercie! De plus, où se trouve la partie qui exécute une action lorsque le temporisateur expire?
Oranges13
1
Vous pouvez l'appeler à tout moment, même avant que le document ne soit prêt. Vous passez une fonction 'callback' qui sera appelée à l'expiration du timer.
Salsepareille
1
L' $(startTimer)équivalent à $(document).ready(startTimer)garantit que le DOM est prêt avant de raccorder les événements mousemove et keypress.
Salsepareille
1
+1 C'est ce que je fais - les gestionnaires de déplacement de souris contribuent à la lenteur et à la réduction de la durée de vie de la batterie, donc ne l'allumer que périodiquement est une excellente idée si vous pouvez vous permettre l'erreur de synchronisation mineure. J'utilise généralement la détection de temps d'inactivité pour les avertissements d'expiration de session automatique (par exemple, "Êtes-vous toujours là?"), J'ai donc tendance à avoir plusieurs minutes avant qu'un utilisateur ne passe en mode "inactif", auquel cas une petite erreur de synchronisation est totalement hors de propos.
chèvre
1
Il vaut mieux utiliser "keydown" que "keypress" car les touches fléchées ne sont pas détectées par l'événement "keypress". Donc, si l'utilisateur navigue sur la page à l'aide des touches fléchées, il deviendra quand même inactif.
aFerrer
13

Vous pourriez probablement pirater quelque chose ensemble en détectant le mouvement de la souris sur le corps du formulaire et en mettant à jour une variable globale avec le dernier temps de mouvement. Vous devrez alors avoir un temporisateur d'intervalle qui vérifie périodiquement le dernier temps de mouvement et fait quelque chose s'il a été suffisamment long depuis que le dernier mouvement de souris a été détecté.

tvanfosson
la source
Il est important de noter que le script ne pourra détecter que les mouvements sur le corps de la page, pas toutes les entrées utilisateur. Je ne pense pas qu'il existe un moyen d'obtenir des informations sur le processeur ou le processus à partir de javascript.
Dave Swersky
1
J'ai pris la liberté d'implémenter votre idée dans jQuery.
Peter J
9

J'ai écrit une petite classe ES6 pour détecter l'activité et autrement déclencher des événements en cas de délai d'inactivité. Il couvre le clavier, la souris et le toucher , peut être activé et désactivé et dispose d'une API très allégée:

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

Il ne dépend pas de jQuery, mais vous devrez peut-être l'exécuter via Babel pour prendre en charge les navigateurs plus anciens.

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

Je pourrais le publier en tant que package npm une fois que j'aurai des commentaires.

Capi Etheriel
la source
8

Si vous ciblez un navigateur pris en charge (Chrome ou Firefox à partir de décembre 2018), vous pouvez tester le requestIdleCallback et inclure le shim requestIdleCallback pour les navigateurs non pris en charge.

rajsite
la source
Et laisser les autres navigateurs tranquilles?
Frank Conijn,
Shim couvre tous les navigateurs. Et c'était la seule réponse! D'autres réponses de ralentissement concernent la souris. L'interactivité ou le CPU n'a été dit qu'à titre d'exemple. Comment détecter le CPU inactif avec une solution de souris?
6

Essayez ce code, il fonctionne parfaitement.

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";
    }
}
vijay
la source
plus 1 pour être vanilla js
frostymarvelous
5
<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> 

Je pense que ce code jquery est parfait, bien que copié et modifié à partir des réponses ci-dessus !! donot a oublié d'inclure la bibliothèque jquery dans votre fichier!

SPidey
la source
4

Le problème avec toutes ces solutions, bien que correctes, elles ne sont pas pratiques, si l'on prend en compte l'ensemble précieux de timeout de session, en utilisant PHP, .NET ou dans le fichier Application.cfc pour les développeurs Coldfusion. L'heure définie par la solution ci-dessus doit être synchronisée avec le délai d'expiration de la session côté serveur. Si les deux ne se synchronisent pas, vous pouvez rencontrer des problèmes qui ne feront que frustrer et dérouter vos utilisateurs. Par exemple, le délai d'expiration de la session côté serveur peut être défini sur 60 minutes, mais l'utilisateur peut croire qu'il est sûr, car la capture du temps d'inactivité JavaScript a augmenté le temps total qu'un utilisateur peut passer sur une seule page. L'utilisateur peut avoir passé du temps à remplir un long formulaire, puis va le soumettre. Le délai d'expiration de la session peut démarrer avant que la soumission du formulaire ne soit traitée. J'ai tendance à accorder 180 minutes à mes utilisateurs, puis utilisez JavaScript pour déconnecter automatiquement l'utilisateur. Essentiellement, en utilisant une partie du code ci-dessus, pour créer un minuteur simple, mais sans la partie d'événement de capture de la souris. De cette façon, mon temps côté client et côté serveur se synchronise parfaitement. Il n'y a pas de confusion, si vous affichez l'heure à l'utilisateur dans votre interface utilisateur, car cela réduit. Chaque fois qu'une nouvelle page est accessible dans le CMS, la session côté serveur et le minuteur JavaScript sont réinitialisés. Simple et élégant. Si un utilisateur reste sur une seule page pendant plus de 180 minutes, je pense qu'il y a un problème avec la page, en premier lieu. car il diminue. Chaque fois qu'une nouvelle page est accessible dans le CMS, la session côté serveur et le minuteur JavaScript sont réinitialisés. Simple et élégant. Si un utilisateur reste sur une seule page pendant plus de 180 minutes, je pense qu'il y a un problème avec la page, en premier lieu. car il diminue. Chaque fois qu'une nouvelle page est accessible dans le CMS, la session côté serveur et le minuteur JavaScript sont réinitialisés. Simple et élégant. Si un utilisateur reste sur une seule page pendant plus de 180 minutes, je pense qu'il y a un problème avec la page, en premier lieu.

Charles Robertson
la source
1
Oui, c'est pourquoi je ne fais cela qu'après avoir supprimé les sessions côté serveur et tout chargé à partir des fichiers html.
Dan Parker
4

JavaScript pur avec un temps de réinitialisation et des liaisons correctement définis via 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);
  });

}());
JackTheKnife
la source
4

(Partiellement inspiré par la bonne logique de base d'Equiman plus haut dans ce fil.)

sessionExpiration.js


sessionExpiration.js est léger mais efficace et personnalisable. Une fois implémenté, utilisez sur une seule ligne:

sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
  • Affecte tous les onglets du navigateur, pas un seul.
  • Écrit en JavaScript pur , sans dépendances. Entièrement côté client.
  • (Si vous le souhaitez.) A une bannière d'avertissement et un compte à rebours , qui sont annulés par l'interaction de l'utilisateur.
  • Incluez simplement sessionExpiration.js et appelez la fonction, avec les arguments [1] nombre de minutes d'inactivité (dans tous les onglets) jusqu'à ce que l'utilisateur soit déconnecté, [2] nombre de minutes d'inactivité jusqu'à ce que l'avertissement et le compte à rebours s'affichent, et [3] URL de déconnexion.
  • Mettez le CSS dans votre feuille de style. Personnalisez-le si vous le souhaitez. (Ou sautez et supprimez la bannière si vous ne le souhaitez pas.)
  • Si vous ne voulez la bannière d'avertissement cependant, vous devez mettre un vide div avec l' ID sessExpirDiv sur votre page (une suggestion met dans le pied de page) .
  • Désormais, l'utilisateur sera automatiquement déconnecté si tous les onglets ont été inactifs pendant la durée donnée.
  • Facultatif: vous pouvez fournir un quatrième argument (URL serverRefresh) à la fonction, afin qu'un minuteur de session côté serveur soit également actualisé lorsque vous interagissez avec la page.

Ceci est un exemple de ce à quoi il ressemble en action, si vous ne changez pas le CSS.

demo_image

Fom
la source
3

J'ai écrit un simple plugin jQuery qui fera ce que vous cherchez.

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]
});

Le script écoutera la souris, le clavier, le toucher et d'autres événements personnalisés d'inactivité (inactifs) et déclenchera des événements globaux d '"activité" et "d'inactivité".

J'espère que cela t'aides :)

Alexandros Filos Kaparelos
la source
Existe-t-il vraiment un besoin de délai, ne déclenche-t-il pas suffisamment un événement personnalisé à partir d'un gestionnaire d'événements personnalisé?
Hibou57
2

Juste quelques réflexions, une ou deux pistes à explorer.

Est-il possible d'avoir une fonction exécutée toutes les 10 secondes, et de faire vérifier une variable "compteur"? Si c'est possible, vous pouvez avoir un survol de la page, n'est-ce pas? Si tel est le cas, utilisez l'événement mouseover pour réinitialiser la variable "compteur". Si votre fonction est appelée et que le compteur est au-dessus de la plage que vous prédéterminez, alors faites votre action.

Encore une fois, juste quelques réflexions ... J'espère que ça aide.

Mark Rullo
la source
2

J'ai testé ce fichier de travail de code:

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);
    });
Vishal Jaura
la source
2

Voici la meilleure solution que j'ai trouvée: http://css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/

Voici le 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)
Casey
la source
2

Vous pouvez utiliser la solution mentionnée ci-dessous

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);
}
Abhishek
la source
2

J'utilise cette approche, car vous n'avez pas besoin de réinitialiser constamment l'heure à laquelle un événement se déclenche, mais nous enregistrons simplement l'heure, cela génère le point de départ inactif.

           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);    
        },
MartinWebb
la source
1

Vous pourriez probablement détecter l'inactivité sur votre page Web à l'aide des astuces de déplacement de souris répertoriées, mais cela ne vous dira pas que l'utilisateur n'est pas sur une autre page dans une autre fenêtre ou un autre onglet, ou que l'utilisateur est dans Word ou Photoshop, ou WOW et ne regarde tout simplement pas votre page pour le moment. En général, je fais juste la prélecture et je compte sur le multitâche du client. Si vous avez vraiment besoin de cette fonctionnalité, vous faites quelque chose avec un contrôle ActiveX dans Windows, mais c'est moche au mieux.

Walden Leverich
la source
1

Voici un service AngularJS pour accomplir 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;
}]);

Gardez à l'esprit que ce vérificateur inactif s'exécutera pour toutes les routes, il doit donc être initialisé lors .run()du chargement de l'application angulaire. Ensuite, vous pouvez utiliser idleChecker.secondsIdleà l'intérieur de chaque itinéraire.

myApp.run(['idleChecker',function(idleChecker){
    idleChecker.init();
}]);
à vapeur
la source
1

Debounce en fait une excellente idée! Voici la version pour les projets gratuits 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 ) 
}
Gleb Dolzikov
la source
1

Aussi simple que possible, détectez uniquement les mouvements de la souris:

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');
}
lucss
la source
0

Eh bien, vous pouvez attacher un événement de clic ou de déplacement de souris au corps du document qui réinitialise une minuterie. Avoir une fonction que vous appelez à des intervalles temporisés qui vérifie si la minuterie est sur une durée spécifiée (comme 1000 millis) et commencez votre préchargement.

Eric Wendelin
la source
0

Javascript n'a aucun moyen de dire l'utilisation du processeur. Cela casserait les javascript du bac à sable à l'intérieur.

En dehors de cela, accrocher les événements onmouseover et onkeydown de la page fonctionnerait probablement.

Vous pouvez également définir use setTimeout dans l'événement onload pour planifier une fonction à appeler après un délai.

// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);
Powerlord
la source
3
Je me demande pourquoi tant de votes négatifs sur cette réponse. Pour autant que je puisse voir, il a répondu à la question posée et est en fait correct. Seulement n'a pas continué à déployer des exemples de code élaborés.
Ifedi Okonkwo
1
Il est maintenant possible d'appeler une fonction javascript quand "il y a du temps libre à la fin d'une trame, ou lorsque l'utilisateur est inactif". Developers.google.com/web/updates/2015/08/…
Max
setTimeout 0 est probablement plus correct pour calculer en moyenne à quel point le tampon est plein en prenant le temps entre FILO