add function elements and global state.

function elements as in, when `json_to_html` encounters a function,
it'll evaluate it and then use that value as input instead.

global state as in, a single state accessible by all nodes that are
created from a `json_to_html` call.
This commit is contained in:
trans_soup 2023-07-15 04:32:44 +02:00
parent 8f45f69d09
commit 416d31b1ad

View file

@ -2,7 +2,7 @@ function use_as_array (val) {
return Array.isArray(val) ? val : [val];
}
function json_as_html (json) {
function json_as_html (json, state = new Map()) {
if (json instanceof Node) {
return json;
}
@ -11,6 +11,10 @@ function json_as_html (json) {
return document.createTextNode(json);
}
if (typeof json === "function") {
return json_as_html(json(state), state);
}
const [type, attributes, children] = json;
const elem = document.createElement(type);
@ -19,7 +23,7 @@ function json_as_html (json) {
elem[key] = value);
// elem.setAttribute(key, value));
const child_nodes = use_as_array(children).map(json_as_html)
const child_nodes = use_as_array(children).map(child => json_as_html(child, state))
child_nodes.forEach(child => elem.appendChild(child));
return elem;
@ -36,10 +40,21 @@ const demo = [
["h1", [], "header :)"],
["p", [], "paragraph! meow"],
["p", [], "another paragraph!! this is so cool"],
["button", [
["onclick", _ => alert("see? it works!")]
state => ["button", [
["onclick", _ => {
state.set("clicked", true);
render();
}]
], "it can even do buttons!"],
state => ["p", [], state.get("clicked") ? "clicked" : "not clicked"],
],
];
document.body.appendChild(json_as_html(demo));
const state = new Map();
function render () {
document.body.innerHTML = "";
document.body.appendChild(json_as_html(demo, state));
}
render();