Opened 3 years ago

Last modified 2 years ago

#9544 open bug

draggable invalid reverts to original mouse position, not true original position - problem with fixed elements

Reported by: alhammer Owned by: alhammer
Priority: minor Milestone: none
Component: ui.draggable Version: 1.10.3
Keywords: Cc:
Blocked by: Blocking:

Description

If you have a fixed parent container, with draggable elements, and you drag them with a helper outside of this parent, and scroll down the page, and have "revert: invalid", it will revert to positions based on the original mouse position of the, and not the actual original position of the original container. Since the container element is fixed, this mean it "moves" down along with the page, but the element reverts to a different position where the fixed element was when "_mouseStart" occurred.

It is easy to fix this, if the helper is a clone just make the originalPosition update based on the original elements offset() instead of original mouse position. If the helper is not a clone, it's not possible to fix in the current way reverted positions are calculated. It only affects fixed/sticky position elements or elements that have changed position via DOM Manipulation/Animations.

I did this:

revert : function(event) {

	$(this).data("ui-draggable").originalPosition = $(this).offset();

	return !event;
}

Change History (6)

comment:1 Changed 3 years ago by alhammer

I created a fiddle: If you notice the blue box (with default behavior) doesn't revert back when scrolled beyond the fixed container. The green box, however, with my fix, reverts to its original position.

http://jsfiddle.net/J2HJD/1/

Also: notice how after trying to scroll down once, and you "revert" and then you start to drag for a second time, it starts way below the page: this shouldn't happen. It thinks the fixed element is not where it actually is. This happens for both elements (even my fix!) Probably has something to do with caching positions as opposed to updating the positions on each mouseStart/mouseStop event.

comment:2 Changed 3 years ago by tj.vantoll

  • Owner set to alhammer
  • Status changed from new to pending

Hi alhammer,

Thanks for taking the time to contribute to the jQuery UI project. This behavior only occurs when you set the appendTo option so that the draggable is outside of the fixed container. In your case you're using appendTo: "body".

Is there any reason you need the helper appended outside of the fixed container?

comment:3 follow-up: Changed 3 years ago by alhammer

  • Status changed from pending to new

Yes. I am working on an HTML5 web game, and on the right column of the website is a fixed UI that contains a users "backpack" with an overflow: auto property. They can then drag items outside of the fixed backpack div to various different places in the game (equip slots to equip armor, trash icon to delete, to your avatar to use potions/etc.).

If I remove the appendTo, I am no longer able to drag the items out of the backpack, as it gets stuck in the "fixed UI".

comment:4 in reply to: ↑ 3 Changed 3 years ago by tj.vantoll

  • Status changed from new to pending

Replying to alhammer:

Yes. I am working on an HTML5 web game, and on the right column of the website is a fixed UI that contains a users "backpack" with an overflow: auto property. They can then drag items outside of the fixed backpack div to various different places in the game (equip slots to equip armor, trash icon to delete, to your avatar to use potions/etc.).

If I remove the appendTo, I am no longer able to drag the items out of the backpack, as it gets stuck in the "fixed UI".

I'm not seeing this. If I remove appendTo on your test case everything seems to work fine http://jsfiddle.net/tj_vantoll/VcY9j/. Am I missing something?

comment:5 Changed 3 years ago by alhammer

  • Status changed from pending to new

http://jsfiddle.net/VcY9j/1/

Sorry, I should have specified more: If you notice, I updated it and added an overflow: scroll; This means the element cannot leave the container, which means the container must be the body. This is necessary because my element is a scrollable fixed width/height panel with items inside of that. Users need to be able to drag items out of it and on to else where.

So the bug is very specific, but it's a use case I can see popping up, especially for UI/HTML5 Games: Draggable elements, in container with "overscroll: auto/scroll", appended to the document, with invalid: revert, does not revert to the fixed container. This is because in the jqueryui code, it "caches" the "original" position, instead of calculating it on the moment of "revert".

comment:6 Changed 2 years ago by mikesherov

  • Status changed from new to open

http://jsfiddle.net/VcY9j/3/ shows the issue.

to repro:

  1. drag blue box out.
  2. while dragging, scroll the page
  3. let go.
  4. observe that it reverts to the offset at the beginning, not the current position.
Note: See TracTickets for help on using tickets.