Maison > interface Web > js tutoriel > le corps du texte

Code d'implémentation de l'effet de glissement multi-lignes du composant JS Bootstrap Table

高洛峰
Libérer: 2017-01-04 10:54:17
original
1572 Les gens l'ont consulté

Avant-propos : avant-hier, je viens d'écrire un article sur l'effet de glissement de ligne du composant JS Bootstrap Table. Aujourd'hui, j'ai reçu un nouveau besoin : il doit pouvoir faire glisser plusieurs lignes sélectionnées en même temps en fonction de la précédente. glisser la ligne du tableau. Après avoir passé une demi-journée à faire des recherches, l'effet est apparu, mais il semblait insatisfaisant. Partagez-le d’abord, puis réfléchissez à de meilleures façons de l’optimiser plus tard.

1. Affichage de l'effet

1. Avant le glisser

Code dimplémentation de leffet de glissement multi-lignes du composant JS Bootstrap Table

2. >

3. Après avoir fait glisser

Code dimplémentation de leffet de glissement multi-lignes du composant JS Bootstrap Table

4 Annuler et revenir à l'état avant de faire glisser

Code dimplémentation de leffet de glissement multi-lignes du composant JS Bootstrap Table

2. Analyse des exigences

D'après l'article précédent, nous savons que si vous souhaitez implémenter le glisser-déposer, vous devez disposer d'une étiquette glisser-déposer, ou d'un conteneur. Par exemple, le tr de l'article précédent est un glisser-déposer. et-drop conteneur, donc si vous souhaitez implémenter Lors de la sélection d'une ligne à faire glisser, la première réaction du blogueur est de placer la ligne sélectionnée dans un conteneur, tel qu'un div, puis d'enregistrer le div pour qu'il puisse être déplacé. La situation est que tr est dans la balise table, si tr est enveloppé dans div, le style dans la table sera perturbé et l'interface sera vraiment gâchée. Évidemment, cette route ne fonctionnera pas. Ensuite, j'ai découvert grâce à l'examen des éléments de Google Chrome que l'élément parent de la table tr généré avec la table Bootstrap était en fait tbody, donc je me demandais si je pouvais enregistrer le glisser-déposer de tbody. La pratique a prouvé que cette méthode est réalisable. Alors commençons. Code dimplémentation de leffet de glissement multi-lignes du composant JS Bootstrap Table

3. Exemple de code

Le code de cshtm ne sera pas répété, il est le même que le précédent. Concentrons-nous sur le code js.

Concentrons-nous sur une partie du code

1 Vous pouvez faire glisser et déposer sur le côté gauche de l'inscription
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 });
 $(&#39;#tb_order_left&#39;).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(&#39;refresh&#39;);
 });
 
 //重置点击事件
 $("#btn_reset").click(function () {
 $(".container-fluid").find(".form-control").val("");
 $("#tb_order_left").bootstrapTable(&#39;refresh&#39;);
 });
 
 //插单操作点击事件
 $("#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);
 
 $(&#39;#tb_order_left&#39;).bootstrapTable(&#39;removeAll&#39;);
 $(&#39;#tb_order_right&#39;).bootstrapTable(&#39;removeAll&#39;);
 $(&#39;#tb_order_left&#39;).bootstrapTable(&#39;append&#39;, 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] });
 }
  
 //$(&#39;#tb_order_right&#39;).bootstrapTable(&#39;append&#39;, arr_right_data);//append之后不能drop
 break;
 }
 i_statuindex--;
 
 //重新注册可拖拽
 m_oTable.InitDrag();
 //m_oTable.InitDrop();
 });
 };
 
 return oInit;
};
Copier après la connexion

Le code ici est très simple. et fait principalement deux choses :

