Get element index for prev/next button

I am trying to finish a slider for a gallery of images and all I’m missing is the prev/next button functionality. Right now the prev button is working but there’s one issue. Here’s the problem, I have a gallery of images, when I click on them a popup shows up displaying the image that was clicked. However, if I click any image that isn’t the first one of the array and click the prev button, it’s gonna take me all they way back to the last image of the array, instead the prev button should take me to the image previous to the one that was clicked.

So if I have 10 images, and I click the one with index of 3 in the array and click the previous button, the popup should show the image with index of 2. Let me show you what I got so far:

<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>

JS:

const overlayString = () => `
<div class="overlay">
  <button class="overlay__close-icon" id="closeOverlay">&times;</button>
  <img src="img/prev.png" alt="Previous button" class="overlay__btn" id="overlayPrev">
  <img src="img/hg-1.jpg" alt="Interior view" class="overlay__img">
  <img src="img/next.png" alt="Next button" class="overlay__btn" id="overlayNext">
</div>`;

// Inject template to html structure
document.querySelector('#main').insertAdjacentHTML('beforeend', overlayString());

// Replace overlay img
const overlay = img => document.querySelector('.overlay__img').src = img.src;

// Show elements based on section
let query = document.querySelector('.gallery');
let images = 'gallery__img';
if (!query) {
  query = document.querySelector('.section-gallery');
  images = 'section-' + images;
}

// Nodelist elements
const imageElems = document.querySelectorAll("." + images);
let currentOverlay;

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

// Change overlay img based on the element that was clicked.
    const target = event.target;
    const index =  Array.prototype.indexOf.call(query.children, target);
    overlay(imageElems[index]);
});

// Overlay prev and next button
document.querySelector('#overlayPrev').addEventListener('click', () => {
  currentOverlay > 0 ? --currentOverlay : currentOverlay = imageElems.length - 1;
  overlay(imageElems[currentOverlay])
});

I know that when I click on the prev button my code is not registering the index of the element that was clicked and that’s probably the reason of why this is it not working as I want, but I’m a stuck here, any help is greatly appreciated.

No jQuery please, I am trying to do this only with pure JS.

Where are you getting the event from?

const target = event.target;

Nowhere, do I need to get it from somewhere?, the event.target in that function is just a reference to the child that was clicked. By using this reference I can then get the index of the child in the nodelist const index = Array.prototype.indexOf.call(query.children, target); and use that to change the overlay image dynamically.

Obviously, you need to get the event somewhere; It is not a special keyword in JavaScript.

This is like trying to use a variable without even defining them.

See documentation about how event handler callback should be implemented.

Are you saying that I should do something like this:

query.addEventListener('click', (event) => {
// Some code here 
const target = event.target
};

That’s what I see in the documentation but in this case I don’t see the need of using event as a parameter of the function since it works the exact same way with or w/o using event as a parameter.

I read your post, which takes me to my last reply, this here:

languages.addEventListener('click', () => {
  const target = event.target;
  const id = target.id;
  const type = target.type;
  if (type === 'radio') {
     console.log('Radio button with id="' + id + '" was clicked');
  }
});

will accomplish the same as this:

languages.addEventListener('click', event => {
  const target = event.target;
  const id = target.id;
  const type = target.type;
  if (type === 'radio') {
     console.log('Radio button with id="' + id + '" was clicked');
  }
});

So, why do I need to use event as a parameter for the callback function? Maybe I didn’t explain well enough in my original post or I totally misunderstood gunhoo first reply.

Oh nvm actually.

You can just set the index to currentOverlay when user clicks one of the image. If this doesn’t work, I need to see the full code.

That is the full code, it’s a fairly small app, it’s basically a slider using some of the concepts you taught me in the other thread but this time using only vanilla JavaScript because I want to get more familiar with it.

I have a practical code pen to show you my problem:

You have 4 squares of different colors, when you click on one of them a popup will show up displaying the image of the square that was clicked, you will also have a prev button, click on it and see what happens. You have to click any square that isn’t the last one on the far right to see what my problem is.

You will have to refresh the page to get out of the popup window.

Like I said just set the currentOverlay when user clicks an image.

const index =  Array.prototype.indexOf.call(query.children, target);
currentOverlay = index
1 Like

So close and yet so far, how did you see this so fast?

The only place to know which img user clicked is the event handler of query. And since currentOverlay is exposed as a global variable. All you need to do is attach the index to that.

1 Like

Honestly, I just knew about this because of OP’s question. So, my situation is no different than yours…

Personally, I’d always stick to specifying it as a parameter because that’s what people normally would expect. Such a special treatment to callback parameter just seems odd to me although there must be a decent reason why that behavior exists.

So, as far as I’m not told the difference, I’ll stay explicit.

I’ve seen this behavior even when there’s no need for a parameter at all and I’ve always wondered about that. As a beginner that was confusing to me.

I would also read about events here

I really didn’t like how I sneaked in currentOverlay = index. Also, I’ve previously mentioned how dumping stuffs here and there is a bad design. So, I’ve decided to decouple Overlay related logic into one place for demonstration purpose and fun. Perhaps, you might be interested in the result:

https://codepen.io/gunhoo93/pen/qyxgvK?editors=1010

The changes are following:

  • Overlay related stuffs are moved into Overlay class
  • Unused codes are commented out (for historic reference)
  • Overlay container element is added to HTML
  • Replaced dead images with cats.

The result is that you don’t have to spread Overlay related stuffs across the code base.

Always. Never, ever, ever use the global event object. It was proprietary to Internet Eroder.

source

1 Like