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 404.html
Daniel Morrisey
6 months ago
ede13414
f4bff11c
+181
-104
4 changed files
expand all
collapse all
unified
split
404.html
index.html
script.js
styles.css
+21
404.html
···
1
1
+
<!DOCTYPE html>
2
2
+
<html lang="en">
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>
8
8
+
</head>
9
9
+
<body>
10
10
+
<h1>404 Not Found</h1>
11
11
+
<p>The page you are looking for does not exist.</p>
12
12
+
<p><a href="index.html">Return to Home</a></p>
13
13
+
<hr>
14
14
+
Cloudflare Pages retured a 404 error.
15
15
+
<br>
16
16
+
The file you requested at <i><url id="error-url"></url></i>could not be found.
17
17
+
<br><br>
18
18
+
Please check the URL for errors and try again.
19
19
+
<hr>
20
20
+
<p>© 2024-<span id="current-year"></span> Made by Danny UK, <i>by Daniel Morrisey</i></p>
21
21
+
</html>
+19
-104
index.html
···
30
30
<!-- Font Awesome CDN -->
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
-
<style>
34
34
-
body {
35
35
-
font-family: 'Fira Code', monospace;
36
36
-
background-color: #121212;
37
37
-
color: #e0e0e0;
38
38
-
margin: 40px;
39
39
-
}
40
40
-
a {
41
41
-
color: #f71900;
42
42
-
text-decoration: none;
43
43
-
}
44
44
-
a:hover {
45
45
-
text-decoration: underline;
46
46
-
}
47
47
-
hr {
48
48
-
border: 0;
49
49
-
height: 1px;
50
50
-
background: #333;
51
51
-
margin: 20px 0;
52
52
-
}
53
53
-
ul {
54
54
-
list-style-type: none;
55
55
-
padding: 0;
56
56
-
}
57
57
-
li {
58
58
-
margin: 10px 0;
59
59
-
}
60
60
-
i {
61
61
-
margin-right: 8px;
62
62
-
}
63
63
-
.title {
64
64
-
font-size: 24px;
65
65
-
margin-bottom: 10px;
66
66
-
}
67
67
-
</style>
33
33
+
<!-- Styles -->
34
34
+
<link rel="stylesheet" href="styles.css">
35
35
+
<!-- Scripts -->
36
36
+
<script src="script.js" defer></script>
68
37
</head>
69
38
<body>
70
39
<p class="title"><b>Hello World</b> I'm Daniel Morrisey</p>
···
74
43
<ul>
75
44
<li><a href="https://bsky.app/profile/danielmorrisey.com" target="_blank"><i class="fa-brands fa-bluesky"></i> Bluesky</a></li>
76
45
<li><a href="https://threads.com/madebydanny.uk" target="_blank"><i class="fa-brands fa-threads"></i> Threads</a></li>
46
46
+
<li><a href="https://mastodon.social/@danielmorrisey" target="_blank"><i class="fa-brands fa-mastodon"></i> Mastodon<i>(.social)</i></a></li>
77
47
<li><a href="https://medium.com/@danielmorrisey" target="_blank"><i class="fa-brands fa-medium"></i> Medium</a></li>
78
48
<li><a href="mailto:danielmorrisey.large390@passinbox.com" target="_blank"><i class="fa-solid fa-envelope"></i> Email</a></li>
79
49
</ul>
80
50
<hr>
81
81
-
<p>Latest Posts by Daniel Morrisey</p>
82
82
-
83
83
-
<div id="loading">Fetching posts...</div>
84
84
-
85
85
-
<div id="post-list" style="display: none;"></div>
86
86
-
87
87
-
<div id="error-message" style="display: none;">Failed to load posts. Please try again later.</div>
88
88
-
89
89
-
<script>
90
90
-
const postList = document.getElementById('post-list');
91
91
-
const loadingIndicator = document.getElementById('loading');
92
92
-
const errorMessage = document.getElementById('error-message');
93
93
-
94
94
-
const fetchPosts = async () => {
95
95
-
const feedUrl = 'https://medium.com/feed/@danielmorrisey';
96
96
-
// Using corsproxy.io instead of allorigins.win as it seems to be more reliable
97
97
-
const proxyUrl = `https://corsproxy.io/?${encodeURIComponent(feedUrl)}`;
98
98
-
99
99
-
try {
100
100
-
const response = await fetch(proxyUrl);
101
101
-
if (!response.ok) {
102
102
-
throw new Error('Network response was not ok');
103
103
-
}
104
104
-
const data = await response.text(); // Get response as text instead of json
105
105
-
106
106
-
const parser = new DOMParser();
107
107
-
const xmlDoc = parser.parseFromString(data, 'text/xml');
108
108
-
109
109
-
const items = xmlDoc.querySelectorAll('item');
110
110
-
const postsToShow = 5;
111
111
-
112
112
-
if (items.length > 0) {
113
113
-
items.forEach((item, index) => {
114
114
-
if (index < postsToShow) {
115
115
-
const title = item.querySelector('title').textContent;
116
116
-
const link = item.querySelector('link').textContent;
117
117
-
118
118
-
const paragraph = document.createElement('p');
119
119
-
const linkElement = document.createElement('a');
120
120
-
const iconElement = document.createElement('i');
121
121
-
122
122
-
linkElement.href = link;
123
123
-
linkElement.textContent = title;
124
124
-
linkElement.target = "_blank";
125
125
-
126
126
-
iconElement.className = "fa-solid fa-arrow-up-right-from-square";
127
127
-
iconElement.style.marginLeft = "5px"; // Add a small space
128
128
-
129
129
-
paragraph.appendChild(linkElement);
130
130
-
paragraph.appendChild(iconElement);
131
131
-
132
132
-
postList.appendChild(paragraph);
133
133
-
}
134
134
-
});
135
135
-
postList.style.display = 'block';
136
136
-
} else {
137
137
-
errorMessage.textContent = "No posts found.";
138
138
-
errorMessage.style.display = 'block';
139
139
-
}
140
140
-
} catch (error) {
141
141
-
console.error('Error fetching or parsing the feed:', error);
142
142
-
errorMessage.style.display = 'block';
143
143
-
} finally {
144
144
-
loadingIndicator.style.display = 'none';
145
145
-
}
146
146
-
};
147
147
-
148
148
-
document.addEventListener('DOMContentLoaded', fetchPosts);
149
149
-
</script>
51
51
+
<p class="heading">Latest Posts by Daniel Morrisey</p>
52
52
+
<p><i>This list will auto refresh</i></p>
53
53
+
<ul id="post-list"></ul>
54
54
+
<div id="loading"><i class="fa-solid fa-arrows-rotate fa-spin"></i>Loading…</div>
55
55
+
<div id="error-message" style="display:none;color:red;"></div>
56
56
+
<hr>
57
57
+
<p class="heading">Made Possible thanks to:</p>
58
58
+
<ul>
59
59
+
<li><a href="https://corsproxy.io/" target="_blank"><i class="fa-solid fa-globe"></i> CORS Proxy</a></li>
60
60
+
<li><a href="https://fontawesome.com/" target="_blank"><i class="fa-brands fa-font-awesome"></i> Font Awesome</a></li>
61
61
+
<li><a href="https://cloudflare.com" target="_blank"><i class="fa-brands fa-cloudflare"></i> Cloudflare</a></li>
62
62
+
</ul>
63
63
+
<hr>
64
64
+
<p>© 2024-<span id="current-year"></span> Made by Danny UK, <i>by Daniel Morrisey</i></p>
150
65
</body>
151
66
</html>
+103
script.js
···
1
1
+
/* ------------------------------------------------------------------ *
2
2
+
* Utility: set the current year
3
3
+
* ------------------------------------------------------------------ */
4
4
+
document.getElementById('current-year').textContent = new Date().getFullYear();
5
5
+
6
6
+
/* ------------------------------------------------------------------ *
7
7
+
* Configuration
8
8
+
* ------------------------------------------------------------------ */
9
9
+
const CONFIG = {
10
10
+
FEED_URL: 'https://medium.com/feed/@danielmorrisey',
11
11
+
PROXY_URL: url => `https://corsproxy.io/?${encodeURIComponent(url)}`,
12
12
+
POSTS_TO_SHOW: 5,
13
13
+
REFRESH_INTERVAL_MS: 60_000, // 1 minute
14
14
+
};
15
15
+
16
16
+
/* ------------------------------------------------------------------ *
17
17
+
* DOM references – grab them once so we don’t query repeatedly
18
18
+
* ------------------------------------------------------------------ */
19
19
+
const dom = {
20
20
+
postList: document.getElementById('post-list'),
21
21
+
loading: document.getElementById('loading'),
22
22
+
errorMessage: document.getElementById('error-message')
23
23
+
};
24
24
+
25
25
+
/* ------------------------------------------------------------------ *
26
26
+
* Helper: show / hide UI elements
27
27
+
* ------------------------------------------------------------------ */
28
28
+
function toggleVisibility(el, visible) {
29
29
+
el.style.display = visible ? '' : 'none';
30
30
+
}
31
31
+
32
32
+
/* ------------------------------------------------------------------ *
33
33
+
* Helper: create a single post element
34
34
+
* ------------------------------------------------------------------ */
35
35
+
function createPostItem({ title = '(no title)', link = '#' }) {
36
36
+
const p = document.createElement('p');
37
37
+
const a = document.createElement('a');
38
38
+
const icn = document.createElement('i');
39
39
+
40
40
+
a.href = link;
41
41
+
a.textContent = title;
42
42
+
a.target = '_blank';
43
43
+
44
44
+
icn.className = 'fa-solid fa-arrow-up-right-from-square';
45
45
+
icn.style.marginLeft = '5px';
46
46
+
47
47
+
p.appendChild(a);
48
48
+
p.appendChild(icn);
49
49
+
return p;
50
50
+
}
51
51
+
52
52
+
/* ------------------------------------------------------------------ *
53
53
+
* Main: fetch, parse and render the RSS feed
54
54
+
* ------------------------------------------------------------------ */
55
55
+
async function fetchPosts() {
56
56
+
toggleVisibility(dom.loading, true);
57
57
+
toggleVisibility(dom.errorMessage, false);
58
58
+
dom.postList.innerHTML = ''; // clear previous items
59
59
+
60
60
+
try {
61
61
+
const response = await fetch(CONFIG.PROXY_URL(CONFIG.FEED_URL));
62
62
+
if (!response.ok) throw new Error(`Network error: ${response.status}`);
63
63
+
64
64
+
const rawXml = await response.text();
65
65
+
const parser = new DOMParser();
66
66
+
const xmlDoc = parser.parseFromString(rawXml, 'application/xml');
67
67
+
68
68
+
const items = [...xmlDoc.querySelectorAll('item')];
69
69
+
if (items.length === 0) throw new Error('No posts found.');
70
70
+
71
71
+
items
72
72
+
.slice(0, CONFIG.POSTS_TO_SHOW)
73
73
+
.map(item => ({
74
74
+
title: item.querySelector('title')?.textContent ?? '(no title)',
75
75
+
link: item.querySelector('link')?.textContent ?? '#'
76
76
+
}))
77
77
+
.forEach(postData => dom.postList.appendChild(createPostItem(postData)));
78
78
+
79
79
+
} catch (err) {
80
80
+
console.error('RSS fetch/parse error:', err);
81
81
+
dom.errorMessage.textContent = err.message || 'Failed to load articles.';
82
82
+
toggleVisibility(dom.errorMessage, true);
83
83
+
} finally {
84
84
+
toggleVisibility(dom.loading, false);
85
85
+
}
86
86
+
}
87
87
+
88
88
+
/* ------------------------------------------------------------------ *
89
89
+
* Helper: store the current URL in the hidden <url> element
90
90
+
* ------------------------------------------------------------------ */
91
91
+
function setErrorUrl() {
92
92
+
const el = document.getElementById('error-url');
93
93
+
if (el) el.textContent = window.location.href;
94
94
+
}
95
95
+
96
96
+
/* ------------------------------------------------------------------ *
97
97
+
* Initialise – run once now and then on an interval
98
98
+
* ------------------------------------------------------------------ */
99
99
+
document.addEventListener('DOMContentLoaded', () => {
100
100
+
setErrorUrl(); // store the URL for your 404 page
101
101
+
fetchPosts(); // initial load
102
102
+
setInterval(fetchPosts, CONFIG.REFRESH_INTERVAL_MS); // repeat periodically
103
103
+
});
+38
styles.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: #333;
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
+
.title {
31
31
+
font-size: 24px;
32
32
+
margin-bottom: 10px;
33
33
+
}
34
34
+
.heading {
35
35
+
font-size: 20px;
36
36
+
margin-top: 20px;
37
37
+
margin-bottom: 10px;
38
38
+
}