all repos — h3 @ 475a461d1af54620941667dcf70a765484aa67d3

A tiny, extremely minimalist JavaScript microframework.

Removed support for regions, simplifying code.
h3rald h3rald@h3rald.com
Mon, 13 Apr 2020 13:56:34 +0200
commit

475a461d1af54620941667dcf70a765484aa67d3

parent

e5762e60a5a428577b1e7b795b7500e7103ce120

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

@@ -1,4 +1,4 @@

-import h3, { createRegion, createRouter, createApp } from "./h3.js"; +import h3, { createApp } from "./h3.js"; import AddTodoForm from "./components/addTodoForm.js"; import EmptyTodoError from "./components/emptyTodoError.js"; import NavigationBar from "./components/navigationBar.js";

@@ -6,45 +6,21 @@ import TodoList from "./components/todoList.js";

import store from "./store.js"; const app = () => { + const { todos, filteredTodos, filter } = store.get(); + store.dispatch("todos/filter", filter); + localStorage.setItem("h3_todo_list", JSON.stringify(todos)); return h3("div#todolist.todo-list-container", [ h3("h1", "To Do List"), - h3("div#main-view"), - ]); -}; - -const main = () => { - const { todos, filteredTodos, filter } = store.get(); - const [error, updateError] = createRegion(EmptyTodoError); - store.on("error/update", updateError); - const [mainArea, updateMainArea] = createRegion(() => { - store.dispatch("todos/filter", filter); - localStorage.setItem("h3_todo_list", JSON.stringify(todos)); - return h3("div#main-area", [NavigationBar(), TodoList()]); - }); - store.on("mainArea/update", () => { - updateMainArea(); - }); - return h3("main", [ - AddTodoForm, - error, - mainArea + h3("main", [ + AddTodoForm, + EmptyTodoError, + h3("div#main-area", [NavigationBar, TodoList]) + ]) ]); } store.dispatch("todos/load"); -createApp('app', app()); +const update = createApp('app', app); -export const router = createRouter({ - fallback: "/", - id: "main-view", - routes: { - "/": main(), - }, -}); - -router.start(); - -if (router.route.params.log) { - store.on("log", (state, data) => console.log(data, state)); -} +store.on('$update', update);
M example/assets/js/components/addTodoForm.jsexample/assets/js/components/addTodoForm.js

@@ -6,7 +6,7 @@ const addTodo = () => {

const newTodo = document.getElementById("new-todo"); if (!newTodo.value) { store.dispatch("error/set"); - store.dispatch("error/update"); + store.dispatch("$update"); document.getElementById("new-todo").focus(); return; }

@@ -16,7 +16,7 @@ key: `todo_${Date.now()}__${newTodo.value}`, // Make todos "unique-enough" to ensure they are processed correctly

text: newTodo.value, }); newTodo.value = ""; - store.dispatch("mainArea/update"); + store.dispatch("$update"); document.getElementById("new-todo").focus(); }; const addTodoOnEnter = (event) => {
M example/assets/js/components/emptyTodoError.jsexample/assets/js/components/emptyTodoError.js

@@ -5,7 +5,7 @@ export default function EmptyTodoError(data, actions) {

const emptyTodoErrorClass = store.get('displayEmptyTodoError') ? "" : ".hidden"; const clearError = () => { store.dispatch('error/clear'); - store.dispatch('error/update'); + store.dispatch('$update'); } return h3(`div#empty-todo-error.error${emptyTodoErrorClass}`, [ h3("span.error-message", ["Please enter a non-empty todo item."]),
M example/assets/js/components/navigationBar.jsexample/assets/js/components/navigationBar.js

@@ -7,7 +7,7 @@ // Set the todo filter.

const setFilter = () => { let f = document.getElementById("filter-text"); store.dispatch("todos/filter", f.value); - store.dispatch("mainArea/update"); + store.dispatch("$update"); f = document.getElementById("filter-text"); f.focus(); };
M example/assets/js/components/paginator.jsexample/assets/js/components/paginator.js

@@ -19,14 +19,14 @@ const page = store.get('page');

const newPage = page - 1; store.dispatch("pages/set", newPage); window.location.hash = `/?page=${newPage}`; - store.dispatch("mainArea/update"); + store.dispatch("$update"); } function setNextPage() { const page = store.get('page'); const newPage = page + 1; store.dispatch("pages/set", newPage); window.location.hash = `/?page=${newPage}`; - store.dispatch("mainArea/update"); + store.dispatch("$update"); } return h3("div.paginator", [ h3(
M example/assets/js/components/todo.jsexample/assets/js/components/todo.js

@@ -5,11 +5,11 @@ export default function Todo(data) {

const todoStateClass = data.done ? ".done" : ".todo"; const toggleTodo = (todo) => { store.dispatch("todos/toggle", data); - store.dispatch("mainArea/update"); + store.dispatch("$update"); }; const removeTodo = (todo) => { store.dispatch("todos/remove", data); - store.dispatch("mainArea/update"); + store.dispatch("$update"); }; return h3(`div#${data.key}.todo-item`, [ h3(`div.todo-content${todoStateClass}`, [
M h3.jsh3.js

@@ -324,21 +324,13 @@

return store; }; -/** - * 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. - */ -const createApp = (id, vnode) => { - document.getElementById(id).appendChild(vnode.render()); -}; -const createRegion = (builder) => { +const createApp = (id, builder) => { const vnode = builder(); - if (!vnode.id) { - throw new Error("Region VNode does not have an ID."); - } - return [vnode, () => vnode.update({ vnode: builder() })]; + document.getElementById(id).appendChild(vnode.render()); + return () => { + vnode.update({vnode: builder()}); + }; }; class Route {

@@ -434,5 +426,5 @@ const h3 = (...args) => {

return new VNode(...args); }; -export { createStore, createRegion, createApp, createRouter }; +export { createStore, createApp, createRouter }; export default h3;