Skip to content

Instantly share code, notes, and snippets.

@jdanyow
Last active October 14, 2017 12:57
Show Gist options
  • Save jdanyow/74fb883f778d60583ab7cb6806d43215 to your computer and use it in GitHub Desktop.
Save jdanyow/74fb883f778d60583ab7cb6806d43215 to your computer and use it in GitHub Desktop.
Aurelia Gist
<template>
<require from="./debounce2"></require>
<style>
label {
display: block;
margin: 16px 0;
}
input {
display: block;
}
</style>
<label>
two-way
<input value.two-way="twoWay & debounce2:1000">
model: ${twoWay}
</label>
<label>
from-view
<input value.from-view="fromView & debounce2:1000">
model: ${fromView}
</label>
<label>
to-view
<input disabled value.to-view="toView & debounce2:2000">
model: ${toView}
</label>
<label>
trigger
<input ref="triggerInput" disabled input.trigger="trigger = trigger + 1 & debounce2:2000">
model: ${trigger}
</label>
</template>
export class App {
twoWay = 'two-way';
fromView = 'from-view';
toView = 'to-view';
trigger = 0;
constructor() {
const interval = setInterval(() => {
this.toView += 'x';
this.triggerInput.dispatchEvent(new CustomEvent('input'));
}, 333);
setTimeout(() => clearInterval(interval), 3000);
}
}
import {bindingMode} from 'aurelia-binding';
// todo: import from binding
const targetContext = 'Binding:target';
const sourceContext = 'Binding:source';
const {twoWay, fromView} = bindingMode;
const unset = {};
function debounceCallSource(event) {
const state = this.debounceState;
clearTimeout(state.timeoutId);
state.timeoutId = setTimeout(() => this.debouncedMethod(event), state.delay);
}
function debounceCall(context, newValue, oldValue) {
const state = this.debounceState;
clearTimeout(state.timeoutId);
if (context !== state.callContextToDebounce) {
state.oldValue = unset;
this.debouncedMethod(context, newValue, oldValue);
return;
}
if (state.oldValue === unset) {
state.oldValue = oldValue;
}
state.timeoutId = setTimeout(() => {
const oldValue = state.oldValue;
state.oldValue = unset;
console.log('firing--', newValue, oldValue);
this.debouncedMethod(context, newValue, oldValue);
}, state.delay);
}
export class Debounce2BindingBehavior {
bind(binding, source, delay = 200) {
const isCallSource = binding.callSource !== undefined;
const methodToDebounce = isCallSource ? 'callSource' : 'call';
const debouncer = isCallSource ? debounceCallSource : debounceCall;
const mode = binding.mode;
const callContextToDebounce = mode === bindingMode.twoWay || mode === bindingMode.fromView ? targetContext : sourceContext;
// stash the original method and it's name.
// note: a generic name like "originalMethod" is not used to avoid collisions
// with other binding behavior types.
binding.debouncedMethod = binding[methodToDebounce];
binding.debouncedMethod.originalName = methodToDebounce;
// replace the original method with the debouncing version.
binding[methodToDebounce] = debouncer;
// create the debounce state.
binding.debounceState = {
callContextToDebounce,
delay,
timeoutId: 0,
oldValue: unset
};
}
unbind(binding, source) {
// restore the state of the binding.
const methodToRestore = binding.debouncedMethod.originalName;
binding[methodToRestore] = binding.debouncedMethod;
binding.debouncedMethod = null;
clearTimeout(binding.debounceState.timeoutId);
binding.debounceState = null;
}
}
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app>
<h1>Loading...</h1>
<script src="https://jdanyow.github.io/rjs-bundle/node_modules/requirejs/require.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/config.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/aurelia.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/babel.js"></script>
<script>
require(['aurelia-bootstrapper']);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment