Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery UI Sortable - Add Placeholders to Lists to Simulate empty spaces

JQuery UI Sortable works great for lists with no gaps, but say I want to render a list of items with gaps, e.g.

1, 2, empty, 4, 5, 6, empty, 8

where the number represents the slot number. The behavior expected then would be if the user drags an element over the 2 slot, the 2 value gets pushed to the empty slot 3, and the user could drop the new element in the 2 slot, whereas if they drag a new element over the empty 3 slot, the list items would not push down, and the user could just drop the new item into the empty 3 slot. Hopefully this makes sense.

I've been looking at the JQuery UI Sortable code, and it seems that I need to utilize the change and receive callbacks in order to achieve this, but, being new to JQuery/JS in general, it's not clear to me what to use to add these empty slot placeholders and manage the selection list so that I don't break the sorting functionality with custom code.

Any pointers, examples, etc. would be much appreciated.

After banging my head on this for a while, I created a jsFiddle: http://jsfiddle.net/pdHnX/

To help explain the problem. I believe everything I'm trying to accomplish can happen in an overridden _rearrange method. The fiddle code handles the case where an item is replacing a filler item, but there is an odd issue, where if you drag an item from the item list to the filler list, drop the item, then drag the same item within the filler list, the filler list is shrunk by 1, which is a problem.

There are more issues once you start dragging more items into the filler list, but this is where I'm at with the problem at the moment.

like image 206
Tom Hartwell Avatar asked Aug 31 '12 19:08

Tom Hartwell


2 Answers

I'm not sure if I understood you correctly, but here's what I came up with:

http://jsfiddle.net/py3DE/

$(".source .item").draggable({ revert: "invalid", appendTo: 'body', helper: 'clone',
    start: function(ev, ui){ ui.helper.width($(this).width()); }                    // ensure helper width
});

$(".target .empty").droppable({ tolerance: 'pointer', hoverClass: 'highlight',
    drop: function(ev, ui){
        var item = ui.draggable;
        if (!ui.draggable.closest('.empty').length) item = item.clone().draggable();// if item was dragged from the source list - clone it
        this.innerHTML = '';                                                        // clean the placeholder
        item.css({ top: 0, left: 0 }).appendTo(this);                                // append item to placeholder
    }
});

Assumptions:

  • If you drag item from the top list - it will be "cloned" (original will remain in the list)
  • If you drag item from the bottom list - it will move (leaving empty placeholder)
  • If you drop any item on a bottom list's placeholder - it will replace the placeholder
  • If you drop any item on bottom list's non-empty placeholder/item - it will replace it
  • sizes of both lists always stay the same

Let me know if this helps or are you looking for something else. Also explaining the whole task (what's the purpose of this dragging) might help :-)

like image 176
Dziad Borowy Avatar answered Oct 18 '22 08:10

Dziad Borowy


Sorry, this was a really difficult question to detail out. The requirements were really specific and hard to describe.

Here is the solution I was looking for.

The others answers here, while they may have been solutions to the poorly described problem, were not what I was looking for.

http://jsfiddle.net/vfezJ/

Unfortunately, the sortable.js code is very hairy so the code linked there is also very hairy. The solution I've posted also makes some assumptions on CSS classes and DOM ids to get the job done.

like image 36
Tom Hartwell Avatar answered Oct 18 '22 08:10

Tom Hartwell