본문 바로가기
Front/JavaScript & jQuery

[JavaScript] <li> 드래그 앤 드롭, 위 아래로 이동시키기

by 은z 2021. 12. 21.

 

<li>형태의 요소들을 드래그 앤 드롭으로 위치를 변경하고자 한다.

참고로 <li>태그 외에 다른 것들도 가능하다.

가장 간단한 방법은 제이쿼리 라이브러리 sortable 를 추가해서 쓰는 것이다.

<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

위 방법으로 아주 손쉽게 구현이 가능하다.

하지만 이번에는 자바스크립트를 이용해서 구현하는 연습을 하려고 한다.

 

HTML5 가 제공해주는

드래그 앤 드롭(drag and drop) API를 이용해보자.

 

0. 드래그 앤 드롭 이벤트

아래 표 내용과 같이 다양한 이벤트가 있는데, dragstart, dragover, dragend를 사용할 예정.

dragstart 사용자가 객체(object)를 드래그하려고 시작할 때 발생함.
dragenter 마우스가 대상 객체의 위로 처음 진입할 때 발생함.
dragover 드래그하면서 마우스가 대상 객체의 위에 자리 잡고 있을 때 발생함.
drag 대상 객체를 드래그하면서 마우스를 움직일 때 발생함.
drop 드래그가 끝나서 드래그하던 객체를 놓는 장소에 위치한 객체에서 발생함.
dragleave 드래그가 끝나서 마우스가 대상 객체의 위에서 벗어날 때 발생함.
dragend 대상 객체를 드래그하다가 마우스 버튼을 놓는 순간 발생함.

 

 

 

1. <li> draggable 속성 추가하기

draggable 속성은 웹 페이지 내의 모든 요소를 드래그될 수 있는 객체(draggable object)로 변환할 수 있다.

draggable="true" 가 드래그 될 수 있도록 변환해주는 속성이다.

일일이 태그에 추가해주어도 되지만, 나는 js단에서 attribute를 추가해주었다.

<ul id="recommend-list">
    <li class="name" >캠핑장 이름</li>
    <li class="name" >자연환경</li>
    <li class="name" >캠핑장 유형</li>
    <li class="name" >주요 시설</li>
    <li class="name" >화장실 개수</li>
    <li class="name" >샤워장 개수</li>
    <li class="name" >반려동물 동반여부></li>
    <li class="name" >주소</li>
    <li class="name" >전화</li>
</ul>
$(".name").attr("draggable", "true");

 

 

2. dragstart

드래그될 수 있는 객체로 만든 후에는 ondragstart 속성을 통해 DataTransfer 객체의 setData() 메소드를 호출한다.

setData() 메소드는 드래그되는 대상 객체의 데이터(data)와 타입(data type)을 설정한다.

	dragStart: function (e) { 
		e.dataTransfer.effectAllowed = 'move';
		e.dataTransfer.setData('text/plain', null);
		selected = e.target;  //selected는 전역변수로 선언되어 있음.
	}

 

 

3. dragover

ondragover 속성은 드래그되는 대상 객체가 어느 요소 위에 놓일 수 있는지를 설정.

dragOver : function(e) { 
		if (this.isBefore(selected, e.target)) { 
			if(e.target.className == "name") {
				console.log(e.target.parentNode); //<ul id="recommend-list">
				console.log(e.target); //<li class="name" >캠핑장 이름</li>
				e.target.parentNode.insertBefore(selected, e.target);   //부모노드의 e.target앞에 selected 넣는다.
				
			}
		} else { 
			if(e.target.className == "name") {
				e.target.parentNode.insertBefore(selected, e.target.nextSibling); //부모노드의 e.target 다음 형제 앞에 selected 넣는다.
			}
		} 
		
	},
	isBefore: function (el1, el2) { 
		let cur;
		
		if (el2.parentNode === el1.parentNode) { 
			console.log(el1.previousSibling);
			for (cur = el1.previousSibling; cur; cur = cur.previousSibling) {
				if (cur === el2) 
				return true; 
			} 
		} 
		return false; 
	}

 

 

4. dragend

마우스를 놓으면 발생하는 속성.

선택된 요소를 초기화해주는 부분이다.

dragEnd: function () {
	selected = null;  //전역변수 초기화
}

 

 

 

 

 

 

5. 전체 코드

let selected = null;

var $recommend = {
	
	/**
	 * 초기화
	 */
	init : function() {
		
		this.fnAddEventListener();
	},
	
	/**
	 * 이벤트 등록
	 */
	fnAddEventListener : function() {
		
		$(".name").attr("draggable", "true");
		
		$(".name").off("dragstart").on("dragstart", function() {
			$recommend.dragStart(event);
		});
		$(".name").off("dragover").on("dragover", function() {
			$recommend.dragOver(event);
		});
		$(".name").off("dragend").on("dragend", function() {
			$recommend.dragEnd();
		});
		
		
	},	
	
	dragStart: function (e) { 
		e.dataTransfer.effectAllowed = 'move';
		e.dataTransfer.setData('text/plain', null);
		selected = e.target;
	},
	
	dragOver : function(e) { 
		
		//위쪽으로 이동했을 때
		if (this.isBefore(selected, e.target)) { 
			if(e.target.className == "name") {
				console.log(e.target.parentNode); //<ul id="recommend-list">
				console.log(e.target); //<li class="name" >캠핑장 이름 <span>${list.facltNm}</span></li>
				e.target.parentNode.insertBefore(selected, e.target);   //부모노드의 e.target앞에 selected 넣는다.
				
			}
		} else { 
			if(e.target.className == "name") {
				e.target.parentNode.insertBefore(selected, e.target.nextSibling); //부모노드의 e.target 다음 형제 앞에 selected 넣는다.
			}
		} 
		
	}, 
		
	dragEnd: function () {
		selected = null;
	},
	
	isBefore: function (el1, el2) { 
		let cur;
		
		if (el2.parentNode === el1.parentNode) { 
			console.log(el1.previousSibling);
			for (cur = el1.previousSibling; cur; cur = cur.previousSibling) {
				if (cur === el2) 
				return true; 
			} 
		} 
		return false; 
	},
	
};

$(function(){
	$recommend.init();
	
});

댓글