https://hydeveloper.tistory.com/170 ์์ ์์ง ํ์ง ๋ชปํ ์ฌํ ๊ณผ์ (3) : ๋๋๊ทธ ์ค ๋๋กญ์ผ๋ก ์์์ ์์น ๋ฐ๊พธ๊ธฐ (์ ๋ ฌํ๊ธฐ) ๋ฅผ ๊ตฌํํ๊ณ ์ ํ๋ค.
์ด์ ์์ draggable ์์ฑ๊ณผ drag ์ด๋ฒคํธ๋ฅผ ์์๋ฌ์ผ ํ๋ค.
draggable ์์ฑ
draggable = "true"๋ฅผ ๋ถ์ฌํ๋ฉด ์ด๋ค ์์๋ ๋๋๊ทธ๋ ์ ์๋ ๊ฐ์ฒด๋ก ๋ณํํ ์ ์๋ค.
drag ์ด๋ฒคํธ
(mdn : https://developer.mozilla.org/ko/docs/Web/API/HTMLElement/drag_event)
drag | ๋๋๊ทธ๊ฐ ๊ฐ๋ฅํ ๋์์์ ๋ฐ์ |
dragstart | ๋๋๊ทธ๋ฅผ ์์ํ ๋ ๋ฐ์ |
dragend | ๋๋๊ทธ๊ฐ ์ข ๋ฃ๋ ๋ ๋ฐ์ |
dragover | ๋๋๊ทธํ๋ฉด์ ๋ง์ฐ์ค๊ฐ ๋์ ๊ฐ์ฒด ์์ ์์ ๋ ๋ฐ์ |
dragenter | ๋๋๊ทธํ๋ฉด์ ๋ง์ฐ์ค๊ฐ ๋์ ๊ฐ์ฒด ์๋ก ์ฒ์ ์ง์ ํ ๋ ๋ฐ์ (1ํ) |
dragleave | ๋๋๊ทธํ๋ฉด์ ๋ง์ฐ์ค๊ฐ ๋์ ๊ฐ์ฒด ์์์ ๋ฒ์ด๋ ๋ ๋ฐ์ |
drop | ๋๋๊ทธํ ์์๊ฐ ๋์ ๊ฐ์ฒด ์์ ๋์ฌ์์ ๋ ๋ฐ์ |
์์ธํ ์ค์ต ์์ ๋ ์๋ ์ฌ์ดํธ๋ค์ ์ถ์ฒํ๋ค.
https://ko.javascript.info/mouse-drag-and-drop
๋๋๊ทธ ์ค ๋๋กญ ์ค๋น
์ฐ์ li์๊ฒ draggable = true ์์ฑ์ ์ถ๊ฐํด์ค๋ค. (๊ทธ๋์ผ ๋๋๊ทธ ์ค ๋๋กญ์ด ๊ฐ๋ฅํจ)
li.setAttribute("draggable", true);
// ๋ฆฌ์คํธ์ ๋ฃ๊ธฐ ์ ์ ์ถ๊ฐํ๊ธฐ
todoList.append(li);
๊ทธ๋ฆฌ๊ณ ํญ๋ชฉ์ ๋๋๊ทธํ๋ ๋๋์ ์ฃผ๊ธฐ ์ํด ์คํ์ผ์ ์กฐ๊ธ ๋ ์ถ๊ฐํ๋ค.
#todo-list li {
cursor: pointer;
padding: 10px;
display: flex;
align-items: center;
border-bottom: 1px solid #ddd;
/* ์ถ๊ฐ */
border-radius: 10px;
background-color: #fff;
}
๋๋๊ทธ ์ค ๋๋กญ์ผ๋ก ๋ฆฌ์คํธ ์ ๋ ฌ
๋๋๊ทธ ์ค ๋๋กญ์ผ๋ก ๋ฆฌ์คํธ๋ฅผ ์ ๋ ฌํ๊ธฐ ์ํด์๋
1) ํ์ฌ ๋๋๊ทธํ๊ณ ์๋ ์์์ ์ธ๋ฑ์ค,
2) ํ์ฌ ๋๋๊ทธ๊ฐ over๋ ์์น(๊ทธ๋์ผ ๊ทธ ์์น๋ก ์ด๋ํ ์ ์๊ธฐ ๋๋ฌธ)
๊ฐ ํ์ํ๋ค.
* ์ธ๋ฑ์ค ๊ตฌํ๊ธฐ
์ธ๋ฑ์ค๋ฅผ ๊ตฌํ๋ ํจ์๋ Array.prototype.indexOf()์ผ๋ก ๊ตฌํ๋๋ฐ, ์ด๋ prototype ๋ถ๋ถ์ ๋ฐฐ์ด์ด ์๋ ๊ฐ์ฒด์์ ์ธ๋ฑ์ค๋ฅผ ๊ตฌํ๊ณ ์ ํ ๋์ ๊ฐ์ฒด๋ฅผ ๋ฃ์ผ๋ฉด ๋๋ค.
Array.from์ ์ํ ๊ฐ๋ฅ ๋๋ ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด์์ ์๊ฒ ๋ณต์ฌ๋ ์๋ก์ด Array ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค. ์ฆ element์ ๋ถ๋ชจ์์์ ์์๋ค์ ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด๋ก ์ทจ๊ธํ๊ณ , ์ด ์ค element์ ์ธ๋ฑ์ค๋ฅผ ๊ตฌํ๋ ๊ฒ์ด๋ค.
const index = Array.from(element.parentNode.children).indexOf(element)
์ด๋ฅผ ์ด์ฉํด ๋๋๊ทธ๋ ์์, ๋๋กญ๋ ์์(์ ์์น)๋ฅผ ๊ตฌํ ์ ์๋ค.
1) ๋๋๊ทธ ์์
// liDrag : ํ์ฌ ๋๋๊ทธ ํ๊ณ ์๋ ์์๋ฅผ ๋ด์ ๋ณ์
let liDrag;
let dragIndex;
// ๋๋๊ทธ ์์ํ์ ๋
li.addEventListener("dragstart", function(e) {
// ํ๊ฒ์ ํ๊ทธ๊ฐ li๊ฐ ์๋๋ผ๋ฉด
if (e.target.tagName.toLowerCase() !== 'li') {
liDrag = e.currentTarget; // ์์ <li> ์์๋ก ์ ํ
} else {
liDrag = e.target;
}
// # ๋ฐฉ๋ฒ 1
dragIndex = Array.from(liDrag.parentNode.children).indexOf(liDrag);
// # ๋ฐฉ๋ฒ 2
// ํผ์นจ์ฐ์ฐ์ ... : ๋ฐฐ์ด์ ํฌํจ๋ ํญ๋ชฉ๋ค์ ๋ชฉ๋ก์ผ๋ก ๋ฐ๊ฟ์ค๋ค.
// const listArr์ ๊ฒฝ์ฐ currentItem.parentElement์ ์์์ธ children๋ชฉ๋ก๋ค์ []์ ๋ด์ ๋ฐฐ์ด ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๊ฒ ๋๋ค.
// const listArr = [...liDrag.parentElement.children];
// let liDragIndx = listArr.indexOf(liDrag);
})
dragstart ์ด๋ฒคํธ๊ฐ ์ผ์ด๋ฌ์ ๋,
ํ๊ฒ์ liDrag์ ๋ด๊ณ
๋ถ๋ชจ์์์์ ํด๋น ํ๊ฒ์ด ๋ช๋ฒ์งธ์ธ์ง ์ธ๋ฑ์ค๋ฅผ ์ฐพ์๋ด ๊ทธ ์ธ๋ฑ์ค๋ฅผ ๋ค๋ฅธ ๋ณ์์ ๋ด๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ด๋ค.
ํ๊ทธ์ ํ๊ฒ์ด li๊ฐ ์๋ ๋ (์ผ๋จ ์ถ๊ฐ๋์ด์๋ ๋ณ์ li(ํ ์ผ ๋ชฉ๋ก์ ๋ด๊ณ ์๋ liํ๊ทธ ๋ง์)๋ก ๋ง๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ด๊ธฐ ๋๋ฌธ์ ๊ทธ ์์์์๋ ๊ด์ฐฎ๋ค.
๋ฌธ์ ๋ li์ ์ถ๊ฐ๋์ด์๋ ์ฒดํฌ๋ฐ์ค(Input), ํ ์ผ ๋ด์ฉ์ ์ถ๋ ฅ(span), ์ญ์ ๋ฒํผ... ํ์์์๊ฐ ์ ํ๋ ์๋ ์๊ธฐ ๋๋ฌธ์, ๊ทธ ๊ฒฝ์ฐ์๋ currentTarget ์์ฑ์ ์ฌ์ฉํด ๋ฐ๋ก ์์์์์ธ li๋ฅผ ์ ํํ๋๋ก ํด์ค๋ค.
2) ๋๋๊ทธ ๋๋ ๋์ค
๊ทธ ์์ค ๋๋๊ทธ ํ๋ ๋์์ ๊ณ์ dragover๊ฐ ๋์ด์๊ธฐ ๋๋ฌธ์ (ulํ๊ทธ ์์์ ๊ณ์ dragover ํ๊ธฐ ๋๋ฌธ) dragover์ผ ์ ๊ณ์ ์๋ก๊ณ ์นจ์ ๋ฐฉ์งํ๊ธฐ ์ํด e.preventDefault)๋ฅผ ์ถ๊ฐํ๋ค.
todoList.addEventListener('dragover', (e) => {
e.preventDefault();
});
3) ๋๋กญํ์ ๋
๋ง์ง๋ง drop์ ์ด๋ฒคํธ๋ค...
todoList.addEventListener("drop", (e) => {
e.preventDefault();
let liDrop;
// ์์ ์์์ ๋์ ๊ฒฝ์ฐ
if (e.target.tagName.toLowerCase() == 'li') {
liDrop = e.target;
} else {
return;
}
const dropIndex = Array.from(liDrop.parentNode.children).indexOf(liDrop);
// after() : ์ ํํ ์์์ ๋ฐ๋ก ๋ค์ ์ ์์ ์ถ๊ฐ
// before() : ์ ํํ ์์์ ๋ฐ๋ก ์์ ์ ์์ ์ถ๊ฐ
if (dragIndex < dropIndex) {
liDrop.after(liDrag);
} else {
liDrop.before(liDrag);
}
์ผ๋จ drop ์ ์๋ก๊ณ ์นจ ๋๋ ํ์์ ๋ง๊ธฐ ์ํด e.preventDefault();๋ฅผ ์ถ๊ฐํ๊ณ
๋ณ์ liDrag๋ ๋๋๊ทธ ํ ๋ณ์๋ฅผ Dropํด์ผ ํ๋ฏ๋ก ์ด๋ฒคํธ ํธ๋ค๋ฌ์์๋ง์ด ์๋ makeToDoList ํจ์ ์ ์ฒด์์ ๋ค ์ธ ์ ์๋ ์ง์ญ๋ณ์๋ก ์ค์ ํด๋จ๋ค.
๋ฐ๋ฉด liDrop์ ๊ฒฝ์ฐ์๋ ๋๋กญ๋๋ ํ๊ฒ (์์น)์ ์๋ฏธํ๊ธฐ ๋๋ฌธ์ drop ์ด๋ฒคํธ์์๋ง ์ฌ์ฉํด๋ ๋๋ค. ๋๋ฌธ์ ํด๋น ์ด๋ฒคํธ ํธ๋ค๋ฌ ์์์ ์ ์ธํ๋ค.
dragstart ์ด๋ฒคํธ๊ฐ ์ผ์ด๋ฌ์ ๋์ฒ๋ผ ์ฒ์์ if๋ฌธ์ด ๋ณด์ด๋๋ฐ ๋ด์ฉ์ ๋ดํ์ด๋ค.
drop์์ liํ๊ทธ๋ค๋ผ๋ฆฌ๋ง ์์๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ถ๊ธฐ ๋๋ฌธ์, if๋ฌธ์ผ๋ก target์ ํ๊ทธ๊ฐ li์ผ๋๋ง liDrop์ ํ๊ฒ์ ๋์ ํ๋๋ก ์์ ํ๋ค. ์๋ ๊ฒฝ์ฐ๋ return์ผ๋ก ์์ ํด๋น ์ด๋ฒคํธ๋ฅผ ์ค์ง์ํจ๋ค. dropIndex๋ dragIndex๋ฅผ ๊ตฌํ๋ ๊ณผ์ ๊ณผ ๊ฐ๋ค.
๋ง์ง๋ง์ ์ ๋ ฌ์ด๋ค.
dragIndex๊ฐ dropIndex๋ณด๋ค ์์ผ๋ฉด after()๋ฉ์๋๋ก liDrag์ ๋ค ์์๋ก liDrop์ ์ถ๊ฐํ๋ค. ๋ฐ๋์ ๊ฒฝ์ฐ์๋ before()๋ฅผ ์ด์ฉํด liDrag์ ์ด์ , ์ฆ ์์ liDrop์ ์ถ๊ฐํ๋ค.
ํด๊ฒฐ๋์ง ์์๋ ๋ถ๋ถ
if๋ฌธ์ ๋ง์ฝ dragํ ์์๊ฐ ul(์์์์)์ผ ๊ฒฝ์ฐ, ์๋๋ฉด ํ์์์์ ๋์ ๊ฒฝ์ฐ, ๊ทธ ์ธ๋ก ๊ตฌ๋ถ์ง์๋๋ฐ ์ฌ๊ธฐ์ ๋ญ๊ฐ ์๋ชป๋ ๊ฒ ๊ฐ๊ธดํ๋ค.. (๋ฌธ์ ์ ์ ์๋์ ์ ์ด๋จ๋ค.)
๋ถ๋ชจ์์๋ฅผ ์ ํํ์ ๋ e.target == liDrag.parentElement ๋ฑ์ผ๋ก๋ ์ ํํด๋ดค๋๋ฐ ์ฝ์์ฐฝ์์ ๊ณ์ ์ ํ์ด ์๋๋๊ฑธ ๋ณด์ํ๋ ์ด๋ถ๋ถ์ ๋ฌธ์ ๊ฐ ๋์ง ์๋ ๋ฏ ํ๋ค.
๋ฌธ์ ๋ else if๋ฌธ์ผ๋ก e.target์ ํ๊ทธ๋ค์์ด li๊ฐ ์๋๊ฒฝ์ฐ (ํ์์์ ์์ผ๋ก ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ๊ฐ ์์ด ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํจ์) ๊ตฌ๊ธ๋งํด์ ๋๋๊ทธ๋ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์๋๋ฐ ์๋ฌด๋๋ liํ๊ทธ๊ฐ ์๋ todoList(ulํ๊ทธ๋ถ๋ถ)์ด ์ ํ๋ ๋ ul์ ์์ํ๊ทธ์ธ todoContainer๊ฐ ์ ํ๋ผ ๊ฑฐ๊ธฐ๋ก ๋น ์ ธ๋๊ฐ๋ ๊ฒ ๊ฐ๋ค...



์๋ฒฝ์ ๋จธ๋ฆฌ๊ฐ ํฐ์ง๋ ์ค ์์๋๋ฐ ์ ์ฌ๋ ๋ ํ๊ฒ๋จน๊ณ ์ปคํผ๋ง์๋ฉด์ ๋ถํ๋ฏ์ด ๊ทธ๋ผ li๋นผ๊ณ ๋ง์๋ฒ๋ฆฌ๋ฉด ์๋๋๋ ์๊ฐ์ด ๋ ์ฌ๋ผ ํด๊ฒฐ๋์๋ค...
๋๋๊ทธ์ค ๋๋กญ ๋ถ๋ถ ์ ์ฒด ์ฝ๋
// ๏ฝฅ๏พ*๏ฝก๏ฝฅ ๏ฝก*๏ฝฅ๏พ ๋๋๊ทธ ์ด๋ฒคํธ ๏ฝฅ๏พ*๏ฝก๏ฝฅ ๏ฝก*๏ฝฅ๏พ
let liDrag;
let dragIndex;
// ๋๋๊ทธ ์์ํ์ ๋
todoList.addEventListener('dragstart', function (e) {
// ๋ง์ฝ ํ๊ฒ์ด liํ๊ทธ๊ฐ ์๋๋ผ๋ฉด?
if (e.target.tagName.toLowerCase() !== 'li') {
liDrag = e.currentTarget; // ์์ <li> ์์๋ก ์ ํ
} else {
liDrag = e.target;
}
// ์ 4๋ฒ์ฉ ์ถ๋ ฅ๋๋๊ฑด๊ฐ...
// console.log(liDrag.parentNode);
dragIndex = Array.from(liDrag.parentNode.children).indexOf(liDrag);
});
// drop ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ํ์ํจ
todoList.addEventListener('dragover', (e) => {
e.preventDefault();
});
todoList.addEventListener('drop', (e) => {
e.preventDefault();
e.stopPropagation();
// ํ๊ฒ์ด ๋๋ ์์๊ฐ ์ด๋ ๊ฒฝ์ฐ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ง์ผ ๋ถ๋ชจ ์์์ drop ๋๋ ๊ฒฝ์ฐ ํ์ถํ๋ค.
let liDrop;
if (e.target.tagName.toLowerCase() == 'li') {
liDrop = e.target;
} else {
return;
}
const dropIndex = Array.from(liDrop.parentNode.children).indexOf(liDrop);
// after() : ์ ํํ ์์์ ๋ฐ๋ก ๋ค์ ์ ์์ ์ถ๊ฐ
// before() : ์ ํํ ์์์ ๋ฐ๋ก ์์ ์ ์์ ์ถ๊ฐ
if (dragIndex < dropIndex) {
liDrop.after(liDrag);
} else if (dragIndex > dropIndex){
liDrop.before(liDrag);
} else {
return;
}
});
์์ฑ๋ณธ.. : https://stackblitz.com/edit/vitejs-vite-5bbnvx8a?embed=1&file=script.js
JavaScript 5์ผ์ฐจ (forked) - StackBlitz
A Vite project based on vite
stackblitz.com
์ฐธ๊ณ
https://duklook.tistory.com/399
'javascript' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
javascript/์์ ๋ณต์ฌ์ ๊น์ ๋ณต์ฌ (0) | 2025.03.20 |
---|---|
javascript/chart.js๋ก ๊ทธ๋ํ ๋ง๋ค๊ธฐ (0) | 2025.03.19 |
250313 to-do ๋ฆฌ์คํธ ๋ง๋ค๊ธฐ (1) (1) | 2025.03.13 |
javascript/var๋ฅผ ๋์ด์ ์ฌ์ฉํ์ง ์๋ ์ด์ (2) | 2025.03.12 |
250307 ํ๋ก๊ทธ๋๋จธ์ค (0) | 2025.03.07 |