zoukankan      html  css  js  c++  java
  • [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();
    

      

  • 相关阅读:
    Python 字典(Dictionary)
    Python函数
    Python 模块
    一步步学习SPD2010--第二章节--处理SP网站(9)---- 关键点
    一步步学习SPD2010--第二章节--处理SP网站(8)---- 保存和使用网站模板
    一步步学习SPD2010--第二章节--处理SP网站(7)---- 导航网站的内容
    一步步学习SPD2010--第二章节--处理SP网站(6)---- 探索SP网站
    一步步学习SPD2010--第二章节--处理SP网站(5)附—升级自定义SP网站的复杂性
    一步步学习SPD2010--第二章节--处理SP网站(5)--重置网站模板
    一步步学习SPD2010--第二章节--处理SP网站(4)--删除SP网站
  • 原文地址:https://www.cnblogs.com/Answer1215/p/13205235.html
Copyright © 2011-2022 走看看