views:

1040

answers:

0

Hello.

Overview

  • The user can drag an image from "#products" to "#container". They will fall into the normal flow of elements.
  • All images inside of "#container" can be dragged around in side that container in a grid.
  • In the "#container", If an image is dropped where another image is, they swap places.

Problem

When I start to move the images around in "#container" a problem arise. Next time I drag an image from "#products" to "#container" the image will fall into the normal flow of elements WITHOUT being aware the elements has been moved around. That result in the image may be lying on top of another image thus covering it.

It's probably something to do with position:relative stays the same when moving elements.

Your help will be much appreciated.

I plan to release it as an jQuery plugin. Anyone helping with making it work will be credited if they want to.

Code

<!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() {
     // --------------
     // - Image swap -
     // --------------
     // The user can drag an image from "#products" to "#container". They will fall into the normal flow of elements.
     // All images inside of "#container" can be dragged around in side that container in a grid.
     // If an image is dropped where another image are, they swap places.

     // Setting global variables.
     var dragged = null;

     // Make a clone of a image from the "#products" container.
     $(".product").draggable({
      helper: 'clone'
     });

     // Make "#container" a droppable and only accept images with ".product" class.
     $("#container").droppable({

      // Only accept images with ".product" class.
      accept: '.product',
      drop: function(event, ui) {

       // When clone of image from "#products" gets dropped on "#container" it is added to "#container".
       // After that we change the class name to "item".
       $(this).append(ui.draggable.clone().addClass("item").removeClass("product"));

       // Images with class "item" in "#container" are made draggable. 
       $(".item").draggable({

        // Prevent draggables to go outside "#container".
        containment: 'parent',

        // Make sure that draggables only can be in 9 positions in a grid.
        grid: [150,150],
        start:function(event, ui) {

         // When image is dragged, make sure it is always on top.
         $(this).css({'z-index' : '100'});

         // Get position where the dragging got started.
         dragged = $(this).position();

         // Below line can be uncommeted if you use Firebug and Firefox so you can trace variable "dragged".
         //console.debug("Dragged: ",dragged);
        },
        stop: function(event, ui) {

         // Revert to original layer position.
         $(this).css({'z-index' : '10'});
        }
       });

       // Inside the "#container" we make all images droppables.
       $(".item").droppable({
        drop: function(event, ui) {

         // If a clone dragged from "#products" over an existing image in "#container" do not do below.
         if(dragged!=null) {

          // Get position of the image where another image from "#container" was dropped on.
          var dropped_on = $(this).position();
          var drop_top = $(this).css("top");
          var drop_left = $(this).css("left");

          // All images has the css property position:relative. Therefore it is needed to calculate the
          // where to move the dropped on image relative to it's current position.
          var newTop = dragged.top - (dropped_on.top - parseInt(drop_top));
          var newLeft = dragged.left - (dropped_on.left - parseInt(drop_left));

          // Only move dropped on image since dragged image has been dropped in the right position.
          $(this).css({'top' : newTop, 'left' : newLeft});

          // Below lines can be uncommeted if you use Firebug and Firefox so you can trace variables.
          // console.debug("newTop: ",newTop," newLeft: ",newTop);
          // console.debug("drop_top: ",drop_top," drop_left: ",drop_left);
         }
        }
       });
      }
     });
    });
    </script>
    <style>
    body {

    }
    #container {
     width:450px;
     height:450px;
     border:1px solid #000;
    }
    .item {
     width:150px;
     height:150px;
     z-index:10;
     cursor:move;
    }
    #products {
     position:absolute;
     width:450px;
     height:450px;
     top:9px;
     left:550px;
     border:1px solid #000;
    }
    .product {

    }
    #testarea {
     position:absolute;
     width:450px;
     height:450px;
     top:9px;
     left:1100px;
     border:1px solid #000;
    }
    </style>
</head>
<body>
    <div id="container">
    </div>
    <div id="products">
     <img id="productid_1" src="images/pic1.jpg" class="product" alt="" title="" /><img id="productid_2" src="images/pic2.jpg" class="product" alt="" title="" /><img id="productid_3" src="images/pic3.jpg" class="product" alt="" title="" /><img id="productid_4" src="images/pic4.jpg" class="product" alt="" title="" /><img id="productid_5" src="images/pic5.jpg" class="product" alt="" title="" /><img id="productid_6" src="images/pic6.jpg" class="product" alt="" title="" /><img id="productid_7" src="images/pic7.jpg" class="product" alt="" title="" /><img id="productid_8" src="images/pic8.jpg" class="product" alt="" title="" /><img id="productid_9" src="images/pic9.jpg" class="product" alt="" title="" />
    </div>
</body>
</html>