Tabbed Accordion

Non-functional link, for testing purposes

HTML Source Code

<ul class="tablist" role="tablist">
    <li>
        <div class="tab active" role="tab" aria-setsize="4" aria-posinset="1" aria-selected="false" aria-controls="panel1" tabindex="0">
            Prospective Students</div>
        <div id="panel1" class="tabpanel active" role="tabpanel" aria-hidden="true">
            <ul>
                <li><a href="#">Prospective Students Home Page</a></li>
                <li><a href="#">Admissions</a></li>
                <li><a href="#">Financing Your Education</a></li>
            </ul>
        </div>
    </li>
    <li>
        <div class="tab inactive" role="tab" aria-setsize="4" aria-posinset="2" aria-selected="false" aria-controls="panel2" tabindex="-1">
            Students</div>
        <div id="panel2" class="tabpanel inactive" role="tabpanel" aria-hidden="true">
            <ul>
                <li><a href="#">Students Home Page</a></li>
                <li><a href="#">Records</a></li>
                <li><a href="#">Student Life</a></li>
                <li><a href="#">Student Organizations</a></li>
                <li><a href="#">Technology</a></li>
                <li><a href="#">Library</a></li>
            </ul>
        </div>
    </li>
    <li>
        <div class="tab inactive" role="tab" aria-setsize="4" aria-posinset="3" aria-selected="false" aria-controls="panel3" tabindex="-1">
            Faculty</div>
        <div id="panel3" class="tabpanel inactive" role="tabpanel" aria-hidden="true">
            <ul>
                <li><a href="#">Faculty Home</a></li>
                <li><a href="#">Directory</a></li>
                <li><a href="#">News</a></li>
                <li><a href="#">Publications</a></li>
            </ul>
        </div>
    </li>
    <li>
        <div class="tab inactive" role="tab" aria-setsize="4" aria-posinset="4" aria-selected="false" aria-controls="panel4" tabindex="-1">
            Alumni</div>
        <div id="panel4" class="tabpanel inactive" role="tabpanel" aria-hidden="true">
            <ul>
                <li><a href="#">Alumni Home Page</a></li>
                <li><a href="#">Benefits and Services</a></li>
                <li><a href="#">Giving</a></li>
                <li><a href="#">Alumni Association</a></li>
                <li><a href="#">Volunteer Opportunities</a></li>
            </ul>
        </div>
    </li>
</ul>

JavaScript Source Code

Dependencies:
  • JQuery
var tabListContainer;
var initTabPanel = function(container) {
    tabListContainer = container;
    $(tabListContainer + ' > li > div.tab')
        .keydown(tabListKeyPress)
        .click(tabListClick);
};

var tabListKeyPress = function(event) {
    console.log($(event.currentTarget));
    if (event.which === 37 || event.which === 38 ||
        (event.which === 33 && event.ctrlKey)) { //left/up/ctrl+pageup
        var prevItem = $(event.currentTarget)
                                            .parent()
                                            .prev("li")
                                            .children("div")
                                            .first();
        if (prevItem.length > 0) {
            focusTab(prevItem);
        } else {
            //go to the last one
            var lastItem = $(event.currentTarget)
                                                .parent()
                                                .siblings("li")
                                                .last().children("div")
                                                .first();
            focusTab(lastItem);
        }
    } else if (event.which === 39 || event.which === 40 ||
               (event.which === 34 && event.ctrlKey)) { //right/down/ctrl+pagedown
        var nextItem = $(event.currentTarget)
                                            .parent()
                                            .next("li")
                                            .children("div")
                                            .first();
        if (nextItem.length > 0) {
            focusTab(nextItem);
        } else {
            //go to the first one
            var firstItem = $(event.currentTarget)
                                                .parent()
                                                .siblings("li")
                                                .first()
                                                .children("div")
                                                .first();
            focusTab(firstItem);
        }
    }
};

var tabListClick = function(event) {
    focusTab($(event.currentTarget));
};

var focusTab = function(newTab) {
    // Identify existing focus tab 
    var activeTab = $(tabListContainer + ' > li > div.tab.active');
    
    if (activeTab) {
        deactivateTab(activeTab);
    }
    activateTab(newTab);
    newTab.focus();
};
var deactivateTab = function(tab) {
    // Forand: 1) Unset aria-selected, 2) set tabindex=-1, 3) replace
    // active class with inactive on both the tab and the panel, 4) set aria-hidden on panel    
    tab
        .addClass("inactive")
        .removeClass("active")
        .attr("aria-selected", "false")
        .attr("tabindex", "-1");

    $("#" + tab.attr("aria-controls"))
        .addClass("inactive")
        .removeClass("active")
        .attr("aria-hidden", "true");
};
var activateTab = function(tab) {
    // For newly focused tab: 1) Set aria-selected, 2) set tabindex=0, 3) replace inactive class
    // with active on both tab and panel, 4) unset aria-hidden on panel
    tab
        .addClass("active")
        .removeClass("inactive")
        .attr("aria-selected", "true")
        .attr("tabindex", "0");

    $("#" + tab.attr("aria-controls"))
        .addClass("active")
        .removeClass("inactive")
        .removeAttr("aria-hidden");
};

$(document).ready(function() {
    initTabPanel(tablistContainerClass); // set tablistContainerClass to the tablist class
});

CSS Source Code

.tablist {
	list-style: none;
	margin: 0;
	padding: 0;
	width: 300px;
}
.tablist li {
	list-style-type: none;
	margin: 0;
	padding: 0;
}
.tablist div.tab:focus {
	background-color: #566ac8;
	outline: 2px solid #8cc63f;
}
.tablist > li:hover {
	cursor: pointer;
}
.tablist div.tab {
	background: #375898;
	border: 1px solid #fff;
	color: #fff;
	padding: 3px 6px;
}
.tablist div.tab.active {
	font-weight: bold;
}
.tabpanel.inactive {
	display: none;
}
.tabpanel ul {
	margin: 0;
	padding: 0;
}
.tabpanel li a {
	text-decoration: none;
}
.tabpanel li {
	background:#fff;
	border-bottom:1px dashed #375898;
	color:#375898;
	padding:3px 5px 3px 20px;
}
.tabpanel li:last-child {
	border-bottom: none;
}

Copy and Paste Full Page Example