668 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			668 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  **      ==============================
 | |
|  **       O           O      O   OOOO
 | |
|  **       O           O     O O  O   O
 | |
|  **       O           O     O O  O   O
 | |
|  **       OOOO   OOOO O     OOO  OOOO
 | |
|  **       O   O       O    O   O O   O
 | |
|  **       O   O       O    O   O O   O
 | |
|  **       OOOO        OOOO O   O OOOO
 | |
|  **      ==============================
 | |
|  **      Dr. Stefan Bosse http://www.bsslab.de
 | |
|  **
 | |
|  **      COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
 | |
|  **                 BY THE AUTHOR.
 | |
|  **                 THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
 | |
|  **                 MODIFIED, OR OTHERWISE USED IN A CONTEXT
 | |
|  **                 OUTSIDE OF THE SOFTWARE SYSTEM.
 | |
|  **
 | |
|  **    $AUTHORS:     Stefan Bosse
 | |
|  **    $INITIAL:     (C) 2013-2015, Christopher Jeffrey and contributors
 | |
|  **    $MODIFIED:    by sbosse (2017-2018)
 | |
|  **    $REVESIO:     1.2.5
 | |
|  **
 | |
|  **    $INFO:
 | |
|  **
 | |
|  **    list.js - list element for blessed
 | |
|  **
 | |
|  **     Added: 
 | |
|  **       - 'arrows', arrow buttons
 | |
|  **
 | |
|  **     Options: {selectlast,selectoffset,label, border, style, arrows?}
 | |
|  **
 | |
|  **       selectlast:boolean    (try to) select always last selected item after modification
 | |
|  **       selectoffset:number   additional (positive, downto) scroll shift on selection 
 | |
|  **                             (otherwise selected line jumps to bottom of window)
 | |
|  **
 | |
|  **     Events In: click, keypress, element wheeldown, element wheelup, resize, adopt, remove
 | |
|  **     Events Out: action(item,selected), select(item,selected), selected(item)
 | |
|  **     Item content text: item.content
 | |
|  **
 | |
|  **
 | |
|  **    Usage:
 | |
|  **     Create list: list=new List({..});
 | |
|  **     Update list: list.setItems([content1:string,content2:string,..]);
 | |
|  **     Get selected item content (label): list.getSelected().getContent();
 | |
|  **
 | |
|  **    $ENDOFINFO
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Modules
 | |
|  */
 | |
| var Comp = Require('com/compat');
 | |
| var Io = Require('com/io');
 | |
| var helpers = Require('term/helpers');
 | |
| 
 | |
| var Node = Require('term/widgets/node');
 | |
| var Box = Require('term/widgets/box');
 | |
| var Button = Require('term/widgets/button');
 | |
| var Arrows = Require('term/widgets/arrows');
 | |
| 
 | |
| /**
 | |
|  * List
 | |
|  */
 | |
| 
 | |
