当前位置:网站首页>拖放表格行
拖放表格行
2022-07-26 20:31:00 【紫微前端】
- 当用户开始移动表格行时,我们创建一个项目列表。每个项目都是从表格的每一行克隆的。
- 我们将列表显示在与表格相同的位置,并隐藏表格。
- 在这一步,移动行实际上是移动列表项。
- 当用户拖动一个项目时,我们确定列表中目标项目的索引。并将原始拖动的行移动到与结束索引关联的行之前或之后。
<table id="table">
...
</table>基本设置
mousedown对于任何行的第一个单元格,因此用户可以单击并拖动每行中的第一个单元格mousemovefordocument:当用户移动行时触发此事件,我们将根据方向(向上或向下)创建并插入占位符行mouseupfordocument:当用户拖动行时发生此事件。
// Query the table
const table = document.getElementById('table');
const mouseDownHandler = function(e) {
...
// Attach the listeners to `document`
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
const mouseMoveHandler = function(e) {
...
};
const mouseUpHandler = function() {
...
// Remove the handlers of `mousemove` and `mouseup`
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
// Query all rows
table.querySelectorAll('tr').forEach(function(row, index) {
// Ignore the header
// We don't want user to change the order of header
if (index === 0) {
return;
}
// Get the first cell of row
const firstCell = row.firstElementChild;
firstCell.classList.add('draggable');
// Attach event handler
firstCell.addEventListener('mousedown', mouseDownHandler);
});当用户移动一行时克隆表
let isDraggingStarted = false;
const mouseMoveHandler = function(e) {
if (!isDraggingStarted) {
isDraggingStarted = true;
cloneTable();
}
...
};cloneTable创建一个与表格具有相同位置的元素,并显示在表格之前:
let list;
const cloneTable = function () {
// Get the bounding rectangle of table
const rect = table.getBoundingClientRect();
// Get the width of table
const width = parseInt(window.getComputedStyle(table).width);
// Create new element
list = document.createElement('div');
// Set the same position as table
list.style.position = 'absolute';
list.style.left = `${rect.left}px`;
list.style.top = `${rect.top}px`;
// Insert it before the table
table.parentNode.insertBefore(list, table);
// Hide the table
table.style.visibility = 'hidden';
};想象一下,它list由从表行克隆的项目组成:
const cloneTable = function() {
...
// Loop over the rows
table.querySelectorAll('tr').forEach(function(row) {
const item = document.createElement('div');
const newTable = document.createElement('table');
const newRow = document.createElement('tr');
// Query the cells of row
const cells = [].slice.call(row.children);
cells.forEach(function(cell) {
const newCell = cell.cloneNode(true);
newRow.appendChild(newCell);
});
newTable.appendChild(newRow);
item.appendChild(newTable);
list.appendChild(item);
});
};在这一步之后,我们有以下内容list:
<!-- The list -->
<div>
<!-- First item -->
<div>
<table>
<!-- The first row of original table -->
<tr>
...
</tr>
</table>
</div>
<!-- Second item -->
<div>
<table>
<!-- The second row of original table -->
<tr>
...
</tr>
</table>
</div>
<!-- ... -->
</div>
<!-- The original table -->
<table>
...
</table>值得注意的是,在克隆每个项目中的单元格时,我们必须将单元格宽度设置为与原始单元格相同。所以该项目看起来完全像原始行:
cells.forEach(function (cell) {
const newCell = cell.cloneNode(true);
// Set the width as the original cell
newCell.style.width = `${parseInt(window.getComputedStyle(cell).width)}px`;
newRow.appendChild(newCell);
});确定拖动行和目标行的索引
let draggingEle; // The dragging element
let draggingRowIndex; // The index of dragging row
const mouseDownHandler = function (e) {
// Get the original row
const originalRow = e.target.parentNode;
draggingRowIndex = [].slice.call(table.querySelectorAll('tr')).indexOf(originalRow);
};
const mouseMoveHandler = function (e) {
if (!isDraggingStarted) {
cloneTable();
// Query the dragging element
draggingEle = [].slice.call(list.children)[draggingRowIndex];
}
};
const mouseUpHandler = function () {
// Get the end index
const endRowIndex = [].slice.call(list.children).indexOf(draggingEle);
};draggingRowIndex和一样endRowIndex,现在可以很容易地检查用户是否掉到了表格的顶部或底部。
const mouseUpHandler = function () {
// Move the dragged row to `endRowIndex`
let rows = [].slice.call(table.querySelectorAll('tr'));
draggingRowIndex > endRowIndex
? // User drops to the top
rows[endRowIndex].parentNode.insertBefore(rows[draggingRowIndex], rows[endRowIndex])
: // User drops to the bottom
rows[endRowIndex].parentNode.insertBefore(rows[draggingRowIndex], rows[endRowIndex].nextSibling);
};边栏推荐
- There are six ways to help you deal with the simpledateformat class, which is not a thread safety problem
- PLSQL package
- Remember the idea of solving the problem of invalid bound statement xxxxx once
- Explain the 190 secondary compiler (decoding table) module of SMR laminated hard disk of Western data in detail
- Deepfake pinches his face. It's hard to tell whether it's true or false. Tom Cruise is more like himself than himself!
- Error in render: “TypeError: data.slice is not a function“
- ROS2获取当前系统时间的方法
- [problem] process the set [','] into (',')
- 力扣每日一题-第43天-168. Excel表列名称
- 洛谷-线段覆盖-(区间排序问题总结)
猜你喜欢
![[download materials of harmoniyos topics] HDD Hangzhou station · offline salon focuses on application innovation to show the ecological charm of Hongmeng](/img/62/9e2ff0dc2c8b049fd32ad56334a0c0.jpg)
[download materials of harmoniyos topics] HDD Hangzhou station · offline salon focuses on application innovation to show the ecological charm of Hongmeng

Error in render: “TypeError: data.slice is not a function“

Redis interview questions

Redis hash和string的区别

Flash source code outline

我们从Crypto市场中学到的最艰难一课

Summary of common interview questions of operating system, including answers

【MySQL系列】-索引知多少

ECCV 2022 | 同时完成四项跟踪任务!Unicorn: 迈向目标跟踪的大统一

How to configure the legendary SF lander to automatically read the list without a network
随机推荐
Summary of 4 years of software testing experience and interviews with more than 20 companies after job hopping
Apaas low code platform (I) | leave complexity to yourself and simplicity to users
GOM and GEE lander list file encryption tutorial
Devops has been practiced for many years. What is the most painful thing?
Go+mysql+redis+vue3 simple chat room, bullet 5: synchronize messages to MySQL using message queues and scheduled tasks
[ffmpeg] add timestamp summary to video files
Niuke multi school -journey- (map building distra+ card often optimization)
Svn uses fragmented ideas
洛谷-线段覆盖-(区间排序问题总结)
我们从Crypto市场中学到的最艰难一课
After chatting with byte programmers with a monthly salary of 3W, I realized that I had been doing chores
修改excel默认编码
一种用于实体关系抽取的统一标签空间
Redis面试题
Introduction of JDBC
Error in render: “TypeError: data.slice is not a function“
IT系统为什么需要可观测性?
【HCIE安全】双机热备-主备备份
TCP的粘包拆包问题解决方案
手机\固定电话座机呼叫转移设置方法