Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I made this piece of code to detect inactivity on different aspects of my app. It is part of a set of pieces to analyze user behavior.

Not saying it's ugly, but good looking constructive criticism to help me improve my code and could be useful to me for other similar components.

function InactivityTimeout(idle_time, callback) {
  this.state = 0; // 0-new, 1=active, 2=idle
  this.idle_time = idle_time;
  this.callback = callback;
  this.start();
}

InactivityTimeout.prototype.start = function() {
 this.state = 1;
 this.timer = setTimeout(this.timeout.bind(this), this.idle_time); 
}
                          
InactivityTimeout.prototype.activity = function() {
 if (this.state == 1) {
   clearTimeout(this.timer);
 }
 this.start();
}

                          
InactivityTimeout.prototype.timeout = function() {
   this.state = 2;
   this.callback();
}

/// usage

var timer=new InactivityTimeout(5000, function() {
    alert("idle reached");  
});

var el = document.getElementById('btn');
el.onclick = function() {
  timer.activity();
}
<button id="btn">Foo</button>

share|improve this question
up vote 2 down vote accepted

You could pass in an object into the constructor instead of using arguments. That way, you don't have to mind order. Additionally, you could add in defaults:

function InactivityTimer(options){

  // Defaults
  this.defaults = {
    timeout : 10
  };

  // Merge options to defaults> Let's just say you use jQuery.
  this.options = $.extend({}, this.defaults, this.options);

}

Now you wouldn't want to make this code run all the time, so I suggest you add in a start as well as a stop. You could also add in an autostart in options so it starts as soon as an instance is created.

InactivityTimer.prototype.start = function(){
  if(this.timer) return;
  this.timer = setTimeout(function(){
    ...
  },this.options.timeout);
}
InactivityTimer.prototype.stop = function(){
  clearTimeout(this.timer);
  this.timer = null;
}

You wouldn't want to hard-code all the code that runs when activity or inactivity occurs. I suggest you extend from an EventEmitter object. I have a simple implementation of such, which you could just plug in. Now you emit events in your code, and code outside can listen.

function InactivityTimer(options){
  EventEmitter.call(this); // Inherit properties
  ...
}

InactivityTimer.prototype = new EventEmitter();
InactivityTimer.prototype.start = function(){
  if(this.timer) return;
  this.timer = setTimeout(function(){
    this.emit('idle');
  },this.options.timeout);
  this.emit('start');
}
InactivityTimer.prototype.stop = function(){
  clearTimeout(this.timer);
  this.timer = null;
  this.emit('stop');
}


var idleCheck = new InactivityTimer({...});

idleCheck.on('start',function(){
  // timer started
});
idleCheck.on('stop',function(){
  // timer stopped
});
idleCheck.on('idle',function(){
  // user became idle
});
idleCheck.on('active',function(){
  // user became active
});

The same with listening for events instead of hard-coding the code that reacts to the events into InactivityTimer, you'd might want to also extract the code that listens for activity. Activity can be anything, and the consumer of your code might consider only click or probably mouse movement etc. Suggesting you add observe to listen for certain activity.

InactivityTimer.prototype.observe = function(observer){
  var instance = this;

  // Call the observer, passing it a callback that should be called when an event happens
  observer.call(this, function(){
    clearTimeout(instance.timer); // clear the timer
    instance.emit('active');      // inform listeners that timer became active
    instance.start                // start another timer
  });
});

// Usage
var timer = new InactivityTimer({...});

timer.observe(function(activate){
  $('body').on('click',activate); // Observe body clicks
  $(window).on('scroll',activate); // Observe scrolling
});
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.