Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
761d177fc2
commit
686dc0c94c
293
js/term/widgets/form.js
Normal file
293
js/term/widgets/form.js
Normal file
|
@ -0,0 +1,293 @@
|
|||
/**
|
||||
** ==============================
|
||||
** 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(S).
|
||||
** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
|
||||
** MODIFIED, OR OTHERWISE USED IN A CONTEXT
|
||||
** OUTSIDE OF THE SOFTWARE SYSTEM.
|
||||
**
|
||||
** $AUTHORS: Christopher Jeffrey, Stefan Bosse
|
||||
** $INITIAL: (C) 2013-2015, Christopher Jeffrey and contributors
|
||||
** $MODIFIED: by sbosse
|
||||
** $REVESIO: 1.2.1
|
||||
**
|
||||
** $INFO:
|
||||
**
|
||||
** form.js - form element for blessed
|
||||
**
|
||||
** $ENDOFINFO
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
var Comp = Require('com/compat');
|
||||
|
||||
var Node = Require('term/widgets/node');
|
||||
var Box = Require('term/widgets/box');
|
||||
|
||||
/**
|
||||
* Form
|
||||
*/
|
||||
|
||||
function Form(options) {
|
||||
var self = this;
|
||||
|
||||
if (!instanceOf(this,Node)) {
|
||||
return new Form(options);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
options.ignoreKeys = true;
|
||||
Box.call(this, options);
|
||||
|
||||
if (options.keys) {
|
||||
this.screen._listenKeys(this);
|
||||
this.on('element keypress', function(el, ch, key) {
|
||||
if ((key.name === 'tab' && !key.shift)
|
||||
|| (el.type === 'textbox' && options.autoNext && key.name === 'enter')
|
||||
|| key.name === 'down'
|
||||
|| (options.vi && key.name === 'j')) {
|
||||
if (el.type === 'textbox' || el.type === 'textarea') {
|
||||
if (key.name === 'j') return;
|
||||
if (key.name === 'tab') {
|
||||
// Workaround, since we can't stop the tab from being added.
|
||||
el.emit('keypress', null, { name: 'backspace' });
|
||||
}
|
||||
el.emit('keypress', '\x1b', { name: 'escape' });
|
||||
}
|
||||
self.focusNext();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((key.name === 'tab' && key.shift)
|
||||
|| key.name === 'up'
|
||||
|| (options.vi && key.name === 'k')) {
|
||||
if (el.type === 'textbox' || el.type === 'textarea') {
|
||||
if (key.name === 'k') return;
|
||||
el.emit('keypress', '\x1b', { name: 'escape' });
|
||||
}
|
||||
self.focusPrevious();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.name === 'escape') {
|
||||
self.focus();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//Form.prototype.__proto__ = Box.prototype;
|
||||
inheritPrototype(Form,Box),
|
||||
|
||||
Form.prototype.type = 'form';
|
||||
|
||||
Form.prototype._refresh = function() {
|
||||
// XXX Possibly remove this if statement and refresh on every focus.
|
||||
// Also potentially only include *visible* focusable elements.
|
||||
// This would remove the need to check for _selected.visible in previous()
|
||||
// and next().
|
||||
if (!this._children) {
|
||||
var out = [];
|
||||
|
||||
this.children.forEach(function fn(el) {
|
||||
if (el.keyable) out.push(el);
|
||||
el.children.forEach(fn);
|
||||
});
|
||||
|
||||
this._children = out;
|
||||
}
|
||||
};
|
||||
|
||||
Form.prototype._visible = function() {
|
||||
return !!this._children.filter(function(el) {
|
||||
return el.visible;
|
||||
}).length;
|
||||
};
|
||||
|
||||
Form.prototype.next = function() {
|
||||
this._refresh();
|
||||
|
||||
if (!this._visible()) return;
|
||||
|
||||
if (!this._selected) {
|
||||
this._selected = this._children[0];
|
||||
if (!this._selected.visible) return this.next();
|
||||
if (this.screen.focused !== this._selected) return this._selected;
|
||||
}
|
||||
|
||||
var i = this._children.indexOf(this._selected);
|
||||
if (!~i || !this._children[i + 1]) {
|
||||
this._selected = this._children[0];
|
||||
if (!this._selected.visible) return this.next();
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
this._selected = this._children[i + 1];
|
||||
if (!this._selected.visible) return this.next();
|
||||
return this._selected;
|
||||
};
|
||||
|
||||
Form.prototype.previous = function() {
|
||||
this._refresh();
|
||||
|
||||
if (!this._visible()) return;
|
||||
|
||||
if (!this._selected) {
|
||||
this._selected = this._children[this._children.length - 1];
|
||||
if (!this._selected.visible) return this.previous();
|
||||
if (this.screen.focused !== this._selected) return this._selected;
|
||||
}
|
||||
|
||||
var i = this._children.indexOf(this._selected);
|
||||
if (!~i || !this._children[i - 1]) {
|
||||
this._selected = this._children[this._children.length - 1];
|
||||
if (!this._selected.visible) return this.previous();
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
this._selected = this._children[i - 1];
|
||||
if (!this._selected.visible) return this.previous();
|
||||
return this._selected;
|
||||
};
|
||||
|
||||
Form.prototype.focusNext = function() {
|
||||
var next = this.next();
|
||||
if (next) next.focus();
|
||||
};
|
||||
|
||||
Form.prototype.focusPrevious = function() {
|
||||
var previous = this.previous();
|
||||
if (previous) previous.focus();
|
||||
};
|
||||
|
||||
Form.prototype.resetSelected = function() {
|
||||
this._selected = null;
|
||||
};
|
||||
|
||||
Form.prototype.focusFirst = function() {
|
||||
this.resetSelected();
|
||||
this.focusNext();
|
||||
};
|
||||
|
||||
Form.prototype.focusLast = function() {
|
||||
this.resetSelected();
|
||||
this.focusPrevious();
|
||||
};
|
||||
|
||||
Form.prototype.submit = function() {
|
||||
var out = {};
|
||||
|
||||
this.children.forEach(function fn(el) {
|
||||
if (el.value != null) {
|
||||
var name = el.name || el.type;
|
||||
if (Array.isArray(out[name])) {
|
||||
out[name].push(el.value);
|
||||
} else if (out[name]) {
|
||||
out[name] = [out[name], el.value];
|
||||
} else {
|
||||
out[name] = el.value;
|
||||
}
|
||||
}
|
||||
el.children.forEach(fn);
|
||||
});
|
||||
|
||||
this.emit('submit', out);
|
||||
|
||||
return this.submission = out;
|
||||
};
|
||||
|
||||
Form.prototype.cancel = function() {
|
||||
this.emit('cancel');
|
||||
};
|
||||
|
||||
Form.prototype.reset = function() {
|
||||
this.children.forEach(function fn(el) {
|
||||
switch (el.type) {
|
||||
case 'screen':
|
||||
break;
|
||||
case 'box':
|
||||
break;
|
||||
case 'text':
|
||||
break;
|
||||
case 'line':
|
||||
break;
|
||||
case 'scrollable-box':
|
||||
break;
|
||||
case 'list':
|
||||
el.select(0);
|
||||
return;
|
||||
case 'form':
|
||||
break;
|
||||
case 'input':
|
||||
break;
|
||||
case 'textbox':
|
||||
el.clearInput();
|
||||
return;
|
||||
case 'textarea':
|
||||
el.clearInput();
|
||||
return;
|
||||
case 'button':
|
||||
delete el.value;
|
||||
break;
|
||||
case 'progress-bar':
|
||||
el.setProgress(0);
|
||||
break;
|
||||
case 'file-manager':
|
||||
el.refresh(el.options.cwd);
|
||||
return;
|
||||
case 'checkbox':
|
||||
el.uncheck();
|
||||
return;
|
||||
case 'radio-set':
|
||||
break;
|
||||
case 'radio-button':
|
||||
el.uncheck();
|
||||
return;
|
||||
case 'prompt':
|
||||
break;
|
||||
case 'question':
|
||||
break;
|
||||
case 'message':
|
||||
break;
|
||||
case 'info':
|
||||
break;
|
||||
case 'loading':
|
||||
break;
|
||||
case 'list-bar':
|
||||
//el.select(0);
|
||||
break;
|
||||
case 'dir-manager':
|
||||
el.refresh(el.options.cwd);
|
||||
return;
|
||||
case 'terminal':
|
||||
el.write('');
|
||||
return;
|
||||
case 'image':
|
||||
//el.clearImage();
|
||||
return;
|
||||
}
|
||||
el.children.forEach(fn);
|
||||
});
|
||||
|
||||
this.emit('reset');
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Form;
|
Loading…
Reference in New Issue
Block a user