Tutorial :Detecting idle time in JavaScript elegantly



Question:

Is it possible to detect "idle" time in JavaScript?
My primary use case probably would be to pre-fetch or preload content.

Idle time: Period of user inactivity or without any CPU usage


Solution:1

Here is a simple script using JQuery that handles mousemove and keypress events. If the time expires, the page reload.

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


Solution:2

Without using jQuery, only 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      }  };  

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

You can add more DOM events if you need to. Most used are:

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;  

DOM Events list: http://www.w3schools.com/jsref/dom_obj_event.asp

Remember use window, or document according your needs. Here you can see the differences between them: What is the difference between window, screen, and document in Javascript?


Solution:3

Improving on Equiman's answer:

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

.
Apart from the improvements regarding activity detection, and the change from document to window, this script actually calls the function, rather than letting it sit idle by.

It doesn't catch zero CPU usage directly, but that is impossible, because executing a function causes CPU usage. And user inactivity eventually leads to zero CPU usage, so indirectly it does catch zero CPU usage.


Solution:4

I have created a small lib that does this a year ago:

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

Description:

Tiny javascript library to report activity of user in the browser (away, idle, not looking at webpage, in a different tab, etc). that is independent of any other javascript libraries such as jquery.

Visual Studio users can get it from NuGet by: PM> Install-Package Idle.js


Solution:5

Here is a rough jQuery implementation of tvanfosson's idea:

$(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.     }    })  


Solution:6

Similar to Iconic's solution above (with jQuery custom event)...

// 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)))  


Solution:7

You can do it more elegantly with underscore and jquery-

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


Solution:8

I know it a relatively old question, but I had the same issue and I found a quite good solution.

I used: jquery.idle and I only needed to do:

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

See JsFiddle demo.

(Just for Info: see this for back-end event tracking Leads browserload)


Solution:9

My answer was inspired by vijay's answer, but is a shorter, more general solution that I thought I'd share for anyone it might help.

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

As it currently stands, this code will execute immediately and reload your current page after 3 minutes of no mouse movement or key presses.

This utilizes plain vanilla JavaScript and an immediately-invoked function expression to handle idle timeouts in a clean and self-contained manner.


Solution:10

You could probably hack something together by detecting mouse movement on the body of the form and updating a global variable with the last movement time. You'd then need to have an interval timer running that periodically checks the last movement time and does something if it has been sufficiently long since the last mouse movement was detected.


Solution:11

Try this its work perfect..

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


Solution:12

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

I think this jquery code is perfect one , though copied and modified from above answers!! donot forgot to include jquery library in your file!


Solution:13

All the previous answers have an always-active mousemove handler. If the handler is jQuery, the additional processing jQuery performs can add up. Especially if the user is using a gaming mouse, as many as 500 events per second can occur.

This solution avoids handling every mousemove event. This result in a small timing error, but which you can adjust to your need.

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/


Solution:14

I wrote a simple jQuery plugin that will do what you are looking for.

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

The script will listen for mouse, keyboard, touch and other custom events inactivity (idle) and fire global "activity" and "inactivity" events.

Hope this helps :)


Solution:15

If you are targeting Chrome you can experiment with the requestIdleCallback


Solution:16

Pure JavaScript with properly set reset time and bindings 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);    });    }());  


Solution:17

I have tested this code working file:

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


Solution:18

The problem with all these solutions, although correct, they are impractical, when taking into account the session timeout valuable set, using PHP, .NET or in the Application.cfc file for Coldfusion developers. The time set by the above solution needs to sync with the server side session timeout. If the two do not sync, you can run into problems that will just frustrate and confuse your users. For example, the server side session timeout might be set to 60 minutes, but the user may believe that he/she is safe, because the JavaScript idle time capture has increased the total amount of time a user can spend on a single page. The user may have spent time filling in a long form, and then goes to submit it. The session timeout might kick in before the form submission is processed. I tend to just give my users 180 minutes, and then use JavaScript to automatically log the user out. Essentially, using some of the code above, to create a simple timer, but without the capturing mouse event part. In this way my client side & server side time syncs perfectly. There is no confusion, if you show the time to the user in your UI, as it reduces. Each time a new page is accessed in the CMS, the server side session & JavaScript timer are reset. Simple & elegant. If a user stays on a single page for more than 180 minutes, I figure there is something wrong with the page, in the first place.


Solution:19

Here is the best solution I have found: http://css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/

Here is the 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)  


Solution:20

You can use the below mentioned solution

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


Solution:21

I use this approach, since you don't need to constantly reset the time when an event fires, instead we just record the time, this generates the idle start point.

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


Solution:22

You could probably detect inactivity on your web page using the mousemove tricks listed, but that won't tell you that the user isn't on another page in another window or tab, or that the user is in Word or Photoshop, or WOW and just isn't looking at your page at this time. Generally I'd just do the prefetch and rely on the client's multi-tasking. If you really need this functionality you do something with an activex control in windows, but it's ugly at best.


Solution:23

For other users with the same problem. Here is a function i just made up.

It does NOT run on every mouse movement the user makes, or clears a timer every time the mouse moves.

<script>  // Timeout in seconds  var timeout = 10; // 10 seconds    // You don't have to change anything below this line, except maybe  // the alert('Welcome back!') :-)  // ----------------------------------------------------------------  var pos = '', prevpos = '', timer = 0, interval = timeout / 5 * 1000;  timeout = timeout * 1000 - interval;  function mouseHasMoved(e){      document.onmousemove = null;      prevpos = pos;      pos = e.pageX + '+' + e.pageY;      if(timer > timeout){          timer = 0;          alert('Welcome back!');      }  }  setInterval(function(){      if(pos == prevpos){          timer += interval;      }else{          timer = 0;          prevpos = pos;      }      document.onmousemove = function(e){          mouseHasMoved(e);      }  }, interval);  </script>  


Solution:24

Here is an AngularJS service for accomplishing 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;  }]);  

Keep in mind this idle checker will run for all routes, so it should be initialized in .run() on load of the angular app. Then you can use idleChecker.secondsIdle inside each route.

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


Solution:25

Just a few thoughts, an avenue or two to explore.

Is it possible to have a function run every 10 seconds, and have that check a "counter" variable? If that's possible, you can have an on mouseover for the page, can you not? If so, use the mouseover event to reset the "counter" variable. If your function is called, and the counter is above the range that you pre-determine, then do your action.

Again, just some thoughts... Hope it helps.


Solution:26

Well you could attach a click or mousemove event to the document body that resets a timer. Have a function that you call at timed intervals that checks if the timer is over a specified time (like 1000 millis) and start your preloading.


Solution:27

Tried @freddoo solution but it didn't work for 1 minute timeouts so I've changed it slightly to record the date+time when the user last clicked on the page and in my timerIncrement function I calculate the difference between the current time and the last clicked time and if the value happens to be bigger or equal to the timeout value then I redirect:

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


Solution:28

Javascript has no way of telling the CPU usage. This would break the sandbox javascript runs inside.

Other than that, hooking the page's onmouseover and onkeydown events would probably work.

You could also set use setTimeout in the onload event to schedule a function to be called after a delay.

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

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »