Reputation: 3813
Can someone explain why does clicking on second "Show details" will not work unless previous "Show details" is already clicked (except for the first "Show details", this will always work)? How can I make every toggle work, regardless of clicking order (ideally, keeping the for loop).
const toggles = document.querySelectorAll('.details-toggle')
toggles.forEach(toggle => {
toggle.addEventListener('click', e => {
const parent = e.target.parentElement
const details = parent.nextElementSibling
let opacity = details.style.opacity === "0" ? "1" : "0"
let maxHeight = details.style.maxHeight === "0px" ? "1000px" : "0px"
details.style.opacity = opacity
details.style.maxHeight = maxHeight
})
})
<!DOCTYPE html>
<html>
<body>
<head>
</head>
<body>
<ul>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details" style="opacity: 0; max-height: 0px">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details" style="opacity: 0; max-height: 0px">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details" style="opacity: 0; max-height: 0px">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
</ul>
</body>
</html>
Upvotes: 2
Views: 59
Reputation: 136164
It has nothing to do with your loop. It has to do with the fact that by just changing the opacity of your "hidden" elements they are still there, and actually overlay your other 2 "show details" elements so they never receive the click.
You can fix this by changing the display to none
and then they actually do receive the click.
const toggles = document.querySelectorAll('div .details-toggle')
toggles.forEach(toggle => {
toggle.addEventListener('click', e => {
const parent = e.target.parentElement
const details = parent.nextElementSibling
console.log(details.style.display);
})
})
<ul>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details" style="display:none">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details" style="display:none">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details" style="display:none">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
</ul>
I would suggest you control the visibility of these detail elements by toggling a class to show/hide:
const toggles = document.querySelectorAll('div .details-toggle')
toggles.forEach(toggle => {
toggle.addEventListener('click', e => {
const parent = e.target.parentElement
const details = parent.nextElementSibling
details.classList.toggle("hidden");
})
})
.hidden{
display:none
}
<ul>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details hidden">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details hidden">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
<li>
<div>
Title
<small class="details-toggle">Show details</small>
</div>
<div class="details hidden">
<ul>
<li>Det 1</li>
<li>Det 2</li>
</ul>
</div>
</li>
</ul>
Upvotes: 3