Detecting If the User is Idle or Inactive

by kirupa   |   11 September 2013

Some apps require your constant attention. Such apps often include games, media players, anything that is CPU/battery intensive, and so on. For these kinds of apps, it may be important (as well as user-friendly) to do something when a user is no longer actively interacting with your app.

Take a look at the following example:

More than likely, you are seeing a moon on a dark gray background. If you hover over the example or click/tap anywhere, notice that your app suddenly jumps to life and shows an animated rocket. As long as you keep interacting with the example by moving the mouse or clicking around, the rocket will continue to display. If you don't do anything for 2 seconds, the example thinks you are no longer paying attention and goes back to the dark background with the moon.

In this article, you will learn how to detect when a user has gone inactive (aka idle) using nothing but a few lines of sweet SWEET JavaScript.

Onwards!

Detecting Inactivity

The way we are going to detect inactivity is pretty straightforward. We have a timer that starts ticking once a user stops interacting with the app. Let's define "stops interacting" as when a user hasn't fiddled with the mouse, keyboard, or the screen (by touching / tapping) for a period of time.

The basic code for this looks as follows:

var timeoutID;

function setup() {
    this.addEventListener("mousemove", resetTimer, false);
    this.addEventListener("mousedown", resetTimer, false);
    this.addEventListener("keypress", resetTimer, false);
    this.addEventListener("DOMMouseScroll", resetTimer, false);
    this.addEventListener("mousewheel", resetTimer, false);
    this.addEventListener("touchmove", resetTimer, false);
    this.addEventListener("MSPointerMove", resetTimer, false);

    startTimer();
}
setup();

function startTimer() {
	// wait 2 seconds before calling goInactive
    timeoutID = window.setTimeout(goInactive, 2000);
}

function resetTimer(e) {
    window.clearTimeout(timeoutID);

    goActive();
}

function goInactive() {
	// do something
}

function goActive() {
	// do something
	    
    startTimer();
}

If you want to incorporate this code as-is, you should make a few minor tweaks. First, our code currently considers a user to be inactive after 2 seconds of idling. You can change how long to wait before playing the "inactive card" in the following line:

function startTimer() {
	// wait 2 seconds before calling goInactive
	timeoutID = window.setTimeout(goInactive, 2000);
}

Just replace the last argument to the setTimeOut function with the number of milliseconds you want to wait.

Next, you should specify what you want your app to do when the user is inactive and when they are active. You can specify your wants in the appropriately named goInactive and goActive functions:

function goInactive() {
	// do something
}

function goActive() {
	// do something
	    
    startTimer();
}

That's all there is to using this very simple script for detecting when users become inactive. To see this code at work, you can view the source for the example you saw earlier by using your browser's View Source command on this page.

 In the next section, let's deconstruct this code and understand how it works.

The Code Explained

Our code can be divided into two parts. The first part deals with setting up all of the events to ensure we are detecting inactivity properly. The second part is setting and resetting the timer depending on whether your user is interacting with the app or not.

Listening for Events

The easy part is setting up the events:

function setup() {
    this.addEventListener("mousemove", resetTimer, false);
    this.addEventListener("mousedown", resetTimer, false);
    this.addEventListener("keypress", resetTimer, false);
    this.addEventListener("DOMMouseScroll", resetTimer, false);
    this.addEventListener("mousewheel", resetTimer, false);
    this.addEventListener("touchmove", resetTimer, false);
    this.addEventListener("MSPointerMove", resetTimer, false);

    startTimer();
}
setup();

Our code listens for various mouse, keyboard, and touch events to ensure that we don't accidentally declare a user as being inactive when he/she is actually still interacting with the app. If any of these events are overheard, the resetTimer function acts as the event handler and gets called.

Meet the Timer

The timer is what determines when to declare an active app as being inactive. That important task is handled by the startTimer and resetTimer functions:

function startTimer() {
	// wait 2 seconds before calling goInactive
	timeoutID = window.setTimeout(goInactive, 2000);
}

function resetTimer(e) {
    window.clearTimeout(timeoutID);

    goActive();
}

The startTimer function gets called at the very beginning by our setup function, and it initializes our global timeoutID variable to an ID value returned by calling the setTimeout function:

function startTimer() {
	// wait 2 seconds before calling goInactive
	timeoutID = window.setTimeout(goInactive, 2000);
}

In our example, the setTimeout function calls goInactive after two seconds. The only way to prevent our app from going into an inactive state is to ensure we reset this setTimeout call so that it never gets a chance to call the goInactive function.

This resetting is handled in the resetTimer function - a function that gets called when any of the events we are listening for gets fired:

function resetTimer(e) {
    window.clearTimeout(timeoutID);

    goActive();
}

More specifically, we negate the setTimeout call from earlier by using the clearTimeout function. The timeoutID variable that you initialized as part of the setTimeout call is what you pass in to the clearTimeout function to ensure you are stopping the right timer.

Once the timer is stopped, we call the goActive function which creates the timer all over again by calling startTimer:

function goActive() {
	// do something
	    
    startTimer();
}

The startTimer and resetTimer functions get called constantly when users are interacting with your app. With every interaction, your timer gets reset. With every pause in the interaction, your timer starts counting down again until it gets a chance to call the goInactive function. Pretty awesome, right?

Conclusion

Most of the time, you probably don't care whether a user is actively interacting with your app or not. Your app will simply be indifferent. During those other times, what you decide to do will vary depending on what exactly your app does. A game may choose to pause if nothing is going on. A media player might choose to hide all of the playback controls when the user stops interacting with it. A document editor might auto-save when it detects a pause.

Getting Help

If you have questions, need some assistance on this topic, or just want to chat - post in the comments below or drop by our friendly forums (where you have a lot more formatting options) and post your question. There are a lot of knowledgeable and witty people who would be happy to help you out

Share

Did you enjoy reading this and found it useful? If so, please share it with your friends:

If you didn't like it, I always like to hear how I can do better next time. Please feel free to contact me directly via e-mail, facebook, or twitter.

Kirupa Chinnathambi
I like to talk a lot - A WHOLE LOT. When I'm not talking, I've been known to write the occasional English word. You can learn more about me by going here.

Add Your Comment (or post on the Forums)

blog comments powered by Disqus

Awesome and high-performance web hosting!
BACK TO TOP
new books - yay!!!