当前位置: 首页 > news >正文

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代码。

  页面整个js代码

还是重点看看部分代码

1、注册左边可拖拽

复制代码
$('#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) {
            }
        });
复制代码

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

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

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

2、注册右边drop

复制代码
    $("#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();
            }
        });
复制代码

这里代码和之前有点变化

(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、撤销操作

复制代码
    $("#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();
        });
复制代码

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

四、总结

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

 

五、优化方案(11月6日)

1、注册drap的方法

复制代码
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();这样在拖动的时候就看不到未选中的行了。

2、精准定位到右边表格指定位置:

复制代码
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();

            }
        });
    };
复制代码

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

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





本文转自懒得安分博客园博客,原文链接:http://www.cnblogs.com/landeanfen/p/4926137.html,如需转载请自行联系原作者


相关文章:

  • HTMl编写计算器
  • 使用PEAP实现802.1X
  • 超实用Mac软件分享(二)
  • JDBC获取新增记录的自增主键
  • HTTP协议中状态码的应用
  • Android笔记:触摸事件的分析与总结----MotionEvent对象
  • Ubuntu的系统安装步骤
  • VC 文件复制函数
  • 再议“创建类似于输入法窗口的非激活窗口”
  • 20.23 20.4 20.5告警系统邮件引擎(上中下);20.26 运行告警系统
  • 20.20 告警系统主脚本;20.21 告警系统配置文件;20.22 告警系统监控项目
  • 2007年1月4日测试在额外域控制器上夺取FSMO笔记
  • centos安装raid卡驱动总结
  • 逻辑DG ORA-16240: Waiting for logfile
  • Zabbix Server is not running: the information displayed may not be current
  • E-HPC支持多队列管理和自动伸缩
  • HashMap剖析之内部结构
  • Mocha测试初探
  • nginx 负载服务器优化
  • node 版本过低
  • React-Native - 收藏集 - 掘金
  • SQLServer插入数据
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • XForms - 更强大的Form
  • 开发基于以太坊智能合约的DApp
  • 开源SQL-on-Hadoop系统一览
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 排序算法学习笔记
  • 树莓派 - 使用须知
  • 微信支付JSAPI,实测!终极方案
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • MyCAT水平分库
  • RDS-Mysql 物理备份恢复到本地数据库上
  • ​LeetCode解法汇总518. 零钱兑换 II
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • #pragma data_seg 共享数据区(转)
  • #QT(串口助手-界面)
  • (1)bark-ml
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (四)汇编语言——简单程序
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • ***详解账号泄露:全球约1亿用户已泄露
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • /bin/rm: 参数列表过长"的解决办法
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • [ 数据结构 - C++]红黑树RBTree
  • [1204 寻找子串位置] 解题报告
  • [20170713] 无法访问SQL Server