Pure js + CSS expand collapse menu
by epinapala
HTML
<div class="panel" data-id="apiOverviewGuidelines">
<button class="panel-header" onClick='handleMenuButtonClick(this)'>API Overview & Guidelines</button>
<div class="panelcontent" style="display: block; height: 0px;">
<div class="collapsed" data-id="introduction"><a class="link" href="#">Introduction</a></div>
<div class="collapsed" data-id="designSummary"><a class="link" href="#">Design Summary</a></div>
<div class="collapsed" data-id="businessUseCases"><a class="link" href="#">Business Use cases</a></div>
<div class="collapsed" data-id="restrictionsLimitations"><a class="link" href="#">Restrictions & limitations</a></div>
</div>
</div>
<div class="panel" data-id="apiReference">
<button class="panel-header" onClick='handleMenuButtonClick(this)'>API Reference</button>
<div class="panelcontent" style="display: block; height: 0px;">
<div class="collapsed" data-id="marketing-resourceTypes"><a class="link" href="/api-docs/sell/marketing/resources/methods">Resource Types</a></div>
<div class="collapsed" data-id="ad_report">
<button class="panel-header" onClick='handleMenuButtonClick(this)'>AD REPORT</button>
<div class="panelcontent">
<div class="collapsed" data-id="marketing-ad_report-getReport"><a class="link" href="/api-docs/sell/marketing/resources/ad_report/methods/getReport">Get Specific Report</a></div>
</div>
</div>
<div class="panel" data-id="ad_report_metadata">
<button class="panel-header" onClick='handleMenuButtonClick(this)'>AD REPORT METADATA</button>
<div class="panelcontent">
<div class="collapsed" data-id="marketing-ad_report_metadata-getReportMetadata"><a class="link selected" href="/api-docs/sell/marketing/resources/ad_report_metadata/methods/getReportMetadata">Get Metadata For All Reports</a></div>
<div class="collapsed" data-id="marketing-ad_report_metadata-getReportMetadataForReportType"><a class="link"...
CSS
/* panel */
.panel,
.panelcollapsed {
margin: 5px;
padding: 0px 0px 5px;
width: 300px;
}
/* panel heading */
.panel h2,
.panelcollapsed h2 {
font-size: 18px;
font-weight: normal;
margin: 0px;
padding: 4px;
background: #CCC url(arrow-up.gif) no-repeat 280px;
border-bottom: 1px solid #999;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-top: 1px solid #FFF;
border-right: 1px solid #FFF;
border-left: 1px solid #FFF;
}
/* panel heading on rollover */
.panel h2:hover,
.panelcollapsed h2:hover {
background-color: #A9BCEF;
}
/* heading of a collapsed panel */
.panelcollapsed h2 {
background: #CCC url(arrow-dn.gif) no-repeat 280px;
border-color: #CCC;
}
/* collapsed panel content */
.panelcollapsed .panelcontent {
display: none;
}
button {
background-color: Transparent;
background-repeat: no-repeat;
border: none;
cursor: pointer;
overflow: hidden;
outline: none;
}
JavaScript
var PANEL_NORMAL_CLASS = "panel";
var PANEL_COLLAPSED_CLASS = "panelcollapsed";
var PANEL_HEADING_TAG = "button";
var PANEL_CONTENT_CLASS = "panelcontent";
var PANEL_COOKIE_NAME = "panels";
var PANEL_ANIMATION_DELAY = 20; /*ms*/
var PANEL_ANIMATION_STEPS = 10;
function setUpPanels() {
var panelsStatus = {};
// get all headings
var headingTags = document.getElementsByTagName(PANEL_HEADING_TAG);
// go through all tags
for (var i = 0; i < headingTags.length; i++) {
var el = headingTags[i];
// make sure it's the heading inside a panel
if (el.parentNode.className != PANEL_NORMAL_CLASS && el.parentNode.className != PANEL_COLLAPSED_CLASS)
continue;
// get the text value of the tag
var name = el.firstChild.nodeValue;
panelsStatus[name] = (el.parentNode.className == PANEL_NORMAL_CLASS) ? "true" : "false";
// add the click behavor to headings
el.onclick = function() {
var target = this.parentNode;
var name = this.firstChild.nodeValue;
var collapsed = (target.className == PANEL_COLLAPSED_CLASS);
animateTogglePanel(target, collapsed);
};
}
}
/**
* Start the expand/collapse animation of the panel
* @param panel reference to the panel div
*/
function animateTogglePanel(panel, expanding) {
// find the .panelcontent div
var elements = panel.getElementsByTagName("div");
var panelContent = null;
for (var i = 0; i < elements.length; i++) {
if (elements[i].className == PANEL_CONTENT_CLASS) {
panelContent = elements[i];
break;
}
}
// make sure the content is visible before getting its height
panelContent.style.display = "block";
// get the height of the content
var contentHeight = panelContent.offsetHeight;
// if panel is collapsed and expanding, we must start with 0 height
if (expanding)
panelContent.style.height = "0px";
var stepHeight = contentHeight / PANEL_ANIMATION_STEPS;
var direction = (!expanding ? -1 : 1);
setTimeout(function() {
...