Skip to main content

Search and Top Navigation

#9635 open bug ()

Opened October 28, 2013 10:43AM UTC

Last modified October 31, 2016 08:23PM UTC

Sortable: Item flying off screen with revert=true

Reported by: the-razer Owned by:
Priority: minor Milestone: none
Component: ui.sortable Version: 1.10.3
Keywords: Cc:
Blocked by: Blocking:
Description

Hi,

When you're dropping a list item on a scrolled page, the item flies off screen by the distance you scrolled down and then returns to the placeholder. Here's a showcase: http://jsfiddle.net/DZ6x4/

I have this bug at least with current Firefox and IE. I use jQuery 1.9.1 and jQuery-UI 1.10.3, the JSFiddle has different versions but it's the same problem (I was not able to include it otherwise, sorry).

It seems that changing in ''jquery.ui.sortable.js'':

if ( !axis || axis === "y" ) {
    animation.top = cur.top - this.offset.parent.top - this.margins.top; // + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
}

to:

if ( !axis || axis === "y" ) {
    animation.top = cur.top - this.offset.parent.top - this.margins.top;
}

solves this for me, but I have no clue if that's really the problem or if I'm using it the wrong way.

Attachments (0)
Change History (5)

Changed October 28, 2013 10:46AM UTC by the-razer comment:1

_comment0: the original code is of course: \ {{{ \ if ( !axis || axis === "y" ) { \ animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); \ } \ }}} \ Sorry1382962381263275

the original code is of course:

if ( !axis || axis === "y" ) {
    animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
}

and I seem to have messed up JSFiddle. Here's the correct link now: http://jsfiddle.net/DZ6x4/6/

That's my first time reporting a bug, so please bear with me

Changed October 28, 2013 01:01PM UTC by tj.vantoll comment:2

status: newopen

Thanks the-razer.

You don't need a placeholder to duplicate the issue - http://jsfiddle.net/NnQAm/. This is possibly a duplicate of #5039.

Changed July 25, 2014 04:45PM UTC by colin.mccabe comment:3

I too see this issue although I have a complex situation where a sortable ul element is inside an absolutely positioned, scrollable parent that is not the document body. This situation has been discussed at length in many places and none of the solutions provided have worked for me. Upon deeper inspection it turns out to be variable initialization issue in ui.sortable. Below shows lines 12210-12222 from the combined jquery-ui-1.10.4.js library.

		$.extend(this.offset, {
			click: { //Where the click happened, relative to the element
				left: event.pageX - this.offset.left,
				top: event.pageY - this.offset.top
			},
			parent: this._getParentOffset(),
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
		});

		// Only after we got the offset, we can change the helper's position to absolute
		// TODO: Still need to figure out a way to make relative sorting possible
		this.helper.css("position", "absolute");
		this.cssPosition = this.helper.css("position");

_getParentOffset() is used to calculate this.offset.parent.top which is critical to correctly (vertically) positioning an item being dragged. The _getParentOffset in turn used relies on this.cssPosition to be "absolute" in this situation. Unfortunately this.cssPosition is not initialized until after the call to _getParentOffset so is.offset.parent.top is calculated incorrectly the first time an item is dragged. I hope this provides insight into the issue. I will also work on providing a fiddle as an exemplar.

Changed April 22, 2016 08:52AM UTC by marioheuvel comment:4

After this many months, this bug still appears in Internet Explorer 11.

http://pastebin.com/LRsyma59

Would be nice if a permanent fix was available. :(

Changed October 31, 2016 08:23PM UTC by Snoturky comment:5

Replying to [comment:3 colin.mccabe]:

I too see this issue although I have a complex situation where a sortable ul element is inside an absolutely positioned, scrollable parent that is not the document body. This situation has been discussed at length in many places and none of the solutions provided have worked for me. Upon deeper inspection it turns out to be variable initialization issue in ui.sortable. Below shows lines 12210-12222 from the combined jquery-ui-1.10.4.js library.
> 		$.extend(this.offset, {
> 			click: { //Where the click happened, relative to the element
> 				left: event.pageX - this.offset.left,
> 				top: event.pageY - this.offset.top
> 			},
> 			parent: this._getParentOffset(),
> 			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
> 		});
> 
> 		// Only after we got the offset, we can change the helper's position to absolute
> 		// TODO: Still need to figure out a way to make relative sorting possible
> 		this.helper.css("position", "absolute");
> 		this.cssPosition = this.helper.css("position");
> 
_getParentOffset() is used to calculate this.offset.parent.top which is critical to correctly (vertically) positioning an item being dragged. The _getParentOffset in turn used relies on this.cssPosition to be "absolute" in this situation. Unfortunately this.cssPosition is not initialized until after the call to _getParentOffset so is.offset.parent.top is calculated incorrectly the first time an item is dragged. I hope this provides insight into the issue. I will also work on providing a fiddle as an exemplar.


This is exactly what I have found. The first time you drag an element after sortable is constructed, the positioning is wrong. But after the first time it works because

cssPosition = 'absolute'
.

There is a simple work-around. set cssPosition to 'absolute' right after construction, before the user has a chance to drag an element.

$('.my-sortable').sortable({
  /* options to construct the sortable */
});
$('.my-sortable').sortable('instance').cssPosition = 'absolute';

Tested on jQuery UI Sortable 1.12.1