mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge pull request #2655 from node-red/reorder-sidebar
Reorderable sidebar tabs
This commit is contained in:
		@@ -29,7 +29,7 @@ RED.tabs = (function() {
 | 
			
		||||
        var currentTabWidth;
 | 
			
		||||
        var currentActiveTabWidth = 0;
 | 
			
		||||
        var collapsibleMenu;
 | 
			
		||||
 | 
			
		||||
        var preferredOrder = options.order;
 | 
			
		||||
        var ul = options.element || $("#"+options.id);
 | 
			
		||||
        var wrapper = ul.wrap( "<div>" ).parent();
 | 
			
		||||
        var scrollContainer = ul.wrap( "<div>" ).parent();
 | 
			
		||||
@@ -132,11 +132,11 @@ RED.tabs = (function() {
 | 
			
		||||
                                    activateTab(id);
 | 
			
		||||
                                }
 | 
			
		||||
                            };
 | 
			
		||||
                            if (tabs[id].pinned) {
 | 
			
		||||
                                pinnedOptions.push(opt);
 | 
			
		||||
                            } else {
 | 
			
		||||
                            // if (tabs[id].pinned) {
 | 
			
		||||
                            //     pinnedOptions.push(opt);
 | 
			
		||||
                            // } else {
 | 
			
		||||
                                options.push(opt);
 | 
			
		||||
                            }
 | 
			
		||||
                            // }
 | 
			
		||||
                        });
 | 
			
		||||
                        options = pinnedOptions.concat(options);
 | 
			
		||||
                        collapsibleMenu = RED.menu.init({options: options});
 | 
			
		||||
@@ -363,23 +363,39 @@ RED.tabs = (function() {
 | 
			
		||||
            var tabWidth;
 | 
			
		||||
 | 
			
		||||
            if (options.collapsible) {
 | 
			
		||||
                var availableCount = collapsedButtonsRow.children().length;
 | 
			
		||||
                var visibleCount = collapsedButtonsRow.children(":visible").length;
 | 
			
		||||
                tabWidth = width - collapsedButtonsRow.width()-10;
 | 
			
		||||
                if (tabWidth < 198) {
 | 
			
		||||
                    var delta = 198 - tabWidth;
 | 
			
		||||
                var maxTabWidth = 198;
 | 
			
		||||
                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 index = collapsedButtonsRow.children().length - 2;
 | 
			
		||||
                    // Work backwards to find the first visible button
 | 
			
		||||
                    while (b.is(":not(:visible)")) {
 | 
			
		||||
                        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();
 | 
			
		||||
                    }
 | 
			
		||||
                    tabWidth = width - collapsedButtonsRow.width()-10;
 | 
			
		||||
                    tabWidth = Math.max(minTabWidth,width - collapsedButtonsRow.width()-10);
 | 
			
		||||
                } 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) {
 | 
			
		||||
                        collapsedButtonsRow.find("a:not(:visible):first").show();
 | 
			
		||||
                        tabWidth = width - collapsedButtonsRow.width()-10;
 | 
			
		||||
                    }
 | 
			
		||||
                    tabWidth = width - collapsedButtonsRow.width()-10;
 | 
			
		||||
                }
 | 
			
		||||
                tabs.css({width:tabWidth});
 | 
			
		||||
 | 
			
		||||
@@ -469,7 +485,7 @@ RED.tabs = (function() {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
        var tabAPI =  {
 | 
			
		||||
            addTab: function(tab,targetIndex) {
 | 
			
		||||
                if (options.onselect) {
 | 
			
		||||
                    var selection = ul.find("li.red-ui-tab.selected");
 | 
			
		||||
@@ -531,11 +547,92 @@ RED.tabs = (function() {
 | 
			
		||||
                        evt.preventDefault();
 | 
			
		||||
                        activateTab(tab.id);
 | 
			
		||||
                    });
 | 
			
		||||
                    pinnedLink.data("tabId",tab.id)
 | 
			
		||||
                    if (tab.pinned) {
 | 
			
		||||
                        pinnedLink.addClass("red-ui-tab-link-button-pinned");
 | 
			
		||||
                        pinnedTabsCount++;
 | 
			
		||||
                    }
 | 
			
		||||
                    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);
 | 
			
		||||
@@ -565,7 +662,7 @@ RED.tabs = (function() {
 | 
			
		||||
                if (ul.find("li.red-ui-tab").length == 1) {
 | 
			
		||||
                    activateTab(link);
 | 
			
		||||
                }
 | 
			
		||||
                if (options.onreorder) {
 | 
			
		||||
                if (options.onreorder && !options.collapsible) {
 | 
			
		||||
                    var originalTabOrder;
 | 
			
		||||
                    var tabDragIndex;
 | 
			
		||||
                    var tabElements = [];
 | 
			
		||||
@@ -652,6 +749,9 @@ RED.tabs = (function() {
 | 
			
		||||
                    collapsibleMenu.remove();
 | 
			
		||||
                    collapsibleMenu = null;
 | 
			
		||||
                }
 | 
			
		||||
                if (preferredOrder) {
 | 
			
		||||
                    tabAPI.order(preferredOrder);
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            removeTab: removeTab,
 | 
			
		||||
            activateTab: activateTab,
 | 
			
		||||
@@ -673,10 +773,8 @@ RED.tabs = (function() {
 | 
			
		||||
            },
 | 
			
		||||
            selection: getSelection,
 | 
			
		||||
            order: function(order) {
 | 
			
		||||
                preferredOrder = order;
 | 
			
		||||
                var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));
 | 
			
		||||
                if (existingTabOrder.length !== order.length) {
 | 
			
		||||
                    return
 | 
			
		||||
                }
 | 
			
		||||
                var i;
 | 
			
		||||
                var match = true;
 | 
			
		||||
                for (i=0;i<order.length;i++) {
 | 
			
		||||
@@ -692,12 +790,41 @@ RED.tabs = (function() {
 | 
			
		||||
                var existingTabs = ul.children().detach().each(function() {
 | 
			
		||||
                    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++) {
 | 
			
		||||
                    existingTabMap[order[i]].appendTo(ul);
 | 
			
		||||
                    if (existingTabMap[order[i]]) {
 | 
			
		||||
                        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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -232,7 +232,11 @@ RED.sidebar = (function() {
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            // 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
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user