Sortable icon indicating copy to clipboard operation
Sortable copied to clipboard

Cancel drop

Open superjodash opened this issue 10 years ago • 38 comments
trafficstars

I looked through all the issues and didn't see this question. Sorry if this is a repeat.

Is there a way to cancel the drop action before it happens? Ideally there would be an onAdding event which allows the add to be canceled. I looked but didn't see anything in the code. I wanted to see if perhaps I was just missing it. If there is not I'll see if I can create a PR for it.

Thanks.

superjodash avatar Feb 07 '15 06:02 superjodash

Already have events add / update / remove / sort. Now need to add the processing isDefaultPrevented.

https://github.com/RubaXa/Sortable/issues/138

RubaXa avatar Feb 07 '15 19:02 RubaXa

@superjodash I'd love to see this as well. Did you come up with a workaround?

jfurrow avatar Mar 17 '15 18:03 jfurrow

@neatstreet I ended up writing code to handle OnAdding (with cancel) as well as fixed the Escape issue where it still leaves the node if you hit the Esc while over another container.

It needs to be cleaned up and tested some more. I also want to add a feature where the container adds a target area if you remove the last item. Right now there's no way to put back items if you remove them all.

I'm more than willing to share code until I can get an official PR created.

superjodash avatar Mar 19 '15 22:03 superjodash

Any updates on this feature? It is very useful but not be implemented in this version. @RubaXa @superjodash

zhongqf avatar May 31 '15 15:05 zhongqf

+1

alexanderdickson avatar Jul 02 '15 00:07 alexanderdickson

I need the same function as well. I want to pass the data to my server and store it to database where user drag the item from one group to another group, but when error happens( server error or db error ...) ,then I would prevent the previous drag action.So it's necessary to add a "Cancel Drop" function. Thanks.

liyj144 avatar Aug 13 '15 02:08 liyj144

Here is a gist and sample of the code I'm using. It's working really well for my purposes. I'm using to do dnd between angular and reactjs so some of the code below is dealing with the uni-directional nature of react.

NOTE: This gist is not merged with the latest edition of Sortable so you may want to consider doing that. I just don't have time to work the merge and submit a PR. Sorry.

https://gist.github.com/superjodash/ea84934797ff1cc91a7a

Sample:

Sortable.create(node, {
        group: {
          name:'users',
          pull:'clone',
          put:true
        },
        sort:true,
        animation:150,
        onSort: function(evt) {

          var $item = $(evt.item);
          var id = $item.data('id');

          if($item.text().trim() === "(I Can't Be Dropped)") {
            evt.preventDefault();
            return;
          }

          if(evt.action === 'add') {
            // put a check to make sure it's unique

            // check to see if this node has already been added  and prevent it it has
            var itemCount = evt.item.parentNode.children.length;
            for(var i = 0; i < itemCount; i++) {
              var $child = $(evt.item.parentNode.children[i]);
              var childId = $child.data('id');
              if(childId === id && i !== evt.newIndex) {
                that.onBroadcastNotification('warning', 'This item is already assigned');
                evt.preventDefault();
                return;
              }
            }

            if(evt.newIndex === itemCount - 1) {
              Sortable.utils.swap(evt.item.parentNode, evt.newIndex, evt.newIndex - 1);
            }
          }
        },
        onAdd: function(evt) {
          var $item = $(evt.item);
          var parent = evt.item.parentNode;

          var $itemOptions = $(".item-options", $item);
          if($itemOptions) {
            $itemOptions.removeAttr("hidden");
          }

          var userId = $item.data('id');
          var projectId = that.props.projectId;
          var date = $(parent).data('date');
          $item.remove();

          $broadcast("Project_AddItem", [userId, projectId, date, false]);
        }
      });

superjodash avatar Aug 13 '15 15:08 superjodash

@RubaXa This would be an awesome addition! :boat:

sandstrom avatar Oct 01 '15 17:10 sandstrom

+1

matikucharski avatar Nov 10 '15 09:11 matikucharski

+1

pbrickell avatar Nov 11 '15 15:11 pbrickell

+1

vsromanc avatar Nov 20 '15 10:11 vsromanc

+1 I have a use where items can be dragged between two lists. But list one has a max of 8, so once it has 8, I need to either prevent dropping onto it, or cancel the drop (and would display an error)

UPDATE: To do this I used onSort to dynamically adjust the put feature which limits if new items can be added. Here's the summary:

