Sources
index.js
const hyptiotes = require("hyptiotes");
const configuration = require("./configuration");
const App = require("./app");
hyptiotes.setElementInitializer(configuration.elementInitializer);
hyptiotes.setItemHandlers(configuration.itemHandlers);
hyptiotes.setAttributeHandlers(configuration.attributeHandlers);
hyptiotes.setElementFinalizer(configuration.elementFinalizer);
const domTree = hyptiotes.castWeb(App);
document.getElementById("root").appendChild(domTree);
configuration.js
const hyptiotes = require("hyptiotes");
const LinkedObservable = require("./LinkedObservable");
module.exports = {
elementInitializer: hyptiotes.DEFAULT_ELEMENT_INITIALIZER,
itemHandlers: [
{
test: (item) => item instanceof LinkedObservable,
handler: ({ item, parent, hyptiotes }) => {
let element = null;
item.map(model => {
let updatedElement = hyptiotes.castWeb(model);
const next = element && element.nextSibling;
if (element) parent.removeChild(element);
parent.insertBefore(updatedElement, next);
element = updatedElement;
}).terminate();
},
},
...hyptiotes.DEFAULT_ITEM_HANDLERS,
],
attributeHandlers: hyptiotes.DEFAULT_ATTRIBUTE_HANDLERS,
elementFinalizer: hyptiotes.DEFAULT_ELEMENT_FINALIZER,
};
app.js
const TodoStore = require("../TodoStore");
const LinkedObservable = require("./LinkedObservable");
module.exports = [
":div",
{ id: "main-content" },
[":h1", "Hyptiotes To-Do"],
TodoList,
AddTodo,
];
function TodoList() {
const Todos = new LinkedObservable(TodoStore.get());
TodoStore.subscribe((v) => Todos.set(v));
return Todos.map((todoList) => {
return [
":ul",
...todoList.map((todo) => {
return [":li", todo];
}),
];
});
}
function AddTodo() {
const inputValue = new LinkedObservable("");
return [
":div",
inputValue.map((val) => {
return [
":input",
{
value: val,
onchange: (e) => {
inputValue.set(e.target.value);
},
},
];
}),
[
":button",
{
onclick: () => {
TodoStore.add(inputValue.current);
inputValue.set("");
},
},
"Add",
],
];
}
Full Configuration
{
"elementInitializer": (tag) => document.createElement(tag.slice(1)),
"itemHandlers": [
{
"test": (item) => item instanceof LinkedObservable,
"handler": ({ item, parent, hyptiotes }) => {
let element = null;
item.map(model => {
let updatedElement = hyptiotes.castWeb(model);
const next = element && element.nextSibling;
if (element) parent.removeChild(element);
parent.insertBefore(updatedElement, next);
element = updatedElement;
}).terminate();
}
},
{
"test": (item) => item === null || item === undefined,
"handler": () => {}
},
{
"test": (item) => item instanceof HTMLElement,
"handler": ({item, parent}) => parent.appendChild(item)
},
{
"test": item => typeof item === "string",
"handler": ({ item, parent }) => {
const textNode = document.createTextNode(item);
parent.appendChild(textNode);
}
},
{
"test": item => Array.isArray(item) && typeof item[0] === "string" && item[0][0] === ":",
"handler": ({item, parent, hyptiotes}) => {
const nested = hyptiotes.castWeb(item);
if (nested) parent.appendChild(nested);
}
},
{
"test": item => Array.isArray(item) && (typeof item[0] !== "string" || item[0][0] !== ":"),
"handler": ({item, parent, hyptiotes}) => {
item.forEach(i => {
const child = typeof i === "string" ? document.createTextNode(item) : hyptiotes.castWeb(i);
parent.appendChild(child);
});
}
},
{
"test": (item) => typeof item === "function",
"handler": ({ item, parent, index, hyptiotes }) => {
hyptiotes.mapItem(item({ parent, hyptiotes }), parent, index);
}
}
],
"attributeHandlers": [
{
"test": key => key === "style",
"handler": ({value, parent}) => {
parent.setAttribute('style', stringifyStyleObject(value));
}
},
{
"test": (_, value) => typeof value === "function",
"handler": ({key, value, parent}) => {
parent[key] = value;
}
},
{
"test": () => true,
"handler": ({key, value, parent}) => {
parent.setAttribute(key, value);
}
}
],
"elementFinalizer": (x) => x
}