(1) Enregistrez la déplaçabilité du corps, et il en va de même pour l'événement déplaçable de JQuery UI.
$(&#39;#tb_order_left tbody&#39;).draggable({
 helper: "clone",
 start: function (event, ui) {
 var old_left_data = JSON.stringify($(&#39;#tb_order_left&#39;).bootstrapTable("getData"));
 var old_right_data = JSON.stringify($(&#39;#tb_order_right&#39;).bootstrapTable("getData"));
 var odata = { index: ++i_statuindex, left_data: old_left_data, right_data: old_right_data };
 arrdata.push(odata);
 },
 stop: function (event, ui) {
 }
 });
Copier après la connexion

(2) Avant de commencer le glisser, enregistrez les données dans les tableaux des deux côtés pour l'opération de restauration.

2. Enregistrez le bon drop

Le code ici est légèrement différent d'avant

(1) Enregistrez le #div_tableright div[class=fixed-table- conteneur] tag droppable, cette balise est automatiquement générée après l'initialisation de la table Bootstrap. Pourquoi ne pas enregistrer directement le droppable de la table #tb_order_right La raison est que la portée de cette balise est trop petite, ce qui empêchera le corps glissé de le faire. capturer l'événement de chute. La balise div #div_tableright div[class=fixed-table-container] en dehors du formulaire d'inscription peut résoudre le problème.
   $("#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 });
$(&#39;#tb_order_left&#39;).bootstrapTable("removeByUniqueId", uniqueid);
}
 
 
oTableInit.InitDrag();
}
});
Copier après la connexion

(2) Utilisez var arrtr = $(ui.helper[0]).find("tr[class=selected]"); pour trouver la ligne sélectionnée glissée dans tbody, puis supprimez le données et insérez-les dans l'ordre. Le tableau de droite et le tableau de gauche suppriment les lignes de données une par une.

(3) Ce qui est un peu gênant ici, c'est de trouver la position de la goutte. On sait que si l'on veut mettre la ligne sélectionnée à gauche à la position spécifiée à droite, il faut arriver. la position du déplacement actuel de la souris. Ici, nous utilisons la propriété ui. helper[0].offsetTop pour obtenir la position de l'axe Y de la souris et calculer la position à insérer.

3. Opération d'annulation

L'opération d'annulation est fondamentalement la même qu'avant.

4. Résumé
$("#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);
 
$(&#39;#tb_order_left&#39;).bootstrapTable(&#39;removeAll&#39;);
$(&#39;#tb_order_right&#39;).bootstrapTable(&#39;removeAll&#39;);
$(&#39;#tb_order_left&#39;).bootstrapTable(&#39;append&#39;, 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] });
}
 
//$(&#39;#tb_order_right&#39;).bootstrapTable(&#39;append&#39;, arr_right_data);//append之后不能drop
break;
}
i_statuindex--;
 
//重写注册可拖拽
m_oTable.InitDrag();
//m_oTable.InitDrop();
});
Copier après la connexion
L'effet est complet. Le seul inconvénient est que chaque fois que vous faites glisser l'intégralité du corps, et non les lignes sélectionnées, plusieurs lignes sélectionnées ne peuvent pas être enveloppées dans un conteneur. Aucune solution adaptée n’a encore été trouvée. Faisons cela pour le moment, puis optimisons-le plus tard lorsque nous trouverons une bonne solution.

5. Plan d'optimisation


1. Méthode d'enregistrement du drap

Ajout de cette phrase $(ui.helper[0]).find("tr[ class !=selected]").remove(); De cette façon, les lignes non sélectionnées ne seront pas visibles lors du glissement.

2. Localisez avec précision la position spécifiée dans le tableau de droite :

oTableInit.InitDrag = function () {
 $(&#39;#tb_order_left tbody&#39;).draggable({
 helper: "clone",
 start: function (event, ui) {
 var old_left_data = JSON.stringify($(&#39;#tb_order_left&#39;).bootstrapTable("getData"));
 var old_right_data = JSON.stringify($(&#39;#tb_order_right&#39;).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) {
 }
 });
 };
Copier après la connexion

Étant donné que la hauteur de chaque ligne est incertaine et est prise en charge dynamiquement par les données de la ligne, la position du la baisse est également calculée dynamiquement ici.

À ce stade, cette petite fonction est pratiquement terminée, et les effets de base et les points à optimiser sont également complétés.
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(&#39;请先选中要插单的行&#39;);
 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 });
 $(&#39;#tb_order_left&#39;).bootstrapTable("removeByUniqueId", uniqueid);
 }
 
 oTableInit.InitDrag();
 
 }
 });
 };
Copier après la connexion

Pour plus d'articles sur le code d'implémentation de l'effet de glisser multi-lignes de la table Bootstrap du composant JS, veuillez faire attention au site Web chinois de PHP !

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal