jQuery UI sortable scroll helper element offset Firefox issue

35,488

Solution 1

I was seeing this issue and was able to solve it by removing the css rule position:relative from one of the containing divs on my page. See also: http://forum.jquery.com/topic/sortable-offset-when-element-is-dragged-and-page-scrolled-down-ff

Solution 2

If you want to prevent browser sniffing, the CSS only solution is to set the ul or a container style to overflow: auto. If you look at the source through firebug, it's the way jQuery does it in their example.

Solution 3

I also had this problem and fixed it with the following code:

var wscrolltop = 0;
$sortable_elements.sortable({ 
    start: function(event, ui) {
        wscrolltop = $(window).scrollTop();
    },
    sort: function(event, ui) {                   
        ui.helper.css({'top' : ui.position.top + wscrolltop + 'px'});
    }
});

I discovered, that there still is a problem if you scroll with your sortable-element. Maybe somebody has a solution for this?

UPDATE: The fix is:

$sortable_elements.sortable({ 
    connectWith: '#personal-favs ul.fitems',
    sort: function(event, ui) {  
        ui.helper.css({'top' : ui.position.top + $(window).scrollTop() + 'px'});
    }
});

But still - if you're leaving the list, the sort-event seems to stop.

Solution 4

You also need to account for the fact this is specific to firefox, here is the snippet I'm using - I got directed the right way from Harris' solution. I encountered this problem w/o using the helper when the sortable was in a relatively positioned container.

  var options = { 
   handle: '.mover', 
   update:updateSorting 
 };
  var userAgent = navigator.userAgent.toLowerCase();
  if(userAgent.match(/firefox/)) {
    options["start"] = function (event, ui) { ui.item.css('margin-top', $(window).scrollTop() ); };
    options["beforeStop"] = function (event, ui) { ui.item.css('margin-top', 0 ); };
  }
  $("#" + list_id+"").sortable(options);
  $("#" + list_id+"").disableSelection();

You could also do this check on the server and then have 2 different calls depending on the browser.

Solution 5

I managed to figure out a fix for this:

$( "items" ).sortable({
start: function (event, ui) {
 if( ui.helper !== undefined )
  ui.helper.css('position','absolute').css('margin-top', $(window).scrollTop() );
},
beforeStop: function (event, ui) {
 if( ui.offset !== undefined )
  ui.helper.css('margin-top', 0);
},
placeholder: 'placeholder-class'
});

Basically, you need to listen for the sortable's "start" event to add the browser's current scrollTop() value to the helper's position, and then you need to listen for the sortable's "beforeStop" event, to remove that offset before the item is officially placed back into the list at its new position.

Hope that's helpful to someone!

Share:
35,488
James
Author by

James

Updated on July 09, 2022

Comments

  • James
    James almost 2 years

    I have a problem with a jQuery UI 1.7.2 sortable list in Firefox 3.6, IE7-8 work fine. When I'm scrolled down a bit, the helper element seems to have an offset of the same height that I'm scrolled down from the mouse pointer which makes it impossible to see which item you originally started dragging. How do I fix this or work around the issue? If there is no fix what is a really good alternative drag-able plugin?

    Here are my initialization parameters for the sortable.

    $("#sortable").sortable( {placeholder: 'ui-state-highlight'  } );
    $("#sortable").disableSelection();
    
  • Dan Fuller
    Dan Fuller almost 14 years
    Excellent, you saved me a lot of trouble here.
  • StuperUser
    StuperUser about 13 years
    This is the only answer that worked for me using JQuery-UI draggables and droppables.
  • deshg
    deshg almost 13 years
    This worked perfectly for me on all browsers and is certainly the simplest/cleanest solution. Cheers!
  • Bart Gloudemans
    Bart Gloudemans almost 13 years
    definitely the cleanest solution. Not being able to define a container position:relative is a quite serious limitation
  • Robin
    Robin over 12 years
    Thanks! As mentioned before, no position:relative is unacceptable... the overflow:auto is still causing me some trouble with elements positioned absolutely, but I'm sure it's easy to fix.
  • Björn
    Björn over 12 years
    This worked for me while the position:relative didn't, thanks.
  • Michi
    Michi about 12 years
    For me that one was also the only one that worked... thanks :-)
  • bbodien
    bbodien over 11 years
    Great find, thanks. It's simply not realistic to avoid having position: relative on any parent element.
  • Mrugen Ramani
    Mrugen Ramani over 11 years
    this is great solution for me because i am using jquery 1.4.2 & jquery-ui.1.8.23 so i had encounter this problem so it will fix now. this problem will be also fix using jquery.1.8.js but i was getting so many issue when i am replacing my jquery.1.4.2 to jquery.1.8.js so thnx
  • Ricardo Gomes
    Ricardo Gomes over 11 years
    it makes me sick to have to do this, but this was the only solution (out of like 50235289) that actually worked. Seriously, though, SICK TO MY STOMACH. Sigh.
  • Ricardo Gomes
    Ricardo Gomes over 11 years
    actually fixed the issue by removing the html { overflow-x: hidden; } in my CSS. unreal.
  • TheGwa
    TheGwa over 11 years
    This should be marked as the correct answer. Works perfectly.
  • Pierluc SS
    Pierluc SS over 11 years
    Combinasion of position: static; and overflow: auto; did it for me
  • Ken Palmer
    Ken Palmer almost 11 years
    Thank you @munch. This worked on a fairly complex page. Per your suggestion, I applied overflow: auto to a div that contained 2 sortable lists.
  • danza
    danza over 10 years
    best answer also for me, but please elaborate more! "if you want to prevent browser sniffing" looks unrelated to the question, explain better in order to help more, i tried this just because of positive feedback
  • Bill
    Bill over 10 years
    Thanks very much for the tip :)
  • MonkeyCoder
    MonkeyCoder over 10 years
    In my case I had a horizontal list, so overflow-x: auto and overflow-y: hidden did the trick! Thanks for this @munch!
  • Stanimir Stoyanov
    Stanimir Stoyanov over 9 years
    Combination of position: relative AND overflow:auto did it for me. The layout was quite complex, combining static & relative in the containers. Thank you buddy!
  • Diego Jancic
    Diego Jancic almost 9 years
    Worked for me, but because of other reasons I cannot remove the position:relative. Instead, @rtcherry 's solution worked in my case: stackoverflow.com/a/20225012/72350
  • Ned
    Ned almost 8 years
    Can someone explain why is this solving the problem?
  • Shawn V
    Shawn V over 7 years
    This worked for me as overflow: Auto was not an option for me.
  • user2718671
    user2718671 over 7 years
    It works but unfortunately causing scrollbars. But at least it's the lesser of the two evils ;)