| function List(options) {
 | |
|   var self = this;
 | |
| 
 | |
|   if (!instanceOf(this,Node)) {
 | |
|     return new List(options);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   options = options || {};
 | |
| 
 | |
|   options.ignoreKeys = true;
 | |
|   // Possibly put this here: this.items = [];
 | |
|   options.scrollable = true;
 | |
|   Box.call(this, options);
 | |
|   this.value = '';
 | |
|   this.items = [];
 | |
|   this.ritems = [];
 | |
|   this.selected = 0;
 | |
|   this._isList = true;
 | |
| 
 | |
|   if (!this.style.selected) {
 | |
|     this.style.selected = {};
 | |
|     this.style.selected.bg = options.selectedBg;
 | |
|     this.style.selected.fg = options.selectedFg;
 | |
|     this.style.selected.bold = options.selectedBold;
 | |
|     this.style.selected.underline = options.selectedUnderline;
 | |
|     this.style.selected.blink = options.selectedBlink;
 | |
|     this.style.selected.inverse = options.selectedInverse;
 | |
|     this.style.selected.invisible = options.selectedInvisible;
 | |
|   }
 | |
| 
 | |
|   if (!this.style.item) {
 | |
|     this.style.item = {};
 | |
|     this.style.item.bg = options.itemBg;
 | |
|     this.style.item.fg = options.itemFg;
 | |
|     this.style.item.bold = options.itemBold;
 | |
|     this.style.item.underline = options.itemUnderline;
 | |
|     this.style.item.blink = options.itemBlink;
 | |
|     this.style.item.inverse = options.itemInverse;
 | |
|     this.style.item.invisible = options.itemInvisible;
 | |
|   }
 | |
| 
 | |
|   // Legacy: for apps written before the addition of item attributes.
 | |
|   ['bg', 'fg', 'bold', 'underline',
 | |
|    'blink', 'inverse', 'invisible'].forEach(function(name) {
 | |
|     if (self.style[name] != null && self.style.item[name] == null) {
 | |
|       self.style.item[name] = self.style[name];
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   if (this.options.itemHoverBg) {
 | |
|     this.options.itemHoverEffects = { bg: this.options.itemHoverBg };
 | |
|   }
 | |
| 
 | |
|   if (this.options.itemHoverEffects) {
 | |
|     this.style.item.hover = this.options.itemHoverEffects;
 | |
|   }
 | |
| 
 | |
|   if (this.options.itemFocusEffects) {
 | |
|     this.style.item.focus = this.options.itemFocusEffects;
 | |
|   }
 | |
| 
 | |
|   this.interactive = options.interactive !== false;
 | |
| 
 | |
|   this.mouse = options.mouse || false;
 | |
| 
 | |
|   if (options.items) {
 | |
|     this.ritems = options.items;
 | |
|     options.items.forEach(this.add.bind(this));
 | |
|   }
 | |
| 
 | |
|   this.select(0);
 | |
| 
 | |
|   if (options.mouse) {
 | |
|     this.screen._listenMouse(this);
 | |
|     this.on('element wheeldown', function() {
 | |
|       self.select(self.selected + 2);
 | |
|       self.screen.render();
 | |
|     });
 | |
|     this.on('element wheelup', function() {
 | |
|       self.select(self.selected - 2);
 | |
|       self.screen.render();
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   if (options.keys) {
 | |
|     this.on('keypress', function(ch, key) {
 | |
|       if (key.name === 'up' || (options.vi && key.name === 'k')) {
 | |
|         self.up();
 | |
|         self.screen.render();
 | |
|         self.emit('selected', self.items[self.selected]);
 | |
|         return;
 | |
|       }
 | |
|       if (key.name === 'down' || (options.vi && key.name === 'j')) {
 | |
|         self.down();
 | |
|         self.screen.render();
 | |
|         self.emit('selected', self.items[self.selected]);
 | |
|         return;
 | |
|       }
 | |
|       if (key.name === 'enter'
 | |
|           || (options.vi && key.name === 'l' && !key.shift)) {
 | |
|         self.enterSelected();
 | |
|         return;
 | |
|       }
 | |
|       if (key.name === 'escape' || (options.vi && key.name === 'q')) {
 | |
|         self.cancelSelected();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'u' && key.ctrl) {
 | |
|         self.move(-((self.height - self.iheight) / 2) | 0);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'd' && key.ctrl) {
 | |
|         self.move((self.height - self.iheight) / 2 | 0);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'b' && key.ctrl) {
 | |
|         self.move(-(self.height - self.iheight));
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'f' && key.ctrl) {
 | |
|         self.move(self.height - self.iheight);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'h' && key.shift) {
 | |
|         self.move(self.childBase - self.selected);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'm' && key.shift) {
 | |
|         // TODO: Maybe use Math.min(this.items.length,
 | |
|         // ... for calculating visible items elsewhere.
 | |
|         var visible = Math.min(
 | |
|           self.height - self.iheight,
 | |
|           self.items.length) / 2 | 0;
 | |
|         self.move(self.childBase + visible - self.selected);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'l' && key.shift) {
 | |
|         // XXX This goes one too far on lists with an odd number of items.
 | |
|         self.down(self.childBase
 | |
|           + Math.min(self.height - self.iheight, self.items.length)
 | |
|           - self.selected);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'g' && !key.shift) {
 | |
|         self.select(0);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
|       if (options.vi && key.name === 'g' && key.shift) {
 | |
|         self.select(self.items.length - 1);
 | |
|         self.screen.render();
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       if (options.vi && (key.ch === '/' || key.ch === '?')) {
 | |
|         if (typeof self.options.search !== 'function') {
 | |
|           return;
 | |
|         }
 | |
|         return self.options.search(function(err, value) {
 | |
|           if (typeof err === 'string' || typeof err === 'function'
 | |
|               || typeof err === 'number' || (err && err.test)) {
 | |
|             value = err;
 | |
|             err = null;
 | |
|           }
 | |
|           if (err || !value) return self.screen.render();
 | |
|           self.select(self.fuzzyFind(value, key.ch === '?'));
 | |
|           self.screen.render();
 | |
|         });
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   this.on('resize', function() {
 | |
|     var visible = self.height - self.iheight;
 | |
|     // if (self.selected < visible - 1) {
 | |
|     if (visible >= self.selected + 1) {
 | |
|       self.childBase = 0;
 | |
|       self.childOffset = self.selected;
 | |
|     } else {
 | |
|       // Is this supposed to be: self.childBase = visible - self.selected + 1; ?
 | |
|       self.childBase = self.selected - visible + 1;
 | |
|       self.childOffset = visible - 1;
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   this.on('adopt', function(el) {
 | |
|     if (!~self.items.indexOf(el)) {
 | |
|       el.fixed = true;
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   // Ensure children are removed from the
 | |
|   // item list if they are items.
 | |
|   this.on('remove', function(el) {
 | |
|     self.removeItem(el);
 | |
|   });
 | |
| 
 | |
|   if (options.arrows) 
 | |
|     Arrows(
 | |
|       self,
 | |
|       options,
 | |
|       function () { self.select(self.selected - 2); self.screen.render()},
 | |
|       function () { self.select(self.selected + 2); self.screen.render()}
 | |
|     );
 | |
| }
 | |
| 
 | |
| //List.prototype.__proto__ = Box.prototype;
 | |
| inheritPrototype(List,Box);
 | |
| 
 | |
| List.prototype.type = 'list';
 | |
| 
 | |
| List.prototype.createItem = function(content) {
 | |
|   var self = this;
 | |
| 
 | |
|   // Note: Could potentially use Button here.
 | |
|   var options = {
 | |
|     screen: this.screen,
 | |
|     content: content,
 | |
|     align: this.align || 'left',
 | |
|     top: 0,
 | |
|     left: 0,
 | |
|     right: (this.scrollbar ? 1 : 0),
 | |
|     tags: this.parseTags,
 | |
|     height: 1,
 | |
|     hoverEffects: this.mouse ? this.style.item.hover : null,
 | |
|     focusEffects: this.mouse ? this.style.item.focus : null,
 | |
|     autoFocus: false
 | |
|   };
 | |
| 
 | |
|   if (!this.screen.autoPadding) {
 | |
|     options.top = 1;
 | |
|     options.left = this.ileft;
 | |
|     options.right = this.iright + (this.scrollbar ? 1 : 0);
 | |
|   }
 | |
| 
 | |
|   // if (this.shrink) {
 | |
|   // XXX NOTE: Maybe just do this on all shrinkage once autoPadding is default?
 | |
|   if (this.shrink && this.options.normalShrink) {
 | |
|     delete options.right;
 | |
|     options.width = 'shrink';
 | |
|   }
 | |
| 
 | |
|   ['bg', 'fg', 'bold', 'underline',
 | |
|    'blink', 'inverse', 'invisible'].forEach(function(name) {
 | |
|     options[name] = function() {
 | |
|       var attr = self.items[self.selected] === item && self.interactive
 | |
|         ? self.style.selected[name]
 | |
|         : self.style.item[name];
 | |
|       if (typeof attr === 'function') attr = attr(item);
 | |
|       return attr;
 | |
|     };
 | |
|   });
 | |
| 
 | |
|   if (this.style.transparent) {
 | |
|     options.transparent = true;
 | |
|   }
 | |
| 
 | |
|   var item = new Box(options);
 | |
| 
 | |
|   if (this.mouse) {
 | |
|     item.on('click', function() {
 | |
|       self.focus();
 | |
|       if (self.items[self.selected] === item) {
 | |
|         self.emit('action', item, self.selected);
 | |
|         self.emit('select', item, self.selected);
 | |
|         return;
 | |
|       }
 | |
|       self.select(item);
 | |
|       self.emit('selected', self.items[self.selected]);
 | |
|       self.screen.render();
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   this.emit('create item');
 | |
| 
 | |
|   return item;
 | |
| };
 | |
| 
 | |
| List.prototype.add =
 | |
| List.prototype.addItem =
 | |
| List.prototype.appendItem = function(content) {
 | |
|   content = typeof content === 'string' ? content : content.getContent();
 | |
| 
 | |
|   var item = this.createItem(content);
 | |
|   item.position.top = this.items.length;
 | |
|   if (!this.screen.autoPadding) {
 | |
|     item.position.top = this.itop + this.items.length;
 | |
|   }
 | |
| 
 | |
|   this.ritems.push(content);
 | |
|   this.items.push(item);
 | |
|   this.append(item);
 | |
| 
 | |
|   if (this.items.length === 1) {
 | |
|     this.select(0);
 | |
|   }
 | |
| 
 | |
|   this.emit('add item');
 | |
| 
 | |
|   return item;
 | |
| };
 | |
| 
 | |
| List.prototype.removeItem = function(child) {
 | |
|   var i = this.getItemIndex(child);
 | |
|   if (~i && this.items[i]) {
 | |
|     child = this.items.splice(i, 1)[0];
 | |
|     this.ritems.splice(i, 1);
 | |
|     this.remove(child);
 | |
|     for (var j = i; j < this.items.length; j++) {
 | |
|       this.items[j].position.top--;
 | |
|     }
 | |
|     if (i === this.selected) {
 | |
|       this.select(i - 1);
 | |
|     }
 | |
|   }
 | |
|   this.emit('remove item');
 | |
|   return child;
 | |
| };
 | |
| 
 | |
| List.prototype.insertItem = function(child, content) {
 | |
|   content = typeof content === 'string' ? content : content.getContent();
 | |
|   var i = this.getItemIndex(child);
 | |
|   if (!~i) return;
 | |
|   if (i >= this.items.length) return this.appendItem(content);
 | |
|   var item = this.createItem(content);
 | |
|   for (var j = i; j < this.items.length; j++) {
 | |
|     this.items[j].position.top++;
 | |
|   }
 | |
|   item.position.top = i + (!this.screen.autoPadding ? 1 : 0);
 | |
|   this.ritems.splice(i, 0, content);
 | |
|   this.items.splice(i, 0, item);
 | |
|   this.append(item);
 | |
|   if (i === this.selected) {
 | |
|     this.select(i + 1);
 | |
|   }
 | |
|   this.emit('insert item');
 | |
| };
 | |
| 
 | |
| List.prototype.getItem = function(child) {
 | |
|   return this.items[this.getItemIndex(child)];
 | |
| };
 | |
| 
 | |
| List.prototype.setItem = function(child, content) {
 | |
|   content = typeof content === 'string' ? content : content.getContent();
 | |
|   var i = this.getItemIndex(child);
 | |
|   if (!~i) return;
 | |
|   this.items[i].setContent(content);
 | |
|   this.ritems[i] = content;
 | |
| };
 | |
| 
 | |
| List.prototype.clearItems = function() {
 | |
|   return this.setItems([]);
 | |
| };
 | |
| 
 | |
| List.prototype.setItems = function(items) {
 | |
|   var original = this.items.slice()
 | |
|     , selected = this.selected
 | |
|     , sel = this.ritems[this.selected]
 | |
|     , i = 0;
 | |
| 
 | |
|   items = items.slice();
 | |
| 
 | |
|   this.select(0);
 | |
| 
 | |
|   for (; i < items.length; i++) {
 | |
|     if (this.items[i]) {
 | |
|       this.items[i].setContent(items[i]);
 | |
|     } else {
 | |
|       this.add(items[i]);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (; i < original.length; i++) {
 | |
|     this.remove(original[i]);
 | |
|   }
 | |
| 
 | |
|   this.ritems = items;
 | |
| 
 | |
|   // Try to find our old item if it still exists.
 | |
|   // But how to deal with ambiquous string items? indexOf can point to wrong item!?
 | |
|   sel = items.indexOf(sel);
 | |
|   if (this.options.selectlast) this.select(selected);
 | |
|   /*
 | |
|   if (~sel) {
 | |
|     this.select(sel);
 | |
|   } else */ if (items.length === original.length) {
 | |
|     this.select(selected);
 | |
|   } else {
 | |
|     this.select(Math.min(selected, items.length - 1));
 | |
|   }
 | |
| 
 | |
|   this.emit('set items');
 | |
| };
 | |
| 
 | |
| List.prototype.pushItem = function(content) {
 | |
|   this.appendItem(content);
 | |
|   return this.items.length;
 | |
| };
 | |
| 
 | |
| List.prototype.popItem = function() {
 | |
|   return this.removeItem(this.items.length - 1);
 | |
| };
 | |
| 
 | |
| List.prototype.unshiftItem = function(content) {
 | |
|   this.insertItem(0, content);
 | |
|   return this.items.length;
 | |
| };
 | |
| 
 | |
| List.prototype.shiftItem = function() {
 | |
|   return this.removeItem(0);
 | |
| };
 | |
| 
 | |
| List.prototype.spliceItem = function(child, n) {
 | |
|   var self = this;
 | |
|   var i = this.getItemIndex(child);
 | |
|   if (!~i) return;
 | |
|   var items = Array.prototype.slice.call(arguments, 2);
 | |
|   var removed = [];
 | |
|   while (n--) {
 | |
|     removed.push(this.removeItem(i));
 | |
|   }
 | |
|   items.forEach(function(item) {
 | |
|     self.insertItem(i++, item);
 | |
|   });
 | |
|   return removed;
 | |
| };
 | |
| 
 | |
| List.prototype.find =
 | |
| List.prototype.fuzzyFind = function(search, back) {
 | |
|   var start = this.selected + (back ? -1 : 1)
 | |
|     , i;
 | |
| 
 | |
|   if (typeof search === 'number') search += '';
 | |
| 
 | |
|   if (search && search[0] === '/' && search[search.length - 1] === '/') {
 | |
|     try {
 | |
|       search = new RegExp(search.slice(1, -1));
 | |
|     } catch (e) {
 | |
|       ;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   var test = typeof search === 'string'
 | |
|     ? function(item) { return !!~item.indexOf(search); }
 | |
|     : (search.test ? search.test.bind(search) : search);
 | |
| 
 | |
|   if (typeof test !== 'function') {
 | |
|     if (this.screen.options.debug) {
 | |
|       throw new Error('fuzzyFind(): `test` is not a function.');
 | |
|     }
 | |
|     return this.selected;
 | |
|   }
 | |
| 
 | |
|   if (!back) {
 | |
|     for (i = start; i < this.ritems.length; i++) {
 | |
|       if (test(helpers.cleanTags(this.ritems[i]))) return i;
 | |
|     }
 | |
|     for (i = 0; i < start; i++) {
 | |
|       if (test(helpers.cleanTags(this.ritems[i]))) return i;
 | |
|     }
 | |
|   } else {
 | |
|     for (i = start; i >= 0; i--) {
 | |
|       if (test(helpers.cleanTags(this.ritems[i]))) return i;
 | |
|     }
 | |
|     for (i = this.ritems.length - 1; i > start; i--) {
 | |
|       if (test(helpers.cleanTags(this.ritems[i]))) return i;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return this.selected;
 | |
| };
 | |
| 
 | |
| List.prototype.getItemIndex = function(child) {
 | |
|   if (typeof child === 'number') {
 | |
|     return child;
 | |
|   } else if (typeof child === 'string') {
 | |
|     var i = this.ritems.indexOf(child);
 | |
|     if (~i) return i;
 | |
|     for (i = 0; i < this.ritems.length; i++) {
 | |
|       if (helpers.cleanTags(this.ritems[i]) === child) {
 | |
|         return i;
 | |
|       }
 | |
|     }
 | |
|     return -1;
 | |
|   } else {
 | |
|     return this.items.indexOf(child);
 | |
|   }
 | |
| };
 | |
| 
 | |
| List.prototype.getSelected = function() {
 | |
|   return this.items[this.selected]; 
 | |
| }
 | |
| 
 | |
| List.prototype.select = function(index) {
 | |
|   var lastindex=this.selected;
 | |
|   if (!this.interactive) {
 | |
|     return;
 | |
|   }
 | |
|   if (!this.items.length) {
 | |
|     this.selected = 0;
 | |
|     this.value = '';
 | |
|     this.scrollTo(0);
 | |
|     return;
 | |
|   }
 | |
|   if (typeof index === 'object') {
 | |
|     index = this.items.indexOf(index);
 | |
|   }
 | |
|   
 | |
|   if (index < 0) {
 | |
|     index = 0;
 | |
|   } else if (index >= this.items.length) {
 | |
|     index = this.items.length - 1;
 | |
|   }
 | |
| 
 | |
|   if (this.selected === index && this._listInitialized) return;
 | |
|   this._listInitialized = true;
 | |
| 
 | |
|   this.selected = index;
 | |
|   this.value = helpers.cleanTags(this.ritems[this.selected]);
 | |
|   if (!this.parent) return;
 | |
|   if (index>=lastindex)
 | |
|     this.scrollTo(this.selected+(this.options.selectoffset||0));
 | |
|   else
 | |
|     this.scrollTo(this.selected);
 | |
|     
 | |
| 
 | |
|   // XXX Move `action` and `select` events here.
 | |
|   this.emit('select item', this.items[this.selected], this.selected);
 | |
| };
 | |
| 
 | |
| List.prototype.move = function(offset) {
 | |
|   this.select(this.selected + offset);
 | |
| };
 | |
| 
 | |
| List.prototype.up = function(offset) {
 | |
|   this.move(-(offset || 1));
 | |
| };
 | |
| 
 | |
| List.prototype.down = function(offset) {
 | |
|   this.move(offset || 1);
 | |
| };
 | |
| 
 | |
| List.prototype.pick = function(label, callback) {
 | |
|   if (!callback) {
 | |
|     callback = label;
 | |
|     label = null;
 | |
|   }
 | |
| 
 | |
|   if (!this.interactive) {
 | |
|     return callback();
 | |
|   }
 | |
| 
 | |
|   var self = this;
 | |
|   var focused = this.screen.focused;
 | |
|   if (focused && focused._done) focused._done('stop');
 | |
|   this.screen.saveFocus();
 | |
| 
 | |
|   // XXX Keep above:
 | |
|   // var parent = this.parent;
 | |
|   // this.detach();
 | |
|   // parent.append(this);
 | |
| 
 | |
|   this.focus();
 | |
|   this.show();
 | |
|   this.select(0);
 | |
|   if (label) this.setLabel(label);
 | |
|   this.screen.render();
 | |
|   this.once('action', function(el, selected) {
 | |
|     if (label) self.removeLabel();
 | |
|     self.screen.restoreFocus();
 | |
|     self.hide();
 | |
|     self.screen.render();
 | |
|     if (!el) return callback();
 | |
|     return callback(null, helpers.cleanTags(self.ritems[selected]));
 | |
|   });
 | |
| };
 | |
| 
 | |
| List.prototype.enterSelected = function(i) {
 | |
|   if (i != null) this.select(i);
 | |
|   this.emit('action', this.items[this.selected], this.selected);
 | |
|   this.emit('select', this.items[this.selected], this.selected);
 | |
| };
 | |
| 
 | |
| List.prototype.cancelSelected = function(i) {
 | |
|   if (i != null) this.select(i);
 | |
|   this.emit('action');
 | |
|   this.emit('cancel');
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Expose
 | |
|  */
 | |
| 
 | |
| module.exports = List;
 |