LIDOR SYSTEMS

Advanced User Interface Controls and Components

Nested Accordions in jQuery and How to Create Them

Created: 25 August 2014

Accordion widget is consisted of multiple groups which can expand/collapse their content when selected. Usually the content of groups contains text, images and other components arranged in custom layouts. By adding a child accordion to each group content panel, we can create nested accordions. In following sections we will show you how to create multiple accordions placed within one another using jQuery and HTML5.

At first we need to create our structure for Accordion using HTML5. Here is an example:

Group 1

SubGroup 11

SubGroup 12

Group 2

SubGroup 21

SubGroup 22

SubGroup 23

Accordion is part of IntegralUI Studio for Web
a suite of UI Components for development of web apps

At first we need to create our structure for Accordion using HTML5. Here is an example:

<!DOCTYPE html>

<html>

<head>

<link rel="stylesheet" href="css/integralui.accordion.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.accordion.min.js"></script>

</head>

<body>

<div id="accordion" class="widget">

<h3><span>Group 1</span></h3>

<div>

<div data-element="accordion" class="child">

<h3><span>SubGroup 11</span></h3>

<div></div>

<h3><span>SubGroup 12</span></h3>

<div></div>

</div>

</div>

<h3><span>Group 2</span></h3>

<div>

<div data-element="accordion" class="child">

<h3><span>SubGroup 21</span></h3>

<div></div>

<h3><span>SubGroup 22</span></h3>

<div></div>

<h3><span>SubGroup 23</span></h3>

<div></div>

</div>

</div>

</div>

</body>

</html>

.widget

{

background: transparent;

width: 300px;

height: 300px;

}

.child

{

height: 200px;

}

As you can see from code above, we have one parent accordion with two groups and each group contains a child accordion. You can add as many groups you like, depending on the requirements in your web application. To simplify our example, additional elements inside group content are omitted.

The next step is to use jQuery to initialize our accordion widgets. We are using an identifier for our parent accordion, but for child accordions this is not necessary. We can locate them using attribute selector. Each child accordion has custom HTML5 attribute called data-element which is set to 'accordion' string value. This makes it easy to locate it within the DOM.

$(document).ready(function() {

// Create an instance of Accordion widget

var $bar = $('#accordion').accordion({

animationSpeed: 300,

showExpandBox: false

});

 

// Locate all nested accordions by using HMTL5 attribute and initialize them

var initNested = function(){

$bar.find("[data-element='accordion']").each(function(index){

$(this).accordion({

allowAnimation: false,

showExpandBox: false

});

});

}

 

initNested();

});

By default, each accordion has animations enabled. This can cause a double-time animations of nested accordions, when parent accordion is expanded. To solve this we can suppress expansion of child accordions before parent expands and enabled it again after it is fully expanded. For this purpose we are adding handlers to beforeexpand and afterexpand events.

$bar.on({

// Before accordion expands suppress its animation and update the layout of its child accordions

"beforeexpand": function(e){

var group = e.object;

var contentPanel = $("#" + group.cid);

if (contentPanel){

var child = contentPanel.children().eq(0);

 

// After child accordions are initialized, make sure they occupy

// the whole space of content panel of their parent accordion

child.accordion("option", "allowAnimation", false);

child

.css({

margin: "5px",

width: contentPanel.width() - 10 + "px"

});

 

child.accordion("refresh");

}

},

// After accordion is expanded suppress its animation and update its layout

"afterexpand": function(e){

var group = e.object;

var contentPanel = $("#" + group.cid);

if (contentPanel){

 

// After parent accordion is fully expanded, update the width and height of its child accordion

var child = contentPanel.children().eq(0);

child

.css({

margin: "5px",

width: contentPanel.width() - 10 + "px",

height: contentPanel.height() - 10 + "px"

});

 

// Update the layout of nested accordion and resume its animation

child.accordion("refresh");

child.accordion("option", "allowAnimation", true);

}

}

});

These events are fired whenever a group from accordion expands. The event object carries the group object that is related to the group element in the DOM. Each group objects hold an identifier to its related content panel. We can use this identifier (the cid variable), to get the content panel element in the DOM. Because we have only one child accordion within each group content panel, to access it we don't need to use an identifier, we can access it by using jQuery children() and eq() methods.

Now we have access to the nested accordions and we can further change their appearance and placement. In our example we have arranged the position and size of our nested accordions, so that they will occupy the whole space of their parent content panel, with margin set to 5 pixels. To update these changes we need to call the refresh method.

As a final result, we have accordions nested within one another, arranged in similar layouts. You can customize this, either using jQuery or CSS3 styles to create different layouts for each nested accordions, for example parent accordion to expand its content vertically, with child accordions to expand their content horizontally. Even further to create 3 or more levels of nested accordions.

Did you Like this Article?


Enter your e-mail address below and you will receive latest articles as well as news on upcoming events and special offers.