Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorGeoSot <geo.sotis@gmail.com>2022-07-28 11:58:28 +0300
committerGitHub <noreply@github.com>2022-07-28 11:58:28 +0300
commitdb86607c088bd307aa21f4b4bd0258262262a4e4 (patch)
tree7acb80965491822be470802088d0ce85d4087e5c /js
parent90c50ab198a4ecffdda6a5ff10fe58cab2c816b2 (diff)
ScrollSpy: make the threshold option configurable (#36750)
* feat(ScrollSpy): make the threshold option configurable
Diffstat (limited to 'js')
-rw-r--r--js/src/scrollspy.js22
-rw-r--r--js/tests/unit/scrollspy.spec.js44
2 files changed, 57 insertions, 9 deletions
diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js
index 102a2e1010..f4d6671013 100644
--- a/js/src/scrollspy.js
+++ b/js/src/scrollspy.js
@@ -40,14 +40,16 @@ const Default = {
offset: null, // TODO: v6 @deprecated, keep it for backwards compatibility reasons
rootMargin: '0px 0px -25%',
smoothScroll: false,
- target: null
+ target: null,
+ threshold: [0.1, 0.5, 1]
}
const DefaultType = {
offset: '(number|null)', // TODO v6 @deprecated, keep it for backwards compatibility reasons
rootMargin: 'string',
smoothScroll: 'boolean',
- target: 'element'
+ target: 'element',
+ threshold: 'array'
}
/**
@@ -110,6 +112,13 @@ class ScrollSpy extends BaseComponent {
// TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case
config.target = getElement(config.target) || document.body
+ // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only
+ config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin
+
+ if (typeof config.threshold === 'string') {
+ config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value))
+ }
+
return config
}
@@ -141,8 +150,8 @@ class ScrollSpy extends BaseComponent {
_getNewObserver() {
const options = {
root: this._rootElement,
- threshold: [0.1, 0.5, 1],
- rootMargin: this._getRootMargin()
+ threshold: this._config.threshold,
+ rootMargin: this._config.rootMargin
}
return new IntersectionObserver(entries => this._observerCallback(entries), options)
@@ -187,11 +196,6 @@ class ScrollSpy extends BaseComponent {
}
}
- // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only
- _getRootMargin() {
- return this._config.offset ? `${this._config.offset}px 0px -30%` : this._config.rootMargin
- }
-
_initializeTargetsAndObservables() {
this._targetLinks = new Map()
this._observableSections = new Map()
diff --git a/js/tests/unit/scrollspy.spec.js b/js/tests/unit/scrollspy.spec.js
index 2bdeb5830c..c7951e6ff1 100644
--- a/js/tests/unit/scrollspy.spec.js
+++ b/js/tests/unit/scrollspy.spec.js
@@ -126,6 +126,50 @@ describe('ScrollSpy', () => {
expect(scrollSpy._rootElement).toBeNull()
})
+ it('should respect threshold option', () => {
+ fixtureEl.innerHTML = [
+ '<ul id="navigation" class="navbar">',
+ ' <a class="nav-link active" id="one-link" href="#">One</a>' +
+ '</ul>',
+ '<div id="content">',
+ ' <div id="one-link">test</div>',
+ '</div>'
+ ].join('')
+
+ const scrollSpy = new ScrollSpy('#content', {
+ target: '#navigation',
+ threshold: [1]
+ })
+
+ expect(scrollSpy._observer.thresholds).toEqual([1])
+ })
+
+ it('should respect threshold option markup', () => {
+ fixtureEl.innerHTML = [
+ '<ul id="navigation" class="navbar">',
+ ' <a class="nav-link active" id="one-link" href="#">One</a>' +
+ '</ul>',
+ '<div id="content" data-bs-threshold="0,0.2,1">',
+ ' <div id="one-link">test</div>',
+ '</div>'
+ ].join('')
+
+ const scrollSpy = new ScrollSpy('#content', {
+ target: '#navigation'
+ })
+
+ // See https://stackoverflow.com/a/45592926
+ const expectToBeCloseToArray = (actual, expected) => {
+ expect(actual.length).toBe(expected.length)
+ for (const x of actual) {
+ const i = actual.indexOf(x)
+ expect(x).withContext(`[${i}]`).toBeCloseTo(expected[i])
+ }
+ }
+
+ expectToBeCloseToArray(scrollSpy._observer.thresholds, [0, 0.2, 1])
+ })
+
it('should not take count to not visible sections', () => {
fixtureEl.innerHTML = [
'<nav id="navigation" class="navbar">',