- Published on
Creating Resizable Table with Drag-Drop Reorder Functionality Using Pure JavaScript and Tailwind CSS
- Authors
Resizable Table with Drag-Drop Reorder Functionality
Drag-and-drop functionality has become a standard feature in many web applications. It allows users to move elements around the page, reordering them as needed. In this tutorial, we'll explore how to create a drag-and-drop reorderable table using HTML and JavaScript.
Getting Started
HTML Code
Creating an HTML table with some sample data:
<table id="my-table">
<thead>
<!-- Resizable area -->
<tr class="text-sm font-semibold">
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr class="text-sm transition-all hover:bg-gray-100">
<td>John Doe</td>
<td>Marketing Manager</td>
<td>New York City</td>
<td>$80,000</td>
</tr>
<tr class="text-sm transition-all hover:bg-gray-100">
<td>Jane Smith</td>
<td>Sales Associate</td>
<td>Los Angeles</td>
<td>$50,000</td>
</tr>
<tr class="text-sm transition-all hover:bg-gray-100">
<td>Michael Johnson</td>
<td>Accountant</td>
<td>Chicago</td>
<td>$70,000</td>
</tr>
<tr class="text-sm transition-all hover:bg-gray-100">
<td>Sarah Williams</td>
<td>Human Resources Manager</td>
<td>Houston</td>
<td>$90,000</td>
</tr>
</tbody>
</table>
JavaScript
Next, add JavaScript to make the table rows draggable and reorderable. Here's the complete code with explanation:
(function () {
// Get the table and its rows
var table = document.getElementById('my-table');
var rows = table.rows;
// Initialize the drag source element to null
var dragSrcEl = null;
// Loop through each row (skipping the first row which contains the table headers)
for (var i = 1; i < rows.length; i++) {
var row = rows[i];
// Make each row draggable
row.draggable = true;
// Add an event listener for when the drag starts
row.addEventListener('dragstart', function (e) {
// Set the drag source element to the current row
dragSrcEl = this;
// Set the drag effect to "move"
e.dataTransfer.effectAllowed = 'move';
// Set the drag data to the outer HTML of the current row
e.dataTransfer.setData('text/html', this.outerHTML);
// Add a class to the current row to indicate it is being dragged
this.classList.add('bg-gray-100');
});
// Add an event listener for when the drag ends
row.addEventListener('dragend', function (e) {
// Remove the class indicating the row is being dragged
this.classList.remove('bg-gray-100');
// Remove the border classes from all table rows
table.querySelectorAll('.border-t-2', '.border-blue-300').forEach(function (el) {
el.classList.remove('border-t-2', 'border-blue-300');
});
});
// Add an event listener for when the dragged row is over another row
row.addEventListener('dragover', function (e) {
// Prevent the default dragover behavior
e.preventDefault();
// Add border classes to the current row to indicate it is a drop target
this.classList.add('border-t-2', 'border-blue-300');
});
// Add an event listener for when the dragged row enters another row
row.addEventListener('dragenter', function (e) {
// Prevent the default dragenter behavior
e.preventDefault();
// Add border classes to the current row to indicate it is a drop target
this.classList.add('border-t-2', 'border-blue-300');
});
// Add an event listener for when the dragged row leaves another row
row.addEventListener('dragleave', function (e) {
// Remove the border classes from the current row
this.classList.remove('border-t-2', 'border-blue-300');
});
// Add an event listener for when the dragged row is dropped onto another row
row.addEventListener('drop', function (e) {
// Prevent the default drop behavior
e.preventDefault();
// If the drag source element is not the current row
if (dragSrcEl != this) {
// Get the index of the drag source element
var sourceIndex = dragSrcEl.rowIndex;
// Get the index of the target row
var targetIndex = this.rowIndex;
// If the source index is less than the target index
if (sourceIndex < targetIndex) {
// Insert the drag source element after the target row
table.tBodies[0].insertBefore(dragSrcEl, this.nextSibling);
} else {
// Insert the drag source element before the target row
table.tBodies[0].insertBefore(dragSrcEl, this);
}
}
// Remove the border classes from all table rows
table.querySelectorAll('.border-t-2', '.border-blue-300').forEach(function (el) {
el.classList.remove('border-t-2', 'border-blue-300');
});
});
}
})();
Let's go through each part of the code to see what it does.
Explanation
First, we declare three variables:
table
,rows,
anddragSrcEl.
Thetable
variable is used to store a reference to the HTML table element with the ID ofmy-table.
The "rows" variable is used to store a collection of all the rows in the table. Finally, thedragSrcEl
variable is used to store a reference to the row that is being dragged during the drag and drop operation.Next, we iterate over each row in the table starting from the second row
(i.e., index 1)
using afor loop
. We skip the first row because it contains the table headers and should not be draggable.For each row, we set the
draggable
attribute totrue
so that it can be dragged and dropped. We also attach event listeners for thedragstart,
dragend,
dragover,
dragenter,
anddragleave
events.The
dragstart
event is fired when the user starts dragging the row. In this event listener, we store a reference to the row being dragged in thedragSrcEl
variable. We also set theeffectAllowed
property tomove
to indicate that the row can be moved. Finally, we set thedataTransfer
property to the HTML of the row being dragged, so that it can be dropped elsewhere in the table.The
dragend
event is fired when the drag operation ends. In this event listener, we remove the gray background color from the row and remove the blue border from any rows that were previously highlighted.The
dragover
event is fired when the dragged element is being dragged over a valid drop target. In this event listener, we prevent the default behavior and add a blue border to the row being dragged over.The
dragenter
event is fired when the dragged element enters a valid drop target. In this event listener, we prevent the default behavior and add a blue border to the row being entered.The
dragleave
event is fired when the dragged element leaves a valid drop target. In this event listener, we remove the blue border from the row being left.Finally, the
drop
event is fired when the dragged element is dropped onto a valid drop target. In this event listener, we prevent the default behavior, check that the source and target rows are different, and then insert the dragged row before or after the target row depending on its position. We then remove the blue border from any highlighted rows.
Overall, this code implements a simple drag and drop reordering functionality for an HTML table using JavaScript.
You can access the full code:
- Name
- Umur Köse