Home > Software engineering >  My Modal Gallery can only open last picture of a list
My Modal Gallery can only open last picture of a list

Time:12-08

I try to do a modal gallery for a website. Actually it work almost. It open my picture but only the last one of the gallery. I know that I need to select the picture clicked in my JS but I don't really know how to do that.

I have that (partial) :

HTML

<section>
    <ul class="gallery">
      <li>
        <img src="images/arcticfox/Arctic_1.jpg" alt="Arctic Fox" />
      </li>
    </ul>
    <!-- The Modal -->
    <div id="myModal" class="modal">

    <!-- The Close Button -->
    <span class="close">&times;</span>

    <!-- Modal Content (The Image) -->
    <img class="modal-content" id="img01">

    <!-- Modal Caption (Image Text) -->
    <div id="caption"></div>
</section>

CSS

.gallery {
    margin: 0;
    padding: 0;
    grid-gap: 10px;
    list-style: none;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}

/* The Modal (background) */
.modal {
    display: none; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 1; /* Sit on top */
    padding-top: 100px; /* Location of the box */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 100%; /* Full height */
    overflow: auto; /* Enable scroll if needed */
    background-color: rgb(0, 0, 0); /* Fallback color */
    background-color: rgba(0, 0, 0, 0.9); /* Black w/ opacity */
}

/* Modal Content (Image) */
.modal-content {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
}

/* Caption of Modal Image (Image Text) - Same Width as the Image */
#caption {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
    text-align: center;
    color: #ccc;
    padding: 10px 0;
    height: 150px;
}

/* Add Animation - Zoom in the Modal */
.modal-content,
#caption {
    animation-name: zoom;
    animation-duration: 0.6s;
}

@keyframes zoom {
    from {
        transform: scale(0);
    }
    to {
        transform: scale(1);
    }
}

/* The Close Button */
.close {
    position: absolute;
    top: 15px;
    right: 35px;
    color: #f1f1f1;
    font-size: 40px;
    font-weight: bold;
    transition: 0.3s;
}

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

JS

const modal = document.getElementById("myModal");
const img = document.querySelectorAll(".gallery li img");
const modalImg = document.getElementById("img01");
const captionText = document.getElementById("caption");
const span = document.getElementsByClassName("close")[0];
const gallery = document.querySelector(".gallery")

gallery.addEventListener("click", () => {
    img.forEach(imgs => {
        console.log(imgs)
        modal.style.display = "block";
        modalImg.src = imgs.src;
        captionText.innerHTML = imgs.alt;
    })
})

span.onclick = function() {
    modal.style.display = "none";
}

modal.onclick = function() {
    modal.style.display = "none";
}

I know that the problem is in my JS but I don't know how to select the right picture.

Can you help me ? Thank's in advance.

CodePudding user response:

It does look like you are very close, it's hard to tell if this will work without your HTML, but try this instead of gallery.addEventListener

document.querySelectorAll('.gallery li img').forEach(item => {
  item.addEventListener('click', event => {
    modal.style.display = "block";
    modalImg.src = item.src;
    captionText.innerHTML = item.alt;
  })
})

Right now you're telling JS:

  • When I click anywhere on the gallery I want you to loop through each img tag in the gallery
  • Then update the modals img attributes with this current img.

When the loop finishes, it will always leave the modal with the attributes of the last image in the gallery.

This new function is telling JS:

  • I want you to get all the images in the gallery and loop through them
  • Then I want you to add an event listener to each item individually
  • When I click on an item, I want you to open the modal, and update the modal image with the attributes of this item.

You may need to tweak this a bit, but the issue you're facing is that you're not telling JS which attributes are the ones you want.

Another way of doing this is to add a custom data attribute to the images in the gallery with the data that you need. Then write a function that takes those attributes and updates the modal. The reason for doing this is that you can then load thumbnail sizes on the gallery, and have the link to the full resolution image on modal. It would look something like this.

<li class="gallery-item" modal-src="https://fullImageURL.com" modal-caption="Caption Text Here">
    <img src="https://thumbnailURL.com"/>
</li>

document.querySelectorAll('.gallery-item').forEach(item => {
  item.addEventListener('click', event => {
   updateModal(item);
  })
})

function updateModal(item) {
  const src = .getAttribute('modal-src');
  const caption = .getAttribute('modal-caption');

  modal.style.display = "block";
  modalImg.src = src;
  captionText.innerHTML = caption;
}

CodePudding user response:

Yes It work Jonathan Knoll, thank you very much. Tue first one is suffisent for my project and I have upgrade the JS into : Because there is already a const for querySelector

const img = document.querySelectorAll(".gallery li img");

img.forEach(item => {
    item.addEventListener('click', event => {
        modal.style.display = "block";
        modalImg.src = item.src;
        captionText.innerHTML = item.alt;
    })
})

The HTML and CSS are now in the post. (partial)

Thank you again, it's a big help.

  • Related