简体   繁体   中英

Get next element with class (that's not a child or sibling)

With the press of a button, I want to toggle the class .active on the next div.bottom . These are basically accordions, but with a different structure.
Using nextElementSibling I guess won't work here to select the target element. How would one select such an element, that's neither a child nor a sibling (in plain JS)?

 <div class="wrapper"> <div class="top"> <div class="inner"> <div><button></button></div> </div> </div> <div class="bottom"></div> </div> <div class="wrapper"> <div class="top"> <div class="inner"> <div><button></button></div> </div> </div> <div class="bottom"></div> </div>

I'd do it by using closest to go up to the container .wrapper element, then querySelector to find the bottom element:

function onClick(event) {
    const wrapper = event.target.closest(".wrapper");
    const bottom = wrapper && wrapper.querySelector(".bottom");
    if (bottom) {
        bottom.classList.toggle("active");
    }
}

Live Example:

 // I've added event delegation here document.body.addEventListener("click", function onClick(event) { const button = event.target.closest(".inner button"); const wrapper = button && button.closest(".wrapper"); const bottom = wrapper && wrapper.querySelector(".bottom"); if (bottom) { bottom.classList.toggle("active"); } });
 .active { color: blue; border: 1px solid black; }
 <div class="wrapper"> <div class="top"> <div class="inner"> <div><button>Button A</button></div> </div> </div> <div class="bottom">Bottom A</div> </div> <div class="wrapper"> <div class="top"> <div class="inner"> <div><button>Button B</button></div> </div> </div> <div class="bottom">Bottom B</div> </div>

Or the same thing using optional chaining (relatively new):

function onClick(event) {
    const wrapper = event.target.closest(".wrapper");
    const bottom = wrapper?.querySelector(".bottom");
    bottom?.classList.toggle("active");
}

Live Example:

 // I've added event delegation here document.body.addEventListener("click", function onClick(event) { const button = event.target.closest(".inner button"); const wrapper = button?.closest(".wrapper"); const bottom = wrapper?.querySelector(".bottom"); bottom?.classList.toggle("active"); });
 .active { color: blue; border: 1px solid black; }
 <div class="wrapper"> <div class="top"> <div class="inner"> <div><button>Button A</button></div> </div> </div> <div class="bottom">Bottom A</div> </div> <div class="wrapper"> <div class="top"> <div class="inner"> <div><button>Button B</button></div> </div> </div> <div class="bottom">Bottom B</div> </div>

By using closest() you can traverse the DOM upwards . With this it's easy to just get the relevant .bottom and toggle the active class on this element.

 document.querySelectorAll('button').forEach(button => { button.addEventListener('click', (e) => { e.currentTarget.closest('.wrapper').querySelector('.bottom').classList.toggle('active'); }); });
 .bottom { display: none }.bottom.active { display: block }
 <div class="wrapper"> <div class="top"> <div class="inner"> <button type="button">Toggle</button> </div> </div> <div class="bottom">Hidden content</div> </div> <div class="wrapper"> <div class="top"> <div class="inner"> <button type="button">Toggle 2</button> </div> </div> <div class="bottom">Hidden content 2</div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM