CSS&JS/⚡Thinkers

vanilla JS로 sortable list 구현하기 (2)

arancia_ 2021. 12. 9. 16:48

이전 게시글 링크 : https://aosceno.tistory.com/600

은혜로운 원본 Code pen 링크 : https://codepen.io/vtno/pen/MXmpoy

맘같아선 대분류인 d1 안에 d2를 넣고 싶지만
그렇게 하면 내 머리가 폭발하는 관계로 (ㅋㅋ ㅠ ) depth는 같고 그냥 아코디언으로 눈속임 한 버젼

HTM:

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
<!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_2</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script src="./main.js" type="module"></script>
</head>
<body>
    
<ul id="myUL">
    <li class="d1">나는 드래그 하면 안되양!!! 001</li>
    <li class="d2">hello 001</li>
    <li class="d2">hello 002</li>
    <li class="d2">hello 003</li>
    <li class="d1">나는 드래그 하면 안되양!!! 002</li>
    <li class="d2">world 004</li>
    <li class="d2">world 005</li>
    <li class="d2">world 006</li>
    <li class="d1">나는 드래그 하면 안되양!!! 003</li>
    <li class="d2">룰루랄라 007</li>
    <li class="d2">룰루랄라 008</li>
    <li class="d2">룰루랄라 009</li>
</ul>
 
</body>
</html>
cs

CSS,main.js, getPosition.js 동일

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
import {getMouseOffset,getElementVerticalCenter} from './getPosition.js'
 
export function sortable(rootEl) {
    let dragEl;
 
    // Making all siblings movable
    const all_list_item = rootEl.children; 
    [].slice.call(all_list_item).forEach(item =>{
        if(item.classList.contains('d2')){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.tagName == 'LI') {
            // Sorting
            const offset = getMouseOffset(evt)
            const middleY = getElementVerticalCenter(evt.target)
            const targetIDX = [].indexOf.call(all_list_item,target);
            if (offset.y > middleY) {
                targetIDX !== -1 && rootEl.insertBefore(dragEl, target.nextSibling);
            } else {
                targetIDX !== -1 && rootEl.insertBefore(dragEl, target);
            }
 
        }//if
    }//_onDragOver
 
    // End of sorting
    function _onDragEnd(evt) {
        evt.preventDefault();
 
        //만일..대분류 위에 드래그 되어버렸다면 다시 정리;
        const dragEl_idx = [].indexOf.call(all_list_item,dragEl);
        if(dragEl_idx == 0){
            const d1 = dragEl.nextElementSibling;
            rootEl.insertBefore(d1, dragEl);
        }//if
 
        //이벤트 및 클래스 제거
        dragEl.classList.remove('ghost');
        rootEl.removeEventListener('dragover', _onDragOver);
        rootEl.removeEventListener('dragend', _onDragEnd);
    }//_onDragEnd
}//sortable
cs