
2、拖动中

3、拖动后

4、撤销回到拖动前状态

二、需求分析
通过上篇我们知道,如果要实现拖拽,必须要有一个可以拖拽的标签,或者叫容器,比如上篇里面的tr就是一个拖拽的容器,那么如果要实现选择行的拖拽,那么博主的第一反应是将选中的行放到一个容器里面,比如放到一个div中,然后注册这个div的可拖拽,可是实际情况是,tr是在table里面的标签,如果将tr用div包起来,势必将table里面的样式打乱,这个界面就真的是乱掉了。很显然,这条路走不通。然后通过谷歌浏览器审核元素知道,用Bootstrap table生成的表格tr的父级元素实际上是tbody,于是在想是否可以注册tbody的拖拽,实践证明,此法可行。于是就此开干。
三、代码示例
cshtm的代码就不再重复,和上篇相同。我们重点来看看js代码。
var i_statuindex = 0;var arrdata = [];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, striped: true, 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", method: "get", toolbar: "#toolbar_right", striped: true, cache: false, striped: true, pagination: true, height: 600, queryParams: oTableInit.queryParamsRight, queryParamsType: "limit", //ajaxOptions: { departmentname: "", statu: "" }, sidePagination: "server", pageSize: 10, pageList: [10, 25, 50, 100], search: true, strictSearch: true, showRefresh: true, minimumCountColumns: 2, columns: [ { 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.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, //页面大小 offset: params.offset, //页码 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;};还是重点看看部分代码$("#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) { } }); $("#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(); } }); $("#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(); });撤销操作和之前也基本相同。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); $(ui.helper[0]).find("tr[class!=selected]").remove(); }, stop: function (event, ui) { } }); };增加了这一句$(ui.helper[0]).find("tr[class!=selected]").remove();这样在拖动的时候就看不到未选中的行了。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) {toastr.warning("请先选中要插单的行");return; } var oTop = ui.helper[0].offsetTop; //因为表格每行的高度可能不一致,所以这里取插入行位置的办法是:取右边表格的行高依次累加,计算行索引。 var rowIndex = 0; var bIsBottom = true; var iRowHeadHeight = 40; var addHeight = iRowHeadHeight; var trs = $("#tb_order_right tbody tr"); for (var i = 0; i < trs.length; i++) {addHeight += $(trs[i]).height();if (addHeight > 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(),BODY_NO: $(arrtd[2]).text(),VIN: $(arrtd[3]).text(),TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(),ORDER_TYPE: $(arrtd[5]).text(),ORDER_STATUS_NAME: $(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,ORDER_STATUS:0};$("#tb_order_right").bootstrapTable("insertRow", { index: rowIndex++, row: rowdata });$("#tb_order_left").bootstrapTable("removeByUniqueId", uniqueid); } oTableInit.InitDrag(); } }); };