Are You Still There?

A scenario: you want to update some content on your page periodically, but you don’t want to waste requests, resources, cycles, etc. on running your script while the user is obviously not interacting with the page. What do you do?

Here’s a jQuery extension I call “Still Alive” which handles this for you. It will run your functions periodically while the user is interacting with the page, but then it will go to sleep and stop executing them if the user goes away, and resume when the user comes back.

Implementation

/*!
* Still Alive v1.2
* http://github.com/justinforce/still-alive
*
* Copyright 2011, Justin Force
* Licensed under the BSD 3-Clause License
*/


/*jslint browser: true, indent: 2 */
/*global jQuery */

(function ($) {

  'use strict';

  // default values for optional arguments
  var DEFAULT_WAKEEVENTS = 'mousemove mousedown mouseup keydown keyup',
    DEFAULT_INTERVAL     = 60000,
    DEFAULT_IMMEDIATELY  = true;

  // sugar. Just get the current time in milliseconds
  function getTime() {
    return (new Date()).getTime();
  }

  $.stillAlive = function (callback, interval, immediately, wakeEvents) {

    var ptr,                // pointer to the interval so it can be cleared from outside
      args,                 // object containing optional arguments
      awake = true,         // awake status. Are we awake?
      lastSeen = getTime(); // the last time the user was seen (a wake event triggered)

    // For named arguments, copy the arguments object and assign its supported
    // properties.
    if (typeof interval === 'object') {
      args = interval;
      interval = args.interval;
      immediately = args.immediately;
      wakeEvents = args.wakeEvents;
    }

    // set default values for optional arguments
    if (interval === undefined) {
      interval = DEFAULT_INTERVAL;
    }
    if (immediately === undefined) {
      immediately = DEFAULT_IMMEDIATELY;
    }
    if (wakeEvents === undefined) {
      wakeEvents = DEFAULT_WAKEEVENTS;
    }

    // true if it's been (1.5 x interval) milliseconds
    function timeToSleep() {
      return (getTime() - lastSeen > (interval + (interval / 2)));
    }

    // set status to awake and update the lastSeen time, then execute the
    // callback.
    function wake() {
      if (!awake) {
        callback();
      }
      awake = true;
      lastSeen = getTime();
    }

    // set status to !awake (asleep)
    function sleep() {
      awake = false;
    }

    $(window).bind(wakeEvents, wake);

    // if enough time has passed without a wake event, sleep. If we happen to
    // be awake, execute the callback.
    ptr = setInterval(function () {
      if (timeToSleep()) {
        sleep();
      }
      if (awake) {
        callback();
      }
    }, interval);

    // if we're supposed to run immediately, execute the callback once
    if (immediately) {
      callback();
    }

    return ptr;
  };

}(jQuery));

Examples

Say I have a function called update defined elsewhere. I want update to be called every 60 seconds unless the user doesn’t seem to be around. I’d just

$.stillAlive(update);

How about every 15 seconds?

$.stillAlive(update, 15);

Let’s toggle a class of some elements every 90 seconds, but only if the user has clicked or typed something, and don’t run it immediately after being set.

$.stillAlive(function() {
  $('.togglies').toggleClass('toggly');
}, 90, false, 'click keyup');

The previous code could also be more explicitly called thusly:

$.stillAlive(function() {
  $('.togglies').toggleClass('toggly');
}, {
  interval: 90,
  immediately: false,
  wakeEvents: 'click keyup'
});

And for good measure, here’s a call using object literal notation, but only adjusting the interval:

$.stillAlive(update, { interval: 5 });

Note that the stillAlive method returns the intervalID, so you can cancel your stillAlive thusly:

var sa = $.stillAlive(update);
clearInterval(sa);

GitHub

The project, like most of my work, lives at GitHub. For complete documentation, forking, and keeping up with the latest version, check out Still Alive on GitHub.

This entry was posted in javascript and tagged , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>