summaryrefslogtreecommitdiffstats
path: root/asset/js/widget/TermInput.js
diff options
context:
space:
mode:
Diffstat (limited to 'asset/js/widget/TermInput.js')
-rw-r--r--asset/js/widget/TermInput.js196
1 files changed, 196 insertions, 0 deletions
diff --git a/asset/js/widget/TermInput.js b/asset/js/widget/TermInput.js
new file mode 100644
index 0000000..537f4c4
--- /dev/null
+++ b/asset/js/widget/TermInput.js
@@ -0,0 +1,196 @@
+define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
+
+ "use strict";
+
+ class TermInput extends BaseInput {
+ constructor(input) {
+ super(input);
+
+ this.separator = this.input.dataset.termSeparator || ' ';
+ this.ignoreSpaceUntil = null;
+ }
+
+ bind() {
+ super.bind();
+
+ // TODO: Compatibility only. Remove as soon as possible once Web 2.12 (?) is out.
+ // Or upon any other update which lets Web trigger a real submit upon auto submit.
+ $(this.input.form).on('change', 'select.autosubmit', this.onSubmit, this);
+ $(this.input.form).on('change', 'input.autosubmit', this.onSubmit, this);
+
+ return this;
+ }
+
+ reset() {
+ super.reset();
+
+ this.ignoreSpaceUntil = null;
+ }
+
+ readPartialTerm(input) {
+ let value = super.readPartialTerm(input);
+ if (value && this.ignoreSpaceUntil && value[0] === this.ignoreSpaceUntil) {
+ value = value.slice(1);
+ if (value.slice(-1) === this.ignoreSpaceUntil) {
+ value = value.slice(0, -1);
+ }
+ }
+
+ return value;
+ }
+
+ writePartialTerm(value, input) {
+ if (this.ignoreSpaceUntil !== null && this.ignoreSpaceSince === 0) {
+ value = this.ignoreSpaceUntil + value;
+ }
+
+ super.writePartialTerm(value, input);
+ }
+
+ readFullTerm(input, termIndex = null) {
+ let termData = super.readFullTerm(input, termIndex);
+ if (termData && this.ignoreSpaceUntil !== null && input.value[0] === this.ignoreSpaceUntil) {
+ if (input.value.slice(-1) !== this.ignoreSpaceUntil || input.value.length < 2) {
+ return false;
+ }
+
+ this.ignoreSpaceUntil = null;
+ }
+
+ return termData;
+ }
+
+ hasSyntaxError(input) {
+ if ((typeof input === 'undefined' || input === this.input) && this.ignoreSpaceUntil !== null) {
+ if (this.input.value === this.ignoreSpaceUntil) {
+ return true;
+ }
+ }
+
+ return super.hasSyntaxError(input);
+ }
+
+ termsToQueryString(terms) {
+ let quoted = [];
+ for (const termData of terms) {
+ let search = this.encodeTerm(termData).search;
+ if (search.indexOf(this.separator) >= 0) {
+ search = '"' + termData.search + '"';
+ }
+
+ quoted.push(search);
+ }
+
+ return quoted.join(this.separator).trim();
+ }
+
+ complete(input, data) {
+ data.exclude = this.usedTerms.map(termData => termData.search);
+
+ super.complete(input, data);
+ }
+
+ /**
+ * Event listeners
+ */
+
+ onSubmit(event) {
+ super.onSubmit(event);
+
+ this.ignoreSpaceUntil = null;
+ }
+
+ onInput(event) {
+ let label = event.target.parentNode;
+ if (label.dataset.index >= 0) {
+ super.onInput(event);
+ return;
+ }
+
+ let input = event.target;
+ let firstChar = input.value[0];
+
+ if (this.ignoreSpaceUntil !== null) {
+ // Reset if the user changes/removes the source char
+ if (firstChar !== this.ignoreSpaceUntil) {
+ this.ignoreSpaceUntil = null;
+ }
+ }
+
+ if (this.ignoreSpaceUntil === null && (firstChar === "'" || firstChar === '"')) {
+ this.ignoreSpaceUntil = firstChar;
+ }
+
+ super.onInput(event);
+ }
+
+ onKeyDown(event) {
+ super.onKeyDown(event);
+ if (event.defaultPrevented) {
+ return;
+ }
+
+ let label = event.target.parentNode;
+ if (label.dataset.index >= 0) {
+ return;
+ }
+
+ if (event.key !== this.separator && event.key !== 'Enter') {
+ return;
+ }
+
+ let addedTerms = this.exchangeTerm();
+ if (Object.keys(addedTerms).length) {
+ this.togglePlaceholder();
+ event.preventDefault();
+ this.autoSubmit(this.input, 'exchange', { terms: addedTerms });
+ }
+ }
+
+ onKeyUp(event) {
+ super.onKeyUp(event);
+
+ let label = event.target.parentNode;
+ if (label.dataset.index >= 0) {
+ return;
+ }
+
+ if (this.ignoreSpaceUntil !== null) {
+ // Reset if the user changes/removes the source char
+ let value = event.target.value;
+ if (value[this.ignoreSpaceSince] !== this.ignoreSpaceUntil) {
+ this.ignoreSpaceUntil = null;
+ this.ignoreSpaceSince = null;
+ }
+ }
+
+ let input = event.target;
+ switch (event.key) {
+ case '"':
+ case "'":
+ if (this.ignoreSpaceUntil === null) {
+ this.ignoreSpaceUntil = event.key;
+ this.ignoreSpaceSince = input.selectionStart - 1;
+ }
+ }
+ }
+
+ onButtonClick(event) {
+ if (! this.hasSyntaxError()) {
+ let addedTerms = this.exchangeTerm();
+ if (Object.keys(addedTerms).length) {
+ this.togglePlaceholder();
+ event.preventDefault();
+ this.autoSubmit(this.input, 'exchange', { terms: addedTerms });
+ this.ignoreSpaceUntil = null;
+
+ return;
+ }
+ }
+
+ super.onButtonClick(event);
+ }
+ }
+
+ return TermInput;
+});