Code coverage report for slap/lib/ui/BaseElement.js

Statements: 81.72% (76 / 93)      Branches: 64.29% (27 / 42)      Functions: 95% (19 / 20)      Lines: 90.41% (66 / 73)      Ignored: none     

All files » slap/lib/ui/ » BaseElement.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 1051 1 1   1   1   1 31   31   31 31 31 31 31 31 31   31   1   1 2 2 2 2 2 2     1 2 2 2 2       1 2 2 2 2         2 2   1 2   1     1 7 2   1 109   1 9 9 9     1 115   1 88 88     1   1 31 31 6 6   31 31 31 31 265               1   1  
var blessed = require('blessed');
var _ = require('lazy.js');
var Point = require('text-buffer/lib/point');
 
var Slap = require('./Slap');
 
var util = require('../util');
 
function BaseElement (opts) {
  var self = this;
 
  Iif (!(self instanceof blessed.Node)) return new BaseElement(opts);
 
  opts = _(Slap.global.options.element).merge(opts || {}).toObject();
  Eif (!('slap' in opts)) opts.slap = Slap.global;
  if (!('parent' in opts)) opts.parent = opts.slap;
  if (self instanceof BaseElement) blessed.Box.call(self, opts); // this should not be called if an element inherits from built-in blessed classes
  if (self.parent instanceof Pane) self.pane = self.parent;
  self.slap = opts.slap;
  self.focusable = opts.focusable;
 
  process.nextTick(function () { self._initHandlers(); });
}
BaseElement.prototype.__proto__ = blessed.Box.prototype;
 
BaseElement.prototype.walkDepthFirst = function (direction, after, fn) {
  Iif (arguments.length === 2) fn = after;
  var children = this.children.slice();
  Iif (direction === -1) children.reverse();
  Iif (after) children = children.slice(children.indexOf(after) + 1);
  return children.some(function (child) {
    return fn.apply(child, arguments) || BaseElement.prototype.walkDepthFirst.call(child, direction, fn);
  });
};
BaseElement.prototype.focusFirst = function (direction, after) {
  return this.walkDepthFirst(direction, after, function () {
    Eif (this.visible && this.focusable) {
      this.focus();
      return true;
    }
  });
};
BaseElement.prototype._focusDirection = function (direction) {
  var self = this;
  var descendantParent;
  var descendant = self.screen.focused;
  while (descendant.hasAncestor(self)) {
    descendantParent = descendant.parent;
    if (BaseElement.prototype.focusFirst.call(descendantParent, direction, descendant)) return self;
    descendant = descendantParent;
  }
  Iif (!self.focusFirst(direction)) throw new Error("no focusable descendant");
  return self;
};
BaseElement.prototype.focusNext = function () {
  return this._focusDirection(1);
};
BaseElement.prototype.focusPrev = function () {
  return this._focusDirection(-1);
};
BaseElement.prototype.focus = function () {
  if (!this.hasFocus()) return blessed.Box.prototype.focus.apply(this, arguments);
  return this;
};
BaseElement.prototype.isAttached = function () {
  return this.hasAncestor(this.screen);
};
BaseElement.prototype.hasFocus = function (asChild) {
  var self = this;
  var focused = self.screen.focused;
  return focused.visible && (focused === self || focused.hasAncestor(self) || (asChild && self.hasAncestor(focused)));
};
 
BaseElement.prototype.pos = function () {
  return new Point(this.top + this.itop, this.left + this.ileft);
};
BaseElement.prototype.size = function () {
  Iif (!this.isAttached()) return new Point(0, 0); // hack
  return new Point(this.height - this.iheight, this.width - this.iwidth);
};
 
BaseElement.prototype.shrinkWidth = function () { return this.content.length + this.iwidth; };
 
BaseElement.prototype._initHandlers = function () {
  var self = this;
  self.on('focus', function () {
    logger.debug('focus', util.typeOf(self));
    if (!self.focusable) self.focusNext();
  });
  self.on('blur', function () { logger.debug('blur', util.typeOf(self)); });
  self.on('show', function () { self.setFront(); });
  self.on('keypress', _.noop); // 'element keypress' doesn't work correctly without this
  self.on('element keypress', function (el, ch, key) {
    switch (util.getBinding(self.options.bindings, key)) {
      case 'hide': self.hide(); return false;
      case 'focusNext': self.focusNext(); return false;
      case 'focusPrev': self.focusPrev(); return false;
    }
  });
};
 
module.exports = BaseElement;
 
var Pane = require('./Pane'); // circular import