Blog/wwwroot/common.module.js 3 K · 146 lines · raw · history

1 function getById(id) {
2 let element = document.getElementById(id);
3 if (element) {
4 return element;
5 } else {
6 throw `Element with id '${id}' not found.`;
7 }
8 }
9
10 /**
11 * @param {string} href
12 * @returns {HTMLAnchorElement}
13 */
14 function a(href, pageName) {
15 const aElem = document.createElement("a");
16 aElem.href = href;
17 aElem.text = pageName;
18 return aElem;
19 }
20
21 function div(...children) {
22 const divElem = document.createElement("div");
23 divElem.replaceChildren(...children);
24 return divElem;
25 }
26
27 function span(text) {
28 const spanElem = document.createElement("span");
29 spanElem.textContent = text;
30 return spanElem;
31 }
32
33 function h(elementTag, ...children) {
34 const elem = document.createElement(elementTag);
35 elem.replaceChildren(...children);
36 return elem;
37 }
38
39 /** @param {HTMLElement} element */
40 function addClass(element, newClass) {
41 element.classList.add(newClass);
42 return element;
43 }
44
45 function writeError(error) {
46 writeLog(error, "error");
47 }
48
49 function writeInfo(msg) {
50 writeLog(msg, "info");
51 }
52
53 function writeDebug(msg) {
54 writeLog(msg, "debug");
55 }
56
57 function writeLog(msg, className) {
58 if (typeof msg === "string" || msg instanceof String) {
59 log.appendChild(div(addClass(span(msg), className)));
60 } else {
61 log.appendChild(div(addClass(msg, className)));
62 }
63 }
64
65 function resetLog() {
66 log.replaceChildren();
67 }
68
69 const log = getById("log");
70
71 // https://stackoverflow.com/questions/75988682/debounce-in-javascript
72 // https://www.joshwcomeau.com/snippets/javascript/debounce/
73 function debounce(callback, wait) {
74 let timeoutId = null;
75 return (...args) => {
76 window.clearTimeout(timeoutId);
77 timeoutId = window.setTimeout(() => {
78 callback(...args);
79 }, wait);
80 };
81 }
82
83 const stylesheet = new CSSStyleSheet();
84 stylesheet.replaceSync(`
85 a {
86 color: var(--color);
87 }
88 nav > ul {
89 list-style-type: none;
90 padding-inline-start: 0;
91 }
92
93 nav > ul > li {
94 display: inline-block;
95 }
96
97 nav > ul > li > a::after {
98 display: inline-block;
99 color: var(--color);
100 content: ">";
101 padding: 0 1em;
102 }
103 `);
104
105 customElements.define("mb-nav",
106 class MBNav extends HTMLElement {
107 constructor() {
108 super();
109 }
110
111 get pagename() {
112 return this.getAttribute("pagename");
113 }
114
115 set pagename(value) {
116 this.setAttribute("pagename", value);
117 }
118
119 connectedCallback() {
120 const shadow = this.attachShadow({ mode: "open" });
121 shadow.adoptedStyleSheets = [stylesheet];
122
123 shadow.appendChild(
124 h("nav",
125 h("ul",
126 h("li", a("/", "MB.bes.is")),
127 h("li", span(this.pagename)),
128 )
129 )
130 )
131 }
132 });
133
134 export {
135 getById,
136 a,
137 div,
138 span,
139 h,
140 addClass,
141 writeError,
142 writeInfo,
143 writeDebug,
144 resetLog,
145 debounce,
146 };