mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	* initial support of merge mode of JOIN node * initial support of reduce mode of JOIN node * update info document of JOIN node * add tests for merge & reduce mode of JOIN node * tidy tabs & spaces * add test for too many pending messages & related fixes * add an test for reduce mode of JOIN node * change order of modes of SWITCH node * add initial topics entry of merge mode * fixed descriptions on "reduce right" checkbox * fixed update of typedInput field of reduce mode * fixed a typo in info document of JOIN node * allow empty string in JSONata input field of reduce mode * fixed a typo * fixed error in reduce mode description
		
			
				
	
	
		
			542 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			542 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			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"><span data-i18n="[html]split.intro"></span></div>
 | |
|     <div class="form-row"><span data-i18n="[html]split.strBuff"></span></div>
 | |
|     <div class="form-row">
 | |
|         <label for="node-input-splt" style="padding-left:10px; margin-right:-10px;" data-i18n="split.splitUsing"></label>
 | |
|         <input type="text" id="node-input-splt" style="width:70%">
 | |
|         <input type="hidden" id="node-input-spltType">
 | |
|     </div>
 | |
|     <div class="form-row">
 | |
|         <input type="checkbox" id="node-input-stream" style="margin-left:10px; vertical-align:top; width:auto;">
 | |
|         <label for="node-input-stream" style="width:auto;" data-i18n="split.stream"></label>
 | |
|     </div>
 | |
|     <div class="form-row"><span data-i18n="[html]split.array"></span></div>
 | |
|     <div class="form-row">
 | |
|         <label for="node-input-arraySplt" style="padding-left:10px; margin-right:-10px;" data-i18n="split.splitUsing"></label>
 | |
|         <input type="text" id="node-input-arraySplt" style="width:70%">
 | |
|         <input type="hidden" id="node-input-arraySpltType">
 | |
|     </div>
 | |
|     <div class="form-row"><span data-i18n="[html]split.object"></span></div>
 | |
|     <div class="form-row" style="padding-left: 10px"><span data-i18n="[html]split.objectSend"></span></div>
 | |
|     <div class="form-row">
 | |
|         <input type="checkbox" id="node-input-addname-cb" style="margin-left:10px; vertical-align:baseline; width:auto;">
 | |
|         <label for="node-input-addname-cb" style="width:auto;" data-i18n="split.addname"></label>
 | |
|         <input type="text" id="node-input-addname" style="width:70%">
 | |
|     </div>
 | |
|     <hr/>
 | |
|     <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/x-red" data-help-name="split">
 | |
|     <p>Splits a message into a sequence of messages.</p>
 | |
| 
 | |
|     <h3>Inputs</h3>
 | |
|     <dl class="message-properties">
 | |
|         <dt>payload<span class="property-type">object | string | array | buffer</span></dt>
 | |
|         <dd>The behaviour of the node is determined by the type of <code>msg.payload</code>:
 | |
|             <ul>
 | |
|                 <li><b>string</b>/<b>buffer</b> - the message is split using the specified character (default: <code>\n</code>), buffer sequence or into fixed lengths.</li>
 | |
|                 <li><b>array</b> - the message is split into either individual array elements, or arrays of a fixed-length.</li>
 | |
|                 <li><b>object</b> - a message is sent for each key/value pair of the object.</li>
 | |
|             </ul>
 | |
|         </dd>
 | |
|     </dl>
 | |
|     <h3>Outputs</h3>
 | |
|     <dl class="message-properties">
 | |
|         <dt>parts<span class="property-type">object</span></dt>
 | |
|         <dd>This property contains information about how the message was split from
 | |
|         the original message. If passed to the <b>join</b> node, the sequence can be
 | |
|         reassembled into a single message. The property has the following properties:
 | |
|         <ul>
 | |
|             <li><code>id</code> - an identifier for the group of messages</li>
 | |
|             <li><code>index</code> - the position within the group</li>
 | |
|             <li><code>count</code> - if known, the total number of messages in the group. See 'streaming mode' below.</li>
 | |
|             <li><code>type</code> - the type of message - string/array/object/buffer</li>
 | |
|             <li><code>ch</code> - for a string or buffer, the data used to the split the message as either the string or an array of bytes</li>
 | |
|             <li><code>key</code> - for an object, the key of the property this message was created from. The node can be configured to also copy this value to another message properties, such as <code>msg.topic</code>.</li>
 | |
|             <li><code>len</code> - the length of each message when split using a fixed length value</li>
 | |
|         </ul>
 | |
|         </dd>
 | |
|     </dl>
 | |
|     <h3>Details</h3>
 | |
|     <p>This node makes it easy to create a flow that performs common actions across
 | |
|     a sequence of messages before, using the <b>join</b> node, recombining the
 | |
|     sequence into a single message.</p>
 | |
|     <p>It uses the <code>msg.parts</code> property to track the individual parts
 | |
|     of a sequence.</p>
 | |
|     <h4>Streaming mode</h4>
 | |
|     <p>The node can also be used to reflow a stream of messages. For example, a
 | |
|     serial device that sends newline-terminated commands may deliver a single message
 | |
|     with a partial command at its end. In 'streaming mode', this node will split
 | |
|     a message and send each complete segment. If there is a partial segment at the end,
 | |
|     the node will hold on to it and prepend it to the next message that is received.
 | |
|     </p>
 | |
|     <p>When operating in this mode, the node will not set the `msg.parts.count`
 | |
|     property as it does not know how many messages to expect in the stream. This
 | |
|     means it cannot be used with the <b>join</b> node in its automatic mode</p>
 | |
| 
 | |
| 
 | |
| </script>
 | |
| 
 | |
| <script type="text/javascript">
 | |
|     RED.nodes.registerType('split',{
 | |
|         category: 'function',
 | |
|         color:"#E2D96E",
 | |
|         defaults: {
 | |
|             name: {value:""},
 | |
|             splt: {value:"\\n"},
 | |
|             spltType: {value:"str"},
 | |
|             arraySplt: {value:1},
 | |
|             arraySpltType: {value:"len"},
 | |
|             stream: {value:false},
 | |
|             addname: {value:""}
 | |
|         },
 | |
|         inputs:1,
 | |
|         outputs:1,
 | |
|         icon: "split.png",
 | |
|         label: function() {
 | |
|             return this.name||"split";
 | |
|         },
 | |
|         labelStyle: function() {
 | |
|             return this.name?"node_label_italic":"";
 | |
|         },
 | |
|         oneditprepare: function() {
 | |
|             $("#node-input-splt").typedInput({
 | |
|                 default: 'str',
 | |
|                 typeField: $("#node-input-spltType"),
 | |
|                 types:[
 | |
|                     'str',
 | |
|                     'bin',
 | |
|                     {value:"len", label:RED._("node-red:split.splitLength"),validate:/^\d+$/}
 | |
|                 ]
 | |
|             });
 | |
|             if (this.arraySplt === undefined) {
 | |
|                 $("#node-input-arraySplt").val(1);
 | |
|             }
 | |
|             $("#node-input-arraySplt").typedInput({
 | |
|                 default: 'len',
 | |
|                 typeField: $("#node-input-arraySpltType"),
 | |
|                 types:[
 | |
|                     {value:"len", label:RED._("node-red:split.splitLength"),validate:/^\d+$/}
 | |
|                 ]
 | |
|             });
 | |
|             $("#node-input-addname").typedInput({
 | |
|                 typeField: $("#node-input-fnameType"),
 | |
|                 types:['msg']
 | |
|             });
 | |
| 
 | |
|             $("#node-input-addname-cb").change(function() {
 | |
|                 $("#node-input-addname").prop('disabled',!this.checked);
 | |
|             })
 | |
|             if (this.addname === "") {
 | |
|                 $("#node-input-addname-cb").prop('checked',false);
 | |
|                 $("#node-input-addname").val('topic');
 | |
|             } else {
 | |
|                 $("#node-input-addname-cb").prop('checked',true);
 | |
|             }
 | |
|             $("#node-input-addname-cb").change();
 | |
|         },
 | |
|         oneditsave: function() {
 | |
|             if (!$("#node-input-addname-cb").prop('checked')) {
 | |
|                 $("#node-input-addname").val('');
 | |
|             }
 | |
|         }
 | |
|     });
 | |
| </script>
 | |
| 
 | |
| 
 | |
| <script type="text/x-red" data-template-name="join">
 | |
|     <div class="form-row">
 | |
|         <label data-i18n="join.mode.mode"></label>
 | |
|         <select id="node-input-mode" style="width:200px;">
 | |
|             <option value="auto" data-i18n="join.mode.auto"></option>
 | |
|             <option value="custom" data-i18n="join.mode.custom"></option>
 | |
|             <option value="merge" data-i18n="join.mode.merge"></option>
 | |
|             <option value="reduce" data-i18n="join.mode.reduce"></option>
 | |
|         </select>
 | |
|     </div>
 | |
|     <div class="node-row-custom">
 | |
|         <div class="form-row node-row-property">
 | |
|             <label data-i18n="join.combine"> </label>
 | |
|             <input type="text" id="node-input-property" style="width:70%;">
 | |
|             <input type="hidden" id="node-input-propertyType">
 | |
|         </div>
 | |
|         <div class="form-row">
 | |
|             <label data-i18n="join.create"></label>
 | |
|             <select id="node-input-build" style="width:70%;">
 | |
|                 <option value="string" data-i18n="join.type.string"></option>
 | |
|                 <option value="buffer" data-i18n="join.type.buffer"></option>
 | |
|                 <option value="array" data-i18n="join.type.array"></option>
 | |
|                 <option value="object" data-i18n="join.type.object"></option>
 | |
|                 <option value="merged" data-i18n="join.type.merged"></option>
 | |
|             </select>
 | |
|         </div>
 | |
|         <div class="form-row node-row-key">
 | |
|             <label style="vertical-align:top; margin-top:7px; width:auto; margin-right: 5px;" data-i18n="join.using"></label>
 | |
|             <div style="display:inline-block">
 | |
|                 <input type="text" id="node-input-key" style="width:220px;"> <span data-i18n="join.key"></span>
 | |
|             </div>
 | |
|         </div>
 | |
|         <div class="form-row node-row-joiner">
 | |
|             <label for="node-input-joiner" data-i18n="join.joinedUsing"></label>
 | |
|             <input type="text" id="node-input-joiner" style="width:70%">
 | |
|             <input type="hidden" id="node-input-joinerType">
 | |
|         </div>
 | |
|         <div class="form-row node-row-trigger" id="trigger-row">
 | |
|             <label style="width:auto;" data-i18n="join.send"></label>
 | |
|             <ul>
 | |
|                 <li>
 | |
|                     <label style="width:280px;" for="node-input-count" data-i18n="join.afterCount"></label> <input id="node-input-count" data-i18n="[placeholder]join.count" type="text" style="width:75px;">
 | |
|                 </li>
 | |
|                 <li class="node-row-accumulate" style="list-style-type:none;">
 | |
|                     <input type="checkbox" id="node-input-accumulate" style="display:inline-block; width:20px; margin-left:20px; vertical-align:top;">  <label style="width: auto" for="node-input-accumulate" data-i18n="join.subsequent"></label>
 | |
|                 </li>
 | |
|                 <li>
 | |
|                     <label style="width:280px;" for="node-input-timeout" data-i18n="join.afterTimeout"></label> <input id="node-input-timeout" data-i18n="[placeholder]join.seconds" type="text" style="width:75px;">
 | |
