Skip to content

Instantly share code, notes, and snippets.

@cferdinandi
Created October 20, 2020 21:30
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cferdinandi/490f1f42c77d4bc97442bda4013b396a to your computer and use it in GitHub Desktop.
Save cferdinandi/490f1f42c77d4bc97442bda4013b396a to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Accordions</title>
<style type="text/css">
body {
margin: 0 auto;
max-width: 40em;
width: 88%;
}
summary {
font-weight: bold;
margin-bottom: 0.25em;
}
p {
margin: 0 0 1.5em;
padding: 0;
}
</style>
</head>
<body>
<h1>Progressively Enhanced Accordions</h1>
<h2>Group 1</h2>
<div data-accordion="1">
<details>
<summary>Click Me to Show More</summary>
<p>Hi there!</p>
</details>
<details>
<summary>Click Me to Show More, Too</summary>
<p>Hi there!</p>
</details>
<details>
<summary>Click Me to Show Even More</summary>
<p>Hi there!</p>
</details>
<details>
<summary>Last one, I promise</summary>
<p>Hi there!</p>
</details>
</div>
<h2>Group 2</h2>
<div data-accordion="2">
<details>
<summary>Click Me to Show More</summary>
<p>Hi there!</p>
</details>
<details>
<summary>Click Me to Show More, Too</summary>
<p>Hi there!</p>
</details>
<details>
<summary>Click Me to Show Even More</summary>
<p>Hi there!</p>
</details>
<details>
<summary>Last one, I promise</summary>
<p>Hi there!</p>
</details>
</div>
<script>
/**
* Progressively Enhanced Accordion Components
* (c) 2020 Chris Ferdinandi, MIT License, https://gomakethings.com
*/
var Accordions = (function () {
'use strict';
//
// Methods
//
/**
* Close any existing open accordion elements
* @param {Node} current The current element being opened
* @param {Node} parent The wrapper for all sibling accordions
*/
var closeOthers = function (current, parent) {
// Get all open accordions inside parent
var opened = Array.from(parent.querySelectorAll('details[open]'));
// Close open ones that aren't current accordion
opened.forEach(function (accordion) {
if (accordion === current) return;
accordion.removeAttribute('open');
});
};
/**
* Handle toggle event on an accordion element
* @param {Event} event The Event object
* @param {String} selector The accordion group selector
*/
var toggle = function (event, selector) {
// Only run on accordions inside our selector
var parent = event.target.closest(selector);
if (!parent) return;
// Only run if accordion is open
if (!event.target.hasAttribute('open')) return;
// Close any existing open accordions
closeOthers(event.target, parent);
};
/**
* Create the Constructor object
*/
var Constructor = function (selector) {
//
// Variables
//
var publicAPIs = {};
//
// Methods
//
/**
* Handle toggle events
* @param {Event} event The Event object
*/
var toggleHandler = function (event) {
toggle(event, selector);
};
/**
* Destroy the current instantiation
*/
publicAPIs.destroy = function () {
document.removeEventListener('toggle', toggleHandler, true);
};
/**
* Initialize a new instantiation
*/
publicAPIs.init = function () {
// Check for errors
if (!selector || typeof selector !== 'string') {
throw new Error('Please provide a valid selector');
}
// Listen for when accordions open or close
document.addEventListener('toggle', toggleHandler, true);
};
//
// Initialized and return the Public APIs
//
publicAPIs.init();
return publicAPIs;
};
//
// Return the Constructor
//
return Constructor;
})();
// Instantiate plugin
var accordion = new Accordions('[data-accordion="1"]');
var otherAccordion = new Accordions('[data-accordion="2"]');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment