137 lines
4.3 KiB
JavaScript
137 lines
4.3 KiB
JavaScript
import h from "hyperscript";
|
|
import "normalize.css/normalize.css";
|
|
import "milligram/dist/milligram.css";
|
|
import "../css/common.css";
|
|
import "../css/nav.css";
|
|
|
|
|
|
/**
|
|
* Alias for `document.querySelector`.
|
|
*
|
|
* @param q {string} the query string
|
|
* @returns {HTMLElement} the element identified by the query string
|
|
*/
|
|
export const $ = q => document.querySelector(q);
|
|
|
|
/**
|
|
* Runs the given function once the page is loaded.
|
|
*
|
|
* This function can be used multiple times. It does not overwrite existing callbacks for the page load event.
|
|
*
|
|
* @param fun {function(...*): *} the function to run
|
|
*/
|
|
export const doAfterLoad = function (fun) {
|
|
const oldOnLoad = window.onload || (() => {
|
|
});
|
|
|
|
window.onload = (() => {
|
|
oldOnLoad();
|
|
fun();
|
|
});
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates a navigation element for navigating through the website.
|
|
*
|
|
* Fetches entries asynchronously from the website's API.
|
|
*
|
|
* @returns {HTMLElement} a base navigation element that will eventually be filled with contents
|
|
*/
|
|
export const nav = function () {
|
|
const base = h("ul",
|
|
h("li", h("a", {href: "https://fwdekker.com/"},
|
|
h("div.logo", h("img.logo", {src: "https://fwdekker.com/favicon.png"})),
|
|
h("b", "FWDekker")
|
|
))
|
|
);
|
|
|
|
fetch("https://fwdekker.com/api/nav/")
|
|
.then(it => it.json())
|
|
.then(json => json.entries.forEach(entry => base.appendChild(unpackEntry(entry))))
|
|
.catch(e => {
|
|
console.error("Failed to fetch navigation elements", e);
|
|
return [];
|
|
});
|
|
|
|
return h("nav.nav", base);
|
|
};
|
|
|
|
/**
|
|
* Unpacks a navigation entry returned from the navigation API into an HTML element.
|
|
*
|
|
* @param entry {Object} the entry to unpack
|
|
* @returns {HTMLElement} the navigation list entry as HTML, described by its children
|
|
*/
|
|
const unpackEntry = function (entry) {
|
|
if (entry.entries.length === 0)
|
|
return h("li", h("a", {href: entry.link, innerHTML: entry.name}));
|
|
|
|
return h("li",
|
|
h("a", {href: entry.link, innerHTML: `${entry.name} ▾`}),
|
|
h("ul", entry.entries.map(it => unpackEntry(it)))
|
|
);
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates a header element with the given title and description.
|
|
*
|
|
* @param [title] {string} the title to display, possibly including HTML
|
|
* @param [description] {string} the description to display, possibly including HTML
|
|
* @returns {HTMLElement} a header element
|
|
*/
|
|
export const header = function ({title, description}) {
|
|
return h("header.header",
|
|
h("section.container",
|
|
title !== undefined ? h("h1", {innerHTML: title}) : undefined,
|
|
description !== undefined ? h("p", h("em", {innerHTML: description})) : undefined
|
|
)
|
|
);
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates a footer element with the given data.
|
|
*
|
|
* @param [author] {string} the author
|
|
* @param [authorURL] {string} the URL to link the author's name to
|
|
* @param [license] {string} the type of license
|
|
* @param [licenseURL] {string} the URL to the license file
|
|
* @param [vcs] {string} the type of version control
|
|
* @param [vcsURL] {string} the URL to the repository
|
|
* @param [version] {string} the page version
|
|
* @returns {HTMLElement} a footer element
|
|
*/
|
|
export const footer = function ({author, authorURL, license, licenseURL, vcs, vcsURL, version}) {
|
|
return h("footer.footer",
|
|
h("section.container",
|
|
footerLink("Made by ", author, authorURL, ". "),
|
|
footerLink("Licensed under the ", license, licenseURL, ". "),
|
|
footerLink("Source code available on ", vcs, vcsURL, ". "),
|
|
h("div", version || "", {style: {"float": "right"}})
|
|
)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Constructs a link that is used in footers.
|
|
*
|
|
* @param prefix {string} the text to display before the text if the text is not undefined
|
|
* @param text {string|undefined} the text to display, or `undefined` if the returned element should be empty
|
|
* @param url {string|undefined} the URL to link the text to, or `undefined` if the text should not be a link
|
|
* @param suffix {string} the text to display after the text if the text is not undefined
|
|
* @returns {HTMLElement} a footer link element
|
|
*/
|
|
const footerLink = function (prefix, text, url, suffix) {
|
|
if (text === undefined) return h("span");
|
|
|
|
return h("span",
|
|
h("span", prefix),
|
|
url !== undefined
|
|
? h("a", text, {href: url})
|
|
: h("span", text),
|
|
h("span", suffix)
|
|
);
|
|
};
|