GIthub 开源项目地址 leave_approval_management_sys,遵循 Apache 2.0 开源协议。
实现拖选功能
由于 DataTable 和 BootstrapTable 插件都没有自带拖选功能,但拖拽多选操作似乎又是必须的,所以自行实现拖选功能。
一、效果预览
二、思路
当 鼠标按下(mousedown)
则进行初始化(标记拖动状态、记录当前坐标为原点等)操作,然后当 鼠标移动(mousemove)
则显示拖拽框,并处理数据选择逻辑,若 鼠标松开(mouseup)
则结束本次拖选过程。
可以把整个功能分为两大块:
-
拖拽框
拖拽框的样式变化可分为“四种”,需要以拖拽原点建立坐标系,然后对第一至四象限的变化分别进行处理。 -
选中逻辑
利用tr
标签的鼠标进入(mouseenter)
和鼠标离开(mouseleave)
这两个事件的offsetY
属性判断“选中行”与“取消选中行”。
三、拖拽框
Ⅰ、HTML 及 CSS
- HTML
<div id="drag-box"></div>
- CSS
#drag-box {
z-index: -999;
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
background-color: rgba(139, 191, 249, 0.5);
border: 1px solid rgb(19, 98, 180);
display: none;
pointer-events: none;
}
Ⅱ、第一象限
newProperty = {
x: originX,
y: nowY,
width: nowX - originX,
height: originY - nowY,
}
Ⅲ、第二象限
newProperty = {
x: nowX,
y: originY,
width: originX - nowX,
height: originY - nowY,
}
Ⅳ、第三象限
newProperty = {
x: nowX,
y: originY,
width: originX - nowX,
height: nowY - originY,
}
Ⅴ、第四象限
newProperty = {
x: originX,
y: originY,
width: nowX - originX,
height: nowY - originY,
}
Ⅵ、总结
// 计算拖选框二维
let originX = $table.selector.x;
let originY = $table.selector.y;
let nowY = e.pageY;
let nowX = e.pageX;
let _x = originX, _y = originY, _width = Math.abs(nowX - originX), _height = Math.abs(nowY - originY);
if(nowY > originY) {
if(nowX > originX) {
_width = nowX - originX;
_height = nowY - originY;
}
else {
_x -= originX - nowX;
}
}
else {
if(nowX > originX) {
_y -= originY - nowY;
}
else {
_x -= originX - nowX;
_y -= originY - nowY;
}
}
// 设置拖选框样式
$('#drag-box').css({
'left': _x + 'px',
'top': _y + 'px',
'width': _width + 'px',
'height': _height + 'px',
});
四、选中逻辑
由于 鼠标移动事件(mousemove)
提供的数据无法计算哪些行被选中了,所以利用 tr
标签的 鼠标进入(mouseenter)
和 鼠标离开(mouseleave)
这两个事件的 offsetY
属性进行判断。
有两种情况,四种状态需要判断:
- mouseenter
nowY > originY
offsetY >= 0
.
nowY < originY
offsetY > 0
.
- mouseleave
nowY > originY
offsetY < 0
.
nowY < originY
offsetY > 0
参考代码:
$(element).on('mouseenter', (e) => {
if(!$table.selector.drag) return;
let _uniqueid = $(e.currentTarget).attr('data-uniqueid');
let originY = $table.selector.y;
let checks = [];
if(e.pageY > originY) {
if(e.offsetY + offset >= 0) checks.push(uniqueIdType === 'int'? parseInt(_uniqueid): _uniqueid);
}
else {
if(e.offsetY + offset > 0) checks.push(uniqueIdType === 'int'? parseInt(_uniqueid): _uniqueid);
}
$table.bootstrapTable('checkBy', {field: uniqueId, values: checks});
});
$(element).on('mouseleave', (e) => {
if(!$table.selector.drag) return;
let _uniqueid = $(e.currentTarget).attr('data-uniqueid');
let originY = $table.selector.y;
let unchecks = [];
if(e.pageY > originY) {
if(e.offsetY < 0) unchecks.push(uniqueIdType === 'int'? parseInt(_uniqueid): _uniqueid);
}
else {
if(e.offsetY > 0) unchecks.push(uniqueIdType === 'int'? parseInt(_uniqueid): _uniqueid);
}
$table.bootstrapTable('uncheckBy', {field: uniqueId, values: unchecks});
});
需要注意的是:BootstrapTable 的
checkBy
和uncheckBy
方法采用的是 “===
” 运算符,请自行转换数据类型。
五、继续优化
- 将 HTML 和 CSS 集成到函数中,减少复杂性,方便管理;
- 优化判断逻辑防止出现隔行选择;
【如果觉得本文不错 “点赞、收藏、关注”,是对作者最大的鼓励。】