Compare commits
3 commits
main
...
reactivity
Author | SHA1 | Date | |
---|---|---|---|
|
ef0b607e42 | ||
|
8e3aa4228c | ||
|
975cde8a31 |
3 changed files with 57 additions and 34 deletions
39
README.md
39
README.md
|
@ -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:
|
||||||
|
|
20
src/core.mjs
20
src/core.mjs
|
@ -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];
|
||||||
|
}
|
||||||
|
|
32
src/demo.mjs
32
src/demo.mjs
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue