3

I've been playing with JQuery UI draggable and have been struggling with maintaining element position when dragging an element from one parent to the other. As soon as move the element to another parent it's positioning is way off. I then proceeded to workout the offset and applied it to the element and it worked very well until I started styling the page and then everything was even worse then before.

It appears to be a simple requirement so not sure if I'm missing an obvious trick?

Apologies if the above isn't clear, quite difficult to explain it well.

Thanks Steve

ps. just the js code below, it's not pretty and some of the values I've hard coded for now:

$(document).ready(function() { 
  makeDraggable($(".draggable"));
});

function makeDraggable(el) {
  var clone ;
  var x = 0;
  var y = 0;
  $(el).draggable({
    zIndex: 1000,
    start:function() {
      if($(this).parent().parent().attr("id") == "browser") {
        clone = $(this).clone();
        makeDraggable($(clone));
        $(clone).css("position","absolute");
        $(clone).css("z-index","0");
        $(this).parent().append($(clone));
      } // end if
    },
    drag:function() {},
    stop:function() {
      if($(this).parent().parent().attr("id") == "browser") {
        var offset = 0;
        var total_item_width = parseInt($(this).css("padding-left"))+parseInt($(this).css("padding-right"))+$(this).width();

        $(clone).css("position","relative");
        $("#canvas").append($(this));

        offset = ($("#canvas").find(".draggable").size()-1)*total_item_width;  
        $(this).css("left",parseInt($(this).css("left"))+827-offset);

        offset = ($("#canvas").find(".draggable").size()-1)*($(this).height()+12);
        $(this).css("top",parseInt($(this).position().top));
      } // end if
    }
  });
}
Steven Cheng
  • 1,071
  • 3
  • 14
  • 25
  • post the code if it's difficult to explain .. – Lukman Aug 10 '10 at 08:47
  • possibly check css position property on the parent elems: http://stackoverflow.com/questions/2451528/jquery-ui-sortable-scroll-helper-element-offset-firefox-issue/ – zack Nov 02 '10 at 17:16

3 Answers3

1

When dragging an object jquery applies an offset, top/left, style directly to the element. If you are adding this draggable to a new container, the new container is the parent and the offsets will now be applied from the containers position, instead of the screen --- at least that is my interpretation.

Here is a workaround I've used: the helper clone receives the styling leaving your original element to be appended cleanly. The start/stop toggles the display, making it look like you are dragging the actual element.

$("#draggable").draggable({
    revert: 'invalid',
    helper: 'clone', 
    zIndex: 350, 
    start:  function() { $(this).toggle(); }, 
    stop:   function() { $(this).toggle(); } 
});
$("#droppable").droppable({
    accept: '#draggable',
    drop: function(event, ui) {
                // example of effecting parent
                // $(this).addClass('highlight').find('p').html('Dropped!');
                $(ui.draggable).draggable("destroy").appendTo($(this));
    }
});
WSkid
  • 2,736
  • 2
  • 22
  • 26
  • Thanks for this, I'm going to give this a go and see how I get on. – Steven Cheng Aug 10 '10 at 09:08
  • I tested your script and first it generated an error on $(ui.draggable).draggable("destroy").appendTo($(this)); and a quick google suggests I use disable instead of destroy which I did and the code executed fine. However, it dropped the element into the parent without keeping the position. Not sure if my question above was clear, but basically as I drag the element I need to re-assign the parent and keep the position within the new parent. – Steven Cheng Aug 10 '10 at 09:23
1

It seems like perhaps you should consider re-organizing your DOM. I don't understand why you change position relative to absolute positioning for the start of the drag and then change that back to relative on drop. That's a recipe for disaster as layouts get more complicated, naturally creating plenty of opportunity for your tags to jump around. If you checked in firebug, you'd find some children who are outside of their parents, which you probably didn't expect if you were dropping on a parent. If you are new to the world of types of positioning, and need to just get it done, stick to keeping these draggable elements absolute, this should minimise difficulties in predicting behavior. But to have nice sites at a variety of resolutions, you really should get to grips with how exactly a browser will place visible objects given their properties.

Good luck :)

sillyMunky
  • 1,260
  • 8
  • 13
  • Since I originally posted this, I've implemented my solution in a much simpler way. I modified my DOM and also made the drag and drop much easier programmatically speaking. I am still learning but have definitely had major exposure to element positioning during this part of my project. Thanks for your answer! – Steven Cheng Sep 27 '10 at 13:08
  • Glad you're getting the hang of it, simplicity is the key! +1 would be nice ;-) – sillyMunky Oct 20 '10 at 09:38
0

This worked best for me.

$(function() {
    var unit;
    $(".unit").draggable();
    $("#rpgGrid td").droppable({
        drop : function(event, ui) {
            jQuery(ui.draggable).css({
                "top": "0",
                "left": "0"
            });
            $(this).append(ui.draggable, function() {
                $(ui.draggable).remove();
            });
        }
    });
});
americanknight
  • 689
  • 3
  • 18
  • 37