2013-03-14 27 views
9

için iki kez çalıştırıyor görünüyor bağlı listeleri sıralamak için jQuery UI sortable kullanıyorum. Güncelleme olayı iki kez çalışıyor gibi görünüyor. İşte Neden jquery sıralanabilir güncelleme olayı ui.sender

$(".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 < tn && (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 
      } 
     } 
    } 
}); 

iki kez çalıştırmak gibi görünüyor parçasıdır:

   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")); 
       } 

Ben sadece ui.sender olarak bir tane alert almak için bekliyorum null zaman sıralamayı edilir Burada

tam sıralanabilir çağrıdır Aynı listenin içinde kalır. Bir öğe diğerine gitmek için bir liste bıraktığında ui.sender artık null olacaktır.

Bir öğeyi yeni bir listeye taşıdığımda sorun, uyarı mesajlarını alacağım. Güncelleme fonksiyonu bir kez çalıştırıldıktan sonra ui.sender ayarlanırsa, güncelleme fonksiyonu üzerinden tekrar çalışır. Açıkçası bu iyi bir şey değil, çünkü üzerine yazılmaması gereken verilerin üzerine yazıyorum.

Böyle bir durum söz konusu ise, kodun üzerine yazmamak için nasıl yazmalıyım?

DÜZENLEME ben güncelleme olayı bir liste DOM genel olarak, sadece DOM her değiştiğinde denir inanıyoruz. Bu nedenle, DOM'a sahip her bir liste için güncelleme çalışır. Bir öğeyi yeni bir listeye taşıdığımda iki listeyi güncelliyorum.

Yeni soru şu: Sanırım iki kez ateş edeceğini bilerek bu kodu nasıl yeniden yazarım? Bunu başarabilecek Alma ve Kaldırma olaylarının bir kombinasyonu var mı?

cevap

42

Bazı her sortable olayı araştırdım. İşte onlar gerçekleşecek sırayla listelenmiş benim bulgular şunlardır: sorunumu ben sadece ui.sender denetleyen bir if else açıklamada sararak sadece koşmak kez benim güncelleme fonksiyonunun içeriğini zorlamak çözerken

$(".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 
    } 
}); 

. Temel olarak, eğer ui.sender'un mevcut olmaması durumunda, bu güncelleme fonksiyonu üzerinden ilk kez gerçekleşir ve fonksiyonu yapmalıyız, aksi halde hiçbir şey yapmayız.

+1

Üzgünüm ama en azından bir aksaklık olduğunu düşünüyorum etkinliklerinizin sırasına göre: 'dur' son olay değil, "update".[Dan Wellman'ın kitabı «jQuery UI 1.8»] 'e (http://my.safaribooksonline.com/book/-9781849516525/the-sortables-component/ch13lvl1sec03) bana destek olmak için referans olarak bakarsak, bu açıktır "Dur" olayının, sıralama bittiğinde "güncelleme" olayı meydana geldiğinde ve DOM değiştiğinde, sıralamada gerçekleştiğini ... "Dur" dan sonra "güncelleştirme" gerçekleşeceğini ve bu şekilde oldukça mantıklı olduğunu, düşünmüyor musun – Cholesterol

+3

@ Cholesterol, daha mantıklı olan girdi için teşekkürler. Ama burada sona eren bilgiler, her olayın test edilmesiydi. Bu olay tetiklendiğinde, console.log ("her ne olursa olsun") çağrısıyla test ettim. Bulgularım, dur etkinlikten önceki günlüğüne gönderilen güncelleme olayıydı. –

+6

Kaynak kodu asla yalan söylemez: [sortable.js] (https://github.com/jquery/jquery-ui/blob/master/ui/sortable.js#L1281) - dur etkinlik son olaydır – tokarev

0

Cevabı burada gönderdiniz: jquery Sortable connectWith calls the update method twice

Sen kaldırmayı birleştirmek ve almak ve değişiklikleri tutun ve daha JSON olarak sunucuya yayınlayacağız bir dizi oluşturabilirsiniz.

Demo: http://jsfiddle.net/r2d3/p3J8z/

HTML:

<div class="container"> 
    <div class="step" id="step_1"> 
     <h2 class="title">Step 1</h2> 
     <div class="image" id="image_10">Image 10</div> 
     <div class="image" id="image_11">Image 11</div> 
     <div class="image" id="image_12">Image 12</div> 
    </div> 
    <div class="step" id="step_2"> 
     <h2 class="title">Step 2</h2> 
     <div class="image" id="image_21">Image 21</div> 
     <div class="image" id="image_22">Image 22</div> 
     <div class="image" id="image_23">Image 23</div> 
    </div> 

JS: solüsyonun

$(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:<pre>"+JSON.stringify(myArguments)+"</pre>");   
      }, 
     }); 
    }); 

Tam açıklama: http://r2d2.cc/2014/07/22/jquery-sortable-connectwith-how-to-save-all-changes-to-the-database/