2020-01-15 03:40:48 +01:00
|
|
|
<script type="text/html" data-template-name="function">
|
2021-02-12 19:14:13 +01:00
|
|
|
<style>
|
2021-02-17 13:04:38 +01:00
|
|
|
.func-tabs-row {
|
|
|
|
margin-bottom: 0;
|
|
|
|
}
|
2021-02-12 19:14:13 +01:00
|
|
|
#node-input-libs-container-row .red-ui-editableList-container {
|
|
|
|
padding: 0px;
|
|
|
|
}
|
|
|
|
#node-input-libs-container-row .red-ui-editableList-container li {
|
2021-07-14 21:23:01 +02:00
|
|
|
padding:0px;
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
#node-input-libs-container-row .red-ui-editableList-item-remove {
|
|
|
|
right: 5px;
|
|
|
|
}
|
2021-07-14 21:23:01 +02:00
|
|
|
|
|
|
|
#node-input-libs-container-row .red-ui-editableList-header {
|
2021-02-12 19:14:13 +01:00
|
|
|
display: flex;
|
2021-07-14 21:23:01 +02:00
|
|
|
background: var(--red-ui-tertiary-background);
|
|
|
|
padding-right: 75px;
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
2021-07-14 21:23:01 +02:00
|
|
|
#node-input-libs-container-row .red-ui-editableList-header > div {
|
2021-02-12 19:14:13 +01:00
|
|
|
flex-grow: 1;
|
|
|
|
}
|
2021-07-14 21:23:01 +02:00
|
|
|
|
|
|
|
.node-libs-entry {
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
|
|
|
|
.node-libs-entry .red-ui-typedInput-container {
|
|
|
|
border-radius: 0;
|
|
|
|
border: none;
|
|
|
|
}
|
|
|
|
.node-libs-entry .red-ui-typedInput-type-select {
|
|
|
|
border-radius: 0 !important;
|
|
|
|
height: 34px;
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
2021-07-14 21:23:01 +02:00
|
|
|
.node-libs-entry > span > input[type=text] {
|
2021-02-12 19:14:13 +01:00
|
|
|
border-radius: 0;
|
2021-07-14 21:23:01 +02:00
|
|
|
border-top-color: var(--red-ui-form-background);
|
|
|
|
border-bottom-color: var(--red-ui-form-background);
|
|
|
|
border-right-color: var(--red-ui-form-background);
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
2021-07-14 21:23:01 +02:00
|
|
|
.node-libs-entry > span > input[type=text].input-error {
|
|
|
|
}
|
|
|
|
.node-libs-entry > span {
|
|
|
|
flex-grow: 1;
|
|
|
|
width: 50%;
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
.node-libs-entry span .node-input-libs-var, .node-libs-entry span .red-ui-typedInput-container {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
.node-libs-entry > span > span > i {
|
2021-02-12 19:14:13 +01:00
|
|
|
display: none;
|
|
|
|
}
|
2021-07-14 21:23:01 +02:00
|
|
|
.node-libs-entry > span > span.input-error > i {
|
2021-02-12 19:14:13 +01:00
|
|
|
display: inline;
|
|
|
|
}
|
2020-03-06 17:55:45 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
</style>
|
|
|
|
<input type="hidden" id="node-input-func">
|
|
|
|
<input type="hidden" id="node-input-noerr">
|
|
|
|
<input type="hidden" id="node-input-finalize">
|
|
|
|
<input type="hidden" id="node-input-initialize">
|
|
|
|
|
2021-02-17 13:04:38 +01:00
|
|
|
<div class="form-row">
|
|
|
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
|
|
|
<div style="display: inline-block; width: calc(100% - 105px)"><input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"></div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="form-row func-tabs-row">
|
2020-03-06 17:55:45 +01:00
|
|
|
<ul style="min-width: 600px; margin-bottom: 20px;" id="func-tabs"></ul>
|
2013-09-05 16:02:48 +02:00
|
|
|
</div>
|
2020-05-11 07:37:14 +02:00
|
|
|
<div id="func-tabs-content" style="min-height: calc(100% - 95px);">
|
2020-03-06 17:55:45 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
<div id="func-tab-config" style="display:none">
|
|
|
|
<div class="form-row">
|
|
|
|
<label for="node-input-outputs"><i class="fa fa-random"></i> <span data-i18n="function.label.outputs"></span></label>
|
|
|
|
<input id="node-input-outputs" style="width: 60px;" value="1">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-row node-input-libs-row hide" style="margin-bottom: 0px;">
|
2021-03-03 02:07:33 +01:00
|
|
|
<label><i class="fa fa-cubes"></i> <span data-i18n="function.label.modules"></span></label>
|
2021-02-12 19:14:13 +01:00
|
|
|
</div>
|
|
|
|
<div class="form-row node-input-libs-row hide" id="node-input-libs-container-row">
|
|
|
|
<ol id="node-input-libs-container"></ol>
|
2020-03-06 17:55:45 +01:00
|
|
|
</div>
|
2021-02-12 19:14:13 +01:00
|
|
|
</div>
|
2020-03-06 17:55:45 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
<div id="func-tab-init" style="display:none">
|
2020-03-06 17:55:45 +01:00
|
|
|
<div class="form-row node-text-editor-row" style="position:relative">
|
2021-02-17 15:41:25 +01:00
|
|
|
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div>
|
2022-09-04 16:21:34 +02:00
|
|
|
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
2020-03-06 17:55:45 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2020-04-06 09:34:41 +02:00
|
|
|
<div id="func-tab-body" style="display:none">
|
2020-03-06 17:55:45 +01:00
|
|
|
<div class="form-row node-text-editor-row" style="position:relative">
|
2021-02-17 15:41:25 +01:00
|
|
|
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
|
2022-09-04 16:21:34 +02:00
|
|
|
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
2020-03-06 17:55:45 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div id="func-tab-finalize" style="display:none">
|
|
|
|
<div class="form-row node-text-editor-row" style="position:relative">
|
2021-02-17 15:41:25 +01:00
|
|
|
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
|
2022-09-04 16:21:34 +02:00
|
|
|
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
2020-03-06 17:55:45 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2013-09-05 16:02:48 +02:00
|
|
|
</div>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
2021-01-27 14:27:54 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
(function() {
|
2021-01-27 14:27:54 +01:00
|
|
|
|
2021-02-16 14:58:59 +01:00
|
|
|
var invalidModuleVNames = [
|
|
|
|
'console',
|
|
|
|
'util',
|
|
|
|
'Buffer',
|
|
|
|
'Date',
|
|
|
|
'RED',
|
|
|
|
'node',
|
|
|
|
'__node__',
|
|
|
|
'context',
|
|
|
|
'flow',
|
|
|
|
'global',
|
|
|
|
'env',
|
|
|
|
'setTimeout',
|
|
|
|
'clearTimeout',
|
|
|
|
'setInterval',
|
|
|
|
'clearInterval',
|
|
|
|
'promisify'
|
|
|
|
]
|
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
var knownFunctionNodes = {};
|
|
|
|
RED.events.on("nodes:add", function(n) {
|
|
|
|
if (n.type === "function") {
|
|
|
|
knownFunctionNodes[n.id] = n;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
RED.events.on("nodes:remove", function(n) {
|
|
|
|
if (n.type === "function") {
|
|
|
|
delete knownFunctionNodes[n.id];
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
var missingModules = [];
|
|
|
|
var missingModuleReasons = {};
|
|
|
|
RED.events.on("runtime-state", function(event) {
|
|
|
|
if (event.error === "missing-modules") {
|
|
|
|
missingModules = event.modules.map(function(m) { missingModuleReasons[m.module] = m.error; return m.module });
|
|
|
|
for (var id in knownFunctionNodes) {
|
|
|
|
if (knownFunctionNodes.hasOwnProperty(id) && knownFunctionNodes[id].libs && knownFunctionNodes[id].libs.length > 0) {
|
|
|
|
RED.editor.validateNode(knownFunctionNodes[id])
|
|
|
|
}
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
2021-02-12 19:14:13 +01:00
|
|
|
} else if (!event.text) {
|
|
|
|
missingModuleReasons = {};
|
|
|
|
missingModules = [];
|
|
|
|
for (var id in knownFunctionNodes) {
|
|
|
|
if (knownFunctionNodes.hasOwnProperty(id) && knownFunctionNodes[id].libs && knownFunctionNodes[id].libs.length > 0) {
|
|
|
|
RED.editor.validateNode(knownFunctionNodes[id])
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
|
|
|
}
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
RED.view.redraw();
|
|
|
|
});
|
2021-01-27 14:27:54 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
var installAllowList = ['*'];
|
|
|
|
var installDenyList = [];
|
2021-01-27 14:27:54 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
var modulesEnabled = true;
|
|
|
|
if (RED.settings.get('externalModules.modules.allowInstall', true) === false) {
|
|
|
|
modulesEnabled = false;
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
2021-02-12 19:14:13 +01:00
|
|
|
var settingsAllowList = RED.settings.get("externalModules.modules.allowList")
|
|
|
|
var settingsDenyList = RED.settings.get("externalModules.modules.denyList")
|
|
|
|
if (settingsAllowList || settingsDenyList) {
|
|
|
|
installAllowList = settingsAllowList;
|
|
|
|
installDenyList = settingsDenyList
|
|
|
|
}
|
|
|
|
installAllowList = RED.utils.parseModuleList(installAllowList);
|
|
|
|
installDenyList = RED.utils.parseModuleList(installDenyList);
|
2021-01-27 14:27:54 +01:00
|
|
|
|
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
// object that maps from library name to its descriptor
|
|
|
|
var allLibs = [];
|
2021-01-27 14:27:54 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
function moduleName(module) {
|
|
|
|
var match = /^([^@]+)@(.+)/.exec(module);
|
|
|
|
if (match) {
|
|
|
|
return [match[1], match[2]];
|
|
|
|
}
|
|
|
|
return [module, undefined];
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
function getAllUsedModules() {
|
|
|
|
var moduleSet = new Set();
|
|
|
|
for (var id in knownFunctionNodes) {
|
|
|
|
if (knownFunctionNodes.hasOwnProperty(id)) {
|
|
|
|
if (knownFunctionNodes[id].libs) {
|
|
|
|
for (var i=0, l=knownFunctionNodes[id].libs.length; i<l; i++) {
|
|
|
|
if (RED.utils.checkModuleAllowed(knownFunctionNodes[id].libs[i].module,null,installAllowList,installDenyList)) {
|
|
|
|
moduleSet.add(knownFunctionNodes[id].libs[i].module);
|
|
|
|
}
|
|
|
|
}
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
|
|
|
}
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
var modules = Array.from(moduleSet);
|
|
|
|
modules.sort();
|
|
|
|
return modules;
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function prepareLibraryConfig(node) {
|
2021-02-12 19:14:13 +01:00
|
|
|
$(".node-input-libs-row").show();
|
|
|
|
var usedModules = getAllUsedModules();
|
|
|
|
var typedModules = usedModules.map(function(l) {
|
|
|
|
return {icon:"fa fa-cube", value:l,label:l,hasValue:false}
|
|
|
|
})
|
|
|
|
typedModules.push({
|
|
|
|
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
|
|
|
|
})
|
|
|
|
|
|
|
|
var libList = $("#node-input-libs-container").css('min-height','100px').css('min-width','450px').editableList({
|
2021-07-14 21:23:01 +02:00
|
|
|
header: $('<div><div data-i18n="node-red:function.require.moduleName"></div><div data-i18n="node-red:function.require.importAs"></div></div>'),
|
2021-01-27 14:27:54 +01:00
|
|
|
addItem: function(container,i,opt) {
|
|
|
|
var parent = container.parent();
|
2021-02-12 19:14:13 +01:00
|
|
|
var row0 = $("<div/>").addClass("node-libs-entry").appendTo(container);
|
2021-07-14 21:23:01 +02:00
|
|
|
var fmoduleSpan = $("<span>").appendTo(row0);
|
2021-01-27 14:27:54 +01:00
|
|
|
var fmodule = $("<input/>", {
|
|
|
|
class: "node-input-libs-val",
|
|
|
|
placeholder: RED._("node-red:function.require.module"),
|
2021-02-12 19:14:13 +01:00
|
|
|
type: "text"
|
2021-01-27 14:27:54 +01:00
|
|
|
}).css({
|
2021-07-14 21:23:01 +02:00
|
|
|
}).appendTo(fmoduleSpan).typedInput({
|
2021-02-12 19:14:13 +01:00
|
|
|
types: typedModules,
|
|
|
|
default: usedModules.indexOf(opt.module) > -1 ? opt.module : "_custom_"
|
|
|
|
});
|
|
|
|
if (usedModules.indexOf(opt.module) === -1) {
|
|
|
|
fmodule.typedInput('value', opt.module);
|
|
|
|
}
|
2021-07-14 21:23:01 +02:00
|
|
|
var moduleWarning = $('<span style="position: absolute;right:2px;top:7px; display:inline-block; width: 16px;"><i class="fa fa-warning"></i></span>').appendTo(fmoduleSpan);
|
2021-02-16 14:58:59 +01:00
|
|
|
RED.popover.tooltip(moduleWarning.find("i"),function() {
|
2021-02-12 19:14:13 +01:00
|
|
|
var val = fmodule.typedInput("type");
|
|
|
|
if (val === "_custom_") {
|
|
|
|
val = fmodule.val();
|
|
|
|
}
|
2021-02-16 14:58:59 +01:00
|
|
|
var errors = [];
|
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
if (!RED.utils.checkModuleAllowed(val,null,installAllowList,installDenyList)) {
|
2021-02-16 14:58:59 +01:00
|
|
|
return RED._("node-red:function.error.moduleNotAllowed",{module:val});
|
2021-02-12 19:14:13 +01:00
|
|
|
} else {
|
2021-02-16 14:58:59 +01:00
|
|
|
return RED._("node-red:function.error.moduleLoadError",{module:val,error:missingModuleReasons[val]});
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
})
|
2021-01-27 14:27:54 +01:00
|
|
|
|
2021-07-14 21:23:01 +02:00
|
|
|
var fvarSpan = $("<span>").appendTo(row0);
|
|
|
|
|
|
|
|
var fvar = $("<input/>", {
|
|
|
|
class: "node-input-libs-var red-ui-font-code",
|
|
|
|
placeholder: RED._("node-red:function.require.var"),
|
|
|
|
type: "text"
|
|
|
|
}).css({
|
|
|
|
}).appendTo(fvarSpan).val(opt.var);
|
|
|
|
var vnameWarning = $('<span style="position: absolute; right:2px;top:7px;display:inline-block; width: 16px;"><i class="fa fa-warning"></i></span>').appendTo(fvarSpan);
|
|
|
|
RED.popover.tooltip(vnameWarning.find("i"),function() {
|
|
|
|
var val = fvar.val();
|
|
|
|
if (invalidModuleVNames.indexOf(val) !== -1) {
|
|
|
|
return RED._("node-red:function.error.moduleNameReserved",{name:val})
|
|
|
|
} else {
|
|
|
|
return RED._("node-red:function.error.moduleNameError",{name:val})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-02-16 14:58:59 +01:00
|
|
|
fvar.on("change keyup paste", function (e) {
|
2021-02-12 19:14:13 +01:00
|
|
|
var v = $(this).val().trim();
|
2021-02-16 14:58:59 +01:00
|
|
|
if (v === "" || / /.test(v) || invalidModuleVNames.indexOf(v) !== -1) {
|
2021-02-12 19:14:13 +01:00
|
|
|
fvar.addClass("input-error");
|
2021-02-16 14:58:59 +01:00
|
|
|
vnameWarning.addClass("input-error");
|
2021-02-12 19:14:13 +01:00
|
|
|
} else {
|
|
|
|
fvar.removeClass("input-error");
|
2021-02-16 14:58:59 +01:00
|
|
|
vnameWarning.removeClass("input-error");
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
2021-01-27 14:27:54 +01:00
|
|
|
});
|
|
|
|
|
2021-02-16 14:58:59 +01:00
|
|
|
fmodule.on("change keyup paste", function (e) {
|
2021-02-12 19:14:13 +01:00
|
|
|
var val = $(this).typedInput("type");
|
|
|
|
if (val === "_custom_") {
|
|
|
|
val = $(this).val();
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
2022-09-10 05:17:18 +02:00
|
|
|
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/\.].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
|
2021-02-12 19:14:13 +01:00
|
|
|
fvar.val(varName);
|
|
|
|
fvar.trigger("change");
|
|
|
|
|
|
|
|
if (RED.utils.checkModuleAllowed(val,null,installAllowList,installDenyList) && (missingModules.indexOf(val) === -1)) {
|
|
|
|
fmodule.removeClass("input-error");
|
2021-02-16 14:58:59 +01:00
|
|
|
moduleWarning.removeClass("input-error");
|
2021-02-12 19:14:13 +01:00
|
|
|
} else {
|
|
|
|
fmodule.addClass("input-error");
|
2021-02-16 14:58:59 +01:00
|
|
|
moduleWarning.addClass("input-error");
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
|
|
|
});
|
2021-02-12 19:14:13 +01:00
|
|
|
if (RED.utils.checkModuleAllowed(opt.module,null,installAllowList,installDenyList) && (missingModules.indexOf(opt.module) === -1)) {
|
|
|
|
fmodule.removeClass("input-error");
|
2021-02-16 14:58:59 +01:00
|
|
|
moduleWarning.removeClass("input-error");
|
2021-02-12 19:14:13 +01:00
|
|
|
} else {
|
|
|
|
fmodule.addClass("input-error");
|
2021-02-16 14:58:59 +01:00
|
|
|
moduleWarning.addClass("input-error");
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
if (opt.var) {
|
|
|
|
fvar.trigger("change");
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
|
|
|
},
|
2021-02-12 19:14:13 +01:00
|
|
|
removable: true
|
2021-01-27 14:27:54 +01:00
|
|
|
});
|
2021-02-12 19:14:13 +01:00
|
|
|
|
|
|
|
var libs = node.libs || [];
|
|
|
|
for (var i=0,l=libs.length;i<l; i++) {
|
|
|
|
libList.editableList('addItem',libs[i])
|
|
|
|
}
|
|
|
|
|
2021-01-27 14:27:54 +01:00
|
|
|
}
|
2021-06-23 15:16:36 +02:00
|
|
|
|
2021-04-29 17:56:16 +02:00
|
|
|
function getLibsList() {
|
|
|
|
var _libs = [];
|
2021-07-15 11:07:52 +02:00
|
|
|
if (RED.settings.functionExternalModules !== false) {
|
2021-04-29 17:56:16 +02:00
|
|
|
var libs = $("#node-input-libs-container").editableList("items");
|
|
|
|
libs.each(function(i) {
|
|
|
|
var item = $(this);
|
|
|
|
var v = item.find(".node-input-libs-var").val();
|
|
|
|
var n = item.find(".node-input-libs-val").typedInput("type");
|
|
|
|
if (n === "_custom_") {
|
|
|
|
n = item.find(".node-input-libs-val").val();
|
|
|
|
}
|
|
|
|
if ((!v || (v === "")) ||
|
|
|
|
(!n || (n === ""))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_libs.push({
|
|
|
|
var: v,
|
|
|
|
module: n
|
|
|
|
});
|
|
|
|
});
|
2021-06-23 15:16:36 +02:00
|
|
|
}
|
2021-04-29 17:56:16 +02:00
|
|
|
return _libs;
|
|
|
|
}
|
2021-01-27 14:27:54 +01:00
|
|
|
|
2013-09-05 16:02:48 +02:00
|
|
|
RED.nodes.registerType('function',{
|
|
|
|
color:"#fdd0a2",
|
|
|
|
category: 'function',
|
|
|
|
defaults: {
|
2022-04-25 21:30:05 +02:00
|
|
|
name: {value:"_DEFAULT_"},
|
2014-04-02 22:20:58 +02:00
|
|
|
func: {value:"\nreturn msg;"},
|
2015-02-13 23:07:31 +01:00
|
|
|
outputs: {value:1},
|
2022-02-14 02:40:49 +01:00
|
|
|
noerr: {value:0,required:true,
|
|
|
|
validate: function(v, opt) {
|
|
|
|
if (!v) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return RED._("node-red:function.error.invalid-js");
|
|
|
|
}},
|
2020-03-06 17:55:45 +01:00
|
|
|
initialize: {value:""},
|
2021-01-11 11:32:16 +01:00
|
|
|
finalize: {value:""},
|
2022-02-14 02:40:49 +01:00
|
|
|
libs: {value: [], validate: function(v, opt) {
|
2021-02-12 19:14:13 +01:00
|
|
|
if (!v) { return true; }
|
|
|
|
for (var i=0,l=v.length;i<l;i++) {
|
|
|
|
var m = v[i];
|
|
|
|
if (!RED.utils.checkModuleAllowed(m.module,null,installAllowList,installDenyList)) {
|
2022-02-14 02:40:49 +01:00
|
|
|
return RED._("node-red:function.error.moduleNotAllowed", {
|
|
|
|
module: m.module
|
|
|
|
});
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
if (m.var === "" || / /.test(m.var)) {
|
2022-02-14 02:40:49 +01:00
|
|
|
return RED._("node-red:function.error.moduleNameError", {
|
|
|
|
name: m.var
|
|
|
|
});
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
if (missingModules.indexOf(m.module) > -1) {
|
2022-02-14 02:40:49 +01:00
|
|
|
return RED._("node-red:function.error.missing-module", {
|
|
|
|
module: m.module
|
|
|
|
});
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
2021-02-16 14:58:59 +01:00
|
|
|
if (invalidModuleVNames.indexOf(m.var) !== -1){
|
2022-02-14 02:40:49 +01:00
|
|
|
return RED._("node-red:function.error.moduleNameError", {
|
|
|
|
name: m.var
|
|
|
|
});
|
2021-02-16 14:58:59 +01:00
|
|
|
}
|
2021-02-12 19:14:13 +01:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}}
|
2013-09-05 16:02:48 +02:00
|
|
|
},
|
|
|
|
inputs:1,
|
|
|
|
outputs:1,
|
2019-06-21 13:36:20 +02:00
|
|
|
icon: "function.svg",
|
2013-09-05 16:02:48 +02:00
|
|
|
label: function() {
|
2018-04-16 12:12:21 +02:00
|
|
|
return this.name||this._("function.function");
|
2013-09-05 16:02:48 +02:00
|
|
|
},
|
2017-12-06 23:47:13 +01:00
|
|
|
labelStyle: function() {
|
|
|
|
return this.name?"node_label_italic":"";
|
|
|
|
},
|
2013-09-05 16:02:48 +02:00
|
|
|
oneditprepare: function() {
|
2015-02-13 01:15:07 +01:00
|
|
|
var that = this;
|
2020-03-06 17:55:45 +01:00
|
|
|
|
|
|
|
var tabs = RED.tabs.create({
|
|
|
|
id: "func-tabs",
|
|
|
|
onchange: function(tab) {
|
|
|
|
$("#func-tabs-content").children().hide();
|
|
|
|
$("#" + tab.id).show();
|
2021-04-29 19:00:23 +02:00
|
|
|
let editor = $("#" + tab.id).find('.monaco-editor').first();
|
2022-04-27 12:23:13 +02:00
|
|
|
if(editor.length) {
|
2021-04-29 19:00:23 +02:00
|
|
|
if(that.editor.nodered && that.editor.type == "monaco") {
|
|
|
|
that.editor.nodered.refreshModuleLibs(getLibsList());
|
|
|
|
}
|
|
|
|
RED.tray.resize();
|
2022-04-27 12:23:13 +02:00
|
|
|
//auto focus editor on tab switch
|
|
|
|
if (that.initEditor.getDomNode() == editor[0]) {
|
|
|
|
that.initEditor.focus();
|
|
|
|
} else if (that.editor.getDomNode() == editor[0]) {
|
|
|
|
that.editor.focus();
|
|
|
|
} else if (that.finalizeEditor.getDomNode() == editor[0]) {
|
|
|
|
that.finalizeEditor.focus();
|
|
|
|
}
|
2021-04-29 19:00:23 +02:00
|
|
|
}
|
2020-03-06 17:55:45 +01:00
|
|
|
}
|
|
|
|
});
|
2021-02-12 19:14:13 +01:00
|
|
|
tabs.addTab({
|
|
|
|
id: "func-tab-config",
|
|
|
|
iconClass: "fa fa-cog",
|
2021-02-17 13:04:38 +01:00
|
|
|
label: that._("function.label.setup")
|
2021-02-12 19:14:13 +01:00
|
|
|
});
|
|
|
|
|
2020-03-06 17:55:45 +01:00
|
|
|
tabs.addTab({
|
|
|
|
id: "func-tab-init",
|
2021-02-16 14:58:59 +01:00
|
|
|
label: that._("function.label.initialize")
|
2020-03-06 17:55:45 +01:00
|
|
|
});
|
|
|
|
tabs.addTab({
|
2020-04-06 09:34:41 +02:00
|
|
|
id: "func-tab-body",
|
2021-02-16 14:58:59 +01:00
|
|
|
label: that._("function.label.function")
|
2020-03-06 17:55:45 +01:00
|
|
|
});
|
|
|
|
tabs.addTab({
|
|
|
|
id: "func-tab-finalize",
|
2021-02-16 14:58:59 +01:00
|
|
|
label: that._("function.label.finalize")
|
2021-01-11 11:32:16 +01:00
|
|
|
});
|
|
|
|
|
2020-04-06 09:34:41 +02:00
|
|
|
tabs.activateTab("func-tab-body");
|
2020-03-06 17:55:45 +01:00
|
|
|
|
2013-09-05 16:02:48 +02:00
|
|
|
$( "#node-input-outputs" ).spinner({
|
2022-09-15 19:10:14 +02:00
|
|
|
min: 0,
|
2022-09-16 17:25:46 +02:00
|
|
|
max: 500,
|
2017-08-21 23:00:23 +02:00
|
|
|
change: function(event, ui) {
|
2022-09-17 19:22:52 +02:00
|
|
|
var value = parseInt(this.value);
|
|
|
|
value = isNaN(value) ? 1 : value;
|
|
|
|
value = Math.max(value, parseInt($(this).attr("aria-valuemin")));
|
|
|
|
value = Math.min(value, parseInt($(this).attr("aria-valuemax")));
|
2017-08-21 23:00:23 +02:00
|
|
|
if (value !== this.value) { $(this).spinner("value", value); }
|
|
|
|
}
|
2013-09-05 16:02:48 +02:00
|
|
|
});
|
|
|
|
|
2022-06-16 07:16:40 +02:00
|
|
|
var buildEditor = function(id, stateId, focus, value, defaultValue, extraLibs, offset) {
|
2020-05-22 15:57:28 +02:00
|
|
|
var editor = RED.editor.createEditor({
|
|
|
|
id: id,
|
|
|
|
mode: 'ace/mode/nrjavascript',
|
|
|
|
value: value || defaultValue || "",
|
2022-04-27 12:23:13 +02:00
|
|
|
stateId: stateId,
|
|
|
|
focus: true,
|
2020-05-22 15:57:28 +02:00
|
|
|
globals: {
|
|
|
|
msg:true,
|
|
|
|
context:true,
|
|
|
|
RED: true,
|
|
|
|
util: true,
|
|
|
|
flow: true,
|
|
|
|
global: true,
|
|
|
|
console: true,
|
|
|
|
Buffer: true,
|
|
|
|
setTimeout: true,
|
|
|
|
clearTimeout: true,
|
|
|
|
setInterval: true,
|
|
|
|
clearInterval: true
|
2021-04-29 19:00:23 +02:00
|
|
|
},
|
|
|
|
extraLibs: extraLibs
|
2020-05-22 15:57:28 +02:00
|
|
|
});
|
|
|
|
if (defaultValue && value === "") {
|
2022-06-16 07:16:40 +02:00
|
|
|
editor.moveCursorTo(defaultValue.split("\n").length +offset, 0);
|
2016-07-28 18:14:55 +02:00
|
|
|
}
|
2022-04-27 12:23:13 +02:00
|
|
|
editor.__stateId = stateId;
|
2020-05-22 15:57:28 +02:00
|
|
|
return editor;
|
2020-05-11 07:37:14 +02:00
|
|
|
}
|
2022-06-16 07:16:40 +02:00
|
|
|
this.initEditor = buildEditor('node-input-init-editor', this.id + "/" + "initEditor", false, $("#node-input-initialize").val(), RED._("node-red:function.text.initialize"), undefined, 0);
|
|
|
|
this.editor = buildEditor('node-input-func-editor', this.id + "/" + "editor", true, $("#node-input-func").val(), undefined, that.libs || [], undefined, -1);
|
|
|
|
this.finalizeEditor = buildEditor('node-input-finalize-editor', this.id + "/" + "finalizeEditor", false, $("#node-input-finalize").val(), RED._("node-red:function.text.finalize"), undefined, 0);
|
2015-05-07 23:02:46 +02:00
|
|
|
|
2015-02-13 01:15:07 +01:00
|
|
|
RED.library.create({
|
|
|
|
url:"functions", // where to get the data from
|
|
|
|
type:"function", // the type of object the library is for
|
2015-02-26 22:29:56 +01:00
|
|
|
editor:this.editor, // the field name the main text body goes to
|
2018-10-03 00:01:34 +02:00
|
|
|
mode:"ace/mode/nrjavascript",
|
2020-04-06 09:34:41 +02:00
|
|
|
fields:[
|
|
|
|
'name', 'outputs',
|
|
|
|
{
|
|
|
|
name: 'initialize',
|
|
|
|
get: function() {
|
|
|
|
return that.initEditor.getValue();
|
|
|
|
},
|
|
|
|
set: function(v) {
|
2020-05-22 15:57:28 +02:00
|
|
|
that.initEditor.setValue(v||RED._("node-red:function.text.initialize"), -1);
|
2020-04-06 09:34:41 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'finalize',
|
|
|
|
get: function() {
|
|
|
|
return that.finalizeEditor.getValue();
|
|
|
|
},
|
|
|
|
set: function(v) {
|
2020-05-22 15:57:28 +02:00
|
|
|
that.finalizeEditor.setValue(v||RED._("node-red:function.text.finalize"), -1);
|
2020-04-06 09:34:41 +02:00
|
|
|
}
|
2020-05-22 16:43:17 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'info',
|
|
|
|
get: function() {
|
|
|
|
return that.infoEditor.getValue();
|
|
|
|
},
|
|
|
|
set: function(v) {
|
|
|
|
that.infoEditor.setValue(v||"", -1);
|
|
|
|
}
|
2020-04-06 09:34:41 +02:00
|
|
|
}
|
|
|
|
],
|
2019-05-21 23:58:56 +02:00
|
|
|
ext:"js"
|
2013-09-05 16:02:48 +02:00
|
|
|
});
|
2019-05-27 16:48:06 +02:00
|
|
|
|
2020-05-22 15:57:28 +02:00
|
|
|
var expandButtonClickHandler = function(editor) {
|
2022-04-27 12:23:13 +02:00
|
|
|
return function (e) {
|
2020-05-22 15:57:28 +02:00
|
|
|
e.preventDefault();
|
|
|
|
var value = editor.getValue();
|
2022-04-27 12:23:13 +02:00
|
|
|
editor.saveView(`inside function-expandButtonClickHandler ${editor.__stateId}`);
|
2022-01-08 20:29:49 +01:00
|
|
|
var extraLibs = that.libs || [];
|
2020-05-22 15:57:28 +02:00
|
|
|
RED.editor.editJavaScript({
|
|
|
|
value: value,
|
|
|
|
width: "Infinity",
|
2022-04-27 12:23:13 +02:00
|
|
|
stateId: editor.__stateId,
|
2020-05-22 15:57:28 +02:00
|
|
|
mode: "ace/mode/nrjavascript",
|
2022-04-27 12:23:13 +02:00
|
|
|
focus: true,
|
|
|
|
cancel: function () {
|
|
|
|
setTimeout(function () {
|
|
|
|
editor.focus();
|
|
|
|
}, 250);
|
|
|
|
},
|
|
|
|
complete: function (v, cursor) {
|
2020-05-22 15:57:28 +02:00
|
|
|
editor.setValue(v, -1);
|
2022-04-27 12:23:13 +02:00
|
|
|
setTimeout(function () {
|
|
|
|
editor.restoreView();
|
2020-05-22 15:57:28 +02:00
|
|
|
editor.focus();
|
2022-04-27 12:23:13 +02:00
|
|
|
}, 250);
|
2022-01-08 20:29:49 +01:00
|
|
|
},
|
|
|
|
extraLibs: extraLibs
|
2022-04-27 12:23:13 +02:00
|
|
|
});
|
2020-05-22 15:57:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
$("#node-init-expand-js").on("click", expandButtonClickHandler(this.initEditor));
|
|
|
|
$("#node-function-expand-js").on("click", expandButtonClickHandler(this.editor));
|
|
|
|
$("#node-finalize-expand-js").on("click", expandButtonClickHandler(this.finalizeEditor));
|
|
|
|
|
|
|
|
RED.popover.tooltip($("#node-init-expand-js"), RED._("node-red:common.label.expand"));
|
2019-05-27 16:48:06 +02:00
|
|
|
RED.popover.tooltip($("#node-function-expand-js"), RED._("node-red:common.label.expand"));
|
2020-05-22 15:57:28 +02:00
|
|
|
RED.popover.tooltip($("#node-finalize-expand-js"), RED._("node-red:common.label.expand"));
|
2020-03-06 17:55:45 +01:00
|
|
|
|
2021-02-12 19:14:13 +01:00
|
|
|
if (RED.settings.functionExternalModules !== false) {
|
|
|
|
prepareLibraryConfig(that);
|
|
|
|
}
|
2013-09-05 16:02:48 +02:00
|
|
|
},
|
|
|
|
oneditsave: function() {
|
2020-03-06 17:55:45 +01:00
|
|
|
var node = this;
|
|
|
|
var noerr = 0;
|
2015-05-08 16:31:48 +02:00
|
|
|
$("#node-input-noerr").val(0);
|
2020-05-22 15:57:28 +02:00
|
|
|
|
|
|
|
var disposeEditor = function(editorName,targetName,defaultValue) {
|
|
|
|
var editor = node[editorName];
|
|
|
|
var annot = editor.getSession().getAnnotations();
|
|
|
|
for (var k=0; k < annot.length; k++) {
|
|
|
|
if (annot[k].type === "error") {
|
|
|
|
noerr += annot.length;
|
|
|
|
break;
|
|
|
|
}
|
2015-02-13 23:07:31 +01:00
|
|
|
}
|
2020-05-22 15:57:28 +02:00
|
|
|
var val = editor.getValue();
|
2020-06-05 11:36:49 +02:00
|
|
|
if (defaultValue) {
|
|
|
|
if (val.trim() == defaultValue.trim()) {
|
|
|
|
val = "";
|
|
|
|
}
|
2020-03-06 17:55:45 +01:00
|
|
|
}
|
2020-05-22 15:57:28 +02:00
|
|
|
editor.destroy();
|
|
|
|
delete node[editorName];
|
|
|
|
$("#"+targetName).val(val);
|
2015-02-13 23:07:31 +01:00
|
|
|
}
|
2020-05-22 15:57:28 +02:00
|
|
|
disposeEditor("editor","node-input-func");
|
|
|
|
disposeEditor("initEditor","node-input-initialize", RED._("node-red:function.text.initialize"));
|
|
|
|
disposeEditor("finalizeEditor","node-input-finalize", RED._("node-red:function.text.finalize"));
|
|
|
|
|
2020-03-06 17:55:45 +01:00
|
|
|
$("#node-input-noerr").val(noerr);
|
|
|
|
this.noerr = noerr;
|
2021-04-29 17:56:16 +02:00
|
|
|
node.libs = getLibsList();
|
2016-01-04 17:53:32 +01:00
|
|
|
},
|
2017-04-21 10:03:41 +02:00
|
|
|
oneditcancel: function() {
|
2020-03-06 17:55:45 +01:00
|
|
|
var node = this;
|
|
|
|
|
|
|
|
node.editor.destroy();
|
|
|
|
delete node.editor;
|
|
|
|
|
|
|
|
node.initEditor.destroy();
|
|
|
|
delete node.initEditor;
|
|
|
|
|
|
|
|
node.finalizeEditor.destroy();
|
|
|
|
delete node.finalizeEditor;
|
2017-04-21 10:03:41 +02:00
|
|
|
},
|
2016-01-04 17:53:32 +01:00
|
|
|
oneditresize: function(size) {
|
|
|
|
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
|
|
|
var height = $("#dialog-form").height();
|
2019-04-29 12:50:15 +02:00
|
|
|
for (var i=0; i<rows.length; i++) {
|
2016-01-04 17:53:32 +01:00
|
|
|
height -= $(rows[i]).outerHeight(true);
|
|
|
|
}
|
|
|
|
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
|
|
|
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
2021-02-17 13:04:38 +01:00
|
|
|
$("#dialog-form .node-text-editor").css("height",height+"px");
|
2020-03-06 17:55:45 +01:00
|
|
|
|
|
|
|
var height = size.height;
|
2021-07-16 10:44:56 +02:00
|
|
|
$("#node-input-init-editor").css("height", (height - 83)+"px");
|
|
|
|
$("#node-input-func-editor").css("height", (height - 83)+"px");
|
|
|
|
$("#node-input-finalize-editor").css("height", (height - 83)+"px");
|
2020-05-22 15:57:28 +02:00
|
|
|
|
|
|
|
this.initEditor.resize();
|
|
|
|
this.editor.resize();
|
|
|
|
this.finalizeEditor.resize();
|
|
|
|
|
2021-07-16 10:44:56 +02:00
|
|
|
$("#node-input-libs-container").css("height", (height - 192)+"px");
|
2022-04-25 21:30:05 +02:00
|
|
|
},
|
|
|
|
onadd: function() {
|
|
|
|
if (this.name === '_DEFAULT_') {
|
|
|
|
this.name = ''
|
2022-06-26 10:08:26 +02:00
|
|
|
RED.actions.invoke("core:generate-node-names", this, {generateHistory: false})
|
2022-04-25 21:30:05 +02:00
|
|
|
}
|
2013-09-05 16:02:48 +02:00
|
|
|
}
|
|
|
|
});
|
2021-02-12 19:14:13 +01:00
|
|
|
})();
|
2013-09-05 16:02:48 +02:00
|
|
|
</script>
|