namespace formgen.input { /** */ type type_item_raw = { input : interface_input; kind ?: string; label ?: string; } /** */ type type_item = { input : interface_input; kind : string; label : string; } /** * @todo do not allow empty? */ export class class_input_sum implements interface_input<(null | {kind : string; value : unknown;})> { /** */ private items : Array; /** */ private label : (null | string); /** */ private active : (null | string); /** */ private kind_to_index_map : Map; /** */ public constructor( items : Array, { "label": label = null, } : { label ?: (null | string); } = { } ) { this.items = ( items .map( (item_raw, index) => ({ "input": item_raw.input, "kind": (item_raw.kind ?? ("" + (index + 1).toFixed(0))), "label": (item_raw.label ?? ("Art " + (index + 1).toFixed(0))), }) ) ); this.label = label; this.active = null; this.kind_to_index_map = new Map(); for (const index of formgen.helpers.list.sequence(this.items.length)) { this.kind_to_index_map.set(this.items[index].kind, index); } } /** * [implementation] */ public async setup( element_target : Element ) : Promise { let element_selection : Element; let element_item_inputs : Element; // structure { const element_container : Element = document.createElement("div"); element_container.classList.add("formgen-input"); element_container.classList.add("formgen-input-sum"); // label { if (this.label === null) { // do nothing } else { const element_label : Element = document.createElement("label"); element_label.textContent = this.label; element_container.appendChild(element_label); } } // selection { const radio_name : string = formgen.helpers.string.generate({"prefix": "formgen-input-sum-selection-"}); element_selection = document.createElement("div"); element_selection.classList.add("formgen-input-sum-selection"); for (const item of this.items) { const input_id : string = formgen.helpers.string.generate({"prefix": "input-label-pair-"}); const element_selector : Element = document.createElement("div"); element_selector.setAttribute("rel", item.kind); element_selector.classList.add("formgen-input-sum-item-selector"); // input { const element_selector_input : Element = document.createElement("input"); element_selector_input.setAttribute("type", "radio"); element_selector_input.setAttribute("name", radio_name); element_selector_input.setAttribute("id", input_id); element_selector.appendChild(element_selector_input); } // label { const element_selector_label : Element = document.createElement("label"); element_selector_label.setAttribute("for", input_id); element_selector_label.textContent = item.label; element_selector.appendChild(element_selector_label); } element_selection.appendChild(element_selector); } element_container.appendChild(element_selection); } // inputs { element_item_inputs = document.createElement("div"); element_item_inputs.classList.add("formgen-input-sum-inputs"); for (const item of this.items) { const element_item_input : Element = document.createElement("div"); element_item_input.classList.add("formgen-input-sum-item-input"); element_item_input.setAttribute("rel", item.kind); await item.input.setup(element_item_input); element_item_inputs.appendChild(element_item_input); } element_container.appendChild(element_item_inputs); } element_target.appendChild(element_container); } // logic { element_selection.childNodes.forEach( (element) => { element.addEventListener( "change", (event) => { if (event.target === null) { // do nothing } else { const parent : (null | Element) = (event.target as Element).parentElement; if (parent === null) { // do nothing } else { const kind : (null | string) = parent.getAttribute("rel"); if (kind === null) { // do nothing } else { const item : type_item = this.items[this.kind_to_index_map.get(kind)]; this.active = kind; element_item_inputs.childNodes.forEach( (node) => { const element_input = (node as Element); element_input.classList.toggle( "formgen-input-sum-item-input-active", (element_input.getAttribute("rel") === kind) ); } ); } } } } ); } ); } } /** * [implementation] */ public async read( ) : Promise<(null | {kind : string; value : unknown;})> { if (this.active === null) { // throw (new Error("nothing active")); return null; } else { const item : type_item = this.items[this.kind_to_index_map.get(this.active)]; return { "kind": item.kind, "value": (await item.input.read()), }; } } /** * [implementation] */ public async write( value : (null | {kind : string; value : unknown;}) ) : Promise { throw (new Error("not implemented")); } } }