@node-red/editor-client 2.1.1 → 2.1.5

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
@@ -566,31 +566,33 @@ var RED = (function() {
566
566
  var typeList;
567
567
  var info;
568
568
  if (topic == "notification/node/added") {
569
- var addedTypes = [];
570
- msg.forEach(function(m) {
571
- var id = m.id;
572
- RED.nodes.addNodeSet(m);
573
- addedTypes = addedTypes.concat(m.types);
574
- RED.i18n.loadNodeCatalog(id, function() {
575
- var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
576
- $.ajax({
577
- headers: {
578
- "Accept":"text/html",
579
- "Accept-Language": lang
580
- },
581
- cache: false,
582
- url: 'nodes/'+id,
583
- success: function(data) {
584
- appendNodeConfig(data);
585
- }
569
+ RED.settings.refreshSettings(function(err, data) {
570
+ var addedTypes = [];
571
+ msg.forEach(function(m) {
572
+ var id = m.id;
573
+ RED.nodes.addNodeSet(m);
574
+ addedTypes = addedTypes.concat(m.types);
575
+ RED.i18n.loadNodeCatalog(id, function() {
576
+ var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
577
+ $.ajax({
578
+ headers: {
579
+ "Accept":"text/html",
580
+ "Accept-Language": lang
581
+ },
582
+ cache: false,
583
+ url: 'nodes/'+id,
584
+ success: function(data) {
585
+ appendNodeConfig(data);
586
+ }
587
+ });
586
588
  });
587
589
  });
588
- });
589
- if (addedTypes.length) {
590
- typeList = "<ul><li>"+addedTypes.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
591
- RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
592
- }
593
- loadIconList();
590
+ if (addedTypes.length) {
591
+ typeList = "<ul><li>"+addedTypes.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
592
+ RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
593
+ }
594
+ loadIconList();
595
+ })
594
596
  } else if (topic == "notification/node/removed") {
595
597
  for (i=0;i<msg.length;i++) {
596
598
  m = msg[i];
@@ -603,27 +605,29 @@ var RED = (function() {
603
605
  loadIconList();
604
606
  } else if (topic == "notification/node/enabled") {
605
607
  if (msg.types) {
606
- info = RED.nodes.getNodeSet(msg.id);
607
- if (info.added) {
608
- RED.nodes.enableNodeSet(msg.id);
609
- typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
610
- RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
611
- } else {
612
- var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
613
- $.ajax({
614
- headers: {
615
- "Accept":"text/html",
616
- "Accept-Language": lang
617
- },
618
- cache: false,
619
- url: 'nodes/'+msg.id,
620
- success: function(data) {
621
- appendNodeConfig(data);
622
- typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
623
- RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
624
- }
625
- });
626
- }
608
+ RED.settings.refreshSettings(function(err, data) {
609
+ info = RED.nodes.getNodeSet(msg.id);
610
+ if (info.added) {
611
+ RED.nodes.enableNodeSet(msg.id);
612
+ typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
613
+ RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
614
+ } else {
615
+ var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
616
+ $.ajax({
617
+ headers: {
618
+ "Accept":"text/html",
619
+ "Accept-Language": lang
620
+ },
621
+ cache: false,
622
+ url: 'nodes/'+msg.id,
623
+ success: function(data) {
624
+ appendNodeConfig(data);
625
+ typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
626
+ RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
627
+ }
628
+ });
629
+ }
630
+ });
627
631
  }
628
632
  } else if (topic == "notification/node/disabled") {
629
633
  if (msg.types) {
@@ -677,7 +681,7 @@ var RED = (function() {
677
681
  {id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"}
678
682
  ]});
679
683
  }
680
- menuOptions.push({id:"menu-item-edit-menu", label:"Edit", options: [
684
+ menuOptions.push({id:"menu-item-edit-menu", label:RED._("menu.label.edit"), options: [
681
685
  {id: "menu-item-edit-undo", label:RED._("keyboard.undoChange"), disabled: true, onselect: "core:undo"},
682
686
  {id: "menu-item-edit-redo", label:RED._("keyboard.redoChange"), disabled: true, onselect: "core:redo"},
683
687
  null,
@@ -1168,6 +1172,8 @@ RED.i18n = (function() {
1168
1172
  defaultNS: "editor",
1169
1173
  fallbackLng: ['en-US'],
1170
1174
  returnObjects: true,
1175
+ keySeparator: ".",
1176
+ nsSeparator: ":",
1171
1177
  interpolation: {
1172
1178
  unescapeSuffix: 'HTML',
1173
1179
  escapeValue: false,
@@ -1408,7 +1414,7 @@ RED.settings = (function () {
1408
1414
  load(done);
1409
1415
  }
1410
1416
 
1411
- var load = function(done) {
1417
+ var refreshSettings = function(done) {
1412
1418
  $.ajax({
1413
1419
  headers: {
1414
1420
  "Accept": "application/json"
@@ -1418,6 +1424,23 @@ RED.settings = (function () {
1418
1424
  url: 'settings',
1419
1425
  success: function (data) {
1420
1426
  setProperties(data);
1427
+ done(null, data);
1428
+ },
1429
+ error: function(jqXHR,textStatus,errorThrown) {
1430
+ if (jqXHR.status === 401) {
1431
+ if (/[?&]access_token=(.*?)(?:$|&)/.test(window.location.search)) {
1432
+ window.location.search = "";
1433
+ }
1434
+ RED.user.login(function() { refreshSettings(done); });
1435
+ } else {
1436
+ console.log("Unexpected error loading settings:",jqXHR.status,textStatus);
1437
+ }
1438
+ }
1439
+ });
1440
+ }
1441
+ var load = function(done) {
1442
+ refreshSettings(function(err, data) {
1443
+ if (!err) {
1421
1444
  if (!RED.settings.user || RED.settings.user.anonymous) {
1422
1445
  RED.settings.remove("auth-tokens");
1423
1446
  }
@@ -1430,18 +1453,8 @@ RED.settings = (function () {
1430
1453
  console.log("D3",d3.version);
1431
1454
  console.groupEnd();
1432
1455
  loadUserSettings(done);
1433
- },
1434
- error: function(jqXHR,textStatus,errorThrown) {
1435
- if (jqXHR.status === 401) {
1436
- if (/[?&]access_token=(.*?)(?:$|&)/.test(window.location.search)) {
1437
- window.location.search = "";
1438
- }
1439
- RED.user.login(function() { load(done); });
1440
- } else {
1441
- console.log("Unexpected error loading settings:",jqXHR.status,textStatus);
1442
- }
1443
1456
  }
1444
- });
1457
+ })
1445
1458
  };
1446
1459
 
1447
1460
  function loadUserSettings(done) {
@@ -1517,6 +1530,7 @@ RED.settings = (function () {
1517
1530
  init: init,
1518
1531
  load: load,
1519
1532
  loadUserSettings: loadUserSettings,
1533
+ refreshSettings: refreshSettings,
1520
1534
  set: set,
1521
1535
  get: get,
1522
1536
  remove: remove,
@@ -4380,7 +4394,6 @@ RED.nodes = (function() {
4380
4394
  var removedGroups = [];
4381
4395
  if (ws) {
4382
4396
  delete workspaces[id];
4383
- allNodes.removeTab(id);
4384
4397
  delete linkTabMap[id];
4385
4398
  workspacesOrder.splice(workspacesOrder.indexOf(id),1);
4386
4399
  var i;
@@ -4418,6 +4431,7 @@ RED.nodes = (function() {
4418
4431
  for (i=removedGroups.length-1; i>=0; i--) {
4419
4432
  removeGroup(removedGroups[i]);
4420
4433
  }
4434
+ allNodes.removeTab(id);
4421
4435
  RED.events.emit('flows:remove',ws);
4422
4436
  }
4423
4437
  return {nodes:removedNodes,links:removedLinks, groups: removedGroups};
@@ -4672,6 +4686,11 @@ RED.nodes = (function() {
4672
4686
  // Until we know how that can happen, add a filter here to remove them
4673
4687
  node.nodes = node.nodes.filter(function(n) { return !!n }).map(function(n) { return n.id });
4674
4688
  }
4689
+ if (n.type === "tab" || n.type === "group") {
4690
+ if (node.env && node.env.length === 0) {
4691
+ delete node.env;
4692
+ }
4693
+ }
4675
4694
  if (n._def.category != "config") {
4676
4695
  node.x = n.x;
4677
4696
  node.y = n.y;
@@ -7799,7 +7818,7 @@ RED.utils = (function() {
7799
7818
  level: 'block', // Is this a block-level or inline-level tokenizer?
7800
7819
  start(src) {
7801
7820
  if (!src) { return null; }
7802
- let m = src.match(/:[^:\n]/);
7821
+ let m = src.match(/:[^:\n]/g);
7803
7822
  return m && m.index; // Hint to Marked.js to stop and check for a match
7804
7823
  },
7805
7824
  tokenizer(src, tokens) {
@@ -7825,7 +7844,7 @@ RED.utils = (function() {
7825
7844
  level: 'inline', // Is this a block-level or inline-level tokenizer?
7826
7845
  start(src) {
7827
7846
  if (!src) { return null; }
7828
- let m = src.match(/:/);
7847
+ let m = src.match(/:/g);
7829
7848
  return m && m.index; // Hint to Marked.js to stop and check for a match
7830
7849
  },
7831
7850
  tokenizer(src, tokens) {
@@ -7914,6 +7933,8 @@ RED.utils = (function() {
7914
7933
  result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-meta"></span>').text('function');
7915
7934
  } else if (value.hasOwnProperty('type') && (value.type === 'number' || value.type === 'bigint')) {
7916
7935
  result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-number"></span>').text(value.data);
7936
+ } else if (value.hasOwnProperty('type') && value.type === 'regexp') {
7937
+ result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-string"></span>').text(value.data);
7917
7938
  } else {
7918
7939
  result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-meta">object</span>');
7919
7940
  }
@@ -8212,6 +8233,8 @@ RED.utils = (function() {
8212
8233
  $('<span class="red-ui-debug-msg-type-null">undefined</span>').appendTo(entryObj);
8213
8234
  } else if (obj.__enc__ && (obj.type === 'number' || obj.type === 'bigint')) {
8214
8235
  e = $('<span class="red-ui-debug-msg-type-number red-ui-debug-msg-object-header"></span>').text(obj.data).appendTo(entryObj);
8236
+ } else if (typeHint === "regexp" || (obj.__enc__ && obj.type === 'regexp')) {
8237
+ e = $('<span class="red-ui-debug-msg-type-string red-ui-debug-msg-object-header"></span>').text((typeof obj === "string")?obj:obj.data).appendTo(entryObj);
8215
8238
  } else if (typeHint === "function" || (obj.__enc__ && obj.type === 'function')) {
8216
8239
  e = $('<span class="red-ui-debug-msg-type-meta red-ui-debug-msg-object-header"></span>').text("function").appendTo(entryObj);
8217
8240
  } else if (typeHint === "internal" || (obj.__enc__ && obj.type === 'internal')) {
@@ -9925,7 +9948,7 @@ RED.utils = (function() {
9925
9948
  if (child.depth !== parent.depth+1) {
9926
9949
  child.depth = parent.depth+1;
9927
9950
  // var labelPaddingWidth = ((child.gutter ? child.gutter[0].offsetWidth + 2 : 0) + (child.depth * 20));
9928
- var labelPaddingWidth = ((child.gutter?child.gutter.width()+2:0)+(child.depth*20));
9951
+ var labelPaddingWidth = (((child.gutter&&!child.gutter.hasClass("red-ui-treeList-gutter-float"))?child.gutter.width()+2:0)+(child.depth*20));
9929
9952
  child.treeList.labelPadding.width(labelPaddingWidth+'px');
9930
9953
  if (child.element) {
9931
9954
  $(child.element).css({
@@ -10147,8 +10170,9 @@ RED.utils = (function() {
10147
10170
  }).appendTo(label)
10148
10171
 
10149
10172
  }
10150
- // var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20);
10151
- var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20)
10173
+
10174
+ var labelPaddingWidth = ((item.gutter&&!item.gutter.hasClass("red-ui-treeList-gutter-float"))?item.gutter.width()+2:0)+(depth*20);
10175
+
10152
10176
  item.treeList.labelPadding = $('<span>').css({
10153
10177
  display: "inline-block",
10154
10178
  "flex-shrink": 0,
@@ -12072,6 +12096,8 @@ RED.tabs = (function() {
12072
12096
  menuOptions = options.menu()
12073
12097
  } else if (Array.isArray(options.menu)) {
12074
12098
  menuOptions = options.menu;
12099
+ } else if (typeof options.menu === 'function') {
12100
+ menuOptions = options.menu();
12075
12101
  }
12076
12102
  menu = RED.menu.init({options: menuOptions});
12077
12103
  menu.attr("id",options.id+"-menu");
@@ -12531,7 +12557,7 @@ RED.tabs = (function() {
12531
12557
 
12532
12558
  function findPreviousVisibleTab(li) {
12533
12559
  if (!li) {
12534
- li = ul.find("li.active").parent();
12560
+ li = ul.find("li.active");
12535
12561
  }
12536
12562
  var previous = li.prev();
12537
12563
  while(previous.length > 0 && previous.hasClass("hide-tab")) {
@@ -12541,9 +12567,9 @@ RED.tabs = (function() {
12541
12567
  }
12542
12568
  function findNextVisibleTab(li) {
12543
12569
  if (!li) {
12544
- li = ul.find("li.active").parent();
12570
+ li = ul.find("li.active");
12545
12571
  }
12546
- var next = ul.find("li.active").next();
12572
+ var next = li.next();
12547
12573
  while(next.length > 0 && next.hasClass("hide-tab")) {
12548
12574
  next = next.next();
12549
12575
  }
@@ -12764,15 +12790,18 @@ RED.tabs = (function() {
12764
12790
  event.preventDefault();
12765
12791
  removeTab(tab.id);
12766
12792
  });
12793
+ RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
12767
12794
  }
12768
12795
  if (tab.hideable) {
12769
12796
  li.addClass("red-ui-tabs-closeable")
12770
- var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
12771
- closeLink.append('<i class="fa fa-times" />');
12797
+ var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
12798
+ closeLink.append('<i class="fa fa-eye" />');
12799
+ closeLink.append('<i class="fa fa-eye-slash" />');
12772
12800
  closeLink.on("click",function(event) {
12773
12801
  event.preventDefault();
12774
12802
  hideTab(tab.id);
12775
12803
  });
12804
+ RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
12776
12805
  }
12777
12806
 
12778
12807
  var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li);
@@ -12781,7 +12810,8 @@ RED.tabs = (function() {
12781
12810
  $('<i class="red-ui-tabs-badge-selected fa fa-check-circle"></i>').appendTo(badges);
12782
12811
  }
12783
12812
 
12784
- link.attr("title",tab.label);
12813
+ // link.attr("title",tab.label);
12814
+ RED.popover.tooltip(link,function() { return tab.label})
12785
12815
 
12786
12816
  if (options.onadd) {
12787
12817
  options.onadd(tab);
@@ -12900,7 +12930,6 @@ RED.tabs = (function() {
12900
12930
  renameTab: function(id,label) {
12901
12931
  tabs[id].label = label;
12902
12932
  var tab = ul.find("a[href='#"+id+"']");
12903
- tab.attr("title",label);
12904
12933
  tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label));
12905
12934
  updateTabWidths();
12906
12935
  },
@@ -13567,7 +13596,8 @@ RED.stack = (function() {
13567
13596
  }
13568
13597
  nlsd = true;
13569
13598
  var that = this;
13570
-
13599
+ this.identifier = this.element.attr('id') || "TypedInput-"+Math.floor(Math.random()*100);
13600
+ if (this.options.debug) { console.log(this.identifier,"Create",{defaultType:this.options.default, value:this.element.val()}) }
13571
13601
  this.disarmClick = false;
13572
13602
  this.input = $('<input class="red-ui-typedInput-input" type="text"></input>');
13573
13603
  this.input.insertAfter(this.element);
@@ -13681,9 +13711,9 @@ RED.stack = (function() {
13681
13711
  // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
13682
13712
  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);
13683
13713
  this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
13684
- RED.popover.tooltip(this.optionSelectLabel,function() {
13685
- return that.optionValue;
13686
- });
13714
+ // RED.popover.tooltip(this.optionSelectLabel,function() {
13715
+ // return that.optionValue;
13716
+ // });
13687
13717
  this.optionSelectTrigger.on("click", function(event) {
13688
13718
  event.preventDefault();
13689
13719
  event.stopPropagation();
@@ -13703,7 +13733,8 @@ RED.stack = (function() {
13703
13733
  this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
13704
13734
  this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
13705
13735
 
13706
- this.type(this.options.default||this.typeList[0].value);
13736
+ this.type(this.typeField.val() || this.options.default||this.typeList[0].value);
13737
+ this.typeChanged = !!this.options.default;
13707
13738
  }catch(err) {
13708
13739
  console.log(err.stack);
13709
13740
  }
@@ -13951,6 +13982,7 @@ RED.stack = (function() {
13951
13982
  var that = this;
13952
13983
  var currentType = this.type();
13953
13984
  this.typeMap = {};
13985
+ var firstCall = (this.typeList === undefined);
13954
13986
  this.typeList = types.map(function(opt) {
13955
13987
  var result;
13956
13988
  if (typeof opt === 'string') {
@@ -13975,10 +14007,14 @@ RED.stack = (function() {
13975
14007
  }
13976
14008
  this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) });
13977
14009
  if (currentType && !this.typeMap.hasOwnProperty(currentType)) {
13978
- this.type(this.typeList[0].value);
14010
+ if (!firstCall) {
14011
+ this.type(this.typeList[0].value);
14012
+ }
13979
14013
  } else {
13980
14014
  this.propertyType = null;
13981
- this.type(currentType);
14015
+ if (!firstCall) {
14016
+ this.type(currentType);
14017
+ }
13982
14018
  }
13983
14019
  if (this.typeList.length === 1 && !this.typeList[0].icon && (!this.typeList[0].label || this.typeList[0].showLabel === false)) {
13984
14020
  this.selectTrigger.hide()
@@ -14005,27 +14041,38 @@ RED.stack = (function() {
14005
14041
  }
14006
14042
  return v;
14007
14043
  } else {
14044
+ if (this.options.debug) { console.log(this.identifier,"----- SET VALUE ------",value) }
14008
14045
  var selectedOption = [];
14046
+ var valueToCheck = value;
14009
14047
  if (opt.options) {
14010
- var checkValues = [value];
14048
+ if (opt.hasValue && opt.parse) {
14049
+ var parts = opt.parse(value);
14050
+ if (this.options.debug) { console.log(this.identifier,"new parse",parts) }
14051
+ value = parts.value;
14052
+ valueToCheck = parts.option || parts.value;
14053
+ }
14054
+
14055
+ var checkValues = [valueToCheck];
14011
14056
  if (opt.multiple) {
14012
14057
  selectedOption = [];
14013
- checkValues = value.split(",");
14058
+ checkValues = valueToCheck.split(",");
14014
14059
  }
14015
- checkValues.forEach(function(value) {
14060
+ checkValues.forEach(function(valueToCheck) {
14016
14061
  for (var i=0;i<opt.options.length;i++) {
14017
14062
  var op = opt.options[i];
14018
14063
  if (typeof op === "string") {
14019
- if (op === value || op === ""+value) {
14064
+ if (op === valueToCheck || op === ""+valueToCheck) {
14020
14065
  selectedOption.push(that.activeOptions[op]);
14021
14066
  break;
14022
14067
  }
14023
- } else if (op.value === value) {
14068
+ } else if (op.value === valueToCheck) {
14024
14069
  selectedOption.push(op);
14025
14070
  break;
14026
14071
  }
14027
14072
  }
14028
14073
  })
14074
+ if (this.options.debug) { console.log(this.identifier,"set value to",value) }
14075
+
14029
14076
  this.input.val(value);
14030
14077
  if (!opt.multiple) {
14031
14078
  if (selectedOption.length === 0) {
@@ -14050,15 +14097,16 @@ RED.stack = (function() {
14050
14097
  return this.propertyType;
14051
14098
  } else {
14052
14099
  var that = this;
14100
+ if (this.options.debug) { console.log(this.identifier,"----- SET TYPE -----",type) }
14053
14101
  var previousValue = null;
14054
14102
  var opt = this.typeMap[type];
14055
14103
  if (opt && this.propertyType !== type) {
14056
14104
  // If previousType is !null, then this is a change of the type, rather than the initialisation
14057
14105
  var previousType = this.typeMap[this.propertyType];
14058
- var typeChanged = !!previousType;
14059
14106
  previousValue = this.input.val();
14060
14107
 
14061
- if (typeChanged) {
14108
+ if (previousType && this.typeChanged) {
14109
+ if (this.options.debug) { console.log(this.identifier,"typeChanged",{previousType,previousValue}) }
14062
14110
  if (previousType.options && opt.hasValue !== true) {
14063
14111
  this.oldValues[previousType.value] = previousValue;
14064
14112
  } else if (previousType.hasValue === false) {
@@ -14068,6 +14116,7 @@ RED.stack = (function() {
14068
14116
  }
14069
14117
  if ((opt.options && opt.hasValue !== true) || opt.hasValue === false) {
14070
14118
  if (this.oldValues.hasOwnProperty(opt.value)) {
14119
+ if (this.options.debug) { console.log(this.identifier,"restored previous (1)",this.oldValues[opt.value]) }
14071
14120
  this.input.val(this.oldValues[opt.value]);
14072
14121
  } else if (opt.options) {
14073
14122
  // No old value for the option type.
@@ -14076,21 +14125,28 @@ RED.stack = (function() {
14076
14125
  // nodes did before 2.1.
14077
14126
  // So we need to be careful to not reset the value if it is a valid option.
14078
14127
  var validOptions = isOptionValueValid(opt,previousValue);
14079
- if (previousValue && validOptions) {
14128
+ if (this.options.debug) { console.log(this.identifier,{previousValue,opt,validOptions}) }
14129
+ if ((previousValue || previousValue === '') && validOptions) {
14130
+ if (this.options.debug) { console.log(this.identifier,"restored previous (2)") }
14080
14131
  this.input.val(previousValue);
14081
14132
  } else {
14082
14133
  if (typeof opt.default === "string") {
14134
+ if (this.options.debug) { console.log(this.identifier,"restored previous (3)",opt.default) }
14083
14135
  this.input.val(opt.default);
14084
14136
  } else if (Array.isArray(opt.default)) {
14137
+ if (this.options.debug) { console.log(this.identifier,"restored previous (4)",opt.default.join(",")) }
14085
14138
  this.input.val(opt.default.join(","))
14086
14139
  } else {
14140
+ if (this.options.debug) { console.log(this.identifier,"restored previous (5)") }
14087
14141
  this.input.val("");
14088
14142
  }
14089
14143
  }
14090
14144
  } else {
14145
+ if (this.options.debug) { console.log(this.identifier,"restored default/blank",opt.default||"") }
14091
14146
  this.input.val(opt.default||"")
14092
14147
  }
14093
14148
  } else {
14149
+ if (this.options.debug) { console.log(this.identifier,"restored old/default/blank") }
14094
14150
  this.input.val(this.oldValues.hasOwnProperty("_")?this.oldValues["_"]:(opt.default||""))
14095
14151
  }
14096
14152
  if (previousType.autoComplete) {
@@ -14098,6 +14154,7 @@ RED.stack = (function() {
14098
14154
  }
14099
14155
  }
14100
14156
  this.propertyType = type;
14157
+ this.typeChanged = true;
14101
14158
  if (this.typeField) {
14102
14159
  this.typeField.val(type);
14103
14160
  }
@@ -14193,7 +14250,8 @@ RED.stack = (function() {
14193
14250
  } else {
14194
14251
  var selectedOption = this.optionValue||opt.options[0];
14195
14252
  if (opt.parse) {
14196
- var parts = opt.parse(this.input.val(),selectedOption);
14253
+ var selectedOptionObj = typeof selectedOption === "string"?{value:selectedOption}:selectedOption
14254
+ var parts = opt.parse(this.input.val(),selectedOptionObj);
14197
14255
  if (parts.option) {
14198
14256
  selectedOption = parts.option;
14199
14257
  if (!this.activeOptions.hasOwnProperty(selectedOption)) {
@@ -14217,6 +14275,7 @@ RED.stack = (function() {
14217
14275
  this._updateOptionSelectLabel(this.activeOptions[selectedOption]);
14218
14276
  }
14219
14277
  } else if (selectedOption) {
14278
+ if (this.options.debug) { console.log(this.identifier,"HERE",{optionValue:selectedOption.value}) }
14220
14279
  this.optionValue = selectedOption.value;
14221
14280
  this._updateOptionSelectLabel(selectedOption);
14222
14281
  } else {
@@ -14507,7 +14566,7 @@ RED.stack = (function() {
14507
14566
  * value: String : the value to insert if selected
14508
14567
  * label: String|DOM Element : the label to display in the dropdown.
14509
14568
  * }
14510
- *
14569
+ *
14511
14570
  */
14512
14571
 
14513
14572
  $.widget( "nodered.autoComplete", {
@@ -14548,7 +14607,7 @@ RED.stack = (function() {
14548
14607
  maxHeight: 200,
14549
14608
  class: "red-ui-autoComplete-container",
14550
14609
  options: completions,
14551
- onselect: (opt) => { this.element.val(opt.value); this.element.focus() },
14610
+ onselect: (opt) => { this.element.val(opt.value); this.element.focus(); this.element.trigger("change") },
14552
14611
  onclose: () => { this.completionMenuShown = false; delete this.menu; this.element.focus()}
14553
14612
  });
14554
14613
  this.menu.show({
@@ -15725,6 +15784,8 @@ RED.deploy = (function() {
15725
15784
  color: "#DDAA99",
15726
15785
  defaults:{name:{value:""}}
15727
15786
  }
15787
+ } else if (node.type === "group") {
15788
+ def = RED.group.def;
15728
15789
  } else {
15729
15790
  def = {};
15730
15791
  }
@@ -15934,16 +15995,15 @@ RED.deploy = (function() {
15934
15995
  }
15935
15996
  }
15936
15997
 
15937
-
15938
15998
  if (node.hasOwnProperty('x')) {
15939
15999
  if (localNode) {
15940
- if (localNode.x !== node.x || localNode.y !== node.y) {
16000
+ if (localNode.x !== node.x || localNode.y !== node.y || localNode.w !== node.w || localNode.h !== node.h ) {
15941
16001
  localChanged = true;
15942
16002
  localChanges++;
15943
16003
  }
15944
16004
  }
15945
16005
  if (remoteNode) {
15946
- if (remoteNode.x !== node.x || remoteNode.y !== node.y) {
16006
+ if (remoteNode.x !== node.x || remoteNode.y !== node.y|| remoteNode.w !== node.w || remoteNode.h !== node.h) {
15947
16007
  remoteChanged = true;
15948
16008
  remoteChanges++;
15949
16009
  }
@@ -15961,7 +16021,12 @@ RED.deploy = (function() {
15961
16021
  localCell.addClass("red-ui-diff-status-"+(localChanged?"changed":"unchanged"));
15962
16022
  $('<span class="red-ui-diff-status">'+(localChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(localCell);
15963
16023
  element = $('<span class="red-ui-diff-list-element"></span>').appendTo(localCell);
15964
- propertyElements['local.position'] = RED.utils.createObjectElement({x:localNode.x,y:localNode.y},
16024
+ var localPosition = {x:localNode.x,y:localNode.y};
16025
+ if (localNode.hasOwnProperty('w')) {
16026
+ localPosition.w = localNode.w;
16027
+ localPosition.h = localNode.h;
16028
+ }
16029
+ propertyElements['local.position'] = RED.utils.createObjectElement(localPosition,
15965
16030
  {
15966
16031
  path: "position",
15967
16032
  exposeApi: true,
@@ -15982,7 +16047,12 @@ RED.deploy = (function() {
15982
16047
  if (remoteNode) {
15983
16048
  $('<span class="red-ui-diff-status">'+(remoteChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(remoteCell);
15984
16049
  element = $('<span class="red-ui-diff-list-element"></span>').appendTo(remoteCell);
15985
- propertyElements['remote.position'] = RED.utils.createObjectElement({x:remoteNode.x,y:remoteNode.y},
16050
+ var remotePosition = {x:remoteNode.x,y:remoteNode.y};
16051
+ if (remoteNode.hasOwnProperty('w')) {
16052
+ remotePosition.w = remoteNode.w;
16053
+ remotePosition.h = remoteNode.h;
16054
+ }
16055
+ propertyElements['remote.position'] = RED.utils.createObjectElement(remotePosition,
15986
16056
  {
15987
16057
  path: "position",
15988
16058
  exposeApi: true,
@@ -16054,11 +16124,11 @@ RED.deploy = (function() {
16054
16124
  }
16055
16125
  }
16056
16126
  }
16057
- var properties = Object.keys(node).filter(function(p) { return p!='inputLabels'&&p!='outputLabels'&&p!='z'&&p!='wires'&&p!=='x'&&p!=='y'&&p!=='id'&&p!=='type'&&(!def.defaults||!def.defaults.hasOwnProperty(p))});
16127
+ var properties = Object.keys(node).filter(function(p) { return p!='inputLabels'&&p!='outputLabels'&&p!='z'&&p!='wires'&&p!=='x'&&p!=='y'&&p!=='w'&&p!=='h'&&p!=='id'&&p!=='type'&&(!def.defaults||!def.defaults.hasOwnProperty(p))});
16058
16128
  if (def.defaults) {
16059
16129
  properties = properties.concat(Object.keys(def.defaults));
16060
16130
  }
16061
- if (node.type !== 'tab') {
16131
+ if (node.type !== 'tab' && node.type !== "group") {
16062
16132
  properties = properties.concat(['inputLabels','outputLabels']);
16063
16133
  }
16064
16134
  if ( ((localNode && localNode.hasOwnProperty('icon')) || (remoteNode && remoteNode.hasOwnProperty('icon'))) &&
@@ -18159,7 +18229,7 @@ RED.workspaces = (function() {
18159
18229
  var tabId = RED.nodes.id();
18160
18230
  do {
18161
18231
  workspaceIndex += 1;
18162
- } while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
18232
+ } while ($("#red-ui-workspace-tabs li[flowname='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
18163
18233
 
18164
18234
  ws = {
18165
18235
  type: "tab",
@@ -18172,12 +18242,15 @@ RED.workspaces = (function() {
18172
18242
  };
18173
18243
  RED.nodes.addWorkspace(ws,targetIndex);
18174
18244
  workspace_tabs.addTab(ws,targetIndex);
18245
+
18175
18246
  workspace_tabs.activateTab(tabId);
18176
18247
  if (!skipHistoryEntry) {
18177
18248
  RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
18178
18249
  RED.nodes.dirty(true);
18179
18250
  }
18180
18251
  }
18252
+ $("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
18253
+
18181
18254
  RED.view.focus();
18182
18255
  return ws;
18183
18256
  }
@@ -18301,65 +18374,84 @@ RED.workspaces = (function() {
18301
18374
  },
18302
18375
  onhide: function(tab) {
18303
18376
  hideStack.push(tab.id);
18377
+
18378
+ var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
18379
+ hiddenTabs[tab.id] = true;
18380
+ RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
18381
+
18304
18382
  RED.events.emit("workspace:hide",{workspace: tab.id})
18305
18383
  },
18306
18384
  onshow: function(tab) {
18307
18385
  removeFromHideStack(tab.id);
18386
+
18387
+ var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
18388
+ delete hiddenTabs[tab.id];
18389
+ RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
18390
+
18308
18391
  RED.events.emit("workspace:show",{workspace: tab.id})
18309
18392
  },
18310
18393
  minimumActiveTabWidth: 150,
18311
18394
  scrollable: true,
18312
18395
  addButton: "core:add-flow",
18313
18396
  addButtonCaption: RED._("workspace.addFlow"),
18314
- menu: [
18315
- {
18316
- id:"red-ui-tabs-menu-option-search-flows",
18317
- label: RED._("workspace.listFlows"),
18318
- onselect: "core:list-flows"
18319
- },
18320
- {
18321
- id:"red-ui-tabs-menu-option-search-subflows",
18322
- label: RED._("workspace.listSubflows"),
18323
- onselect: "core:list-subflows"
18324
- },
18325
- null,
18326
- {
18327
- id:"red-ui-tabs-menu-option-add-flow",
18328
- label: RED._("workspace.addFlow"),
18329
- onselect: "core:add-flow"
18330
- },
18331
- {
18332
- id:"red-ui-tabs-menu-option-add-flow-right",
18333
- label: RED._("workspace.addFlowToRight"),
18334
- onselect: "core:add-flow-to-right"
18335
- },
18336
- null,
18337
- {
18338
- id:"red-ui-tabs-menu-option-add-hide-flows",
18339
- label: RED._("workspace.hideFlow"),
18340
- onselect: "core:hide-flow"
18341
- },
18342
- {
18343
- id:"red-ui-tabs-menu-option-add-hide-other-flows",
18344
- label: RED._("workspace.hideOtherFlows"),
18345
- onselect: "core:hide-other-flows"
18346
- },
18347
- {
18348
- id:"red-ui-tabs-menu-option-add-show-all-flows",
18349
- label: RED._("workspace.showAllFlows"),
18350
- onselect: "core:show-all-flows"
18351
- },
18352
- {
18353
- id:"red-ui-tabs-menu-option-add-hide-all-flows",
18354
- label: RED._("workspace.hideAllFlows"),
18355
- onselect: "core:hide-all-flows"
18356
- },
18357
- {
18358
- id:"red-ui-tabs-menu-option-add-show-last-flow",
18359
- label: RED._("workspace.showLastHiddenFlow"),
18360
- onselect: "core:show-last-hidden-flow"
18397
+ menu: function() {
18398
+ var menuItems = [
18399
+ {
18400
+ id:"red-ui-tabs-menu-option-search-flows",
18401
+ label: RED._("workspace.listFlows"),
18402
+ onselect: "core:list-flows"
18403
+ },
18404
+ {
18405
+ id:"red-ui-tabs-menu-option-search-subflows",
18406
+ label: RED._("workspace.listSubflows"),
18407
+ onselect: "core:list-subflows"
18408
+ },
18409
+ null,
18410
+ {
18411
+ id:"red-ui-tabs-menu-option-add-flow",
18412
+ label: RED._("workspace.addFlow"),
18413
+ onselect: "core:add-flow"
18414
+ },
18415
+ {
18416
+ id:"red-ui-tabs-menu-option-add-flow-right",
18417
+ label: RED._("workspace.addFlowToRight"),
18418
+ onselect: "core:add-flow-to-right"
18419
+ },
18420
+ null,
18421
+ {
18422
+ id:"red-ui-tabs-menu-option-add-hide-flows",
18423
+ label: RED._("workspace.hideFlow"),
18424
+ onselect: "core:hide-flow"
18425
+ },
18426
+ {
18427
+ id:"red-ui-tabs-menu-option-add-hide-other-flows",
18428
+ label: RED._("workspace.hideOtherFlows"),
18429
+ onselect: "core:hide-other-flows"
18430
+ },
18431
+ {
18432
+ id:"red-ui-tabs-menu-option-add-show-all-flows",
18433
+ label: RED._("workspace.showAllFlows"),
18434
+ onselect: "core:show-all-flows"
18435
+ },
18436
+ {
18437
+ id:"red-ui-tabs-menu-option-add-hide-all-flows",
18438
+ label: RED._("workspace.hideAllFlows"),
18439
+ onselect: "core:hide-all-flows"
18440
+ },
18441
+ {
18442
+ id:"red-ui-tabs-menu-option-add-show-last-flow",
18443
+ label: RED._("workspace.showLastHiddenFlow"),
18444
+ onselect: "core:show-last-hidden-flow"
18445
+ }
18446
+ ]
18447
+ if (hideStack.length > 0) {
18448
+ menuItems.unshift({
18449
+ label: RED._("workspace.hiddenFlows",{count: hideStack.length}),
18450
+ onselect: "core:list-hidden-flows"
18451
+ })
18361
18452
  }
18362
- ]
18453
+ return menuItems;
18454
+ }
18363
18455
  });
18364
18456
  workspaceTabCount = 0;
18365
18457
  }
@@ -18499,7 +18591,9 @@ RED.workspaces = (function() {
18499
18591
  }
18500
18592
  }
18501
18593
  })
18502
-
18594
+ RED.actions.add("core:list-hidden-flows",function() {
18595
+ RED.actions.invoke("core:search","is:hidden ");
18596
+ })
18503
18597
  RED.actions.add("core:list-flows",function() {
18504
18598
  RED.actions.invoke("core:search","type:tab ");
18505
18599
  })
@@ -18543,7 +18637,7 @@ RED.workspaces = (function() {
18543
18637
  var changes = { disabled: workspace.disabled };
18544
18638
  workspace.disabled = disabled;
18545
18639
  $("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
18546
- if (id || activeWorkspace) {
18640
+ if (!id || (id === activeWorkspace)) {
18547
18641
  $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
18548
18642
  }
18549
18643
  var historyEvent = {
@@ -18624,11 +18718,11 @@ RED.workspaces = (function() {
18624
18718
  }
18625
18719
  if (workspace_tabs.contains(id)) {
18626
18720
  workspace_tabs.hideTab(id);
18627
- var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
18628
- hiddenTabs[id] = true;
18629
- RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
18630
18721
  }
18631
18722
  },
18723
+ isHidden: function(id) {
18724
+ return hideStack.includes(id)
18725
+ },
18632
18726
  show: function(id,skipStack,unhideOnly) {
18633
18727
  if (!workspace_tabs.contains(id)) {
18634
18728
  var sf = RED.nodes.subflow(id);
@@ -18651,14 +18745,11 @@ RED.workspaces = (function() {
18651
18745
  }
18652
18746
  workspace_tabs.activateTab(id);
18653
18747
  }
18654
- var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
18655
- delete hiddenTabs[id];
18656
- RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
18657
18748
  },
18658
18749
  refresh: function() {
18659
18750
  RED.nodes.eachWorkspace(function(ws) {
18660
18751
  workspace_tabs.renameTab(ws.id,ws.label);
18661
-
18752
+ $("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
18662
18753
  })
18663
18754
  RED.nodes.eachSubflow(function(sf) {
18664
18755
  if (workspace_tabs.contains(sf.id)) {
@@ -22401,7 +22492,11 @@ RED.view = (function() {
22401
22492
  nodeEl = document.getElementById(d.id);
22402
22493
  }
22403
22494
  if (nodeEl) {
22404
- if (!showStatus || !d.status) {
22495
+ // Do not show node status if:
22496
+ // - global flag set
22497
+ // - node has no status
22498
+ // - node is disabled
22499
+ if (!showStatus || !d.status || d.d === true) {
22405
22500
  nodeEl.__statusGroup__.style.display = "none";
22406
22501
  } else {
22407
22502
  nodeEl.__statusGroup__.style.display = "inline";
@@ -23147,6 +23242,9 @@ RED.view = (function() {
23147
23242
  n.selected = true;
23148
23243
  n.dirty = true;
23149
23244
  movingSet.add(n);
23245
+ if (targets.length === 1) {
23246
+ RED.view.reveal(n.id);
23247
+ }
23150
23248
  });
23151
23249
  updateSelection();
23152
23250
  redraw();
@@ -23683,7 +23781,7 @@ RED.view = (function() {
23683
23781
  counts.push(RED._("clipboard.group",{count:newGroupCount}));
23684
23782
  }
23685
23783
  if (newConfigNodeCount > 0) {
23686
- counts.push(RED._("clipboard.configNode",{count:newNodeCount}));
23784
+ counts.push(RED._("clipboard.configNode",{count:newConfigNodeCount}));
23687
23785
  }
23688
23786
  if (new_subflows.length > 0) {
23689
23787
  counts.push(RED._("clipboard.subflow",{count:new_subflows.length}));
@@ -23755,6 +23853,7 @@ RED.view = (function() {
23755
23853
  delete node.d;
23756
23854
  }
23757
23855
  node.dirty = true;
23856
+ node.dirtyStatus = true;
23758
23857
  node.changed = true;
23759
23858
  RED.events.emit("nodes:change",node);
23760
23859
  }
@@ -26917,6 +27016,7 @@ RED.sidebar.info = (function() {
26917
27016
  n.d = true;
26918
27017
  }
26919
27018
  n.dirty = true;
27019
+ n.dirtyStatus = true;
26920
27020
  n.changed = true;
26921
27021
  RED.events.emit("nodes:change",n);
26922
27022
  groupHistoryEvent.events.push(historyEvent);
@@ -26945,6 +27045,7 @@ RED.sidebar.info = (function() {
26945
27045
  n.d = true;
26946
27046
  }
26947
27047
  n.dirty = true;
27048
+ n.dirtyStatus = true;
26948
27049
  n.changed = true;
26949
27050
  RED.events.emit("nodes:change",n);
26950
27051
  RED.history.push(historyEvent);
@@ -27014,6 +27115,7 @@ RED.sidebar.info = (function() {
27014
27115
  {label:RED._("sidebar.info.search.invalidNodes"), value: "is:invalid"},
27015
27116
  {label:RED._("sidebar.info.search.uknownNodes"), value: "type:unknown"},
27016
27117
  {label:RED._("sidebar.info.search.unusedSubflows"), value:"is:subflow is:unused"},
27118
+ {label:RED._("sidebar.info.search.hiddenFlows"), value:"is:hidden"},
27017
27119
  ]
27018
27120
  });
27019
27121
 
@@ -27305,7 +27407,7 @@ RED.sidebar.info = (function() {
27305
27407
  }
27306
27408
  }
27307
27409
  function getGutter(n) {
27308
- var span = $("<span>",{class:"red-ui-info-outline-gutter"});
27410
+ var span = $("<span>",{class:"red-ui-info-outline-gutter red-ui-treeList-gutter-float"});
27309
27411
  var revealButton = $('<button type="button" class="red-ui-info-outline-item-control-reveal red-ui-button red-ui-button-small"><i class="fa fa-search"></i></button>').appendTo(span).on("click",function(evt) {
27310
27412
  evt.preventDefault();
27311
27413
  evt.stopPropagation();
@@ -27806,7 +27908,7 @@ RED.sidebar.help = (function() {
27806
27908
  var currentVersionParts = RED.settings.version.split(".");
27807
27909
  var tourVersionParts = tour.version.split(".");
27808
27910
  if (tourVersionParts[0] === currentVersionParts[0] && tourVersionParts[1] === currentVersionParts[1]) {
27809
- tourHeader = '<div><button type="button" onclick="RED.actions.invoke(\'core:show-welcome-tour\')" class="red-ui-button">Take a tour</button></div>'
27911
+ tourHeader = '<div><button type="button" onclick="RED.actions.invoke(\'core:show-welcome-tour\')" class="red-ui-button">' + RED._("tourGuide.takeATour") + '</button></div>';
27810
27912
  }
27811
27913
  }
27812
27914
  var aboutHeader = '<div style="text-align:center;">'+tourHeader+'</div>'
@@ -30587,7 +30689,16 @@ RED.editor = (function() {
30587
30689
  delete cn.__label__;
30588
30690
  });
30589
30691
 
30590
- select.append('<option value="_ADD_"'+(value===""?" selected":"")+'>'+RED._("editor.addNewType", {type:type})+'</option>');
30692
+ var label = type;
30693
+ if (typeof node_def.paletteLabel !== "undefined") {
30694
+ try {
30695
+ label = RED.utils.sanitize((typeof node_def.paletteLabel === "function" ? node_def.paletteLabel.call(node_def) : node_def.paletteLabel)||type);
30696
+ } catch(err) {
30697
+ console.log("Definition error: "+type+".paletteLabel",err);
30698
+ }
30699
+ }
30700
+
30701
+ select.append('<option value="_ADD_"'+(value===""?" selected":"")+'>'+RED._("editor.addNewType", {type:label})+'</option>');
30591
30702
  window.setTimeout(function() { select.trigger("change");},50);
30592
30703
  }
30593
30704
  }
@@ -32425,9 +32536,15 @@ RED.editor = (function() {
32425
32536
  }
32426
32537
  });
32427
32538
  }
32428
- if (!isSameObj(old_env, new_env)) {
32429
- node.env = new_env;
32539
+ if (!old_env && new_env.length === 0) {
32540
+ delete node.env;
32541
+ } else if (!isSameObj(old_env, new_env)) {
32430
32542
  editState.changes.env = node.env;
32543
+ if (new_env.length === 0) {
32544
+ delete node.env;
32545
+ } else {
32546
+ node.env = new_env;
32547
+ }
32431
32548
  editState.changed = true;
32432
32549
  }
32433
32550
  }
@@ -32857,34 +32974,6 @@ RED.editor = (function() {
32857
32974
  }
32858
32975
 
32859
32976
  })();
32860
- ;;(function() {
32861
-
32862
- RED.editor.registerEditPane(
32863
- "editor-tab-testing",
32864
- function(node) {
32865
- return {
32866
- label: "Testing",
32867
- name: "Testing",
32868
- iconClass: "fa fa-paper-plane",
32869
- create: function(container) {
32870
- },
32871
- resize: function(size) {
32872
- },
32873
- close: function() {
32874
- },
32875
- show: function() {
32876
- },
32877
- apply: function(editState) {
32878
- }
32879
- }
32880
- },
32881
- function(node) {
32882
- if (node.type === "inject") {
32883
- return true;
32884
- }
32885
- }
32886
- );
32887
- })();
32888
32977
  ;/**
32889
32978
  * Copyright JS Foundation and other contributors, http://js.foundation
32890
32979
  *
@@ -34274,7 +34363,7 @@ RED.editor = (function() {
34274
34363
  var currentExpression = expressionEditor.getValue();
34275
34364
  var expr;
34276
34365
  var usesContext = false;
34277
- var legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
34366
+ var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
34278
34367
  $(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
34279
34368
  try {
34280
34369
  expr = jsonata(currentExpression);
@@ -34563,7 +34652,8 @@ RED.editor = (function() {
34563
34652
  clearTimeout: true,
34564
34653
  setInterval: true,
34565
34654
  clearInterval: true
34566
- }
34655
+ },
34656
+ extraLibs: options.extraLibs
34567
34657
  });
34568
34658
  if (options.cursor) {
34569
34659
  expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
@@ -37582,6 +37672,7 @@ RED.clipboard = (function() {
37582
37672
  text: RED._("common.label.cancel"),
37583
37673
  click: function() {
37584
37674
  $( this ).dialog( "close" );
37675
+ RED.view.focus();
37585
37676
  }
37586
37677
  },
37587
37678
  { // red-ui-clipboard-dialog-download
@@ -37592,6 +37683,7 @@ RED.clipboard = (function() {
37592
37683
  var data = $("#red-ui-clipboard-dialog-export-text").val();
37593
37684
  downloadData("flows.json", data);
37594
37685
  $( this ).dialog( "close" );
37686
+ RED.view.focus();
37595
37687
  }
37596
37688
  },
37597
37689
  { // red-ui-clipboard-dialog-export
@@ -37606,6 +37698,7 @@ RED.clipboard = (function() {
37606
37698
  $( this ).dialog( "close" );
37607
37699
  copyText(flowData);
37608
37700
  RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"});
37701
+ RED.view.focus();
37609
37702
  } else {
37610
37703
  var flowToExport = $("#red-ui-clipboard-dialog-export-text").val();
37611
37704
  var selectedPath = activeLibraries[activeTab].getSelected();
@@ -37621,6 +37714,7 @@ RED.clipboard = (function() {
37621
37714
  contentType: "application/json; charset=utf-8"
37622
37715
  }).done(function() {
37623
37716
  $(dialog).dialog( "close" );
37717
+ RED.view.focus();
37624
37718
  RED.notify(RED._("library.exportedToLibrary"),"success");
37625
37719
  }).fail(function(xhr,textStatus,err) {
37626
37720
  if (xhr.status === 401) {
@@ -37682,6 +37776,7 @@ RED.clipboard = (function() {
37682
37776
  }
37683
37777
  }
37684
37778
  $( this ).dialog( "close" );
37779
+ RED.view.focus();
37685
37780
  }
37686
37781
  },
37687
37782
  { // red-ui-clipboard-dialog-import-conflict
@@ -37714,6 +37809,7 @@ RED.clipboard = (function() {
37714
37809
  // console.table(pendingImportConfig.importNodes.map(function(n) { return {id:n.id,type:n.type,result:importMap[n.id]}}))
37715
37810
  RED.view.importNodes(newNodes, pendingImportConfig.importOptions);
37716
37811
  $( this ).dialog( "close" );
37812
+ RED.view.focus();
37717
37813
  }
37718
37814
  }
37719
37815
  ],
@@ -38451,28 +38547,25 @@ RED.clipboard = (function() {
38451
38547
  if (truncated) {
38452
38548
  msg += "_truncated";
38453
38549
  }
38454
- $("#red-ui-clipboard-hidden").val(value).focus().select();
38455
- var result = document.execCommand("copy");
38456
- if (result && element) {
38457
- var popover = RED.popover.create({
38458
- target: element,
38459
- direction: 'left',
38460
- size: 'small',
38461
- content: RED._(msg)
38462
- });
38463
- setTimeout(function() {
38464
- popover.close();
38465
- },1000);
38466
- popover.open();
38467
- }
38468
- $("#red-ui-clipboard-hidden").val("");
38469
- if (currentFocus) {
38470
- $(currentFocus).focus();
38471
- }
38472
- return result;
38550
+ navigator.clipboard.writeText(value).then(function () {
38551
+ if (element) {
38552
+ var popover = RED.popover.create({
38553
+ target: element,
38554
+ direction: 'left',
38555
+ size: 'small',
38556
+ content: RED._(msg)
38557
+ });
38558
+ setTimeout(function() {
38559
+ popover.close();
38560
+ },1000);
38561
+ popover.open();
38562
+ }
38563
+ if (currentFocus) {
38564
+ $(currentFocus).focus();
38565
+ }
38566
+ }).catch(err => { console.error("Failed to copy:",err) });
38473
38567
  }
38474
38568
 
38475
-
38476
38569
  function importNodes(nodesStr,addFlow) {
38477
38570
  var newNodes = nodesStr;
38478
38571
  if (typeof nodesStr === 'string') {
@@ -38747,8 +38840,6 @@ RED.clipboard = (function() {
38747
38840
  init: function() {
38748
38841
  setupDialogs();
38749
38842
 
38750
- $('<textarea type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
38751
-
38752
38843
  RED.actions.add("core:show-export-dialog",showExportNodes);
38753
38844
  RED.actions.add("core:show-import-dialog",showImportNodes);
38754
38845
 
@@ -40122,6 +40213,7 @@ RED.search = (function() {
40122
40213
  val = extractFlag(val,"unused",flags);
40123
40214
  val = extractFlag(val,"config",flags);
40124
40215
  val = extractFlag(val,"subflow",flags);
40216
+ val = extractFlag(val,"hidden",flags);
40125
40217
  // uses:<node-id>
40126
40218
  val = extractValue(val,"uses",flags);
40127
40219
 
@@ -40167,7 +40259,15 @@ RED.search = (function() {
40167
40259
  continue;
40168
40260
  }
40169
40261
  }
40170
-
40262
+ if (flags.hasOwnProperty("hidden")) {
40263
+ // Only tabs can be hidden
40264
+ if (node.node.type !== 'tab') {
40265
+ continue
40266
+ }
40267
+ if (!RED.workspaces.isHidden(node.node.id)) {
40268
+ continue
40269
+ }
40270
+ }
40171
40271
  if (flags.hasOwnProperty("unused")) {
40172
40272
  var isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
40173
40273
  (isConfigNode && node.node.users.length === 0)
@@ -49931,6 +50031,8 @@ RED.touch.radialMenu = (function() {
49931
50031
  if (step.fallback) {
49932
50032
  focus.one("mouseenter", function(evt) {
49933
50033
  setTimeout(function() {
50034
+ var pos = targetElement[0].getBoundingClientRect();
50035
+ var dimension = Math.max(50, Math.max(pos.width,pos.height)*1.5);
49934
50036
  focus.css({
49935
50037
  width: (4*dimension)+"px",
49936
50038
  height: (4*dimension)+"px"