Is there a way to navigate to the next or previous image in a lightbox by using ev.target.nextElementSibling or ev.target.prevElementSibling?

I am new to the world of web development

Currently, I'm facing an issue with my lightbox feature. I want to navigate between images by using ev.target.nextElementSibling and ev.target.prevElementSibling when clicking on the next/previous arrow.png icons. I have tried several solutions but haven't been successful so far. When I click on an image, it zooms in correctly, but when I click on the arrow, the image disappears instead of transitioning to the next/previous one.

const imgs = document.querySelectorAll('.gallery img');
const lightbox = document.querySelector('.lightbox');
const arrowNext = document.querySelector('.arrowNext');
for (let index = 0; index < imgs.length; index++) {
  const img = imgs[index];
  img.addEventListener('click', showLightbox);
}

function showLightbox(ev) {
  const prevEl = ev.target.prevElementSibling;
  const nextEl = ev.target.nextElementSibling;
  console.log(ev)
  const lightbox = document.querySelector('.lightbox');
  const img = document.querySelector('.lightbox img');
  const imgUrl = ev.target.src;
  img.src = imgUrl;

  lightbox.classList.add('visible');
}

lightbox.addEventListener('click', hideLightbox);

function hideLightbox() {
  lightbox.classList.remove('visible');
}

arrowNext.addEventListener('click', nextPhoto);

function nextPhoto(ev) {
  const arrowNext = document.querySelector('.arrowNext');
  const img = document.querySelector('.arrowNext img');
  const imgUrl = ev.target.src;
  img.src = imgUrl;
  const next = ev.target.nextElementSibling;
}
body {
  background: #eee;
}

.lightbox {
  position: absolute;
  z-index: 100;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
  top: 0;
  left: 0;
  justify-content: center;
  align-items: center;
  display: flex;
  transition: all 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
  transform: scale(0);
}

.visible {
  transform: scale(1);
}

.lightbox img {
  max-width: 80%;
  max-height: 80%;
}

.arrowNext {
  cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Lightbox</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <section class="gallery">
    <img src="/img/img1.jpg" alt="photo1">
    <img src="/img/img2.jpg" alt="photo2">
    <img src="/img/img3.jpg" alt="photo3">
    <img src="/img/img4.jpg" alt="photo4">
  </section>
  <div class="lightbox">
    <div class="arrowPrev">
      <img src="/img/prev arrow.png" alt="">
    </div>
    <img src="/img/img5.jp" alt="">
    <div class="arrowNext">
      <img src="/img/next arrow.png" alt="">
    </div>
  </div>
  <script src="main.js" type="text/javascript"></script>
</body>

</html>

Answer №1

Just a heads up, ev.target refers to the element that the mouse clicks on, which in this case is the arrow. What you actually want is to access the next image, not the next arrow.

I recommend using an index variable to keep track of which image is currently displayed, and then use

document.querySelectorAll('img')[index+1]
to retrieve the next image.

Your code might result in something like:

(Note: Using ev.stopPropagation() is essential to prevent closing the lightbox when the arrow is clicked.)

const imgs = document.querySelectorAll('.gallery img');
const lightbox = document.querySelector('.lightbox');
const arrowNext = document.querySelector('.arrowNext');

var index = 0;

for (let index = 0; index < imgs.length; index++) {
  const img = imgs[index];
  img.addEventListener('click', (e) => {showLightbox(e, index)});
}

function showLightbox(ev, i) {
  const prevEl = ev.target.prevElementSibling;
  const nextEl = ev.target.nextElementSibling;
  const lightbox = document.querySelector('.lightbox');
  const img = document.querySelector('.lightbox img');
  const imgUrl = ev.target.src;
  img.src = imgUrl;
  
  index = i;

  lightbox.classList.add('visible');
}

lightbox.addEventListener('click', hideLightbox);

function hideLightbox() {
  lightbox.classList.remove('visible');
}

arrowNext.addEventListener('click', nextPhoto);

function nextPhoto(ev) {
  ev.stopPropagation();
  index++;

  const arrowNext = document.querySelector('.arrowNext');
  const img = document.querySelector('.arrowNext img');
  const imgUrl = imgs[index].src;
  img.src = imgUrl;
}
body {
  background: #eee;
}

.lightbox {
  position: absolute;
  z-index: 100;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
  top: 0;
  left: 0;
  justify-content: center;
  align-items: center;
  display: flex;
  transition: all 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
  transform: scale(0);
}

.visible {
  transform: scale(1);
}

.lightbox img {
  max-width: 80%;
  max-height: 80%;
}

.arrowNext {
  cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Lightbox</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <section class="gallery">
    <img src="/img/img1.jpg" alt="photo1">
    <img src="/img/img2.jpg" alt="photo2">
    <img src="/img/img3.jpg" alt="photo3">
    <img src="/img/img4.jpg" alt="photo4">
  </section>
  <div class="lightbox">
    <div class="arrowPrev">
      <img src="/img/prev arrow.png" alt="">
    </div>
    <img src="/img/img5.jp" alt="">
    <div class="arrowNext">
      <img src="/img/next arrow.png" alt="" style="background:red;padding:20px">
    </div>
  </div>
  <script src="main.js" type="text/javascript"></script>
</body>

</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issues with CodeIgniter paths causing disruption to CSS background-image declaration

I've been working on a website with backend for two separate customers, each with their own unique URLs. I encountered an issue with Javascript links (ajax calls using url:) but managed to resolve it by using a global variable: var SiteURL='< ...

Functionality fails to load correctly post completion of AJAX request

After successfully implementing an API call to OS Maps (UK map builder) as per their documentation, I encountered a problem when trying to display a map based on a custom field name using ACF (Advanced Custom Fields) in WordPress. The issue arises because ...

Endless cycle occurs when an asynchronous action is dispatched within useEffect

I encountered a never-ending loop problem when I added a dispatch function in my code within the useEffect hook. Despite looking into similar issues raised by others, I still can't seem to figure out the root cause of the problem. Here is how my compo ...

The query callback does not recognize 'done' as a function, leading to a

I'm attempting to save the result of a query into a variable. I've learned that using a callback is necessary for this task. However, I am encountering errors in the process. function fetchUserData(user) { if (user.checkUserStatus) { var u ...

Prisma DB is a versatile database that excels in handling m-n

In my database, I have implemented a structure with 3 tables: Member, Characters, and MemberCharacters. Each member can have multiple Characters, and each Character can be used by multiple Members. To handle this many-to-many relationship, I have utilized ...

Is it possible to nest HTML within a Route component?

<Router> <Routes> <Route path='/' element={<Navbar />} /> <Route path='/' element={<div className='recipes'> {query ? query.map((object, i) => ( <Recipe ...

What types of numerical values is the Number data type capable of storing?

Is it true that a JavaScript number has the ability to store both a 64-bit number and a 64-bit Integer? I'm still unsure about this concept. ...

How do you efficiently include several elements within a single column in Boostrap 5?

I've been working with Bootstrap 5 to display a grid of images similar to this link, but the images are not displaying as intended due to some CSS code. #projects img { width: 100%; height: 100%; } <section id="projects"> ...

Guide to making a reusable AJAX function in JavaScript

Currently, I'm working on developing a function that utilizes AJAX to call data from another server and then processes the returned data using a callback. My goal is to be able to make multiple calls to different URLs and use the distinct responses in ...

Creating a custom data type with a specific value in GraphQL

I am new to graphQL and have some questions regarding it. After going through the documentation, I decided to build something of my own. Currently, my setup is quite simple. At the beginning of my application, I have the following code: const express = ...

Passing a JSON file name as an argument to a command line in Node.js

When I run app.js using the command node app.js, it will execute const inputData = require('./input.json'); Now, my question is - can I pass the file name as an argument to const inputData = require('./file.json'); directly from the co ...

Unlock the potential of accessing data from the parent controller within a child controller in AngularJS

Is it possible to retrieve model data from the parent controller within a child controller? <div ng-controller="abc"> <div ng-controller="def"> <span> {{name}}</span> </div> </div> Can we access the val ...

Tips for utilizing process.stdin in Node.js with Javascript?

Currently, I'm developing a Javascript-based poker game that is designed to process standard input in the following manner: https://i.stack.imgur.com/D1u15.png The initial line of input will consist of an integer indicating the total number of playe ...

How can I reduce the delay in Angular 5 to a minimum?

The following code represents a simple request function: getItem() { return this.http .post<ItemModel>(`${this.apiUrl}/${methodUrl}`, {}) .subscribe(response => { ... }); } Depending on the duration of the ...

Managing uncaught exceptions in node.js

While working on my project, I encountered an issue with catching exceptions when opening a connection using mongoose.createConnection. Here's the code snippet causing the problem: var createdDb = mongoose.createConnection(connectionString); createdD ...

Add the following code snippet below every second set of two paragraphs that are enclosed within h

I am looking to add Advertisements following the 2nd paragraph in every h2 tag. Here is an example of what I want: <h2>Sub title</h2> <p>1st paragraph</p> <p>2nd paragraph</p> <div>INSERTED AD</div> functio ...

When you scroll a fixed element on the page, the block is truncated

I made a modification for adding cart items and included a script for managing my cart The cart is supposed to stick to the right edge and scroll up and down on the page Everything seems to work, but there's a slight issue when I click on Add 1 and ...

.load() not triggering for images that are not in the cache - jquery

In Safari and Opera, the callback function of .load doesn't wait for uncached images to be fully loaded. With cached images, it works perfectly fine. The code may seem a little complicated, but I'll do my best to simplify it... So, here is my J ...

Removing items dynamically from a list created using ng-repeat

I have an array of nested JSON objects and I am using ng-repeat to create a list with the nested arrays. My goal is to dynamically delete items from this list upon button click by calling a function in the controller: $scope.remove= function(path){ va ...

Achieving a consistent user experience across both mobile and desktop devices without using a separate mobile version or media queries

Is it possible to have the same URL website.com display completely different content depending on whether it is accessed from a mobile device or not? I am looking for a solution that does not involve using CSS media queries or creating a separate subdomai ...