<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> <link href="https://cdn.bootcss.com/bootstrap-table/1.12.1/bootstrap-table.min.css" rel="stylesheet"> <style type="text/css"> .transferBox { height: 100%; border: 1px solid #beb8b8; border-radius: 6px; } .shuttleBtn { height: 100%; } .transferBtn .btn { display: block; } .transferBtn .btn:first-child { margin-bottom: 20px; } .transferBtn .btnList { position: absolute; width: 80%; top: 50%; margin-top: -40px; } .transferBox .search { width: 100%; } .transferBtn .btn-default { background: #ccc; cursor: no-drop; } </style> </head> <body> <div id="transferContainer" class="row" style="height: 700px;width: 950px;"></div> </body> </html> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> <script src="https://cdn.bootcss.com/bootstrap-table/1.12.1/bootstrap-table.min.js"></script> <script src="https://cdn.bootcss.com/bootstrap-table/1.12.1/locale/bootstrap-table-zh-CN.min.js"></script> <script src="Transfer.js"></script> <!-- 中间点击按钮图标没显示出来没关系 是因为引入的cdn问题 正常下载引入bootstrap.css的话没问题的 --> <!-- 此处演示的数据源为一个 用falg去区分在哪个里面 --> <script type="text/javascript"> var data = [{ "importUnitId": "950258484706803712", "importUnitName": "分数对比2016", "flag": false, }, { "importUnitId": "949202813861232640", "importUnitName": "对比1", "flag": false, }, { "importUnitId": "948380218236600320", "importUnitName": "测试2", "flag": false, }, { "importUnitId": "946590730653007872", "importUnitName": "对比4", "flag": false, }, { "importUnitId": "946590730653007889", "importUnitName": "对比954", "flag": true, }, { "importUnitId": "946590730653008647", "importUnitName": "对比88", "flag": true, } ] $('#transferContainer').transfer({ titles: ['待选对比档案', '已选对比档案'], search: true, uniqueId: "importUnitId",//唯一id dataSource: data, maxSelect: 6, diffKey: 'flag', unselectColumns: [{ field: 'flag', checkbox: true }, { field: 'importUnitName', title: '档案名称' } ] }); $('#btn').click(function(){ var data= $('#transferContainer').transfer('getData', 'selectData', 'importUnitId'); console.log(data) }) $('#refresh').click(function(){ $('#transferContainer').transfer('refresh',data) }) </script>
Transfer.js
(function ($, window, document) { var transfer = function (el, options) { this.option = options; this.$el = $(el); this.selectData=[]; this.unselectData=[]; this.init(); }; transfer.DEFAULTS = { titles:['待选列表','已选列表'], search: true,///是否显示搜索查询 showRefresh: false,// clickToSelect: true, pagination: false,//是否支持分页 autoHeight:false, url:'', type:"get", queryParams:{}, contentType: 'application/json', paginationDetail:false, maxSelect:undefined, uniqueId: "",//每行的id dataSource:[],//默认数据源为同一个 内部会通过diffKey去区分是待选框的 还是已选框的数据,如果selectdataSource存在 则或解析为待选数据框里的数据 selectdataSource:undefined, diffKey:'flag', selectColumns:[], unselectColumns:[] }; transfer.prototype = { init: function () { this.initoption(); this.initContainer(); this.initBothTable(); if(this.option.url){ this.initServer(); }else{ this.classifyData(); } this.initEvent(); }, /* * 渲染穿梭框页面结构*/ initContainer: function () { var _this=this; var containerHtml=['<div class="col-sm-5 transferBox">', '<h3 class="unselectTitle" style="margin: 0;padding: 5px 0 10px 0;">'+this.unselectTitle+'<span style="margin-left: 5px;">(<span id="checkedNum1"></span><span id="unselectTotalNum"></span>)</span></h3>', '<table id="transferUnselectTable"></table>', '</div>', '<div class="col-sm-2 transferBtn" style="height: 100%">', '<div class="btnList">', '<span class="btn btn-default forwardBtn" ><i class="glyphicon glyphicon-forward"></i></span>', '<span class="btn btn-default backwardBtn" ><i class="glyphicon glyphicon-backward"></i></span>', '</div>', '</div>', '<div class="col-sm-5 transferBox">', '<h3 class="selectTitle" style="margin: 0;padding: 5px 0 10px 0;">'+this.selectTitle+'<span style="margin-left: 5px;">(<span id="checkedNum2"></span><span id="selectTotalNum"></span>)</span></h3>', '<table id="transferSelectTable"></table>', '</div>'].join(''); this.$el.html(containerHtml); this.$unselectTable=this.$el.find('#transferUnselectTable');//待选表格 this.$unselectTotalNum=this.$el.find('#unselectTotalNum');//存放待选表格内总的数量 this.$checkedNum1=this.$el.find('#checkedNum1');//存放待选表格中已勾选的数量 this.$forwardBtn=this.$el.find('.forwardBtn');//向待选表格内添加的按钮 this.$selectTable=this.$el.find('#transferSelectTable');//已选表格 this.$selectTotalNum=this.$el.find('#selectTotalNum');//存放已选表格内总的数量 this.$checkedNum2=this.$el.find('#checkedNum2');//存放已选表格中已勾选的数量 this.$backwardBtn=this.$el.find('.backwardBtn');//向待选表格内添加的按钮 this.option.height=this.$el.outerHeight()-this.$el.find('h3.unselectTitle').outerHeight()-8; }, /* * 参数处理*/ initoption:function(){ /* * 两边标题参数处理*/ if(typeof this.option.titles=='string'|| (this.option.titles instanceof Array&&this.option.titles.length==1)){ this.selectTitle=this.unselectTitle=this.option.titles+''; }else if(this.option.titles instanceof Array&&this.option.titles.length>1){ this.unselectTitle=this.option.titles[0]; this.selectTitle=this.option.titles[1]; } /* * 两个table渲染内容若一样,给任意一个columns即可*/ if(this.option.selectColumns instanceof Array&&this.option.unselectColumns instanceof Array&&(!this.option.selectColumns.length&&this.option.unselectColumns.length)){ this.option.selectColumns= $.extend(true,[],this.option.unselectColumns); }else if(this.option.selectColumns instanceof Array&&this.option.unselectColumns instanceof Array&&(this.option.selectColumns.length&&!this.option.unselectColumns.length)){ this.option.unselectColumns=$.extend(true,[],this.option.selectColumns); }else if(!this.option.selectColumns instanceof Array||!this.option.unselectColumns instanceof Array){ console.error('参数selectColumns和unselectColumns必须为数组'); return false; } /* * 两边table两边渲染选中的field不能一样,此处强制替换了,参数中可不写field*/ this.option.selectColumns[0].field=this.option.diffKey+'s'; this.option.unselectColumns[0].field=this.option.diffKey; }, /* * 从数据中挑出已选列表和待选列表的数据*/ classifyData:function(){ /* *数据源如果为同一个则通过diffKey去区分 * */ if(!this.option.dataSource){console.error('dataSource参数为必填项,请检查');return false;} if(this.option.selectdataSource){ this.selectData=this.option.selectdataSource; this.unselectData=this.option.dataSource; }else{ for(var i=0;i<this.option.dataSource.length;i++){ if(this.option.dataSource[i][this.option.diffKey]){ this.selectData.push(JSON.parse(JSON.stringify(this.option.dataSource[i]))); }else{ this.unselectData.push(JSON.parse(JSON.stringify(this.option.dataSource[i]))); } } } this.refreshTable(); this.showTotalNum(); }, /* * 当数据发生变化重新渲染表格*/ refreshTable:function(){ this.$unselectTable.bootstrapTable("load",this.unselectData); this.$selectTable.bootstrapTable("load",this.selectData); }, /* * 当表格数据总量发生变化,相应改变其总数*/ showTotalNum:function(){ this.$unselectTotalNum.html(this.unselectData.length+'条'); this.$selectTotalNum.html(this.selectData.length+'条'); }, /* * 初始化表格,开始是没有数据加入*/ initBothTable:function(){ var _this=this; this.$unselectBootstrapTable=this.$unselectTable.bootstrapTable({ search: _this.option.search, showRefresh: _this.option.showRefresh, showToggle: false, showColumns: false, paginationDetail:_this.option.paginationDetail, clickToSelect: _this.option.clickToSelect, pagination: _this.option.pagination, sidePagination: 'client', autoHeight:false, height:_this.option.height, data:[], sortName: "createTime", sortOrder: "desc", uniqueId: _this.option.uniqueId, columns:_this.option.unselectColumns }); this.$selectBootstrapTable=this.$selectTable.bootstrapTable({ search: _this.option.search, showRefresh: _this.option.showRefresh, showToggle: false, paginationDetail:_this.option.paginationDetail, showColumns: false, clickToSelect: _this.option.clickToSelect, pagination: _this.option.pagination, autoHeight:false, height:_this.option.height, data:[], sortName: "createTime", sortOrder: "desc", uniqueId: _this.option.uniqueId, columns:_this.option.selectColumns }); this.$selectBootstrapTable.on('check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table', function (e, rows) { var num=_this.$selectTable.find('tr input[name="btSelectItem"]:checked').length; if(num){ _this.$backwardBtn.removeClass('btn-default').addClass('btn-info'); _this.$checkedNum2.html(num+'/'); }else{ _this.$backwardBtn.removeClass('btn-info').addClass('btn-default'); _this.$checkedNum2.html(''); } }); this.$unselectBootstrapTable.on('check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table', function (e, rows) { var num=_this.$unselectTable.find('tr input[name="btSelectItem"]:checked').length; if(num){ _this.$forwardBtn.removeClass('btn-default').addClass('btn-info'); _this.$checkedNum1.html(num+'/'); }else{ _this.$forwardBtn.removeClass('btn-info').addClass('btn-default'); _this.$checkedNum1.html(''); } }); }, /* * 请求数据*/ initServer:function(){ var _this=this; if(this.option.url){ $.ajax({ url: _this.option.url, type: _this.option.type, contentType: _this.option.contentType, //对应后台的@RequestBody data:_this.option.queryParams||null, data: _this.option.contentType==='application/json' && _this.option.type === 'post' ? JSON.stringify(_this.option.queryParams) : _this.option.queryParams, success: function (res) { if(res.success){ _this.option.dataSource=res.data; _this.selectData=[]; _this.unselectData=[]; _this.classifyData(); } }, error: function (result) { } }); } }, /* * 初始化点击事件*/ initEvent:function(){ var _this=this; this.$forwardBtn.click(function(){ _this.transferData($(this),1); }); this.$backwardBtn.click(function(){ _this.transferData($(this),0); }); }, /* * 获取选中行的id*/ getSelect:function($tr){ return $.map($tr,function(ele,index){ if($(ele).find('input[name="btSelectItem"]').is(':checked')){ return $(ele).attr("data-uniqueid"); } }); }, /* * 两边数据穿梭逻辑 * @params type:穿梭方向*/ transferData:function($dom,type){ var _this=this; if(!$dom.hasClass('btn-info')){ return false; } if(type){ var selectList=this.getSelect(this.$unselectTable.find('tbody tr')); if((this.option.maxSelect-0)&&typeof (this.option.maxSelect-0)=="number"){ var currenNum=selectList.length+this.selectData.length; if(currenNum>this.option.maxSelect){ alert(this.selectTitle+'最多只能存在'+this.option.maxSelect+'个,您选的太多了!'); return false; } } for(var i=0;i<this.unselectData.length;i++){ if(selectList.indexOf(this.unselectData[i][this.option.uniqueId])>=0){ this.unselectData[i][this.option.selectColumns[0].field]=false; this.selectData.push(this.unselectData[i]); this.unselectData.splice(i,1); i--; } } this.refreshTable(); this.$forwardBtn.removeClass('btn-info').addClass('btn-default'); this.$checkedNum1.html(''); }else{ var selectList=this.getSelect(this.$selectTable.find('tbody tr')); for(var i=0;i<this.selectData.length;i++){ if(selectList.indexOf(this.selectData[i][this.option.uniqueId])>=0){ this.selectData[i][this.option.unselectColumns[0].field]=false; this.unselectData.push(this.selectData[i]); this.selectData.splice(i,1); i--; } } this.refreshTable(); this.$backwardBtn.removeClass('btn-info').addClass('btn-default'); this.$checkedNum2.html(''); } this.showTotalNum(); }, /* * 暴露到外面的实例的方法,可返回两个表格内的数据集合 * @params type: 必填 unselectData待选列表数据,selectData已选列表数据 * @params arr: 非必填 若不存在直接返回源数据集合,若配置字段名则返回所需的字段集合*/ getData:function(type,arr){ if(!type){console.error('请填写想要返回的数据名称unselectData或selectData');return false;} if(arr&&typeof arr=='string'){ return $.map(this[type],function(item,index){ return item[arr]; }); }else if(arr&&arr instanceof Array && arr.length>0){ return $.map(this[type],function(item,index){ var obj={}; for(var i=0;i<arr.length;i++){ obj[arr[i]]=item[arr[i]]; } return obj; }); }else{ return this[type]; } }, /* * 销毁实例*/ destroy :function () { this.$el.html(''); }, /* * 刷新表格 只当数据源为一个时有效*/ refresh:function(data){ if(this.option.url) { this.initServer(); }else{ this.option.dataSource=JSON.parse(JSON.stringify(data)); this.selectData=[]; this.unselectData=[]; this.classifyData(); } } } var allowedMethods = ['refresh','destroy','getData']; $.fn.transfer = function (option) { //向jQuery注册插件 var e = this, value, args = Array.prototype.slice.call(arguments, 1); e.each(function () { var $this = $(this), data = $this.data('transfer'), options = $.extend({}, transfer.DEFAULTS, $this.data(), typeof option === 'object' && option); if (typeof option === 'string') { if ($.inArray(option, allowedMethods) < 0) { throw new Error("Unknown method: " + option); } if (!data) { return; } value = data[option].apply(data, args); if (option === 'destroy') { $this.removeData('transfer'); } } if (!data) { $this.data('transfer', (data = new transfer(this, options))); } }); return typeof value === 'undefined' ? this : value; }; $.fn.transfer.Constructor = transfer; $.fn.transfer.defaults = transfer.DEFAULTS; $.fn.transfer.methods = allowedMethods; })(jQuery, window, document);