| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>AI Image Gallery</title> |
| <style> |
| |
| body { |
| font-family: 'Roboto', sans-serif; |
| margin: 0; |
| padding: 0; |
| background-color: #f0f4f8; |
| color: #333; |
| } |
| |
| h1 { |
| text-align: center; |
| margin-top: 40px; |
| font-size: 40px; |
| color: #212121; |
| font-weight: 700; |
| letter-spacing: 1px; |
| } |
| |
| .loading { |
| display: none; |
| text-align: center; |
| margin-top: 20px; |
| font-size: 18px; |
| color: #007bff; |
| } |
| |
| |
| .gallery { |
| display: grid; |
| grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); |
| gap: 20px; |
| padding: 30px; |
| max-width: 1200px; |
| margin: 0 auto; |
| } |
| |
| .gallery img { |
| width: 100%; |
| height: auto; |
| border-radius: 15px; |
| box-shadow: 0 12px 25px rgba(0, 0, 0, 0.1); |
| transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out; |
| cursor: pointer; |
| border: 4px solid #fff; |
| } |
| |
| .gallery img:hover { |
| transform: scale(1.05); |
| box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2); |
| } |
| |
| |
| .pagination { |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| margin-top: 40px; |
| } |
| |
| .pagination button { |
| padding: 12px 20px; |
| background: linear-gradient(45deg, #007bff, #00aaff); |
| color: white; |
| border: none; |
| border-radius: 50px; |
| font-size: 18px; |
| cursor: pointer; |
| margin: 0 10px; |
| box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1); |
| transition: all 0.3s ease; |
| } |
| |
| .pagination button:hover { |
| background: linear-gradient(45deg, #00aaff, #007bff); |
| box-shadow: 0 12px 30px rgba(0, 0, 0, 0.2); |
| transform: scale(1.1); |
| } |
| |
| .pagination button:disabled { |
| background: #ccc; |
| cursor: not-allowed; |
| } |
| |
| .pagination .page-info { |
| font-size: 18px; |
| color: #333; |
| margin: 0 15px; |
| } |
| |
| |
| .modal { |
| display: none; |
| position: fixed; |
| z-index: 9999; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| background-color: rgba(0, 0, 0, 0.8); |
| justify-content: center; |
| align-items: center; |
| animation: fadeIn 0.3s ease; |
| } |
| |
| .modal img { |
| max-width: 90%; |
| max-height: 90%; |
| border-radius: 10px; |
| } |
| |
| .modal .close { |
| position: absolute; |
| top: 20px; |
| right: 30px; |
| color: white; |
| font-size: 40px; |
| font-weight: bold; |
| cursor: pointer; |
| background-color: transparent; |
| border: none; |
| } |
| |
| .modal .close:hover { |
| color: #bbb; |
| } |
| |
| |
| @keyframes fadeIn { |
| from { opacity: 0; } |
| to { opacity: 1; } |
| } |
| |
| |
| .loading { |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| margin-top: 20px; |
| } |
| |
| .loading::before { |
| content: ""; |
| border: 4px solid #f3f3f3; |
| border-top: 4px solid #007bff; |
| border-radius: 50%; |
| width: 40px; |
| height: 40px; |
| animation: spin 1s linear infinite; |
| } |
| |
| @keyframes spin { |
| 0% { transform: rotate(0deg); } |
| 100% { transform: rotate(360deg); } |
| } |
| </style> |
| </head> |
| <body> |
|
|
| <h1>AI Image Gallery</h1> |
| <div class="loading">Loading more images...</div> |
| <div class="gallery" id="gallery"></div> |
|
|
| |
| <div class="pagination"> |
| <button id="prevBtn" disabled>Previous</button> |
| <span class="page-info" id="pageInfo">Page 1 of 1</span> |
| <button id="nextBtn">Next</button> |
| </div> |
|
|
| |
| <div id="myModal" class="modal"> |
| <button class="close" id="closeModal">×</button> |
| <img id="modalImg" src="" alt="Expanded Image"> |
| </div> |
|
|
| <script> |
| const markdownUrl = "https://proxy.gpt-chatbot.workers.dev/https://pub-fdaeaa9117e64f39ae731591e713d186.r2.dev/logs/imgnaicloud.txt"; |
| const imagesPerPage = 8; |
| let imageUrls = []; |
| let currentPage = 0; |
| |
| |
| fetch(markdownUrl) |
| .then(response => response.text()) |
| .then(markdownContent => { |
| imageUrls = parseImageUrls(markdownContent); |
| imageUrls.reverse(); |
| renderImages(); |
| updatePageInfo(); |
| }) |
| .catch(error => { |
| console.error("Error fetching markdown:", error); |
| document.querySelector('.loading').textContent = "Failed to load images."; |
| }); |
| |
| |
| function parseImageUrls(markdown) { |
| const regex = /!\[.*?\]\((https?:\/\/[^\s]+)\)/g; |
| let match; |
| const urls = []; |
| while ((match = regex.exec(markdown)) !== null) { |
| urls.push(match[1]); |
| } |
| return urls; |
| } |
| |
| |
| function renderImages() { |
| const gallery = document.getElementById("gallery"); |
| const loading = document.querySelector('.loading'); |
| const startIndex = currentPage * imagesPerPage; |
| const imagesToRender = imageUrls.slice(startIndex, startIndex + imagesPerPage); |
| |
| |
| loading.style.display = 'block'; |
| |
| gallery.innerHTML = ''; |
| imagesToRender.forEach(url => { |
| const imgElement = document.createElement("img"); |
| imgElement.src = url; |
| imgElement.alt = "Image from markdown"; |
| imgElement.onload = () => { imgElement.style.opacity = 1 }; |
| imgElement.onerror = () => { imgElement.style.opacity = 0.5 }; |
| imgElement.addEventListener('click', () => openModal(url)); |
| gallery.appendChild(imgElement); |
| }); |
| |
| loading.style.display = 'none'; |
| updatePageInfo(); |
| } |
| |
| |
| function updatePageInfo() { |
| const totalPages = Math.ceil(imageUrls.length / imagesPerPage); |
| const pageInfo = document.getElementById("pageInfo"); |
| pageInfo.textContent = `Page ${currentPage + 1} of ${totalPages}`; |
| |
| document.getElementById("prevBtn").disabled = currentPage === 0; |
| document.getElementById("nextBtn").disabled = currentPage === totalPages - 1; |
| } |
| |
| |
| function openModal(imgSrc) { |
| const modal = document.getElementById("myModal"); |
| const modalImg = document.getElementById("modalImg"); |
| modalImg.src = imgSrc; |
| modal.style.display = "flex"; |
| } |
| |
| |
| document.getElementById("closeModal").addEventListener("click", () => { |
| document.getElementById("myModal").style.display = "none"; |
| }); |
| |
| |
| document.getElementById("prevBtn").addEventListener("click", () => { |
| if (currentPage > 0) { |
| currentPage--; |
| renderImages(); |
| } |
| }); |
| |
| document.getElementById("nextBtn").addEventListener("click", () => { |
| if ((currentPage + 1) * imagesPerPage < imageUrls.length) { |
| currentPage++; |
| renderImages(); |
| } |
| }); |
| </script> |
|
|
| </body> |
| </html> |
|
|