Завершенные и незавершенные задачи

#javascript #html #css

#javascript #HTML #css

Вопрос:

 //selectors

const todoInput = document.querySelector('.todo-input');
const todoButton = document.querySelector('.todo-button');
const todoList = document.querySelector('.todo-list');
const filterOption = document.querySelector('.filter-todo');
//event listeners
todoButton.addEventListener("click", addTodo);
todoList.addEventListener('click', deleteCheck);
filterOption.addEventListener('click', filterTodo);

//funtions
function addTodo(event) {

    //prevent form from submiting
    event.preventDefault();


/// todo div

const todoDiv = document.createElement("div");
todoDiv.classList.add("todo");

//create li
const newTodo = document.createElement('li');
newTodo.innerText = todoInput.value;
newTodo.classList.add('todo-item');
todoDiv.appendChild(newTodo);

//check mark button
const completedButton = document.createElement('button');
completedButton.innerHTML= '<i class="fas fa-check"></i>';
completedButton.classList.add("complete-btn");
todoDiv.appendChild(completedButton);
//check trash button
const trashButton = document.createElement('button');
trashButton.innerHTML= '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
todoDiv.appendChild(trashButton);

//append to list
todoList.appendChild(todoDiv);

//clear todoinput value
todoInput.value="";


}

function deleteCheck(e){
    const item = e.target;
    //delete todo
    if(item.classList[0] === 'trash-btn'){
      const todo = item.parentElement;

      //animation
      todo.classList.add("fall");
      todo.addEventListener("transitionend", function(){
        todo.remove();
      });


     
    }

    //check mark
  if (item.classList[0] === "complete-btn") {
      const todo =  item.parentElement;
      todo.classList.toggle("completed");
  }
    
}

function filterTodo(e) {
    const todos = [...todoList.children];
    todos.forEach(function(todo) {
        switch (e.target.value) {
            case "all":
                todo.style.display = "flex";
                break;
                case "completed":
                    if (todo.classList.contains("completed")) {
                        todo.style.display = "flex";

                    } else {
                        todo.style.display = "none";
                    }
                    case "uncompleted":
                        if(!todo.classList.contains("completed")) {
                            todo.style.display = "flex";
                        } else {
                            todo.style.display = "none";
                        }
                   
        }
    });

}  
 * {
    font-family: 'Montserrat', sans-serif;
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    color: white;
    min-height: 100vh;
    background-image: linear-gradient(120deg, #f6d365, #fda085);
}
header{
    font-size: 1.5rem;

}

header,form{
    min-height: 20vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

form input, form button{
    padding: 0.5rem;
    font-size: 2rem;
    border: none;
    background: white;

}

form button{
    color: #d88771;
    background: white;
    cursor: pointer;
    transition: all 0.3s ease;

}
form button:hover{
    background: #d88771;
    color: white;
}

.todo-container{
    display: flex;
    justify-content: center;
    align-items: center;

}
.todo-list{
    min-width: 30%;
    list-style: none;

}
.todo {
    margin: 0.5rem;
    background: white;
    color: black;
    font-size: 1.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition: all 0.5s ease;
    
}
.todo li{
    flex: 1;
}
.trash-btn, .complete-btn{
    background: #ff6f47;
    color: white;
    padding: 1rem;
    border: none;
    cursor: pointer;
    font-size: 1rem;
}


.complete-btn{
    background: rgb(73,204,73);
}
.todo-item{
    padding: 0rem 0.5rem;
}
.fa-trash, .fa-check{
    pointer-events: none;;
}

.completed{
    text-decoration: line-through;
    opacity: 0.5;
}
.fall{
    transform: translateY(8rem) rotateZ(20deg);
    opacity: 0;
}

select{
   -webkit-appearance: none;
   -moz-appearance: none;
   appearance: none;
   outline: none;
   border: none;
}

.select{
    margin: 1rem;
    position: relative;
    overflow: hidden;

}
select{
    color: #ff6f47;
    width: 10rem;
    cursor: pointer;
    padding: 1rem;
}
.select::after{
    content: "25BC";
    position: absolute;
    background: #ff6f47;
    top: 0;
    right: 0;
    padding: 1rem;
    pointer-events: none;
    transition: all 0.3s ease;
}

.select:hover::after{
    background: white;
    color: #ff6f47;
}  
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" integrity="sha512- 4zCK9k qNFUR5X cKL9EIR ZOhtIloNl9GIKS57V1MyNsYpYcUrUeQc9vNfzsWfV28IaLL3i96P9sdNyeRssA==" crossorigin="anonymous" />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;800amp;amp;display=swap" rel="stylesheet">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To do list</title>
</head>
<body>
   <header>
       <h1>Yours todos</h1>
   </header>
   <form>
       <input type="text" class="todo-input">
       <button class="todo-button" type="submit">
           <i class="fas fa-plus-square"></i>
       </button>
       <div class="select">
           <select name="todos" class="filter-todo">
               <option value="all">All</option>
               <option value="completed">Completed</option>
               <option value="uncompleted">Uncompleted</option>
           </select>
       </div>
   </form>

   <div class="todo-container">
       <ul class="todo-list">
          
       </ul>
   </div>

    <script src="app.js"></script>
</body>
</html>  

When im use menu with completed and all its popin :

 Uncaught TypeError: Cannot set property 'display' of undefined
    at app.js:79
    at NodeList.forEach (<anonymous>)
    at HTMLSelectElement.filterTodo (app.js:76)
  

 //selectors

const todoInput = document.querySelector('.todo-input');
const todoButton = document.querySelector('.todo-button');
const todoList = document.querySelector('.todo-list');
const filterOption = document.querySelector('.filter-todo');
//event listeners
todoButton.addEventListener("click", addTodo);
todoList.addEventListener('click', deleteCheck);
filterOption.addEventListener('click', filterTodo);

//funtions
function addTodo(event) {

    //prevent form from submiting
    event.preventDefault();


/// todo div

const todoDiv = document.createElement("div");
todoDiv.classList.add("todo");

//create li
const newTodo = document.createElement('li');
newTodo.innerText = todoInput.value;
newTodo.classList.add('todo-item');
todoDiv.appendChild(newTodo);

//check mark button
const completedButton = document.createElement('button');
completedButton.innerHTML= '<i class="fas fa-check"></i>';
completedButton.classList.add("complete-btn");
todoDiv.appendChild(completedButton);
//check trash button
const trashButton = document.createElement('button');
trashButton.innerHTML= '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
todoDiv.appendChild(trashButton);

//append to list
todoList.appendChild(todoDiv);

//clear todoinput value
todoInput.value="";


}

function deleteCheck(e){
    const item = e.target;
    //delete todo
    if(item.classList[0] === 'trash-btn'){
      const todo = item.parentElement;

      //animation
      todo.classList.add("fall");
      todo.addEventListener("transitionend", function(){
        todo.remove();
      });


     
    }

    //check mark
  if (item.classList[0] === "complete-btn") {
      const todo =  item.parentElement;
      todo.classList.toggle("completed");
  }
    
}

function filterTodo(e) {
    const todos = todoList.childNodes;
    todos.forEach(function(todo) {
        switch (e.target.value) {
            case "all":
                todo.style.display = "flex";
                break;
                case "completed":
                    if (todo.classList.contains("completed")) {
                        todo.style.display = "flex";

                    } else {
                        todo.style.display = "none";
                    }
                    
        }
    });
}  
 * {
    font-family: 'Montserrat', sans-serif;
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    color: white;
    min-height: 100vh;
    background-image: linear-gradient(120deg, #f6d365, #fda085);
}
header{
    font-size: 1.5rem;

}

header,form{
    min-height: 20vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

form input, form button{
    padding: 0.5rem;
    font-size: 2rem;
    border: none;
    background: white;

}

form button{
    color: #d88771;
    background: white;
    cursor: pointer;
    transition: all 0.3s ease;

}
form button:hover{
    background: #d88771;
    color: white;
}

.todo-container{
    display: flex;
    justify-content: center;
    align-items: center;

}
.todo-list{
    min-width: 30%;
    list-style: none;

}
.todo {
    margin: 0.5rem;
    background: white;
    color: black;
    font-size: 1.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition: all 0.5s ease;
    
}
.todo li{
    flex: 1;
}
.trash-btn, .complete-btn{
    background: #ff6f47;
    color: white;
    padding: 1rem;
    border: none;
    cursor: pointer;
    font-size: 1rem;
}


.complete-btn{
    background: rgb(73,204,73);
}
.todo-item{
    padding: 0rem 0.5rem;
}
.fa-trash, .fa-check{
    pointer-events: none;;
}

.completed{
    text-decoration: line-through;
    opacity: 0.5;
}
.fall{
    transform: translateY(8rem) rotateZ(20deg);
    opacity: 0;
}

select{
   -webkit-appearance: none;
   -moz-appearance: none;
   appearance: none;
   outline: none;
   border: none;
}

.select{
    margin: 1rem;
    position: relative;
    overflow: hidden;

}
select{
    color: #ff6f47;
    width: 10rem;
    cursor: pointer;
    padding: 1rem;
}
.select::after{
    content: "25BC";
    position: absolute;
    background: #ff6f47;
    top: 0;
    right: 0;
    padding: 1rem;
    pointer-events: none;
    transition: all 0.3s ease;
}

.select:hover::after{
    background: white;
    color: #ff6f47;
}  
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" integrity="sha512- 4zCK9k qNFUR5X cKL9EIR ZOhtIloNl9GIKS57V1MyNsYpYcUrUeQc9vNfzsWfV28IaLL3i96P9sdNyeRssA==" crossorigin="anonymous" />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;800amp;amp;display=swap" rel="stylesheet">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To do list</title>
</head>
<body>
   <header>
       <h1>Yours todos</h1>
   </header>
   <form>
       <input type="text" class="todo-input">
       <button class="todo-button" type="submit">
           <i class="fas fa-plus-square"></i>
       </button>
       <div class="select">
           <select name="todos" class="filter-todo">
               <option value="all">All</option>
               <option value="completed">Completed</option>
               <option value="uncompleted">Uncompleted</option>
           </select>
       </div>
   </form>

   <div class="todo-container">
       <ul class="todo-list">
          
       </ul>
   </div>

    <script src="app.js"></script>
</body>
</html>  

Im tring to build to do list but i have problem with show completed and uncompleted todos code looks good but its poppin a type error. I dont know its popin problem with the display if i try to display other stuff its diplaed normaly .Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the i [

 //selectors

const todoInput = document.querySelector('.todo-input');
const todoButton = document.querySelector('.todo-button');
const todoList = document.querySelector('.todo-list');
const filterOption = document.querySelector('.filter-todo');
//event listeners
todoButton.addEventListener("click", addTodo);
todoList.addEventListener('click', deleteCheck);
filterOption.addEventListener('click', filterTodo);

//funtions
function addTodo(event) {

    //prevent form from submiting
    event.preventDefault();


/// todo div

const todoDiv = document.createElement("div");
todoDiv.classList.add("todo");

//create li
const newTodo = document.createElement('li');
newTodo.innerText = todoInput.value;
newTodo.classList.add('todo-item');
todoDiv.appendChild(newTodo);

//check mark button
const completedButton = document.createElement('button');
completedButton.innerHTML= '<i class="fas fa-check"></i>';
completedButton.classList.add("complete-btn");
todoDiv.appendChild(completedButton);
//check trash button
const trashButton = document.createElement('button');
trashButton.innerHTML= '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
todoDiv.appendChild(trashButton);

//append to list
todoList.appendChild(todoDiv);

//clear todoinput value
todoInput.value="";


}

function deleteCheck(e){
    const item = e.target;
    //delete todo
    if(item.classList[0] === 'trash-btn'){
      const todo = item.parentElement;

      //animation
      todo.classList.add("fall");
      todo.addEventListener("transitionend", function(){
        todo.remove();
      });


     
    }

    //check mark
  if (item.classList[0] === "complete-btn") {
      const todo =  item.parentElement;
      todo.classList.toggle("completed");
  }
    
}

function filterTodo(e) {
    const todos = todoList.childNodes;
    todos.forEach(function(todo) {
        switch (e.target.value) {
            case "all" :
                todo.style.display = "flex";
                break;
                case "completed":
                    if(todo.classList.contains("done")) {
                        todo.style.display = "flex";

                    } else {
                        todo.style.display = "none";
                    }
        }
    });
}  
 * {
    font-family: 'Montserrat', sans-serif;
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    color: white;
    min-height: 100vh;
    background-image: linear-gradient(120deg, #f6d365, #fda085);
}
header{
    font-size: 1.5rem;

}

header,form{
    min-height: 20vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

form input, form button{
    padding: 0.5rem;
    font-size: 2rem;
    border: none;
    background: white;

}

form button{
    color: #d88771;
    background: white;
    cursor: pointer;
    transition: all 0.3s ease;

}
form button:hover{
    background: #d88771;
    color: white;
}

.todo-container{
    display: flex;
    justify-content: center;
    align-items: center;

}
.todo-list{
    min-width: 30%;
    list-style: none;

}
.todo {
    margin: 0.5rem;
    background: white;
    color: black;
    font-size: 1.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition: all 0.5s ease;
    
}
.todo li{
    flex: 1;
}
.trash-btn, .complete-btn{
    background: #ff6f47;
    color: white;
    padding: 1rem;
    border: none;
    cursor: pointer;
    font-size: 1rem;
}


.complete-btn{
    background: rgb(73,204,73);
}
.todo-item{
    padding: 0rem 0.5rem;
}
.fa-trash, .fa-check{
    pointer-events: none;;
}

.completed{
    text-decoration: line-through;
    opacity: 0.5;
}
.fall{
    transform: translateY(8rem) rotateZ(20deg);
    opacity: 0;
}

select{
   -webkit-appearance: none;
   -moz-appearance: none;
   appearance: none;
   outline: none;
   border: none;
}

.select{
    margin: 1rem;
    position: relative;
    overflow: hidden;

}
select{
    color: #ff6f47;
    width: 10rem;
    cursor: pointer;
    padding: 1rem;
}
.select::after{
    content: "25BC";
    position: absolute;
    background: #ff6f47;
    top: 0;
    right: 0;
    padding: 1rem;
    pointer-events: none;
    transition: all 0.3s ease;
}

.select:hover::after{
    background: white;
    color: #ff6f47;
}  
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" integrity="sha512- 4zCK9k qNFUR5X cKL9EIR ZOhtIloNl9GIKS57V1MyNsYpYcUrUeQc9vNfzsWfV28IaLL3i96P9sdNyeRssA==" crossorigin="anonymous" />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;800amp;amp;display=swap" rel="stylesheet">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To do list</title>
</head>
<body>
   <header>
       <h1>Yours todos</h1>
   </header>
   <form>
       <input type="text" class="todo-input">
       <button class="todo-button" type="submit">
           <i class="fas fa-plus-square"></i>
       </button>
       <div class="select">
           <select name="todos" class="filter-todo">
               <option value="all">All</option>
               <option value="done">done</option>
               <option value="uncompleted">Uncompleted</option>
           </select>
       </div>
   </form>

   <div class="todo-container">
       <ul class="todo-list">
          
       </ul>
   </div>

    <script src="app.js"></script>
</body>
</html>  

Комментарии:

1. Что такое полное сообщение об ошибке?

2. Я не знаю, почему я не могу добавить фотографию, поэтому я просто добавляю cpo и вставляю здесь: app.js:79 Неперехваченная ошибка типа: не удается установить свойство ‘display’ для undefined в app.js:79 в NodeList.forEach (<анонимный>) в HTMLSelectElement.filterTodo (app.js:76) (анонимный) @ app.js:79 filterTodo @ app.js:76

Ответ №1:

Метод filterTodo

 const todos = todoList.childNodes;
  

Свойство childNodes возвращает коллекцию дочерних узлов узла в виде объекта NodeList.
Пробелы внутри элементов рассматриваются как текст, а текст рассматривается как узлы. Комментарии также рассматриваются как узлы.

Вам нужны только узлы элементов, чтобы получить узлы элементов, используйте дочернее свойство

 const todos = todoList.children;
  

Это вернет HTMLCollection, который не является обычным массивом, который вы можете перебирать, вам нужно преобразовать его в простой массив, для этого используйте оператор распространения (…)

 const todos = [...todoList.children];
  

Решение

 function filterTodo(e) {
    const todos = [...todoList.children];
    todos.forEach(function(todo, index) {
        switch (e.target.value) {
            case "all" :
                todo.style.display = "flex";
                break;
            case "completed":
                if(todo.classList.contains("completed")) {
                    todo.style.display = "flex";
                }
                else {
                    todo.style.display = "none";
                }
                break;
            case "uncompleted":
                if(!todo.classList.contains("completed")) {
                    todo.style.display = "flex";
                }
                else {
                    todo.style.display = "none";
                }
                break;
        }
    });
}
  

Комментарии:

1. У меня есть еще одна проблема, теперь она не показывает другим дочерним элементам «завершено». Я обновляю код, взгляните. Я должен создать другое свойство для этих дочерних элементов?

2. В списке опций вы используете done класс, в то время как в вашем filterTodo методе вы сопоставляете со completed значением. Это создает проблему. Кроме того, вы не добавили регистр переключения для uncompleted задач. Просто используйте это условие => if(!todo.classList.contains("completed"))

3. Я уже изменил обе вещи (посмотрите на последнее обновление кода), но проблема все еще существует, вы можете попробовать, как это работает…