all repos — h3 @ d253248136ef08dce340f4c57341861b9f6d1deb

A tiny, extremely minimalist JavaScript microframework.

Refactoring.
h3rald h3rald@h3rald.com
Fri, 10 Apr 2020 15:47:02 +0200
commit

d253248136ef08dce340f4c57341861b9f6d1deb

parent

0d4d426f3bb76982050378d573b2956b21af39ec

4 files changed, 53 insertions(+), 72 deletions(-)

jump to
M example/assets/js/app.jsexample/assets/js/app.js

@@ -1,10 +1,10 @@

-import h3 from "./h3.js"; +import h3, { mount } from "./h3.js"; import Paginator from "./paginator.js"; import Todo from "./todo.js"; let todos = []; let filteredTodos = []; -let view = null; +let app; let emptyTodoError = false; let filter = ""; let pagesize = 10;

@@ -24,21 +24,17 @@

// Actual DOM creation/updateing const update = () => { save(); - view.update({ vnode: build() }); + app.update({ vnode: build() }); }; const toggle = (todo) => { todo.done = !todo.done; update(); -} +}; const remove = (todo) => { todos = todos.filter(({ key }) => key !== todo.key); update(); -} -// Todo component -const todo = Todo({ toggle, remove }); -// Paginator Component -const paginator = Paginator(update); +}; // UI Methods // Add a todo item

@@ -81,7 +77,7 @@ // Display todo items

const displayTodos = () => { const start = (page - 1) * pagesize; const end = Math.min(start + pagesize, filteredTodos.length); - return filteredTodos.slice(start, end).map(todo); + return filteredTodos.slice(start, end).map((t) => Todo(t, {toggle, remove})); }; // Clear error message

@@ -143,11 +139,11 @@ placeholder: "Type to filter todo items...",

onkeyup: setFilter, value: filter, }), - paginator(paginatorData), + Paginator(paginatorData, {update}), ]), h3("div.todo-list", displayTodos()), ]); }; load(); -view = build(); -document.getElementById("app").appendChild(view.render()); +app = build(); +mount("app", app);
M example/assets/js/paginator.jsexample/assets/js/paginator.js

@@ -1,39 +1,38 @@

import h3 from "./h3.js"; -export default function Paginator(update) { - return function (data) { - let page = data.page; - const size = data.size; - const total = data.total; - const pages = Math.ceil(total / size) || 1; - const previousClass = page > 1 ? ".link" : ".disabled"; - const nextClass = page < pages ? ".link" : ".disabled"; - function setPreviousPage() { - page = page - 1; - window.location.hash = `/?page=${page}`; - update(); - } - function setNextPage() { - page = page + 1; - window.location.hash = `/?page=${page}`; - update(); - } - return h3("div.paginator", [ - h3( - `span.previous-page${previousClass}`, - { - onclick: setPreviousPage, - }, - ["←"] - ), - h3("span.current-page", [`${String(page)}/${String(pages)}`]), - h3( - `span.next-page${nextClass}`, - { - onclick: setNextPage, - }, - ["→"] - ), - ]); - }; +export default function Paginator(data, actions) { + const { update } = actions; + let page = data.page; + const size = data.size; + const total = data.total; + const pages = Math.ceil(total / size) || 1; + const previousClass = page > 1 ? ".link" : ".disabled"; + const nextClass = page < pages ? ".link" : ".disabled"; + function setPreviousPage() { + page = page - 1; + window.location.hash = `/?page=${page}`; + update(); + } + function setNextPage() { + page = page + 1; + window.location.hash = `/?page=${page}`; + update(); + } + return h3("div.paginator", [ + h3( + `span.previous-page${previousClass}`, + { + onclick: setPreviousPage, + }, + ["←"] + ), + h3("span.current-page", [`${String(page)}/${String(pages)}`]), + h3( + `span.next-page${nextClass}`, + { + onclick: setNextPage, + }, + ["→"] + ), + ]); }
M example/assets/js/todo.jsexample/assets/js/todo.js

@@ -1,14 +1,12 @@

import h3 from "./h3.js"; -export default function Todo(actions) { +export default function Todo(data, actions) { const { toggle, remove } = actions; - return function (data) { - const todoStateClass = data.done ? ".done" : ".todo"; - return h3("div.todo-item", { id: data.key }, [ - h3(`div.todo-content${todoStateClass}`, [ - h3("span.todo-text", { onclick: () => toggle(data) }, [data.text]), - ]), - h3("span.delete-todo", { onclick: () => remove(data) }, ["✘"]), - ]); - }; -} + const todoStateClass = data.done ? ".done" : ".todo"; + return h3("div.todo-item", { id: data.key }, [ + h3(`div.todo-content${todoStateClass}`, [ + h3("span.todo-text", { onclick: () => toggle(data) }, [data.text]), + ]), + h3("span.delete-todo", { onclick: () => remove(data) }, ["✘"]), + ]); +};
M h3.jsh3.js

@@ -55,18 +55,6 @@ return checkProperties(o1, o2) && checkProperties(o2, o1);

} /** - * Creates an updatable region within a page, identified by a unique ID. - * @param {Function} builder A function returning a VNode object. - * @returns {Array[Element, Function]} The DOM element resulting by rendering the built VNode and a function used to update (rebuild) the element. - */ -export const region = (builder) => { - const vnode = builder(); - if (!vnode.id) { - throw 'No ID specified for region VNode.'; - } - return [vnode.render(), () => vnode.update(builder())]; -} -/** * Mounts a VNode and renders it as a child of an existing DOM Element. * @param {string} id A unique ID of of an existing DOM Element. * @param {VNode} vnode The VNode to mount as child of the specified DOM element.