mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Move type editors into their own files
This commit is contained in:
parent
99af79fcf3
commit
80062b6a62
@ -150,6 +150,7 @@ module.exports = function(grunt) {
|
||||
"editor/js/ui/tab-config.js",
|
||||
"editor/js/ui/palette-editor.js",
|
||||
"editor/js/ui/editor.js",
|
||||
"editor/js/ui/editors/*.js",
|
||||
"editor/js/ui/tray.js",
|
||||
"editor/js/ui/clipboard.js",
|
||||
"editor/js/ui/library.js",
|
||||
|
@ -1818,658 +1818,22 @@ RED.editor = (function() {
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
|
||||
var expressionTestCache = {};
|
||||
|
||||
function editExpression(options) {
|
||||
var expressionTestCacheId = "_";
|
||||
function showTypeEditor(type, options) {
|
||||
if (RED.editor.types.hasOwnProperty(type)) {
|
||||
if (editStack.length > 0) {
|
||||
expressionTestCacheId = editStack[editStack.length-1].id;
|
||||
options.parent = editStack[editStack.length-1].id;
|
||||
}
|
||||
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_expression"
|
||||
editStack.push({type:type});
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var testDataEditor;
|
||||
var testResultEditor
|
||||
var panels;
|
||||
|
||||
var trayOptions = {
|
||||
title: getEditStackTitle(),
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
$("#node-input-expression-help").html("");
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
if (dimensions) {
|
||||
editTrayWidthCache[type] = dimensions.width;
|
||||
}
|
||||
var height = $("#dialog-form").height();
|
||||
if (panels) {
|
||||
panels.resize(height);
|
||||
}
|
||||
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
trayBody.addClass("node-input-expression-editor")
|
||||
var dialogForm = buildEditForm(tray.find('.editor-tray-body'),'dialog-form','_expression','editor');
|
||||
var funcSelect = $("#node-input-expression-func");
|
||||
Object.keys(jsonata.functions).forEach(function(f) {
|
||||
funcSelect.append($("<option></option>").val(f).text(f));
|
||||
})
|
||||
funcSelect.change(function(e) {
|
||||
var f = $(this).val();
|
||||
var args = RED._('jsonata:'+f+".args",{defaultValue:''});
|
||||
var title = "<h5>"+f+"("+args+")</h5>";
|
||||
var body = marked(RED._('jsonata:'+f+'.desc',{defaultValue:''}));
|
||||
$("#node-input-expression-help").html(title+"<p>"+body+"</p>");
|
||||
|
||||
})
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression',
|
||||
value: "",
|
||||
mode:"ace/mode/jsonata",
|
||||
options: {
|
||||
enableBasicAutocompletion:true,
|
||||
enableSnippets:true,
|
||||
enableLiveAutocompletion: true
|
||||
}
|
||||
});
|
||||
var currentToken = null;
|
||||
var currentTokenPos = -1;
|
||||
var currentFunctionMarker = null;
|
||||
|
||||
expressionEditor.getSession().setValue(value||"",-1);
|
||||
expressionEditor.on("changeSelection", function() {
|
||||
var c = expressionEditor.getCursorPosition();
|
||||
var token = expressionEditor.getSession().getTokenAt(c.row,c.column);
|
||||
if (token !== currentToken || (token && /paren/.test(token.type) && c.column !== currentTokenPos)) {
|
||||
currentToken = token;
|
||||
var r,p;
|
||||
var scopedFunction = null;
|
||||
if (token && token.type === 'keyword') {
|
||||
r = c.row;
|
||||
scopedFunction = token;
|
||||
} else {
|
||||
var depth = 0;
|
||||
var next = false;
|
||||
if (token) {
|
||||
if (token.type === 'paren.rparen') {
|
||||
// If this is a block of parens ')))', set
|
||||
// depth to offset against the cursor position
|
||||
// within the block
|
||||
currentTokenPos = c.column;
|
||||
depth = c.column - (token.start + token.value.length);
|
||||
}
|
||||
r = c.row;
|
||||
p = token.index;
|
||||
} else {
|
||||
r = c.row-1;
|
||||
p = -1;
|
||||
}
|
||||
while ( scopedFunction === null && r > -1) {
|
||||
var rowTokens = expressionEditor.getSession().getTokens(r);
|
||||
if (p === -1) {
|
||||
p = rowTokens.length-1;
|
||||
}
|
||||
while (p > -1) {
|
||||
var type = rowTokens[p].type;
|
||||
if (next) {
|
||||
if (type === 'keyword') {
|
||||
scopedFunction = rowTokens[p];
|
||||
// console.log("HIT",scopedFunction);
|
||||
break;
|
||||
}
|
||||
next = false;
|
||||
}
|
||||
if (type === 'paren.lparen') {
|
||||
depth-=rowTokens[p].value.length;
|
||||
} else if (type === 'paren.rparen') {
|
||||
depth+=rowTokens[p].value.length;
|
||||
}
|
||||
if (depth < 0) {
|
||||
next = true;
|
||||
depth = 0;
|
||||
}
|
||||
// console.log(r,p,depth,next,rowTokens[p]);
|
||||
p--;
|
||||
}
|
||||
if (!scopedFunction) {
|
||||
r--;
|
||||
}
|
||||
}
|
||||
}
|
||||
expressionEditor.session.removeMarker(currentFunctionMarker);
|
||||
if (scopedFunction) {
|
||||
//console.log(token,.map(function(t) { return t.type}));
|
||||
funcSelect.val(scopedFunction.value).change();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialogForm.i18n();
|
||||
$("#node-input-expression-func-insert").click(function(e) {
|
||||
e.preventDefault();
|
||||
var pos = expressionEditor.getCursorPosition();
|
||||
var f = funcSelect.val();
|
||||
var snippet = jsonata.getFunctionSnippet(f);
|
||||
expressionEditor.insertSnippet(snippet);
|
||||
expressionEditor.focus();
|
||||
});
|
||||
$("#node-input-expression-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = expressionEditor.getValue()||"";
|
||||
try {
|
||||
v = jsonata.format(v);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
|
||||
var tabs = RED.tabs.create({
|
||||
element: $("#node-input-expression-tabs"),
|
||||
onchange:function(tab) {
|
||||
$(".node-input-expression-tab-content").hide();
|
||||
tab.content.show();
|
||||
trayOptions.resize();
|
||||
}
|
||||
})
|
||||
|
||||
tabs.addTab({
|
||||
id: 'expression-help',
|
||||
label: RED._('expressionEditor.functionReference'),
|
||||
content: $("#node-input-expression-tab-help")
|
||||
});
|
||||
tabs.addTab({
|
||||
id: 'expression-tests',
|
||||
label: RED._('expressionEditor.test'),
|
||||
content: $("#node-input-expression-tab-test")
|
||||
});
|
||||
testDataEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-data',
|
||||
value: expressionTestCache[expressionTestCacheId] || '{\n "payload": "hello world"\n}',
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false
|
||||
});
|
||||
var changeTimer;
|
||||
$(".node-input-expression-legacy").click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("expressionEditor.compatModeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
})
|
||||
var testExpression = function() {
|
||||
var value = testDataEditor.getValue();
|
||||
var parsedData;
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".node-input-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
expr = jsonata(currentExpression);
|
||||
expr.assign('flowContext',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign('globalContext',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
parsedData = JSON.parse(value);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-msg",{message:err.toString()}))
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var result = expr.evaluate(legacyMode?{msg:parsedData}:parsedData);
|
||||
if (usesContext) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
|
||||
var formattedResult;
|
||||
if (result !== undefined) {
|
||||
formattedResult = JSON.stringify(result,null,4);
|
||||
} else {
|
||||
formattedResult = RED._("expressionEditor.noMatch");
|
||||
}
|
||||
testResultEditor.setValue(formattedResult,-1);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.eval",{message:err.message}),-1);
|
||||
}
|
||||
}
|
||||
|
||||
testDataEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
expressionTestCache[expressionTestCacheId] = testDataEditor.getValue();
|
||||
});
|
||||
expressionEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
});
|
||||
|
||||
testResultEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-result',
|
||||
value: "",
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false,
|
||||
readOnly: true
|
||||
});
|
||||
panels = RED.panels.create({
|
||||
id:"node-input-expression-panels",
|
||||
resize: function(p1Height,p2Height) {
|
||||
var p1 = $("#node-input-expression-panel-expr");
|
||||
p1Height -= $(p1.children()[0]).outerHeight(true);
|
||||
var editorRow = $(p1.children()[1]);
|
||||
p1Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-expression").css("height",(p1Height-5)+"px");
|
||||
expressionEditor.resize();
|
||||
|
||||
var p2 = $("#node-input-expression-panel-info > .form-row > div:first-child");
|
||||
p2Height -= p2.outerHeight(true) + 20;
|
||||
$(".node-input-expression-tab-content").height(p2Height);
|
||||
$("#node-input-expression-test-data").css("height",(p2Height-5)+"px");
|
||||
testDataEditor.resize();
|
||||
$("#node-input-expression-test-result").css("height",(p2Height-5)+"px");
|
||||
testResultEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
$("#node-input-example-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = testDataEditor.getValue()||"";
|
||||
try {
|
||||
v = JSON.stringify(JSON.parse(v),null,4);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
testDataEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
|
||||
testExpression();
|
||||
},
|
||||
close: function() {
|
||||
options.title = options.title || getEditStackTitle();
|
||||
options.onclose = function() {
|
||||
editStack.pop();
|
||||
expressionEditor.destroy();
|
||||
testDataEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
|
||||
function editJSON(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_json"
|
||||
editStack.push({type:type});
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var changeTimer;
|
||||
|
||||
var checkValid = function() {
|
||||
var v = expressionEditor.getValue();
|
||||
try {
|
||||
JSON.parse(v);
|
||||
$("#node-dialog-ok").removeClass('disabled');
|
||||
return true;
|
||||
} catch(err) {
|
||||
$("#node-dialog-ok").addClass('disabled');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var trayOptions = {
|
||||
title: options.title || getEditStackTitle(),
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
if (options.requireValid && !checkValid()) {
|
||||
return;
|
||||
}
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
editTrayWidthCache[type] = dimensions.width;
|
||||
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-json',
|
||||
value: "",
|
||||
mode:"ace/mode/json"
|
||||
});
|
||||
expressionEditor.getSession().setValue(value||"",-1);
|
||||
if (options.requireValid) {
|
||||
expressionEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(checkValid,200);
|
||||
});
|
||||
checkValid();
|
||||
}
|
||||
$("#node-input-json-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = expressionEditor.getValue()||"";
|
||||
try {
|
||||
v = JSON.stringify(JSON.parse(v),null,4);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
editStack.pop();
|
||||
expressionEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
function editMarkdown(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_markdown"
|
||||
editStack.push({type:type});
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title || getEditStackTitle(),
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
editTrayWidthCache[type] = dimensions.width;
|
||||
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-markdown',
|
||||
value: value,
|
||||
mode:"ace/mode/markdown"
|
||||
});
|
||||
if (options.header) {
|
||||
options.header.appendTo(tray.find('#node-input-markdown-title'));
|
||||
}
|
||||
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
editStack.pop();
|
||||
expressionEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
function stringToUTF8Array(str) {
|
||||
var data = [];
|
||||
var i=0, l = str.length;
|
||||
for (i=0; i<l; i++) {
|
||||
var char = str.charCodeAt(i);
|
||||
if (char < 0x80) {
|
||||
data.push(char);
|
||||
} else if (char < 0x800) {
|
||||
data.push(0xc0 | (char >> 6));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
} else if (char < 0xd800 || char >= 0xe000) {
|
||||
data.push(0xe0 | (char >> 12));
|
||||
data.push(0x80 | ((char>>6) & 0x3f));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
RED.editor.types[type].show(options);
|
||||
} else {
|
||||
i++;
|
||||
char = 0x10000 + (((char & 0x3ff)<<10) | (str.charAt(i) & 0x3ff));
|
||||
data.push(0xf0 | (char >>18));
|
||||
data.push(0x80 | ((char>>12) & 0x3f));
|
||||
data.push(0x80 | ((char>>6) & 0x3f));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
console.log("Unknown type editor:",type);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function editBuffer(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_buffer"
|
||||
editStack.push({type:type});
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var bufferStringEditor = [];
|
||||
var bufferBinValue;
|
||||
|
||||
var panels;
|
||||
|
||||
var trayOptions = {
|
||||
title: getEditStackTitle(),
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
onComplete(JSON.stringify(bufferBinValue));
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
if (dimensions) {
|
||||
editTrayWidthCache[type] = dimensions.width;
|
||||
}
|
||||
var height = $("#dialog-form").height();
|
||||
if (panels) {
|
||||
panels.resize(height);
|
||||
}
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
|
||||
bufferStringEditor = RED.editor.createEditor({
|
||||
id: 'node-input-buffer-str',
|
||||
value: "",
|
||||
mode:"ace/mode/text"
|
||||
});
|
||||
bufferStringEditor.getSession().setValue(value||"",-1);
|
||||
|
||||
bufferBinEditor = RED.editor.createEditor({
|
||||
id: 'node-input-buffer-bin',
|
||||
value: "",
|
||||
mode:"ace/mode/text",
|
||||
readOnly: true
|
||||
});
|
||||
|
||||
var changeTimer;
|
||||
var buildBuffer = function(data) {
|
||||
var valid = true;
|
||||
var isString = typeof data === 'string';
|
||||
var binBuffer = [];
|
||||
if (isString) {
|
||||
bufferBinValue = stringToUTF8Array(data);
|
||||
} else {
|
||||
bufferBinValue = data;
|
||||
}
|
||||
var i=0,l=bufferBinValue.length;
|
||||
var c = 0;
|
||||
for(i=0;i<l;i++) {
|
||||
var d = parseInt(bufferBinValue[i]);
|
||||
if (!isString && (isNaN(d) || d < 0 || d > 255)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (i>0) {
|
||||
if (i%8 === 0) {
|
||||
if (i%16 === 0) {
|
||||
binBuffer.push("\n");
|
||||
} else {
|
||||
binBuffer.push(" ");
|
||||
}
|
||||
} else {
|
||||
binBuffer.push(" ");
|
||||
}
|
||||
}
|
||||
binBuffer.push((d<16?"0":"")+d.toString(16).toUpperCase());
|
||||
}
|
||||
if (valid) {
|
||||
$("#node-input-buffer-type-string").toggle(isString);
|
||||
$("#node-input-buffer-type-array").toggle(!isString);
|
||||
bufferBinEditor.setValue(binBuffer.join(""),1);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
var bufferStringUpdate = function() {
|
||||
var value = bufferStringEditor.getValue();
|
||||
var isValidArray = false;
|
||||
if (/^[\s]*\[[\s\S]*\][\s]*$/.test(value)) {
|
||||
isValidArray = true;
|
||||
try {
|
||||
var data = JSON.parse(value);
|
||||
isValidArray = buildBuffer(data);
|
||||
} catch(err) {
|
||||
isValidArray = false;
|
||||
}
|
||||
}
|
||||
if (!isValidArray) {
|
||||
buildBuffer(value);
|
||||
}
|
||||
|
||||
}
|
||||
bufferStringEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(bufferStringUpdate,200);
|
||||
});
|
||||
|
||||
bufferStringUpdate();
|
||||
|
||||
dialogForm.i18n();
|
||||
|
||||
panels = RED.panels.create({
|
||||
id:"node-input-buffer-panels",
|
||||
resize: function(p1Height,p2Height) {
|
||||
var p1 = $("#node-input-buffer-panel-str");
|
||||
p1Height -= $(p1.children()[0]).outerHeight(true);
|
||||
var editorRow = $(p1.children()[1]);
|
||||
p1Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-buffer-str").css("height",(p1Height-5)+"px");
|
||||
bufferStringEditor.resize();
|
||||
|
||||
var p2 = $("#node-input-buffer-panel-bin");
|
||||
editorRow = $(p2.children()[0]);
|
||||
p2Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-buffer-bin").css("height",(p2Height-5)+"px");
|
||||
bufferBinEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
$(".node-input-buffer-type").click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("bufferEditor.modeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
close: function() {
|
||||
editStack.pop();
|
||||
bufferStringEditor.destroy();
|
||||
bufferBinEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
@ -2482,14 +1846,22 @@ RED.editor = (function() {
|
||||
$("#node-dialog-cancel").click();
|
||||
$("#node-config-dialog-cancel").click();
|
||||
});
|
||||
|
||||
for (var type in RED.editor.types) {
|
||||
if (RED.editor.types.hasOwnProperty(type)) {
|
||||
RED.editor.types[type].init();
|
||||
}
|
||||
}
|
||||
},
|
||||
types: {},
|
||||
edit: showEditDialog,
|
||||
editConfig: showEditConfigNodeDialog,
|
||||
editSubflow: showEditSubflowDialog,
|
||||
editExpression: editExpression,
|
||||
editJSON: editJSON,
|
||||
editMarkdown: editMarkdown,
|
||||
editBuffer: editBuffer,
|
||||
editExpression: function(options) { showTypeEditor("_expression", options) },
|
||||
editJSON: function(options) { showTypeEditor("_json", options) },
|
||||
editMarkdown: function(options) { showTypeEditor("_markdown", options) },
|
||||
editBuffer: function(options) { showTypeEditor("_buffer", options) },
|
||||
buildEditForm: buildEditForm,
|
||||
validateNode: validateNode,
|
||||
updateNodeProperties: updateNodeProperties, // TODO: only exposed for edit-undo
|
||||
|
||||
|
209
editor/js/ui/editors/buffer.js
Normal file
209
editor/js/ui/editors/buffer.js
Normal file
@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.editor.types._buffer = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_buffer"><div id="node-input-buffer-panels"><div id="node-input-buffer-panel-str" class="red-ui-panel"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><span class="node-input-buffer-type"><i class="fa fa-exclamation-circle"></i> <span id="node-input-buffer-type-string" data-i18n="bufferEditor.modeString"></span><span id="node-input-buffer-type-array" data-i18n="bufferEditor.modeArray"></span></span></div><div class="form-row node-text-editor-row"><div class="node-text-editor" id="node-input-buffer-str"></div></div></div><div id="node-input-buffer-panel-bin" class="red-ui-panel"><div class="form-row node-text-editor-row" style="margin-top: 10px"><div class="node-text-editor" id="node-input-buffer-bin"></div></div></div></div></script>';
|
||||
|
||||
function stringToUTF8Array(str) {
|
||||
var data = [];
|
||||
var i=0, l = str.length;
|
||||
for (i=0; i<l; i++) {
|
||||
var char = str.charCodeAt(i);
|
||||
if (char < 0x80) {
|
||||
data.push(char);
|
||||
} else if (char < 0x800) {
|
||||
data.push(0xc0 | (char >> 6));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
} else if (char < 0xd800 || char >= 0xe000) {
|
||||
data.push(0xe0 | (char >> 12));
|
||||
data.push(0x80 | ((char>>6) & 0x3f));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
} else {
|
||||
i++;
|
||||
char = 0x10000 + (((char & 0x3ff)<<10) | (str.charAt(i) & 0x3ff));
|
||||
data.push(0xf0 | (char >>18));
|
||||
data.push(0x80 | ((char>>12) & 0x3f));
|
||||
data.push(0x80 | ((char>>6) & 0x3f));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_buffer"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var bufferStringEditor = [];
|
||||
var bufferBinValue;
|
||||
|
||||
var panels;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
onComplete(JSON.stringify(bufferBinValue));
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var height = $("#dialog-form").height();
|
||||
if (panels) {
|
||||
panels.resize(height);
|
||||
}
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
|
||||
bufferStringEditor = RED.editor.createEditor({
|
||||
id: 'node-input-buffer-str',
|
||||
value: "",
|
||||
mode:"ace/mode/text"
|
||||
});
|
||||
bufferStringEditor.getSession().setValue(value||"",-1);
|
||||
|
||||
bufferBinEditor = RED.editor.createEditor({
|
||||
id: 'node-input-buffer-bin',
|
||||
value: "",
|
||||
mode:"ace/mode/text",
|
||||
readOnly: true
|
||||
});
|
||||
|
||||
var changeTimer;
|
||||
var buildBuffer = function(data) {
|
||||
var valid = true;
|
||||
var isString = typeof data === 'string';
|
||||
var binBuffer = [];
|
||||
if (isString) {
|
||||
bufferBinValue = stringToUTF8Array(data);
|
||||
} else {
|
||||
bufferBinValue = data;
|
||||
}
|
||||
var i=0,l=bufferBinValue.length;
|
||||
var c = 0;
|
||||
for(i=0;i<l;i++) {
|
||||
var d = parseInt(bufferBinValue[i]);
|
||||
if (!isString && (isNaN(d) || d < 0 || d > 255)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (i>0) {
|
||||
if (i%8 === 0) {
|
||||
if (i%16 === 0) {
|
||||
binBuffer.push("\n");
|
||||
} else {
|
||||
binBuffer.push(" ");
|
||||
}
|
||||
} else {
|
||||
binBuffer.push(" ");
|
||||
}
|
||||
}
|
||||
binBuffer.push((d<16?"0":"")+d.toString(16).toUpperCase());
|
||||
}
|
||||
if (valid) {
|
||||
$("#node-input-buffer-type-string").toggle(isString);
|
||||
$("#node-input-buffer-type-array").toggle(!isString);
|
||||
bufferBinEditor.setValue(binBuffer.join(""),1);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
var bufferStringUpdate = function() {
|
||||
var value = bufferStringEditor.getValue();
|
||||
var isValidArray = false;
|
||||
if (/^[\s]*\[[\s\S]*\][\s]*$/.test(value)) {
|
||||
isValidArray = true;
|
||||
try {
|
||||
var data = JSON.parse(value);
|
||||
isValidArray = buildBuffer(data);
|
||||
} catch(err) {
|
||||
isValidArray = false;
|
||||
}
|
||||
}
|
||||
if (!isValidArray) {
|
||||
buildBuffer(value);
|
||||
}
|
||||
|
||||
}
|
||||
bufferStringEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(bufferStringUpdate,200);
|
||||
});
|
||||
|
||||
bufferStringUpdate();
|
||||
|
||||
dialogForm.i18n();
|
||||
|
||||
panels = RED.panels.create({
|
||||
id:"node-input-buffer-panels",
|
||||
resize: function(p1Height,p2Height) {
|
||||
var p1 = $("#node-input-buffer-panel-str");
|
||||
p1Height -= $(p1.children()[0]).outerHeight(true);
|
||||
var editorRow = $(p1.children()[1]);
|
||||
p1Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-buffer-str").css("height",(p1Height-5)+"px");
|
||||
bufferStringEditor.resize();
|
||||
|
||||
var p2 = $("#node-input-buffer-panel-bin");
|
||||
editorRow = $(p2.children()[0]);
|
||||
p2Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-buffer-bin").css("height",(p2Height-5)+"px");
|
||||
bufferBinEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
$(".node-input-buffer-type").click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("bufferEditor.modeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
close: function() {
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
bufferStringEditor.destroy();
|
||||
bufferBinEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
}
|
||||
})();
|
325
editor/js/ui/editors/expression.js
Normal file
325
editor/js/ui/editors/expression.js
Normal file
@ -0,0 +1,325 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.editor.types._expression = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_expression"><div id="node-input-expression-panels"><div id="node-input-expression-panel-expr" class="red-ui-panel"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><span class="node-input-expression-legacy"><i class="fa fa-exclamation-circle"></i> <span data-i18n="expressionEditor.compatMode"></span></span><button id="node-input-expression-reformat" class="editor-button editor-button-small"><span data-i18n="expressionEditor.format"></span></button></div><div class="form-row node-text-editor-row"><div class="node-text-editor" id="node-input-expression"></div></div></div><div id="node-input-expression-panel-info" class="red-ui-panel"><div class="form-row"><ul id="node-input-expression-tabs"></ul><div id="node-input-expression-tab-help" class="node-input-expression-tab-content hide"><div><select id="node-input-expression-func"></select><button id="node-input-expression-func-insert" class="editor-button" data-i18n="expressionEditor.insert"></button></div><div id="node-input-expression-help"></div></div><div id="node-input-expression-tab-test" class="node-input-expression-tab-content hide"><div><span style="display: inline-block; width: calc(50% - 5px);"><span data-i18n="expressionEditor.data"></span><button style="float: right; margin-right: 5px;" id="node-input-example-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button></span><span style="display: inline-block; width: calc(50% - 5px);" data-i18n="expressionEditor.result"></span></div><div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-data"></div><div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-result"></div></div></div></div></div></script>';
|
||||
var expressionTestCache = {};
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var expressionTestCacheId = options.parent||"_";
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_expression"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var testDataEditor;
|
||||
var testResultEditor
|
||||
var panels;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
$("#node-input-expression-help").html("");
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var height = $("#dialog-form").height();
|
||||
if (panels) {
|
||||
panels.resize(height);
|
||||
}
|
||||
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
trayBody.addClass("node-input-expression-editor")
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form','_expression','editor');
|
||||
var funcSelect = $("#node-input-expression-func");
|
||||
Object.keys(jsonata.functions).forEach(function(f) {
|
||||
funcSelect.append($("<option></option>").val(f).text(f));
|
||||
})
|
||||
funcSelect.change(function(e) {
|
||||
var f = $(this).val();
|
||||
var args = RED._('jsonata:'+f+".args",{defaultValue:''});
|
||||
var title = "<h5>"+f+"("+args+")</h5>";
|
||||
var body = marked(RED._('jsonata:'+f+'.desc',{defaultValue:''}));
|
||||
$("#node-input-expression-help").html(title+"<p>"+body+"</p>");
|
||||
|
||||
})
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression',
|
||||
value: "",
|
||||
mode:"ace/mode/jsonata",
|
||||
options: {
|
||||
enableBasicAutocompletion:true,
|
||||
enableSnippets:true,
|
||||
enableLiveAutocompletion: true
|
||||
}
|
||||
});
|
||||
var currentToken = null;
|
||||
var currentTokenPos = -1;
|
||||
var currentFunctionMarker = null;
|
||||
|
||||
expressionEditor.getSession().setValue(value||"",-1);
|
||||
expressionEditor.on("changeSelection", function() {
|
||||
var c = expressionEditor.getCursorPosition();
|
||||
var token = expressionEditor.getSession().getTokenAt(c.row,c.column);
|
||||
if (token !== currentToken || (token && /paren/.test(token.type) && c.column !== currentTokenPos)) {
|
||||
currentToken = token;
|
||||
var r,p;
|
||||
var scopedFunction = null;
|
||||
if (token && token.type === 'keyword') {
|
||||
r = c.row;
|
||||
scopedFunction = token;
|
||||
} else {
|
||||
var depth = 0;
|
||||
var next = false;
|
||||
if (token) {
|
||||
if (token.type === 'paren.rparen') {
|
||||
// If this is a block of parens ')))', set
|
||||
// depth to offset against the cursor position
|
||||
// within the block
|
||||
currentTokenPos = c.column;
|
||||
depth = c.column - (token.start + token.value.length);
|
||||
}
|
||||
r = c.row;
|
||||
p = token.index;
|
||||
} else {
|
||||
r = c.row-1;
|
||||
p = -1;
|
||||
}
|
||||
while ( scopedFunction === null && r > -1) {
|
||||
var rowTokens = expressionEditor.getSession().getTokens(r);
|
||||
if (p === -1) {
|
||||
p = rowTokens.length-1;
|
||||
}
|
||||
while (p > -1) {
|
||||
var type = rowTokens[p].type;
|
||||
if (next) {
|
||||
if (type === 'keyword') {
|
||||
scopedFunction = rowTokens[p];
|
||||
// console.log("HIT",scopedFunction);
|
||||
break;
|
||||
}
|
||||
next = false;
|
||||
}
|
||||
if (type === 'paren.lparen') {
|
||||
depth-=rowTokens[p].value.length;
|
||||
} else if (type === 'paren.rparen') {
|
||||
depth+=rowTokens[p].value.length;
|
||||
}
|
||||
if (depth < 0) {
|
||||
next = true;
|
||||
depth = 0;
|
||||
}
|
||||
// console.log(r,p,depth,next,rowTokens[p]);
|
||||
p--;
|
||||
}
|
||||
if (!scopedFunction) {
|
||||
r--;
|
||||
}
|
||||
}
|
||||
}
|
||||
expressionEditor.session.removeMarker(currentFunctionMarker);
|
||||
if (scopedFunction) {
|
||||
//console.log(token,.map(function(t) { return t.type}));
|
||||
funcSelect.val(scopedFunction.value).change();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialogForm.i18n();
|
||||
$("#node-input-expression-func-insert").click(function(e) {
|
||||
e.preventDefault();
|
||||
var pos = expressionEditor.getCursorPosition();
|
||||
var f = funcSelect.val();
|
||||
var snippet = jsonata.getFunctionSnippet(f);
|
||||
expressionEditor.insertSnippet(snippet);
|
||||
expressionEditor.focus();
|
||||
});
|
||||
$("#node-input-expression-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = expressionEditor.getValue()||"";
|
||||
try {
|
||||
v = jsonata.format(v);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
|
||||
var tabs = RED.tabs.create({
|
||||
element: $("#node-input-expression-tabs"),
|
||||
onchange:function(tab) {
|
||||
$(".node-input-expression-tab-content").hide();
|
||||
tab.content.show();
|
||||
trayOptions.resize();
|
||||
}
|
||||
})
|
||||
|
||||
tabs.addTab({
|
||||
id: 'expression-help',
|
||||
label: RED._('expressionEditor.functionReference'),
|
||||
content: $("#node-input-expression-tab-help")
|
||||
});
|
||||
tabs.addTab({
|
||||
id: 'expression-tests',
|
||||
label: RED._('expressionEditor.test'),
|
||||
content: $("#node-input-expression-tab-test")
|
||||
});
|
||||
testDataEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-data',
|
||||
value: expressionTestCache[expressionTestCacheId] || '{\n "payload": "hello world"\n}',
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false
|
||||
});
|
||||
var changeTimer;
|
||||
$(".node-input-expression-legacy").click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("expressionEditor.compatModeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
})
|
||||
var testExpression = function() {
|
||||
var value = testDataEditor.getValue();
|
||||
var parsedData;
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".node-input-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
expr = jsonata(currentExpression);
|
||||
expr.assign('flowContext',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign('globalContext',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
parsedData = JSON.parse(value);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-msg",{message:err.toString()}))
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var result = expr.evaluate(legacyMode?{msg:parsedData}:parsedData);
|
||||
if (usesContext) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
|
||||
var formattedResult;
|
||||
if (result !== undefined) {
|
||||
formattedResult = JSON.stringify(result,null,4);
|
||||
} else {
|
||||
formattedResult = RED._("expressionEditor.noMatch");
|
||||
}
|
||||
testResultEditor.setValue(formattedResult,-1);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.eval",{message:err.message}),-1);
|
||||
}
|
||||
}
|
||||
|
||||
testDataEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
expressionTestCache[expressionTestCacheId] = testDataEditor.getValue();
|
||||
});
|
||||
expressionEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
});
|
||||
|
||||
testResultEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-result',
|
||||
value: "",
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false,
|
||||
readOnly: true
|
||||
});
|
||||
panels = RED.panels.create({
|
||||
id:"node-input-expression-panels",
|
||||
resize: function(p1Height,p2Height) {
|
||||
var p1 = $("#node-input-expression-panel-expr");
|
||||
p1Height -= $(p1.children()[0]).outerHeight(true);
|
||||
var editorRow = $(p1.children()[1]);
|
||||
p1Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-expression").css("height",(p1Height-5)+"px");
|
||||
expressionEditor.resize();
|
||||
|
||||
var p2 = $("#node-input-expression-panel-info > .form-row > div:first-child");
|
||||
p2Height -= p2.outerHeight(true) + 20;
|
||||
$(".node-input-expression-tab-content").height(p2Height);
|
||||
$("#node-input-expression-test-data").css("height",(p2Height-5)+"px");
|
||||
testDataEditor.resize();
|
||||
$("#node-input-expression-test-result").css("height",(p2Height-5)+"px");
|
||||
testResultEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
$("#node-input-example-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = testDataEditor.getValue()||"";
|
||||
try {
|
||||
v = JSON.stringify(JSON.parse(v),null,4);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
testDataEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
|
||||
testExpression();
|
||||
},
|
||||
close: function() {
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
expressionEditor.destroy();
|
||||
testDataEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
}
|
||||
})();
|
118
editor/js/ui/editors/json.js
Normal file
118
editor/js/ui/editors/json.js
Normal file
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.editor.types._json = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_json"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><button id="node-input-json-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button></div><div class="form-row node-text-editor-row"><div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div></div></script>';
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_json"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var changeTimer;
|
||||
|
||||
var checkValid = function() {
|
||||
var v = expressionEditor.getValue();
|
||||
try {
|
||||
JSON.parse(v);
|
||||
$("#node-dialog-ok").removeClass('disabled');
|
||||
return true;
|
||||
} catch(err) {
|
||||
$("#node-dialog-ok").addClass('disabled');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
if (options.requireValid && !checkValid()) {
|
||||
return;
|
||||
}
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-json',
|
||||
value: "",
|
||||
mode:"ace/mode/json"
|
||||
});
|
||||
expressionEditor.getSession().setValue(value||"",-1);
|
||||
if (options.requireValid) {
|
||||
expressionEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(checkValid,200);
|
||||
});
|
||||
checkValid();
|
||||
}
|
||||
$("#node-input-json-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = expressionEditor.getValue()||"";
|
||||
try {
|
||||
v = JSON.stringify(JSON.parse(v),null,4);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
expressionEditor.destroy();
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
}
|
||||
})();
|
90
editor/js/ui/editors/markdown.js
Normal file
90
editor/js/ui/editors/markdown.js
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.editor.types._markdown = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_markdown"><div class="form-row" id="node-input-markdown-title" style="margin-bottom: 3px; text-align: right;"></div><div class="form-row node-text-editor-row"><div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-markdown"></div></div></script>';
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_markdown"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-markdown',
|
||||
value: value,
|
||||
mode:"ace/mode/markdown"
|
||||
});
|
||||
if (options.header) {
|
||||
options.header.appendTo(tray.find('#node-input-markdown-title'));
|
||||
}
|
||||
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
expressionEditor.destroy();
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
|
||||
}
|
||||
}
|
||||
})();
|
@ -18,6 +18,12 @@ RED.library = (function() {
|
||||
var exportToLibraryDialog;
|
||||
var elementPrefix = "node-input-";
|
||||
|
||||
|
||||
var _librarySaveConfirm = '<div id="node-dialog-library-save-confirm" class="hide"><form class="form-horizontal"><div style="text-align: center; padding-top: 30px;" id="node-dialog-library-save-content"></div></form></div>';
|
||||
var _librarySave = '<div id="node-dialog-library-save" class="hide"><form class="form-horizontal"><div class="form-row"><label for="node-dialog-library-save-folder" data-i18n="[append]library.folder"><i class="fa fa-folder-open"></i> </label><input type="text" id="node-dialog-library-save-folder" data-i18n="[placeholder]library.folderPlaceholder"></div><div class="form-row"><label for="node-dialog-library-save-filename" data-i18n="[append]library.filename"><i class="fa fa-file"></i> </label><input type="text" id="node-dialog-library-save-filename" data-i18n="[placeholder]library.filenamePlaceholder"></div></form></div>';
|
||||
var _libraryLookup = '<div id="node-dialog-library-lookup" class="hide"><form class="form-horizontal"><div class="form-row"><ul id="node-dialog-library-breadcrumbs" class="breadcrumb"><li class="active"><a href="#" data-i18n="[append]library.breadcrumb"></a></li></ul></div><div class="form-row"><div style="vertical-align: top; display: inline-block; height: 100%; width: 30%; padding-right: 20px;"><div id="node-select-library" style="border: 1px solid #999; width: 100%; height: 100%; overflow:scroll;"><ul></ul></div></div><div style="vertical-align: top; display: inline-block;width: 65%; height: 100%;"><div style="height: 100%; width: 95%;" class="node-text-editor" id="node-select-library-text" ></div></div></div></form></div>';
|
||||
|
||||
|
||||
function loadFlowLibrary() {
|
||||
$.getJSON("library/flows",function(data) {
|
||||
//console.log(data);
|
||||
@ -410,6 +416,11 @@ RED.library = (function() {
|
||||
return {
|
||||
init: function() {
|
||||
|
||||
|
||||
$(_librarySave).appendTo(document.body);
|
||||
$(_librarySaveConfirm).appendTo(document.body);
|
||||
$(_libraryLookup).appendTo(document.body);
|
||||
|
||||
RED.actions.add("core:library-export",exportFlow);
|
||||
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
|
@ -17,6 +17,10 @@
|
||||
RED.subflow = (function() {
|
||||
|
||||
|
||||
var _subflowEditTemplate = '<script type="text/x-red" data-template-name="subflow"><div class="form-row"><label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label><input type="text" id="node-input-name"></div></script>';
|
||||
var _subflowTemplateEditTemplate = '<script type="text/x-red" data-template-name="subflow-template"><div class="form-row"><i class="fa fa-tag"></i><label for="subflow-input-name" data-i18n="common.label.name"></label><input type="text" id="subflow-input-name"></div><div class="form-row" style="margin-bottom: 0px;"><label for="subflow-input-info" data-i18n="editor:subflow.info"></label><a href="https://help.github.com/articles/markdown-basics/" style="font-size: 0.8em; float: right;" data-i18n="[html]subflow.format"></a></div><div class="form-row node-text-editor-row"><div style="height: 250px;" class="node-text-editor" id="subflow-input-info-editor"></div></div><div class="form-row form-tips" id="subflow-dialog-user-count"></div></script>';
|
||||
|
||||
|
||||
function getSubflow() {
|
||||
return RED.nodes.subflow(RED.workspaces.active());
|
||||
}
|
||||
@ -386,6 +390,10 @@ RED.subflow = (function() {
|
||||
|
||||
RED.actions.add("core:create-subflow",createSubflow);
|
||||
RED.actions.add("core:convert-to-subflow",convertToSubflow);
|
||||
|
||||
$(_subflowEditTemplate).appendTo(document.body);
|
||||
$(_subflowTemplateEditTemplate).appendTo(document.body);
|
||||
|
||||
}
|
||||
|
||||
function createSubflow() {
|
||||
|
@ -82,134 +82,6 @@
|
||||
<div id="notifications"></div>
|
||||
<div id="dropTarget"><div data-i18n="[append]workspace.dropFlowHere"><br/><i class="fa fa-download"></i></div></div>
|
||||
|
||||
<div id="node-dialog-library-save-confirm" class="hide">
|
||||
<form class="form-horizontal">
|
||||
<div style="text-align: center; padding-top: 30px;" id="node-dialog-library-save-content">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="node-dialog-library-save" class="hide">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-row">
|
||||
<label for="node-dialog-library-save-folder" data-i18n="[append]library.folder"><i class="fa fa-folder-open"></i> </label>
|
||||
<input type="text" id="node-dialog-library-save-folder" data-i18n="[placeholder]library.folderPlaceholder">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-dialog-library-save-filename" data-i18n="[append]library.filename"><i class="fa fa-file"></i> </label>
|
||||
<input type="text" id="node-dialog-library-save-filename" data-i18n="[placeholder]library.filenamePlaceholder">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="node-dialog-library-lookup" class="hide">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-row">
|
||||
<ul id="node-dialog-library-breadcrumbs" class="breadcrumb">
|
||||
<li class="active"><a href="#" data-i18n="[append]library.breadcrumb"></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div style="vertical-align: top; display: inline-block; height: 100%; width: 30%; padding-right: 20px;">
|
||||
<div id="node-select-library" style="border: 1px solid #999; width: 100%; height: 100%; overflow:scroll;"><ul></ul></div>
|
||||
</div>
|
||||
<div style="vertical-align: top; display: inline-block;width: 65%; height: 100%;">
|
||||
<div style="height: 100%; width: 95%;" class="node-text-editor" id="node-select-library-text" ></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<script type="text/x-red" data-template-name="subflow">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>
|
||||
<input type="text" id="node-input-name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="subflow-template">
|
||||
<div class="form-row">
|
||||
<i class="fa fa-tag"></i>
|
||||
<label for="subflow-input-name" data-i18n="common.label.name"></label><input type="text" id="subflow-input-name">
|
||||
</div>
|
||||
<div class="form-row" style="margin-bottom: 0px;">
|
||||
<label for="subflow-input-info" data-i18n="editor:subflow.info"></label>
|
||||
<a href="https://help.github.com/articles/markdown-basics/" style="font-size: 0.8em; float: right;" data-i18n="[html]subflow.format"></a>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 250px;" class="node-text-editor" id="subflow-input-info-editor"></div>
|
||||
</div>
|
||||
<div class="form-row form-tips" id="subflow-dialog-user-count"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="_expression">
|
||||
<div id="node-input-expression-panels">
|
||||
<div id="node-input-expression-panel-expr" class="red-ui-panel">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<span class="node-input-expression-legacy"><i class="fa fa-exclamation-circle"></i> <span data-i18n="expressionEditor.compatMode"></span></span>
|
||||
<button id="node-input-expression-reformat" class="editor-button editor-button-small"><span data-i18n="expressionEditor.format"></span></button>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div class="node-text-editor" id="node-input-expression"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="node-input-expression-panel-info" class="red-ui-panel">
|
||||
<div class="form-row">
|
||||
<ul id="node-input-expression-tabs"></ul>
|
||||
<div id="node-input-expression-tab-help" class="node-input-expression-tab-content hide">
|
||||
<div>
|
||||
<select id="node-input-expression-func"></select>
|
||||
<button id="node-input-expression-func-insert" class="editor-button" data-i18n="expressionEditor.insert"></button>
|
||||
</div>
|
||||
<div id="node-input-expression-help"></div>
|
||||
</div>
|
||||
<div id="node-input-expression-tab-test" class="node-input-expression-tab-content hide">
|
||||
<div>
|
||||
<span style="display: inline-block; width: calc(50% - 5px);">
|
||||
<span data-i18n="expressionEditor.data"></span>
|
||||
<button style="float: right; margin-right: 5px;" id="node-input-example-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button>
|
||||
</span>
|
||||
<span style="display: inline-block; width: calc(50% - 5px);" data-i18n="expressionEditor.result"></span>
|
||||
</div>
|
||||
<div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-data"></div>
|
||||
<div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-result"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/x-red" data-template-name="_json">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<button id="node-input-json-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/x-red" data-template-name="_markdown">
|
||||
<div class="form-row" id="node-input-markdown-title" style="margin-bottom: 3px; text-align: right;">
|
||||
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-markdown"></div>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/x-red" data-template-name="_buffer">
|
||||
<div id="node-input-buffer-panels">
|
||||
<div id="node-input-buffer-panel-str" class="red-ui-panel">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<span class="node-input-buffer-type"><i class="fa fa-exclamation-circle"></i> <span id="node-input-buffer-type-string" data-i18n="bufferEditor.modeString"></span><span id="node-input-buffer-type-array" data-i18n="bufferEditor.modeArray"></span></span>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div class="node-text-editor" id="node-input-buffer-str"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="node-input-buffer-panel-bin" class="red-ui-panel">
|
||||
<div class="form-row node-text-editor-row" style="margin-top: 10px">
|
||||
<div class="node-text-editor" id="node-input-buffer-bin"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script src="vendor/vendor.js"></script>
|
||||
<script src="vendor/jsonata/jsonata.min.js"></script>
|
||||
<script src="vendor/ace/ace.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user