Project final - Gallery
Finalize the gallery app and run fetch, grid and large-view flow.
Project wrap-up: the main flow
Three pieces are ready: fetchImages pulls data, renderGrid builds the grid, and the modal opens the large view. Now we'll combine them in a main function.
main is async because it can await fetchImages. The flow:
- fetch the image list
- draw the grid
- the modal listeners are ready (previous lesson)
Finally we start the app with a main() call.
Starting the app
After writing the main function, we call it with main() at the end of the file. Since the browser reads code top to bottom, main() runs after all definitions are ready.
Inside it we draw the grid with renderGrid(images). In this example we used a ready images array; in a real app you could first fetch the data with await fetchImages(url) and then pass it to renderGrid.
This is the final step that completes the project.
Exercise Write the main function and call it
Continue on top of the previous lesson's solution. Write async function main(). Inside it, call renderGrid(images). Then, outside the function, add a main() call.
Show example solution
Start with async function main(), call renderGrid(images); inside it. Then write main(); outside the function to start the app.
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");
});
async function main() {
renderGrid(images);
}
main();
Test yourself
-
Why should main be async?
async function main() { const data = await fetchImages(url); // ... }- Because it runs faster
- Because it uses await fetchImages
- Because it needs a modal
- Because it errors otherwise
Show answer
Because it uses await fetchImages — Correct! To use await, the function must be async.
-
Complete the renderGrid call
async function main() { ____; } main();Show answer
async function main() { renderGrid(images); } main(); -
Match lesson to feature
- Lesson 1
- Skeleton and heading
- Lesson 2
- Fetching from API
- Lesson 3
- Building the grid
- Lesson 4
- Large view
- Lesson 5
- Starting with main