madebydanny.uk written in html, css, and a lot of JavaScript I don't understand madeydanny.uk
html css javascript

added photos page

+343 -1
+1 -1
index.html
··· 19 19 <div id="total-visitors" style="font-size: 0.8em; color: gray; text-align: center;"> 20 20 Calculating total visits... 21 21 </div> 22 - <p><a href="https://guestbook.madebydanny.uk">Sign the Guestbook</a> ~ <a href="https://pdsls.dev/at://did:plc:l37td5yhxl2irrzrgvei4qay/fm.teal.alpha.feed.play">Recently played Music</a> ~ <a href="/about.html">About Me</a></p> 22 + <p><a href="https://guestbook.madebydanny.uk">Guestbook</a> ~ <a href="https://pdsls.dev/at://did:plc:l37td5yhxl2irrzrgvei4qay/fm.teal.alpha.feed.play">Recently played Music</a> ~ <a href="/about.html">About Me</a> ~ <a href="https://microblog.madebydanny.uk">Microblog</a> ~ <a href="/photos.html">Photos</a></p> 23 23 <p>I like to listen to Music <i>(Mainly Tate McRae and Taylor Swift)</i>, and post on Bluesky<br>I'm also on <a href="https://threads.net/@madebydanny.uk" target="_blank">Threads</a> and <a href="ttps://mastodon.social/@danielmorrisey" target="_blank">Mastodon</a>, but active on <a href="https://aturi.to/did:plc:l37td5yhxl2irrzrgvei4qay" target="_blank">Bluesky</a>, becuase it's the best social media platform</p> 24 24 <div id="music-status-card"> 25 25 <div class="bsky-header">
+150
js/photos.js
··· 1 + // Photos Gallery Manager 2 + const PHOTOS = [ 3 + // Add your photos here in this format: 4 + // { 5 + // src: '/path/to/image.jpg', 6 + // title: 'Photo Title', 7 + // date: '2024-01-15' 8 + // } 9 + { 10 + src: 'https://cloudflareisawesome.madebydanny.uk/photos-upload-1/20240622_235041500_iOS.jpg', 11 + title: 'DSC_3811.jpg', 12 + date: '2025-10-14' 13 + }, 14 + { 15 + src: 'https://cloudflareisawesome.madebydanny.uk/photos-upload-1/DSC_3773.jpg', 16 + title: 'DSC_3773.jpg', 17 + date: '2025-10-14' 18 + }, 19 + { 20 + src: 'https://cloudflareisawesome.madebydanny.uk/photos-upload-1/DSC_3766.jpg', 21 + title: 'DSC_3766.jpg', 22 + date: '2025-10-14' 23 + }, 24 + { 25 + src: 'https://cloudflareisawesome.madebydanny.uk/photos-upload-1/DSC_3765.jpg', 26 + title: 'DSC_3765.jpg', 27 + date: '2025-10-14' 28 + }, 29 + { 30 + src: 'https://cloudflareisawesome.madebydanny.uk/photos-upload-1/DSC_3704.jpg', 31 + title: 'DSC_3704.jpg', 32 + date: '2025-10-14' 33 + }, 34 + { 35 + src: `https://cloudflareisawesome.madebydanny.uk/photos-upload-1/DSC_3692.jpg`, 36 + title: 'DSC_3692.jpg', 37 + date: '2025-10-14' 38 + }, 39 + { 40 + src: 'https://cloudflareisawesome.madebydanny.uk/photos-upload-1/20240622_234015800_iOS.jpg', 41 + title: 'DSC_3683.jpg', 42 + date: '2025-10-14' 43 + } 44 + ]; 45 + 46 + function renderPhotosGallery() { 47 + const gallery = document.getElementById('photos-gallery'); 48 + const emptyState = document.getElementById('empty-photos'); 49 + 50 + if (!gallery) return; 51 + 52 + gallery.innerHTML = ''; 53 + 54 + if (PHOTOS.length === 0) { 55 + emptyState.style.display = 'block'; 56 + return; 57 + } 58 + 59 + emptyState.style.display = 'none'; 60 + 61 + PHOTOS.forEach((photo, index) => { 62 + const photoItem = document.createElement('div'); 63 + photoItem.className = 'photo-item'; 64 + photoItem.role = 'button'; 65 + photoItem.tabIndex = 0; 66 + photoItem.setAttribute('aria-label', `View photo: ${photo.title}`); 67 + 68 + const img = document.createElement('img'); 69 + img.src = photo.src; 70 + img.alt = photo.title; 71 + img.loading = 'lazy'; 72 + 73 + const info = document.createElement('div'); 74 + info.className = 'photo-info'; 75 + 76 + const title = document.createElement('h3'); 77 + title.className = 'photo-title'; 78 + title.textContent = photo.title; 79 + 80 + const date = document.createElement('p'); 81 + date.className = 'photo-date'; 82 + date.textContent = new Date(photo.date).toLocaleDateString('en-US', { 83 + year: 'numeric', 84 + month: 'short', 85 + day: 'numeric' 86 + }); 87 + 88 + info.appendChild(title); 89 + info.appendChild(date); 90 + photoItem.appendChild(img); 91 + photoItem.appendChild(info); 92 + 93 + photoItem.addEventListener('click', () => openPhotoModal(photo.src, photo.title)); 94 + photoItem.addEventListener('keydown', (e) => { 95 + if (e.key === 'Enter' || e.key === ' ') { 96 + openPhotoModal(photo.src, photo.title); 97 + } 98 + }); 99 + 100 + gallery.appendChild(photoItem); 101 + }); 102 + } 103 + 104 + function openPhotoModal(src, alt) { 105 + const modal = document.getElementById('photo-modal'); 106 + const modalImg = document.getElementById('modal-photo'); 107 + 108 + if (modal && modalImg) { 109 + modalImg.src = src; 110 + modalImg.alt = alt; 111 + modal.classList.add('active'); 112 + document.body.style.overflow = 'hidden'; 113 + } 114 + } 115 + 116 + function closePhotoModal() { 117 + const modal = document.getElementById('photo-modal'); 118 + if (modal) { 119 + modal.classList.remove('active'); 120 + document.body.style.overflow = 'auto'; 121 + } 122 + } 123 + 124 + // Initialize on page load 125 + document.addEventListener('DOMContentLoaded', () => { 126 + renderPhotosGallery(); 127 + 128 + // Modal close button 129 + const closeBtn = document.getElementById('modal-close'); 130 + if (closeBtn) { 131 + closeBtn.addEventListener('click', closePhotoModal); 132 + } 133 + 134 + // Close modal when clicking outside image 135 + const modal = document.getElementById('photo-modal'); 136 + if (modal) { 137 + modal.addEventListener('click', (e) => { 138 + if (e.target === modal) { 139 + closePhotoModal(); 140 + } 141 + }); 142 + 143 + // Close on Escape key 144 + document.addEventListener('keydown', (e) => { 145 + if (e.key === 'Escape') { 146 + closePhotoModal(); 147 + } 148 + }); 149 + } 150 + });
+192
photos.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8"> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 + <title>Photos · madebydanny.uk</title> 7 + <script src="https://kit.fontawesome.com/0ca27f8db1.js" crossorigin="anonymous"></script> 8 + <link rel="icon" id="favicon" href="https://imrs.madebydanny.uk/?url=https://cloudflareisawesome.madebydanny.uk/madebydanny.uk/seo/favicon.webp"> 9 + <meta name="description" content="Photo gallery from Daniel Morrisey"> 10 + <meta property="og:title" content="Photos · madebydanny.uk"> 11 + <meta property="og:description" content="Photo gallery from Daniel Morrisey"> 12 + <meta property="og:type" content="website"> 13 + <meta property="og:url" content="https://madebydanny.uk/photos"> 14 + <meta property="og:image" content="/media/og.png"> 15 + <link rel="stylesheet" href="/css/index.css"> 16 + <style> 17 + .photos-header { 18 + margin-bottom: 32px; 19 + text-align: center; 20 + } 21 + 22 + .photos-header h1 { 23 + margin: 0 0 12px 0; 24 + font-size: 2rem; 25 + } 26 + 27 + .photos-header p { 28 + margin: 0; 29 + color: var(--bsky-subtext-color); 30 + } 31 + 32 + .photos-gallery { 33 + display: grid; 34 + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); 35 + gap: 16px; 36 + margin: 24px 0; 37 + } 38 + 39 + .photo-item { 40 + position: relative; 41 + overflow: hidden; 42 + border-radius: 12px; 43 + background: var(--bsky-card-bg); 44 + border: 1px solid var(--bsky-border); 45 + cursor: pointer; 46 + transition: transform 0.2s ease, box-shadow 0.2s ease; 47 + } 48 + 49 + .photo-item:hover { 50 + transform: translateY(-4px); 51 + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); 52 + } 53 + 54 + .photo-item img { 55 + width: 100%; 56 + height: 250px; 57 + object-fit: cover; 58 + display: block; 59 + } 60 + 61 + .photo-info { 62 + padding: 12px; 63 + background: var(--bsky-post-bg); 64 + } 65 + 66 + .photo-title { 67 + font-weight: 600; 68 + margin: 0 0 4px 0; 69 + font-size: 0.95rem; 70 + } 71 + 72 + .photo-date { 73 + font-size: 0.8rem; 74 + color: var(--bsky-subtext-color); 75 + margin: 0; 76 + } 77 + 78 + .empty-state { 79 + text-align: center; 80 + padding: 48px 24px; 81 + color: var(--bsky-subtext-color); 82 + } 83 + 84 + .empty-state i { 85 + font-size: 3rem; 86 + margin-bottom: 16px; 87 + opacity: 0.5; 88 + } 89 + 90 + /* Modal for full-size image view */ 91 + .photo-modal { 92 + display: none; 93 + position: fixed; 94 + z-index: 1000; 95 + left: 0; 96 + top: 0; 97 + width: 100%; 98 + height: 100%; 99 + background-color: rgba(0, 0, 0, 0.9); 100 + animation: fadeIn 0.2s ease; 101 + } 102 + 103 + .photo-modal.active { 104 + display: flex; 105 + align-items: center; 106 + justify-content: center; 107 + } 108 + 109 + .photo-modal-content { 110 + position: relative; 111 + max-width: 90%; 112 + max-height: 90%; 113 + } 114 + 115 + .photo-modal-img { 116 + width: 100%; 117 + height: auto; 118 + border-radius: 8px; 119 + } 120 + 121 + .photo-modal-close { 122 + position: absolute; 123 + top: -40px; 124 + right: 0; 125 + color: white; 126 + font-size: 2rem; 127 + cursor: pointer; 128 + background: none; 129 + border: none; 130 + padding: 0; 131 + transition: opacity 0.2s ease; 132 + } 133 + 134 + .photo-modal-close:hover { 135 + opacity: 0.7; 136 + } 137 + 138 + @keyframes fadeIn { 139 + from { 140 + opacity: 0; 141 + } 142 + to { 143 + opacity: 1; 144 + } 145 + } 146 + 147 + @media (max-width: 640px) { 148 + .photos-gallery { 149 + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); 150 + gap: 12px; 151 + } 152 + 153 + .photo-item img { 154 + height: 180px; 155 + } 156 + 157 + .photos-header h1 { 158 + font-size: 1.5rem; 159 + } 160 + } 161 + </style> 162 + </head> 163 + <body> 164 + <div class="photos-header"> 165 + <h1>Photos</h1> 166 + </div> 167 + 168 + <div id="photos-gallery" class="photos-gallery"></div> 169 + 170 + <div id="empty-photos" class="empty-state" style="display: none;"> 171 + <i class="fas fa-image"></i> 172 + <p>No photos yet. Check back soon!</p> 173 + </div> 174 + 175 + <!-- Photo Modal --> 176 + <div id="photo-modal" class="photo-modal"> 177 + <div class="photo-modal-content"> 178 + <button class="photo-modal-close" id="modal-close">&times;</button> 179 + <img id="modal-photo" class="photo-modal-img" src="" alt=""> 180 + </div> 181 + </div> 182 + 183 + <hr> 184 + <p><b>Social Links:</b></p> 185 + <div id="social-links"></div> 186 + <hr> 187 + <div id="site-footer"></div> 188 + 189 + <script src="/js/social-links.js"></script> 190 + <script src="/js/photos.js"></script> 191 + </body> 192 + </html>