Skip to content

Commit 6174dc7

Browse files
committed
UI utils
1 parent c838a10 commit 6174dc7

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

lib/ui-utils.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
3+
*/
4+
import { el } from "./utils.js";
5+
6+
function exportButton(fileName) {
7+
const button = el('button',
8+
{
9+
style: 'z-index: 1000; position: fixed; top: 1rem; right: 1rem; padding: 0.5rem 1.5rem; background-color: #0152a9; color: white; border: none; border-radius: 0.5rem; cursor: pointer; font-size: 1.1rem;'
10+
},
11+
'Save snapshot'
12+
);
13+
button.addEventListener('click', () => {
14+
button.remove(); // remove button before saving
15+
const html = '<!DOCTYPE html>\n' + document.documentElement.outerHTML;
16+
document.body.append(button); // re-add button after getting HTML
17+
const blob = new Blob([html], { type: 'text/html;charset=utf-8' });
18+
const url = URL.createObjectURL(blob);
19+
const a = el('a', { href: url, download: fileName });
20+
a.click();
21+
URL.revokeObjectURL(url);
22+
});
23+
24+
document.body.append(button);
25+
}
26+
27+
/**
28+
* Add a "Save snapshot" button that saves the current document as an HTML file.
29+
*
30+
* Thanks to https://github.com/sideshowbarker
31+
* https://lists.w3.org/Archives/Team/team-project/2026Jan/0007.html
32+
*
33+
* @param {String} fileName The name of the file to save, e.g. "snapshot.html"
34+
* @returns {void}
35+
* @example
36+
* import { addExportButton } from "https://w3.org/PM/Groups/lib/ui-utils.js";
37+
* // when you're ready to add the button, use
38+
* addExportButton("filename");
39+
*/
40+
export
41+
function addExportButton(fileName) {
42+
if (document.readyState === 'loading') {
43+
document.addEventListener('DOMContentLoaded', () => exportButton(fileName));
44+
} else {
45+
exportButton(fileName);
46+
}
47+
}
48+
49+
50+
let promiseLogger = null;
51+
52+
function logElement() {
53+
// I prefer Promises over callbacks!
54+
return new Promise((resolve, reject) => {
55+
function presolve() {
56+
let logElement = document.getElementById('log');
57+
if (!logElement) {
58+
logElement = el('pre', { id: 'log', style: 'position: fixed; bottom: 0; left: 0; width: 100%; max-height: 30%; overflow: auto; background-color: rgba(0,0,0,0.8); color: white; font-size: 0.8rem; padding: 0.5rem; z-index: 1000;' });
59+
document.body.append(logElement);
60+
}
61+
resolve(logElement);
62+
}
63+
if (document.readyState === 'loading') {
64+
document.addEventListener('DOMContentLoaded', presolve);
65+
} else {
66+
presolve();
67+
}
68+
});
69+
}
70+
71+
/**
72+
* A simple logger function that logs to a fixed log element at the bottom of the page.
73+
*
74+
* @returns Function<...any> The log function
75+
* @example
76+
* import { logger } from "https://w3.org/PM/Groups/lib/ui-utils.js";
77+
* const log = (config.debug) ? logger() : () => {};
78+
* log("This is a log message", someObject, new Error("Something went wrong"));
79+
*/
80+
export
81+
function logger() {
82+
function convert(arg) {
83+
const type = (arg && arg.name)? arg.name: Object.prototype?.toString.call(arg).slice(8, -1);
84+
switch (type) {
85+
case "Date":
86+
return `${type}: ${arg.toISOString()}`;
87+
break;
88+
case "HttpError":
89+
return `${type} ${arg.status}: ${arg.statusText} -- ${arg.url}`;
90+
break;
91+
case "Error":
92+
return type + ": " + ((arg.cause) ? arg.cause.message : arg.message);
93+
break;
94+
case "TypeError":
95+
return `${type}: ${arg.message}`;
96+
break;
97+
case "CacheError":
98+
return `${type}: ${arg.message} ${(arg.cause) ? ' -- Cause: ' + arg.cause.message : ''}`;
99+
break;
100+
case "Object":
101+
return JSON.stringify(arg, null, 2);
102+
break;
103+
default:
104+
// fall through
105+
break;
106+
}
107+
return arg;
108+
}
109+
return function (...args) {
110+
args = args.map(arg => convert(arg));
111+
if (!promiseLogger) {
112+
promiseLogger = logElement();
113+
}
114+
promiseLogger = promiseLogger.then(logElement => {
115+
logElement.appendChild(document.createTextNode(args.join(" ") + "\n"));
116+
logElement.scrollTo(0, 1000);
117+
});
118+
}
119+
}

0 commit comments

Comments
 (0)