JS组件Bootstrap Table表格多行拖拽效果实现代码

前端之家收集整理的这篇文章主要介绍了JS组件Bootstrap Table表格多行拖拽效果实现代码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前言:前天刚写了篇,今天接到新的需要,需要在之前表格行拖拽的基础上能够同时拖拽选中的多行。用了半天时间研究了下,效果是出来了,但是感觉不尽如人意。先把它分享出来,以后想到更好的办法再优化吧。

一、效果展示

1、拖动前

2、拖动中

3、拖动后

4、撤销回到拖动前状态

二、需求分析 通过上篇我们知道,如果要实现拖拽,必须要有一个可以拖拽的标签,或者叫容器,比如上篇里面的tr就是一个拖拽的容器,那么如果要实现选择行的拖拽,那么博主的第一反应是将选中的行放到一个容器里面,比如放到一个div中,然后注册这个div的可拖拽,可是实际情况是,tr是在table里面的标签,如果将tr用div包起来,势必将table里面的样式打乱,这个界面就真的是乱掉了。很显然,这条路走不通。然后通过谷歌浏览器审核元素知道,用Bootstrap table生成的表格tr的父级元素实际上是tbody,于是在想是否可以注册tbody的拖拽,实践证明,此法可行。于是就此开干。

三、代码示例 cshtm的代码就不再重复,和上篇相同。我们重点来看看js代码。

var m_oTable = null;

$(function () {
//1.初始化表格
m_oTable = new TableInit();
m_oTable.Init();

//2.初始化按钮事件
var oButtonInit = new ButtonInit();
oButtonInit.Init();

//3.日期控件的初始化
$(".datetimepicker").datetimepicker({
format: 'yyyy-mm-dd hh:ii',autoclose: true,todayBtn: true,});

});

//表格相关事件和方法
var TableInit = function () {
var oTableInit = new Object();

oTableInit.Init = function () {
$('#tb_order_left').bootstrapTable({
url: '/api/OrderApi/get',method: 'get',striped: true,cache: false,pagination: true,height: 600,uniqueId:"TO_ORDER_ID",queryParams: oTableInit.queryParams,queryParamsType: "limit",sidePagination: "server",pageSize: 10,pageList: [10,25,50,100],search: true,strictSearch: true,showColumns: true,showRefresh: true,minimumCountColumns: 2,clickToSelect: true,columns: [{
checkbox: true
},{
field: 'ORDER_NO',title: '订单号'
},{
field: 'BODY_NO',title: '车身号'
},{
field: 'VIN',title: 'VIN码'
},{
field: 'TM_MODEL_MATERIAL_ID',title: '整车编码'
},{
field: 'ORDER_TYPE',title: '订单类型'
},{
field: 'ORDER_STATUS',title: '订单状态'
},{
field: 'CREATE_DATE',title: '订单导入时间'
},{
field: 'PLAN_DATE',title: '订单计划上线日期'
},{
field: 'VMS_NO',title: 'VMS号'
},{
field: 'ENGIN_CODE',title: '发动机号'
},{
field: 'TRANS_CODE',title: '变速箱号'
},{
field: 'OFFLINE_DATE_ACT',title: '实际下线日期'
},{
field: 'HOLD_RES',title: 'hold理由'
},{
field: 'SPC_FLAG',title: '特殊标记'
},],onLoadSuccess: function (data) {
oTableInit.InitDrag();
if (data.total > 0) {
var iheight = $('#div_tableleft').find(".fixed-table-container").height();
$('#div_tableleft').find(".fixed-table-container").height(iheight + 36);
}
},onCheckAll: function (rows) {
$("#tb_order_left tbody tr").addClass("selected");
},onUncheckAll: function (rows) {
$("#tb_order_left tbody tr").removeClass("selected");
}
});

$('#tb_order_right').bootstrapTable({
url: '/api/OrderApi/get',toolbar: '#toolbar_right',queryParams: oTableInit.queryParamsRight,//ajaxOptions: { departmentname: "",statu: "" },columns: [
{
field: 'ORDER_NO',onLoadSuccess: function (data) {
oTableInit.InitDrop();
}
});
};

oTableInit.InitDrag = function () {
$('#tb_order_left tbody').draggable({
helper: "clone",start: function (event,ui) {
var old_left_data = JSON.stringify($('#tb_order_left').bootstrapTable("getData"));
var old_right_data = JSON.stringify($('#tb_order_right').bootstrapTable("getData"));
var odata = { index: ++i_statuindex,left_data: old_left_data,right_data: old_right_data };
arrdata.push(odata);
},stop: function (event,ui) {
}
});
};

oTableInit.InitDrop = function () {
$("#div_tableright div[class=fixed-table-container]").droppable({
drop: function (event,ui) {
var arrtr = $(ui.helper[0]).find("tr[class=selected]");
if (arrtr.length <= 0) {
alert("请先选中要插单的行");
return;
}
var oTop = ui.helper[0].offsetTop;
var iRowHeadHeight = 40;
var iRowHeight = 37;
var rowIndex = 0;
if (oTop <= iRowHeadHeight + iRowHeight / 2) {
rowIndex = 0;
}
else {
rowIndex = Math.ceil((oTop - iRowHeadHeight) / iRowHeight);
}
for (var i = 0; i < arrtr.length; i++) {
var arrtd = $(arrtr[i]).find("td");
var uniqueid = $(arrtr[i]).attr("data-uniqueid");
var rowdata = {
ORDER_NO: $(arrtd[1]).text(),BODY_NO: $(arrtd[2]).text(),VIN: $(arrtd[3]).text(),TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(),ORDER_TYPE: $(arrtd[5]).text(),ORDER_STATUS: $(arrtd[6]).text(),CREATE_DATE: $(arrtd[7]).text() == "-" ? null : $(arrtd[7]).text(),PLAN_DATE: $(arrtd[8]).text() == "-" ? null : $(arrtd[8]).text(),VMS_NO: $(arrtd[9]).text(),ENGIN_CODE: $(arrtd[10]).text(),TRANS_CODE: $(arrtd[11]).text(),OFFLINE_DATE_ACT: $(arrtd[12]).text() == "-" ? null : $(arrtd[12]).text(),HOLD_RES: $(arrtd[13]).text(),SPC_FLAG: $(arrtd[14]).text(),TO_ORDER_ID: uniqueid

};
$("#tb_order_right").bootstrapTable("insertRow",{ index: rowIndex++,row: rowdata });
$('#tb_order_left').bootstrapTable("removeByUniqueId",uniqueid);
}

oTableInit.InitDrag();
}
});
};

oTableInit.queryParams = function (params) { //配置参数
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit,//页面大小
offset: params.offset,//页码
strBodyno: $("#txt_search_bodynumber").val(),strVin: $("#txt_search_vinnumber").val(),strOrderno: $("#txt_search_ordernumber").val(),strEngincode: $("#txt_search_engin_code").val(),strOrderstatus: 0,strTranscode: $("#txt_search_trans_code").val(),strVms: $("#txt_search_vms").val(),strCarcode: $("#txt_search_carcode").val(),strImportStartdate: $("#txt_search_import_startdate").val(),strImportEnddate: $("#txt_search_import_enddate").val(),strSendStartdate: $("#txt_search_send_startdate").val(),strSendEnddate: $("#txt_search_send_enddate").val(),};
return temp;
};

oTableInit.queryParamsRight = function (params) { //配置参数
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit,//页码
strBodyno: "",strVin: "",strOrderno: "",strEngincode: "",strOrderstatus: 5,strTranscode: "",strVms: "",strCarcode: "",strImportStartdate: "",strImportEnddate: "",strSendStartdate: "",strSendEnddate: "",};
return temp;
};

return oTableInit;
};

