@node-red/editor-client 3.0.0-beta.2 → 3.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/public/red/red.js CHANGED
@@ -4360,6 +4360,10 @@ RED.nodes = (function() {
4360
4360
  moveGroupToTab(node,z);
4361
4361
  return;
4362
4362
  }
4363
+ if (node.type === "junction") {
4364
+ moveJunctionToTab(node,z);
4365
+ return;
4366
+ }
4363
4367
  var oldZ = node.z;
4364
4368
  allNodes.moveNode(node,z);
4365
4369
  var nl = nodeLinks[node.id];
@@ -4394,6 +4398,39 @@ RED.nodes = (function() {
4394
4398
  RED.events.emit("groups:change",group);
4395
4399
  }
4396
4400
 
4401
+ function moveJunctionToTab(junction, z) {
4402
+ var index = junctionsByZ[junction.z].indexOf(junction);
4403
+ junctionsByZ[junction.z].splice(index,1);
4404
+ junctionsByZ[z] = junctionsByZ[z] || [];
4405
+ junctionsByZ[z].push(junction);
4406
+
4407
+ var oldZ = junction.z;
4408
+ junction.z = z;
4409
+
4410
+ var nl = nodeLinks[junction.id];
4411
+ if (nl) {
4412
+ nl.in.forEach(function(l) {
4413
+ var idx = linkTabMap[oldZ].indexOf(l);
4414
+ if (idx != -1) {
4415
+ linkTabMap[oldZ].splice(idx, 1);
4416
+ }
4417
+ if ((l.source.z === z) && linkTabMap[z]) {
4418
+ linkTabMap[z].push(l);
4419
+ }
4420
+ });
4421
+ nl.out.forEach(function(l) {
4422
+ var idx = linkTabMap[oldZ].indexOf(l);
4423
+ if (idx != -1) {
4424
+ linkTabMap[oldZ].splice(idx, 1);
4425
+ }
4426
+ if ((l.target.z === z) && linkTabMap[z]) {
4427
+ linkTabMap[z].push(l);
4428
+ }
4429
+ });
4430
+ }
4431
+ RED.events.emit("junctions:change",junction);
4432
+ }
4433
+
4397
4434
  function removeLink(l) {
4398
4435
  var index = links.indexOf(l);
4399
4436
  if (index != -1) {
@@ -7353,6 +7390,14 @@ RED.history = (function() {
7353
7390
  var undoHistory = [];
7354
7391
  var redoHistory = [];
7355
7392
 
7393
+ function nodeOrJunction(id) {
7394
+ var node = RED.nodes.node(id);
7395
+ if (node) {
7396
+ return node;
7397
+ }
7398
+ return RED.nodes.junction(id);
7399
+ }
7400
+
7356
7401
  function undoEvent(ev) {
7357
7402
  var i;
7358
7403
  var len;
@@ -7845,6 +7890,7 @@ RED.history = (function() {
7845
7890
  var z = ev.activeWorkspace;
7846
7891
  var fullNodeList = RED.nodes.filterNodes({z:ev.subflow.subflow.id});
7847
7892
  fullNodeList = fullNodeList.concat(RED.nodes.groups(ev.subflow.subflow.id))
7893
+ fullNodeList = fullNodeList.concat(RED.nodes.junctions(ev.subflow.subflow.id))
7848
7894
  fullNodeList.forEach(function(n) {
7849
7895
  n.x += ev.subflow.offsetX;
7850
7896
  n.y += ev.subflow.offsetY;
@@ -7854,7 +7900,7 @@ RED.history = (function() {
7854
7900
  });
7855
7901
  inverseEv.subflows = [];
7856
7902
  for (i=0;i<ev.nodes.length;i++) {
7857
- inverseEv.subflows.push(RED.nodes.node(ev.nodes[i]));
7903
+ inverseEv.subflows.push(nodeOrJunction(ev.nodes[i]));
7858
7904
  RED.nodes.remove(ev.nodes[i]);
7859
7905
  }
7860
7906
  }
@@ -9198,6 +9244,8 @@ RED.utils = (function() {
9198
9244
  return "font-awesome/fa-circle-o"
9199
9245
  } else if (def.category === 'config') {
9200
9246
  return RED.settings.apiRootUrl+"icons/node-red/cog.svg"
9247
+ } else if ((node && /^_action_:/.test(node.type)) || /^_action_:/.test(def.type)) {
9248
+ return "font-awesome/fa-cogs"
9201
9249
  } else if (node && node.type === 'tab') {
9202
9250
  return "red-ui-icons/red-ui-icons-flow"
9203
9251
  // return RED.settings.apiRootUrl+"images/subflow_tab.svg"
@@ -11116,6 +11164,7 @@ RED.utils = (function() {
11116
11164
  RED.menu = (function() {
11117
11165
 
11118
11166
  var menuItems = {};
11167
+ let menuItemCount = 0
11119
11168
 
11120
11169
  function createMenuItem(opt) {
11121
11170
  var item;
@@ -11159,15 +11208,16 @@ RED.menu = (function() {
11159
11208
  item = $('<li class="red-ui-menu-divider"></li>');
11160
11209
  } else {
11161
11210
  item = $('<li></li>');
11162
-
11211
+ if (!opt.id) {
11212
+ opt.id = 'red-ui-menu-item-'+(menuItemCount++)
11213
+ }
11163
11214
  if (opt.group) {
11164
11215
  item.addClass("red-ui-menu-group-"+opt.group);
11165
-
11166
11216
  }
11167
11217
  var linkContent = '<a '+(opt.id?'id="'+opt.id+'" ':'')+'tabindex="-1" href="#">';
11168
11218
  if (opt.toggle) {
11169
- linkContent += '<i class="fa fa-square pull-left"></i>';
11170
- linkContent += '<i class="fa fa-check-square pull-left"></i>';
11219
+ linkContent += '<i class="fa fa-square'+(opt.direction!=='right'?" pull-left":"")+'"></i>';
11220
+ linkContent += '<i class="fa fa-check-square'+(opt.direction!=='right'?" pull-left":"")+'"></i>';
11171
11221
 
11172
11222
  }
11173
11223
  if (opt.icon !== undefined) {
@@ -11177,12 +11227,15 @@ RED.menu = (function() {
11177
11227
  linkContent += '<i class="'+(opt.icon?opt.icon:'" style="display: inline-block;"')+'"></i> ';
11178
11228
  }
11179
11229
  }
11180
-
11230
+ let label = opt.label
11231
+ if (!opt.label && typeof opt.onselect === 'string') {
11232
+ label = RED.actions.getLabel(opt.onselect)
11233
+ }
11181
11234
  if (opt.sublabel) {
11182
- linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+opt.label+'</span>'+
11235
+ linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+label+'</span>'+
11183
11236
  '<span class="red-ui-menu-sublabel">'+opt.sublabel+'</span></span>'
11184
11237
  } else {
11185
- linkContent += '<span class="red-ui-menu-label"><span>'+opt.label+'</span></span>'
11238
+ linkContent += '<span class="red-ui-menu-label"><span>'+label+'</span></span>'
11186
11239
  }
11187
11240
 
11188
11241
  linkContent += '</a>';
@@ -11226,10 +11279,21 @@ RED.menu = (function() {
11226
11279
  });
11227
11280
  }
11228
11281
  if (opt.options) {
11229
- item.addClass("red-ui-menu-dropdown-submenu pull-left");
11282
+ item.addClass("red-ui-menu-dropdown-submenu"+(opt.direction!=='right'?" pull-left":""));
11230
11283
  var submenu = $('<ul id="'+opt.id+'-submenu" class="red-ui-menu-dropdown"></ul>').appendTo(item);
11231
11284
 
11232
11285
  for (var i=0;i<opt.options.length;i++) {
11286
+
11287
+ if (opt.options[i]) {
11288
+ if (opt.onpreselect && opt.options[i].onpreselect === undefined) {
11289
+ opt.options[i].onpreselect = opt.onpreselect
11290
+ }
11291
+ if (opt.onpostselect && opt.options[i].onpostselect === undefined) {
11292
+ opt.options[i].onpostselect = opt.onpostselect
11293
+ }
11294
+ opt.options[i].direction = opt.direction
11295
+ }
11296
+
11233
11297
  var li = createMenuItem(opt.options[i]);
11234
11298
  if (li) {
11235
11299
  li.appendTo(submenu);
@@ -11247,7 +11311,9 @@ RED.menu = (function() {
11247
11311
  }
11248
11312
  function createMenu(options) {
11249
11313
  var topMenu = $("<ul/>",{class:"red-ui-menu red-ui-menu-dropdown pull-right"});
11250
-
11314
+ if (options.direction) {
11315
+ topMenu.addClass("red-ui-menu-dropdown-direction-"+options.direction)
11316
+ }
11251
11317
  if (options.id) {
11252
11318
  topMenu.attr({id:options.id+"-submenu"});
11253
11319
  var menuParent = $("#"+options.id);
@@ -11275,6 +11341,15 @@ RED.menu = (function() {
11275
11341
  var lastAddedSeparator = false;
11276
11342
  for (var i=0;i<options.options.length;i++) {
11277
11343
  var opt = options.options[i];
11344
+ if (opt) {
11345
+ if (options.onpreselect && opt.onpreselect === undefined) {
11346
+ opt.onpreselect = options.onpreselect
11347
+ }
11348
+ if (options.onpostselect && opt.onpostselect === undefined) {
11349
+ opt.onpostselect = options.onpostselect
11350
+ }
11351
+ opt.direction = options.direction || 'left'
11352
+ }
11278
11353
  if (opt !== null || !lastAddedSeparator) {
11279
11354
  var li = createMenuItem(opt);
11280
11355
  if (li) {
@@ -11290,6 +11365,9 @@ RED.menu = (function() {
11290
11365
  function triggerAction(id, args) {
11291
11366
  var opt = menuItems[id];
11292
11367
  var callback = opt.onselect;
11368
+ if (opt.onpreselect) {
11369
+ opt.onpreselect.call(opt,args)
11370
+ }
11293
11371
  if (typeof opt.onselect === 'string') {
11294
11372
  callback = RED.actions.get(opt.onselect);
11295
11373
  }
@@ -11298,6 +11376,9 @@ RED.menu = (function() {
11298
11376
  } else {
11299
11377
  console.log("No callback for",id,opt.onselect);
11300
11378
  }
11379
+ if (opt.onpostselect) {
11380
+ opt.onpostselect.call(opt,args)
11381
+ }
11301
11382
  }
11302
11383
 
11303
11384
  function isSelected(id) {
@@ -12154,10 +12235,13 @@ RED.popover = (function() {
12154
12235
  var target = options.target;
12155
12236
  var align = options.align || "right";
12156
12237
  var offset = options.offset || [0,0];
12238
+ var xPos = options.x;
12239
+ var yPos = options.y;
12240
+ var isAbsolutePosition = (xPos !== undefined && yPos !== undefined)
12157
12241
 
12158
- var pos = target.offset();
12159
- var targetWidth = target.width();
12160
- var targetHeight = target.outerHeight();
12242
+ var pos = isAbsolutePosition?{left:xPos, top: yPos}:target.offset();
12243
+ var targetWidth = isAbsolutePosition?0:target.width();
12244
+ var targetHeight = isAbsolutePosition?0:target.outerHeight();
12161
12245
  var panelHeight = panel.height();
12162
12246
  var panelWidth = panel.width();
12163
12247
 
@@ -13225,7 +13309,7 @@ RED.tabs = (function() {
13225
13309
  }
13226
13310
 
13227
13311
  // link.attr("title",tab.label);
13228
- RED.popover.tooltip(link,function() { return tab.label})
13312
+ RED.popover.tooltip(link,function() { return RED.utils.sanitize(tab.label); });
13229
13313
 
13230
13314
  if (options.onadd) {
13231
13315
  options.onadd(tab);
@@ -15142,6 +15226,34 @@ RED.stack = (function() {
15142
15226
  function getAction(name) {
15143
15227
  return actions[name].handler;
15144
15228
  }
15229
+ function getActionLabel(name) {
15230
+ let def = actions[name]
15231
+ if (!def) {
15232
+ return ''
15233
+ }
15234
+ if (!def.label) {
15235
+ var options = def.options;
15236
+ var key = options ? options.label : undefined;
15237
+ if (!key) {
15238
+ key = "action-list." +name.replace(/^.*:/,"");
15239
+ }
15240
+ var label = RED._(key);
15241
+ if (label === key) {
15242
+ // no translation. convert `name` to description
15243
+ label = name.replace(/(^.+:([a-z]))|(-([a-z]))/g, function() {
15244
+ if (arguments[5] === 0) {
15245
+ return arguments[2].toUpperCase();
15246
+ } else {
15247
+ return " "+arguments[4].toUpperCase();
15248
+ }
15249
+ });
15250
+ }
15251
+ def.label = label;
15252
+ }
15253
+ return def.label
15254
+ }
15255
+
15256
+
15145
15257
  function invokeAction() {
15146
15258
  var args = Array.prototype.slice.call(arguments);
15147
15259
  var name = args.shift();
@@ -15152,7 +15264,7 @@ RED.stack = (function() {
15152
15264
  }
15153
15265
  function listActions() {
15154
15266
  var result = [];
15155
- var missing = [];
15267
+
15156
15268
  Object.keys(actions).forEach(function(action) {
15157
15269
  var def = actions[action];
15158
15270
  var shortcut = RED.keyboard.getShortcut(action);
@@ -15163,28 +15275,8 @@ RED.stack = (function() {
15163
15275
  isUser = !!RED.keyboard.getUserShortcut(action);
15164
15276
  }
15165
15277
  if (!def.label) {
15166
- var name = action;
15167
- var options = def.options;
15168
- var key = options ? options.label : undefined;
15169
- if (!key) {
15170
- key = "action-list." +name.replace(/^.*:/,"");
15171
- }
15172
- var label = RED._(key);
15173
- if (label === key) {
15174
- // no translation. convert `name` to description
15175
- label = name.replace(/(^.+:([a-z]))|(-([a-z]))/g, function() {
15176
- if (arguments[5] === 0) {
15177
- return arguments[2].toUpperCase();
15178
- } else {
15179
- return " "+arguments[4].toUpperCase();
15180
- }
15181
- });
15182
- missing.push(key);
15183
- }
15184
- def.label = label;
15278
+ def.label = getActionLabel(action)
15185
15279
  }
15186
- //console.log("; missing:", missing);
15187
-
15188
15280
  result.push({
15189
15281
  id:action,
15190
15282
  scope:shortcut?shortcut.scope:undefined,
@@ -15200,6 +15292,7 @@ RED.stack = (function() {
15200
15292
  add: addAction,
15201
15293
  remove: removeAction,
15202
15294
  get: getAction,
15295
+ getLabel: getActionLabel,
15203
15296
  invoke: invokeAction,
15204
15297
  list: listActions
15205
15298
  }
@@ -19664,7 +19757,15 @@ RED.view = (function() {
19664
19757
  function init() {
19665
19758
 
19666
19759
  chart = $("#red-ui-workspace-chart");
19667
-
19760
+ chart.on('contextmenu', function(evt) {
19761
+ evt.preventDefault()
19762
+ evt.stopPropagation()
19763
+ RED.contextMenu.show({
19764
+ x:evt.clientX-5,
19765
+ y:evt.clientY-5
19766
+ })
19767
+ return false
19768
+ })
19668
19769
  outer = d3.select("#red-ui-workspace-chart")
19669
19770
  .append("svg:svg")
19670
19771
  .attr("width", space_width)
@@ -19688,6 +19789,7 @@ RED.view = (function() {
19688
19789
  .on("mousedown", canvasMouseDown)
19689
19790
  .on("mouseup", canvasMouseUp)
19690
19791
  .on("mouseenter", function() {
19792
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
19691
19793
  if (lasso) {
19692
19794
  if (d3.event.buttons !== 1) {
19693
19795
  lasso.remove();
@@ -19703,6 +19805,7 @@ RED.view = (function() {
19703
19805
  }
19704
19806
  }
19705
19807
  })
19808
+ .on("mouseleave", canvasMouseLeave)
19706
19809
  .on("touchend", function() {
19707
19810
  d3.event.preventDefault();
19708
19811
  clearTimeout(touchStartTime);
@@ -19843,6 +19946,9 @@ RED.view = (function() {
19843
19946
  drag_lines = [];
19844
19947
 
19845
19948
  RED.events.on("workspace:change",function(event) {
19949
+ // Just in case the mouse left the workspace whilst doing an action,
19950
+ // put us back into default mode so the refresh works
19951
+ mouse_mode = 0
19846
19952
  if (event.old !== 0) {
19847
19953
  workspaceScrollPositions[event.old] = {
19848
19954
  left:chart.scrollLeft(),
@@ -19984,6 +20090,23 @@ RED.view = (function() {
19984
20090
  nn.x = mousePos[0];
19985
20091
  nn.y = mousePos[1];
19986
20092
 
20093
+ var minX = nn.w/2 -5;
20094
+ if (nn.x < minX) {
20095
+ nn.x = minX;
20096
+ }
20097
+ var minY = nn.h/2 -5;
20098
+ if (nn.y < minY) {
20099
+ nn.y = minY;
20100
+ }
20101
+ var maxX = space_width -nn.w/2 +5;
20102
+ if (nn.x > maxX) {
20103
+ nn.x = maxX;
20104
+ }
20105
+ var maxY = space_height -nn.h +5;
20106
+ if (nn.y > maxY) {
20107
+ nn.y = maxY;
20108
+ }
20109
+
19987
20110
  if (snapGrid) {
19988
20111
  var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
19989
20112
  nn.x -= gridOffset.x;
@@ -20413,7 +20536,7 @@ RED.view = (function() {
20413
20536
  }
20414
20537
 
20415
20538
  function canvasMouseDown() {
20416
- if (RED.view.DEBUG) {
20539
+ if (RED.view.DEBUG) {
20417
20540
  console.warn("canvasMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
20418
20541
  }
20419
20542
  if (mouse_mode === RED.state.SELECTING_NODE) {
@@ -20428,7 +20551,10 @@ RED.view = (function() {
20428
20551
  scroll_position = [chart.scrollLeft(),chart.scrollTop()];
20429
20552
  return;
20430
20553
  }
20431
- if (!mousedown_node && !mousedown_link && !mousedown_group) {
20554
+ if (d3.event.button === 2) {
20555
+ return
20556
+ }
20557
+ if (!mousedown_node && !mousedown_link && !mousedown_group && !d3.event.shiftKey) {
20432
20558
  selectedLinks.clear();
20433
20559
  updateSelection();
20434
20560
  }
@@ -20482,6 +20608,7 @@ RED.view = (function() {
20482
20608
  options = options || {};
20483
20609
  var point = options.position || lastClickPosition;
20484
20610
  var spliceLink = options.splice;
20611
+ var spliceMultipleLinks = options.spliceMultiple
20485
20612
  var targetGroup = options.group;
20486
20613
  var touchTrigger = options.touchTrigger;
20487
20614
 
@@ -20494,6 +20621,10 @@ RED.view = (function() {
20494
20621
  var ox = point[0];
20495
20622
  var oy = point[1];
20496
20623
 
20624
+ const offset = $("#red-ui-workspace-chart").offset()
20625
+ var clientX = ox + offset.left
20626
+ var clientY = oy + offset.top
20627
+
20497
20628
  if (RED.settings.get("editor").view['view-snap-grid']) {
20498
20629
  // eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
20499
20630
  point[0] = Math.round(point[0] / gridSize) * gridSize;
@@ -20545,8 +20676,12 @@ RED.view = (function() {
20545
20676
  }
20546
20677
  hideDragLines();
20547
20678
  }
20548
- if (spliceLink) {
20549
- filter = {input:true, output:true}
20679
+ if (spliceLink || spliceMultipleLinks) {
20680
+ filter = {
20681
+ input:true,
20682
+ output:true,
20683
+ spliceMultiple: spliceMultipleLinks
20684
+ }
20550
20685
  }
20551
20686
 
20552
20687
  var rebuildQuickAddLink = function() {
@@ -20571,8 +20706,8 @@ RED.view = (function() {
20571
20706
  var lastAddedWidth;
20572
20707
 
20573
20708
  RED.typeSearch.show({
20574
- x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
20575
- y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
20709
+ x:clientX-mainPos.left-node_width/2 - (ox-point[0]),
20710
+ y:clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
20576
20711
  disableFocus: touchTrigger,
20577
20712
  filter: filter,
20578
20713
  move: function(dx,dy) {
@@ -20600,7 +20735,7 @@ RED.view = (function() {
20600
20735
  hideDragLines();
20601
20736
  redraw();
20602
20737
  },
20603
- add: function(type,keepAdding) {
20738
+ add: function(type, keepAdding) {
20604
20739
  if (touchTrigger) {
20605
20740
  keepAdding = false;
20606
20741
  resetMouseVars();
@@ -20608,7 +20743,13 @@ RED.view = (function() {
20608
20743
 
20609
20744
  var nn;
20610
20745
  var historyEvent;
20611
- if (type === 'junction') {
20746
+ if (/^_action_:/.test(type)) {
20747
+ const actionName = type.substring(9)
20748
+ quickAddActive = false;
20749
+ ghostNode.remove();
20750
+ RED.actions.invoke(actionName)
20751
+ return
20752
+ } else if (type === 'junction') {
20612
20753
  nn = {
20613
20754
  _def: {defaults:{}},
20614
20755
  type: 'junction',
@@ -21174,10 +21315,17 @@ RED.view = (function() {
21174
21315
  redraw();
21175
21316
  }
21176
21317
  }
21177
-
21318
+ function canvasMouseLeave() {
21319
+ if (mouse_mode !== 0 && d3.event.buttons !== 0) {
21320
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', function() {
21321
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
21322
+ canvasMouseUp.call(this)
21323
+ })
21324
+ }
21325
+ }
21178
21326
  function canvasMouseUp() {
21179
21327
  lastClickPosition = [d3.event.offsetX/scaleFactor,d3.event.offsetY/scaleFactor];
21180
- if (RED.view.DEBUG) {
21328
+ if (RED.view.DEBUG) {
21181
21329
  console.warn("canvasMouseUp", { mouse_mode, point: d3.mouse(this), event: d3.event });
21182
21330
  }
21183
21331
  var i;
@@ -21273,8 +21421,20 @@ RED.view = (function() {
21273
21421
  }
21274
21422
  }
21275
21423
  })
21276
-
21277
-
21424
+ activeLinks.forEach(function(link) {
21425
+ if (!link.selected) {
21426
+ var sourceY = link.source.y
21427
+ var targetY = link.target.y
21428
+ var sourceX = link.source.x+(link.source.w/2) + 10
21429
+ var targetX = link.target.x-(link.target.w/2) - 10
21430
+ if (
21431
+ sourceX > x && sourceX < x2 && sourceY > y && sourceY < y2 &&
21432
+ targetX > x && targetX < x2 && targetY > y && targetY < y2
21433
+ ) {
21434
+ selectedLinks.add(link);
21435
+ }
21436
+ }
21437
+ })
21278
21438
 
21279
21439
  // var selectionChanged = false;
21280
21440
  // do {
@@ -21322,114 +21482,118 @@ RED.view = (function() {
21322
21482
  slicePath = null;
21323
21483
  RED.view.redraw(true);
21324
21484
  } else if (mouse_mode == RED.state.SLICING_JUNCTION) {
21325
- var removedLinks = new Set()
21326
- var addedLinks = []
21327
- var addedJunctions = []
21328
-
21329
- var groupedLinks = {}
21330
- selectedLinks.forEach(function(l) {
21331
- var sourceId = l.source.id+":"+l.sourcePort
21332
- groupedLinks[sourceId] = groupedLinks[sourceId] || []
21333
- groupedLinks[sourceId].push(l)
21334
-
21335
- groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
21336
- groupedLinks[l.target.id].push(l)
21337
- });
21338
- var linkGroups = Object.keys(groupedLinks)
21339
- linkGroups.sort(function(A,B) {
21340
- return groupedLinks[B].length - groupedLinks[A].length
21341
- })
21342
- linkGroups.forEach(function(gid) {
21343
- var links = groupedLinks[gid]
21344
- var junction = {
21345
- _def: {defaults:{}},
21346
- type: 'junction',
21347
- z: RED.workspaces.active(),
21348
- id: RED.nodes.id(),
21349
- x: 0,
21350
- y: 0,
21351
- w: 0, h: 0,
21352
- outputs: 1,
21353
- inputs: 1,
21354
- dirty: true
21355
- }
21356
- links = links.filter(function(l) { return !removedLinks.has(l) })
21357
- if (links.length === 0) {
21358
- return
21359
- }
21360
- links.forEach(function(l) {
21361
- junction.x += l._sliceLocation.x
21362
- junction.y += l._sliceLocation.y
21363
- })
21364
- junction.x = Math.round(junction.x/links.length)
21365
- junction.y = Math.round(junction.y/links.length)
21366
- if (snapGrid) {
21367
- junction.x = (gridSize*Math.round(junction.x/gridSize));
21368
- junction.y = (gridSize*Math.round(junction.y/gridSize));
21369
- }
21370
-
21371
- var nodeGroups = new Set()
21372
-
21373
- RED.nodes.addJunction(junction)
21374
- addedJunctions.push(junction)
21375
- let newLink
21376
- if (gid === links[0].source.id+":"+links[0].sourcePort) {
21377
- newLink = {
21378
- source: links[0].source,
21379
- sourcePort: links[0].sourcePort,
21380
- target: junction
21381
- }
21382
- } else {
21383
- newLink = {
21384
- source: junction,
21385
- sourcePort: 0,
21386
- target: links[0].target
21387
- }
21388
- }
21389
- addedLinks.push(newLink)
21390
- RED.nodes.addLink(newLink)
21391
- links.forEach(function(l) {
21392
- removedLinks.add(l)
21393
- RED.nodes.removeLink(l)
21394
- let newLink
21395
- if (gid === l.target.id) {
21396
- newLink = {
21397
- source: l.source,
21398
- sourcePort: l.sourcePort,
21399
- target: junction
21400
- }
21401
- } else {
21402
- newLink = {
21403
- source: junction,
21404
- sourcePort: 0,
21405
- target: l.target
21406
- }
21407
- }
21408
- addedLinks.push(newLink)
21409
- RED.nodes.addLink(newLink)
21410
- nodeGroups.add(l.source.g || "__NONE__")
21411
- nodeGroups.add(l.target.g || "__NONE__")
21412
- })
21413
- if (nodeGroups.size === 1) {
21414
- var group = nodeGroups.values().next().value
21415
- if (group !== "__NONE__") {
21416
- RED.group.addToGroup(RED.nodes.group(group), junction)
21417
- }
21418
- }
21419
- })
21485
+ RED.actions.invoke("core:split-wires-with-junctions")
21420
21486
  slicePath.remove();
21421
21487
  slicePath = null;
21422
21488
 
21423
- if (addedJunctions.length > 0) {
21424
- RED.history.push({
21425
- t: 'add',
21426
- links: addedLinks,
21427
- junctions: addedJunctions,
21428
- removedLinks: Array.from(removedLinks)
21429
- })
21430
- RED.nodes.dirty(true)
21431
- }
21432
- RED.view.redraw(true);
21489
+ // var removedLinks = new Set()
21490
+ // var addedLinks = []
21491
+ // var addedJunctions = []
21492
+ //
21493
+ // var groupedLinks = {}
21494
+ // selectedLinks.forEach(function(l) {
21495
+ // var sourceId = l.source.id+":"+l.sourcePort
21496
+ // groupedLinks[sourceId] = groupedLinks[sourceId] || []
21497
+ // groupedLinks[sourceId].push(l)
21498
+ //
21499
+ // groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
21500
+ // groupedLinks[l.target.id].push(l)
21501
+ // });
21502
+ // var linkGroups = Object.keys(groupedLinks)
21503
+ // linkGroups.sort(function(A,B) {
21504
+ // return groupedLinks[B].length - groupedLinks[A].length
21505
+ // })
21506
+ // linkGroups.forEach(function(gid) {
21507
+ // var links = groupedLinks[gid]
21508
+ // var junction = {
21509
+ // _def: {defaults:{}},
21510
+ // type: 'junction',
21511
+ // z: RED.workspaces.active(),
21512
+ // id: RED.nodes.id(),
21513
+ // x: 0,
21514
+ // y: 0,
21515
+ // w: 0, h: 0,
21516
+ // outputs: 1,
21517
+ // inputs: 1,
21518
+ // dirty: true
21519
+ // }
21520
+ // links = links.filter(function(l) { return !removedLinks.has(l) })
21521
+ // if (links.length === 0) {
21522
+ // return
21523
+ // }
21524
+ // links.forEach(function(l) {
21525
+ // junction.x += l._sliceLocation.x
21526
+ // junction.y += l._sliceLocation.y
21527
+ // })
21528
+ // junction.x = Math.round(junction.x/links.length)
21529
+ // junction.y = Math.round(junction.y/links.length)
21530
+ // if (snapGrid) {
21531
+ // junction.x = (gridSize*Math.round(junction.x/gridSize));
21532
+ // junction.y = (gridSize*Math.round(junction.y/gridSize));
21533
+ // }
21534
+ //
21535
+ // var nodeGroups = new Set()
21536
+ //
21537
+ // RED.nodes.addJunction(junction)
21538
+ // addedJunctions.push(junction)
21539
+ // let newLink
21540
+ // if (gid === links[0].source.id+":"+links[0].sourcePort) {
21541
+ // newLink = {
21542
+ // source: links[0].source,
21543
+ // sourcePort: links[0].sourcePort,
21544
+ // target: junction
21545
+ // }
21546
+ // } else {
21547
+ // newLink = {
21548
+ // source: junction,
21549
+ // sourcePort: 0,
21550
+ // target: links[0].target
21551
+ // }
21552
+ // }
21553
+ // addedLinks.push(newLink)
21554
+ // RED.nodes.addLink(newLink)
21555
+ // links.forEach(function(l) {
21556
+ // removedLinks.add(l)
21557
+ // RED.nodes.removeLink(l)
21558
+ // let newLink
21559
+ // if (gid === l.target.id) {
21560
+ // newLink = {
21561
+ // source: l.source,
21562
+ // sourcePort: l.sourcePort,
21563
+ // target: junction
21564
+ // }
21565
+ // } else {
21566
+ // newLink = {
21567
+ // source: junction,
21568
+ // sourcePort: 0,
21569
+ // target: l.target
21570
+ // }
21571
+ // }
21572
+ // addedLinks.push(newLink)
21573
+ // RED.nodes.addLink(newLink)
21574
+ // nodeGroups.add(l.source.g || "__NONE__")
21575
+ // nodeGroups.add(l.target.g || "__NONE__")
21576
+ // })
21577
+ // if (nodeGroups.size === 1) {
21578
+ // var group = nodeGroups.values().next().value
21579
+ // if (group !== "__NONE__") {
21580
+ // RED.group.addToGroup(RED.nodes.group(group), junction)
21581
+ // }
21582
+ // }
21583
+ // })
21584
+ // slicePath.remove();
21585
+ // slicePath = null;
21586
+ //
21587
+ // if (addedJunctions.length > 0) {
21588
+ // RED.history.push({
21589
+ // t: 'add',
21590
+ // links: addedLinks,
21591
+ // junctions: addedJunctions,
21592
+ // removedLinks: Array.from(removedLinks)
21593
+ // })
21594
+ // RED.nodes.dirty(true)
21595
+ // }
21596
+ // RED.view.redraw(true);
21433
21597
  }
21434
21598
  if (mouse_mode == RED.state.MOVING_ACTIVE) {
21435
21599
  if (movingSet.length() > 0) {
@@ -23177,7 +23341,7 @@ RED.view = (function() {
23177
23341
  function junctionMouseOutProxy(e) { junctionMouseOut(d3.select(this), this.__data__) }
23178
23342
 
23179
23343
  function linkMouseDown(d) {
23180
- if (RED.view.DEBUG) {
23344
+ if (RED.view.DEBUG) {
23181
23345
  console.warn("linkMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
23182
23346
  }
23183
23347
  if (mouse_mode === RED.state.SELECTING_NODE) {
@@ -25177,7 +25341,12 @@ RED.view = (function() {
25177
25341
  node.dirty = true;
25178
25342
  node.dirtyStatus = true;
25179
25343
  node.changed = true;
25180
- RED.events.emit("nodes:change",node);
25344
+ if (node.type === "junction") {
25345
+ RED.events.emit("junctions:change",node);
25346
+ }
25347
+ else {
25348
+ RED.events.emit("nodes:change",node);
25349
+ }
25181
25350
  }
25182
25351
  }
25183
25352
  }
@@ -26250,17 +26419,17 @@ RED.view.tools = (function() {
26250
26419
 
26251
26420
  }
26252
26421
 
26253
- function addNode() {
26254
- var selection = RED.view.selection();
26255
- if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
26256
- var selectedNode = selection.nodes[0];
26257
- RED.view.showQuickAddDialog([
26258
- selectedNode.x + selectedNode.w + 50,selectedNode.y
26259
- ])
26260
- } else {
26261
- RED.view.showQuickAddDialog();
26262
- }
26263
- }
26422
+ // function addNode() {
26423
+ // var selection = RED.view.selection();
26424
+ // if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
26425
+ // var selectedNode = selection.nodes[0];
26426
+ // RED.view.showQuickAddDialog([
26427
+ // selectedNode.x + selectedNode.w + 50,selectedNode.y
26428
+ // ])
26429
+ // } else {
26430
+ // RED.view.showQuickAddDialog();
26431
+ // }
26432
+ // }
26264
26433
 
26265
26434
 
26266
26435
  function gotoNearestNode(direction) {
@@ -26729,6 +26898,9 @@ RED.view.tools = (function() {
26729
26898
  */
26730
26899
  function splitWiresWithLinkNodes(wires) {
26731
26900
  let wiresToSplit = wires || RED.view.selection().links;
26901
+ if (!wiresToSplit) {
26902
+ return
26903
+ }
26732
26904
  if (!Array.isArray(wiresToSplit)) {
26733
26905
  wiresToSplit = [wiresToSplit];
26734
26906
  }
@@ -26961,6 +27133,135 @@ RED.view.tools = (function() {
26961
27133
  }
26962
27134
  }
26963
27135
 
27136
+ function addJunctionsToWires(wires) {
27137
+ let wiresToSplit = wires || RED.view.selection().links;
27138
+ if (!wiresToSplit) {
27139
+ return
27140
+ }
27141
+ if (!Array.isArray(wiresToSplit)) {
27142
+ wiresToSplit = [wiresToSplit];
27143
+ }
27144
+ if (wiresToSplit.length === 0) {
27145
+ return;
27146
+ }
27147
+
27148
+ var removedLinks = new Set()
27149
+ var addedLinks = []
27150
+ var addedJunctions = []
27151
+
27152
+ var groupedLinks = {}
27153
+ wiresToSplit.forEach(function(l) {
27154
+ var sourceId = l.source.id+":"+l.sourcePort
27155
+ groupedLinks[sourceId] = groupedLinks[sourceId] || []
27156
+ groupedLinks[sourceId].push(l)
27157
+
27158
+ groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
27159
+ groupedLinks[l.target.id].push(l)
27160
+ });
27161
+ var linkGroups = Object.keys(groupedLinks)
27162
+ linkGroups.sort(function(A,B) {
27163
+ return groupedLinks[B].length - groupedLinks[A].length
27164
+ })
27165
+ linkGroups.forEach(function(gid) {
27166
+ var links = groupedLinks[gid]
27167
+ var junction = {
27168
+ _def: {defaults:{}},
27169
+ type: 'junction',
27170
+ z: RED.workspaces.active(),
27171
+ id: RED.nodes.id(),
27172
+ x: 0,
27173
+ y: 0,
27174
+ w: 0, h: 0,
27175
+ outputs: 1,
27176
+ inputs: 1,
27177
+ dirty: true
27178
+ }
27179
+ links = links.filter(function(l) { return !removedLinks.has(l) })
27180
+ if (links.length === 0) {
27181
+ return
27182
+ }
27183
+ let pointCount = 0
27184
+ links.forEach(function(l) {
27185
+ if (l._sliceLocation) {
27186
+ junction.x += l._sliceLocation.x
27187
+ junction.y += l._sliceLocation.y
27188
+ delete l._sliceLocation
27189
+ pointCount++
27190
+ } else {
27191
+ junction.x += l.source.x + l.source.w/2 + l.target.x - l.target.w/2
27192
+ junction.y += l.source.y + l.target.y
27193
+ pointCount += 2
27194
+ }
27195
+ })
27196
+ junction.x = Math.round(junction.x/pointCount)
27197
+ junction.y = Math.round(junction.y/pointCount)
27198
+ if (RED.view.snapGrid) {
27199
+ let gridSize = RED.view.gridSize()
27200
+ junction.x = (gridSize*Math.round(junction.x/gridSize));
27201
+ junction.y = (gridSize*Math.round(junction.y/gridSize));
27202
+ }
27203
+
27204
+ var nodeGroups = new Set()
27205
+
27206
+ RED.nodes.addJunction(junction)
27207
+ addedJunctions.push(junction)
27208
+ let newLink
27209
+ if (gid === links[0].source.id+":"+links[0].sourcePort) {
27210
+ newLink = {
27211
+ source: links[0].source,
27212
+ sourcePort: links[0].sourcePort,
27213
+ target: junction
27214
+ }
27215
+ } else {
27216
+ newLink = {
27217
+ source: junction,
27218
+ sourcePort: 0,
27219
+ target: links[0].target
27220
+ }
27221
+ }
27222
+ addedLinks.push(newLink)
27223
+ RED.nodes.addLink(newLink)
27224
+ links.forEach(function(l) {
27225
+ removedLinks.add(l)
27226
+ RED.nodes.removeLink(l)
27227
+ let newLink
27228
+ if (gid === l.target.id) {
27229
+ newLink = {
27230
+ source: l.source,
27231
+ sourcePort: l.sourcePort,
27232
+ target: junction
27233
+ }
27234
+ } else {
27235
+ newLink = {
27236
+ source: junction,
27237
+ sourcePort: 0,
27238
+ target: l.target
27239
+ }
27240
+ }
27241
+ addedLinks.push(newLink)
27242
+ RED.nodes.addLink(newLink)
27243
+ nodeGroups.add(l.source.g || "__NONE__")
27244
+ nodeGroups.add(l.target.g || "__NONE__")
27245
+ })
27246
+ if (nodeGroups.size === 1) {
27247
+ var group = nodeGroups.values().next().value
27248
+ if (group !== "__NONE__") {
27249
+ RED.group.addToGroup(RED.nodes.group(group), junction)
27250
+ }
27251
+ }
27252
+ })
27253
+ if (addedJunctions.length > 0) {
27254
+ RED.history.push({
27255
+ t: 'add',
27256
+ links: addedLinks,
27257
+ junctions: addedJunctions,
27258
+ removedLinks: Array.from(removedLinks)
27259
+ })
27260
+ RED.nodes.dirty(true)
27261
+ }
27262
+ RED.view.redraw(true);
27263
+ }
27264
+
26964
27265
  return {
26965
27266
  init: function() {
26966
27267
  RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
@@ -27023,6 +27324,7 @@ RED.view.tools = (function() {
27023
27324
  RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
27024
27325
 
27025
27326
  RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
27327
+ RED.actions.add("core:split-wires-with-junctions", function () { addJunctionsToWires() });
27026
27328
 
27027
27329
  RED.actions.add("core:generate-node-names", generateNodeNames )
27028
27330
 
@@ -27540,7 +27842,7 @@ RED.palette = (function() {
27540
27842
  }
27541
27843
 
27542
27844
  function escapeCategory(category) {
27543
- return category.replace(/[ /.]/g,"_");
27845
+ return category.replace(/[\x00-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/g,"_");
27544
27846
  }
27545
27847
  function addNodeType(nt,def) {
27546
27848
  if (getPaletteNode(nt).length) {
@@ -40421,6 +40723,7 @@ RED.clipboard = (function() {
40421
40723
  } else if (type === 'flow') {
40422
40724
  var activeWorkspace = RED.workspaces.active();
40423
40725
  nodes = RED.nodes.groups(activeWorkspace);
40726
+ nodes = nodes.concat(RED.nodes.junctions(activeWorkspace));
40424
40727
  nodes = nodes.concat(RED.nodes.filterNodes({z:activeWorkspace}));
40425
40728
  RED.nodes.eachConfig(function(n) {
40426
40729
  if (n.z === RED.workspaces.active() && n._def.hasUsers === false) {
@@ -41390,106 +41693,112 @@ RED.library = (function() {
41390
41693
  options.onconfirm(item);
41391
41694
  }
41392
41695
  });
41393
- var itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
41394
- var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>')
41395
- .on("click", function(evt) {
41396
- evt.preventDefault();
41397
- evt.stopPropagation();
41398
- var elementPos = menuButton.offset();
41399
-
41400
- var menuOptionMenu = RED.menu.init({id:"red-ui-library-browser-menu",
41401
- options: [
41402
- {id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
41403
- var defaultFolderName = "new-folder";
41404
- var defaultFolderNameMatches = {};
41405
-
41406
- var selected = dirList.treeList('selected');
41407
- if (!selected.children) {
41408
- selected = selected.parent;
41409
- }
41410
- var complete = function() {
41411
- selected.children.forEach(function(c) {
41412
- if (/^new-folder/.test(c.label)) {
41413
- defaultFolderNameMatches[c.label] = true
41414
- }
41415
- });
41416
- var folderIndex = 2;
41417
- while(defaultFolderNameMatches[defaultFolderName]) {
41418
- defaultFolderName = "new-folder-"+(folderIndex++)
41419
- }
41420
-
41421
- selected.treeList.expand();
41422
- var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName);
41423
- var newItem = {
41424
- icon: "fa fa-folder-o",
41425
- children:[],
41426
- path: selected.path,
41427
- element: input
41428
- }
41429
- var confirmAdd = function() {
41430
- var val = input.val().trim();
41431
- if (val === "") {
41432
- cancelAdd();
41433
- return;
41434
- } else {
41435
- for (var i=0;i<selected.children.length;i++) {
41436
- if (selected.children[i].label === val) {
41437
- cancelAdd();
41438
- return;
41439
- }
41440
- }
41441
- }
41442
- newItem.treeList.remove();
41443
- var finalItem = {
41444
- library: selected.library,
41445
- type: selected.type,
41446
- icon: "fa fa-folder",
41447
- children:[],
41448
- label: val,
41449
- path: newItem.path+val+"/"
41450
- }
41451
- selected.treeList.addChild(finalItem,true);
41452
- }
41453
- var cancelAdd = function() {
41454
- newItem.treeList.remove();
41455
- }
41456
- input.on('keydown', function(evt) {
41457
- evt.stopPropagation();
41458
- if (evt.keyCode === 13) {
41459
- confirmAdd();
41460
- } else if (evt.keyCode === 27) {
41461
- cancelAdd();
41462
- }
41463
- })
41464
- input.on("blur", function() {
41465
- confirmAdd();
41466
- })
41467
- selected.treeList.addChild(newItem);
41468
- setTimeout(function() {
41469
- input.trigger("focus");
41470
- input.select();
41471
- },400);
41472
- }
41473
- selected.treeList.expand(complete);
41474
-
41475
- } },
41476
- // null,
41477
- // {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} },
41478
- // {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} }
41479
- ]
41480
- }).on('mouseleave', function(){ $(this).remove(); dirList.focus() })
41481
- .on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)})
41482
- .appendTo("body");
41483
- menuOptionMenu.css({
41484
- position: "absolute",
41485
- top: elementPos.top+"px",
41486
- left: (elementPos.left - menuOptionMenu.width() + 20)+"px"
41487
- }).show();
41488
-
41489
- }).appendTo(itemTools);
41696
+ var itemTools = null;
41490
41697
  if (options.folderTools) {
41491
41698
  dirList.on('treelistselect', function(event, item) {
41492
41699
  if (item.writable !== false && item.treeList) {
41700
+ if (itemTools) {
41701
+ itemTools.remove();
41702
+ }
41703
+ itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
41704
+ var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>')
41705
+ .on("click", function(evt) {
41706
+ evt.preventDefault();
41707
+ evt.stopPropagation();
41708
+ var elementPos = menuButton.offset();
41709
+
41710
+ var menuOptionMenu
41711
+ = RED.menu.init({id:"red-ui-library-browser-menu",
41712
+ options: [
41713
+ {id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
41714
+ var defaultFolderName = "new-folder";
41715
+ var defaultFolderNameMatches = {};
41716
+
41717
+ var selected = dirList.treeList('selected');
41718
+ if (!selected.children) {
41719
+ selected = selected.parent;
41720
+ }
41721
+ var complete = function() {
41722
+ selected.children.forEach(function(c) {
41723
+ if (/^new-folder/.test(c.label)) {
41724
+ defaultFolderNameMatches[c.label] = true
41725
+ }
41726
+ });
41727
+ var folderIndex = 2;
41728
+ while(defaultFolderNameMatches[defaultFolderName]) {
41729
+ defaultFolderName = "new-folder-"+(folderIndex++)
41730
+ }
41731
+
41732
+ selected.treeList.expand();
41733
+ var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName);
41734
+ var newItem = {
41735
+ icon: "fa fa-folder-o",
41736
+ children:[],
41737
+ path: selected.path,
41738
+ element: input
41739
+ }
41740
+ var confirmAdd = function() {
41741
+ var val = input.val().trim();
41742
+ if (val === "") {
41743
+ cancelAdd();
41744
+ return;
41745
+ } else {
41746
+ for (var i=0;i<selected.children.length;i++) {
41747
+ if (selected.children[i].label === val) {
41748
+ cancelAdd();
41749
+ return;
41750
+ }
41751
+ }
41752
+ }
41753
+ newItem.treeList.remove();
41754
+ var finalItem = {
41755
+ library: selected.library,
41756
+ type: selected.type,
41757
+ icon: "fa fa-folder",
41758
+ children:[],
41759
+ label: val,
41760
+ path: newItem.path+val+"/"
41761
+ }
41762
+ selected.treeList.addChild(finalItem,true);
41763
+ }
41764
+ var cancelAdd = function() {
41765
+ newItem.treeList.remove();
41766
+ }
41767
+ input.on('keydown', function(evt) {
41768
+ evt.stopPropagation();
41769
+ if (evt.keyCode === 13) {
41770
+ confirmAdd();
41771
+ } else if (evt.keyCode === 27) {
41772
+ cancelAdd();
41773
+ }
41774
+ })
41775
+ input.on("blur", function() {
41776
+ confirmAdd();
41777
+ })
41778
+ selected.treeList.addChild(newItem);
41779
+ setTimeout(function() {
41780
+ input.trigger("focus");
41781
+ input.select();
41782
+ },400);
41783
+ }
41784
+ selected.treeList.expand(complete);
41785
+
41786
+ } },
41787
+ // null,
41788
+ // {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} },
41789
+ // {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} }
41790
+ ]
41791
+ }).on('mouseleave', function(){ $(this).remove(); dirList.focus() })
41792
+ .on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)})
41793
+ .appendTo("body");
41794
+ menuOptionMenu.css({
41795
+ position: "absolute",
41796
+ top: elementPos.top+"px",
41797
+ left: (elementPos.left - menuOptionMenu.width() + 20)+"px"
41798
+ }).show();
41799
+
41800
+ }).appendTo(itemTools);
41801
+
41493
41802
  itemTools.appendTo(item.treeList.label);
41494
41803
  }
41495
41804
  });
@@ -42887,6 +43196,181 @@ RED.search = (function() {
42887
43196
  };
42888
43197
 
42889
43198
  })();
43199
+ ;RED.contextMenu = (function() {
43200
+
43201
+ let menu;
43202
+ function createMenu() {
43203
+ // menu = RED.popover.menu({
43204
+ // options: [
43205
+ // {
43206
+ // label: 'delete selection',
43207
+ // onselect: function() {
43208
+ // RED.actions.invoke('core:delete-selection')
43209
+ // RED.view.focus()
43210
+ // }
43211
+ // },
43212
+ // { label: 'world' }
43213
+ // ],
43214
+ // width: 200,
43215
+ // })
43216
+
43217
+
43218
+
43219
+
43220
+ }
43221
+
43222
+ function disposeMenu() {
43223
+ $(document).off("mousedown.red-ui-workspace-context-menu");
43224
+ if (menu) {
43225
+ menu.remove();
43226
+ }
43227
+ menu = null;
43228
+ }
43229
+ function show(options) {
43230
+ if (menu) {
43231
+ menu.remove()
43232
+ }
43233
+
43234
+ const selection = RED.view.selection()
43235
+ const hasSelection = (selection.nodes && selection.nodes.length > 0);
43236
+ const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
43237
+ const hasLinks = selection.links && selection.links.length > 0;
43238
+ const isSingleLink = !hasSelection && hasLinks && selection.links.length === 1
43239
+ const isMultipleLinks = !hasSelection && hasLinks && selection.links.length > 1
43240
+ const canDelete = hasSelection || hasLinks
43241
+ const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
43242
+
43243
+ const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
43244
+
43245
+
43246
+ const menuItems = [
43247
+ { onselect: 'core:show-action-list', onpostselect: function() {} },
43248
+ {
43249
+ label: 'Insert',
43250
+ options: [
43251
+ {
43252
+ label: 'Node',
43253
+ onselect: function() {
43254
+ RED.view.showQuickAddDialog({
43255
+ position: [ options.x - offset.left, options.y - offset.top ],
43256
+ touchTrigger: true,
43257
+ splice: isSingleLink?selection.links[0]:undefined,
43258
+ // spliceMultiple: isMultipleLinks
43259
+ })
43260
+ }
43261
+ },
43262
+ {
43263
+ label: 'Junction',
43264
+ onselect: 'core:split-wires-with-junctions',
43265
+ disabled: hasSelection || !hasLinks
43266
+ },
43267
+ {
43268
+ label: 'Link Nodes',
43269
+ onselect: 'core:split-wire-with-link-nodes',
43270
+ disabled: hasSelection || !hasLinks
43271
+ }
43272
+ ]
43273
+
43274
+
43275
+
43276
+ }
43277
+ ]
43278
+ // menuItems.push(
43279
+ // {
43280
+ // label: (isSingleLink || isMultipleLinks)?'Insert into wire...':'Add node...',
43281
+ // onselect: function() {
43282
+ // RED.view.showQuickAddDialog({
43283
+ // position: [ options.x - offset.left, options.y - offset.top ],
43284
+ // touchTrigger: true,
43285
+ // splice: isSingleLink?selection.links[0]:undefined,
43286
+ // spliceMultiple: isMultipleLinks
43287
+ // })
43288
+ // }
43289
+ // },
43290
+ // )
43291
+ // if (hasLinks && !hasSelection) {
43292
+ // menuItems.push({ onselect: 'core:split-wires-with-junctions', label: 'Insert junction'})
43293
+ // }
43294
+ menuItems.push(
43295
+ null,
43296
+ { onselect: 'core:undo', disabled: RED.history.list().length === 0 },
43297
+ { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
43298
+ null,
43299
+ { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection},
43300
+ { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
43301
+ { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
43302
+ { onselect: 'core:delete-selection', disabled: !canDelete },
43303
+ { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
43304
+ { onselect: 'core:select-all-nodes' }
43305
+ )
43306
+
43307
+ if (hasSelection) {
43308
+ menuItems.push(
43309
+ null,
43310
+ isGroup ?
43311
+ { onselect: 'core:ungroup-selection', disabled: !isGroup }
43312
+ : { onselect: 'core:group-selection', disabled: !hasSelection }
43313
+ )
43314
+ if (canRemoveFromGroup) {
43315
+ menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
43316
+ }
43317
+
43318
+ }
43319
+ const offset = $("#red-ui-workspace-chart").offset()
43320
+ menu = RED.menu.init({
43321
+ direction: 'right',
43322
+ onpreselect: function() {
43323
+ disposeMenu()
43324
+ },
43325
+ onpostselect: function() {
43326
+ RED.view.focus()
43327
+ },
43328
+ options: menuItems
43329
+ });
43330
+
43331
+ menu.attr("id","red-ui-workspace-context-menu");
43332
+ menu.css({
43333
+ position: "absolute"
43334
+ })
43335
+ menu.appendTo("body");
43336
+
43337
+ // TODO: prevent the menu from overflowing the window.
43338
+
43339
+ var top = options.y
43340
+ var left = options.x
43341
+
43342
+ if (top+menu.height()-$(document).scrollTop() > $(window).height()) {
43343
+ top -= (top+menu.height())-$(window).height() + 22;
43344
+ }
43345
+ if (left+menu.width()-$(document).scrollLeft() > $(window).width()) {
43346
+ left -= (left+menu.width())-$(window).width() + 18;
43347
+ }
43348
+ menu.css({
43349
+ top: top+"px",
43350
+ left: left+"px"
43351
+ })
43352
+ $(".red-ui-menu.red-ui-menu-dropdown").hide();
43353
+ $(document).on("mousedown.red-ui-workspace-context-menu", function(evt) {
43354
+ if (menu && menu[0].contains(evt.target)) {
43355
+ return
43356
+ }
43357
+ disposeMenu()
43358
+ });
43359
+ menu.show();
43360
+
43361
+ // menu.show({
43362
+ // target: $('#red-ui-main-container'),
43363
+ // x: options.x,
43364
+ // y: options.y
43365
+ // })
43366
+
43367
+
43368
+ }
43369
+
43370
+ return {
43371
+ show: show
43372
+ }
43373
+ })()
42890
43374
  ;/**
42891
43375
  * Copyright JS Foundation and other contributors, http://js.foundation
42892
43376
  *
@@ -43225,7 +43709,9 @@ RED.actionList = (function() {
43225
43709
  var index = Math.max(0,selected);
43226
43710
  if (index < children.length) {
43227
43711
  var n = $(children[index]).find(".red-ui-editableList-item-content").data('data');
43228
- typesUsed[n.type] = Date.now();
43712
+ if (!/^_action_:/.test(n.type)) {
43713
+ typesUsed[n.type] = Date.now();
43714
+ }
43229
43715
  if (n.def.outputs === 0) {
43230
43716
  confirm(n);
43231
43717
  } else {
@@ -43294,6 +43780,8 @@ RED.actionList = (function() {
43294
43780
  var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
43295
43781
  if (object.type === "junction") {
43296
43782
  nodeDiv.addClass("red-ui-palette-icon-junction");
43783
+ } else if (/^_action_:/.test(object.type)) {
43784
+ nodeDiv.addClass("red-ui-palette-icon-junction")
43297
43785
  } else {
43298
43786
  var colour = RED.utils.getNodeColor(object.type,def);
43299
43787
  nodeDiv.css('backgroundColor',colour);
@@ -43303,11 +43791,14 @@ RED.actionList = (function() {
43303
43791
  var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
43304
43792
  RED.utils.createIconElement(icon_url, iconContainer, false);
43305
43793
 
43306
- if (object.type !== "junction" && def.inputs > 0) {
43307
- $('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
43308
- }
43309
- if (object.type !== "junction" && def.outputs > 0) {
43310
- $('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
43794
+
43795
+ if (!/^_action_:/.test(object.type) && object.type !== "junction") {
43796
+ if (def.inputs > 0) {
43797
+ $('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
43798
+ }
43799
+ if (def.outputs > 0) {
43800
+ $('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
43801
+ }
43311
43802
  }
43312
43803
 
43313
43804
  var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
@@ -43328,7 +43819,9 @@ RED.actionList = (function() {
43328
43819
  }
43329
43820
  function confirm(def) {
43330
43821
  hide();
43331
- typesUsed[def.type] = Date.now();
43822
+ if (!/^_action_:/.test(def.type)) {
43823
+ typesUsed[def.type] = Date.now();
43824
+ }
43332
43825
  addCallback(def.type);
43333
43826
  }
43334
43827
 
@@ -43437,6 +43930,7 @@ RED.actionList = (function() {
43437
43930
  function applyFilter(filter,type,def) {
43438
43931
  return !filter ||
43439
43932
  (
43933
+ (!filter.spliceMultiple) &&
43440
43934
  (!filter.type || type === filter.type) &&
43441
43935
  (!filter.input || type === 'junction' || def.inputs > 0) &&
43442
43936
  (!filter.output || type === 'junction' || def.outputs > 0)
@@ -43451,6 +43945,13 @@ RED.actionList = (function() {
43451
43945
  'inject','debug','function','change','switch','junction'
43452
43946
  ].filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)); });
43453
43947
 
43948
+ // if (opts.filter && opts.filter.input && opts.filter.output && !opts.filter.type) {
43949
+ // if (opts.filter.spliceMultiple) {
43950
+ // common.push('_action_:core:split-wires-with-junctions')
43951
+ // }
43952
+ // common.push('_action_:core:split-wire-with-link-nodes')
43953
+ // }
43954
+
43454
43955
  var recentlyUsed = Object.keys(typesUsed);
43455
43956
  recentlyUsed.sort(function(a,b) {
43456
43957
  return typesUsed[b]-typesUsed[a];
@@ -43475,6 +43976,8 @@ RED.actionList = (function() {
43475
43976
  var itemDef = RED.nodes.getType(common[i]);
43476
43977
  if (common[i] === 'junction') {
43477
43978
  itemDef = { inputs:1, outputs: 1, label: 'junction', type: 'junction'}
43979
+ } else if (/^_action_:/.test(common[i]) ) {
43980
+ itemDef = { inputs:1, outputs: 1, label: common[i], type: common[i]}
43478
43981
  }
43479
43982
  if (itemDef) {
43480
43983
  item = {
@@ -44128,6 +44631,14 @@ RED.subflow = (function() {
44128
44631
  return x;
44129
44632
  }
44130
44633
 
44634
+ function nodeOrJunction(id) {
44635
+ var node = RED.nodes.node(id);
44636
+ if (node) {
44637
+ return node;
44638
+ }
44639
+ return RED.nodes.junction(id);
44640
+ }
44641
+
44131
44642
  function convertToSubflow() {
44132
44643
  var selection = RED.view.selection();
44133
44644
  if (!selection.nodes) {
@@ -44316,14 +44827,15 @@ RED.subflow = (function() {
44316
44827
 
44317
44828
  subflow.in.forEach(function(input) {
44318
44829
  input.wires.forEach(function(wire) {
44319
- var link = {source: input, sourcePort: 0, target: RED.nodes.node(wire.id) }
44830
+ var link = {source: input, sourcePort: 0, target: nodeOrJunction(wire.id) }
44320
44831
  new_links.push(link);
44321
44832
  RED.nodes.addLink(link);
44322
44833
  });
44323
44834
  });
44835
+
44324
44836
  subflow.out.forEach(function(output,i) {
44325
44837
  output.wires.forEach(function(wire) {
44326
- var link = {source: RED.nodes.node(wire.id), sourcePort: wire.port , target: output }
44838
+ var link = {source: nodeOrJunction(wire.id), sourcePort: wire.port , target: output }
44327
44839
  new_links.push(link);
44328
44840
  RED.nodes.addLink(link);
44329
44841
  });
@@ -44339,7 +44851,7 @@ RED.subflow = (function() {
44339
44851
  n.links = n.links.filter(function(id) {
44340
44852
  var isLocalLink = nodes.hasOwnProperty(id);
44341
44853
  if (!isLocalLink) {
44342
- var otherNode = RED.nodes.node(id);
44854
+ var otherNode = nodeOrJunction(id);
44343
44855
  if (otherNode && otherNode.links) {
44344
44856
  var i = otherNode.links.indexOf(n.id);
44345
44857
  if (i > -1) {
@@ -44355,7 +44867,6 @@ RED.subflow = (function() {
44355
44867
  RED.nodes.moveNodeToTab(n, subflow.id);
44356
44868
  }
44357
44869
 
44358
-
44359
44870
  var historyEvent = {
44360
44871
  t:'createSubflow',
44361
44872
  nodes:[subflowInstance.id],