진정한 아코디언 형식으로 이제 쌉가능하지만, ... 다만!! 리스트가 비게 되면 더이상 추가가 되지 않기 때문에 ㅠ.ㅠ 만일 내가 옮기려는 아이템이 그 해당 sub에서 단 1개뿐이었다면 이동후 다시 취소 시킨다.
HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test_3</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script src="./main.js" type="module"></script>
</head>
<body>
이렇게 하면.. 리스트가 비었을때 ㅎ.. 더이상 안 들어가...
<ul id="myUL">
<li>
<div class="d1">A.나는 드래그 하면 안되양~~~</div>
<ul class="sub">
<li class="d2-item">001</li>
<li class="d2-item">002</li>
<li class="d2-item">003</li>
</ul>
</li>
<li>
<div class="d1">B.나는 드래그 하면 안되양~~~</div>
<ul class="sub">
<li class="d2-item">가가가</li>
<li class="d2-item">나나나나나나나</li>
<li class="d2-item">다ㅏㅏㅏㅏㅏㅏㅏ</li>
</ul>
</li>
<li>
<div class="d1">A.나는 드래그 하면 안되양~~~</div>
<ul class="sub">
<li class="d2-item">001</li>
<li class="d2-item">002</li>
<li class="d2-item">003</li>
</ul>
</li>
</ul>
</body>
</html>
|
cs |
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@charset "utf-8";
*{margin:0;padding:0;box-sizing:border-box;}
html,body{width:100%;min-height:100vh;}
li{list-style-type:none;}
#myUL{
position:relative;
margin:3rem auto; padding:10px;
width:500px;
border:1px solid black;}
#myUL li{
position:relative;
width:100%;}
.d1{
padding:1.5em 1.5em;
border:1px solid black;
user-select:none;}
.sub{
min-height:57px;
}
.d2-item{
margin:10px 0; padding:.8em 1.5em;
background:#eee;
cursor:pointer; user-select:none;}
.ghost{background:rgb(93, 93, 182);color:#fff;}
|
cs |
main.js
1
2
3
4
5
|
import { sortable } from "./sortable.js";
const myUL = document.getElementById('myUL');
sortable(myUL);
|
cs |
getPosition.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// let dragIndex, dragSource
export function getMouseOffset(evt) {
const targetRect = evt.target.getBoundingClientRect()
const offset = {
x: evt.pageX - targetRect.left,
y: evt.pageY - targetRect.top
}
return offset
}//getMouseOffset
export function getElementVerticalCenter(el) {
const rect = el.getBoundingClientRect()
return (rect.bottom - rect.top) / 2
}//getElementVerticalCenter
|
cs |
sortable.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
import {getMouseOffset,getElementVerticalCenter} from './getPosition.js'
export function sortable(rootEl) {
let dragEl;
// Making all siblings movable
const all_list_item = rootEl.getElementsByClassName('d2-item');
[].slice.call(all_list_item).forEach(item =>{
item.draggable = true;
});
// Sorting starts
rootEl.addEventListener('dragstart', function (evt) {
dragEl = evt.target; // Remembering an element that will be moved
// Subscribing to the events at dnd
rootEl.addEventListener('dragover', _onDragOver);
rootEl.addEventListener('dragend', _onDragEnd);
setTimeout(()=>{
// If this action is performed without setTimeout, then
// the moved object will be of this class.
dragEl.classList.add('ghost');
}, 0)
}); //dragstart
// Function responsible for sorting
function _onDragOver(evt) {
evt.preventDefault();
evt.dataTransfer.dropEffect = 'move';
const target = evt.target;
// console.log(
// `내가 드래그한건 ${dragEl.innerText}
// 드래그 하며 지나치는 타겟은 ${target.innerText}`);
if (target && target !== dragEl && target.classList.contains('d2-item')) {
// Sorting
const offset = getMouseOffset(evt)
const middleY = getElementVerticalCenter(evt.target)
const targetIDX = [].indexOf.call(all_list_item,target);
if (offset.y > middleY) {
const temp_parent = target.parentElement;
targetIDX !== -1 && temp_parent.insertBefore(dragEl, target.nextSibling);
} else {
const temp_parent = target.parentElement;
targetIDX !== -1 && temp_parent.insertBefore(dragEl, target);
}
}//if
}//_onDragOver
// End of sorting
function _onDragEnd(evt) {
evt.preventDefault();
//이동 다시켰는데 sub에 아이템이 하나도 없으면
//다음번에 추가 안되서..ㅎ..;
const all_sub = rootEl.getElementsByClassName('sub');
for(let sub of all_sub){
if(sub.children.length == 0){
sub.appendChild(dragEl);
}//if
}//for
//이벤트 및 클래스 제거
dragEl.classList.remove('ghost');
rootEl.removeEventListener('dragover', _onDragOver);
rootEl.removeEventListener('dragend', _onDragEnd);
}//_onDragEnd
}//sortable
|
cs |
'CSS&JS > ⚡Thinkers' 카테고리의 다른 글
[JS + CSS] transform을 이용한 초간단 상단 progress bar 만들기 (0) | 2021.12.14 |
---|---|
vanilla JS로 sortable list 구현하기(3.2) (0) | 2021.12.09 |
vanilla JS로 sortable list 구현하기 (2) (0) | 2021.12.09 |
vanilla js로 sortable list 구현하기 (0) | 2021.12.09 |
[vanilla JS] 드래그 가능한(움직이는) 모달창 만들기 (0) | 2021.11.01 |