Created
July 17, 2022 15:50
-
-
Save Weltraumschaf/0ca4493110e3cd626f8d240727c6a624 to your computer and use it in GitHub Desktop.
This plugin provides some util functions and methods inspired by the book "JavaScript: The Good Parts" from Douglas Crockford.
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
/** | |
* This plugin provides some util functions and methods inspired | |
* by the book "JavaScript: The Good Parts" from Douglas Crockford | |
* | |
* @author Sven Strittmatter <[email protected]> | |
*/ | |
(function($) { // pass in the jQuery object as $ (see end of file) | |
/** | |
* Adds a method to an Object. This method is used | |
* to augment the standard objects with some usefull | |
* functions (see below) | |
* | |
* @param string name | |
* @param function func | |
* @return function | |
*/ | |
Function.prototype.method = function(name, func) { | |
if (!this.prototype[name]) { | |
this.prototype[name] = func; | |
} | |
return this; | |
}; | |
/** | |
* Adds the namespace() method to the Object type. | |
* It creates namespace object structures, e.g.: | |
* | |
* <code> | |
* Object.namespace('foo.bar.baz'); | |
* // ... | |
* foo.bar.baz.MyType = function() { | |
* // ... | |
* }; | |
* </code> | |
* | |
* This method is alos available as jQuery util | |
* function, e.g.: | |
* | |
* <code> | |
* $.namespace('foo.bar.baz'); | |
* // ... | |
* foo.bar.baz.MyType = function() { | |
* // ... | |
* }; | |
* | |
* You can also create more than one namespace at one time: | |
* <code> | |
* Object.namespace('foo.bar.baz', 'foo.bar.biz', 'foo.bar.buz'); | |
* </code> | |
* | |
* or | |
* <code> | |
* $.namespace('foo.bar.baz', 'foo.bar.biz', 'foo.bar.buz'); | |
* </code> | |
* | |
* @param string namespace | |
* @return object | |
*/ | |
$.namespace = Object.method('namespace', function() { | |
var a = arguments, | |
o = null, | |
i, j, d; | |
for (i = 0; i < a.length; i = i + 1) { | |
d = ('' + a[i]).split('.'); | |
o = {}; | |
for (j = 0; j < d.length; j = j + 1) { | |
o[d[j]] = o[d[j]] || {}; | |
o = o[d[j]]; | |
} | |
} | |
return o; | |
}; | |
/** | |
* With this method you can debounce other founctions. This is | |
* usefull when you have a clickhandler which you want to debounce: | |
* If a user clicks repetly and triggers mor than one event in short | |
* time these events are cummulated to a single debounced event. | |
* | |
* With the threshold parameter you can define the time in miliseconds | |
* in which the repeted function calles will be debounced.The default | |
* threshold is 100. | |
* | |
* Withe the thir parameter you can choose if the functions is triggered | |
* on the first event and ignores the followed calls in the threshold time. | |
* Or you can choose that the debounced function is called after the last | |
* function called which was triggered while threshold. Default is false. | |
* | |
* This example debounces for 300 milliseconds and triggers the debounced | |
* function imidiatelly: | |
* <code> | |
* var myClickHandler = Function.debounce(function(event) { | |
* // ... | |
* }, 300, true); | |
* </code> | |
* | |
* This example triggers the debounced function 100 milliseconds after the last | |
* occurance of a function call: | |
* <code> | |
* var myClickHandler = Function.debounce(function(event) { | |
* // ... | |
* }); | |
* </code> | |
* | |
* @param function func | |
* @param number threshold | |
* @param boolean execAsap | |
* @return function | |
*/ | |
$.debounce = Function.method('debounce', function (func, threshold, execAsap) { | |
var timeout; // handle to setTimeout async task (detection period) | |
/* | |
* return the new debounced function which executes the | |
* original function only once until the detection period expires. | |
*/ | |
function debounced() { | |
var obj = this, // reference to original context object | |
args = arguments; // arguments at execution time | |
/* | |
* this is the detection function. it will be executed | |
* if/when the threshold expires | |
*/ | |
function delayed () { | |
// if we're executing at the end of the detection period | |
if (!execAsap) { | |
func.apply(obj, args); // execute now | |
} | |
// clear timeout handle | |
timeout = null; | |
} | |
// stop any current detection period | |
if (timeout) { | |
clearTimeout(timeout); | |
} else if (execAsap) { | |
// otherwise, if we're not already waiting and we're executing at the beginning of the detection period | |
func.apply(obj, args); // execute now | |
} | |
// reset the detection period | |
timeout = setTimeout(delayed, threshold || 100); | |
} | |
return debounced; | |
}; | |
/** | |
* | |
*/ | |
Function.method('curry', function() { | |
var slice = Array.prototype.slice, | |
args = slice.apply(arguments), | |
that = this; | |
return function() { | |
return that.apply(null, args.concat(slice.apply(arguments))); | |
} | |
}); | |
/** | |
* With this function you can reduce the recursiv function call | |
* overhead on tail recursiv functions. | |
* | |
* Examples: | |
* | |
* Fibonacci | |
* <code> | |
* var fibonnaci = Function.memorizer([0, 1], function(shell, n) { | |
* return shell(n - 1) + shell(n - 2); | |
* }); | |
* </code> | |
* | |
* Factorial | |
* <code> | |
* var factorial = Function.memorizer([1, 1], function(shell, n) { | |
* return n * shell(n - 1); | |
* }); | |
* </code> | |
* | |
* @param array memo | |
* @param function fundamental | |
* @return object | |
*/ | |
Function.method('memorizer', function(memo, fundamental) { | |
var shell = function(n) { | |
var result = memo[n]; | |
if (typeof result !== 'number') { | |
result = fundamental(shell, n); | |
memo[n] = result; | |
} | |
return result; | |
}; | |
return shell; | |
}); | |
/** | |
* Gives the integer part of a floating number object. | |
* | |
* <code> | |
* var myInt = 5.34.integer(); | |
* </code> | |
* | |
* @return number | |
*/ | |
Number.method('integer', function() { | |
return Math[this < 0 ? 'ceil' : 'floor'](this); | |
}); | |
$.integer = function(n) { | |
if (typeof n === 'number' && typeof n.integer === 'function') { | |
return n.integer(); | |
} else { | |
return 0; | |
} | |
}; | |
Array.dim = function(dimension, initial) { | |
var a = [], i; | |
for (i = 0; i < dimension; i += 1) { | |
a[i] = initial; | |
} | |
return a; | |
}; | |
Array.matrix = function(m, n, initial) { | |
var a, i, j, mat = []; | |
for (i = 0; i < m; i += 1) { | |
a = []; | |
for (j = 0; j < n; j += 1) { | |
a[j] = initial; | |
} | |
mat[i] = a; | |
} | |
return mat; | |
}; | |
Array.identity = function(n) { | |
var i, mat = Array.matrix(n, n, 0); | |
for (i = 0; i < n; i += 1) { | |
mat[i][i] = 1; | |
} | |
return mat; | |
}; | |
/** | |
* Trims the white space characters of an string. | |
* | |
* <code> | |
* var trimmedString = ' this is a string '.trim(); | |
* </code> | |
* | |
* @return string | |
*/ | |
String.method('trim', function() { | |
return this.replace(/^\s+|\s+$/g, ''); | |
}); | |
(function() { // Closure to hide the entity character maps. | |
var entity2char = { | |
lt: '<', | |
gt: '>', | |
quot: '"' | |
}, | |
char2entity = { | |
'<': '<', | |
'>': '>', | |
'&': '&', | |
'"': '"' | |
}; | |
/** | |
* Replaces characters which where entites: | |
* > -> > | |
* < -> < | |
* & -> & | |
* " -> " | |
* | |
* <code> | |
* '<p>This & that</p>'.entityify(); | |
* </code> | |
* | |
* @return string | |
*/ | |
String.method('entityify', function() { | |
return function() { | |
return this.replace(/[<>&"/g, function(matchedCharcter) { | |
return char2entity[matchedCharcter]; | |
}) | |
}; | |
}); | |
/** | |
* Replaces entities with the corresponding characters: | |
* > -> > | |
* < -> < | |
* & -> & | |
* " -> " | |
* | |
* <code> | |
* '<p>This & that</p>'.deEntityify(); | |
* </code> | |
* | |
* @return string | |
*/ | |
String.method('deEntityify', function() { | |
return function() { | |
return this.replace(/&([^&;]+);/g, function(a, b) { | |
var r = entity2char[b]; | |
return (typeof r === 'string') ? r : a; | |
}); | |
}; | |
}); | |
})(); // Self invocation | |
})(jQuery); // pass the global jQuery object for $.noConflict mode |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment