joshfire/joshfire-framework

Control the minimum time interval between consecutive keypresses

Opened this issue · 0 comments

We sometimes need to define a minimum time interval between consecutive keypresses.

On TV in particular, some applications react badly to repeated/extended keypresses on the remote. Doing so can sometimes cause refreshing issues, leading to manipulating DOM elements that aren't updated yet.

Making the application code more robust to unexpected DOM structure can become complex in large code bases. In that case, having a way to control the minimum interval between two keypresses might be useful.

One way to do so without impacting code on the framework side is to redefine the current adapter's processKey method on the client side:

var originalProcessKey = UIElement.prototype.processKey;

// Takes the originalProcessKey and calls it only if it is available.
// Each keypress will make it unavailable for 1s.

var available = true;
var myNewProcessKey = function(event) {

  if (available) {
    available = false;
    originalProcessKey.call(this, event);
    setTimeout(function() { available = true; }, 1000);
  }
}
UIElement.prototype.processKey = myNewProcessKey;

This approach has the benefit of not impacting any code on the framework, and very little on the client side.

However, this approach fails with some view elements.

UIElement#processKey method will call the corresponding action (navUp, navRight, etc.) only if the current view has it, if not, then it will call processKey on the view's origin (this.origin) and will do so until the action is either found or the view has no origin.

Since processKey has been redefined, the new version will be called, which will prevent further call to the original processKey method, making pressing the key ineffective.

A simple way to remedy to this situation would be to add an intermediate call in the framework on each keypresses:

Suppose we are in the UIElement module of an adapter (say googletv for instance):

// Dispatches an event to processKey.
// This can be redefined to allow a delay between
// key presses, often useful on TV.
keyDispatch: function(event) {
  this.processKey(event);
}

With this addition, the above solution would work: we'd only control access to keyDispatch, and processKey will be able to call itself recursively:

var originalKeyDispatch = UIElement.prototype.keyDispatch;

// Takes the originalProcessKey and calls it only if it is available.
// Each keypress will make it unavailable for 1s.

var available = true;
var newKeyDispatch = function(event) {

  if (available) {
    available = false;
    originalKeyDispatch.call(this, event);
    setTimeout(function() { available = true; }, 1000);
  }
}
UIElement.prototype.keyDispatch = newKeyDispatch;

As it currently stands, this little change would need to be rippled to each adapters since key bindings are defined in the adapters' UIElement modules.

Should this approach be kept? Should the framework provide an easier way to control the minimum time interval between consecutive keypresses (maybe as a general helper)?