前段时间,客户反映,系统里有一部分功能需要一个排序,因为这部分数据导出的时候需要严格按照顺序来。但是一直忙于别的需求,没有取考虑这部分内容,周末的时候,客户又反映了这个问题。前端一向不好,英文也很差的我只能求助百度。之后得知jquery ui能满足这种需求。整合项目中也引入了这个js,决定试一试。
前端排序
不得不说jquery ui这个东西强大,只需要两行代码就能再表格上实现界面拖动。
//在table标签加一个class
$( ".sort tbody").sortable(); //移动表格
$( ".sort tbody").disableSelection(); //移动后固定
后端排序
前端排序并不能满足我们的需求,因为需要应用到数据库中,确保刷新后顺序仍然正常。
sorttable提供了几个事件供我们实现数据的排序
var fixHelper = function(e, ui) {
ui.children().each(function() {
$(this).width($(this).width()); //在拖动时,拖动行的cell(单元格)宽度会发生改变。在这里做了处理就没问题了
});
return ui;
};
//上面部分的代码是我从网上找得,确保移动行的时候,宽度保持不变。这样比较美观
$( ".sort tbody").sort({
cursor: "move",
helper: fixHelper, //调用fixHelper
axis:"y", //行移动
start:function(e, ui){
ui.helper.css({"background":"#fff"}) //拖动时的行,要用ui.helper
return ui;
},sort:function(e, ui){
item = ui.item; //当前拖动的元素
move_id = item.attr("id");
move_sort = item.attr("sort"); //当前元素的顺序
//alert(item);
replace_item = $(this).find('tr').filter('.ui-sort-placeholder').prev('tr');//当移动行时,会出现一个代替行的中间件,因为这个中间件会一直出现在移动行的下方,所以当临界值时会取不到值。
replace_sort = replace_item.attr('sort');
replace_id = replace_item.attr('id');
// 选中的id和sort
move_sort = parseInt(move_sort);
move_id = parseInt(move_id);
// 当从下往上移动时,调整取值(.ui-sort-placeholder)为移动的中间值
if (move_sort > replace_sort) {
replace_item = $(this).find('tr').filter('.ui-sort-placeholder').next('tr');
replace_sort = replace_item.attr('sort');
replace_id = replace_item.attr('id');
}
// 替换的sort 和id
replace_sort = parseInt(replace_sort);
replace_id = parseInt(replace_id);
},stop:function(e, ui){
// alert(move_id);
if (move_sort==replace_sort) { //不移动
return false;
}else if (isNaN(replace_sort)){
replace_id = $('.sort tbody').find('tr').eq(1).attr('id');
replace_sort = $('.sort tbody').find('tr').eq(1).attr('sort');
}
if(window.confirm("是否确定排列顺序?")){
var schedule_id = $("#schedule_id").val();
var big_media_id = $('#big_media_id').val();
var csrf = "<?= Yii::$app->request->csrfToken ?>";
$.post('/subject/sort',{move_id:move_id,
replace_id:replace_id,
move_sort:move_sort,
replace_sort:replace_sort,
schedule_id:schedule_id,
big_media_id:big_media_id,
_csrf:csrf},function(data){
$(".forajax").empty();
$(".forajax").append(data);
})
}
// alert('选择'+move_sort);
// alert('替换'+replace_sort);
// return false;
}
});
$( ".sort tbody" ).disableSelection();
上面的代码已经有了可观的注释,下面简单说一下思路。
前端代码使用了三个事件。start、sort、stop。分别是拖动样式配置,拖动过程取值和松开鼠标后的异步提交。
后端的逻辑比较简单,主要是通过在行上的id(主键)sort(排序)。将移动的id和sort,与将要插入位置的id和sort提交到后端。
当从上往下拖的时候(即顺序)。先将插入位置sort以后(不包括)的值加1,再把移动的sort等于插入位置的sort+1.
当从下往上拖的时候(即倒序)。先将插入位置sort及以后(包括)的值加1,再把移动的sort等于插入位置的sort+1.
前端取数的时候需要多加注意,主要考虑临界值的问题和顺序、倒序的问题。确保拖动的值与交换位置的值相对应,避免混乱。 这里思路就不说了,因为需要操作才会发现问题在哪里。
我的逻辑可能比较笨,但是能解决问题。我一般喜欢做法是保证无论正序,倒序。取数一致后再交给后端处理,避免混乱。如果有较好的逻辑也欢迎提供。