Jump to content

Multiple lightbox on one page


red_baron

Recommended Posts

Hello!  Newbie here.  I'm OK with HTML and CSS, but seriously lack knowledge on JS.  Wanting to learn, but I am under the gun to complete a new web site first and I'm stumped on some JS requirements.  W3 Schools is a great source of info and learning for me, but I can't seem to find a complete and useful answer yet to this problem.  I am making a Products page for my business where I want to show 4 - 6 pictures in a LightBox mode for each of four separate product lines, with all of the products lines shown on one page.  Similar to how this company did it on their page: https://sonicenclosures.com/products/.

I've come to W3Schools and, to ensure that my first try would be successful, simply copied and pasted their LightBox code from the How To sections into my site.  Everything worked fine for the first product line section.  I even increased the number of images from four in the sample to six without any issues.  Then I added another product line section a few DIVs down the page, and tried to recreate the Lightbox code using the original sample, and this is where everything fell apart.  Now, when I click on any picture in my first product line row, the LightBox modal opens, and I can cycle through the images in that product line using the forward/reverse buttons, but when I reach the last image in that product line, it automatically jumps and cycles through the next six pictures of the following product line, which is not what I want it to do.  If I try to click on any of the images in the second product line row, it opens the LightBox modal starting with the images from the first product line images, and then scrolls trough to the second line of images.  I want each Lightbox to only show it's correlating product line images.

I'm sure that there must be some way to do this, as the referenced company's web site seems to work the way I'm looking for.  Must be in my unique "IDs" or placement of my code snippets?? I have my CSS called from a separate CSS page, and I've got my JavaScript code at the end of the HTML for the LightBox sections. 

 Can anyone please show me the correct coding to allow me to have multiple separate LightBoxes on one page for individual product line imagery?

Hoping someone's out there with the correct info and kind enough to take pity on a poor wretched sole under a demanding deadline, like me!

Here's the code that I used - straight out of W3 Schools:

CSS:

body {
  font-family: Verdana, sans-serif;
  margin: 0;
}

* {
  box-sizing: border-box;
}

.row > .column {
  padding: 0 8px;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}

.column {
  float: left;
  width: 25%;
}

/* The Modal (background) */
.modal {
  display: none;
  position: fixed;
  z-index: 1;
  padding-top: 100px;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: black;
}

/* Modal Content */
.modal-content {
  position: relative;
  background-color: #fefefe;
  margin: auto;
  padding: 0;
  width: 90%;
  max-width: 1200px;
}

/* The Close Button */
.close {
  color: white;
  position: absolute;
  top: 10px;
  right: 25px;
  font-size: 35px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: #999;
  text-decoration: none;
  cursor: pointer;
}

.mySlides {
  display: none;
}

.cursor {
  cursor: pointer;
}

/* Next & previous buttons */
.prev,
.next {
  cursor: pointer;
  position: absolute;
  top: 50%;
  width: auto;
  padding: 16px;
  margin-top: -50px;
  color: white;
  font-weight: bold;
  font-size: 20px;
  transition: 0.6s ease;
  border-radius: 0 3px 3px 0;
  user-select: none;
  -webkit-user-select: none;
}

/* Position the "next button" to the right */
.next {
  right: 0;
  border-radius: 3px 0 0 3px;
}

/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover {
  background-color: rgba(0, 0, 0, 0.8);
}

/* Number text (1/3 etc) */
.numbertext {
  color: #f2f2f2;
  font-size: 12px;
  padding: 8px 12px;
  position: absolute;
  top: 0;
}

img {
  margin-bottom: -4px;
}

.caption-container {
  text-align: center;
  background-color: black;
  padding: 2px 16px;
  color: white;
}

.demo {
  opacity: 0.6;
}

.active,
.demo:hover {
  opacity: 1;
}

img.hover-shadow {
  transition: 0.3s;
}

.hover-shadow:hover {
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}

HTMIL:

<h2 style="text-align:center">Lightbox</h2>

<div class="row">
  <div class="column">
    <img src="img_nature.jpg" style="width:100%" onclick="openModal();currentSlide(1)" class="hover-shadow cursor">
  </div>
  <div class="column">
    <img src="img_snow.jpg" style="width:100%" onclick="openModal();currentSlide(2)" class="hover-shadow cursor">
  </div>
  <div class="column">
    <img src="img_mountains.jpg" style="width:100%" onclick="openModal();currentSlide(3)" class="hover-shadow cursor">
  </div>
  <div class="column">
    <img src="img_lights.jpg" style="width:100%" onclick="openModal();currentSlide(4)" class="hover-shadow cursor">
  </div>
</div>

<div id="myModal" class="modal">
  <span class="close cursor" onclick="closeModal()">&times;</span>
  <div class="modal-content">

    <div class="mySlides">
      <div class="numbertext">1 / 4</div>
      <img src="img_nature_wide.jpg" style="width:100%">
    </div>

    <div class="mySlides">
      <div class="numbertext">2 / 4</div>
      <img src="img_snow_wide.jpg" style="width:100%">
    </div>

    <div class="mySlides">
      <div class="numbertext">3 / 4</div>
      <img src="img_mountains_wide.jpg" style="width:100%">
    </div>
    
    <div class="mySlides">
      <div class="numbertext">4 / 4</div>
      <img src="img_lights_wide.jpg" style="width:100%">
    </div>
    
    <a class="prev" onclick="plusSlides(-1)">&#10094;</a>
    <a class="next" onclick="plusSlides(1)">&#10095;</a>

    <div class="caption-container">
      <p id="caption"></p>
    </div>


    <div class="column">
      <img class="demo cursor" src="img_nature_wide.jpg" style="width:100%" onclick="currentSlide(1)" alt="Nature and sunrise">
    </div>
    <div class="column">
      <img class="demo cursor" src="img_snow_wide.jpg" style="width:100%" onclick="currentSlide(2)" alt="Snow">
    </div>
    <div class="column">
      <img class="demo cursor" src="img_mountains_wide.jpg" style="width:100%" onclick="currentSlide(3)" alt="Mountains and fjords">
    </div>
    <div class="column">
      <img class="demo cursor" src="img_lights_wide.jpg" style="width:100%" onclick="currentSlide(4)" alt="Northern Lights">
    </div>
  </div>
</div>
 

JavaScript:

<script>
function openModal() {
  document.getElementById("myModal").style.display = "block";
}

function closeModal() {
  document.getElementById("myModal").style.display = "none";
}

var slideIndex = 1;
showSlides(slideIndex);

function plusSlides(n) {
  showSlides(slideIndex += n);
}

function currentSlide(n) {
  showSlides(slideIndex = n);
}

function showSlides(n) {
  var i;
  var slides = document.getElementsByClassName("mySlides");
  var dots = document.getElementsByClassName("demo");
  var captionText = document.getElementById("caption");
  if (n > slides.length) {slideIndex = 1}
  if (n < 1) {slideIndex = slides.length}
  for (i = 0; i < slides.length; i++) {
      slides[i].style.display = "none";
  }
  for (i = 0; i < dots.length; i++) {
      dots[i].className = dots[i].className.replace(" active", "");
  }
  slides[slideIndex-1].style.display = "block";
  dots[slideIndex-1].className += " active";
  captionText.innerHTML = dots[slideIndex-1].alt;
}
</script>

 

 

Link to comment
Share on other sites

  • 2 weeks later...

Little disappointed here.  I've been counting on W3Schools material and experts for some time now.  I appreciate this service and the ability for it to help me learn this craft at my own pace.  I learn best by examples, and W3 has proven to work very well for me in this format to date.

However, now that I've run into a real head scratcher for me, I've turned to the expert users who kindly feed this service with their vast and valuable knowledge to help me through a critical problem.  But I have had no responses during the nine days since I posted my original help request on this topic.  This must be an easy topic to answer for the many coding gods out there on W3, as I've seen what I'm asking for in use on other web sites.  I'm just not quick enough in JS on my own to get it with only a tutorial explanation, but I would appreciate an actual coding answer to which I could immediately use, and then decipher the logic later as I continue to learn JS at the pace I can afford.

I have listed the exact code directly from W3 Schools' How To pages, and I would love to have an answer that would use that exact same code back to me with the appropriate modified coding to allow two, or more, different lightbox modals to work on the same page.  Sort of a plug 'n play code to get my web page finished on time.

Can anyone out there help me, pleeeaaassee???

Link to comment
Share on other sites

This forum is completely community run, the W3Schools staff do not actively participate here. The members of the forum are random people who just signed up and kindly decided to answer questions.

I am just a moderator, I'm not actually part of the W3Schools staff. I used to answer questions more frequently but these days I don't have as much time, so beyond keeping the forums in check I usually only answer shorter questions.

I can provide a short answer but it will require some knowledge on your part, otherwise you'll just be blindly copying code which I don't have time to explain in detail.

First of all, we can generalize the modal. Instead of an id attribute, use a class attribute. You already have class="modal", so we can work with that.

Second, we should get rid of all of the onclick attributes. Events are best handled exclusively by Javascript instead of embedded in the HTML.

Finally, remove all id attributes from the system since we want to generalize this.

With those steps out of the way, we will use HTML DOM properties and methods to access elements and assign event listeners to them. For the following code, I am assuming that <div class="row"> always directly precedes a <div class="modal"> in your code. If the structure is different then you will need different code to access the elements.

// Declare iterators.
var i, j;

// Go through each row and assign events
var rows = document.getElementsByClassName(".row");
var images;
for(i = 0; i < rows.length; i++) {
  // Prepare each image in the row
  images = rows[i].getElementsByTagName("img");
  for(j = 0; j < images.length; j++) {
    // Use the image's position as its slide number and save it in an attribute
    images[j].setAttribute("data-number", j);
    
    // Assign an event listener to the image
    images[j].addEventListener("click", openModal);
  }
}

// Gather all modal boxes and assign events to the buttons inside
var modals = document.querySelector(".modal");
var modal, close, prev, next;
for(i = 0; i < modals.length; i++) {
  modal = modals[i];

  // Close button
  close = modal.querySelector(".close");
  close.addEventListener("click", closeModal);
  
  // Next button
  next = modal.querySelector(".next");
  next.addEventListener("click", nextSlide);
  
  // Prev button
  prev = modal.querySelector(".prev");
  prev.addEventListener("click", prevSlide);
  
}

// Declare all the functions
function openModal(e) {
  var image = e.currentTarget;

  // This assumes the HTML structure is exactly as you posted
  var modal = image.parentNode.parentNode.nextElementSibling;
  
  // Set the display to block
  modal.style.display = "block";

  // Choose a slide
  if(image.hasAttribute("data-number")) {
    var slideNum = image.getAttribute("data-number");
    showSlide(modal, slideNum);
  }
}

function closeModal(e) {
  var modal = e.currentTarget.parentNode;
  modal.style.display = "none";
}

function nextSlide(e) {
  // This assumes the HTML structure is exactly as you posted
  var modal = e.currentTarget.parentNode.parentNode;
  var num = modal.getAttribute("data-slide");
  if(!num) num = 0;
  num++;
  showSlide(modal, num);
}

function prevSlide(e) {
  // This assumes the HTML structure is exactly as you posted
  var modal = e.currentTarget.parentNode.parentNode;
  var num = modal.getAttribute("data-slide");
  if(!num) num = 0;
  num--;
  showSlide(modal, num);
}

function showSlide(modal, num) {
  var slides = modal.getElementsByClassName("mySlides");
  var dots = modal.getElementsByClassName("demo");
  var captionText = modal.querySelector(".caption p");
  if (num >= slides.length) { num = 0 }
  if (num < 0) {num = slides.length - 1}
  for (i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
  }
  for (i = 0; i < dots.length; i++) {
      dots[i].className = dots[i].className.replace(" active", "");
  }
  slides[num].style.display = "block";
  dots[num].className += " active";
  captionText.innerHTML = dots[num].alt;

  // Store the current slide in an attribute
  modal.setAttribute("data-slide", num);
}

 

I haven't tested this code, so there might be some typing mistakes. You can use the browsers error console (usually available by pressing F12) to look for errors and try to fix them.

Link to comment
Share on other sites

@Ingolme  Thank you for your response.  I apologize if I inadvertently offended any forum contributors or moderators.  It was not my intent.  You are all valuable contributors to these forums, and I appreciate your volunteers services.  Maybe too much pressure in a too short of a time frame for me at the moment.  

Thank you for your code and explanations/directions.  I will attempt to implement them as best as I can with my limited JS knowledge, but I do appreciate your assistance.

I will let you know how it works once I get some results.

Again, much appreciated.  Have a good one!!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...