From 634eebf85b871b08422871aa332e046d48ef749d Mon Sep 17 00:00:00 2001 From: Florian Strohmaier Date: Mon, 21 Mar 2016 11:06:54 +0100 Subject: [PATCH] JS: Add responsive-tabbar behavior draft --- .../js/icinga/behavior/responsive-tabbar.js | 188 ++++++++++++------ 1 file changed, 124 insertions(+), 64 deletions(-) diff --git a/public/js/icinga/behavior/responsive-tabbar.js b/public/js/icinga/behavior/responsive-tabbar.js index ad24e8421..377913978 100644 --- a/public/js/icinga/behavior/responsive-tabbar.js +++ b/public/js/icinga/behavior/responsive-tabbar.js @@ -4,87 +4,144 @@ 'use strict'; - /** - * In case of unsufficient space hide tabitems behind a dropdown - * - * @param {object} e Event - */ + + function onRendered(e) { - var $tabs = $(this).find(".tabs"); - - if ($tabs.length) { - var breakIndex = determineBreakIndex($tabs) - - if (breakIndex) { - createDropdown($tabs, breakIndex); - } else { - console.log("tab items fit", breakIndex); - } + var _this = e.data.self; + var $this = $(this); + console.log("on rendered", e.type); + if ($this.find(".tabs")) { + cacheTabWidths($this, _this); + updateBreakIndex($this, _this); } } - /** - * Hide tab items behind a dropdown - * - * @param {jQuery} $tabs The tab navigation element to modify - * @param {int} breakindex The index for the first tab to hide - */ - function createDropdown($tabs, breakIndex) { - var $tabItems = $tabs.children('li'); - var index = breakIndex - 1; + function onWindowResized (e) { + console.log("window resize", e); + var _this = e.data.self; - if ($tabs.children('.additional-items').length < 1) { - - var $additionalTabsDropdown = $(''); - - for (var i = index; i < $tabItems.length; i++) { - var $item = $($tabItems.get(i)); - if ($item.children('ul.nav').length > 0) { - - $item.children('ul.nav').children('li').each(function(j) { - - var $clonedItem = $(this).clone(); - - console.log("itemtext", $clonedItem.text()); - - $additionalTabsDropdown.children('ul').append($clonedItem); - }); - } else { - var $clonedItem = $item.clone(); - $additionalTabsDropdown.children('ul').append( $clonedItem ); - $clonedItem.children('a').append($clonedItem.children("a").attr("title")); - } - $item.hide(); + $('#col1, #col2').each(function(i) { + var $this = $(this); + if ($this.find(".tabs")) { + if (_this.containerData[$this.attr("id")]) { + console.log("update"); + updateBreakIndex($this, _this); + } } - - $tabs.append($additionalTabsDropdown); - } + }); } - /** + function onLayoutChange (e) { + + var _this = e.data.self; + + $('#col1, #col2').each(function(i) { + var $this = $(this); + if ($this.find(".tabs")) { + cacheTabWidths($this, _this); + updateBreakIndex($this, _this); + } + }); + } + + /** + * Calculate the breakIndex according to tabs container width * + * @param {jQuery} $container Element containing the tabs * - * @param {jQuery} $tabContainer The element containing the tabs - * - * @returns {Bool} false if there is sufficiently wide, the index of the first tab + * @param {object} e Event */ - function determineBreakIndex($tabContainer) { + function updateBreakIndex($container, e) { + var breakIndex = false; - var $tabItems = $tabContainer.children('li'); - var itemsWidth = 0; - $tabItems.each(function(i) { + var w = 0; + var tabsElWidth = $container.find('.tabs').not(".cloned").width() - parseFloat($container.find('.tabs').not(".cloned").css("padding-left")); + var tabWidths = e.containerData[$container.attr("id")].tabWidths; - itemsWidth += $(this).width() + parseFloat($(this).css('margin-right')); - - if (itemsWidth > $tabContainer.width()) { + for (var i = 0; i < tabWidths.length; i++) { + w += tabWidths[i]; + if (w > Math.floor(tabsElWidth)) { breakIndex = i; + } else { + breakIndex = false; } + } - console.log("too wide?", itemsWidth, ":", $tabContainer.width()); + console.log("w : tabsW", w, tabsElWidth, $container, tabWidths); + + setBreakIndex($container, breakIndex, e); + } + + + /** + * Set the breakIndex and if value has changed render Tabs + * + * @param {jQuery} $container Element containing the tabs + * + * @param {Int} NewIndex New Value for the breakIndex + */ + function setBreakIndex($container, newIndex, e) { + if (newIndex == e.containerData[$container.attr("id")].breakIndex) { + return; + } else { + $container.breakIndex = newIndex; + renderTabs($container); + console.log("break index change", $container, $container.breakIndex); + } + } + + /** + * Save horizontal dimensions of the tabs once + * + * @param {jQuery} $container Element containing the tabs + * + * @param {object} e Event + */ + function cacheTabWidths($container, e) { + var containerData = {}; + containerData.tabWidths = []; + + $container.find(".tabs").not(".cloned").children("li").each(function () { + containerData.tabWidths.push($(this).width() + parseFloat($(this).css("margin-right"))); }); - return breakIndex; + e.containerData[$container.attr("id")] = containerData; + + console.log("tab widths cached", $container, containerData, e.containerData); + } + + /** + * Render Tabs of a container according to the updated breakIndex + * + * @param {jQuery} $container Element containing the tabs + */ + function renderTabs($container) { + $container.find('.tabs.cloned').remove(); + var $tabs = $container.find(".tabs").show(); + if ($container.breakIndex) { + var $additionalTabsDropdown = $(''); + var $clonedTabs = $tabs.clone().addClass("cloned"); + var $tabItems = $clonedTabs.children('li'); + + for (var i = $container.breakIndex-1; i < $tabItems.length + 1; i++) { + var $item = $($tabItems.get(i)); + + if ($item.children('ul.nav').length > 0) { + $item.children('ul.nav').children('li').each(function(j) { + $additionalTabsDropdown.children("ul").append(this); + }); + $item.remove(); + } else { + $additionalTabsDropdown.children("ul").append($item); + $item.children("a").append($item.children("a").attr("title")); + } + } + $clonedTabs.append($additionalTabsDropdown); + $container.find(".controls").prepend($clonedTabs); + + $tabs.hide(); + } } Icinga.Behaviors = Icinga.Behaviors || {}; @@ -93,16 +150,19 @@ * Behavior for managing tab bar width * * The ResponsiveTabBar will wrap tabs in a dropdown if the containing - * tab bar becomes too narrow + * tab bar becomes insufficient * * @param {Icinga} icinga * * @constructor */ var ResponsiveTabBar = function(icinga) { + this.containerData = []; Icinga.EventListener.call(this, icinga); this.on('rendered', '#col1, #col2', onRendered, this); - $(document).on("resize", onRendered, this); + $(window).resize({self: this}, onWindowResized); + this.on('layout-change', '#col1, #col2', onLayoutChange, this); + this.on('close-column', '#col1, #col2', onRendered, this); }; ResponsiveTabBar.prototype = new Icinga.EventListener();