/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ RED.tabs = (function() { var defaultTabIcon = "fa fa-lemon-o"; var dragActive = false; var dblClickTime; var dblClickArmed = false; function createTabs(options) { var tabs = {}; var pinnedTabsCount = 0; var currentTabWidth; var currentActiveTabWidth = 0; var collapsibleMenu; var mousedownTab; var preferredOrder = options.order; var ul = options.element || $("#"+options.id); var wrapper = ul.wrap( "
" ).parent(); var scrollContainer = ul.wrap( "
" ).parent(); wrapper.addClass("red-ui-tabs"); if (options.vertical) { wrapper.addClass("red-ui-tabs-vertical"); } if (options.addButton) { wrapper.addClass("red-ui-tabs-add"); var addButton = $('
').appendTo(wrapper); addButton.find('a').on("click", function(evt) { evt.preventDefault(); if (typeof options.addButton === 'function') { options.addButton(); } else if (typeof options.addButton === 'string') { RED.actions.invoke(options.addButton); } }) if (typeof options.addButton === 'string') { var l = options.addButton; if (options.addButtonCaption) { l = options.addButtonCaption } RED.popover.tooltip(addButton,l,options.addButton); } ul.on("dblclick", function(evt) { var existingTabs = ul.children(); var clickX = evt.clientX; var targetIndex = 0; existingTabs.each(function(index) { var pos = $(this).offset(); if (pos.left > clickX) { return false; } targetIndex = index+1; }) if (typeof options.addButton === 'function') { options.addButton({index:targetIndex}); } else if (typeof options.addButton === 'string') { RED.actions.invoke(options.addButton,{index:targetIndex}); } }); } if (options.searchButton) { // This is soft-deprecated as we don't use this in the core anymore // We no use the `menu` option to provide a drop-down list of actions wrapper.addClass("red-ui-tabs-search"); var searchButton = $('').appendTo(wrapper); searchButton.find('a').on("click", function(evt) { evt.preventDefault(); if (typeof options.searchButton === 'function') { options.searchButton() } else if (typeof options.searchButton === 'string') { RED.actions.invoke(options.searchButton); } }) if (typeof options.searchButton === 'string') { var l = options.searchButton; if (options.searchButtonCaption) { l = options.searchButtonCaption } RED.popover.tooltip(searchButton,l,options.searchButton); } } if (options.menu) { wrapper.addClass("red-ui-tabs-menu"); var menuButton = $('
').appendTo(wrapper); var menuButtonLink = menuButton.find('a') var menuOpen = false; var menu; menuButtonLink.on("click", function(evt) { evt.stopPropagation(); evt.preventDefault(); if (menuOpen) { menu.remove(); menuOpen = false; return; } menuOpen = true; var menuOptions = []; if (typeof options.searchButton === 'function') { menuOptions = options.menu() } else if (Array.isArray(options.menu)) { menuOptions = options.menu; } else if (typeof options.menu === 'function') { menuOptions = options.menu(); } menu = RED.menu.init({options: menuOptions}); menu.attr("id",options.id+"-menu"); menu.css({ position: "absolute" }) menu.appendTo("body"); var elementPos = menuButton.offset(); menu.css({ top: (elementPos.top+menuButton.height()-2)+"px", left: (elementPos.left - menu.width() + menuButton.width())+"px" }) $(".red-ui-menu.red-ui-menu-dropdown").hide(); $(document).on("click.red-ui-tabmenu", function(evt) { $(document).off("click.red-ui-tabmenu"); menuOpen = false; menu.remove(); }); menu.show(); }) } if (options.contextmenu) { wrapper.on('contextmenu', function(evt) { let clickedTab let target = evt.target while(target.nodeName !== 'A' && target.nodeName !== 'UL' && target.nodeName !== 'BODY') { target = target.parentNode } if (target.nodeName === 'A') { const href = target.getAttribute('href') if (href) { clickedTab = tabs[href.slice(1)] } } evt.preventDefault() evt.stopPropagation() RED.contextMenu.show({ x:evt.clientX-5, y:evt.clientY-5, options: options.contextmenu(clickedTab) }) return false }) } var scrollLeft; var scrollRight; if (options.scrollable) { wrapper.addClass("red-ui-tabs-scrollable"); scrollContainer.addClass("red-ui-tabs-scroll-container"); scrollContainer.on("scroll",function(evt) { // Generated by trackpads - not mousewheel updateScroll(evt); }); scrollContainer.on("wheel", function(evt) { if (evt.originalEvent.deltaX === 0) { // Prevent the scroll event from firing evt.preventDefault(); // Assume this is wheel event which might not trigger // the scroll event, so do things manually var sl = scrollContainer.scrollLeft(); sl += evt.originalEvent.deltaY; scrollContainer.scrollLeft(sl); } }) scrollLeft = $('
').appendTo(wrapper).find("a"); scrollLeft.on('mousedown',function(evt) {scrollEventHandler(evt, evt.shiftKey?('-='+scrollContainer.scrollLeft()):'-=150') }).on('click',function(evt){ evt.preventDefault();}); scrollRight = $('
').appendTo(wrapper).find("a"); scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,evt.shiftKey?('+='+(scrollContainer[0].scrollWidth - scrollContainer.width()-scrollContainer.scrollLeft())):'+=150') }).on('click',function(evt){ evt.preventDefault();}); } if (options.collapsible) { // var dropDown = $('
',{class:"red-ui-tabs-select"}).appendTo(wrapper); // ul.hide(); wrapper.addClass("red-ui-tabs-collapsible"); var collapsedButtonsRow = $('').appendTo(wrapper); if (options.menu !== false) { var selectButton = $('').appendTo(collapsedButtonsRow); selectButton.addClass("red-ui-tab-link-button-menu") selectButton.on("click", function(evt) { evt.stopPropagation(); evt.preventDefault(); if (!collapsibleMenu) { var pinnedOptions = []; var options = []; ul.children().each(function(i,el) { var id = $(el).data('tabId'); var opt = { id:"red-ui-tabs-menu-option-"+id, icon: tabs[id].iconClass || defaultTabIcon, label: tabs[id].name, onselect: function() { activateTab(id); } }; // if (tabs[id].pinned) { // pinnedOptions.push(opt); // } else { options.push(opt); // } }); options = pinnedOptions.concat(options); collapsibleMenu = RED.menu.init({options: options}); collapsibleMenu.css({ position: "absolute" }) collapsibleMenu.appendTo("body"); } var elementPos = selectButton.offset(); collapsibleMenu.css({ top: (elementPos.top+selectButton.height()-2)+"px", left: (elementPos.left - collapsibleMenu.width() + selectButton.width())+"px" }) if (collapsibleMenu.is(":visible")) { $(document).off("click.red-ui-tabmenu"); } else { $(".red-ui-menu.red-ui-menu-dropdown").hide(); $(document).on("click.red-ui-tabmenu", function(evt) { $(document).off("click.red-ui-tabmenu"); collapsibleMenu.hide(); }); } collapsibleMenu.toggle(); }) } } function scrollEventHandler(evt,dir) { evt.preventDefault(); if ($(this).hasClass('disabled')) { return; } var currentScrollLeft = scrollContainer.scrollLeft(); scrollContainer.animate( { scrollLeft: dir }, 100); var interval = setInterval(function() { var newScrollLeft = scrollContainer.scrollLeft() if (newScrollLeft === currentScrollLeft) { clearInterval(interval); return; } currentScrollLeft = newScrollLeft; scrollContainer.animate( { scrollLeft: dir }, 100); },100); $(this).one('mouseup',function() { clearInterval(interval); }) } ul.children().first().addClass("active"); ul.children().addClass("red-ui-tab"); function getSelection() { var selection = ul.find("li.red-ui-tab.selected"); var selectedTabs = []; selection.each(function() { selectedTabs.push(tabs[$(this).find('a').attr('href').slice(1)]) }) return selectedTabs; } function selectionChanged() { options.onselect(getSelection()); } function onTabClick(evt) { if (dragActive) { return } if (evt.currentTarget !== mousedownTab) { mousedownTab = null; return; } mousedownTab = null; if (dblClickTime && Date.now()-dblClickTime < 400) { dblClickTime = 0; dblClickArmed = true; return onTabDblClick.call(this,evt); } dblClickTime = Date.now(); var currentTab = ul.find("li.red-ui-tab.active"); var thisTab = $(this).parent(); var fireSelectionChanged = false; if (options.onselect) { if (evt.metaKey || evt.ctrlKey) { if (thisTab.hasClass("selected")) { thisTab.removeClass("selected"); if (thisTab[0] !== currentTab[0]) { // Deselect background tab // - don't switch to it selectionChanged(); return; } else { // Deselect current tab // - if nothing remains selected, do nothing // - otherwise switch to first selected tab var selection = ul.find("li.red-ui-tab.selected"); if (selection.length === 0) { selectionChanged(); return; } thisTab = selection.first(); } } else { if (!currentTab.hasClass("selected")) { var currentTabObj = tabs[currentTab.find('a').attr('href').slice(1)]; // Auto select current tab currentTab.addClass("selected"); } thisTab.addClass("selected"); } fireSelectionChanged = true; } else if (evt.shiftKey) { if (currentTab[0] !== thisTab[0]) { var firstTab,lastTab; if (currentTab.index() < thisTab.index()) { firstTab = currentTab; lastTab = thisTab; } else { firstTab = thisTab; lastTab = currentTab; } ul.find("li.red-ui-tab").removeClass("selected"); firstTab.addClass("selected"); lastTab.addClass("selected"); firstTab.nextUntil(lastTab).addClass("selected"); } fireSelectionChanged = true; } else { var selection = ul.find("li.red-ui-tab.selected"); if (selection.length > 0) { selection.removeClass("selected"); fireSelectionChanged = true; } } } var thisTabA = thisTab.find("a"); if (options.onclick) { options.onclick(tabs[thisTabA.attr('href').slice(1)]); } activateTab(thisTabA); if (fireSelectionChanged) { selectionChanged(); } } 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(evt) { evt.preventDefault(); if (evt.metaKey || evt.shiftKey) { return; } if (options.ondblclick) { options.ondblclick(tabs[$(this).attr('href').slice(1)]); } return false; } function activateTab(link) { if (typeof link === "string") { link = ul.find("a[href='#"+link+"']"); } if (link.length === 0) { return; } if (link.parent().hasClass("hide-tab")) { link.parent().removeClass("hide-tab").removeClass("hide"); if (options.onshow) { options.onshow(tabs[link.attr('href').slice(1)]) } } if (!link.parent().hasClass("active")) { ul.children().removeClass("active"); ul.children().css({"transition": "width 100ms"}); link.parent().addClass("active"); var parentId = link.parent().attr('id'); wrapper.find(".red-ui-tab-link-button").removeClass("active selected"); $("#"+parentId+"-link-button").addClass("active selected"); 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)]); } updateTabWidths(); setTimeout(function() { ul.children().css({"transition": ""}); },100); } } function activatePreviousTab() { var previous = findPreviousVisibleTab(); if (previous.length > 0) { activateTab(previous.find("a")); } } function activateNextTab() { var next = findNextVisibleTab(); if (next.length > 0) { activateTab(next.find("a")); } } function updateTabWidths() { if (options.vertical) { return; } var allTabs = ul.find("li.red-ui-tab"); var tabs = allTabs.filter(":not(.hide-tab)"); var hiddenTabs = allTabs.filter(".hide-tab"); var width = wrapper.width(); var tabCount = tabs.length; var tabWidth; if (options.collapsible) { var availableCount = collapsedButtonsRow.children().length; var visibleCount = collapsedButtonsRow.children(":visible").length; tabWidth = width - collapsedButtonsRow.width()-10; var maxTabWidth = 198; var minTabWidth = 120; 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 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 = Math.max(minTabWidth,width - collapsedButtonsRow.width()-10); } else { 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; } tabs.css({width:tabWidth}); } else { var tabWidth = (width-12-(tabCount*6))/tabCount; currentTabWidth = (100*tabWidth/width)+"%"; currentActiveTabWidth = currentTabWidth+"%"; 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)+"%"; currentActiveTabWidth = options.minimumActiveTabWidth+"px"; } else { currentActiveTabWidth = 0; } } // if (options.collapsible) { // console.log(currentTabWidth); // } tabs.css({width:currentTabWidth}); hiddenTabs.css({width:"0px"}); if (tabWidth < 50) { // ul.find(".red-ui-tab-close").hide(); ul.find(".red-ui-tab-icon").hide(); ul.find(".red-ui-tab-label").css({paddingLeft:Math.min(12,Math.max(0,tabWidth-38))+"px"}) } else { // ul.find(".red-ui-tab-close").show(); ul.find(".red-ui-tab-icon").show(); ul.find(".red-ui-tab-label").css({paddingLeft:""}) } if (currentActiveTabWidth !== 0) { ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth}); // ul.find("li.red-ui-tab.active .red-ui-tab-close").show(); ul.find("li.red-ui-tab.active .red-ui-tab-icon").show(); ul.find("li.red-ui-tab.active .red-ui-tab-label").css({paddingLeft:""}) } } } ul.find("li.red-ui-tab a") .on("mousedown", function(evt) { mousedownTab = evt.currentTarget }) .on("mouseup",onTabClick) .on("click", function(evt) {evt.preventDefault(); }) .on("dblclick", function(evt) {evt.stopPropagation(); evt.preventDefault(); }) setTimeout(function() { updateTabWidths(); },0); function removeTab(id) { if (options.onselect) { var selection = ul.find("li.red-ui-tab.selected"); if (selection.length > 0) { selection.removeClass("selected"); selectionChanged(); } } var li = ul.find("a[href='#"+id+"']").parent(); if (li.hasClass("active")) { var tab = findPreviousVisibleTab(li); if (tab.length === 0) { tab = findNextVisibleTab(li); } if (tab.length > 0) { activateTab(tab.find("a")); } else { if (options.onchange) { options.onchange(null); } } } li.remove(); if (tabs[id].pinned) { pinnedTabsCount--; } if (options.onremove) { options.onremove(tabs[id]); } delete tabs[id]; updateTabWidths(); if (collapsibleMenu) { collapsibleMenu.remove(); collapsibleMenu = null; } } function findPreviousVisibleTab(li) { if (!li) { li = ul.find("li.active"); } var previous = li.prev(); while(previous.length > 0 && previous.hasClass("hide-tab")) { previous = previous.prev(); } return previous; } function findNextVisibleTab(li) { if (!li) { li = ul.find("li.active"); } var next = li.next(); while(next.length > 0 && next.hasClass("hide-tab")) { next = next.next(); } return next; } function showTab(id) { if (tabs[id]) { var li = ul.find("a[href='#"+id+"']").parent(); if (li.hasClass("hide-tab")) { li.removeClass("hide-tab").removeClass("hide"); if (ul.find("li.red-ui-tab:not(.hide-tab)").length === 1) { activateTab(li.find("a")) } updateTabWidths(); if (options.onshow) { options.onshow(tabs[id]) } } } } function hideTab(id) { if (tabs[id]) { var li = ul.find("a[href='#"+id+"']").parent(); if (!li.hasClass("hide-tab")) { if (li.hasClass("active")) { var tab = findPreviousVisibleTab(li); if (tab.length === 0) { tab = findNextVisibleTab(li); } if (tab.length > 0) { activateTab(tab.find("a")); } else { if (options.onchange) { options.onchange(null); } } } li.removeClass("active"); li.one("transitionend", function(evt) { li.addClass("hide"); updateTabWidths(); if (options.onhide) { options.onhide(tabs[id]) } setTimeout(function() { updateScroll() },200) }) li.addClass("hide-tab"); li.css({width:0}) } } } var tabAPI = { addTab: function(tab,targetIndex) { if (options.onselect) { var selection = ul.find("li.red-ui-tab.selected"); if (selection.length > 0) { selection.removeClass("selected"); selectionChanged(); } } tabs[tab.id] = tab; var li = $("
  • ",{class:"red-ui-tab"}); if (ul.children().length === 0) { targetIndex = undefined; } if (targetIndex === 0) { li.prependTo(ul); } else if (targetIndex > 0) { li.insertAfter(ul.find("li:nth-child("+(targetIndex)+")")); } else { li.appendTo(ul); } li.attr('id',"red-ui-tab-"+(tab.id.replace(".","-"))); li.data("tabId",tab.id); if (options.maximumTabWidth || tab.maximumTabWidth) { li.css("maxWidth",(options.maximumTabWidth || tab.maximumTabWidth) +"px"); } var link = $("",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li); if (tab.icon) { $('',{class:"red-ui-tab-icon", style:"mask-image: url("+tab.icon+"); -webkit-mask-image: url("+tab.icon+");"}).appendTo(link); } else if (tab.iconClass) { $('',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link); } var span = $('',{class:"red-ui-text-bidi-aware"}).text(tab.label).appendTo(link); span.attr('dir', RED.text.bidi.resolveBaseTextDir(tab.label)); if (options.collapsible) { li.addClass("red-ui-tab-pinned"); var pinnedLink = $(''); if (tab.pinned) { if (pinnedTabsCount === 0) { pinnedLink.prependTo(collapsedButtonsRow) } else { pinnedLink.insertAfter(collapsedButtonsRow.find("a.red-ui-tab-link-button-pinned:last")); } } else { if (options.menu !== false) { pinnedLink.insertBefore(collapsedButtonsRow.find("a:last")); } else { pinnedLink.appendTo(collapsedButtonsRow); } } pinnedLink.attr('id',li.attr('id')+"-link-button"); if (tab.iconClass) { $('',{class:tab.iconClass}).appendTo(pinnedLink); } else { $('',{class:defaultTabIcon}).appendTo(pinnedLink); } pinnedLink.on("click", function(evt) { 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[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) { dragActive = false; 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("mousedown", function(evt) { mousedownTab = evt.currentTarget }) link.on("mouseup",onTabClick); link.on("click", function(evt) { evt.preventDefault(); }) link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); }) $('').appendTo(li); if (tab.closeable) { li.addClass("red-ui-tabs-closeable") var closeLink = $("",{href:"#",class:"red-ui-tab-close"}).appendTo(li); closeLink.append(''); closeLink.on("click",function(event) { event.preventDefault(); removeTab(tab.id); }); RED.popover.tooltip(closeLink,RED._("workspace.closeFlow")); } // if (tab.hideable) { // li.addClass("red-ui-tabs-closeable") // var closeLink = $("",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li); // closeLink.append(''); // closeLink.append(''); // closeLink.on("click",function(event) { // event.preventDefault(); // hideTab(tab.id); // }); // RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); // } var badges = $('').appendTo(li); if (options.onselect) { $('').appendTo(badges); } // link.attr("title",tab.label); RED.popover.tooltip(link,function() { return RED.utils.sanitize(tab.label); }); if (options.onadd) { options.onadd(tab); } if (ul.find("li.red-ui-tab").length == 1) { activateTab(link); } if (options.onreorder && !options.collapsible) { var originalTabOrder; var tabDragIndex; var tabElements = []; var startDragIndex; li.draggable({ axis:"x", distance: 20, start: function(event,ui) { if (dblClickArmed) { dblClickArmed = false; return false } dragActive = true; originalTabOrder = []; tabElements = []; ul.children().each(function(i) { tabElements[i] = { el:$(this), text: $(this).text(), left: $(this).position().left, width: $(this).width() }; if ($(this).is(li)) { tabDragIndex = i; startDragIndex = i; } originalTabOrder.push($(this).data("tabId")); }); ul.children().each(function(i) { if (i!==tabDragIndex) { $(this).css({ position: 'absolute', left: tabElements[i].left+"px", width: tabElements[i].width+2, transition: "left 0.3s" }); } }) if (!li.hasClass('active')) { li.css({'zIndex':1}); } }, drag: function(event,ui) { ui.position.left += tabElements[tabDragIndex].left+scrollContainer.scrollLeft(); var tabCenter = ui.position.left + tabElements[tabDragIndex].width/2 - scrollContainer.scrollLeft(); for (var i=0;i tabElements[i].left && tabCenter < tabElements[i].left+tabElements[i].width) { if (i < tabDragIndex) { tabElements[i].left += tabElements[tabDragIndex].width+8; tabElements[tabDragIndex].el.detach().insertBefore(tabElements[i].el); } else { tabElements[i].left -= tabElements[tabDragIndex].width+8; tabElements[tabDragIndex].el.detach().insertAfter(tabElements[i].el); } tabElements[i].el.css({left:tabElements[i].left+"px"}); tabElements.splice(i, 0, tabElements.splice(tabDragIndex, 1)[0]); tabDragIndex = i; break; } } }, stop: function(event,ui) { dragActive = false; ul.children().css({position:"relative",left:"",transition:""}); if (!li.hasClass('active')) { li.css({zIndex:""}); } updateTabWidths(); if (startDragIndex !== tabDragIndex) { options.onreorder(originalTabOrder, $.makeArray(ul.children().map(function() { return $(this).data('tabId');}))); } activateTab(tabElements[tabDragIndex].el.data('tabId')); } }) } setTimeout(function() { updateTabWidths(); },10); if (collapsibleMenu) { collapsibleMenu.remove(); collapsibleMenu = null; } if (preferredOrder) { tabAPI.order(preferredOrder); } }, removeTab: removeTab, activateTab: activateTab, nextTab: activateNextTab, previousTab: activatePreviousTab, resize: updateTabWidths, count: function() { return ul.find("li.red-ui-tab:not(.hide)").length; }, activeIndex: function() { return ul.find("li.active").index() }, getTabIndex: function (id) { return ul.find("a[href='#"+id+"']").parent().index() }, contains: function(id) { return ul.find("a[href='#"+id+"']").length > 0; }, showTab: showTab, hideTab: hideTab, renameTab: function(id,label) { tabs[id].label = label; var tab = ul.find("a[href='#"+id+"']"); tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label)); updateTabWidths(); }, listTabs: function() { return $.makeArray(ul.children().map(function() { return $(this).data('tabId');})); }, selection: getSelection, clearSelection: function() { if (options.onselect) { var selection = ul.find("li.red-ui-tab.selected"); if (selection.length > 0) { selection.removeClass("selected"); selectionChanged(); } } }, order: function(order) { preferredOrder = order; var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');})); var i; var match = true; for (i=0;i