259 lines
4.4 KiB
JavaScript
259 lines
4.4 KiB
JavaScript
class ElementBuilder {
|
|
constructor(tag) {
|
|
let parts = tag.split(/(\.|#)/);
|
|
|
|
if(parts.length % 2 == 0) {
|
|
throw new Error("invalid element builder tag string");
|
|
}
|
|
|
|
this.element = document.createElement(parts[0]);
|
|
|
|
parts = parts.slice(1);
|
|
|
|
for(let i = 0; i < parts.length; i += 2) {
|
|
let type = parts[i];
|
|
let value = parts[i + 1];
|
|
|
|
switch(type) {
|
|
case ".":
|
|
this.element.classList.add(value);
|
|
break;
|
|
|
|
case "#":
|
|
this.element.id = value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Need more stuff? Just implement it here.
|
|
|
|
id(id) {
|
|
this.element.id = id;
|
|
return this;
|
|
}
|
|
|
|
class(clazz) {
|
|
for(const subclass of clazz.split(" ").filter(x => x !== "")) {
|
|
this.element.classList.add(subclass);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
text(text) {
|
|
this.element.innerText = text;
|
|
return this;
|
|
}
|
|
|
|
html(html) {
|
|
this.element.innerHTML = html;
|
|
return this;
|
|
}
|
|
|
|
on_click(handler) {
|
|
this.element.onclick = handler;
|
|
return this;
|
|
}
|
|
|
|
on_input(handler) {
|
|
this.element.oninput = handler;
|
|
return this;
|
|
}
|
|
|
|
for(fr) {
|
|
this.element.htmlFor = fr;
|
|
return this;
|
|
}
|
|
|
|
src(src) {
|
|
this.element.src = src;
|
|
return this;
|
|
}
|
|
|
|
target(target) {
|
|
this.element.target = target;
|
|
return this;
|
|
}
|
|
|
|
href(href) {
|
|
this.element.href = href;
|
|
return this;
|
|
}
|
|
|
|
download(download) {
|
|
this.element.download = download;
|
|
return this;
|
|
}
|
|
|
|
type(type) {
|
|
this.element.type = type;
|
|
return this;
|
|
}
|
|
|
|
value(value) {
|
|
this.element.value = value;
|
|
return this;
|
|
}
|
|
|
|
checked(checked) {
|
|
this.element.checked = checked;
|
|
return this;
|
|
}
|
|
|
|
placeholder(placeholder) {
|
|
this.element.placeholder = placeholder;
|
|
return this;
|
|
}
|
|
|
|
append(element) {
|
|
if(element instanceof ElementBuilder) {
|
|
element = element.finish();
|
|
}
|
|
|
|
this.element.appendChild(element);
|
|
return this;
|
|
}
|
|
|
|
append_all(elements) {
|
|
for(const element of elements) {
|
|
this.element.appendChild(element);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
style(name, value) {
|
|
this.element.style[name] = value;
|
|
return this;
|
|
}
|
|
|
|
if(cond, handler) {
|
|
if(cond) handler(this);
|
|
return this;
|
|
}
|
|
|
|
finish() {
|
|
return this.element;
|
|
}
|
|
}
|
|
|
|
class ButtonListBuilder {
|
|
constructor(list) {
|
|
this.list = list;
|
|
this.display_handler = null;
|
|
this.onclick_handler = null;
|
|
this.modify_handler = null;
|
|
}
|
|
|
|
should_be_pressed(handler) {
|
|
this.display_handler = handler;
|
|
return this;
|
|
}
|
|
|
|
on_click(handler) {
|
|
this.onclick_handler = handler;
|
|
return this;
|
|
}
|
|
|
|
modify(handler) {
|
|
this.modify_handler = handler;
|
|
return this;
|
|
}
|
|
|
|
finish() {
|
|
let buttons = this.list.map((key) => new ElementBuilder("button")
|
|
.if(this.modify_handler !== null, (b) => this.modify_handler(b, key))
|
|
.if(this.display_handler(key), (b) => b.class("accent"))
|
|
.finish()
|
|
);
|
|
|
|
for(let i = 0; i < buttons.length; i++) {
|
|
buttons[i].onclick = () => {
|
|
if(this.onclick_handler !== null) this.onclick_handler(this.list[i]);
|
|
|
|
for(let j = 0; j < buttons.length; j++) {
|
|
buttons[j].classList.remove("accent");
|
|
|
|
if(this.display_handler(this.list[j])) {
|
|
buttons[j].classList.add("accent");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
return buttons;
|
|
}
|
|
}
|
|
|
|
class TextInputBuilder {
|
|
constructor(result, key) {
|
|
this.result = result;
|
|
this.key = key;
|
|
this.text = "";
|
|
}
|
|
|
|
placeholder(placeholder) {
|
|
this.text = placeholder;
|
|
return this;
|
|
}
|
|
|
|
finish() {
|
|
return new ElementBuilder("input")
|
|
.type("text")
|
|
.placeholder(this.text)
|
|
.value(this.result[this.key])
|
|
.on_input((e) => this.result[this.key] = e.target.value)
|
|
.finish();
|
|
}
|
|
}
|
|
|
|
class BinaryInputBuilder {
|
|
constructor(result, key) {
|
|
this.result = result;
|
|
this.key = key;
|
|
this.text = "";
|
|
this.update_handler = null;
|
|
}
|
|
|
|
label(label) {
|
|
this.text = label;
|
|
return this;
|
|
}
|
|
|
|
on_update(handler) {
|
|
this.update_handler = handler;
|
|
return this;
|
|
}
|
|
|
|
finish() {
|
|
let input = new ElementBuilder("input#" + this.key)
|
|
.type("checkbox")
|
|
.checked(this.result[this.key])
|
|
.if(this.update_handler !== null, b => b.on_click(e => {
|
|
console.log(e.target.checked);
|
|
this.result[this.key] = e.target.checked;
|
|
this.update_handler(e.target.checked);
|
|
}))
|
|
.finish();
|
|
|
|
let bundle = new ElementBuilder("div.horizontal-list")
|
|
.append(input)
|
|
.append(new ElementBuilder("label")
|
|
.for(this.key)
|
|
.text(this.text))
|
|
.finish();
|
|
|
|
if(this.update_handler !== null) {
|
|
this.update_handler(this.result[this.key]);
|
|
}
|
|
|
|
return bundle;
|
|
}
|
|
}
|
|
|
|
async function delay_ms(ms) {
|
|
await new Promise((r) => setTimeout(r, ms));
|
|
}
|
|
|