Day 26: Drag + Drop (reorder list)
Build a simple list where users can drag items up or down to reorder them.
JavaScript focus
- Drag and Drop API
- dragstart
- dragover
- dragend
- e.preventDefault()
- closest()
- insertBefore()
- DOM reordering
- class toggling
Nice extras
- Add a drag handle
- Show the current order as text
- Save reordered list to localStorage
- Add keyboard reorder buttons
- Add a “Reset order” button
MDN prep
Drag + Drop (reorder list)
- Apple
- Banana
- Orange
- Grapes
- Strawberry
- Blueberry
- Mango
- Pineapple
- Watermelon
- Peach
The HTML
<ul class="drag_list">
<li draggable="true">Apple</li>
<li draggable="true">Banana</li>
<li draggable="true">Orange</li>
<li draggable="true">Grapes</li>
<li draggable="true">Strawberry</li>
<li draggable="true">Blueberry</li>
<li draggable="true">Mango</li>
<li draggable="true">Pineapple</li>
<li draggable="true">Watermelon</li>
<li draggable="true">Peach</li>
</ul>
The JavaScript
function initDragAndDrop() {
const root = document.querySelector(".drag_list");
if (!root) return;
const savedList = localStorage.getItem("ordered_list");
const savedOrder = savedList ? JSON.parse(savedList) : [];
let dragged;
function saveOrder() {
const items = root.querySelectorAll("li");
const order = Array.from(items).map((item) => item.textContent.trim());
localStorage.setItem("ordered_list", JSON.stringify(order));
}
function restoreOrder() {
if (!savedOrder.length) return;
const items = Array.from(root.querySelectorAll("li"));
savedOrder.forEach((savedText) => {
const matchingItem = items.find((item) => {
return item.textContent.trim() === savedText;
});
if (matchingItem) {
root.append(matchingItem);
}
});
}
function addDragEvents() {
const items = root.querySelectorAll('li[draggable="true"]');
items.forEach((item) => {
item.addEventListener("dragstart", (e) => {
dragged = e.target;
});
item.addEventListener("dragend", (e) => {
dragged = null;
});
});
}
restoreOrder();
addDragEvents();
root.addEventListener("dragover", (e) => {
e.preventDefault();
const target = e.target.closest("li");
if (!target || target === dragged) return;
root.insertBefore(dragged, target);
});
root.addEventListener("drop", saveOrder);
}
initDragAndDrop();