1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add buffer mode to typedInput

This commit is contained in:
Nick O'Leary 2017-06-11 21:19:46 +01:00
parent d407f31ae5
commit d9dc171c28
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
11 changed files with 256 additions and 15 deletions

View File

@ -39,7 +39,6 @@ RED.panels = (function() {
var height = container.height(); var height = container.height();
startPosition = ui.position.top; startPosition = ui.position.top;
panelHeights = [$(children[0]).height(),$(children[1]).height()]; panelHeights = [$(children[0]).height(),$(children[1]).height()];
console.log("START",height,panelHeights,panelHeights[0]+panelHeights[1],height-(panelHeights[0]+panelHeights[1]));
}, },
drag: function(event,ui) { drag: function(event,ui) {
var height = container.height(); var height = container.height();
@ -68,7 +67,6 @@ RED.panels = (function() {
panelHeights = [topPanelHeight,bottomPanelHeight]; panelHeights = [topPanelHeight,bottomPanelHeight];
$(children[0]).height(panelHeights[0]); $(children[0]).height(panelHeights[0]);
$(children[1]).height(panelHeights[1]); $(children[1]).height(panelHeights[1]);
console.log("SET",height,panelHeights,panelHeights[0]+panelHeights[1],height-(panelHeights[0]+panelHeights[1]));
} }
if (options.resize) { if (options.resize) {
options.resize(panelHeights[0],panelHeights[1]); options.resize(panelHeights[0],panelHeights[1]);

View File

@ -62,6 +62,20 @@
} }
}) })
} }
},
bin: {
value: "bin",
label: "buffer",
icon: "red/images/typedInput/bin.png",
expand: function() {
var that = this;
RED.editor.editBuffer({
value: this.value(),
complete: function(v) {
that.value(v);
}
})
}
} }
}; };
var nlsd = false; var nlsd = false;

View File

@ -496,6 +496,8 @@ RED.editor = (function() {
label = RED._("expressionEditor.title"); label = RED._("expressionEditor.title");
} else if (node.type === '_json') { } else if (node.type === '_json') {
label = RED._("jsonEditor.title"); label = RED._("jsonEditor.title");
} else if (node.type === '_buffer') {
label = RED._("bufferEditor.title");
} else if (node.type === 'subflow') { } else if (node.type === 'subflow') {
label = RED._("subflow.editSubflow",{name:node.name}) label = RED._("subflow.editSubflow",{name:node.name})
} else if (node.type.indexOf("subflow:")===0) { } else if (node.type.indexOf("subflow:")===0) {
@ -1874,7 +1876,7 @@ RED.editor = (function() {
}); });
legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression); legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
} catch(err) { } catch(err) {
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message})); testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
return; return;
} }
$(".node-input-expression-legacy").toggle(legacyMode); $(".node-input-expression-legacy").toggle(legacyMode);
@ -1888,7 +1890,7 @@ RED.editor = (function() {
try { try {
var result = expr.evaluate(legacyMode?{msg:parsedData}:parsedData); var result = expr.evaluate(legacyMode?{msg:parsedData}:parsedData);
if (usesContext) { if (usesContext) {
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported")); testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
return; return;
} }
@ -1898,9 +1900,9 @@ RED.editor = (function() {
} else { } else {
formattedResult = RED._("expressionEditor.noMatch"); formattedResult = RED._("expressionEditor.noMatch");
} }
testResultEditor.setValue(formattedResult); testResultEditor.setValue(formattedResult,-1);
} catch(err) { } catch(err) {
testResultEditor.setValue(RED._("expressionEditor.errors.eval",{message:err.message})); testResultEditor.setValue(RED._("expressionEditor.errors.eval",{message:err.message}),-1);
} }
} }
@ -2028,6 +2030,191 @@ RED.editor = (function() {
RED.tray.show(trayOptions); 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));
} 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;
}
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(),
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();
},
show: function() {}
}
if (editTrayWidthCache.hasOwnProperty(type)) {
trayOptions.width = editTrayWidthCache[type];
}
RED.tray.show(trayOptions);
}
return { return {
init: function() { init: function() {
RED.tray.init(); RED.tray.init();
@ -2045,6 +2232,7 @@ RED.editor = (function() {
editSubflow: showEditSubflowDialog, editSubflow: showEditSubflowDialog,
editExpression: editExpression, editExpression: editExpression,
editJSON: editJSON, editJSON: editJSON,
editBuffer: editBuffer,
validateNode: validateNode, validateNode: validateNode,
updateNodeProperties: updateNodeProperties, // TODO: only exposed for edit-undo updateNodeProperties: updateNodeProperties, // TODO: only exposed for edit-undo
@ -2071,6 +2259,7 @@ RED.editor = (function() {
} }
if (options.readOnly) { if (options.readOnly) {
editor.setOption('readOnly',options.readOnly); editor.setOption('readOnly',options.readOnly);
editor.container.classList.add("ace_read-only");
} }
if (options.hasOwnProperty('lineNumbers')) { if (options.hasOwnProperty('lineNumbers')) {
editor.renderer.setOption('showGutter',options.lineNumbers); editor.renderer.setOption('showGutter',options.lineNumbers);

View File

@ -282,16 +282,21 @@
} }
} }
} }
.node-input-expression-legacy { .node-input-expression-legacy, .node-input-buffer-type {
font-size: 0.8em;
float: left; float: left;
cursor: pointer; cursor: pointer;
border: 1px solid white; border: 1px solid white;
padding: 0 5px; padding: 2px 5px;
border-radius: 2px; border-radius: 2px;
&:hover { &:hover {
border-color: $primary-border-color; border-color: $form-input-border-color;
} }
} }
.node-input-buffer-type {
float: none;
text-align: right;
}
#clipboard-hidden { #clipboard-hidden {
position: absolute; position: absolute;
@ -318,3 +323,11 @@
color: #999; color: #999;
} }
} }
.ace_read-only {
background: #eee !important;
.ace_cursor {
color: transparent !important;
}
}

