We use Paragraphs as a layout tool in our page content area for UMassP.edu. Paragraphs are referenced using the Entity Reference field and a contributed module provides a set of well coded pre-configured paragraphs that can provide different layouts.
Modules
Entity Reference Field
Paragraphs Module
Bootstrap Paragraphs Module
HTML
Each accordion item starts with the button element. Initially the aria-expanded attribute is false and when selected, it switches to true.
<button class="display" data-toggle="collapse" data-parent="#accordion-1401" href="#collapse-accordion-1401-1" aria-expanded="false" aria-controls="collapse-accordion-1401-1">
<div id="heading-accordion-1401-1">
<div>5.1 Elective Deferral Retirement Savings Plan and Deferred Compensation 457(b)/MA SMART Plan</div>
</div>
</button>
The accordion content can be any type of HTML content. When the button element is clicked, the class "show" is added to the div.
<div id="collapse-accordion-1401-1" class="card-block panel-collapse collapse" role="tabpanel" aria-labelledby="heading-accordion-1401-1" style="">
<p> </p>
....
</div>
Javascript
/**
* @file
* The JavaScript file for Bootstrap Paragraphs Accordion.
*/
(function ($) {
$(document).ready(function ($) {
var buttonSelector = ".bp-accordion-button";
/*
* Loop through every bootstrap paragraphs accordion container to check if
* all the accordions are open then the "Expand/Collapse All" button text
* needs to be changed. This is a very unique case for example if there is
* only 1 accordion and that was default one to be open then the
* "Expand/Collapse All" needs to be changed.
*/
$(".paragraph--bp-accordion-container").each(function () {
if ($(".panel-collapse.in", this).length === $(".panel-collapse", this).length) {
changePanelButtonToCollapse($(buttonSelector, this));
}
});
/*
* When the page loads and there are some accordions defaulted to open this
* function will grab those accordions and change the alt text for them.
*/
$(".panel-collapse.in").each(function () {
changeAccordionAlt($(this).siblings(".panel-heading").find("a"));
});
/*
* When the "Expand/Collapse All" button is click this function will be
* called. If the button has the class "active" then open all the accordions
* else close all the accordions.
*/
$(buttonSelector).click(function () {
if (!$(this).hasClass("active")) {
openAllPanels(this);
}
else {
closeAllPanels(this);
}
});
/*
* When an accordion is opened this function will be called.
*/
$(".paragraph--type--bp-accordion").on('shown.bs.collapse', function () {
// Get the number of open accordions in the container.
var numPanelOpen = $(this).find(".panel-collapse.in").length;
// Get the total number of accordions in the container.
var totalNumberPanels = $(this).find(".panel-collapse").length;
// Call the function to change the alt text of the accordion that was
// clicked.
changeAccordionAlt($(".panel-title a", this));
// If the number of open accordions equals the total number of accordions
// then the "Expand/Collapse All" button needs to be changed.
if (numPanelOpen === totalNumberPanels) {
changePanelButtonToCollapse($(this).siblings(buttonSelector));
}
});
/*
* When an accordion is closed this function will be called.
*/
$(".paragraph--type--bp-accordion").on('hidden.bs.collapse', function () {
// Get the number of open accordions in a container.
var numPanelOpen = $(this).find(".panel-collapse.in").length;
// Call the function to change the alt text of the accordion that was
// clicked.
changeAccordionAlt($(".panel-title a", this));
// If the number of open accordions equals 0 then the
// "Expand/Collapse All" button needs to be changed.
if (numPanelOpen === 0) {
changePanelButtonToExpand($(this).siblings(buttonSelector));
}
});
/*
* Take in a container id and open all the panels within that container.
*/
function openAllPanels(id) {
$(id).siblings('.paragraph').find(".panel-collapse").collapse('show');
}
/*
* Take in a container id and close all the panels within that container.
*/
function closeAllPanels(id) {
$(id).siblings('.paragraph').find(".panel-collapse").collapse('hide');
}
/*
* Take in an id parameter. First check that the variable sent has the
* class 'active' this would mean it is open. If the variable does then go
* ahead and switch the title text and display text to say 'Collapse All'.
*/
function changePanelButtonToCollapse(id) {
if ($(id).hasClass("active")) {
return;
}
$(id).attr("title", Drupal.t("Click to collapse all accordions in this section."));
$(id).text(Drupal.t("Collapse All"));
$(id).toggleClass("active");
}
/*
* Take in an id parameter. First check that the variable sent doesn't have
* class 'active' this would mean it is open. If the variable does not
* then go ahead and switch the title text and display text to say
* 'Expand All'.
*/
function changePanelButtonToExpand(id) {
if (!$(id).hasClass("active")) {
return;
}
$(id).attr("title", Drupal.t("Click to expand all accordions in this section."));
$(id).text(Drupal.t("Expand All"));
$(id).toggleClass("active");
}
/*
* Take in an id parameter and use that variable to in a jQuery call to see
* if the accordion is open or closed then change the alt text based on the
* results.
*/
function changeAccordionAlt(id) {
if ($(id).attr("aria-expanded") === 'true') {
$(id).attr("alt", Drupal.t("Currently open. Click to collapse this section."));
}
else {
$(id).attr("alt", Drupal.t("Currently closed. Click to expand this section."));
}
}
});
})(jQuery);
CSS
Block display is inherent to the div element so only the following CSS is necessary to hide it when not shown.
.collapse:not(.show) {
display: none;
}