Ashwin
Ashwin

Reputation: 12411

jquery cancel sortable if item exists

How to cancel sortable for an item if that item already exists?

I have a set of items on left side and a sortable list on right side. Draggable items from left side can be dropped on the sortable list.

Please Note: Items on the left side are draggable and not sortable.

I tried all these, bug none of them worked:

ui.sender.sortable("cancel");
ui.item.sortable("cancel");
ui.helper.sortable("cancel");
ui.sender.remove();
ui.item.remove();
ui.helper.remove();

Fiddle is here - http://jsfiddle.net/NA6c8/2/

Upvotes: 2

Views: 3144

Answers (3)

schuhwerk
schuhwerk

Reputation: 462

Just took Perry Tew's fiddle and changed it a bit. To avoid the "id-problem" I just inserted a "card" attribute and count it. This way you dont't need the second function. See http://jsfiddle.net/RxKkA/17/

Upvotes: 1

Perry Tew
Perry Tew

Reputation: 2632

Well, this feels inelegant, but it gets the job done. Here's a jsfiddle to show what I'm about to explain: http://jsfiddle.net/perrytew/RxKkA/3/

Setup: I removed your ids for each item, since they would be cloned on the copy to avoid having the same id in a document twice. I use classes instead. Here's what my html looked like:

<div class="leftDiv">
    <div class="item item1">Item 1</div>
    <div class="item item2">Item 2</div>
    <div class="item item3">Item 3</div>
    <div class="item item4">Item 4</div>
    <div class="item item5">Item 5</div>
    <div class="item item6">Item 6</div>
</div>
<div class="rightDiv">
</div>
<div id='errorMessage'></div>

To make it work, I added a hook to the 'receive' event of the sortable object. When that fired, I did two things:

  • set the dragged item's revert to true, so future drags would snap back.
  • check to see if the item already existed in the drop table. If so, I deleted the new one.

It seems to be a design flaw of the jquery ui, because even when revert is set to true, the dragged item is still dropped. It reverts, but a copy still appears in the drop table. So that's why I do the clean up with the remove() call. It feels hackish, but it gives a very satisfying visual experience. I added a little fade out message to alert the user why the drag failed.

Cheers.

Javascript:

$(document).ready(function(){
    $(".leftDiv .item").draggable({
        helper: function(ev, ui) {
            return "<span class='helperPick'>"+$(this).html()+"</span>";
        },
        connectToSortable: ".rightDiv"
    });

    $(".rightDiv").sortable({
        'items': ".item",
        'receive': function(event, ui){
            // find the class of the dropped ui, look for the one 
            //with the integer suffix.
            var clazz = getClassNameWithNumberSuffix(ui.item);
            $('.leftDiv .' + clazz).draggable( "option", "revert", true );
            if($('.rightDiv .' + clazz).length > 1){
                $('.rightDiv .' + clazz + ':not(:first)').remove(); 
                var msg = $('#errorMessage');
                msg.html(ui.item.html() + ' already added.  Duplicates not allowed');
                msg.show();
                msg.fadeOut(3000);               
            }
        }
    });

});

function getClassNameWithNumberSuffix(el) {
  var className = null;
  var regexp = /\w+\d+/;
  $($(el).attr('class').split(' ')).each(function() {
    if (regexp.test(this)) {
      className = this;
      return false;
    }
  });

  return className;
}

CSS:

.leftDiv, .rightDiv {width:120px; float:left; border:1px solid #000; 
    padding:5px; margin:10px; min-height:130px}
.rightDiv {margin-left:40px}

.item {height:20px; line-height:20px; text-align:center; 
    border:1px solid #EEE; background-color:#FFF}

.helperPick {border:1px dashed red; height:20px; line-height:20px; 
    text-align:center; width:120px}

#errorMessage{
    margin:10px;
    clear:both;
    color:red; font-weight:bold;
}

Upvotes: 4

Diode
Diode

Reputation: 25145

Did you try .sortable( "destroy" ) ?

http://jqueryui.com/demos/sortable/ See methods here

Upvotes: 1

Related Questions