Drag and Drop Events in JavaScript

Implement drag and drop functionality

AdvancedEvents ProgramsExample 10 of 10
drag-and-drop-events.js
1// Method 1: HTML5 Drag and Drop API
2const draggable = document.getElementById('draggable');
3const dropzone = document.getElementById('dropzone');
4
5// Make element draggable
6draggable.draggable = true;
7
8// Drag events on source
9draggable.addEventListener('dragstart', function(e) {
10 console.log('Drag started');
11 e.dataTransfer.setData('text/plain', draggable.id);
12 e.dataTransfer.effectAllowed = 'move';
13 draggable.style.opacity = '0.5';
14});
15
16draggable.addEventListener('dragend', function(e) {
17 console.log('Drag ended');
18 draggable.style.opacity = '1';
19});
20
21// Drop events on target
22dropzone.addEventListener('dragover', function(e) {
23 e.preventDefault(); // Allow drop
24 e.dataTransfer.dropEffect = 'move';
25 dropzone.style.backgroundColor = 'lightblue';
26});
27
28dropzone.addEventListener('dragleave', function(e) {
29 dropzone.style.backgroundColor = '';
30});
31
32dropzone.addEventListener('drop', function(e) {
33 e.preventDefault();
34 console.log('Dropped');
35 const data = e.dataTransfer.getData('text/plain');
36 const element = document.getElementById(data);
37 dropzone.appendChild(element);
38 dropzone.style.backgroundColor = '';
39});
40
41// Method 2: Custom drag implementation
42let isDragging = false;
43let currentX, currentY, initialX, initialY;
44
45const customDraggable = document.getElementById('customDraggable');
46
47customDraggable.addEventListener('mousedown', function(e) {
48 isDragging = true;
49 initialX = e.clientX - customDraggable.offsetLeft;
50 initialY = e.clientY - customDraggable.offsetTop;
51 customDraggable.style.cursor = 'grabbing';
52});
53
54document.addEventListener('mousemove', function(e) {
55 if (isDragging) {
56 e.preventDefault();
57 currentX = e.clientX - initialX;
58 currentY = e.clientY - initialY;
59
60 customDraggable.style.left = currentX + 'px';
61 customDraggable.style.top = currentY + 'px';
62 }
63});
64
65document.addEventListener('mouseup', function() {
66 if (isDragging) {
67 isDragging = false;
68 customDraggable.style.cursor = 'grab';
69 }
70});
71
72// Method 3: Drag with touch support
73customDraggable.addEventListener('touchstart', function(e) {
74 isDragging = true;
75 const touch = e.touches[0];
76 initialX = touch.clientX - customDraggable.offsetLeft;
77 initialY = touch.clientY - customDraggable.offsetTop;
78});
79
80document.addEventListener('touchmove', function(e) {
81 if (isDragging) {
82 e.preventDefault();
83 const touch = e.touches[0];
84 currentX = touch.clientX - initialX;
85 currentY = touch.clientY - initialY;
86
87 customDraggable.style.left = currentX + 'px';
88 customDraggable.style.top = currentY + 'px';
89 }
90});
91
92document.addEventListener('touchend', function() {
93 isDragging = false;
94});
95
96// Method 4: Drag with constraints
97function dragWithConstraints(element, minX, minY, maxX, maxY) {
98 let isDragging = false;
99 let startX, startY, offsetX, offsetY;
100
101 element.addEventListener('mousedown', function(e) {
102 isDragging = true;
103 startX = e.clientX;
104 startY = e.clientY;
105 offsetX = element.offsetLeft;
106 offsetY = element.offsetTop;
107 });
108
109 document.addEventListener('mousemove', function(e) {
110 if (isDragging) {
111 let newX = offsetX + (e.clientX - startX);
112 let newY = offsetY + (e.clientY - startY);
113
114 // Apply constraints
115 newX = Math.max(minX, Math.min(maxX, newX));
116 newY = Math.max(minY, Math.min(maxY, newY));
117
118 element.style.left = newX + 'px';
119 element.style.top = newY + 'px';
120 }
121 });
122
123 document.addEventListener('mouseup', function() {
124 isDragging = false;
125 });
126}
127
128// Method 5: Sortable list
129const sortableList = document.getElementById('sortableList');
130
131sortableList.addEventListener('dragstart', function(e) {
132 if (e.target.tagName === 'LI') {
133 e.target.style.opacity = '0.5';
134 e.dataTransfer.effectAllowed = 'move';
135 e.dataTransfer.setData('text/html', e.target.innerHTML);
136 }
137});
138
139sortableList.addEventListener('dragover', function(e) {
140 e.preventDefault();
141 const afterElement = getDragAfterElement(sortableList, e.clientY);
142 const dragging = document.querySelector('.dragging');
143
144 if (afterElement == null) {
145 sortableList.appendChild(dragging);
146 } else {
147 sortableList.insertBefore(dragging, afterElement);
148 }
149});
150
151function getDragAfterElement(container, y) {
152 const draggableElements = [...container.querySelectorAll('li:not(.dragging)')];
153
154 return draggableElements.reduce((closest, child) => {
155 const box = child.getBoundingClientRect();
156 const offset = y - box.top - box.height / 2;
157
158 if (offset < 0 && offset > closest.offset) {
159 return { offset: offset, element: child };
160 } else {
161 return closest;
162 }
163 }, { offset: Number.NEGATIVE_INFINITY }).element;
164}

Output

// Output depends on drag and drop interaction

What's going on

Drag and drop enables interactive UI.

HTML5 Drag and Drop API

draggable: Make element draggable
dragstart: Drag begins
dragend: Drag ends
dragover: Over drop target
dragleave: Leave drop target
drop: Item dropped

Data Transfer

setData(): Set drag data
getData(): Get drop data
effectAllowed: Allowed effects
dropEffect: Visual feedback

Custom Implementation

Mouse events
Touch events
Position tracking
Constraints

Use Cases

File uploads
Sortable lists
Drag to reorder
Interactive games

Best Practices

Provide visual feedback
Handle touch events
Add constraints
Test accessibility