View File

@ -35,7 +35,7 @@
} }
input { input {
width: 100%; width: 100%;
padding: 0 0 0 1px; padding: 0 0 0 3px;
margin:0; margin:0;
height: 32px; height: 32px;
border:none; border:none;

View File

@ -206,7 +206,23 @@
<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div> <div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>
</div> </div>
</script> </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/vendor.js"></script>
<script src="vendor/jsonata/jsonata.min.js"></script> <script src="vendor/jsonata/jsonata.min.js"></script>

View File

@ -256,7 +256,7 @@ If you want every 20 minutes from now - use the <i>"interval"</i> option.</p>
$("#node-input-payload").typedInput({ $("#node-input-payload").typedInput({
default: 'str', default: 'str',
typeField: $("#node-input-payloadType"), typeField: $("#node-input-payloadType"),
types:['flow','global','str','num','bool','json','date'] types:['flow','global','str','num','bool','json','bin','date']
}); });
$("#inject-time-type-select").change(function() { $("#inject-time-type-select").change(function() {

View File

@ -143,7 +143,7 @@
.appendTo(row2); .appendTo(row2);
var propertyValue = $('<input/>',{class:"node-input-rule-property-value",type:"text"}) var propertyValue = $('<input/>',{class:"node-input-rule-property-value",type:"text"})
.appendTo(row2) .appendTo(row2)
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','date','jsonata']}); .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata']});
var row3_1 = $('<div/>').appendTo(row3); var row3_1 = $('<div/>').appendTo(row3);
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"}) $('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
@ -159,7 +159,7 @@
.appendTo(row3_2); .appendTo(row3_2);
var toValue = $('<input/>',{class:"node-input-rule-property-replace-value",type:"text"}) var toValue = $('<input/>',{class:"node-input-rule-property-replace-value",type:"text"})
.appendTo(row3_2) .appendTo(row3_2)
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json']}); .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin']});
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"}) $('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
.text(to) .text(to)

View File

@ -76,7 +76,7 @@ module.exports = function(RED) {
} }
if (rule.tot === 'num') { if (rule.tot === 'num') {
rule.to = Number(rule.to); rule.to = Number(rule.to);
} else if (rule.tot === 'json') { } else if (rule.tot === 'json' || rule.tot === 'bin') {
try { try {
// check this is parsable JSON // check this is parsable JSON
JSON.parse(rule.to); JSON.parse(rule.to);
@ -102,6 +102,8 @@ module.exports = function(RED) {
var value = rule.to; var value = rule.to;
if (rule.tot === 'json') { if (rule.tot === 'json') {
value = JSON.parse(rule.to); value = JSON.parse(rule.to);
} else if (rule.tot === 'bin') {
value = Buffer.from(JSON.parse(rule.to))
} }
var current; var current;
var fromValue; var fromValue;

View File

@ -419,5 +419,11 @@
"jsonEditor": { "jsonEditor": {
"title": "JSON editor", "title": "JSON editor",
"format": "format JSON" "format": "format JSON"
},
"bufferEditor": {
"title": "Buffer editor",
"modeString": "Handle as UTF-8 String",
"modeArray": "Handle as JSON array",
"modeDesc":"<h3>Buffer editor</h3><p>The Buffer type is stored as a JSON array of byte values. The editor will attempt to parse the entered value as a JSON array. If it is not valid JSON, it will be treated as a UTF-8 String and converted to an array of the individual character code points.</p><p>For example, a value of <code>Hello World</code> will be converted to the JSON array:<pre>[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]</pre></p>"
} }
} }

View File

@ -314,6 +314,9 @@ function evaluateNodeProperty(value, type, node, msg) {
return new RegExp(value); return new RegExp(value);
} else if (type === 'date') { } else if (type === 'date') {
return Date.now(); return Date.now();
} else if (type === 'bin') {
var data = JSON.parse(value);
return Buffer.from(data);
} else if (type === 'msg' && msg) { } else if (type === 'msg' && msg) {
return getMessageProperty(msg,value); return getMessageProperty(msg,value);
} else if (type === 'flow' && node) { } else if (type === 'flow' && node) {