Home > front end >  Add and remove classes when click on multiple divs using javascript
Add and remove classes when click on multiple divs using javascript

Time:11-17

I am actually trying to add class (Selected) to the li when clicked and remove Class from neighbour li.

Issue is it doesn't work when there is 2 ul, the below code only work on the 1st ul or when i click on the li of the second li, first li active gets removed

const menuLis = document.querySelectorAll("#top-nav > li");

for (let li of menuLis) {
  
  li.addEventListener("click", function(){
    // 1. Remove Class from All Lis
    for (let li of menuLis) {
      li.classList.remove('selected');
    }
    
    // 2. Add Class to Relevant Li
    this.classList.add('selected');
  });
  
}
.selected{color:red}
<ul id='top-nav'>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

<ul id='top-nav'>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Thank you for the help

CodePudding user response:

You need to use a class, as well to separate handling for each ul for it to properly work:

const menuUls = document.querySelectorAll('.top-nav');

for (const ul of menuUls) {
  const menuLis = ul.querySelectorAll('li');

  for (const li of menuLis) {
    li.addEventListener('click', function () {
      // 1. Remove Class from All Lis
      for (let li of menuLis) {
        li.classList.remove('selected');
      }

      // 2. Add Class to Relevant Li
      this.classList.add('selected');
    });
  }
}
.selected{color:red}
<ul class='top-nav'>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

<ul class='top-nav'>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You can select the element's siblings, and remove the selected class.

const menuLis = document.querySelectorAll(".top-nav > li");

for (let li of menuLis) {
  
  li.addEventListener("click", function(){
    for (let sibling of this.parentNode.children) {
        sibling.classList.remove('selected');
    }
    this.classList.add('selected');
  });
  
}
.selected{color:red}
<ul class='top-nav'>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

<ul class='top-nav'>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Ids must be unique - one per page only, so you should use a class instead.

Another thing to think about is: on every click you're adding new listeners to all the list items which might be okay for a small example but might prove inefficient at scale.

An alternative method would be to use event delegation - attach one listener to each parent element, the list item, and check the information on the event target to update its list items.

const menus = document.querySelectorAll('.top-nav');

menus.forEach(menu => {
  menu.addEventListener('click', handleClick, false);
});

function handleClick(e) {

  const { nodeName, parentNode } = e.target;

  // If the clicked element is a list item
  if (nodeName === 'LI') {

    // Find all the list items of the current list
    const items = parentNode.querySelectorAll('li')

    // Remove the class from each, and then add the
    // class to the element that was clicked
    items.forEach(i => i.classList.remove('selected'));
    e.target.classList.add('selected');

  }

}
.selected { color:red; }
li:hover { cursor: pointer; }
<ul class="top-nav">
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

<ul class="top-nav">
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Additional documentation

  • Related