Let's enhance our TodoList.
Three buttons have been added to the status bar. Here is the code to display and manage them :
function createStatus () { selectBase(div("", cssStatus)); function displayCompleted (isCompleted) { todos.forEach(todo => todo.dataset.completed == isCompleted ? todo.style.display = "flex" : todo.style.display = "none"); } button("active(s)", cssBtn).onclick = () => displayCompleted("false"); button("completed", cssBtn).onclick = () => displayCompleted("true"); button("all", cssBtn).onclick = () => todos.forEach(todo => todo.style.display = "flex"); unselectBase(); }
Could it be simpler ?
See how we easily we reference and add events on our three created buttons.
You cant play with it here : TodoList
Here is the full code so far :
import { make, selectBase, unselectBase } from "./dml"; const TodoApp = function (target) { const blueblack = "rgb(40, 42, 54)" if (!target) { target = document.body; } const cType = function (type, content, attribs) { return (content, attribs) => make(type, attribs, content); }; const div = cType("div"); const h1 = cType("h1"); const input = cType("input"); const button = cType("button"); let reflistTodos = null; let todos = []; const cssTodoApp = ` width:75%; max-width:480px; min-width:360px; padding:10px; padding-bottom:5px; margin:0 auto; background: white; `; const cssTodo = () => ` padding:5px; display:flex; justify-content:space-around; margin-bottom:5px`; const cssEntryTodo = ` margin-bottom: 10px; width:98%; padding:5px; border: 1px solid ${blueblack}; ` const cssStatus = ` margin-top:10px; margin-bottom: 10px; color: ${blueblack}; border: 1px solid ${blueblack}; padding:5px; text-align:center; `; const cssBtn = `border:1px solid grey;margin:2px`; function createEntryTodo () { selectBase(div("", cssEntryTodo)); let entry = input("", { style: "width:99%; border:none", placeholder: "input new todo and press Enter" }); entry.onkeypress = function (e) { if (e.which === 13) { addTodo(entry.value); entry.value = ""; } } unselectBase() } function createTodoItem(todo) { selectBase(reflistTodos) let divtodo = selectBase(div("", cssTodo())) let checktodo = input("", { type: "checkbox" }); let inptodo = input("", { style: "flex:0.99", value: todo }); let deltodo = input("", { type: "checkbox", style: "visibility:hidden" }); divtodo.dataset.completed = "false" checktodo.onchange = () => checkTodo({divtodo, checktodo, inptodo}); deltodo.onchange = () => deleteTodo(divtodo) divtodo.onmouseover = () => (deltodo.style.visibility = "visible"); divtodo.onmouseout = () => (deltodo.style.visibility = "hidden"); unselectBase(); unselectBase(); return divtodo } function createListTodos(todos = []) { reflistTodos = selectBase(div("", "padding:5px")) todos.map(addTodo); unselectBase() } function deleteTodo (todo) { todos = todos.filter(t => t != todo); todo.remove(); } function addTodo(todo) { // calling createTodoItem update the view todos = [...todos, createTodoItem(todo)]; } function checkTodo ({divtodo, checktodo, inptodo}) { let checked = checktodo.checked if (checked) { inptodo.style.color = 'red' inptodo.style.textDecoration = 'line-through'; divtodo.dataset.completed = 'true'; } else { inptodo.style.color = blueblack; inptodo.style.textDecoration = 'none'; divtodo.dataset.completed = 'false'; } } function createStatus () { function displayCompleted (isCompleted) { todos.forEach(todo => todo.dataset.completed == isCompleted ? todo.style.display = "flex" : todo.style.display = "none"); } button("active(s)", cssBtn).onclick = () => displayCompleted("false"); button("completed", cssBtn).onclick = () => displayCompleted("true"); button("all", cssBtn).onclick = () => todos.forEach(todo => todo.style.display = "flex"); } function initApp(todos) { target.style = cssTodoApp; let app = selectBase(target); createEntryTodo(); createListTodos(todos); selectBase(div("", cssStatus)); createStatus(); unselectBase(); unselectBase(); return app } return { init: initApp, addTodo: addTodo, }; }; export default TodoApp;
Top comments (2)
As styles are most frequently used, you don´t need to set the style property explicitly. The two definitions are identical:
´´´js
button("all", {style: cssBtn}) // Properties as JSON-object
button("all", cssBtn) // style attributes as string only are converted
´´´
DML distinguishes the type of the second argument. Any string is automatically converted to a style property:
´´´js
"color: red;" ==> {style: "color: red;"}
´´´
This is just for convenience, but as in 95% of the cases only the style is set, this is a very handy abbreviation.
Thanks Eckehard☺
Very handy for sure, I have made the modification