UNPKG

2.08 kBPlain TextView Raw
1import {bindingMode, bindingBehavior} from 'aurelia-binding';
2
3function throttle(newValue) {
4 let state = this.throttleState;
5 let elapsed = +new Date() - state.last;
6 if (elapsed >= state.delay) {
7 clearTimeout(state.timeoutId);
8 state.timeoutId = null;
9 state.last = +new Date();
10 this.throttledMethod(newValue);
11 return;
12 }
13 state.newValue = newValue;
14 if (state.timeoutId === null) {
15 state.timeoutId = setTimeout(
16 () => {
17 state.timeoutId = null;
18 state.last = +new Date();
19 this.throttledMethod(state.newValue);
20 },
21 state.delay - elapsed);
22 }
23}
24
25@bindingBehavior('throttle')
26export class ThrottleBindingBehavior {
27 bind(binding, source, delay = 200) {
28 // determine which method to throttle.
29 let methodToThrottle = 'updateTarget'; // one-way bindings or interpolation bindings
30 if (binding.callSource) {
31 methodToThrottle = 'callSource'; // listener and call bindings
32 } else if (binding.updateSource && binding.mode === bindingMode.twoWay) {
33 methodToThrottle = 'updateSource'; // two-way bindings
34 }
35
36 // stash the original method and it's name.
37 // note: a generic name like "originalMethod" is not used to avoid collisions
38 // with other binding behavior types.
39 binding.throttledMethod = binding[methodToThrottle];
40 binding.throttledMethod.originalName = methodToThrottle;
41
42 // replace the original method with the throttling version.
43 binding[methodToThrottle] = throttle;
44
45 // create the throttle state.
46 binding.throttleState = {
47 delay: delay,
48 last: 0,
49 timeoutId: null
50 };
51 }
52
53 // eslint-disable-next-line @typescript-eslint/no-unused-vars
54 unbind(binding, source) {
55 // restore the state of the binding.
56 let methodToRestore = binding.throttledMethod.originalName;
57 binding[methodToRestore] = binding.throttledMethod;
58 binding.throttledMethod = null;
59 clearTimeout(binding.throttleState.timeoutId);
60 binding.throttleState = null;
61 }
62}