In my last article, I showed you how to extend the Bootstrap accordion. While the jQuery and CSS I created worked, I realized that I forgot a couple of things. In this article, you'll learn to ensure that the glyphs added to the accordion work when you click on the title of the accordion. In addition, you'll see how to make the jQuery work with multiple accordions on one page. Finally, you'll see how you can use different glyphs on each accordion on each page and use data- attributes to control the glyphs used.

A Review of the Extended Bootstrap Accordion

In the last article, you learned to add glyphs to the Bootstrap accordion on the right-hand side of each panel's title area (see Figure 1).

Figure 1: An accordion with extra glyphs in the right-hand corner
Figure 1: An accordion with extra glyphs in the right-hand corner

To place the glyph on the right, add an extra anchor tag in the “panel-title” area, as shown in line 5 of the following code snippet.

1. <h1 class="panel-title">
2.   <a data-toggle="collapse"
3.      data-parent="#accordion"
4.      href="#country">Country Music</a>
5.   <a class="pdsa-panel-toggle"></a>
6. </h1>

You also need a little CSS to move this glyph to the right side of the panel title area. The CSS is shown in the following code snippet.

.panel > .panel-heading > .panel-title > a {
    text-decoration: none;
}
.pdsa-panel-toggle {
    float: right;
    cursor: pointer;
}

Instead of adding the glyph icons directly to the anchor tag, you write jQuery to add a glyph to those anchor tags that have the class pdsa-panel-toggle. The jQuery to accomplish this is shown below.

$(document).ready(function () {
    // Add the down glyph to all elements
    // that have the class 'pdsa-panel-toggle'
    $("#genre .pdsa-panel-toggle").addClass("glyphicon glyphicon-chevron-down");
});

After adding all of the glyphs to each title area, you then need to look for any div tags that have the class .in and change the down glyph to an up glyph.

var list = $("#genre .in");
for (var i = 0; i < list.length; i++) {
    $($("a[href='#" + $(list[i]).attr("id") + "']")).next()
        .removeClass("glyphicon glyphicon-chevron-down")
        .addClass("glyphicon glyphicon-chevron-up");
}

Toggle the Up/Down Glyph

