1//@ts-check
2// Helpers to work with html elements
3// by Humans for All
4//
5
6
7/**
8 * Set the class of the children, based on whether it is the idSelected or not.
9 * @param {HTMLDivElement} elBase
10 * @param {string} idSelected
11 * @param {string} classSelected
12 * @param {string} classUnSelected
13 */
14export function el_children_config_class(elBase, idSelected, classSelected, classUnSelected="") {
15 for(let child of elBase.children) {
16 if (child.id == idSelected) {
17 child.className = classSelected;
18 } else {
19 child.className = classUnSelected;
20 }
21 }
22}
23
24/**
25 * Create button and set it up.
26 * @param {string} id
27 * @param {(this: HTMLButtonElement, ev: MouseEvent) => any} callback
28 * @param {string | undefined} name
29 * @param {string | undefined} innerText
30 */
31export function el_create_button(id, callback, name=undefined, innerText=undefined) {
32 if (!name) {
33 name = id;
34 }
35 if (!innerText) {
36 innerText = id;
37 }
38 let btn = document.createElement("button");
39 btn.id = id;
40 btn.name = name;
41 btn.innerText = innerText;
42 btn.addEventListener("click", callback);
43 return btn;
44}
45
46/**
47 * Create a para and set it up. Optionaly append it to a passed parent.
48 * @param {string} text
49 * @param {HTMLElement | undefined} elParent
50 * @param {string | undefined} id
51 */
52export function el_create_append_p(text, elParent=undefined, id=undefined) {
53 let para = document.createElement("p");
54 para.innerText = text;
55 if (id) {
56 para.id = id;
57 }
58 if (elParent) {
59 elParent.appendChild(para);
60 }
61 return para;
62}
63
64/**
65 * Create a button which represents bool value using specified text wrt true and false.
66 * When ever user clicks the button, it will toggle the value and update the shown text.
67 *
68 * @param {string} id
69 * @param {{true: string, false: string}} texts
70 * @param {boolean} defaultValue
71 * @param {function(boolean):void} cb
72 */
73export function el_create_boolbutton(id, texts, defaultValue, cb) {
74 let el = document.createElement("button");
75 el["xbool"] = defaultValue;
76 el["xtexts"] = structuredClone(texts);
77 el.innerText = el["xtexts"][String(defaultValue)];
78 if (id) {
79 el.id = id;
80 }
81 el.addEventListener('click', (ev)=>{
82 el["xbool"] = !el["xbool"];
83 el.innerText = el["xtexts"][String(el["xbool"])];
84 cb(el["xbool"]);
85 })
86 return el;
87}
88
89/**
90 * Create a div wrapped button which represents bool value using specified text wrt true and false.
91 * @param {string} id
92 * @param {string} label
93 * @param {{ true: string; false: string; }} texts
94 * @param {boolean} defaultValue
95 * @param {(arg0: boolean) => void} cb
96 * @param {string} className
97 */
98export function el_creatediv_boolbutton(id, label, texts, defaultValue, cb, className="gridx2") {
99 let div = document.createElement("div");
100 div.className = className;
101 let lbl = document.createElement("label");
102 lbl.setAttribute("for", id);
103 lbl.innerText = label;
104 div.appendChild(lbl);
105 let btn = el_create_boolbutton(id, texts, defaultValue, cb);
106 div.appendChild(btn);
107 return { div: div, el: btn };
108}
109
110
111/**
112 * Create a select ui element, with a set of options to select from.
113 * * options: an object which contains name-value pairs
114 * * defaultOption: the value whose name should be choosen, by default.
115 * * cb : the call back returns the name string of the option selected.
116 *
117 * @param {string} id
118 * @param {Object<string,*>} options
119 * @param {*} defaultOption
120 * @param {function(string):void} cb
121 */
122export function el_create_select(id, options, defaultOption, cb) {
123 let el = document.createElement("select");
124 el["xselected"] = defaultOption;
125 el["xoptions"] = structuredClone(options);
126 for(let cur of Object.keys(options)) {
127 let op = document.createElement("option");
128 op.value = cur;
129 op.innerText = cur;
130 if (options[cur] == defaultOption) {
131 op.selected = true;
132 }
133 el.appendChild(op);
134 }
135 if (id) {
136 el.id = id;
137 el.name = id;
138 }
139 el.addEventListener('change', (ev)=>{
140 let target = /** @type{HTMLSelectElement} */(ev.target);
141 console.log("DBUG:UI:Select:", id, ":", target.value);
142 cb(target.value);
143 })
144 return el;
145}
146
147/**
148 * Create a div wrapped select ui element, with a set of options to select from.
149 *
150 * @param {string} id
151 * @param {any} label
152 * @param {{ [x: string]: any; }} options
153 * @param {any} defaultOption
154 * @param {(arg0: string) => void} cb
155 * @param {string} className
156 */
157export function el_creatediv_select(id, label, options, defaultOption, cb, className="gridx2") {
158 let div = document.createElement("div");
159 div.className = className;
160 let lbl = document.createElement("label");
161 lbl.setAttribute("for", id);
162 lbl.innerText = label;
163 div.appendChild(lbl);
164 let sel = el_create_select(id, options,defaultOption, cb);
165 div.appendChild(sel);
166 return { div: div, el: sel };
167}
168
169
170/**
171 * Create a input ui element.
172 *
173 * @param {string} id
174 * @param {string} type
175 * @param {any} defaultValue
176 * @param {function(any):void} cb
177 */
178export function el_create_input(id, type, defaultValue, cb) {
179 let el = document.createElement("input");
180 el.type = type;
181 el.value = defaultValue;
182 if (id) {
183 el.id = id;
184 }
185 el.addEventListener('change', (ev)=>{
186 cb(el.value);
187 })
188 return el;
189}
190
191/**
192 * Create a div wrapped input.
193 *
194 * @param {string} id
195 * @param {string} label
196 * @param {string} type
197 * @param {any} defaultValue
198 * @param {function(any):void} cb
199 * @param {string} className
200 */
201export function el_creatediv_input(id, label, type, defaultValue, cb, className="gridx2") {
202 let div = document.createElement("div");
203 div.className = className;
204 let lbl = document.createElement("label");
205 lbl.setAttribute("for", id);
206 lbl.innerText = label;
207 div.appendChild(lbl);
208 let el = el_create_input(id, type, defaultValue, cb);
209 div.appendChild(el);
210 return { div: div, el: el };
211}