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/
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?
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/
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With