Compare commits

...

3 commits

Author SHA1 Message Date
trans_soup
ef0b607e42 make readme branch-relevant. 2023-07-18 18:12:52 +02:00
trans_soup
8e3aa4228c create messy reactivity-ish test stuff.
(it works but it's messy.)
2023-07-18 17:52:02 +02:00
trans_soup
975cde8a31 add list demo. 2023-07-18 11:27:30 +02:00
3 changed files with 57 additions and 34 deletions

View file

@ -1,3 +1,13 @@
# `reactivity-test`
this branch is for testing out things related to making elements change in reaction to changes in data.
right now, functions passed to `json_as_html` will have an optional additional argument, that's a function. calling it with another function, will make it so that that other function is applied to the element returned from the first function (the one passed to `json_as_html`).
the demo uses this to create an event listener (in a tiny event system made for this), that modifies the contents of an element. the event is triggered by a button onclick just like it was previously.
---
small utility for creating DOM trees from javascript arrays. small utility for creating DOM trees from javascript arrays.
note that this doesn't actually take a json string, but rather an actual array, as input. `array_as_html` would be a bit inaccurate though, since it also handles some other things such as functions and strings in ways that make sense. note that this doesn't actually take a json string, but rather an actual array, as input. `array_as_html` would be a bit inaccurate though, since it also handles some other things such as functions and strings in ways that make sense.
@ -6,35 +16,6 @@ to use, clone/submodule/subtree/whatever the `main` branch, and import `json_as_
to see a demo, or contribute, clone the `dev` branch. to see a demo, or contribute, clone the `dev` branch.
# example
here's the demo array being used at the time of writing this:
```javascript
[
"div",
[
["id", "wrapper"],
["class", "demo_div"],
],
[
["h1", [], "header :)"],
["p", [], "paragraph! meow"],
["p", [], "another paragraph!! this is so cool"],
state => ["button", [
["onclick", _ => {
state.set("clicked", true);
render();
}]
], "it can even do buttons!"],
state => ["p", [], state.get("clicked") ? "clicked" : "not clicked"],
],
]
```
it assumes a function `render` which replaces the contents of the `<body>` with the result of calling `json_as_html` with this array as argument. it also assumes a `Map` called `state`.
# how to use # how to use
the `json_as_html` function takes two arguments: the `json_as_html` function takes two arguments:

View file

@ -12,7 +12,7 @@ export function json_as_html (json, state = new Map()) {
} }
if (typeof json === "function") { if (typeof json === "function") {
return json_as_html(json(state), state); return from_function(json, state);
} }
const [type, attributes = [], children = []] = json; const [type, attributes = [], children = []] = json;
@ -32,3 +32,21 @@ export function json_as_html (json, state = new Map()) {
return elem; return elem;
} }
// these two functions are pretty messy.
function from_function (fn, state) {
const [after, has_run_after] = delayed(fn => elem => fn(elem));
const initial = json_as_html(fn(state, after), state);
if (has_run_after()) after(initial);
return initial;
}
function delayed (fn) {
let has_run_once = false;
let initial_result = undefined;
return [(...args) => {
if (has_run_once) return initial_result(...args);
has_run_once = true;
initial_result = fn(...args);
return initial_result;
}, _ => has_run_once];
}

View file

@ -15,18 +15,42 @@ const demo = [
state => ["button", [ state => ["button", [
["onclick", _ => { ["onclick", _ => {
state.set("clicked", true); state.set("clicked", true);
render(); trigger_event("button_pressed");
}] }]
], "it can even do buttons!"], ], "it can even do buttons!"],
state => ["p", [], state.get("clicked") ? "clicked" : "not clicked"], (state, after) => {
// this is very messy.
const generate = _ => ["p", [], state.get("clicked") ? "clicked" : "not clicked"];
after(elem => listen_event("button_pressed", _ => elem.replaceWith(json_as_html(generate(), state))));
return generate();
},
["ul",
[],
[
["li", [], "meow"],
["li", [], "uwu"],
],
],
], ],
]; ];
const state = new Map(); let event_listeners = new Map();
function trigger_event (name) {
if (event_listeners.has(name)) {
event_listeners.get(name).forEach(fn => fn());
}
}
function listen_event (name, fn) {
if (!event_listeners.has(name)) event_listeners.set(name, []);
event_listeners.get(name).push(fn);
}
function render () { function render () {
document.body.innerHTML = ""; document.body.innerHTML = "";
document.body.appendChild(json_as_html(demo, state)); document.body.appendChild(json_as_html(demo));
} }
render(); render();