Created
October 20, 2020 21:30
-
-
Save cferdinandi/490f1f42c77d4bc97442bda4013b396a to your computer and use it in GitHub Desktop.
Source code for https://gomakethings.com/how-to-build-a-progressively-enhanced-accordion-component-with-vanilla-js/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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