I'm actually occurring a situation when making an accordion. I already add a close button (x text) inside my div to close the accordion, but it won't close after I clicked on that. Btw, my reference design is from https://dribbble.com/shots/6584063-Daily-UI-Accordion-Cards-Experiment. It's only the example of the behavior. Like in my reference, I don't want to have an active class on the first time. Then when clicked the other tab, the current active class is inactive, and have an external close button.
document.addEventListener("DOMContentLoaded", (e) => {
const accordion = document.querySelectorAll('.a');
const button = document.querySelectorAll('b');
/* add Class from the div itself being clicked */
accordion.forEach((accs, idx) => {
accs.addEventListener('click', () => {
addActive(accs, idx);
});
});
function addActive(el, index) {
el.classList.add('active');
accordion.forEach((accs, idx) => {
if (idx !== index) {
accs.classList.remove("active");
}
});
}
/* remove class from button */
button.forEach(xer => {
xer.addEventListener('click', () => {
removeActive();
});
});
function removeActive() {
accordion.forEach(accs => {
accs.classList.remove('active');
})
}
})
.toggle {
display: none
}
.a .b {
display: none;
}
.a.active {
color: blue;
}
.a.active .b {
color: rgba(0, 0, 0, 1);
display: block;
cursor: pointer;
}
<div id="1" class="a"> Source
<div id="button-1" class="b"> x </div>
</div>
<div id="2" class="a"> Share
<div id="button-2" class="b"> x </div>
</div>
<div id="3" class="a"> Report
<div id="button-3" class="b"> x </div>
</div>
Please help me to fix that. Thank you so much.
There were two problems in your snippet:
const button = document.querySelectorAll('b'); will select all <b/> elements, not elements with class .b; updated below to const button = document.querySelectorAll('.b');.active class, then the click handler for the accordion was triggering and immediately reopening it. Adding a e.stopPropagation(); inside the handler stopped the event from bubbling up to the parent and resolved the problem.See below for a working example:
document.addEventListener("DOMContentLoaded", (e) => {
const accordion = document.querySelectorAll('.a');
const button = document.querySelectorAll('.b');
/* add Class from the div itself being clicked */
accordion.forEach((accs, idx) => {
accs.addEventListener('click', () => {
addActive(accs, idx);
});
});
function addActive(el, index) {
el.classList.add('active');
accordion.forEach((accs, idx) => {
if (idx !== index) {
accs.classList.remove("active");
}
});
}
/* remove class from button */
button.forEach(xer => {
xer.addEventListener('click', (e) => {
e.stopPropagation();
removeActive();
});
});
function removeActive() {
accordion.forEach(accs => {
accs.classList.remove('active');
})
}
})
.toggle {
display: none
}
.a .b {
display: none;
}
.a.active {
color: blue;
}
.a.active .b {
color: rgba(0, 0, 0, 1);
display: block;
cursor: pointer;
}
<div id="1" class="a"> Source
<div id="button-1" class="b"> x </div>
</div>
<div id="2" class="a"> Share
<div id="button-2" class="b"> x </div>
</div>
<div id="3" class="a"> Report
<div id="button-3" class="b"> x </div>
</div>