Sortable
Sortable copied to clipboard
Cancel drop
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.
Already have events add / update / remove / sort.
Now need to add the processing isDefaultPrevented.
https://github.com/RubaXa/Sortable/issues/138
@superjodash I'd love to see this as well. Did you come up with a workaround?
@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.
Any updates on this feature? It is very useful but not be implemented in this version. @RubaXa @superjodash
+1
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.
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]);
}
});
@RubaXa This would be an awesome addition! :boat:
+1
+1
+1
+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"
:+1:
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 manage to do this with onMove method.
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 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)
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 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.
+1
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 :)
+1
I'd really appreciate this feature as well.
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 :)
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;
}
}
})
Alas, there is no way to cancel the native dnd.
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.
@designcouch great... saved me a ton of research ahead
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 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!