user173420
user173420

Reputation: 376

Javascript Accordion function should work multiple times

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

Answers (3)

pullidea-dev
pullidea-dev

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

Prakash M
Prakash M

Reputation: 390

  1. You are having same 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 below

const 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

  1. Set 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

FTav
FTav

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

Related Questions