Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!--
- 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.
- -->
- <script type="text/x-red" data-template-name="sentiment">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('sentiment',{
- category: 'analysis-function',
- color:"#E6E0F8",
- defaults: {
- name: {value:""},
- },
- inputs:1,
- outputs:1,
- icon: "arrow-in.png",
- label: function() {
- return this.name||"sentiment";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="sentiment">
- <p>Analyses the <code>msg.payload</code> and adds a <code>msg.sentiment</code> object
- that contains the resulting AFINN-111 sentiment score as <code>msg.sentiment.score</code>.</p>
- <p>A score greater than zero is positive and less than zero is negative.</p>
- <p>The score typically ranges from -5 to +5, but can go higher and lower.</p>
- <p>An object of word score overrides can be supplied as <code>msg.overrides</code>.</p>
- <p>See <a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_blank">the Sentiment docs here</a>.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="inject">
- <div class="form-row">
- <label for="node-input-payload"><i class="fa fa-envelope"></i> <span data-i18n="common.label.payload"></span></label>
- <input type="text" id="node-input-payload" style="width:70%">
- <input type="hidden" id="node-input-payloadType">
- </div>
- <div class="form-row">
- <label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
- <input type="text" id="node-input-topic">
- </div>
- <div class="form-row">
- <label for=""><i class="fa fa-repeat"></i> <span data-i18n="inject.label.repeat"></span></label>
- <select id="inject-time-type-select">
- <option value="none" data-i18n="inject.none"></option>
- <option value="interval" data-i18n="inject.interval"></option>
- <option value="interval-time" data-i18n="inject.interval-time"></option>
- <option value="time" data-i18n="inject.time"></option>
- </select>
- <input type="hidden" id="node-input-repeat">
- <input type="hidden" id="node-input-crontab">
- </div>
- <div class="form-row inject-time-row hidden" id="inject-time-row-interval">
- <span data-i18n="inject.every"></span>
- <input id="inject-time-interval-count" class="inject-time-count" value="1"></input>
- <select style="width: 100px" id="inject-time-interval-units">
- <option value="s" data-i18n="inject.seconds"></option>
- <option value="m" data-i18n="inject.minutes"></option>
- <option value="h" data-i18n="inject.hours"></option>
- </select><br/>
- </div>
- <div class="form-row inject-time-row hidden" id="inject-time-row-interval-time">
- <span data-i18n="inject.every"></span> <select style="width:90px" id="inject-time-interval-time-units" class="inject-time-int-count" value="1">
- <option value="1">1</option>
- <option value="2">2</option>
- <option value="3">3</option>
- <option value="4">4</option>
- <option value="5">5</option>
- <option value="6">6</option>
- <option value="10">10</option>
- <option value="12">12</option>
- <option value="15">15</option>
- <option value="20">20</option>
- <option value="30">30</option>
- <option value="0">60</option>
- </select> <span data-i18n="inject.minutes"></span><br/>
- <span data-i18n="inject.between"></span> <select id="inject-time-interval-time-start" class="inject-time-times"></select>
- <span data-i18n="inject.and"></span> <select id="inject-time-interval-time-end" class="inject-time-times"></select><br/>
- <div id="inject-time-interval-time-days" class="inject-time-days">
- <div style="display: inline-block; vertical-align: top;margin-right:5px;" data-i18n="inject.on">on</div>
- <div style="display:inline-block;">
- <div>
- <label><input type='checkbox' checked value='1'/> <span data-i18n="inject.days.0"></span></label>
- <label><input type='checkbox' checked value='2'/> <span data-i18n="inject.days.1"></span></label>
- <label><input type='checkbox' checked value='3'/> <span data-i18n="inject.days.2"></span></label>
- </div>
- <div>
- <label><input type='checkbox' checked value='4'/> <span data-i18n="inject.days.3"></span></label>
- <label><input type='checkbox' checked value='5'/> <span data-i18n="inject.days.4"></span></label>
- <label><input type='checkbox' checked value='6'/> <span data-i18n="inject.days.5"></span></label>
- </div>
- <div>
- <label><input type='checkbox' checked value='0'/> <span data-i18n="inject.days.6"></span></label>
- </div>
- </div>
- </div>
- </div>
- <div class="form-row inject-time-row hidden" id="inject-time-row-time">
- <span data-i18n="inject.at"></span> <input id="inject-time-time" value="12:00"></input><br/>
- <div id="inject-time-time-days" class="inject-time-days">
- <div style="display: inline-block; vertical-align: top;margin-right: 5px;">on </div>
- <div style="display:inline-block;">
- <div>
- <label><input type='checkbox' checked value='1'/> <span data-i18n="inject.days.0"></span></label>
- <label><input type='checkbox' checked value='2'/> <span data-i18n="inject.days.1"></span></label>
- <label><input type='checkbox' checked value='3'/> <span data-i18n="inject.days.2"></span></label>
- </div>
- <div>
- <label><input type='checkbox' checked value='4'/> <span data-i18n="inject.days.3"></span></label>
- <label><input type='checkbox' checked value='5'/> <span data-i18n="inject.days.4"></span></label>
- <label><input type='checkbox' checked value='6'/> <span data-i18n="inject.days.5"></span></label>
- </div>
- <div>
- <label><input type='checkbox' checked value='0'/> <span data-i18n="inject.days.6"></span></label>
- </div>
- </div>
- </div>
- </div>
- <div class="form-row" id="node-once">
- <label> </label>
- <input type="checkbox" id="node-input-once" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-once" style="width: 70%;" data-i18n="inject.onstart"></label>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips" data-i18n="[html]inject.tip"></div>
- </script>
- <style>
- .inject-time-row {
- padding-left: 110px;
- }
- .inject-time-row select {
- margin: 3px 0;
- }
- .inject-time-days label {
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- vertical-align: top;
- width: 100px;
- }
- .inject-time-days input {
- width: auto;
- }
- .inject-time-times {
- width: 90px;
- }
- #inject-time-time {
- width: 75px;
- }
- .inject-time-count {
- width: 40px !important;
- }
- </style>
- <script type="text/javascript">
- RED.nodes.registerType('inject',{
- category: 'input',
- color:"#a6bbcf",
- defaults: {
- name: {value:""},
- topic: {value:""},
- payload: {value:"", validate: RED.validators.typedInput("payloadType")},
- payloadType: {value:"date"},
- repeat: {value:""},
- crontab: {value:""},
- once: {value:false}
- },
- inputs:0,
- outputs:1,
- icon: "inject.png",
- label: function() {
- var suffix = "";
- // if fire once then add small indication
- if (this.once) {
- suffix = " ¹";
- }
- // but replace with repeat one if set to repeat
- if (this.repeat || this.crontab) {
- suffix = " ↻";
- }
- if (this.name) {
- return this.name+suffix;
- } else if (this.payloadType === "string" ||
- this.payloadType === "str" ||
- this.payloadType === "num" ||
- this.payloadType === "bool" ||
- this.payloadType === "json") {
- if ((this.topic !== "") && ((this.topic.length + this.payload.length) <= 32)) {
- return this.topic + ":" + this.payload+suffix;
- } else if (this.payload.length > 0 && this.payload.length < 24) {
- return this.payload+suffix;
- } else {
- return this._("inject.inject")+suffix;
- }
- } else if (this.payloadType === 'date') {
- if ((this.topic !== "") && (this.topic.length <= 16)) {
- return this.topic + ":" + this._("inject.timestamp")+suffix;
- } else {
- return this._("inject.timestamp")+suffix;
- }
- } else if (this.payloadType === 'flow' && this.payload.length < 19) {
- return 'flow.'+this.payload+suffix;
- } else if (this.payloadType === 'global' && this.payload.length < 17) {
- return 'global.'+this.payload+suffix;
- } else {
- return this._("inject.inject")+suffix;
- }
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- if (this.payloadType == null) {
- if (this.payload == "") {
- this.payloadType = "date";
- } else {
- this.payloadType = "str";
- }
- } else if (this.payloadType === 'string' || this.payloadType === 'none') {
- this.payloadType = "str";
- }
- $("#node-input-payloadType").val(this.payloadType);
- $("#node-input-payload").typedInput({
- default: 'str',
- typeField: $("#node-input-payloadType"),
- types:['flow','global','str','num','bool','json','date']
- });
- $("#inject-time-type-select").change(function() {
- $("#node-input-crontab").val('');
- var id = $("#inject-time-type-select").val();
- $(".inject-time-row").hide();
- $("#inject-time-row-"+id).show();
- if ((id == "none") || (id == "interval")) {
- $("#node-once").show();
- }
- else {
- $("#node-once").hide();
- $("#node-input-once").prop('checked', false);
- }
- });
- $(".inject-time-times").each(function() {
- for (var i=0;i<24;i++) {
- var l = (i<10?"0":"")+i+":00";
- $(this).append($("<option></option>").val(i).text(l));
- }
- });
- $("<option></option>").val(24).text("00:00").appendTo("#inject-time-interval-time-end");
- $("#inject-time-interval-time-start").change(function() {
- var start = Number($("#inject-time-interval-time-start").val());
- var end = Number($("#inject-time-interval-time-end").val());
- $("#inject-time-interval-time-end option").remove();
- for (var i=start+1;i<25;i++) {
- var l = (i<10?"0":"")+i+":00";
- if (i==24) {
- l = "00:00";
- }
- var opt = $("<option></option>").val(i).text(l).appendTo("#inject-time-interval-time-end");
- if (i === end) {
- opt.attr("selected","selected");
- }
- }
- });
- $(".inject-time-count").spinner({
- //max:60,
- min:1
- });
- $.widget( "ui.injecttimespinner", $.ui.spinner, {
- options: {
- // seconds
- step: 60 * 1000,
- // hours
- page: 60
- },
- _parse: function( value ) {
- if ( typeof value === "string" ) {
- // already a timestamp
- if ( Number( value ) == value ) {
- return Number( value );
- }
- var p = value.split(":");
- var offset = new Date().getTimezoneOffset();
- return ((Number(p[0])*60)+Number(p[1])+offset)*60*1000;
- }
- return value;
- },
- _format: function( value ) {
- var d = new Date(value);
- var h = d.getHours();
- var m = d.getMinutes();
- return ((h < 10)?"0":"")+h+":"+((m < 10)?"0":"")+m;
- }
- });
- $("#inject-time-time").injecttimespinner();
- var repeattype = "none";
- if (this.repeat != "" && this.repeat != 0) {
- repeattype = "interval";
- var r = "s";
- var c = this.repeat;
- if (this.repeat % 60 === 0) { r = "m"; c = c/60; }
- if (this.repeat % 1440 === 0) { r = "h"; c = c/60; }
- $("#inject-time-interval-count").val(c);
- $("#inject-time-interval-units").val(r);
- $("#inject-time-interval-days").prop("disabled","disabled");
- } else if (this.crontab) {
- var cronparts = this.crontab.split(" ");
- var days = cronparts[4];
- if (!isNaN(cronparts[0]) && !isNaN(cronparts[1])) {
- repeattype = "time";
- // Fixed time
- var time = cronparts[1]+":"+cronparts[0];
- $("#inject-time-time").val(time);
- $("#inject-time-type-select").val("s");
- if (days == "*") {
- $("#inject-time-time-days input[type=checkbox]").prop("checked",true);
- } else {
- $("#inject-time-time-days input[type=checkbox]").removeAttr("checked");
- days.split(",").forEach(function(v) {
- $("#inject-time-time-days [value=" + v + "]").prop("checked", true);
- });
- }
- } else {
- repeattype = "interval-time";
- // interval - time period
- var minutes = cronparts[0].slice(2);
- if (minutes === "") { minutes = "0"; }
- $("#inject-time-interval-time-units").val(minutes);
- if (days == "*") {
- $("#inject-time-interval-time-days input[type=checkbox]").prop("checked",true);
- } else {
- $("#inject-time-interval-time-days input[type=checkbox]").removeAttr("checked");
- days.split(",").forEach(function(v) {
- $("#inject-time-interval-time-days [value=" + v + "]").prop("checked", true);
- });
- }
- var time = cronparts[1];
- var timeparts = time.split(",");
- var start;
- var end;
- if (timeparts.length == 1) {
- // 0 or 0-10
- var hours = timeparts[0].split("-");
- if (hours.length == 1) {
- if (hours[0] === "") {
- start = "0";
- end = "0";
- }
- else {
- start = hours[0];
- end = Number(hours[0])+1;
- }
- } else {
- start = hours[0];
- end = Number(hours[1])+1;
- }
- } else {
- // 23,0 or 17-23,0-10 or 23,0-2 or 17-23,0
- var startparts = timeparts[0].split("-");
- start = startparts[0];
- var endparts = timeparts[1].split("-");
- if (endparts.length == 1) {
- end = Number(endparts[0])+1;
- } else {
- end = Number(endparts[1])+1;
- }
- }
- $("#inject-time-interval-time-end").val(end);
- $("#inject-time-interval-time-start").val(start);
- }
- } else {
- $("#inject-time-type-select").val("none");
- }
- $(".inject-time-row").hide();
- $("#inject-time-type-select").val(repeattype);
- $("#inject-time-row-"+repeattype).show();
- $("#node-input-payload").typedInput('type',this.payloadType);
- $("#inject-time-type-select").change();
- $("#inject-time-interval-time-start").change();
- },
- oneditsave: function() {
- var repeat = "";
- var crontab = "";
- var type = $("#inject-time-type-select").val();
- if (type == "none") {
- // nothing
- } else if (type == "interval") {
- var count = $("#inject-time-interval-count").val();
- var units = $("#inject-time-interval-units").val();
- if (units == "s") {
- repeat = count;
- } else {
- if (units == "m") {
- //crontab = "*/"+count+" * * * "+days;
- repeat = count * 60;
- } else if (units == "h") {
- //crontab = "0 */"+count+" * * "+days;
- repeat = count * 60 * 60;
- }
- }
- } else if (type == "interval-time") {
- repeat = "";
- var count = $("#inject-time-interval-time-units").val();
- var startTime = Number($("#inject-time-interval-time-start").val());
- var endTime = Number($("#inject-time-interval-time-end").val());
- var days = $('#inject-time-interval-time-days input[type=checkbox]:checked').map(function(_, el) {
- return $(el).val()
- }).get();
- if (days.length == 0) {
- crontab = "";
- } else {
- if (days.length == 7) {
- days="*";
- } else {
- days = days.join(",");
- }
- var timerange = "";
- if (endTime == 0) {
- timerange = startTime+"-23";
- } else if (startTime+1 < endTime) {
- timerange = startTime+"-"+(endTime-1);
- } else if (startTime+1 == endTime) {
- timerange = startTime;
- } else {
- var startpart = "";
- var endpart = "";
- if (startTime == 23) {
- startpart = "23";
- } else {
- startpart = startTime+"-23";
- }
- if (endTime == 1) {
- endpart = "0";
- } else {
- endpart = "0-"+(endTime-1);
- }
- timerange = startpart+","+endpart;
- }
- if (count === "0") {
- crontab = count+" "+timerange+" * * "+days;
- } else {
- crontab = "*/"+count+" "+timerange+" * * "+days;
- }
- }
- } else if (type == "time") {
- var time = $("#inject-time-time").val();
- var days = $('#inject-time-time-days input[type=checkbox]:checked').map(function(_, el) {
- return $(el).val()
- }).get();
- if (days.length == 0) {
- crontab = "";
- } else {
- if (days.length == 7) {
- days="*";
- } else {
- days = days.join(",");
- }
- var parts = time.split(":");
- repeat = "";
- crontab = parts[1]+" "+parts[0]+" * * "+days;
- }
- }
- $("#node-input-repeat").val(repeat);
- $("#node-input-crontab").val(crontab);
- },
- button: {
- onclick: function() {
- var label = (this.name||this.payload).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
- if (this.payloadType === "date") { label = this._("inject.timestamp"); }
- if (this.payloadType === "none") { label = this._("inject.blank"); }
- var node = this;
- $.ajax({
- url: "inject/"+this.id,
- type:"POST",
- success: function(resp) {
- RED.notify(node._("inject.success",{label:label}),"success");
- },
- error: function(jqXHR,textStatus,errorThrown) {
- if (jqXHR.status == 404) {
- RED.notify(node._("common.notification.error",{message:node._("common.notification.errors.not-deployed")}),"error");
- } else if (jqXHR.status == 500) {
- RED.notify(node._("common.notification.error",{message:node._("inject.errors.failed")}),"error");
- } else if (jqXHR.status == 0) {
- RED.notify(node._("common.notification.error",{message:node._("common.notification.errors.no-response")}),"error");
- } else {
- RED.notify(node._("common.notification.error",{message:node._("common.notification.errors.unexpected",{status:jqXHR.status,message:textStatus})}),"error");
- }
- }
- });
- }
- }
- });
- </script>
- <script type="text/x-red" data-help-name="inject">
- <p>Pressing the button on the left side of the node allows a message on a topic
- to be injected into the flow.</p>
- <p>The payload defaults to the current time in millisecs since 1970, but can
- also be set to various other javascript types.</p>
- <p>The repeat function allows the payload to be sent on the required schedule.</p>
- <p>The <i>Inject once at start</i> option actually waits a short interval before firing
- to give other nodes a chance to instantiate properly.</p>
- <p>The <i>Flow</i> and <i>Global</i> options allow one to inject a flow or global
- context value.
- </p>
- <p><b>Note: </b>"Interval between times" and "at a specific time" uses cron.
- This means that 20 minutes will be at the next hour, 20 minutes past and
- 40 minutes past - not in 20 minutes time. If you want every 20 minutes
- from now - use the "interval" option.</p>
- <p><b>Note: </b>all string input is escaped. To add a carriage return to a string
- you should use a following function.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="catch">
- <div class="form-row">
- <label style="width: auto" for="node-input-scope" data-i18n="catch.label.source"></label>
- <select id="node-input-scope-select">
- <option value="all" data-i18n="catch.scope.all"></option>
- <option value="target" data-i18n="catch.scope.selected"></options>
- </select>
- </div>
- <div class="form-row node-input-target-row" style="display: none;">
- <div id="node-input-catch-target-container-div" style="min-height: 100px;position: relative; box-sizing: border-box; border-radius: 2px; height: 180px; border: 1px solid #ccc;overflow:hidden; ">
- <div style="box-sizing: border-box; line-height: 20px; font-size: 0.8em; border-bottom: 1px solid #ddd; height: 20px;">
- <input type="checkbox" data-i18n="[title]catch.label.selectAll" id="node-input-target-node-checkbox-all" style="width: 30px; margin: 0 2px 1px 2px;">
- <div style="display: inline-block;"><a id="node-input-target-sort-label" href="#" data-i18n="[title]catch.label.sortByLabel"><span data-i18n="catch.label.node"></span> <i class="node-input-catch-sort-label-a fa fa-caret-down"></i><i class="node-input-catch-sort-label-d fa fa-caret-up"></i></a></div>
- <div style="position: absolute; right: 10px; width: 50px; display: inline-block; text-align: right;"><a id="node-input-target-sort-type" href="#" data-i18n="[title]catch.label.sortByType"><i class="node-input-catch-sort-sublabel-a fa fa-caret-down"></i><i class="node-input-catch-sort-sublabel-d fa fa-caret-up"></i> <span data-i18n="catch.label.type"></span></a></div>
- </div>
- <div style="background: #fbfbfb; box-sizing: border-box; position:absolute; top:20px;bottom:0;left:0px;right:0px; overflow-y: scroll; overflow-x: hidden;">
- <ul id="node-input-catch-target-container" style=" list-style-type:none; margin: 0;"></ul>
- </div>
- </div>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <style>
- #node-input-catch-target-container {
- position: relative;
- }
- #node-input-catch-target-container li {
- padding: 2px 5px;
- background: none;
- font-size: 0.8em;
- margin:0;
- white-space: nowrap;
- }
- #node-input-catch-target-container li label {
- margin-bottom: 0;
- width: 100%;
- }
- #node-input-catch-target-container li label input {
- vertical-align: top;
- width:15px;
- margin-right: 10px;
- }
- #node-input-catch-target-container li:hover,
- #node-input-catch-target-container li:hover .node-input-target-node-sublabel {
- background: #f0f0f0;
- }
- .node-input-target-node-sublabel {
- position:absolute;
- right: 0px;
- padding-right: 10px;
- padding-left: 10px;
- font-size: 0.8em;
- background: #fbfbfb;
- }
- </style>
- <script type="text/javascript">
- RED.nodes.registerType('catch',{
- category: 'input',
- color:"#e49191",
- defaults: {
- name: {value:""},
- scope: {value:null}
- },
- inputs:0,
- outputs:1,
- icon: "alert.png",
- label: function() {
- return this.name||(this.scope?this._("catch.catchNodes",{number:this.scope.length}):this._("catch.catch"));
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var nodeList = $("#node-input-catch-target-container");
- var node = this;
- this.resize = function() {
- var rows = $("#dialog-form>div:not(.node-input-target-row)");
- var height = $("#dialog-form").height();
- for (var i=0;i<rows.size();i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-input-target-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $("#node-input-catch-target-container-div").css("height",height+"px");
- }
- function createNodeList() {
- var scope = node.scope || [];
- nodeList.empty();
- var candidateNodes = RED.nodes.filterNodes({z:node.z});
- var allChecked = true;
- candidateNodes.forEach(function(n) {
- if (n.id === node.id) {
- return;
- }
- var isChecked = scope.indexOf(n.id) !== -1;
- allChecked = allChecked && isChecked;
- var container = $('<li/>',{class:"node-input-target-node"});
- var row = $('<label/>',{for:"node-input-target-node-"+n.id}).appendTo(container);
- $('<input>',{type:"checkbox",class:"node-input-target-node-checkbox",id:"node-input-target-node-"+n.id})
- .data('node-id',n.id)
- .prop('checked', isChecked)
- .appendTo(row);
- container.on('mouseover',function(e) {
- n.highlighted = true;
- n.dirty = true;
- RED.view.redraw();
- });
- container.on('mouseout',function(e) {
- n.highlighted = false;
- n.dirty = true;
- RED.view.redraw();
- });
- var labelSpan = $('<span>');
- var nodeDef = RED.nodes.getType(n.type);
- var label;
- var sublabel;
- if (nodeDef) {
- var l = nodeDef.label;
- label = (typeof l === "function" ? l.call(n) : l)||"";
- sublabel = n.type;
- if (sublabel.indexOf("subflow:") === 0) {
- var subflowId = sublabel.substring(8);
- var subflow = RED.nodes.subflow(subflowId);
- sublabel = "subflow : "+subflow.name;
- }
- }
- if (!nodeDef || !label) {
- label = n.type;
- }
- $('<span>',{class:"node-input-target-node-label",style:"white-space:nowrap"}).text(label).appendTo(row);
- if (sublabel) {
- $('<span>',{class:"node-input-target-node-sublabel"}).text(sublabel).appendTo(row);
- }
- container.appendTo(nodeList);
- });
- $(".node-input-target-node-checkbox").change(function() {
- if (!this.checked) {
- $("#node-input-target-node-checkbox-all").prop('checked',false);
- }
- });
- $("#node-input-target-node-checkbox-all").prop('checked',allChecked);
- sortNodeList('label');
- }
- function sortNodeList(sortOn) {
- var currentSort = nodeList.data('currentSort');
- var currentSortOrder = nodeList.data('currentSortOrder');
- if (!currentSort) {
- currentSort = sortOn;
- currentSortOrder = 'a';
- } else {
- if (currentSort === sortOn) {
- currentSortOrder = (currentSortOrder === 'a'?'d':'a');
- } else {
- currentSortOrder = 'a';
- }
- currentSort = sortOn;
- }
- nodeList.data('currentSort',currentSort);
- nodeList.data('currentSortOrder',currentSortOrder);
- $("#node-input-catch-target-container-div .fa").hide();
- $(".node-input-catch-sort-"+currentSort+"-"+currentSortOrder).show();
- var items = nodeList.find("li").get();
- items.sort(function(a,b) {
- var labelA = $(a).find(".node-input-target-node-"+currentSort).text().toLowerCase();
- var labelB = $(b).find(".node-input-target-node-"+currentSort).text().toLowerCase();
- if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
- if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
- return 0;
- });
- $.each(items, function(i, li){
- nodeList.append(li);
- });
- }
- $("#node-input-target-sort-label").click(function(e) {
- e.preventDefault();
- sortNodeList('label');
- });
- $("#node-input-target-sort-type").click(function(e) {
- e.preventDefault();
- sortNodeList('sublabel')
- });
- $("#node-input-target-node-checkbox-all").change(function() {
- $(".node-input-target-node-checkbox").prop('checked',this.checked);
- })
- $("#node-input-scope-select").change(function(e) {
- var scope = $(this).val();
- if (scope === "target") {
- createNodeList();
- $(".node-input-target-row").show();
- } else {
- $(".node-input-target-row").hide();
- }
- node.resize();
- });
- if (this.scope == null) {
- $("#node-input-scope-select").val("all");
- } else {
- $("#node-input-scope-select").val("target");
- }
- $("#node-input-scope-select").change();
- },
- oneditsave: function() {
- var scope = $("#node-input-scope-select").val();
- if (scope === 'all') {
- this.scope = null;
- } else {
- var node = this;
- node.scope = [];
- $(".node-input-target-node-checkbox").each(function(n) {
- if ($(this).prop("checked")) {
- node.scope.push($(this).data('node-id'));
- }
- })
- }
- },
- oneditresize: function(size) {
- this.resize();
- }
- });
- </script>
- <script type="text/x-red" data-help-name="catch">
- <p>Catch errors thrown by nodes on the same tab.</p>
- <p>If a node throws a error whilst handling a message, the flow will typically
- halt. This node can be used to catch those errors and handle them with a
- dedicated flow.</p>
- <p>The node will catch errors thrown by any node on the same tab. If there
- are multiple catch nodes on a tab, they will all get triggered.</p>
- <p>If an error is thrown within a subflow, the error will get handled by any
- catch nodes within the subflow. If none exists, the error is propagated
- up to the tab the subflow instance is on.</p>
- <p>The message sent by this node will be the original message if the node that
- threw the error provided it. The message will have an <code>error</code>
- property with the following attributes:
- <ul>
- <li><code>message</code> : the error message</li>
- <li><code>source.id</code> : the id of the node that threw the error</li>
- <li><code>source.type</code> : the type of the node that threw the error</li>
- <li><code>source.name</code> : the name, if set, of the node that threw the error</li>
- </ul>
- </p>
- <p>If the message already had a <code>error</code> property, it is copied to <code>_error</code>.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="status">
- <div class="form-row">
- <label style="width: auto" for="node-input-scope" data-i18n="status.label.source"></label>
- <select id="node-input-scope-select">
- <option value="all" data-i18n="status.scope.all"></option>
- <option value="target" data-i18n="status.scope.selected"></options>
- </select>
- </div>
- <div class="form-row node-input-target-row" style="display: none;">
- <div id="node-input-status-target-container-div" style=" min-height: 100px;position: relative; box-sizing: border-box; border-radius: 2px; height: 180px; border: 1px solid #ccc;overflow:hidden; ">
- <div style="box-sizing: border-box; line-height: 20px; font-size: 0.8em; border-bottom: 1px solid #ddd; height: 20px;">
- <input type="checkbox" data-i18n="[title]status.label.selectAll" id="node-input-target-node-checkbox-all" style="width: 30px; margin: 0 2px 1px 2px;">
- <div style="display: inline-block;"><a id="node-input-target-sort-label" href="#" data-i18n="[title]status.label.sortByLabel"><span data-i18n="status.label.node"></span> <i class="node-input-status-sort-label-a fa fa-caret-down"></i><i class="node-input-status-sort-label-d fa fa-caret-up"></i></a></div>
- <div style="position: absolute; right: 10px; width: 50px; display: inline-block; text-align: right;"><a id="node-input-target-sort-type" href="#" data-i18n="[title]status.label.sortByType"><i class="node-input-status-sort-sublabel-a fa fa-caret-down"></i><i class="node-input-status-sort-sublabel-d fa fa-caret-up"></i> <span data-i18n="status.label.type"></span></a></div>
- </div>
- <div style="background: #fbfbfb; box-sizing: border-box; position:absolute; top:20px;bottom:0;left:0px;right:0px; overflow-y: scroll; overflow-x: hidden;">
- <ul id="node-input-status-target-container" style=" list-style-type:none; margin: 0;"></ul>
- </div>
- </div>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <style>
- #node-input-status-target-container {
- position: relative;
- }
- #node-input-status-target-container li {
- padding: 2px 5px;
- background: none;
- font-size: 0.8em;
- margin:0;
- white-space: nowrap;
- }
- #node-input-status-target-container li label {
- margin-bottom: 0;
- width: 100%;
- }
- #node-input-status-target-container li label input {
- vertical-align: top;
- width:15px;
- margin-right: 10px;
- }
- #node-input-status-target-container li:hover,
- #node-input-status-target-container li:hover .node-input-target-node-sublabel {
- background: #f0f0f0;
- }
- .node-input-target-node-sublabel {
- position:absolute;
- right: 0px;
- padding-right: 10px;
- padding-left: 10px;
- font-size: 0.8em;
- background: #fbfbfb;
- }
- </style>
- <script type="text/javascript">
- RED.nodes.registerType('status',{
- category: 'input',
- color:"#c0edc0",
- defaults: {
- name: {value:""},
- scope: {value:null}
- },
- inputs:0,
- outputs:1,
- icon: "alert.png",
- label: function() {
- return this.name||(this.scope?this._("status.statusNodes",{number:this.scope.length}):this._("status.status"));
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var nodeList = $("#node-input-status-target-container");
- var node = this;
- this.resize = function() {
- var rows = $("#dialog-form>div:not(.node-input-target-row)");
- var height = $("#dialog-form").height();
- for (var i=0;i<rows.size();i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-input-target-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $("#node-input-status-target-container-div").css("height",height+"px");
- }
- function createNodeList() {
- var scope = node.scope || [];
- nodeList.empty();
- var candidateNodes = RED.nodes.filterNodes({z:node.z});
- var allChecked = true;
- candidateNodes.forEach(function(n) {
- if (n.id === node.id) {
- return;
- }
- var isChecked = scope.indexOf(n.id) !== -1;
- allChecked = allChecked && isChecked;
- var container = $('<li/>',{class:"node-input-target-node"});
- var row = $('<label/>',{for:"node-input-target-node-"+n.id}).appendTo(container);
- $('<input>',{type:"checkbox",class:"node-input-target-node-checkbox",id:"node-input-target-node-"+n.id})
- .data('node-id',n.id)
- .prop('checked', isChecked)
- .appendTo(row);
- container.on('mouseover',function(e) {
- n.highlighted = true;
- n.dirty = true;
- RED.view.redraw();
- });
- container.on('mouseout',function(e) {
- n.highlighted = false;
- n.dirty = true;
- RED.view.redraw();
- });
- var labelSpan = $('<span>');
- var nodeDef = RED.nodes.getType(n.type);
- var label;
- var sublabel;
- if (nodeDef) {
- var l = nodeDef.label;
- label = (typeof l === "function" ? l.call(n) : l)||"";
- sublabel = n.type;
- if (sublabel.indexOf("subflow:") === 0) {
- var subflowId = sublabel.substring(8);
- var subflow = RED.nodes.subflow(subflowId);
- sublabel = "subflow : "+subflow.name;
- }
- }
- if (!nodeDef || !label) {
- label = n.type;
- }
- $('<span>',{class:"node-input-target-node-label",style:"white-space:nowrap"}).text(label).appendTo(row);
- if (sublabel) {
- $('<span>',{class:"node-input-target-node-sublabel"}).text(sublabel).appendTo(row);
- }
- container.appendTo(nodeList);
- });
- $(".node-input-target-node-checkbox").change(function() {
- if (!this.checked) {
- $("#node-input-target-node-checkbox-all").prop('checked',false);
- }
- });
- $("#node-input-target-node-checkbox-all").prop('checked',allChecked);
- sortNodeList('label');
- }
- function sortNodeList(sortOn) {
- var currentSort = nodeList.data('currentSort');
- var currentSortOrder = nodeList.data('currentSortOrder');
- if (!currentSort) {
- currentSort = sortOn;
- currentSortOrder = 'a';
- } else {
- if (currentSort === sortOn) {
- currentSortOrder = (currentSortOrder === 'a'?'d':'a');
- } else {
- currentSortOrder = 'a';
- }
- currentSort = sortOn;
- }
- nodeList.data('currentSort',currentSort);
- nodeList.data('currentSortOrder',currentSortOrder);
- $("#node-input-status-target-container-div .fa").hide();
- $(".node-input-status-sort-"+currentSort+"-"+currentSortOrder).show();
- var items = nodeList.find("li").get();
- items.sort(function(a,b) {
- var labelA = $(a).find(".node-input-target-node-"+currentSort).text().toLowerCase();
- var labelB = $(b).find(".node-input-target-node-"+currentSort).text().toLowerCase();
- if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
- if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
- return 0;
- });
- $.each(items, function(i, li){
- nodeList.append(li);
- });
- }
- $("#node-input-target-sort-label").click(function(e) {
- e.preventDefault();
- sortNodeList('label');
- });
- $("#node-input-target-sort-type").click(function(e) {
- e.preventDefault();
- sortNodeList('sublabel')
- });
- $("#node-input-target-node-checkbox-all").change(function() {
- $(".node-input-target-node-checkbox").prop('checked',this.checked);
- })
- $("#node-input-scope-select").change(function(e) {
- var scope = $(this).val();
- if (scope === "target") {
- createNodeList();
- $(".node-input-target-row").show();
- } else {
- $(".node-input-target-row").hide();
- }
- node.resize();
- });
- if (this.scope == null) {
- $("#node-input-scope-select").val("all");
- } else {
- $("#node-input-scope-select").val("target");
- }
- $("#node-input-scope-select").change();
- },
- oneditsave: function() {
- var scope = $("#node-input-scope-select").val();
- if (scope === 'all') {
- this.scope = null;
- } else {
- var node = this;
- node.scope = [];
- $(".node-input-target-node-checkbox").each(function(n) {
- if ($(this).prop("checked")) {
- node.scope.push($(this).data('node-id'));
- }
- })
- }
- },
- oneditresize: function(size) {
- this.resize();
- }
- });
- </script>
- <script type="text/x-red" data-help-name="status">
- <p>Send status messages from other nodes on the same tab.</p>
- <p>The message sent by this node will have a <code>status</code> property
- with the following attributes:
- <ul>
- <li><code>text</code> : the status text</li>
- <li><code>source.type</code> : the type of the node that reported status</li>
- <li><code>source.id</code> : the id of the node that reported status</li>
- <li><code>source.name</code> : the name, if set, of the node that reported status</li>
- </ul>
- </p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="debug">
- <div class="form-row">
- <label for="node-input-typed-complete"><i class="fa fa-list"></i> <span data-i18n="debug.output"></span></label>
- <input id="node-input-typed-complete" type="text" style="width: 70%">
- <input id="node-input-complete" type="hidden">
- </div>
- <div class="form-row">
- <label for="node-input-console"><i class="fa fa-random"></i> <span data-i18n="debug.to"></span></label>
- <select type="text" id="node-input-console" style="display: inline-block; width: 250px; vertical-align: top;">
- <option value="false" data-i18n="debug.debtab"></option>
- <option value="true" data-i18n="debug.tabcon"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script src="debug/view/debug-utils.js"></script>
- <script type="text/javascript">
- (function() {
- var subWindow = null;
- RED.nodes.registerType('debug',{
- category: 'output',
- defaults: {
- name: {value:""},
- active: {value:true},
- console: {value:"false"},
- complete: {value:"false", required:true}
- },
- label: function() {
- var suffix = "";
- if (this.console === true || this.console === "true") { suffix = " ⇲"; }
- if (this.complete === true || this.complete === "true") {
- return (this.name||"msg") + suffix;
- } else {
- return (this.name || "msg." + ((!this.complete || this.complete === "false") ? "payload" : this.complete)) + suffix;
- }
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- color:"#87a980",
- inputs:1,
- outputs:0,
- icon: "debug.png",
- align: "right",
- button: {
- toggle: "active",
- onclick: function() {
- var label = this.name||"debug";
- var node = this;
- $.ajax({
- url: "debug/"+this.id+"/"+(this.active?"enable":"disable"),
- type: "POST",
- success: function(resp, textStatus, xhr) {
- if (xhr.status == 200) {
- RED.notify(node._("debug.notification.activated",{label:label}),"success");
- } else if (xhr.status == 201) {
- RED.notify(node._("debug.notification.deactivated",{label:label}),"success");
- }
- },
- error: function(jqXHR,textStatus,errorThrown) {
- if (jqXHR.status == 404) {
- RED.notify(node._("common.notification.error", {message: node._("common.notification.errors.not-deployed")}),"error");
- } else if (jqXHR.status == 0) {
- RED.notify(node._("common.notification.error", {message: node._("common.notification.errors.no-response")}),"error");
- } else {
- RED.notify(node._("common.notification.error",{message:node._("common.notification.errors.unexpected",{status:err.status,message:err.response})}),"error");
- }
- }
- });
- }
- },
- onpaletteadd: function() {
- var options = {
- messageMouseEnter: function(sourceId) {
- if (sourceId) {
- var n = RED.nodes.node(sourceId);
- if (n) {
- n.highlighted = true;
- n.dirty = true;
- }
- RED.view.redraw();
- }
- },
- messageMouseLeave: function(sourceId) {
- if (sourceId) {
- var n = RED.nodes.node(sourceId);
- if (n) {
- n.highlighted = false;
- n.dirty = true;
- }
- RED.view.redraw();
- }
- },
- messageSourceClick: function(sourceId) {
- RED.view.reveal(sourceId);
- },
- clear: function() {
- RED.nodes.eachNode(function(node) {
- node.highlighted = false;
- node.dirty = true;
- });
- RED.view.redraw();
- }
- }
- var uiComponents = RED.debug.init(options);
- RED.sidebar.addTab({
- id: "debug",
- label: this._("debug.sidebar.label"),
- name: this._("debug.sidebar.name"),
- content: uiComponents.content,
- toolbar: uiComponents.footer,
- enableOnEdit: true
- });
- RED.actions.add("core:show-debug-tab",function() { RED.sidebar.show('debug')});
- var that = this;
- RED._debug = function(msg) {
- that.handleDebugMessage("",{
- name:"debug",
- msg:msg
- });
- }
- this.refreshMessageList = function() {
- RED.debug.refreshMessageList(RED.workspaces.active());
- if (subWindow) {
- try {
- subWindow.postMessage({event:"workspaceChange",activeWorkspace:RED.workspaces.active()},"*")
- } catch(err) {
- console.log(err);
- }
- }
- }
- this.handleDebugMessage = function(t,o) {
- var sourceNode = RED.nodes.node(o.id) || RED.nodes.node(o.z);
- if (sourceNode) {
- o._source = {id:sourceNode.id,z:sourceNode.z,name:sourceNode.name};
- }
- RED.debug.handleDebugMessage(o);
- if (subWindow) {
- try {
- subWindow.postMessage({event:"message",msg:o},"*")
- } catch(err) {
- console.log(err);
- }
- }
- };
- RED.comms.subscribe("debug",this.handleDebugMessage);
- RED.events.on("workspace:change", this.refreshMessageList);
- $("#debug-tab-open").click(function(e) {
- e.preventDefault();
- subWindow = window.open(document.location.toString().replace(/[?#].*$/,"")+"debug/view/view.html"+document.location.search,"nodeREDDebugView","menubar=no,location=no,toolbar=no,chrome,height=500,width=600");
- subWindow.onload = function() {
- subWindow.postMessage({event:"workspaceChange",activeWorkspace:RED.workspaces.active()},"*");
- }
- });
- $(window).unload(function() {
- if (subWindow) {
- try {
- subWindow.close()
- } catch(err) {
- console.log(err);
- }
- }
- });
- this.handleWindowMessage = function(evt) {
- var msg = evt.data;
- if (msg.event === "mouseEnter") {
- options.messageMouseEnter(msg.id);
- } else if (msg.event === "mouseLeave") {
- options.messageMouseLeave(msg.id);
- } else if (msg.event === "mouseClick") {
- options.messageSourceClick(msg.id);
- } else if (msg.event === "clear") {
- options.clear();
- }
- }
- window.addEventListener('message',this.handleWindowMessage);
- },
- onpaletteremove: function() {
- RED.comms.unsubscribe("debug",this.handleDebugMessage);
- RED.sidebar.removeTab("debug");
- RED.events.off("workspace:change", this.refreshMessageList);
- window.removeEventListener("message",this.handleWindowMessage);
- RED.actions.remove("core:show-debug");
- delete RED._debug;
- },
- oneditprepare: function() {
- $("#node-input-typed-complete").typedInput({types:['msg', {value:"full",label:RED._("node-red:debug.msgobj"),hasValue:false}]});
- if (this.complete === "true" || this.complete === true) {
- // show complete message object
- $("#node-input-typed-complete").typedInput('type','full');
- } else {
- var property = (!this.complete||(this.complete === "false")) ? "payload" : this.complete+"";
- $("#node-input-typed-complete").typedInput('type','msg');
- $("#node-input-typed-complete").typedInput('value',property);
- }
- $("#node-input-typed-complete").on('change',function() {
- if ($("#node-input-typed-complete").typedInput('type') === 'msg'
- &&
- $("#node-input-typed-complete").typedInput('value') === ''
- ) {
- $("#node-input-typed-complete").typedInput('value','payload');
- }
- });
- },
- oneditsave: function() {
- var type = $("#node-input-typed-complete").typedInput('type');
- if (type === 'full') {
- $("#node-input-complete").val("true");
- } else {
- $("#node-input-complete").val($("#node-input-typed-complete").typedInput('value'));
- }
- }
- });
- })();
- </script>
- <script type="text/x-red" data-help-name="debug">
- <p>The Debug node can be connected to the output of any node. It can be used to display the output of any message
- property in the debug tab of the sidebar. The default is to display <code>msg.payload</code>.</p>
- <p>Each message will also display the timestamp, <code>msg.topic</code> and the type of property chosen to output.</p>
- <p>The sidebar can be accessed under the options drop-down in the top right corner.</p>
- <p>The button to the right of the node will toggle its output on and off so you can de-clutter the debug window.</p>
- <p>If the payload is an object or buffer it will be stringified first for display and indicate that by saying "(Object)" or "(Buffer)".</p>
- <p>Selecting any particular message will highlight (in red) the debug node that reported it. This is useful if you wire up multiple debug nodes.</p>
- <p>Optionally can show the complete <code>msg</code> object, and send messages to the console log (⇶).</p>
- <p>In addition any calls to node.warn or node.error will appear here.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="link in">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row node-input-link-row"></div>
- </script>
- <script type="text/x-red" data-template-name="link out">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row node-input-link-row"></div>
- </script>
- <style>
- #node-input-link-container {
- position: relative;
- }
- #node-input-link-container li {
- padding: 2px 5px;
- background: none;
- font-size: 0.8em;
- margin:0;
- white-space: nowrap;
- }
- #node-input-link-container li label {
- margin-bottom: 0;
- width: 100%;
- }
- #node-input-link-container li label input {
- vertical-align: top;
- width:15px;
- margin-right: 10px;
- }
- #node-input-link-container li:hover,
- #node-input-link-container li:hover .node-input-target-node-sublabel {
- background: #f0f0f0;
- }
- .node-input-link-node-sublabel {
- position:absolute;
- right: 0px;
- padding-right: 10px;
- padding-left: 10px;
- font-size: 0.8em;
- }
- </style>
- <script type="text/javascript">
- (function() {
- function sortNodeList(nodeList,sortOn,sortOnSecond) {
- var currentSort = nodeList.data('currentSort');
- var currentSortOrder = nodeList.data('currentSortOrder');
- if (!currentSort) {
- currentSort = sortOn;
- currentSortOrder = 'a';
- } else {
- if (currentSort === sortOn) {
- currentSortOrder = (currentSortOrder === 'a'?'d':'a');
- } else {
- currentSortOrder = 'a';
- }
- currentSort = sortOn;
- }
- nodeList.data('currentSort',currentSort);
- nodeList.data('currentSortOrder',currentSortOrder);
- $("#node-input-link-container-div .fa").hide();
- $(".node-input-link-sort-"+currentSort+"-"+currentSortOrder).show();
- var items = nodeList.find("li").get();
- items.sort(function(a,b) {
- var labelA = $(a).find(".node-input-link-node-"+currentSort).text().toLowerCase();
- var labelB = $(b).find(".node-input-link-node-"+currentSort).text().toLowerCase();
- if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
- if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
- if (sortOnSecond) {
- labelA = $(a).find(".node-input-link-node-"+sortOnSecond).text().toLowerCase();
- labelB = $(b).find(".node-input-link-node-"+sortOnSecond).text().toLowerCase();
- if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
- if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
- }
- return 0;
- });
- $.each(items, function(i, li){
- nodeList.append(li);
- });
- }
- function onEditPrepare(node,targetType) {
- if (!node.links) {
- node.links = [];
- }
- node.oldLinks = [];
- $('<div id="node-input-link-container-div" style="min-height: 100px;position: relative; box-sizing: border-box; border-radius: 2px; height: 180px; border: 1px solid #ccc;overflow:hidden; ">'+
- ' <div style="box-sizing: border-box; line-height: 20px; font-size: 0.8em; border-bottom: 1px solid #ddd; height: 20px;">'+
- ' <div style="display: inline-block;margin-left: 5px;"><a id="node-input-link-sort-label" href="#" data-i18n="[title]link.label.sortByLabel"><span data-i18n="link.label.node">name</span> <i class="node-input-link-sort-label-a fa fa-caret-down"></i><i class="node-input-link-sort-label-d fa fa-caret-up"></i></a></div>'+
- ' <div style="position: absolute; right: 10px; width: 50px; display: inline-block; text-align: right;"><a id="node-input-link-sort-type" href="#" data-i18n="[title]link.label.sortByFlow"><i class="node-input-link-sort-sublabel-a fa fa-caret-down"></i><i class="node-input-link-sort-sublabel-d fa fa-caret-up"></i> <span data-i18n="link.label.type">flow</span></a></div>'+
- ' </div>'+
- ' <div style="background: #fbfbfb; box-sizing: border-box; position:absolute; top:20px;bottom:0;left:0px;right:0px; overflow-y: scroll; overflow-x: hidden;">'+
- ' <ul id="node-input-link-container" style=" list-style-type:none; margin: 0;"></ul>'+
- ' </div>'+
- '</div>').appendTo('.node-input-link-row');
- var nodeList = $("#node-input-link-container");
- var candidateNodes = RED.nodes.filterNodes({type:targetType});
- var inSubflow = (RED.nodes.subflow(node.z) != null);
- candidateNodes.forEach(function(n) {
- if (inSubflow) {
- if (n.z !== node.z) {
- return;
- }
- } else {
- if (RED.nodes.subflow(n.z)!=null) {
- return;
- }
- }
- var isChecked = false;
- isChecked = (node.links.indexOf(n.id) !== -1) || (n.links||[]).indexOf(node.id) !== -1;
- if (isChecked) {
- node.oldLinks.push(n.id);
- }
- var container = $('<li/>',{class:"node-input-link-node"});
- var row = $('<label/>',{for:"node-input-link-node-"+n.id}).appendTo(container);
- $('<input>',{type:"checkbox",class:"node-input-link-node-checkbox",id:"node-input-link-node-"+n.id})
- .data('node-id',n.id)
- .prop('checked', isChecked)
- .appendTo(row);
- container.on('mouseover',function(e) {
- n.highlighted = true;
- n.dirty = true;
- RED.view.redraw();
- });
- container.on('mouseout',function(e) {
- n.highlighted = false;
- n.dirty = true;
- RED.view.redraw();
- });
- var labelSpan = $('<span>');
- var label = n.name||n.id;
- var sublabel;
- var tab = RED.nodes.workspace(n.z);
- if (tab) {
- sublabel = tab.label||tab.id;
- } else {
- tab = RED.nodes.subflow(n.z);
- sublabel = "subflow : "+tab.name;
- }
- $('<span>',{class:"node-input-link-node-label",style:"white-space:nowrap"}).text(label).appendTo(row);
- if (sublabel) {
- $('<span>',{class:"node-input-link-node-sublabel"}).text(sublabel).appendTo(row);
- }
- container.appendTo(nodeList);
- });
- sortNodeList(nodeList,'sublabel','label');
- $("#node-input-link-sort-label").click(function(e) {
- e.preventDefault();
- sortNodeList(nodeList,'label');
- });
- $("#node-input-link-sort-type").click(function(e) {
- e.preventDefault();
- sortNodeList(nodeList,'sublabel');
- });
- }
- function resizeNodeList() {
- var rows = $("#dialog-form>div:not(.node-input-link-row)");
- var height = $("#dialog-form").height();
- for (var i=0;i<rows.size();i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-input-link-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $("#node-input-link-container-div").css("height",height+"px");
- }
- function onEditSave(node) {
- node.links = [];
- $(".node-input-link-node-checkbox").each(function(n) {
- if ($(this).prop("checked")) {
- node.links.push($(this).data('node-id'));
- }
- })
- node.oldLinks.sort();
- node.links.sort();
- var nodeMap = {};
- var length = Math.max(node.oldLinks.length,node.links.length);
- for (var i=0;i<length;i++) {
- if (i<node.oldLinks.length) {
- nodeMap[node.oldLinks[i]] = nodeMap[node.oldLinks[i]]||{};
- nodeMap[node.oldLinks[i]].old = true;
- }
- if (i<node.links.length) {
- nodeMap[node.links[i]] = nodeMap[node.links[i]]||{};
- nodeMap[node.links[i]].new = true;
- }
- }
- var n;
- for (var id in nodeMap) {
- if (nodeMap.hasOwnProperty(id)) {
- n = RED.nodes.node(id);
- if (n) {
- if (nodeMap[id].old && !nodeMap[id].new) {
- // Removed id
- i = n.links.indexOf(node.id);
- if (i > -1) {
- n.links.splice(i,1);
- }
- } else if (!nodeMap[id].old && nodeMap[id].new){
- // Added id
- i = n.links.indexOf(id);
- if (i === -1) {
- n.links.push(node.id);
- }
- }
- }
- }
- }
- }
- function onAdd() {
- for (var i=0;i<this.links.length;i++) {
- var n = RED.nodes.node(this.links[i]);
- if (n.links.indexOf(this.id) === -1) {
- n.links.push(this.id);
- }
- }
- }
- RED.nodes.registerType('link in',{
- category: 'input',
- color:"#ddd",//"#87D8CF",
- defaults: {
- name: {value:""},
- links: { value: [] }
- },
- inputs:0,
- outputs:1,
- icon: "link-out.png",
- label: function() {
- return this.name||this._("link.linkIn");
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- onEditPrepare(this,"link out");
- },
- oneditsave: function() {
- onEditSave(this);
- },
- onadd: onAdd,
- oneditresize: resizeNodeList
- });
- RED.nodes.registerType('link out',{
- category: 'output',
- color:"#ddd",//"#87D8CF",
- defaults: {
- name: {value:""},
- links: { value: []}
- },
- align:"right",
- inputs:1,
- outputs:0,
- icon: "link-out.png",
- label: function() {
- return this.name||this._("link.linkOut");
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- onEditPrepare(this,"link in");
- },
- oneditsave: function() {
- onEditSave(this);
- },
- onadd: onAdd,
- oneditresize: resizeNodeList
- });
- })();
- </script>
- <script type="text/x-red" data-help-name="link in">
- <p>Create virtual wires between flows.</p>
- <p>The node can be connected to any <b>link out</b> node that exists on any tab.
- Once connected, they behave as if they were wired together.</p>
- <p>The wires between link nodes are only displayed when a link node is selected.
- If there are any wires to other tabs, a virtual node is show that can be clicked
- on to jump to the appropriate tab.</p>
- <p>Links cannot be created going into, or out of, a subflow.</p>
- </script><script type="text/x-red" data-help-name="link out">
- <p>Create virtual wires between flows.</p>
- <p>The node can be connected to any <b>link in</b> node that exists on any tab.
- Once connected, they behave as if they were wired together.</p>
- <p>The wires between link nodes are only displayed when a link node is selected.
- If there are any wires to other tabs, a virtual node is show that can be clicked
- on to jump to the appropriate tab.</p>
- <p>Links cannot be created going into, or out of, a subflow.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="exec">
- <div class="form-row">
- <label for="node-input-command"><i class="fa fa-file"></i> <span data-i18n="exec.label.command"></span></label>
- <input type="text" id="node-input-command" data-i18n="[placeholder]exec.label.command">
- </div>
- <div class="form-row">
- <label><i class="fa fa-plus"></i> <span data-i18n="exec.label.append"></span></label>
- <input type="checkbox" id="node-input-addpay" style="display: inline-block; width: auto; vertical-align: top;">
- msg.payload
- </div>
- <div class="form-row">
- <label for="node-input-append"> </label>
- <input type="text" id="node-input-append" data-i18n="[placeholder]exec.placeholder.extraparams">
- </div>
- <div class="form-row">
- <label> </label>
- <input type="checkbox" id="node-input-useSpawn" placeholder="spawn" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-useSpawn" style="width:70%;"><span data-i18n="exec.spawn"></span></label>
- </div>
- <div class="form-row">
- <label for="node-input-timer"><i class="fa fa-clock-o"></i> <span data-i18n="exec.label.timeout"></span></label>
- <input type="text" id="node-input-timer" style="width:65px;" data-i18n="[placeholder]exec.label.timeoutplace"> seconds
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('exec',{
- category: 'advanced-function',
- color:"darksalmon",
- defaults: {
- command: {value:"",required:true},
- addpay: {value:true},
- append: {value:""},
- useSpawn: {value:""},
- timer: {value:""},
- name: {value:""}
- },
- inputs:1,
- outputs:3,
- icon: "arrow-in.png",
- align: "right",
- label: function() {
- return this.name||this.command;
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="exec">
- <p>Calls out to a system command.<br/></p>
- <p>Provides 3 outputs: stdout, stderr, and return code.</p>
- <p>By default uses the <code>exec</code> system call which calls the command, then gets a callback
- on completion, returning the complete result in one message, along with any errors.</p>
- <p>Optionally can use <code>spawn</code> instead, which returns the output from stdout and stderr
- as the command runs (usually one line at a time). On completion it then returns a return code
- (on the 3rd output).</p>
- <p>The optional append gets added to the command after <code>msg.payload</code> - so you can do
- things like pipe the result to another command.</p>
- <p>Commands or parameters with spaces should be enclosed in quotes - <i>"This is a single parameter"</i></p>
- <p>If stdout is binary a <i>buffer</i> is returned - otherwise returns a <i>string</i>.</p>
- <p>The blue status icon will be visible while the node is active.</p>
- <p>If running a Python app you may need to use the <code>-u</code> parameter to stop the output being buffered.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="function">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row" style="margin-bottom: 0px;">
- <label for="node-input-func"><i class="fa fa-wrench"></i> <span data-i18n="function.label.function"></span></label>
- <input type="hidden" id="node-input-func" autofocus="autofocus">
- <input type="hidden" id="node-input-noerr">
- </div>
- <div class="form-row node-text-editor-row">
- <div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
- </div>
- <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-tips"><span data-i18n="function.tip"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('function',{
- color:"#fdd0a2",
- category: 'function',
- defaults: {
- name: {value:""},
- func: {value:"\nreturn msg;"},
- outputs: {value:1},
- noerr: {value:0,required:true,validate:function(v){ return ((!v) || (v === 0)) ? true : false; }}
- },
- inputs:1,
- outputs:1,
- icon: "function.png",
- label: function() {
- return this.name;
- },
- oneditprepare: function() {
- var that = this;
- $( "#node-input-outputs" ).spinner({
- min:1
- });
- this.editor = RED.editor.createEditor({
- id: 'node-input-func-editor',
- mode: 'ace/mode/javascript',
- value: $("#node-input-func").val(),
- 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
- }
- });
- RED.library.create({
- url:"functions", // where to get the data from
- type:"function", // the type of object the library is for
- editor:this.editor, // the field name the main text body goes to
- mode:"ace/mode/javascript",
- fields:['name','outputs']
- });
- this.editor.focus();
- },
- oneditsave: function() {
- var annot = this.editor.getSession().getAnnotations();
- this.noerr = 0;
- $("#node-input-noerr").val(0);
- for (var k=0; k < annot.length; k++) {
- //console.log(annot[k].type,":",annot[k].text, "on line", annot[k].row);
- if (annot[k].type === "error") {
- $("#node-input-noerr").val(annot.length);
- this.noerr = annot.length;
- }
- }
- $("#node-input-func").val(this.editor.getValue());
- delete this.editor;
- },
- oneditresize: function(size) {
- var rows = $("#dialog-form>div:not(.node-text-editor-row)");
- var height = $("#dialog-form").height();
- for (var i=0;i<rows.size();i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-text-editor-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $(".node-text-editor").css("height",height+"px");
- this.editor.resize();
- }
- });
- </script>
- <script type="text/x-red" data-help-name="function">
- <p>A function block where you can write code to do more interesting things.</p>
- <p>The message is passed in as a JavaScript object called <code>msg</code>.</p>
- <p>By convention it will have a <code>msg.payload</code> property containing
- the body of the message.</p>
- <h4>Logging and Error Handling</h4>
- <p>To log any information, or report an error, the following functions are available:</p>
- <ul>
- <li><code>node.log("Log")</code></li>
- <li><code>node.warn("Warning")</code></li>
- <li><code>node.error("Error")</code></li>
- </ul>
- </p>
- <p>The Catch node can also be used to handle errors. To invoke a Catch node,
- pass <code>msg</code> as a second argument to <code>node.error</code>:</p>
- <pre>node.error("Error",msg)</pre>
- <h4>Sending messages</h4>
- <p>The function can either return the messages it wants to pass on to the next nodes
- in the flow, or can call <code>node.send(messages)</code>.</p>
- <p>It can return/send:</p>
- <ul>
- <li>a single message object - passed to nodes connected to the first output</li>
- <li>an array of message objects - passed to nodes connected to the corresponding outputs</li>
- </ul>
- <p>If any element of the array is itself an array of messages, multiple
- messages are sent to the corresponding output.</p>
- <p>If null is returned, either by itself or as an element of the array, no
- message is passed on.</p>
- <p>See the <a target="_blank" href="http://nodered.org/docs/writing-functions.html">online documentation</a> for more help.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="template">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row">
- <label for="node-input-field"><i class="fa fa-edit"></i> <span data-i18n="template.label.property"></span></label>
- <input type="text" id="node-input-field" placeholder="payload" style="width:250px;">
- <input type="hidden" id="node-input-fieldType">
- </div>
- <div class="form-row" style="position: relative; margin-bottom: 0px;">
- <label for="node-input-template"><i class="fa fa-file-code-o"></i> <span data-i18n="template.label.template"></span></label>
- <input type="hidden" id="node-input-template" autofocus="autofocus">
- <div style="position: absolute; right:0;display:inline-block; text-align: right; font-size: 0.8em;">
- <span data-i18n="template.label.format"></span>:
- <select id="node-input-format" style="width:110px; font-size: 10px !important; height: 24px; padding:0;">
- <option value="handlebars">mustache</option>
- <option value="html">HTML</option>
- <option value="json">JSON</option>
- <option value="javascript">Javascript</option>
- <option value="css">CSS</option>
- <option value="markdown">Markdown</option>
- <option value="yaml">YAML</option>
- <option value="text">none</option>
- </select>
- </div>
- </div>
- <div class="form-row node-text-editor-row">
- <div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-template-editor" ></div>
- </div>
- <div class="form-row">
- <label for="node-input-syntax"><i class="fa fa-code"></i> <span data-i18n="template.label.syntax"></span></label>
- <select id="node-input-syntax" style="width:180px;">
- <option value="mustache" data-i18n="template.label.mustache"></option>
- <option value="plain" data-i18n="template.label.plain"></option>
- </select>
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('template',{
- color:"rgb(243, 181, 103)",
- category: 'function',
- defaults: {
- name: {value:""},
- field: {value:"payload", validate: RED.validators.typedInput("fieldType")},
- fieldType: {value:"msg"},
- format: {value:"handlebars"},
- syntax: {value:"mustache"},
- template: {value:"This is the payload: {{payload}} !"},
- },
- inputs:1,
- outputs:1,
- icon: "template.png",
- label: function() {
- return this.name;
- },
- oneditprepare: function() {
- var that = this;
- if (!this.fieldType) {
- this.fieldType = 'msg';
- }
- if (!this.syntax) {
- this.syntax = 'mustache';
- $("#node-input-syntax").val(this.syntax);
- }
- $("#node-input-field").typedInput({
- default: 'msg',
- types: ['msg','flow','global'],
- typeField: $("#node-input-fieldType")
- });
- this.editor = RED.editor.createEditor({
- id: 'node-input-template-editor',
- mode: 'ace/mode/html',
- value: $("#node-input-template").val()
- });
- RED.library.create({
- url:"functions", // where to get the data from
- type:"function", // the type of object the library is for
- editor:that.editor, // the field name the main text body goes to
- fields:['name','outputs']
- });
- this.editor.focus();
- $("#node-input-format").change(function() {
- var mod = "ace/mode/"+$("#node-input-format").val();
- that.editor.getSession().setMode({
- path: mod,
- v: Date.now()
- })
- });
- },
- oneditsave: function() {
- $("#node-input-template").val(this.editor.getValue())
- delete this.editor;
- },
- oneditresize: function(size) {
- var rows = $("#dialog-form>div:not(.node-text-editor-row)");
- var height = $("#dialog-form").height();
- for (var i=0;i<rows.size();i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-text-editor-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $(".node-text-editor").css("height",height+"px");
- this.editor.resize();
- }
- });
- </script>
- <script type="text/x-red" data-help-name="template">
- <p>Sets a property based on the provided template.</p>
- <p>By default this uses the <i><a href="http://mustache.github.io/mustache.5.html" target="_blank">mustache</a></i>
- format, but this can be switched off if required.</p>
- <p>For example, when a template of:
- <pre>Hello {{name}}. Today is {{date}}</pre>
- <p>receives a message containing:
- <pre>{
- name: "Fred",
- date: "Monday"
- payload: ...
- }</pre>
- <p>The resulting property will be:
- <pre>Hello Fred. Today is Monday</pre>
- <p>It is possible to use property from flow context or global context. Just use <code>{{flow.name}}</code> or <code>{{global.name}}</code>.
- <p>By default, mustache will escape any HTML entities in the values it substitutes.
- To prevent this, use <code>{{{triple}}}</code> braces.
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="delay">
- <div class="form-row">
- <label for="node-input-pauseType"><i class="fa fa-tasks"></i> <span data-i18n="delay.action"></span></label>
- <select id="node-input-pauseType" style="width:270px !important">
- <option value="delay" data-i18n="delay.delaymsg"></option>
- <option value="random" data-i18n="delay.randomdelay"></option>
- <option value="rate" data-i18n="delay.limitrate"></option>
- <option value="queue" data-i18n="delay.fairqueue"></option>
- <option value="timed" data-i18n="delay.timedqueue"></option>
- </select>
- </div>
- <div id="delay-details" class="form-row">
- <label for="node-input-timeout"><i class="fa fa-clock-o"></i> <span data-i18n="delay.for"></span></label>
- <input type="text" id="node-input-timeout" placeholder="Time" style="text-align:end; width:50px !important">
- <select id="node-input-timeoutUnits" style="width:200px !important">
- <option value="milliseconds" data-i18n="delay.milisecs"></option>
- <option value="seconds" data-i18n="delay.secs"></option>
- <option value="minutes" data-i18n="delay.mins"></option>
- <option value="hours" data-i18n="delay.hours"></option>
- <option value="days" data-i18n="delay.days"></option>
- </select>
- </div>
- <div id="rate-details" class="form-row">
- <label for="node-input-rate"><i class="fa fa-clock-o"></i> <span data-i18n="delay.rate"></span></label>
- <input type="text" id="node-input-rate" placeholder="1" style="text-align:end; width:30px !important">
- <label for="node-input-rateUnits"><span data-i18n="delay.msgper"></span></label>
- <input type="text" id="node-input-nbRateUnits" placeholder="1" style="text-align:end; width:30px !important">
- <select id="node-input-rateUnits" style="width:110px !important">
- <option value="second" data-i18n="delay.label.units.second.singular"></option>
- <option value="minute" data-i18n="delay.label.units.minute.singular"></option>
- <option value="hour" data-i18n="delay.label.units.hour.singular"></option>
- <option value="day" data-i18n="delay.label.units.day.singular"></option>
- </select>
- <br/>
- <div id="node-input-dr"><input style="margin: 20px 0 20px 100px; width: 30px;" type="checkbox" id="node-input-drop"><label style="width: 250px;" for="node-input-drop"><span data-i18n="delay.dropmsg"></span></label></div>
- </div>
- <div id="random-details" class="form-row">
- <label for="node-input-randomFirst"><i class="fa fa-clock-o"></i> <span data-i18n="delay.between"></span></label>
- <input type="text" id="node-input-randomFirst" placeholder="" style="text-align:end; width:30px !important">
- &
- <input type="text" id="node-input-randomLast" placeholder="" style="text-align:end; width:30px !important">
- <select id="node-input-randomUnits" style="width:140px !important">
- <option value="milliseconds" data-i18n="delay.milisecs"></option>
- <option value="seconds" data-i18n="delay.secs"></option>
- <option value="minutes" data-i18n="delay.mins"></option>
- <option value="hours" data-i18n="delay.hours"></option>
- <option value="days" data-i18n="delay.days"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('delay',{
- category: 'function',
- color:"#E6E0F8",
- defaults: {
- name: {value:""},
- pauseType: {value:"delay", required:true},
- timeout: {value:"5", required:true, validate:RED.validators.number()},
- timeoutUnits: {value:"seconds"},
- rate: {value:"1", required:true, validate:RED.validators.number()},
- nbRateUnits: {value:"1", required:false, validate:RED.validators.regex(/\d+|/)},
- rateUnits: {value: "second"},
- randomFirst: {value:"1", required:true, validate:RED.validators.number()},
- randomLast: {value:"5", required:true, validate:RED.validators.number()},
- randomUnits: {value: "seconds"},
- drop: {value:false}
- },
- inputs:1,
- outputs:1,
- icon: "timer.png",
- label: function() {
- if (this.pauseType == "delay") {
- var units = this.timeoutUnits ? this.timeoutUnits.charAt(0) : "s";
- if (this.timeoutUnits == "milliseconds") { units = "ms"; }
- return this.name||this._("delay.label.delay")+" "+this.timeout+" "+units;
- } else if (this.pauseType == "rate") {
- var units = this.rateUnits ? (this.nbRateUnits > 1 ? this.nbRateUnits : '') + this.rateUnits.charAt(0) : "s";
- return this.name||this._("delay.label.limit")+" "+this.rate+" msg/"+units;
- } else if (this.pauseType == "random") {
- return this.name || this._("delay.label.random");
- }
- else if (this.pauseType == "timed") {
- var units = '';
- if (this.nbRateUnits > 1) {
- units = this.nbRateUnits + ' ' + this._("delay.label.units." + this.rateUnits + ".plural");
- } else {
- units = this._("delay.label.units." + this.rateUnits + ".singular");
- }
- return this.name || this.rate + " " + this._("delay.label.timed") + ' ' + units;
- }
- else {
- var units = this.rateUnits ? (this.nbRateUnits > 1 ? this.nbRateUnits : '') + this.rateUnits.charAt(0) : "s";
- return this.name || this._("delay.label.queue")+" "+this.rate+" msg/"+units;
- }
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var node = this;
- $( "#node-input-timeout" ).spinner({min:1});
- $( "#node-input-rate" ).spinner({min:1});
- $( "#node-input-nbRateUnits" ).spinner({min:1});
- $( "#node-input-randomFirst" ).spinner({min:0});
- $( "#node-input-randomLast" ).spinner({min:1});
- $('.ui-spinner-button').click(function() {
- $(this).siblings('input').change();
- });
- $( "#node-input-nbRateUnits" ).on('change keyup', function() {
- var $this = $(this);
- var val = parseInt($this.val());
- var type = "singular";
- if(val > 1) {
- type = "plural";
- }
- if($this.attr("data-type") == type) {
- return;
- }
- $this.attr("data-type", type);
- $("#node-input-rateUnits option").each(function () {
- var $option = $(this);
- var key = "delay.label.units." + $option.val() + "." + type;
- $option.attr('data-i18n', 'node-red:' + key);
- $option.html(node._(key));
- })
- });
- if (this.pauseType == "delay") {
- $("#delay-details").show();
- $("#rate-details").hide();
- $("#random-details").hide();
- $("#node-input-dr").hide();
- } else if (this.pauseType == "rate") {
- $("#delay-details").hide();
- $("#rate-details").show();
- $("#random-details").hide();
- $("#node-input-dr").show();
- } else if (this.pauseType == "random") {
- $("#delay-details").hide();
- $("#rate-details").hide();
- $("#random-details").show();
- $("#node-input-dr").hide();
- } else if (this.pauseType == "queue") {
- $("#delay-details").hide();
- $("#rate-details").show();
- $("#random-details").hide();
- $("#node-input-dr").hide();
- } else if (this.pauseType == "timed") {
- $("#delay-details").hide();
- $("#rate-details").show();
- $("#random-details").hide();
- $("#node-input-dr").hide();
- }
- if (!this.timeoutUnits) {
- $("#node-input-timeoutUnits option").filter(function() {
- return $(this).val() == 'seconds';
- }).attr('selected', true);
- }
- if (!this.randomUnits) {
- $("#node-input-randomUnits option").filter(function() {
- return $(this).val() == 'seconds';
- }).attr('selected', true);
- }
- $("#node-input-pauseType").on("change",function() {
- if (this.value == "delay") {
- $("#delay-details").show();
- $("#rate-details").hide();
- $("#random-details").hide();
- $("#node-input-dr").hide();
- } else if (this.value == "rate") {
- $("#delay-details").hide();
- $("#rate-details").show();
- $("#random-details").hide();
- $("#node-input-dr").show();
- } else if (this.value == "random") {
- $("#delay-details").hide();
- $("#rate-details").hide();
- $("#random-details").show();
- $("#node-input-dr").hide();
- } else if (this.value == "queue") {
- $("#delay-details").hide();
- $("#rate-details").show();
- $("#random-details").hide();
- $("#node-input-dr").hide();
- } else if (this.value == "timed") {
- $("#delay-details").hide();
- $("#rate-details").show();
- $("#random-details").hide();
- $("#node-input-dr").hide();
- }
- });
- }
- });
- </script>
- <script type="text/x-red" data-help-name="delay">
- <p>Introduces a delay into a flow or rate limits messages.</p>
- <p>The default delay is 5 seconds and rate limit of 1 msg/second, but both can be configured.</p>
- <p>When set to rate limit messages, they are spread across the configured time period. It can
- also be set to discard any intermediate messages that arrive.</p>
- <p>The "topic based fair queue" adds messages to a release queue tagged by their <code>msg.topic</code> property.
- At each "tick", derived from the rate, the next "topic" is released.
- Any messages arriving on the same topic before release replace those in that position in the queue.
- So each "topic" gets a turn - but the most recent value is always the one sent.</p>
- <p>The "timed release queue" adds messages to an array based on their <code>msg.topic</code> property.
- At each "tick", all the latest messages are released. Any new messages arriving before release will
- replace those of the same topic.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="trigger">
- <div class="form-row">
- <label data-i18n="trigger.send" for="node-input-op1"></label>
- <input type="hidden" id="node-input-op1type">
- <input style="width: 70%" type="text" id="node-input-op1">
- </div>
- <div class="form-row">
- <label data-i18n="trigger.then"></label>
- <select id="node-then-type" style="width:70%;">
- <option value="block" data-i18n="trigger.wait-reset"></option>
- <option value="wait" data-i18n="trigger.wait-for"></option>
- </select>
- </div>
- <div class="form-row node-type-wait">
- <label></label>
- <input type="text" id="node-input-duration" style="text-align:end; width:70px !important">
- <select id="node-input-units" style="width:140px !important">
- <option value="ms" data-i18n="trigger.duration.ms"></option>
- <option value="s" data-i18n="trigger.duration.s"></option>
- <option value="min" data-i18n="trigger.duration.m"></option>
- <option value="hr" data-i18n="trigger.duration.h"></option>
- </select>
- </div>
- <div class="form-row node-type-wait">
- <label></label>
- <input type="checkbox" id="node-input-extend" style="margin-left: 0px; vertical-align: top; width: auto !important;"> <label style="width:auto !important;" for="node-input-extend" data-i18n="trigger.extend"></label>
- </div>
- <div class="form-row node-type-wait">
- <label data-i18n="trigger.then-send"></label>
- <input type="hidden" id="node-input-op2type">
- <input style="width: 70%" type="text" id="node-input-op2">
- </div>
- <div class="form-row">
- <label data-i18n="trigger.label.reset" style="width:auto"></label>
- <div style="display:inline-block; width:70%;vertical-align:top">
- <ul>
- <li data-i18n="trigger.label.resetMessage"></li>
- <li><span data-i18n="trigger.label.resetPayload"></span> <input type="text" id="node-input-reset" style="width:150px" data-i18n="[placeholder]trigger.label.resetprompt"></li>
- </ul>
- </div>
- <br/>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"></input>
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('trigger',{
- category: 'function',
- color:"#E6E0F8",
- defaults: {
- op1: {value:"1", validate: RED.validators.typedInput("op1type")},
- op2: {value:"0", validate: RED.validators.typedInput("op2type")},
- op1type: {value:"val"},
- op2type: {value:"val"},
- duration: {value:"250",required:true,validate:RED.validators.number()},
- extend: {value:"false"},
- units: {value:"ms"},
- reset: {value:""},
- name: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "trigger.png",
- label: function() {
- if (this.duration > 0) {
- return this.name|| this._("trigger.label.trigger")+" "+this.duration+this.units;
- }
- else {
- return this.name|| this._("trigger.label.trigger-block");
- }
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- $("#node-then-type").change(function() {
- if ($(this).val() == "block") {
- $(".node-type-wait").hide();
- } else {
- $(".node-type-wait").show();
- }
- });
- if (this.op1type === 'val') {
- $("#node-input-op1type").val('str');
- }
- if (this.op2type === 'val') {
- $("#node-input-op2type").val('str');
- }
- var optionNothing = {value:"nul",label:this._("trigger.output.nothing"),hasValue:false};
- var optionPayload = {value:"pay",label:this._("trigger.output.existing"),hasValue:false}
- var optionOriginalPayload = {value:"pay",label:this._("trigger.output.original"),hasValue:false}
- var optionLatestPayload = {value:"payl",label:this._("trigger.output.latest"),hasValue:false}
- $("#node-input-op1").typedInput({
- default: 'str',
- typeField: $("#node-input-op1type"),
- types:['flow','global','str','num','bool','json',
- optionPayload,
- optionNothing
- ]
- });
- $("#node-input-op2").typedInput({
- default: 'str',
- typeField: $("#node-input-op2type"),
- types:['flow','global','str','num','bool','json',
- optionOriginalPayload,
- optionLatestPayload,
- optionNothing
- ]
- });
- if (this.duration == "0") {
- $("#node-then-type").val("block");
- } else {
- $("#node-then-type").val("wait");
- }
- $("#node-then-type").change();
- if (this.extend === "true" || this.extend === true) {
- $("#node-input-extend").prop("checked",true);
- } else {
- $("#node-input-extend").prop("checked",false);
- }
- },
- oneditsave: function() {
- if ($("#node-then-type").val() == "block") {
- $("#node-input-duration").val("0");
- }
- }
- });
- </script>
- <script type="text/x-red" data-help-name="trigger">
- <p>Creates two messages on the output separated by a timeout whenever <i>any</i> <code>msg</code> arrives on the input.</p>
- <p>For example, this can be used to toggle a Raspberry PI GPIO pin on and off.</p>
- <p>The two output states can be specified as can the duration of the timer.
- Either output can be set to a value, or templated from the inbound
- <code>msg</code> using mustache syntax. <pre>The payload is {{payload}}</pre></p>
- <p>If the <code>msg.payload</code> is an object then setting the output to
- <i>existing payload</i> will pass the complete payload object through.</p>
- <p>Optionally the timer can be extended by being retriggered... or not.</p>
- <p>By setting the first output to <i>nothing</i>, and selecting extend timer - a watchdog timer can be created.
- No output will happen as long as repeated inputs occur within the timeout period.</p>
- <p>Setting the timer to 0 creates an "infinite" timeout - the first output will happen but the second
- never will, and neither can the first be retriggered - so a true one shot.</p>
- <p>If a <code>msg.reset</code> property is present, or the <code>msg.payload</code>
- matches the optional reset value, any timeout currently in progress
- will be cleared and the second output will not happen.</p>
- <p>The blue status icon will be visible while the node is active.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="comment">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-comment"></i> <span data-i18n="comment.label.title"></span></label>
- <input type="text" id="node-input-name">
- </div>
- <div class="form-row" style="margin-bottom: 0px;">
- <label for="node-input-info" style="width: 100% !important;"><i class="fa fa-comments"></i> <span data-i18n="comment.label.body"></span></label>
- <input type="hidden" id="node-input-info" autofocus="autofocus">
- </div>
- <div class="form-row node-text-editor-row">
- <div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-info-editor"></div>
- </div>
- <div class="form-tips" data-i18n="[html]comment.tip"></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('comment',{
- category: 'function',
- color:"#ffffff",
- defaults: {
- name: {value:""},
- info: {value:""}
- },
- inputs:0,
- outputs:0,
- icon: "comment.png",
- label: function() {
- return this.name||"";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- info: function() {
- return (this.name?"# "+this.name+"\n":"")+(this.info||"");
- },
- oneditprepare: function() {
- var that = this;
- this.editor = RED.editor.createEditor({
- id: 'node-input-info-editor',
- mode: 'ace/mode/markdown',
- value: $("#node-input-info").val()
- });
- this.editor.focus();
- },
- oneditsave: function() {
- $("#node-input-info").val(this.editor.getValue());
- delete this.editor;
- },
- oneditresize: function(size) {
- var rows = $("#dialog-form>div:not(.node-text-editor-row)");
- var height = $("#dialog-form").height();
- for (var i=0;i<rows.size();i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-text-editor-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $(".node-text-editor").css("height",height+"px");
- this.editor.resize();
- }
- });
- </script>
- <script type="text/x-red" data-help-name="comment">
- <p>A node you can use to add comments to your flows.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="unknown">
- <div class="form-tips"><span data-i18n="[html]unknown.tip"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('unknown',{
- category: 'unknown',
- color:"#fff0f0",
- defaults: {
- name: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "",
- label: function() {
- return "("+this.name+")"||this._("unknown.label.unknown");
- },
- labelStyle: function() {
- return "node_label_unknown";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="unknown">
- <p>This node is a type unknown to your installation of Node-RED.</p>
- <p><i>If you deploy with the node in this state, it's configuration will be preserved, but
- the flow will not start until the missing type is installed.</i></p>
- <p>It is possible this node type is already installed, but is missing a dependency. Check the Node-RED start-up log for
- any error messages associated with the missing node type. Use <b>npm install <module></b> to install any missing modules
- and restart Node-RED and reimport the nodes.</p>
- <p>Otherwise, you should contact the author of the flow to obtain a copy of the missing node type.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="tls-config">
- <div class="form-row">
- <label style="width: 120px;" for="node-config-input-cert"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.cert"></span></label>
- <input style="width: 60%;" type="text" id="node-config-input-cert" data-i18n="[placeholder]tls.placeholder.cert">
- </div>
- <div class="form-row">
- <label style="width: 120px;" for="node-config-input-key"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.key"></span></label>
- <input style="width: 60%;" type="text" id="node-config-input-key" data-i18n="[placeholder]tls.placeholder.key">
- </div>
- <div class="form-row">
- <label style="width: 120px;" for="node-config-input-ca"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.ca"></span></label>
- <input style="width: 60%;" type="text" id="node-config-input-ca" data-i18n="[placeholder]tls.placeholder.ca">
- </div>
- <div class="form-row">
- <input type="checkbox" id="node-config-input-verifyservercert" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-config-input-verifyservercert" style="width: 70%;" data-i18n="tls.label.verify-server-cert"></label>
- </div>
- <div class="form-row">
- <label style="width: 120px;" for="node-config-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input style="width: 60%;" type="text" id="node-config-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('tls-config',{
- category: 'config',
- defaults: {
- name: {value:""},
- cert: {value:"", validate: function(v) {
- var currentKey = $("#node-config-input-key").val();
- if (currentKey === undefined) {
- currentKey = this.key;
- }
- return currentKey === '' || v != '';
- }},
- key: {value:"", validate: function(v) {
- var currentCert = $("#node-config-input-cert").val();
- if (currentCert === undefined) {
- currentCert = this.cert;
- }
- return currentCert === '' || v != '';
- }},
- ca: {value:""},
- verifyservercert: {value: true}
- },
- label: function() {
- return this.name || this._("tls.tls");
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="tls-config">
- <p>Configuration options for TLS connections.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="mqtt in">
- <div class="form-row">
- <label for="node-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
- <input type="text" id="node-input-broker">
- </div>
- <div class="form-row">
- <label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
- <input type="text" id="node-input-topic" data-i18n="[placeholder]common.label.topic">
- </div>
- <div class="form-row">
- <label for="node-input-qos"><i class="fa fa-empire"></i> <span data-i18n="mqtt.label.qos"></span></label>
- <select id="node-input-qos" style="width:125px !important">
- <option value="0">0</option>
- <option value="1">1</option>
- <option value="2">2</option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('mqtt in',{
- category: 'input',
- defaults: {
- name: {value:""},
- topic: {value:"",required:true,validate: RED.validators.regex(/^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/)},
- qos: {value: "2"},
- broker: {type:"mqtt-broker", required:true}
- },
- color:"#d8bfd8",
- inputs:0,
- outputs:1,
- icon: "bridge.png",
- label: function() {
- return this.name||this.topic||"mqtt";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- if (this.qos === undefined) {
- $("#node-input-qos").val("2");
- }
- }
- });
- </script>
- <script type="text/x-red" data-template-name="mqtt out">
- <div class="form-row">
- <label for="node-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
- <input type="text" id="node-input-broker">
- </div>
- <div class="form-row">
- <label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
- <input type="text" id="node-input-topic" data-i18n="[placeholder]common.label.topic">
- </div>
- <div class="form-row">
- <label for="node-input-qos"><i class="fa fa-empire"></i> <span data-i18n="mqtt.label.qos"></span></label>
- <select id="node-input-qos" style="width:125px !important">
- <option value=""></option>
- <option value="0">0</option>
- <option value="1">1</option>
- <option value="2">2</option>
- </select>
- <i class="fa fa-history"></i> <span data-i18n="mqtt.retain"></span> <select id="node-input-retain" style="width:125px !important">
- <option value=""></option>
- <option value="false" data-i18n="mqtt.false"></option>
- <option value="true" data-i18n="mqtt.true"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips"><span data-i18n="mqtt.tip"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('mqtt out',{
- category: 'output',
- defaults: {
- name: {value:""},
- topic: {value:""},
- qos: {value:""},
- retain: {value:""},
- broker: {type:"mqtt-broker", required:true}
- },
- color:"#d8bfd8",
- inputs:1,
- outputs:0,
- icon: "bridge.png",
- align: "right",
- label: function() {
- return this.name||this.topic||"mqtt";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-template-name="mqtt-broker">
- <div class="form-row">
- <ul style="background: #fff; min-width: 600px; margin-bottom: 20px;" id="node-config-mqtt-broker-tabs"></ul>
- </div>
- <div id="node-config-mqtt-broker-tabs-content" style="min-height: 170px;">
- <div id="mqtt-broker-tab-connection" style="display:none">
- <div class="form-row node-input-broker">
- <label for="node-config-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
- <input class="input-append-left" type="text" id="node-config-input-broker" placeholder="e.g. localhost" style="width: 40%;" >
- <label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> <span data-i18n="mqtt.label.port"></span></label>
- <input type="text" id="node-config-input-port" data-i18n="[placeholder]mqtt.label.port" style="width:45px">
- </div>
- <div class="form-row">
- <input type="checkbox" id="node-config-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-config-input-usetls" style="width: auto" data-i18n="mqtt.label.use-tls"></label>
- <div id="node-config-row-tls" class="hide">
- <label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-config-input-tls"><span data-i18n="mqtt.label.tls-config"></span></label><input style="width: 300px;" type="text" id="node-config-input-tls">
- </div>
- </div>
- <div class="form-row">
- <label for="node-config-input-clientid"><i class="fa fa-tag"></i> <span data-i18n="mqtt.label.clientid"></span></label>
- <input type="text" id="node-config-input-clientid" data-i18n="[placeholder]mqtt.placeholder.clientid">
- </div>
- <div class="form-row">
- <label for="node-config-input-keepalive" style="width: auto"><i class="fa fa-clock-o"></i> <span data-i18n="mqtt.label.keepalive"></span></label>
- <input type="text" id="node-config-input-keepalive" style="width: 50px">
- <input type="checkbox" id="node-config-input-cleansession" style="margin-left: 30px; height: 1em;display: inline-block; width: auto; vertical-align: middle;">
- <label for="node-config-input-cleansession" style="width: auto;" data-i18n="mqtt.label.cleansession"></label>
- </div>
- <div class="form-row">
- <input type="checkbox" id="node-config-input-compatmode" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-config-input-compatmode" style="width: auto;" data-i18n="mqtt.label.compatmode"></label>
- </div>
- </div>
- <div id="mqtt-broker-tab-security" style="display:none">
- <div class="form-row">
- <label for="node-config-input-user"><i class="fa fa-user"></i> <span data-i18n="common.label.username"></span></label>
- <input type="text" id="node-config-input-user">
- </div>
- <div class="form-row">
- <label for="node-config-input-password"><i class="fa fa-lock"></i> <span data-i18n="common.label.password"></span></label>
- <input type="password" id="node-config-input-password">
- </div>
- </div>
- <div id="mqtt-broker-tab-birth" style="display:none">
- <div class="form-row">
- <label for="node-config-input-birthTopic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
- <input type="text" id="node-config-input-birthTopic" data-i18n="[placeholder]mqtt.placeholder.birth-topic">
- </div>
- <div class="form-row">
- <label for="node-config-input-birthQos"><i class="fa fa-empire"></i> <span data-i18n="mqtt.label.qos"></span></label>
- <select id="node-config-input-birthQos" style="width:125px !important">
- <option value="0">0</option>
- <option value="1">1</option>
- <option value="2">2</option>
- </select>
- <i class="fa fa-history"></i> <span data-i18n="mqtt.retain"></span> <select id="node-config-input-birthRetain" style="width:125px !important">
- <option value="false" data-i18n="mqtt.false"></option>
- <option value="true" data-i18n="mqtt.true"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-config-input-birthPayload"><i class="fa fa-envelope"></i> <span data-i18n="common.label.payload"></span></label>
- <input type="text" id="node-config-input-birthPayload" data-i18n="[placeholder]common.label.payload">
- </div>
- </div>
- <div id="mqtt-broker-tab-will" style="display:none">
- <div class="form-row">
- <label for="node-config-input-willTopic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
- <input type="text" id="node-config-input-willTopic" data-i18n="[placeholder]mqtt.placeholder.will-topic">
- </div>
- <div class="form-row">
- <label for="node-config-input-willQos"><i class="fa fa-empire"></i> <span data-i18n="mqtt.label.qos"></span></label>
- <select id="node-config-input-willQos" style="width:125px !important">
- <option value="0">0</option>
- <option value="1">1</option>
- <option value="2">2</option>
- </select>
- <i class="fa fa-history"></i> <span data-i18n="mqtt.retain"></span> <select id="node-config-input-willRetain" style="width:125px !important">
- <option value="false" data-i18n="mqtt.false"></option>
- <option value="true" data-i18n="mqtt.true"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-config-input-willPayload"><i class="fa fa-envelope"></i> <span data-i18n="common.label.payload"></span></label>
- <input type="text" id="node-config-input-willPayload" data-i18n="[placeholder]common.label.payload">
- </div>
- </div>
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('mqtt-broker',{
- category: 'config',
- defaults: {
- broker: {value:"",required:true},
- port: {value:1883,required:true,validate:RED.validators.number()},
- tls: {type:"tls-config",required: false},
- clientid: {value:"", validate: function(v) {
- if ($("#node-config-input-clientid").length) {
- // Currently editing the node
- return $("#node-config-input-cleansession").is(":checked") || (v||"").length > 0;
- } else {
- return (this.cleansession===undefined || this.cleansession) || (v||"").length > 0;
- }
- }},
- usetls: {value: false},
- verifyservercert: { value: false},
- compatmode: { value: true},
- keepalive: {value:60,validate:RED.validators.number()},
- cleansession: {value: true},
- willTopic: {value:""},
- willQos: {value:"0"},
- willRetain: {value:false},
- willPayload: {value:""},
- birthTopic: {value:""},
- birthQos: {value:"0"},
- birthRetain: {value:false},
- birthPayload: {value:""}
- },
- credentials: {
- user: {type:"text"},
- password: {type: "password"}
- },
- label: function() {
- var b = this.broker;
- if (b === "") { b = "undefined"; }
- return (this.clientid?this.clientid+"@":"")+b+":"+this.port;
- },
- oneditprepare: function () {
- var tabs = RED.tabs.create({
- id: "node-config-mqtt-broker-tabs",
- onchange: function(tab) {
- $("#node-config-mqtt-broker-tabs-content").children().hide();
- $("#" + tab.id).show();
- }
- });
- tabs.addTab({
- id: "mqtt-broker-tab-connection",
- label: this._("mqtt.tabs-label.connection")
- });
- tabs.addTab({
- id: "mqtt-broker-tab-security",
- label: this._("mqtt.tabs-label.security")
- });
- tabs.addTab({
- id: "mqtt-broker-tab-birth",
- label: this._("mqtt.tabs-label.birth")
- });
- tabs.addTab({
- id: "mqtt-broker-tab-will",
- label: this._("mqtt.tabs-label.will")
- });
- setTimeout(function() { tabs.resize()},0);
- if (typeof this.cleansession === 'undefined') {
- this.cleansession = true;
- $("#node-config-input-cleansession").prop("checked",true);
- }
- if (typeof this.usetls === 'undefined') {
- this.usetls = false;
- $("#node-config-input-usetls").prop("checked",false);
- }
- if (typeof this.compatmode === 'undefined') {
- this.compatmode = true;
- $("#node-config-input-compatmode").prop('checked', true);
- }
- if (typeof this.keepalive === 'undefined') {
- this.keepalive = 15;
- $("#node-config-input-keepalive").val(this.keepalive);
- }
- if (typeof this.willQos === 'undefined') {
- this.willQos = "0";
- $("#node-config-input-willQos").val("0");
- }
- if (typeof this.birthQos === 'undefined') {
- this.birthQos = "0";
- $("#node-config-input-birthQos").val("0");
- }
- function updateTLSOptions() {
- if ($("#node-config-input-usetls").is(':checked')) {
- $("#node-config-row-tls").show();
- } else {
- $("#node-config-row-tls").hide();
- }
- }
- updateTLSOptions();
- $("#node-config-input-usetls").on("click",function() {
- updateTLSOptions();
- });
- var node = this;
- function updateClientId() {
- if ($("#node-config-input-cleansession").is(":checked")) {
- $("#node-config-input-clientid").attr("placeholder",node._("mqtt.placeholder.clientid"));
- } else {
- $("#node-config-input-clientid").attr("placeholder",node._("mqtt.placeholder.clientid-nonclean"));
- }
- $("#node-config-input-clientid").change();
- }
- setTimeout(updateClientId,0);
- $("#node-config-input-cleansession").on("click",function() {
- updateClientId();
- });
- },
- oneditsave: function() {
- if (!$("#node-config-input-usetls").is(':checked')) {
- $("#node-config-input-tls").val("");
- }
- }
- });
- </script>
- <script type="text/x-red" data-help-name="mqtt in">
- <p>Connects to a broker and subscribes to the specified topic.</p>
- <p>Outputs a message with the properties:</p>
- <ul>
- <li><code>msg.topic</code></li>
- <li><code>msg.payload</code></li>
- <li><code>msg.qos</code></li>
- <li><code>msg.retain</code></li>
- </ul>
- <p><code>msg.payload</code> will be a String, unless it is detected as a binary buffer.</p>
- </script><script type="text/x-red" data-help-name="mqtt out">
- <p>Connects to a MQTT broker and publishes messages.</p>
- <p><code>msg.payload</code> is used as the payload of the published message.
- If it contains an Object it will be converted to JSON before being sent.
- </p>
- <p>The topic used can be configured in the node or, if left blank, can be set
- by <code>msg.topic</code>.</p>
- <p>Likewise the QoS and retain values can be configured in the node or, if left
- blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.
- By default, messages are published at QoS 0 with the retain flag set to false.</p>
- </script><script type="text/x-red" data-help-name="mqtt-broker">
- <p>A minimum MQTT broker connection requires only a broker server address to be added to the default configuration.</p>
- <p>To secure the connection with SSL/TLS, a TLS Configuration must also be configured and selected.</p>
- <p>If you create a Client ID it must be unique to the broker you are connecting to.</p>
- <p>For more information about MQTT see the <a href="http://www.eclipse.org/paho/" target="_blank">Eclipse Paho</a> site.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="http in">
- <div class="form-row">
- <label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
- <select type="text" id="node-input-method" style="width:70%;">
- <option value="get">GET</option>
- <option value="post">POST</option>
- <option value="put">PUT</option>
- <option value="delete">DELETE</option>
- <option value="patch">PATCH</option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="httpin.label.url"></span></label>
- <input id="node-input-url" type="text" placeholder="/url">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row row-swagger-doc">
- <label for="node-input-swaggerDoc"><i class="fa fa-file-text-o"></i> <span data-i18n="httpin.label.doc"></span></label>
- <input type="text" id="node-input-swaggerDoc">
- </div>
- <div id="node-input-tip" class="form-tips"><span data-i18n="httpin.tip.in"></span><code><span id="node-input-path"></span></code>.</div>
- </script>
- <script type="text/x-red" data-template-name="http response">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips"><span data-i18n="[html]httpin.tip.res"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('http in',{
- category: 'input',
- color:"rgb(231, 231, 174)",
- defaults: {
- name: {value:""},
- url: {value:"",required:true},
- method: {value:"get",required:true},
- swaggerDoc: {type:"swagger-doc", required:false}
- },
- inputs:0,
- outputs:1,
- icon: "white-globe.png",
- label: function() {
- if (this.name) {
- return this.name;
- } else if (this.url) {
- var root = RED.settings.httpNodeRoot;
- if (root.slice(-1) != "/") {
- root = root+"/";
- }
- if (this.url.charAt(0) == "/") {
- root += this.url.slice(1);
- } else {
- root += this.url;
- }
- return "["+this.method+"] "+root;
- } else {
- return "http";
- }
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var root = RED.settings.httpNodeRoot;
- if (root.slice(-1) == "/") {
- root = root.slice(0,-1);
- }
- if (root == "") {
- $("#node-input-tip").hide();
- } else {
- $("#node-input-path").html(root);
- $("#node-input-tip").show();
- }
- if(!RED.nodes.getType("swagger-doc")){
- $('.row-swagger-doc').hide();
- }
- }
- });
- RED.nodes.registerType('http response',{
- category: 'output',
- color:"rgb(231, 231, 174)",
- defaults: {
- name: {value:""}
- },
- inputs:1,
- outputs:0,
- align: "right",
- icon: "white-globe.png",
- label: function() {
- return this.name||"http";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="http in">
- <p>Provides an input node for http requests, allowing the creation of simple web services.</p>
- <p>The resulting message has the following properties:
- <ul>
- <li>msg.req : <a href="http://expressjs.com/api.html#req">http request</a></li>
- <li>msg.res : <a href="http://expressjs.com/api.html#res">http response</a></li>
- </ul>
- </p>
- <p>For POST/PUT requests, the body is available under <code>msg.req.body</code>. This
- uses the <a href="http://expressjs.com/api.html#bodyParser">Express bodyParser middleware</a> to parse the content to a JSON object.
- </p>
- <p>
- By default, this expects the body of the request to be url encoded:
- <pre>foo=bar&this=that</pre>
- </p>
- <p>
- To send JSON encoded data to the node, the content-type header of the request must be set to
- <code>application/json</code>.
- </p>
- <p>
- <b>Note: </b>This node does not send any response to the http request.
- This should be done with a subsequent HTTP Response node.
- </p>
- </script><script type="text/x-red" data-help-name="http response">
- <p>Sends responses back to http requests received from an HTTP Input node.</p>
- <p>The response can be customised using the following message properties:</p>
- <ul>
- <li><code>payload</code> is sent as the body of the response</li>
- <li><code>statusCode</code>, if set, is used as the response status code (default: 200)</li>
- <li><code>headers</code>, if set, should be an object containing field/value
- pairs to be added as response headers.</li>
- <li><code>cookies</code>, if set, can be used to set or delete cookies.
- </ul>
- <h3>Cookie handling</h3>
- <p>The <code>cookies</code> property must be an object of name/value pairs.
- The value can be either a string to set the value of the cookie with default
- options, or it can be an object of options.<p>
- <p>The following example sets two cookies - one called <code>name</code> with
- a value of <code>nick</code>, the other called <code>session</code> with a
- value of <code>1234</code> and an expiry set to 15 minutes.</p>
- <pre>
- msg.cookies = {
- name: 'nick',
- session: {
- value: '1234',
- maxAge: 900000
- }
- }</pre>
- <p>The valid options include:</p>
- <ul>
- <li><code>domain</code> - (String) domain name for the cookie</li>
- <li><code>expires</code> - (Date) expiry date in GMT. If not specified or set to 0, creates a session cookie</li>
- <li><code>maxAge</code> - (String) expiry date as relative to the current time in milliseconds</li>
- <li><code>path</code> - (String) path for the cookie. Defaults to /</li>
- <li><code>value</code> - (String) the value to use for the cookie</li>
- </ul>
- <p>To delete a cookie, set its <code>value</code> to <code>null</code>.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="http request">
- <div class="form-row">
- <label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
- <select type="text" id="node-input-method" style="width:70%;">
- <option value="GET">GET</option>
- <option value="POST">POST</option>
- <option value="PUT">PUT</option>
- <option value="DELETE">DELETE</option>
- <option value="use" data-i18n="httpin.setby"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="httpin.label.url"></span></label>
- <input id="node-input-url" type="text" placeholder="http://">
- </div>
- <div class="form-row">
- <input type="checkbox" id="node-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-usetls" style="width: auto" data-i18n="httpin.use-tls"></label>
- <div id="node-row-tls" class="hide">
- <label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-input-tls"><span data-i18n="httpin.tls-config"></span></label><input type="text" style="width: 300px" id="node-input-tls">
- </div>
- </div>
- <div class="form-row">
- <input type="checkbox" id="node-input-useAuth" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-useAuth" style="width: 70%;"><span data-i18n="httpin.basicauth"></span></label>
- <div style="margin-left: 20px" class="node-input-useAuth-row hide">
- <div class="form-row">
- <label for="node-input-user"><i class="fa fa-user"></i> <span data-i18n="common.label.username"></span></label>
- <input type="text" id="node-input-user">
- </div>
- <div class="form-row">
- <label for="node-input-password"><i class="fa fa-lock"></i> <span data-i18n="common.label.password"></span></label>
- <input type="password" id="node-input-password">
- </div>
- </div>
- </div>
- <div class="form-row">
- <label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label>
- <select type="text" id="node-input-ret" style="width:70%;">
- <option value="txt" data-i18n="httpin.utf8"></option>
- <option value="bin" data-i18n="httpin.binary"></option>
- <option value="obj" data-i18n="httpin.json"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips" id="tip-json" hidden><span data-i18n="httpin.tip.req"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('http request',{
- category: 'function',
- color:"rgb(231, 231, 174)",
- defaults: {
- name: {value:""},
- method:{value:"GET"},
- ret: {value:"txt"},
- url:{value:""},
- tls: {type:"tls-config",required: false}
- },
- credentials: {
- user: {type:"text"},
- password: {type: "password"}
- },
- inputs:1,
- outputs:1,
- icon: "white-globe.png",
- label: function() {
- return this.name||this._("httpin.httpreq");
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- $("#node-input-useAuth").change(function() {
- if ($(this).is(":checked")) {
- $(".node-input-useAuth-row").show();
- } else {
- $(".node-input-useAuth-row").hide();
- $('#node-input-user').val('');
- $('#node-input-password').val('');
- }
- });
- if (this.credentials.user || this.credentials.has_password) {
- $('#node-input-useAuth').prop('checked', true);
- } else {
- $('#node-input-useAuth').prop('checked', false);
- }
- $("#node-input-useAuth").change();
- function updateTLSOptions() {
- if ($("#node-input-usetls").is(':checked')) {
- $("#node-row-tls").show();
- } else {
- $("#node-row-tls").hide();
- }
- }
- if (this.tls) {
- $('#node-input-usetls').prop('checked', true);
- } else {
- $('#node-input-usetls').prop('checked', false);
- }
- updateTLSOptions();
- $("#node-input-usetls").on("click",function() {
- updateTLSOptions();
- });
- $("#node-input-ret").change(function() {
- if ($("#node-input-ret").val() === "obj") {
- $("#tip-json").show();
- } else {
- $("#tip-json").hide();
- }
- });
- },
- oneditsave: function() {
- if (!$("#node-input-usetls").is(':checked')) {
- $("#node-input-tls").val("_ADD_");
- }
- }
- });
- </script>
- <script type="text/x-red" data-help-name="http request">
- <p>Provides a node for making http requests.</p>
- <p>The URL and HTTP method can be configured in the node, if they are left blank they should be set in an incoming message on <code>msg.url</code> and <code>msg.method</code>:</p>
- <ul>
- <li><code>url</code>, if set, is used as the url of the request. Must start with http: or https:</li>
- <li><code>method</code>, if set, is used as the HTTP method of the request.
- Must be one of <code>GET</code>, <code>PUT</code>, <code>POST</code>, <code>PATCH</code> or <code>DELETE</code> (default: GET)</li>
- <li><code>headers</code>, if set, should be an object containing field/value
- pairs to be added as request headers</li>
- <li><code>payload</code> is sent as the body of the request</li>
- </ul>
- <p>When configured within the node, the URL property can contain <a href="http://mustache.github.io/mustache.5.html" target="_blank">mustache-style</a> tags. These allow the
- url to be constructed using values of the incoming message. For example, if the url is set to
- <code>example.com/{{{topic}}}</code>, it will have the value of <code>msg.topic</code> automatically inserted.
- Using {{{...}}} prevents mustache from escaping characters like / & etc.</p>
- <p>
- The output message contains the following properties:
- <ul>
- <li><code>payload</code> is the body of the response</li>
- <li><code>statusCode</code> is the status code of the response, or the error code if the request could not be completed</li>
- <li><code>headers</code> is an object containing the response headers</li>
- <li><code>responseUrl</code> is the url of the server that responds</li>
- </ul>
- <p><b>Note</b>: If you need to configure a proxy please add <b>http_proxy=...</b> to your environment variables and restart Node-RED.</p>
- </script><!--
- 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.
- -->
- <!-- WebSocket Input Node -->
- <script type="text/x-red" data-template-name="websocket in">
- <div class="form-row">
- <label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> <span data-i18n="websocket.label.type"></span></label>
- <select id="node-input-mode">
- <option value="server" data-i18n="websocket.listenon"></option>
- <option value="client" data-i18n="websocket.connectto"></option>
- </select>
- </div>
- <div class="form-row" id="websocket-server-row">
- <label for="node-input-server"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.path"></span></label>
- <input type="text" id="node-input-server">
- </div>
- <div class="form-row" id="websocket-client-row">
- <label for="node-input-client"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.url"></span></label>
- <input type="text" id="node-input-client">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- (function() {
- function ws_oneditprepare() {
- $("#websocket-client-row").hide();
- $("#node-input-mode").change(function() {
- if ( $("#node-input-mode").val() === 'client') {
- $("#websocket-server-row").hide();
- $("#websocket-client-row").show();
- }
- else {
- $("#websocket-server-row").show();
- $("#websocket-client-row").hide();
- }
- });
- if (this.client) {
- $("#node-input-mode").val('client').change();
- }
- else {
- $("#node-input-mode").val('server').change();
- }
- }
- function ws_oneditsave() {
- if ($("#node-input-mode").val() === 'client') {
- $("#node-input-server").append('<option value="">Dummy</option>');
- $("#node-input-server").val('');
- }
- else {
- $("#node-input-client").append('<option value="">Dummy</option>');
- $("#node-input-client").val('');
- }
- }
- function ws_label() {
- var nodeid = (this.client)?this.client:this.server;
- var wsNode = RED.nodes.node(nodeid);
- return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");
- }
- function ws_validateserver() {
- if ($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
- return true;
- }
- else {
- return RED.nodes.node(this.server) != null;
- }
- }
- function ws_validateclient() {
- if ($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
- return RED.nodes.node(this.client) != null;
- }
- else {
- return true;
- }
- }
- RED.nodes.registerType('websocket in',{
- category: 'input',
- defaults: {
- name: {value:""},
- server: {type:"websocket-listener", validate: ws_validateserver},
- client: {type:"websocket-client", validate: ws_validateclient}
- },
- color:"rgb(215, 215, 160)",
- inputs:0,
- outputs:1,
- icon: "white-globe.png",
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- label: ws_label,
- oneditsave: ws_oneditsave,
- oneditprepare: ws_oneditprepare
- });
- RED.nodes.registerType('websocket out',{
- category: 'output',
- defaults: {
- name: {value:""},
- server: {type:"websocket-listener", validate: ws_validateserver},
- client: {type:"websocket-client", validate: ws_validateclient}
- },
- color:"rgb(215, 215, 160)",
- inputs:1,
- outputs:0,
- icon: "white-globe.png",
- align: "right",
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- label: ws_label,
- oneditsave: ws_oneditsave,
- oneditprepare: ws_oneditprepare
- });
- RED.nodes.registerType('websocket-listener',{
- category: 'config',
- defaults: {
- path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/)},
- wholemsg: {value:"false"}
- },
- inputs:0,
- outputs:0,
- label: function() {
- var root = RED.settings.httpNodeRoot;
- if (root.slice(-1) != "/") {
- root = root+"/";
- }
- if (this.path.charAt(0) == "/") {
- root += this.path.slice(1);
- } else {
- root += this.path;
- }
- return root;
- },
- oneditprepare: function() {
- var root = RED.settings.httpNodeRoot;
- if (root.slice(-1) == "/") {
- root = root.slice(0,-1);
- }
- if (root === "") {
- $("#node-config-ws-tip").hide();
- } else {
- $("#node-config-ws-path").html(root);
- $("#node-config-ws-tip").show();
- }
- }
- });
- RED.nodes.registerType('websocket-client',{
- category: 'config',
- defaults: {
- path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/)},
- wholemsg: {value:"false"}
- },
- inputs:0,
- outputs:0,
- label: function() {
- return this.path;
- }
- });
- })();
- </script>
- <!-- WebSocket out Node -->
- <script type="text/x-red" data-template-name="websocket out">
- <div class="form-row">
- <label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> <span data-i18n="websocket.label.type"></span></label>
- <select id="node-input-mode">
- <option value="server" data-i18n="websocket.listenon"></option>
- <option value="client" data-i18n="websocket.connectto"></option>
- </select>
- </div>
- <div class="form-row" id="websocket-server-row">
- <label for="node-input-server"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.path"></span></label>
- <input type="text" id="node-input-server">
- </div>
- <div class="form-row" id="websocket-client-row">
- <label for="node-input-client"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.url"></span></label>
- <input type="text" id="node-input-client">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <!-- WebSocket Server configuration node -->
- <script type="text/x-red" data-template-name="websocket-listener">
- <div class="form-row">
- <label for="node-config-input-path"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.path"></span></label>
- <input id="node-config-input-path" type="text" placeholder="/ws/example">
- </div>
- <div class="form-row">
- <label for="node-config-input-wholemsg"> </label>
- <select type="text" id="node-config-input-wholemsg" style="width: 70%;">
- <option value="false" data-i18n="websocket.payload"></option>
- <option value="true" data-i18n="websocket.message"></option>
- </select>
- </div>
- <div class="form-tips">
- <span data-i18n="[html]websocket.tip.path1"></span>
- <p id="node-config-ws-tip"><span data-i18n="[html]websocket.tip.path2"></span><code><span id="node-config-ws-path"></span></code>.</p>
- </div>
- </script>
- <!-- WebSocket Client configuration node -->
- <script type="text/x-red" data-template-name="websocket-client">
- <div class="form-row">
- <label for="node-config-input-path"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.url"></span></label>
- <input id="node-config-input-path" type="text" placeholder="ws://example.com/ws">
- </div>
- <div class="form-row">
- <label for="node-config-input-wholemsg"> </label>
- <select type="text" id="node-config-input-wholemsg" style="width: 70%;">
- <option value="false" data-i18n="websocket.payload"></option>
- <option value="true" data-i18n="websocket.message"></option>
- </select>
- </div>
- <div class="form-tips">
- <p><span data-i18n="[html]websocket.tip.url1"></span></p>
- <span data-i18n="[html]websocket.tip.url2"></span>
- </div>
- </script>
- <script type="text/x-red" data-help-name="websocket in">
- <p>WebSocket input node.</p>
- <p>By default, the data received from the WebSocket will be in <code>msg.payload</code>.
- The socket can be configured to expect a properly formed JSON string, in which
- case it will parse the JSON and send on the resulting object as the entire message.</p>
- </script><script type="text/x-red" data-help-name="websocket out">
- <p>WebSocket out node.</p>
- <p>By default, <code>msg.payload</code> will be sent over the WebSocket. The socket
- can be configured to encode the entire <code>msg</code> object as a JSON string and send that
- over the WebSocket.</p>
- <p>If the message arriving at this node started at a WebSocket In node, the message
- will be sent back to the client that triggered the flow. Otherwise, the message
- will be broadcast to all connected clients.</p>
- <p>If you want to broadcast a message that started at a WebSocket In node, you
- should delete the <code>msg._session</code> property within the flow.</p>
- </script><script type="text/x-red" data-help-name="websocket-listener">
- <p>This configuration node creates a WebSocket Server endpoint using the specified path.</p>
- </script><script type="text/x-red" data-help-name="websocket-client">
- <p>This configuration node connects a WebSocket client to the specified URL.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="watch">
- <div class="form-row node-input-filename">
- <label for="node-input-files"><i class="fa fa-file"></i> <span data-i18n="watch.label.files"></span></label>
- <input id="node-input-files" type="text" tabindex="1" data-i18n="[placeholder]watch.placeholder.files">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div id="node-input-tip" class="form-tips"><span data-i18n="watch.tip"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('watch',{
- category: 'advanced-input',
- defaults: {
- name: {value:""},
- files: {value:"",required:true}
- },
- color:"BurlyWood",
- inputs:0,
- outputs:1,
- icon: "watch.png",
- label: function() {
- return this.name||this.files;
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="watch">
- <p>Watches a directory or file for changes.</p>
- <p>You can enter a list of comma separated directories and/or files. You will
- need to put quotes "..." around any that have spaces in.</p>
- <p>On Windows you must use double back-slashes \\ in any directory names.</p>
- <p>The full filename of the file that actually changed is put into <code>msg.payload</code>,
- while a stringified version of the watch list is returned in <code>msg.topic</code>.</p>
- <p><code>msg.file</code> contains just the short filename of the file that changed.
- <code>msg.type</code> has the type of thing changed, usually <i>file</i> or <i>directory</i>,
- while <code>msg.size</code> holds the file size in bytes.</p>
- <p>Of course in Linux, <i>everything</i> is a file and thus can be watched...</p>
- <p><b>Note: </b>The directory or file must exist in order to be watched. If the file
- or directory gets deleted it may no longer be monitored even if it gets re-created.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="tcp in">
- <div class="form-row">
- <label for="node-input-server"><i class="fa fa-dot-circle-o"></i> <span data-i18n="tcpin.label.type"></span></label>
- <select id="node-input-server" style="width:120px; margin-right:5px;">
- <option value="server" data-i18n="tcpin.type.listen"></option>
- <option value="client" data-i18n="tcpin.type.connect"></option>
- </select>
- <span data-i18n="tcpin.label.port"></span> <input type="text" id="node-input-port" style="width: 65px">
- </div>
- <div class="form-row hidden" id="node-input-host-row" style="padding-left: 110px;">
- <span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;">
- </div>
- <div class="form-row">
- <label><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.output"></span></label>
- <select id="node-input-datamode" style="width:110px;">
- <option value="stream" data-i18n="tcpin.output.stream"></option>
- <option value="single" data-i18n="tcpin.output.single"></option>
- </select>
- <select id="node-input-datatype" style="width:140px;">
- <option value="buffer" data-i18n="tcpin.output.buffer"></option>
- <option value="utf8" data-i18n="tcpin.output.string"></option>
- <option value="base64" data-i18n="tcpin.output.base64"></option>
- </select>
- <span data-i18n="tcpin.label.payload"></span>
- </div>
- <div id="node-row-newline" class="form-row hidden" style="padding-left: 110px;">
- <span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width: 110px;">
- </div>
- <div class="form-row">
- <label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
- <input type="text" id="node-input-topic" data-i18n="[placeholder]common.label.topic">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('tcp in',{
- category: 'input',
- color:"Silver",
- defaults: {
- name: {value:""},
- server: {value:"server",required:true},
- host: {value:"",validate:function(v) { return (this.server == "server")||v.length > 0;} },
- port: {value:"",required:true,validate:RED.validators.number()},
- datamode:{value:"stream"},
- datatype:{value:"buffer"},
- newline:{value:""},
- topic: {value:""},
- base64: {/*deprecated*/ value:false,required:true}
- },
- inputs:0,
- outputs:1,
- icon: "bridge-dash.png",
- label: function() {
- return this.name || "tcp:"+(this.host?this.host+":":"")+this.port;
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var updateOptions = function() {
- var sockettype = $("#node-input-server").val();
- if (sockettype == "client") {
- $("#node-input-host-row").show();
- } else {
- $("#node-input-host-row").hide();
- }
- var datamode = $("#node-input-datamode").val();
- var datatype = $("#node-input-datatype").val();
- if (datamode == "stream") {
- if (datatype == "utf8") {
- $("#node-row-newline").show();
- } else {
- $("#node-row-newline").hide();
- }
- } else {
- $("#node-row-newline").hide();
- }
- };
- updateOptions();
- $("#node-input-server").change(updateOptions);
- $("#node-input-datatype").change(updateOptions);
- $("#node-input-datamode").change(updateOptions);
- }
- });
- </script>
- <script type="text/x-red" data-template-name="tcp out">
- <div class="form-row">
- <label for="node-input-beserver"><i class="fa fa-dot-circle-o"></i> <span data-i18n="tcpin.label.type"></span></label>
- <select id="node-input-beserver" style="width:150px; margin-right:5px;">
- <option value="server" data-i18n="tcpin.type.listen"></option>
- <option value="client" data-i18n="tcpin.type.connect"></option>
- <option value="reply" data-i18n="tcpin.type.reply"></option>
- </select>
- <span id="node-input-port-row"><span data-i18n="tcpin.label.port"></span> <input type="text" id="node-input-port" style="width: 65px"></span>
- </div>
- <div class="form-row hidden" id="node-input-host-row" style="padding-left: 110px;">
- <span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" style="width: 60%;">
- </div>
- <div class="form-row hidden" id="node-input-end-row">
- <label> </label>
- <input type="checkbox" id="node-input-end" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-end" style="width: 70%;"><span data-i18n="tcpin.label.close-connection"></span></label>
- </div>
- <div class="form-row">
- <label> </label>
- <input type="checkbox" id="node-input-base64" placeholder="base64" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-base64" style="width: 70%;"><span data-i18n="tcpin.label.decode-base64"></span></label>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('tcp out',{
- category: 'output',
- color:"Silver",
- defaults: {
- host: {value:"",validate:function(v) { return (this.beserver != "client")||v.length > 0;} },
- port: {value:"",validate:function(v) { return (this.beserver == "reply")||RED.validators.number()(v) } },
- beserver: {value:"client",required:true},
- base64: {value:false,required:true},
- end: {value:false,required:true},
- name: {value:""}
- },
- inputs:1,
- outputs:0,
- icon: "bridge-dash.png",
- align: "right",
- label: function() {
- return this.name || "tcp:"+(this.host?this.host+":":"")+this.port;
- },
- labelStyle: function() {
- return (this.name)?"node_label_italic":"";
- },
- oneditprepare: function() {
- var updateOptions = function() {
- var sockettype = $("#node-input-beserver").val();
- if (sockettype == "reply") {
- $("#node-input-port-row").hide();
- $("#node-input-host-row").hide();
- $("#node-input-end-row").hide();
- } else {
- $("#node-input-port-row").show();
- $("#node-input-end-row").show();
- }
- if (sockettype == "client") {
- $("#node-input-host-row").show();
- } else {
- $("#node-input-host-row").hide();
- }
- };
- updateOptions();
- $("#node-input-beserver").change(updateOptions);
- }
- });
- </script>
- <script type="text/x-red" data-template-name="tcp request">
- <div class="form-row">
- <label for="node-input-server"><i class="fa fa-globe"></i> <span data-i18n="tcpin.label.server"></span></label>
- <input type="text" id="node-input-server" placeholder="ip.address" style="width:45%">
- port <input type="text" id="node-input-port" style="width:60px">
- </div>
- <div class="form-row">
- <label for="node-input-out"><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.return"></span></label>
- <select type="text" id="node-input-out" style="width:56%;">
- <option value="time" data-i18n="tcpin.return.timeout"></option>
- <option value="char" data-i18n="tcpin.return.character"></option>
- <option value="count" data-i18n="tcpin.return.number"></option>
- <option value="sit" data-i18n="tcpin.return.never"></option>
- </select>
- <input type="text" id="node-input-splitc" style="width:50px;">
- <span id="node-units"></span>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('tcp request',{
- category: 'function',
- color:"Silver",
- defaults: {
- server: {value:""},
- port: {value:"",validate:RED.validators.regex(/^(\d*|)$/)},
- out: {value:"time",required:true},
- splitc: {value:"0",required:true},
- name: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "bridge-dash.png",
- label: function() {
- return this.name || "tcp:"+(this.server?this.server+":":"")+this.port;
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var previous = null;
- $("#node-input-out").on('focus', function () { previous = this.value; }).change(function() {
- if (previous == null) { previous = $("#node-input-out").val(); }
- if ($("#node-input-out").val() == "char") {
- if (previous != "char") $("#node-input-splitc").val("\\n");
- $("#node-units").text("");
- }
- else if ($("#node-input-out").val() == "time") {
- if (previous != "time") $("#node-input-splitc").val("0");
- $("#node-units").text("ms");
- }
- else if ($("#node-input-out").val() == "count") {
- if (previous != "count") $("#node-input-splitc").val("12");
- $("#node-units").text("chars");
- }
- else {
- if (previous != "sit") $("#node-input-splitc").val("0");
- $("#node-units").text("");
- }
- });
- }
- });
- </script>
- <script type="text/x-red" data-help-name="tcp in">
- <p>Provides a choice of TCP inputs. Can either connect to a remote TCP port,
- or accept incoming connections.</p>
- </script><script type="text/x-red" data-help-name="tcp out">
- <p>Provides a choice of TCP outputs. Can either connect to a remote TCP port,
- accept incoming connections, or reply to messages received from a TCP In node.</p>
- <p>Only <code>msg.payload</code> is sent.</p>
- <p>If <code>msg.payload</code> is a string containing a Base64 encoding of binary
- data, the Base64 decoding option will cause it to be converted back to binary
- before being sent.</p>
- <p>If <code>msg._session</code> is not present the payload is
- sent to <b>all</b> connected clients.</p>
- </script><script type="text/x-red" data-help-name="tcp request">
- <p>A simple TCP request node - sends the <code>msg.payload</code> to a server tcp port and expects a response.</p>
- <p>Connects, sends the "request", and reads the "response". It can either count a number of
- returned characters into a fixed buffer, match a specified character before returning,
- wait a fixed timeout from first reply and then return, or just sit and wait for data.</p>
- <p>The response will be output in <code>msg.payload</code> as a buffer, so you may want to .toString() it.</p>
- <p>If you leave tcp host or port blank they must be set by using the <code>msg.host</code> and <code>msg.port</code> properties.</p>
- </script><!--
- 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.
- -->
- <!-- The Input Node -->
- <script type="text/x-red" data-template-name="udp in">
- <div class="form-row">
- <label for="node-input-port"><i class="fa fa-sign-in"></i> <span data-i18n="udp.label.listen"></span></label>
- <select id="node-input-multicast" style='width:70%'>
- <option value="false" data-i18n="udp.udpmsgs"></option>
- <option value="true" data-i18n="udp.mcmsgs"></option>
- </select>
- </div>
- <div class="form-row node-input-group">
- <label for="node-input-group"><i class="fa fa-list"></i> <span data-i18n="udp.label.group"></span></label>
- <input type="text" id="node-input-group" placeholder="225.0.18.83">
- </div>
- <div class="form-row node-input-iface">
- <label for="node-input-iface"><i class="fa fa-random"></i> <span data-i18n="udp.label.interface"></span></label>
- <input type="text" id="node-input-iface" data-i18n="[placeholder]udp.label.interfaceprompt">
- </div>
- <div class="form-row">
- <label for="node-input-port"><i class="fa fa-sign-in"></i> <span data-i18n="udp.label.onport"></span></label>
- <input type="text" id="node-input-port" style="width:80px">
- <span data-i18n="udp.label.using"></span> <select id="node-input-ipv" style="width:80px">
- <option value="udp4">ipv4</option>
- <option value="udp6">ipv6</option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-datatype"><i class="fa fa-sign-out"></i> <span data-i18n="udp.label.output"></span></label>
- <select id="node-input-datatype" style="width:70%;">
- <option value="buffer" data-i18n="udp.output.buffer"></option>
- <option value="utf8" data-i18n="udp.output.string"></option>
- <option value="base64" data-i18n="udp.output.base64"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips"><span data-i18n="udp.tip.in"></span></div>
- <div class="form-tips" id="udpporttip"><span data-i18n="[html]udp.tip.port"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('udp in',{
- category: 'input',
- color:"Silver",
- defaults: {
- name: {value:""},
- iface: {value:""},
- port: {value:"",required:true,validate:RED.validators.number()},
- ipv: {value:"udp4"},
- multicast: {value:"false"},
- group: {value:"",validate:function(v) { return (this.multicast !== "true")||v.length > 0;} },
- datatype: {value:"buffer",required:true}
- },
- inputs:0,
- outputs:1,
- icon: "bridge-dash.png",
- label: function() {
- if (this.multicast=="false") {
- return this.name||"udp "+this.port;
- }
- else {
- return this.name||"udp "+(this.group+":"+this.port);
- }
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- $("#node-input-multicast").change(function() {
- var id = $("#node-input-multicast").val();
- if (id == "false") {
- $(".node-input-group").hide();
- $(".node-input-iface").hide();
- }
- else {
- $(".node-input-group").show();
- $(".node-input-iface").show();
- }
- });
- $("#node-input-multicast").change();
- var porttip = this._("udp.tip.port");
- var alreadyused = this._("udp.errors.alreadyused");
- var portsInUse = {};
- $.getJSON('udp-ports/'+this.id,function(data) {
- portsInUse = data || {};
- $('#udpporttip').html(porttip + data);
- });
- $("#node-input-port").change(function() {
- var portnew = $("#node-input-port").val();
- if (portsInUse.hasOwnProperty($("#node-input-port").val())) {
- RED.notify(alreadyused+" "+$("#node-input-port").val(),"warn");
- }
- });
- }
- });
- </script>
- <!-- The Output Node -->
- <script type="text/x-red" data-template-name="udp out">
- <div class="form-row">
- <label for="node-input-port"><i class="fa fa-envelope"></i> <span data-i18n="udp.label.send"></span></label>
- <select id="node-input-multicast" style="width:40%">
- <option value="false" data-i18n="udp.udpmsg"></option>
- <option value="broad" data-i18n="udp.bcmsg"></option>
- <option value="multi" data-i18n="udp.mcmsg"></option>
- </select>
- <span data-i18n="udp.label.toport"></span> <input type="text" id="node-input-port" style="width:70px">
- </div>
- <div class="form-row node-input-addr">
- <label for="node-input-addr" id="node-input-addr-label"><i class="fa fa-list"></i> <span data-i18n="udp.label.address"></span></label>
- <input type="text" id="node-input-addr" data-i18n="[placeholder]udp.placeholder.address" style="width:50%;">
- <select id="node-input-ipv" style="width:70px">
- <option value="udp4">ipv4</option>
- <option value="udp6">ipv6</option>
- </select>
- </div>
- <div class="form-row node-input-iface">
- <label for="node-input-iface"><i class="fa fa-random"></i> <span data-i18n="udp.label.interface"></span></label>
- <input type="text" id="node-input-iface" data-i18n="[placeholder]udp.placeholder.interface">
- </div>
- <div class="form-row">
- <label for="node-input-outport-type"> </label>
- <select id="node-input-outport-type">
- <option id="node-input-outport-type-random" value="random" data-i18n="udp.bind.random"></option>
- <option value="fixed" data-i18n="udp.bind.local"></option>
- </select>
- <input type="text" id="node-input-outport" style="width:70px;">
- </div>
- <div class="form-row">
- <label> </label>
- <input type="checkbox" id="node-input-base64" style="display:inline-block; width:auto; vertical-align:top;">
- <label for="node-input-base64" style="width:70%;"><span data-i18n="udp.label.decode-base64"></span></label>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips"><span data-i18n="[html]udp.tip.out"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('udp out',{
- category: 'output',
- color:"Silver",
- defaults: {
- name: {value:""},
- addr: {value:""},
- iface: {value:""},
- port: {value:""},
- ipv: {value:"udp4"},
- outport: {value:""},
- base64: {value:false,required:true},
- multicast: {value:"false"}
- },
- inputs:1,
- outputs:0,
- icon: "bridge-dash.png",
- align: "right",
- label: function() {
- return this.name||"udp "+(this.addr+":"+this.port);
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var addresslabel = this._("udp.label.address");
- var addressph = this._("udp.placeholder.address");
- var grouplabel = this._("udp.label.group");
- var bindrandom = this._("udp.bind.random");
- var bindtarget = this._("udp.bind.target");
- var type = this.outport===""?"random":"fixed";
- $("#node-input-outport-type").val(type);
- $("#node-input-outport-type").change(function() {
- var type = $(this).val();
- if (type == "random") {
- $("#node-input-outport").val("").hide();
- } else {
- $("#node-input-outport").show();
- }
- });
- $("#node-input-outport-type").change();
- $("#node-input-multicast").change(function() {
- var id = $("#node-input-multicast").val();
- if (id === "multi") {
- $(".node-input-iface").show();
- $("#node-input-addr-label").html('<i class="fa fa-list"></i> ' + grouplabel);
- $("#node-input-addr")[0].placeholder = '225.0.18.83';
- }
- else if (id === "broad") {
- $(".node-input-iface").hide();
- $("#node-input-addr-label").html('<i class="fa fa-list"></i> ' + addresslabel);
- $("#node-input-addr")[0].placeholder = '255.255.255.255';
- }
- else {
- $(".node-input-iface").hide();
- $("#node-input-addr-label").html('<i class="fa fa-list"></i> ' + addresslabel);
- $("#node-input-addr")[0].placeholder = addressph;
- }
- var type = $(this).val();
- if (type == "false") {
- $("#node-input-outport-type-random").html(bindrandom);
- } else {
- $("#node-input-outport-type-random").html(bindtarget);
- }
- });
- $("#node-input-multicast").change();
- }
- });
- </script>
- <script type="text/x-red" data-help-name="udp in">
- <p>A UDP input node, that produces a <code>msg.payload</code> containing a
- Buffer, string, or base64 encoded string. Supports multicast.</p>
- <p>It also provides <code>msg.ip</code> and <code>msg.port</code> set to the
- ip address and port from which the message was received.</p>
- <p><b>Note</b>: On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
- </script><script type="text/x-red" data-help-name="udp out">
- <p>This node sends <code>msg.payload</code> to the designated UDP host and port. Supports multicast.</p>
- <p>You may also use <code>msg.ip</code> and <code>msg.port</code> to set the destination values, but the statically configured values have precedence.</p>
- <p>If you select broadcast either set the address to the local broadcast ip address, or maybe try 255.255.255.255, which is the global broadcast address.</p>
- <p><b>Note</b>: On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="switch">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row">
- <label data-i18n="switch.label.property"></label>
- <input type="text" id="node-input-property" style="width: 70%"/>
- </div>
- <div class="form-row node-input-rule-container-row">
- <ol id="node-input-rule-container"></ol>
- </div>
- <div class="form-row">
- <select id="node-input-checkall" style="width:100%; margin-right:5px;">
- <option value="true" data-i18n="switch.checkall"></option>
- <option value="false" data-i18n="switch.stopfirst"></option>
- </select>
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('switch', {
- color: "#E2D96E",
- category: 'function',
- defaults: {
- name: {value:""},
- property: {value:"payload", required:true, validate: RED.validators.typedInput("propertyType")},
- propertyType: { value:"msg" },
- rules: {value:[{t:"eq", v:""}]},
- checkall: {value:"true", required:true},
- outputs: {value:1}
- },
- inputs: 1,
- outputs: 1,
- icon: "switch.png",
- label: function() {
- return this.name||"switch";
- },
- oneditprepare: function() {
- var node = this;
- var previousValueType = {value:"prev",label:this._("inject.previous"),hasValue:false};
- $("#node-input-property").typedInput({default:this.propertyType||'msg',types:['msg','flow','global','jsonata']});
- var operators = [
- {v:"eq",t:"=="},
- {v:"neq",t:"!="},
- {v:"lt",t:"<"},
- {v:"lte",t:"<="},
- {v:"gt",t:">"},
- {v:"gte",t:">="},
- {v:"btwn",t:this._("switch.rules.btwn")},
- {v:"cont",t:this._("switch.rules.cont")},
- {v:"regex",t:this._("switch.rules.regex")},
- {v:"true",t:this._("switch.rules.true")},
- {v:"false",t:this._("switch.rules.false")},
- {v:"null",t:this._("switch.rules.null")},
- {v:"nnull",t:this._("switch.rules.nnull")},
- {v:"else",t:this._("switch.rules.else")}
- ];
- var andLabel = this._("switch.and");
- var caseLabel = this._("switch.ignorecase");
- function resizeRule(rule) {
- var newWidth = rule.width();
- var selectField = rule.find("select");
- var type = selectField.val()||"";
- var valueField = rule.find(".node-input-rule-value");
- var btwnField1 = rule.find(".node-input-rule-btwn-value");
- var btwnField2 = rule.find(".node-input-rule-btwn-value2");
- var selectWidth;
- if (type.length < 4) {
- selectWidth = 60;
- } else if (type === "regex") {
- selectWidth = 147;
- } else {
- selectWidth = 120;
- }
- selectField.width(selectWidth);
- if (type === "btwn") {
- btwnField1.typedInput("width",(newWidth-selectWidth-70));
- btwnField2.typedInput("width",(newWidth-selectWidth-70));
- } else {
- if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else") {
- // valueField.hide();
- } else {
- valueField.typedInput("width",(newWidth-selectWidth-70));
- }
- }
- }
- $("#node-input-rule-container").css('min-height','250px').css('min-width','450px').editableList({
- addItem: function(container,i,opt) {
- if (!opt.hasOwnProperty('r')) {
- opt.r = {};
- }
- var rule = opt.r;
- if (!rule.hasOwnProperty('t')) {
- rule.t = 'eq';
- }
- var row = $('<div/>').appendTo(container);
- var row2 = $('<div/>',{style:"padding-top: 5px; padding-left: 175px;"}).appendTo(container);
- var row3 = $('<div/>',{style:"padding-top: 5px; padding-left: 102px;"}).appendTo(container);
- var selectField = $('<select/>',{style:"width:120px; margin-left: 5px; text-align: center;"}).appendTo(row);
- for (var d in operators) {
- selectField.append($("<option></option>").val(operators[d].v).text(operators[d].t));
- }
- var valueField = $('<input/>',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'str',types:['msg','flow','global','str','num','jsonata',previousValueType]});
- var btwnValueField = $('<input/>',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata',previousValueType]});
- var btwnAndLabel = $('<span/>',{class:"node-input-rule-btwn-label"}).text(" "+andLabel+" ").appendTo(row3);
- var btwnValue2Field = $('<input/>',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata',previousValueType]});
- var finalspan = $('<span/>',{style:"float: right;margin-top: 6px;"}).appendTo(row);
- finalspan.append(' → <span class="node-input-rule-index">'+(i+1)+'</span> ');
- var caseSensitive = $('<input/>',{id:"node-input-rule-case-"+i,class:"node-input-rule-case",type:"checkbox",style:"width:auto;vertical-align:top"}).appendTo(row2);
- $('<label/>',{for:"node-input-rule-case-"+i,style:"margin-left: 3px;"}).text(caseLabel).appendTo(row2);
- selectField.change(function() {
- resizeRule(container);
- var type = selectField.val();
- if (type === "btwn") {
- valueField.typedInput('hide');
- btwnValueField.typedInput('show');
- } else {
- btwnValueField.typedInput('hide');
- if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else") {
- valueField.typedInput('hide');
- } else {
- valueField.typedInput('show');
- }
- }
- if (type === "regex") {
- row2.show();
- row3.hide();
- } else if (type === "btwn"){
- row2.hide();
- row3.show();
- } else {
- row2.hide();
- row3.hide();
- }
- });
- selectField.val(rule.t);
- if (rule.t == "btwn") {
- btwnValueField.typedInput('value',rule.v);
- btwnValueField.typedInput('type',rule.vt||'num');
- btwnValue2Field.typedInput('value',rule.v2);
- btwnValue2Field.typedInput('type',rule.v2t||'num');
- } else if (typeof rule.v != "undefined") {
- valueField.typedInput('value',rule.v);
- valueField.typedInput('type',rule.vt||'str');
- }
- if (rule.case) {
- caseSensitive.prop('checked',true);
- } else {
- caseSensitive.prop('checked',false);
- }
- selectField.change();
- },
- removeItem: function(opt) {
- if (opt.hasOwnProperty('i')) {
- var removedList = $("#node-input-rule-container").data('removedList')||[];
- removedList.push(opt.i);
- $("#node-input-rule-container").data('removedList',removedList);
- }
- var rules = $("#node-input-rule-container").editableList('items');
- rules.each(function(i) { $(this).find(".node-input-rule-index").html(i+1); });
- },
- resizeItem: resizeRule,
- sortItems: function(rules) {
- var rules = $("#node-input-rule-container").editableList('items');
- rules.each(function(i) { $(this).find(".node-input-rule-index").html(i+1); });
- },
- sortable: true,
- removable: true
- });
- for (var i=0;i<this.rules.length;i++) {
- var rule = this.rules[i];
- $("#node-input-rule-container").editableList('addItem',{r:rule,i:i});
- }
- },
- oneditsave: function() {
- var rules = $("#node-input-rule-container").editableList('items');
- var ruleset;
- var node = this;
- node.rules = [];
- var changedOutputs = {};
- var removedList = $("#node-input-rule-container").data('removedList')||[];
- removedList.forEach(function(i) {
- changedOutputs[i] = -1;
- });
- rules.each(function(i) {
- var ruleData = $(this).data('data');
- var rule = $(this);
- var type = rule.find("select").val();
- var r = {t:type};
- if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else")) {
- if (type === "btwn") {
- r.v = rule.find(".node-input-rule-btwn-value").typedInput('value');
- r.vt = rule.find(".node-input-rule-btwn-value").typedInput('type');
- r.v2 = rule.find(".node-input-rule-btwn-value2").typedInput('value');
- r.v2t = rule.find(".node-input-rule-btwn-value2").typedInput('type');
- } else {
- r.v = rule.find(".node-input-rule-value").typedInput('value');
- r.vt = rule.find(".node-input-rule-value").typedInput('type');
- }
- if (type === "regex") {
- r.case = rule.find(".node-input-rule-case").prop("checked");
- }
- }
- if (ruleData.hasOwnProperty('i')) {
- if (ruleData.i !== i) {
- changedOutputs[ruleData.i] = i;
- }
- }
- node.rules.push(r);
- });
- this._outputs = changedOutputs;
- this.outputs = node.rules.length;
- this.propertyType = $("#node-input-property").typedInput('type');
- },
- oneditresize: function(size) {
- var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
- var height = size.height;
- for (var i=0;i<rows.size();i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-input-rule-container-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $("#node-input-rule-container").editableList('height',height);
- }
- });
- </script>
- <script type="text/x-red" data-help-name="switch">
- <p>A node to route messages based on property values.</p>
- <p>When a message arrives, the selected property is evaluated against each
- of the defined rules. The message is then sent to the output of <i>all</i>
- rules that pass.</p>
- <p><b>Note</b>: the <i>otherwise</i> rule applies as a "not any of" the rules preceding it.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="change">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row" style="margin-bottom:0;">
- <label><i class="fa fa-list"></i> <span data-i18n="change.label.rules"></span></label>
- </div>
- <div class="form-row node-input-rule-container-row">
- <ol id="node-input-rule-container"></ol>
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('change', {
- color: "#E2D96E",
- category: 'function',
- defaults: {
- name: {value:""},
- rules:{value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}]},
- // legacy
- action: {value:""},
- property: {value:""},
- from: {value:""},
- to: {value:""},
- reg: {value:false}
- },
- inputs: 1,
- outputs: 1,
- icon: "swap.png",
- label: function() {
- if (this.name) {
- return this.name;
- }
- if (!this.rules) {
- if (this.action === "replace") {
- return this._("change.label.set",{property:"msg."+this.property});
- } else if (this.action === "change") {
- return this._("change.label.change",{property:"msg."+this.property});
- } else if (this.action === "move") {
- return this._("change.label.move",{property:"msg."+this.property});
- } else {
- return this._("change.label.delete",{property:"msg."+this.property});
- }
- } else {
- if (this.rules.length == 1) {
- if (this.rules[0].t === "set") {
- return this._("change.label.set",{property:(this.rules[0].pt||"msg")+"."+this.rules[0].p});
- } else if (this.rules[0].t === "change") {
- return this._("change.label.change",{property:(this.rules[0].pt||"msg")+"."+this.rules[0].p});
- } else if (this.rules[0].t === "move") {
- return this._("change.label.move",{property:(this.rules[0].pt||"msg")+"."+this.rules[0].p});
- } else {
- return this._("change.label.delete",{property:(this.rules[0].pt||"msg")+"."+this.rules[0].p});
- }
- } else {
- return this._("change.label.changeCount",{count:this.rules.length});
- }
- }
- },
- labelStyle: function() {
- return this.name ? "node_label_italic" : "";
- },
- oneditprepare: function() {
- var set = this._("change.action.set");
- var change = this._("change.action.change");
- var del = this._("change.action.delete");
- var move = this._("change.action.move");
- var to = this._("change.action.to");
- var search = this._("change.action.search");
- var replace = this._("change.action.replace");
- var regex = this._("change.label.regex");
- function resizeRule(rule) {
- var newWidth = rule.width();
- rule.find('.red-ui-typedInput').typedInput("width",newWidth-150);
- }
- $('#node-input-rule-container').css('min-height','300px').css('min-width','450px').editableList({
- addItem: function(container,i,opt) {
- var rule = opt;
- if (!rule.hasOwnProperty('t')) {
- rule = {t:"set",p:"payload",to:"",tot:"str"};
- }
- if (rule.t === "change" && rule.re) {
- rule.fromt = 're';
- delete rule.re;
- }
- if (rule.t === "set" && !rule.tot) {
- if (rule.to.indexOf("msg.") === 0 && !rule.tot) {
- rule.to = rule.to.substring(4);
- rule.tot = "msg";
- } else {
- rule.tot = "str";
- }
- }
- if (rule.t === "move" && !rule.tot) {
- rule.tot = "msg";
- }
- var row1 = $('<div/>').appendTo(container);
- var row2 = $('<div/>',{style:"margin-top:8px;"}).appendTo(container);
- var row3 = $('<div/>',{style:"margin-top:8px;"}).appendTo(container);
- var row4 = $('<div/>',{style:"margin-top:8px;"}).appendTo(container);
- var selectField = $('<select/>',{class:"node-input-rule-type",style:"width:110px; margin-right:10px;"}).appendTo(row1);
- var selectOptions = [{v:"set",l:set},{v:"change",l:change},{v:"delete",l:del},{v:"move",l:move}];
- for (var i=0; i<4; i++) {
- selectField.append($("<option></option>").val(selectOptions[i].v).text(selectOptions[i].l));
- }
- var propertyName = $('<input/>',{class:"node-input-rule-property-name",type:"text"})
- .appendTo(row1)
- .typedInput({types:['msg','flow','global']});
- $('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
- .text(to)
- .appendTo(row2);
- var propertyValue = $('<input/>',{class:"node-input-rule-property-value",type:"text"})
- .appendTo(row2)
- .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','date','jsonata']});
- var row3_1 = $('<div/>').appendTo(row3);
- $('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
- .text(search)
- .appendTo(row3_1);
- var fromValue = $('<input/>',{class:"node-input-rule-property-search-value",type:"text"})
- .appendTo(row3_1)
- .typedInput({default:'str',types:['msg','flow','global','str','re','num','bool']});
- var row3_2 = $('<div/>',{style:"margin-top:8px;"}).appendTo(row3);
- $('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
- .text(replace)
- .appendTo(row3_2);
- var toValue = $('<input/>',{class:"node-input-rule-property-replace-value",type:"text"})
- .appendTo(row3_2)
- .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json']});
- $('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
- .text(to)
- .appendTo(row4);
- var moveValue = $('<input/>',{class:"node-input-rule-property-move-value",type:"text"})
- .appendTo(row4)
- .typedInput({default:'msg',types:['msg','flow','global']});
- selectField.change(function() {
- var width = $("#node-input-rule-container").width();
- var type = $(this).val();
- if (type == "set") {
- row2.show();
- row3.hide();
- row4.hide();
- } else if (type == "change") {
- row2.hide();
- row3.show();
- row4.hide();
- } else if (type == "delete") {
- row2.hide();
- row3.hide();
- row4.hide();
- } else if (type == "move") {
- row2.hide();
- row3.hide();
- row4.show();
- }
- resizeRule(container);
- });
- selectField.val(rule.t);
- propertyName.typedInput('value',rule.p);
- propertyName.typedInput('type',rule.pt);
- propertyValue.typedInput('value',rule.to);
- propertyValue.typedInput('type',rule.tot);
- moveValue.typedInput('value',rule.to);
- moveValue.typedInput('type',rule.tot);
- fromValue.typedInput('value',rule.from);
- fromValue.typedInput('type',rule.fromt);
- toValue.typedInput('value',rule.to);
- toValue.typedInput('type',rule.tot);
- selectField.change();
- var newWidth = $("#node-input-rule-container").width();
- resizeRule(container);
- },
- resizeItem: resizeRule,
- removable: true,
- sortable: true
- });
- if (!this.rules) {
- var rule = {
- t:(this.action=="replace"?"set":this.action),
- p:this.property,
- pt:"msg"
- }
- if ((rule.t === "set")||(rule.t === "move")) {
- rule.to = this.to;
- } else if (rule.t === "change") {
- rule.from = this.from;
- rule.to = this.to;
- rule.re = this.reg;
- }
- delete this.to;
- delete this.from;
- delete this.reg;
- delete this.action;
- delete this.property;
- this.rules = [rule];
- }
- for (var i=0; i<this.rules.length; i++) {
- var rule = this.rules[i];
- $("#node-input-rule-container").editableList('addItem',rule);
- }
- },
- oneditsave: function() {
- var rules = $("#node-input-rule-container").editableList('items');
- var ruleset;
- var node = this;
- node.rules= [];
- rules.each(function(i) {
- var rule = $(this);
- var type = rule.find(".node-input-rule-type").val();
- var r = {
- t:type,
- p:rule.find(".node-input-rule-property-name").typedInput('value'),
- pt:rule.find(".node-input-rule-property-name").typedInput('type')
- };
- if (type === "set") {
- r.to = rule.find(".node-input-rule-property-value").typedInput('value');
- r.tot = rule.find(".node-input-rule-property-value").typedInput('type');
- } else if (type === "move") {
- r.to = rule.find(".node-input-rule-property-move-value").typedInput('value');
- r.tot = rule.find(".node-input-rule-property-move-value").typedInput('type');
- } else if (type === "change") {
- r.from = rule.find(".node-input-rule-property-search-value").typedInput('value');
- r.fromt = rule.find(".node-input-rule-property-search-value").typedInput('type');
- r.to = rule.find(".node-input-rule-property-replace-value").typedInput('value');
- r.tot = rule.find(".node-input-rule-property-replace-value").typedInput('type');
- }
- node.rules.push(r);
- });
- },
- oneditresize: function(size) {
- var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
- var height = size.height;
- for (var i=0; i<rows.size(); i++) {
- height -= $(rows[i]).outerHeight(true);
- }
- var editorRow = $("#dialog-form>div.node-input-rule-container-row");
- height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
- $("#node-input-rule-container").editableList('height',height);
- }
- });
- </script>
- <script type="text/x-red" data-help-name="change">
- <p>Set, change, delete or move properties of a message, flow context or global context.</p>
- <p>The node can specify multiple rules that will be applied in turn.</p>
- <p>The available operations are:</p>
- <ul>
- <li><b>Set</b> - set a property. The value can be a variety of different types, or
- can be taken from an existing message or context property.</li>
- <li><b>Change</b> - search & replace parts of the property. If regular expressions
- are enabled, the <b>replace with</b> property can include capture groups, for
- example <code>$1</code>. Replace will only change the <b>type</b> if there
- is a complete match.</li>
- <li><b>Delete</b> - delete a property.</li>
- <li><b>Move</b> - move or rename a property.</li>
- </ul>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="range">
- <div class="form-row">
- <label for="node-input-action"><i class="fa fa-dot-circle-o"></i> <span data-i18n="range.label.action"></span></label>
- <select id="node-input-action" style="width:70%;">
- <option value="scale" data-i18n="range.scale.payload"></option>
- <option value="clamp" data-i18n="range.scale.limit"></option>
- <option value="roll" data-i18n="range.scale.wrap"></option>
- </select>
- </div>
- <br/>
- <div class="form-row"><i class="fa fa-sign-in"></i> <span data-i18n="range.label.inputrange"></span>:</div>
- <div class="form-row"><label></label>
- <span data-i18n="range.label.from"></span>: <input type="text" id="node-input-minin" data-i18n="[placeholder]range.placeholder.min" style="width:100px;"/>
- <span data-i18n="range.label.to"></span>: <input type="text" id="node-input-maxin" data-i18n="[placeholder]range.placeholder.maxin" style="width:100px;"/>
- </div>
- <div class="form-row"><i class="fa fa-sign-out"></i> <span data-i18n="range.label.resultrange"></span>:</div>
- <div class="form-row"><label></label>
- <span data-i18n="range.label.from"></span>: <input type="text" id="node-input-minout" data-i18n="[placeholder]range.placeholder.min" style="width:100px;"/>
- <span data-i18n="range.label.to"></span>: <input type="text" id="node-input-maxout" data-i18n="[placeholder]range.placeholder.maxout" style="width:100px;"/>
- </div>
- <br/>
- <div class="form-row"><label></label>
- <input type="checkbox" id="node-input-round" style="display: inline-block; width: auto; vertical-align: top;">
- <label style="width: auto;" for="node-input-round"><span data-i18n="range.label.roundresult"></span></label></input>
- </div>
- <br/>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips" id="node-tip"><span data-i18n="range.tip"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('range', {
- color: "#E2D96E",
- category: 'function',
- defaults: {
- minin: {value:"",required:true,validate:RED.validators.number()},
- maxin: {value:"",required:true,validate:RED.validators.number()},
- minout: {value:"",required:true,validate:RED.validators.number()},
- maxout: {value:"",required:true,validate:RED.validators.number()},
- action: {value:"scale"},
- round: {value:false},
- name: {value:""}
- },
- inputs: 1,
- outputs: 1,
- icon: "range.png",
- label: function() {
- return this.name || "range";
- },
- labelStyle: function() {
- return this.name ? "node_label_italic" : "";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="range">
- <p>A simple function node to remap numeric input values to another scale.</p>
- <p>Currently only does a linear scaling.</p>
- <p><b>Note:</b> This only operates on <b>numbers</b>. Anything else will try to be made into a number and rejected if that fails.</p>
- <p><i>Scale and limit to target range</i> means that the result will never be outside the range specified within the result range.</p>
- <p><i>Scale and wrap within the target range</i> means that the result will essentially be a "modulo-style" wrap-around within the result range.</p>
- </script><!DOCTYPE html>
- <!--
- 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.
- -->
- <script type="text/x-red" data-template-name="split">
- <div class="form-row">
- <label for="node-input-splt"><i class="fa fa-scissors"></i> Split</label>
- <input type="text" id="node-input-splt" placeholder="character to split strings on : e.g. \n">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
- <input type="text" id="node-input-name" placeholder="Name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('split',{
- category: 'function',
- color:"#E2D96E",
- defaults: {
- name: {value:""},
- splt: {value:"\\n"}
- },
- inputs:1,
- outputs:1,
- icon: "split.png",
- label: function() {
- return this.name||"split";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-template-name="join">
- <div class="form-row">
- <label>Mode</label>
- <select id="node-input-mode" style="width:200px;">
- <option value="auto">automatic</option>
- <option value="custom">manual</option>
- </select>
- </div>
- <div class="node-row-custom">
- <div class="form-row node-row-property">
- <label>Combine each </label>
- <input type="text" id="node-input-property" style="width:70%;">
- <input type="hidden" id="node-input-propertyType">
- </div>
- <div class="form-row">
- <label>to create </label>
- <select id="node-input-build" style="width:200px;">
- <option id="node-input-build-string" value="string">a String</option>
- <option value="array">an Array</option>
- <option value="object">a key/value Object</option>
- <option value="merged">a merged Object</option>
- </select>
- </div>
- <div class="form-row node-row-key">
- <label style="vertical-align: top; margin-top: 7px;">using</label>
- <div style="display:inline-block">
- <input type="text" id="node-input-key" style="width:300px;">
- <div style="margin-top: 7px;">as the property key</div>
- </div>
- </div>
- <div class="form-row node-row-joiner">
- <label for="node-input-joiner">joined using</label>
- <input type="text" id="node-input-joiner" style="width: 40px">
- </div>
- <div class="form-row node-row-trigger">
- <label style="width: auto;">Send the message:</label>
- <ul>
- <li style="height: 40px;">
- <label style="width: 280px;" for="node-input-count">After a fixed number of messages:</label> <input id="node-input-count" placeholder="count" type="text" style="width: 75px;">
- </li>
- <li style="height: 40px;">
- <label style="width: 280px;" for="node-input-timeout">After a timeout following the first message:</label> <input id="node-input-timeout" placeholder="seconds" type="text" style="width: 75px;">
- </li>
- <li style="height: 40px;">
- <label style="width: auto; padding-top: 6px;">After a message with the <code>msg.complete</code> property set</label>
- </li>
- </ul>
- </div>
- </div>
- <div class="form-tips form-tips-auto hide">This mode assumes this node is either
- paired with a <i>split</i> node or the received messages will have a properly
- configured <code>msg.parts</code> property.</div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('join',{
- category: 'function',
- color:"#E2D96E",
- defaults: {
- name: {value:""},
- mode: {value:"auto"},
- build: { value:"string"},
- property: { value: "payload", validate: RED.validators.typedInput("propertyType")},
- propertyType: { value:"msg"},
- key: {value:"topic"},
- joiner: { value:"\\n"},
- timeout: {value:""},
- count: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "join.png",
- label: function() {
- return this.name||"join";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- $("#node-input-mode").change(function(e) {
- var val = $(this).val();
- $(".node-row-custom").toggle(val==='custom');
- $(".form-tips-auto").toggle(val==='auto');
- });
- $("#node-input-build").change(function(e) {
- var val = $(this).val();
- $(".node-row-key").toggle(val==='object');
- $(".node-row-joiner").toggle(val==='string');
- $(".node-row-trigger").toggle(val!=='auto');
- if (val === 'string') {
- $("#node-input-property").typedInput('types',['msg']);
- } else {
- $("#node-input-property").typedInput('types',['msg', {value:"full",label:"complete message",hasValue:false}]);
- }
- })
- $("#node-input-property").typedInput({
- typeField: $("#node-input-propertyType"),
- types:['msg', {value:"full",label:"complete message",hasValue:false}]
- })
- $("#node-input-key").typedInput({
- types:['msg', {value:"merge",label:"",hasValue: false}]
- })
- $("#node-input-build").change();
- $("#node-input-mode").change();
- }
- });
- </script>
- <script type="text/x-red" data-help-name="split">
- <p>A function that splits <code>msg.payload</code> into multiple messages.</p>
- <p>The behaviour is determined by the type of <code>msg.payload</code>:</p>
- <ul>
- <li><b>string</b> - a message is sent for each part of the string after it is split using the specified character, by default a newline (<code>\n</code>).
- <li><b>array</b> - a message is sent for each element of the array</li>
- <li><b>object</b> - a message is sent for each key/value pair of the object. <code>msg.parts.key</code> is set to the key of the property.</li>
- </ul>
- <p>Each message is sent with the <code>msg.parts</code> property set. This is
- an object that provides any subsequent <i>join</i> node the necessary information
- for it to reassemble the messages back into a single one. The object has the following
- properties:</p>
- <ul>
- <li><b>id</b> - an identifier for the group of messages</li>
- <li><b>index</b> - the position within the group</li>
- <li><b>count</b> - the total number of messages in the group</li>
- <li><b>type</b> - the type of message - string/array/object</li>
- <li><b>ch</b> - for a string, the character used to split</li>
- <li><b>key</b> - for an object, the key of the property this message was created from</li>
- </ul>
- </script><script type="text/x-red" data-help-name="join">
- <p>A function that joins a sequence of messages into a single message.</p>
- <p>When paired with the <b>split</b> node, it will automatically join the messages
- to reverse the split that was performed.</p>
- <p>The node can join either a specific property of each received message or,
- if the output type is not string, the entire message.</p>
- <p>The type of the resulting message property can be:</p>
- <ul>
- <li>a <b>string</b> - created by joining the property of each message with the specified join character.</li>
- <li>an <b>array</b>.</li>
- <li>a <b>key/value object</b> - created by using a property of each message to determine the key under which
- the required value is stored.</li>
- <li>a <b>merged object</b> - created by merging the property of each message under a single object.</li>
- </ul>
- The other properties of the output message are taken from the last message received before the result is sent.</p>
- <p>A <i>count</i> can be set for how many messages should be received before generating the output message</p>
- <p>A <i>timeout</i> can be set to trigger sending the new message using whatever has been received so far.</p>
- <p>If a message is received with the <b>msg.complete</b> property set, the output message is sent.</p>
- <p>The automatic behaviour relies on the received messages to have <b>msg.parts</b> set. The split node generates
- this property, but can be manually created. It has the following properties:</p>
- <ul>
- <li><b>id</b> - an identifier for the group of messages</li>
- <li><b>index</b> - the position within the group</li>
- <li><b>count</b> - the total number of messages in the group</li>
- <li><b>type</b> - the type of message - string/array/object</li>
- <li><b>ch</b> - for a string, the character used to split</li>
- <li><b>key</b> - for an object, the key of the property this message was created from</li>
- </ul>
- </script>
- <!--
- 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.
- -->
- <script type="text/x-red" data-template-name="csv">
- <div class="form-row">
- <label for="node-input-temp"><i class="fa fa-list"></i> <span data-i18n="csv.label.columns"></span></label>
- <input type="text" id="node-input-temp" data-i18n="[placeholder]csv.placeholder.columns">
- </div>
- <div class="form-row">
- <label for="node-input-select-sep"><i class="fa fa-text-width"></i> <span data-i18n="csv.label.separator"></span></label>
- <select style="width: 150px" id="node-input-select-sep">
- <option value="," data-i18n="csv.separator.comma"></option>
- <option value="\t" data-i18n="csv.separator.tab"></option>
- <option value=" " data-i18n="csv.separator.space"></option>
- <option value=";" data-i18n="csv.separator.semicolon"></option>
- <option value=":" data-i18n="csv.separator.colon"></option>
- <option value="#" data-i18n="csv.separator.hashtag"></option>
- <option value="" data-i18n="csv.separator.other"></option>
- </select>
- <input style="width: 40px;" type="text" id="node-input-sep" pattern=".">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <hr align="middle"/>
- <div class="form-row">
- <label style="width: 100%;"><i class="fa fa-gears"></i> <span data-i18n="csv.label.c2o"></span></label>
- <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-sign-in"></i> <span data-i18n="csv.label.input"></span></label>
- <input style="width: 30px" type="checkbox" id="node-input-hdrin"><label style="width: auto;" for="node-input-hdrin"><span data-i18n="csv.label.firstrow"></span></span>
- </div>
- <div class="form-row">
- <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-sign-out"></i> <span data-i18n="csv.label.output"></span></label>
- <select type="text" id="node-input-multi" style="width: 250px;">
- <option value="one" data-i18n="csv.output.row"></option>
- <option value="mult" data-i18n="csv.output.array"></option>
- </select>
- </div>
- <hr align="middle"/>
- <div class="form-row">
- <label style="width: 100%;"><i class="fa fa-gears"></i> <span data-i18n="csv.label.o2c"></span></label>
- <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-sign-in"></i> <span data-i18n="csv.label.output"></span></label>
- <input style="width: 30px" type="checkbox" id="node-input-hdrout"><label style="width: auto;" for="node-input-hdrout"><span data-i18n="csv.label.includerow"></span></span>
- </div>
- <div class="form-row">
- <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-align-left"></i> <span data-i18n="csv.label.newline"></span></label>
- <select style="width: 150px" id="node-input-ret">
- <option value='\n' data-i18n="csv.newline.linux"></option>
- <option value='\r' data-i18n="csv.newline.mac"></option>
- <option value='\r\n' data-i18n="csv.newline.windows"></option>
- </select>
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('csv',{
- category: 'function',
- color:"#DEBD5C",
- defaults: {
- name: {value:""},
- sep: {value:',',required:true,validate:RED.validators.regex(/^.{1,2}$/)},
- //quo: {value:'"',required:true},
- hdrin: {value:""},
- hdrout: {value:""},
- multi: {value:"one",required:true},
- ret: {value:'\\n'},
- temp: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "parser-csv.png",
- label: function() {
- return this.name||"csv";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- if (this.sep == "," || this.sep == "\\t" || this.sep == ";" || this.sep == ":" || this.sep == " " || this.sep == "#") {
- $("#node-input-select-sep").val(this.sep);
- $("#node-input-sep").hide();
- } else {
- $("#node-input-select-sep").val("");
- $("#node-input-sep").val(this.sep);
- $("#node-input-sep").show();
- }
- $("#node-input-select-sep").change(function() {
- var v = $("#node-input-select-sep").val();
- $("#node-input-sep").val(v);
- if (v == "") {
- $("#node-input-sep").val("");
- $("#node-input-sep").show().focus();
- } else {
- $("#node-input-sep").hide();
- }
- });
- }
- });
- </script>
- <script type="text/x-red" data-help-name="csv">
- <p>A function that parses the <code>msg.payload</code> to convert CSV to/from a javascript object.
- Places the result in the payload.</p>
- <p>If the input is a string it tries to parse it as CSV and creates a javascript object.</p>
- <p>If the input is a javascript object it tries to build a CSV string.</p>
- <p>If the input is a simple array the output is just a CSV generated from that array.</p>
- <p>If the input is an array of arrays, or an array of objects, a multiple-line CSV is created.</p>
- <p>The columns template should contain an ordered list of column headers. For CSV input these become the property names.
- For CSV output these specify the properties to extract from the object and the order for the CSV.</p>
- <p>If the input is an array then the columns template does not matter, but can be used to generate a row of column titles.</p>
- <p><b>Note:</b> the columns should always be specified comma separated - even if another separator is chosen for the data.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="html">
- <div class="form-row">
- <label for="node-input-tag"><i class="fa fa-filter"></i> <span data-i18n="html.label.select"></span></label>
- <input type="text" id="node-input-tag" placeholder="h1">
- </div>
- <div class="form-row">
- <label for="node-input-ret"><i class="fa fa-sign-out"></i> <span data-i18n="html.label.output"></span></label>
- <select id="node-input-ret" style="width:70%">
- <option value="html" data-i18n="html.output.html"></option>
- <option value="text" data-i18n="html.output.text"></option>
- <option value="attr" data-i18n="html.output.attr"></option>
- <!-- <option value="val">return the value from a form element</option> -->
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-as"> </label>
- <select id="node-input-as" style="width:70%">
- <option value="single" data-i18n="html.format.single"></option>
- <option value="multi" data-i18n="html.format.multi"></option>
- </select>
- </div>
- <br/>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" style="width:70%" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips"><span data-i18n="[html]html.tip"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('html',{
- category: 'function',
- color:"#DEBD5C",
- defaults: {
- name: {value:""},
- tag: {value:""},
- ret: {value:"html"},
- as: {value:"single"}
- },
- inputs:1,
- outputs:1,
- icon: "parser-html.png",
- label: function() {
- return this.name||this.tag||"html";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="html">
- <p>Extracts elements from an html document held in <code>msg.payload</code> using a selector.</p>
- <p>If left blank the selector may be set dynamically by passing in <code>msg.select</code> along with the <code>msg.payload</code>.
- <p>The selector uses <a href="https://github.com/cheeriojs/cheerio/blob/master/Readme.md" target="_blank">Cheerio</a>
- which uses the <a href="https://github.com/fb55/CSSselect#user-content-supported-selectors" target="_blank">CSS selector</a> syntax.</p>
- <p>The result can be either a single message with a payload containing an array of the matched elements, or multiple
- messages that each contain a matched element.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="json">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('json',{
- category: 'function',
- color:"#DEBD5C",
- defaults: {
- name: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "parser-json.png",
- label: function() {
- return this.name||"json";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="json">
- <p>A function that parses the <code>msg.payload</code> to convert a JSON string to/from a javascript object. Places the result back into the payload.</p>
- <p>If the input is a JSON string it tries to parse it to a javascript object.</p>
- <p>If the input is a javascript object it creates a JSON string.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="xml">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-row" id="advanced">
- </div>
- <div id="advanced-options">
- <div class="form-row">
- <i class="fa fa-key"></i> <span data-i18n="xml.label.represent"></span> <input type="text" id="node-input-attr" style="text-align:center; width:40px" placeholder="$">
- </div>
- <div class="form-row">
- <i class="fa fa-key"></i> <span data-i18n="xml.label.prefix"></span> <input type="text" id="node-input-chr" style="text-align:center; width:40px" placeholder="_">
- </div>
- <div class="form-tips"><span data-i18n="xml.tip"></span></div>
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('xml',{
- category: 'function',
- color:"#DEBD5C",
- defaults: {
- name: {value:""},
- attr: {value:""},
- chr: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "parser-xml.png",
- label: function() {
- return this.name||"xml";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var showadvanced = showadvanced || true;
- var advanced = this._("xml.label.advanced");
- var showall = function() {
- showadvanced = !showadvanced;
- if (showadvanced) {
- $("#advanced-options").show();
- $("#advanced").html('<label for="node-advanced" style="width:200px !important"><i class="fa fa-minus-square"></i> '+advanced+'</label>');
- }
- else {
- $("#advanced-options").hide();
- $("#advanced").html('<label for="node-advanced" style="width:200px !important"><i class="fa fa-plus-square"></i> '+advanced+' ...</label>');
- }
- };
- showall();
- $("#advanced").click( function() { showall(); });
- }
- });
- </script>
- <script type="text/x-red" data-help-name="xml">
- <p>A function that parses the <code>msg.payload</code> to convert xml to/from a javascript object. Places the result in the payload.</p>
- <p>If the input is a string it tries to parse it as XML and creates a javascript object.</p>
- <p>If the input is a javascript object it tries to build an XML string.</p>
- <p>You can also pass in a <code>msg.options</code> object to override all the multitude of parameters. See
- <a href="https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md#options" target="_blank">the xml2js docs</a>
- for more information.</p>
- <p>If set, options in the edit dialogue override those passed in on the msg.options object.</p>
- </script>
- <script type="text/x-red" data-template-name="yaml">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('yaml',{
- category: 'function',
- color:"#DEBD5C",
- defaults: {
- name: {value:""}
- },
- inputs:1,
- outputs:1,
- icon: "parser-yaml.png",
- label: function() {
- return this.name||"yaml";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="yaml">
- <p>A function that parses the <code>msg.payload</code> to convert a YAML string to/from a javascript object. Places the result back into the payload.</p>
- <p>If the input is a YAML string it tries to parse it to a javascript object.</p>
- <p>If the input is a javascript object it creates a YAML string.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="tail">
- <div class="form-row">
- <label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="tail.label.filename"></span></label>
- <input id="node-input-filename" type="text">
- </div>
- <div class="form-row">
- <label for="node-input-filetype"><i class="fa fa-file-text-o"></i> <span data-i18n="tail.label.type"></span></label>
- <select type="text" id="node-input-filetype">
- <option value="text" data-i18n="tail.action.text"></option>
- <option value="binary" data-i18n="tail.action.binary"></option>
- </select>
- </div>
- <div class="form-row" id="node-tail-split">
- <label> </label>
- <input type="checkbox" id="node-input-split" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-split" style="width: 70%;"><span data-i18n="tail.label.splitlines"></span></label>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('tail',{
- category: 'storage-input',
- defaults: {
- name: {value:""},
- filetype: {value:"text"},
- split: {value:false},
- filename: {value:"",required:true}
- },
- color:"BurlyWood",
- inputs:0,
- outputs:1,
- icon: "file.png",
- label: function() {
- return this.name||this.filename;
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- $("#node-input-filetype").on("change",function() {
- if (this.value === "text") { $("#node-tail-split").show(); }
- else { $("#node-tail-split").hide(); }
- });
- }
- });
- </script>
- <script type="text/x-red" data-help-name="tail">
- <p>Tails (watches for things to be added) to the configured file. (Linux/Mac ONLY)</p>
- <p>This will not work on Windows filesystems, as it relies on the <b>tail -F</b> command.</p>
- <p>Text (UTF-8) files will be returned as strings. Binary files will be returned as a Buffer object.</p>
- </script><!--
- 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.
- -->
- <script type="text/x-red" data-template-name="file">
- <div class="form-row node-input-filename">
- <label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
- <input id="node-input-filename" type="text">
- </div>
- <div class="form-row">
- <label for="node-input-overwriteFile"><i class="fa fa-random"></i> <span data-i18n="file.label.action"></span></label>
- <select type="text" id="node-input-overwriteFile" style="display: inline-block; width: 250px; vertical-align: top;">
- <option value="false" data-i18n="file.action.append"></option>
- <option value="true" data-i18n="file.action.overwrite"></option>
- <option value="delete" data-i18n="file.action.delete"></option>
- </select>
- </div>
- <div class="form-row" id="node-appline">
- <label> </label>
- <input type="checkbox" id="node-input-appendNewline" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-appendNewline" style="width: 70%;"><span data-i18n="file.label.addnewline"></span></label>
- </div>
- <div class="form-row">
- <label> </label>
- <input type="checkbox" id="node-input-createDir" style="display: inline-block; width: auto; vertical-align: top;">
- <label for="node-input-createDir" style="width: 70%;"><span data-i18n="file.label.createdir"></span></label>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- <div class="form-tips"><span data-i18n="file.tip"></span></div>
- </script>
- <script type="text/x-red" data-template-name="file in">
- <div class="form-row">
- <label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
- <input id="node-input-filename" type="text" data-i18n="[placeholder]file.label.filename">
- </div>
- <div class="form-row">
- <label for="node-input-format"><i class="fa fa-sign-out"></i> <span data-i18n="file.label.outputas"></span></label>
- <select id="node-input-format">
- <option value="utf8" data-i18n="file.output.utf8"></option>
- <option value="" data-i18n="file.output.buffer"></option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('file',{
- category: 'storage-output',
- defaults: {
- name: {value:""},
- filename: {value:""},
- appendNewline: {value:true},
- createDir: {value:false},
- overwriteFile: {value:"false"}
- },
- color:"BurlyWood",
- inputs:1,
- outputs:0,
- icon: "file.png",
- align: "right",
- label: function() {
- if (this.overwriteFile === "delete") {
- return this.name||this._("file.label.deletelabel",{file:this.filename})
- } else {
- return this.name||this.filename||this._("file.label.filelabel");
- }
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- $("#node-input-overwriteFile").on("change",function() {
- if (this.value === "delete") { $("#node-appline").hide(); }
- else { $("#node-appline").show(); }
- });
- }
- });
- RED.nodes.registerType('file in',{
- category: 'storage-input',
- defaults: {
- name: {value:""},
- filename: {value:""},
- format: {value:"utf8"},
- },
- color:"BurlyWood",
- inputs:1,
- outputs:1,
- icon: "file.png",
- label: function() {
- return this.name||this.filename||this._("file.label.filelabel");
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="file">
- <p>Writes <code>msg.payload</code> to the file specified, for example to create a log.</p>
- <p>The filename can be configured in the node. If left blank it should be
- set by <code>msg.filename</code> on the incoming message.</p>
- <p>A newline is added to every message. But this can be turned off if required, for example, to allow binary files to be written.</p>
- <p>The default behaviour is to append to the file. This can be changed to overwrite the file each time, for example if you want to output a "static" web page or report.</p>
- <p>This node can also be configured to delete a file if required.</p>
- </script><script type="text/x-red" data-help-name="file in">
- <p>Reads the specified file and sends the content as <code>msg.payload</code>,
- and the filename as <code>msg.filename</code>.</p>
- <p>The filename can be configured in the node. If left blank it should be
- set by <code>msg.filename</code> on the incoming message.</p>
- </script>
- <script type="text/x-red" data-template-name="e-mail">
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-envelope"></i> <span data-i18n="email.label.to"></span></label>
- <input type="text" id="node-input-name" placeholder="[email protected]">
- </div>
- <!-- <div class="form-row">
- <label for="node-input-pin"><i class="fa fa-asterisk"></i> Service</label>
- <select type="text" id="node-input-pin" style="width: 150px;">
- <option value="-" disabled> </option>
- <option value="DynectEmail">DynectEmail</option>
- <option value="Gmail">Gmail</option>
- <option value="hot.ee">hot.ee</option>
- <option value="Hotmail">Hotmail</option>
- <option value="iCloud">iCloud</option>
- <option value="mail.ee">mail.ee</option>
- <option value="Mail.Ru">Mail.Ru</option>
- <option value="Mailgun">Mailgun</option>
- <option value="Mailjet">Mailjet</option>
- <option value="Mandrill">Mandrill</option>
- <option value="Postmark">Postmark</option>
- <option value="QQ">QQ</option>
- <option value="QQex">QQex</option>
- <option value="SendGrid">SendGrid</option>
- <option value="SendCloud">SendCloud</option>
- <option value="SES">SES</option>
- <option value="Yahoo">Yahoo</option>
- <option value="yandex">yandex</option>
- <option value="Zoho">Zoho</option>
- </select>
- </div> -->
- <div class="form-row">
- <label for="node-input-server"><i class="fa fa-globe"></i> <span data-i18n="email.label.server"></span></label>
- <input type="text" id="node-input-server" placeholder="smtp.gmail.com">
- </div>
- <div class="form-row">
- <label for="node-input-port"><i class="fa fa-random"></i> <span data-i18n="email.label.port"></span></label>
- <input type="text" id="node-input-port" placeholder="465">
- </div>
- <div class="form-row">
- <label for="node-input-userid"><i class="fa fa-user"></i> <span data-i18n="email.label.userid"></span></label>
- <input type="text" id="node-input-userid">
- </div>
- <div class="form-row">
- <label for="node-input-password"><i class="fa fa-lock"></i> <span data-i18n="email.label.password"></span></label>
- <input type="password" id="node-input-password">
- </div>
- <br/>
- <div class="form-row">
- <label for="node-input-dname"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
- <input type="text" id="node-input-dname" data-i18n="[placeholder]node-red:common.label.name">
- </div>
- <div class="form-tips" id="node-tip"><span data-i18n="[html]email.tip.cred"></span></div>
- </script>
- <script type="text/javascript">
- (function() {
- RED.nodes.registerType('e-mail',{
- category: 'social-output',
- color:"#c7e9c0",
- defaults: {
- server: {value:"smtp.gmail.com",required:true},
- port: {value:"465",required:true},
- name: {value:""},
- dname: {value:""}
- },
- credentials: {
- userid: {type:"text"},
- password: {type: "password"},
- global: { type:"boolean"}
- },
- inputs:1,
- outputs:0,
- icon: "envelope.png",
- align: "right",
- label: function() {
- return this.dname||this.name||"email";
- },
- labelStyle: function() {
- return (this.dname||!this.topic)?"node_label_italic":"";
- },
- oneditprepare: function() {
- if (this.credentials.global) {
- $('#node-tip').show();
- } else {
- $('#node-tip').hide();
- }
- }
- });
- })();
- </script>
- <script type="text/x-red" data-template-name="e-mail in">
- <div class="form-row node-input-repeat">
- <label for="node-input-repeat"><i class="fa fa-repeat"></i> <span data-i18n="email.label.repeat"></span></label>
- <input type="text" id="node-input-repeat" style="width: 80px"> <span data-i18n="email.label.seconds">seconds</span>
- </div>
- <div class="form-row">
- <label for="node-input-protocol"><i class="fa fa-envelope"></i> <span data-i18n="email.label.protocol"></span></label>
- <select type="text" id="node-input-protocol">
- <option value="IMAP">IMAP</option>
- <option value="POP3">POP3</option>
- </select>
- </div>
- <div class="form-row">
- <label for="node-input-useSSL"><i class="fa fa-lock"></i> <span data-i18n="email.label.useSSL"></span></label>
- <input type="checkbox" id="node-input-useSSL" style="width: auto;">
- </div>
- <div class="form-row">
- <label for="node-input-server"><i class="fa fa-globe"></i> <span data-i18n="email.label.server"></span></label>
- <input type="text" id="node-input-server" placeholder="imap.gmail.com">
- </div>
- <div class="form-row">
- <label for="node-input-port"><i class="fa fa-random"></i> <span data-i18n="email.label.port"></span></label>
- <input type="text" id="node-input-port" placeholder="993">
- </div>
- <div class="form-row">
- <label for="node-input-userid"><i class="fa fa-user"></i> <span data-i18n="email.label.userid"></span></label>
- <input type="text" id="node-input-userid">
- </div>
- <div class="form-row">
- <label for="node-input-password"><i class="fa fa-lock"></i> <span data-i18n="email.label.password"></span></label>
- <input type="password" id="node-input-password">
- </div>
- <div class="form-row node-input-box">
- <label for="node-input-box"><i class="fa fa-inbox"></i> <span data-i18n="email.label.folder"></span></label>
- <input type="text" id="node-input-box">
- </div>
- <div class="form-row node-input-disposition">
- <label for="node-input-disposition"><i class="fa fa-trash"></i> <span data-i18n="email.label.disposition"></span></label>
- <select type="text" id="node-input-disposition">
- <option value="None" selected="selected">None</option>
- <option value="Read">Mark Read</option>
- <option value="Delete">Delete</option>
- </select>
- </div>
- <br/>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
- </div>
- <script>
- var checkPorts = function() {
- var currentPort = $("#node-input-port").val();
- if (currentPort === "143" || currentPort === "993" || currentPort === "110" || currentPort == "995") {
- if ($("#node-input-useSSL").prop("checked") === true) {
- $("#node-input-port").val($("#node-input-protocol").val() === "IMAP"?"993":"995");
- } else {
- $("#node-input-port").val($("#node-input-protocol").val() === "IMAP"?"143":"110");
- }
- }
- };
- $("#node-input-useSSL").change(function(x, y) {
- console.log("useSSL: x="+ JSON.stringify(x) + ", y=" + y);
- console.log("Value: " + $("#node-input-useSSL").prop("checked"));
- checkPorts();
- });
- $("#node-input-protocol").change(function() {
- var protocol = $("#node-input-protocol").val();
- if (protocol === "IMAP") {
- $(".node-input-box").show();
- $(".node-input-disposition").show();
- } else {
- $(".node-input-box").hide();
- $(".node-input-disposition").hide();
- }
- checkPorts();
- });
- </script>
- </script>
- <script type="text/javascript">
- (function() {
- RED.nodes.registerType('e-mail in',{
- category: 'social-input',
- color:"#c7e9c0",
- defaults: {
- name: {value:""},
- protocol: {value: "IMAP", required:true}, // Which protocol to use to connect to the mail server ("IMAP" or "POP3")
- server: {value:"imap.gmail.com",required:true},
- useSSL: {value: true},
- port: {value:"993",required:true},
- box: {value:"INBOX"}, // For IMAP, The mailbox to process
- disposition: { value: "Read" }, // For IMAP, the disposition of the read email
- repeat: {value:"300",required:true}
- },
- credentials: {
- userid: {type:"text"},
- password: {type: "password"},
- global: { type:"boolean"}
- },
- inputs:0,
- outputs:1,
- icon: "envelope.png",
- label: function() {
- return this.name||"email";
- },
- labelStyle: function() {
- return (this.name||!this.topic)?"node_label_italic":"";
- },
- oneditprepare: function() {
- if (this.credentials.global) {
- $('#node-tip').show();
- } else {
- $('#node-tip').hide();
- }
- if (typeof this.box === 'undefined') {
- $("#node-input-box").val("INBOX");
- this.box = "INBOX";
- }
- }
- });
- })();
- </script>
- <script type="text/x-red" data-help-name="e-mail">
- <p>Sends the <code>msg.payload</code> as an email, with a subject of <code>msg.topic</code>.</p>
- <p>The default message recipient can be configured in the node, if it is left
- blank it should be set using the <code>msg.to</code> property of the incoming message. If left blank
- you can also specify <code>msg.cc</code> and/or <code>msg.bcc</code> properties.</p>
- <p>You may optionally set <code>msg.from</code> in the payload which will override the <code>userid</code>
- default value.</p>
- <p>The payload can be html format.</p>
- <p>If the payload is a binary buffer then it will be converted to an attachment.
- The filename should be set using <code>msg.filename</code>. Optionally <code>msg.description</code> can be added for the body text.</p>
- <p>Alternatively you may provide <code>msg.attachments</code> which should contain an array of one or
- more attachments in <a href="https://www.npmjs.com/package/nodemailer#attachments" target="_new">nodemailer</a> format.</p>
- <p>If required by your recipient you may also pass in a <code>msg.envelope</code> object, typically containing extra from and to properties.</p>
- <p>Note: uses SMTP with SSL to port 465.</p>
- </script><script type="text/x-red" data-help-name="e-mail in">
- <p>Repeatedly gets a <b>single email</b> from an IMAP server and forwards on as a msg if not already seen.</p>
- <p>The subject is loaded into <code>msg.topic</code> and <code>msg.payload</code> is the plain text body.
- If there is text/html then that is returned in <code>msg.html</code>. <code>msg.from</code> and <code>msg.date</code> are also set if you need them.</p>
- <p>Additionally <code>msg.header</code> contains the complete header object including
- <i>to</i>, <i>cc</i> and other potentially useful properties.</p>
- <p>Uses the imap module.</p>
- <p><b>Note:</b> this node <i>only</i> gets the most recent single email from the inbox, so set the repeat (polling) time appropriately.</p>
- <p>Note: uses IMAP with SSL to port 993.</p>
- <p>Any attachments supplied in the incoming email can be found in the <code>msg.attachments</code> property. This will be an array of objects where
- each object represents a specific attachments. The format of the object is:</p>
- <pre>
- {
- contentType: // The MIME content description
- fileName: // A suggested file name associated with this attachment
- transferEncoding: // How was the original email attachment encodded?
- contentDisposition: // Unknown
- generatedFileName: // A suggested file name associated with this attachment
- contentId: // A unique generated ID for this attachment
- checksum: // A checksum against the data
- length: // Size of data in bytes
- content: // The actual content of the data contained in a Node.js Buffer object
- // We can turn this into a base64 data string with content.toString('base64')
- }
- </pre>
- <p>For POP3, the default port numbers are 110 for plain TCP and 995 for SSL. For IMAP the port numbers are 143 for plain TCP and 993 for SSL.</p>
- </script>
- <script type="text/x-red" data-template-name="feedparse">
- <div class="form-row">
- <label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="feedparse.label.feedurl"></span></label>
- <input type="text" id="node-input-url">
- </div>
- <div class="form-row">
- <label for="node-input-interval"><i class="fa fa-repeat"></i> <span data-i18n="feedparse.label.refresh"></span></label>
- <input type="text" id="node-input-interval" style="width: 50px"> <span data-i18n="feedparse.label.minutes"></span>
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('feedparse',{
- category: 'advanced-input',
- color:"#C0DEED",
- defaults: {
- name: {value:""},
- url: {value:"", required:true},
- interval: { value:15, required: true,validate:RED.validators.number()}
- },
- inputs:0,
- outputs:1,
- icon: "feed.png",
- label: function() {
- return this.name||this.url;
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- }
- });
- </script>
- <script type="text/x-red" data-help-name="feedparse">
- <p>Monitors an RSS/atom feed for new entries.</p>
- <p>The <code>msg.topic</code> contains the original article link. The <code>msg.payload</code>
- contains the description, and <code>msg.article</code> contains the complete article object,
- which has properties such as <code>.title</code>, <code>.summary</code>, <code>.date</code> and so on.</p>
- </script>
- <script type="text/x-red" data-template-name="rbe">
- <div class="form-row">
- <label for="node-input-func"><i class="fa fa-wrench"></i> <span data-i18n="rbe.label.func"></span></label>
- <select type="text" id="node-input-func" style="width:74%;">
- <option value="rbe" data-i18n="rbe.opts.rbe"></option>
- <option value="deadband" data-i18n="rbe.opts.deadband"></option>
- <option value="narrowband" data-i18n="rbe.opts.narrowband"></option>
- </select>
- </div>
- <div class="form-row" id="node-bandgap">
- <label for="node-input-gap"> </label>
- <input type="text" id="node-input-gap" data-i18n="[placeholder]rbe.placeholder.bandgap" style="width:70px;">
- <select type="text" id="node-input-inout" style="width:55%;">
- <option value="out" data-i18n="rbe.opts.out"></option>
- <option value="in" data-i18n="rbe.opts.in"></option>
- </select>
- </div>
- <div class="form-row" id="node-startvalue">
- <label for="node-input-start"><i class="fa fa-thumb-tack"/> <span data-i18n="rbe.label.start"></span></label>
- <input type="text" id="node-input-start" data-i18n="[placeholder]rbe.placeholder.start" style="width:71%;">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"/> <span data-i18n="rbe.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]rbe.label.name" style="width:71%;">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType("rbe", {
- color:"#E2D96E",
- category: 'function',
- defaults: {
- name: {value:""},
- func: {value:"rbe"},
- gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)},
- start: {value:""},
- inout: {value:"out"}
- },
- inputs:1,
- outputs:1,
- icon: "rbe.png",
- label: function() {
- return this.name||this.func||"rbe";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- //$( "#node-input-gap" ).spinner({min:0});
- if ($("#node-input-inout").val() === null) {
- $("#node-input-inout").val("out");
- }
- $("#node-input-func").on("change",function() {
- if ($("#node-input-func").val() === "rbe") {
- $("#node-bandgap").hide();
- } else {
- $("#node-bandgap").show();
- }
- if ($("#node-input-func").val() === "narrowband") {
- $("#node-startvalue").show();
- } else {
- $("#node-startvalue").hide();
- }
- });
- }
- });
- </script>
- <script type="text/x-red" data-help-name="rbe">
- <p>Report by Exception node - only passes on data if it has changed.</p>
- <p>The node can either block until the <code>msg.payload</code> is
- different to the previous one - <b>rbe</b> mode. This works on numbers, strings, and simple objects.</p>
- <p>Or it can block until the value changes by a specified amount - <b>deadband</b> mode.</p>
- <p>In deadband mode the incoming payload must contain a parseable <i>number</i> and is
- output only if greater than + or - the <i>band gap</i> away from a previous value.</p>
- <p>Deadband also supports % - only sends if the input differs by more than x% of the original value.</p>
- <p>It can also ignore outlier values - <b>narrowband</b> mode.</p>
- <p>In narrowband mode the incoming payload is blocked if it is more than + or - the band gap
- away from the previous value. Useful for ignoring outliers from a faulty sensor for example.</p>
- <p>Both Deadband and Narrowband allow comparison against either the <i>previous valid output value</i>, thus
- ignoring any values out of range; or the <i>previous input value</i>, which resets the set point, thus allowing
- gradual drift (deadband), or a step change (narrowband).</p>
- <p><b>Note:</b> This works on a per <code>msg.topic</code> basis. This means that a single rbe node can
- handle multiple topics at the same time.</p>
- </script>
- <script type="text/x-red" data-template-name="twitter-credentials">
- <div class="form-row" id="node-config-twitter-row"></div>
- <input type="hidden" id="node-config-input-screen_name">
- </script>
- <script type="text/javascript">
- (function() {
- var twitterConfigNodeId = null;
- var twitterConfigNodeIntervalId = null;
- RED.nodes.registerType('twitter-credentials',{
- category: 'config',
- defaults: {
- screen_name: {value:""}
- },
- credentials: {
- screen_name: {type:"text"},
- access_token: {type: "password"},
- access_token_secret: {type:"password"}
- },
- label: function() {
- return this.screen_name;
- },
- exportable: false,
- oneditprepare: function() {
- var twitterConfigNodeId = this.id;
- var clickhere = this._("twitter.label.clickhere");
- var twitterID = this._("twitter.label.twitter-id");
- function showTwitterAuthStart() {
- var pathname = document.location.pathname;
- if (pathname.slice(-1) != "/") {
- pathname += "/";
- }
- var callback = encodeURIComponent(location.protocol+"//"+location.hostname+":"+location.port+pathname+"twitter-credentials/"+twitterConfigNodeId+"/auth/callback");
- $("#node-config-dialog-ok").button("disable");
- $("#node-config-twitter-row").html('<div style="text-align: center; margin-top: 20px; "><a class="btn" id="node-config-twitter-start" href="twitter-credentials/'+twitterConfigNodeId+'/auth?callback='+callback+'" target="_blank">'+clickhere+'</a></div>');
- $("#node-config-twitter-start").click(function() {
- twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000);
- });
- }
- function updateTwitterScreenName(sn) {
- $("#node-config-input-screen_name").val(sn);
- $("#node-config-twitter-row").html('<label><i class="fa fa-user"></i> '+twitterID+'</label><span class="input-xlarge uneditable-input">'+sn+'</span>');
- }
- function pollTwitterCredentials(e) {
- $.getJSON('credentials/twitter-credentials/'+twitterConfigNodeId,function(data) {
- if (data.screen_name) {
- updateTwitterScreenName(data.screen_name);
- twitterConfigNodeIntervalId = null;
- $("#node-config-dialog-ok").button("enable");
- } else {
- twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000);
- }
- })
- }
- if (!this.screen_name || this.screen_name === "") {
- showTwitterAuthStart();
- } else {
- if (this.credentials.screen_name) {
- updateTwitterScreenName(this.credentials.screen_name);
- } else {
- showTwitterAuthStart();
- }
- }
- },
- oneditsave: function() {
- if (twitterConfigNodeIntervalId) {
- window.clearTimeout(twitterConfigNodeIntervalId);
- }
- },
- oneditcancel: function(adding) {
- if (twitterConfigNodeIntervalId) {
- window.clearTimeout(twitterConfigNodeIntervalId);
- }
- }
- });
- })();
- </script>
- <script type="text/x-red" data-template-name="twitter in">
- <div class="form-row">
- <label for="node-input-twitter"><i class="fa fa-user"></i> <span data-i18n="twitter.label.twitter-id"></span></label>
- <input type="text" id="node-input-twitter">
- </div>
- <div class="form-row">
- <label for="node-input-user"><i class="fa fa-search"></i> <span data-i18n="twitter.label.search"></span></label>
- <select type="text" id="node-input-user" style="display: inline-block; vertical-align: middle; width:60%;">
- <option value="false" data-i18n="twitter.search.public"></option>
- <option value="true" data-i18n="twitter.search.follow"></option>
- <option value="user" data-i18n="twitter.search.user"></option>
- <option value="dm" data-i18n="twitter.search.direct"></option>
- <option value="event" data-i18n="twitter.search.events"></option>
- </select>
- </div>
- <div class="form-row" id="node-input-tags-row">
- <label for="node-input-tags"><i class="fa fa-tags"></i> <span id="node-input-tags-label" data-i18n="twitter.label.for"></span></label>
- <input type="text" id="node-input-tags" data-i18n="[placeholder]twitter.placeholder.for">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
- </div>
- <div class="form-tips"><span data-i18n="[html]twitter.tip"></span></div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('twitter in',{
- category: 'social-input',
- color:"#C0DEED",
- defaults: {
- twitter: {type:"twitter-credentials",required:true},
- tags: {value:""},
- user: {value:"false",required:true},
- name: {value:""},
- topic: {value:"tweets"},
- inputs: {value:0}
- },
- inputs: 0,
- outputs: 1,
- icon: "twitter.png",
- label: function() {
- if (this.name) {
- return this.name;
- }
- var uname = RED.nodes.node(this.twitter);
- if (this.user == "dm") {
- return (uname?uname.label()+" ":"")+this._("twitter.label.dmslabel");
- } else if (this.user == "event") {
- var user = RED.nodes.node(this.twitter);
- return (user?user.label()+" ":"")+this._("twitter.label.eventslabel");
- } else if (this.user == "user") {
- return this.tags+" "+this._("twitter.label.tweetslabel");
- }
- else if (this.user == "true") {
- return this._("twitter.label.followers") + (uname?(" "+uname.label()):"");
- }
- return "twitter";
- },
- labelStyle: function() {
- return this.name?"node_label_italic":"";
- },
- oneditprepare: function() {
- var userlabel = this._("twitter.label.user");
- var userph = this._("twitter.placeholder.user");
- var forlabel = this._("twitter.label.for");
- var forph = this._("twitter.placeholder.for");
- $("#node-input-user").change(function() {
- var type = $("#node-input-user option:selected").val();
- if (type == "user") {
- $("#node-input-tags-row").show();
- $("#node-input-tags-label").html(userlabel);
- $("#node-input-tags").attr("placeholder",userph);
- } else if ((type == "dm")||(type == "true")||(type == "event")) {
- $("#node-input-tags-row").hide();
- } else {
- $("#node-input-tags-row").show();
- $("#node-input-tags-label").html(forlabel);
- $("#node-input-tags").attr("placeholder",forph);
- }
- });
- $("#node-input-user").change();
- },
- oneditsave: function() {
- if ($('#node-input-tags').val() === '' && $("#node-input-user option:selected").val() === 'false') {
- this.inputs = 1;
- }
- else {
- //set back the default state of 0 inputs
- //this.inputs = 0;
- }
- }
- });
- </script>
- <script type="text/x-red" data-template-name="twitter out">
- <div class="form-row">
- <label for="node-input-twitter"><i class="fa fa-user"></i> <span data-i18n="twitter.label.twitter-id"></span></label>
- <input type="text" id="node-input-twitter">
- </div>
- <div class="form-row">
- <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
- <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
- </div>
- </script>
- <script type="text/javascript">
- RED.nodes.registerType('twitter out',{
- category: 'social-output',
- color:"#C0DEED",
- defaults: {
- twitter: {type:"twitter-credentials",required:true},
- name: {value:"Tweet"}
- },
- inputs:1,
- outputs:0,
- icon: "twitter.png",
- align: "right",
- label: function() {
- return this.name;
- }
- });
- </script>
- <script type="text/x-red" data-help-name="twitter in">
- <p>Twitter input node. Can be used to search either:
- <ul><li>the public stream for tweets containing the configured search term</li>
- <li>all the tweets from accounts that the authenticated user follows</li>
- <li>all tweets by specified users</li>
- <li>direct messages received by the authenticated user</li>
- <li>twitter events for the authenticated user</li>
- </ul></p>
- <p>Use space for <i>and</i> and comma , for <i>or</i> when searching for multiple terms.
- If you want to pass in the search term(s) via the <code>msg.payload</code>, leave the <b>for</b> field blank.</p>
- <p>Sets the <code>msg.topic</code> to <i>tweets/</i> and then appends the senders screen name.</p>
- <p>Sets <code>msg.location</code> to the tweeters location if known.</p>
- <p>When returning events it sets the <code>msg.payload</code> to the twitter event, a full list is documented by
- <a href="https://dev.twitter.com/streaming/overview/messages-types#Events_event" target="_new">Twitter</a>.</p>
- <p>Sets <code>msg.tweet</code> to the full tweet object as documented by <a href="https://dev.twitter.com/overview/api/tweets" target="_new">Twitter</a>.
- <p><b>Note</b>: This node is not connected to the FireHose, so will not return 100% of all tweets to a busy @id or #hashtag.</p>
- <p><b>Note:</b> when set to follow specific users, or your direct messages, the node is subject to
- the rate limiting of the Twitter API. If you deploy the flows multiple times within a 15 minute window, you may
- exceed the limit and will see errors from the node. These errors will clear automatically when the current 15
- minute window passes.</p>
- </script><script type="text/x-red" data-help-name="twitter out">
- <p>Twitter out node. Tweets the <code>msg.payload</code>.</p>
- <p>To send a Direct Message (DM) - use a payload like "D {username} {message}"</p>
- <p>If <code>msg.media</code> exists and is a Buffer object, this node will treat it
- as an image and attach it to the tweet.</p>
- <p>If <code>msg.params</code> exists and is an object of name:value pairs,
- this node will treat it as parameters for the update request.</p>
- </script>
Add Comment
Please, Sign In to add comment