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}