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