October 13, 2011

jQuery sortable - getting the new and original index

The jQuery sortable plugin allows us to give our users that drag ‘n drop experience they all love so much.

Often we need to sort items and POST the updated order to the server. One method of doing this is to call the toArray function that generates an ordered array of item id’s within your list:

$("ul.media-grid").sortable('toArray')

So given the following html:

<ul>
    <li id="red">Red</li>
    <li id="green">Green</li>
    <li id="blue">Blue</li>
</ul>

A call to toArray would produce:

["red", "green", "blue"]

We could then POST this to the server using ajax.

I tend to use this method for sorting smaller lists as it typically involves more work on the server (as we have to enumerate the entire collection).

Getting the new and original index of an individual item

We can achieve this by subscribing to the plugin’s start and stop events. The following code demonstrates how we can use these events along with jQuery’s data() method to POST the index values to the server:

var updateUrl;

self.sendUpdatedIndex = function ($item) {
    // increment by 1 as we're using 1 based index on server
    var startIndex = $item.data("startindex") + 1;
    var newIndex = $item.index() + 1;
    if (newIndex != startIndex) {
        $.post(
            updateUrl,
            { id: $item.attr("id"), oldPosition: startIndex, newPosition: newIndex }
        );
    }
}

pub.init = function (url) {

    updateUrl = url;

    $("ul.project-grid").sortable({
        start: function (event, ui) {
            $(ui.item).data("startindex", ui.item.index());
        },
        stop: function (event, ui) {
            self.sendUpdatedIndex(ui.item);
        }
    }).disableSelection();
}

The key point here is the item’s index() method that returns its current index. In this example we check the original index against the new index and only POST to the server if it has changed.

© 2020 Ben Foster