Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion timeline/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -987,11 +987,28 @@ <h2 data-de="Wie man es liest">How to read it</h2>
// began while a role ran still did. The selection is state, not a place: remembered in
// the browser like the card's width, never written into the address — and a link to a
// row of a kind that is off turns that kind back on, because a link must land.
//
// A link can still set it. ?kinds= names the kinds to show, by name and in any case,
// comma-separated: those are on and the rest off, and the page reads it the way it reads
// ?lang= — once, on arrival, then strips it from the address and remembers the selection
// as if the menu had been used, so the link hands the visitor a view and nothing they
// copy afterwards carries it. A name the model does not know is dropped, and a list naming
// no kind at all is ignored whole rather than emptying the ledger.
var KINDS = data.entities.filter(function(e){ return e.type === "experience-kind"; })
.sort(function(a, b){ return a.name.localeCompare(b.name, "en"); });
var KIND_KEY = "timeline-kinds", on = {};
KINDS.forEach(function(k){ on[k.name] = true; });
try { var saved = JSON.parse(localStorage.getItem(KIND_KEY) || "null"); if (saved) KINDS.forEach(function(k){ if (k.name in saved) on[k.name] = !!saved[k.name]; }); } catch (e) {}
var linked = /[?&]kinds=([^&#]*)(&|$)/.exec(location.search), linkedKinds = null;
if (linked) {
var named = decodeURIComponent(linked[1]).toLowerCase().split(",");
var known = KINDS.filter(function(k){ return named.indexOf(k.name.toLowerCase()) >= 0; });
if (known.length) { linkedKinds = {}; KINDS.forEach(function(k){ linkedKinds[k.name] = known.indexOf(k) >= 0; }); }
try {
var q = location.search.replace(/([?&])kinds=[^&#]*(&|$)/, "$1").replace(/[?&]$/, "");
history.replaceState(null, "", location.pathname + q + location.hash);
} catch (e) {}
}
var kinds = document.getElementById("kinds"), kindsLabel = document.getElementById("kindslabel"), kindsMenu = document.getElementById("kindsmenu");
var none = h("li", null, "none"); none.hidden = true; ol.appendChild(none);
var boxes = [];
Expand Down Expand Up @@ -1087,7 +1104,7 @@ <h2 data-de="Wie man es liest">How to read it</h2>
window.addEventListener("hashchange", arrive);
new MutationObserver(render).observe(document.documentElement, { attributes: true, attributeFilter: ["lang"] });

applyKinds();
if (linkedKinds) { on = linkedKinds; applyKinds(true); } else applyKinds();
arrive();
}

Expand Down
2 changes: 1 addition & 1 deletion timeline/og.sha
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4e61cc3847555fee53e2bee1397ed745291be6cddfabbc66b882562466fbc59a
c82190396ef09ea5f16cd25f466022be5b674e4828d9e1e9172acee71c1c1f10
22 changes: 21 additions & 1 deletion verify/check.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,27 @@ const CHECKS = {
await page.goto(BASE + spec.path + "#" + target);
const opened = await page.evaluate((id) => document.getElementById(id).open, target);
if (!opened) return `arriving at #${target} did not open that row`;
// Leave the page as it was found — at rest, no row open — for whatever check runs next.
// Arriving with ?kinds= sets the selection from the address: the kinds named are on and
// the rest off, the parameter leaves the address the way ?lang= does, and the selection
// is remembered as if the menu had been used. A name the model does not know is ignored,
// and a list naming no kind at all is ignored whole.
await page.goto(BASE + spec.path + "?kinds=" + kindOff.toLowerCase() + ",nosuchkind");
const linked = await page.evaluate((kind) => ({
hidden: [...document.querySelectorAll("#ledger li.k-" + kind.toLowerCase())].filter(li => li.hidden).length,
others: [...document.querySelectorAll("#ledger li:has(details)")].filter(li => !li.classList.contains("k-" + kind.toLowerCase()) && !li.hidden).length,
label: document.getElementById("kindslabel").textContent, search: location.search,
stored: (() => { try { return JSON.parse(localStorage.getItem("timeline-kinds")); } catch (e) { return null; } })() }), kindOff);
if (linked.hidden) return `?kinds=${kindOff} hid ${linked.hidden} rows of that kind`;
if (linked.others) return `?kinds=${kindOff} left ${linked.others} rows of other kinds showing`;
if (linked.label !== kindOff) return `with ?kinds=${kindOff} the filter reads ${JSON.stringify(linked.label)}`;
if (linked.search) return `the address still carries ${linked.search}`;
if (!linked.stored || linked.stored[kindOff] !== true || Object.keys(linked.stored).some(k => k !== kindOff && linked.stored[k])) return `?kinds=${kindOff} was not remembered: ${JSON.stringify(linked.stored)}`;
await page.goto(BASE + spec.path + "?kinds=nosuchkind");
const ignored = await page.evaluate(() => ({ hidden: [...document.querySelectorAll("#ledger li:has(details)")].filter(li => li.hidden).length, label: document.getElementById("kindslabel").textContent }));
if (ignored.label !== kindOff) return `?kinds naming no kind changed the selection to ${JSON.stringify(ignored.label)}`;
// Leave the page as it was found — at rest, every kind on, no row open — for whatever
// check runs next.
await page.evaluate(() => { try { localStorage.removeItem("timeline-kinds"); } catch (e) {} });
await page.goto(BASE + spec.path);
return null;
},
Expand Down