Use vanilla javascript to add / remove class to a different element after clicking on another one
Asked Answered
C

2

30

I have looked through a number of similar questions but can not find a specific example of one that answers in vanilla JS how to add and remove a class to a different element from the one clicked on. I know it has something to do with setting up a loop and iterating through the elements, but I got lost in the exact process.

I have a number of elements with a class name of faq-container and when I click on any of them, I would like the class faq-display added to the body tag. I know I have to set up a loop like for (var i = 0; i < elements.length; i++) { elements[i].classList.remove('hover'); } but I am unsure as to exactly where to write it in the code to make this work. I have tried a number of ways but all fail.

My current script is as follows, where I simply target the first element in the array, but I want to be able to click on any of the faq-container elements and add the class name to the first and only body tag:

document.addEventListener("DOMContentLoaded", function() {

  document.getElementsByClassName('faq-container')[0].addEventListener('click', function() {
    var faqToggle = document.getElementsByTagName('body')[0];
    if (faqToggle.classList.contains('faq-display')) {
      faqToggle.classList.remove('faq-display');
      // alert("remove faq display!");
    } else {
      faqToggle.classList.add('faq-display');
      // alert("add faq display!");
    }
  });


});
<div class="faq-container cf" id="faq-container">
  <h3 <?=ifxless::element( 'name')?>><?=ifxless::fill($this,'name');?> </h3>

  <div class="faq-content">
    <div class="h_line">&nbsp;</div>

    <div class="faq-bullets" <?=ifxless::element( 'content')?>>
      <?=ifxless::fill($this, 'content');?>
    </div>

  </div>

</div>
Culch answered 9/1, 2017 at 14:49 Comment(2)
Please update your snippet with HTML to make it a minimal reproducible exampleAllamerican
the mark up is part of a company content management system using code blocks. But I will add it to my example ...Culch
H
50

document.addEventListener("DOMContentLoaded", function() {
  var faqContainers = document.getElementsByClassName('faq-container');
  var faqToggle = document.getElementsByTagName('body')[0];
  for (var i = 0; i < faqContainers.length; i++) {

    faqContainers[i].addEventListener('click', function() {

      if (faqToggle.classList.contains('faq-display')) {
        faqToggle.classList.remove('faq-display');
        // alert("remove faq display!");
      } else {
        faqToggle.classList.add('faq-display');
        // alert("add faq display!");
      }

    });
  }


});
Horseshit answered 9/1, 2017 at 14:57 Comment(2)
Apart from me being first and using the better querySelectorAll what is the difference between this and mine?Allamerican
This works but @mplungjan's answer is betterVerecund
A
15

You need to loop:

[...document.querySelectorAll('.faq-container')] // spread is compatible with older EDGE
  .forEach(faq => faq.addEventListener('click', () => 
  document.querySelector('body').classList.toggle('faq-display')))

NOTE: if you have MANY of these divs, you are better off having one event handler for a parent and test what was clicked.

document.getElementById('faqContainerParent')
  .addEventListener('click', e => {
  const tgt = e.target;
  if (tgt.matches(".faq-container") || tgt.closest("div.faq-container")) { // is it the faq-container or one of the descendants
    document.querySelector('body').classList.toggle('faq-display')
  }
});
Allamerican answered 9/1, 2017 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.