Skip to main content

Search and Top Navigation

#10062 closed feature (wontfix)

Opened May 23, 2014 07:55PM UTC

Closed May 27, 2014 01:23AM UTC

Fix JQuery Sortable to Operate Harmoniously with Meteor UI (Blaze)

Reported by: sotarules Owned by: sotarules
Priority: minor Milestone: none
Component: ui.sortable Version: 1.10.4
Keywords: Cc:
Blocked by: Blocking:
Description

I’ve spent the last several days trying to track down a problem with JQuery Sortable and Meteor UI (aka Blaze). After significant effort, I have determined that the issue has to do with how JQuery Sortable changes the DOM to facilitate animations, including the helper, the placeholder and the rearrangement of items.

Brief background: Meteor UI really wants to control updates to the DOM. It carries metadata in the DOM about so called DomRanges, which are areas that Meteor dynamically updates. These DomRanges are delimited by so-called marker text nodes. Meteor characterizes a "range" to be updated as the nodes (sibilings) which fall within a range from a given start text node to an end text node. Meteor will automatically supply these marker nodes when the page is refreshed.

Thus, Meteor is very picky about how the elements in the DOM, and their delimiting text nodes are arranged. Because of sensitivity to indiscriminate changes in the DOM, when using a tool like JQuery Sortable, Meteor UI recommendation is to always cancel a drag/drop operation in the update or stop event. The theory is that this would return the DOM to its original state, allowing Meteor to control the DOM.

Unfortunately, this doesn't happen. Because of the way JQuery Sortable handles animations, the dragging of elements can end up "corrupting" the DOM, well, at least from the perspective of Meteor's DomRange metadata. This is not an error in JQuery per se, but rather that Meteor is very sensitive to the precise arrangement of nodes in the DOM.

I am opening this ticket now because I have a fix for this, and I'm paving the way for a pull request. My fix is largely limited to functions "_clear" and "cancel". The idea is to take special care so that when a JQuery Sortable drag/drop operation is cancelled, the node that was being dragged is returned to precisely the same position in the DOM relative to its original siblings. In my own system, this seems to work beautifully. Since the DOM is unchanged, Meteor UI is able to properly perform "differencing" in the DOM to update it correctly in response to state change notifications from MongoDB.

Notwithstanding that the operation is actually cancelled, from the user's perspective, it appears as if the drag/drop operation completely successfully, but the actual DOM updates are being done by Meteor.

This may seem like a small thing, but the who impetus for the Meteor UI (Blaze) release was to pave the way to operate harmoniously with tools like JQuery Sortable. In fact, the Meteor team demonstrates this interoperability, but somehow their demo case "masks" the problem which can occur with more complex cases (i.e., it works only on the "happy path").

Attachments (0)
Change History (4)

Changed May 23, 2014 08:16PM UTC by scottgonzalez comment:1

component: ui.coreui.sortable
owner: → sotarules
status: newpending

If you're canceling the actual sort, what animation are you referring to?

Changed May 23, 2014 08:49PM UTC by sotarules comment:2

status: pendingnew

Scott, the animations are the addition and removal of the helper, the addition and removal of the placeholder, and the rearrangement of the list items as the drag operation is in process. When the drag operation is cancelled, ideally the DOM would be returned to precisely its original state. From the UI perspective, it is. However, the internal arrangement of nodes at a low level (siblings) is changed.

Changed May 23, 2014 11:47PM UTC by sotarules comment:3

OK so this is pull request 1253, hopefully Travis CI will come up green:

https://github.com/jquery/jquery-ui/pull/1253

Changed May 27, 2014 01:23AM UTC by scottgonzalez comment:4

resolution: → wontfix
status: newclosed

See the discussion in the pull request.