-
-
Notifications
You must be signed in to change notification settings - Fork 79k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle multiple zero-offset Scrollspy elements. #15593
Handle multiple zero-offset Scrollspy elements. #15593
Conversation
Tests passed. Automated cross-browser testing via Sauce Labs and Travis CI shows that the JavaScript changes in this pull request are: CONFIRMED Commit: 22f9e30e990a3d09e3cc585c5ddd5a38729ef1a6 (Please note that this is a fully automated comment.) |
👍 I ran into this issue yesterday and spent about 5-6 hours trying to debug it. It was really challenging because everything was set up like the doc suggests. I narrowed down the culprit to be using It took @neoeno an hour reading the source code to figure out the jankiness was happening. It'd be really great to have this fix be incorporated into bootstrap. |
} | ||
|
||
$.when(testElementsAreActiveAfterScroll()) | ||
.then(function () { return testElementsAreActiveAfterScroll() }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this and the next line should be indented
Agreed on all counts. Commits added. Can squish before merge (— or not, not sure which is the preferred practice here!) ( |
@neoeno: yeah, fetch, rebase and squash into one. |
@XhmikosR what's the purpose of fetching before the rebase? Sorry to bring this PR off topic I'm just curious about that. Thanks 😃 |
@kkirsche: that's the only way you can bring everything on par with upstream/master. |
Ah. I always rebase with |
For rebasing one branch against another, I've always done |
Done. I also updated some of the tests to conform to a newer style that had been brought in by @cvrebert — think I did it right, but I'm new to QUnit so some review would be great! |
var scrollHeight = $content.scrollTop() + 10 | ||
var done = assert.async() | ||
$content.one('scroll', function () { | ||
ok($('#li-1').hasClass('active'), 'element' + element) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These need to be assert.ok(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done!
@cvrebert Thanks for the comments — I think I understand assert a little better now. |
Tests passed. Automated cross-browser testing via Sauce Labs and Travis CI shows that the JavaScript changes in this pull request are: CONFIRMED Commit: a9cbfc08c86341a732a758260927ec424e4af5ab (Please note that this is a fully automated comment.) |
@hnrch02 LGTY? |
|
||
$.when(testElementsAreActiveAfterScroll()) | ||
.then(testElementsAreActiveAfterScroll) | ||
.then(testElementsAreActiveAfterScroll) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this works as you intended - QUnit shows that only two of the planned six assertions are actually made.
If I make this test work like I think you intended (https://gist.github.com/hnrch02/434c11d59153663b999c), the fourth assertion actually fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi! I'm having a little confusion over this.
The first confusion is that the test in your gist only runs the assertions once. Since on the first pass ++times == 1
and the second pass ++times == 2
, which triggers done()
before doing an iteration.
When I change the condition to == 4
then the test iterates three times, as the one in this commit does. However, all the assertions pass as expected — I can't seem to reproduce the failure you mention.
I've made a new branch with both tests in, and some hacky logging to show the value of the assertion and the scrollTop
. Both tests seem to generate the same output. Here's the branch.
Am I missing something?
I actually think your test, using recursion, looks a fair bit cleaner than this approach using promises. Perhaps at the expense of some readability (for me), but I'm definitely open to either option. I just copied and rewrote the "should add the active class correctly when there are nested elements at 0 scroll offset".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I stand corrected, silly mistake on my end - sorry. The test works fine, would appreciate it though if you replaced this one with the new one from your second branch without the debug code. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
Tests passed. Automated cross-browser testing via Sauce Labs and Travis CI shows that the JavaScript changes in this pull request are: CONFIRMED Commit: 87b0b373d5a444812924188a241390e6396874bc (Please note that this is a fully automated comment.) |
|
||
var $content = $(contentHtml) | ||
.appendTo('#qunit-fixture') | ||
.bootstrapScrollspy({ offset: 0, target: '.navbar' }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For precision, let's use an ID selector here instead of a class selector.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actioned.
When the first two elements in a scrollspy content block have a document offset of zero (i.e. they're hard against the top of the page), Scrollspy would switch between them on every scroll event. This could happen, for example, in a system of nested sections: ``` <section id="animals"> <section id="dogs"> Content </section> </section> ``` This ocurred because Scrollspy's check to see if it's at the end of the array of sections uses `!arr[index]`. This misses the case where `arr[index]` does exist and is zero. This commit explicitly checks the array bounds.
Tests passed. Automated cross-browser testing via Sauce Labs and Travis CI shows that the JavaScript changes in this pull request are: CONFIRMED Commit: a1aa0f8 (Please note that this is a fully automated comment.) |
…ollspy_elements Handle multiple zero-offset Scrollspy elements.
@neoeno Thank you! |
My pleasure! ✨ |
When the first two elements tracked by Scrollspy have an
offset.top
of 0, Scrollspy will flip between activating their respective nav events on every scroll event. This causes a visual 'flicker', and heavily degrades scroll performance.Examples:
Minimal example.
Example with nested sections.
I saw this happen in a system of nested sections positioned hard against the top of the document, e.g.
The bug is that Scrollspy's check to see if it's at the end of the array of sections uses
!arr[index + 1]
. This misses the case wherearr[index + 1]
does exist and is zero.This commit explicitly checks the array bounds. A unit test is included, but I'm not familiar with bootstrap's testing approach so feedback is appreciated.
(Thanks go to @theroux and @tnguyen14!)