|                 </li>
 | |
|                 <li>
 | |
|                     <label style="width:auto; padding-top:6px;" data-i18n="[html]join.complete"></label>
 | |
|                 </li>
 | |
|             </ul>
 | |
|         </div>
 | |
|     </div>
 | |
|     <div class="node-row-merge">
 | |
|         <div class="form-row">
 | |
|             <label data-i18n="join.merge.topics-label"></label>
 | |
|             <div class="form-row node-input-topics-container-row">
 | |
|                 <ol id="node-input-topics-container"></ol>
 | |
|             </div>
 | |
|         </div>
 | |
|         <div class="form-row">
 | |
|             <input type="checkbox" id="node-input-mergeOnChange" style="margin-left:10px; vertical-align:top; width:auto;">
 | |
|             <label for="node-input-mergeOnChange" style="width:auto;" data-i18n="join.merge.on-change"></label>
 | |
|         </div>
 | |
|     </div>
 | |
|     <div class="node-row-reduce">
 | |
|         <div class="form-row">
 | |
|             <label for="node-input-reduceExp" data-i18n="join.reduce.exp" style="margin-left:10px;"></label>
 | |
|             <input type="text" id="node-input-reduceExp" data-i18n="[placeholder]join.reduce.exp-value" style="width:65%">
 | |
|         </div>
 | |
|         <div class="form-row">
 | |
|             <label for="node-input-reduceInit" data-i18n="join.reduce.init" style="margin-left:10px;"></label>
 | |
|             <input type="text" id="node-input-reduceInit" data-i18n="[placeholder]join.reduce.init" style="width:65%">
 | |
|             <input type="hidden" id="node-input-reduceInitType">
 | |
|         </div>
 | |
|         <div class="form-row">
 | |
|             <label for="node-input-reduceFixup" data-i18n="join.reduce.fixup" style="margin-left:10px;"></label>
 | |
|             <input type="text" id="node-input-reduceFixup" data-i18n="[placeholder]join.reduce.exp-value" style="width:65%">
 | |
|         </div>
 | |
|         <div class="form-row">
 | |
|             <label> </label>
 | |
|             <input type="checkbox" id="node-input-reduceRight" style="display:inline-block; width:auto; vertical-align:top; margin-left:10px;">
 | |
|             <label for="node-input-reduceRight" style="width:70%;" data-i18n="join.reduce.right" style="margin-left:10px;"/>
 | |
|         </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>
 | |
|     <div class="form-tips form-tips-auto hide" data-i18n="[html]join.tip"></div>
 | |
| </script>
 | |
| 
 | |
| <script type="text/x-red" data-help-name="join">
 | |
|     <p>Joins sequences of messages into a single message.  This node provides four mode for message combination:</p>
 | |
|     <dl>
 | |
|         <dt>automatic</dt>
 | |
|         <dd>When paired with the <b>split</b> node, it will automatically join the messages to reverse the split that was performed.</dd>
 | |
|         <dt>manual</dt>
 | |
|         <dd>It will join sequences of messages in a variety of ways.</dd>
 | |
|         <dt>merge sequence</dt>
 | |
|         <dd>It will merge incoming messages into single message using <code>topic</code> property.</dd>
 | |
|         <dt>reduce sequence</dt>
 | |
|         <dd>When paired with the <b>split</b> node, it will reduce the message sequence into single message.</dd>
 | |
|     </dl>
 | |
|     <h3>Inputs</h3>
 | |
|     <dl class="message-properties">
 | |
|         <dt class="optional">parts<span class="property-type">object</span></dt>
 | |
|         <dd>To automatically join a sequence of messages, they should all have
 | |
|         this property set. The <b>split</b> node generates this property but it
 | |
|         can be manually created. It has the following properties:
 | |
|         <ul>
 | |
|             <li><code>id</code> - an identifier for the group of messages</li>
 | |
