#14820 closed bug (invalid)
scroll event fires after scrollTop animation is complete
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | undecided | Milestone: | None |
Component: | unfiled | Version: | 2.1.0 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
Animations that animate the scrollTop
property trigger scroll events, however it appears that an additional scroll
event is triggered after the animation's complete
callback has been called.
I'm experiencing this in Chrome, Firefox, and IE10 on Windows 7.
Change History (10)
comment:1 follow-ups: 2 4 Changed 9 years ago by
comment:2 follow-up: 3 Changed 9 years ago by
Replying to [email protected]…: Argh, nevermind. I was of course forgetting the most important thing: setting animatingScroll = false in the complete callback. Then I see the exact same behavior, see http://jsfiddle.net/89pnX/. PS: We're on jQuery 1.7.2 so this problem seems to have been around for a while.
comment:3 Changed 9 years ago by
Replying to anonymous: Aaaaand here is the correct URL, sorry for the mess: http://jsfiddle.net/89pnX/3/
A possible workaround seems to be to delay the execution of the complete callback by a magic number: http://jsfiddle.net/89pnX/4/
comment:4 Changed 9 years ago by
Replying to [email protected]…:
Does animate() really return a deferred? If I try your example with a self-created Deferred and the 'complete' callback, it seems to work:
function animate(){ var deferred = new jQuery.Deferred(); $('html, body').animate({ scrollTop: 500 }, { complete : function() { deferred.resolve(); }, duration : 3000 }); return deferred; }
animate()
doesn't return a deferred, promise()
on a jQuery collection returns a deferred that resolves when all 'fx'
queues have completed. The provided example code resolves when the first 'fx'
queue has completed.
comment:5 Changed 9 years ago by
It appears as though this isn't actually a bug with jQuery, and instead seems to be a quirk of scroll events in the browser. See this related question on StackOverflow for additional details.
Assigning a new scroll value does not immediately queue a scroll event. Instead, there can be an unknown amount of delay between setting scrollTop
and the scroll
event firing (http://jsfiddle.net/jSBn2/). Sometimes the scroll
event will be immediately queued in the event loop, sometimes not.
This delay is what's causing the odd behavior of the scroll
event after the complete
callback.
comment:6 follow-up: 7 Changed 9 years ago by
I thought this was what happened: When you set scrollTop
it queues an event to occur once the thread completes. On the final step of the animation the Deferred resolves synchronously and immediately calls all the callbacks. Then the thread completes and the event fires.
comment:7 Changed 9 years ago by
Replying to dmethvin:
I thought this was what happened: When you set
scrollTop
it queues an event to occur once the thread completes. On the final step of the animation the Deferred resolves synchronously and immediately calls all the callbacks. Then the thread completes and the event fires.
Promises aren't supposed to resolve synchronously, although I'm aware that jQuery's deferreds deviate from the Promises/A+ spec. Even if that were the case, including a delay(0)
call into the chain before the promise should fix the issue, which it doesn't.
comment:8 follow-up: 10 Changed 9 years ago by
Owner: | set to [email protected]… |
---|---|
Status: | new → pending |
Oh, I see you were animating two things and then using the per-element callback. That's not going to work consistently anyway. See the discussion here: https://github.com/jquery/api.jquery.com/issues/417
Does that docs issue answer your question?
comment:9 Changed 9 years ago by
Resolution: | → invalid |
---|---|
Status: | pending → closed |
Because we get so many tickets, we often need to return them to the initial reporter for more information. If that person does not reply within 14 days, the ticket will automatically be closed, and that has happened in this case. If you still are interested in pursuing this issue, feel free to add a comment with the requested information and we will be happy to reopen the ticket if it is still valid. Thanks!
comment:10 Changed 9 years ago by
Replying to dmethvin:
Oh, I see you were animating two things and then using the per-element callback.
I'm not sure I follow. I animated two things and set up a promise to fire once when both fx queues were clear.
voelzmo's snippet uses the per-animation callback, maybe that's what you were referring to.
Either way, I found that the scroll
event doesn't fire synchronously after scrollTop
is changed, which is what is causing the erratic behavior. As it's a native browser behavior, it's not a bug in jQuery, so this ticket can remain closed.
Does animate() really return a deferred? If I try your example with a self-created Deferred and the 'complete' callback, it seems to work: