javascriptonclickinnerhtmlcaption

Image alt captions showing as 'undefined' on modal image


I have mutiple art galleries on my website containing lots of images, I use an onclick event to pull up a full res, uncropped version of the image and it works perfectly fine. However, I want a unique caption to pop up with each image, using the image's alt as the caption; I've got the caption popping up onclick, but it shows as 'undefined'.

I've tried everything I can think of and looked through countless questions, answers and comments and I just can't seem to figure it out at all.

Here is the code:

function showFullRes(imageSrc) {
  const overlay = document.getElementById("full-res-overlay");
  const fullResImage = document.getElementById("full-res-image");
  const captionText = document.getElementById("caption");

  fullResImage.src = imageSrc;
  overlay.style.display = "block";
  captionText.innerHTML = this.alt;
}

function closeFullRes() {
  const overlay = document.getElementById("full-res-overlay");
  overlay.style.display = "none";
}
.full-res-overlay {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.9);
  z-index: 10;
  text-align: center;
}

.full-res-image {
  max-width: 80%;
  max-height: 80%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.caption {
  font-family: 'MATRIX';
  font-size: 2vw;
  margin: auto;
  display: block;
  width: 80%;
  max-width: 700px;
  text-align: center;
  padding: 10px 0;
  height: 150px;
}

.artwork {
  cursor: pointer;
  width: 18vw;
  height: 25vw;
  max-width: 100%;
  position: relative;
}

.artwork:hover {
  opacity: 0.8;
  transform: scale(95%);
  transition: opacity 0.3s ease;
  transition: transform 0.3s ease;
}

.artwork img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.artwork-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 20px;
}

.gallery-container {
  width: 89%;
  max-width: 89%;
  padding: 20px;
  background-color: transparent;
  border-radius: 10px;
  text-align: center;
}
<div class="gallery-container expanded" style="width: 89%;">
  <div class="artwork-container">

    <div class="artwork" style="width: 35vw; height: 44vw;" onclick="showFullRes('https://sinniister.neocities.org/ARTWORK/VASCHA/REDVOH2.JPG')" alt="Original sketch">
      <img
              src="https://sinniister.neocities.org/ARTWORK/VASCHA/REDVOH2TN.jpeg" alt="Original Sketch"
             />
    </div>

    <div class="artwork" style="width: 35vw; height: 44vw;" onclick="showFullRes('https://sinniister.neocities.org/ARTWORK/VASCHA/VOH21.JPG')" alt="Final version">
      <img
              src="https://sinniister.neocities.org/ARTWORK/VASCHA/VOH21S.JPG" alt="Final Version"
             />
    </div>
  </div>
</div>

<div class="full-res-overlay" id="full-res-overlay" onclick="closeFullRes()">
  <img
        src=""
        alt="Full Resolution Artwork"
        class="full-res-image"
        id="full-res-image"
      />
  <div id="caption" style="color: white;"></div>
</div>


Solution

  • A couple of problems:

    1. this in your code just points to the global window object, so when you write this.alt, there's no such property on the global object. If you use proper event binding (e.g. with addEventListener) rather than inline event handlers then this would represent the element the event was bound to. More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

    2. Even if you fix point 1, alt isn't a property of a div (which in JS is represented as an instance of HTMLElement), so accessing that doesn't return anything. (Only a HTMLImageElement has an alt property).

    You could use this.getAttribute("alt") to fix point 2, but in the working example below, I've taken both the "alt" text on the div, and the URL previously being passed as imageSrc and make them both into data attributes of the div, so they can be accessed consistently through a recognised approach.

    Demo:

    var imageDivs = document.querySelectorAll(".artwork");
    
    imageDivs.forEach(function(div) 
    { 
      div.addEventListener("click", function(e) 
      { 
        const overlay = document.getElementById("full-res-overlay");
        const fullResImage = document.getElementById("full-res-image");
        const captionText = document.getElementById("caption");
        fullResImage.src = this.dataset.url;
        overlay.style.display = "block";
        captionText.innerHTML = this.dataset.text;
      });
    });
    
    document.querySelector("#full-res-overlay").addEventListener("click", function(e) {
      this.style.display = "none";
    });
    .full-res-overlay {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.9);
      z-index: 10;
      text-align: center;
    }
    
    .full-res-image {
      max-width: 80%;
      max-height: 80%;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
    .caption {
      font-family: 'MATRIX';
      font-size: 2vw;
      margin: auto;
      display: block;
      width: 80%;
      max-width: 700px;
      text-align: center;
      padding: 10px 0;
      height: 150px;
    }
    
    .artwork {
      cursor: pointer;
      width: 18vw;
      height: 25vw;
      max-width: 100%;
      position: relative;
    }
    
    .artwork:hover {
      opacity: 0.8;
      transform: scale(95%);
      transition: opacity 0.3s ease;
      transition: transform 0.3s ease;
    }
    
    .artwork img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    
    .artwork-container {
      display: flex;
      flex-wrap: wrap;
      justify-content: center;
      gap: 20px;
    }
    
    .gallery-container {
      width: 89%;
      max-width: 89%;
      padding: 20px;
      background-color: transparent;
      border-radius: 10px;
      text-align: center;
    }
    <div class="gallery-container expanded" style="width: 89%;">
      <div class="artwork-container">
    
        <div class="artwork" style="width: 35vw; height: 44vw;" data-url="https://sinniister.neocities.org/ARTWORK/VASCHA/REDVOH2.JPG" data-text="Original sketch">
          <img src="https://sinniister.neocities.org/ARTWORK/VASCHA/REDVOH2TN.jpeg" alt="Original Sketch" />
        </div>
    
        <div class="artwork" style="width: 35vw; height: 44vw;" data-url="https://sinniister.neocities.org/ARTWORK/VASCHA/VOH21.JPG" data-text="Final version">
          <img src="https://sinniister.neocities.org/ARTWORK/VASCHA/VOH21S.JPG" alt="Final Version"/>
        </div>
      </div>
    </div>
    
    <div class="full-res-overlay" id="full-res-overlay">
      <img
            src=""
            alt="Full Resolution Artwork"
            class="full-res-image"
            id="full-res-image"
          />
      <div id="caption" style="color: white;"></div>
    </div>