Building an Image Gallery with Pure JavaScript
Tags: todayilearned, beginners, javascript, frontend
Published: 2023-03-16 20:27:39

Hello there! 👋 

I'm Lucas, a Brazilian engineer, and this is _Yet Another DEV Content_ nobody asked for (but I made it anyway 😂). My goal with this blog is to talk about things related to the software development world and document personal projects I've worked on, while also honing recently acquired knowledge by sharing it. If you like it, follow me for more posts like this one!

Today we'll tackle a small JavaScript project called **[Image Gallery](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery#project_brief)** featured in one of MDN's JavaScript tutorials. 

Please note that this is my solution to this challenge and probably not the best one you will find out there. Also note that the code is shown in this article in a manner that not always represent the final files. If you want to check the final code, a link to the Github repository as well as a link to the deployed app are provided in the Reference section at the end of the article.

The GIF below shows how the project should look like when we're finished. Let's build it!

![final project gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5h5s9ppmanksij0dsd3b.gif)


---

## 👣 Step-by-step Breakdown

The [MDN tutorial](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery#project_brief) provides initial boilerplate code for this project and all five images that we're going to use.

We won't get into details on how the HTML was structured nor how it was styled since the goal here is to focus on the JavaScript part.

If you open the boilerplate _index.html_ file, this is how it initially looks like:

![project initial state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06xm3t8tuus30tz2xj4a.png)

You can immediately notice that the thumbnail images are missing and the button has no functionality for now. So here's what we're going to do step-by-step:

1. Declare array of image filenames and append them to the DOM (inside the thumb bar);
2. Add a click event handler to each thumbnail image;
3. Add a click event handler to the Darken/Lighten button.

---

## 1️⃣ Adding the thumbnail images to the DOM

We can do it by first declaring a constant array to hold the image filenames for us. This is a viable alternative because we know the number of images is low and static (five).

Then it is time to declare an object with an alt description for each image. This step is extra important to improve the accessibility of our app and is often overlooked. I chose to use the filenames as keys, so its easier to retrieve the value we want in the next steps.

We'll also need to store a reference to the thumb bar div HTML element, so we can append the images to it next. Fortunately this has been provided in the boilerplate code already as the _thumbBar_ constant.

```javascript
/** 
  File: "~/main.js"
  Showing: Only code related to step 1
*/

const thumbBar = document.querySelector('.thumb-bar');

/* Declaring the array of image filenames */
const imageFilenames = [
  'pic1.jpg',
  'pic2.jpg',
  'pic3.jpg',
  'pic4.jpg',
  'pic5.jpg',
];

/* Declaring the alternative text for each image file */
const altTexts = {
  'pic1.jpg': 'A closeup of an human eye',
  'pic2.jpg': 'An abstract pattern painting',
  'pic3.jpg': 'A lot of violet and white flowers',
  'pic4.jpg': 'An Egyptian painting in a wall',
  'pic5.jpg': 'A yellow butterfly in a leaf',
};
```

Next, we'll loop through the array with the forEach method so we can append the images. The image elements will be created inside each iteration of the loop, the needed HTML attributes will be added and finally the element will be appended as a child of the thumb bar container div.

```javascript
/** 
  File: "~/main.js"
  Showing: Only code related to step 1
*/

/* Looping through images */
imageFilenames.forEach((imageName) => {
  const newImage = document.createElement('img');
  newImage.setAttribute('src', `images/${imageName}`);
  newImage.setAttribute('alt', altTexts[imageName]);
  thumbBar.appendChild(newImage);
});
```

With this we've finished the first step. Again, we won't dive into how it was styled. This is how it should like now:

![A GIF showing the project after step one is finished](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ax84ax7wr83yyxhs8w7t.png)

---

## 2️⃣ Add a click event handler to each thumbnail image

What we want to achieve next is to change the displayed image (the bigger one) whenever the user clicks any of the thumbnail images that we added. In order to achieve that, we will need reference to the displayed image element just like we did for the thumb bar container, but it was also already declared in the boilerplate code.

Let's create a function to handle the click event on the images. Any function passed as a callback to the _addEventListener()_ method will automatically pass the event as an argument. The Event object has a _target_ property that holds a reference to the HTML element that triggered the event. We will use the target element so we can know the new src and alt attributes of the clicked image, and change the attributes of the displayed image to equals the target image.

```javascript
/** 
  File: "~/main.js"
  Showing: Only code related to step 2
*/

function handleImageClick({ target }) {
  displayedImage.setAttribute('src', target.getAttribute('src'));
  displayedImage.setAttribute('alt', target.getAttribute('alt'));
}

const displayedImage = document.querySelector('.displayed-img');

/* Looping through images */
imageFilenames.forEach((imageName) => {
  const newImage = document.createElement('img');
  newImage.setAttribute('src', `images/${imageName}`);
  newImage.setAttribute('alt', altTexts[imageName]);
  thumbBar.appendChild(newImage);
  img.addEventListener('click', handleImageClick);
});
```

With this we have successfully achieved step 2 and are only missing the last part!

![A GIF showing the project after step2 is completed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ljxdq8tidk43w9fcelo.gif)

---

## 3️⃣ Add a click event handler to the Darken/Lighten button

To achieve what we want in the third and last step let's create a function to handle the click event on the button. This function should read the class name value of the button and take one of two actions depending on the result.

If the class is "dark", it means the user clicked the Darken button. When this happens the text content of the button should change to "Lighten", the overlay div background opacity should change to "0.5" and finally the class name should change to "light" so the action changes when the next click happens.

Else it means the class is "light". In this case the button text content should change to "Lighten", the overlay div opacity should change to "0" so it becomes invisible again and finally the class name should change to "dark" so the action changes when the next click happens.

```javascript
/** 
  File: "~/main.js"
  Showing: Only code related to step 3
*/

/* Wiring up the Darken/Lighten button */
function handleButtonClick() {
  let currentClass = btn.getAttribute('class');
  if (currentClass === 'dark') {
    btn.textContent = 'Lighten';
    overlay.style.backgroundColor = 'rgba(0,0,0,0.5)';
    btn.setAttribute('class', 'light');
  } else {
    btn.textContent = 'Darken';
    overlay.style.backgroundColor = 'rgba(0,0,0,0)';
    btn.setAttribute('class', 'dark');
  }
}

btn.addEventListener('click', handleButtonClick);
```

We're done! This is how the button functionality should look like now:

![A gif of the project ready](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/464ny8kfjetjf4bub9hk.gif)

---

If you've read this far, I hope the content has added something for you. If it didn't, remember: _This is just another ordinary DEV content_ 😬.

🍀 See ya!

### 🔍 References
[Image gallery - Learn web development | MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery#project_brief)
[Image gallery finished example](https://mdn.github.io/learning-area/javascript/building-blocks/gallery/)
[Github repository with the final code](https://github.com/lucashdoa/lucashdoa.github.io/tree/main/mdn-image-gallery)
[Final app deployed on Github Actions](https://lucashdoa.github.io/mdn-image-gallery)

### 😁 Let's chat!
[Github](https://github.com/lucashdoa)
[Linkedin](https://www.linkedin.com/in/lucashdoa/)

{% user lucashdoa %}