#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. Я уже изменил обе вещи (посмотрите на последнее обновление кода), но проблема все еще существует, вы можете попробовать, как это работает…