【发布时间】:2020-09-20 03:36:52
【问题描述】:
在我的一列n行的HTML表格中,例如:
<table id="my-table">
<tr>
<td>How</td>
</tr>
<tr>
<td>Are</td>
</tr>
<tr>
<td>You</td>
</tr>
</table>
我想让每一行都可以拖放到另一行。如果将 A 行放到另一行 B 中,则应交换这些相应行的 HTML 内容。
为此,我阅读了相当多的文档和教程,但似乎缺少一些我无法弄清楚的东西。到目前为止,我所做的是将以下代码附加到每个 <td>tag 中:
draggable="true" ondragstart="dragCell(event)" ondragover="allowDrop(event)" ondrop="dropCell(event)" ondragenter="handleDragEnter(event)" ondragleave="handleDragLeave(event)" ondragend="handleDragEnd(event)"
我的 JavaScript 是:
/*##############################################################################
## 1. Dragstart Handler ##
##############################################################################*/
function dragCell(ev) {
let draggedRow = ev.target.closest("tr");
let rowNumber = draggedRow.rowIndex;
let tableId = draggedRow.parentNode.parentNode.getAttribute("id");
let data = {"id":tableId,"rowNumber":rowNumber};
let cellsdragged = draggedRow.children;
let amountOfCells = cellsdragged.length;
let dataToTransfer = [];
for (let i = 0; i < amountOfCells; i++) {
let currentCell = cellsdragged[i];
dataToTransfer.push(currentCell.outerHTML);
}
data["cellContents"] = dataToTransfer;
data = JSON.stringify(data);
ev.dataTransfer.setData("text/plain",data);
document.getElementsByTagName("body")[0].style.cursor = "grabbing";
}
/*##############################################################################
## 2. Dragover Handler ##
##############################################################################*/
function allowDrop(ev) {
ev.preventDefault();
}
/*##############################################################################
## 3. Drop Handler ##
##############################################################################*/
function dropCell(ev) {
ev.preventDefault();
if (ev.stopPropagation) {
ev.stopPropagation();
}
document.getElementsByTagName("body")[0].style.cursor = "default";
let data = ev.dataTransfer.getData("text/plain");
data = JSON.parse(data);
let rowToDrop = ev.target.closest('tr');
let targetIndex = rowToDrop.rowIndex;
let targetId = rowToDrop.parentNode.parentNode.getAttribute("id");
if (data.id == targetId && data.rowNumber != targetIndex) {
let targetContents = [];
let cellsForDrop = rowToDrop.children;
let amountOfCells = cellsForDrop.length;
for (let i = 0; i < amountOfCells; i++) {
targetContents
.push(cellsForDrop[i].outerHTML);
}
let draggedRow = document.getElementById(data.id).rows[data.rowNumber];
let cellsOfDrag = draggedRow.children;
for (let i = 0; i < amountOfCells; i++) {
cellsForDrop[i].outerHTML = data.cellContents[i][0];
cellsOfDrag[i].outerHTML = targetContents[i][0];
}
}
}
/*##############################################################################
## 4. Dragenter Handler ##
##############################################################################*/
function handleDragEnter(ev) {
ev.target.closest('tr').classList.add('ready-for-drop');
}
/*##############################################################################
## 5. Dragleave Handler ##
##############################################################################*/
function handleDragLeave(ev) {
ev.target.closest('tr').classList.remove('ready-for-drop');
}
/*##############################################################################
## 6. Dragend Handler ##
##############################################################################*/
function handleDragEnd(event) {
let rows = ev.target.closest("table").rows;
let amount = rows.length;
for (let i = 0; i < amount; i++) {
if (rows[i].classList.contains('ready-for-drop')) {
rows[i].classList.remove('ready-for-drop')
}
}
}
当我运行此程序并将一行拖入另一行时,控制台为我提供了有关 ev.target.closest 的错误,对于 Dragenter、Dragleave 和 Dragend Handler 函数,总是说 ev.target.closest is not a function。尽管我在 dragstart 处理程序函数中使用完全相同的语法,但在该行的控制台中没有报告错误。完成拖拽后,拖拽行的内容都变为<。
我在这里缺少什么?请考虑我不想使用任何 jQuery 解决方案,我想坚持使用 vanilla JavaScript。另请考虑我确实需要交换整个outerHTML,因为我的<td> 标签可能包含特定于单元格的属性值。
【问题讨论】:
标签: javascript html-table drag-and-drop