1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
/*
This file is part of jshelper (https://codeberg.org/metamuffin/jshelper)
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2023 metamuffin <metamuffin.org>
*/
import { OVar } from "./observable.ts";
interface Opts<E> {
class?: string[] | string,
id?: string,
src?: string,
for?: string,
type?: string,
href?: string,
onclick?: (e: E) => void,
onchange?: (e: E) => void,
}
function apply_opts<E extends HTMLElement>(e: E, o: Opts<E>): (() => unknown) | void {
if (o.id) e.id = o.id
if (o.for) (e as unknown as HTMLLabelElement).htmlFor = o.for
if (o.type && e instanceof HTMLInputElement) e.type = o.type
if (o.href && e instanceof HTMLAnchorElement) e.href = o.href;
if (o.onclick) e.addEventListener("click", () => o.onclick!(e))
if (o.onchange) e.addEventListener("change", () => o.onchange!(e))
if (typeof o?.class == "string") e.classList.add(o.class)
if (typeof o?.class == "object") e.classList.add(...o.class)
}
type EEl<K extends keyof HTMLElementTagNameMap> = string
| HTMLElement
| Opts<HTMLElementTagNameMap[K]>
| OVar<Opts<HTMLElementTagNameMap[K]>>
| OVar<string>
| OVar<HTMLElement>
| OVar<HTMLUListElement> // is this possible with dudplication?
| OVar<HTMLOListElement>
| OVar<HTMLInputElement>
| OVar<HTMLPreElement>
| OVar<HTMLCanvasElement>
| OVar<HTMLVideoElement>
| OVar<HTMLImageElement>
| OVar<HTMLDetailsElement>
| OVar<HTMLSpanElement>
| OVar<HTMLSelectElement>
| OVar<HTMLLabelElement>
| OVar<HTMLButtonElement>
| OVar<HTMLDivElement>
| OVar<HTMLParagraphElement>
| undefined;
export function e<K extends keyof HTMLElementTagNameMap>(name: K, ...children: EEl<K>[]): HTMLElementTagNameMap[K] {
const el = document.createElement(name)
for (const c of children) e_apply(el, c)
return el
}
function e_apply<K extends keyof HTMLElementTagNameMap, C extends EEl<K>>(el: HTMLElementTagNameMap[K], c: C): () => unknown {
if (typeof c == "undefined") {
return () => { }
}
if (typeof c == "string") {
el.append(c)
return () => {
el.textContent = ""
}
}
else if (c instanceof HTMLElement) {
el.append(c)
return () => el.removeChild(c)
}
else if (c instanceof OVar) {
let undo_last: () => unknown;
return c.onchangeinit(val => {
if (undo_last) undo_last()
undo_last = e_apply(el, val)
})
}
else return apply_opts(el, c) ?? (() => { })
}
|