Drag-and-Drop List Builder
Generate code for a sortable list using native JavaScript.
<ul class="draggable-list">
<li draggable="true">Item 1</li>
<li draggable="true">Item 2</li>
<li draggable="true">Item 3</li>
<li draggable="true">Item 4</li>
</ul>.draggable-list li {
padding: 1rem;
margin: 0.5rem 0;
background-color: #f0f0f0;
border: 1px solid #ddd;
border-radius: 4px;
cursor: move;
}
.dragging {
opacity: 0.5;
}
.drag-over {
border-top: 2px solid blue;
}document.addEventListener('DOMContentLoaded', () => {
const lists = document.querySelectorAll('.draggable-list');
let draggedItem = null;
lists.forEach(list => {
list.addEventListener('dragstart', e => {
draggedItem = e.target;
setTimeout(() => e.target.classList.add('dragging'), 0);
});
list.addEventListener('dragend', e => {
setTimeout(() => {
draggedItem.classList.remove('dragging');
draggedItem = null;
}, 0);
});
list.addEventListener('dragover', e => {
e.preventDefault();
const afterElement = getDragAfterElement(list, e.clientY);
const currentlyDragged = document.querySelector('.dragging');
if (afterElement == null) {
list.appendChild(currentlyDragged);
} else {
list.insertBefore(currentlyDragged, 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;
}
});