Maarten Kuijper
Maarten Kuijper

Reputation: 354

ajax, jquery sortable, order updates

What I wanted to achieve is to update the order of slides in the database, by changing the 'order' input's value in the overview (each row has it's own input), or by dragging the rows.

So I first fixed this input, and placed the ajax request in a function. This function expects the row itself and the new order value, see ajax_order(row, newval);.

Then I made the rows sortable and added a update: function to it:

$( ".rows-container" ).sortable();

$(".rows-container").sortable({
    update: function( ) {
        $('.rows-container').children().each(function(i, el){
            ajax_order($(this), i + 1);
            $(this).find('.overview-number').val(i+1);
        });
    }
});

Right now I'm looping through the rows, and using the index as the new order number. It's working fine, but every time you drag 1 row, it updates all the rows.. even if a row actualy stayed in place.

Also it might not be realy efficient if there are 30 slides saved (of which a couple might be flagged as inactive). What is a good way to do this? happy with some tips

Update:

when I added this to the function, it gives me the current (old) order when I start dragging, but also 1 extra console.log 'undefined'.. so now I have 5 console.logs and only 4 actual rows. Would be a good thing if we didn't need to track the old order or use start:

start: function(event, ui) {
    $('.rows-container').children().each(function(i, el){
        console.log($(this).find('.overview-number').val());
    });

},

Update:

So I've been puzzling all night xD zzzZZzz. Been adding php functions and removing again, adding JS objects storing old order + index and shit..tried with differend types of array in both start: and stop:

It got a big mess, so I decided to write down some scenarios on paper.. and figured a good way to go is to track the last 'order' used. Here is the result

$( ".rows-container" ).sortable();

$(".rows-container").sortable({

    update: function() {

        var last_val = 0;//used to compare with the next row and determine it's value
        //if the next row has lower value as the one before, it needs to become higher value
       //note that the view always gets loaded on order ASC 

        $('.rows-container').children().each(function(i){

            //the current row's order
            var current = parseInt($(this).find('.overview-number').val());

            if(i == 0 || current > last_val){ 

                if(current < last_val+5){ //row doesnt need update, yee!!!!
                    last_val = current;

                //makes sure the values dont add up too much, when the difference gets too big
                }else{
                    current = last_val+1;
                    ajax_order($(this), current);
                    $(this).find('.overview-number').val(current);
                    last_val = current;
                }

            //if the next row has lower value as the one before, it needs to become higher value
            }else if(current <= last_val){
                current = last_val+1;
                ajax_order($(this), current);
                $(this).find('.overview-number').val(current);
                last_val = current;
            }
        });
    },
});

Runs like a train... but as you can see there is some duplication in there, the part that runs the ajax. I've tried to put it into a function in that object and keep 'last_value' and 'current' available, but didn't succeed yet.

Upvotes: 0

Views: 661

Answers (1)

K Scandrett
K Scandrett

Reputation: 16540

You can pass the start and end position to your back-end service, and then on the server adjust records in that range. It will be more efficient that way:

var initialPos, finalPos;

$("#sortable")
  .sortable()
  .on("sortstart", function( event, ui ) {
     initialPos = ui.item.index() + 1; // when using a 1-based index    
     //console.log("Item started at position", initialPos);
  })  
  .on("sortupdate", function( event, ui ) {
     finalPos =  ui.item.index() + 1; // when using a 1-based index  	
     console.log(ui.item.attr('id'), "moved from position", initialPos, "to", finalPos);
    
     // call ajax function here, passing in initialPos & finalPos
     // server will need to re-order values for all elements between (and including) initialPos & finalPos
  });
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.12.4.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<ul id="sortable">
  <li id="itm1">Item 1</li>
  <li id="itm2">Item 2</li>
  <li id="itm3">Item 3</li>
  <li id="itm4">Item 4</li>
  <li id="itm5">Item 5</li>
</ul>

Upvotes: 1

Related Questions