HN
Hào Nguyễn

Gallery: Masonry & Carousel

Improve my code : <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF 8"> <meta name="viewport" content="width=device width, initial scale=1.0"> <title>Gallery: Masonry & Carousel</title> <! Bootstrap CDN > <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"> <! Lightbox2 CSS CDN > <link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.3/css/lightbox.min.css" rel="stylesheet"> <! Font Awesome CDN for icons > <link href="https://cdnjs.cloudflare.com/ajax/libs/font awesome/5.15.4/css/all.min.css" rel="stylesheet"> <style> body { font family: Arial, sans serif; background color: #121212; color: #e0e0e0; margin: 0; padding: 20px; } .gallery { column count: 3; column gap: 15px; padding: 0; margin: 0; display: none; } .gallery item { position: relative; margin bottom: 15px; overflow: hidden; } .gallery item img { width: 100%; display: block; border radius: 5px; cursor: pointer; } .icon container { position: absolute; top: 5px; right: 5px; display: flex; gap: 5px; opacity: 0; transition: opacity 0.3s ease; } .gallery item:hover .icon container { opacity: 1; } .icon { background color: rgba(255, 255, 255, 0.1); color: #e0e0e0; padding: 5px; border radius: 50%; text decoration: none; display: flex; align items: center; justify content: center; width: 30px; height: 30px; transition: all 0.3s ease; } .icon:hover { background color: rgba(255, 255, 255, 0.3); transform: scale(1.1); } .carousel { display: none; max height: 80vh; overflow: hidden; } .carousel item img { max height: 60vh; object fit: contain; width: auto; max width: 100%; } .carousel caption { position: static; background: transparent; padding: 10px; display: flex; justify content: center; gap: 20px; margin top: 10px; } .carousel caption .icon { background color: rgba(255, 255, 255, 0.1); color: #e0e0e0; padding: 5px; border radius: 50%; text decoration: none; display: flex; align items: center; justify content: center; width: 30px; height: 30px; transition: all 0.3s ease; } .carousel caption .icon:hover { background color: rgba(255, 255, 255, 0.3); transform: scale(1.1); } @media (max width: 768px) { .gallery { column count: 2; } } @media (max width: 480px) { .gallery { column count: 1; } .icon container { opacity: 1; } } input[type="text"], button, select { margin bottom: 15px; background color: #1e1e1e; color: #e0e0e0; border: none; } button { background color: #6200ea; } button:hover { background color: #3700b3; } </style> </head> <body> <div class="container"> <input type="text" id="driveUrl" class="form control" placeholder="Enter Google Drive Folder URL" /> <button class="btn btn primary btn block" onclick="fetchImages()">Fetch Images</button> <select class="form control" id="viewMode" onchange="toggleViewMode()"> <option value="masonry">Masonry</option> <option value="carousel">Carousel</option> </select> <div class="gallery" id="gallery"></div> <div class="progress" style="display: none; margin top: 15px;" id="progressContainer"> <div class="progress bar" role="progressbar" style="width: 0%;" id="progressBar">0%</div> </div> <div id="carouselGallery" class="carousel slide carousel fade" data ride="carousel"> <div class="carousel inner" id="carousel inner"></div> <a class="carousel control prev" href="#carouselGallery" role="button" data slide="prev"> <span class="carousel control prev icon" aria hidden="true"></span> <span class="sr only">Previous</span> </a> <a class="carousel control next" href="#carouselGallery" role="button" data slide="next"> <span class="carousel control next icon" aria hidden="true"></span> <span class="sr only">Next</span> </a> </div> </div> <! Lightbox2 JS CDN > <script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.3/js/lightbox plus jquery.min.js"></script> <! Bootstrap JS CDN > <script src="https://code.jquery.com/jquery 3.5.1.slim.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script> <script> function toggleViewMode() { const viewMode = document.getElementById('viewMode').value; const gallery = document.getElementById('gallery'); const carousel = document.getElementById('carouselGallery'); if (viewMode === 'masonry') { gallery.style.display = 'block'; carousel.style.display = 'none'; } else { gallery.style.display = 'none'; carousel.style.display = 'block'; } } async function fetchImages() { const driveUrl = document.getElementById('driveUrl').value.trim(); if (!driveUrl) return alert('Please enter a Google Drive folder URL.'); const progressContainer = document.getElementById('progressContainer'); const progressBar = document.getElementById('progressBar'); try { progressContainer.style.display = 'block'; progressBar.style.width = '0%'; progressBar.textContent = '0%'; const response = await fetch(`/fetch images?driveUrl=${encodeURIComponent(driveUrl)}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); if (data.error) { throw new Error(data.error); } const gallery = document.getElementById('gallery'); const carouselInner = document.getElementById('carousel inner'); gallery.innerHTML = ''; carouselInner.innerHTML = ''; const totalImages = data.images.length; let loadedImages = 0; data.images.forEach((image, index) => { // Masonry view const container = document.createElement('div'); container.classList.add('gallery item'); const link = document.createElement('a'); link.href = image.webpPath; link.setAttribute('data lightbox', 'gallery'); link.setAttribute('data title', image.name); const img = document.createElement('img'); img.src = image.webpPath; img.alt = image.name; link.appendChild(img); const iconContainer = document.createElement('div'); iconContainer.classList.add('icon container'); const downloadIcon = document.createElement('a'); downloadIcon.href = image.downloadLink; downloadIcon.classList.add('icon'); downloadIcon.target = '_blank'; downloadIcon.innerHTML = '<i class="fas fa download"></i>'; iconContainer.appendChild(downloadIcon); container.appendChild(link); container.appendChild(iconContainer); gallery.appendChild(container); // Carousel view const carouselItem = document.createElement('div'); carouselItem.classList.add('carousel item'); if (index === 0) { carouselItem.classList.add('active'); } const carouselImage = document.createElement('img'); carouselImage.src = image.webpPath; carouselImage.alt = image.name; carouselImage.classList.add('d block', 'w 100'); const carouselCaption = document.createElement('div'); carouselCaption.classList.add('carousel caption'); const lightboxLink = document.createElement('a'); lightboxLink.href = image.webpPath; lightboxLink.setAttribute('data lightbox', 'carousel gallery'); lightboxLink.setAttribute('data title', image.name); lightboxLink.classList.add('icon'); lightboxLink.innerHTML = '<i class="fas fa expand"></i>'; const downloadLink = document.createElement('a'); downloadLink.href = image.downloadLink; downloadLink.classList.add('icon'); downloadLink.target = '_blank'; downloadLink.innerHTML = '<i class="fas fa download"></i>'; carouselCaption.appendChild(lightboxLink); carouselCaption.appendChild(downloadLink); carouselItem.appendChild(carouselImage); carouselItem.appendChild(carouselCaption); carouselInner.appendChild(carouselItem); // Update progress bar loadedImages++; const progressPercentage = Math.round((loadedImages / totalImages) * 100); progressBar.style.width = `${progressPercentage}%`; progressBar.textContent = `${progressPercentage}%`; }); toggleViewMode(); // Display the selected view mode } catch (error) { console.error('Error fetching images:', error); alert(error.message || 'Failed to fetch images. Please check the folder URL and try again.'); } finally { progressContainer.style.display = 'none'; } } </script> </body> </html>

Prompt
Component Preview

About

Create a dynamic and responsive image gallery featuring masonry layout and carousel view using Bootstrap. Enhance user experience with lightbox integration and easy image fetching.

Share

Last updated 1 month ago