Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#9462 closed bug (duplicate)

Sortover/sortout changes from jquery 1.9 (and inconsistencies)

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

Description

See: http://jsfiddle.net/3X2bL/2/

Status 1 and status 2 record the last sortover or sortout event seen by the first and second lists respectively. If you drag an item from list 1 over list 2 you'll see Status 2 change to "sortover" if you drag the item BELOW list 2 (i.e. not back over list 1) you'll see Status 2 change to "sortout". If you then drag the item back into list 2 you'll not see Status 2 change. If you then drag the item back over list 1 you'll see Status 1 change to "sortover". If you then drag the item back over list 2 you'll see Status 1 change to "sortout" and Status 2 change to "sortover".

Perhaps related to this is in jquery UI 1.9 when you start dragging an item within a sortable list the "sortover" event is called and if you drag the item outside the list the "sortout" event is called. With 1.10 you don't get that initial "sortover" call and if you drag an item below the list it's in (i.e. outside of it, but not over a connected list) the "sortout" event doesn't fire at all. However if you drag that item over a connected list then back to its original list and drag it outside the original list then "sortout" does fire.

I haven't fully worked through the code, but from a quick skim I'm wondering if the first problem is down to the fact that when the list item is dragged outside the sortable "this.currentContainer" is still pointing to the last sortable the item was over.

The trigger for "over" is called after this piece of code:

if(this.currentContainer === this.containers[innermostIndex]) {
    return;
}

So because you've dragged the item back over the container already set in "this.currentContainer" then the "over" event isn't fired.

Now the trigger for "out" is called in this piece of code:

                                // container doesn't intersect. trigger "out" event if necessary
                                if(this.containers[i].containerCache.over) {
                                        this.containers[i]._trigger("out", event, this._uiHash(this));
                                        this.containers[i].containerCache.over = 0;
                                }

Now in the initial state of starting to drag an item from a sortable I don't think "containerCache.over" will have been set for that sortable because no initial over is firing, hence why no "out" gets called when dragging out initially.

This may well be related to #9335 (that talks about dragging draggables over sortables though). It may well also be related to what's described in #9099.

Change History (5)

comment:1 Changed 7 years ago by Skaffen

Looking further through the code I think I'm probably way off on the possible cause - I see the lines I've highlighted are in 1.9 as well. Hopefully someone who knows the sortable internals will be able to figure it out :).

comment:2 Changed 7 years ago by Skaffen

This commit is the one that brought in the "if(this.currentContainer === this.containers[innermostIndex]) {" check... https://github.com/jquery/jquery-ui/commit/07ce771a13504b851bb9f74c8ce8e960d207384a

I just tried switching my test case to 1.10.0 and found that sortover/sortout behave under that version (except for sortover being repeatedly called). In the application where I first spotted the issue if I just delete that line then sortover/sortout behaves, except for sortover being repeatedly called. So perhaps it is a side effect of that fix that the initial "sortover" never gets called and sortout.

As a quick hack I tried changing _mouseStart to initialise this.currentContainer to undefined and leaving it then to the code under _contactContainers (called from _mouseDrag). I also tweaked the two bits of code which call "this.containers[i]._trigger("out", null, this._uiHash(this));" to do this:

                                        if(this.currentContainer === this.containers[i]) {
                                                this.currentContainer = undefined;
                                        }

... and there's also some code in _clear which delayedTriggers a couple of events against this.currentContainer so I wrapped those in a check that this.currentContainer has a value. After doing that the case in my application which was misbehaving before is now behaving. This is probably entirely the wrong approach to fixing the underlying problem (as mentioned before I don't really understand the ui sortable code) but figured I'd mention it anyway :).

comment:3 Changed 7 years ago by Skaffen

Musing on it further I've realised that the fix is probably to leave currentContainer alone but just rejig the checks and use containerCache.over to determine if sortover needs triggering... http://pastebin.com/FE2vrexA

comment:4 Changed 7 years ago by tj.vantoll

Resolution: duplicate
Status: newclosed

Duplicate of #9335.
Hi Skaffen,

Thanks for taking the time to contribute to the jQuery UI project. I'm closing this as a duplicate of #9335 because this behavior also started in 1.10.2 with the commit that both these tickets reference. I'll comment in #9335 that it affects more than just draggables.

If you are interested in submitting your patch please do so as a pull request.

Thanks.

comment:5 Changed 7 years ago by Skaffen

Ok - I'll try my patch out against the test case on #9335 and see about doing a pull request.

Note: See TracTickets for help on using tickets.