fix textbox/textarea.

This commit is contained in:
Christopher Jeffrey 2013-07-29 15:49:25 -05:00
parent d2226c3295
commit 36415f76b6
2 changed files with 115 additions and 59 deletions

View File

@ -364,6 +364,10 @@ function Screen(options) {
return process.exit(1);
});
process.on('SIGTERM', function() {
return process.exit(0);
});
process.on('exit', function() {
reset();
});
@ -1390,9 +1394,11 @@ Screen.prototype.rewindFocus = function() {
var old = this.history[this.history.length-1]
, el;
this.history.pop();
while (this.history.length) {
el = this.history.pop();
if (!el.detached && !el.visible) {
if (!el.detached && el.visible) {
this.history.push(el);
el._focus(old);
return el;
@ -1916,25 +1922,6 @@ Element.prototype.setContent = function(content, noClear) {
this.parseContent();
};
Element.prototype.setContent_ = function(content, noClear) {
var old, pos;
if (!noClear) {
old = this._pcontent;
pos = this._getCoords();
}
this.content = content || '';
this.parseContent();
if (!noClear && pos && this._pcontent !== old) {
// this.clearPos(pos);
this.screen.clearRegion(
pos.xi, pos.xl,
pos.yi, pos.yl);
}
};
Element.prototype.getContent = function() {
return this._clines.fake.join('\n');
};
@ -4167,6 +4154,8 @@ Input.prototype.type = 'input';
*/
function Textarea(options) {
var self = this;
if (!(this instanceof Node)) {
return new Textarea(options);
}
@ -4181,11 +4170,34 @@ function Textarea(options) {
this.value = options.value || '';
//this.on('prerender', this._render.bind(this));
this.__updateCursor = this._updateCursor.bind(this);
this.on('resize', this.__updateCursor);
this.on('move', this.__updateCursor);
this.on('focus', this.readInput.bind(this, null));
//this.on('prerender', this._render.bind(this));
if (options.inputOnFocus) {
this.on('focus', this.readInput.bind(this, null));
}
if (!options.inputOnFocus && options.keys) {
this.on('keypress', function(ch, key) {
if (self._reading) return;
if (key.name === 'enter' || (options.vi && key.name === 'i')) {
return self.readInput();
}
if (key.name === 'e') {
return self.readEditor();
}
});
}
if (options.mouse) {
this.on('click', function(data) {
if (self._reading) return;
if (data.button !== 'right') return;
self.readEditor();
});
}
}
Textarea.prototype.__proto__ = Input.prototype;
@ -4221,6 +4233,8 @@ Textarea.prototype._updateCursor = function() {
cy = lpos.yi + this.itop + line;
cx = lpos.xi + this.ileft + last.length;
// XXX Not sure, but this may still sometimes
// cause problems when leaving editor.
if (cy === program.y && cx === program.x) {
return;
}
@ -4248,13 +4262,10 @@ Textarea.prototype.readInput = function(callback) {
var self = this
, focused = this.screen.focused === this;
// We need to maintain an array of
// callbacks for legacy reasons.
if (this._callback) {
return callback ? this._callbacks.push(callback) : null;
}
if (this._reading) return;
this._reading = true;
this._callbacks = callback ? [callback] : [];
this._callback = callback;
if (!focused) {
this.screen.saveFocus();
@ -4265,19 +4276,24 @@ Textarea.prototype.readInput = function(callback) {
this._updateCursor();
this.screen.program.showCursor();
this.screen.program.sgr('normal');
//this.screen.program.sgr('normal');
this._done = function fn(err, value) {
if (!self._reading) return;
this._callback = function fn(err, value) {
if (fn.done) return;
fn.done = true;
self._reading = false;
delete self._callback;
delete self._done;
self.removeListener('keypress', self.__listener);
delete self.__listener;
self.removeListener('blur', self.__callback);
delete self.__callback;
self.removeListener('blur', self.__done);
delete self.__done;
self.screen.program.hideCursor();
self.screen.grabKeys = false;
@ -4286,6 +4302,13 @@ Textarea.prototype.readInput = function(callback) {
self.screen.restoreFocus();
}
if (self.options.inputOnFocus) {
self.screen.rewindFocus();
}
// Ugly
if (err === 'stop') return;
if (err) {
self.emit('error', err);
} else if (value != null) {
@ -4295,24 +4318,22 @@ Textarea.prototype.readInput = function(callback) {
}
self.emit('action', value);
self._callbacks.forEach(function(callback) {
return err
? callback(err)
: callback(null, value);
});
if (!callback) return;
delete self._callbacks;
return err
? callback(err)
: callback(null, value);
};
this.__listener = this._listener.bind(this);
this.on('keypress', this.__listener);
this.__callback = this._callback.bind(this, null, null);
this.on('blur', this.__callback);
this.__done = this._done.bind(this, null, null);
this.on('blur', this.__done);
};
Textarea.prototype._listener = function(ch, key) {
var callback = this._callback
var done = this._done
, value = this.value;
if (key.name === 'enter') {
@ -4325,14 +4346,22 @@ Textarea.prototype._listener = function(ch, key) {
;
}
if (this.options.keys && key.ctrl && key.name === 'e') {
return this.readEditor();
}
// TODO: Optimize typing by writing directly
// to the screen and screen buffer here.
if (key.name === 'escape') {
callback(null, key.name === 'enter' ? value : null);
done(null, null);
} else if (key.name === 'backspace') {
if (this.value.length) {
this.value = this.value.slice(0, -1);
}
} else if (ch) {
this.value += ch;
if (!/^[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]$/.test(ch)) {
this.value += ch;
}
}
if (this.value !== value) {
@ -4373,11 +4402,13 @@ Textarea.prototype.clearValue = function() {
};
Textarea.prototype.submit = function() {
return this._listener('\x1b', { name: 'escape' });
if (!this.__listener) return;
return this.__listener('\x1b', { name: 'escape' });
};
Textarea.prototype.cancel = function() {
return this._listener('\x1b', { name: 'escape' });
if (!this.__listener) return;
return this.__listener('\x1b', { name: 'escape' });
};
Textarea.prototype._render = Box.prototype.render;
@ -4390,6 +4421,19 @@ Textarea.prototype.editor =
Textarea.prototype.setEditor =
Textarea.prototype.readEditor = function(callback) {
var self = this;
if (this._reading) {
var _cb = this._callback
, cb = callback;
this._done('stop');
callback = function(err, value) {
if (_cb) _cb(err, value);
if (cb) cb(err, value);
};
}
return this.screen.readEditor({ value: this.value }, function(err, value) {
if (err) return callback && callback(err);
self.setValue(value);
@ -4426,7 +4470,7 @@ Textbox.prototype.type = 'textbox';
Textbox.prototype.__olistener = Textbox.prototype._listener;
Textbox.prototype._listener = function(ch, key) {
if (key.name === 'enter') {
this._callback(null, key.name === 'enter' ? this.value : null);
this._done(null, this.value);
return;
}
return this.__olistener(ch, key);
@ -4454,6 +4498,11 @@ Textbox.prototype.setValue = function(value) {
}
};
Textarea.prototype.submit = function() {
if (!this.__listener) return;
return this.__listener('\r', { name: 'enter' });
};
/**
* Button
*/

View File

@ -213,11 +213,17 @@ var input = blessed.textbox({
width: '30%',
height: 3,
right: 0,
top: 2
top: 2,
keys: true,
vi: true,
mouse: true
//inputOnFocus: true
});
input.on('submit', function() {
input.on('submit', function(value) {
if (value) screen.children[0].setContent(value);
input.clearInput();
screen.render();
});
screen.append(input);
@ -240,6 +246,7 @@ var button = blessed.Button({
button.on('press', function() {
button.setContent('Clicked!');
screen.render();
});
screen.append(button);
@ -247,19 +254,19 @@ screen.append(button);
screen.on('keypress', function(ch, key) {
if (key.name === 'tab') {
return key.shift
? screen.focusPrev()
? screen.focusPrevious()
: screen.focusNext();
}
if (key.name === 'i') {
return input.readInput(function(err, value) {
if (value) screen.children[0].setContent(value);
});
}
if (key.name === 'e') {
return input.readEditor(function(err, value) {
if (value) screen.children[0].setContent(value);
});
}
//if (key.name === 'i') {
// return input.readInput(function(err, value) {
// ;
// });
//}
//if (key.name === 'e') {
// return input.readEditor(function(err, value) {
// ;
// });
//}
if (key.name === 'escape' || key.name === 'q') {
return process.exit(0);
}