TIL 16 | To-do List 만들기 리뷰

hyounglee·2020년 7월 25일
0

JavaScript

목록 보기
7/46
post-thumbnail

jQuery 로 만들어봤던 To-do List를 순수 Javascript로 다시 만들어본다.

To-do List 페이지
To-do List 깃허브

JS function

1. 클릭해서 To-Do 가로선 그리기


var list = document.querySelector("ul");

list.addEventListener("click", function(event){
	if (event.target.tagName === "LI") {
		event.target.classList.toggle("completed");
	}
}, false);
  • event.target : 이벤트가 발생된 속성
  • event.target.tagName : 속성의 tagName을 파악할 수 있다. 태그는 대문자로 작성한다.
  • Element.classList : 엘리먼트의 클래스 속성의 컬렉션인 활성 DOMTokenList를 반환하는 읽기 전용 프로퍼티이다.

classList와 사용되는 Methods

add( String [, String [, ...]] )
지정한 클래스 값을 추가한다. 만약 추가하려는 클래스가 엘리먼트의 class 속성에 이미 존재한다면 무시한다.
remove( String [, String [, ...]] )
지정한 클래스 값을 제거한다. (존재하지 않는 클래스를 제거하는 것은 에러를 발생시키지 않는다.)
item( Number )
콜렉션의 인덱스를 이용하여 클래스 값을 반환한다.
toggle( String [, force] )
하나의 인수만 있을 때: 클래스 값을 토글링한다. 즉, 클래스가 존재한다면 제거하고 false를 반환하며, 존재하지 않으면 클래스를 추가하고 true를 반환한다.
두번째 인수가 있을 때: 두번째 인수가 true로 평가되면 지정한 클래스 값을 추가하고 false로 평가되면 제거한다.
contains( String )
지정한 클래스 값이 엘리먼트의 class 속성에 존재하는지 확인한다.
replace( oldClass, newClass )
존재하는 클래스를 새로운 클래스로 교체한다.

출처 : https://developer.mozilla.org/ko/docs/Web/API/Element/classList

  • false : useCapture 라 불리는 Boolean값으로, 이벤트 버블링이나 캡쳐링을 사용할것인지 나타낸다.

이벤트의 발생 순서

태그가 중첩되어 있고, 자식과 부모가 똑같은 이벤트를 가지고 있는 경우
자식을 클릭했을 때 부모, 자식 중 어떤 요소부터 이벤트를 처리할 지 지정(생략가능)

false : 기본값. 클릭된 자식부터 최상위 부모까지 상위로 이동하며 이벤트를 처리(Event Bubbling)
true : 최상위 부모부터 하위로 이동하며 이벤트를 처리(Event Capturing)

캡처링이나 버블링은 자식과 부모가 같은 이벤트가 적용됬을 때만 발생하고, 다른 이벤트를 가지고 있으면 발생하지 않는다. 보통 같은 이벤트 속성이 들어있다면, 내가 클릭한 엘리먼트의 이벤트만 발생시키고자 하는 경우가 많음. 이 경우, 발생하고자 하는 이벤트에 e.stopPropagation(); 추가 하면 전파를 막을 수 있음

출처: https://ibrahimovic.tistory.com/62 [Web Standard]

2. <span> 클릭시 To-Do 삭제하기

list.addEventListener("click", function(event){
	if (event.target.tagName === "SPAN") {
		var parent = event.target.parentNode;
		parent.remove();
	}
})
  • event.target.parentNode : 바로 위의 부모태그
  • .childNode : 바로 아래 자식태그
  • .nextSibling : 형제태그

심화내용 참고하기 : https://grace-go.tistory.com/79

3. input 설정하기

var input = document.querySelector("input[type='text']")

input.addEventListener("keypress", function(event){
	if (event.which === 13){
		// input 에서 텍스트 가져오기
		var todoText = this.value;
		// 새로운 li 추가하기
		var newLi = "<li><span><i class=\"fa fa-trash-alt\"></i></span> " + todoText +"</li>";
		list.innerHTML += newLi;
		input.value = "";
	}
})
  • event.which : keypress된 키의 유니코드 value를 가져온다.
  • event.which === 13 : enter(code 13)키를 눌렀다면 작동한다.
  • this.value : input 된 텍스트 value이다.
  • .innerHTML : QuerySelector로 가져온 도큐먼트 오브젝트의 내용이나, 내부 HTML 코드를 JavaScript 코드에서 변경 할 수 있다.
  • .innerText : HTML 코드가 그대로 입력되지 않으며, 텍스트로 입력된다.

keyCode event value 확인하는 사이트 : https://css-tricks.com/snippets/javascript/javascript-keycodes/
참고자료 : https://ofcourse.kr/js-course/innerHTML-속성

4. + 아이콘 토글

var plus = document.querySelector(".fa-plus")

plus.addEventListener("click", function(event){
	if (input.style.display === "none") {
		input.style.display = "block";
		event.target.classList.toggle("rotated")
	} else {
		input.style.display = "none";
		event.target.classList.toggle("rotated")
	}
})

궁금한 것

input.style.displaytoggle로 바꿀 수 있을까? replace를 써야하는 건가....
조금 더 간단하게 코드 구현이 가능할 것 같은데...

HTML 소스

