Skip to content

Commit

Permalink
feat: throttle leading options, closes #113
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume Chau committed Oct 20, 2019
1 parent f8f0b8a commit ff96e4a
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 2 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,19 @@ You can use the `throttle` options (in ms) specifying minimal state duration aft
}">
```

You can also pass a `leading` option to trigger the callback the first time when the visibility changes without waiting for the throttle delay.
I can either be `visible`, `hidden` or `both`.

```html
<div v-observe-visibility="{
callback: visibilityChanged,
throttle: 300,
throttleOptions: {
leading: 'visible',
},
}">
```

## Passing custom arguments

You can add custom argument by using an intermediate function:
Expand Down
17 changes: 17 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,26 @@
<div class="wrapper">
<input id="is-visible" type="checkbox" v-model="isVisible" disabled>
<label for="is-visible">Is visible?</label>

<input id="disabled" type="checkbox" v-model="disabled">
<label for="disabled">Disable</label>

<span class="separator"></span>

<button @click="show = !show">Toggle</button>

<span class="separator"></span>

<label for="throttle">Throttle</label>
<input id="throttle" type="number" v-model="throttle" min="0" step="100">

<input id="throttle-leading-visible" type="checkbox" v-model="leadingVisible">
<label for="throttle-leading-visible">Leading (Visible)</label>
<input id="throttle-leading-hidden" type="checkbox" v-model="leadingHidden">
<label for="throttle-leading-hidden">Leading (Hidden)</label>

<span class="separator"></span>

<label for="threshold">Threshold</label>
<span class="number">{{ threshold }}</span>
<input type="range" v-model="threshold" min="0" max="1" step="0.01">
Expand All @@ -109,6 +121,9 @@
v-observe-visibility="disabled ? false : {
callback: visibilityChanged,
throttle,
throttleOptions: {
leading: leadingVisible && leadingHidden ? 'both' : leadingVisible ? 'visible' : leadingHidden ? 'hidden' : false,
},
intersection: {
threshold,
},
Expand All @@ -131,6 +146,8 @@
show: true,
isVisible: true,
throttle: 0,
leadingVisible: false,
leadingHidden: false,
threshold: 0,
count: 1,
once: false,
Expand Down
7 changes: 6 additions & 1 deletion src/directives/observe-visibility.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ class VisibilityState {
}
// Throttle
if (this.callback && this.options.throttle) {
this.callback = throttle(this.callback, this.options.throttle)
const { leading } = this.options.throttleOptions
this.callback = throttle(this.callback, this.options.throttle, {
leading: (state) => {
return leading === 'both' || (leading === 'visible' && state) || (leading === 'hidden' && !state)
},
})
}

this.oldResult = undefined
Expand Down
10 changes: 9 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,20 @@ export function processOptions (value) {
return options
}

export function throttle (callback, delay) {
export function throttle (callback, delay, options = {}) {
let timeout
let lastState
let currentArgs
const throttled = (state, ...args) => {
currentArgs = args
if (timeout && state === lastState) return
let leading = options.leading
if (typeof leading === 'function') {
leading = leading(state, lastState)
}
if ((!timeout || (state !== lastState)) && leading) {
callback(state, ...currentArgs)
}
lastState = state
clearTimeout(timeout)
timeout = setTimeout(() => {
Expand All @@ -28,6 +35,7 @@ export function throttle (callback, delay) {
}
throttled._clear = () => {
clearTimeout(timeout)
timeout = null
}
return throttled
}
Expand Down

0 comments on commit ff96e4a

Please # to comment.