0

I tried to create a nested collapsible <div>.

The problem I am facing: when I tried to click the second <div> the first time after loading the page, it is not working. Whereas, if we try to click the first <div>, it works perfectly.

document.addEventListener('DOMContentLoaded', function() {
  const found = document.querySelectorAll('.collapse-content .collapse-head-content');
  
  for (let i = 0, len = found.length; i < len; i++) {
    found[i].addEventListener('click', handler, true);
  }

  function handler(e) {
    const hidden = e.target.classList.contains('hide-content');
    
    if (hidden) {
      e.target.classList.remove('hide-content');
    }
    else {
      e.target.classList.add('hide-content');
    }
  }
});
.collapse-content .collapse-head-content::before {
  content: ' ^ ';
  cursor: pointer;
}

.collapse-content .hide-content.collapse-head-content::before {
  content: ' > ';
}

.collapse-content .hide-content.collapse-head-content~.collapse-body-content {
  display: none;
}
<div class="bank-details collapse-content">
  <div class="state-name collapse-head-content hide-content">
    Click me to collapse / show
  </div>
  <div class="collapse-body-content">
    <div class="collapse-content">
      <div class="district-name collapse-head-content hide-content">
        District
      </div>
      <div class="branch-name collapse-body-content">
        <a href="#">name</a>
        <a href="#">name</a>
        <a href="#">name</a>
      </div>
    </div>
  </div>
  <div class="state-name collapse-head-content hide-content">
    Click me to collapse / show
  </div>
  <div class="collapse-body-content">
    <div class="collapse-content">
      <div class="district-name collapse-head-content hide-content">
        District
      </div>
      <div class="branch-name collapse-body-content">
        <a href="#">name</a>
        <a href="#">name</a>
      </div>
    </div>
  </div>
</div>
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
vishnu kp
  • 7
  • 5
  • Use `+` instead of `~` in the CSS. Otherwise, each collapsible `
    ` will only show if there is no `.hide-content` sibling element _anywhere_ before it. You want to show them if _only_ the sibling right before the collapsible `
    ` does not match `.hide-content`.
    – Sebastian Simon Jan 20 '23 at 16:24

1 Answers1

0

Use an adjacent sibling selector + to toggle visibility

In the updated snippet below, I modified the third CSS block to use + selector. That is, if .collapse-body-content block is directly following .hide-content, it's hiddent; otherwise, it'll remain visible. In doing so, each time you toggle the .hide-content class, its content will automatically toggle its visibility.

document.addEventListener('DOMContentLoaded', function() {
  const found = document.querySelectorAll('.collapse-content .collapse-head-content');
  
  for (let i = 0, len = found.length; i < len; i++) {
    found[i].addEventListener('click', handler, true);
  }

  function handler(e) {
    const hidden = e.target.classList.contains('hide-content');
    
    if (hidden) {
      e.target.classList.remove('hide-content');
    }
    else {
      e.target.classList.add('hide-content');
    }
  }
});
.collapse-content .collapse-head-content::before {
  content: ' ^ ';
  cursor: pointer;
}

.collapse-content .hide-content.collapse-head-content::before {
  content: ' > ';
}

.hide-content + .collapse-body-content {
  display: none;
}
<div class="bank-details collapse-content">
  <div class="state-name collapse-head-content hide-content">
    Click me to collapse / show
  </div>
  <div class="collapse-body-content">
    <div class="collapse-content">
      <div class="district-name collapse-head-content hide-content">
        District
      </div>
      <div class="branch-name collapse-body-content">
        <a href="#">name</a>
        <a href="#">name</a>
        <a href="#">name</a>
      </div>
    </div>
  </div>
  <div class="state-name collapse-head-content hide-content">
    Click me to collapse / show
  </div>
  <div class="collapse-body-content">
    <div class="collapse-content">
      <div class="district-name collapse-head-content hide-content">
        District
      </div>
      <div class="branch-name collapse-body-content">
        <a href="#">name</a>
        <a href="#">name</a>
      </div>
    </div>
  </div>
</div>
Bumhan Yu
  • 2,078
  • 1
  • 10
  • 20