JavaScript Projects
Build a Kanban Board (Drag & Drop)
Build a production-grade Kanban Board in JavaScript using native HTML5 Drag and Drop API, state persistence, and dynamic column mutations.
1. Introduction
A Kanban Board organizes tasks into columns representing workflow states (e.g. Todo, In Progress, Done). Building a Kanban Board tests your understanding of the native HTML5 Drag and Drop API, event delegation, state serialization, and local storage persistence.
2. Why It Matters
Interactive drag-and-drop interfaces rely on event sequences: dragstart, dragover, dragenter, dragleave, drop, and dragend. Mastering these events without external third-party libraries gives you fine-grained control over UI responsiveness.
3. Real-World Analogy
Think of a Magnetic Whiteboard:
- DragStart (Picking up a magnet): You pick up a task magnet from the "Todo" column. The magnet is held in your hand (active drag state).
- DragOver (Hovering over column): You hover your hand over the "In Progress" column. The column highlights to show it can receive the magnet.
- Drop (Sticking magnet to board): You release your hand over the target area. The magnet sticks to the new column, and the board registry updates its position.
4. State Model Architecture
5. HTML5 Drag and Drop Event Implementation
6. Practical Complete Interface
7. Common Mistakes
- Forgetting to call e.preventDefault() inside dragover: By default, the browser prevents dropping elements onto web page elements. If you omit
e.preventDefault()inside thedragoverlistener, thedropevent will never fire.
8. Quick Quiz
Q1: Which event listener MUST invoke e.preventDefault() to allow an element to accept drop events?
A) dragstart
B) dragover
Answer: B — You must call e.preventDefault() inside the dragover event handler to enable drop target behavior.
9. Scenario-Based Challenge
The In-Column Card Reordering Challenge:
Currently, dropping a card appends it to the end of the column. Calculate mouse Y offsets relative to existing card siblings during dragover to determine the exact insertion index, enabling reordering within the same column.
10. Debugging Exercise
Explain why this drop event handler throws a DataTransfer security error, and how to fix it:
card.addEventListener('dragstart', (e) => { e.dataTransfer.setData('text/plain', card.id); });
column.addEventListener('dragover', (e) => { // Bug: Attempting to read dataTransfer data during dragover! const id = e.dataTransfer.getData('text/plain'); console.log('Hovering card:', id); // Returns empty string or fails! Why? });
View Solution
Diagnosis: For security reasons, the HTML5 Drag and Drop specification restricts e.dataTransfer.getData() so that it can ONLY be read inside the drop event handler. Calling it inside dragover or dragenter returns an empty string.
Fix: Store the active dragged task ID in a local closure variable during dragstart, or read getData() exclusively inside the drop listener:
column.addEventListener('drop', (e) => {
e.preventDefault();
const id = e.dataTransfer.getData('text/plain'); // Allowed here!
});
11. Interview Questions
🟢 Q1: Explain the sequence of events in the HTML5 Drag and Drop API.
Answer:
1. dragstart: Fires on the source element when dragging begins.
2. drag: Fires continuously on the source element while dragging.
3. dragenter: Fires on a target container when the dragged element enters its boundaries.
4. dragover: Fires continuously on a target container while dragging over it. Must call e.preventDefault() to allow dropping.
5. dragleave: Fires when the dragged element leaves a target container.
6. drop: Fires on the target container when the mouse button is released over a valid target.
7. dragend: Fires on the source element after the drag operation completes (whether successful or canceled).
12. Production Considerations
- • Mobile Touch Support: The native HTML5 Drag and Drop API is not supported on mobile touchscreens. In production, provide touch event listeners (
touchstart,touchmove,touchend) or use a touch-friendly polyfill.