Comparing version 3.1.0 to 4.0.0
@@ -5,3 +5,3 @@ # Deployment Steps | ||
edit version number in deployed file (until Handlebars substitution is built) | ||
git push | ||
git push --tags | ||
npm publish |
{ | ||
"name": "rjs", | ||
"version": "3.1.0", | ||
"version": "4.0.0", | ||
"description": "A library of Javascript utility functions with an emphasis on Functional Programming.", | ||
@@ -5,0 +5,0 @@ "main": "rjs.js", |
354
rjs.js
/** | ||
* Raine's Javascript Extensions | ||
* TODO: Use Handlebars to insert version number from Cakefile | ||
* supplantFile(filename, { version: 'test' }); | ||
* {version} | ||
@@ -25,20 +23,19 @@ * A library of Javascript utility functions with an emphasis on Functional Programming. | ||
/** Returns true if the given function evaluates to true for any item in the given array. Returns false for []. */ | ||
function any(arr, f) { | ||
for(var i=0, len=arr.length; i<len; i++) { | ||
if(f(arr[i])) { | ||
return true; | ||
/** Returns the composition of the given functions, e.g. f(g(h(i(...)))) */ | ||
function compose(f/*, rest*/) { | ||
var rest = Array.prototype.slice.call(arguments, 1); | ||
if(arguments.length === 1) { | ||
return f; | ||
} | ||
else { | ||
return function() { | ||
var r = compose.apply(this, rest); | ||
return f(r.apply(this, arguments)); | ||
} | ||
} | ||
return false; | ||
} | ||
/** Returns true if the given function evaluates to true for all items in the given array. Returns true for []. */ | ||
function all(arr, f) { | ||
for(var i=0, len=arr.length; i<len; i++) { | ||
if(!f(arr[i])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
/** Returns a reverse composition of the given functions (i.e. executed in order) e.g. i(h(g(f(...)))) */ | ||
function sequence(/*first, f*/) { | ||
return compose.apply(this, reversed(arguments)); | ||
} | ||
@@ -51,3 +48,3 @@ | ||
return function() { | ||
var givenArgs = Array.prototype.slice.call(arguments, 0); | ||
var givenArgs = Array.prototype.slice.call(arguments); | ||
@@ -72,9 +69,2 @@ // handle negative indices | ||
/** Returns a new function that calls a function within a given scope. */ | ||
function bind(f, context) { | ||
return function() { | ||
return f.apply(context, arguments); | ||
} | ||
} | ||
/** Returns a new function that calls the given function with a limit on the number of arguments. */ | ||
@@ -106,3 +96,3 @@ function arritize(f, n) { | ||
function callTillValue(value) { | ||
return typeof(value) == 'function' ? callTillValue(value()) : value; | ||
return typeof value === 'function' ? callTillValue(value()) : value; | ||
} | ||
@@ -122,3 +112,8 @@ | ||
/** Assigns the given list of methods from the host object to the protoObj's prototype after converting them with toInstance. */ | ||
function install(protoObj, host, methods, thisIndex) { | ||
function install(protoObj, host, methods, safe) { | ||
if(safe === undefined) { | ||
safe = true; | ||
} | ||
var len = methods.length; | ||
@@ -128,19 +123,31 @@ for(var i=0; i<len; i++) { | ||
// the method can be a string if the hostKey and protoKey are the same ('contains') or an object that maps the host key to the proto key ({repeatString: 'repeat'}) | ||
var hostKey, protoKey; | ||
if(typeof(methods[i]) === 'string') { | ||
hostKey = methods[i]; | ||
protoKey = methods[i]; | ||
if(typeof methods[i] === 'string') { | ||
if(safe && !(methods[i] in protoObj.prototype)) { | ||
protoObj.prototype[methods[i]] = toInstance(host[methods[i]]); | ||
} | ||
} | ||
else { | ||
for(var name in methods[i]) { | ||
hostKey = name; | ||
protoKey = methods[i][name]; | ||
break; | ||
if(safe && !(methods[i][name] in protoObj.prototype)) { | ||
protoObj.prototype[methods[i][name]] = toInstance(host[name]); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
protoObj.prototype[protoKey] = toInstance(host[hostKey], thisIndex); | ||
/** Calls the given function as normal, then passes its inputs and output to the spier (defaults to console.log) */ | ||
function spy(f, spier) { | ||
var that = this; | ||
spier = spier || console.log.bind(console); | ||
return function() { | ||
var args = Array.prototype.slice.call(arguments); | ||
var out = f.apply(that, args); | ||
spier.call(that, f, args, out); | ||
return out; | ||
} | ||
} | ||
/*********************************** | ||
@@ -154,7 +161,2 @@ * String | ||
function supplant(str, o) { | ||
if(arguments.length > 2) { | ||
o = [].slice.apply(arguments, [1]); | ||
} | ||
return str.replace(/{([^{}]*)}/g, | ||
@@ -167,9 +169,2 @@ function (a, b) { | ||
/** Removes whitespace from both ends of a string. | ||
@author Douglas Crockford http://javascript.crockford.com/remedial.html | ||
*/ | ||
function trim(str) { | ||
return str.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, '$1'); | ||
} | ||
/** Returns true if the string starts with the given substring. */ | ||
@@ -197,5 +192,5 @@ function startsWith(str, sub){ | ||
/** Wraps a string with a beginning & end. */ | ||
function bookend(middle, beg, end) { | ||
return (beg || '') + middle + (end || beg || ''); | ||
/** Wraps a string with a left and right */ | ||
function bookend(middle, left, right) { | ||
return (left || '') + middle + (right || left || ''); | ||
} | ||
@@ -209,9 +204,13 @@ | ||
/** Capitalizes the first letter of each word in the given string. */ | ||
function toTitleCase(str) { | ||
var capitalizeFirst = function(s) { return s.substring(0,1).toUpperCase() + s.substring(1).toLowerCase(); }; | ||
return map(str.split(' '), capitalizeFirst).join(' '); | ||
var capitalizeFirst = function(s) { | ||
return s.length ? s[0].toUpperCase() + s.substring(1).toLowerCase() : ''; | ||
}; | ||
return str.split(' ').map(capitalizeFirst).join(' '); | ||
} | ||
function strContains(str, look) { | ||
return str.indexOf(look) !== -1; | ||
function strContains(str) { | ||
var args = Array.prototype.slice.call(arguments, 1); | ||
return String.prototype.indexOf.apply(str, args) !== -1; | ||
} | ||
@@ -247,23 +246,6 @@ | ||
/** Calls a function on each item in an array and returns a new array of the results. If f is not defined, attempts to call each item in the array as a function. */ | ||
function map(arr, f) { | ||
var results = []; | ||
var len = arr.length; | ||
for(var i=0; i<len; i++) { | ||
results.push(f ? f(arr[i], i) : arr[i](i)); | ||
} | ||
return results; | ||
} | ||
function each(arr, f) { | ||
var len = arr.length; | ||
for(var i=0; i<len; i++) { | ||
f(arr[i], i); | ||
} | ||
} | ||
/** Returns a list of values plucked from the property from the given array. If the values are functions, | ||
they wll be bound to the array item. */ | ||
function pluck(arr, property) { | ||
return map(arr, function(item) { | ||
return arr.map(function(item) { | ||
var val = item[property]; | ||
@@ -281,3 +263,3 @@ return typeof val === 'function' ? val.bind(item) : val; | ||
var getGroupKey = typeof(propOrFunc) == 'function' ? | ||
var getGroupKey = typeof propOrFunc === 'function' ? | ||
propOrFunc : | ||
@@ -305,3 +287,3 @@ function(item) { return item[propOrFunc]; }; | ||
var getGroupKey = typeof(propOrFunc) == 'function' ? | ||
var getGroupKey = typeof propOrFunc === 'function' ? | ||
propOrFunc : | ||
@@ -336,24 +318,8 @@ function(item) { return item[propOrFunc]; }; | ||
/** Returns true if the array contains the given value (==). */ | ||
function contains(arr, value) { | ||
var len = arr.length; | ||
for(var i=0; i<len; i++) { | ||
if(arr[i] == value) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
/** Returns true if the array contains the given value. */ | ||
function contains(arr) { | ||
var args = Array.prototype.slice.call(arguments, 1); | ||
return Array.prototype.indexOf.apply(arr, args) !== -1; | ||
} | ||
/** Returns true if the array contains the given value (===). */ | ||
function strictContains(arr, value) { | ||
var len = arr.length; | ||
for(var i=0; i<len; i++) { | ||
if(arr[i] === value) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
/** Returns the unique values in the array. */ | ||
@@ -364,3 +330,3 @@ function unique(arr) { | ||
for(var i=0; i<len; i++) { | ||
if(!strictContains(output, arr[i])) { | ||
if(!contains(output, arr[i])) { | ||
output.push(arr[i]); | ||
@@ -463,3 +429,3 @@ } | ||
/** Returns an array of sequential integers from start to end. If only one parameter is specified, start is 1. */ | ||
/** Returns an array of sequential integers from start to end (inclusive). If only one parameter is specified, start is 1. */ | ||
function range(start, end) { | ||
@@ -477,16 +443,5 @@ if(arguments.length === 1) { | ||
/** Returns a new array that only includes items for which f(item, i) is truthy. */ | ||
function filter(arr, f) { | ||
var result = []; | ||
for(var i=0, len=arr.length; i<len; i++) { | ||
if(f(arr[i], i)) { | ||
result.push(arr[i]); | ||
} | ||
} | ||
return result; | ||
} | ||
/** Returns a new array that only includes items with a specific value of a given property. */ | ||
function filterBy(arr, prop, value) { | ||
return filter(arr, function(item) { | ||
return arr.filter(function(item) { | ||
return item[prop] === value; | ||
@@ -497,3 +452,3 @@ }); | ||
/** Returns a new array with the array's items in random order. */ | ||
function randomize(arr) { | ||
function shuffle(arr) { | ||
var output = arr.slice(); | ||
@@ -516,11 +471,11 @@ function swap(i,j) { | ||
/** Breaks up the array into n evenly-sized chunks. | ||
Solution from http://stackoverflow.com/questions/8188548/splitting-a-js-array-into-n-arrays | ||
Solution from http://stackoverflow.com/questions/8188548/splitting-a-js-array-into-n-arrays | ||
*/ | ||
function chunk(a, n) { | ||
var len = a.length,out = [], i = 0; | ||
while (i < len) { | ||
var size = Math.ceil((len - i) / n--); | ||
out.push(a.slice(i, i += size)); | ||
} | ||
return out; | ||
var len = a.length,out = [], i = 0; | ||
while (i < len) { | ||
var size = Math.ceil((len - i) / n--); | ||
out.push(a.slice(i, i += size)); | ||
} | ||
return out; | ||
} | ||
@@ -533,11 +488,2 @@ | ||
/** Returns an array of the object's keys (converted to strings). */ | ||
function keys(o) { | ||
var output = []; | ||
for(var key in o) { | ||
output.push(key); | ||
} | ||
return output; | ||
} | ||
/** Returns an array of the object's values. */ | ||
@@ -573,3 +519,3 @@ function values(o) { | ||
var i, v; | ||
if (typeOf(o) === 'object') { | ||
if(typeOf(o) === 'object') { | ||
for (i in o) { | ||
@@ -630,3 +576,3 @@ v = o[i]; | ||
/** Returns an array whose items are the result of calling f(key, value) on each property of the given object. */ | ||
/** Returns an array whose items are the result of calling f(key, value) on each property of the given object. If f is undefined, returns a list of { key: ___, value: ___ } objects. */ | ||
function toArray(obj, f) { | ||
@@ -670,3 +616,3 @@ var f = f || function(key, value) { return { key: key, value: value }; }; | ||
/** Compares two items lexigraphically. Returns 1 if a>b, 0 if a==b, or -1 if a<b. */ | ||
/** Compares two items lexigraphically. Returns 1 if a>b, 0 if a==b, or -1 if a<b. */ | ||
function compare(a,b) { | ||
@@ -728,3 +674,3 @@ return a > b ? 1 : | ||
if(typeof(a) !== typeof(b)) { | ||
if(typeof a !== typeof b) { | ||
return false; | ||
@@ -749,3 +695,3 @@ } | ||
// compare primitives | ||
else if(typeof(a) === 'number' || typeof(a) === 'string' || typeof(a) === 'boolean' || typeof(a) === 'undefined') { | ||
else if(typeof a === 'number' || typeof a === 'string' || typeof a === 'boolean' || typeof a === 'undefined') { | ||
if(a !== b) { | ||
@@ -770,2 +716,7 @@ return false; | ||
/** in operator as a function. */ | ||
function hasKey(creamFilling, donut) { | ||
return creamFilling in donut; | ||
} | ||
/** Returns true if the given value is not undefined, null, or an empty string. */ | ||
@@ -784,3 +735,3 @@ function hasValue(x) { | ||
} | ||
else if(typeof(o) === 'string' || typeof(o) === 'number') { | ||
else if(typeof o === 'string' || typeof o === 'number') { | ||
return '' + o; | ||
@@ -808,3 +759,3 @@ } | ||
var S4 = function() { | ||
return (((1+Math.random())*0x10000)|0).toString(16).substring(1); | ||
return (((1+Math.random())*0x10000)|0).toString(16).substring(1); | ||
} | ||
@@ -835,7 +786,7 @@ return function() { | ||
/** Calls the given constructor and returns the new instance. Useful for higher order programmer where the new keyword won't work. | ||
@warning Does not support more than 10 arguments! Done this way because accessing __proto__ directly for true variable number of arguments doesn't seem to be consistent across browsers. http://lmeyerov.blogspot.com/2007/12/wrapping-javascript-new-constructor.html | ||
*/ | ||
function createNew(f) { | ||
return new f(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10]); | ||
/** Create a new instance of the given constructor with the given constructor arguments. Useful for higher order programmer where the new keyword won't work. */ | ||
function createNew(C, args) { | ||
var o = new C(); | ||
C.apply(o, args); | ||
return o; | ||
} | ||
@@ -850,6 +801,6 @@ | ||
var rjs = rjs || RJS; | ||
install(String, rjs, ['supplant', 'trim', 'startsWith', 'before', 'after', 'between', 'bookend', { repeatString: 'repeat' }, 'toTitleCase', { strContains: 'contains' }, 'index' ]); | ||
install(String, rjs, ['supplant', 'startsWith', 'before', 'after', 'between', 'bookend', { repeatString: 'repeat' }, 'toTitleCase', { strContains: 'contains' }, 'index' ]); | ||
install(Number, rjs, ['ordinal', { mapNumber: 'map' }]); | ||
install(Array, rjs, ['map', 'each', 'pluck', 'group', 'orderedGroup', 'tally', 'contains', 'strictContains', 'unique', 'reversed', 'index', 'rotate', 'toObject', 'find', 'findByProperty', 'filterBy', 'any', 'all', 'spliced', 'randomize', 'chunk' ]); | ||
install(Function, rjs, ['any', 'all', 'bind', 'curryAt', 'curry', 'rcurry', 'arritize', 'currify', 'toInstance', 'new']); | ||
install(Array, rjs, ['each', 'pluck', 'group', 'orderedGroup', 'tally', 'contains', 'unique', 'reversed', 'index', 'rotate', 'toObject', 'find', 'findByProperty', 'filterBy', 'any', 'all', 'spliced', 'shuffle', 'chunk' ]); | ||
install(Function, rjs, ['any', 'all', 'compose', 'sequence', 'curryAt', 'curry', 'rcurry', 'arritize', 'currify', 'toInstance', 'new', 'spy']); | ||
return rjs; | ||
@@ -866,78 +817,73 @@ } | ||
// function | ||
I : I, | ||
not : not, | ||
any : any, | ||
all : all, | ||
bind : bind, | ||
curryAt : curryAt, | ||
curry : curry, | ||
rcurry : rcurry, | ||
arritize : arritize, | ||
currify : currify, | ||
callTillValue : callTillValue, | ||
toInstance : toInstance, | ||
install : install, | ||
I : I, | ||
not : not, | ||
compose : compose, | ||
sequence : sequence, | ||
curryAt : curryAt, | ||
curry : curry, | ||
rcurry : rcurry, | ||
arritize : arritize, | ||
currify : currify, | ||
callTillValue : callTillValue, | ||
toInstance : toInstance, | ||
install : install, | ||
spy : spy, | ||
// string | ||
supplant : supplant, | ||
trim : trim, | ||
startsWith : startsWith, | ||
before : before, | ||
after : after, | ||
between : between, | ||
supplant : supplant, | ||
startsWith : startsWith, | ||
before : before, | ||
after : after, | ||
between : between, | ||
bookend : bookend, | ||
repeatString : repeatString, | ||
toTitleCase : toTitleCase, | ||
strContains : strContains, | ||
repeatString : repeatString, | ||
toTitleCase : toTitleCase, | ||
strContains : strContains, | ||
// number | ||
ordinal : ordinal, | ||
mapNumber : mapNumber, | ||
ordinal : ordinal, | ||
mapNumber : mapNumber, | ||
// array | ||
map : map, | ||
each : each, | ||
pluck : pluck, | ||
group : group, | ||
orderedGroup : orderedGroup, | ||
tally : tally, | ||
contains : contains, | ||
strictContains : strictContains, | ||
unique : unique, | ||
reversed : reversed, | ||
index : index, | ||
rotate : rotate, | ||
toObject : toObject, | ||
find : find, | ||
findByProperty : findByProperty, | ||
spliced : spliced, | ||
range : range, | ||
filter : filter, | ||
filterBy : filterBy, | ||
randomize : randomize, | ||
pluck : pluck, | ||
group : group, | ||
orderedGroup : orderedGroup, | ||
tally : tally, | ||
contains : contains, | ||
unique : unique, | ||
reversed : reversed, | ||
index : index, | ||
rotate : rotate, | ||
toObject : toObject, | ||
find : find, | ||
findByProperty : findByProperty, | ||
spliced : spliced, | ||
range : range, | ||
filterBy : filterBy, | ||
shuffle : shuffle, | ||
chunk : chunk, | ||
// object | ||
keys : keys, | ||
values : values, | ||
keyValue : keyValue, | ||
joinObj : joinObj, | ||
isEmpty : isEmpty, | ||
numProperties : numProperties, | ||
merge : merge, | ||
mapObject : mapObject, | ||
toArray : toArray, | ||
filterObject : filterObject, | ||
changeKeys : changeKeys, | ||
values : values, | ||
keyValue : keyValue, | ||
joinObj : joinObj, | ||
isEmpty : isEmpty, | ||
numProperties : numProperties, | ||
merge : merge, | ||
mapObject : mapObject, | ||
toArray : toArray, | ||
filterObject : filterObject, | ||
changeKeys : changeKeys, | ||
// utility | ||
compare : compare, | ||
compareProperty : compareProperty, | ||
dynamicCompare : dynamicCompare, | ||
equals : equals, | ||
hasValue : hasValue, | ||
hash : hash, | ||
guid : guid, | ||
typeOf : typeOf, | ||
'new' : createNew, | ||
compare : compare, | ||
compareProperty : compareProperty, | ||
dynamicCompare : dynamicCompare, | ||
equals : equals, | ||
hasKey : hasKey, | ||
hasValue : hasValue, | ||
hash : hash, | ||
guid : guid, | ||
typeOf : typeOf, | ||
'new' : createNew, | ||
@@ -951,4 +897,4 @@ // prototype installation | ||
// nodejs module | ||
if(typeof(module) != 'undefined') { | ||
if(typeof module !== 'undefined') { | ||
module.exports = RJS; | ||
} |
@@ -0,1 +1,3 @@ | ||
# TODO | ||
* add minification to build process | ||
* function coercion on all higher order functions | ||
@@ -9,6 +11,2 @@ | ||
}; | ||
* currify everything! | ||
* dynamically insert version number into cake file | ||
* add minified version | ||
* split into two libraries: | ||
@@ -19,1 +17,3 @@ - utility functions not included in underscore | ||
* switch to Chai testing | ||
* Use Handlebars to insert version number into deployed rjs.js from Cakefile | ||
e.g. supplantFile(filename, { version: 'test' }); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
759983
44
19964