@node-red/editor-client 5.0.0-beta.0 → 5.0.0-beta.1

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
@@ -910,6 +910,7 @@ var RED = (function() {
910
910
  // Register the core set of sidebar panels now the menu is ready to receive items
911
911
  RED.palette.init();
912
912
  RED.sidebar.info.init();
913
+ RED.sidebar.info.outliner.init();
913
914
  RED.sidebar.help.init();
914
915
  RED.sidebar.config.init();
915
916
  RED.sidebar.context.init();
@@ -13308,6 +13309,13 @@ RED.panels = (function() {
13308
13309
  $(children[1]).addClass("red-ui-panel");
13309
13310
 
13310
13311
  var separator = $('<div class="red-ui-panels-separator"></div>').insertAfter(children[0]);
13312
+ if (options.invisibleSeparator) {
13313
+ if (!vertical) {
13314
+ throw new Error("invisibleSeparator option is only valid for vertical panels");
13315
+ }
13316
+ separator.addClass("red-ui-panels-separator-invisible");
13317
+ $('<div class="red-ui-panels-separator-handle"></div>').appendTo(separator)
13318
+ }
13311
13319
  var startPosition;
13312
13320
  var panelSizes = [];
13313
13321
  var modifiedSizes = false;
@@ -31072,10 +31080,12 @@ RED.view.navigator = (function() {
31072
31080
  scrollPos = [$("#red-ui-workspace-chart").scrollLeft(),$("#red-ui-workspace-chart").scrollTop()];
31073
31081
  // Convert scroll position (in scaled pixels) to workspace coordinates, then to minimap coordinates
31074
31082
  // scrollPos is in scaled canvas pixels, divide by scaleFactor to get workspace coords
31075
- navBorder.attr('x',scrollPos[0]/scaleFactor/nav_scale)
31076
- .attr('y',scrollPos[1]/scaleFactor/nav_scale)
31077
- .attr('width',chartSize[0]/nav_scale/scaleFactor)
31078
- .attr('height',chartSize[1]/nav_scale/scaleFactor)
31083
+ if (chartSize[0] > 0 && chartSize[1] > 0) {
31084
+ navBorder.attr('x',scrollPos[0]/scaleFactor/nav_scale)
31085
+ .attr('y',scrollPos[1]/scaleFactor/nav_scale)
31086
+ .attr('width',chartSize[0]/nav_scale/scaleFactor)
31087
+ .attr('height',chartSize[1]/nav_scale/scaleFactor)
31088
+ }
31079
31089
  }
31080
31090
  }
31081
31091
  function show () {
@@ -31139,8 +31149,8 @@ RED.view.navigator = (function() {
31139
31149
  RED.actions.add("core:toggle-navigator",toggle);
31140
31150
  navContainer = $('<div>').css({
31141
31151
  "position":"absolute",
31142
- "bottom":$("#red-ui-workspace-footer").height(),
31143
- "right":0,
31152
+ "bottom":$("#red-ui-workspace-footer").height() + 2,
31153
+ "right": 4,
31144
31154
  zIndex: 1
31145
31155
  }).addClass('red-ui-navigator-container').appendTo("#red-ui-workspace").hide();
31146
31156
  navBox = d3.select(navContainer[0])
@@ -31149,6 +31159,8 @@ RED.view.navigator = (function() {
31149
31159
  .attr("height", nav_height)
31150
31160
  .attr("pointer-events", "all")
31151
31161
  .attr("id","red-ui-navigator-canvas")
31162
+ navVis = navBox.append("svg:g")
31163
+
31152
31164
  navBox.append("rect").attr("x",0).attr("y",0).attr("width",nav_width).attr("height",nav_height).style({
31153
31165
  fill:"none",
31154
31166
  stroke:"none",
@@ -31189,7 +31201,6 @@ RED.view.navigator = (function() {
31189
31201
  }
31190
31202
  })
31191
31203
  navBorder = navBox.append("rect").attr("class","red-ui-navigator-border")
31192
- navVis = navBox.append("svg:g")
31193
31204
  RED.statusBar.add({
31194
31205
  id: "view-navigator",
31195
31206
  align: "right",
@@ -32695,7 +32706,8 @@ RED.sidebar = (function() {
32695
32706
  menuToggle: 'menu-item-sidebar',
32696
32707
  minimumWidth: 180,
32697
32708
  maximumWidth: 800,
32698
- defaultWidth: 300
32709
+ defaultWidth: 300,
32710
+ defaultTopHeight: 0.7
32699
32711
  },
32700
32712
  secondary: {
32701
32713
  id: 'secondary',
@@ -32704,29 +32716,37 @@ RED.sidebar = (function() {
32704
32716
  minimumWidth: 180,
32705
32717
  maximumWidth: 800,
32706
32718
  // Make LH side slightly narrower by default as its the palette that doesn't require a lot of width
32707
- defaultWidth: 210
32719
+ defaultWidth: 210,
32720
+ defaultTopHeight: 1
32708
32721
  }
32709
32722
  }
32710
32723
  const defaultSidebarConfiguration = {
32711
- primary: ['info','debug','help','config','context'],
32712
- secondary: ['palette']
32724
+ primary: [ ['info','help','config','context'], ['debug'] ],
32725
+ secondary: [ ['explorer','palette'], [] ]
32713
32726
  }
32714
32727
 
32715
32728
  const knownTabs = {};
32716
32729
 
32717
32730
  function exportSidebarState () {
32718
32731
  const state = {
32719
- primary: [],
32720
- secondary: []
32732
+ primary: [[], []],
32733
+ secondary: [[], []]
32721
32734
  }
32722
- sidebars.primary.tabBar.children('button').each(function() {
32723
- const tabId = $(this).attr('data-tab-id');
32724
- state.primary.push(tabId);
32725
- })
32726
- sidebars.secondary.tabBar.children('button').each(function() {
32727
- const tabId = $(this).attr('data-tab-id');
32728
- state.secondary.push(tabId);
32729
- })
32735
+ function getTabButtons(tabBar) {
32736
+ const result = []
32737
+ tabBar.children('button').each(function() {
32738
+ const tabId = $(this).attr('data-tab-id');
32739
+ if (tabId) {
32740
+ result.push(tabId);
32741
+ }
32742
+ })
32743
+ return result
32744
+ }
32745
+ state.primary[0] = getTabButtons(sidebars.primary.tabBars.top.container);
32746
+ state.primary[1] = getTabButtons(sidebars.primary.tabBars.bottom.container);
32747
+ state.secondary[0] = getTabButtons(sidebars.secondary.tabBars.top.container);
32748
+ state.secondary[1] = getTabButtons(sidebars.secondary.tabBars.bottom.container);
32749
+
32730
32750
  RED.settings.set('editor.sidebar.state', state)
32731
32751
  }
32732
32752
 
@@ -32758,18 +32778,36 @@ RED.sidebar = (function() {
32758
32778
  let targetTabButtonIndex = -1 // Append to end by default
32759
32779
 
32760
32780
  // Check the saved sidebar state to see if this tab should be added to the primary or secondary sidebar
32761
- const savedState = RED.settings.get('editor.sidebar.state', defaultSidebarConfiguration)
32781
+ let savedState = RED.settings.get('editor.sidebar.state', defaultSidebarConfiguration)
32782
+ if (true || typeof savedState.primary[0] === 'string' || typeof savedState.secondary[0] === 'string') {
32783
+ // This is a beta.0 format. Reset it for beta.1
32784
+ savedState = defaultSidebarConfiguration
32785
+ RED.settings.set('editor.sidebar.state', savedState)
32786
+ }
32787
+ let targetSidebar = null
32788
+ let targetSection = null
32762
32789
  if (savedState) {
32763
- let targetSidebar = null
32764
32790
  let sidebarState
32765
- if (savedState.secondary.includes(options.id)) {
32791
+ if (savedState.secondary[0].includes(options.id)) {
32792
+ options.target = 'secondary'
32793
+ sidebarState = savedState.secondary[0]
32794
+ targetSidebar = sidebars.secondary
32795
+ targetSection = 'top'
32796
+ } else if (savedState.secondary[1].includes(options.id)) {
32766
32797
  options.target = 'secondary'
32767
- sidebarState = savedState.secondary
32798
+ sidebarState = savedState.secondary[1]
32768
32799
  targetSidebar = sidebars.secondary
32769
- } else if (savedState.primary.includes(options.id)) {
32800
+ targetSection = 'bottom'
32801
+ } else if (savedState.primary[0].includes(options.id)) {
32770
32802
  options.target = 'primary'
32771
- sidebarState = savedState.primary
32803
+ sidebarState = savedState.primary[0]
32772
32804
  targetSidebar = sidebars.primary
32805
+ targetSection = 'top'
32806
+ } else if (savedState.primary[1].includes(options.id)) {
32807
+ options.target = 'primary'
32808
+ sidebarState = savedState.primary[1]
32809
+ targetSidebar = sidebars.primary
32810
+ targetSection = 'bottom'
32773
32811
  }
32774
32812
  if (targetSidebar) {
32775
32813
  // This tab was found in the saved sidebar state. Now find the target position for the tab button
@@ -32778,10 +32816,13 @@ RED.sidebar = (function() {
32778
32816
  }
32779
32817
 
32780
32818
 
32781
- const targetSidebar = options.target === 'secondary' ? sidebars.secondary : sidebars.primary;
32819
+ targetSidebar = targetSidebar || (options.target === 'secondary' ? sidebars.secondary : sidebars.primary);
32820
+ targetSection = targetSection || 'top'
32821
+ options.targetSection = targetSection;
32822
+
32782
32823
  delete options.closeable;
32783
32824
 
32784
- options.wrapper = $('<div>',{style:"height:100%"}).appendTo(targetSidebar.content)
32825
+ options.wrapper = $('<div>',{style:"height:100%"}).appendTo(targetSidebar.sections[targetSection].content)
32785
32826
  options.wrapper.append(options.content);
32786
32827
  options.wrapper.hide();
32787
32828
 
@@ -32790,7 +32831,7 @@ RED.sidebar = (function() {
32790
32831
  }
32791
32832
 
32792
32833
  if (options.toolbar) {
32793
- targetSidebar.footer.append(options.toolbar);
32834
+ targetSidebar.sections[targetSection].footer.append(options.toolbar);
32794
32835
  $(options.toolbar).hide();
32795
32836
  }
32796
32837
  var id = options.id;
@@ -32810,12 +32851,12 @@ RED.sidebar = (function() {
32810
32851
  knownTabs[options.id] = options;
32811
32852
  options.tabButton = $('<button></button>')
32812
32853
  // Insert the tab button at the correct index
32813
- if (targetTabButtonIndex === -1 || targetTabButtonIndex >= targetSidebar.tabBar.children().length) {
32854
+ if (targetTabButtonIndex === -1) {
32814
32855
  // Append to end
32815
- options.tabButton = $('<button></button>').appendTo(targetSidebar.tabBar);
32856
+ targetSidebar.tabBars[targetSection].addButton(options.tabButton)
32816
32857
  } else {
32817
32858
  // Insert before the item at targetTabButtonIndex
32818
- options.tabButton = $('<button></button>').insertBefore(targetSidebar.tabBar.children().eq(targetTabButtonIndex));
32859
+ targetSidebar.tabBars[targetSection].addButton(options.tabButton, targetTabButtonIndex)
32819
32860
  }
32820
32861
  options.tabButton.attr('data-tab-id', options.id)
32821
32862
 
@@ -32831,15 +32872,17 @@ RED.sidebar = (function() {
32831
32872
  return
32832
32873
  }
32833
32874
  const targetSidebar = options.target === 'secondary' ? sidebars.secondary : sidebars.primary;
32834
- if (targetSidebar.activeTab === options.id && RED.menu.isSelected(targetSidebar.menuToggle)) {
32875
+ //
32876
+ if (targetSidebar.tabBars[options.targetSection].active === options.id && RED.menu.isSelected(targetSidebar.menuToggle)) {
32835
32877
  RED.menu.setSelected(targetSidebar.menuToggle, false);
32836
32878
  } else {
32837
32879
  RED.sidebar.show(options.id)
32838
32880
  }
32839
32881
  })
32840
- if (targetSidebar.content.children().length === 1) {
32882
+ if (targetSidebar.sections[targetSection].content.children().length === 1) {
32841
32883
  RED.sidebar.show(options.id)
32842
32884
  }
32885
+ targetSidebar.resizeSidebarTabBar()
32843
32886
  }
32844
32887
 
32845
32888
  function removeTab(id) {
@@ -32862,47 +32905,133 @@ RED.sidebar = (function() {
32862
32905
  }
32863
32906
  }
32864
32907
 
32865
- function moveTab(id, srcSidebar, targetSidebar) {
32908
+ function moveTab(id, srcSidebar, srcPosition, targetSidebar, targetPosition) {
32866
32909
  const options = knownTabs[id];
32867
32910
  options.target = targetSidebar.id;
32868
- $(options.wrapper).appendTo(targetSidebar.content);
32911
+ options.targetSection = targetPosition;
32912
+
32913
+ $(options.wrapper).appendTo(targetSidebar.sections[targetPosition].content);
32869
32914
  if (options.toolbar) {
32870
- targetSidebar.footer.append(options.toolbar);
32915
+ targetSidebar.sections[targetPosition].footer.append(options.toolbar);
32871
32916
  }
32872
32917
  // Reset the tooltip so its left/right direction is recalculated
32873
32918
  options.tabButtonTooltip.delete()
32874
32919
  options.tabButtonTooltip = RED.popover.tooltip(options.tabButton, options.name, options.action);
32875
32920
 
32876
- if (targetSidebar.content.children().length === 1) {
32921
+ if (targetSidebar.sections[targetPosition].content.children().length === 1) {
32877
32922
  RED.sidebar.show(options.id)
32878
32923
  }
32879
- if (srcSidebar.content.children().length === 0) {
32880
- RED.menu.setSelected(srcSidebar.menuToggle, false);
32924
+ if (srcSidebar.sections[srcPosition].content.children().length === 0 && srcPosition === 'bottom') {
32925
+ srcSidebar.hideSection(srcPosition)
32926
+ } else if (targetSidebar.sections[targetPosition].hidden) {
32927
+ targetSidebar.showSection(targetPosition)
32881
32928
  }
32882
32929
  }
32883
32930
 
32884
32931
  let draggingTabButton = false
32932
+
32885
32933
  function setupSidebarTabs(sidebar) {
32886
32934
  const tabBar = $('<div class="red-ui-sidebar-tab-bar"></div>').addClass('red-ui-sidebar-' + sidebar.direction);
32887
- tabBar.attr('id', sidebar.container.attr('id') + '-tab-bar')
32888
- tabBar.data('sidebar', sidebar.id)
32889
32935
  if (sidebar.direction === 'right') {
32890
32936
  tabBar.insertAfter(sidebar.container);
32891
32937
  } else if (sidebar.direction === 'left') {
32892
32938
  tabBar.insertBefore(sidebar.container);
32893
32939
  }
32894
- tabBar.sortable({
32940
+
32941
+ // TODO: make this an API object, not just a jQuery object
32942
+ sidebar.tabBars = {
32943
+ top: setupTabSection(sidebar, tabBar, 'top'),
32944
+ bottom: setupTabSection(sidebar, tabBar, 'bottom')
32945
+ }
32946
+ sidebar.tabBar = sidebar.tabBars.top.container;
32947
+ sidebar.resizeSidebarTabBar = function () {
32948
+ sidebar.tabBars.top.resizeSidebarTabBar();
32949
+ sidebar.tabBars.bottom.resizeSidebarTabBar();
32950
+ }
32951
+ sidebar.hideSection = function (position) {
32952
+ sidebar.sections.bottom.container.hide()
32953
+ sidebar.sections.bottom.hidden = true
32954
+ sidebar.sections.top.container.css('flex-grow', '1')
32955
+ sidebar.tabBars.top.container.css('flex-grow', '1')
32956
+ sidebar.tabBars.bottom.container.css('flex-grow', '0')
32957
+ sidebar.tabBars.bottom.container.css('height', '60px')
32958
+
32959
+ sidebar.resizeSidebar()
32960
+ }
32961
+ sidebar.showSection = function (position) {
32962
+ sidebar.sections.bottom.container.show()
32963
+ sidebar.sections.bottom.hidden = false
32964
+ sidebar.sections.top.container.css('flex-grow', '0')
32965
+ sidebar.sections.top.container.css('height', '70%')
32966
+ sidebar.tabBars.top.container.css('flex-grow', '')
32967
+ sidebar.tabBars.bottom.container.css('flex-grow', '')
32968
+ sidebar.tabBars.bottom.container.css('height', '')
32969
+
32970
+ sidebar.resizeSidebar()
32971
+ }
32972
+ }
32973
+
32974
+ function setupTabSection(sidebar, tabBar, position) {
32975
+ const tabBarButtonsContainer = $('<div class="red-ui-sidebar-tab-bar-buttons"></div>').appendTo(tabBar);
32976
+ const tabOverflowButton = $('<button class="red-ui-sidebar-tab-bar-overflow-button"><i class="fa fa-ellipsis-h"></i></button>').appendTo(tabBarButtonsContainer);
32977
+ tabOverflowButton.hide()
32978
+ tabOverflowButton.on('click', function(evt) {
32979
+ try {
32980
+ const menuOptions = []
32981
+ tabBarButtonsContainer.find('button:not(.red-ui-sidebar-tab-bar-overflow-button)').each(function () {
32982
+ if ($(this).is(':visible')) {
32983
+ return
32984
+ }
32985
+ const tabId = $(this).attr('data-tab-id')
32986
+ const tabOptions = knownTabs[tabId]
32987
+ menuOptions.push({
32988
+ label: tabOptions.name,
32989
+ onselect: function() {
32990
+ RED.sidebar.show(tabId)
32991
+ }
32992
+ })
32993
+ })
32994
+ if (menuOptions.length === 0) {
32995
+ return
32996
+ }
32997
+ const menu = RED.menu.init({ options: menuOptions });
32998
+ menu.attr("id",sidebar.container.attr('id')+"-menu");
32999
+ menu.css({
33000
+ position: "absolute"
33001
+ })
33002
+ menu.appendTo("body");
33003
+ var elementPos = tabOverflowButton.offset();
33004
+ menu.css({
33005
+ top: (elementPos.top+tabOverflowButton.height()- menu.height() - 10)+"px",
33006
+ left: (elementPos.left - menu.width() - 3)+"px"
33007
+ })
33008
+ $(".red-ui-menu.red-ui-menu-dropdown").hide();
33009
+ setTimeout(() => {
33010
+ $(document).on("click.red-ui-sidebar-tabmenu", function(evt) {
33011
+ $(document).off("click.red-ui-sidebar-tabmenu");
33012
+ menu.remove();
33013
+ });
33014
+ }, 0)
33015
+ menu.show();
33016
+ } catch (err) {
33017
+ console.log(err)
33018
+ }
33019
+ })
33020
+ tabBarButtonsContainer.data('sidebar', sidebar.id)
33021
+ tabBarButtonsContainer.data('sidebar-position', position)
33022
+ tabBarButtonsContainer.sortable({
32895
33023
  distance: 10,
32896
33024
  cancel: false,
33025
+ items: "button:not(.red-ui-sidebar-tab-bar-overflow-button)",
32897
33026
  placeholder: "red-ui-sidebar-tab-bar-button-placeholder",
32898
- connectWith: ".red-ui-sidebar-tab-bar",
33027
+ connectWith: ".red-ui-sidebar-tab-bar-buttons",
32899
33028
  start: function(event, ui) {
32900
- // Remove the tooltip so it doesn't display unexpectedly whilst dragging
32901
33029
  const tabId = ui.item.attr('data-tab-id');
32902
33030
  const options = knownTabs[tabId];
32903
33031
  options.tabButtonTooltip.delete()
32904
33032
  draggingTabButton = true
32905
33033
  tabBar.css('z-index','inherit')
33034
+ $(".red-ui-sidebar-tab-bar").addClass("red-ui-sidebar-dragging-tab");
32906
33035
  },
32907
33036
  stop: function(event, ui) {
32908
33037
  // Restore the tooltip
@@ -32913,33 +33042,89 @@ RED.sidebar = (function() {
32913
33042
  // Save the sidebar state
32914
33043
  exportSidebarState()
32915
33044
  tabBar.css('z-index','')
33045
+ $(".red-ui-sidebar-tab-bar").removeClass("red-ui-sidebar-dragging-tab");
32916
33046
  },
32917
33047
  receive: function(event, ui) {
32918
33048
  // Tab has been moved from one sidebar to another
32919
33049
  const src = sidebars[ui.sender.data('sidebar')]
32920
33050
  const dest = sidebars[$(this).data('sidebar')]
33051
+ const srcPosition = ui.sender.data('sidebar-position')
33052
+ const destPosition = $(this).data('sidebar-position')
32921
33053
  const tabId = ui.item.attr('data-tab-id');
32922
- moveTab(tabId, src, dest)
33054
+ moveTab(tabId, src, srcPosition, dest, destPosition);
32923
33055
  if (ui.item.hasClass('selected')) {
32924
- const firstTab = src.tabBar.find('button').first().attr('data-tab-id');
33056
+ const firstTab = src.tabBars[srcPosition].container.find('button').first().attr('data-tab-id');
32925
33057
  if (firstTab) {
32926
33058
  RED.sidebar.show(firstTab);
32927
33059
  }
32928
33060
  }
33061
+ src.resizeSidebarTabBar();
33062
+ dest.resizeSidebarTabBar();
33063
+
32929
33064
  RED.sidebar.show(tabId)
32930
33065
  }
32931
33066
  })
32932
- // $(window).on("resize", function () {
32933
- // const lastChild = tabBar.children().last();
32934
- // if (lastChild.length > 0) {
32935
- // const tabBarHeight = tabBar.height();
32936
- // const lastChildBottom = lastChild.position().top + lastChild.outerHeight();
32937
- // if (lastChildBottom > tabBarHeight) {
32938
- // console.log('overflow')
32939
- // }
32940
- // }
32941
- // })
32942
- return tabBar
33067
+
33068
+ let hasHidden = false
33069
+ const resizeSidebarTabBar = function () {
33070
+ let tabBarButtonsBottom = tabBarButtonsContainer.position().top + tabBarButtonsContainer.outerHeight();
33071
+ const buttonHeight = tabOverflowButton.outerHeight()
33072
+ // Find the last visible button
33073
+ let bottomButton = tabBarButtonsContainer.children(":visible").last()
33074
+ if (bottomButton.length === 0) {
33075
+ // Nothing visible - bail out
33076
+ return
33077
+ }
33078
+ if (tabBarButtonsBottom < bottomButton.position().top + buttonHeight * 1.5) {
33079
+ tabOverflowButton.show()
33080
+ let tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 1.5;
33081
+ while (tabBarButtonsBottom < tabOverflowButtonBottom) {
33082
+ const lastVisible = tabBarButtonsContainer.children(':not(".red-ui-sidebar-tab-bar-overflow-button"):visible').last()
33083
+ if (lastVisible.length === 0) {
33084
+ // Nothing left to hide
33085
+ break
33086
+ }
33087
+ lastVisible.hide()
33088
+ tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 1.5;
33089
+ }
33090
+ } else {
33091
+ const hiddenChildren = tabBarButtonsContainer.children(':not(".red-ui-sidebar-tab-bar-overflow-button"):hidden')
33092
+ if (hiddenChildren.length > 0) {
33093
+ // We may be able to show some more buttons
33094
+ let tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 2;
33095
+ let shownCount = 0
33096
+ while (tabBarButtonsBottom > tabOverflowButtonBottom + buttonHeight) {
33097
+ const firstHidden = tabBarButtonsContainer.children(':not(".red-ui-sidebar-tab-bar-overflow-button"):hidden').first()
33098
+ if (firstHidden.length === 0) {
33099
+ // Nothing left to show
33100
+ break
33101
+ }
33102
+ firstHidden.show()
33103
+ shownCount++
33104
+ tabOverflowButtonBottom = tabOverflowButton.position().top + buttonHeight * 2;
33105
+ }
33106
+ if (hiddenChildren.length - shownCount <= 0) {
33107
+ // We were able to show all of the hidden buttons
33108
+ // so hide the overflow button again
33109
+ tabOverflowButton.hide()
33110
+ }
33111
+ }
33112
+ }
33113
+ }
33114
+ return {
33115
+ container: tabBarButtonsContainer,
33116
+ addButton: function(button, position) {
33117
+ if (position === undefined || position >= tabBarButtonsContainer.children().length) {
33118
+ button.insertBefore(tabOverflowButton);
33119
+ } else {
33120
+ button.insertBefore(tabBarButtonsContainer.children().eq(position));
33121
+ }
33122
+ },
33123
+ clearSelected: function() {
33124
+ tabBarButtonsContainer.children('button').removeClass('selected')
33125
+ },
33126
+ resizeSidebarTabBar
33127
+ }
32943
33128
  }
32944
33129
  function setupSidebarSeparator(sidebar) {
32945
33130
  const separator = $('<div class="red-ui-sidebar-separator"></div>');
@@ -33031,10 +33216,17 @@ RED.sidebar = (function() {
33031
33216
  if (!state) {
33032
33217
  sidebar.container.hide()
33033
33218
  sidebar.separator.hide()
33034
- sidebar.tabBar.find('button').removeClass('selected')
33219
+ sidebar.tabBars.top.clearSelected()
33220
+ sidebar.tabBars.bottom.clearSelected()
33035
33221
  } else {
33036
33222
  sidebar.container.show()
33037
33223
  sidebar.separator.show()
33224
+ if (sidebar.tabBars.top.active) {
33225
+ sidebar.tabBars.top.container.find('button[data-tab-id="'+sidebar.tabBars.top.active+'"]').addClass('selected')
33226
+ }
33227
+ if (sidebar.tabBars.bottom.active) {
33228
+ sidebar.tabBars.bottom.container.find('button[data-tab-id="'+sidebar.tabBars.bottom.active+'"]').addClass('selected')
33229
+ }
33038
33230
  }
33039
33231
  RED.events.emit("sidebar:resize");
33040
33232
  }
@@ -33046,7 +33238,7 @@ RED.sidebar = (function() {
33046
33238
  const sidebar = sidebars[sidebarKey];
33047
33239
  let lastTabId = lastSessionSelectedTabs[sidebarKey];
33048
33240
  if (!lastTabId) {
33049
- lastTabId = sidebar.tabBar.children('button').first().attr('data-tab-id');
33241
+ lastTabId = sidebar.tabBars.top.container.children('button').first().attr('data-tab-id');
33050
33242
  }
33051
33243
  showSidebar(lastTabId, true)
33052
33244
  })
@@ -33056,8 +33248,9 @@ RED.sidebar = (function() {
33056
33248
  const tabOptions = knownTabs[id];
33057
33249
  if (tabOptions) {
33058
33250
  const targetSidebar = tabOptions.target === 'secondary' ? sidebars.secondary : sidebars.primary;
33059
- targetSidebar.content.children().hide();
33060
- targetSidebar.footer.children().hide();
33251
+ const targetSection = tabOptions.targetSection || 'top'
33252
+ targetSidebar.sections[targetSection].content.children().hide();
33253
+ targetSidebar.sections[targetSection].footer.children().hide();
33061
33254
  if (tabOptions.onchange) {
33062
33255
  tabOptions.onchange.call(tabOptions);
33063
33256
  }
@@ -33066,9 +33259,10 @@ RED.sidebar = (function() {
33066
33259
  $(tabOptions.toolbar).show();
33067
33260
  }
33068
33261
  RED.settings.setLocal("last-sidebar-tab-" + targetSidebar.id, tabOptions.id)
33069
- targetSidebar.tabBar.find('button').removeClass('selected')
33070
- targetSidebar.tabBar.find('button[data-tab-id="'+id+'"]').addClass('selected')
33071
- targetSidebar.activeTab = id
33262
+ // TODO: find which tabBar the button is in
33263
+ targetSidebar.tabBars[targetSection].clearSelected()
33264
+ targetSidebar.tabBars[targetSection].container.find('button[data-tab-id="'+id+'"]').addClass('selected')
33265
+ targetSidebar.tabBars[targetSection].active = id
33072
33266
 
33073
33267
  if (!skipShowSidebar && !RED.menu.isSelected(targetSidebar.menuToggle)) {
33074
33268
  RED.menu.setSelected(targetSidebar.menuToggle,true);
@@ -33082,13 +33276,88 @@ RED.sidebar = (function() {
33082
33276
  }
33083
33277
 
33084
33278
  function setupSidebar(sidebar) {
33279
+ // Get the appropriate height for the sidebar - as the sidebar will be hidden at this point in time, we need to use
33280
+ // the main-container height as a decent proxy
33281
+ const sidebarHeight = $("#red-ui-main-container").height();
33085
33282
  sidebar.container.addClass("red-ui-sidebar").addClass('red-ui-sidebar-' + sidebar.direction);
33086
33283
  sidebar.container.width(sidebar.defaultWidth);
33284
+ if (sidebar.direction === 'right') {
33285
+ $('<div>',{class:"red-ui-sidebar-shade hide"}).css("z-index", 0).appendTo(sidebar.container);
33286
+ }
33287
+ sidebar.sections = {};
33288
+ sidebar.sections.top = {}
33289
+ sidebar.sections.top.container = $('<div class="red-ui-sidebar-section red-ui-sidebar-section-top"></div>').appendTo(sidebar.container);
33290
+ sidebar.sections.top.content = $('<div class="red-ui-sidebar-content"></div>').appendTo(sidebar.sections.top.container);
33291
+ sidebar.sections.top.footer = $('<div class="red-ui-sidebar-footer"></div>').appendTo(sidebar.sections.top.container);
33292
+ sidebar.sectionsSeparator = $('<div class="red-ui-sidebar-tab-bar-separator"><div class="red-ui-sidebar-separator-handle"></div></div>').appendTo(sidebar.container);
33293
+ sidebar.sections.bottom = {}
33294
+ sidebar.sections.bottom.container = $('<div class="red-ui-sidebar-section red-ui-sidebar-section-bottom"></div>').appendTo(sidebar.container);
33295
+ sidebar.sections.bottom.content = $('<div class="red-ui-sidebar-content"></div>').appendTo(sidebar.sections.bottom.container);
33296
+ sidebar.sections.bottom.footer = $('<div class="red-ui-sidebar-footer"></div>').appendTo(sidebar.sections.bottom.container);
33297
+
33298
+ let startPosition
33299
+ let startTopSectionHeight
33300
+ let startTopTabSectionHeight
33301
+ let startSidebarHeight
33302
+ sidebar.sectionsSeparator.draggable({
33303
+ axis: "y",
33304
+ containment: sidebar.container,
33305
+ scroll: false,
33306
+ start:function(event,ui) {
33307
+ startPosition = ui.position.top
33308
+ startTopSectionHeight = sidebar.sections.top.container.outerHeight()
33309
+ startTopTabSectionHeight = sidebar.tabBars.top.container.outerHeight()
33310
+ startSidebarHeight = sidebar.container.height()
33311
+ },
33312
+ drag: function(event,ui) {
33313
+ const delta = ui.position.top - startPosition
33314
+ const newTopHeight = startTopSectionHeight + delta
33315
+ const newBottomHeight = startSidebarHeight - newTopHeight
33316
+ if (newTopHeight < 100 || newBottomHeight < 100) {
33317
+ ui.position.top += delta
33318
+ return
33319
+ }
33320
+ sidebar.sections.top.container.outerHeight(startTopSectionHeight + delta)
33321
+ sidebar.tabBars.top.container.outerHeight(startTopTabSectionHeight + delta)
33322
+ ui.position.top -= delta
33323
+ sidebar.resizeSidebar()
33324
+ },
33325
+ stop:function(event,ui) {
33326
+ }
33327
+ });
33328
+
33329
+ // sidebar.shade = $('<div class="red-ui-sidebar-shade hide"></div>').appendTo(sidebar.container);
33330
+
33087
33331
  sidebar.separator = setupSidebarSeparator(sidebar);
33088
- sidebar.tabBar = setupSidebarTabs(sidebar)
33089
- sidebar.content = $('<div class="red-ui-sidebar-content"></div>').appendTo(sidebar.container);
33090
- sidebar.footer = $('<div class="red-ui-sidebar-footer"></div>').appendTo(sidebar.container);
33091
- sidebar.shade = $('<div class="red-ui-sidebar-shade hide"></div>').appendTo(sidebar.container);
33332
+ setupSidebarTabs(sidebar)
33333
+ sidebar.resizeSidebar = function () {
33334
+ // Resize sidebar sections as needed
33335
+ const topSectionHeight = sidebar.sections.top.container.outerHeight()
33336
+ if (!sidebar.sections.bottom.hidden) {
33337
+ const bottomSectionHeight = sidebar.sections.bottom.container.outerHeight()
33338
+
33339
+ // Shrink the top section if the bottom section is too small
33340
+ if (bottomSectionHeight < 90 && topSectionHeight > 90) {
33341
+ sidebar.sections.top.container.outerHeight(topSectionHeight - (90 - bottomSectionHeight));
33342
+ }
33343
+ sidebar.tabBars.top.container.height(sidebar.sections.top.container.outerHeight())
33344
+ // } else {
33345
+ // sidebar.tabBars.top.container.height(sidebar.sections.top.container.outerHeight() - 60)
33346
+ }
33347
+ // Trigger a resize of the tab bars to handle overflow
33348
+ sidebar.resizeSidebarTabBar()
33349
+ RED.events.emit("sidebar:resize");
33350
+
33351
+ }
33352
+ $(window).on("resize", sidebar.resizeSidebar)
33353
+ if (sidebar.defaultTopHeight > 0) {
33354
+ if (sidebar.defaultTopHeight === 1) {
33355
+ sidebar.hideSection('bottom')
33356
+ } else {
33357
+ sidebar.sections.top.container.outerHeight(sidebarHeight * sidebar.defaultTopHeight);
33358
+ }
33359
+ }
33360
+ sidebar.resizeSidebar()
33092
33361
 
33093
33362
  }
33094
33363
  function init () {
@@ -33457,6 +33726,7 @@ RED.palette = (function() {
33457
33726
  var paletteWidth;
33458
33727
  var paletteTop;
33459
33728
  var dropEnabled;
33729
+ let chartOffset;
33460
33730
  $(d).draggable({
33461
33731
  helper: 'clone',
33462
33732
  appendTo: '#red-ui-editor',
@@ -33473,6 +33743,7 @@ RED.palette = (function() {
33473
33743
  if (activeGroup) {
33474
33744
  document.getElementById("group_select_"+activeGroup.id).classList.add("red-ui-flow-group-active-hovered");
33475
33745
  }
33746
+ chartOffset = chart.offset()
33476
33747
  RED.view.focus();
33477
33748
  },
33478
33749
  stop: function() {
@@ -33490,12 +33761,13 @@ RED.palette = (function() {
33490
33761
  },
33491
33762
  drag: function(e,ui) {
33492
33763
  var paletteNode = getPaletteNode(nt);
33493
- console.log(ui.originalPosition.left, paletteNode.offset().left)
33764
+ // console.log(ui.originalPosition.left, paletteNode.offset().left)
33494
33765
  // ui.originalPosition.left = paletteNode.offset().left;
33495
33766
  // console.log(paletteNode.offset())
33496
33767
  if (dropEnabled) {
33497
- mouseX = ui.position.left - paletteWidth + (ui.helper.width()/2) + chart.scrollLeft();
33498
- mouseY = ui.position.top - paletteTop + (ui.helper.height()/2) + chart.scrollTop() + 10;
33768
+ mouseX = ui.offset.left - chartOffset.left + (ui.helper.width()/2) + chart.scrollLeft();
33769
+ mouseY = ui.offset.top - chartOffset.top + (ui.helper.height()/2) + chart.scrollTop() + 10;
33770
+ // console.log(mouseX, mouseY)
33499
33771
  if (!groupTimer) {
33500
33772
  groupTimer = setTimeout(function() {
33501
33773
  var mx = mouseX / RED.view.scale();
@@ -33752,7 +34024,7 @@ RED.palette = (function() {
33752
34024
  content,
33753
34025
  toolbar,
33754
34026
  pinned: true,
33755
- enableOnEdit: true
34027
+ enableOnEdit: false
33756
34028
  });
33757
34029
 
33758
34030
  $('<img src="red/images/spin.svg" class="red-ui-palette-spinner hide"/>').appendTo("#red-ui-palette");
@@ -33959,10 +34231,6 @@ RED.sidebar.info = (function() {
33959
34231
 
33960
34232
  var stackContainer = $("<div>",{class:"red-ui-sidebar-info-stack"}).appendTo(content);
33961
34233
 
33962
- var outlinerPanel = $("<div>").css({
33963
- "overflow": "hidden",
33964
- "height": "calc(70%)"
33965
- }).appendTo(stackContainer);
33966
34234
  var propertiesPanel = $("<div>").css({
33967
34235
  "overflow":"hidden",
33968
34236
  "height":"100%",
@@ -33978,7 +34246,7 @@ RED.sidebar.info = (function() {
33978
34246
 
33979
34247
  propertiesPanelHeaderCopyLink = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-link"></button>').css({
33980
34248
  position: 'absolute',
33981
- top: '12px',
34249
+ top: '6px',
33982
34250
  right: '32px'
33983
34251
  }).on("click", function(evt) {
33984
34252
  RED.actions.invoke('core:copy-item-url',selectedObject)
@@ -33987,7 +34255,7 @@ RED.sidebar.info = (function() {
33987
34255
 
33988
34256
  propertiesPanelHeaderHelp = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-book"></button>').css({
33989
34257
  position: 'absolute',
33990
- top: '12px',
34258
+ top: '6px',
33991
34259
  right: '56px'
33992
34260
  }).on("click", function(evt) {
33993
34261
  evt.preventDefault();
@@ -34000,7 +34268,7 @@ RED.sidebar.info = (function() {
34000
34268
 
34001
34269
  propertiesPanelHeaderReveal = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-search"></button>').css({
34002
34270
  position: 'absolute',
34003
- top: '12px',
34271
+ top: '6px',
34004
34272
  right: '8px'
34005
34273
  }).on("click", function(evt) {
34006
34274
  evt.preventDefault();
@@ -34019,17 +34287,16 @@ RED.sidebar.info = (function() {
34019
34287
  }).appendTo(propertiesPanel);
34020
34288
 
34021
34289
 
34022
- panels = RED.panels.create({container: stackContainer})
34023
- panels.ratio(0.6);
34024
- RED.sidebar.info.outliner.build().appendTo(outlinerPanel);
34025
-
34290
+ // panels = RED.panels.create({container: stackContainer})
34291
+ // panels.ratio(0.6);
34292
+ // RED.sidebar.info.outliner.build().appendTo(outlinerPanel);
34026
34293
 
34027
34294
  RED.sidebar.addTab({
34028
34295
  id: "info",
34029
34296
  // target: "secondary",
34030
34297
  label: RED._("sidebar.info.label"),
34031
34298
  name: RED._("sidebar.info.name"),
34032
- icon: "red/images/explorer.svg",
34299
+ iconClass: "fa fa-info",
34033
34300
  action:"core:show-info-tab",
34034
34301
  content: content,
34035
34302
  pinned: true,
@@ -35204,9 +35471,30 @@ RED.sidebar.info = (function() {
35204
35471
  function onSelectionChanged(selection) {
35205
35472
  // treeList.treeList('clearSelection');
35206
35473
  }
35474
+ function show() {
35475
+ RED.sidebar.show("explorer");
35476
+ }
35477
+ function init() {
35478
+ const content = build()
35479
+
35480
+ RED.actions.add("core:show-explorer-tab",show);
35481
+
35482
+
35483
+ RED.sidebar.addTab({
35484
+ id: "explorer",
35485
+ // target: "secondary",
35486
+ label: 'Explorer', // RED._("sidebar.info.label"),
35487
+ name: 'Explorer', //RED._("sidebar.info.name"),
35488
+ icon: "red/images/explorer.svg",
35489
+ action:"core:show-explorer-tab",
35490
+ content: content,
35491
+ pinned: true,
35492
+ enableOnEdit: true
35493
+ });
35494
+ }
35207
35495
 
35208
35496
  return {
35209
- build: build,
35497
+ init,
35210
35498
  search: function(val) {
35211
35499
  searchInput.searchBox('value',val)
35212
35500
  },
@@ -46846,14 +47134,14 @@ RED.eventLog = (function() {
46846
47134
  }
46847
47135
  function showTray(options) {
46848
47136
  var el = $('<div class="red-ui-tray"></div>');
46849
- // `editor-tray-header` is deprecated - use red-ui-tray-body instead
46850
- var header = $('<div class="red-ui-tray-header editor-tray-header"></div>').appendTo(el);
46851
- var bodyWrapper = $('<div class="red-ui-tray-body-wrapper"></div>').appendTo(el);
46852
- // `editor-tray-body` is deprecated - use red-ui-tray-body instead
46853
- var body = $('<div class="red-ui-tray-body editor-tray-body"></div>').appendTo(bodyWrapper);
46854
- // `editor-tray-footer` is deprecated - use red-ui-tray-footer instead
46855
- var footer = $('<div class="red-ui-tray-footer"></div>').appendTo(el);
46856
47137
  var resizer = $('<div class="red-ui-tray-resize-handle"></div>').appendTo(el);
47138
+ var wrapper = $('<div class="red-ui-tray-wrapper"></div>').appendTo(el);
47139
+
47140
+ var header = $('<div class="red-ui-tray-header"></div>').appendTo(wrapper);
47141
+ var bodyWrapper = $('<div class="red-ui-tray-body-wrapper"></div>').appendTo(wrapper);
47142
+ var body = $('<div class="red-ui-tray-body"></div>').appendTo(bodyWrapper);
47143
+ // `editor-tray-footer` is deprecated - use red-ui-tray-footer instead
47144
+ var footer = $('<div class="red-ui-tray-footer"></div>').appendTo(wrapper);
46857
47145
  // var growButton = $('<a class="red-ui-tray-resize-button" style="cursor: w-resize;"><i class="fa fa-angle-left"></i></a>').appendTo(resizer);
46858
47146
  // var shrinkButton = $('<a class="red-ui-tray-resize-button" style="cursor: e-resize;"><i style="margin-left: 1px;" class="fa fa-angle-right"></i></a>').appendTo(resizer);
46859
47147
  if (options.title) {
@@ -47015,8 +47303,8 @@ RED.eventLog = (function() {
47015
47303
  }
47016
47304
 
47017
47305
  function handleWindowResize() {
47018
- let sidebarWidth = $("#red-ui-sidebar").is(":visible") ? $("#red-ui-sidebar").outerWidth() + $("#red-ui-sidebar-separator").outerWidth() : 0;
47019
- $("#red-ui-editor-stack").css('right', sidebarWidth + $("#red-ui-sidebar-tab-bar").outerWidth() + 1);
47306
+ let sidebarWidth = $("#red-ui-sidebar").is(":visible") ? $("#red-ui-sidebar").outerWidth() : 0;
47307
+ $("#red-ui-editor-stack").css('right', sidebarWidth + $("#red-ui-sidebar + .red-ui-sidebar-tab-bar").outerWidth() + 4);
47020
47308
  if (stack.length > 0) {
47021
47309
  var tray = stack[stack.length-1];
47022
47310
  if (tray.options.maximized || tray.width > $("#red-ui-editor-stack").position().left-8) {
@@ -47041,11 +47329,11 @@ RED.eventLog = (function() {
47041
47329
  function raiseTrayZ() {
47042
47330
  setTimeout(function(){
47043
47331
  $('#red-ui-editor-stack').css("zIndex","13");
47044
- },300);
47332
+ },100);
47045
47333
  }
47046
47334
  //lower tray z-index back to original place for correct slide animation (related to fix for editor context menu clipped by sidebar)
47047
47335
  function lowerTrayZ(){
47048
- $('#red-ui-editor-stack').css("zIndex","9");
47336
+ $('#red-ui-editor-stack').css("zIndex","11");
47049
47337
  }
47050
47338
 
47051
47339
  return {