diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2023-05-12 17:42:09 -0300 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2023-05-13 12:48:36 -0300 |
commit | 6ea74c268a12325296a1d2e7fc31b02030ddb8bc (patch) | |
tree | 5da94d93acb64e7ab650d240d6cb23c659ad02ca /ui/controls/Form.js | |
parent | e783bcf8522fa68e6b221afd18469c3c265b1bb7 (diff) |
use ESM module syntax & minor cleanups
The biggest change here is moving various element classes under more scope-specific directories, which helps to avoid circular dependencies and is just cleaner to navigate and expand in the future. Otherwise this is a largely uncritical port to ESM module syntax! There are probably a number of changes and other cleanups that remain much needed. Whenever I make changes to tui-lib it's hard to believe it's already been <INSERT COUNTING NUMBER HERE> years since the previous time. First commits are from January 2017, and the code originates a month earlier in KAaRMNoD!
Diffstat (limited to 'ui/controls/Form.js')
-rw-r--r-- | ui/controls/Form.js | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/ui/controls/Form.js b/ui/controls/Form.js new file mode 100644 index 0000000..921096a --- /dev/null +++ b/ui/controls/Form.js @@ -0,0 +1,143 @@ +import telc from 'tui-lib/util/telchars' + +import {FocusElement} from 'tui-lib/ui/primitives' + +export default class Form extends FocusElement { + constructor() { + super() + + this.inputs = [] + this.curIndex = 0 + this.captureTab = true + } + + addInput(input, asChild = true, opts = {}) { + // Adds the given input as a child element and pushes it to the input + // list. If the optional argument asChild is false, it won't add the + // input element as a child of the form. + + this.inputs.push(input) + + if (asChild) { + this.addChild(input, this.children.length, opts) + } + } + + removeInput(input, asChild = true, opts = {}) { + // Removes the given input from the form's input list. If the optional + // argument asChild is false, it won't try to removeChild the input. + + if (this.inputs.includes(input)) { + this.inputs.splice(this.inputs.indexOf(input), 1) + + if (asChild) { + this.removeChild(input, opts) + } + } + } + + selectInput(input) { + if (this.inputs.includes(input)) { + this.curIndex = this.inputs.indexOf(input) + this.updateSelectedElement() + } + } + + keyPressed(keyBuf) { + // Don't do anything if captureTab is set to false. This is handy for + // nested forms. + if (!this.captureTab) { + return + } + + if (telc.isTab(keyBuf) || telc.isBackTab(keyBuf)) { + // No inputs to tab through, so do nothing. + if (this.inputs.length < 2) { + return + } + + if (telc.isTab(keyBuf)) { + this.nextInput() + } else { + this.previousInput() + } + + return false + } + } + + get selectable() { + return this.inputs.some(inp => inp.selectable) + } + + updateSelectedElement() { + if (this.root.select && this.inputs.length) { + if (this.curIndex > this.inputs.length - 1) { + this.curIndex = this.inputs.length - 1 + } + + this.root.select(this.inputs[this.curIndex], {fromForm: true}) + } + } + + previousInput() { + // TODO: Forms currently assume there is at least one selectable input, + // but this isn't necessarily always the case. + do { + this.curIndex = (this.curIndex - 1) + if (this.curIndex < 0) { + this.curIndex = (this.inputs.length - 1) + } + } while (!this.inputs[this.curIndex].selectable) + + this.updateSelectedElement() + } + + nextInput() { + // TODO: See previousInput + do { + this.curIndex = (this.curIndex + 1) % this.inputs.length + } while (!this.inputs[this.curIndex].selectable) + + this.updateSelectedElement() + } + + firstInput(selectForm = true) { + this.curIndex = 0 + + // TODO: See previousInput + if (!this.inputs[this.curIndex].selectable) { + this.nextInput() + } + + if (selectForm || ( + this.root.isChildOrSelfSelected && this.root.isChildOrSelfSelected(this) + )) { + this.updateSelectedElement() + } + } + + lastInput(selectForm = true) { + this.curIndex = this.inputs.length - 1 + + // TODO: See previousInput + if (!this.inputs[this.curIndex].selectable) { + this.previousInput() + } + + if (selectForm || ( + this.root.isChildOrSelfSelected && this.root.isChildOrSelfSelected(this) + )) { + this.updateSelectedElement() + } + } + + selected() { + if (this.root.selectedElement === this) { + this.updateSelectedElement() + } + } + + get curIndex() { return this.getDep('curIndex') } + set curIndex(v) { return this.setDep('curIndex', v) } +} |