//页面按钮初始化事件
var ButtonInit = function () {
var oInit = new Object();
var postdata = {};

oInit.Init = function () {

//查询点击事件
$("#btn_query").click(function () {
$("#tb_order_left").bootstrapTable('refresh');
});

//重置点击事件
$("#btn_reset").click(function () {
$(".container-fluid").find(".form-control").val("");
$("#tb_order_left").bootstrapTable('refresh');
});

//插单操作点击事件
$("#btn_insertorder").click(function () {

});

//撤销操作点击事件
$("#btn_cancel").click(function () {
if (i_statuindex <= 0) {
return;
}
for (var i = 0; i < arrdata.length; i++) {
if (arrdata[i].index != i_statuindex) {
continue;
}
var arr_left_data = eval(arrdata[i].left_data);
var arr_right_data = eval(arrdata[i].right_data);

$('#tb_order_left').bootstrapTable('removeAll');
$('#tb_order_right').bootstrapTable('removeAll');
$('#tb_order_left').bootstrapTable('append',arr_left_data);
for (var x = 0; x < arr_right_data.length; x++) {
$("#tb_order_right").bootstrapTable("insertRow",{ index: x,row: arr_right_data[x] });
}

//$('#tb_order_right').bootstrapTable('append',arr_right_data);//append之后不能drop
break;
}
i_statuindex--;

//重新注册可拖拽
m_oTable.InitDrag();
//m_oTable.InitDrop();
});
};

return oInit;
};

还是重点看看部分代码

1、注册左边可拖拽

这里代码很简单,主要做了两件事:

(1)注册tbody的可拖拽,同样适用的JQuery UI的draggable事件。

(2)在开始拖拽前,保存两边表格的数据,用于还原的操作。

2、注册右边drop

oTableInit.InitDrag();
}
});

这里代码和之前有点变化

(1)注册#div_tableright div[class=fixed-table-container]标签的droppable,这个标签是Bootstrap Table表格初始化后自动生成的,为什么不直接注册表格#tb_order_right的droppable,是因为这个标签作用域太小,会导致拖过来的tbody捕捉不到drop事件。而注册表格外部的#div_tableright div[class=fixed-table-container]这个div标签可以解决问题。

(2)通过var arrtr = $(ui.helper[0]).find("tr[class=selected]");找到拖过来tbody里面选中的行,然后将数据取出依次插入右边表格,左边表格则依次删除行数据。

(3)这里有点麻烦的是找drop的位置,我们知道,要想将左边选中的行放到右边指定的位置,那么就得得到当前鼠标drop的位置,这里通过ui.helper[0].offsetTop属性来获得鼠标的Y轴位置,通过计算得到要插入的位置。

3、撤销操作  

$('#tb_order_left').bootstrapTable('removeAll');
$('#tb_order_right').bootstrapTable('removeAll');
$('#tb_order_left').bootstrapTable('append',arr_right_data);//append之后不能drop
break;
}
i_statuindex--;

//重写注册可拖拽
m_oTable.InitDrag();
//m_oTable.InitDrop();
});

撤销操作和之前也基本相同。

四、总结

效果是完成了,美中不足的是每次拖过去的都是整个tbody,而不是选中的行,奈何多个选中的行无法用某一个容器包起来。暂时没找到合适的解决方案。先这样吧,等以后想到好的方案了再优化吧。

五、优化方案

1、注册drap的方法

增加了这一句$(ui.helper[0]).find("tr[class!=selected]").remove();这样在拖动的时候就看不到未选中的行了。 2、精准定位到右边表格指定位置:

oTop) { rowIndex = i; bIsBottom = false;//这里参数用来定义拖动到右边表格最下面的情况,这时没有进入到此条件判断里面。 break; } } if (bIsBottom) { rowIndex = trs.length; }

for (var i = 0; i < arrtr.length; i++) {
var arrtd = $(arrtr[i]).find("td");
var uniqueid = $(arrtr[i]).attr("data-uniqueid");
var rowdata = {
ORDER_NO: $(arrtd[1]).text(),ORDER_STATUS_NAME: $(arrtd[6]).text(),TO_ORDER_ID: uniqueid,ORDER_STATUS:0

};
$("#tb_order_right").bootstrapTable("insertRow",uniqueid);
}

oTableInit.InitDrag();

}
});
};

因为每一行的行高不确定,是由行里面的数据动态撑出来的,所以这里也动态计算drop的位置。

至此,这个小的功能基本告一段落,基本的效果和待优化点也完成了。

源码下载:Bootstrap Table表格多行拖拽效果

如果大家还想深入学习,可以点击进行学习,再为大家附两个精彩的专题:

以上就是本文的全部内容,希望本文所述对大家学习javascript程序设计有所帮助。

原文链接:https://www.f2er.com/bootstrap/51240.html

猜你在找的Bootstrap相关文章