DEV Community

Cover image for TodoList part 4/n
artydev
artydev

Posted on • Edited on

1

TodoList part 4/n

Let's enhance our TodoList.

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();    
 }
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (2)

Collapse
 
efpage profile image
Eckehard

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.

Collapse
 
artydev profile image
artydev • Edited

Thanks Eckehard☺
Very handy for sure, I have made the modification

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay