Drag and drop change destination objects
Maybe a little hard to explain. I have a grid with 9 images of 100 x 100 pixels like this (each number represents an image):
1 2 3
4 5 6
7 8 9
I want the user to be able to drag and drop eg. 9 over 1, and they swap places like this:
9 2 3
4 5 6
7 8 1
Sorts from jquery UI won't work as their solution uses floats. This will "push" all fields to the right or left, for example:
9 1 2
3 4 5
6 7 8
early.
a source to share
In this case, Draggable and Droppable are used. Draggable returns to its original position when dripping. When dragging starts, Draggable creates a function to indicate where to insert the Droppable that the element is dropping on. When an item is dropped, the drop function inserts the dropped item after the item has been dropped and calls the drop function on the dropped item to move the Droppable to the desired position.
$(function() {
$('.item').draggable( {
containment: 'parent',
revert: true,
revertDuration: 0,
start: function() {
var that = $(this);
var previous = that.prev( '.item:last' );
var next = that.next( '.item:first' );
that.data( 'insert' , function(elem) {
if (previous.size() > 0) {
$(elem).insertAfter(previous);
}
else if (next.size() > 0) {
$(elem).insertBefore(next);
}
});
}
});
$('.item').droppable( {
accept: '.item',
drop: function(event, ui) {
var elem = $(this);
if (elem.siblings('.item').size() > 1) {
ui.draggable.insertAfter(elem);
var insert = ui.draggable.data('insert');
insert(elem);
}
else { // case where there are only two elements, swap
var parent = elem.closest('.container');
var first = parent.children( '.item:first' );
var last = parent.children( '.item:last' );
last.insertBefore( first );
}
}
});
});
<div id="container">
<span class="item">1</span>
<span class="item">2</span>
<span class="item">3</span>
<span class="item">4</span>
<span class="item">5</span>
</div>
a source to share
Thanks for the quick answers!
Your solutions look good, but the first one causes some errors when changing positions 1 and 2. The second one is not quite there. But they help a lot!
I tried to do some code which I think is a step in the right direction. What do you think?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
<title>Drag drop 1</title>
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.7.1.custom.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$(".item").draggable({
// Elements cannot go outside #container
containment: 'parent',
// Make sure the element can only be dropped in a grid
grid: [150,150],
start: function(event, ui) {
// Make sure picture always are on top when dragged (z-index)
$(this).css({'z-index' : '100'});
// Show start dragged position
var Startpos = $(this).position();
$("div#start").text("START: \nLeft: "+ Startpos.left + "\nTop: " + Startpos.top);
},
stop: function(event, ui) {
// Revert to default layer position when dropped (z-index)
$(this).css({'z-index' : '10'});
// Show dropped position
var Stoppos = $(this).position();
$("div#stop").text("STOP: \nLeft: "+ Stoppos.left + "\nTop: " + Stoppos.top);
}
});
});
</script>
<style>
#container {
width:480px;
border:1px solid #000;
}
.item {
position:relative;
width:150px;
height:150px;
z-index:10;
}
</style>
</head>
<body>
<div id="container">
<img id="productid_1" src="images/pic1.jpg" class="item" alt="" title="" /><img id="productid_2" src="images/pic2.jpg" class="item" alt="" title="" /><img id="productid_3" src="images/pic3.jpg" class="item" alt="" title="" /><img id="productid_4" src="images/pic4.jpg" class="item" alt="" title="" /><img id="productid_5" src="images/pic5.jpg" class="item" alt="" title="" /><img id="productid_6" src="images/pic6.jpg" class="item" alt="" title="" /><img id="productid_7" src="images/pic7.jpg" class="item" alt="" title="" /><img id="productid_8" src="images/pic8.jpg" class="item" alt="" title="" /><img id="productid_9" src="images/pic9.jpg" class="item" alt="" title="" />
</div>
<div style="clear:both;"></div>
<div id="start">Waiting...</div>
<div id="stop">Waiting...</div>
</body>
</html>
a source to share