diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js index 0b1747c8ae..69de7151be 100644 --- a/js/src/scrollspy.js +++ b/js/src/scrollspy.js @@ -208,11 +208,11 @@ class ScrollSpy extends BaseComponent { continue } - const observableSection = SelectorEngine.findOne(anchor.hash, this._element) + const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element) // ensure that the observableSection exists & is visible if (isVisible(observableSection)) { - this._targetLinks.set(anchor.hash, anchor) + this._targetLinks.set(decodeURI(anchor.hash), anchor) this._observableSections.set(anchor.hash, observableSection) } } diff --git a/js/tests/unit/scrollspy.spec.js b/js/tests/unit/scrollspy.spec.js index 070448c17e..ecbd9522c0 100644 --- a/js/tests/unit/scrollspy.spec.js +++ b/js/tests/unit/scrollspy.spec.js @@ -940,5 +940,39 @@ describe('ScrollSpy', () => { }, 100) link.click() }) + + it('should smoothscroll to observable with anchor link that contains a french word as id', done => { + fixtureEl.innerHTML = [ + '', + '
', + '
div 1
', + '
' + ].join('') + + const div = fixtureEl.querySelector('.content') + const link = fixtureEl.querySelector('[href="#présentation"]') + const observable = fixtureEl.querySelector('#présentation') + const clickSpy = getElementScrollSpy(div) + // eslint-disable-next-line no-new + new ScrollSpy(div, { + offset: 1, + smoothScroll: true + }) + + setTimeout(() => { + if (div.scrollTo) { + expect(clickSpy).toHaveBeenCalledWith({ top: observable.offsetTop - div.offsetTop, behavior: 'smooth' }) + } else { + expect(clickSpy).toHaveBeenCalledWith(observable.offsetTop - div.offsetTop) + } + + done() + }, 100) + link.click() + }) }) }) diff --git a/js/tests/visual/scrollspy.html b/js/tests/visual/scrollspy.html index 2daa7abd69..541028478d 100644 --- a/js/tests/visual/scrollspy.html +++ b/js/tests/visual/scrollspy.html @@ -29,6 +29,7 @@
  • One
  • Two
  • Three
  • +
  • Présentation