- Remove inputType from previous check in. Will replace with MaskEditTextView stuff
* Cleanup self.options in Views. Just use self.XXXXXX and pass in options to configure * View's take one param for ctor: options. Including options.client * Experimental / WIP cursor show/hide in Views
This commit is contained in:
parent
6d84018ef5
commit
2bac8e006e
|
@ -54,7 +54,10 @@ var CONTROL = {
|
||||||
blinkToBrightIntensity : '?33h',
|
blinkToBrightIntensity : '?33h',
|
||||||
blinkNormal : '?33l',
|
blinkNormal : '?33l',
|
||||||
|
|
||||||
emulationSpeed : '*r' // Set output emulation speed. See cterm.txt
|
emulationSpeed : '*r', // Set output emulation speed. See cterm.txt
|
||||||
|
|
||||||
|
hideCursor : '?25l', // Nonstandard - cterm.txt
|
||||||
|
showCursor : '?25h', // Nonstandard - cterm.txt
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,12 +8,13 @@ var assert = require('assert');
|
||||||
|
|
||||||
exports.ButtonView = ButtonView;
|
exports.ButtonView = ButtonView;
|
||||||
|
|
||||||
function ButtonView(client, options) {
|
function ButtonView(options) {
|
||||||
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
||||||
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
||||||
options.justify = miscUtil.valueWithDefault(options.justify, 'center');
|
options.justify = miscUtil.valueWithDefault(options.justify, 'center');
|
||||||
|
options.cursor = miscUtil.valueWithDefault(options.cursor, 'hide');
|
||||||
|
|
||||||
TextView.call(this, client, options);
|
TextView.call(this, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(ButtonView, TextView);
|
util.inherits(ButtonView, TextView);
|
||||||
|
|
|
@ -9,14 +9,11 @@ var assert = require('assert');
|
||||||
|
|
||||||
exports.EditTextView = EditTextView;
|
exports.EditTextView = EditTextView;
|
||||||
|
|
||||||
function EditTextView(client, options) {
|
function EditTextView(options) {
|
||||||
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
||||||
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
||||||
options.inputType = miscUtil.valueWithDefault(options.inputType, 'normal');
|
|
||||||
|
|
||||||
TextView.call(this, client, options);
|
TextView.call(this, options);
|
||||||
|
|
||||||
assert(this.inputType in EditTextView.InputTypes);
|
|
||||||
|
|
||||||
this.clientBackspace = function() {
|
this.clientBackspace = function() {
|
||||||
this.client.term.write(
|
this.client.term.write(
|
||||||
|
@ -26,27 +23,6 @@ function EditTextView(client, options) {
|
||||||
|
|
||||||
util.inherits(EditTextView, TextView);
|
util.inherits(EditTextView, TextView);
|
||||||
|
|
||||||
EditTextView.InputTypes = {
|
|
||||||
normal : 1,
|
|
||||||
email : 2,
|
|
||||||
numeric : 3,
|
|
||||||
alpha : 4,
|
|
||||||
alphaNumeric : 5,
|
|
||||||
phone : 6,
|
|
||||||
};
|
|
||||||
Object.freeze(EditTextView.InputTypes);
|
|
||||||
|
|
||||||
EditTextView.prototype.isKeyValidForInputType = function(key) {
|
|
||||||
// :TODO: add in the actual validations:
|
|
||||||
switch(this.inputType) {
|
|
||||||
case 'normal' : return true;
|
|
||||||
case 'email' : return true; // :TODO: validate based on char + position
|
|
||||||
case 'numeric' : return !isNaN(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
EditTextView.prototype.onKeyPress = function(key, isSpecial) {
|
EditTextView.prototype.onKeyPress = function(key, isSpecial) {
|
||||||
if(isSpecial) {
|
if(isSpecial) {
|
||||||
return;
|
return;
|
||||||
|
@ -54,13 +30,9 @@ EditTextView.prototype.onKeyPress = function(key, isSpecial) {
|
||||||
|
|
||||||
assert(1 === key.length);
|
assert(1 === key.length);
|
||||||
|
|
||||||
if(!this.isKeyValidForInputType(key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// :TODO: how to handle justify left/center?
|
// :TODO: how to handle justify left/center?
|
||||||
|
|
||||||
if(this.text.length < this.options.maxLength) {
|
if(this.text.length < this.maxLength) {
|
||||||
key = strUtil.stylizeString(key, this.textStyle);
|
key = strUtil.stylizeString(key, this.textStyle);
|
||||||
|
|
||||||
this.text += key;
|
this.text += key;
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* jslint node: true */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var TextView = require('./text_view.js').TextView;
|
||||||
|
var miscUtil = require('./misc_util.js');
|
||||||
|
|
||||||
|
var util = require('util');
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
function MaskEditTextView(client, options) {
|
||||||
|
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
||||||
|
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
||||||
|
|
||||||
|
TextView.call(this, client, options);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.mask = options.mask || '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(MaskEditTextView, TextView);
|
||||||
|
|
||||||
|
MaskEditTextView.MaskCharacterRegEx = {
|
||||||
|
'#' : /[0-9]/,
|
||||||
|
'?' : /[a-zA-Z]/,
|
||||||
|
'&' : /[\w\d\s]/, // 32-126, 128-255
|
||||||
|
'A' : /[0-9a-zA-Z]/,
|
||||||
|
};
|
||||||
|
|
||||||
|
MaskEditTextView.prototype.setMask = function(mask) {
|
||||||
|
this.mask = mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
MaskEditTextView.prototype.onKeyPress = function(key, isSpecial) {
|
||||||
|
if(isSpecial) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(1 === key.length);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MaskEditTextView.super_.prototype.onKeyPress(this, key, isSpecial);
|
||||||
|
};
|
||||||
|
|
||||||
|
MaskEditTextView.prototype.onSpecialKeyPress = function(keyName) {
|
||||||
|
|
||||||
|
if(this.isSpecialKeyMapped('backspace', keyName)) {
|
||||||
|
/*
|
||||||
|
if(this.text.length > 0) {
|
||||||
|
this.text = this.text.substr(0, this.text.length - 1);
|
||||||
|
this.clientBackspace();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
MaskEditTextView.super_.prototype.onSpecialKeyPress.call(this, keyName);
|
||||||
|
};
|
|
@ -33,6 +33,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||||
|
|
||||||
var view;
|
var view;
|
||||||
var options = {
|
var options = {
|
||||||
|
client : this.client,
|
||||||
id : mci.id,
|
id : mci.id,
|
||||||
color : mci.color,
|
color : mci.color,
|
||||||
focusColor : mci.focusColor,
|
focusColor : mci.focusColor,
|
||||||
|
@ -63,7 +64,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||||
options.dimens = { width : options.maxLength };
|
options.dimens = { width : options.maxLength };
|
||||||
}
|
}
|
||||||
|
|
||||||
view = new TextView(this.client, options);
|
view = new TextView(options);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ET' :
|
case 'ET' :
|
||||||
|
@ -76,7 +77,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||||
|
|
||||||
setFocusOption(0, 'focusTextStyle');
|
setFocusOption(0, 'focusTextStyle');
|
||||||
|
|
||||||
view = new EditTextView(this.client, options);
|
view = new EditTextView(options);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'PL' :
|
case 'PL' :
|
||||||
|
@ -91,7 +92,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||||
options.dimens = { width : options.maxLength };
|
options.dimens = { width : options.maxLength };
|
||||||
}
|
}
|
||||||
|
|
||||||
view = new TextView(this.client, options);
|
view = new TextView(options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -106,7 +107,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||||
|
|
||||||
setFocusOption(0, 'focusTextStyle');
|
setFocusOption(0, 'focusTextStyle');
|
||||||
|
|
||||||
view = new ButtonView(this.client, options);
|
view = new ButtonView(options);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'VM' :
|
case 'VM' :
|
||||||
|
@ -116,7 +117,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||||
|
|
||||||
setFocusOption(0, 'focusTextStyle');
|
setFocusOption(0, 'focusTextStyle');
|
||||||
|
|
||||||
view = new VerticalMenuView(this.client, options);
|
view = new VerticalMenuView(options);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,31 +9,31 @@ var assert = require('assert');
|
||||||
|
|
||||||
exports.MenuView = MenuView;
|
exports.MenuView = MenuView;
|
||||||
|
|
||||||
function MenuView(client, options) {
|
function MenuView(options) {
|
||||||
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
||||||
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
||||||
|
|
||||||
View.call(this, client, options);
|
View.call(this, options);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if(this.options.items) {
|
if(options.items) {
|
||||||
this.setItems(this.options.items);
|
this.setItems(options.items);
|
||||||
} else {
|
} else {
|
||||||
this.items = [];
|
this.items = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.focusedItemIndex = this.options.focusedItemIndex || 0;
|
this.focusedItemIndex = options.focusedItemIndex || 0;
|
||||||
this.focusedItemIndex = this.items.length >= this.focusedItemIndex ? this.focusedItemIndex : 0;
|
this.focusedItemIndex = this.items.length >= this.focusedItemIndex ? this.focusedItemIndex : 0;
|
||||||
|
|
||||||
this.itemSpacing = this.options.itemSpacing || 1;
|
this.itemSpacing = options.itemSpacing || 1;
|
||||||
this.itemSpacing = parseInt(this.itemSpacing, 10);
|
this.itemSpacing = parseInt(this.itemSpacing, 10);
|
||||||
|
|
||||||
this.focusPrefix = this.options.focusPrefix || '';
|
this.focusPrefix = options.focusPrefix || '';
|
||||||
this.focusSuffix = this.options.focusSuffix || '';
|
this.focusSuffix = options.focusSuffix || '';
|
||||||
|
|
||||||
this.fillChar = miscUtil.valueWithDefault(this.options.fillChar, ' ').substr(0, 1);
|
this.fillChar = miscUtil.valueWithDefault(options.fillChar, ' ').substr(0, 1);
|
||||||
this.justify = this.options.justify || 'none';
|
this.justify = options.justify || 'none';
|
||||||
|
|
||||||
this.moveSelection = function(fromIndex, toIndex) {
|
this.moveSelection = function(fromIndex, toIndex) {
|
||||||
assert(!self.positionCacheExpired);
|
assert(!self.positionCacheExpired);
|
||||||
|
|
|
@ -10,19 +10,19 @@ var assert = require('assert');
|
||||||
|
|
||||||
exports.TextView = TextView;
|
exports.TextView = TextView;
|
||||||
|
|
||||||
function TextView(client, options) {
|
function TextView(options) {
|
||||||
View.call(this, client, options);
|
View.call(this, options);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if(this.options.maxLength) {
|
if(options.maxLength) {
|
||||||
this.maxLength = this.options.maxLength;
|
this.maxLength = options.maxLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.multiLine = this.options.multiLine || false;
|
this.multiLine = options.multiLine || false;
|
||||||
this.fillChar = miscUtil.valueWithDefault(this.options.fillChar, ' ').substr(0, 1);
|
this.fillChar = miscUtil.valueWithDefault(options.fillChar, ' ').substr(0, 1);
|
||||||
this.justify = this.options.justify || 'right';
|
this.justify = options.justify || 'right';
|
||||||
this.inputType = this.options.inputType || 'normal';
|
//this.inputType = options.inputType || 'normal';
|
||||||
|
|
||||||
this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle;
|
this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ function TextView(client, options) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setText(this.options.text || '');
|
this.setText(options.text || '');
|
||||||
|
|
||||||
if(this.isPasswordTextStyle) {
|
if(this.isPasswordTextStyle) {
|
||||||
this.textMaskChar = miscUtil.valueWithDefault(this.textMaskChar, '*').substr(0, 1);
|
this.textMaskChar = miscUtil.valueWithDefault(this.textMaskChar, '*').substr(0, 1);
|
||||||
|
|
|
@ -10,13 +10,13 @@ var assert = require('assert');
|
||||||
|
|
||||||
exports.TickerTextView = TickerTextView;
|
exports.TickerTextView = TickerTextView;
|
||||||
|
|
||||||
function TickerTextView(client, options) {
|
function TickerTextView(options) {
|
||||||
View.call(this, client, options);
|
View.call(this, options);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.text = this.options.text || '';
|
this.text = options.text || '';
|
||||||
this.tickerStyle = this.options.tickerStyle || 'rightToLeft';
|
this.tickerStyle = options.tickerStyle || 'rightToLeft';
|
||||||
assert(this.tickerStyle in TickerTextView.TickerStyles);
|
assert(this.tickerStyle in TickerTextView.TickerStyles);
|
||||||
|
|
||||||
// :TODO: Ticker |text| should have ANSI stripped before calculating any lengths/etc.
|
// :TODO: Ticker |text| should have ANSI stripped before calculating any lengths/etc.
|
||||||
|
|
|
@ -9,8 +9,10 @@ var assert = require('assert');
|
||||||
|
|
||||||
exports.VerticalMenuView = VerticalMenuView;
|
exports.VerticalMenuView = VerticalMenuView;
|
||||||
|
|
||||||
function VerticalMenuView(client, options) {
|
function VerticalMenuView(options) {
|
||||||
MenuView.call(this, client, options);
|
options.cursor = options.cursor || 'hide';
|
||||||
|
|
||||||
|
MenuView.call(this, options);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
|
38
core/view.js
38
core/view.js
|
@ -5,6 +5,7 @@ var events = require('events');
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var ansi = require('./ansi_term.js');
|
var ansi = require('./ansi_term.js');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
exports.View = View;
|
exports.View = View;
|
||||||
exports.VIEW_SPECIAL_KEY_MAP_DEFAULT = VIEW_SPECIAL_KEY_MAP_DEFAULT;
|
exports.VIEW_SPECIAL_KEY_MAP_DEFAULT = VIEW_SPECIAL_KEY_MAP_DEFAULT;
|
||||||
|
@ -19,15 +20,17 @@ var VIEW_SPECIAL_KEY_MAP_DEFAULT = {
|
||||||
down : [ 'down arrow' ],
|
down : [ 'down arrow' ],
|
||||||
};
|
};
|
||||||
|
|
||||||
function View(client, options) {
|
function View(options) {
|
||||||
events.EventEmitter.call(this);
|
events.EventEmitter.call(this);
|
||||||
|
|
||||||
assert(client);
|
assert(_.isObject(options));
|
||||||
|
assert(_.isObject(options.client));
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.client = client;
|
this.client = options.client;
|
||||||
this.options = options || {};
|
|
||||||
|
this.cursor = options.cursor || 'show';
|
||||||
|
|
||||||
this.acceptsFocus = options.acceptsFocus || false;
|
this.acceptsFocus = options.acceptsFocus || false;
|
||||||
this.acceptsInput = options.acceptsInput || false;
|
this.acceptsInput = options.acceptsInput || false;
|
||||||
|
@ -37,34 +40,34 @@ function View(client, options) {
|
||||||
this.position = { x : 0, y : 0 };
|
this.position = { x : 0, y : 0 };
|
||||||
this.dimens = { height : 1, width : 0 };
|
this.dimens = { height : 1, width : 0 };
|
||||||
|
|
||||||
this.textStyle = this.options.textStyle || 'normal';
|
this.textStyle = options.textStyle || 'normal';
|
||||||
this.focusTextStyle = this.options.focusTextStyle || this.textStyle;
|
this.focusTextStyle = options.focusTextStyle || this.textStyle;
|
||||||
|
|
||||||
if(this.options.id) {
|
if(options.id) {
|
||||||
this.setId(this.options.id);
|
this.setId(options.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.options.position) {
|
if(options.position) {
|
||||||
this.setPosition(this.options.position);
|
this.setPosition(options.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle;
|
// this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle;
|
||||||
|
|
||||||
// :TODO: Don't allow width/height > client.term
|
// :TODO: Don't allow width/height > client.term
|
||||||
if(this.options.dimens && this.options.dimens.height) {
|
if(options.dimens && options.dimens.height) {
|
||||||
this.dimens.height = this.options.dimens.height;
|
this.dimens.height = options.dimens.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.options.dimens && this.options.dimens.width) {
|
if(options.dimens && options.dimens.width) {
|
||||||
this.dimens.width = this.options.dimens.width;
|
this.dimens.width = options.dimens.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.color = this.options.color || { flags : 0, fg : 7, bg : 0 };
|
this.color = options.color || { flags : 0, fg : 7, bg : 0 };
|
||||||
this.focusColor = this.options.focusColor || this.color;
|
this.focusColor = options.focusColor || this.color;
|
||||||
|
|
||||||
if(this.acceptsInput) {
|
if(this.acceptsInput) {
|
||||||
this.specialKeyMap = this.options.specialKeyMap || VIEW_SPECIAL_KEY_MAP_DEFAULT;
|
this.specialKeyMap = options.specialKeyMap || VIEW_SPECIAL_KEY_MAP_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isSpecialKeyMapped = function(keySet, keyName) {
|
this.isSpecialKeyMapped = function(keySet, keyName) {
|
||||||
|
@ -129,6 +132,7 @@ View.prototype.setFocus = function(focused) {
|
||||||
assert(this.acceptsFocus, 'View does not accept focus');
|
assert(this.acceptsFocus, 'View does not accept focus');
|
||||||
|
|
||||||
this.hasFocus = focused;
|
this.hasFocus = focused;
|
||||||
|
this.client.term.write('show' === this.cursor ? ansi.showCursor() : ansi.hideCursor());
|
||||||
};
|
};
|
||||||
|
|
||||||
View.prototype.onKeyPress = function(key, isSpecial) {
|
View.prototype.onKeyPress = function(key, isSpecial) {
|
||||||
|
|
Loading…
Reference in New Issue