jQuery draggable shows helper in wrong place after page scrolled

Solution 1:

This might be a related bug report, it's been around for quite a while: http://bugs.jqueryui.com/ticket/3740

It seems to happen on every browser I tested (Chrome, FF4, IE9). There are a few ways you can work around this issue:

1. Use position:absolute; in your css. Absolutely positioned elements don't seem to be affected.

2. Make sure the parent element (event if it's the body) has overflow:auto; set. My test showed that this solution fixes the position, but it disables the autoscroll functionality. You can still scroll using the mousewheel or the arrow keys.

3. Apply the fix suggested in the above bug report manually and test thouroughly if it causes other problems.

4. Wait for an official fix. It's scheduled to jQuery UI 1.9, although it has been postponed a few times in the past.

5. If you're confident that it happens on every browser, you can put these hacks into the affected draggables' events to correct the calculations. It's a lot of different browsers to test though, so it should only be used as a last resort:

$('.drag').draggable({
   scroll:true,
   start: function(){
      $(this).data("startingScrollTop",$(this).parent().scrollTop());
   },
   drag: function(event,ui){
      var st = parseInt($(this).data("startingScrollTop"));
      ui.position.top -= $(this).parent().scrollTop() - st;
   }
});

Solution 2:

This solution works without adjusting the positioning of anything, you just clone the element and make it absolutely positioned.

$(".sidebar_container").sortable({
  ..
  helper: function(event, ui){
    var $clone =  $(ui).clone();
    $clone .css('position','absolute');
    return $clone.get(0);
  },
  ...
});

The helper can be a function which needs to return the DOM element to drag with.

Solution 3:

This worked for me:

start: function (event, ui) {
   $(this).data("startingScrollTop",window.pageYOffset);
},
drag: function(event,ui){
   var st = parseInt($(this).data("startingScrollTop"));
   ui.position.top -= st;
},

Solution 4:

Sorry for writing another answer. As none of the solutions in the above answer could be used by me I did a lot of Googling and made many frustrating minor edits before finding another reasonable solution.

This issue seems to occur whenever any of the parent elements have position set to 'relative'. I had to reshuffle my markup and alter my CSS but by removing this property from all parents, I was able to get .sortable() working properly in all browsers.

Solution 5:

It looks like this bug comes around very often, and every time there is a different solution. None of the above, or anything else I found on the internet worked. I'm using jQuery 1.9.1 and Jquery UI 1.10.3. This is how I fixed it:

$(".dragme").draggable({
  appendTo: "body",
  helper: "clone",
  scroll: false,
  cursorAt: {left: 5, top: 5},
  start: function(event, ui) {
    if(! $.browser.chrome) ui.position.top -= $(window).scrollTop();
  },
  drag: function(event, ui) {
    if(! $.browser.chrome) ui.position.top -= $(window).scrollTop();
  }
});

Works in FF, IE, Chrome, I've not yet tested it in other browsers.