jQuery UI Sortable with connected tables and empty rows

Sortables are pretty cool. But one thing many people struggle with when trying to implement them is get them to work with tables. I had some issues specially with empty rows, and since I learned a little by working with it, I want to spare you all the searches and tries.

Sorting table rows

The examples on jQuery UI demos page are using ul and li elements. If you are working with them you are fine. When you are working with tables though, the first thing you need to change is which items will be moved/sorted, in this case, the tr. The code will look like this:

$(".sortable").sortable({
    items: 'tbody > tr'
});

Connecting the tables

To connect the tables, we will use the connectWith option:

$(".sortable").sortable({
    items: 'tbody > tr',
    connectWith: ".sortable"
});

It basically says which elements talk to each other. This will work as long as both tables have the same class, which is the easiest way you can do it. If in your case the tables do not have the same class, just separate the selectors by comma, like "#table1, #table2".

Drop table cells on empty rows

I found some code that had tables with empty rows working http://jsfiddle.net/zlzu3/62/ and I was following that code almost exactly but mine still wasn’t working. Then I noticed, it has Table Headers! So, I realized that you need a little visible space in order to be able to drop something on it. Let’s make our table visible:

.sortable {
    background-color: silver;    
    height: 10px;
}

.sortable td { background-color: white; }

I gave my table a background color and a height, I also added an invisible row to the tbody because I couldn’t set a height for an empty table.

<table class='sortable'>    
    <tbody>
        <tr><td colspan="2" class="drop-row" style="display: none;"></td></tr>
    </tbody>    
</table>

Great! Now I can see it and it works!

Here is the full code: http://jsfiddle.net/stanleystl/cea944zp/

Drop table cells on empty rows (version with tfoot)

I wasn’t happy with the fact that I had to isolate my empty row every time I need to get the items in my table, like the :not in my items selector, so I came up with a version using tfoot. No big changes. Here it is:

http://jsfiddle.net/stanleystl/aL72L974/

The technique consists in having an invisible tr with visibility: hidden inside my table. The visibility will hide that row, but still occupies its space, and here is where I can drop my rows. Then, I customized the sortable receive event to check if there is any row in the table, and if there is, I hide the hidden row (or I kill it until it is dead!), but now with display: none; which will no longer occupy that space. I also check if I need to hide any empty rows when the page loads.

function hideOrShowDropRow(){    
    $(".sortable").each(function() {
        var dropRow = $(this).find(".drop-row"),
            hasRows = $(this).find("tbody tr").length;
                        
        hasRows ? dropRow.hide() : dropRow.show();
    });
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s