Home > Net >  Click button to toggle class of parent element - pure javascript
Click button to toggle class of parent element - pure javascript

Time:07-01

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 >
<button ></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!

CodePudding user response:

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 >
  <button >button</button>
</div>
<div >
  <button >button</button>
</div>
<div >
  <button >button</button>
</div>
<div >
  <button >button</button>
</div>
<div >
  <button >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 >
  <div >
    <button >button</button>
  </div>
</div>
<div >
  <div >
    <button >button</button>
  </div>
</div>
<div >
  <div >
    <button >button</button>
  </div>
</div>
<div >
  <div >
    <button >button</button>
  </div>
</div>

CodePudding user response:

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 >
<button >1</button>
</div>
<div >
<button >2</button>
</div>
<div >
<button >3</button>
</div>

<div >
<button >4</button>
</div>

CodePudding user response:

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 >
  <button >${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(`           
  • Related