', { class: "red-ui-search-result-node" }).css({
"margin-top": "2px",
"margin-left": "3px"
}).appendTo(container);
@@ -268,117 +274,117 @@
"margin-left": "6px"
}).appendTo(container);
if (node) {
- var colour = RED.utils.getNodeColor(node.type,node._def);
- var icon_url = RED.utils.getNodeIcon(node._def,node);
+ var colour = RED.utils.getNodeColor(node.type, node._def);
+ var icon_url = RED.utils.getNodeIcon(node._def, node);
if (node.type === 'tab') {
colour = "#C0DEED";
}
- nodeDiv.css('backgroundColor',colour);
- var iconContainer = $('
',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
+ nodeDiv.css('backgroundColor', colour);
+ var iconContainer = $('
', { class: "red-ui-palette-icon-container" }).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
- var l = RED.utils.getNodeLabel(node,node.id);
+ var l = RED.utils.getNodeLabel(node, node.id);
nodeLabel.text(l);
} else {
nodeDiv.css({
'backgroundColor': '#eee',
- 'border-style' : 'dashed'
+ 'border-style': 'dashed'
});
}
},
- expand: function() {
+ expand: function () {
var that = this;
RED.tray.hide();
RED.view.selectNodes({
single: true,
selected: [that.value()],
- onselect: function(selection) {
+ onselect: function (selection) {
that.value(selection.id);
RED.tray.show();
},
- oncancel: function() {
+ oncancel: function () {
RED.tray.show();
}
})
}
},
- cred:{
- value:"cred",
- label:"credential",
- icon:"fa fa-lock",
+ cred: {
+ value: "cred",
+ label: "credential",
+ icon: "fa fa-lock",
inputType: "password",
- valueLabel: function(container,value) {
+ valueLabel: function (container, value) {
var that = this;
- container.css("pointer-events","none");
- container.css("flex-grow",0);
+ container.css("pointer-events", "none");
+ container.css("flex-grow", 0);
this.elementDiv.hide();
var buttons = $('
').css({
position: "absolute",
- right:"6px",
+ right: "6px",
top: "6px",
- "pointer-events":"all"
+ "pointer-events": "all"
}).appendTo(container);
var eyeButton = $('
').css({
- width:"20px"
- }).appendTo(buttons).on("click", function(evt) {
+ width: "20px"
+ }).appendTo(buttons).on("click", function (evt) {
evt.preventDefault();
var cursorPosition = that.input[0].selectionStart;
var currentType = that.input.attr("type");
if (currentType === "text") {
- that.input.attr("type","password");
+ that.input.attr("type", "password");
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
- setTimeout(function() {
+ setTimeout(function () {
that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
- },50);
+ }, 50);
} else {
- that.input.attr("type","text");
+ that.input.attr("type", "text");
eyeCon.removeClass("fa-eye").addClass("fa-eye-slash");
- setTimeout(function() {
+ setTimeout(function () {
that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
- },50);
+ }, 50);
}
}).hide();
- var eyeCon = $('
').css("margin-left","-2px").appendTo(eyeButton);
+ var eyeCon = $('
').css("margin-left", "-2px").appendTo(eyeButton);
if (value === "__PWRD__") {
var innerContainer = $('
').css({
- padding:"6px 6px",
- borderRadius:"4px"
+ padding: "6px 6px",
+ borderRadius: "4px"
}).addClass("red-ui-typedInput-value-label-inactive").appendTo(container);
- var editButton = $('
').appendTo(buttons).on("click", function(evt) {
+ var editButton = $('
').appendTo(buttons).on("click", function (evt) {
evt.preventDefault();
innerContainer.hide();
- container.css("background","none");
- container.css("pointer-events","none");
+ container.css("background", "none");
+ container.css("pointer-events", "none");
that.input.val("");
that.element.val("");
that.elementDiv.show();
editButton.hide();
cancelButton.show();
eyeButton.show();
- setTimeout(function() {
+ setTimeout(function () {
that.input.focus();
- },50);
+ }, 50);
});
- var cancelButton = $('
').css("margin-left","3px").appendTo(buttons).on("click", function(evt) {
+ var cancelButton = $('
').css("margin-left", "3px").appendTo(buttons).on("click", function (evt) {
evt.preventDefault();
innerContainer.show();
- container.css("background","");
+ container.css("background", "");
that.input.val("__PWRD__");
that.element.val("__PWRD__");
that.elementDiv.hide();
editButton.show();
cancelButton.hide();
eyeButton.hide();
- that.input.attr("type","password");
+ that.input.attr("type", "password");
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
}).hide();
} else {
- container.css("background","none");
- container.css("pointer-events","none");
+ container.css("background", "none");
+ container.css("pointer-events", "none");
this.elementDiv.show();
eyeButton.show();
}
@@ -1234,25 +1240,41 @@
}
},
validate: function() {
- var result;
- var value = this.value();
- var type = this.type();
+ let valid = true;
+ const value = this.value();
+ const type = this.type();
if (this.typeMap[type] && this.typeMap[type].validate) {
- var val = this.typeMap[type].validate;
- if (typeof val === 'function') {
- result = val(value);
+ const validate = this.typeMap[type].validate;
+ if (typeof validate === 'function') {
+ valid = validate(value, {});
} else {
- result = val.test(value);
+ // Regex
+ valid = validate.test(value);
+ if (!valid) {
+ valid = RED._("validator.errors.invalid-regexp");
+ }
+ }
+ }
+ if ((typeof valid === "string") || !valid) {
+ this.uiSelect.addClass("input-error");
+ if (typeof valid === "string") {
+ let tooltip = this.element.data("tooltip");
+ if (tooltip) {
+ tooltip.setContent(valid);
+ } else {
+ tooltip = RED.popover.tooltip(this.elementDiv, valid);
+ this.element.data("tooltip", tooltip);
+ }
}
} else {
- result = true;
+ this.uiSelect.removeClass("input-error");
+ const tooltip = this.element.data("tooltip");
+ if (tooltip) {
+ this.element.data("tooltip", null);
+ tooltip.delete();
+ }
}
- if (result) {
- this.uiSelect.removeClass('input-error');
- } else {
- this.uiSelect.addClass('input-error');
- }
- return result;
+ return !!valid;
},
show: function() {
this.uiSelect.show();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
index 6475b19f5..1677dea04 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
@@ -888,11 +888,25 @@ RED.utils = (function() {
return parts;
}
- function validatePropertyExpression(str) {
+ /**
+ * Validate a property expression
+ * @param {*} str - the property value
+ * @returns {boolean|string} whether the node proprty is valid. `true`: valid `false|String`: invalid
+ */
+ function validatePropertyExpression(str, opt) {
try {
- var parts = normalisePropertyExpression(str);
+ const parts = normalisePropertyExpression(str);
return true;
} catch(err) {
+ // If the validator has opt, it is a 3.x validator that
+ // can return a String to mean 'invalid' and provide a reason
+ if (opt) {
+ if (opt.label) {
+ return opt.label + ': ' + err.message;
+ }
+ return err.message;
+ }
+ // Otherwise, a 2.x returns a false value
return false;
}
}
@@ -906,23 +920,24 @@ RED.utils = (function() {
* @returns true if valid, String if invalid
*/
function validateTypedProperty(propertyValue, propertyType, opt) {
-
- let error
+ let error;
if (propertyType === 'json') {
try {
JSON.parse(propertyValue);
} catch(err) {
error = RED._("validator.errors.invalid-json", {
error: err.message
- })
+ });
}
} else if (propertyType === 'msg' || propertyType === 'flow' || propertyType === 'global' ) {
- if (!RED.utils.validatePropertyExpression(propertyValue)) {
- error = RED._("validator.errors.invalid-prop")
+ // To avoid double label
+ const valid = RED.utils.validatePropertyExpression(propertyValue, opt ? {} : undefined);
+ if (valid !== true) {
+ error = opt ? valid : RED._("validator.errors.invalid-prop");
}
} else if (propertyType === 'num') {
if (!/^NaN$|^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$|^[+-]?(0b|0B)[01]+$|^[+-]?(0o|0O)[0-7]+$|^[+-]?(0x|0X)[0-9a-fA-F]+$/.test(propertyValue)) {
- error = RED._("validator.errors.invalid-num")
+ error = RED._("validator.errors.invalid-num");
}
} else if (propertyType === 'jsonata') {
try {
@@ -930,16 +945,16 @@ RED.utils = (function() {
} catch(err) {
error = RED._("validator.errors.invalid-expr", {
error: err.message
- })
+ });
}
}
if (error) {
if (opt && opt.label) {
- return opt.label+': '+error
+ return opt.label + ': ' + error;
}
- return error
+ return error;
}
- return true
+ return true;
}
function getMessageProperty(msg,expr) {
From 282d52cf0b9717813a182462fa4599943d70b458 Mon Sep 17 00:00:00 2001
From: GogoVega <92022724+GogoVega@users.noreply.github.com>
Date: Sun, 17 Dec 2023 19:22:44 +0100
Subject: [PATCH 2/7] Fix non-boolean returned value + try to find validation
msg in tooltip
---
.../@node-red/editor-client/src/js/ui/common/popover.js | 8 ++++++--
.../editor-client/src/js/ui/common/typedInput.js | 3 ++-
.../@node-red/editor-client/src/js/ui/editor.js | 8 ++++++++
.../@node-red/editor-client/src/js/ui/utils.js | 2 +-
4 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
index 9ddd3d866..1b0ded805 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
@@ -53,6 +53,7 @@
* Returns the popover object with the following properties/functions:
* properties:
* - element : DOM element - the popover dom element
+ * - content : string|function - the popover content
* functions:
* - setContent(content) - change the popover content. This only works if the
* popover is not currently displayed. It does not
@@ -159,7 +160,7 @@ RED.popover = (function() {
var size = options.size||"default";
var popupOffset = options.offset || 0;
if (!deltaSizes[size]) {
- throw new Error("Invalid RED.popover size value:",size);
+ throw new Error("Invalid RED.popover size value:" + size);
}
var timer = null;
@@ -419,6 +420,7 @@ RED.popover = (function() {
}
var res = {
get element() { return div },
+ get content() { return content },
setContent: function(_content) {
content = _content;
@@ -440,7 +442,6 @@ RED.popover = (function() {
}
}
return res;
-
}
return {
@@ -465,6 +466,9 @@ RED.popover = (function() {
content: label,
delay: { show: 750, hide: 50 }
});
+ popover.getContent = function () {
+ return content;
+ }
popover.setContent = function(newContent) {
content = newContent;
}
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
index 752c24eff..f1ebfabe5 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
@@ -1274,7 +1274,8 @@
tooltip.delete();
}
}
- return !!valid;
+ // Must return a boolean
+ return (typeof valid === "string") ? false : valid;
},
show: function() {
this.uiSelect.show();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
index 4908373c7..680aecd62 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
@@ -191,6 +191,14 @@ RED.editor = (function() {
const isTypedInput = input.length > 0 && input.next(".red-ui-typedInput-container").length > 0;
if (isTypedInput) {
valid = input.typedInput("validate");
+ if (valid === false) {
+ // Try to find validation message in the tooltip
+ const tooltip = input.data("tooltip");
+ if (tooltip) {
+ const content = tooltip.getContent();
+ valid = label ? label + ": " + content : content;
+ }
+ }
}
}
}
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
index 1677dea04..b056ee1f1 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
@@ -931,7 +931,7 @@ RED.utils = (function() {
}
} else if (propertyType === 'msg' || propertyType === 'flow' || propertyType === 'global' ) {
// To avoid double label
- const valid = RED.utils.validatePropertyExpression(propertyValue, opt ? {} : undefined);
+ const valid = RED.utils.validatePropertyExpression(propertyValue, opt ? {} : null);
if (valid !== true) {
error = opt ? valid : RED._("validator.errors.invalid-prop");
}
From 6aae50294f1d9364e85ddf23ccccf07459403464 Mon Sep 17 00:00:00 2001
From: GogoVega <92022724+GogoVega@users.noreply.github.com>
Date: Sun, 2 Jun 2024 20:16:10 +0200
Subject: [PATCH 3/7] Cleanup + fix popover.getContent can be a function and
apply #4450 changes
---
.../@node-red/editor-client/src/js/ui/common/popover.js | 7 +++----
.../@node-red/editor-client/src/js/ui/common/typedInput.js | 2 ++
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
index ecfc3a6b9..29c756749 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
@@ -53,8 +53,8 @@
* Returns the popover object with the following properties/functions:
* properties:
* - element : DOM element - the popover dom element
- * - content : string|function - the popover content
* functions:
+ * - getContent() - get the popover content
* - setContent(content) - change the popover content. This only works if the
* popover is not currently displayed. It does not
* change the content of a visible popover.
@@ -160,7 +160,7 @@ RED.popover = (function() {
var size = options.size||"default";
var popupOffset = options.offset || 0;
if (!deltaSizes[size]) {
- throw new Error("Invalid RED.popover size value:" + size);
+ throw new Error("Invalid RED.popover size value: " + size);
}
var timer = null;
@@ -420,7 +420,6 @@ RED.popover = (function() {
}
var res = {
get element() { return div },
- get content() { return content },
setContent: function(_content) {
content = _content;
@@ -471,7 +470,7 @@ RED.popover = (function() {
delay: { show: 750, hide: 50 }
});
popover.getContent = function () {
- return content;
+ return label();
}
popover.setContent = function(newContent) {
content = newContent;
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
index 16b066afb..013e5098c 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
@@ -1560,6 +1560,7 @@
}
}
if ((typeof valid === "string") || !valid) {
+ this.element.addClass("input-error");
this.uiSelect.addClass("input-error");
if (typeof valid === "string") {
let tooltip = this.element.data("tooltip");
@@ -1571,6 +1572,7 @@
}
}
} else {
+ this.element.removeClass("input-error");
this.uiSelect.removeClass("input-error");
const tooltip = this.element.data("tooltip");
if (tooltip) {
From 34ed9c5cd81e70fb12b49a7b36a074ae099d04f3 Mon Sep 17 00:00:00 2001
From: GogoVega <92022724+GogoVega@users.noreply.github.com>
Date: Mon, 3 Jun 2024 18:41:40 +0200
Subject: [PATCH 4/7] Don't use the typedInput tooltip to get the validation
message
---
.../editor-client/src/js/ui/common/typedInput.js | 7 +++++--
.../@node-red/editor-client/src/js/ui/editor.js | 11 +++--------
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
index 013e5098c..db678e6b1 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
@@ -1543,7 +1543,7 @@
}
}
},
- validate: function() {
+ validate: function(options) {
let valid = true;
const value = this.value();
const type = this.type();
@@ -1580,7 +1580,10 @@
tooltip.delete();
}
}
- // Must return a boolean
+ if (options.returnErrorMessage === true) {
+ return valid;
+ }
+ // Must return a boolean for no 3.x validator
return (typeof valid === "string") ? false : valid;
},
show: function() {
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
index e5247fbd8..72e3044e8 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
@@ -190,14 +190,9 @@ RED.editor = (function() {
const input = $("#"+prefix+"-"+property);
const isTypedInput = input.length > 0 && input.next(".red-ui-typedInput-container").length > 0;
if (isTypedInput) {
- valid = input.typedInput("validate");
- if (valid === false) {
- // Try to find validation message in the tooltip
- const tooltip = input.data("tooltip");
- if (tooltip) {
- const content = tooltip.getContent();
- valid = label ? label + ": " + content : content;
- }
+ valid = input.typedInput("validate", { returnErrorMessage: true });
+ if (typeof valid === "string") {
+ valid = label ? label + ": " + valid : valid;
}
}
}
From da7c7ede022fb2ce7a206dce6feee785e6db5fa1 Mon Sep 17 00:00:00 2001
From: GogoVega <92022724+GogoVega@users.noreply.github.com>
Date: Mon, 3 Jun 2024 18:57:41 +0200
Subject: [PATCH 5/7] Fix a String value is an error, so return the value
---
.../node_modules/@node-red/editor-client/src/js/ui/editor.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
index 72e3044e8..97f64f774 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
@@ -192,7 +192,7 @@ RED.editor = (function() {
if (isTypedInput) {
valid = input.typedInput("validate", { returnErrorMessage: true });
if (typeof valid === "string") {
- valid = label ? label + ": " + valid : valid;
+ return label ? label + ": " + valid : valid;
}
}
}
From bd2c020e8492d9385135a66a4ea622133f192a21 Mon Sep 17 00:00:00 2001
From: GogoVega <92022724+GogoVega@users.noreply.github.com>
Date: Mon, 3 Jun 2024 21:11:13 +0200
Subject: [PATCH 6/7] My bad, options can be undefined
---
.../@node-red/editor-client/src/js/ui/common/typedInput.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
index db678e6b1..f42c1ac92 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
@@ -1580,7 +1580,7 @@
tooltip.delete();
}
}
- if (options.returnErrorMessage === true) {
+ if (options?.returnErrorMessage === true) {
return valid;
}
// Must return a boolean for no 3.x validator
From bffa923f056be264dff6996a3770185959896272 Mon Sep 17 00:00:00 2001
From: GogoVega <92022724+GogoVega@users.noreply.github.com>
Date: Mon, 10 Jun 2024 18:02:28 +0200
Subject: [PATCH 7/7] Revert all changes for `RED.popover`
---
.../@node-red/editor-client/src/js/ui/common/popover.js | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
index 29c756749..381bb9d3a 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
@@ -54,7 +54,6 @@
* properties:
* - element : DOM element - the popover dom element
* functions:
- * - getContent() - get the popover content
* - setContent(content) - change the popover content. This only works if the
* popover is not currently displayed. It does not
* change the content of a visible popover.
@@ -160,7 +159,7 @@ RED.popover = (function() {
var size = options.size||"default";
var popupOffset = options.offset || 0;
if (!deltaSizes[size]) {
- throw new Error("Invalid RED.popover size value: " + size);
+ throw new Error("Invalid RED.popover size value:",size);
}
var timer = null;
@@ -441,6 +440,7 @@ RED.popover = (function() {
}
}
return res;
+
}
return {
@@ -469,9 +469,6 @@ RED.popover = (function() {
interactive,
delay: { show: 750, hide: 50 }
});
- popover.getContent = function () {
- return label();
- }
popover.setContent = function(newContent) {
content = newContent;
}