Code coverage report for lib/ui/BaseElement.js

Statements: 78.72% (74 / 94)      Branches: 61.9% (26 / 42)      Functions: 85% (17 / 20)      Lines: 88% (66 / 75)      Ignored: none     

All files » 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 105 106 107 1081 1 1 1   1   1   1 56   56   56 56 56 56 56 56 56   56 56     1   1 1 1 1 1 1 1     1 1 1 1 1       1 1 1 1 1         1 1   1 1   1     1 2     1 21   1 3 3 3     1 10   1 20 20     1   1 56 56 2 2   56 56 56 56                 1   1  
var Promise = require('bluebird');
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;
 
  self.ready = Promise.delay(0)
    .then(function () { return self._initHandlers(); })
    .return(self);
}
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 () {
  Eif (!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