[Javascript] HTML5 DOM project
import ‘./assets/css/style.css‘;
const app = document.getElementById(‘app‘);
app.innerHTML = `
  <div class="todos">
    <div class="todos-header">
      <h3 class="todos-title">Todo List</h3>
      <div>
        <p>You have <span class="todos-count"></span> items</p>
        <button type="button" class="todos-clear" style="display: none;">
          Clear Completed
        </button>
      </div>
    </div>
    <form class="todos-form" name="todos">
      <input type="text" placeholder="What‘s next?" name="todo">
    </form>
    <ul class="todos-list"></ul>
  </div>
`;
// state
let todos = JSON.parse(localStorage.getItem(‘todos‘)) || [];
// selectors
const root = document.querySelector(‘.todos‘);
const list = root.querySelector(‘.todos-list‘);
const count = root.querySelector(‘.todos-count‘);
const clear = root.querySelector(‘.todos-clear‘);
const form = document.forms.todos;
const input = form.elements.todo;
// functions
function saveToStorage(todos) {
  localStorage.setItem(‘todos‘, JSON.stringify(todos));
}
function renderTodos(todos) {
  let todoString = ‘‘;
  todos.forEach((todo, index) => {
    todoString += `
      <li data-id="${index}"${todo.complete ? ‘ class="todos-complete"‘ : ‘‘}>
        <input type="checkbox"${todo.complete ? ‘ checked‘ : ‘‘}>
        <span>${todo.label}</span>
        <button type="button"></button>
      </li>
    `;
  });
  list.innerHTML = todoString;
  count.innerText = todos.filter(todo => !todo.complete).length;
  clear.style.display = todos.filter(todo => todo.complete).length
    ? ‘block‘
    : ‘none‘;
}
function addTodo(event) {
  event.preventDefault();
  const label = input.value.trim();
  const complete = false;
  todos = [
    ...todos,
    {
      label,
      complete,
    },
  ];
  renderTodos(todos);
  saveToStorage(todos);
  input.value = ‘‘;
}
function updateTodo(event) {
  // find span‘s parnet node‘s data-id attribute
  const id = parseInt(event.target.parentNode.getAttribute(‘data-id‘), 10);
  const complete = event.target.checked;
  todos = todos.map((todo, index) => {
    if (index === id) {
      return {
        ...todo,
        complete,
      };
    }
    return todo;
  });
  renderTodos(todos);
  saveToStorage(todos);
}
function editTodo(event) {
  // get current node tag name
  if (event.target.nodeName.toLowerCase() !== ‘span‘) {
    return;
  }
  const id = parseInt(event.target.parentNode.getAttribute(‘data-id‘), 10);
  const todoLabel = todos[id].label;
  const input = document.createElement(‘input‘);
  input.type = ‘text‘;
  input.value = todoLabel;
  function handleEdit(event) {
    // because list also has ‘change‘ event, so stop propgation
    event.stopPropagation();
    // this point to input
    const label = this.value;
    if (label !== todoLabel) {
      todos = todos.map((todo, index) => {
        if (index === id) {
          return {
            ...todo,
            label,
          };
        }
        return todo;
      });
      renderTodos(todos);
      saveToStorage(todos);
    }
    // clean up
    event.target.style.display = ‘‘;
    // this point to input element ref
    this.removeEventListener(‘change‘, handleEdit);
    // remove input element
    this.remove();
  }
  event.target.style.display = ‘none‘;
  event.target.parentNode.append(input);
  input.addEventListener(‘change‘, handleEdit);
  // focus has to be called in the last of function.
  // otherwise focus() has no effect
  input.focus();
}
function deleteTodo(event) {
  if (event.target.nodeName.toLowerCase() !== ‘button‘) {
    return;
  }
  const id = parseInt(event.target.parentNode.getAttribute(‘data-id‘), 10);
  // get button‘s sibling element span
  const label = event.target.previousElementSibling.innerText;
  if (window.confirm(`Delete ${label}?`)) {
    todos = todos.filter((todo, index) => index !== id);
    renderTodos(todos);
    saveToStorage(todos);
  }
}
function clearCompleteTodos() {
  const count = todos.filter(todo => todo.complete).length;
  if (count === 0) {
    return;
  }
  if (window.confirm(`Delete ${count} todos?`)) {
    todos = todos.filter(todo => !todo.complete);
    renderTodos(todos);
    saveToStorage(todos);
  }
}
// init
function init() {
  renderTodos(todos);
  // Add Todo
  form.addEventListener(‘submit‘, addTodo);
  // Update Todo
  list.addEventListener(‘change‘, updateTodo);
  // Edit Todo
  list.addEventListener(‘dblclick‘, editTodo);
  // Delete Todo
  list.addEventListener(‘click‘, deleteTodo);
  // Complete All Todos
  clear.addEventListener(‘click‘, clearCompleteTodos);
}
init(); 相关推荐
  往后余生    2020-09-17  
   CXsilent    2020-09-16  
   webgm    2020-08-16  
   sqliang    2020-06-14  
   xcguoyu    2020-06-13  
   徐建岗网络管理    2020-06-11  
   前端开发Kingcean    2020-06-11  
   cbao    2020-06-10  
   yezitoo    2020-06-06  
   bigname    2020-06-04  
   前端开发Kingcean    2020-05-29  
   xiaofanguan    2020-05-29  
   ELEMENTS爱乐小超    2020-05-28  
   皖林    2020-05-11  
   wbczyh    2020-05-03  
   zuihaobushi    2020-04-30  
   89500297    2020-04-29