Last active
March 12, 2023 17:42
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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