Is it possible to have navigation buttons within a modal to easily browse through an image gallery?

I recently set up an image gallery on my website using CSS and Javascript based on a tutorial from w3schools.com. After encountering some challenges with linking to external images, a helpful individual here guided me in the right direction to fix it. Now, I am looking to add navigation buttons for moving forwards and backwards through the gallery without having to close the modal each time. While I have successfully added arrow buttons to the modal that appear as desired, I'm struggling to make them change the image and text content in the center. So far, my attempts have only prevented the modal from crashing but not achieved the desired functionality. Here is the current state of my code:


        <div id="myModal" class="modal">
          <span class="close">×</span>
          <div class="backButton" id="bckBtn"><img src="../gallery_images/buttonPlaceHolder.png" alt="Back" style="width:100%; float:left"></div>
          <img class="modal-content" id="img01">
          <div id="caption"></div>
          <div class="forwardButton" id="fwdBtn"><img src="../gallery_images/buttonPlaceHolder.png" alt="Forward" style="width:100%; float:right;"></div>
        </div>


        <script>
            // JavaScript code here...
        </script>
    

Working with Javascript for the first time today, the process seems lengthy and complex. Any tips or advice on simplifying this would be greatly appreciated.

Answer №1

It seems like your question is more along the lines of "Is there anyone here cool enough to code something for me?" isn't it?

I decided to take it as a fun exercise to complete, especially since Turnip had already contributed a lot on your previous question. I thought it would be nice to encourage someone on their first day working with Javascript.
But who knows if you'll get this lucky in the future!
;)

Essentially, what this code does is assign an onclick function to all your thumbnails to display the corresponding larger image in your modal. It also initiates the opening of your modal with the click on the first thumbnail.
This part was done by Turnip.
Note that these thumbnail images must now have the "GalleryImg" class.
I made this addition to Turnip's version to exclude your back and forward buttons from the loop, since they are also considered images.

For your back and forward buttons, I incorporated a hidden input which serves as a memory slot holding the currently displayed image in the modal.
Hence, it's important that the thumbnails are all assigned an id that follows a "zero-based" sequence: The first thumbnail id should be img-0.
With this information, your back and forward buttons can determine the id number of the image you want to display based on the button clicked.

Oh, I also anticipated your potential next question – how to restart from the first image once the last one has been reached, and vice versa.
Try to identify which lines handle this scenario! ;)

Here is the code:

<!-- The Modal -->
<div id="myModal" class="modal">
  <span class="close">×</span>
  <div class="backButton" id="bckBtn"><img src="../gallery_images/buttonPlaceHolder.png" alt="Back" style="width:100%; float:left"></div>
  <img class="modal-content" id="img01">
  <div id="caption"></div>
  <div class="forwardButton" id="fwdBtn"><img src="../gallery_images/buttonPlaceHolder.png" alt="Forward" style="width:100%; float:right;"></div>
  <input type="hidden" id="mem">
</div>

<img class="GalleryImg" id="img-0" src="../path/to/image1" alt="alternate text 1"><div>caption text 1</div>
<img class="GalleryImg" id="img-1" src="../path/to/image2" alt="alternate text 2"><div>caption text 2</div>
<img class="GalleryImg" id="img-2" src="../path/to/image3" alt="alternate text 3"><div>caption text 3</div>
<img class="GalleryImg" id="img-3" src="../path/to/image4" alt="alternate text 4"><div>caption text 4</div>
<!-- and so forth... -->

<script>
var modal = document.getElementById('myModal');

var span = document.getElementsByClassName("close")[0];
span.onclick = function() { 
    modal.style.display = "none";
}

var backButton = document.getElementById('bckBtn');
var forwardButton = document.getElementById('fwdBtn');
var images = document.getElementsByClassName('GalleryImg');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
var i;
for (i = 0; i < images.length; i++) {
   images[i].onclick = function(){
       modal.style.display = "block";
       var src = this.src;
       var filename = src.substring(src.lastIndexOf('/')+1);
       var filepath = src.substring(0, src.lastIndexOf('/')+1);
       modalImg.src = filepath + 'large-' + filename;
       modalImg.alt = this.alt;
       captionText.innerHTML = this.nextElementSibling.innerHTML;
       document.getElementById("mem").value=this.id;
   }
}

backButton.onclick = function(){
    ImageId = document.getElementById("mem").value.split("-");
    PreviousImage = parseInt(ImageId[1])-1;
    if(PreviousImage<0){PreviousImage=images.length-1;}
    images[PreviousImage].click();
}

forwardButton.onclick = function(){
    ImageId = document.getElementById("mem").value.split("-");
    NextImage = parseInt(ImageId[1])+1;
    if(NextImage>=images.length-1){NextImage=0;}
    images[NextImage].click();
}
</script>


EDIT (2016-05-03)

To reverse the numbering of ids, as requested in the comments below, making them look like this:

<!-- Future images to be added here-->
<img class="GalleryImg" id="img-3" src="../path/to/image4" alt="alternate text 4"><div>caption text 4</div>
<img class="GalleryImg" id="img-2" src="../path/to/image3" alt="alternate text 3"><div>caption text 3</div>
<img class="GalleryImg" id="img-1" src="../path/to/image2" alt="alternate text 2"><div>caption text 2</div>
<img class="GalleryImg" id="img-0" src="../path/to/image1" alt="alternate text 1"><div>caption text 1</div>

An array of the images elements needs to be reversed... Since the ids are linked to the position of the target image in an array of elements.
Then, the logic of the back and forward buttons needs to be reversed as well.

Use the following code:

// Create a "reversed" images array
var imagesReversed = [];    
var i = images.length;
while(i--){
    imagesReversed.push(images[i]);
}

// Increment by 1 from the current id to get the targeted image position in the reversed array.
backButton.onclick = function(){
    ImageId = document.getElementById("mem").value.split("-");
    PreviousImage = parseInt(ImageId[1])+1;
    if(PreviousImage>images.length-1){PreviousImage=0;}
    imagesReversed[PreviousImage].click();
}

// Decrement by 1 from the current id to get the targeted image position in the reversed array.
forwardButton.onclick = function(){
    ImageId = document.getElementById("mem").value.split("-");
    NextImage = parseInt(ImageId[1])-1;
    if(NextImage<0){NextImage=images.length-1;}
    imagesReversed[NextImage].click();
}

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

How CSS properties can cause one div to push down another

I am looking to incorporate a simple sidebar into an existing layout (content). Here is what I have so far: HTML <div class="container"> <div class="side-menui"> </div> .... </div> Full HTML <div class="c ...

Manipulation of CSS DOM elements for achieving responsive design

I am working with a div field that contains an input element and a label element, both set to display:block <div class="cf-full"> <input id="a" > <label class="helptext"></label> </div> In the standard view, the inpu ...

Is there a way to make the menu slide up from the bottom button instead of instantly appearing? Looking for solutions in HTML, CSS, and JS

I have attempted numerous methods, but the menu keeps showing up in the same way every time. I've experimented with changing the height from 0 to 20%, width from 0 to 100%, using jQuery, JavaScript, slideUp/Down, hide/Show, adjusting margin-bottom fro ...

Unable to use addEventListener on media queries exceeding 768px

When testing the site on Firefox 49 and Chrome 63, I encountered the same issue. Clicking on each card worked fine on iPhone4, Galaxy 5, and iPhone 8 using Chrome. However, after switching orientations from 640px to 320px portrait view, the top card would ...

Utilize the ng-file-upload library to easily upload files to MongoDB's GridFS

I need to upload a file larger than 16MB to my Mongo database. I am using the ng-file-upload module on the front end (https://github.com/danialfarid/ng-file-upload). On the back-end, I am utilizing connect-busboy and gridfs-stream modules. However, I enc ...

Using Three JS: Import an OBJ file, move it to the center of the scene, and rotate around it

I am trying to figure out how to load an OBJ file and translate its coordinates to the world origin (0,0,0) in order to make orbit controls function smoothly without using Pivot points. My goal is to automatically translate random OBJ objects with differe ...

When using Google login in React and Node.js, the requested scope may not be returned as expected

Looking to get additional scope data from Google API during login on my app. I am utilizing react-google-login to obtain a token in my React application with the following scopes: scope='https://www.googleapis.com/auth/user.birthday.read https://www. ...

Utilizing CSS transitions in combination with Bootstrap flexboxes: A guide

I'm attempting to incorporate a transition delay into my flexbox on hover. However, it seems like there might be an issue in my code. .flex-fill { transition-delay: 250ms !important; transition:flex 0.5s ease-out !important; } .flex-fill:hover {w ...

Trigger a modal from one sibling Angular component to another

My application utilizes an Angular6 component architecture with the following components: <app-navbar></app-navbar> <app-dashboard></app-dashboard> The Dashboard component consists of: <app-meseros> </app-meseros> < ...

Is there a way to make jQuery Validate display errors within the form elements rather than outside of them?

Given the jQuery Validate basic example provided in the link below, what method can be used to display error messages within form elements whenever feasible (excluding checkboxes)? http://docs.jquery.com/Plugins/validation#source ...

Convert the existing jQuery function to Angular 9 syntax

I have just started learning Angular and am finding it challenging to rewrite a jQuery code that I use for loading the "classycountdown" script. Below is the jQuery function that I need to convert: $(document).ready(function() { var remainingSec = $(& ...

Creating a custom JavaScript library using an existing npm module (codius)

Embarking on a new journey with this, never tried it before. Currently utilizing https://github.com/codius/codius-host. The development of Codiu§ has been abandoned, however I am determined to salvage some parts of it for my own project. It is crucial fo ...

bootstrap hstack containing a table with scroll functionality

Trying to implement a scrollable table within a container alongside other components has proven challenging. While the table functions perfectly on its own, integrating other components below it has presented issues. The use of hstack and d-flex came to mi ...

What makes fastify-plugin better than simply calling a regular function?

I recently came across a detailed explanation of how fastify-plugin operates and its functionality. Despite understanding the concept, I am left with a lingering question; what sets it apart from a standard function call without using the .register() metho ...

What could be causing the malfunction of the Bootstrap-3 Modal?

<div class='container row'> <div style='padding-top:2em;' class='col-md-4 col-sm-4 col-xs-4'> <img data-toggle='modal' href='#modal-id' src='img/".$row_now[' image ']."&a ...

Add each individual item from the array into the database sequentially

I have a collection of data entries that I need to individually insert into the database, like so: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}] In essence, I plan to use a for..of loop to iterate over this array and add them one by one. If ...

What is the process for transferring an image from the main page to another?

For days, I have been searching for an answer without any luck. It seems that I just can't wrap my head around it and apply it to what I am working on. Currently, I am using PHP to store images on the server when a user hits submit. My goal is to dis ...

The process of registering with JWT tokens and the challenge that arises when a token expires

I had the idea to implement a registration process that requires users to provide their username, email (which must not already exist in the database), password, and confirm password. The project is built using NextJS with pages router and Typescript. impo ...

Apache Server Efficiently Retrieves .php Files from Subfolders

After tirelessly searching the vast expanse of the internet for a solution to my dilemma and trying every method I stumbled upon, I am still facing the same issue. The problem arises when I attempt to access a .php file in a subdirectory from another file ...

When attempting to call a function from a separate JavaScript file in Vue, the returned value is showing

My goal is to trigger my notification function from another JS file, but I keep getting an undefined error. The code snippet for the notification function in notification.js is as follows: function notification(message, level = 'success') { ...