@node-red/editor-client 2.1.0-beta.2 → 2.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/editor-client",
3
- "version": "2.1.0-beta.2",
3
+ "version": "2.1.3",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
package/public/red/about CHANGED
@@ -1,3 +1,57 @@
1
+ #### 2.1.3: Maintenance Release
2
+
3
+ Runtime
4
+
5
+ - Update gen-publish script to update 'next' tag for main releases
6
+ - Add environment variable to enable/disable tours (#3221) @hardillb
7
+ - Fix loading non-default language files leaving runtime in wrong locale (#3225) @knolleary
8
+
9
+ Editor
10
+
11
+ - Refresh editor settings whenever a node is added or enabled (#3227) @knolleary
12
+ - Revert spinner css change that made it shrink in some cases (#3229) @knolleary
13
+ - Fix import notification message when importing config nodes (#3224) @knolleary
14
+ - Handle changing types of TypedInput repeatedly (#3223) @knolleary
15
+
16
+
17
+ #### 2.1.2: Maintenance Release
18
+
19
+
20
+ Runtime
21
+
22
+ - node-red-pi: Remove bash dependency (#3216) @a16bitsysop
23
+
24
+ Editor
25
+
26
+ - Improved regex for markdown renderer (#3213) @GerwinvBeek
27
+ - Fix TypedInput initialisation (#3220) @knolleary
28
+
29
+ Nodes
30
+
31
+ - MQTT: fix datatype in node config not used. fixes #3215 (#3219) @Steve-Mcl
32
+
33
+ #### 2.1.1: Maintenance Release
34
+
35
+ Editor
36
+
37
+ - Ensure tourGuide popover doesn't fall offscreen (#3212) @knolleary
38
+ - Fix issue with old inject nodes that migrated topic to 'string' type (#3210) @knolleary
39
+ - Add cache-busting query params to index.mst (#3211) @knolleary
40
+ - Fix TypedInput validation of type without options (#3207) @knolleary
41
+
42
+ #### 2.1.0: Milestone Release
43
+
44
+ Editor
45
+
46
+ - Position popover properly on a scrolled page
47
+ - Fixes from 2.1.0-beta.2 (#3202) @knolleary
48
+
49
+ Nodes
50
+
51
+ - Link Out: Fix saving link out node links (#3201) @knolleary
52
+ - Switch: Refix #3170 - copy switch rule type when adding new rule
53
+ - TCP Request: Add string option to TCP request node output (#3204) @dceejay
54
+
1
55
  #### 2.1.0-beta.2: Beta Release
2
56
 
3
57
  Editor
@@ -26,8 +80,6 @@ Nodes
26
80
  - Inject: Widen Inject interval box for >1 digit (#3184) @knolleary
27
81
  - Switch: Fix rule focus when switch 'otherwise' rule is used (#3185) @knolleary
28
82
 
29
-
30
-
31
83
  #### 2.1.0-beta.1: Beta Release
32
84
 
33
85
  Editor
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright JS Foundation and other contributors, http://js.foundation
2
+ * Copyright OpenJS Foundation and other contributors, https://openjsf.org/
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
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) {
@@ -1408,7 +1412,7 @@ RED.settings = (function () {
1408
1412
  load(done);
1409
1413
  }
1410
1414
 
1411
- var load = function(done) {
1415
+ var refreshSettings = function(done) {
1412
1416
  $.ajax({
1413
1417
  headers: {
1414
1418
  "Accept": "application/json"
@@ -1418,6 +1422,23 @@ RED.settings = (function () {
1418
1422
  url: 'settings',
1419
1423
  success: function (data) {
1420
1424
  setProperties(data);
1425
+ done(null, data);
1426
+ },
1427
+ error: function(jqXHR,textStatus,errorThrown) {
1428
+ if (jqXHR.status === 401) {
1429
+ if (/[?&]access_token=(.*?)(?:$|&)/.test(window.location.search)) {
1430
+ window.location.search = "";
1431
+ }
1432
+ RED.user.login(function() { refreshSettings(done); });
1433
+ } else {
1434
+ console.log("Unexpected error loading settings:",jqXHR.status,textStatus);
1435
+ }
1436
+ }
1437
+ });
1438
+ }
1439
+ var load = function(done) {
1440
+ refreshSettings(function(err, data) {
1441
+ if (!err) {
1421
1442
  if (!RED.settings.user || RED.settings.user.anonymous) {
1422
1443
  RED.settings.remove("auth-tokens");
1423
1444
  }
@@ -1430,18 +1451,8 @@ RED.settings = (function () {
1430
1451
  console.log("D3",d3.version);
1431
1452
  console.groupEnd();
1432
1453
  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
1454
  }
1444
- });
1455
+ })
1445
1456
  };
1446
1457
 
1447
1458
  function loadUserSettings(done) {
@@ -1517,6 +1528,7 @@ RED.settings = (function () {
1517
1528
  init: init,
1518
1529
  load: load,
1519
1530
  loadUserSettings: loadUserSettings,
1531
+ refreshSettings: refreshSettings,
1520
1532
  set: set,
1521
1533
  get: get,
1522
1534
  remove: remove,
@@ -7799,7 +7811,7 @@ RED.utils = (function() {
7799
7811
  level: 'block', // Is this a block-level or inline-level tokenizer?
7800
7812
  start(src) {
7801
7813
  if (!src) { return null; }
7802
- let m = src.match(/:[^:\n]/);
7814
+ let m = src.match(/:[^:\n]/g);
7803
7815
  return m && m.index; // Hint to Marked.js to stop and check for a match
7804
7816
  },
7805
7817
  tokenizer(src, tokens) {
@@ -7825,7 +7837,7 @@ RED.utils = (function() {
7825
7837
  level: 'inline', // Is this a block-level or inline-level tokenizer?
7826
7838
  start(src) {
7827
7839
  if (!src) { return null; }
7828
- let m = src.match(/:/);
7840
+ let m = src.match(/:/g);
7829
7841
  return m && m.index; // Hint to Marked.js to stop and check for a match
7830
7842
  },
7831
7843
  tokenizer(src, tokens) {
@@ -9703,6 +9715,9 @@ RED.utils = (function() {
9703
9715
  switch(evt.keyCode) {
9704
9716
  case 32: // SPACE
9705
9717
  case 13: // ENTER
9718
+ if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) {
9719
+ return
9720
+ }
9706
9721
  evt.preventDefault();
9707
9722
  evt.stopPropagation();
9708
9723
  if (focussed.checkbox) {
@@ -11717,7 +11732,7 @@ RED.popover = (function() {
11717
11732
  var panelWidth = panel.width();
11718
11733
 
11719
11734
  var top = (targetHeight+pos.top) + offset[1];
11720
- if (top+panelHeight > $(window).height()) {
11735
+ if (top+panelHeight-$(document).scrollTop() > $(window).height()) {
11721
11736
  top -= (top+panelHeight)-$(window).height() + 5;
11722
11737
  }
11723
11738
  if (top < 0) {
@@ -13490,6 +13505,47 @@ RED.stack = (function() {
13490
13505
  }
13491
13506
  }
13492
13507
  };
13508
+
13509
+ // For a type with options, check value is a valid selection
13510
+ // If !opt.multiple, returns the valid option object
13511
+ // if opt.multiple, returns an array of valid option objects
13512
+ // If not valid, returns null;
13513
+
13514
+ function isOptionValueValid(opt, currentVal) {
13515
+ if (!opt.multiple) {
13516
+ for (var i=0;i<opt.options.length;i++) {
13517
+ op = opt.options[i];
13518
+ if (typeof op === "string" && op === currentVal) {
13519
+ return {value:currentVal}
13520
+ } else if (op.value === currentVal) {
13521
+ return op;
13522
+ }
13523
+ }
13524
+ } else {
13525
+ // Check to see if value is a valid csv of
13526
+ // options.
13527
+ var currentValues = {};
13528
+ var selected = [];
13529
+ currentVal.split(",").forEach(function(v) {
13530
+ if (v) {
13531
+ currentValues[v] = true;
13532
+ }
13533
+ });
13534
+ for (var i=0;i<opt.options.length;i++) {
13535
+ op = opt.options[i];
13536
+ var val = typeof op === "string" ? op : op.value;
13537
+ if (currentValues.hasOwnProperty(val)) {
13538
+ delete currentValues[val];
13539
+ selected.push(typeof op === "string" ? {value:op} : op.value)
13540
+ }
13541
+ }
13542
+ if (!$.isEmptyObject(currentValues)) {
13543
+ return null;
13544
+ }
13545
+ return selected
13546
+ }
13547
+ }
13548
+
13493
13549
  var nlsd = false;
13494
13550
 
13495
13551
  $.widget( "nodered.typedInput", {
@@ -13523,7 +13579,8 @@ RED.stack = (function() {
13523
13579
  }
13524
13580
  nlsd = true;
13525
13581
  var that = this;
13526
-
13582
+ this.identifier = this.element.attr('id') || "TypedInput-"+Math.floor(Math.random()*100);
13583
+ if (this.options.debug) { console.log(this.identifier,"Create",{defaultType:this.options.default, value:this.element.val()}) }
13527
13584
  this.disarmClick = false;
13528
13585
  this.input = $('<input class="red-ui-typedInput-input" type="text"></input>');
13529
13586
  this.input.insertAfter(this.element);
@@ -13553,6 +13610,8 @@ RED.stack = (function() {
13553
13610
  });
13554
13611
 
13555
13612
  this.defaultInputType = this.input.attr('type');
13613
+ // Used to remember selections per-type to restore them when switching between types
13614
+ this.oldValues = {};
13556
13615
 
13557
13616
  this.uiSelect.addClass("red-ui-typedInput-container");
13558
13617
 
@@ -13635,9 +13694,9 @@ RED.stack = (function() {
13635
13694
  // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
13636
13695
  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);
13637
13696
  this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
13638
- RED.popover.tooltip(this.optionSelectLabel,function() {
13639
- return that.optionValue;
13640
- });
13697
+ // RED.popover.tooltip(this.optionSelectLabel,function() {
13698
+ // return that.optionValue;
13699
+ // });
13641
13700
  this.optionSelectTrigger.on("click", function(event) {
13642
13701
  event.preventDefault();
13643
13702
  event.stopPropagation();
@@ -13657,10 +13716,8 @@ RED.stack = (function() {
13657
13716
  this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
13658
13717
  this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
13659
13718
 
13660
- // Used to remember selections per-type to restore them when switching between types
13661
- this.oldValues = {};
13662
-
13663
13719
  this.type(this.options.default||this.typeList[0].value);
13720
+ this.typeChanged = !!this.options.default;
13664
13721
  }catch(err) {
13665
13722
  console.log(err.stack);
13666
13723
  }
@@ -13951,7 +14008,10 @@ RED.stack = (function() {
13951
14008
  },
13952
14009
  value: function(value) {
13953
14010
  var that = this;
13954
- var opt = this.typeMap[this.propertyType];
14011
+ // If the default type has been set to an invalid type, then on first
14012
+ // creation, the current propertyType will not exist. Default to an
14013
+ // empty object on the assumption the corrent type will be set shortly
14014
+ var opt = this.typeMap[this.propertyType] || {};
13955
14015
  if (!arguments.length) {
13956
14016
  var v = this.input.val();
13957
14017
  if (opt.export) {
@@ -13959,27 +14019,38 @@ RED.stack = (function() {
13959
14019
  }
13960
14020
  return v;
13961
14021
  } else {
14022
+ if (this.options.debug) { console.log(this.identifier,"----- SET VALUE ------",value) }
13962
14023
  var selectedOption = [];
14024
+ var valueToCheck = value;
13963
14025
  if (opt.options) {
13964
- var checkValues = [value];
14026
+ if (opt.hasValue && opt.parse) {
14027
+ var parts = opt.parse(value);
14028
+ if (this.options.debug) { console.log(this.identifier,"new parse",parts) }
14029
+ value = parts.value;
14030
+ valueToCheck = parts.option || parts.value;
14031
+ }
14032
+
14033
+ var checkValues = [valueToCheck];
13965
14034
  if (opt.multiple) {
13966
14035
  selectedOption = [];
13967
- checkValues = value.split(",");
14036
+ checkValues = valueToCheck.split(",");
13968
14037
  }
13969
- checkValues.forEach(function(value) {
14038
+ checkValues.forEach(function(valueToCheck) {
13970
14039
  for (var i=0;i<opt.options.length;i++) {
13971
14040
  var op = opt.options[i];
13972
14041
  if (typeof op === "string") {
13973
- if (op === value || op === ""+value) {
14042
+ if (op === valueToCheck || op === ""+valueToCheck) {
13974
14043
  selectedOption.push(that.activeOptions[op]);
13975
14044
  break;
13976
14045
  }
13977
- } else if (op.value === value) {
14046
+ } else if (op.value === valueToCheck) {
13978
14047
  selectedOption.push(op);
13979
14048
  break;
13980
14049
  }
13981
14050
  }
13982
14051
  })
14052
+ if (this.options.debug) { console.log(this.identifier,"set value to",value) }
14053
+
13983
14054
  this.input.val(value);
13984
14055
  if (!opt.multiple) {
13985
14056
  if (selectedOption.length === 0) {
@@ -14004,23 +14075,56 @@ RED.stack = (function() {
14004
14075
  return this.propertyType;
14005
14076
  } else {
14006
14077
  var that = this;
14078
+ if (this.options.debug) { console.log(this.identifier,"----- SET TYPE -----",type) }
14079
+ var previousValue = null;
14007
14080
  var opt = this.typeMap[type];
14008
14081
  if (opt && this.propertyType !== type) {
14009
14082
  // If previousType is !null, then this is a change of the type, rather than the initialisation
14010
14083
  var previousType = this.typeMap[this.propertyType];
14011
- var typeChanged = !!previousType;
14084
+ previousValue = this.input.val();
14012
14085
 
14013
- if (typeChanged) {
14086
+ if (previousType && this.typeChanged) {
14087
+ if (this.options.debug) { console.log(this.identifier,"typeChanged",{previousType,previousValue}) }
14014
14088
  if (previousType.options && opt.hasValue !== true) {
14015
- this.oldValues[previousType.value] = this.input.val();
14089
+ this.oldValues[previousType.value] = previousValue;
14016
14090
  } else if (previousType.hasValue === false) {
14017
- this.oldValues[previousType.value] = this.input.val();
14091
+ this.oldValues[previousType.value] = previousValue;
14018
14092
  } else {
14019
- this.oldValues["_"] = this.input.val();
14093
+ this.oldValues["_"] = previousValue;
14020
14094
  }
14021
14095
  if ((opt.options && opt.hasValue !== true) || opt.hasValue === false) {
14022
- this.input.val(this.oldValues.hasOwnProperty(opt.value)?this.oldValues[opt.value]:(opt.default||[]).join(","))
14096
+ if (this.oldValues.hasOwnProperty(opt.value)) {
14097
+ if (this.options.debug) { console.log(this.identifier,"restored previous (1)",this.oldValues[opt.value]) }
14098
+ this.input.val(this.oldValues[opt.value]);
14099
+ } else if (opt.options) {
14100
+ // No old value for the option type.
14101
+ // It is possible code has called 'value' then 'type'
14102
+ // to set the selected option. This is what the Inject/Switch/Change
14103
+ // nodes did before 2.1.
14104
+ // So we need to be careful to not reset the value if it is a valid option.
14105
+ var validOptions = isOptionValueValid(opt,previousValue);
14106
+ if (this.options.debug) { console.log(this.identifier,{previousValue,opt,validOptions}) }
14107
+ if ((previousValue || previousValue === '') && validOptions) {
14108
+ if (this.options.debug) { console.log(this.identifier,"restored previous (2)") }
14109
+ this.input.val(previousValue);
14110
+ } else {
14111
+ if (typeof opt.default === "string") {
14112
+ if (this.options.debug) { console.log(this.identifier,"restored previous (3)",opt.default) }
14113
+ this.input.val(opt.default);
14114
+ } else if (Array.isArray(opt.default)) {
14115
+ if (this.options.debug) { console.log(this.identifier,"restored previous (4)",opt.default.join(",")) }
14116
+ this.input.val(opt.default.join(","))
14117
+ } else {
14118
+ if (this.options.debug) { console.log(this.identifier,"restored previous (5)") }
14119
+ this.input.val("");
14120
+ }
14121
+ }
14122
+ } else {
14123
+ if (this.options.debug) { console.log(this.identifier,"restored default/blank",opt.default||"") }
14124
+ this.input.val(opt.default||"")
14125
+ }
14023
14126
  } else {
14127
+ if (this.options.debug) { console.log(this.identifier,"restored old/default/blank") }
14024
14128
  this.input.val(this.oldValues.hasOwnProperty("_")?this.oldValues["_"]:(opt.default||""))
14025
14129
  }
14026
14130
  if (previousType.autoComplete) {
@@ -14028,6 +14132,7 @@ RED.stack = (function() {
14028
14132
  }
14029
14133
  }
14030
14134
  this.propertyType = type;
14135
+ this.typeChanged = true;
14031
14136
  if (this.typeField) {
14032
14137
  this.typeField.val(type);
14033
14138
  }
@@ -14096,22 +14201,12 @@ RED.stack = (function() {
14096
14201
 
14097
14202
  var op;
14098
14203
  if (!opt.hasValue) {
14099
- var validValue = false;
14100
- var currentVal = this.input.val();
14204
+ // Check the value is valid for the available options
14205
+ var validValues = isOptionValueValid(opt,this.input.val());
14101
14206
  if (!opt.multiple) {
14102
- for (var i=0;i<opt.options.length;i++) {
14103
- op = opt.options[i];
14104
- if (typeof op === "string" && op === currentVal) {
14105
- that._updateOptionSelectLabel({value:currentVal});
14106
- validValue = true;
14107
- break;
14108
- } else if (op.value === currentVal) {
14109
- that._updateOptionSelectLabel(op);
14110
- validValue = true;
14111
- break;
14112
- }
14113
- }
14114
- if (!validValue) {
14207
+ if (validValues) {
14208
+ that._updateOptionSelectLabel(validValues)
14209
+ } else {
14115
14210
  op = opt.options[0];
14116
14211
  if (typeof op === "string") {
14117
14212
  this.value(op);
@@ -14122,31 +14217,19 @@ RED.stack = (function() {
14122
14217
  }
14123
14218
  }
14124
14219
  } else {
14125
- // Check to see if value is a valid csv of
14126
- // options.
14127
- var currentValues = {};
14128
- var selected = [];
14129
- currentVal.split(",").forEach(function(v) {
14130
- if (v) {
14131
- selected.push(v);
14132
- currentValues[v] = true;
14133
- }
14134
- });
14135
- for (var i=0;i<opt.options.length;i++) {
14136
- op = opt.options[i];
14137
- delete currentValues[op.value||op];
14138
- }
14139
- if (!$.isEmptyObject(currentValues)) {
14140
- selected = opt.default || [];
14141
- // Invalid, set to default/empty
14142
- this.value(selected.join(","));
14220
+ if (!validValues) {
14221
+ validValues = (opt.default || []).map(function(v) {
14222
+ return typeof v === "string"?v:v.value
14223
+ });
14224
+ this.value(validValues.join(","));
14143
14225
  }
14144
- that._updateOptionSelectLabel(selected);
14226
+ that._updateOptionSelectLabel(validValues);
14145
14227
  }
14146
14228
  } else {
14147
14229
  var selectedOption = this.optionValue||opt.options[0];
14148
14230
  if (opt.parse) {
14149
- var parts = opt.parse(this.input.val(),selectedOption);
14231
+ var selectedOptionObj = typeof selectedOption === "string"?{value:selectedOption}:selectedOption
14232
+ var parts = opt.parse(this.input.val(),selectedOptionObj);
14150
14233
  if (parts.option) {
14151
14234
  selectedOption = parts.option;
14152
14235
  if (!this.activeOptions.hasOwnProperty(selectedOption)) {
@@ -14170,6 +14253,7 @@ RED.stack = (function() {
14170
14253
  this._updateOptionSelectLabel(this.activeOptions[selectedOption]);
14171
14254
  }
14172
14255
  } else if (selectedOption) {
14256
+ if (this.options.debug) { console.log(this.identifier,"HERE",{optionValue:selectedOption.value}) }
14173
14257
  this.optionValue = selectedOption.value;
14174
14258
  this._updateOptionSelectLabel(selectedOption);
14175
14259
  } else {
@@ -23636,7 +23720,7 @@ RED.view = (function() {
23636
23720
  counts.push(RED._("clipboard.group",{count:newGroupCount}));
23637
23721
  }
23638
23722
  if (newConfigNodeCount > 0) {
23639
- counts.push(RED._("clipboard.configNode",{count:newNodeCount}));
23723
+ counts.push(RED._("clipboard.configNode",{count:newConfigNodeCount}));
23640
23724
  }
23641
23725
  if (new_subflows.length > 0) {
23642
23726
  counts.push(RED._("clipboard.subflow",{count:new_subflows.length}));
@@ -32810,34 +32894,6 @@ RED.editor = (function() {
32810
32894
  }
32811
32895
 
32812
32896
  })();
32813
- ;;(function() {
32814
-
32815
- RED.editor.registerEditPane(
32816
- "editor-tab-testing",
32817
- function(node) {
32818
- return {
32819
- label: "Testing",
32820
- name: "Testing",
32821
- iconClass: "fa fa-paper-plane",
32822
- create: function(container) {
32823
- },
32824
- resize: function(size) {
32825
- },
32826
- close: function() {
32827
- },
32828
- show: function() {
32829
- },
32830
- apply: function(editState) {
32831
- }
32832
- }
32833
- },
32834
- function(node) {
32835
- if (node.type === "inject") {
32836
- return true;
32837
- }
32838
- }
32839
- );
32840
- })();
32841
32897
  ;/**
32842
32898
  * Copyright JS Foundation and other contributors, http://js.foundation
32843
32899
  *
@@ -49868,7 +49924,12 @@ RED.touch.radialMenu = (function() {
49868
49924
  maxWidth: maxWidth+"px",
49869
49925
  direction: direction,
49870
49926
  })
49871
-
49927
+ setTimeout(function() {
49928
+ var pos = popover.element.position()
49929
+ if (pos.left < 0) {
49930
+ popover.element.css({left: 0});
49931
+ }
49932
+ },100);
49872
49933
  if (nextButton) {
49873
49934
  setTimeout(function() {
49874
49935
  nextButton.focus();