JavaScript
// Method 1: HTML5 Drag and Drop API
const draggable = document.getElementById('draggable');
const dropzone = document.getElementById('dropzone');
// Make element draggable
draggable.draggable = true;
// Drag events on source
draggable.addEventListener('dragstart', function(e) {
console.log('Drag started');
e.dataTransfer.setData('text/plain', draggable.id);
e.dataTransfer.effectAllowed = 'move';
draggable.style.opacity = '0.5';
});
draggable.addEventListener('dragend', function(e) {
console.log('Drag ended');
draggable.style.opacity = '1';
});
// Drop events on target
dropzone.addEventListener('dragover', function(e) {
e.preventDefault(); // Allow drop
e.dataTransfer.dropEffect = 'move';
dropzone.style.backgroundColor = 'lightblue';
});
dropzone.addEventListener('dragleave', function(e) {
dropzone.style.backgroundColor = '';
});
dropzone.addEventListener('drop', function(e) {
e.preventDefault();
console.log('Dropped');
const data = e.dataTransfer.getData('text/plain');
const element = document.getElementById(data);
dropzone.appendChild(element);
dropzone.style.backgroundColor = '';
});
// Method 2: Custom drag implementation
let isDragging = false;
let currentX, currentY, initialX, initialY;
const customDraggable = document.getElementById('customDraggable');
customDraggable.addEventListener('mousedown', function(e) {
isDragging = true;
initialX = e.clientX - customDraggable.offsetLeft;
initialY = e.clientY - customDraggable.offsetTop;
customDraggable.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', function(e) {
if (isDragging) {
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
customDraggable.style.left = currentX + 'px';
customDraggable.style.top = currentY + 'px';
}
});
document.addEventListener('mouseup', function() {
if (isDragging) {
isDragging = false;
customDraggable.style.cursor = 'grab';
}
});
// Method 3: Drag with touch support
customDraggable.addEventListener('touchstart', function(e) {
isDragging = true;
const touch = e.touches[0];
initialX = touch.clientX - customDraggable.offsetLeft;
initialY = touch.clientY - customDraggable.offsetTop;
});
document.addEventListener('touchmove', function(e) {
if (isDragging) {
e.preventDefault();
const touch = e.touches[0];
currentX = touch.clientX - initialX;
currentY = touch.clientY - initialY;
customDraggable.style.left = currentX + 'px';
customDraggable.style.top = currentY + 'px';
}
});
document.addEventListener('touchend', function() {
isDragging = false;
});
// Method 4: Drag with constraints
function dragWithConstraints(element, minX, minY, maxX, maxY) {
let isDragging = false;
let startX, startY, offsetX, offsetY;
element.addEventListener('mousedown', function(e) {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
offsetX = element.offsetLeft;
offsetY = element.offsetTop;
});
document.addEventListener('mousemove', function(e) {
if (isDragging) {
let newX = offsetX + (e.clientX - startX);
let newY = offsetY + (e.clientY - startY);
// Apply constraints
newX = Math.max(minX, Math.min(maxX, newX));
newY = Math.max(minY, Math.min(maxY, newY));
element.style.left = newX + 'px';
element.style.top = newY + 'px';
}
});
document.addEventListener('mouseup', function() {
isDragging = false;
});
}
// Method 5: Sortable list
const sortableList = document.getElementById('sortableList');
sortableList.addEventListener('dragstart', function(e) {
if (e.target.tagName === 'LI') {
e.target.style.opacity = '0.5';
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', e.target.innerHTML);
}
});
sortableList.addEventListener('dragover', function(e) {
e.preventDefault();
const afterElement = getDragAfterElement(sortableList, e.clientY);
const dragging = document.querySelector('.dragging');
if (afterElement == null) {
sortableList.appendChild(dragging);
} else {
sortableList.insertBefore(dragging, afterElement);
}
});
function getDragAfterElement(container, y) {
const draggableElements = [...container.querySelectorAll('li:not(.dragging)')];
return draggableElements.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) {
return { offset: offset, element: child };
} else {
return closest;
}
}, { offset: Number.NEGATIVE_INFINITY }).element;
}Output
// Output depends on drag and drop interaction
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