Skip to content

Commit 6042395

Browse files
committed
Allow a node to reorder its outputs and maintain links
Fixes node-red#1031
1 parent 8a5db8c commit 6042395

3 files changed

Lines changed: 60 additions & 8 deletions

File tree

editor/js/history.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,16 @@ RED.history = (function() {
236236
RED.editor.updateNodeProperties(n);
237237
});
238238
} else {
239-
RED.editor.updateNodeProperties(ev.node);
239+
var outputMap;
240+
if (ev.outputMap) {
241+
outputMap = {};
242+
for (var port in ev.outputMap) {
243+
if (ev.outputMap.hasOwnProperty(port) && ev.outputMap[port] !== -1) {
244+
outputMap[ev.outputMap[port]] = port;
245+
}
246+
}
247+
}
248+
RED.editor.updateNodeProperties(ev.node,outputMap);
240249
RED.editor.validateNode(ev.node);
241250
}
242251
if (ev.links) {

editor/js/ui/editor.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,19 +180,31 @@ RED.editor = (function() {
180180
* Marks the node as dirty and needing a size check.
181181
* Removes any links to non-existant outputs.
182182
* @param node - the node that has been updated
183+
* @param outputMap - (optional) a map of old->new port numbers if wires should be moved
183184
* @returns {array} the links that were removed due to this update
184185
*/
185-
function updateNodeProperties(node) {
186+
function updateNodeProperties(node, outputMap) {
186187
node.resize = true;
187188
node.dirty = true;
188189
var removedLinks = [];
189190
if (node.ports) {
191+
if (outputMap) {
192+
RED.nodes.eachLink(function(l) {
193+
if (l.source === node && outputMap.hasOwnProperty(l.sourcePort)) {
194+
if (outputMap[l.sourcePort] === -1) {
195+
removedLinks.push(l);
196+
} else {
197+
l.sourcePort = outputMap[l.sourcePort];
198+
}
199+
}
200+
});
201+
}
190202
if (node.outputs < node.ports.length) {
191203
while (node.outputs < node.ports.length) {
192204
node.ports.pop();
193205
}
194206
RED.nodes.eachLink(function(l) {
195-
if (l.source === node && l.sourcePort >= node.outputs) {
207+
if (l.source === node && l.sourcePort >= node.outputs && removedLinks.indexOf(l) === -1) {
196208
removedLinks.push(l);
197209
}
198210
});
@@ -597,6 +609,7 @@ RED.editor = (function() {
597609
var changed = false;
598610
var wasDirty = RED.nodes.dirty();
599611
var d;
612+
var outputMap;
600613

601614
if (editing_node._def.oneditsave) {
602615
var oldValues = {};
@@ -681,8 +694,14 @@ RED.editor = (function() {
681694
var credsChanged = updateNodeCredentials(editing_node,credDefinition,prefix);
682695
changed = changed || credsChanged;
683696
}
684-
685-
var removedLinks = updateNodeProperties(editing_node);
697+
if (editing_node.hasOwnProperty("_outputs")) {
698+
outputMap = editing_node._outputs;
699+
delete editing_node._outputs;
700+
if (Object.keys(outputMap).length > 0) {
701+
changed = true;
702+
}
703+
}
704+
var removedLinks = updateNodeProperties(editing_node,outputMap);
686705
if (changed) {
687706
var wasChanged = editing_node.changed;
688707
editing_node.changed = true;
@@ -712,6 +731,9 @@ RED.editor = (function() {
712731
dirty:wasDirty,
713732
changed:wasChanged
714733
};
734+
if (outputMap) {
735+
historyEvent.outputMap = outputMap;
736+
}
715737
if (subflowInstances) {
716738
historyEvent.subflow = {
717739
instances:subflowInstances

nodes/core/logic/10-switch.html

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@
115115

116116
$("#node-input-rule-container").css('min-height','250px').css('min-width','450px').editableList({
117117
addItem: function(container,i,opt) {
118-
var rule = opt;
118+
if (!opt.hasOwnProperty('r')) {
119+
opt.r = {};
120+
}
121+
var rule = opt.r;
119122
if (!rule.hasOwnProperty('t')) {
120123
rule.t = 'eq';
121124
}
@@ -177,6 +180,12 @@
177180
selectField.change();
178181
},
179182
removeItem: function(opt) {
183+
if (opt.hasOwnProperty('i')) {
184+
var removedList = $("#node-input-rule-container").data('removedList')||[];
185+
removedList.push(opt.i);
186+
$("#node-input-rule-container").data('removedList',removedList);
187+
}
188+
180189
var rules = $("#node-input-rule-container").editableList('items');
181190
rules.each(function(i) { $(this).find(".node-input-rule-index").html(i+1); });
182191
},
@@ -191,15 +200,21 @@
191200

192201
for (var i=0;i<this.rules.length;i++) {
193202
var rule = this.rules[i];
194-
$("#node-input-rule-container").editableList('addItem',rule);
203+
$("#node-input-rule-container").editableList('addItem',{r:rule,i:i});
195204
}
196205
},
197206
oneditsave: function() {
198207
var rules = $("#node-input-rule-container").editableList('items');
199208
var ruleset;
200209
var node = this;
201-
node.rules= [];
210+
node.rules = [];
211+
var changedOutputs = {};
212+
var removedList = $("#node-input-rule-container").data('removedList')||[];
213+
removedList.forEach(function(i) {
214+
changedOutputs[i] = -1;
215+
});
202216
rules.each(function(i) {
217+
var ruleData = $(this).data('data');
203218
var rule = $(this);
204219
var type = rule.find("select").val();
205220
var r = {t:type};
@@ -217,8 +232,14 @@
217232
r.case = rule.find(".node-input-rule-case").prop("checked");
218233
}
219234
}
235+
if (ruleData.hasOwnProperty('i')) {
236+
if (ruleData.i !== i) {
237+
changedOutputs[ruleData.i] = i;
238+
}
239+
}
220240
node.rules.push(r);
221241
});
242+
this._outputs = changedOutputs;
222243
this.outputs = node.rules.length;
223244
this.propertyType = $("#node-input-property").typedInput('type');
224245
},

0 commit comments

Comments
 (0)