CodeBlanks Logo Icon CodeBlanks

Large image view

JavaScript course · Intermediate · Lesson 98/134

Show the large image when a card is clicked using click event and event delegation.

Clicks with event delegation

Instead of adding a listener to each image, we add a single click listener to the gallery container. This pattern is called event delegation.

The clicked element is given by event.target. If event.target.tagName === 'IMG', an image was clicked; we open the large view with that image's source.

This way, even if images are added to the grid later, the listener doesn't need to be set up again.

The large view with classList

For the large view we'll use a modal div. It starts hidden with the hidden class, so it's not visible on screen. When a card is clicked we do two things:

  • set the large image source with modalImg.src = event.target.src
  • open the view with modal.classList.remove('hidden')

To close it, we add a click listener to the modal itself; when clicked, modal.classList.add('hidden') hides it again.

Exercise Add the large view listeners

Continue on top of the previous lesson's solution. A modal div and a modalImg have been added to the skeleton; you'll write the click listeners. Add gallery.addEventListener('click', function(event) {...}); inside it, if event.target.tagName === 'IMG', set modalImg.src = event.target.src and call modal.classList.remove('hidden'). For closing, add modal.addEventListener('click', function() {...}) and inside it call modal.classList.add('hidden').

Show example solution
Start with gallery.addEventListener('click', function(event) {...}); inside, if (event.target.tagName === 'IMG') set modalImg.src = event.target.src and call modal.classList.remove('hidden'). Close with modal.addEventListener('click', function() { modal.classList.add('hidden'); }).

Example solution:
// Gallery application
const app = document.getElementById("app");
const title = document.createElement("h1");
title.textContent = "Gallery";
app.appendChild(title);

const gallery = document.createElement("div");
gallery.className = "gallery";
app.appendChild(gallery);

const images = [
  { url: "https://picsum.photos/id/1/200/200", title: "Mountain view", author: "Alex" },
  { url: "https://picsum.photos/id/2/200/200", title: "City streets", author: "Mark" },
  { url: "https://picsum.photos/id/3/200/200", title: "Lakeside", author: "Zoe" }
];

async function fetchImages(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error("HTTP " + response.status);
    }
    return await response.text();
  } catch (error) {
    console.log(error.message);
  }
}

function renderGrid(images) {
  images.forEach(function(image) {
    const card = document.createElement("figure");
    const img = document.createElement("img");
    const caption = document.createElement("figcaption");
    img.src = image.url;
    img.alt = image.title;
    caption.textContent = image.author;
    card.appendChild(img);
    card.appendChild(caption);
    gallery.appendChild(card);
  });
}

// Large view modal
const modal = document.createElement("div");
modal.classList.add("hidden");
const modalImg = document.createElement("img");
app.appendChild(modal);
modal.appendChild(modalImg);

gallery.addEventListener("click", function(event) {
  if (event.target.tagName === "IMG") {
    modalImg.src = event.target.src;
    modal.classList.remove("hidden");
  }
});

modal.addEventListener("click", function() {
  modal.classList.add("hidden");
});

Test yourself

  1. Why is event delegation useful?

    gallery.addEventListener('click', function(event) {
      // ...
    });
    • It runs more slowly
    • It only works on form elements
    • It needs a separate listener per item
    • One listener watches all children
    Show answer

    One listener watches all children — Correct! A single listener on the parent watches all children.

  2. Get the clicked element

    const target = ____;
    Show answer
    const target = event.target;
  3. Match the event concepts

    event.target
    Clicked element
    tagName
    Element type
    classList.remove
    Removing a class
    classList.add
    Adding a class
    addEventListener
    Listening for events

All lessons in Intermediate