지난 주에 배웠던 open graph를 사용해봤다. fontawesome 활용하여 아이콘도 추가했다.

<!DOCTYPE html>
<html lang="en" dir="ltr">
	<head>
		<meta charset="utf-8">

		<meta property="og:type" content="website">
    		<meta property="og:site_name" content="To-Do List">
    		<meta property="og:title" content="To-Do List">
    		<meta property="og:description" content="당신에게 중요한 것들을 대신 기억해드려요!">
    		<meta property="og:image" content="assets/img/og.png">
    		<meta property="og:url" content="https://https://miajlee.github.io/todos/">

		<title>Todo List</title>
		<link rel="stylesheet" type="text/css" href="assets/css/todos.css">
		<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>

	</head>
	<body>
		<div id="container">
			<h1>To-Do List<i class="fal fa-plus rotated"></i></h1>
			<input type="text" placeholder="Add New Todo">

			<ul>
				<li><span><i class="fa fa-trash-alt"></i></span> TIL 작성하기</li>
				<li><span><i class="fa fa-trash-alt"></i></span> 여름휴가 숙소 예약하기</li>
				<li><span><i class="fa fa-trash-alt"></i></span> 수민이 생일선물 사기</li>
				<li><span><i class="fa fa-trash-alt"></i></span> 포기하지 않기 &#128580;</li>
			</ul>

		</div>

		<script type="text/javascript" src="assets/js/todos.js"></script>
	</body>
</html>

CSS 코드

body {
	background: #12c2e9;
	background: -webkit-linear-gradient(to right, #f64f59, #c471ed, #12c2e9);
	background: linear-gradient(to right, #f64f59, #c471ed, #12c2e9);
	font-family: "Apple SD Gothic Neo";
}

h1 {
	background: #000;
	color: white;
	margin: 0;
	padding: 10px 20px;
	font-size: 24px;
	font-weight: 600;
}

ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

li {
	background: #fff;
	height: 40px;
	line-height: 40px;
	color: #333;
}

li:nth-child(2n) {
	background: #f7f7f7;
}

li:hover span {
	width: 40px;
	opacity: 1.0;
}

span {
	background-color: #e74c3c;
	color: white;
	height: 40px;
	margin-right: 20px;
	text-align: center;
	width: 0px;
	display: inline-block;
	transition: 0.2s linear;
	opacity: 0;
}

input {
	font-size: 18px;
	background: #f7f7f7;
	width: 100%;
	padding: 13px 13px 13px 20px;
	border-style: none;
	box-sizing: border-box;
	color: #000;
}

input:focus {
	background-color: #fff;
	border: 3px solid #000;
	outline: none;
}

#container {
	width: 400px;
	margin: 100px auto;
	background: #f7f7f7;
	box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
}

.completed {
	color: gray;
	text-decoration: line-through;
}

.fa-plus {
	float: right;
}

.rotated {
  transform: rotate(45deg);
}

JavaScript 소스

// 클릭해서 TODO 가로선 그리기

var list = document.querySelector("ul");

list.addEventListener("click", function(event){
	if (event.target.tagName === "LI") {
		event.target.classList.toggle("completed");
	}
}, false);

// span 클릭시 TODO 삭제하기
list.addEventListener("click", function(event){
	if (event.target.tagName === "SPAN") {
		var parent = event.target.parentNode;
		parent.remove();
	}
})

// input 설정
var input = document.querySelector("input[type='text']")

input.addEventListener("keypress", function(event){
	if (event.which === 13){
		// input 에서 텍스트 가져오기
		var todoText = this.value;
		// 새로운 li 추가하기
		var newLi = "<li><span><i class=\"fa fa-trash-alt\"></i></span> " + todoText +"</li>";
		list.innerHTML += newLi;
		input.value = "";
	}
})

// + 아이콘 토글
var plus = document.querySelector(".fa-plus")

plus.addEventListener("click", function(event){
	if (input.style.display === "none") {
		input.style.display = "block";
		event.target.classList.toggle("rotated")
	} else {
		input.style.display = "none";
		event.target.classList.toggle("rotated")
	}
})

jQuery 소스 (원작업)

자바스크립트에 비해 코드가 훨씬 간단해진다. JS에서 To-Do 삭제시 fadeOut되는 것을 구현하지 못했다.

// Check Off Specific Todos By Clicking
$("ul").on("click", "li", function(){
	$(this).toggleClass("completed");
});

// Click on X to delete Todo
$("ul").on("click", "span", function(event){
	$(this).parent().fadeOut(500, function(){
		$(this).remove();
	});
	event.stopPropagation();
});

$("input[type='text']").keypress(function(event){
	if(event.which === 13){
		//grabbing a new todo text from input
		var todoText = $(this).val();
		$(this).val(""); 
		//create a new li and add to ul
		$("ul").append("<li><span><i class=\"fa fa-trash-alt\"></i></span> " + todoText + "</li>");
	};
});


$(".fa-plus").click(function(){
	$("input[type='text']").fadeToggle();
});
profile
(~˘▾˘)~♫❝ 쉽게만 살아가면 재미없어 빙고 .ᐟ ❞•*¨*•.¸¸♪

1개의 댓글

comment-user-thumbnail
2020년 7월 31일

와 확실이 jQuery 코드 길이가 훨씬 짧네요!

답글 달기