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