241 lines
5.5 KiB
TypeScript
241 lines
5.5 KiB
TypeScript
|
|
namespace formgen.input
|
||
|
|
{
|
||
|
|
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
type type_item_raw = {
|
||
|
|
input : interface_input<unknown>;
|
||
|
|
kind ?: string;
|
||
|
|
label ?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
type type_item = {
|
||
|
|
input : interface_input<unknown>;
|
||
|
|
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<type_item>;
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
private label : (null | string);
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
private active : (null | string);
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
private kind_to_index_map : Map<string, int>;
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
public constructor(
|
||
|
|
items : Array<type_item_raw>,
|
||
|
|
{
|
||
|
|
"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<string, int>();
|
||
|
|
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<void>
|
||
|
|
{
|
||
|
|
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<void>
|
||
|
|
{
|
||
|
|
throw (new Error("not implemented"));
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|