0

I'm trying to use a function for multiple buttons. I have a loop and for every button is clicked I want to add a specific class to the element

for (let i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener("click", openAside);
}
function openAside() {
    document.querySelectorAll("#overlay").classList.add("active");
}

but for some reason i got

Cannot read property 'add' of undefined at HTMLDivElement.openAside

I feel like its a basic mistake, but I'm new to javascript and I can't really figure it out.

Barmar
  • 741,623
  • 53
  • 500
  • 612
Denis
  • 5
  • 2
  • Use `querySelector`, not `querySelectorAll`. – Barmar Jul 20 '20 at 17:21
  • Change `querySelectorAll` to `querySelector`. the former returns a nodelist while the latter returns a single element – j08691 Jul 20 '20 at 17:21
  • @Barmar That would make the `#overlay` button always get the `active` class no matter which button you click on. – Scott Marcus Jul 20 '20 at 17:32
  • @ScottMarcus There's nothing in the question that suggests it should do something else. – Barmar Jul 20 '20 at 17:41
  • @Barmar I interpret this to mean just that: *I have a loop and for every button is clicked I want to add a specific class to the element* – Scott Marcus Jul 20 '20 at 17:41
  • He didn't say "add a specific class to the button". I interpret "the element" to mean the overlay, not the button. – Barmar Jul 20 '20 at 17:42

1 Answers1

1

document.querySelectorAll() returns a node list (collection of elements) and a collection of elements doesn't have a classList, a single element does. Instead make the code

this.classList.add("active");

because this will be bound to the object that triggered the event callback in the first place, which is the element that you want the style added to.

But, better yet, instead of looping over all the buttons and attaching the same event listener to each of them, use event delegation and just add a single event listener to the parent of all the buttons. Because events bubble, the event will reach the parent and is handled there. When it is handled, using event.target you can access the object that initially triggered the event and operate on it that way.

Here's an example:

// Add the event listener to the parent
document.querySelector(".buttons").addEventListener("click", function(event){
  // Whichever button was clicked will be the: event.target
  event.target.classList.toggle("active");
});
.active { background-color:#ff0; }
<div class="buttons">
  <button type="button">One</button> 
  <button type="button">Two</button> 
  <button type="button">Three</button>
</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71