-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction.js
More file actions
342 lines (292 loc) · 9.04 KB
/
Copy pathfunction.js
File metadata and controls
342 lines (292 loc) · 9.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/*jshint laxcomma: true, smarttabs: true*/
/*globals module,process,require,exports,__dirname,__filename */
'use strict';
/**
* Standard utilities for dealing with functions
* @module gaz/function
* @author Eric satterwhite
* @since 0.1.0
* @requires gaz/lang
* @requires gaz/array
*/
var mfn = require( './function' )
var toArray = require('./lang').toArray
var append = require('./array').append
var debug = require('debug')('hive:stdlib:function')
var _wrapDumbFunction
,enumerables
,i
,_extend;
_wrapDumbFunction = function( func ){
var args, i;
// covers common cases so we don't
// have to loop every time
switch( arguments.length){
case 0:
return func();
case 1:
return func( arguments[0]);
case 2:
return func( arguments[0], arguments[1], arguments[2]);
}
args = [];
for( i=0; i < arguments.length; i++ ){
args.push( 'arguments[' + i +']');
}
return eval('(func(' +args.join(',') + '))');
};
_extend = function( fn, key, value){
if( typeof key === 'string' ){
fn[key] = value;
}
};
/**
* An empty function
**/
exports.noop = function(){ };
/**
* Returns a function that calls the passed in function under the given context
* @param {Function} func the function to rebind
* @param {Object} self the object to bind to
* @return {Function} The resulting function
*/
exports.bind = function(func, self ){
var args
,newfn
,F;
if( typeof func === 'string'){
func = self[func];
}
args = arguments.length > 1 ? Array.prototype.slice.call(arguments, 2) : null
,F = function(){};
if( typeof func === 'function' && typeof func.apply == null){
func = _wrapDumbFunction( func );
}
newfn = function(){
var length = arguments.length
,context = self
,result;
if( func instanceof newfn ){
F.prototype = self.prototype;
context = new F;
}
result = ( !args && !length ) ?
func.call( context ) : // if there are no arguments, jut call it
func.apply( context , args && length ? args.concat( Array.prototype.slice.apply(arguments)) : args || arguments );
return context == self ? result : context;
};
return newfn;
};
exports.run = function( fn, scope, args, appendArgs ){
if( arguments.length === 2 ){
return fn.apply( scope, arguments );
}
var method = fn
,slice = Array.prototype.slice;
return function(){
var callArgs = args || arguments;
if(appendArgs === true ){
callArgs = slice.call( arguments, 0 );
callArgs = callArgs.concat( args );
}
return method.apply( scope || window, callArgs );
};
};
/**
* Returns a function that allow for afunction to accept either a (key, value )signature or a ({key1:value1, key2:value2}) signature
* @paran {Function} fn the function to overload
* @return {Function} a function wrapper around the original function
*/
exports.overloadSetter = function( fn ){
return function overloadedSetter( keyOrObj, value ){
if( typeof keyOrObj !== 'string' ){
for( var key in keyOrObj ){
fn.call( this, key, keyOrObj[key ]);
}
}else{
fn.call(this, keyOrObj, value );
}
return this;
};
};
/**
* similar to overloadSetter, but used for retrieving values. The new function will accept a ( v1, v2,v3 ) signature or a ([v1,v2,v3]) signature
* @param {Function} fn The function to overload
* @param {Boolean} plural
* @returns {Function}
*/
exports.overloadGetter = function( fn, plural ){
return function ( a ){
var ret = {}
,args
,_fn = fn;
if( typeof a != 'string'){
args = a;
} else if ( arguments.length > 1 ){
args = arguments;
} else if ( plural ){
args = [a];
}
if( args && args.length ){
for( var x = 0; x< args.length; x ++ ){
ret[ args[x] ] = _fn.call(_fn, args[x]);
}
} else{
return _fn.call(_fn, a);
}
return ret;
};
};
exports.simpleGetter = function( fn ){
return function overloadedGetter(key) {
var me = this;
if (arguments.length > 1) {
return Array.map.call(arguments, function(name) {
return fn.call(me, name);
});
} else {
return fn.call(this, key);
}
};
};
/**
* Allows for a setup function to be called before the original function. Setup function must return a function
* @param {Object} obj The object modify
* @param {String} key The key in the object to lazify
*/
exports.lazy = function( obj, key, setup ){
obj[key] = function(){
obj[key] = setup.apply( this, arguments );
obj[key].apply( this, arguments );
};
};
/**
* Given a function and some know params, will rturn a function that will be executed with additional arguments appended. Useful when not all parameters are known
* @param {Function} fn the function to use
* @param {Mixed} args Arbitrary known arguments
* @returns {Function} a function bound to a specific scope
*/
exports.partial = function( fn ){
var args = toArray( arguments );
args.shift();
return exports.bind.apply( this, append([fn, undefined], args));
};
exports.pass = function( fn, args, bind ){
if( args != null ){
args = Array.prototype.slice.call( args );
}
return function(){
return fn.apply( bind, args || arguments );
};
};
exports.periodical = function( fn, period, bind, args ){
var id = setInterval( this.pass(fn, args ,bind), period );
return id;
};
/**
* return the value of the first successfull function call of the passed in functions
* @param {...Function} an arbitrarty number of functions to test
* @return {?Object} the value of the firs function to execute without error, If there is not a successfull attempt, null will be returned
*/
exports.attempt = function(){
for (var i = 0, l = arguments.length; i < l; i++){
try {
return arguments[i]();
} catch (e){
debug("function attempt fail ", e, e.stack)
}
}
return null;
};
exports.intercept = function( orig, fn, bind ){
if(typeof fn != 'function'){
return orig;
}else{
return function( ){
var that = this
,args = arguments;
fn.target = that;
fn.method = orig;
return ( fn.apply( bind, args ) !== false ? orig.apply( that, args ) : null);
};
}
};
/**
* Ensures a minimum delay before a callback is executed after being called
* @function
* @param {Function} callback
* @param {Number} [delay=4] time in miliseconds to delay function execution
* @return {Function} a wrapper around the callback which ensures a delay
**/
exports.awaitDelay = mfn.awaitDelay
/**
* Returns a function that composes multiple functions, passing results to the next
* @function
* @param {...Function} fn one or more function to compase
* @return {Function} a function that when executed returns the result all the functions
**/
exports.compose = mfn.compose
/**
* Creates a function that will always return the passed in value
* @function
* @param {Mixed} value The value to be returned
* @return {Mixed} The original value
**/
exports.constant = mfn.constant
/**
* Creates a function that will delay the execution of fn until after delay milliseconds have elapsed since the last time it was invoked.
* @function
* @param {TYPE} fn the function to execut
* @param {TYPE} delay the amount of time in miliseconds to delay execution
* @return {Function} the debounced function wrapper
**/
exports.debounce = mfn.debounce
/**
* A function that returns a callback to call a method on an object
* @function
* @param {String} name The name of the method to call
* @return {Function}
* @example
var caller = function.func(test);
caller({test:function(){console.log("TEST!")}}) // TEST!`
**/
exports.func = mfn.func
exports.identity = mfn.identity
exports.makeIterator_ = mfn.makeIterator_
exports.prop = mfn.prop
exports.timeout = mfn.timeout
/**
* creates a function that executes a list of function passing the same aguments to each
* @function
* @param {...Function} fn A function to execute
* @return {Function} function that will execute all passed in functions
**/
exports.series = mfn.series
/**
* Creates a function that, when executed, will only call the fn function at most once per every interval milliseconds.
* If the throttled function is invoked more than once during the wait timeout, fn will also be called on the trailing edge of the timeout.
* Subsequent calls to the throttled function will return the result of the last fn call.
* @function
* @param {Function} function to throttle
* @param {Number} interval The maximum time interval in miliseconds
* @return {Function} A wrapper function to apply the throttled function
**/
exports.throttle = mfn.throttle
/**
* Executes a function a specified number of times
* @function
* @param {!Number} times number of times to call the function
* @param {Function} function the function to execute
**/
exports.times = mfn.times
/**
* Returns the first function passed as an argument to the second,
* allowing you to adjust arguments, run code before and after, and
* conditionally execute the original function
* @function
* @see module:gaz/function.partial
* @param {Function} fn function to execute
* @param {Function} wrapper the function to be passed into `fn`
* @return {Function}
**/
exports.wrap = mfn.wrap