views:

248

answers:

3

Hi.

Maybe a bit complex to explain. I have a grid with 9 images 100 x 100 px like this (each number symbolize a picture):

1 2 3
4 5 6
7 8 9

What I want is that the user can drag and drop e.g. 9 over 1 and they change places like this:

9 2 3
4 5 6
7 8 1

Sortables from jquery UI will not work since their solution is using floats. That will "push" all the boxes to the right or left e.g.:

9 1 2
3 4 5
6 7 8

thanks in advance.

A: 

take a look at this plugin:

http://github.com/brandonaaron/jquery-swap/tree/master

jhensley2
+2  A: 

This uses both Draggable and Droppable. The Draggable reverts to it's original position on drop. When dragging starts, the Draggable creates a function to specify where to insert the Droppable that the item gets dropped on. When the item is dropped the drop function inserts the dragged item after the item it was dropped on and invokes the insert function on the dropped item to move the Droppable to the correct 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>
tvanfosson
A: 

Thanks for the fast replies!

Your solutions looks good but the first one throws some errors when changing position 1 and 2. The second one is not quite there. But they help alot!

I have tried to make some code that 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"&gt;
<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>
Cudos