Reputation: 376
I have an accordion that should work multiple times. When there are more than one accordions, only 1st respond.
I quite like the way that it works with aria-controls, but I can't figure it out how to make it working multiple times reusing the same function.
I created the 2nd accordion below the 1st one. When I click the 2nd accordion button it doesn't respond, but the 1st accordion is responding and opening. The same with 3rd and 4th if added.
Any help much appreciated
const headers = document.querySelectorAll('[data-accordion-header]');
headers.forEach(header => {
let identifier = header.getAttribute("aria-controls");
let target = document.querySelector(`[aria-labelledby="${identifier}"]`);
header.addEventListener("click", event => {
event.preventDefault();
let expanded = header.getAttribute("aria-expanded") === "true" || false;
header.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
});
});
<nav class="accordion-navigation">
<h3>Accordion 1</h3>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-1" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z" fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-1" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-2" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z" fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-2" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
</nav>
<nav class="accordion-navigation">
<h3>Accordion 2</h3>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-1" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z" fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-1" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-2" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z" fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-2" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
</nav>
.
Upvotes: 0
Views: 150
Reputation: 1803
const headers = document.querySelectorAll('[data-accordion-header]');
headers.forEach(header => {
// let identifier = header.getAttribute("aria-controls");
// let target = document.querySelector(`[aria-labelledby="${identifier}"]`);
header.addEventListener("click", event => {
event.preventDefault();
me = event.target;
let identifier = me.getAttribute("aria-controls");
let target = me.parentElement.parentElement.querySelector(`[aria-labelledby="${identifier}"]`);
let expanded = target.getAttribute("aria-expanded") === "true" || false;
target.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
});
});
Upvotes: 1
Reputation: 390
aria-controls="accordion-navigation-1"
(1 & 2) in each accordion navs. So you should toggle each child accordions with the use of parent .accordion-navigation
navs. Check belowconst navs = document.querySelectorAll('.accordion-navigation');
navs.forEach(nav => {
const headers = nav.querySelectorAll('[data-accordion-header]');
headers.forEach(header => {
let identifier = header.getAttribute("aria-controls")
let target = nav.querySelector(`[aria-labelledby="${identifier}"]`);
header.addEventListener("click", event => {
event.preventDefault();
let expanded = header.getAttribute("aria-expanded") === "true" || false;
header.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
});
});
});
<nav class="accordion-navigation">
<h3>Accordion 1</h3>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-1" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-1" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-2" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-2" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
</nav>
<nav class="accordion-navigation">
<h3>Accordion 2</h3>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-1" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-1" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-2" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-2" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
</nav>
Or
aria-controls
attribute with different values not unique values (Like IDs). Below I changed second set of accordions aria-controls attributes to accordion-navigation-3
and accordion-navigation-4
const headers = document.querySelectorAll('[data-accordion-header]');
headers.forEach(header => {
let identifier = header.getAttribute("aria-controls")
let target = document.querySelector(`[aria-labelledby="${identifier}"]`);
header.addEventListener("click", event => {
event.preventDefault();
let expanded = header.getAttribute("aria-expanded") === "true" || false;
header.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
});
});
<nav class="accordion-navigation">
<h3>Accordion 1</h3>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-1" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-1" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-2" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-2" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
</nav>
<nav class="accordion-navigation">
<h3>Accordion 2</h3>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-3" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-3" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
<div class="accordion-navigation__title accordion__title">
<button class="accordion__toggle" aria-controls="accordion-navigation-4" aria-expanded="false" data-accordion-header=""></button> Level 0
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M-3.49691e-07 8L1.41 9.41L7 3.83L7 16L9 16L9 3.83L14.59 9.41L16 8L8 -3.49691e-07L-3.49691e-07 8Z"
fill="white"></path>
</svg>
</div>
<ol class="accordion-navigation__list" aria-labelledby="accordion-navigation-4" hidden="">
<li aria-current="true">
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
<li>
<a href="#_">Level 1</a>
</li>
</ol>
</nav>
Upvotes: 1
Reputation: 409
If you do not mandatorily want to stay with the aria-controls you can also achieve this quite easily with some simple css.
label {
display: block;
}
input[type='checkbox'], input[type='checkbox']:not(:checked) + * {
display: none;
}
ul {
margin-top: 0
}
<label for="area1">Open Area 1</label><input type="checkbox" id="area1">
<ul>
<li>new entries</li>
<li>new entries</li>
</ul>
<label for="area2">Open Area 2</label><input type="checkbox" id="area2">
<ul>
<li>new entries in area 2</li>
<li>new entries</li>
</ul>
<label for="area3">Open Area 3</label><input type="checkbox" id="area3">
<ul>
<li>even more entries</li>
<li>new entries</li>
<li>new entries</li>
</ul>
<label for="area4">Open Area 4</label><input type="checkbox" id="area4">
<ul>
<li>it's area 4 alright?</li>
</ul>
Upvotes: 0