var listone_sortable = new Sortable( document.getElementById("listone"), { group: {name:"list1", put: $("#listone > *").length < 8 ? ["list2"] : false, onSort: function() { listone_sortable.options.group.put = $("#listone > *").length < 8 ? ["list2"] : false; } }); // The other list is normal, with a group: "list2"

efreed avatar Dec 08 '15 18:12 efreed

:+1:

cmfcmf avatar Dec 26 '15 08:12 cmfcmf

I also need to be able to Cancel the drop inside of the onSort() event using some logic. Is there a way with the existing js file to do this?

neonash7777 avatar Jan 12 '16 17:01 neonash7777

I manage to do this with onMove method.

vsromanc avatar Jan 12 '16 19:01 vsromanc

I also need to be able to Cancel the drop inside of the onSort() event using some logic. Is there a way with the existing js file to do this?

I currently manually put the element back to the right position inside the onUpdate callback: https://github.com/cmfcmf/MediaModule/blob/master/Resources/public/js/Collection/Permission/View.js#L24

I manage to do this with onMove method.

@vasyl-romanchak could you please provide an example?

cmfcmf avatar Jan 12 '16 19:01 cmfcmf

@cmfcmf In my case they are moving across multiple Sortable lists tied to the same "group". Is there a generic Jquery way to "undue" the changes in the onSort() event? (I would assume by using the evt parameters)

neonash7777 avatar Jan 12 '16 19:01 neonash7777

In my case they are moving across multiple Sortable lists tied to the same "group". Is there a generic Jquery way to "undue" the changes in the onSort() event? (I would assume by using the evt parameters)

I don't think there is an easy way then :-/

cmfcmf avatar Jan 12 '16 20:01 cmfcmf

@cmfcmf from official docs:

    // Event when you move an item in the list or between lists
    onMove: function (/**Event*/evt) {
        // Example: http://jsbin.com/tuyafe/1/edit?js,output
        evt.dragged; // dragged HTMLElement
        evt.draggedRect; // TextRectangle {left, top, right и bottom}
        evt.related; // HTMLElement on which have guided
        evt.relatedRect; // TextRectangle
        // return false; — for cancel
    }
});

onMove method will be called before onSort, onUpdate, etc. It just prevents user from dropping of the selected item into list.

romanchak avatar Jan 13 '16 09:01 romanchak

+1

achtan avatar Feb 26 '16 08:02 achtan

I undo the changes done by sortable with:

onSort: function (evt) {

    var oldId = evt.oldIndex,
        newId = evt.newIndex,
        reArrange = sortable.toArray(),
        oldSort = sortable.toArray();

    if (oldId < newId) {
        for (var i = oldId; i < newId; i++)
            reArrange[i+1] = oldSort[i];
    } else {
        for (var i = newId + 1; i <= oldId; i++)
            reArrange[i-1] = oldSort[i];
    }

    reArrange[oldId] = oldSort[newId];
    sortable.sort(reArrange);

}

Hope it helps someone :)

jaruba avatar Jun 07 '16 00:06 jaruba

+1

snez avatar Nov 01 '16 15:11 snez

I'd really appreciate this feature as well.

ghost avatar Nov 01 '16 16:11 ghost

For those of you looking to do this, I've found a solution as well. For some context, my need was very similar to @efreed; I have two lists (Options List and Preview List). The options list and the preview list needed to be able to drag options between them, but the preview list needed a max of 5 options at a time. I used the ability to place a formula within the group > put/pull options to accomplish this.

My HTML

<ul id="formula_preview_list" class="ui-sortable formula_ul">
     <li class="ui-sortable-handle option">Option5</li>
</ul>

<ul id="formula_options_list" class="ui-sortable formula_ul">
     <li class="ui-sortable-handle option">Option1</li>
     <li class="ui-sortable-handle option">Option2</li>
     <li class="ui-sortable-handle option">Option3</li>
     <li class="ui-sortable-handle option">Option4</li>
</ul>

My JS

Sortable.create(formula_options_list, {
     group: {
          name: 'optionslist',
          put: 'previewlist',
          pull: function (to, from) {
               return from.el.children.length > 1; 
          }
     },
     animation: 150
});
						
Sortable.create(formula_preview_list, {
     group: {
          name: 'previewlist',
          put: function (to) {
               return to.el.children.length < 5;
          }
     },
     animation: 150
});

You can find a similar technique in the complex logic jsbin example directly from the docs: Group Option

I hope this helps someone :)

designcouch avatar Dec 29 '16 18:12 designcouch

I found the easiest way of doing this was to use an array variable to check if the destination had the object in it already and if so set a different variable to true. Then I check the variable in the onMove function.

var DestinationArray;
var isItemInDestination = false;
$('#sourceContainerID').sortable({
   group:{
      name: "A",
      pull: ['clone'],
      put: [false]
   },
   dataIdAttr: 'ID',
   sort: false,
   onStart: function(evt){
      isItemInDestination = false; //Reset our boolean
      DestinationArray = $('#destinationContainerID').sortable('toArray');
      if(DestinationArray.indexOf(evt.item.id)>-1){
            isItemInDestination = true;
      }
   },
   onMove: function(evt){
      if(isItemInDestination){
         return false;
      }
   }
})

joshberg avatar Feb 16 '17 14:02 joshberg

Alas, there is no way to cancel the native dnd.

RubaXa avatar Feb 16 '17 14:02 RubaXa

Alas, there is no way to cancel the native dnd.

Why do you come to that conclusion @RubaXa? AFAIK all native DND implementations cancel the DND operation when pressing escape (assuming you're not on a touch-only device) or when ending the DND operation outside a droppable area.

p-bakker avatar Apr 06 '17 07:04 p-bakker

@designcouch great... saved me a ton of research ahead

milewski avatar Apr 09 '17 06:04 milewski

Hi, please, any update on canceling the drag with Escape button (and returning dragged item to original location)? I have tried the codes in this thread, but with no luck, and this function is critical for the project. Thank you for any tip

vlastapolach avatar Jul 16 '17 20:07 vlastapolach

@vlastapolach for the time being, you'll have to save the order before starting the drag event and manually revert the order on pressing the ESC-key. It's not a hard script to write. Good luck!

ghost avatar Jul 16 '17 20:07 ghost