Files
tultemplategen/utils.js

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));
}