Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery ui sortable limit max to 1 item

I have a Main list .sortable and 3 or more other lists connected that I want a person to drag an item and drop which works great and its easy. But i want to be able to limit the new list to 1 item, and they can also drag that item back if they changed their mind and drag a new one.

example what i have so far: http://jsfiddle.net/TQqdF/25/

like image 597
c3cris Avatar asked Nov 06 '11 03:11

c3cris


3 Answers

In the receive option, run some logic and then call 'cancel' on the ui.sender utility object:

$('#main_list,ul').sortable({
        placeholder: 'placeholder',
        connectWith: '.connect_lists',
        receive: function(event, ui) {
            var $this = $(this);
            if ($this.children('li').length > 1 && $this.attr('id') != "main_list") {
                console.log('Only one per list!');
                $(ui.sender).sortable('cancel');
            }
        }
    });

http://jsfiddle.net/TQqdF/62/

[Updated as per John's helpful and correct comment!]

[Update: If it's not one thing it's another! Now it seems that there's no way to avoid the animation (revert: true that you set). However, I have a partial solution for the problem mentioned further in the comment thread.

If you use absolutely positioned LI elements inside a relatively positioned UL, new items being added will not push the others out of the way. However, you do need to explicitly declare that those same LI items are statically positioned when inside the draggables container. Here's the CSS I threw at the bottom of your existing code:

#droppables ul { position: relative; }
#droppables li { position: absolute; top: 3px; left: 3px; }
#draggables li { position: static; }

And a fiddle: http://jsfiddle.net/w38dK/5/

So, the main thing left is that it animates before being rejected and reverting. I had a poke around the docs and I couldn't find a way to resolve it. Perhaps a second question on Stack Overflow specifically regarding that issue?

like image 166
Greg Pettit Avatar answered Sep 27 '22 20:09

Greg Pettit


If anyone is still interested, I took a slightly different approach to solving this problem.

Instead of using the receive event, I use mousedown and mouseup events on the list items to detect whether the target lists are at their max or not.

This essentially disables the target lists upon click if they are already full. This means no nasty placeholder.

$('.sortable li').mousedown(function() {
    $('.sortable').not($(this).parent()).each(function() {
        if ($(this).find('li').length >= 1) {
            if ($(this).attr('id') != "main_list" ) {
                $(this).sortable('disable');
            }
        }
    });
});
$('.sortable li').mouseup(function() {
    $('.sortable').each(function() {
        $(this).sortable('enable');
    });
});

Full jsfiddle is here: http://jsfiddle.net/P9bS8/

like image 26
dalemac Avatar answered Sep 27 '22 20:09

dalemac


Here is my version: http://jsfiddle.net/DwXnV/3

Dragged item replaces content of target list. Replaced item is moved to origin list. Assumed that each target list can contain only 1 item.

like image 21
Maciej Kuś Avatar answered Sep 27 '22 20:09

Maciej Kuś