const $todos = document.querySelector('.todos');
const $inputTodo = document.querySelector('.input-todo');
const $custom = document.querySelector('.custom-checkbox');
const $btn = document.querySelector('.btn');
let $active = document.querySelector('.active-todos');
const $nav = document.querySelector('.nav'); //css nav클래스의 ul엘리먼트를 $nav변수에 할당
let todos = [];
function render() {
let html = '';
todos.forEach(({ id, content, completed }) => {
html += `<li id="${id}" class="todo-item"><input class="custom-checkbox" type="checkbox" ${completed ? 'checked' : ''} id="ck-${id}"><label for="ck-${id}">${content}</label><i class="remove-todo far fa-times-circle"></i></li>`;
});
$active.innerHTML = todos.length;
document.querySelector('.completed-todos').innerHTML = todos.filter(todo => todo.completed).length;
$todos.innerHTML = html;
}
function generateId() {
return todos.length ? Math.max(...todos.map(todo => todo.id)) + 1 : 1;
}
function toggleCompletedAll(check) {
todos = todos.map(todo => Object.assign({}, todo, { completed: check }));
}
$inputTodo.onkeyup = function (e) {
const content = $inputTodo.value.trim();
if (content === '' || e.keyCode !== 13) return;
$inputTodo.value = '';
todos = [{ id: generateId(), content, completed: false }, ...todos];
render();
};
$todos.onclick = (e) => {
if (!e.target.classList.contains('remove-todo')) return;
todos = todos.filter(todo => todo.id !== +e.target.parentNode.id);
render();
};
$todos.onchange = function (e) {
const id = +e.target.parentNode.id;
todos = todos.map(todo => (todo.id === id ? Object.assign({},
todo, { completed: !todo.completed }) : todo));
render();
};
$custom.onchange = function (e) {
toggleCompletedAll(e.target.checked);
render();
};
$btn.onclick = function () {
todos = todos.filter(todo => !todo.completed);
render();
};
//나브중 무엇인가 누르면 누른애의 부모 클래스를 다지우고, '그'눌려진 li에 클래스를 추가한다.
$nav.onclick = function (e) { //ul태그가 눌리면(자식포함), 이벤트발생 및 함수실행(매개변수 이벤트)
// 여기서 e는 click 이벤트, console.log(e.target);은 li 라인
//$nav.children에는 nav의 자식요소들중 txtnode 제외한 친구들
//$nav.childNode에는 nav 자식 요소들중 text노드까지 포함해서
if (e.target.nodeName === 'LI') { //만약, li의 노드네임이 LI면,node네임은 대문자 반환
let arr = [...$nav.children] 유사배열을 배열로 바꾸어, 풀어서 arr변수에 할당한다
arr.forEach(name => { //배열이 됬으니 고차함수인 forEach메소드를 사용해서
name.classList.remove('active'); //요소값인 name이라는것에 클래스리스트에 active를제거
}); // 검사해서 li인 애들의 li태그전체에 class제거
if (e.target.id === 'all') { //이벤트 발생한 타겟(li)의 id가 all이면,
e.target.classList.add('active'); //발생한 li에 클래스 active추가
render(); 화면랜더함수 호출
}
if (e.target.id === 'active') { //이벤트 발생한 타겟(li)의 id가 active면
let html = ' '; // html 변수 설정해두고
e.target.classList.add('active'); 발생한 li에 클래스에 active추가
act = todos.filter(todo => { act라는 변수에, 필터메소드를 활용해 todo라는 요소값으로
return !todo.completed; 요소값의 프로퍼티가 completed가 아닌애들을 리턴한다
});
act.forEach(({ id, content, completed }) => { // act배열을 forEach문으로
html += `<li id="${id}" class="todo-item"><input class="custom-checkbox" type="checkbox" ${completed ? 'checked' : ''} id="ck-${id}"><label for="ck-${id}">${content}</label><i class="remove-todo far fa-times-circle"></i></li>`;
}); //html변수에 누적
$todos.innerHTML = html; 누적한변수를 전역 ul에 출력한다
}
if (e.target.id === 'completed') { // 발생한타겟의 아이디가 컴플리티드면
e.target.classList.add('active'); // 발생한타겟에 클래스 active추가
let html = ' '; // html변수 하나 구해두고
com = todos.filter(todo => { com이라는 변수에 배열을 필터하는데, todo라는 요소값으로
return todo.completed; 요소값의 프로퍼티가 completed인애들을 리턴해서 할당
});
com.forEach(({ id, content, completed }) => { com이라는 배열을 forEach문으로
html += `<li id="${id}" class="todo-item"><input class="custom-checkbox" type="checkbox" ${completed ? 'checked' : ''} id="ck-${id}"><label for="ck-${id}">${content}</label><i class="remove-todo far fa-times-circle"></i></li>`;
}); //html 변수에 누적
$todos.innerHTML = html; // 전역 ul에 html에 할당해준다
}
}
}
// 오늘 배운것은 classList와 className의 차이 ,childNodes와 childrend의차이
// 클래스 리스트는 메소드를 사용할 수 있다(컨테인,에드,리무브) 추가삭제는 클래스 리스트를 사용해야한다
// 클래스 네임은 클래스 이름만 알 수있다 class = 'active'에서 active
// $nav.childNodes // 애는 택스트노드까지 다포함, $nav.childrend은 택스트노드 제외
// 배열메소드들을 잘알면 좀더 문제해결이 쉬웠을것이다 forEach,map,filter,reduce
반응형