简体   繁体   中英

Click button to toggle class of parent element - pure javascript

I have multiple divs on the page with the class 'item' – I'd like to include a button within the div that when clicked will toggle append/remove the class 'zoom' on the 'item' div…

<div class="item">
<button class="zoomer"></button>
</div>

I've found plenty of code examples that target an id element, but struggling to find a solution that works with multiples of the same class element on one page.

Many thanks in advance

You can use querySelectorAll to get all of the buttons and then you can use forEach so you can target the element's item parent.

 // Get all the buttons let zoomer_button = document.querySelectorAll('.zoomer'); // Loop through the buttons. // Arrow function allows to pass the element zoomer_button.forEach(button => { // Add an event listener for a click on the button. button.addEventListener('click', function(e) { // the e is the event, and then you check what the target is, which is the button. // then you can toggle a 'zoom' class on the parent 'item' e.target.parentNode.classList.toggle('zoom'); }); });
 .item.zoom { background-color: blue; }
 <div class="item"> <button class="zoomer">button</button> </div> <div class="item"> <button class="zoomer">button</button> </div> <div class="item"> <button class="zoomer">button</button> </div> <div class="item"> <button class="zoomer">button</button> </div> <div class="item"> <button class="zoomer">button</button> </div>

If it's nested a layer deeper, you can use parentNode twice.

 // Get all the buttons let zoomer_button = document.querySelectorAll('.zoomer'); // Loop through the buttons. // Arrow function allows to pass the element zoomer_button.forEach(button => { // Add an event listener for a click on the button. button.addEventListener('click', function(e) { // the e is the event, and then you check what the target is, which is the button. // then you can toggle a 'zoom' class on the parent 'item' e.target.parentNode.parentNode.classList.toggle('zoom'); }); });
 .item.zoom { background-color: blue; }
 <div class="item"> <div class="media"> <button class="zoomer">button</button> </div> </div> <div class="item"> <div class="media"> <button class="zoomer">button</button> </div> </div> <div class="item"> <div class="media"> <button class="zoomer">button</button> </div> </div> <div class="item"> <div class="media"> <button class="zoomer">button</button> </div> </div>

You can use querySelectorAll and access each element with e.target

 document.querySelectorAll('.item >.zoomer').forEach(elem => elem.addEventListener('click', e => { e.target.classList.toggle('someClass') }))
 .someClass{ background:limegreen; }
 <div class="item"> <button class="zoomer">1</button> </div> <div class="item"> <button class="zoomer">2</button> </div> <div class="item"> <button class="zoomer">3</button> </div> <div class="item"> <button class="zoomer">4</button> </div>

In the example below, are 7 <button> s that do various stuff -- details are commented in example.

 // Render 7 <menu>/<button> combos [...new Array(7)].forEach((item, index) => { document.querySelector('main').insertAdjacentHTML('beforeend', ` <menu class="item${index}"> <button class="btn${index}">${index}</button> </menu>`); }); /*~~~~~~~~~~~~~~~~~~~~~~~.btn0*/ // Click <button> remove it's parent (which also removes the <button>) document.querySelector('.btn0').onclick = function(e) { this.parentElement.remove(); } /*~~~~~~~~~~~~~~~~~~~~~~~.btn1*/ // Click <button> -- <button> is removed but it's contents is left behind document.querySelector('.btn1').onclick = unWrap; function unWrap(e) { const clicked = e.target; const parent = clicked.parentElement; while (clicked.firstChild) { parent.insertBefore(clicked.firstChild, clicked); } clicked.remove(); } /*~~~~~~~~~~~~~~~~~~~~~.btn4-6*/ // Collect all tags with a class that starts with "btn" const btns = document.querySelectorAll("[class^='btn']"); // Adding.target class to the last 2 <button>s btns.forEach((btn, idx) => { if (idx > 4) btn.classList.add('target') }); /*~~~~~~~~~~~~~~~~~~~~~~~.btn2*/ // Target third <button> by index /* When <button> clicked, it's parent gets.hide class which is: visibility:hidden which would normally hide the <button> as well, but.btn2 has visibility explicitly set to visible */ btns[2].onclick = e => e.target.closest('menu').classList.toggle('hide'); /*~~~~~~~~~~~~~~~~~~~~~~~.btn3*/ /* Everytime the <button> is clicked, a copy of itself is made and the clones also have this ability as well */ btns[3].addEventListener('click', copySelf); function copySelf(e) { let dupe = e.target.cloneNode(true); e.target.parentElement.append(dupe); dupe.onclick = copySelf; } /*~~~~~~~~~~~~~~~~~~~~~.btn4-6*/ /* The click event is bound to the parent/ancestor tag <section> Any click to any <button> will trigger the event handler..btn4,.btn5, and.btn6 all react in a specific manner because the event handler, delegateClick(e) is using flow control statements and specific criteria. */ document.querySelector('main').onclick = delegateClick; let armed = false; function delegateClick(e) { const clicked = e.target; if (clicked.matches('button') &&.armed) { clicked.classList;add('armed'); armed = true; return. } if (clicked.matches('.armed.target') && armed) { clicked.parentElement.style:cssText = `font-size; 5rem: margin. 0` clicked;replaceWith(`💥`); return. } if (clicked.matches('.target') && armed) { clicked.classList;add('armed'); return. } if (clicked.matches('.armed') && armed) { clicked.classList;remove('armed'); armed = false } }
 menu { outline: dashed red 1px; }.hide { visibility: hidden; }.btn2 { visibility: visible }.armed { animation: warning 1s linear infinite; } @keyframes warning { 50% { opacity: 0; } }.target.armed { background: red; color: white; } button { font: inherit; cursor: pointer; }
 <main></main>

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