Adding class to multiple elements same class Javascript?

As you can see all images has “gallery__img” class, but the overlay is only showing up when I click the first image, if I click any img that isn’t the first child nothing will happen, why? What’s wrong with my code? This seems pretty basic but I wouldn’t know why this is happening.

<div class="gallery">
      <img src="img/hg-1.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-2.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-3.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-4.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-5.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-6.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-7.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-8.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-9.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-10.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-11.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-12.jpg" alt="Interior view" class="gallery__img">
    </div>
//Open overlay
document.querySelector('.gallery__img').addEventListener('click', function () {
  document.querySelector('.overlay').classList.add('showOverlay');
});

// Close overlay
document.querySelector('#closeOverlay').addEventListener('click', function() {
  document.querySelector('.overlay').classList.remove('showOverlay');
});
.overlay {
  height: 100vh;
  width: 100%;
  padding: 0 5rem;
  background-color: black;
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  opacity: 0;
  visibility: hidden;
  @include transition;
}

.showOverlay {
  opacity: 1;
  visibility: visible;
}

I’ve been using jQuery and I thought pure JS would be as easy, how naive. While this code here works:

document.querySelectorAll('.gallery__img').forEach(img => {
  img.addEventListener('click', function() {
    document.querySelector('.overlay').classList.add('showOverlay');
  })
});

I find your solution much cleaner and reusable, thanks.

Following your advice I did this:

const addClickEvent = () => document.querySelectorAll('.gallery__img').forEach( () => document.querySelector('.overlay').classList.add('showOverlay') );

document.querySelector('.gallery').addEventListener('click', addClickEvent);

This works, but I am trying to do the following:

let homeIMG = document.querySelectorAll('.gallery__img');
let sectionIMG = document.querySelectorAll('.section-gallery__img');

const addClickEvent = el => el.forEach( () => document.querySelector('.overlay').classList.add('showOverlay'));

document.querySelector('.gallery').addEventListener('click', addClickEvent(homeIMG));
document.querySelector('.section-gallery').addEventListener('click', addClickEvent(sectionIMG));

And it’s giving me an error, as you can see I am just trying to use the same callback function with a different parameter to handle different sections.

Uncaught TypeError: Cannot read property ‘addEventListener’ of null” Why am I getting this error?

It does work, which makes me wonder why if I do it like this:

document.querySelector('.gallery').addEventListener('click', addClickEvent(homeIMG));

It’s like if I was calling the function instead of triggering it with the click event, like your code does.

But something odd is happening, I have 2 html files (index.html and section.html), the structure of these files look like like this:

<!-- index.html -->
<div class="gallery">
      <img src="img/hg-1.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-2.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-3.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-4.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-5.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-6.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-7.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-8.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-9.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-10.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-11.jpg" alt="Interior view" class="gallery__img">
      <img src="img/hg-12.jpg" alt="Interior view" class="gallery__img">
    </div>
<!-- Popup window -->
  <div class="overlay">
    <button class="overlay__close-icon" id="closeOverlay">&times;</button>
    <img src="img/prev.png" alt="Previous button" class="overlay__btn">
    <img src="img/hg-1.jpg" alt="Interior view" class="overlay__img">
    <img src="img/next.png" alt="Next button" class="overlay__btn">
  </div>
<!-- Script -->
 <script src="app.js"></script>
<!-- section.html -->
  <div class="section-gallery">
      <img src="img/5east-1.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-2.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-3.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-4.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-5.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-6.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-7.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-8.jpg" alt="Interior view" class="section-gallery__img">
      <img src="img/5east-9.jpg" alt="Interior view" class="section-gallery__img">
    </div>
<!-- Popup window -->
  <div class="overlay">
    <button class="overlay__close-icon" id="closeOverlay">&times;</button>
    <img src="img/prev.png" alt="Previous button" class="overlay__btn">
    <img src="img/hg-1.jpg" alt="Interior view" class="overlay__img">
    <img src="img/next.png" alt="Next button" class="overlay__btn">
  </div>
<!-- Script -->
 <script src="app.js"></script>

The JS so far:

//Open overlay
let homeIMG = document.querySelectorAll('.gallery__img');
let sectionIMG = document.querySelectorAll('.section-gallery__img');

const addClickEvent = el => el.forEach( () => document.querySelector('.overlay').classList.add('showOverlay') );

document.querySelector('.gallery').addEventListener('click', function() {
  addClickEvent(homeIMG)
});

document.querySelector('.section-gallery').addEventListener('click', function() {
  addClickEvent(sectionIMG)
});

// Close overlay
document.querySelector('#closeOverlay').addEventListener('click', function() {
  document.querySelector('.overlay').classList.remove('showOverlay');
});

I keep getting this message in the console: “Uncaught TypeError: Cannot read property ‘addEventListener’ of null” It’s like a conflict with the files, this is probably a noobie mistake but I’m failing to understand of why this conflict is happening.

Yes… I solved it like this:

if (document.querySelector('.gallery')) {
  document.querySelector('.gallery').addEventListener('click', function() {
    addClickEvent(homeIMG);
  });
} else {
  document.querySelector('.section-gallery').addEventListener('click', function() {
    addClickEvent(sectionIMG);
  });
}

The thing is that when I use jQuery I don’t get this conflict, but the more I use pure JS the more I see all the differences. Doing this project with pure JS is going to be fun and frustrating for me. Would you say this was a fine solution?

Yeah you are right about that, I originally coded everything in a different and less efficient way and I just left it there as I was just testing. But with your solution I may not need that function at all, instead I could just do this:

// Open overlay
query.addEventListener('click', () => {
  document.querySelector('.overlay').classList.add('showOverlay');
  document.querySelector('body').style.overflow = 'hidden';
});

This way I have everything inside one function.