From e594ffe0f8a5188f6c6ee0909c46d411412b0210 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sun, 5 Jun 2016 23:32:03 +0100 Subject: [PATCH] Update Join node runtime to match UI changes --- editor/js/ui/typedInput.js | 101 ++++++++--------- nodes/core/logic/17-split.html | 58 +++++----- nodes/core/logic/17-split.js | 146 +++++++++++++------------ test/nodes/core/logic/17-split_spec.js | 8 +- 4 files changed, 169 insertions(+), 144 deletions(-) diff --git a/editor/js/ui/typedInput.js b/editor/js/ui/typedInput.js index 94abdb9a0..1fd63abc0 100644 --- a/editor/js/ui/typedInput.js +++ b/editor/js/ui/typedInput.js @@ -124,21 +124,11 @@ this.options.types = this.options.types||Object.keys(allOptions); - var hasSubOptions = false; - this.typeMap = {}; - this.types = this.options.types.map(function(opt) { - var result; - if (typeof opt === 'string') { - result = allOptions[opt]; - } else { - result = opt; - } - that.typeMap[result.value] = result; - if (result.options) { - hasSubOptions = true; - } - return result; - }); + this.selectTrigger = $('').prependTo(this.uiSelect); + $('').appendTo(this.selectTrigger); + this.selectLabel = $('').appendTo(this.selectTrigger); + + this.types(this.options.types); if (this.options.typeField) { this.typeField = $(this.options.typeField).hide(); @@ -150,13 +140,6 @@ this.typeField = $("",{type:'hidden'}).appendTo(this.uiSelect); } - this.selectTrigger = $('').prependTo(this.uiSelect); - $('').appendTo(this.selectTrigger); - if (this.types.length === 1) { - this.selectTrigger.addClass("disabled"); - } - this.selectLabel = $('').appendTo(this.selectTrigger); - this.element.on('focus', function() { that.uiSelect.addClass('red-ui-typedInput-focus'); }); @@ -166,36 +149,29 @@ this.element.on('change', function() { that.validate(); }) - if (this.types.length > 1) { - this.selectTrigger.click(function(event) { - event.preventDefault(); + this.selectTrigger.click(function(event) { + event.preventDefault(); + if (that.typeList.length > 1) { that._showMenu(that.menu,that.selectTrigger); - }); - } else { - this.selectTrigger.click(function(event) { - event.preventDefault(); + } else { that.element.focus(); - }) - } + } + }); + // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline' + this.optionSelectTrigger = $('').appendTo(this.uiSelect); + this.optionSelectLabel = $('').prependTo(this.optionSelectTrigger); + this.optionSelectTrigger.click(function(event) { + event.preventDefault(); + if (that.optionMenu) { + that.optionMenu.css({ + minWidth:that.optionSelectLabel.width() + }); - if (hasSubOptions) { - // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline' - this.optionSelectTrigger = $('').appendTo(this.uiSelect); - this.optionSelectLabel = $('').prependTo(this.optionSelectTrigger); - this.optionSelectTrigger.click(function(event) { - event.preventDefault(); - if (that.optionMenu) { - that.optionMenu.css({ - minWidth:that.optionSelectLabel.width() - }); - - that._showMenu(that.optionMenu,that.optionSelectLabel) - } - }); - } - this.menu = this._createMenu(this.types, function(v) { that.type(v) }); - this.type(this.options.default||this.types[0].value); + that._showMenu(that.optionMenu,that.optionSelectLabel) + } + }); + this.type(this.options.default||this.typeList[0].value); }, _hideMenu: function(menu) { $(document).off("mousedown.close-property-select"); @@ -278,7 +254,6 @@ return labelWidth; }, _resize: function() { - if (this.typeMap[this.propertyType] && this.typeMap[this.propertyType].hasValue === false) { this.selectTrigger.width(this.uiWidth+5); } else { @@ -298,6 +273,29 @@ _destroy: function() { this.menu.remove(); }, + types: function(types) { + var that = this; + var currentType = this.type(); + this.typeMap = {}; + this.typeList = types.map(function(opt) { + var result; + if (typeof opt === 'string') { + result = allOptions[opt]; + } else { + result = opt; + } + that.typeMap[result.value] = result; + return result; + }); + this.selectTrigger.toggleClass("disabled", this.typeList.length === 1); + if (this.menu) { + this.menu.remove(); + } + this.menu = this._createMenu(this.typeList, function(v) { that.type(v) }); + if (currentType && !this.typeMap.hasOwnProperty(currentType)) { + this.type(this.typeList[0].value); + } + }, width: function(desiredWidth) { this.uiWidth = desiredWidth; this._resize(); @@ -359,9 +357,14 @@ this.optionSelectTrigger.hide(); } if (opt.hasValue === false) { + this.oldValue = this.element.val(); this.element.val(""); this.element.hide(); } else { + if (this.oldValue !== undefined) { + this.element.val(this.oldValue); + delete this.oldValue; + } this.element.show(); } this.element.trigger('change'); diff --git a/nodes/core/logic/17-split.html b/nodes/core/logic/17-split.html index e847baf0d..5e0cb1a04 100644 --- a/nodes/core/logic/17-split.html +++ b/nodes/core/logic/17-split.html @@ -44,7 +44,7 @@ color:"#E2D96E", defaults: { name: {value:""}, - splt: {value:""} + splt: {value:"\\n"} }, inputs:1, outputs:1, @@ -61,12 +61,12 @@ diff --git a/nodes/core/logic/17-split.js b/nodes/core/logic/17-split.js index ece2d9b69..48d6314a2 100644 --- a/nodes/core/logic/17-split.js +++ b/nodes/core/logic/17-split.js @@ -68,6 +68,9 @@ module.exports = function(RED) { function JoinNode(n) { RED.nodes.createNode(this,n); + this.property = n.property||"payload"; + this.propertyType = n.propertyType||"msg"; + this.key = n.key||"topic"; this.timer = Number(n.timeout || 0); this.timerr = n.timerr || "send"; this.count = Number(n.count || 0); @@ -78,10 +81,6 @@ module.exports = function(RED) { var misc = (this.build === "array") ? [] : {}; var tout; - function isObject (item) { - return (typeof item === "object" && !Array.isArray(item)&& ! Buffer.isBuffer(item) && item !== null); - } - // if array came from a string then reassemble it and send it var sendIt = function(m) { if (inflight[m.parts.id].ch !== undefined) { // if it was a string - rejoin it using the split char @@ -116,80 +115,93 @@ module.exports = function(RED) { m.payload = misc.join(node.joiner.replace(/\\n/,"\n").replace(/\\r/,"\r").replace(/\\t/,"\t").replace(/\\e/,"\e").replace(/\\f/,"\c").replace(/\\0/,"\0")); } if (node.build === "array") { misc = []; } - if (node.build === "object") { misc = {}; } + else if (node.build === "object") { misc = {}; } node.send(m); } this.on("input", function(msg) { - if (msg.hasOwnProperty("payload")) { - if (msg.hasOwnProperty("parts")) { // only act if it has parts - var count = node.count || msg.parts.count || 1; - if (msg.parts.hasOwnProperty("index")) { // it's a numbered part (from a split node) - if (!inflight[msg.parts.id]) { // New message - create new empty array of correct size - if (msg.parts.type === "object") { - inflight[msg.parts.id] = {i:0, a:{}, c:msg.parts.count, ch:msg.parts.ch, t:msg.parts.type}; - } else { // it's an array or string - inflight[msg.parts.id] = {i:0, a:new Array(msg.parts.count), ch:msg.parts.ch, t:msg.parts.type}; - } - if (node.timer !== 0) { // If there is a timer to set start it now - inflight[msg.parts.id].timeout = setTimeout(function() { - if (node.timerr === "send") { sendIt(msg); } - if (node.timerr === "error") { node.error("Incomplete",msg); } - delete inflight[msg.parts.id]; - }, node.timer); - } - } + var property; + if (node.propertyType == "full") { + property = msg; + } else { + try { + property = RED.util.getMessageProperty(msg,node.property); + } catch(err) { + node.warn("Message property "+node.property+" not found"); + return; + } + } + if (msg.hasOwnProperty("parts")) { + // only act if it has parts + var count = node.count || msg.parts.count || 1; + if (msg.parts.hasOwnProperty("index")) { + // it's a numbered part (from a split node) + if (!inflight[msg.parts.id]) { + // New message - create new empty array of correct size if (msg.parts.type === "object") { - inflight[msg.parts.id].a[msg.parts.key] = msg.payload; // Add to the tracking array - inflight[msg.parts.id].i = Object.keys(inflight[msg.parts.id].a).length; - } else { // it's an array or string - inflight[msg.parts.id].a[msg.parts.index] = msg.payload; // Add to the tracking array - inflight[msg.parts.id].i += 1; // Increment the count + inflight[msg.parts.id] = {i:0, a:{}, c:msg.parts.count, ch:msg.parts.ch, t:msg.parts.type}; + } else { + // it's an array or string + inflight[msg.parts.id] = {i:0, a:new Array(msg.parts.count), ch:msg.parts.ch, t:msg.parts.type}; } - if (inflight[msg.parts.id].i >= count) { sendIt(msg); } // All arrived - send - } // otherwise ignore it - if (msg.hasOwnProperty("complete")) { // if set then send right away anyway... - delete(msg.complete); + if (node.timer !== 0) { // If there is a timer to set start it now + inflight[msg.parts.id].timeout = setTimeout(function() { + if (node.timerr === "send") { sendIt(msg); } + else if (node.timerr === "error") { node.error("Incomplete",msg); } + delete inflight[msg.parts.id]; + }, node.timer); + } + } + if (msg.parts.type === "object") { + // Add to the tracking array + inflight[msg.parts.id].a[msg.parts.key] = property; + inflight[msg.parts.id].i = Object.keys(inflight[msg.parts.id].a).length; + } else { + // it's an array or string + // Add to the tracking array + inflight[msg.parts.id].a[msg.parts.index] = property; + // Increment the count + inflight[msg.parts.id].i += 1; + } + if (inflight[msg.parts.id].i >= count) { + // All arrived - send sendIt(msg); } + } // otherwise ignore it + if (msg.hasOwnProperty("complete")) { // if set then send right away anyway... + delete(msg.complete); + sendIt(msg); } - + } else { // The case for any messages arriving without parts - ie random messages you want to join. - else { - var l; - if (node.build === "array") { // simple case of build the array - misc.push(msg.payload); // Add the payload to an array - l = misc.length; - } else { // OK so let's build an object - if ((msg.key === undefined) && ((msg.topic === undefined) || (msg.topic === ''))) { - if (isObject(msg.payload)) { // if it's already an object (and no topic or key) just append it - misc = Object.assign(misc,msg.payload); - l = Object.keys(misc).length; - } - else { // if no topic or key and not an object then warn and drop it. - node.warn("key or topic not defined"); - return; - } - } - else { // if it's got a msg.key or msg.topic then use key||topic as the property name - misc[ msg.key || msg.topic ] = msg.payload; - //if (msg.topic) { msg.topic = (msg.topic.split('/')).slice(0,-1).join('/'); } - l = Object.keys(misc).length; - } - } - if (l >= node.count) { sendMisc(msg); } // if it's long enough send it - else if (msg.hasOwnProperty("complete")) { // if set then send right away anyway... - delete(msg.complete); - sendMisc(msg); - } - else if ((node.timer !== 0) && !tout) { // if not start the timer if there is one. - tout = setTimeout(function() { - if (node.timerr === "send") { sendMisc(msg); } - if (node.timerr === "error") { node.error("Timeout",msg); } - if (node.build === "array") { misc = []; } - if (node.build === "object") { misc = {}; } - }, node.timer); + var l; + if (node.build === "array" || node.build === "string") { + // simple case of build the array + // Add the payload to an array + misc.push(property); + l = misc.length; + } else { + // OK so let's build an object + if (msg.hasOwnProperty(node.key) && msg[node.key] !== "") { + misc[msg[node.key]] = property; } + l = Object.keys(misc).length; + } + if (l >= node.count) { + // if it's long enough send it + sendMisc(msg); + } else if (msg.hasOwnProperty("complete")) { + // if set then send right away anyway... + delete(msg.complete); + sendMisc(msg); + } else if ((node.timer !== 0) && !tout) { + // if not start the timer if there is one. + tout = setTimeout(function() { + if (node.timerr === "send") { sendMisc(msg); } + else if (node.timerr === "error") { node.error("Timeout",msg); } + if (node.build === "array") { misc = []; } + else if (node.build === "object") { misc = {}; } + }, node.timer); } } }); diff --git a/test/nodes/core/logic/17-split_spec.js b/test/nodes/core/logic/17-split_spec.js index cc34c3274..b77768b89 100644 --- a/test/nodes/core/logic/17-split_spec.js +++ b/test/nodes/core/logic/17-split_spec.js @@ -181,8 +181,9 @@ describe('JOIN node', function() { msg.payload.should.have.property("b","2"); msg.payload.should.have.property("c",true); msg.payload.should.have.property("d"); - msg.payload.d.should.have.property("e",5); - msg.payload.should.have.property("f",6); + msg.payload.d.should.have.property("e",7); + msg.payload.should.have.property("g"); + msg.payload.g.should.have.property("f",6); done(); } catch(e) { }//console.log(e); } @@ -191,7 +192,8 @@ describe('JOIN node', function() { n1.receive({payload:"2", topic:"b"}); n1.receive({payload:true, topic:"c"}); n1.receive({payload:{e:5}, topic:"d"}); - n1.receive({payload:{f:6}}); + n1.receive({payload:{e:7}, topic:"d"}); + n1.receive({payload:{f:6}, topic:"g"}); }); });