summaryrefslogtreecommitdiff
path: root/webring.js
diff options
context:
space:
mode:
Diffstat (limited to 'webring.js')
-rw-r--r--webring.js206
1 files changed, 103 insertions, 103 deletions
diff --git a/webring.js b/webring.js
index 7ab184f..621e281 100644
--- a/webring.js
+++ b/webring.js
@@ -2,47 +2,47 @@ const RING_CACHE_KEY = 'tarantino-ring-cache';
const RING_CACHE_TTL_MS = 5 * 60_000;
async function fetchRingMembers() {
- const cached = localStorage.getItem(RING_CACHE_KEY);
- if (cached) {
- const { data, ts } = JSON.parse(cached);
- if (Date.now() - ts < RING_CACHE_TTL_MS) return data;
- }
-
- const res = await fetch('https://roughlynamed.net/tarantino/ring.json');
- if (!res.ok) throw new Error(`tarantino webring fetch failed: ${res.status}`);
- const { members } = await res.json();
-
- localStorage.setItem(RING_CACHE_KEY, JSON.stringify({ data: members, ts: Date.now() }));
- return members;
+ const cached = localStorage.getItem(RING_CACHE_KEY);
+ if (cached) {
+ const { data, ts } = JSON.parse(cached);
+ if (Date.now() - ts < RING_CACHE_TTL_MS) return data;
+ }
+
+ const res = await fetch('https://roughlynamed.net/tarantino/ring.json');
+ if (!res.ok) throw new Error(`tarantino webring fetch failed: ${res.status}`);
+ const { members } = await res.json();
+
+ localStorage.setItem(RING_CACHE_KEY, JSON.stringify({ data: members, ts: Date.now() }));
+ return members;
}
function originOf(member) {
- try {
- return new URL(member.url).origin;
- } catch (err) {
- console.error('tarantino webring: bad url on member', member, err);
- return null;
- }
+ try {
+ return new URL(member.url).origin;
+ } catch (err) {
+ console.error('tarantino webring: bad url on member', member, err);
+ return null;
+ }
}
function warningLabel(m) {
- return m.content_warnings?.length ? ` (cw: ${m.content_warnings.join(', ')})` : '';
+ return m.content_warnings?.length ? ` (cw: ${m.content_warnings.join(', ')})` : '';
}
function ensureWarningDialog() {
- let dialog = document.getElementById('ring-warning-dialog');
- if (dialog) return dialog;
+ let dialog = document.getElementById('ring-warning-dialog');
+ if (dialog) return dialog;
- dialog = document.createElement('dialog');
- dialog.id = 'ring-warning-dialog';
- dialog.innerHTML = `
+ dialog = document.createElement('dialog');
+ dialog.id = 'ring-warning-dialog';
+ dialog.innerHTML = `
<p id="ring-warning-text"></p>
<menu style="display: flex; gap: 0.5rem; justify-content: flex-end; padding: 0; margin: 0.75rem 0 0;">
<button type="button" value="cancel">cancel</button>
<button type="button" value="continue" autofocus>continue</button>
</menu>
`;
- dialog.style.cssText = `
+ dialog.style.cssText = `
background: var(--bg, #fff);
color: var(--text, #000);
border: 1px solid var(--border, #ccc);
@@ -50,102 +50,102 @@ function ensureWarningDialog() {
max-width: 28rem;
padding: 1rem;
`;
- document.body.appendChild(dialog);
+ document.body.appendChild(dialog);
- dialog.querySelector('button[value="cancel"]').addEventListener('click', () => dialog.close('cancel'));
- dialog.querySelector('button[value="continue"]').addEventListener('click', () => dialog.close('continue'));
+ dialog.querySelector('button[value="cancel"]').addEventListener('click', () => dialog.close('cancel'));
+ dialog.querySelector('button[value="continue"]').addEventListener('click', () => dialog.close('continue'));
- return dialog;
+ return dialog;
}
function confirmIfFlagged(e, member) {
- if (!member.content_warnings?.length) return;
- e.preventDefault();
-
- const dialog = ensureWarningDialog();
- dialog.querySelector('#ring-warning-text').textContent =
- `Heads up: this site is flagged for ${member.content_warnings.join(', ')}. Continue?`;
-
- dialog.addEventListener(
- 'close',
- () => {
- if (dialog.returnValue === 'continue') location.href = member.url;
- },
- { once: true }
- );
-
- dialog.showModal();
+ if (!member.content_warnings?.length) return;
+ e.preventDefault();
+
+ const dialog = ensureWarningDialog();
+ dialog.querySelector('#ring-warning-text').textContent =
+ `Heads up: this site is flagged for ${member.content_warnings.join(', ')}. Continue?`;
+
+ dialog.addEventListener(
+ 'close',
+ () => {
+ if (dialog.returnValue === 'continue') location.href = member.url;
+ },
+ { once: true }
+ );
+
+ dialog.showModal();
}
function wireNavLink(id, member) {
- const el = document.getElementById(id);
- if (!el || !member) return;
- el.href = member.url;
- el.addEventListener('click', e => confirmIfFlagged(e, member));
+ const el = document.getElementById(id);
+ if (!el || !member) return;
+ el.href = member.url;
+ el.addEventListener('click', e => confirmIfFlagged(e, member));
}
function disableNavLink(id) {
- const el = document.getElementById(id);
- if (!el) return;
- el.removeAttribute('href');
- el.setAttribute('aria-disabled', 'true');
+ const el = document.getElementById(id);
+ if (!el) return;
+ el.removeAttribute('href');
+ el.setAttribute('aria-disabled', 'true');
}
function renderMembersTable(members) {
- const tbody = document.getElementById('members-tbody');
- if (!tbody) return;
-
- const frag = document.createDocumentFragment();
- for (const m of members) {
- const tr = document.createElement('tr');
-
- const nameTd = document.createElement('td');
- nameTd.textContent = m.name;
-
- const linkTd = document.createElement('td');
- const a = document.createElement('a');
- a.href = m.url;
- a.textContent = m.url + warningLabel(m);
- a.addEventListener('click', e => confirmIfFlagged(e, m));
- linkTd.appendChild(a);
-
- tr.append(nameTd, linkTd);
- frag.appendChild(tr);
- }
- tbody.appendChild(frag);
+ const tbody = document.getElementById('members-tbody');
+ if (!tbody) return;
+
+ const frag = document.createDocumentFragment();
+ for (const m of members) {
+ const tr = document.createElement('tr');
+
+ const nameTd = document.createElement('td');
+ nameTd.textContent = m.name;
+
+ const linkTd = document.createElement('td');
+ const a = document.createElement('a');
+ a.href = m.url;
+ a.textContent = m.url + warningLabel(m);
+ a.addEventListener('click', e => confirmIfFlagged(e, m));
+ linkTd.appendChild(a);
+
+ tr.append(nameTd, linkTd);
+ frag.appendChild(tr);
+ }
+ tbody.appendChild(frag);
}
async function initRing() {
- try {
- const members = await fetchRingMembers();
- const me = members.findIndex(m => originOf(m) === location.origin);
-
- if (me === -1) {
- console.error('this site is not in the tarantino webring');
- } else if (members.length <= 1) {
- disableNavLink('ring-prev');
- disableNavLink('ring-next');
- disableNavLink('ring-random');
- } else {
- const next = members[(me + 1) % members.length];
- const prev = members[(me - 1 + members.length) % members.length];
- const others = members.filter((_, i) => i !== me);
-
- wireNavLink('ring-prev', prev);
- wireNavLink('ring-next', next);
-
- if (others.length > 0) {
- const random = others[Math.floor(Math.random() * others.length)];
- wireNavLink('ring-random', random);
- } else {
- disableNavLink('ring-random');
- }
+ try {
+ const members = await fetchRingMembers();
+ const me = members.findIndex(m => originOf(m) === location.origin);
+
+ if (me === -1) {
+ console.error('this site is not in the tarantino webring');
+ } else if (members.length <= 1) {
+ disableNavLink('ring-prev');
+ disableNavLink('ring-next');
+ disableNavLink('ring-random');
+ } else {
+ const next = members[(me + 1) % members.length];
+ const prev = members[(me - 1 + members.length) % members.length];
+ const others = members.filter((_, i) => i !== me);
+
+ wireNavLink('ring-prev', prev);
+ wireNavLink('ring-next', next);
+
+ if (others.length > 0) {
+ const random = others[Math.floor(Math.random() * others.length)];
+ wireNavLink('ring-random', random);
+ } else {
+ disableNavLink('ring-random');
+ }
+ }
+
+ renderMembersTable(members);
+ } catch (err) {
+ console.error('tarantino webring failed:', err);
}
-
- renderMembersTable(members);
- } catch (err) {
- console.error('tarantino webring failed:', err);
- }
}
initRing();