summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/main.ts71
-rw-r--r--js/navigation.ts97
-rw-r--r--js/page.ts104
-rw-r--r--js/theme.ts11
4 files changed, 58 insertions, 225 deletions
diff --git a/js/main.ts b/js/main.ts
index 3c3b25b..a3d33c7 100644
--- a/js/main.ts
+++ b/js/main.ts
@@ -1,31 +1,66 @@
-/// <reference path="navigation.ts" />
-/// <reference path="page.ts" />
/// <reference path="theme.ts" />
namespace Ach {
- export async function init() {
+ export async function init(): Promise<void> {
Ach.loadTheme();
- Ach.initImages();
- Ach.initLinks();
-
- window.addEventListener("popstate", (_e) => {
- location.reload();
- });
- }
-
- export function currentPage() {
- let body = Ach.getFirstElement(document, "body");
- let page = body.getAttribute("data-page");
+ let glyph = Ach.getOnlyElementIn(document, "glyph");
+ let page = glyph.getAttribute("alt");
if (!page) {
- throw new Error("body does not specify page");
+ throw new Error('glyph does not specify page in "alt" attribute');
}
- return page;
+ let portrait = matchMedia("(orientation: portrait)");
+ let reducedMotion = matchMedia("(prefers-reduced-motion)");
+
+ let updateDynamicGlyph = (): void => {
+ console.log("updating dynamic glyph");
+ console.log(`note: configuration is { page: "${page}", portrait: ${portrait.matches}, reducedMotion: ${reducedMotion.matches} }`);
+
+ let newGlyphAddr: string | undefined = undefined;
+ switch (page) {
+ case "achernar":
+ switch (true) {
+ case portrait.matches && reducedMotion.matches:
+ newGlyphAddr = "/svg/glyph/achernarVertical.svg";
+ break;
+
+ case portrait.matches && !reducedMotion.matches:
+ newGlyphAddr = "/image/achernarVerticalAnimated.webp";
+ break;
+
+ case !portrait.matches && reducedMotion.matches:
+ newGlyphAddr = "/svg/glyph/achernar.svg";
+ break;
+
+ case !portrait.matches && !reducedMotion.matches:
+ newGlyphAddr = "/image/achernarAnimated.webp";
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (newGlyphAddr) {
+ console.log(`note: new glyph is at "${newGlyphAddr}"`);
+
+ glyph.setAttribute("src", newGlyphAddr);
+ } else {
+ console.log("note: no new glyph was found suitable");
+ }
+ };
+
+ updateDynamicGlyph();
+
+ portrait .addEventListener("change", updateDynamicGlyph);
+ reducedMotion.addEventListener("change", updateDynamicGlyph);
}
- export function getFirstElement(dom: Document, tag: string): Element {
+ export function getFirstElementIn(dom: Document, tag: string): Element {
let elements = dom.getElementsByTagName(tag);
if (elements.length < 0x0) {
@@ -35,7 +70,7 @@ namespace Ach {
return elements[0x0];
}
- export function getOnlyElement(dom: Document, id: string): Element {
+ export function getOnlyElementIn(dom: Document, id: string): Element {
let element = dom.getElementById(id);
if (!element) {
diff --git a/js/navigation.ts b/js/navigation.ts
deleted file mode 100644
index c1af99f..0000000
--- a/js/navigation.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-namespace Ach {
- export async function loadPage(page_name: string, anchor?: string) {
- console.log(`loading page \`${page_name}\``);
-
- window.scrollTo({
- top: 0.0,
- left: undefined,
- behavior: "smooth",
- });
-
- let url = `/html/${page_name}.html`;
- console.log(`note: page is at "${url}"`);
-
- window.history.pushState(page_name, "", url);
-
- let response = await fetch(url);
-
- if (!response.ok) {
- throw new Error(`unable to load page: \"${response.status}\"`);
- }
-
- let markup = await response.text();
-
- let parser = new DOMParser();
- let dom = parser.parseFromString(markup, "text/html");
-
- let body = Ach.getFirstElement(document, "body");
-
- let title = Ach.getFirstElement(document, "title");
- let page = Ach.getOnlyElement(document, "page");
-
- let newTitle = Ach.getFirstElement(dom, "title");
- let newPage = Ach.getOnlyElement(dom, "page");
-
- title.replaceWith(newTitle);
- body.setAttribute("data-page", page_name);
- page.replaceWith(newPage);
-
- initImages();
- initLinks();
-
- if (anchor) {
- console.log(`going to anchor \`${anchor}\``);
-
- anchor = `anchor.${anchor}`;
-
- console.log(`note: anchor has id "${anchor}"`);
-
- let anchor_element = document.getElementById(anchor);
-
- if (!anchor_element) {
- throw new Error(`unable to find anchor "${anchor}"`);
- }
-
- anchor_element.scrollIntoView({
- behavior: "smooth",
- });
- }
- }
-
- export function toggleSideMenu() {
- window.scrollTo({
- top: 0.0,
- left: undefined,
- behavior: "smooth",
- });
-
- let sideMenu = Ach.getOnlyElement(document, "sideMenu");
- let navBar = Ach.getOnlyElement(document, "navBar");
- let glyph = Ach.getOnlyElement(document, "glyph");
-
- sideMenu.classList.toggle("visible");
- glyph.classList.toggle("hidden");
-
- for (let link of navBar.getElementsByTagName("a")) {
- link.classList.toggle("hidden");
- }
- }
-
- export function parseInternalLink(address: string): [string, string | undefined] | undefined {
- let regex = /\/html\/([A-Za-z0-9]+)\.html(?:#([A-Za-z0-9]+)){0,1}/;
- let regex_result = regex.exec(address);
-
- if (!regex_result) {
- return;
- }
-
- let page = regex_result[0x1];
- let anchor = regex_result[0x2];
-
- if (!page) {
- return;
- }
-
- return [page, anchor];
- }
-}
diff --git a/js/page.ts b/js/page.ts
deleted file mode 100644
index c4f0d71..0000000
--- a/js/page.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-namespace Ach {
- export async function initImages() {
- let page = Ach.getOnlyElement(document, "page");
-
- let imageList = Array.from(page.getElementsByTagName("x-image"));
-
- for (let image of imageList) {
- let alt = image.getAttribute("alt");
- let file = image.getAttribute("data-file");
-
- if (!alt) {
- alert("stupid superuser forgot to add image caption, please notify");
- alt = "";
- }
-
- if (!file) {
- throw new Error("file not set for image element");
- }
-
- console.log("initialising image that links to \"" + file + "\"");
-
- let sourceUrl = "/image/source/" + file + ".webp";
- let thumbnailUrl = "/image/thumbnail/" + file + ".avif";
-
- let blurElement = document.createElement("img");
- blurElement.setAttribute("class", "blur");
- blurElement.setAttribute("src", thumbnailUrl);
-
- let hyperlinkElement = document.createElement("a");
- hyperlinkElement.setAttribute("href", sourceUrl);
- hyperlinkElement.setAttribute("rel", "noopener noreferrer");
- hyperlinkElement.setAttribute("target", "_blank");
- hyperlinkElement.setAttribute("title", "Click to view image source.");
-
- let image_element = document.createElement("img");
- image_element.setAttribute("alt", alt);
- image_element.setAttribute("src", thumbnailUrl);
-
- hyperlinkElement.appendChild(image_element);
-
- image.appendChild(blurElement);
- image.appendChild(hyperlinkElement);
- }
- }
-
- export async function initLinks() {
- console.log("initialising links");
-
- let stats = {
- total: 0x0,
- overrideCount: 0x0,
- currentCount: 0x0,
- };
-
- for (let link of document.getElementsByTagName("a")) {
- ++stats.total;
-
- let address = link.getAttribute("href");
-
- if (!address) {
- console.log("note: skipping override of empty link");
- continue;
- }
-
- let pageAnchor = Ach.parseInternalLink(address);
-
- if (!pageAnchor) {
- console.log(`note: skipping override of link to "${address}"`);
- continue;
- }
-
- console.log(`note: overriding link to "${address}"`);
- ++stats.overrideCount;
-
- let command = `Ach.loadPage(${JSON.stringify(pageAnchor[0x0])}, ${JSON.stringify(pageAnchor[0x1])})`
-
- link.removeAttribute("href");
- link.setAttribute("data-page", pageAnchor[0x0]);
- link.setAttribute("onclick", command);
-
- if (pageAnchor[0x1]) {
- link.setAttribute("data-anchor", pageAnchor[0x1]);
- }
- }
-
- let currentPage = Ach.currentPage();
-
- for (let link of document.getElementsByTagName("a")) {
- let page = link.getAttribute("data-page");
- let anchor = link.getAttribute("data-anchor");
-
- if (page == currentPage && !anchor) {
- ++stats.currentCount;
- link.setAttribute("aria-current", "page");
- } else {
- link.setAttribute("aria-current", "false");
- }
- }
-
- console.log(`note: initialised (${stats.total}) links`);
- console.log(`note: of which (${stats.overrideCount}) overrides were done`);
- console.log(`note: and of which (${stats.currentCount}) were marked as current`);
- }
-}
diff --git a/js/theme.ts b/js/theme.ts
index 45101da..611f225 100644
--- a/js/theme.ts
+++ b/js/theme.ts
@@ -1,9 +1,8 @@
namespace Ach {
- export function toggleTheme() {
- let body = Ach.getFirstElement(document, "body");
+ export function toggleTheme(): void {
+ let body = Ach.getFirstElementIn(document, "body");
let theme = "light";
-
if (body.classList.contains("light")) {
theme = "dark";
}
@@ -14,7 +13,7 @@ namespace Ach {
sessionStorage.setItem("theme", theme);
}
- export function loadTheme() {
+ export function loadTheme(): void {
let theme = sessionStorage.getItem("theme");
if (!theme) {
@@ -24,11 +23,11 @@ namespace Ach {
switch (theme) {
case "dark":
- // We assume this theme in our stylesheets.
+ // We already assume this theme in our stylesheets.
break;
case "light":
- let body = Ach.getFirstElement(document, "body");
+ let body = Ach.getFirstElementIn(document, "body");
body.classList.add("light");
break;