Skip to main content
added 91 characters in body; edited tags; deleted 18 characters in body
Source Link
200_success
  • 145.7k
  • 22
  • 191
  • 481

I am learning JavaScript and this is a simple todo application I made which uses local storage. It is currently running at: https://koraytugay.github.io/vanillatodo/#. The code is as follows. I am open to any suggestions on how the structure / architecture or implementation details should/can be improved. Can be cloned from: https://github.com/koraytugay/vanillatodohttps://github.com/koraytugay/vanillatodo and it looks like this:

enter image description herescreenshot

I am learning JavaScript and this is a simple todo application I made which uses local storage. It is currently running at: https://koraytugay.github.io/vanillatodo/#. The code is as follows. I am open to any suggestions on how the structure / architecture or implementation details should/can be improved. Can be cloned from: https://github.com/koraytugay/vanillatodo and it looks like this:

enter image description here

I am learning JavaScript and this is a simple todo application I made which uses local storage. It is currently running at: https://koraytugay.github.io/vanillatodo/#. The code is as follows. I am open to any suggestions on how the structure / architecture or implementation details should/can be improved. Can be cloned from: https://github.com/koraytugay/vanillatodo and it looks like this:

screenshot

Source Link
Koray Tugay
  • 1.6k
  • 5
  • 20
  • 44

Todo App with JavaScript

I am learning JavaScript and this is a simple todo application I made which uses local storage. It is currently running at: https://koraytugay.github.io/vanillatodo/#. The code is as follows. I am open to any suggestions on how the structure / architecture or implementation details should/can be improved. Can be cloned from: https://github.com/koraytugay/vanillatodo and it looks like this:

enter image description here

index.html

<!DOCTYPE html>
<html>
<head>
  <title>VanillaTodo</title>
  <link rel="stylesheet" href="style.css"/>
</head>
<body>
<div id="container">
  <input id="new-todo-input" type="text">
  <h2>To Do Items</h2>
  <div id="todo-items"></div>
  <hr/>
  <a href="#" id="delete-all-todo-items">Delete All</a>
</div>
<script type="module" src="src/todoController.js"></script>
</body>
</html>

todoItemStorageService.js

export default (function() {
  const todoItems = 'todo-items';
  const idCounter = 'id-counter';

  function getTodoItems() {
    if (localStorage.getItem(todoItems) === null) {
      localStorage.setItem(todoItems, JSON.stringify([]));
      localStorage.setItem(idCounter, '1');
    }
    return JSON.parse(localStorage.getItem(todoItems));
  }

  function getNextTodoItemId() {
    const nextTodoItemId = parseInt(localStorage.getItem(idCounter));
    localStorage.setItem(idCounter, '' + (nextTodoItemId + 1));
    return nextTodoItemId;
  }

  function setTodoItems(items) {
    localStorage.setItem(todoItems, JSON.stringify(items));
  }

  function deleteTodoItem(id) {
    setTodoItems(getTodoItems().filter(todoItem => todoItem.id !== id));
  }

  function deleteTodoItems() {
    setTodoItems([]);
  }

  function addTodoItem(todoItem) {
    setTodoItems([...getTodoItems(), todoItem]);
  }

  function getTodoItem(id) {
    return getTodoItems().filter(todoItem => todoItem.id === id)[0];
  }

  function updateTodoItem(todoItem) {
    const allTodoItems = getTodoItems();
    const itemIndex = allTodoItems.findIndex(item => item.id === todoItem.id);
    allTodoItems[itemIndex].text = todoItem.text;
    allTodoItems[itemIndex].id = todoItem.id;
    allTodoItems[itemIndex].completed = todoItem.completed;
    setTodoItems(allTodoItems);
  }

  return {
    getNextTodoItemId,
    addTodoItem,
    getTodoItems,
    getTodoItem,
    updateTodoItem,
    deleteTodoItem,
    deleteTodoItems
  }
}());

todoService.js

import todoItemsStorageService from './todoItemsStorageService.js';

export default (function() {
  function Todo(text) {
    this.text = text;
    this.id = `todo-item-${todoItemsStorageService.getNextTodoItemId()}`;
    this.completed = false;
    todoItemsStorageService.addTodoItem(this);
  }

  function toggleTodoItemCompletedStatus(id) {
    const todoItem = todoItemsStorageService.getTodoItem(id);
    todoItem.completed = !todoItem.completed;
    todoItemsStorageService.updateTodoItem(todoItem);
  }

  const getTodoItems = () => todoItemsStorageService.getTodoItems();
  const deleteTodoItem = (id) => todoItemsStorageService.deleteTodoItem(id);
  const deleteTodoItems = () => todoItemsStorageService.deleteTodoItems();

  return {
    Todo,
    getTodoItems,
    toggleTodoItemCompletedStatus,
    deleteTodoItem,
    deleteTodoItems
  };
}());

todoController.js


(function() {
  const findById = id => document.querySelector(`#${id}`);
  const createElement = (tag, options) => document.createElement(tag, options);

  window.addEventListener('load', function() {
    refreshUi();
  });

  findById('new-todo-input').addEventListener('keydown', e => {
    if ('Enter' === e.key && e.target.value) {
      new todoService.Todo(e.target.value);
      e.target.value = '';
      refreshUi();
    }
  });

  findById('delete-all-todo-items').addEventListener('click', e => {
    todoService.deleteTodoItems();
    refreshUi();
  });

  function toggleTodoCompleteStatus(id) {
    todoService.toggleTodoItemCompletedStatus(id);
    refreshUi();
  }

  function deleteTodoItem(id) {
    todoService.deleteTodoItem(id);
    refreshUi();
  }

  function createTodoDiv(todoItem) {
    const todoDiv = createElement('div');
    todoDiv.id = todoItem.id;

    const markAsDoneCheckbox = createElement('input');
    markAsDoneCheckbox.setAttribute('type', 'checkbox');
    markAsDoneCheckbox.addEventListener('click', () => toggleTodoCompleteStatus(todoItem.id));

    const todoSpan = createElement('span');
    todoSpan.innerText = todoItem.text;

    const deleteTodoItemLink = createElement('a');
    deleteTodoItemLink.setAttribute('href', '#');
    deleteTodoItemLink.addEventListener('click', () => deleteTodoItem(todoItem.id));
    deleteTodoItemLink.innerText = '❌';

    if (todoItem.completed) {
      todoSpan.classList.add('done');
      markAsDoneCheckbox.setAttribute('checked', 'checked');
    }

    todoDiv.appendChild(markAsDoneCheckbox);
    todoDiv.appendChild(todoSpan);
    todoDiv.appendChild(deleteTodoItemLink);

    return todoDiv;
  }

  function refreshUi() {
    const todoItemsDiv = findById('todo-items');
    todoItemsDiv.innerHTML = '';
    todoService.getTodoItems().forEach(todoItem => todoItemsDiv.appendChild(createTodoDiv(todoItem)));
  }
})();