|             <li><code>index</code> - the position within the group</li>
 | |
|             <li><code>count</code> - the total number of messages in the group</li>
 | |
|             <li><code>type</code> - the type of message - string/array/object/buffer</li>
 | |
|             <li><code>ch</code> - for a string or buffer, the data used to the split the message as either the string or an array of bytes</li>
 | |
|             <li><code>key</code> - for an object, the key of the property this message was created from</li>
 | |
|             <li><code>len</code> - the length of each message when split using a fixed length value</li>
 | |
|         </ul>
 | |
|         </dd>
 | |
|         <dt class="optional">complete</dt>
 | |
|         <dd>If set, the node will send its output message in its current state.</dd>
 | |
|     </dl>
 | |
|     <h3>Details</h3>
 | |
| 
 | |
|     <h4>Automatic mode</h4>
 | |
|     <p>When configured to join in manual mode, the node is able to join sequences of messages using <code>parts</code> property of incoming messages.</p>
 | |
| 
 | |
|     <h4>Manual mode</h4>
 | |
|     <p>When configured to join in manual mode, the node is able to join sequences
 | |
|      of messages in a variety of ways.</p>
 | |
|     <ul>
 | |
|         <li>a <b>string</b> or <b>buffer</b> - created by joining the selected property of each message with the specified join characters or buffer.</li>
 | |
|         <li>an <b>array</b> - created by adding each selected property, or entire message, to the output array.</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>
 | |
|     <p>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.
 | |
|     For object outputs, once this count has been reached, the node can be configured to send a message for each subsequent message
 | |
|     received.</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>
 | |
| 
 | |
|     <h4>Merge Sequence mode</h4>
 | |
|     <p>When configured to join in merge mode, the join node can create a message based on <code>topic</code> value.</p>
 | |
|     <p>Input messages are merged in order specified by <b>Topics</b> value.
 | |
|     <p>For example, if value of <b>Topics</b> is <b>x,x,y</b>, two input messages with topic <b>x</b> and one input message with topic <b>y</b> are merged into a new message in order of arrival.</p>
 | |
|     <p>If "Send merged message on arrival of a new topic" check box is selected, the last messages with each topic is kept internally and output message is sent when a message with new topics arrives.</p>
 | |
| 
 | |
|     <p>The merged message contains <code>payload</code> property and properties for each topic.  The <code>payload</code> property represents ordered array of payload value of input messages for each topic.  The property for each topic represents a payload value for single occurrence of topic or array of payload values for multiple occurrences of the topic.</p>
 | |
| 
 | |
|     <h4>Reduce Sequence mode</h4>
 | |
|     <p>When configured to join in reduce sequence mode, following values can be specified:</p>
 | |
|     <dl class="message-properties">
 | |
|         <dt>Reduce exp</dt>
 | |
|         <dd>JSONata expression for reducing message group.  This expression represents the accumulated result.  In the expression, following special variables can be used:
 | |
|             <ul>
 | |
|                 <li><code>$A</code> accumulated value, </li>
 | |
|                 <li><code>$I</code> index of the message in a group, </li>
 | |
|                 <li><code>$N</code> number of messages of a group.</li>
 | |
|             </ul>
 | |
|         </dd>
 | |
|         <dt>Initial value</dt>
 | |
|         <dd>
 | |
|             initial value of reduction.
 | |
|         </dd>
 | |
|         <dt>Fixup exp</dt>
 | |
|         <dd>
 | |
|             JSONata expression applied after reduction of a message group completed.  In the expression, following special variables can be used:
 | |
|             <ul>
 | |
|                 <li><code>$A</code> accumulated value, </li>
 | |
|                 <li><code>$N</code> number of messages of a group.</li>
 | |
|             </ul>
 | |
|         </dd>
 | |
|         <p>Order of reduction on a message group can be specified by checkbox (<b>Evaluate in reverse order (right to left)</b>).</p>
 | |
|     </dl>
 | |
|     <p><b>Example:</b> Join node outputs an average for each input message group with the following setting:
 | |
|         <ul>
 | |
|             <li><b>Reduce exp</b>: <code>$A+payload</code></li>
 | |
|             <li><b>Initial value</b>: <code>0</code></li>
 | |
|             <li><b>Fixup exp</b>: <code>$A/$N</code></li>
 | |
|         </ul>
 | |
|     </p>
 | |
| 
 | |
|     <h4>Note:</h4>
 | |
|     <p>This node internally keeps messages for its operation.  In order to prevent unexpected memory usage, maximum number of messages kept can be specified by <code>joinMaxKeptMsgsCount</code> property in <b>settings.js</b>.</p>
 | |
| </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"},
 | |
|             joinerType: { value:"str"},
 | |
|             accumulate: { value:"false" },
 | |
|             timeout: {value:""},
 | |
|             count: {value:""},
 | |
|             topics: {value:[{topic:""}]},
 | |
|             mergeOnChange: {value:false},
 | |
|             reduceRight: {value:false},
 | |
|             reduceExp: {value:undefined},
 | |
|             reduceInit: {value:undefined},
 | |
|             reduceInitType: {value:undefined},
 | |
|             reduceFixup: {value:undefined}
 | |
|         },
 | |
|         inputs:1,
 | |
|         outputs:1,
 | |
|         icon: "join.png",
 | |
|         label: function() {
 | |
|             return this.name||"join";
 | |
|         },
 | |
|         labelStyle: function() {
 | |
|             return this.name?"node_label_italic":"";
 | |
|         },
 | |
|         oneditprepare: function() {
 | |
|             var node = this;
 | |
|             var topic_str = node._("join.merge.topic");
 | |
|             
 | |
|             function resizeTopics(topic) {
 | |
|                 var newWidth = topic.width();
 | |
|                 topic.find('.red-ui-typedInput')
 | |
|                      .typedInput("width",newWidth-15);
 | |
|             }
 | |
|             $("#node-input-topics-container")
 | |
|                 .css('min-height','250px').css('min-width','420px')
 | |
|                 .editableList({
 | |
|                 addItem: function(container,i,opt) {
 | |
|                     if (!opt.hasOwnProperty('topic')) {
 | |
|                         opt.topic = "";
 | |
|                     }
 | |
|                     var row = $('<div/>').appendTo(container);
 | |
|                     var valueField = $('<input/>',{
 | |
|                         class:"node-input-topic-value",
 | |
|                         type:"text",
 | |
|                         style:"margin-left: 5px;"
 | |
|                     }).appendTo(row)
 | |
|                       .typedInput({default:'str', types:['str']});
 | |
|                     valueField.typedInput('value', opt.topic);
 | |
|                     valueField.typedInput('type', 'str');
 | |
|                     valueField.attr('placeholder', topic_str);
 | |
|                     resizeTopics(container);
 | |
|                 },
 | |
|                 resizeItem: resizeTopics,
 | |
|                 sortable: true,
 | |
|                 removable: true
 | |
|             });
 | |
| 
 | |
|             $("#node-input-mode").change(function(e) {
 | |
|                 var val = $(this).val();
 | |
|                 $(".node-row-custom").toggle(val==='custom');
 | |
|                 $(".node-row-merge").toggle(val==='merge');
 | |
|                 $(".node-row-reduce").toggle(val==='reduce');
 | |
|                 $(".form-tips-auto").toggle((val==='auto') || (val==='reduce'));
 | |
|                 if (val === "auto") {
 | |
|                     $("#node-input-accumulate").attr('checked', false);
 | |
|                 }
 | |
|                 else if (val === "merge") {
 | |
|                     var topics = node.topics;
 | |
|                     var container = $("#node-input-topics-container");
 | |
|                     container.editableList('empty');
 | |
|                     for (var i=0;i<topics.length;i++) {
 | |
|                         var topic = topics[i];
 | |
|                         container.editableList('addItem', topic);
 | |
|                     }
 | |
|                 }
 | |
|                 else if (val === "reduce") {
 | |
|                     var jsonata_or_empty = {
 | |
|                         value: "jsonata",
 | |
|                         label: "expression",
 | |
|                         icon: "red/images/typedInput/expr.png",
 | |
|                         validate: function(v) {
 | |
|                             try{
 | |
|                                 if(v !== "") {
 | |
|                                     jsonata(v);
 | |
|                                 }
 | |
|                                 return true;
 | |
|                             }
 | |
|                             catch(e){
 | |
|                                 return false;
 | |
|                             }
 | |
|                         },
 | |
|                         expand:function() {
 | |
|                             var that = this;
 | |
|                             RED.editor.editExpression({
 | |
|                                 value: this.value().replace(/\t/g,"\n"),
 | |
|                                 complete: function(v) {
 | |
|                                     that.value(v.replace(/\n/g,"\t"));
 | |
|                                 }
 | |
|                             })
 | |
|                         }
 | |
|                     };
 | |
|                     $("#node-input-reduceExp").typedInput({types:[jsonata_or_empty]});
 | |
|                     $("#node-input-reduceInit").typedInput({
 | |
|                         default: 'num',
 | |
|                         types:['flow','global','str','num','bool','json','bin','date','jsonata'],
 | |
|                         typeField: $("#node-input-reduceInitType")
 | |
|                     });
 | |
|                     $("#node-input-reduceFixup").typedInput({types:[jsonata_or_empty]});
 | |
|                 }
 | |
|             });
 | |
| 
 | |
|             $("#node-input-build").change(function(e) {
 | |
|                 var val = $(this).val();
 | |
|                 $(".node-row-key").toggle(val==='object');
 | |
|                 $(".node-row-accumulate").toggle(val==='object' || val==='merged');
 | |
|                 $(".node-row-joiner").toggle(val==='string' || val==='buffer');
 | |
|                 $(".node-row-trigger").toggle(val!=='auto');
 | |
|                 if (val === 'string' || val==='buffer') {
 | |
|                     $("#node-input-property").typedInput('types',['msg']);
 | |
|                 } else {
 | |
|                     $("#node-input-property").typedInput('types',['msg', {value:"full",label:"complete message",hasValue:false}]);
 | |
|                 }
 | |
|             });
 | |
| 
 | |
|             $("#node-input-joiner").typedInput({
 | |
|                 default: 'str',
 | |
|                 typeField: $("#node-input-joinerType"),
 | |
|                 types:[
 | |
|                     'str',
 | |
|                     'bin'
 | |
|                 ]
 | |
|             });
 | |
| 
 | |
|             $("#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();
 | |
|         },
 | |
|         oneditsave: function() {
 | |
|             var build = $("#node-input-build").val();
 | |
|             if (build !== 'object' && build !== 'merged') {
 | |
|                 $("#node-input-accumulate").prop("checked",false);
 | |
|             }
 | |
|             var topics = $("#node-input-topics-container").editableList('items');
 | |
|             var node = this;
 | |
|             node.topics = [];
 | |
|             topics.each(function(i) {
 | |
|                 var topicData = $(this).data('data');
 | |
|                 var topic = $(this);
 | |
|                 var vf = topic.find(".node-input-topic-value");
 | |
|                 var value = vf.typedInput('value');
 | |
|                 var r = {topic:value};
 | |
|                 node.topics.push(r);
 | |
|             });
 | |
|         },
 | |
|         oneditresize: function(size) {
 | |
|             var rows = $("#dialog-form>div:not(.node-input-topics-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-topics-container-row");
 | |
|             height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
 | |
|             $("#node-input-topics-container").editableList('height',height);
 | |
|         }
 | |
|     });
 | |
| </script>
 |