For practice JavaScript I created simple To-do app.
This app can add TODOs and track the number of total TODOs as well as the number of unchecked TODOs.
For this I written 4 functions:
- for add newTodo - newTodo(), where I add new todo to todos array
- for render list of todo - drawTodoList(), where I also add event listener to each checkbox item
- confirmCheck() for change state of todo checked property
- countItem() for counting all items and unchecked items
My questions:
- was it right to use innerHTML to add li items?
- adding event listener to all checkboxes in my case takes 4 line (in end drawTodoList). How can I short this?
- how can I improve my function countItem()?
const todos = []
let newTodoId = 0
let checkboxes
let checkboxArray
const classNames = {
TODO_ITEM: 'todo-container',
TODO_CHECKBOX: 'todo-checkbox',
TODO_TEXT: 'todo-text',
TODO_DELETE: 'todo-delete',
}
const list = document.getElementById('todo-list')
const itemCountSpan = document.getElementById('item-count')
const uncheckedCountSpan = document.getElementById('unchecked-count')
function newTodo() {
let getTodo = prompt("Add new to-do", "")
if(getTodo == null || getTodo == "") {
console.log("you don't add new to-do")
} else {
todos.push({
id: newTodoId ++,
text: getTodo,
isChecked: false,
})
drawTodoList()
}
}
function drawTodoList() {
const liItem = todos.map((todo) => {
if (!todo.isChecked) {
return `<li id=${todo.id} class=${classNames.TODO_ITEM}>
<input type='checkbox' class=${classNames.TODO_CHECKBOX}>${todo.text}</li>`
} else {
return `<li id=${todo.id} class=${classNames.TODO_ITEM}>
<input type='checkbox' class=${classNames.TODO_CHECKBOX} checked>${todo.text}</li>`
}
})
list.innerHTML = liItem.join('')
checkboxes = document.querySelectorAll('input[type=checkbox]')
checkboxArray = Array.from(checkboxes)
checkboxArray.forEach(function(checkbox) {
checkbox.addEventListener('change', confirmCheck)
})
countItem()
}
function confirmCheck() {
let checkedToDo = todos.find(todo => {
return todo.id == this.parentElement.id
})
checkedToDo.isChecked = !checkedToDo.isChecked
countItem()
}
function countItem() {
let itemCount = document.querySelectorAll('input[type="checkbox"]').length
let checkedCount = document.querySelectorAll('input[type="checkbox"]:checked').length
let uncheckedCount = itemCount - checkedCount
itemCountSpan.innerHTML = itemCount
uncheckedCountSpan.innerHTML = uncheckedCount
}
.center {
align-self: center;
}
.flow-right {
display: flex;
justify-content: space-around;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 10px;
display: flex;
flex-direction: column;
background-color: white;
height: 100vh;
}
.title, .controls, .button {
flex: none;
}
.button {
padding: 10px 20px;
}
<!DOCTYPE html>
<html>
<head>
<title>TODO App</title>
<link rel="stylesheet" type="text/css" href="./styles.css" />
</head>
<body>
<div class="container center">
<h1 class="center title">My TODO App</h1>
<div class="flow-right controls">
<span>Item count: <span id="item-count">0</span></span>
<span>Unchecked count: <span id="unchecked-count">0</span></span>
</div>
<button class="button center" onClick="newTodo()">New TODO</button>
<ul id="todo-list" class="todo-list"></ul>
</div>
<script src="./script.js"></script>
</body>
</html>