Angular Sortable Containment prevents drop operation - javascript

I have a horizontal sortable Angular list but the containment option doesn't work and actually prevents the dragged item from being dropped.
Here's the sortable list without a containment option - notice that you have to "shake" the boxes to make them drop sometimes:
http://jsfiddle.net/zobgawqt/
$scope.sortableOptions = {
tolerance: 'pointer',
update: function(event, ui) { alert(ui.item.index()); }
};
Here's the sortable list WITH a containment option:
http://jsfiddle.net/4b4jzycs/2/
$scope.sortableOptions = {
containment: 'parent',
tolerance: 'pointer',
update: function(event, ui) { alert(ui.item.index()); }
};
Notice in the second version that the boxes are draggable but not droppable.
Here's a jQuery version that works with the same containment option:
http://jsfiddle.net/L7jemdbh/

Looks like the containment property needs a common ancestor of all the sortable items. If you give it a selector of the .sort-container node, it works as expected:
$scope.sortableOptions = {
containment: '.sort-container',
tolerance: 'pointer',
update: function(event, ui) { alert(ui.item.index()); }
};
Updated Fiddle

This is the simplest example I could create that works:
http://jsfiddle.net/0sx1wnyr/1/
There is a fix for the problem with having to shake the block to drop it - you need to add a 'start' event handler:
https://github.com/angular-ui/ui-sortable/issues/19
$scope.sortableOptions = {
containment: "parent",
axis: "x",
tolerance: "pointer",
start: function(e, ui) {
$(e.target).data("ui-sortable").floating = true;
}
};

Related

Drop is called when draggable is leaving nested sortable

I have Droppable div with nested Sortable and Draggable which is connected to the Sortable and is accepted by the Droppable.
<div id="droppable">
<div id="nested-sortable"></div>
</div>
<div class="draggable">
test
</div>
jQuery (2.0.2)
$("#droppable").droppable({
accept: ".draggable",
drop: function() {
console.log('Dropped'); //This should be called on drop!!
}
});
$("#nested-sortable").sortable({
placeholder: 'item',
});
$(".draggable").draggable({
connectToSortable: "#nested-sortable",
helper: "clone"
});
My problem is that when I drag the Draggable over the Sortable, drop event is triggered. I don't understand why - I haven't dropped it.
I reproduced it in this fiddle: http://jsfiddle.net/9ydp3L7q/3/
Thanks
I found a dirty workaround. I really don't like it but it seems to work alright.
I ignore drop if the helper has ui-sortable-helper (which it gets when it's over the sortable).
$("#droppable").droppable({
accept: ".draggable",
drop: function(event, ui) {
if (ui.helper.hasClass("ui-sortable-helper")) {
return;
}
console.log('Dropped');
}
});
But I have to remove the class manually on out of the sortable. If I try to just remove the class I get into and infinate loop (and javascript on the page crashes) - so I had to do it in timeout.
$("#nested-sortable").sortable({
placeholder: 'item',
out: function(event, ui) {
// this looks kind of dirty to me
setTimeout(function () {
$(ui.helper).removeClass("ui-sortable-helper")
}, 1);
}
});
Fixed fiddle: http://jsfiddle.net/9ydp3L7q/6/
Use disable for sortable while using draggable. and Use disable for draggable while using sortable.
$( ".selector" ).sortable( "disable" );
$( ".selector" ).draggable( "disable" );
or
$('.selector').draggable({
disabled: false
});
$(".selector").sortable({
disabled: false
});

Sortable, droppable nested list issue [duplicate]

I'm working on a project where I'm dragging elements from a 3rd party jQuery control to a jQuery sortable, using a combination of droppable and sortable.
This works perfectly fine, except the item being added is always added to the bottom of the sortable list, and you must then move it to the correct location as a separate step.
Is it possible to have the item added to the location where you dropped it in the list?
You can see this behavior in the jQuery shopping card droppable demo from here. Here is a jsfiddle of the same code. As you add items from the products to your cart at the bottom, it always adds at the bottom, even if you drop it near the top.
Here's the jQuery code:
$(function () {
$("#catalog").accordion();
$("#catalog li").draggable({
appendTo: "body",
helper: "clone"
});
$("#cart ol").droppable({
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
accept: ":not(.ui-sortable-helper)",
drop: function (event, ui) {
$(this).find(".placeholder").remove();
$("<li></li>").text(ui.draggable.text()).appendTo(this);
}
}).sortable({
items: "li:not(.placeholder)",
sort: function () {
$(this).removeClass("ui-state-default");
}
});
});
use droppable's drop event's callback to compare the current top offset position of the draggable helper with the top offset of every element already present or previously added in the droppable
drop: function (event, ui) {
if($(this).find(".placeholder").length>0) //add first element when cart is empty
{
$(this).find(".placeholder").remove();
$("<li></li>").text(ui.draggable.text()).appendTo(this);
}
else
{
var i=0; //used as flag to find out if element added or not
$(this).children('li').each(function()
{
if($(this).offset().top>=ui.offset.top) //compare
{
$("<li></li>").text(ui.draggable.text()).insertBefore($(this));
i=1;
return false; //break loop
}
})
if(i!=1) //if element dropped at the end of cart
{
$("<li></li>").text(ui.draggable.text()).appendTo(this);
}
}
}
DEMO WITH CODE
FULL SCREEN DEMO
What about doing this? Using both the connectToSortable AND connectWith options works, I think. There might be a more clever way to hide/show the placeholder, but this definitely works.
$(function () {
$("#catalog").accordion();
$("#catalog li").draggable({
appendTo: "body",
helper: "clone",
connectToSortable: "#cart ol"
});
$("#cart ol").sortable({
items: "li:not(.placeholder)",
connectWith: "li",
sort: function () {
$(this).removeClass("ui-state-default");
},
over: function () {
//hides the placeholder when the item is over the sortable
$(".placeholder").hide();
},
out: function () {
if ($(this).children(":not(.placeholder)").length == 0) {
//shows the placeholder again if there are no items in the list
$(".placeholder").show();
}
}
});
});
Work Demo in Fiddle

drag and drop jquery not working

I'm trying to drag the boxes from the man to the top of the car, target div called 'droppable'. This seems to work when previewing from Dreamweaver but not when previewing in jsfiddle:
http://jsfiddle.net/dantest2014/9JTSQ/7/
$(function () {
var dfd1 = $.Deferred();
var dfd2 = $.Deferred();
$("#lft_box_layer").draggable({
revert: "invalid",
cursor: "move"
});
$("#rgt_box_layer").draggable({
revert: "invalid",
cursor: "move"
});
$("#btm_box_layer").draggable({
revert: "invalid",
cursor: "move"
});
$("#droppable").droppable({
accept: "#lft_box_layer, #rgt_box_layer, #btm_box_layer",
// tolerance can be set to 'fit', 'intersect', 'pointer', or 'touch'
tolerance: 'intersect',
// Add .hoverClass whenever #draggable is being hovered over #droppable
over: function (event, ui) {
$('.ui-draggable-dragging').addClass('hover');
},
// Remove .hoverClass whenever #draggable is no longer hovered over #droppable
out: function (event, ui) {
$('.ui-draggable-dragging').removeClass('hover');
},
// Add .dropClass whenever #draggable is dropped on #droppable
drop: function (event, ui) {
$('.ui-draggable-dragging').removeClass('hover').addClass('drop');
$('.ui-draggable-dragging').draggable('option', 'disabled', true);
$("#car").attr('src', "images/removals-car-break.jpg");
}
});
});
Can someone help me with this?
After the three boxes have been dragged to the top of the car I would like to trigger a change of car image and also change the text.
Any help with any part of this question would be great.
Thanks!
Dan
In order to preview it on JSFiddle you first need to implement jQueryUI (not just jQuery) on the project.
Here is the same example with jQueryUI bound into your project (and cleaned the code a little to not waste code calling the draggable for all of the elements): http://jsfiddle.net/9JTSQ/11/
$(".toDrag").draggable({
revert: "invalid",
cursor: "move"
});
$("#droppable").droppable({
accept: ".toDrag",
.....................
});
I just bound jQueryUI from its CDN in "external resources"

change item attribute when it change list-items container

i have 2 sortable connected list-items and i want to make the item change his attribute when it change the list container (i mean by drag and drop the item from the first list items to the second one)and here is my code:
$(".column").sortable({
connectWith: $(".column") ,
placeholder: 'widget-placeholder',
cursor: 'move' ,
helper: function (evt, ui) {
return $(ui).clone().appendTo('body').show();
},
dropOnEmpty: true,
zIndex: 10
});
$("#column2").droppable({
out: function( event, ui ) {
$(ui.item).attr("rel",'0');
},
over: function( event, ui ) {
$(ui.item).attr("rel",'1');
}
});
You've made a good start, but there are a few things that need correcting, and some issues you may not have realised:
Your items are constructed thus:
<li id="1" class="item">
<h3 rel="1">item1</h3>
</li>
so you need to set the rel for the h3 element, but the code in your jsFiddle is:
$("#column2").droppable({
drop: function( event, ui ) {
$(this).find('.item').attr("rel",'0');
}
});
so this is finding all the elements under $(this) (i.e. the droppable) that have the class item - which corresponds to all the li elements. You need to use:
ui.item.find("h3").attr("rel", "0");
Your sortable in your jsFiddle is:
$(".column").sortable({
connectWith: $(".column") ,
placeholder: 'widget-placeholder',
cursor: 'move' ,
// utiliser helper-clone pour que le sortable n'est donc pas contenue par un volet
helper: function (evt, ui) {
return $(ui).clone().appendTo('body').show();
},
dropOnEmpty: true,
zIndex: 10
});
the helper function isn't needed - you can just use helper: "clone". I have added forcePlaceholderSize: true to my solution, because it provides useful feedback to the user in showing where the droppable is going to be dropped. If ordering is not critical, you can remove it.
There is a problem with using droppable.drop and droppable.out - they do not capture events for droppables that are dropped onto the start or the end of a list (I suspect this is because the droppable has to be dropped *into* the list to trigger the events, and if you drop it at the start/end of the list, it's effectively a new position and is not within the list).
So, we can use sortable instead:
$(".column").sortable({
connectWith: $(".column"),
placeholder: "widget-placeholder",
forcePlaceholderSize: true,
cursor: "move",
helper: "clone",
dropOnEmpty: true,
zIndex: 10
});
$("#column2").on("sortreceive", function (event, ui) {
ui.item.find("h3").attr("rel", "0");
});
$("#column2").on("sortremove", function (event, ui) {
ui.item.find("h3").attr("rel", "1");
});
See my jsFiddle for a working solution.

Only allowing one droppable area jquery drag and drop

I have jquery drag and drop working so I can move one row in a table to another.
the demo is here:
http://www.aussiehaulage.com.au/Default.aspx
I use jquery-ui-1.8.22 to make my table draggable/droppable.
My javascript is :
$(document).ready(function () {
$(".draggable").draggable({
helper: function () { return "<div class='ghost'></div>"; },
start: resizeGhost,
revert: 'invalid'
});
$(".droppable").droppable({
hoverClass: 'active',
drop: function (event, ui) {
var target = $(event.target);
var draggable = ui.draggable;
draggable.insertBefore(target);
},
tolerance: 'touch'
});
});
However when i move the row, if the mouse cursor is in between 2 rows on the droppable table both droppable rows are highlighted.. I need to make it so it will only highlight 1 droppable row at a time..
is this possible?
Add a new option in your droppable element, using either tolerance fit or intersect
$(".droppable").droppable({
hoverClass: 'active',
tolerence: 'intersect',
drop: function (event, ui) {
var target = $(event.target);
var draggable = ui.draggable;
draggable.insertBefore(target);
},
tolerance: 'touch'
});
And for your reference: jquery-ui

Categories

Resources