mol-proto
Advanced tools
Comparing version 0.1.8 to 0.1.9
{ | ||
"name": "proto", | ||
"version": "0.1.8", | ||
"version": "0.1.9", | ||
"homepage": "https://github.com/MailOnline/proto", | ||
@@ -5,0 +5,0 @@ "authors": [ |
@@ -23,2 +23,3 @@ 'use strict'; | ||
* - [once](#once) | ||
* - [waitFor](#waitFor) | ||
* | ||
@@ -41,3 +42,4 @@ * These methods can be [chained](proto.js.html#Proto) | ||
throttle: throttle, | ||
once: once | ||
once: once, | ||
waitFor: waitFor | ||
}; | ||
@@ -346,2 +348,28 @@ | ||
}; | ||
} | ||
} | ||
/** | ||
* Execute a function when the condition function returns a truthy value | ||
* it runs the condition function every `checkInterval` milliseconds (default 50) | ||
* | ||
* @param {Function} self function: if it returns true the callback is executed | ||
* @param {Function} callback runs when the condition is true | ||
* @param {Number} maxTimeout timeout before giving up (time in milliseconds) | ||
* @param {Function} timedOutFunc a function called if timeout is reached | ||
* @param {Number} checkInterval time interval when you run the condition function (time in milliseconds), default 50 ms | ||
*/ | ||
function waitFor(callback, maxTimeout, timedOutFunc, checkInterval){ | ||
var start = Date.now(); | ||
var condition = this; | ||
checkInterval = checkInterval || 50; | ||
var interval = setInterval(testCondition, checkInterval); | ||
function testCondition() { | ||
if (condition()) callback(); | ||
else if (Date.now() - start >= maxTimeout) | ||
timedOutFunc && timedOutFunc(); | ||
else return; | ||
clearInterval(interval); | ||
}; | ||
} |
@@ -82,3 +82,4 @@ 'use strict'; | ||
* - [once](proto_function.js.html#once) | ||
*/ | ||
* - [waitFor](proto_function.js.html#waitFor) | ||
*/ | ||
var functionMethods = require('./proto_function'); | ||
@@ -85,0 +86,0 @@ |
{ | ||
"name": "mol-proto", | ||
"version": "0.1.8", | ||
"version": "0.1.9", | ||
"description": "ES5 object manipulation library for node and modern browsers", | ||
@@ -5,0 +5,0 @@ "main": "lib/proto.js", |
@@ -13,2 +13,3 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
* - [makeSubclass](proto_prototype.js.html#makeSubclass) | ||
* - [newApply](proto_prototype.js.html#newApply) | ||
*/ | ||
@@ -27,3 +28,5 @@ var prototypeMethods = require('./proto_prototype'); | ||
* - [deepClone](proto_object.js.html#deepClone) | ||
* - [keys](proto_object.js.html#keys) | ||
* - [allKeys](proto_object.js.html#allKeys) | ||
* - [values](proto_object.js.html#values) | ||
* - [keyOf](proto_object.js.html#keyOf) | ||
@@ -41,2 +44,3 @@ * - [allKeysOf](proto_object.js.html#allKeysOf) | ||
* - [omitKeys](proto_object.js.html#omitKeys) | ||
* - [isEqual](proto_object.js.html#isEqual) | ||
*/ | ||
@@ -53,2 +57,3 @@ var objectMethods = require('./proto_object'); | ||
* - [prependArray](proto_array.js.html#prependArray) | ||
* - [spliceItem](proto_array.js.html#spliceItem) | ||
* - [toArray](proto_array.js.html#toArray) | ||
@@ -74,2 +79,5 @@ * - [object](proto_array.js.html#object) | ||
* - [defer](proto_function.js.html#defer) | ||
* - [delayed](proto_function.js.html#delayed) | ||
* - [deferred](proto_function.js.html#deferred) | ||
* - [deferTicks](proto_function.js.html#deferTicks) | ||
* - [delayMethod](proto_function.js.html#delayMethod) | ||
@@ -79,2 +87,3 @@ * - [deferMethod](proto_function.js.html#deferMethod) | ||
* - [throttle](proto_function.js.html#throttle) | ||
* - [once](proto_function.js.html#once) | ||
*/ | ||
@@ -91,2 +100,8 @@ var functionMethods = require('./proto_function'); | ||
* - [toFunction](proto_string.js.html#toFunction) | ||
* - [toDate](proto_string.js.html#toDate) | ||
* - [toQueryString](proto_string.js.html#toQueryString) | ||
* - [fromQueryString](proto_string.js.html#fromQueryString) | ||
* - [jsonParse](proto_string.js.html#jsonParse) | ||
* - [hashCode](proto_string.js.html#hashCode) | ||
* - [unPrefix](proto_string.js.html#unPrefix) | ||
*/ | ||
@@ -107,3 +122,7 @@ var stringMethods = require('./proto_string'); | ||
* | ||
* - [times](proto_util.js.html#times) | ||
* - [repeat](proto_util.js.html#repeat) | ||
* - [tap](proto_util.js.html#tap) | ||
* - [result](proto_util.js.html#result) | ||
* - [identity](proto_util.js.html#identity) | ||
*/ | ||
@@ -186,3 +205,3 @@ var utilMethods = require('./proto_util'); | ||
// expose global _ | ||
// expose global _ and Proto | ||
window._ = Proto; | ||
@@ -207,2 +226,3 @@ } | ||
* - [prependArray](#prependArray) | ||
* - [spliceItem](#spliceItem) | ||
* - [toArray](#toArray) | ||
@@ -225,3 +245,4 @@ * - [object](#object) | ||
unique: unique, | ||
deepForEach: deepForEach | ||
deepForEach: deepForEach, | ||
spliceItem: spliceItem | ||
}; | ||
@@ -283,3 +304,5 @@ | ||
if (! arrayToAppend.length) return this; | ||
if (! Array.isArray(arrayToAppend)) | ||
arrayToAppend = toArray.call(arrayToAppend); | ||
var args = [this.length, 0].concat(arrayToAppend); | ||
@@ -302,2 +325,4 @@ arrayMethods.splice.apply(this, args); | ||
if (! arrayToPrepend.length) return this; | ||
if (! Array.isArray(arrayToPrepend)) | ||
arrayToPrepend = toArray.call(arrayToPrepend); | ||
@@ -312,2 +337,17 @@ var args = [0, 0].concat(arrayToPrepend); | ||
/** | ||
* Removes item from array that is found using indexOf (i.e. '===') | ||
* Modifies original array and returns the reference to it. | ||
* | ||
* @param {Array} self An array that will be modified | ||
* @param {Any} item item to be removed | ||
* @return {Array} | ||
*/ | ||
function spliceItem(item) { | ||
var index = this.indexOf(item); | ||
if (index >= 0) this.splice(index, 1); | ||
return this; | ||
} | ||
/** | ||
* Returns new array created from array-like object (e.g., `arguments` pseudo-array). | ||
@@ -416,2 +456,7 @@ * | ||
var makeProtoFunction = require('./utils').makeProtoFunction | ||
, repeat = require('./proto_util').repeat; | ||
/** | ||
@@ -424,2 +469,5 @@ * - [makeFunction](#makeFunction) | ||
* - [defer](#defer) | ||
* - [delayed](#delayed) | ||
* - [deferred](#deferred) | ||
* - [deferTicks](#deferTicks) | ||
* - [delayMethod](#delayMethod) | ||
@@ -429,2 +477,3 @@ * - [deferMethod](#deferMethod) | ||
* - [throttle](#throttle) | ||
* - [once](#once) | ||
* | ||
@@ -440,6 +489,11 @@ * These methods can be [chained](proto.js.html#Proto) | ||
defer: defer, | ||
delayed: delayed, | ||
deferred: deferred, | ||
deferTicks: deferTicks, | ||
delayMethod: delayMethod, | ||
deferMethod: deferMethod, | ||
debounce: debounce, | ||
throttle: throttle | ||
throttle: throttle, | ||
once: once, | ||
waitFor: waitFor | ||
}; | ||
@@ -565,14 +619,34 @@ | ||
/** | ||
* Same as _.defer, takes first argument as the function to be deferred | ||
*/ | ||
var deferFunc = makeProtoFunction(defer); | ||
/** | ||
* Defers function execution for `times` ticks (executes after execution loop becomes free `times` times) | ||
* The context in function when it is executed is set to `null`. | ||
* | ||
* @param {Function} self function that execution has to be delayed | ||
* @param {Integer} ticks number of times to defer execution | ||
* @param {List} arguments optional arguments that will be passed to the function | ||
*/ | ||
function deferTicks(ticks) { // , arguments | ||
if (ticks < 2) return defer.apply(this, arguments); | ||
var args = repeat.call(deferFunc, ticks - 1); | ||
args = args.concat(this, slice.call(arguments, 1)); | ||
deferFunc.apply(null, args); | ||
} | ||
/** | ||
* Works like _.delay but allows to defer method call of `self` which will be the first _.delayMethod parameter | ||
* | ||
* @param {Object} self object to delay method call of | ||
* @param {String} methodName name of method | ||
* @param {Function|String} funcOrMethodName function or name of method | ||
* @param {Number} wait approximate dalay time in milliseconds | ||
* @param {List} arguments arguments to pass to method | ||
*/ | ||
function delayMethod(methodName, wait) { // , ... arguments | ||
function delayMethod(funcOrMethodName, wait) { // , ... arguments | ||
var args = slice.call(arguments, 2); | ||
_delayMethod(this, methodName, wait, args); | ||
_delayMethod(this, funcOrMethodName, wait, args); | ||
} | ||
@@ -585,13 +659,16 @@ | ||
* @param {Object} self object to defer method call of | ||
* @param {String} methodName name of method | ||
* @param {Function|String} funcOrMethodName function or name of method | ||
* @param {List} arguments arguments to pass to method | ||
*/ | ||
function deferMethod(methodName) { // , ... arguments | ||
function deferMethod(funcOrMethodName) { // , ... arguments | ||
var args = slice.call(arguments, 1); | ||
_delayMethod(this, methodName, 1, args); | ||
_delayMethod(this, funcOrMethodName, 1, args); | ||
} | ||
function _delayMethod(object, methodName, wait, args) { | ||
function _delayMethod(object, funcOrMethodName, wait, args) { | ||
return setTimeout(function() { | ||
object[methodName].apply(object, args); | ||
var func = typeof funcOrMethodName == 'string' | ||
? object[funcOrMethodName] | ||
: funcOrMethodName; | ||
func.apply(object, args); | ||
}, wait); | ||
@@ -602,2 +679,37 @@ } | ||
/** | ||
* Returns function that will execute the original function `wait` ms after it has been called | ||
* The context in function when it is executed is set to `null`. | ||
* | ||
* @param {Function} self function which execution has to be deferred | ||
* @param {Number} wait approximate dalay time in milliseconds | ||
* @param {List} arguments optional arguments that will be passed to the function | ||
* @return {Function} | ||
*/ | ||
function delayed(wait) { //, ... arguments | ||
var func = this | ||
, args = slice.call(arguments, 1); | ||
return function() { | ||
return _delay(func, wait, args); | ||
} | ||
} | ||
/** | ||
* Returns function that will execute the original function on the next tick once it has been called | ||
* The context in function when it is executed is set to `null`. | ||
* | ||
* @param {Function} self function which execution has to be deferred | ||
* @param {List} arguments optional arguments that will be passed to the function | ||
* @return {Function} | ||
*/ | ||
function deferred() { //, ... arguments | ||
var func = this | ||
, args = arguments; | ||
return function() { | ||
return _delay(func, 1, args); | ||
} | ||
} | ||
/** | ||
* Creates a function that will call original function once it has not been called for a specified time | ||
@@ -677,3 +789,52 @@ * | ||
},{}],4:[function(require,module,exports){ | ||
/** | ||
* Call passed function only once | ||
* @return {Function} self | ||
*/ | ||
function once() { | ||
var func = this | ||
, ran = false | ||
, memo; | ||
return function() { | ||
if (ran) return memo; | ||
ran = true; | ||
memo = func.apply(this, arguments); | ||
func = null; | ||
return memo; | ||
}; | ||
} | ||
/** | ||
* Execute a function when the condition function returns a truthy value | ||
* it runs the condition function every n milliseconds (default 50) | ||
* | ||
* @param {Function} condition function: if it returns true the callback is executed | ||
* @param {Function} callback: runs when the condition is true | ||
* @param {Number} maximum timeout before giving up (time in milliseconds) | ||
* @param {Function} a function called if timeout is reached | ||
* @param {Number} time interval when you run the condition function (time in milliseconds), default 50 ms | ||
*/ | ||
function waitFor(success, timeout, timedOutFunc, checkInterval){ | ||
var start = new Date(); | ||
var condition = this; | ||
checkInterval = checkInterval || 50; | ||
(function try_this(){ | ||
var now; | ||
if (condition()){ | ||
success(); | ||
} | ||
else { | ||
now = new Date(); | ||
if ((now - start) < timeout){ | ||
setTimeout(try_this, checkInterval); | ||
} | ||
else { | ||
if (timedOutFunc) timedOutFunc(); | ||
} | ||
} | ||
}()); | ||
} | ||
},{"./proto_util":8,"./utils":9}],4:[function(require,module,exports){ | ||
'use strict'; | ||
@@ -713,3 +874,5 @@ | ||
* - [deepClone](#deepClone) | ||
* - [keys](#keys) | ||
* - [allKeys](#allKeys) | ||
* - [values](#values) | ||
* - [keyOf](#keyOf) | ||
@@ -727,2 +890,3 @@ * - [allKeysOf](#allKeysOf) | ||
* - [omitKeys](#omitKeys) | ||
* - [isEqual](#isEqual) | ||
* | ||
@@ -738,3 +902,5 @@ * All these methods can be [chained](proto.js.html#Proto) | ||
deepClone: deepClone, | ||
keys: keys, | ||
allKeys: allKeys, | ||
values: values, | ||
keyOf: keyOf, | ||
@@ -749,3 +915,4 @@ allKeysOf: allKeysOf, | ||
pickKeys: pickKeys, | ||
omitKeys: omitKeys | ||
omitKeys: omitKeys, | ||
isEqual: isEqual | ||
}; | ||
@@ -777,2 +944,3 @@ | ||
* @param {Object} thisArg optional context (`this`) of callback call | ||
* @param {Boolean} onlyEnumerable An optional `true` to iterate enumerable properties only. | ||
* @return {Any} | ||
@@ -790,2 +958,3 @@ */ | ||
* @param {Object} thisArg optional context (`this`) of callback call | ||
* @param {Boolean} onlyEnumerable An optional `true` to iterate enumerable properties only. | ||
* @return {Integer} | ||
@@ -826,3 +995,3 @@ */ | ||
* ``` | ||
* This function should not be used to clone an array, both because it is inefficient and because the result will look very much like an array, it will not be a real array. | ||
* This function should not be used to clone an array, because it is inefficient. | ||
* | ||
@@ -833,2 +1002,5 @@ * @param {Object} self An object to be cloned | ||
function clone() { | ||
if (Array.isArray(this)) return this.slice(); | ||
if (this instanceof Date) return new Date(this); | ||
if (this instanceof RegExp) return new RegExp(this); | ||
var clonedObject = Object.create(this.constructor.prototype); | ||
@@ -954,8 +1126,11 @@ extend.call(clonedObject, this); | ||
eachKey.call(objNode, function(value, prop) { | ||
var loop = Array.isArray(objNode) ? Array.prototype.forEach : eachKey; | ||
loop.call(objNode, function(value, prop) { | ||
var descriptor = Object.getOwnPropertyDescriptor(objNode, prop); | ||
if (typeof value == 'object' && value != null) { | ||
if (typeof value == 'object' && value != null | ||
&& ! (value instanceof RegExp) && ! (value instanceof Date)) { | ||
if (! (selfNode.hasOwnProperty(prop) | ||
&& typeof selfNode[prop] == 'object' && selfNode[prop] != null)) | ||
selfNode[prop] = {}; | ||
selfNode[prop] = (Array.isArray(value)) ? [] : {}; | ||
_extendTree(selfNode[prop], value, onlyEnumerable, objTraversed); | ||
@@ -978,3 +1153,5 @@ } else | ||
function deepClone(onlyEnumerable) { | ||
var clonedObject = {}; | ||
if (this instanceof Date) return new Date(this); | ||
if (this instanceof RegExp) return new RegExp(this); | ||
var clonedObject = Array.isArray(this) ? [] : {}; | ||
deepExtend.call(clonedObject, this, onlyEnumerable); | ||
@@ -986,2 +1163,30 @@ return clonedObject; | ||
/** | ||
* Returns array of enumerable properties of the object | ||
* | ||
* @param {Object} self object to return keys of | ||
* @return {Array} | ||
*/ | ||
function keys() { | ||
return Object.keys(this); | ||
} | ||
/** | ||
* Returns array of values of the object's keys | ||
* | ||
* @param {Object} self object to return values from | ||
* @return {Array} | ||
*/ | ||
function values(onlyEnumerable) { | ||
var properties = onlyEnumerable | ||
? Object.keys(this) | ||
: allKeys.call(this); | ||
return properties.map(function(prop) { | ||
return this[prop]; | ||
}, this); | ||
} | ||
/** | ||
* Returns array of all property names of an object `self` (including non-enumerbale). | ||
@@ -1223,3 +1428,3 @@ * To get only enumerable properties, use `Object.keys()`. | ||
, obj = Object.create(this.constructor.prototype); | ||
keys.forEach(function(key){ | ||
keys.forEach(function(key) { | ||
if (this.hasOwnProperty(key)) | ||
@@ -1248,2 +1453,41 @@ obj[key] = this[key]; | ||
/** | ||
* Performs deep equality test of the object. Does not work with recursive objects | ||
* @param {Any} self object to compare | ||
* @param {Any} obj object to compare | ||
* @return {Boolean} | ||
*/ | ||
function isEqual(obj) { | ||
if (this === obj) return this !== 0 || 1/this == 1/obj; // 0 and -0 are considered not equal, although 0 === -0 is true | ||
if (this == null || obj == null) return false; | ||
var className = this.constructor.name; | ||
if (className != obj.constructor.name) return false; | ||
switch (className) { | ||
case 'String': | ||
return this == String(obj); | ||
case 'Number': | ||
return this != +this ? obj != +obj : (this == 0 ? 1/this == 1/obj : this == +obj); | ||
case 'Date': | ||
case 'Boolean': | ||
return +this == +obj; | ||
case 'RegExp': | ||
return this.source == obj.source | ||
&& this.global == obj.global | ||
&& this.multiline == obj.multiline | ||
&& this.ignoreCase == obj.ignoreCase; | ||
} | ||
if (typeof this != 'object' || typeof obj != 'object') return false; | ||
if (Array.isArray(this)) | ||
return this.length == obj.length | ||
&& this.every(function(item, index) { | ||
return isEqual.call(item, obj[index]); | ||
}); | ||
else | ||
return everyKey.call(this, function(value, key) { | ||
return isEqual.call(value, obj[key]); | ||
}); | ||
} | ||
},{"./utils":9}],6:[function(require,module,exports){ | ||
@@ -1256,2 +1500,3 @@ 'use strict'; | ||
* - [makeSubclass](#makeSubclass) | ||
* - [newApply](#newApply) | ||
* | ||
@@ -1263,3 +1508,4 @@ * These methods can be [chained](proto.js.html#Proto) | ||
createSubclass: createSubclass, | ||
makeSubclass: makeSubclass | ||
makeSubclass: makeSubclass, | ||
newApply: newApply | ||
}; | ||
@@ -1365,5 +1611,24 @@ | ||
/** | ||
* Calls constructor `this` with arguments passed as array | ||
* | ||
* @param {Function} thisClass A class constructor that will be called | ||
* @return {Array|Array-like} args Array of arguments that will be passed to constructor | ||
*/ | ||
function newApply(args) { | ||
if (! Array.isArray(args)) | ||
args = Array.prototype.slice.call(args); | ||
// "null" is context to pass to class constructor, first parameter of bind | ||
var args = [null].concat(args); | ||
return new (Function.prototype.bind.apply(this, args)); | ||
} | ||
},{"./proto_function":3,"./proto_object":5}],7:[function(require,module,exports){ | ||
'use strict'; | ||
var __ = require('./proto_object'); | ||
/** | ||
@@ -1374,2 +1639,8 @@ * - [firstUpperCase](#firstUpperCase) | ||
* - [toFunction](#toFunction) | ||
* - [toDate](#toDate) | ||
* - [toQueryString](#toQueryString) | ||
* - [fromQueryString](#fromQueryString) | ||
* - [jsonParse](#jsonParse) | ||
* - [hashCode](#hashCode) | ||
* - [unPrefix](#unPrefix) | ||
*/ | ||
@@ -1380,3 +1651,9 @@ var stringMethods = module.exports = { | ||
toRegExp: toRegExp, | ||
toFunction: toFunction | ||
toFunction: toFunction, | ||
toDate: toDate, | ||
toQueryString: toQueryString, | ||
fromQueryString: fromQueryString, | ||
jsonParse: jsonParse, | ||
hashCode: hashCode, | ||
unPrefix: unPrefix | ||
}; | ||
@@ -1435,10 +1712,122 @@ | ||
},{}],8:[function(require,module,exports){ | ||
/** | ||
* Converts string to date in a safe way so that the resiult is undefined if date is invalid | ||
* | ||
* @param {String|Date} self string or date object to convert to VALID date | ||
* @return {[type]} [description] | ||
*/ | ||
function toDate() { | ||
if (! this) return; | ||
try { | ||
var date = new Date(this); | ||
} catch (e) {} | ||
if (date && date.getTime && !isNaN(date.getTime())) | ||
return date; | ||
} | ||
/** | ||
* Convert params object to a url style query string (without "?") | ||
* | ||
* @param {Object} self The object hash to be converted | ||
* @param {Function} encode optional function used to encode data, encodeURIComponent is used if not specified | ||
* @return {String} the resulting query string | ||
*/ | ||
function toQueryString(encode) { | ||
var qs = '' | ||
, params = this || {} | ||
, encode = encode || encodeURIComponent; | ||
__.eachKey.call(params, function(value, key) { | ||
qs += key + '=' + encode(value) + '&'; | ||
}); | ||
return qs.slice(0, -1); | ||
} | ||
/** | ||
* Convert url style query string (without "?") into object hash | ||
* | ||
* @param {String} self The string to be converted | ||
* @param {Function} decode optional decode function, decodeURIComponent will be used if not supplied | ||
* @return {Object} The resulting object hash | ||
*/ | ||
function fromQueryString(decode) { | ||
var pairs = this.split('&') | ||
, results = {} | ||
, decode = decode || decodeURIComponent; | ||
pairs.forEach(function(pair) { | ||
var splitPair = pair.split('='); | ||
if (splitPair.length < 2) return; | ||
var key = splitPair[0] | ||
, value = decode(splitPair[1] || ''); | ||
if (!key) return; | ||
results[key] = value; | ||
}); | ||
return results; | ||
} | ||
/** | ||
* Safe JSON.parse, returns undefined if JSON.parse throws an exception | ||
* | ||
* @param {String} self JSON string representation of object | ||
* @return {Object|undefined} | ||
*/ | ||
function jsonParse() { | ||
try { | ||
return JSON.parse(this); | ||
} catch (e) {} | ||
} | ||
/** | ||
* Dan Bernstein's algorythm to create hash from string | ||
* | ||
* @param {String} self string to convert to hash | ||
* @return {Number} | ||
*/ | ||
function hashCode() { | ||
var hash = 5381 | ||
, str = this | ||
, len = str.length; | ||
for (var i = 0; i < len; i++) { | ||
var char = str.charCodeAt(i); | ||
hash = ((hash << 5) + hash) + char; /* hash * 33 + c */ | ||
} | ||
return hash; | ||
} | ||
/** | ||
* Removes given prefix from the string. If string does not begin from the prefix, returns undefined | ||
* | ||
* @param {String} self | ||
* @return {String} | ||
*/ | ||
function unPrefix(str) { | ||
if (this.indexOf(str) == 0) | ||
return this.replace(str, ''); | ||
} | ||
},{"./proto_object":5}],8:[function(require,module,exports){ | ||
'use strict'; | ||
/** | ||
* - [times](#times) | ||
* - [repeat](#repeat) | ||
* - [tap](#tap) | ||
* - [result](#result) | ||
* - [identity](#identity) | ||
*/ | ||
var utilMethods = module.exports = { | ||
tap: tap | ||
times: times, | ||
repeat: repeat, | ||
tap: tap, | ||
result: result, | ||
identity: identity | ||
}; | ||
@@ -1448,13 +1837,70 @@ | ||
/** | ||
* Calls `callback` `self` times with `thisArg` as context. Callback is passed iteration index from 0 to `self-1` | ||
* | ||
* @param {Integer} self | ||
* @param {Function} callback | ||
* @param {Any} thisArg | ||
* @return {Array} | ||
*/ | ||
function times(callback, thisArg) { | ||
var arr = Array(Math.max(0, this)); | ||
for (var i = 0; i < this; i++) | ||
arr[i] = callback.call(thisArg, i); | ||
return arr; | ||
} | ||
/** | ||
* Returns array with the first argument repeated `times` times | ||
* @param {Any} self | ||
* @param {Integer} times | ||
* @return {Array[Any]} | ||
*/ | ||
function repeat(times) { | ||
var arr = Array(Math.max(0, times));; | ||
for (var i = 0; i < times; i++) | ||
arr[i] = this; | ||
return arr; | ||
} | ||
/** | ||
* Function to tap into chained methods and to inspect intermediary result | ||
* | ||
* @param {Any} self value that's passed between chained methods | ||
* @param {Function} func function that will be called with the value | ||
* @param {Function} func function that will be called with the value (both as context and as the first parameter) | ||
* @return {Any} | ||
*/ | ||
function tap(func) { | ||
func(this); | ||
func.call(this, this); | ||
return this; | ||
}; | ||
/** | ||
* Calls function `self` (first parameter of _.result) with given context and arguments | ||
* | ||
* @param {Function|Any} self | ||
* @param {Any} thisArg context | ||
* @param {List} arguments extra arguments | ||
* @return {Any} | ||
*/ | ||
function result(thisArg) { //, arguments | ||
var args = Array.prototype.slice.call(arguments, 1); | ||
return typeof this == 'function' | ||
? this.apply(thisArg, args) | ||
: this; | ||
} | ||
/** | ||
* Returns self. Useful for using as an iterator if the actual value needs to be returned. Unlike in underscore and lodash, this function is NOT used as default iterator. | ||
* | ||
* @param {Any} self | ||
* @return {Any} | ||
*/ | ||
function identity() { | ||
return this; | ||
} | ||
},{}],9:[function(require,module,exports){ | ||
@@ -1499,6 +1945,6 @@ 'use strict'; | ||
return function findValueOrIndex(callback, thisArg) { | ||
return function findValueOrIndex(callback, thisArg, onlyEnumerable) { | ||
var caughtError; | ||
try { | ||
eachMethod.call(this, testItem, thisArg); | ||
eachMethod.call(this, testItem, thisArg, onlyEnumerable); | ||
} catch (found) { | ||
@@ -1505,0 +1951,0 @@ if (found === _error) throw caughtError; |
@@ -112,2 +112,3 @@ proto | ||
* [once](http://mailonline.github.io/proto/proto_function.js.html#once) | ||
* [waitFor](http://mailonline.github.io/proto/proto_function.js.html#waitFor) | ||
@@ -114,0 +115,0 @@ |
@@ -401,2 +401,50 @@ 'use strict'; | ||
}); | ||
it('should define waitFor function', function(done) { | ||
var semaphore = 'red', | ||
state = 'stopped'; | ||
_.waitFor(function (){ | ||
return semaphore == 'green'; | ||
}, | ||
function (){ | ||
state = 'running'; | ||
}, 1000); | ||
assert.equal(state, 'stopped'); | ||
setTimeout(function (){ | ||
assert.equal(state, 'stopped'); | ||
semaphore = 'green'; | ||
setTimeout(function (){ | ||
assert.equal(state, 'running'); | ||
done(); | ||
}, 100); | ||
}, 200); | ||
}); | ||
it('should define waitFor function 2', function(done) { | ||
var counter = 0; | ||
var timedOut = false; | ||
_.waitFor(function (){ | ||
counter++; | ||
return false; | ||
}, | ||
function (){ | ||
counter = "cannot pass here"; | ||
}, 500, | ||
function (){ | ||
timedOut = true; | ||
}, | ||
50); | ||
setTimeout(function (){ | ||
assert.equal(counter, 10); | ||
assert.equal(timedOut, true); | ||
done(); | ||
}, 600); | ||
}); | ||
}); |
189985
4687
137