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

Scrollable tabs 👍

This commit is contained in:
Nick O'Leary 2016-09-26 22:56:28 +01:00
parent 1866c9c7ef
commit e4626ee52b
5 changed files with 258 additions and 130 deletions

View File

@ -17,15 +17,58 @@
RED.tabs = (function() {
function createTabs(options) {
var tabs = {};
var currentTabWidth;
var currentActiveTabWidth = 0;
var ul = $("#"+options.id);
ul.addClass("red-ui-tabs");
var wrapper = ul.wrap( "<div>" ).parent();
var scrollContainer = ul.wrap( "<div>" ).parent();
wrapper.addClass("red-ui-tabs");
if (options.addButton && typeof options.addButton === 'function') {
wrapper.addClass("red-ui-tabs-add");
var addButton = $('<div class="red-ui-tab-button"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
addButton.find('a').click(function(evt) {
evt.preventDefault();
options.addButton();
})
}
var scrollLeft;
var scrollRight;
if (options.scrollable) {
wrapper.addClass("red-ui-tabs-scrollable");
scrollContainer.addClass("red-ui-tabs-scroll-container");
scrollContainer.scroll(updateScroll);
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
scrollLeft.on('mousedown',function(evt) { scrollEventHandler(evt,'-=150') });
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') });
}
function scrollEventHandler(evt,dir) {
evt.preventDefault();
if ($(this).hasClass('disabled')) {
return;
}
var currentScrollLeft = scrollContainer.scrollLeft();
scrollContainer.animate( { scrollLeft: dir }, 300);
var interval = setInterval(function() {
var newScrollLeft = scrollContainer.scrollLeft()
if (newScrollLeft === currentScrollLeft) {
clearInterval(interval);
return;
}
currentScrollLeft = newScrollLeft;
scrollContainer.animate( { scrollLeft: dir }, 300);
},300);
$(this).one('mouseup',function() {
clearInterval(interval);
})
}
ul.children().first().addClass("active");
ul.children().addClass("red-ui-tab");
@ -34,6 +77,23 @@ RED.tabs = (function() {
return false;
}
function updateScroll() {
if (ul.children().length !== 0) {
var sl = scrollContainer.scrollLeft();
var scWidth = scrollContainer.width();
var ulWidth = ul.width();
if (sl === 0) {
scrollLeft.hide();
} else {
scrollLeft.show();
}
if (sl === ulWidth-scWidth) {
scrollRight.hide();
} else {
scrollRight.show();
}
}
}
function onTabDblClick() {
if (options.ondblclick) {
options.ondblclick(tabs[$(this).attr('href').slice(1)]);
@ -49,6 +109,14 @@ RED.tabs = (function() {
ul.children().removeClass("active");
ul.children().css({"transition": "width 100ms"});
link.parent().addClass("active");
if (options.scrollable) {
var pos = link.parent().position().left;
if (pos-21 < 0) {
scrollContainer.animate( { scrollLeft: '+='+(pos-50) }, 300);
} else if (pos + 120 > scrollContainer.width()) {
scrollContainer.animate( { scrollLeft: '+='+(pos + 140-scrollContainer.width()) }, 300);
}
}
if (options.onchange) {
options.onchange(tabs[link.attr('href').slice(1)]);
}
@ -61,23 +129,29 @@ RED.tabs = (function() {
function updateTabWidths() {
var tabs = ul.find("li.red-ui-tab");
var width = ul.width();
var width = wrapper.width();
var tabCount = tabs.size();
var tabWidth = (width-12-(tabCount*6))/tabCount;
currentTabWidth = 100*tabWidth/width;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = currentTabWidth+"%";
if (options.hasOwnProperty("minimumActiveTabWidth")) {
if (options.scrollable) {
tabWidth = Math.max(tabWidth,140);
currentTabWidth = tabWidth+"px";
currentActiveTabWidth = 0;
var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
ul.width(listWidth);
updateScroll();
} else if (options.hasOwnProperty("minimumActiveTabWidth")) {
if (tabWidth < options.minimumActiveTabWidth) {
tabCount -= 1;
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
currentTabWidth = 100*tabWidth/width;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
} else {
currentActiveTabWidth = 0;
}
}
tabs.css({width:currentTabWidth+"%"});
tabs.css({width:currentTabWidth});
if (tabWidth < 50) {
ul.find(".red-ui-tab-close").hide();
ul.find(".red-ui-tab-icon").hide();
@ -97,7 +171,9 @@ RED.tabs = (function() {
}
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
setTimeout(function() {
updateTabWidths();
},0);
function removeTab(id) {
@ -210,8 +286,6 @@ RED.tabs = (function() {
break;
}
}
// console.log(ui.position.left,ui.offset.left);
},
stop: function(event,ui) {
ul.children().css({position:"relative",left:"",transition:""});

View File

@ -166,13 +166,16 @@ RED.workspaces = (function() {
RED.nodes.dirty(true);
setWorkspaceOrder(newOrder);
},
minimumActiveTabWidth: 150
minimumActiveTabWidth: 150,
scrollable: true,
addButton: function() {
addWorkspace();
}
});
}
function init() {
createWorkspaceTabs();
$('#btn-workspace-add-tab').on("click",function(e) {addWorkspace(); e.preventDefault()});
RED.events.on("sidebar:resize",workspace_tabs.resize);
RED.menu.setAction('menu-item-workspace-delete',function() {

View File

@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright 2015, 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,20 +14,34 @@
* limitations under the License.
**/
ul.red-ui-tabs {
.red-ui-tabs {
position: relative;
background: #fff;
overflow: hidden;
height: 35px;
box-sizing: border-box;
.red-ui-tabs-scroll-container {
height: 60px;
overflow-x: scroll;
overflow-y: hidden;
&::-webkit-scrollbar {
display: none;
}
}
& ul {
//background: #9999ff;
list-style-type: none;
padding:0;
margin: 0;
display: block;
height: 35px;
box-sizing:border-box;
white-space: nowrap;
border-bottom: 1px solid $primary-border-color;
background: #fff;
white-space: nowrap;
@include disable-selection;
}
ul.red-ui-tabs li {
li {
box-sizing: border-box;
display: inline-block;
border-left: 1px solid $primary-border-color;
@ -42,9 +56,9 @@ ul.red-ui-tabs li {
width: 14%;
overflow: hidden;
white-space: nowrap;
}
position: relative;
ul.red-ui-tabs li a.red-ui-tab-label {
a.red-ui-tab-label {
display: block;
font-size: 14px;
padding-left: 12px;
@ -52,9 +66,122 @@ ul.red-ui-tabs li a.red-ui-tab-label {
height: 100%;
color: #666;
}
ul.red-ui-tabs li {
position: relative;
a:hover {
text-decoration: none;
}
a:focus {
text-decoration: none;
}
&:not(.active) a:hover+a.red-ui-tab-close {
background: $tab-background-hover;
}
&.active {
background: $tab-background-active;
font-weight: bold;
border-bottom: 1px solid #fff;
z-index: 2;
a {
color: #333;
}
a.red-ui-tab-close {
color: #aaa;
background: $tab-background-active;
&:hover {
background: $workspace-button-background-hover !important;
color: $workspace-button-color-hover;
}
}
.red-ui-tab-icon {
opacity: 0.2;
}
}
&:not(.active) a:hover {
color: $workspace-button-color-hover;
background: $tab-background-hover;
}
}
}
&.red-ui-tabs-scrollable {
padding-left: 21px;
padding-right: 21px;
}
&.red-ui-tabs-add {
padding-right: 35px;
}
&.red-ui-tabs-add.red-ui-tabs-scrollable {
padding-right: 59px;
}
}
.red-ui-tab-button {
position: absolute;
box-sizing: border-box;
top: 0;
right: 0;
height: 35px;
background: #fff;
border-bottom: 1px solid $primary-border-color;
z-index: 3;
a {
@include workspace-button;
line-height: 32px;
height: 32px;
width: 32px;
margin-top: 3px;
margin-right:3px;
margin-left:3px;
border: 1px solid $primary-border-color;
z-index: 3;
}
}
.red-ui-tab-scroll {
width: 21px;
top: 0;
a {
height: 35px;
width: 21px;
display: block;
color: $link-color;
font-size: 22px;
text-align: center;
margin:0;
border-left: none;
border-right: none;
border-top: none;
}
}
.red-ui-tab-scroll-left {
left:0;
a {
border-right: 1px solid $primary-border-color;
// box-shadow: 8px 0px 5px -2px rgba(0,0,0,0.1);
}
}
.red-ui-tab-scroll-right {
right: 0px;
a {
border-left: 1px solid $primary-border-color;
// box-shadow: -8px 0px 5px -2px rgba(0,0,0,0.1);
}
}
.red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right {
right: 38px;
}
.red-ui-tab-icon {
margin-left: -8px;
margin-right: 3px;
margin-top: -2px;
opacity: 0.1;
width: 20px;
height: 20px;
vertical-align: middle;
}
.red-ui-tabs-badges {
position: absolute;
top:2px;
@ -96,51 +223,3 @@ ul.red-ui-tabs li {
opacity: 1;
}
}
ul.red-ui-tabs li:not(.active) a:hover+a.red-ui-tab-close {
background: $tab-background-hover;
}
ul.red-ui-tabs li.active a.red-ui-tab-close {
color: #aaa;
background: $tab-background-active;
&:hover {
background: $workspace-button-background-hover !important;
color: $workspace-button-color-hover;
}
}
ul.red-ui-tabs li a:hover {
text-decoration: none;
}
ul.red-ui-tabs li:not(.active) a:hover {
color: $workspace-button-color-hover;
background: $tab-background-hover;
}
ul.red-ui-tabs li a:focus {
text-decoration: none;
}
ul.red-ui-tabs li.active {
background: $tab-background-active;
font-weight: bold;
border-bottom: 1px solid #fff;
z-index: 2;
}
ul.red-ui-tabs li.active a {
color: #333;
}
.red-ui-tab-icon {
margin-left: -8px;
margin-right: 3px;
margin-top: -2px;
opacity: 0.1;
width: 20px;
height: 20px;
vertical-align: middle;
}
ul.red-ui-tabs li.active .red-ui-tab-icon {
opacity: 0.2;
}

View File

@ -48,33 +48,6 @@
@include component-footer-button;
}
#workspace-tabs {
margin-right: 35px;
}
#workspace-add-tab {
position: absolute;
box-sizing: border-box;
top: 0;
right: 0;
height: 35px;
width: 35px;
background: #fff;
border-bottom: 1px solid $primary-border-color;
}
#btn-workspace-add-tab {
@include workspace-button;
line-height: 32px;
height: 32px;
width: 32px;
margin-top: 3px;
margin-right:3px;
border: 1px solid $primary-border-color;
}
#workspace-footer {
@include component-footer;
}

View File

@ -45,7 +45,6 @@
<div id="main-container" class="sidebar-closed hide">
<div id="workspace">
<ul id="workspace-tabs"></ul>
<div id="workspace-add-tab"><a id="btn-workspace-add-tab" href="#"><i class="fa fa-plus"></i></a></div>
<div id="chart" tabindex="1"></div>
<div id="workspace-toolbar"></div>
<div id="workspace-footer">