JS: Add responsive-tabbar behavior draft

This commit is contained in:
Florian Strohmaier 2016-03-21 11:06:54 +01:00
parent 9f9cd71d02
commit 634eebf85b

View File

@ -4,87 +4,144 @@
'use strict'; 'use strict';
/**
* In case of unsufficient space hide tabitems behind a dropdown
*
* @param {object} e Event
*/
function onRendered(e) { function onRendered(e) {
var $tabs = $(this).find(".tabs"); var _this = e.data.self;
var $this = $(this);
if ($tabs.length) { console.log("on rendered", e.type);
var breakIndex = determineBreakIndex($tabs) if ($this.find(".tabs")) {
cacheTabWidths($this, _this);
if (breakIndex) { updateBreakIndex($this, _this);
createDropdown($tabs, breakIndex);
} else {
console.log("tab items fit", breakIndex);
}
} }
} }
/** function onWindowResized (e) {
* Hide tab items behind a dropdown console.log("window resize", e);
* var _this = e.data.self;
* @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;
if ($tabs.children('.additional-items').length < 1) { $('#col1, #col2').each(function(i) {
var $this = $(this);
var $additionalTabsDropdown = $('<li class="dropdown-nav-item additional-items"><a href="#" class="dropdown-toggle"><i class="icon-attention-alt"></i></a><ul class="nav"></ul></li>'); if ($this.find(".tabs")) {
if (_this.containerData[$this.attr("id")]) {
for (var i = index; i < $tabItems.length; i++) { console.log("update");
var $item = $($tabItems.get(i)); updateBreakIndex($this, _this);
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();
} }
});
$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 * @param {object} e Event
*
* @returns {Bool} false if there is sufficiently wide, the index of the first tab
*/ */
function determineBreakIndex($tabContainer) { function updateBreakIndex($container, e) {
var breakIndex = false; 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')); for (var i = 0; i < tabWidths.length; i++) {
w += tabWidths[i];
if (itemsWidth > $tabContainer.width()) { if (w > Math.floor(tabsElWidth)) {
breakIndex = i; 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 = $('<li class="dropdown-nav-item additional-items"><a href="#" class="dropdown-toggle"><i class="icon-ellipsis"></i></a><ul class="nav"></ul></li>');
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 || {}; Icinga.Behaviors = Icinga.Behaviors || {};
@ -93,16 +150,19 @@
* Behavior for managing tab bar width * Behavior for managing tab bar width
* *
* The ResponsiveTabBar will wrap tabs in a dropdown if the containing * The ResponsiveTabBar will wrap tabs in a dropdown if the containing
* tab bar becomes too narrow * tab bar becomes insufficient
* *
* @param {Icinga} icinga * @param {Icinga} icinga
* *
* @constructor * @constructor
*/ */
var ResponsiveTabBar = function(icinga) { var ResponsiveTabBar = function(icinga) {
this.containerData = [];
Icinga.EventListener.call(this, icinga); Icinga.EventListener.call(this, icinga);
this.on('rendered', '#col1, #col2', onRendered, this); 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(); ResponsiveTabBar.prototype = new Icinga.EventListener();