/*
* throttle-debounce-fn - v1.0.1 * jQuery-based plugin that allows you to throttle and debounce your functions * https://github.com/migueldemoura/throttle-debounce-fn * * Made by Miguel de Moura * Under MIT License */
;(function ($, window, document, undefined) {
// Throttle execution of a function. Especially useful for rate limiting // execution of handlers on events like resize and scroll. If you want to // rate-limit execution of a function to a single time, see the // <$.debounce> method. // // In this visualization, | is a throttled-function call and X is the actual // callback execution: // // > Throttled with `noTrailing` specified as false or unspecified: // > ||||||||||||||||||||||||| (pause) ||||||||||||||||||||||||| // > X X X X X X X X X X X X // > // > Throttled with `noTrailing` specified as true: // > ||||||||||||||||||||||||| (pause) ||||||||||||||||||||||||| // > X X X X X X X X X X // // Usage: // // > var throttled = $.throttle(delay, [ noTrailing, ] callback); // > // > $('selector').bind('someevent', throttled); // > $('selector').unbind('someevent', throttled); // // Arguments: // // delay - (Number) A zero-or-greater delay in milliseconds. For event // callbacks, values around 100 or 250 (or even higher) are most useful. // noTrailing - (Boolean) Optional, defaults to false. If noTrailing is // true, callback will only execute every `delay` milliseconds while the // throttled-function is being called. If noTrailing is false or // unspecified, callback will be executed one final time after the last // throttled-function call. (After the throttled-function has not been // called for `delay` milliseconds, the internal counter is reset) // callback - (Function) A function to be executed after delay milliseconds. // The `this` context and all arguments are passed through, as-is, to // `callback` when the throttled-function is executed. // // Returns: // // (Function) A new, throttled, function. $.throttle = function(delay, noTrailing, callback, debounceMode) { // After wrapper has stopped being called, this timeout ensures that // `callback` is executed at the proper times in `throttle` and `end` // debounce modes. var timeoutId, // Keep track of the last time `callback` was executed. lastExec = 0; // `noTrailing` defaults to false. if (typeof noTrailing !== 'boolean') { debounceMode = callback; callback = noTrailing; noTrailing = undefined; } // The `wrapper` function encapsulates all of the throttling / debouncing // functionality and when executed will limit the rate at which `callback` // is executed. function wrapper() { var that = this, elapsed = +new Date() - lastExec, args = arguments; // Execute `callback` and update the `lastExec` timestamp. function exec() { lastExec = +new Date(); callback.apply(that, args); } // If `debounceMode` is true (atBegin) this is used to clear the flag // to allow future `callback` executions. function clear() { timeoutId = undefined; } if (debounceMode && !timeoutId) { // Since `wrapper` is being called for the first time and // `debounceMode` is true (atBegin), execute `callback`. exec(); } // Clear any existing timeout. timeoutId && clearTimeout(timeoutId); if (debounceMode === undefined && elapsed > delay) { // In throttle mode, if `delay` time has been exceeded, execute // `callback`. exec(); } else if (noTrailing !== true) { // In trailing throttle mode, since `delay` time has not been // exceeded, schedule `callback` to execute `delay` ms after most // recent execution. // If `debounceMode` is true (atBegin), schedule `clear` to execute // after `delay` ms. // If `debounceMode` is false (at end), schedule `callback` to // execute after `delay` ms. timeoutId = setTimeout( debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay ); } } return wrapper; }; // Debounce execution of a function. Debouncing, unlike throttling, // guarantees that a function is only executed a single time, either at the // very beginning of a series of calls, or at the very end. If you want to // simply rate-limit execution of a function, see the <$.throttle> // method. // // In this visualization, | is a debounced-function call and X is the actual // callback execution: // // > Debounced with `atBegin` specified as false or unspecified: // > ||||||||||||||||||||||||| (pause) ||||||||||||||||||||||||| // > X X // > // > Debounced with `atBegin` specified as true: // > ||||||||||||||||||||||||| (pause) ||||||||||||||||||||||||| // > X X // // Usage: // // > var debounced = $.debounce(delay, [ atBegin, ] callback); // > // > $('selector').bind('someevent', debounced); // > $('selector').unbind('someevent', debounced); // // Arguments: // // delay - (Number) A zero-or-greater delay in milliseconds. For event // callbacks, values around 100 or 250 (or even higher) are most useful. // atBegin - (Boolean) Optional, defaults to false. If atBegin is false or // unspecified, callback will only be executed `delay` milliseconds after // the last debounced-function call. If atBegin is true, callback will be // executed only at the first debounced-function call. (After the // throttled-function has not been called for `delay` milliseconds, the // internal counter is reset) // callback - (Function) A function to be executed after delay milliseconds. // The `this` context and all arguments are passed through, as-is, to // `callback` when the debounced-function is executed. // // Returns: // // (Function) A new, debounced, function. $.debounce = function(delay, atBegin, callback) { return callback === undefined ? $.throttle(delay, atBegin, false) : $.throttle(delay, callback, atBegin !== false); };
}(jQuery, window, document));