46 lines
1.4 KiB
JavaScript
46 lines
1.4 KiB
JavaScript
/**
|
|
* Tiny DOM helpers — enough structure to avoid a framework without the
|
|
* ergonomics falling apart.
|
|
*
|
|
* el('div', { class: 'card', onclick: fn }, 'text', childNode)
|
|
*/
|
|
export function el(tag, props = {}, ...children) {
|
|
const node = document.createElement(tag);
|
|
for (const [key, value] of Object.entries(props || {})) {
|
|
if (value == null || value === false) continue;
|
|
if (key === 'class') node.className = value;
|
|
else if (key === 'dataset') Object.assign(node.dataset, value);
|
|
else if (key === 'html') node.innerHTML = value;
|
|
else if (key.startsWith('on') && typeof value === 'function') {
|
|
node.addEventListener(key.slice(2).toLowerCase(), value);
|
|
} else if (key in node) {
|
|
try {
|
|
node[key] = value;
|
|
} catch {
|
|
node.setAttribute(key, value);
|
|
}
|
|
} else {
|
|
node.setAttribute(key, value);
|
|
}
|
|
}
|
|
append(node, children);
|
|
return node;
|
|
}
|
|
|
|
export function append(node, children) {
|
|
for (const child of children.flat(Infinity)) {
|
|
if (child == null || child === false) continue;
|
|
node.append(child.nodeType ? child : document.createTextNode(String(child)));
|
|
}
|
|
}
|
|
|
|
export function clear(node) {
|
|
node.replaceChildren();
|
|
return node;
|
|
}
|
|
|
|
/** Run a cleanup fn when the view node is torn down by the router. */
|
|
export function onTeardown(viewNode, fn) {
|
|
viewNode.addEventListener('view:teardown', fn, { once: true });
|
|
}
|