Skip to content

Commit

Permalink
undo debounce/throttle changes
Browse files Browse the repository at this point in the history
Relates to: phoenixframework#3097
Relates to: phoenixframework#3033
Relates to: phoenixframework#2318
Relates to: phoenixframework#3076

This reverts the changes made in phoenixframework#3097 and phoenixframework#3033. It adds one small
change to the original behavior to clear the throttle timeout on blur.

For cases where the user wants to get the latest value on blur when
throttle is used, adding a `phx-blur={JS.dispatch("change")}` is the
way to go:

```
<input
  name="tick_frequency"
  type="range"
  min="100"
  max="1000"
  value={@tick_frequency}
  phx-throttle="2000"
  phx-change="change-tick-frequency"
  phx-blur={JS.dispatch("change")}
/>
```
  • Loading branch information
SteffenDE committed Feb 10, 2024
1 parent 767b40e commit 3e452ef
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 51 deletions.
38 changes: 8 additions & 30 deletions assets/js/phoenix_live_view/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,27 +221,7 @@ let DOM = {

default:
let timeout = parseInt(value)
let trigger = (blur) => {
const throttled = this.private(el, THROTTLED)
if(blur){
// if the input is blurred, we need to cancel the next throttle timeout
// therefore we store the timer id in the THROTTLED private attribute
if(throttle && throttled !== null){
clearTimeout(throttled.timeout)
this.deletePrivate(el, THROTTLED)
}
// on debounce we just trigger the callback
return callback()
}
// no blur, remove the throttle attribute if we are in throttle mode
if(throttle){
this.deletePrivate(el, THROTTLED)
// run callback if there was a throttled event
if(throttled && throttled.updated) callback()
} else {
callback()
}
}
let trigger = () => throttle ? this.deletePrivate(el, THROTTLED) : callback()
let currentCycle = this.incCycle(el, DEBOUNCE_TRIGGER, trigger)
if(isNaN(timeout)){ return logError(`invalid throttle/debounce value: ${value}`) }
if(throttle){
Expand All @@ -253,18 +233,13 @@ let DOM = {
}

if(!newKeyDown && this.private(el, THROTTLED)){
this.updatePrivate(el, THROTTLED, {}, (existing) => ({...existing, updated: true}))
return false
} else {
callback()
// store the throttle timer id in the THROTTLED private attribute,
// so that we can cancel it if the input is blurred
// otherwise, when new events happen after blur, but before the old
// timeout is triggered, we would actually trigger the callback multiple times
const t = setTimeout(() => {
if(asyncFilter()){ this.triggerCycle(el, DEBOUNCE_TRIGGER) }
}, timeout)
this.putPrivate(el, THROTTLED, {timer: t})
this.putPrivate(el, THROTTLED, t)
}
} else {
setTimeout(() => {
Expand All @@ -283,17 +258,20 @@ let DOM = {
})
}
if(this.once(el, "bind-debounce")){
el.addEventListener("blur", () => this.triggerCycle(el, DEBOUNCE_TRIGGER, null, [true]))
el.addEventListener("blur", () => {
clearTimeout(this.private(el, THROTTLED))
this.triggerCycle(el, DEBOUNCE_TRIGGER)
})
}
}
},

triggerCycle(el, key, currentCycle, params=[]){
triggerCycle(el, key, currentCycle){
let [cycle, trigger] = this.private(el, key)
if(!currentCycle){ currentCycle = cycle }
if(currentCycle === cycle){
this.incCycle(el, key)
trigger(...params)
trigger()
}
},

Expand Down
34 changes: 13 additions & 21 deletions assets/test/debounce_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,21 +169,16 @@ describe("throttle", function (){
DOM.dispatchEvent(el, "click")
expect(calls).toBe(1)
expect(el.innerText).toBe("now:1")
after(100, () => {
after(250, () => {
expect(calls).toBe(1)
// now wait another 150ms (after 100ms, so 200 total we expect 2 events)
after(150, () => {
expect(el.innerText).toBe("now:1")
DOM.dispatchEvent(el, "click")
DOM.dispatchEvent(el, "click")
DOM.dispatchEvent(el, "click")
after(250, () => {
expect(calls).toBe(2)
expect(el.innerText).toBe("now:2")
DOM.dispatchEvent(el, "click")
DOM.dispatchEvent(el, "click")
DOM.dispatchEvent(el, "click")
// the first and last event are processed
after(250, () => {
expect(calls).toBe(4)
expect(el.innerText).toBe("now:4")
done()
})
done()
})
})
})
Expand Down Expand Up @@ -279,16 +274,13 @@ describe("throttle keydown", function (){
el.dispatchEvent(pressA)

expect(keyPresses["a"]).toBe(1)
after(100, () => {
after(250, () => {
expect(keyPresses["a"]).toBe(1)
after(150, () => {
expect(keyPresses["a"]).toBe(2)
el.dispatchEvent(pressA)
el.dispatchEvent(pressA)
el.dispatchEvent(pressA)
expect(keyPresses["a"]).toBe(3)
done()
})
el.dispatchEvent(pressA)
el.dispatchEvent(pressA)
el.dispatchEvent(pressA)
expect(keyPresses["a"]).toBe(2)
done()
})
})

Expand Down

0 comments on commit 3e452ef

Please sign in to comment.