From 3c643f0c6a587b04eb602bcfeb41f8940f41e088 Mon Sep 17 00:00:00 2001 From: barsdeveloper Date: Sun, 8 May 2022 20:21:37 +0200 Subject: [PATCH] Fix input details --- dist/ueblueprint.js | 230 +++++++++++++++++++------------ js/Utility.js | 4 +- js/element/PinElement.js | 2 + js/entity/TypeInitialization.js | 11 -- js/template/IInputPinTemplate.js | 15 +- js/template/NamePinTemplate.js | 53 +++++++ js/template/RealPinTemplate.js | 7 +- 7 files changed, 214 insertions(+), 108 deletions(-) create mode 100644 js/template/NamePinTemplate.js diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js index 6c8ae3c..3d78921 100755 --- a/dist/ueblueprint.js +++ b/dist/ueblueprint.js @@ -214,6 +214,75 @@ class IInput { // @ts-check +/** + * @template T + */ +class TypeInitialization { + + /** @type {Constructor|Array} */ + #type + get type() { + return this.#type + } + set type(v) { + this.#type = v; + } + + #showDefault = true + get showDefault() { + return this.#showDefault + } + set showDefault(v) { + this.#showDefault = v; + } + + /** @type {T} */ + #value + get value() { + return this.#value + } + set value(v) { + this.#value = v; + } + + static sanitize(value, targetType) { + if (targetType === undefined) { + targetType = value?.constructor; + } + let wrongType = false; + if (targetType && value?.constructor !== targetType && !(value instanceof targetType)) { + wrongType = true; + } + if (value instanceof Boolean || value instanceof Number || value instanceof String) { + value = value.valueOf(); // Get the relative primitive value + } + if (wrongType) { + return new targetType(value) + } + return value + } + + /** + * @typedef {(new () => T) | StringConstructor | NumberConstructor | BooleanConstructor} Constructor + * @param {Constructor|Array} type + * @param {Boolean} showDefault + * @param {any} value + */ + constructor(type, showDefault = true, value = undefined) { + if (value === undefined) { + if (type instanceof Array) { + value = []; + } else { + value = TypeInitialization.sanitize(new type()); + } + } + this.#showDefault = showDefault; + this.#type = type; + } +} + +// @ts-check + class Utility { static sigmoid(x, curvature = 1.7) { @@ -378,7 +447,6 @@ class Utility { return value .replace(/\n$/, "") // Remove trailing newline .replaceAll("\u00A0", " ") // Replace special space symbol - .replaceAll("\r\n", String.raw`\r\n`) // Replace newline with \r\n .replaceAll("\n", String.raw`\r\n`) // Replace newline with \r\n } @@ -387,8 +455,7 @@ class Utility { */ static decodeInputString(value) { return value - .replaceAll(" ", "\u00A0") // Replace special space symbol - .replaceAll(String.raw`\r\n`, "
\n") // Replace newline with \r\n + .replaceAll("\\r\n", "\n") // Replace newline with \r\n } /** @@ -422,84 +489,6 @@ class Utility { // @ts-check -/** - * @template T - */ -class TypeInitialization { - - /** @type {Constructor|Array} */ - #type - get type() { - return this.#type - } - set type(v) { - this.#type = v; - } - - #showDefault = true - get showDefault() { - return this.#showDefault - } - set showDefault(v) { - this.#showDefault = v; - } - - /** @type {T} */ - #value - get value() { - return this.#value - } - set value(v) { - this.#value = v; - } - - #decodeString - get decodeString() { - return this.#decodeString - } - set decodeString(v) { - this.#decodeString = v; - } - - static sanitize(value, targetType) { - if (targetType === undefined) { - targetType = value?.constructor; - } - let wrongType = false; - if (targetType && value?.constructor !== targetType && !(value instanceof targetType)) { - wrongType = true; - } - if (value instanceof Boolean || value instanceof Number || value instanceof String) { - value = value.valueOf(); // Get the relative primitive value - } - if (wrongType) { - return new targetType(value) - } - return value - } - - /** - * @typedef {(new () => T) | StringConstructor | NumberConstructor | BooleanConstructor} Constructor - * @param {Constructor|Array} type - * @param {Boolean} showDefault - * @param {any} value - */ - constructor(type, showDefault = true, value = undefined) { - if (value === undefined) { - if (type instanceof Array) { - value = []; - } else { - value = TypeInitialization.sanitize(new type()); - } - } - this.#value = type === String ? Utility.decodeString(value) : value; - this.#showDefault = showDefault; - this.#type = type; - } -} - -// @ts-check - class IEntity { static attributes = {} @@ -2960,6 +2949,9 @@ class IInputPinTemplate extends PinTemplate { /** @type {HTMLElement[]} */ #inputContentElements + get inputContentElements() { + return this.#inputContentElements + } hasInput = true /** @@ -2971,7 +2963,7 @@ class IInputPinTemplate extends PinTemplate { [...pin.querySelectorAll(".ueb-pin-input-content")] ); if (this.#inputContentElements.length) { - this.setInputs(pin, [pin.entity.DefaultValue]); + this.setInputs(pin, [Utility.decodeInputString(pin.entity.DefaultValue)]); let self = this; this.onFocusHandler = _ => pin.blueprint.dispatchEditTextEvent(true); this.onFocusOutHandler = e => { @@ -3019,16 +3011,18 @@ class IInputPinTemplate extends PinTemplate { * @param {PinElement} pin */ getInputs(pin) { - return this.#inputContentElements.map(element => Utility.encodeInputString(element.textContent)) + return this.#inputContentElements.map(element => element.innerText) } /** * @param {PinElement} pin * @param {String[]?} values */ - setInputs(pin, values = []) { - this.#inputContentElements.forEach((element, i) => element.innerText = Utility.decodeInputString(values[i])); - pin.entity.DefaultValue = this.getInput(pin); + setInputs(pin, values = [], updateDefaultValue = true) { + this.#inputContentElements.forEach((element, i) => element.innerText = values[i]); + if (updateDefaultValue) { + pin.entity.DefaultValue = this.getInput(pin); + } } /** @@ -3151,11 +3145,18 @@ class RealPinTemplate extends IInputPinTemplate { */ setInputs(pin, values = []) { let num = parseFloat(values.length ? values[0] : this.getInput(pin)); + let updateDefaultValue = true; if (isNaN(num)) { - num = parseFloat(pin.entity.DefaultValue != "" ? pin.entity.DefaultValue : pin.entity.AutogeneratedDefaultValue); + num = parseFloat(pin.entity.DefaultValue != "" + ? pin.entity.DefaultValue + : pin.entity.AutogeneratedDefaultValue); + } + if (isNaN(num)) { + num = 0; + updateDefaultValue = false; } values[0] = Utility.minDecimals(num); - super.setInputs(pin, values); + super.setInputs(pin, values, updateDefaultValue); } } @@ -3177,6 +3178,58 @@ class StringPinTemplate extends IInputPinTemplate { // @ts-check +/** + * @typedef {import("../element/PinElement").default} PinElement + */ + +class NamePinTemplate extends IInputPinTemplate { + + /** @type {(e : InputEvent) => void} */ + onInputHandler + + /** + * @param {PinElement} pin + */ + setup(pin) { + super.setup(pin); + this.onInputHandler = e => { + e.stopPropagation(); + if ( + e.inputType == "insertParagraph" + || e.inputType == "insertLineBreak" + || (e.inputType == "insertFromPaste" && /** @type {HTMLElement} */(e.target).innerText.includes("\n")) + ) { + /** @type {HTMLElement} */(e.target).blur(); // Loose focus in case it tries to insert newline + this.inputContentElements.forEach(element => element.innerText = element.innerText.replaceAll("\n", "")); + } + }; + this.inputContentElements.forEach(element => { + element.addEventListener("input", /** @type {(e : Event) => void} */(this.onInputHandler)); + }); + } + + /** + * @param {PinElement} pin + */ + cleanup(pin) { + super.cleanup(pin); + this.inputContentElements.forEach(element => { + element.removeEventListener("input", /** @type {(e : Event) => void} */(this.onInputHandler)); + }); + } + + /** + * @param {PinElement} pin + * @param {String[]?} values + */ + setInputs(pin, values = [], updateDefaultValue = true) { + values = values.map(value => value.replaceAll("\n", "")); + super.setInputs(pin, values, updateDefaultValue); + } +} + +// @ts-check + /** * @typedef {import("../entity/GuidEntity").default} GuidEntity * @typedef {import("../entity/PinEntity").default} PinEntity @@ -3192,6 +3245,7 @@ class PinElement extends IElement { static #typeTemplateMap = { "bool": BoolPinTemplate, "exec": ExecPinTemplate, + "name": NamePinTemplate, "real": RealPinTemplate, "string": StringPinTemplate, } diff --git a/js/Utility.js b/js/Utility.js index eca2af7..55eac2d 100755 --- a/js/Utility.js +++ b/js/Utility.js @@ -166,7 +166,6 @@ export default class Utility { return value .replace(/\n$/, "") // Remove trailing newline .replaceAll("\u00A0", " ") // Replace special space symbol - .replaceAll("\r\n", String.raw`\r\n`) // Replace newline with \r\n .replaceAll("\n", String.raw`\r\n`) // Replace newline with \r\n } @@ -175,8 +174,7 @@ export default class Utility { */ static decodeInputString(value) { return value - .replaceAll(" ", "\u00A0") // Replace special space symbol - .replaceAll(String.raw`\r\n`, "
\n") // Replace newline with \r\n + .replaceAll("\\r\n", "\n") // Replace newline with \r\n } /** diff --git a/js/element/PinElement.js b/js/element/PinElement.js index 845d653..b0f0530 100644 --- a/js/element/PinElement.js +++ b/js/element/PinElement.js @@ -8,6 +8,7 @@ import PinTemplate from "../template/PinTemplate" import RealPinTemplate from "../template/RealPinTemplate" import StringPinTemplate from "../template/StringPinTemplate" import Utility from "../Utility" +import NamePinTemplate from "../template/NamePinTemplate" /** * @typedef {import("../entity/GuidEntity").default} GuidEntity @@ -24,6 +25,7 @@ export default class PinElement extends IElement { static #typeTemplateMap = { "bool": BoolPinTemplate, "exec": ExecPinTemplate, + "name": NamePinTemplate, "real": RealPinTemplate, "string": StringPinTemplate, } diff --git a/js/entity/TypeInitialization.js b/js/entity/TypeInitialization.js index 1e710fd..abed842 100755 --- a/js/entity/TypeInitialization.js +++ b/js/entity/TypeInitialization.js @@ -1,7 +1,5 @@ // @ts-check -import Utility from "../Utility" - /** * @template T */ @@ -33,14 +31,6 @@ export default class TypeInitialization { this.#value = v } - #decodeString - get decodeString() { - return this.#decodeString - } - set decodeString(v) { - this.#decodeString = v - } - static sanitize(value, targetType) { if (targetType === undefined) { targetType = value?.constructor @@ -72,7 +62,6 @@ export default class TypeInitialization { value = TypeInitialization.sanitize(new type()) } } - this.#value = type === String ? Utility.decodeString(value) : value this.#showDefault = showDefault this.#type = type } diff --git a/js/template/IInputPinTemplate.js b/js/template/IInputPinTemplate.js index 116a8fb..1c0f573 100644 --- a/js/template/IInputPinTemplate.js +++ b/js/template/IInputPinTemplate.js @@ -13,6 +13,9 @@ export default class IInputPinTemplate extends PinTemplate { /** @type {HTMLElement[]} */ #inputContentElements + get inputContentElements() { + return this.#inputContentElements + } hasInput = true /** @@ -24,7 +27,7 @@ export default class IInputPinTemplate extends PinTemplate { [...pin.querySelectorAll(".ueb-pin-input-content")] ) if (this.#inputContentElements.length) { - this.setInputs(pin, [pin.entity.DefaultValue]) + this.setInputs(pin, [Utility.decodeInputString(pin.entity.DefaultValue)]) let self = this this.onFocusHandler = _ => pin.blueprint.dispatchEditTextEvent(true) this.onFocusOutHandler = e => { @@ -72,16 +75,18 @@ export default class IInputPinTemplate extends PinTemplate { * @param {PinElement} pin */ getInputs(pin) { - return this.#inputContentElements.map(element => Utility.encodeInputString(element.textContent)) + return this.#inputContentElements.map(element => element.innerText) } /** * @param {PinElement} pin * @param {String[]?} values */ - setInputs(pin, values = []) { - this.#inputContentElements.forEach((element, i) => element.innerText = Utility.decodeInputString(values[i])) - pin.entity.DefaultValue = this.getInput(pin) + setInputs(pin, values = [], updateDefaultValue = true) { + this.#inputContentElements.forEach((element, i) => element.innerText = values[i]) + if (updateDefaultValue) { + pin.entity.DefaultValue = this.getInput(pin) + } } /** diff --git a/js/template/NamePinTemplate.js b/js/template/NamePinTemplate.js new file mode 100644 index 0000000..0e1802f --- /dev/null +++ b/js/template/NamePinTemplate.js @@ -0,0 +1,53 @@ +// @ts-check + +import IInputPinTemplate from "./IInputPinTemplate" + +/** + * @typedef {import("../element/PinElement").default} PinElement + */ + +export default class NamePinTemplate extends IInputPinTemplate { + + /** @type {(e : InputEvent) => void} */ + onInputHandler + + /** + * @param {PinElement} pin + */ + setup(pin) { + super.setup(pin) + this.onInputHandler = e => { + e.stopPropagation() + if ( + e.inputType == "insertParagraph" + || e.inputType == "insertLineBreak" + || (e.inputType == "insertFromPaste" && /** @type {HTMLElement} */(e.target).innerText.includes("\n")) + ) { + /** @type {HTMLElement} */(e.target).blur() // Loose focus in case it tries to insert newline + this.inputContentElements.forEach(element => element.innerText = element.innerText.replaceAll("\n", "")) + } + } + this.inputContentElements.forEach(element => { + element.addEventListener("input", /** @type {(e : Event) => void} */(this.onInputHandler)) + }) + } + + /** + * @param {PinElement} pin + */ + cleanup(pin) { + super.cleanup(pin) + this.inputContentElements.forEach(element => { + element.removeEventListener("input", /** @type {(e : Event) => void} */(this.onInputHandler)) + }) + } + + /** + * @param {PinElement} pin + * @param {String[]?} values + */ + setInputs(pin, values = [], updateDefaultValue = true) { + values = values.map(value => value.replaceAll("\n", "")) + super.setInputs(pin, values, updateDefaultValue) + } +} diff --git a/js/template/RealPinTemplate.js b/js/template/RealPinTemplate.js index 7da2960..3302136 100644 --- a/js/template/RealPinTemplate.js +++ b/js/template/RealPinTemplate.js @@ -15,12 +15,17 @@ export default class RealPinTemplate extends IInputPinTemplate { */ setInputs(pin, values = []) { let num = parseFloat(values.length ? values[0] : this.getInput(pin)) + let updateDefaultValue = true if (isNaN(num)) { num = parseFloat(pin.entity.DefaultValue != "" ? pin.entity.DefaultValue : pin.entity.AutogeneratedDefaultValue) } + if (isNaN(num)) { + num = 0 + updateDefaultValue = false + } values[0] = Utility.minDecimals(num) - super.setInputs(pin, values) + super.setInputs(pin, values, updateDefaultValue) } }