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

added photos

+370 -4
+2 -2
404.html
··· 3 3 <head> 4 4 <title>404 Not Found</title> 5 5 <meta charset="UTF-8"> 6 - <link rel ="stylesheet" href="styles.css"> 7 - <script src="script.js" defer></script> 6 + <link rel ="stylesheet" href="/css/styles.css"> 7 + <script src="/js/script.js" defer></script> 8 8 </head> 9 9 <body> 10 10 <h1>404 Not Found</h1>
+113
css/photos.css
··· 1 + body { 2 + font-family: 'Fira Code', monospace; 3 + background-color: #121212; 4 + color: #e0e0e0; 5 + margin: 40px; 6 + } 7 + a { 8 + color: #f71900; 9 + text-decoration: none; 10 + } 11 + a:hover { 12 + text-decoration: underline; 13 + } 14 + hr { 15 + border: 0; 16 + height: 1px; 17 + background: #e0e0e0; 18 + margin: 20px 0; 19 + } 20 + ul { 21 + list-style-type: none; 22 + padding: 0; 23 + } 24 + li { 25 + margin: 10px 0; 26 + } 27 + i { 28 + margin-right: 8px; 29 + } 30 + .header { 31 + display: flex; 32 + justify-content: space-between; 33 + align-items: center; 34 + flex-wrap: wrap; 35 + margin-bottom: 20px; 36 + } 37 + .title { 38 + font-size: 24px; 39 + margin: 0; 40 + } 41 + .subtitle { 42 + font-size: 16px; 43 + margin-bottom: 20px; 44 + color: #b0b0b0; 45 + width: 100%; 46 + } 47 + .heading { 48 + font-size: 20px; 49 + margin-top: 20px; 50 + margin-bottom: 10px; 51 + } 52 + .download-btn { 53 + background-color: #f71900; 54 + color: white; 55 + border: none; 56 + padding: 10px 20px; 57 + border-radius: 5px; 58 + cursor: pointer; 59 + font-family: 'Fira Code', monospace; 60 + transition: background-color 0.3s; 61 + } 62 + .download-btn:hover { 63 + background-color: #e01600; 64 + } 65 + .download-message { 66 + color: #f71900; 67 + font-size: 14px; 68 + margin-top: 10px; 69 + height: 20px; /* Reserve space to prevent layout shift */ 70 + } 71 + 72 + /* Photo Gallery specific styles for grid layout */ 73 + .photo-gallery { 74 + display: grid; 75 + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); 76 + gap: 20px; 77 + margin-top: 20px; 78 + } 79 + .photo-item { 80 + position: relative; /* Needed for positioning the overlay */ 81 + overflow: hidden; 82 + } 83 + .photo-item img { 84 + width: 100%; 85 + height: 100%; 86 + object-fit: cover; 87 + display: block; 88 + border: 1px solid #1a1a1a; 89 + } 90 + .image-overlay { 91 + position: absolute; 92 + bottom: 0; 93 + left: 0; 94 + width: 100%; 95 + background-color: rgba(0, 0, 0, 0.7); 96 + color: white; 97 + padding: 10px; 98 + box-sizing: border-box; 99 + font-size: 12px; 100 + opacity: 0; 101 + transition: opacity 0.3s ease-in-out; 102 + } 103 + .photo-item:hover .image-overlay { 104 + opacity: 1; 105 + } 106 + 107 + /* Span classes to create the layout from the image */ 108 + .span-2-columns { 109 + grid-column: span 2; 110 + } 111 + .span-2-rows { 112 + grid-row: span 2; 113 + }
+3 -2
index.html
··· 31 31 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" xintegrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer" /> 32 32 33 33 <!-- Styles --> 34 - <link rel="stylesheet" href="styles.css"> 34 + <link rel="stylesheet" href="/css/styles.css"> 35 35 <!-- Scripts --> 36 - <script src="script.js" defer></script> 36 + <script src="/js/script.js" defer></script> 37 37 </head> 38 38 <body> 39 39 <p class="title"><b>Hello World</b> I'm Daniel Morrisey</p> 40 40 <p>Writer @ <a href="https://medium.com/code-and-chaos" target="_blank">Code and Chaos</a> & HTML, CSS, Javascript & Python developer</p> 41 + <p><a href="/photos.html">View my Photos</a></p> 41 42 <hr> 42 43 <p>Find me on:</p> 43 44 <ul>
+187
js/photos.js
··· 1 + document.addEventListener('DOMContentLoaded', function() { 2 + // This array acts as our JavaScript database 3 + const images = [ 4 + // --- root --- 5 + "https://img.madebydanny.uk/img/DSC_4726.avif", 6 + "https://img.madebydanny.uk/img/IMG_1489.avif", 7 + "https://img.madebydanny.uk/img/IMG_1593.avif", 8 + "https://img.madebydanny.uk/img/IMG_1594.avif", 9 + "https://img.madebydanny.uk/img/IMG_1595.avif", 10 + "https://img.madebydanny.uk/img/IMG_1596.avif", 11 + "https://img.madebydanny.uk/img/IMG_1597.avif", 12 + "https://img.madebydanny.uk/img/IMG_1598.avif", 13 + "https://img.madebydanny.uk/img/IMG_1599.avif", 14 + "https://img.madebydanny.uk/img/IMG_1600.avif", 15 + "https://img.madebydanny.uk/img/IMG_1601.avif", 16 + "https://img.madebydanny.uk/img/IMG_1602.avif", 17 + "https://img.madebydanny.uk/img/IMG_1603.avif", 18 + "https://img.madebydanny.uk/img/IMG_1604.avif", 19 + "https://img.madebydanny.uk/img/IMG_1605.avif", 20 + "https://img.madebydanny.uk/img/IMG_1606.avif", 21 + "https://img.madebydanny.uk/img/IMG_1607.avif", 22 + "https://img.madebydanny.uk/img/IMG_1608.avif", 23 + "https://img.madebydanny.uk/img/IMG_1609.avif", 24 + "https://img.madebydanny.uk/img/IMG_1610.avif", 25 + "https://img.madebydanny.uk/img/IMG_1611.avif", 26 + "https://img.madebydanny.uk/img/IMG_1612.avif", 27 + "https://img.madebydanny.uk/img/IMG_1613.avif", 28 + "https://img.madebydanny.uk/img/IMG_1676.avif", 29 + "https://img.madebydanny.uk/img/IMG_1678.avif", 30 + "https://img.madebydanny.uk/img/IMG_1685.avif", 31 + "https://img.madebydanny.uk/img/IMG_1686.avif", 32 + "https://img.madebydanny.uk/img/IMG_1689.avif", 33 + "https://img.madebydanny.uk/img/IMG_1690.avif", 34 + "https://img.madebydanny.uk/img/IMG_1708.avif", 35 + "https://img.madebydanny.uk/img/IMG_1710.avif", 36 + "https://img.madebydanny.uk/img/IMG_1711.avif", 37 + "https://img.madebydanny.uk/img/IMG_1726.avif", 38 + "https://img.madebydanny.uk/img/IMG_1728.avif", 39 + "https://img.madebydanny.uk/img/IMG_1729.avif", 40 + "https://img.madebydanny.uk/img/IMG_1730.avif", 41 + "https://img.madebydanny.uk/img/IMG_1734.avif", 42 + "https://img.madebydanny.uk/img/IMG_1735.avif", 43 + "https://img.madebydanny.uk/img/IMG_1737.avif", 44 + "https://img.madebydanny.uk/img/IMG_1738.avif", 45 + "https://img.madebydanny.uk/img/IMG_1739.avif", 46 + "https://img.madebydanny.uk/img/IMG_1740.avif", 47 + "https://img.madebydanny.uk/img/IMG_1747.avif", 48 + "https://img.madebydanny.uk/img/IMG_1749.avif", 49 + "https://img.madebydanny.uk/img/IMG_1751.avif", 50 + "https://img.madebydanny.uk/img/IMG_1752.avif", 51 + "https://img.madebydanny.uk/img/IMG_1753.avif", 52 + "https://img.madebydanny.uk/img/IMG_1754.avif", 53 + "https://img.madebydanny.uk/img/IMG_1756.avif", 54 + "https://img.madebydanny.uk/img/IMG_1757.avif", 55 + "https://img.madebydanny.uk/img/IMG_1758.avif", 56 + "https://img.madebydanny.uk/img/IMG_1759.avif", 57 + "https://img.madebydanny.uk/img/IMG_1760.avif", 58 + "https://img.madebydanny.uk/img/IMG_1761.avif", 59 + "https://img.madebydanny.uk/img/IMG_1763.avif", 60 + "https://img.madebydanny.uk/img/IMG_1764.avif", 61 + "https://img.madebydanny.uk/img/IMG_1766.avif", 62 + "https://img.madebydanny.uk/img/JPEG image 2.avif", 63 + "https://img.madebydanny.uk/img/JPEG image 3.avif", 64 + "https://img.madebydanny.uk/img/JPEG image.avif", 65 + 66 + // --- upload-2 --- 67 + "https://img.madebydanny.uk/img/upload-2/DSC_2753.avif", 68 + "https://img.madebydanny.uk/img/upload-2/DSC_2754.avif", 69 + "https://img.madebydanny.uk/img/upload-2/DSC_2758.avif", 70 + "https://img.madebydanny.uk/img/upload-2/DSC_2772.avif", 71 + "https://img.madebydanny.uk/img/upload-2/DSC_2791.avif", 72 + "https://img.madebydanny.uk/img/upload-2/DSC_2817.avif", 73 + "https://img.madebydanny.uk/img/upload-2/DSC_2850.avif", 74 + "https://img.madebydanny.uk/img/upload-2/DSC_2852.avif", 75 + "https://img.madebydanny.uk/img/upload-2/DSC_2863.avif", 76 + "https://img.madebydanny.uk/img/upload-2/DSC_2879.avif", 77 + 78 + // --- upload-3 --- 79 + "https://img.madebydanny.uk/img/upload-3/CSC_3608.avif", 80 + "https://img.madebydanny.uk/img/upload-3/DSC_3535.avif", 81 + "https://img.madebydanny.uk/img/upload-3/DSC_3622.avif", 82 + "https://img.madebydanny.uk/img/upload-3/DSC_3633.avif", 83 + "https://img.madebydanny.uk/img/upload-3/DSC_3636.avif", 84 + "https://img.madebydanny.uk/img/upload-3/DSC_3692.avif", 85 + "https://img.madebydanny.uk/img/upload-3/DSC_3764.avif", 86 + "https://img.madebydanny.uk/img/upload-3/DSC_3765.avif", 87 + "https://img.madebydanny.uk/img/upload-3/DSC_3767.avif", 88 + "https://img.madebydanny.uk/img/upload-3/DSC_3773.avif", 89 + "https://img.madebydanny.uk/img/upload-3/DSC_3793.avif", 90 + "https://img.madebydanny.uk/img/upload-3/DSC_3811.avif", 91 + "https://img.madebydanny.uk/img/upload-3/DSC_3827.avif", 92 + 93 + // --- upload-4 --- 94 + "https://img.madebydanny.uk/img/upload-4/DSC_0114.avif", 95 + "https://img.madebydanny.uk/img/upload-4/DSC_0126.avif", 96 + "https://img.madebydanny.uk/img/upload-4/DSC_0140.avif", 97 + "https://img.madebydanny.uk/img/upload-4/DSC_0141.avif", 98 + "https://img.madebydanny.uk/img/upload-4/DSC_0142.avif", 99 + "https://img.madebydanny.uk/img/upload-4/DSC_0144.avif", 100 + "https://img.madebydanny.uk/img/upload-4/DSC_0152.avif", 101 + 102 + // --- upload-5 --- 103 + "https://img.madebydanny.uk/img/upload-5/DSC_0007.avif", 104 + "https://img.madebydanny.uk/img/upload-5/DSC_0009.avif", 105 + "https://img.madebydanny.uk/img/upload-5/DSC_0010.avif", 106 + "https://img.madebydanny.uk/img/upload-5/DSC_0012.avif", 107 + "https://img.madebydanny.uk/img/upload-5/DSC_0015.avif", 108 + "https://img.madebydanny.uk/img/upload-5/DSC_0017.avif", 109 + "https://img.madebydanny.uk/img/upload-5/DSC_0019.avif", 110 + "https://img.madebydanny.uk/img/upload-5/DSC_0044.avif", 111 + "https://img.madebydanny.uk/img/upload-5/DSC_0046.avif", 112 + "https://img.madebydanny.uk/img/upload-5/DSC_0050.avif", 113 + "https://img.madebydanny.uk/img/upload-5/DSC_0065.avif", 114 + "https://img.madebydanny.uk/img/upload-5/DSC_0073.avif", 115 + "https://img.madebydanny.uk/img/upload-5/DSC_0080.avif", 116 + "https://img.madebydanny.uk/img/upload-5/DSC_0093.avif", 117 + "https://img.madebydanny.uk/img/upload-5/DSC_0096.avif", 118 + "https://img.madebydanny.uk/img/upload-5/DSC_0097.avif", 119 + "https://img.madebydanny.uk/img/upload-5/DSC_0115.avif", 120 + ]; 121 + 122 + const gallery = document.getElementById('photo-gallery'); 123 + const downloadAllBtn = document.getElementById('downloadAllBtn'); 124 + const downloadMessage = document.getElementById('downloadMessage'); 125 + 126 + // Dynamically create and add images to the gallery 127 + images.forEach(imageUrl => { 128 + const photoItem = document.createElement('div'); 129 + photoItem.classList.add('photo-item'); 130 + 131 + const img = document.createElement('img'); 132 + img.src = imageUrl; 133 + img.alt = imageUrl.split('/').pop().split('.')[0]; // Set alt text from filename 134 + 135 + // Add an onerror listener to handle failed images 136 + img.onerror = function() { 137 + console.error(`Failed to load image: ${this.src}. Replacing with placeholder.`); 138 + this.src = "https://placehold.co/600x400/94a3b8/e2e8f0?text=Image+Failed"; 139 + }; 140 + 141 + const overlay = document.createElement('div'); 142 + overlay.classList.add('image-overlay'); 143 + overlay.textContent = img.alt; 144 + 145 + photoItem.appendChild(img); 146 + photoItem.appendChild(overlay); 147 + gallery.appendChild(photoItem); 148 + }); 149 + 150 + // Set the current year in the footer 151 + document.getElementById('current-year').textContent = new Date().getFullYear(); 152 + 153 + // Bulk download functionality 154 + downloadAllBtn.addEventListener('click', async () => { 155 + downloadMessage.textContent = 'Preparing files...'; 156 + const zip = new JSZip(); 157 + let filesProcessed = 0; 158 + 159 + for (const imageUrl of images) { 160 + try { 161 + const response = await fetch(imageUrl); 162 + if (!response.ok) { 163 + throw new Error(`Failed to fetch ${imageUrl}: ${response.statusText}`); 164 + } 165 + const blob = await response.blob(); 166 + const filename = imageUrl.substring(imageUrl.lastIndexOf('/') + 1); 167 + zip.file(filename, blob, { binary: true }); 168 + filesProcessed++; 169 + downloadMessage.textContent = `Downloaded ${filesProcessed} of ${images.length} files...`; 170 + } catch (error) { 171 + console.error('Error fetching image for download:', error); 172 + // We'll continue to the next image even if one fails 173 + } 174 + } 175 + 176 + downloadMessage.textContent = `Creating zip file...`; 177 + zip.generateAsync({ type: "blob" }).then(function(content) { 178 + const link = document.createElement('a'); 179 + link.href = URL.createObjectURL(content); 180 + link.download = "photos.zip"; 181 + link.click(); 182 + link.remove(); 183 + downloadMessage.textContent = 'Download complete!'; 184 + setTimeout(() => downloadMessage.textContent = '', 3000); 185 + }); 186 + }); 187 + });
+65
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>My Photos</title> 7 + <meta name="description" content="A photo gallery by Daniel Morrisey"> 8 + 9 + <!-- Google Fonts for a monospaced terminal font --> 10 + <link rel="preconnect" href="https://fonts.googleapis.com"> 11 + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 12 + <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;600&display=swap" rel="stylesheet"> 13 + 14 + <meta name="keywords" content="Daniel Morrisey, Danny Morrisey, MBD, Made by Danny, Made by Danny UK, photos, gallery"/> 15 + <meta name="author" content="Daniel Morrisey"/> 16 + 17 + <meta property="og:type" content="website"/> 18 + <meta property="og:url" content="https://danielmorrisey.com/photos.html"/> 19 + <meta property="og:title" content="Daniel Morrisey - Photos"/> 20 + <meta property="og:description" content="A photo gallery by Daniel Morrisey"/> 21 + <meta property="og:image" content="https://public-danielmorrisey-com.danielmorrisey.com/media/banner.jpg"/> 22 + 23 + <link rel="me" href="https://mastodon.social/@danielmorrisey"/> 24 + <link rel="icon" type="image/x-icon" href="https://public-danielmorrisey-com.danielmorrisey.com/media/icon.jpg"> 25 + 26 + <!-- Status Banner --> 27 + <script src="https://uptime.betterstack.com/widgets/announcement.js" data-id="223534" async="async" type="text/javascript"></script> 28 + 29 + <!-- Font Awesome CDN --> 30 + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" /> 31 + 32 + <!-- JSZip Library for file compression --> 33 + <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script> 34 + 35 + <!-- External Stylesheets --> 36 + <link rel="stylesheet" href="/css/photos.css"> 37 + </head> 38 + <body> 39 + <div class="header"> 40 + <p class="title">My Photos</p> 41 + <p class="subtitle">100's of photos supercharged by Cloudflare</p> 42 + <button id="downloadAllBtn" class="download-btn"> 43 + <i class="fa-solid fa-download"></i> Download All 44 + </button> 45 + <div id="downloadMessage" class="download-message"></div> 46 + <p><a href="/index.html"><i class="fa-solid fa-arrow-left"></i>Back</a></p> 47 + </div> 48 + <hr> 49 + <div class="photo-gallery" id="photo-gallery"> 50 + <!-- Photo items will be generated here by JavaScript --> 51 + </div> 52 + <hr> 53 + <p class="heading">Made Possible thanks to:</p> 54 + <ul> 55 + <li><a href="https://corsproxy.io/" target="_blank"><i class="fa-solid fa-globe"></i> CORS Proxy</a></li> 56 + <li><a href="https://fontawesome.com/" target="_blank"><i class="fa-brands fa-font-awesome"></i> Font Awesome</a></li> 57 + <li><a href="https://cloudflare.com" target="_blank"><i class="fa-brands fa-cloudflare"></i> Cloudflare</a></li> 58 + </ul> 59 + <hr> 60 + <p>&copy; 2024-<span id="current-year"></span> Made by Danny UK, <i>by Daniel Morrisey</i></p> 61 + 62 + <!-- External JavaScript file --> 63 + <script src="/js/photos.js" defer></script> 64 + </body> 65 + </html>
script.js js/script.js
styles.css css/styles.css