node-red-contrib-curve
Version:
Node to calculate output by a given mathematical function expression
208 lines (172 loc) • 6.06 kB
HTML
<!--
Copyright (c) 2017 Sebastian Barwe
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.
-->
<script type="text/javascript">
var fpoptions = {
target: '#function-plot-graph',
grid: true,
disableZoom: false,
xAxis: {
label: 'x',
domain: [0, 1]
},
yAxis: {
label: 'y = f(x)',
domain: [0, 1]
},
annotations: [{
x: 1,
text: 'x = 1'
}, {
y: 1,
text: 'y = 1'
}]
};
function plot() {
try {
functionPlot(fpoptions);
$('#function-plot-graph-message').text('');
}
catch (err) {
$('#function-plot-graph-message').text(err.message);
}
}
RED.nodes.registerType('curve', {
category: 'function', // Pallette category
defaults: {
fexpression: {
value: '', required: true, validate: function (f) {
try {
functionPlot.eval.builtIn({ fn: f.replace(/{{.*}}/, '1') }, 'fn', { x: 0 })
} catch (e) { return false; }
return true;
}
},
valuex: { value: '', required: false },
outputtype: { value: "float", required: false },
name: { value: '' },
topic: { value: '' }
},
inputs: 1,
outputs: 1,
color: '#E6E0F8',
paletteLabel: 'f(x) curve', // can be a function
label: function () { return this.name || this.fexpression || 'curve f(x)' }, // can be a string
inputLabels: 'number x', // string or function, NR v0.17+
outputLabels: function () { return 'f(x) = ' + this.fexpression }, // string or function, NR v0.17+
icon: "function.png", // stock icon, or use own in icons dir
oneditprepare: function () {
$("#node-input-valuex").typedInput({
default: "string",
types: [{
value: "string",
label: "msg"
}]
});
var node = this;
//fpoptions.plugins = [functionPlot.plugins.zoomBox()];
let f = this.fexpression.replace(/{{.*}}/, '1');
fpoptions.data = [{
fn: f != "" ? f : "0",
color: 'red',
graphType: 'polyline'
}];
plot();
var timerid;
var lastval;
var inputChange = function (value) {
if (lastval != value) {
lastval = value;
value = value.replace(/{{.*}}/, '1');
clearTimeout(timerid);
timerid = setTimeout(function () {
fpoptions.data = [{
fn: value != "" ? value : "0",
color: 'red',
graphType: 'polyline'
}];
plot();
}, 500);
};
};
$('#node-input-outputtype').select(this.outputtype);
this.editor = RED.editor.createEditor({
id: 'node-input-fexpression-editor',
mode: 'ace/mode/handlebars',
value: $("#node-input-fexpression").val(),
globals: {
msg: true,
flow: true,
global: true
}
});
this.editor.on("input", function () { inputChange(node.editor.getValue()) });
RED.library.create({
url: "curve", // where to get the data from
type: "node-red-contrib-curve", // the type of object the library is for
editor: this.editor,
mode: "ace/mode/handlebars",
fields: ['name']
});
},
oneditsave: function () {
$("#node-input-fexpression").val(this.editor.getValue());
delete this.editor;
},
oneditcancel: function () { delete this.editor; },
oneditdelete: function () { delete this.editor; },
oneditresize: function (size) {
fpoptions.width = 0.95 * size.width;
fpoptions.height = 0.40 * size.height;
plot();
},
onpaletteadd: function () {
$.getScript('node-red-contrib-curve/function-plot.min.js')
},
onpaletteremove: function () { },
});
</script>
<script type="text/x-red" data-template-name="curve">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name">
</div>
<div id="function-plot-graph" style="width:100%;">
</div>
<div id="function-plot-graph-message" style="width:100%; color:red; ">
</div>
<div class="form-row">
<label for="node-input-fexpression-editor"><i class="fa fa-industry"></i> <span data-i18n="curve.label.fexpression"></span></label>
<input type="text" id="node-input-fexpression" style="width:57%;" data-i18n="[placeholder]curve.placeholder.fexpression"
/>
</div>
<div class="form-row node-text-editor-row">
<div style="height: 70px; min-height:50px;" class="node-text-editor" id="node-input-fexpression-editor"></div>
</div>
<div class="form-row">
<label for="node-input-valuex"> <i class='fa fa-tasks'></i> <span data-i18n="curve.label.valuex"></span> </label>
<input type="text" id="node-input-valuex" style="width:100%;" data-i18n="[placeholder]curve.placeholder.valuex">
</div>
<div class="form-row">
<label for="node-input-outputtype"><i class="fa fa-compress"></i> <span data-i18n="curve.label.outputtype"></span></label>
<select id="node-input-outputtype" style="width:100%;">
<option value="float" data-i18n="curve.option.float"></option>
<option value="ceil" data-i18n="curve.option.ceil"></option>
<option value="floor" data-i18n="curve.option.floor"></option>
</select>
</div>
<div class="form-row" style="width:100%;">
<div class="form-tips">
<b>Tip:</b> <span data-i18n="curve.label.tip"></span>
</div>
</div>
</script>