Idle Timeout w/ Angular JS

A client was concerned about keeping users on the site, and wanted a way to “shout” a call-to-action be if the user was about to leave the site. The call-to-action could be some text, or a video, or a form, the client wasn’t sure what would work.

I see this kind of thing on blogs all the time, and wondered to do it. Particularly, how do I anticipate the user leaving the site? Browsers prohibit using modals and tooltips when listening for document.unload events. I could listen for when the user loses focus on the browser window (ie. $('body').on('mouseout'...)) but that wouldn’t work on phones.

How do I gracefully and respectfully grab the attention of the user without impacting on usability?

As with any solutions, there are user-friendly solutions, and solutions that are intrusive. The solutions that I liked involved a modal showing, fading out the rest of the site, and easily dismisible. It grabs my attention, but simply goes away and shuts up if I don’t want to engage.

It was an interesting problem. At the very least, the problem was a useful challenge as I continue to grow my Angular JS skills. How do I gracefully and respectfully grab the attention of the user without impacting on usability?

While I waited for the client to figure out what he wanted, I took time for myself to explore how I could use AngularJS to solve the problem swirling in my head. I decided I wanted an object that created a mechanism that listened to the user’s behavior, and fired an event if the user goes idle. Once the user goes idle, I would listen for the user to make another move and use that event to fire my call to action.

The Solution

Inspired by this post on StackOverflow, I created a Factory object that listened for idle behavior. I knew I needed two pieces of functionality. One piece would manage a timeout with the ability to create a timeout, and fire an event when the timeout ended. Also needed was the ability to “interrupt” the timeout by canceling the existing timeout and starting a new timeout on every user action. The second piece needed was the listening for the user interaction, forwarding those events to the timeout object, and to stop listening if the timeout ended.

See the Pen Idle Timeout with AngularJS by Jeff Wilkerson (@stljeff1) on CodePen.0

Some other examples solving similar problems that I saw used $rootScope and variable watches. I understand that approach conceptually, however I am still confused on the whole Digest Cycle thing in Angular JS, and for this little exercise, I wanted to avoid using $rootScope to propagate events.