Here’s my dilemma – I have a two-column list of elements (styled <div>s) that I need to make sortable. With elements that live in one or the other column, this is easy – I just set up two columns, place my elements where they need to be initially, mark them as “sortable,” and let jQuery do its magic.
However, I have two elements in the list that need to span both columns. This, unfortunately, breaks the usability of the model. If I stick with my standard 2-column setup, I run into situations where the wide elements overlap or underlap with elements in the other column.
I also tried iterating through both columns to reposition elements so there would be no overlap, but then I realized another issue: my second column (on the right) has no knowledge of the elements positioned in the first column (on the left).
Here’s a stripped down example of my markup:
<div id="wrapper">
<div id="column-1" class="column" style="width:400px;">
<div id="item-1" class="item" style="width:200px;">
...
</div>
<div id="item-2" class="item wide" style="width:400px;">
...
</div>
<div id="item-3" class="item" style="width:200px;">
...
</div>
</div>
<div id="column-2" class="column">
<div id="item-4" class="item" style="width:200px;">
...
</div>
<div id="item-5" class="item" style="width:200px;">
...
</div>
</div>
</div>
The way this should line up is something like this table:
-------------------
| item 1 | item 4 |
| item 2 |
| item 3 | item 5 |
-------------------
And each item can be dragged and dropped anywhere else, with items 1, 3, 4, 5 moving interchangeably between the two columns, and with item 2 moving up and down as necessary. Realistically, you should also be able to end up with something like this:
-------------------
| item 1 | |
| item 2 |
| item 3 | item 5 |
| item 4 | |
-------------------
But with a standard column model (i.e. the stock jQuery examples, the only resources I can find from several days of Google searches, and every attempt I’ve made thus far) this won’t work.
So what can I do to implement this kind of layout with the jQuery UI Sortable plug-in so I can continue building my UI?
I invested more time and have hacked my way through to one possible solution. It still has its problems, but I’m at least getting most of the functionality I need.
The trick is to create multiple sortable elements and to nest them. So my document structure becomes:
Then, you instantiate 2 different sortables – one to sort the smaller 1-column elements among themselves and the other to sort the 1-column “macro” elements. Note that there are 3 macro elements on this page:
The code to make this all work together is remarkably simple:
This connects the various
.columnelements so that the 1-column elements can be interchanged anywhere on the page. The second code block turns the entire#wrapperelement into its own sortable, which allows you to reposition the large, 2-column element on the page as well.Since I’m explicitly declaring the drag handle (a div with the
section-handleclass attached to each sortable element), you don’t need acancelproperty on yoursortable()call … the “fixed” macro elements don’t have the drag handle to begin with, so they can’t be manually repositioned. However, you can drag the “mobile” macro element (item-2) to anywhere else on the page without any problem.The only issue I’m still facing (and it’s more a personal frustration than anything else) is that the two sortables (
#wrapperand.column) aren’t aware of one another. So if you have the following layout:And items 3, 4, and 5 are in the same sortable container, then you can’t drag item 2 in between items 3 and 4. When dragging item 2, the page is aware of 3 sortable elements – the block containing item 1, the block you’re dragging (item 2), and the block containing items 3, 4, and 5. So while from a usability perspective you should be able to place item 2 below items 3 and 5 … the method I’ve outlined above doesn’t allow you to do that.
So for now it works, but there’s definitely massive room for improvement here.