코딩테스트를 보러갔는데.. 자바스크립트로 심플한 투두리스트를 만드는 과제였다.
마크업과 스타일링은 20분?정도 걸렸는데 문제는... 자바스크립트를 다 까먹어서 ㅋㅋㅋㅋ...
추가하는 기능까진 만들었는데... 시간이 없어서 나머지는 못 만들었다. 그래서 만들어본 투두리스트..
자바스크립트 공부 좀 열심히 해야겠다 ^^;
To-Do List
구조
<div class="container">
<h1>
<span>✍️</span>
<span>T</span>
<span>o</span>
<span>-</span>
<span>D</span>
<span>o</span>
<span></span>
<span>L</span>
<span>i</span>
<span>s</span>
<span>t</span>
</h1>
<div id="newtask">
<input type="text" placeholder="Write task here!" />
<button id="push">Add</button>
</div>
<div id="tasks"></div>
</div>
h1태그에선 CSS로 애니메이션 효과를 주고싶어서 span으로 쪼갰습니다.
// 폰트
@font-face {
font-family: "SUITE-Regular";
src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2304-2@1.0/SUITE-Regular.woff2")
format("woff2");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: "PyeongChangPeace-Bold";
src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2206-02@1.0/PyeongChangPeace-Bold.woff2")
format("woff2");
font-weight: 700;
font-style: normal;
}
*,
*:before,
*:after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background: rgb(255, 173, 208);
background: linear-gradient(
133deg,
rgba(255, 173, 208, 1) 0%,
rgba(173, 154, 255, 1) 100%
);
}
// 컨테이너
.container {
width: 40%;
min-width: 450px;
position: absolute;
margin: 0 auto;
left: 0;
right: 0;
top: 30px;
padding: 30px 40px;
}
.container h1 {
margin-bottom: 20px;
}
// 제목 애니메이션
h1 span {
position: relative;
top: 10px;
display: inline-block;
animation: bounce 0.3s ease infinite alternate;
font-family: "PyeongChangPeace-Bold";
font-size: 30px;
color: #000000;
text-shadow: 0 0.5px 0 #d6a8ff, 0 2px 0 #d6a8ff, 0 3px 0 #d6a8ff,
0 4px 0 #d6a8ff, 0 5px 0 #d6a8ff, 0 6px 0 transparent, 0 7px 0 transparent,
0 8px 0 transparent, 0 9px 0 transparent, 0 10px 10px rgba(0, 0, 0, 0.4);
}
h1 span:nth-child(2) {
animation-delay: 0.05s;
}
h1 span:nth-child(3) {
animation-delay: 0.07s;
}
h1 span:nth-child(4) {
animation-delay: 0.09s;
}
h1 span:nth-child(5) {
animation-delay: 0.11s;
}
h1 span:nth-child(6) {
animation-delay: 0.13s;
}
h1 span:nth-child(7) {
animation-delay: 0.15s;
}
h1 span:nth-child(8) {
animation-delay: 0.17s;
}
h1 span:nth-child(9) {
animation-delay: 0.19s;
}
h1 span:nth-child(10) {
animation-delay: 0.21s;
}
h1 span:nth-child(11) {
animation-delay: 0.23s;
}
@keyframes bounce {
100% {
top: -3px;
text-shadow: 0 1px 0 #fff, 0 2px 0 #fff, 0 3px 0 #fff, 0 4px 0 #fff,
0 5px 0 #fff, 0 6px 0 #fff, 0 7px 0 #fff, 0 8px 0 #fff, 0 9px 0 #fff,
0 50px 25px rgba(0, 0, 0, 0.2);
}
}
// 인풋박스
#newtask {
position: relative;
background-color: #ffffff;
padding: 30px 20px;
border-radius: 5px;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.169);
}
#newtask input {
width: 70%;
width: 70%;
height: 45px;
font-family: "SUITE-Regular", sans-serif;
font-size: 15px;
border: 2px solid #d1d3d4;
padding: 12px;
color: #111111;
font-weight: 500;
position: relative;
border-radius: 5px;
}
#newtask input:focus {
outline: none;
border-color: #8052ec;
}
// Add 버튼
#newtask button {
position: relative;
float: right;
width: 20%;
height: 45px;
border-radius: 5px;
font-family: "SUITE-Regular", sans-serif;
font-weight: 500;
font-size: 16px;
background-color: #8052ec;
border: none;
color: #ffffff;
cursor: pointer;
outline: none;
}
// 리스트
#tasks {
background-color: #ffffff;
padding: 30px 20px;
margin-top: 60px;
border-radius: 10px;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
width: 100%;
position: relative;
}
.task {
background-color: #ffffff;
height: 50px;
padding: 5px 10px;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid #d1d3d4;
cursor: pointer;
}
.task span {
font-family: "SUITE-Regular", sans-serif;
font-size: 15px;
font-weight: 400;
}
// 삭제 버튼
.task button {
background-color: #8052ec;
color: #ffffff;
height: 100%;
width: 40px;
border-radius: 5px;
border: none;
cursor: pointer;
outline: none;
}
// 완료 토글
.completed {
text-decoration: line-through;
}
스크립트
// 엔터 기능
document
.querySelector("#newtask input")
.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
addNewTask();
}
});
// add 버튼
document.querySelector("#push").onclick = function () {
addNewTask();
};
function addNewTask() {
if (document.querySelector("#newtask input").value.length == 0) {
alert("리스트를 작성해주세요!");
} else {
// 현재 입력된 값을 가져옴
const newTaskValue = document.querySelector("#newtask input").value;
// 새로운 항목을 생성
const newTaskHTML = `
<div class="task">
<span id="taskname">
${newTaskValue}
</span>
<button class="delete">
<i class="far fa-trash-alt"></i>
</button>
</div>
`;
// 기존의 tasks에 최신순으로 쌓기
document
.querySelector("#tasks")
.insertAdjacentHTML("afterbegin", newTaskHTML);
// 삭제 버튼
const current_tasks = document.querySelectorAll(".delete");
for (let i = 0; i < current_tasks.length; i++) {
current_tasks[i].onclick = function () {
this.parentNode.remove();
};
}
// 완료 토글 기능
const tasks = document.querySelectorAll(".task");
for (let i = 0; i < tasks.length; i++) {
tasks[i].onclick = function () {
this.classList.toggle("completed");
};
}
// 입력 필드 초기화
document.querySelector("#newtask input").value = "";
}
}
1. 이벤트 리스너 등록
#newtask input 요소에 키보드 이벤트 리스너를 등록합니다.
keypress 이벤트가 발생하면, 이벤트 객체의 key 속성을 확인하여 Enter 키인지 확인하고, Enter 키가 눌렸다면 addNewTask 함수를 호출합니다.
2. 추가 버튼 클릭 이벤트 핸들러
#push 요소(추가 버튼)를 클릭했을 때 addNewTask 함수를 호출합니다.
3. addNewTask 함수
입력 필드(#newtask input)의 값이 비어있으면 알림창을 띄웁니다.
값이 비어있지 않으면 새로운 항목을 생성하고, 이를 투두리스트에 추가합니다.
추가된 항목에는 삭제 버튼과 완료 토글 기능이 추가되어 있습니다.
마지막으로 입력 필드를 초기화합니다.
완성된 화면과 코드
https://github.com/YeoDaSeul4355/web2023/tree/main/javascirpt/project/todo
728x90
반응형