Toolbly

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;
    }
});