a suite of UI Components for development of web apps
Advanced User Interface Controls and Components
Created: 11 August 2014
In this article we are going to explain how to add child tabs to each tab in a TabStrip widget using jQuery. For this purpose we are going to use HTML5 to create the structure for parent and nested tabs, and then use jQuery to further customize the layout of nested tabs.
At first we need to create the structure of our tabstrips, including parent and child tabs. Here is how this looks like:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/integralui.tabstrip.css" />
<link rel="stylesheet" href="css/themes/theme-blue.css" />
<script type="text/javascript" src="external/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="external/jquery.ui.core.min.js"></script>
<script type="text/javascript" src="external/jquery.ui.widget.min.js"></script>
<script type="text/javascript" src="js/jquery.integralui.widget.min.js"></script>
<script type="text/javascript" src="js/jquery.integralui.tabstrip.min.js"></script>
</head>
<body>
<div id="tabstrip" class="widget">
<ul>
<li><span>Tab1</span></li>
<li><span>Tab2</span></li>
<li><span>Tab3</span></li>
</ul>
<div>
<div data-element="tabstrip" class="child">
<ul>
<li><span>ChildTab11</span></li>
<li><span>ChildTab12</span></li>
</ul>
<div></div>
<div></div>
</div>
</div>
<div>
<div data-element="tabstrip" class="child">
<ul>
<li><span>ChildTab21</span></li>
<li><span>ChildTab22</span></li>
<li><span>ChildTab23</span></li>
<li><span>ChildTab24</span></li>
</ul>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div>
<div data-element="tabstrip" class="child">
<ul>
<li><span>ChildTab31</span></li>
<li><span>ChildTab32</span></li>
<li><span>ChildTab32</span></li>
</ul>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</body>
</html>
<style type="text/css">
.widget
{
width: 300px;
height: 300px;
}
.child
{
height: 200px;
}
</style>
Each tab consists of tab header represented by <li> element and tab content represented by <div> element. Inside the content of parent tab we are adding another tabstrip widget. In this way tabs from the second tabstrip becomes nested inside the tab of first tabstrip. We can further add additional tabstrips in our child tabs and create additional nested tabs, but to simplify our example we will work only with one set of parent and child tabs.
From our HTML5 code you will notice that we have set only the identifier for out topmost tabstrip, and for our nested tabstrips we have set a custom attribute, data-element to tabstrip value. We can set identifiers for our nested tabs also, but in our example is not necessary, because we can locate them using jQuery selector.
Now when we have our structure set, let’s create an instance of our tab strips, parent and child.
// Create an instance of TabStrip widget
var $tabs = $('#tabstrip').tabstrip();
// Initialize all nested tabs and update their layout and appearance
var initNested = function(){
// Locate the nested tabs by using HMTL5 attribute and initialize them
$tabs.find("[data-element='tabstrip']").each(function(){
$(this).tabstrip();
});
}
initNested();
To initialize the nested tabs, instead of locating them using their identifier its better if we use their custom attribute set to tabstrip. This way is quicker and avoid holding a separate reference for each nested tabstrip. For this purpose we have created the initNested function like it is shown in above code.
After they are initialized, meaning their HTML element is linked with the tabstrip widget code, we can modify their layout and appearance. We will further modify the code inside our initNested function to place each nested in center of their parent tab content. Whenever parent tabstrip is resize we can use this code to make sure nested tabs always occupy the whole space of their parent, that’s minus set margin of 5 pixels.
// Cycle through each parent tab and set the appearance of nested tabs
var tabList = $tabs.tabstrip("getList");
tabList.forEach(function(tab, index){
var contentPanel = $("#" + tab.cid);
if (contentPanel){
var child = contentPanel.children().eq(0);
// After child tabs are initialized, make sure they occupy
// the whole space of content panel of their parent tab
child
.css({
margin: "5px",
width: contentPanel.width() - 10 + "px",
height: contentPanel.height() - 10 + "px"
});
// Change the placement of child tabs
// Align the second nested tabs to the left side of its parent, and
// Align the third set of nested tabs to the bottom side of its parent
switch (index){
case 1:
child.tabstrip("option", "tabStripPlacement", "left");
break;
case 2:
child.tabstrip("option", "tabStripPlacement", "bottom");
break;
}
// Update the layout of each tabstrip
child.tabstrip("refresh");
}
});
As it can be seen from code above, at first we are retrieving the list of all tabs in our topmost tabstrip. For this purpose we are using the getList method. Each tab object contains the unique identifier of their content panel. We can use this identifier to quickly locate the element in DOM and get access to the nested tabs.
Because we have only one child in our content panel, that is a nested tabstrip widget, we can get a reference to it by using jQuery. After that we are ready to modify its appearance and layout. For example we have modified the appearance of child tabs depending on their position in parent tab, by changing their alignment to left and bottom, to show you how this can be easily set from code.
After we are finished, we need to call the refresh method to apply the changes.
TabStrip widget only shows the content of currently selected tab. Because of this, the layout of all other parent tabs is hidden and it may have their content width and height also changed. To make sure the layout of their nested tabs is shown correctly we need to update it. This is done by handling the afterselect event, where we just are calling the refresh method for each nested tabstrip:
// After tab is selected, update the layout of child tabs
$tabs.on({
"afterselect": function(e){
var tab = e.object;
var contentPanel = $("#" + tab.cid);
if (contentPanel){
var child = contentPanel.children().eq(0);
child.tabstrip("refresh");
}
}
});
As a final result, we have multiple tabstrips nested one within another. You can further customize their appearance by changing their corresponding CSS styles.