我正在使用 jQuery UI 附带的可排序函数来对表行重新排序。它工作正常,这里是一个 JSFiddle,下面是我的 HTML 和 JS
<table style="width: 100%;">
<thead>
<tr>
<th>ID</th>
<th>Fruit</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Apple</td>
</tr>
<tr>
<td>2</td>
<td>Pear</td>
</tr>
<tr class="sticky">
<td>3</td>
<td>Banana</td>
</tr>
<tr>
<td>4</td>
<td>Raspberry</td>
</tr>
<tr>
<td>5</td>
<td>Mango</td>
</tr>
</tbody>
</table>
$(function(){
$("table tbody").sortable();
});
但是我希望能够同时拖动多行。基本上,当您拖动
tr
时,如果其正下方的 tr
具有 sticky
类,则需要将 tr
与其一起拖动。因此,在我的示例中,任何时候您想要拖动并重新排序“Pear”行,下面的“Banana”行都会随之移动。
我认为可以使用辅助函数来做到这一点,但我真的不知道从哪里开始。如果有人可以建议我最好的方法并为我指明正确的方向,那就太好了。
您可以使用
start
事件检查下一个 tr
的 class
是否为 sticky
并将其插入到 stop
事件上拖动的项目之后。我正在使用 css
方法来为“粘性”项目设置动画。
$(function() {
var $draggedItem, $stickyItem, itemWidth, itemHeight;
$("table tbody").sortable({
start: function(event, ui) {
$draggedItem = $(ui.item[0]);
//Store the constant width and height values in variables.
itemWidth = $draggedItem.width();
itemHeight = $draggedItem.height();
//next is called twice because a hidden "tr" is added when sorting.
var $nextChild = $(ui.item[0]).next().next();
if ($nextChild.hasClass('sticky')) {
$stickyItem = $nextChild;
}
else {
$stickyItem = undefined;
}
},
sort: function() {
if ($stickyItem != undefined) {
//Set the css to match the dragged item's css, with the exception of "top", which includes an offset.
$stickyItem.css({
"z-index": $draggedItem.css('z-index'),
"position": "absolute",
"width": itemWidth,
"height": itemHeight,
"left": $draggedItem.css('left'),
"top": $draggedItem.position().top + itemHeight,
});
}
},
stop: function() {
if ($stickyItem != undefined) {
$stickyItem.insertAfter($draggedItem);
//Remove the style attribute to reset to thed default style.
$stickyItem.removeAttr('style');
}
}
});
});
注意: 如果存在粘性项目,您可以通过仅绑定
sort
和 stop
事件来进一步改进上述内容。
对于那些想要防止在粘性行与其上方的行之间插入行的人,这里是 Yass 解决方案的稍微修改版本:
$(function () {
let $draggedItem, $stickyItem, itemWidth, itemHeight, cancelSortable;
$("table tbody").sortable({
start: function (event, ui) {
$draggedItem = $(ui.item[0]);
//Store the constant width and height values in variables.
itemWidth = $draggedItem.width();
itemHeight = $draggedItem.height();
//next is called twice because a hidden "tr" is added when sorting.
let $nextChild = $(ui.item[0]).next().next();
if ($nextChild.hasClass('sticky')) {
$stickyItem = $nextChild;
} else {
$stickyItem = undefined;
}
},
sort: function (event, ui) {
if ($stickyItem !== undefined) {
//Set the css to match the dragged item's css, with the exception of "top", which includes an offset.
$stickyItem.css({
"z-index": $draggedItem.css('z-index'),
"position": "absolute",
"width": itemWidth,
"height": itemHeight,
"left": $draggedItem.css('left'),
"top": $draggedItem.position().top + itemHeight,
});
}
if (ui.placeholder.next() !== undefined && ui.placeholder.next().hasClass("sticky")) {
ui.placeholder.hide();
cancelSortable = true;
} else {
ui.placeholder.show();
cancelSortable = false;
}
},
stop: function () {
if (cancelSortable) {
$(this).sortable("cancel");
}
if ($stickyItem !== undefined) {
$stickyItem.insertAfter($draggedItem);
//Remove the style attribute to reset to the default style.
$stickyItem.removeAttr('style');
}
}
});
});
可对两行以上进行分组的可排序选项(编辑连续两次使用 next() 的“start”参数中的行):
let $nextChildren = $(ui.item[0]).nextAll(".sticky:visible").not(".ui-sortable-placeholder");
if ($(ui.item[0]).next().next().hasClass('sticky')) {
$stickyItem = $nextChildren;
}
此代码获取所有具有“粘性”类的下一行,即使它们之间存在没有该类的行。