@node-red/editor-client 3.0.0-beta.4 → 3.0.2

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
@@ -857,7 +857,7 @@ var RED = (function() {
857
857
  $('<div id="red-ui-header-shade" class="hide"></div>').appendTo(header);
858
858
  $('<div id="red-ui-main-container" class="red-ui-sidebar-closed hide">'+
859
859
  '<div id="red-ui-workspace"></div>'+
860
- '<div id="red-ui-editor-stack"></div>'+
860
+ '<div id="red-ui-editor-stack" tabindex="-1"></div>'+
861
861
  '<div id="red-ui-palette"></div>'+
862
862
  '<div id="red-ui-sidebar"></div>'+
863
863
  '<div id="red-ui-sidebar-separator"></div>'+
@@ -4530,14 +4530,7 @@ RED.nodes = (function() {
4530
4530
  var node;
4531
4531
 
4532
4532
  if (allNodes.hasTab(id)) {
4533
- removedNodes = allNodes.getNodes(id).filter(n => {
4534
- if (n.type === 'junction') {
4535
- removedJunctions.push(n)
4536
- return false
4537
- } else {
4538
- return true
4539
- }
4540
- })
4533
+ removedNodes = allNodes.getNodes(id).slice()
4541
4534
  }
4542
4535
  for (i in configNodes) {
4543
4536
  if (configNodes.hasOwnProperty(i)) {
@@ -4547,6 +4540,7 @@ RED.nodes = (function() {
4547
4540
  }
4548
4541
  }
4549
4542
  }
4543
+ removedJunctions = RED.nodes.junctions(id)
4550
4544
 
4551
4545
  for (i=0;i<removedNodes.length;i++) {
4552
4546
  var result = removeNode(removedNodes[i].id);
@@ -4993,7 +4987,6 @@ RED.nodes = (function() {
4993
4987
  } else {
4994
4988
  nodeSet = [sf];
4995
4989
  }
4996
- console.log(nodeSet);
4997
4990
  return createExportableNodeSet(nodeSet);
4998
4991
  }
4999
4992
  /**
@@ -5029,6 +5022,10 @@ RED.nodes = (function() {
5029
5022
  exportedConfigNodes[n.id] = true;
5030
5023
  }
5031
5024
  });
5025
+
5026
+ subflowSet = subflowSet.concat(RED.nodes.junctions(subflowId))
5027
+ subflowSet = subflowSet.concat(RED.nodes.groups(subflowId))
5028
+
5032
5029
  var exportableSubflow = createExportableNodeSet(subflowSet, exportedIds, exportedSubflows, exportedConfigNodes);
5033
5030
  nns = exportableSubflow.concat(nns);
5034
5031
  }
@@ -5326,6 +5323,7 @@ RED.nodes = (function() {
5326
5323
  function importNodes(newNodesObj,options) { // createNewIds,createMissingWorkspace) {
5327
5324
  const defOpts = { generateIds: false, addFlow: false, reimport: false, importMap: {} }
5328
5325
  options = Object.assign({}, defOpts, options)
5326
+ options.importMap = options.importMap || {}
5329
5327
  const createNewIds = options.generateIds;
5330
5328
  const reimport = (!createNewIds && !!options.reimport)
5331
5329
  const createMissingWorkspace = options.addFlow;
@@ -9837,7 +9835,7 @@ RED.utils = (function() {
9837
9835
  this.element.css("maxHeight",null);
9838
9836
  }
9839
9837
  if (this.options.height !== 'auto') {
9840
- this.uiContainer.css("overflow-y","scroll");
9838
+ this.uiContainer.css("overflow-y","auto");
9841
9839
  if (!isNaN(this.options.height)) {
9842
9840
  this.uiHeight = this.options.height;
9843
9841
  }
@@ -13840,10 +13838,10 @@ RED.stack = (function() {
13840
13838
  optEl.append(generateSpans(srcMatch));
13841
13839
  optEl.appendTo(element);
13842
13840
  }
13843
- matches.push({
13844
- value: optVal,
13845
- label: element,
13846
- i: (valMatch.found ? valMatch.index : srcMatch.index)
13841
+ matches.push({
13842
+ value: optVal,
13843
+ label: element,
13844
+ i: (valMatch.found ? valMatch.index : srcMatch.index)
13847
13845
  });
13848
13846
  }
13849
13847
  })
@@ -14251,7 +14249,7 @@ RED.stack = (function() {
14251
14249
  this.options.types = this.options.types||Object.keys(allOptions);
14252
14250
  }
14253
14251
 
14254
- this.selectTrigger = $('<button class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect);
14252
+ this.selectTrigger = $('<button type="button" class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect);
14255
14253
  $('<i class="red-ui-typedInput-icon fa fa-caret-down"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
14256
14254
 
14257
14255
  this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
@@ -14320,7 +14318,7 @@ RED.stack = (function() {
14320
14318
  })
14321
14319
 
14322
14320
  // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
14323
- this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect);
14321
+ this.optionSelectTrigger = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect);
14324
14322
  this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
14325
14323
  // RED.popover.tooltip(this.optionSelectLabel,function() {
14326
14324
  // return that.optionValue;
@@ -14341,7 +14339,7 @@ RED.stack = (function() {
14341
14339
  that.uiSelect.addClass('red-ui-typedInput-focus');
14342
14340
  });
14343
14341
 
14344
- this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
14342
+ this.optionExpandButton = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
14345
14343
  this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
14346
14344
 
14347
14345
  this.type(this.typeField.val() || this.options.default||this.typeList[0].value);
@@ -15444,8 +15442,8 @@ RED.deploy = (function() {
15444
15442
  null
15445
15443
  ]
15446
15444
  if (RED.settings.runtimeState && RED.settings.runtimeState.ui === true) {
15447
- mainMenuItems.push({id:"deploymenu-item-runtime-start", icon:"red/images/start.svg",label:"Start"/*RED._("deploy.startFlows")*/,sublabel:"Start Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:start-flows", visible:false})
15448
- mainMenuItems.push({id:"deploymenu-item-runtime-stop", icon:"red/images/stop.svg",label:"Stop"/*RED._("deploy.startFlows")*/,sublabel:"Stop Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:stop-flows", visible:false})
15445
+ mainMenuItems.push({id:"deploymenu-item-runtime-start", icon:"red/images/start.svg",label:RED._("deploy.startFlows"),sublabel:RED._("deploy.startFlowsDesc"),onselect:"core:start-flows", visible:false})
15446
+ mainMenuItems.push({id:"deploymenu-item-runtime-stop", icon:"red/images/stop.svg",label:RED._("deploy.stopFlows"),sublabel:RED._("deploy.stopFlowsDesc"),onselect:"core:stop-flows", visible:false})
15449
15447
  }
15450
15448
  mainMenuItems.push({id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"})
15451
15449
  RED.menu.init({id:"red-ui-header-button-deploy-options", options: mainMenuItems });
@@ -18554,13 +18552,18 @@ RED.keyboard = (function() {
18554
18552
  if (partialState) {
18555
18553
  partialState = null;
18556
18554
  return resolveKeyEvent(evt);
18557
- } else if (Object.keys(handler).length > 0) {
18558
- partialState = handler;
18559
- evt.preventDefault();
18560
- return null;
18561
- } else {
18562
- return null;
18563
18555
  }
18556
+ if (Object.keys(handler).length > 0) {
18557
+ // check if there's a potential combined handler initiated by this keyCode
18558
+ for (let h in handler) {
18559
+ if (matchHandlerToEvent(evt,handler[h]) > -1) {
18560
+ partialState = handler;
18561
+ evt.preventDefault();
18562
+ break;
18563
+ }
18564
+ }
18565
+ }
18566
+ return null;
18564
18567
  } else {
18565
18568
  var depth = Infinity;
18566
18569
  var matchedHandler;
@@ -19779,6 +19782,7 @@ RED.view = (function() {
19779
19782
  let flashingNodeId;
19780
19783
 
19781
19784
  var clipboard = "";
19785
+ let clipboardSource
19782
19786
 
19783
19787
  // Note: these are the permitted status colour aliases. The actual RGB values
19784
19788
  // are set in the CSS - flow.scss/colors.scss
@@ -20312,8 +20316,10 @@ RED.view = (function() {
20312
20316
  });
20313
20317
 
20314
20318
  RED.actions.add("core:copy-selection-to-internal-clipboard",copySelection);
20315
- RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();});
20316
- RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true, generateDefaultNames: true});});
20319
+ RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection(true);deleteSelection();});
20320
+ RED.actions.add("core:paste-from-internal-clipboard",function(){
20321
+ importNodes(clipboard,{generateIds: clipboardSource === 'copy', generateDefaultNames: clipboardSource === 'copy'});
20322
+ });
20317
20323
 
20318
20324
  RED.actions.add("core:detach-selected-nodes", function() { detachSelectedNodes() })
20319
20325
 
@@ -20752,12 +20758,15 @@ RED.view = (function() {
20752
20758
  RED.view.redraw();
20753
20759
  }
20754
20760
 
20761
+ // `point` is the place in the workspace the mouse has clicked.
20762
+ // This takes into account scrolling and scaling of the workspace.
20755
20763
  var ox = point[0];
20756
20764
  var oy = point[1];
20757
20765
 
20766
+ // Need to map that to browser location to position the pop-up
20758
20767
  const offset = $("#red-ui-workspace-chart").offset()
20759
- var clientX = ox + offset.left - $("#red-ui-workspace-chart").scrollLeft()
20760
- var clientY = oy + offset.top - $("#red-ui-workspace-chart").scrollTop()
20768
+ var clientX = (ox * scaleFactor) + offset.left - $("#red-ui-workspace-chart").scrollLeft()
20769
+ var clientY = (oy * scaleFactor) + offset.top - $("#red-ui-workspace-chart").scrollTop()
20761
20770
 
20762
20771
  if (RED.settings.get("editor").view['view-snap-grid']) {
20763
20772
  // eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
@@ -21833,6 +21842,9 @@ RED.view = (function() {
21833
21842
  }
21834
21843
  }
21835
21844
  if (mouse_mode == RED.state.IMPORT_DRAGGING) {
21845
+ if (clipboardSource === 'cut') {
21846
+ clipboardSource = 'copy'
21847
+ }
21836
21848
  updateActiveNodes();
21837
21849
  RED.nodes.dirty(true);
21838
21850
  }
@@ -22387,7 +22399,7 @@ RED.view = (function() {
22387
22399
  }
22388
22400
  }
22389
22401
 
22390
- function copySelection() {
22402
+ function copySelection(isCut) {
22391
22403
  if (mouse_mode === RED.state.SELECTING_NODE) {
22392
22404
  return;
22393
22405
  }
@@ -22451,6 +22463,7 @@ RED.view = (function() {
22451
22463
  }
22452
22464
  }
22453
22465
  clipboard = JSON.stringify(nns);
22466
+ clipboardSource = isCut ? 'cut' : 'copy'
22454
22467
  RED.menu.setDisabled("menu-item-edit-paste", false);
22455
22468
  if (nodeCount > 0) {
22456
22469
  RED.notify(RED._("clipboard.nodeCopied",{count:nodeCount}),{id:"clipboard"});
@@ -22970,11 +22983,17 @@ RED.view = (function() {
22970
22983
 
22971
22984
  if (active && ((portType === PORT_TYPE_INPUT && ((d._def && d._def.inputLabels)||d.inputLabels)) || (portType === PORT_TYPE_OUTPUT && ((d._def && d._def.outputLabels)||d.outputLabels)))) {
22972
22985
  portLabelHoverTimeout = setTimeout(function() {
22986
+ const n = port && port.node()
22987
+ const nId = n && n.__data__ && n.__data__.id
22988
+ //check see if node has been deleted since timeout started
22989
+ if(!n || !n.parentNode || !RED.nodes.node(n.__data__.id)) {
22990
+ return; //node is gone!
22991
+ }
22973
22992
  var tooltip = getPortLabel(d,portType,portIndex);
22974
22993
  if (!tooltip) {
22975
22994
  return;
22976
22995
  }
22977
- var pos = getElementPosition(port.node());
22996
+ var pos = getElementPosition(n);
22978
22997
  portLabelHoverTimeout = null;
22979
22998
  portLabelHover = showTooltip(
22980
22999
  (pos[0]+(portType===PORT_TYPE_INPUT?-2:12)),
@@ -23161,6 +23180,9 @@ RED.view = (function() {
23161
23180
  updateSelection();
23162
23181
  RED.nodes.dirty(true);
23163
23182
  redraw();
23183
+ if (clipboardSource === 'cut') {
23184
+ clipboardSource = 'copy'
23185
+ }
23164
23186
  resetMouseVars();
23165
23187
  d3.event.stopPropagation();
23166
23188
  return;
@@ -23408,6 +23430,10 @@ RED.view = (function() {
23408
23430
  if (d.hasOwnProperty('l')?!d.l : (d.type === "link in" || d.type === "link out")) {
23409
23431
  var parentNode = this.parentNode;
23410
23432
  portLabelHoverTimeout = setTimeout(function() {
23433
+ //check see if node has been deleted since timeout started
23434
+ if(!parentNode || !parentNode.parentNode || !RED.nodes.node(parentNode.id)) {
23435
+ return; //node is gone!
23436
+ }
23411
23437
  var tooltip;
23412
23438
  if (d._def.label) {
23413
23439
  tooltip = d._def.label;
@@ -23770,7 +23796,7 @@ RED.view = (function() {
23770
23796
  var mdn = mousedown_node;
23771
23797
  var options = [];
23772
23798
  options.push({name:"delete",disabled:(movingSet.length()===0 && selectedLinks.length() === 0),onselect:function() {deleteSelection();}});
23773
- options.push({name:"cut",disabled:(movingSet.length()===0),onselect:function() {copySelection();deleteSelection();}});
23799
+ options.push({name:"cut",disabled:(movingSet.length()===0),onselect:function() {copySelection(true);deleteSelection();}});
23774
23800
  options.push({name:"copy",disabled:(movingSet.length()===0),onselect:function() {copySelection();}});
23775
23801
  options.push({name:"paste",disabled:(clipboard.length===0),onselect:function() {importNodes(clipboard, {generateIds: true, touchImport: true});}});
23776
23802
  options.push({name:"edit",disabled:(movingSet.length() != 1),onselect:function() { RED.editor.edit(mdn);}});
@@ -24244,12 +24270,10 @@ RED.view = (function() {
24244
24270
  icon_groupEl.setAttribute("y",0);
24245
24271
  icon_groupEl.style["pointer-events"] = "none";
24246
24272
  node[0][0].__iconGroup__ = icon_groupEl;
24247
- var icon_shade = document.createElementNS("http://www.w3.org/2000/svg","rect");
24273
+ var icon_shade = document.createElementNS("http://www.w3.org/2000/svg","path");
24248
24274
  icon_shade.setAttribute("x",0);
24249
24275
  icon_shade.setAttribute("y",0);
24250
24276
  icon_shade.setAttribute("class","red-ui-flow-node-icon-shade")
24251
- icon_shade.setAttribute("width",30);
24252
- icon_shade.setAttribute("height",Math.min(50,d.h-4));
24253
24277
  icon_groupEl.appendChild(icon_shade);
24254
24278
  node[0][0].__iconShade__ = icon_shade;
24255
24279
 
@@ -24542,9 +24566,20 @@ RED.view = (function() {
24542
24566
  }
24543
24567
 
24544
24568
  icon.attr("y",function(){return (d.h-d3.select(this).attr("height"))/2;});
24545
- this.__iconShade__.setAttribute("height", d.h );
24569
+
24570
+
24571
+ const iconShadeHeight = d.h
24572
+ const iconShadeWidth = 30
24573
+ this.__iconShade__.setAttribute("d", hideLabel ?
24574
+ `M5 0 h${iconShadeWidth-10} a 5 5 0 0 1 5 5 v${iconShadeHeight-10} a 5 5 0 0 1 -5 5 h-${iconShadeWidth-10} a 5 5 0 0 1 -5 -5 v-${iconShadeHeight-10} a 5 5 0 0 1 5 -5` : (
24575
+ "right" === d._def.align ?
24576
+ `M 0 0 h${iconShadeWidth-5} a 5 5 0 0 1 5 5 v${iconShadeHeight-10} a 5 5 0 0 1 -5 5 h-${iconShadeWidth-5} v-${iconShadeHeight}` :
24577
+ `M5 0 h${iconShadeWidth-5} v${iconShadeHeight} h-${iconShadeWidth-5} a 5 5 0 0 1 -5 -5 v-${iconShadeHeight-10} a 5 5 0 0 1 5 -5`
24578
+ )
24579
+ )
24580
+ this.__iconShadeBorder__.style.display = hideLabel?'none':''
24546
24581
  this.__iconShadeBorder__.setAttribute("d",
24547
- "M " + (((!d._def.align && d.inputs !== 0 && d.outputs === 0) || "right" === d._def.align) ? 0 : 30) + " 1 l 0 " + (d.h - 2)
24582
+ "M " + (((!d._def.align && d.inputs !== 0 && d.outputs === 0) || "right" === d._def.align) ? 0.5 : 29.5) + " "+(d.selected?1:0.5)+" l 0 " + (d.h - (d.selected?2:1))
24548
24583
  );
24549
24584
  faIcon.attr("y",(d.h+13)/2);
24550
24585
  }
@@ -24561,7 +24596,7 @@ RED.view = (function() {
24561
24596
  if (d._def.button) {
24562
24597
  var buttonEnabled = isButtonEnabled(d);
24563
24598
  this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-disabled", !buttonEnabled);
24564
- if (RED.runtime && Object.hasOwn(RED.runtime,'started')) {
24599
+ if (RED.runtime && RED.runtime.started !== undefined) {
24565
24600
  this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-stopped", !RED.runtime.started);
24566
24601
  }
24567
24602
 
@@ -25920,7 +25955,13 @@ RED.view = (function() {
25920
25955
  showQuickAddDialog:showQuickAddDialog,
25921
25956
  calculateNodeDimensions: calculateNodeDimensions,
25922
25957
  getElementPosition:getElementPosition,
25923
- showTooltip:showTooltip
25958
+ showTooltip:showTooltip,
25959
+ dimensions: function() {
25960
+ return {
25961
+ width: space_width,
25962
+ height: space_height
25963
+ };
25964
+ }
25924
25965
  };
25925
25966
  })();
25926
25967
  ;RED.view.annotations = (function() {
@@ -26339,6 +26380,9 @@ RED.view.tools = (function() {
26339
26380
  $(document).one('keyup',endKeyboardMove);
26340
26381
  endMoveSet = true;
26341
26382
  }
26383
+ var dim = RED.view.dimensions();
26384
+ var space_width = dim.width;
26385
+ var space_height = dim.height;
26342
26386
  var minX = 0;
26343
26387
  var minY = 0;
26344
26388
  var node;
@@ -26354,6 +26398,12 @@ RED.view.tools = (function() {
26354
26398
  node.n.dirty = true;
26355
26399
  node.n.x += dx;
26356
26400
  node.n.y += dy;
26401
+ if ((node.n.x +node.n.w/2) >= space_width) {
26402
+ node.n.x = space_width -node.n.w/2;
26403
+ }
26404
+ if ((node.n.y +node.n.h/2) >= space_height) {
26405
+ node.n.y = space_height -node.n.h/2;
26406
+ }
26357
26407
  node.n.dirty = true;
26358
26408
  if (node.n.type === "group") {
26359
26409
  RED.group.markDirty(node.n);
@@ -27048,7 +27098,7 @@ RED.view.tools = (function() {
27048
27098
  * @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes.
27049
27099
  */
27050
27100
  function splitWiresWithLinkNodes(wires) {
27051
- let wiresToSplit = wires || RED.view.selection().links;
27101
+ let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
27052
27102
  if (!wiresToSplit) {
27053
27103
  return
27054
27104
  }
@@ -27240,7 +27290,7 @@ RED.view.tools = (function() {
27240
27290
  const nodeDef = n._def || RED.nodes.getType(n.type)
27241
27291
  if (nodeDef && nodeDef.defaults && nodeDef.defaults.name) {
27242
27292
  const paletteLabel = RED.utils.getPaletteLabel(n.type, nodeDef)
27243
- const defaultNodeNameRE = new RegExp('^'+paletteLabel+' (\\d+)$')
27293
+ const defaultNodeNameRE = new RegExp('^'+paletteLabel.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')+' (\\d+)$')
27244
27294
  if (!typeIndex.hasOwnProperty(n.type)) {
27245
27295
  const existingNodes = RED.nodes.filterNodes({type: n.type})
27246
27296
  let maxNameNumber = 0;
@@ -27286,7 +27336,7 @@ RED.view.tools = (function() {
27286
27336
  }
27287
27337
 
27288
27338
  function addJunctionsToWires(wires) {
27289
- let wiresToSplit = wires || RED.view.selection().links;
27339
+ let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
27290
27340
  if (!wiresToSplit) {
27291
27341
  return
27292
27342
  }
@@ -27314,6 +27364,7 @@ RED.view.tools = (function() {
27314
27364
  linkGroups.sort(function(A,B) {
27315
27365
  return groupedLinks[B].length - groupedLinks[A].length
27316
27366
  })
27367
+ const wasDirty = RED.nodes.dirty()
27317
27368
  linkGroups.forEach(function(gid) {
27318
27369
  var links = groupedLinks[gid]
27319
27370
  var junction = {
@@ -27404,12 +27455,14 @@ RED.view.tools = (function() {
27404
27455
  })
27405
27456
  if (addedJunctions.length > 0) {
27406
27457
  RED.history.push({
27458
+ dirty: wasDirty,
27407
27459
  t: 'add',
27408
27460
  links: addedLinks,
27409
27461
  junctions: addedJunctions,
27410
27462
  removedLinks: Array.from(removedLinks)
27411
27463
  })
27412
27464
  RED.nodes.dirty(true)
27465
+ RED.view.select({nodes: addedJunctions });
27413
27466
  }
27414
27467
  RED.view.redraw(true);
27415
27468
  }
@@ -28575,7 +28628,7 @@ RED.sidebar.info = (function() {
28575
28628
 
28576
28629
  propertiesPanelContent = $("<div>").css({
28577
28630
  "flex":"1 1 auto",
28578
- "overflow-y":"scroll",
28631
+ "overflow-y":"auto",
28579
28632
  }).appendTo(propertiesPanel);
28580
28633
 
28581
28634
 
@@ -29802,7 +29855,7 @@ RED.sidebar.help = (function() {
29802
29855
 
29803
29856
  tocPanel = $("<div>", {class: "red-ui-sidebar-help-toc"}).appendTo(stackContainer);
29804
29857
  var helpPanel = $("<div>").css({
29805
- "overflow-y": "scroll"
29858
+ "overflow-y": "auto"
29806
29859
  }).appendTo(stackContainer);
29807
29860
 
29808
29861
  panels = RED.panels.create({
@@ -33316,6 +33369,10 @@ RED.editor = (function() {
33316
33369
  if (editing_node) {
33317
33370
  RED.sidebar.info.refresh(editing_node);
33318
33371
  RED.sidebar.help.show(editing_node.type, false);
33372
+ //ensure focused element is NOT body (for keyboard scope to operate correctly)
33373
+ if (document.activeElement.tagName === 'BODY') {
33374
+ $('#red-ui-editor-stack').trigger('focus')
33375
+ }
33319
33376
  }
33320
33377
  }
33321
33378
  }
@@ -34519,6 +34576,7 @@ RED.editor = (function() {
34519
34576
  RED.editor.colorPicker.create({
34520
34577
  id: "red-ui-editor-node-color",
34521
34578
  value: color,
34579
+ defaultValue: "#DDAA99",
34522
34580
  palette: recommendedColors,
34523
34581
  sortPalette: function (a, b) {return a.l - b.l;}
34524
34582
  }).appendTo(colorRow);
@@ -35789,6 +35847,9 @@ RED.editor = (function() {
35789
35847
  var focusTarget = colorInput;
35790
35848
  colorInput.on("change", function (e) {
35791
35849
  var color = colorInput.val();
35850
+ if (options.defaultValue && !color.match(/^([a-z]+|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3})$/)) {
35851
+ color = options.defaultValue;
35852
+ }
35792
35853
  colorHiddenInput.val(color).trigger('change');
35793
35854
  refreshDisplay(color);
35794
35855
  });
@@ -39046,7 +39107,7 @@ RED.editor.codeEditor.monaco = (function() {
39046
39107
 
39047
39108
 
39048
39109
  if(!options.stateId && options.stateId !== false) {
39049
- options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title).split("/").pop());
39110
+ options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title || "").split("/").pop());
39050
39111
  }
39051
39112
  var el = options.element || $("#"+options.id)[0];
39052
39113
  var toolbarRow = $("<div>").appendTo(el);
@@ -42898,7 +42959,7 @@ RED.search = (function() {
42898
42959
  }
42899
42960
  if (flags.hasOwnProperty("unused")) {
42900
42961
  var isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
42901
- (isConfigNode && node.node.users.length === 0)
42962
+ (isConfigNode && node.node.users.length === 0 && node.node._def.hasUsers !== false)
42902
42963
  if (flags.unused !== isUnused) {
42903
42964
  continue;
42904
42965
  }
@@ -43249,7 +43310,7 @@ RED.search = (function() {
43249
43310
  $(previousActiveElement).trigger("focus");
43250
43311
  }
43251
43312
  previousActiveElement = null;
43252
- }
43313
+ }
43253
43314
  if(!keepSearchToolbar) {
43254
43315
  clearActiveSearch();
43255
43316
  }
@@ -43341,7 +43402,7 @@ RED.search = (function() {
43341
43402
  $("#red-ui-sidebar-shade").on('mousedown',hide);
43342
43403
 
43343
43404
  $("#red-ui-view-searchtools-close").on("click", function close() {
43344
- clearActiveSearch();
43405
+ clearActiveSearch();
43345
43406
  updateSearchToolbar();
43346
43407
  });
43347
43408
  $("#red-ui-view-searchtools-close").trigger("click");
@@ -43375,7 +43436,7 @@ RED.search = (function() {
43375
43436
  };
43376
43437
 
43377
43438
  })();
43378
- ;RED.contextMenu = (function() {
43439
+ ;RED.contextMenu = (function () {
43379
43440
 
43380
43441
  let menu;
43381
43442
  function createMenu() {
@@ -43392,10 +43453,6 @@ RED.search = (function() {
43392
43453
  // ],
43393
43454
  // width: 200,
43394
43455
  // })
43395
-
43396
-
43397
-
43398
-
43399
43456
  }
43400
43457
 
43401
43458
  function disposeMenu() {
@@ -43411,42 +43468,80 @@ RED.search = (function() {
43411
43468
  }
43412
43469
 
43413
43470
  const selection = RED.view.selection()
43471
+ const noSelection = !selection || Object.keys(selection).length === 0
43414
43472
  const hasSelection = (selection.nodes && selection.nodes.length > 0);
43415
43473
  const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
43416
- const hasLinks = selection.links && selection.links.length > 0;
43417
- const isSingleLink = !hasSelection && hasLinks && selection.links.length === 1
43418
- const isMultipleLinks = !hasSelection && hasLinks && selection.links.length > 1
43474
+ const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
43475
+ const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
43476
+ const hasLinks = wireLinks.length > 0;
43477
+ const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
43478
+ const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
43419
43479
  const canDelete = hasSelection || hasLinks
43420
43480
  const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
43421
43481
 
43422
43482
  const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
43483
+ const offset = $("#red-ui-workspace-chart").offset()
43423
43484
 
43485
+ // addX/addY must be the position in the workspace accounting for both scroll and scale
43486
+ // The +5 is because we display the contextMenu -5,-5 to actual click position
43487
+ let addX = (options.x + 5 - offset.left + $("#red-ui-workspace-chart").scrollLeft()) / RED.view.scale()
43488
+ let addY = (options.y + 5 - offset.top + $("#red-ui-workspace-chart").scrollTop()) / RED.view.scale()
43424
43489
 
43425
43490
  const menuItems = [
43426
- { onselect: 'core:show-action-list', onpostselect: function() {} },
43491
+ { onselect: 'core:show-action-list', onpostselect: function () { } },
43427
43492
  {
43428
43493
  label: RED._("contextMenu.insert"),
43429
43494
  options: [
43430
43495
  {
43431
43496
  label: RED._("contextMenu.node"),
43432
- onselect: function() {
43497
+ onselect: function () {
43433
43498
  RED.view.showQuickAddDialog({
43434
- position: [ options.x - offset.left, options.y - offset.top ],
43499
+ position: [addX, addY],
43435
43500
  touchTrigger: true,
43436
- splice: isSingleLink?selection.links[0]:undefined,
43501
+ splice: isSingleLink ? selection.links[0] : undefined,
43437
43502
  // spliceMultiple: isMultipleLinks
43438
43503
  })
43504
+ },
43505
+ onpostselect: function() {
43506
+ // ensure quick add dialog search input has focus
43507
+ $('#red-ui-type-search-input').trigger('focus')
43439
43508
  }
43440
43509
  },
43441
- {
43510
+ (hasLinks) ? { // has least 1 wire selected
43442
43511
  label: RED._("contextMenu.junction"),
43443
43512
  onselect: 'core:split-wires-with-junctions',
43444
- disabled: hasSelection || !hasLinks
43513
+ disabled: !hasLinks
43514
+ } : {
43515
+ label: RED._("contextMenu.junction"),
43516
+ onselect: function () {
43517
+ const nn = {
43518
+ _def: { defaults: {} },
43519
+ type: 'junction',
43520
+ z: RED.workspaces.active(),
43521
+ id: RED.nodes.id(),
43522
+ x: addX,
43523
+ y: addY,
43524
+ w: 0, h: 0,
43525
+ outputs: 1,
43526
+ inputs: 1,
43527
+ dirty: true
43528
+ }
43529
+ const historyEvent = {
43530
+ dirty: RED.nodes.dirty(),
43531
+ t: 'add',
43532
+ junctions: [nn]
43533
+ }
43534
+ RED.nodes.addJunction(nn);
43535
+ RED.history.push(historyEvent);
43536
+ RED.nodes.dirty(true);
43537
+ RED.view.select({nodes: [nn] });
43538
+ RED.view.redraw(true)
43539
+ }
43445
43540
  },
43446
43541
  {
43447
43542
  label: RED._("contextMenu.linkNodes"),
43448
43543
  onselect: 'core:split-wire-with-link-nodes',
43449
- disabled: hasSelection || !hasLinks
43544
+ disabled: !hasLinks
43450
43545
  }
43451
43546
  ]
43452
43547
 
@@ -43454,28 +43549,13 @@ RED.search = (function() {
43454
43549
 
43455
43550
  }
43456
43551
  ]
43457
- // menuItems.push(
43458
- // {
43459
- // label: (isSingleLink || isMultipleLinks)?'Insert into wire...':'Add node...',
43460
- // onselect: function() {
43461
- // RED.view.showQuickAddDialog({
43462
- // position: [ options.x - offset.left, options.y - offset.top ],
43463
- // touchTrigger: true,
43464
- // splice: isSingleLink?selection.links[0]:undefined,
43465
- // spliceMultiple: isMultipleLinks
43466
- // })
43467
- // }
43468
- // },
43469
- // )
43470
- // if (hasLinks && !hasSelection) {
43471
- // menuItems.push({ onselect: 'core:split-wires-with-junctions', label: 'Insert junction'})
43472
- // }
43552
+
43473
43553
  menuItems.push(
43474
43554
  null,
43475
43555
  { onselect: 'core:undo', disabled: RED.history.list().length === 0 },
43476
43556
  { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
43477
43557
  null,
43478
- { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection},
43558
+ { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection },
43479
43559
  { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
43480
43560
  { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
43481
43561
  { onselect: 'core:delete-selection', disabled: !canDelete },
@@ -43487,27 +43567,34 @@ RED.search = (function() {
43487
43567
  menuItems.push(
43488
43568
  null,
43489
43569
  isGroup ?
43490
- { onselect: 'core:ungroup-selection', disabled: !isGroup }
43491
- : { onselect: 'core:group-selection', disabled: !hasSelection }
43570
+ { onselect: 'core:ungroup-selection', disabled: !isGroup }
43571
+ : { onselect: 'core:group-selection', disabled: !hasSelection }
43492
43572
  )
43493
43573
  if (canRemoveFromGroup) {
43494
43574
  menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
43495
43575
  }
43496
43576
 
43497
43577
  }
43498
- const offset = $("#red-ui-workspace-chart").offset()
43578
+
43579
+ var direction = "right";
43580
+ var MENU_WIDTH = 500; // can not use menu width here
43581
+ if ((options.x -$(document).scrollLeft()) >
43582
+ ($(window).width() -MENU_WIDTH)) {
43583
+ direction = "left";
43584
+ }
43585
+
43499
43586
  menu = RED.menu.init({
43500
- direction: 'right',
43587
+ direction: direction,
43501
43588
  onpreselect: function() {
43502
43589
  disposeMenu()
43503
43590
  },
43504
- onpostselect: function() {
43591
+ onpostselect: function () {
43505
43592
  RED.view.focus()
43506
43593
  },
43507
43594
  options: menuItems
43508
43595
  });
43509
43596
 
43510
- menu.attr("id","red-ui-workspace-context-menu");
43597
+ menu.attr("id", "red-ui-workspace-context-menu");
43511
43598
  menu.css({
43512
43599
  position: "absolute"
43513
43600
  })
@@ -43518,34 +43605,35 @@ RED.search = (function() {
43518
43605
  var top = options.y
43519
43606
  var left = options.x
43520
43607
 
43521
- if (top+menu.height()-$(document).scrollTop() > $(window).height()) {
43522
- top -= (top+menu.height())-$(window).height() + 22;
43608
+ if (top + menu.height() - $(document).scrollTop() > $(window).height()) {
43609
+ top -= (top + menu.height()) - $(window).height() + 22;
43523
43610
  }
43524
- if (left+menu.width()-$(document).scrollLeft() > $(window).width()) {
43525
- left -= (left+menu.width())-$(window).width() + 18;
43611
+ if (left + menu.width() - $(document).scrollLeft() > $(window).width()) {
43612
+ left -= (left + menu.width()) - $(window).width() + 18;
43526
43613
  }
43527
43614
  menu.css({
43528
- top: top+"px",
43529
- left: left+"px"
43615
+ top: top + "px",
43616
+ left: left + "px"
43530
43617
  })
43531
43618
  $(".red-ui-menu.red-ui-menu-dropdown").hide();
43532
- $(document).on("mousedown.red-ui-workspace-context-menu", function(evt) {
43619
+ $(document).on("mousedown.red-ui-workspace-context-menu", function (evt) {
43533
43620
  if (menu && menu[0].contains(evt.target)) {
43534
43621
  return
43535
43622
  }
43536
43623
  disposeMenu()
43537
43624
  });
43538
43625
  menu.show();
43539
-
43540
- // menu.show({
43541
- // target: $('#red-ui-main-container'),
43542
- // x: options.x,
43543
- // y: options.y
43544
- // })
43545
-
43626
+ // set focus to first item so that pressing escape key closes the menu
43627
+ $("#red-ui-workspace-context-menu :first(ul) > a").trigger("focus")
43546
43628
 
43547
43629
  }
43548
-
43630
+ // Allow escape key hook and other editor events to close context menu
43631
+ RED.keyboard.add("red-ui-workspace-context-menu", "escape", function () { RED.contextMenu.hide() })
43632
+ RED.events.on("editor:open", function () { RED.contextMenu.hide() });
43633
+ RED.events.on("search:open", function () { RED.contextMenu.hide() });
43634
+ RED.events.on("type-search:open", function () { RED.contextMenu.hide() });
43635
+ RED.events.on("actionList:open", function () { RED.contextMenu.hide() });
43636
+ RED.events.on("view:selection-changed", function () { RED.contextMenu.hide() });
43549
43637
  return {
43550
43638
  show: show,
43551
43639
  hide: disposeMenu
@@ -44054,8 +44142,8 @@ RED.actionList = (function() {
44054
44142
  moveCallback = opts.move;
44055
44143
  RED.events.emit("type-search:open");
44056
44144
  //shade.show();
44057
- if ($("#red-ui-main-container").height() - opts.y - 150 < 0) {
44058
- opts.y = opts.y - 235;
44145
+ if ($("#red-ui-main-container").height() - opts.y - 195 < 0) {
44146
+ opts.y = opts.y - 275;
44059
44147
  }
44060
44148
  dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
44061
44149
  searchResultsDiv.slideDown(300);
@@ -44713,6 +44801,13 @@ RED.subflow = (function() {
44713
44801
  RED.nodes.groups(id).forEach(function(n) {
44714
44802
  removedGroups.push(n);
44715
44803
  })
44804
+
44805
+ var removedJunctions = RED.nodes.junctions(id)
44806
+ for (var i=0;i<removedJunctions.length;i++) {
44807
+ var removedEntities = RED.nodes.removeJunction(removedJunctions[i])
44808
+ removedLinks = removedLinks.concat(removedEntities.links)
44809
+ }
44810
+
44716
44811
  var removedConfigNodes = [];
44717
44812
  for (var i=0;i<removedNodes.length;i++) {
44718
44813
  var removedEntities = RED.nodes.remove(removedNodes[i].id);
@@ -44743,6 +44838,7 @@ RED.subflow = (function() {
44743
44838
  nodes:removedNodes,
44744
44839
  links:removedLinks,
44745
44840
  groups: removedGroups,
44841
+ junctions: removedJunctions,
44746
44842
  subflows: [activeSubflow]
44747
44843
  }
44748
44844
  }
@@ -45084,6 +45180,7 @@ RED.subflow = (function() {
45084
45180
  RED.nodes.dirty(true);
45085
45181
  RED.view.updateActive();
45086
45182
  RED.view.select(null);
45183
+ RED.view.focus();
45087
45184
  }
45088
45185
 
45089
45186
 
@@ -45198,6 +45295,17 @@ RED.subflow = (function() {
45198
45295
  default: inputType
45199
45296
  })
45200
45297
  input.typedInput('value',val.value)
45298
+ if (inputType === 'cred') {
45299
+ if (node.credentials) {
45300
+ if (node.credentials[tenv.name]) {
45301
+ input.typedInput('value', node.credentials[tenv.name]);
45302
+ } else if (node.credentials['has_'+tenv.name]) {
45303
+ input.typedInput('value', "__PWRD__")
45304
+ } else {
45305
+ input.typedInput('value', "");
45306
+ }
45307
+ }
45308
+ }
45201
45309
  } else {
45202
45310
  input.val(val.value)
45203
45311
  }
@@ -45632,6 +45740,7 @@ RED.group = (function() {
45632
45740
  RED.editor.colorPicker.create({
45633
45741
  id:"node-input-style-stroke",
45634
45742
  value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
45743
+ defaultValue: "#a4a4a4",
45635
45744
  palette: colorPalette,
45636
45745
  cellPerRow: colorCount,
45637
45746
  cellWidth: 16,
@@ -45643,6 +45752,7 @@ RED.group = (function() {
45643
45752
  RED.editor.colorPicker.create({
45644
45753
  id:"node-input-style-fill",
45645
45754
  value: style.fill || defaultGroupStyle.fill ||"none",
45755
+ defaultValue: "none",
45646
45756
  palette: colorPalette,
45647
45757
  cellPerRow: colorCount,
45648
45758
  cellWidth: 16,
@@ -45660,6 +45770,7 @@ RED.group = (function() {
45660
45770
  RED.editor.colorPicker.create({
45661
45771
  id:"node-input-style-color",
45662
45772
  value: style.color || defaultGroupStyle.color ||"#a4a4a4",
45773
+ defaultValue: "#a4a4a4",
45663
45774
  palette: colorPalette,
45664
45775
  cellPerRow: colorCount,
45665
45776
  cellWidth: 16,
@@ -45839,6 +45950,7 @@ RED.group = (function() {
45839
45950
  RED.history.push(historyEvent);
45840
45951
  RED.view.select({nodes:[group]});
45841
45952
  RED.nodes.dirty(true);
45953
+ RED.view.focus();
45842
45954
  }
45843
45955
  }
45844
45956
  }
@@ -45861,6 +45973,7 @@ RED.group = (function() {
45861
45973
  RED.history.push(historyEvent);
45862
45974
  RED.view.select({nodes:newSelection})
45863
45975
  RED.nodes.dirty(true);
45976
+ RED.view.focus();
45864
45977
  }
45865
45978
  }
45866
45979
 
@@ -45955,6 +46068,7 @@ RED.group = (function() {
45955
46068
  });
45956
46069
  RED.history.push(historyEvent);
45957
46070
  RED.nodes.dirty(true);
46071
+ RED.view.focus();
45958
46072
  }
45959
46073
  }
45960
46074
 
@@ -45982,6 +46096,7 @@ RED.group = (function() {
45982
46096
  }
45983
46097
  }
45984
46098
  RED.view.select({nodes:selection.nodes})
46099
+ RED.view.focus();
45985
46100
  }
45986
46101
  }
45987
46102
  function createGroup(nodes) {
@@ -53127,17 +53242,17 @@ RED.touch.radialMenu = (function() {
53127
53242
  return [
53128
53243
  {
53129
53244
  id: "3_0",
53130
- label: "3.0.0-beta.4",
53245
+ label: "3.0",
53131
53246
  path: "./tours/welcome.js"
53132
53247
  },
53133
53248
  {
53134
53249
  id: "2_2",
53135
- label: "2.2.0",
53250
+ label: "2.2",
53136
53251
  path: "./tours/2.2/welcome.js"
53137
53252
  },
53138
53253
  {
53139
53254
  id: "2_1",
53140
- label: "2.1.0",
53255
+ label: "2.1",
53141
53256
  path: "./tours/2.1/welcome.js"
53142
53257
  }
53143
53258
  ];