mirror of
https://github.com/tabler/tabler.git
synced 2026-10-12 05:06:55 +04:00
Fix complete.bs.countup firing twice when update() runs before the element is in view (#3193)
This commit is contained in:
1 parent
e2da442007
commit
77480290dc
3 files changed
+62
-7
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tabler/core": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixed CountUp firing `complete.bs.countup` twice when `update()` ran before it scrolled into view.
|
||||||
+15
-7
@@ -147,6 +147,7 @@ class CountUp extends BaseComponent {
|
|||||||
_elapsed = 0
|
_elapsed = 0
|
||||||
_running = false
|
_running = false
|
||||||
_paused = false
|
_paused = false
|
||||||
|
_started = false
|
||||||
|
|
||||||
constructor(element: ElementSelector, config?: ComponentConfigInput) {
|
constructor(element: ElementSelector, config?: ComponentConfigInput) {
|
||||||
super(element, config)
|
super(element, config)
|
||||||
@@ -175,13 +176,7 @@ class CountUp extends BaseComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this._observer = new IntersectionObserver((entries) => {
|
this._observer = new IntersectionObserver((entries) => this._observerCallback(entries))
|
||||||
if (entries.some((entry) => entry.isIntersecting)) {
|
|
||||||
this._observer?.disconnect()
|
|
||||||
this._observer = null
|
|
||||||
this.start()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this._observer.observe(this._element)
|
this._observer.observe(this._element)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,8 +248,21 @@ class CountUp extends BaseComponent {
|
|||||||
return super._mergeConfigObj({ ...coerceOptions(dataOptions), ...config }, element)
|
return super._mergeConfigObj({ ...coerceOptions(dataOptions), ...config }, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_observerCallback(entries: IntersectionObserverEntry[]): void {
|
||||||
|
if (entries.some((entry) => entry.isIntersecting)) {
|
||||||
|
this._observer?.disconnect()
|
||||||
|
this._observer = null
|
||||||
|
|
||||||
|
// update() may have already animated it while it was off screen.
|
||||||
|
if (!this._started) {
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_animate(from: number, to: number): void {
|
_animate(from: number, to: number): void {
|
||||||
this._stop()
|
this._stop()
|
||||||
|
this._started = true
|
||||||
|
|
||||||
// Users who asked for less motion get the final number at once.
|
// Users who asked for less motion get the final number at once.
|
||||||
if (from === to || this._config.duration <= 0 || reducedMotion()) {
|
if (from === to || this._config.duration <= 0 || reducedMotion()) {
|
||||||
|
|||||||
@@ -113,6 +113,48 @@ describe('CountUp', () => {
|
|||||||
|
|
||||||
expect(element().textContent).toBe('77')
|
expect(element().textContent).toBe('77')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not fire complete.bs.countup a second time when the element scrolls into view after update()', () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
element().addEventListener('complete.bs.countup', spy)
|
||||||
|
|
||||||
|
const instance = new CountUp(element(), { duration: 0 })
|
||||||
|
instance.update(77)
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
instance._observerCallback([{ isIntersecting: true } as unknown as IntersectionObserverEntry])
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(element().textContent).toBe('77')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not fire complete.bs.countup twice when update() ran off screen and it then really scrolls into view', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const off = document.createElement('h1')
|
||||||
|
off.dataset.countup = '{"duration":0.1}'
|
||||||
|
off.textContent = '500'
|
||||||
|
off.style.position = 'absolute'
|
||||||
|
off.style.top = '-10000px'
|
||||||
|
off.style.left = '-10000px'
|
||||||
|
document.body.append(off)
|
||||||
|
off.addEventListener('complete.bs.countup', spy)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const instance = new CountUp(off)
|
||||||
|
instance.update(77)
|
||||||
|
await wait(300)
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
off.style.top = '0px'
|
||||||
|
off.style.left = '0px'
|
||||||
|
await wait(500)
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(off.textContent).toBe('77')
|
||||||
|
} finally {
|
||||||
|
off.remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('data-tblr-countup', () => {
|
describe('data-tblr-countup', () => {
|
||||||
|
|||||||
Reference in new issue
Block a user