A plain JS (Typescript) module that will countdown and timeout when users are inactive/idle.
Switch branches/tags
Nothing to show
Clone or download
Pull request Compare This branch is 1 commit ahead of Benefex:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.



###A plain JS (Typescript) module that will countdown and timeout when users are inactive/idle.

Can be used to transition away from sensitive on screen information and redirect to another page. Useful when a user forgets to close their browser or tab before walking away from their computer.


npm install @benefex/inactivity-countdown-timer --save


// Optional config vars
let settings = {
    idleTimeoutTime?: number;
    startCountDownTimerAt?: number;
    resetEvents?: string[];
    timeoutCallback?(): void;
    countDownCallback?(secondsLeft: number): void;
    countDownCancelledCallback?(): void;
    localStorageKey?: string;
    redirectHREF?: string;

// Instantiate new logout object
let IL = new InactivityLogout(settings);

// make sure you cleanup the object when you are finished using it.
// will not be garbage collected unless you clean it up because of the timers

See the demo code for a detailed example

run npm start to view the demo locally


  • A count down callback - alert users you are going to transition them.
  • Activity is synced across tabs using local storage (users won't be transitioned if they are active in any other tab).
  • Dynamically adjusting timer. Which will set itself to initially timeout when the count down starts, then change to timeout every second for the countdown.
  • Configure what events reset your timer and count as an 'Activity' by passing in you're own reset event list.
  • Written in typescript and bundled as a UMD module.
  • Tests with a saucelabs setup for cross browser testing.

By default the inactivity timeout is reset by these events:

  • clicks
  • mousemovement
  • keypresses


  • IE8+ (you need to include the ie8EventListenerPolyfill)
  • Chrome
  • Firefox
  • Safari


The project is setup with both main.ts used for exporting the library and a demo.ts used to demo components and setup testing.


npm install installs node modules and runs tests

NPM Tasks

  • npm start runs a development server
  • npm test runs the tests via karma (from the main ts file)
  • npm test-via-saucelabs runs the tests via karma against Saucelabs config(from the main ts file)
  • npm build builds a version for distribution via npm
  • npm prepublish used when publishing to npm


This module was published with support from Benefex.

Benefex is the business behind RewardHub, the award-winning global employee benefits platform. RewardHub enables over 200 of the world’s largest employers to run, manage and engage their employees in reward and benefit programmes. Benefex

Are you a smart cookie? We’re always looking for bright, enthusiastic people to join our team in Southampton. Benefex Careers

Publishing workflow

  1. Run tests npm test
  2. Run build and check that your module was built (needs to be exported via main.ts)
  3. Install it into your project to test before publishing by running npm install '/path-to-this/'
  4. Bump version in package.json following Semantic Versioning SemVer
  5. Tag the release commit in git: git tag -a v0.1.5 -m "Published v0.1.5"
  6. Push the tags up to github: git push origin --tags
  7. Publish npm publish

IE8 Notes

Make sure you are importing the included ie8EventListenerPolyfill when supporting ie8.

How we deal with the context of this when attaching an event listener

It's not easy to set the context of this when you need to support IE8 because you cannot use .bind. So we have to use the handleEvent work around:

export class InactivityLogout {
            // we pass in the value this not a function 
            // this.handleEvent is called (i.e the handleEvent function on the class)
            this.attachEvent(document, 'click', this);
        handleEvent(eventName: string): void {
            console.log('**** clear timeout for event', eventName);

Excerpt from MDN dealing with handling the attached EventListeners

The value of this within the handler

It is often desirable to reference the element on which the event handler was fired, such as when using a generic handler for a set of similar elements.

When attaching a handler function to an element using addEventListener(), the value of this inside the handler is a reference to the element. It is the same as the value of the currentTarget property of the event argument that is passed to the handler.

A solution is using a special function called handleEvent to catch any events:

var Something = function(element) {
  this.name = 'Something Good';
  this.handleEvent = function(event) {
    console.log(this.name); // 'Something Good', as this is the Something object
    switch(event.type) {
      case 'click':
        // some code here...
      case 'dblclick':
        // some code here...

  // Note that the listeners in this case are this, not this.handleEvent
  element.addEventListener('click', this, false);
  element.addEventListener('dblclick', this, false);

  // You can properly remove the listeners
  element.removeEventListener('click', this, false);
  element.removeEventListener('dblclick', this, false);

Read the full document ont EventTarget.addEventListener() on MDN