I've a sortable element inside another sortable element. Both are connected to each other. Following the the sample markup:
<div id='container'>
<div class='parent'>
<div class='child'>1</div>
<div class='child'>2</div>
<div class='child'>3</div>
<div class='child'>4</div>
</div>
<div class='parent'>
<div class='child'>5</div>
<div class='child'>6</div>
<div class='child'>7</div>
<div class='child'>8</div>
</div>
</div>
What i'm trying to do is to drag multiple items between .parent
's and #container
.
Following is the JS:
$("#container").on('click', '.child', function () {
$(this).toggleClass('selected');
});
$('.parent').sortable({
appendTo: "#container",
connectWith: '.parent, #container',
revert: 0,
helper: function (e, item) {
if (!item.hasClass('selected')) {
item.addClass('selected').siblings().removeClass('selected');
}
var elements = $('#container').find('.selected').clone();
$('#container').find('.selected').not(item).addClass('hidden');
var helper = $('<div/>', {
class: 'parent'
});
return helper.append(elements);
},
start: function (e, ui) {
var len = ui.helper.children().length;
var width = ui.item.width() + 2;
ui.helper.width((len * width));
ui.placeholder.width((len * width));
},
stop: function (e, ui) {
$('.selected').removeClass('selected');
}
});
$('#container').sortable({
connectWith: '.parent',
tolerance: "pointer"
});
The following
JSFiddle
with the whole code (I removed the code for appending items to minimize the code since that is not relevant to the placeholder position) demonstrates the issue i'm facing:
I'm able to drag items from .parent
to the #container
as follows:
- By dragging the items to the left of
#container
as shown below: - By dragging items above
#container
through the space between.parents
(This is a bit tricky but it works when the center is exactly hovered over the space) as shown below:
But Once i drag an item outside, the placeholder does not appear to the right side of #container
even when i directly hover the item over it.
Expected output:
Current result:
As shown in the image, the placeholder is inside the .parent
even though the item is away from it, inside #container
.
From what i tried, the issue is with the following:
$('#container').find('.selected').not(item).addClass('hidden');
Where i hide the selected items using display:none
, Possibly causing miscalculations with jQuery UI.
So i tried refresh and refreshPositions in the start event, as in this JSFiddle, Which is produces the expected output, but it no longer properly displays the placeholder in #container
in the other two scenario.
What i want to do is to be able to drag items from .parent
to #container
by
- Dragging items to the left of
#container
- Dragging items above
#container
through the space between.parents
- Dragging items to the right of
#container
Side note: Most of the sortable options are added while trying to fix the issue, and the css dimensions are for demo purpose only, these can be added or removed if necessary.
Update: this seems like a bug, which i reported here. The jQuery UI team replied that they are in the process of rewriting all interactions. So hopefully this will be fixed in the next release.
I've a sortable element inside another sortable element. Both are connected to each other. Following the the sample markup:
<div id='container'>
<div class='parent'>
<div class='child'>1</div>
<div class='child'>2</div>
<div class='child'>3</div>
<div class='child'>4</div>
</div>
<div class='parent'>
<div class='child'>5</div>
<div class='child'>6</div>
<div class='child'>7</div>
<div class='child'>8</div>
</div>
</div>
What i'm trying to do is to drag multiple items between .parent
's and #container
.
Following is the JS:
$("#container").on('click', '.child', function () {
$(this).toggleClass('selected');
});
$('.parent').sortable({
appendTo: "#container",
connectWith: '.parent, #container',
revert: 0,
helper: function (e, item) {
if (!item.hasClass('selected')) {
item.addClass('selected').siblings().removeClass('selected');
}
var elements = $('#container').find('.selected').clone();
$('#container').find('.selected').not(item).addClass('hidden');
var helper = $('<div/>', {
class: 'parent'
});
return helper.append(elements);
},
start: function (e, ui) {
var len = ui.helper.children().length;
var width = ui.item.width() + 2;
ui.helper.width((len * width));
ui.placeholder.width((len * width));
},
stop: function (e, ui) {
$('.selected').removeClass('selected');
}
});
$('#container').sortable({
connectWith: '.parent',
tolerance: "pointer"
});
The following
JSFiddle
with the whole code (I removed the code for appending items to minimize the code since that is not relevant to the placeholder position) demonstrates the issue i'm facing:
I'm able to drag items from .parent
to the #container
as follows:
- By dragging the items to the left of
#container
as shown below: - By dragging items above
#container
through the space between.parents
(This is a bit tricky but it works when the center is exactly hovered over the space) as shown below:
But Once i drag an item outside, the placeholder does not appear to the right side of #container
even when i directly hover the item over it.
Expected output:
Current result:
As shown in the image, the placeholder is inside the .parent
even though the item is away from it, inside #container
.
From what i tried, the issue is with the following:
$('#container').find('.selected').not(item).addClass('hidden');
Where i hide the selected items using display:none
, Possibly causing miscalculations with jQuery UI.
So i tried refresh and refreshPositions in the start event, as in this JSFiddle, Which is produces the expected output, but it no longer properly displays the placeholder in #container
in the other two scenario.
What i want to do is to be able to drag items from .parent
to #container
by
- Dragging items to the left of
#container
- Dragging items above
#container
through the space between.parents
- Dragging items to the right of
#container
Side note: Most of the sortable options are added while trying to fix the issue, and the css dimensions are for demo purpose only, these can be added or removed if necessary.
Update: this seems like a bug, which i reported here. The jQuery UI team replied that they are in the process of rewriting all interactions. So hopefully this will be fixed in the next release.
Share Improve this question edited Sep 28, 2014 at 9:46 T J asked Aug 31, 2014 at 18:16 T JT J 43.2k13 gold badges86 silver badges142 bronze badges 2-
First you said
As shown in the image, the placeholder is inside the .parent even though the item is away from it, inside #container.
.. I just checked it and the placeholders are outside the parent, just a child of container, am I right? check this screenshot prntscr./4j2qpl – Pablo Matias Gomez Commented Sep 2, 2014 at 20:44 - Well you probably took that screenshot from second fiddle, in which i'm unable to create the placeholder in container on the left side along with other issues as i mentioned in the question... Did you check whether you can perform all the three actions in same fiddle? – T J Commented Sep 3, 2014 at 7:30
2 Answers
Reset to default 1In my code, it has almost bee a convention to just apply this poorly documented hack to Sortable’s over
and out
callback functions:
if($.ui.ddmanager.current)
$.ui.ddmanager.prepareOffsets($.ui.ddmanager.current, null);
This will make sure positions are refreshed, and in contrast to the built-in refresh
and refreshPositions
methods, it seems to work.
Could you try this approach, and see if it improves your Sortable’s behavior?
Edit:
Never mind the third-party plugin, check this out let me know if this is what you were after: http://jsfiddle/6opxyvkp/7/ - old
http://jsfiddle/6opxyvkp/9/ - new
HTML
<div id='container'>
<div class='parent'>
<div class='child'>1</div>
<div class='child'>2</div>
<div class='child'>3</div>
<div class='child'>4</div>
</div>
<div class='parent'>
<div class='child'>5</div>
<div class='child'>6</div>
<div class='child'>7</div>
<div class='child'>8</div>
</div>
</div>
CSS
#container {
display: inline-block;
height:60px;
background:dodgerblue;
}
.parent {
float:left;
height:58px;
margin:0 15px;
border:0px solid red;
background:silver;
}
.child {
float:left;
width:50px;
height:60px;
text-align: left;
background:#fff;
border:1px solid;
margin:0px;
}
.ui-sortable-placeholder {
visibility: visible !important;
border: none;
padding:1px;
background:rgba(0, 0, 0, 0.5) !important;
}
.selected {
background:red;
}
.hidden {
display:none !important;
}
JS
$("#container").on('click', '.child', function () {
$(this).toggleClass('selected');
});
$('.parent').sortable({
connectWith: '.parent, #container',
appendTo: '#container',
revert: 0,
helper: 'clone',
helper: function (e, item) {
var helper = $('<div/>');
if (!item.hasClass('selected')) {
item.addClass('selected').siblings().removeClass('selected');
}
var elements = item.parent().children('.selected').clone();
item.data('multidrag', elements).siblings('.selected').remove();
return helper.append(elements);
},
start: function (e, ui) {
var len = ui.helper.children().length;
var width = ui.item.width() + 2;
ui.helper.width((len * width));
ui.placeholder.width((len * width));
},
stop: function (e, info) {
info.item.after(info.item.data('multidrag')).remove();
}
});
$('#container').sortable({
connectWith: '.parent',
tolerance: 'pointer'
});
If third-party jQuery
plugins are allowed, take a look at https://github./shvetsgroup/jquery.multisortable.