My initial plan was to rebuild my portfolio website using code in seven weeks, thus freeing me from the constraints of cargo. However, I ultimately found that seven weeks was still too short, especially considering I was taking multiple courses simultaneously. My current project website uses the simplest text and image layouts from before. I think I can use the remaining two weeks to tackle some of the more difficult parts of my original portfolio website. I can fill in the rest of the project later when I have more time.

There are two remaining challenging parts: the waterfall layout on my gallery page and the visual effects on my home page.

968751ea40a3517287924f04f3f4d0e7.mp4

However, the book Internating is Hard doesn't cover this topic, and I think finding references from MDN is a bit slow. Since my midterm deadline for another course is next week, I want to save as much time as possible. Ultimately, I decided to use AI. However, I'll have AI interpret the code given to me and learn from it.

<!DOCTYPE html>
<html lang="EN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gallery</title>
    <link rel="stylesheet" href="navbar.css">
    <link rel="stylesheet" href="gallery.css">
</head>

<body>
    <div id="navbar-root"></div>
    <div class="page">
        <div class="page-layout">
            <div class="page-content">
                <main>
                    <h1>Gallery</h1>
                    <div class="gallery" id="gallery"></div>
                </main>
            </div>
        </div>
    </div>

    <div class="lightbox" id="lightbox">
        <div class="lightbox-overlay" id="lightboxOverlay"></div>
        <div class="lightbox-content">
            <img id="lightboxImage" src="" alt="">
            <button class="lightbox-close" id="lightboxClose">&times;</button>
        </div>
    </div>

    <script src="navbar.js"></script>
    <script src="galleryData.js"></script>
    <script src="gallery.js"></script>
</body>

</html>

According to Copilot’s explanation, this HTML file is essentially an empty shell. It does not contain any actual content by itself. Instead, the content appears only after the later JavaScript code reads my local image files and injects them into the page. In the last few lines of the HTML file, two JS files are loaded: one stores metadata for all images, and the other fetches the images and inserts them into the HTML.

<div class="gallery" id="gallery"></div> 
<div class="lightbox" id="lightbox">     
    <div class="lightbox-overlay"></div> 
    <img id="lightboxImage" src="">      
</div>
<script src="galleryData.js"></script>  <!-- 1st: define image data -->
<script src="gallery.js"></script>      <!-- 2nd: use the data and initialize -->

const GALLERY_IMAGES = [
    { id: 0, url: 'gallery_img/photo1.jpg', title: 'Artwork 1' },
    { id: 1, url: 'gallery_img/photo2.jpg', title: 'Artwork 2' },
    // ...
];

In gallery.js, a lot of createElement calls are used to write the images into the HTML.

function initGallery() {
    const gallery = document.getElementById('gallery');
    const images = GALLERY_IMAGES; // Get data from galleryData.js

    images.forEach((item) => {
        // Create a div for each image
        const itemEl = document.createElement('div');
        itemEl.className = 'gallery-item';

        // Create the img tag
        const img = document.createElement('img');
        img.src = item.url;  // 使用 gallery_img/photo1.jpg

        // Append to the gallery container
        gallery.appendChild(itemEl);
        itemEl.appendChild(img);

        // Bind click event
        itemEl.addEventListener('click', () => {
            openLightbox(item.url, item.id);
        });
    });
}

When the page runs, the HTML should look like this:

<div class="gallery">
    <div class="gallery-item">
        <img src="gallery_img/photo1.jpg">
    </div>
    <div class="gallery-item">
        <img src="gallery_img/photo2.jpg">
    </div>
    <!-- ... more images ... -->
</div>

Interaction logic: show the lightbox when the user clicks an image.

// Triggered when the user clicks an image
openLightbox(imageUrl, itemId) {
    // Show the lightbox
    lightbox.classList.add('active');
    // Set the image to display
    lightboxImage.src = imageUrl;
    // Trigger a smooth transition animation
    document.startViewTransition(() => { ... });
}

Close the lightbox (hide it directly).

closeLightbox() {
    // Hide the lightbox
    lightbox.classList.remove('active');
}

// Supports three ways to close:
// 1. Click the close button
// 2. Click the background overlay
// 3. Press the ESC key

The file that defines the masonry-style layout. It uses the CSS column-count property, and the browser automatically arranges elements into multiple columns.