'use strict';
/**
* Creates a debounced function that delays invoking `func` until after `wait`
* milliseconds have elapsed since the last time the debounced function was
* invoked. The debounced function comes with a `cancel` method to cancel
* delayed `func` invocations and a `flush` method to immediately invoke them.
* Provide `options` to indicate whether `func` should be invoked on the
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
* with the last arguments provided to the debounced function. Subsequent
* calls to the debounced function return the result of the last `func`
* invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the debounced function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.debounce` and `_.throttle`.
*
* from lodash - https://github.com/lodash/lodash/blob/4.16.2/lodash.js#L10218
*/
function debounce(func, wait, options) {
\t if (!options) options = {};
\t let lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0,
\t \t leading = false,
\t \t maxing = false,
\t \t trailing = true;
\t wait = wait || 0;
\t leading = !!options.leading;
\t maxing = 'maxWait' in options;
\t maxWait = maxing ? Math.max(options.maxWait || 0, wait) : maxWait;
\t trailing = 'trailing' in options ? !!options.trailing : trailing;
\t function invokeFunc(time) {
\t \t const args = lastArgs,
\t \t \t thisArg = lastThis;
\t \t lastArgs = lastThis = undefined;
\t \t lastInvokeTime = time;
\t \t result = func.apply(thisArg, args);
\t \t return result;
\t }
\t function leadingEdge(time) {
\t \t // Reset any `maxWait` timer.
\t \t lastInvokeTime = time;
\t \t // Start the timer for the trailing edge.
\t \t timerId = setTimeout(timerExpired, wait);
\t \t // Invoke the leading edge.
\t \t return leading ? invokeFunc(time) : result;
\t }
\t function remainingWait(time) {
\t \t const timeSinceLastCall = time - lastCallTime,
\t \t \t timeSinceLastInvoke = time - lastInvokeTime,
\t \t \t result = wait - timeSinceLastCall;
\t \t return maxing ? Math.min(result, maxWait - timeSinceLastInvoke) : result;
\t }
\t function shouldInvoke(time) {
\t \t const timeSinceLastCall = time - lastCallTime,
\t \t \t timeSinceLastInvoke = time - lastInvokeTime;
\t \t // Either this is the first call, activity has stopped and we're at the
\t \t // trailing edge, the system time has gone backwards and we're treating
\t \t // it as the trailing edge, or we've hit the `maxWait` limit.
\t \t return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
\t \t \t (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
\t }
\t function timerExpired() {
\t \t const time = Date.now();
\t \t if (shouldInvoke(time)) {
\t \t \t return trailingEdge(time);
\t \t }
\t \t // Restart the timer.
\t \t timerId = setTimeout(timerExpired, remainingWait(time));
\t }
\t function trailingEdge(time) {
\t \t timerId = undefined;
\t \t // Only invoke if we have `lastArgs` which means `func` has been
\t \t // debounced at least once.
\t \t if (trailing && lastArgs) {
\t \t \t return invokeFunc(time);
\t \t }
\t \t lastArgs = lastThis = undefined;
\t \t return result;
\t }
\t function cancel() {
\t \t if (timerId !== undefined) {
\t \t \t clearTimeout(timerId);
\t \t }
\t \t lastInvokeTime = 0;
\t \t lastArgs = lastCallTime = lastThis = timerId = undefined;
\t }
\t function flush() {
\t \t return timerId === undefined ? result : trailingEdge(Date.now());
\t }
\t function debounced(...args) {
\t \t const time = Date.now(),
\t \t \t isInvoking = shouldInvoke(time);
\t \t lastArgs = args;
\t \t lastThis = this;
\t \t lastCallTime = time;
\t \t if (isInvoking) {
\t \t \t if (timerId === undefined) {
\t \t \t \t return leadingEdge(lastCallTime);
\t \t \t }
\t \t \t if (maxing) {
\t \t \t \t // Handle invocations in a tight loop.
\t \t \t \t timerId = setTimeout(timerExpired, wait);
\t \t \t \t return invokeFunc(lastCallTime);
\t \t \t }
\t \t }
\t \t if (timerId === undefined) {
\t \t \t timerId = setTimeout(timerExpired, wait);
\t \t }
\t \t return result;
\t }
\t debounced.cancel = cancel;
\t debounced.flush = flush;
\t return debounced;
}
/**
* Creates a throttled function that only invokes `func` at most once per
* every `wait` milliseconds. The throttled function comes with a `cancel`
* method to cancel delayed `func` invocations and a `flush` method to
* immediately invoke them. Provide `options` to indicate whether `func`
* should be invoked on the leading and/or trailing edge of the `wait`
* timeout. The `func` is invoked with the last arguments provided to the
* throttled function. Subsequent calls to the throttled function return the
* result of the last `func` invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the throttled function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.throttle` and `_.debounce`.
*/
function throttle(func, wait, options) {
\t if (!options) options = {};
\t let leading = true,
\t \t trailing = true;
\t leading = 'leading' in options ? !!options.leading : leading;
\t trailing = 'trailing' in options ? !!options.trailing : trailing;
\t return debounce(func, wait, {
\t \t 'leading': leading,
\t \t 'maxWait': wait,
\t \t 'trailing': trailing
\t });
}
let counter=0;
$('#slider').slider({
min: 1,
max: 99,
orientation: 'vertical',
slide: throttle(function(event, ui) {
$(event.target).slider('option', 'value', ui.value); // making sure value is correct
console.log(ui.value);
}, 100)
});
<link href="//code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div id="slider"></div>