Skip to content

Instantly share code, notes, and snippets.

@c-kick
Last active March 12, 2023 17:42
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save c-kick/d359fce36257cf4c9fb5ea5f2c0033b6 to your computer and use it in GitHub Desktop.
Save c-kick/d359fce36257cf4c9fb5ea5f2c0033b6 to your computer and use it in GitHub Desktop.
JavaScript function prototype debouncer v4.1 - debounces functions that are prone to repetitive calling (on events such as mousewheel, orientationchange, resize, etc). Demo: https://code.hnldesign.nl/demo/hnl.debounce.html
/**
* JavaScript function prototype debouncer 4.3 - 2010-2022 hnldesign.nl - Klaas Leussink
* Demo: https://code.hnldesign.nl/demo/hnl.debounce.html
*
* Based on code by Paul Irish and the original debouncing function from John Hann
* http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
* Register deBouncer as a function prototype.
*
* All debounced variants of the function (depending on the supplied debouncing parameters (see below)
* are stored inside a 'dbObj' Object inside the debounced function.
*
* Usage:
*
* orginal: myFunction(arguments);
* debounced: myFunction.deBounce(100, true, true, false)(arguments);
*
* Or define an already debounced function:
* var myFunction = (function(e){
* console.log('myFunction!', e);
* }).deBounce(100, true, true, true);
*
* @memberOf(Object)
* @name deBounce
*
* @param {int} threshold
* Time in ms to wait for repeated calls.
*
* @param {boolean} execFirst
* True: Function is executed, subsequent calls are stopped during threshold.
* False: calls are stopped during threshold, when it passes, function is called.
*
* @param {boolean} execLast
* True: continue executing immediately after the threshold has passed, while the function is still being called.
* False: threshold serves as 'cool down' period; only if function calls have ended, and threshold passes, function can be called again.
*
* @param {boolean} execWhile
* True: execute while called, with threshold as interval. Will produce same end-result as execLast
* False: will hold execution of the function while repetitive calls are still coming within the threshold
*
* @returns {function} The debounced function
*/
if (typeof Function.prototype.deBounce !== 'function') {
Object.defineProperty(Function.prototype, 'deBounce', {
value : function (threshold, execFirst, execLast, execWhile) {
'use strict';
//defaults, non-ES6 way to stay ES5 compatible
threshold = threshold !== undefined ? threshold : 100;
execFirst = execFirst !== undefined ? execFirst : true;
execLast = execLast !== undefined ? execLast : false;
execWhile = execWhile !== undefined ? execWhile : false;
var func = this, uid = (Math.random() + 1).toString(36).substring(7) + threshold.toString() + execFirst.toString() + execLast.toString() + execWhile.toString();
if (func.dbObj === undefined) {
func.dbObj = {};
} else if (func.dbObj[uid] !== undefined) {
return func.dbObj[uid].debounced;
}
func.dbObj[uid] = {
'debounced' : function (a) {
var obj = this, args = arguments, cid = [a].toString();
function delayed() {
if (execLast || execWhile) {
func.apply(obj, args);
}
func.dbObj[uid][cid] = null;
}
if (!func.dbObj[uid][cid]) {
if (execFirst) {
func.apply(obj, args);
}
func.dbObj[uid][cid] = setTimeout(delayed, threshold || 100);
} else if (func.dbObj[uid][cid] && !execWhile) {
clearTimeout(func.dbObj[uid][cid]);
func.dbObj[uid][cid] = setTimeout(delayed, threshold || 100);
}
}
};
return func.dbObj[uid].debounced;
}
});
}
/**
* Wraps the deBouncer for easy use in jQuery
* Usage:
* jQdeBounce($, 'smartresize', 'resize', 20, true, true, false); //creates the function
* $(window).smartresize(function () {
* //use the function
* console.log('jquery resize debounce');
* });
*
* @param {object} $ The jQuery object to register in.
* @param {function} createMethod The dbObj method/function to create.
* @param {function} originalMethod The original method/function to use as source
*/
if (!!$) {
return function ($, createMethod, originalMethod, thresh, execFirst, execLast, execWhile) {
'use strict';
$.fn[createMethod] = function (fn) { return fn ? this.bind(originalMethod, fn.deBounce(thresh, execFirst, execLast, execWhile)) : this.trigger(createMethod);};
};
} else {
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment