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">×</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">×</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.