Opened 9 years ago

Last modified 6 years ago

#9635 open bug

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.

Change History (5)

comment:1 Changed 9 years ago by the-razer

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

Last edited 9 years ago by the-razer (previous) (diff)

comment:2 Changed 9 years ago by tj.vantoll

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.

comment:3 Changed 9 years ago by 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.

comment:4 Changed 7 years ago by marioheuvel

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. :(

comment:5 in reply to:  3 Changed 6 years ago by Tom

Replying to 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

Note: See TracTickets for help on using tickets.