Swapping two jQuery draggable list items not working properly (with jsFiddle example)
The minimalist working example below swaps the two boxes when box 'one' is dragged and dropped on box 'two'. The problem is that when box 'one' is dropped, its style has 'top' & 'left' values causing it to be placed away from where it should drop. Its class includes 'ui-draggable-dragging'. It seems the top & left values are related to the amount the elements were dragged before the drop. And the dragging was 'interrupted' hence the residual 'ui-draggable-dragging' class?
What am I missing to make the swap work seamlessly? full jsfiddle example here
<html>
<head>
<script type="text/javascript" src="includes/jquery开发者_运维问答-1.4.2.min.js"></script>
<script type="text/javascript" src="includes/jquery-ui-1.8.2.custom.min.js"></script>
<script type="text/javascript">
jQuery.fn.swapWith = function(to) {
return this.each(function() {
var copy_to = $(to).clone(true);
var copy_from = $(this).clone(true);
$(to).replaceWith(copy_from);
$(this).replaceWith(copy_to);
});
};
$(document).ready(function() {
options = {revert: true};
$("li").draggable(options)
$('#wrapper').droppable({
drop: function(event, ui) {
$(ui.draggable).swapWith($('#two'));
}
});
});
</script>
</head>
<body>
<form>
<ul id="wrapper">
<li id='one'>
<div style="width: 100px; height: 100px; border: 1px solid green">
one<br /></div>
</li>
<li id='two'>
<div style="width: 110px; height: 110px; border: 1px solid red">
two<br /></div>
</li>
</ul>
<br />
</form>
</body>
</html>
This is my workaround.
My guess, without looking at and understanding how jQuery's internal drop and drag stuff works, is that there's some elapsed time before everything in the drag & drop has finished processing.
So I figured that the swap should not be initiated until everything is done. Because I don't know when this happens, I had the swap occur after some delay. I used setTimeout in the drop event. I had to use at least 600ms to be sure 'everything was clear and safe'. Less than 600ms, the 'top' & 'left' still had some values which meant the process wasn't done yet. The longer the delay, the smaller those values are; until anything bigger had top and left equal zeros. By trial and error 600ms seems to do it.
If anyone has a 'cleaner' solution I would appreciate it. Plus a 'scientific' explanation is helpful.
In continuation from your other post, I added the helper: 'clone' option, and then told the script to remove any elements with the .ui-draggable-dragging class
<script type="text/javascript">
jQuery.fn.swapWith = function(to) {
return this.each(function() {
var copy_to = $(to).clone();
var copy_from = $(this).clone();
$(to).replaceWith(copy_from);
$(this).replaceWith(copy_to);
});
};
$(document).ready(function() {
options = {
revert: true,
helper: 'clone'
};
$("li").draggable(options);
$('#wrapper').droppable({
drop: function(event, ui) {
// window.setTimeout(function(){
$('#one').swapWith($('#two'));
$(".ui-draggable-dragging").remove();
$("li").draggable(options);
//}, 1);
}
});
});
</script>
working example: http://jsfiddle.net/XkUDv/26/
Hope that helps!
PS: I hadn't used jsfiddle before so thanks for your part in showing me that :)
精彩评论