diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..355e71f Binary files /dev/null and b/.DS_Store differ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0a72520 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6b665aa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} diff --git a/index.html b/index.html index d241b1b..3c1f304 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,23 @@ -
+
+
+
📚 투두리스트
+
+ + +
+
+
+

📋 TO DO ()

+ +
+ +
- + diff --git a/reset.css b/reset.css new file mode 100644 index 0000000..e2c4153 --- /dev/null +++ b/reset.css @@ -0,0 +1,117 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, +body, +div, +span, +applet, +object, +iframe, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} +body { + line-height: 1; +} + +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/script.js b/script.js index b0ec50d..6398ecf 100644 --- a/script.js +++ b/script.js @@ -1 +1,77 @@ -// 다들 화이팅!! ٩( *˙0˙*)۶ \ No newline at end of file +const todoInput = document.getElementById('todo-input'); // 할 일 입력창 +const todoList = document.getElementById('todo-list'); // 할 일 리스트창 +const addTodoBtn = document.getElementById('add-todo-btn'); // 버튼 +const doneTodoList = document.getElementById('done-todo-list'); // 완료된 할 일 리스트창 +const todoListTitle = document.getElementById('todo-list-title'); // 할 일 제목 +const doneTodoListTitle = document.getElementById('done-todo-list-title'); // 완료된 할 일 제목 + +// input으로 입력 받은 할 일을 리스트창에 추가 +function addTodo(event) { + event.preventDefault(); // form 태그의 기본 새로고침 기능 지우기 + + const $li = document.createElement('li'); + const $btn = document.createElement('button'); + + const todoText = todoInput.value.trim(); + + //공백 방지 + if (!todoText) { + alert('공백은 입력할 수 없습니다.'); + } + + $li.innerText = todoText; + todoList.appendChild($li); + todoInput.value = ''; // 입력 필드 초기화 + todoInput.focus(); // 입력 필드로 커서 이동 + + $li.appendChild($btn); + $btn.innerText = '❌'; + + // 삭제 버튼 클릭 시 해당 li 삭제 + $btn.addEventListener('click', (e) => { + e.stopPropagation(); // 이벤트 전파 막기 -> li태그의 자식요소로 삭제버튼이 있기 때문에 버튼을 눌러도 완료항목으로 이동하는 문제발생 + removeTodo(li, true); + }); + todoFlagCount(true); + + $li.addEventListener('click', () => doneTodo($li)); +} + +addTodoBtn.addEventListener('click', addTodo); + +// 완료 +function doneTodo(liItem) { + let doneLi = document.createElement('li'); + let doneBtn = document.createElement('button'); + + doneLi.innerText = liItem.innerText.replace('❌', ''); // *텍스트만 가져오기* + doneTodoList.appendChild(doneLi); + + doneBtn.innerText = '❌'; + doneLi.appendChild(doneBtn); + + doneBtn.addEventListener('click', () => { + removeTodo(doneLi, false); + }); + // 원래 todo 목록에서 삭제 + liItem.remove(); + todoFlagCount(true); + todoFlagCount(false); +} + +// 할 일 삭제 +function removeTodo(liItem, isTodo) { + liItem.remove(); + todoFlagCount(isTodo); +} + +// 할 일 개수 업데이트 +function todoFlagCount(isTodo) { + if (isTodo) { + let count = todoList.getElementsByTagName('li').length; + todoListTitle.innerText = `📋 TO DO (${count})`; + } else { + let count = doneTodoList.getElementsByTagName('li').length; + doneTodoListTitle.innerText = `💿 DONE (${count})`; + } +} diff --git a/style.css b/style.css index dd32f0e..4d59b2c 100644 --- a/style.css +++ b/style.css @@ -1 +1,94 @@ -/* 자유롭게 디자인 해 주세요! */ \ No newline at end of file +@import './reset.css'; + +* { + font-family: 'SpoqaHanSansNeo-Regular'; +} +html, +body { + margin: 0; +} +body { + width: 100vw; + height: 100vh; + display: flex; + align-items: center; + justify-content: center; + background: radial-gradient(#e66465, #9198e5); +} +.container { + display: flex; + flex-direction: column; + width: 360px; + height: 600px; + border-radius: 20px; + background-color: white; + box-shadow: 0 0 25px rgba(0, 0, 0, 0.25); +} +.header-wrapper { + flex-direction: row; +} +header { + margin: 5% 5% 0; + font-size: 24px; +} +.input-box { + display: flex; + align-items: center; + justify-content: center; + border-bottom: 1px solid lightgray; + padding: 5%; +} +#todo-input { + width: 80%; + height: 60%; + margin: 1%; + padding: 5%; + border: 0.5px solid gray; + border-radius: 15px; +} +#add-todo-btn { + height: 60%; + margin: 1%; + border: 0px; + background-color: transparent; + cursor: pointer; +} +.body { + height: 40%; + display: flex; + flex-direction: column; + border-bottom: 1px solid lightgray; +} +#todo-list-title { + margin: 18px; +} +.footer { + height: 40%; + display: flex; + flex-direction: column; +} +#done-todo-list-title { + margin: 18px; +} + +ul { + height: 70%; + overflow: auto; + + padding-left: 40px; +} + +li { + margin: 0 16px 16px; +} + +#done-todo-list:nth-child(2) { + color: lightgray; + text-decoration: line-through; +} + +li > button { + margin-left: 10px; + background: transparent; + border: 0px; +}