0

I built an app which add a class when i click on specified element. I want to add an additional functionality to my app. When i will click on an item i want to add my class clicked ( now the app works in the same way), but when i will click on another item i want to add the class on the last item and to remove the class from the first item.

document.addEventListener("DOMContentLoaded", () => {
    const list = document.querySelectorAll('.item');
    for (let i = 0; i < list.length; i++) {
        list[i].addEventListener('click', function (e) {
            const curentItem = e.target;
            if (curentItem) {
                curentItem.classList.add('clicked');
                console.log(curentItem)
            }

        })
    }
});
const arr = [1, 2, 3, 4]
const mapping = arr.map(item => `<li class="item">${item}</li>`);
document.querySelector('.items').innerHTML = mapping.join(' ');
.clicked {
    background-color: blue;
}
<div class="app">
  <ul class="items">
  </ul>
</div>

How to change my code to get the specified result?

Asking
  • 3,487
  • 11
  • 51
  • 106
  • So basically you only want one element to have the 'clicked' class at any given time, right? – Tanner Jan 27 '20 at 15:46
  • Does this answer your question? [How do I toggle an element's class in pure JavaScript?](https://stackoverflow.com/questions/18880890/how-do-i-toggle-an-elements-class-in-pure-javascript) – enno.void Jan 27 '20 at 15:46

4 Answers4

5

You can loop through list and remove class from each item and then add to the last item

document.addEventListener("DOMContentLoaded", () => {
    const list = document.querySelectorAll('.item');
    for (let i = 0; i < list.length; i++) {
        list[i].addEventListener('click', function (e) {
            const curentItem = e.target;
            if (curentItem) {
                list.forEach(item => item.classList.remove('clicked'))
                curentItem.classList.add('clicked');
                console.log(curentItem)
            }

        })
    }
});
const arr = [1, 2, 3, 4]
const mapping = arr.map(item => `<li class="item">${item}</li>`);
document.querySelector('.items').innerHTML = mapping.join(' ');
.clicked {
    background-color: blue;
}
<div class="app">
  <ul class="items">
  </ul>
</div>

Further more you shouldn't create html element using innerHTML and after that use
querySelectorAll() and select the elements.

A better and clean way for same functionality is like.

const ul = document.querySelector('.items');
const listItems = [];
document.addEventListener("DOMContentLoaded", () => {
  initalizeItems([1, 2, 3, 4])
});

function initalizeItems(items){
  items.forEach(text => {
    const li = document.createElement('li');
    li.innerHTML = text;
    li.addEventListener('click', onItemClick) 
    listItems.push(li);
    ul.appendChild(li)
  })
}

function onItemClick(){
  listItems.forEach(item => item.classList.remove('clicked'));
  this.classList.add('clicked');
}
.clicked {
    background-color: blue;
}
<div class="app">
  <ul class="items">
  </ul>
</div>
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
0

Just remove the class white looping all items inside the click event listner :

.....
for (let i = 0; i < list.length; i++) {
    list[i].classList.remove('clicked');
.....
M0ns1f
  • 2,705
  • 3
  • 15
  • 25
0

document.addEventListener("DOMContentLoaded", () => {
    const list = document.querySelectorAll('.item');
    for (let i = 0; i < list.length; i++) {
        list[i].addEventListener('click', function (e) {
            for (let i = 0; i < list.length; i++){
              list[i].classList.remove('clicked');
            // querySelectorAll return an array of dom elements, u can access them directly.
            }
            const curentItem = e.target;
            if (curentItem){
                curentItem.classList.add('clicked');
                console.log(curentItem)
            }

        })
    }
});
const arr = [1, 2, 3, 4]
const mapping = arr.map(item => `<li class="item">${item}</li>`);
document.querySelector('.items').innerHTML = mapping.join(' ');
.clicked {
    background-color: blue;
}
<div class="app">
  <ul class="items">
  </ul>
</div>
darkhouse
  • 205
  • 5
  • 15
0

Just use Element.classList.toggle, and as a boolean (toggle takes an optional second argument that basically says add if true, and remove if false), pass currentlyIteratedItem === clickedItem:

document.addEventListener("DOMContentLoaded", () => {
  const list = document.querySelectorAll('.item');
  for (const listItem of list) {
    listItem.addEventListener('click', function(e) {
      const clickedItem = e.target;
      for (const currentlyIteratedItem of list) {
        currentlyIteratedItem.classList.toggle('clicked', currentlyIteratedItem === clickedItem);
      }
    })
  }
});
const arr = [1, 2, 3, 4]
const mapping = arr.map(item => `<li class="item">${item}</li>`);
document.querySelector('.items').innerHTML = mapping.join(' ');
.clicked {
  background-color: blue;
}
<div class="app">
  <ul class="items">
  </ul>
</div>
connexo
  • 53,704
  • 14
  • 91
  • 128