owned this note
owned this note
Published
Linked with GitHub
---
tags: web
---
# HTML drag and drop API
유저는 draggable element를 마우스로 선택하고, drag하여 droppable element에 drop한다.
## Drag Event
- drag (ondrag) : 드래그할 때 발생
- dragend (ondragend)
- dragexit
- dragenter : 유효한 drag target에 진입했을 경우
- dragleave : 유효한 drag target을 떠났을 경우
- dragover : 적절한 드롭 대상위로 지나갈 때 발생
- 매 100 밀리세컨마다 발생한다.
- dragstart
- drop
## Interface
- interface : DragEvent, DataTransfer, DataTransferItem, DataTransferItemList
- DragEvent : constructor와 DataTransfer 개체인 dataTransfer 프로퍼티를 갖는다.
- DataTransfer 객체 : drag event state를 갖는다. 각 drag event는 dragTransfer 프로퍼티를 갖고 있다.
- 프로퍼티
- items : `DataTransferItem` 객체의 list이다.
- effectAllowed : 모든 가능한 operation의 타입 - none, copy, copyLink, copyMove, link, linkMove, move, all, uninitialized 중의 하나이다.
- dropEffect : 현재 선택된 DnD operation의 타입을 얻거나, 새로운 타입으로 operation을 설정한다. none, copy, link, move 중 하나여야 한다.
- files
- types : dragstart event에서 결정되는 포맷의 string 배열이다.
- 메서드
- clearData()
- getData()
- setData()
- setDragImage()
- DataTransferItem 객체 : 하나의 Drag itemdlek.
- `kind` property : string or file
- `type` property : data item의 MIME type
- drag item의 Data를 get하는 메서드를 갖는다.
- DataTransferItemList 객체 : list of DataTransferItem 객체
- 메서드 : drag item 추가, 삭제, 전체 drag items 삭제
- DataTransfer와 DataTransferItem 인터페이스의 차이
- DataTransfer : 동기적 getData() 메서드 : drag item의 데이타에 접근
- DataTransferItem : 비동기 getAsString() 메서드
- DragTransferItem와 DragTransferItemList 인터페이스는 브라우저의 지원 범위가 제한된다.
## draggable attribute
- draggable 이 true일 경우, 해당 엘리먼트를 drag할 수 있다고 판단한다.
- 디폴트는 auto : text selection, image, link만 drag할 수 있다.
```htmlembedded
<p draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'This text may be dragged')">
This text <strong>may</strong> be dragged.
</p>
```
## Drag Effects
`dropEffect` 프로퍼티는 유저에게 drag and drop 중에 어떠한 일이 일어나는지를 유저에게 피드백을 주는 역할을 한다. 주로, drag를 하는 동안 어떠한 cursor가 보일 것인지를 결정한다.
여기에 세 operation이 있고, 이를 조합한 것들도 존재한다.
- copy : data가 drop location으로 카피될 것임을 알린다. => + 커서
- move : drag되는 데이타가 움직일 것이다.
- link : source와 drop 위치 간의 관계가 있을 것이다. => link 커서...(약간 공유할 때 아이콘)
`dragstart` event listener 안에서 `effectAllowed` 프로퍼티에 어떠한 operation이 허용되는지를 지정할 수 있다.
- **dropEffect**
drag operation이 일어나는 동안, **`dragenter`와 `dragover` events**는 effectAllowed 프로퍼티를 보고 어떠한 operation이 허용되는지를 확인한다. **`dropEffect` 프로퍼티도 이 이벤트 중 하나에 지정되어야** 한다.
**dropEffect에 허용되는 operation은 none, copy, move, link 중 하나**이다.
## Drop Target 지정하기
`dragenter`와 `dragover` 이벤트에서 유효한 drop target인지를 지정한다. 대부분의 웹 페이지에서는 data를 drop하기에 적절하지 않으므로, 이 이벤트들의 디폴트 핸들러는 drop을 허용하지 않는 것이다.
따라서, **drop을 허용하고 싶을 때는 `dragenter`와 `dragover` 이벤트 둘 다에 디폴트 핸들링을 취소**해야 한다. defaul handling을 취소하는 방법은
1. 이벤트 핸들러에서 false를 리턴하기 or
2. event의 preventDefault 메서드를 호출하기
dragenter와 dragover 이벤트 둘 다에 preventDefault를 호출함으로써, 그 위치에 drop이 허용된다.
## Drop
마우스가 drop target에서 놓아지면, drop 이벤트가 발생한다.
웹페이지에서 **drop 이벤트 핸들러에 반드시 `preventDefault` 메서드를 호출해야 drop 이벤트를 받아들인다는 의미**가 되고, 브라우저도 default handling을 수행하지 않게 된다. 예를 들어, firefox는 링크를 드래그하면, 링크를 열게 되는데, 이 디폴트 핸들링을 취소해야 한다.
## Finishing a Drag
drag가 끝나게 되면, `dragend` 이벤트가 **source element(dragstart가 시작된 element)에 발생**하게 된다.
drop이 성공했던, 실패했던 이 이벤트는 발생한다. 실패와 성공 여부는 dropEffect 프로퍼티로 알 수 있다.
- 여기서 dropEffect 프로퍼티가 none이면, drag는 취소되었음을 알 수 있다.
- 만약 drag가 성공적이었다면, 다른 operation이 set되어있을 것이다.
## 출처
- [HTML Drag and Drop API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)
- [Drag Effects - MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#drageffects)