1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #2655 from node-red/reorder-sidebar

Reorderable sidebar tabs
This commit is contained in:
Nick O'Leary 2020-09-03 14:07:17 +01:00 committed by GitHub
commit 3ad1803057
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 150 additions and 19 deletions

View File

@ -29,7 +29,7 @@ RED.tabs = (function() {
var currentTabWidth; var currentTabWidth;
var currentActiveTabWidth = 0; var currentActiveTabWidth = 0;
var collapsibleMenu; var collapsibleMenu;
var preferredOrder = options.order;
var ul = options.element || $("#"+options.id); var ul = options.element || $("#"+options.id);
var wrapper = ul.wrap( "<div>" ).parent(); var wrapper = ul.wrap( "<div>" ).parent();
var scrollContainer = ul.wrap( "<div>" ).parent(); var scrollContainer = ul.wrap( "<div>" ).parent();
@ -132,11 +132,11 @@ RED.tabs = (function() {
activateTab(id); activateTab(id);
} }
}; };
if (tabs[id].pinned) { // if (tabs[id].pinned) {
pinnedOptions.push(opt); // pinnedOptions.push(opt);
} else { // } else {
options.push(opt); options.push(opt);
} // }
}); });
options = pinnedOptions.concat(options); options = pinnedOptions.concat(options);
collapsibleMenu = RED.menu.init({options: options}); collapsibleMenu = RED.menu.init({options: options});
@ -363,23 +363,39 @@ RED.tabs = (function() {
var tabWidth; var tabWidth;
if (options.collapsible) { if (options.collapsible) {
var availableCount = collapsedButtonsRow.children().length;
var visibleCount = collapsedButtonsRow.children(":visible").length;
tabWidth = width - collapsedButtonsRow.width()-10; tabWidth = width - collapsedButtonsRow.width()-10;
if (tabWidth < 198) { var maxTabWidth = 198;
var delta = 198 - tabWidth; var minTabWidth = 80;
if (tabWidth <= minTabWidth || (tabWidth < maxTabWidth && visibleCount > 5)) {
// The tab is too small. Hide the next button to make room
// Start at the end of the button row, -1 for the menu button
var b = collapsedButtonsRow.find("a:last").prev(); var b = collapsedButtonsRow.find("a:last").prev();
var index = collapsedButtonsRow.children().length - 2;
// Work backwards to find the first visible button
while (b.is(":not(:visible)")) { while (b.is(":not(:visible)")) {
b = b.prev(); b = b.prev();
index--;
} }
if (!b.hasClass("red-ui-tab-link-button-pinned")) { // If it isn't a pinned button, hide it to get the room
if (tabWidth <= minTabWidth || visibleCount>6) {//}!b.hasClass("red-ui-tab-link-button-pinned")) {
b.hide(); b.hide();
} }
tabWidth = width - collapsedButtonsRow.width()-10; tabWidth = Math.max(minTabWidth,width - collapsedButtonsRow.width()-10);
} else { } else {
var space = width - 198 - collapsedButtonsRow.width(); if (visibleCount !== availableCount) {
if (visibleCount < 6) {
tabWidth = minTabWidth;
} else {
tabWidth = maxTabWidth;
}
}
var space = width - tabWidth - collapsedButtonsRow.width();
if (space > 40) { if (space > 40) {
collapsedButtonsRow.find("a:not(:visible):first").show(); collapsedButtonsRow.find("a:not(:visible):first").show();
tabWidth = width - collapsedButtonsRow.width()-10;
} }
tabWidth = width - collapsedButtonsRow.width()-10;
} }
tabs.css({width:tabWidth}); tabs.css({width:tabWidth});
@ -469,7 +485,7 @@ RED.tabs = (function() {
} }
} }
return { var tabAPI = {
addTab: function(tab,targetIndex) { addTab: function(tab,targetIndex) {
if (options.onselect) { if (options.onselect) {
var selection = ul.find("li.red-ui-tab.selected"); var selection = ul.find("li.red-ui-tab.selected");
@ -531,11 +547,92 @@ RED.tabs = (function() {
evt.preventDefault(); evt.preventDefault();
activateTab(tab.id); activateTab(tab.id);
}); });
pinnedLink.data("tabId",tab.id)
if (tab.pinned) { if (tab.pinned) {
pinnedLink.addClass("red-ui-tab-link-button-pinned"); pinnedLink.addClass("red-ui-tab-link-button-pinned");
pinnedTabsCount++; pinnedTabsCount++;
} }
RED.popover.tooltip($(pinnedLink), tab.name, tab.action); RED.popover.tooltip($(pinnedLink), tab.name, tab.action);
if (options.onreorder) {
var pinnedLinkIndex;
var pinnedLinks = [];
var startPinnedIndex;
pinnedLink.draggable({
distance: 10,
axis:"x",
containment: ".red-ui-tab-link-buttons",
start: function(event,ui) {
dragActive = true;
$(".red-ui-tab-link-buttons").width($(".red-ui-tab-link-buttons").width());
if (dblClickArmed) { dblClickArmed = false; return false }
collapsedButtonsRow.children().each(function(i) {
pinnedLinks[i] = {
el:$(this),
text: $(this).text(),
left: $(this).position().left,
width: $(this).width(),
menu: $(this).hasClass("red-ui-tab-link-button-menu")
};
if ($(this).is(pinnedLink)) {
pinnedLinkIndex = i;
startPinnedIndex = i;
}
});
collapsedButtonsRow.children().each(function(i) {
if (i!==pinnedLinkIndex) {
$(this).css({
position: 'absolute',
left: pinnedLinks[i].left+"px",
width: pinnedLinks[i].width+2,
transition: "left 0.3s"
});
}
})
if (!pinnedLink.hasClass('active')) {
pinnedLink.css({'zIndex':1});
}
},
drag: function(event,ui) {
ui.position.left += pinnedLinks[pinnedLinkIndex].left;
var tabCenter = ui.position.left + pinnedLinks[pinnedLinkIndex].width/2;
for (var i=0;i<pinnedLinks.length;i++) {
if (i === pinnedLinkIndex || pinnedLinks[i].menu || pinnedLinks[i].el.is(":not(:visible)")) {
continue;
}
if (tabCenter > pinnedLinks[i].left && tabCenter < pinnedLinks[i].left+pinnedLinks[i].width) {
if (i < pinnedLinkIndex) {
pinnedLinks[i].left += pinnedLinks[pinnedLinkIndex].width+8;
pinnedLinks[pinnedLinkIndex].el.detach().insertBefore(pinnedLinks[i].el);
} else {
pinnedLinks[i].left -= pinnedLinks[pinnedLinkIndex].width+8;
pinnedLinks[pinnedLinkIndex].el.detach().insertAfter(pinnedLinks[i].el);
}
pinnedLinks[i].el.css({left:pinnedLinks[i].left+"px"});
pinnedLinks.splice(i, 0, pinnedLinks.splice(pinnedLinkIndex, 1)[0]);
pinnedLinkIndex = i;
break;
}
}
},
stop: function(event,ui) {
collapsedButtonsRow.children().css({position:"relative",left:"",transition:""});
$(".red-ui-tab-link-buttons").width('auto');
pinnedLink.css({zIndex:""});
updateTabWidths();
if (startPinnedIndex !== pinnedLinkIndex) {
if (collapsibleMenu) {
collapsibleMenu.remove();
collapsibleMenu = null;
}
var newOrder = $.makeArray(collapsedButtonsRow.children().map(function() { return $(this).data('tabId');}));
tabAPI.order(newOrder);
options.onreorder(newOrder);
}
}
});
}
} }
link.on("mouseup",onTabClick); link.on("mouseup",onTabClick);
@ -565,7 +662,7 @@ RED.tabs = (function() {
if (ul.find("li.red-ui-tab").length == 1) { if (ul.find("li.red-ui-tab").length == 1) {
activateTab(link); activateTab(link);
} }
if (options.onreorder) { if (options.onreorder && !options.collapsible) {
var originalTabOrder; var originalTabOrder;
var tabDragIndex; var tabDragIndex;
var tabElements = []; var tabElements = [];
@ -652,6 +749,9 @@ RED.tabs = (function() {
collapsibleMenu.remove(); collapsibleMenu.remove();
collapsibleMenu = null; collapsibleMenu = null;
} }
if (preferredOrder) {
tabAPI.order(preferredOrder);
}
}, },
removeTab: removeTab, removeTab: removeTab,
activateTab: activateTab, activateTab: activateTab,
@ -673,10 +773,8 @@ RED.tabs = (function() {
}, },
selection: getSelection, selection: getSelection,
order: function(order) { order: function(order) {
preferredOrder = order;
var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');})); var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));
if (existingTabOrder.length !== order.length) {
return
}
var i; var i;
var match = true; var match = true;
for (i=0;i<order.length;i++) { for (i=0;i<order.length;i++) {
@ -692,13 +790,42 @@ RED.tabs = (function() {
var existingTabs = ul.children().detach().each(function() { var existingTabs = ul.children().detach().each(function() {
existingTabMap[$(this).data("tabId")] = $(this); existingTabMap[$(this).data("tabId")] = $(this);
}); });
var pinnedButtons = {};
if (options.collapsible) {
collapsedButtonsRow.children().detach().each(function() {
var id = $(this).data("tabId");
if (!id) {
id = "__menu__"
}
pinnedButtons[id] = $(this);
});
}
for (i=0;i<order.length;i++) { for (i=0;i<order.length;i++) {
if (existingTabMap[order[i]]) {
existingTabMap[order[i]].appendTo(ul); existingTabMap[order[i]].appendTo(ul);
if (options.collapsible) {
pinnedButtons[order[i]].appendTo(collapsedButtonsRow);
}
delete existingTabMap[order[i]];
} }
} }
// Add any tabs that aren't known in the order
for (i in existingTabMap) {
if (existingTabMap.hasOwnProperty(i)) {
existingTabMap[i].appendTo(ul);
if (options.collapsible) {
pinnedButtons[i].appendTo(collapsedButtonsRow);
} }
} }
}
if (options.collapsible) {
pinnedButtons["__menu__"].appendTo(collapsedButtonsRow);
updateTabWidths();
}
}
}
return tabAPI;
}
return { return {
create: createTabs create: createTabs

View File

@ -232,7 +232,11 @@ RED.sidebar = (function() {
} }
}, },
// minimumActiveTabWidth: 70, // minimumActiveTabWidth: 70,
collapsible: true collapsible: true,
onreorder: function(order) {
RED.settings.set("editor.sidebar.order",order);
},
order: RED.settings.get("editor.sidebar.order",["info", "help", "version-control", "debug"])
// scrollable: true // scrollable: true
}); });