
dispatchEvent() / ์ด๋ฒคํธ ๋ฒ๋ธ๋ง ๋ง๋ ๋ฐฉ๋ฒ / event.preventDefault() / ์ด๋ฒคํธ ์์ / keydown๊ณผ keyup ๋น๊ต / ์ปค์คํ ๋ฐ์ดํฐ ์์ฑ
๋ด๊ฐ ์ง ์ฝ๋์ ๊ฐ์ ๋ด์ฉ ๋น๊ตยท๋ถ์ ๋ฐ ์์ (์ผํ ๋ชฉ๋ก ์ฑ ๋ง๋ค๊ธฐ)
์ต์ด ์ฝ๋๋ ์ด์ TIL ์ฐธ๊ณ
๊ฐ์๋ฅผ ๋ณธ ํ ๋ด ์ฝ๋์์ ์ฐจ์ด์ , ๋ฐฐ์ด ์ ์ ๋ฆฌ
๋๋ input์ ๋ณธ๋ฌธ์ ๋ฃ์๋๋ฐ, ๊ฐ์์์๋ input์ ๋ณธ๋ฌธ์ด ์๋๋ผ footer์ ๋ฃ์๋ค.
๋๋ ์ผํ ๋ชฉ๋ก๋ค์ด ์ถ๊ฐ๋ ๋ณธ๋ฌธ์ div๋ก ์ง์ ํด์ค ํ javascript์์ ๊ทธ ์์ ๋งํฌ์ ๋ชจ๋๋ฅผ ๋์ ์ผ๋ก ์๋ก ๋ง๋ค์ด ์ฃผ์๋๋ฐ, ๊ฐ์์์๋ ul๋ก ์ง์ ํด์ค ํ li, div, span, button์ html ๋ฌธ์์๋ ๋ชจ๋ ์ ์ด์ฃผ์๋ค. (javascript ์์ฑ ์ ์ฐธ๊ณ ์ฉ์ด์์, ๋ง์ง๋ง์ ์ง์ด๋ค)
์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ํจ์์ ์ด๋ฆ ์์๋ ํต์์ ์ผ๋ก on์ ๋ถ์ธ๋ค. ex) onAdd, onDelete, onClick ๋ฑ
๋๋ add ํจ์์ ์๋ก์ด ์์๋ฅผ ๋ง๋๋ ๊ฒ๊น์ง ์ ๋ถ ์ญ ์ผ๋๋ฐ, ๊ฐ์์์๋ createItem ํจ์๋ฅผ ๋ง๋ค์ด์ ๋ฐ๋ก ๋นผ๋๋ค.
๋๋ ํด์งํต ์์ด์ฝ์ ํด๋ฆญํด์ ๋ชฉ๋ก์ด ์ญ์ ๋๋ฉด input ์์ ๊ธ์๋ ์ญ์ ๋๋ ๊ฒ๊น์ง๋ง ๋ง๋ค์๋๋ฐ, ๊ฐ์์์๋ ์ฌ๊ธฐ์ ๋ค์ ์ปค์๊ฐ input ์ฐฝ์ ์๊ฒจ์ ์ฌ์ฉ์๊ฐ ๋ฐ๋ก ๊ธ์๋ฅผ ์
๋ ฅํ ์ ์๋๋ก ํ๋ค. document.querySelector('input').focus() ์ถ๊ฐ
document.querySelector('input').setAttribute('autoFocus') ์๋ ์ฃผ์
๋๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ createElement๋ฅผ ์ด์ฉํด ์๋กญ๊ฒ ์์๋ฅผ ๋ง๋ค ๋๋ง๋ค style ์์ฑ์ ์ด์ฉํด ์คํ์ผ์ ์ถ๊ฐํ ๋ฐ๋ฉด, ๊ฐ์์์๋ ์๋กญ๊ฒ ๋ง๋ ์์์ class๋ฅผ ๋ถ์ฌํด์ ๋ฏธ๋ฆฌ class๋ง๋ค ์ ์ํด๋ CSS ์คํ์ผ๋ง์ ์๋ก ๋ง๋ ์์์ ์
ํ๋ค.
๋๋ ๋ชฉ๋ก์ ์ด๋ฃจ๋ ์์๋ค ์ค ์ ์ผ ์์ ์์๋ง์ createElement๋ฅผ ์ด์ฉํด ๋ง๋ ํ ๊ทธ ๋ค์๋ถํด innerHTML์ ์ฌ์ฉํ๋๋ฐ, ๊ฐ์์์๋ ๋ชฉ๋ก์ ์ด๋ฃจ๋ ์์๋ค ์ ๋ถ๋ฅผ createElement๋ฅผ ์ด์ฉํด ๋ง๋ ํ appendChild๋ก ์์ ๋ฐ์ ์์๋ฅผ ๋ฃ์ด์คฌ๋ค.
createElement ํจ์๊ฐ '๋ชฉ๋ก'์ ๋ฐํํ ์ ์๋๋ก ๋ง์ง๋ง์ ๊ผญ return์ ์จ์ค์ผ ํ๋ค !
๊ฐ์์์๋ ๋ชฉ๋ก๋ค์ด ํ๋ฉด์ ๋์ด๋ณด๋ค ๊ธธ์ด์ง๋ฉด ์คํฌ๋กค์ ์ํด ์๋์ผ๋ก ๊ฐ์ฅ ์ต๊ทผ์ ์ถ๊ฐํ ๋ชฉ๋ก์ด ๋ณด์ฌ์ง๋๋ก scrollIntoView๋ฅผ ์ ์ฉํ๋ค.
๐ HTML
<html>
<body>
<section>
<header>
<h1>Shopping List</h1>
</header>
<ul class="items"></ul>
<footer>
<input class="footer-input" type="text">
<button class="footer-addBtn"><i class="fas fa-plus-circle"></i></button>
</footer>
</section>
</body>
<html>
๐ CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
button {
border-style: none;
background-color: transparent;
cursor: pointer;
color: rgb(82, 82, 82);
}
button:hover {
transform: scale(1.1);
color: rgb(106, 173, 151);
transition: all 300ms;
}
body {
font-family: "Gowun Batang", serif;
color: rgb(65, 65, 65);
}
section {
/* ์น์
๋๋น */
width: 80vw;
min-width: 300px;
max-width: 500px;
margin: 100px auto;
border-radius: 10px;
-webkit-box-shadow: 0 0 10px gray;
box-shadow: 0 0 10px gray;
}
header {
/* ํค๋ ๋์ด */
height: 70px;
text-align: center;
background: linear-gradient(70deg, rgb(196, 202, 255), rgb(220, 255, 255));
border-radius: 10px 10px 0 0;
}
h1 {
line-height: 2.2;
}
.items {
/* ul ๋์ด */
height: 50vh;
min-height: 300px;
background: rgb(245, 245, 245);
overflow: auto;
padding: 10px;
}
.item-row {
list-style: none;
padding: 10px 20px 0 20px;
}
.item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 10px;
}
.far {
font-size: 1.2em;
}
.item-line {
width: 100%;
height: 1px;
background-color: rgb(65, 65, 65);
margin: 0 auto;
}
footer {
background: linear-gradient(70deg, rgb(196, 202, 255), rgb(220, 255, 255));
border-radius: 0 0 10px 10px;
}
.footer-input {
/* input ๋๋น & ๋์ด */
width: 100%;
height: 40px;
font-family: "Gowun Batang", serif;
padding: 10px 10px;
border-style: none;
color: rgb(48, 48, 48);
}
.footer-input:focus {
outline: none;
-webkit-box-shadow: inset 0px 0px 5px 2px #b6b6b6;
box-shadow: inset 0px 0px 5px 2px #b6b6b6;
}
.footer-addBtn {
display: block;
margin: 0 auto;
font-size: 50px;
padding: 10px 0 5px 0;
}
::selection {
background-color: rgb(127, 197, 164);
color: white;
}
๐ javascript
const input = document.querySelector('input');
const addBtn = document.querySelector('.footer-addBtn');
const items = document.querySelector('.items');
// input ํ
์คํธ ๊ฐ ( input.value )
function onAdd () {
if (input.value === '') {
return;
} else {
const itemRow = createItem();
items.appendChild(itemRow);
itemRow.scrollIntoView();
input.value = '';
input.focus();
}
}
function createItem () {
const itemRow = document.createElement('li');
itemRow.classList.add('item-row');
const item = document.createElement('div');
item.classList.add('item');
const itemName = document.createElement('span');
itemName.classList.add('item-name');
itemName.innerHTML = input.value;
const DeleteBtn = document.createElement('button');
DeleteBtn.innerHTML = '<i class="far fa-trash-alt">';
DeleteBtn.classList.add('item-deleteBtn');
DeleteBtn.addEventListener('click', () => items.removeChild(itemRow));
const itemLine = document.createElement('div');
itemLine.classList.add('item-line');
item.appendChild(itemName);
item.appendChild(DeleteBtn);
itemRow.appendChild(item);
itemRow.appendChild(itemLine);
console.log(itemRow);
return itemRow;
}
addBtn.addEventListener('click', () => onAdd());
input.addEventListener('keyup', e => {
if (e.key === "Enter") {
onAdd();
} else {
return;
}
});
%20-%20OneNote%202021-09-28%20%EC%98%A4%ED%9B%84%2011_58_12.png)
DeleteBtn.addEventListener('click', () => items.removeChild(itemRow)); ๋ถ๋ถ ์์
โป ์ฌ๊ธฐ์๋ data-id์ ๊ฐ์ผ๋ก ๊ธ๋ก๋ฒ ์ซ์ ๋ณ์๋ฅผ ์ด์ฉํ์ง๋ง, ์๋ UUID๋ ์ค๋ธ์ ํธ์ ํด์ ์ฝ๋๋ฅผ ์ด์ฉํด ๊ณ ์ ํ ์์ด๋๋ฅผ ๋ง๋๋ ๊ฒ์ด ์ข๋ค.
const input = document.querySelector('input');
const addBtn = document.querySelector('.footer-addBtn');
const items = document.querySelector('.items');
function onAdd () {
if (input.value === '') {
return;
} else {
const itemRow = createItem();
items.appendChild(itemRow);
itemRow.scrollIntoView();
input.value = '';
input.focus();
}
}
// โ inneHTML ์ด์ฉํด์ '์ด๋ฒคํธ ํ๊น'๊ณผ '์ง์์ง ๋์'์ ๊ฐ์ data-id ๋ถ์ฌํ๊ธฐ
let id = 0
function createItem () {
const itemRow = document.createElement('li');
itemRow.classList.add('item-row');
itemRow.setAttribute('data-id', id);
itemRow.innerHTML = `
<div class="item">
<span class="item-name">${input.value}</span>
<button class="item-deleteBtn"><i class="far fa-trash-alt" data-id="${id}"></i></button>
</div>
<div class="item-line"></div>
`;
id++;
return itemRow;
}
addBtn.addEventListener('click', () => onAdd());
input.addEventListener('keydown', e => {
if (e.key === "Enter") {
onAdd();
} else {
return;
}
});
items.addEventListener('click', event => {
const id = event.target.dataset.id;
if (id) { // = event.target์ dataset์ id๊ฐ ์์ผ๋ฉด
const toBeDeleted = document.querySelector(`.item-row[data-id="${id}"]`);
toBeDeleted.remove();
}
});
<form class="footer-form">
<input class="footer-input" type="text">
<button type="submit" class="footer-addBtn"><i class="fas fa-plus-circle"></i></button>
</form>
const form = document.querySelector('.footer-form');
form.addEventListener('submit', event => {
event.preventDefault();
onAdd();
});