为什么jquery sortable中的update事件在测试ui.sender时似乎运行了两次

我正在使用jQuery UI对可连接列表进行排序。 更新事件似乎正在运行两次。

这是完整的可排序电话:

$(".pageContent").sortable({ handle: ".quesText", connectWith: ".pageContent", containment: "section", start: function(e, ui){ ui.placeholder.height(ui.item.height()); }, placeholder: "sortable-placeholder", opacity: 0.5, cursor: "move", cancel: "input, select, button, a, .openClose", update: function(e, ui){ var thisItem = ui.item; var next = ui.item.next(); var prev = ui.item.prev(); var thisNumber = thisItem.find(".quesNumb"); var nextNumber = next.find(".quesNumb"); var prevNumber = prev.find(".quesNumb"); var tn = parseInt(thisNumber.text()); var nn = parseInt(nextNumber.text()); var pn = parseInt(prevNumber.text()); var quesNumbs = $(".quesNumb"); var newItemId = thisItem.attr("id").replace(/_\d+$/, "_"); //test if we are dragging top down if(ui.position.top > ui.originalPosition.top){ quesNumbs.each(function(i){ var thisVal = parseInt($(this).text()); var grandparent = $(this).parent().parent(); var grandId = grandparent.attr("id").replace(/_\d+$/, "_"); if(thisVal > tn && (thisVal <= pn || thisVal <= (nn - 1))){ $(this).text(thisVal - 1 + "."); grandparent.attr("id",grandId + (thisVal - 1)); } }); if(!isNaN(pn) || !isNaN(nn)){ if(!isNaN(pn)){ //for some reason when there is a sender pn gets updated, so we check if sender exists //only occurs sorting top down if($.type(ui.sender) !== "null"){ var senderId = ui.sender.attr("id"); thisNumber.text(pn + 1 + "."); thisItem.attr("id",senderId + "_" + (pn + 1)); alert(thisItem.attr("id")); } else { thisNumber.text(pn + "."); thisItem.attr("id",newItemId + pn); alert(thisItem.attr("id")); } } else { thisNumber.text(nn - 1 + "."); } } else { //something will happen here } } //otherwise we are dragging bottom up else { quesNumbs.each(function(i){ var thisVal = parseInt($(this).text()); if(thisVal = nn || thisVal >= (pn + 1))){ $(this).text(thisVal + 1 + "."); } }); if(!isNaN(pn) || !isNaN(nn)){ if(!isNaN(pn)){ thisNumber.text(pn + 1 + "."); } else { thisNumber.text(nn + "."); } } else { //something will happen here } } } }); 

这是似乎运行两次的部分:

  if($.type(ui.sender) !== "null"){ var senderId = ui.sender.attr("id"); thisNumber.text(pn + 1 + "."); thisItem.attr("id",senderId + "_" + (pn + 1)); alert(thisItem.attr("id")); } else { thisNumber.text(pn + "."); thisItem.attr("id",newItemId + pn); alert(thisItem.attr("id")); } 

我希望只有一个alert因为当排序保留在同一个列表中时, ui.sendernull 。 当一个项目离开列表去另一个项目时, ui.sender将不再为null

问题是当我将项目移动到新列表时,我将收到2条警报消息。 它好像ui.sender在更新函数运行一次后设置,然后再次运行更新function。 显然这不好,因为我覆盖的数据不一定会被覆盖。

如果是这种情况,我应该如何重写我的代码以避免覆盖数据?

编辑

我相信每次更改列表DOM时都会调用update事件,而不仅仅是DOM。 因此,对于每个具有DOM更改的列表,更新都会运行。 当我将一个项目移动到新列表时,我正在更新两个列表。

所以我想新的问题是:我怎么重写这段代码知道它会发射两次? 是否有可以实现此目的的Receive和Remove事件的组合?

我对每个可排序的事件做了一些调查。 以下是我的调查结果,按照它们发生的顺序列出:

 $(".pageContent").sortable({ start: function(e,ui){ //Before all other events //Only occurs once each time sorting begins }, activate: function(e,ui){ //After the start event and before all other events //Occurs once for each connected list each time sorting begins }, change: function(e,ui){ //After start/active but before over/sort/out events //Occurs every time the item position changes //Does not occur when item is outside of a connected list }, over: function(e,ui){ //After change but before sort/out events //Occurs while the item is hovering over a connected list }, sort: function(e,ui){ //After over but before out event //Occurs during sorting //Does not matter if the item is outside of a connected list or not }, out: function(e,ui){ //This one is unique //After sort event before all drop/ending events unless **see NOTE //Occurs, only once, the moment an item leaves a connected list //NOTE: Occurs again when the item is dropped/sorting stops //--> EVEN IF the item never left the list //--> Called just before the stop event but after all other ending events }, beforeStop: function(e,ui){ //Before all other ending events: update,remove,receive,deactivate,stop //Occurs only once at the last possible moment before sorting stops }, remove: function(e,ui){ //After beforeStop and before all other ending events //Occurs only once when an item is removed from a list }, receive: function(e,ui){ //After remove and before all other ending events //Occurs only once when an item is added to a list }, update: function(e,ui){ //After receive and before all other ending events //Occurs when the DOM changes for each connected list //This can fire twice because two lists can change (remove from one //list but add to another) }, deactivate: function(e,ui){ //After all other events but before out (kinda) and stop //Occurs once for each connected list each time sorting ends }, stop: function(e,ui){ //After all other events //Occurs only once when sorting ends } }); 

在解决我的问题时,我只是通过将其包装在检查ui.senderif else语句中来强制我的更新函数的内容只运行一次。 基本上它说如果ui.sender不存在那么这是第一次通过更新function,我们应该执行该function,否则什么也不做。

我在这里发布了答案: jquery Sortable connectWith两次调用update方法

您可以组合删除和接收,并创建一个包含更改的数组,然后将其作为JSON发布到服务器。

演示: http : //jsfiddle.net/r2d3/p3J8z/

HTML:

 

Step 1

Image 10
Image 11
Image 12

Step 2

Image 21
Image 22
Image 23

JS:

  $(function(){ /* Here we will store all data */ var myArguments = {}; function assembleData(object,arguments) { var data = $(object).sortable('toArray'); // Get array data var step_id = $(object).attr("id"); // Get step_id and we will use it as property name var arrayLength = data.length; // no need to explain /* Create step_id property if it does not exist */ if(!arguments.hasOwnProperty(step_id)) { arguments[step_id] = new Array(); } /* Loop through all items */ for (var i = 0; i < arrayLength; i++) { var image_id = data[i]; /* push all image_id onto property step_id (which is an array) */ arguments[step_id].push(image_id); } return arguments; } /* Sort images */ $('.step').sortable({ connectWith: '.step', items : ':not(.title)', /* That's fired first */ start : function( event, ui ) { myArguments = {}; /* Reset the array*/ }, /* That's fired second */ remove : function( event, ui ) { /* Get array of items in the list where we removed the item */ myArguments = assembleData(this,myArguments); }, /* That's fired thrird */ receive : function( event, ui ) { /* Get array of items where we added a new item */ myArguments = assembleData(this,myArguments); }, update: function(e,ui) { if (this === ui.item.parent()[0]) { /* In case the change occures in the same container */ if (ui.sender == null) { myArguments = assembleData(this,myArguments); } } }, /* That's fired last */ stop : function( event, ui ) { /* Send JSON to the server */ $("#result").html("Send JSON to the server:
"+JSON.stringify(myArguments)+"

"); }, }); });

解决方案的完整说明: http : //r2d2.cc/2014/07/22/jquery-sortable-connectwith-how-to-save-all-changes-to-the-database/