In the last article, Extending the Bootstrap Accordion (http://www.codemag.com/Article/1501031), a jQuery function is used to toggle the glyphs when the user clicks on the anchor tag. In this article, let's learn to use the Bootstrap events that go along with the accordion to perform the toggling. The two events you hook into are show and hide. The ID of the div class for the accordion in this article is called genre, so you'll hook the two events to that ID.

<div class="panel-group" id="genre">
    <div class="panel panel-primary">
        // Rest of the HTML
    </div>
</div>

Within the document Ready function for the page, write code to hook the genre ID to the show event, as shown in the next code snippet. In the event, you grab the ID of the e.target, which is the div tag that contains the panel-body class. You then navigate to the previous sibling in the DOM, which is the div tag that contains the panel-heading class. You then find the anchor tag that has the class pdsa-panel-toggle. This is the anchor tag to which you remove the “up” glyph and add the “down” glyph.

$(document).ready(function () {
    $("#genre").on('show.bs.collapse', function (e) {
        $("#" + e.target.id).prev()
            .find(".pdsa-panel-toggle")
            .removeClass("glyphicon glyphicon-up")
            .addClass("glyphicon glyphicon-down");
    });
});

You also need to write code to hook to the Hide event on the same panel group with the ID of genre. You perform the same exact jQuery to find the anchor tag with the class pdsa-panel-toggle and you remove the “down” glyph and add the “up” glyph.

$("#genre").on('hide.bs.collapse', function (e) {
    $("#" + e.target.id).prev()
        .find(".pdsa-panel-toggle")
        .removeClass("glyphicon glyphicon-down")
        .addClass("glyphicon glyphicon-up");
});

The final code you write within the document ready event is hooking into the click event of the anchor tag that contains the glyph. When this click event fires, locate the anchor tag used for the title of the accordion and call the collapse function on it with the parameter toggle. This causes the accordion to either collapse or expand. This, in turn, causes the accordion to fire either the show or hide event, which toggles the glyph.

$("#genre .pdsa-panel-toggle").click(function () {
    // Retrieve the previous anchor tag's
    // 'href' attribute so we can toggle it.
    $($(this).prev().attr("href")).collapse("toggle");
});

This is all the code you need to be able to expand and collapse an accordion and toggle the glyphs on the accordion. Feel free to use any glyphs you want on your accordion. For example, you could use the glyphs glyphicon-plus and glyphicon-minus if you want a plus and a minus sign to signify open and close to your users.

Use data- Attributes

One of the problems with the above code is that we're hard-coding the name of the glyphs in several locations. Instead of doing this, let's create some data- attributes to help identify the name of the accordion that you wish to extend with glyphs and the names of the glyphs to signify open and closed. By adding on three data- attributes, you can now have one accordion on your page with glyphs and another without. The next snippet is an example of how you would use these data- attributes on one of your accordions.

<div class="panel-group" id="genre"
    data-pdsa-collapser-name="genre"
    data-pdsa-collapser-open="glyphicon glyphicon-minus"
    data-pdsa-collapser-close="glyphicon glyphicon-plus">
    <div class="panel panel-primary">
        // Rest of the HTML
    </div>
</div>

You now need to modify the jQuery code that you wrote earlier to take advantage of these new data- attributes. The first change to make is to create two variables to hold the names of the open and close glyph icons.

$(document).ready(function () {
    var open = $("#genre").data("pdsa-collapser-open");
    var close = $("#genre").data("pdsa-collapser-close");

You use the data() function to get access to the data- attributes on the accordion. In the code above, you grab the pdsa-collapser-open data- value and place that value into the open variable. You then grab the pdsa-collapser-close data- value and place it into the close variable. Next, you modify the lines of code to add the close glyph to all the panels, and the code to loop through all the panels that have the .in class and add the open glyph.

$("#genre .pdsa-panel-toggle").addClass(close);
var list = $("#genre .in");
for (var i = 0; i < list.length; i++) {
    $($("a[href='#" + $(list[i]).attr("id") + "']")).next()
        .removeClass(close)
        .addClass(open);
}

Modify the hide event to grab the data- attribute from the accordion and use that to remove the open glyph and add the close glyph.

// Hook into 'hide' event
$("#genre").on('hide.bs.collapse', function (e) {
    $("#" + e.target.id).prev()
        .find(".pdsa-panel-toggle")
        .removeClass($("#genre")
        .data("pdsa-collapser-open"))
        .addClass($("#genre")
        .data("pdsa-collapser-close"));
});

Next, modify the show event to grab the data- attribute from the accordion and use that to remove the close glyph and add the open glyph.

// Hook into 'show' event
$("#genre").on('show.bs.collapse', function (e) {
    $("#" + e.target.id).prev()
        .find(".pdsa-panel-toggle")
        .removeClass($("#genre")
        .data("pdsa-collapser-close"))
        .addClass($("#genre")
        .data("pdsa-collapser-open"));
});

Make jQuery Code More Generic

Making the open and close glyphs data-driven by using data- attributes really helps simplify the code. However, the problem is that the ID of the panel group of the accordion is hard-coded in the jQuery code. If you wish to have two accordions on one page, you'd have to duplicate all of the jQuery code. This isn't very practical. Let's modify the jQuery code to allow the ability to support multiple accordions on each page. Assume that you have the genre accordion seen earlier in this article.

<div class="panel-group" id="genre"
     data-pdsa-collapser-name="genre"
     data-pdsa-collapser-open="glyphicon glyphicon-up"
     data-pdsa-collapser-close="glyphicon glyphicon-down">
    <div class="panel panel-primary">
        // Rest of the HTML
    </div>
</div>

Then assume that you wish to create a second accordion called artists that will use different glyphs, as shown in the code below.

<div class="panel-group" id="artists"
    data-pdsa-collapser-name="artists"
    data-pdsa-collapser-open="glyphicon glyphicon-chevron-minus"
    data-pdsa-collapser-close="glyphicon glyphicon-chevron-plus">
    </div>
</div>

You now change the jQuery code to loop through all of the panel groups that have the attribute data-pdsa-collapser-name. You grab that name and use that in place of where you used #genre in the previous jQuery code. Below is the code you wrap around the jQuery code you wrote earlier.

$(document).ready(function () {
    var pdsaCollapser = $("[data-pdsa-collapser-name]");
    for (var i = 0; i < pdsaCollapser.length; i++) {
        var name = pdsaCollapser[i].id;

        // Rest of the jQuery code here
    });

Now, wherever in the code you see #genre, you substitute with # + name. For example:

// Add 'close' icon to all panels
$("#" + name + " .pdsa-panel-toggle").addClass(close);
// Find any panels that have the class '.in',
// remove the 'close' glyph and add the 'open' glyph
var list = $("#" + name + " .in");
for (var index = 0; index < list.length; index++) {
    $($("a[href='#" + $(list[index]).attr("id") + "']")).next()
        .removeClass(close)
        .addClass(open);
}

Once you have completed all of these substitutions, you should move the jQuery code into a .js file so you can reuse it on any page in your site.

Summary

In this article, I built upon an accordion extension that I presented in the CODE Magazine article “Extending the Bootstrap Accordion” (http://www.codemag.com/Article/1501031). I took advantage of the built-in Bootstrap events for showing and hiding the collapsible elements in an accordion to toggle the glyphs. In addition, I added on data- attributes to data-drive the glyphs to use for open and close. Finally, I showed you how to make the code more generic and talked about how to move the code into a .js file so you can reuse accordions on any page in your site.