torba 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2793 @@
1
+ /*!
2
+ * Lo-Dash v0.1.0 <https://github.com/bestiejs/lodash>
3
+ * Copyright 2012 John-David Dalton <http://allyoucanleet.com/>
4
+ * Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
5
+ * <http://documentcloud.github.com/underscore>
6
+ * Available under MIT license <http://mths.be/mit>
7
+ */
8
+ ;(function(window, undefined) {
9
+ 'use strict';
10
+
11
+ /** Used to escape and unescape characters in templates */
12
+ var escapes = {
13
+ '\\': '\\',
14
+ "'": "'",
15
+ 'r': '\r',
16
+ 'n': '\n',
17
+ 't': '\t',
18
+ 'u2028': '\u2028',
19
+ 'u2029': '\u2029'
20
+ };
21
+
22
+ // assign the result as keys and the keys as values
23
+ (function() {
24
+ for (var prop in escapes) {
25
+ escapes[escapes[prop]] = prop;
26
+ }
27
+ }());
28
+
29
+ /** Detect free variable `exports` */
30
+ var freeExports = typeof exports == 'object' && exports &&
31
+ (typeof global == 'object' && global && global == global.global && (window = global), exports);
32
+
33
+ /** Used to generate unique IDs */
34
+ var idCounter = 0;
35
+
36
+ /** Used to restore the original `_` reference in `noConflict` */
37
+ var oldDash = window._;
38
+
39
+ /** Used to replace unescape characters with their escaped counterpart */
40
+ var reEscaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
41
+
42
+ /**
43
+ * Used for `templateSettings` properties such as `escape`, `evaluate`,
44
+ * or `interpolate` with explicitly assigned falsey values to ensure no match
45
+ * is made.
46
+ */
47
+ var reNoMatch = /.^/;
48
+
49
+ /** Used to replace escaped characters with their unescaped counterpart */
50
+ var reUnescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
51
+
52
+ /** Object#toString result shortcuts */
53
+ var arrayClass = '[object Array]',
54
+ boolClass = '[object Boolean]',
55
+ dateClass = '[object Date]',
56
+ funcClass = '[object Function]',
57
+ numberClass = '[object Number]',
58
+ regexpClass = '[object RegExp]',
59
+ stringClass = '[object String]';
60
+
61
+ /** Native prototype shortcuts */
62
+ var ArrayProto = Array.prototype,
63
+ ObjProto = Object.prototype;
64
+
65
+ /** Native method shortcuts */
66
+ var concat = ArrayProto.concat,
67
+ hasOwnProperty = ObjProto.hasOwnProperty,
68
+ push = ArrayProto.push,
69
+ slice = ArrayProto.slice,
70
+ toString = ObjProto.toString,
71
+ unshift = ArrayProto.unshift;
72
+
73
+ /* Native method shortcuts for methods with the same name as other `lodash` methods */
74
+ var nativeIsArray = Array.isArray,
75
+ nativeIsFinite = window.isFinite,
76
+ nativeKeys = Object.keys;
77
+
78
+ /** Timer shortcuts */
79
+ var clearInteval = window.clearInterval,
80
+ setTimeout = window.setTimeout;
81
+
82
+ /** Compilation options for `_.difference` */
83
+ var differenceFactoryOptions = {
84
+ 'args': 'array',
85
+ 'top': 'var values=concat.apply([],slice.call(arguments,1))',
86
+ 'init': '[]',
87
+ 'inLoop': 'if(indexOf(values,array[index])<0)result.push(array[index])'
88
+ };
89
+
90
+ /** Compilation options for `_.every` */
91
+ var everyFactoryOptions = {
92
+ 'init': 'true',
93
+ 'inLoop': 'if(!callback(collection[index],index,collection))return !result'
94
+ };
95
+
96
+ /** Compilation options for `_.extend` */
97
+ var extendFactoryOptions = {
98
+ 'args': 'object',
99
+ 'init': 'object',
100
+ 'beforeLoop': 'for(var source,j=1,length=arguments.length;j<length;j++){\nsource=arguments[j]',
101
+ 'loopExp': 'index in source',
102
+ 'inLoop': 'object[index]=source[index]',
103
+ 'useHas': false,
104
+ 'afterLoop': '}'
105
+ };
106
+
107
+ /** Compilation options for `_.filter` */
108
+ var filterFactoryOptions = {
109
+ 'init': '[]',
110
+ 'inLoop': 'callback(collection[index],index,collection)&&result.push(collection[index])'
111
+ };
112
+
113
+ /** Compilation options for `_.forEach` */
114
+ var forEachFactoryOptions = {
115
+ 'args': 'collection,callback,thisArg',
116
+ 'top':
117
+ 'if(!callback){\ncallback=identity\n}\n' +
118
+ 'else if(thisArg){\ncallback=bind(callback,thisArg)\n}',
119
+ 'init': 'collection',
120
+ 'inLoop': 'callback(collection[index],index,collection)'
121
+ };
122
+
123
+ /** Compilation options for `_.keys` */
124
+ var keysFactoryOptions = {
125
+ 'args': 'object',
126
+ 'top': 'if(object!==Object(object))throw TypeError()',
127
+ 'init': '[]',
128
+ 'inLoop': 'result.push(index)'
129
+ };
130
+
131
+ /** Compilation options for `_.map` */
132
+ var mapFactoryOptions = {
133
+ 'init': '',
134
+ 'exits': '[]',
135
+ 'beforeLoop': {
136
+ 'array': 'result=Array(length)',
137
+ 'object': 'result=[]'
138
+ },
139
+ 'inLoop': {
140
+ 'array': 'result[index]=callback(collection[index],index,collection)',
141
+ 'object': 'result[result.length]=callback(collection[index],index,collection)'
142
+ }
143
+ };
144
+
145
+ /** Compilation options for `_.max` */
146
+ var maxFactoryOptions = {
147
+ 'top':
148
+ 'var current,result=-Infinity,computed=result;\n' +
149
+ 'if(!callback){\n' +
150
+ 'if(isArray(collection)&&collection[0]===+collection[0])return Math.max.apply(Math,collection);\n' +
151
+ 'if(isEmpty(collection))return result;\n' +
152
+ '}else if(thisArg)callback=bind(callback,thisArg)',
153
+ 'inLoop':
154
+ 'current=callback?callback(collection[index],index,collection):collection[index];\n' +
155
+ 'if(current>=computed)computed=current,result=collection[index]'
156
+ };
157
+
158
+ /*--------------------------------------------------------------------------*/
159
+
160
+ /**
161
+ * The `lodash` function.
162
+ *
163
+ * @name _
164
+ * @param {Mixed} value The value to wrap in a `Lodash` instance.
165
+ * @returns {Object} Returns a `Lodash` instance.
166
+ */
167
+ function lodash(value) {
168
+ // allow invoking `lodash` without the `new` operator
169
+ return new Lodash(value);
170
+ }
171
+
172
+ /**
173
+ * Creates a `Lodash` instance that wraps a value to allow chaining.
174
+ *
175
+ * @private
176
+ * @constructor
177
+ * @param {Mixed} value The value to wrap.
178
+ */
179
+ function Lodash(value) {
180
+ this._wrapped = value;
181
+ }
182
+
183
+ /*--------------------------------------------------------------------------*/
184
+
185
+ /**
186
+ * Checks if a `value` is an array.
187
+ *
188
+ * @static
189
+ * @memberOf _
190
+ * @category Objects
191
+ * @param {Mixed} value The value to check.
192
+ * @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
193
+ * @example
194
+ *
195
+ * (function() { return _.isArray(arguments); })();
196
+ * // => false
197
+ *
198
+ * _.isArray([1, 2, 3]);
199
+ * // => true
200
+ */
201
+ var isArray = nativeIsArray || function isArray(value) {
202
+ return toString.call(value) == arrayClass;
203
+ };
204
+
205
+ /**
206
+ * Checks if a `value` is empty. Arrays or strings with a length of 0 and
207
+ * objects with no enumerable own properties are considered "empty".
208
+ *
209
+ * @static
210
+ * @memberOf _
211
+ * @category Objects
212
+ * @param {Mixed} value The value to check.
213
+ * @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
214
+ * @example
215
+ *
216
+ * _.isEmpty([1, 2, 3]);
217
+ * // => false
218
+ *
219
+ * _.isEmpty({});
220
+ * // => true
221
+ */
222
+ var isEmpty = iterationFactory({
223
+ 'args': 'value',
224
+ 'iterate': 'objects',
225
+ 'top': 'var className=toString.call(value)',
226
+ 'init': 'true',
227
+ 'beforeLoop': 'if(className==arrayClass||className==stringClass)return !value.length',
228
+ 'inLoop': 'return false'
229
+ });
230
+
231
+ /*--------------------------------------------------------------------------*/
232
+
233
+ /**
234
+ * Compiles iteration functions.
235
+ *
236
+ * @private
237
+ * @param {Object} [options1, options2, ..] The compile options objects.
238
+ * @returns {Function} Returns the compiled function.
239
+ */
240
+ function iterationFactory() {
241
+ var prop,
242
+ index = -1,
243
+ array = {},
244
+ object = {},
245
+ options = {},
246
+ props = ['beforeLoop', 'loopExp', 'inLoop', 'afterLoop'];
247
+
248
+ while (++index < arguments.length) {
249
+ for (prop in arguments[index]) {
250
+ options[prop] = arguments[index][prop];
251
+ }
252
+ }
253
+
254
+ while ((prop = props.pop())) {
255
+ if (typeof options[prop] == 'object') {
256
+ array[prop] = options[prop].array;
257
+ object[prop] = options[prop].object;
258
+ } else {
259
+ array[prop] = object[prop] = options[prop] || '';
260
+ }
261
+ }
262
+
263
+ var args = options.args,
264
+ firstArg = /^[^,]+/.exec(args)[0],
265
+ init = options.init,
266
+ iterate = options.iterate,
267
+ arrayBranch = !(args == 'object' || iterate == 'objects'),
268
+ objectBranch = !(args == 'array' || iterate == 'arrays'),
269
+ useHas = options.useHas !== false;
270
+
271
+ return Function('arrayClass,bind,concat,funcClass,hasOwnProperty,identity,' +
272
+ 'indexOf,Infinity,isArray,isEmpty,Math,slice,stringClass,' +
273
+ 'toString,undefined',
274
+ '"use strict";' +
275
+ 'return function(' + args + '){\n' +
276
+ (options.top || '') + ';\n' +
277
+ ('var index, result' + (init ? '=' + init : '')) + ';\n' +
278
+ 'if(' + firstArg + '==undefined)return ' + (options.exits || 'result') + ';\n' +
279
+ (arrayBranch
280
+ ? 'var length=' + firstArg + '.length;\nindex=-1;\n' +
281
+ ((objectBranch ? 'if(length===+length){\n' : '') +
282
+ (array.beforeLoop || '') + ';\n' +
283
+ 'while(' + (array.loopExp || '++index<length') + '){\n' + array.inLoop + '\n}' +
284
+ (array.afterLoop || '') + ';\n' +
285
+ (objectBranch ? '\n}\n' : ''))
286
+ : ''
287
+ ) +
288
+ (objectBranch
289
+ ? ((arrayBranch ? 'else{\n' : '') +
290
+ (object.beforeLoop || '') + ';\n' +
291
+ 'for(' + (object.loopExp || 'index in ' + firstArg) + '){\n' +
292
+ (useHas ? 'if(hasOwnProperty.call(' + /\S+$/.exec(object.loopExp || firstArg)[0] + ',index)){\n' : '') +
293
+ object.inLoop +
294
+ (useHas ? '\n}' : '') +
295
+ '\n}' +
296
+ (object.afterLoop || '') + ';\n' +
297
+ (arrayBranch ? '\n}\n' : ''))
298
+ : ''
299
+ ) +
300
+ (options.bottom || '') + ';\n' +
301
+ 'return ' + (options.returns || 'result') +
302
+ '\n}'
303
+ )(arrayClass, bind, concat, funcClass, hasOwnProperty, identity,
304
+ indexOf, Infinity, isArray, isEmpty, Math, slice, stringClass, toString);
305
+ }
306
+
307
+ /**
308
+ * Unescapes characters, previously escaped for inclusion in compiled string
309
+ * literals, so they may compiled into function bodies.
310
+ * (Used for template interpolation, evaluation, or escaping)
311
+ *
312
+ * @private
313
+ * @param {String} string The string to unescape.
314
+ * @returns {String} Returns the unescaped string.
315
+ */
316
+ function unescape(string) {
317
+ return string.replace(reUnescaper, function(match, escaped) {
318
+ return escapes[escaped];
319
+ });
320
+ }
321
+
322
+ /*--------------------------------------------------------------------------*/
323
+
324
+ /**
325
+ * Checks if a given `target` value is present in a `collection` using strict
326
+ * equality for comparisons, i.e. `===`.
327
+ *
328
+ * @static
329
+ * @memberOf _
330
+ * @alias include
331
+ * @category Collections
332
+ * @param {Array|Object} collection The collection to iterate over.
333
+ * @param {Mixed} target The value to check for.
334
+ * @returns {Boolean} Returns `true` if `target` value is found, else `false`.
335
+ * @example
336
+ *
337
+ * _.contains([1, 2, 3], 3);
338
+ * // => true
339
+ */
340
+ var contains = iterationFactory({
341
+ 'args': 'collection,target',
342
+ 'init': 'false',
343
+ 'inLoop': 'if(collection[index]===target)return true'
344
+ });
345
+
346
+ /**
347
+ * Checks if the `callback` returns truthy for **all** values of a `collection`.
348
+ * The `callback` is invoked with 3 arguments; for arrays they are
349
+ * (value, index, array) and for objects they are (value, key, object).
350
+ *
351
+ * @static
352
+ * @memberOf _
353
+ * @alias all
354
+ * @category Collections
355
+ * @param {Array|Object} collection The collection to iterate over.
356
+ * @param {Function} callback The function called per iteration.
357
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
358
+ * @returns {Boolean} Returns `true` if all values pass the callback check, else `false`.
359
+ * @example
360
+ *
361
+ * _.every([true, 1, null, 'yes'], Boolean);
362
+ * => false
363
+ */
364
+ var every = iterationFactory(forEachFactoryOptions, everyFactoryOptions);
365
+
366
+ /**
367
+ * Examines each value in a `collection`, returning an array of all values the
368
+ * `callback` returns truthy for. The `callback` is invoked with 3 arguments;
369
+ * for arrays they are (value, index, array) and for objects they are
370
+ * (value, key, object).
371
+ *
372
+ * @static
373
+ * @memberOf _
374
+ * @alias select
375
+ * @category Collections
376
+ * @param {Array|Object} collection The collection to iterate over.
377
+ * @param {Function} callback The function called per iteration.
378
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
379
+ * @returns {Array} Returns a new array of values that passed callback check.
380
+ * @example
381
+ *
382
+ * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
383
+ * // => [2, 4, 6]
384
+ */
385
+ var filter = iterationFactory(forEachFactoryOptions, filterFactoryOptions);
386
+
387
+ /**
388
+ * Examines each value in a `collection`, returning the first one the `callback`
389
+ * returns truthy for. The function returns as soon as it finds an acceptable
390
+ * value, and does not iterate over the entire `collection`. The `callback` is
391
+ * invoked with 3 arguments; for arrays they are (value, index, array) and for
392
+ * objects they are (value, key, object).
393
+ *
394
+ * @static
395
+ * @memberOf _
396
+ * @alias detect
397
+ * @category Collections
398
+ * @param {Array|Object} collection The collection to iterate over.
399
+ * @param {Function} callback The function called per iteration.
400
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
401
+ * @returns {Mixed} Returns the value that passed the callback check, else `undefined`.
402
+ * @example
403
+ *
404
+ * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
405
+ * // => 2
406
+ */
407
+ var find = iterationFactory(forEachFactoryOptions, {
408
+ 'inLoop': 'if(callback(collection[index],index,collection))return collection[index]'
409
+ });
410
+
411
+ /**
412
+ * Iterates over a `collection`, executing the `callback` for each value in the
413
+ * `collection`. The `callback` is bound to the `thisArg` value, if one is passed.
414
+ * The `callback` is invoked with 3 arguments; for arrays they are
415
+ * (value, index, array) and for objects they are (value, key, object).
416
+ *
417
+ * @static
418
+ * @memberOf _
419
+ * @alias each
420
+ * @category Collections
421
+ * @param {Array|Object} collection The collection to iterate over.
422
+ * @param {Function} callback The function called per iteration.
423
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
424
+ * @returns {Array|Object} Returns the `collection`.
425
+ * @example
426
+ *
427
+ * _.forEach([1, 2, 3], function(num) { alert(num); });
428
+ * // => alerts each number in turn...
429
+ *
430
+ * _.forEach({ 'one': 1, 'two': 2, 'three': 3}, function(num) { alert(num); });
431
+ * // => alerts each number in turn...
432
+ */
433
+ var forEach = iterationFactory(forEachFactoryOptions);
434
+
435
+ /**
436
+ * Splits a `collection` into sets, grouped by the result of running each value
437
+ * through `callback`. The `callback` is invoked with 3 arguments; for arrays
438
+ * they are (value, index, array) and for objects they are (value, key, object).
439
+ * The `callback` argument may also be the name of a property to group by.
440
+ *
441
+ * @static
442
+ * @memberOf _
443
+ * @category Collections
444
+ * @param {Array|Object} collection The collection to iterate over.
445
+ * @param {Function|String} callback The function called per iteration or
446
+ * property name to group by.
447
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
448
+ * @returns {Object} Returns an object of grouped values.
449
+ * @example
450
+ *
451
+ * _.groupBy([1.3, 2.1, 2.4], function(num) { return Math.floor(num); });
452
+ * // => { '1': [1.3], '2': [2.1, 2.4] }
453
+ *
454
+ * _.groupBy(['one', 'two', 'three'], 'length');
455
+ * // => { '3': ['one', 'two'], '5': ['three'] }
456
+ */
457
+ function groupBy(collection, callback, thisArg) {
458
+ var result = {};
459
+ if (!isFunction(callback)) {
460
+ var prop = callback;
461
+ callback = function(collection) { return collection[prop]; };
462
+ }
463
+ forEach(collection, function(value, index, collection) {
464
+ var prop = callback(value, index, collection);
465
+ (result[prop] || (result[prop] = [])).push(value);
466
+ });
467
+ return result;
468
+ }
469
+
470
+ /**
471
+ * Calls the method named by `methodName` for each value of the `collection`.
472
+ * Additional arguments will be passed to each invoked method.
473
+ *
474
+ * @static
475
+ * @memberOf _
476
+ * @category Collections
477
+ * @param {Array|Object} collection The collection to iterate over.
478
+ * @param {String} methodName The name of the method to invoke.
479
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
480
+ * @returns {Array} Returns a new array of values returned from each invoked method.
481
+ * @example
482
+ *
483
+ * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
484
+ * // => [[1, 5, 7], [1, 2, 3]]
485
+ */
486
+ function invoke(collection, methodName) {
487
+ var args = slice.call(arguments, 2),
488
+ isFunc = isFunction(methodName);
489
+
490
+ return map(collection, function(value) {
491
+ return (isFunc ? methodName || value : value[methodName]).apply(value, args);
492
+ });
493
+ }
494
+
495
+ /**
496
+ * Produces a new array of values by mapping each value in the `collection`
497
+ * through a transformation `callback`. The `callback` is bound to the `thisArg`
498
+ * value, if one is passed. The `callback` is invoked with 3 arguments; for
499
+ * arrays they are (value, index, array) and for objects they are (value, key, object).
500
+ *
501
+ * @static
502
+ * @memberOf _
503
+ * @alias collect
504
+ * @category Collections
505
+ * @param {Array|Object} collection The collection to iterate over.
506
+ * @param {Function} callback The function called per iteration.
507
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
508
+ * @returns {Array} Returns a new array of values returned by the callback.
509
+ * @example
510
+ *
511
+ * _.map([1, 2, 3], function(num) { return num * 3; });
512
+ * // => [3, 6, 9]
513
+ *
514
+ * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
515
+ * // => [3, 6, 9]
516
+ */
517
+ var map = iterationFactory(forEachFactoryOptions, mapFactoryOptions);
518
+
519
+ /**
520
+ * Retrieves the maximum value of a `collection`. If `callback` is passed,
521
+ * it will be executed for each value in the `collection` to generate the
522
+ * criterion by which the value is ranked. The `callback` is invoked with 3
523
+ * arguments; for arrays they are (value, index, array) and for objects they
524
+ * are (value, key, object).
525
+ *
526
+ * @static
527
+ * @memberOf _
528
+ * @category Collections
529
+ * @param {Array|Object} collection The collection to iterate over.
530
+ * @param {Function} [callback] The function called per iteration.
531
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
532
+ * @returns {Mixed} Returns the maximum value.
533
+ * @example
534
+ *
535
+ * var stooges = [
536
+ * { 'name': 'moe', 'age': 40 },
537
+ * { 'name': 'larry', 'age': 50 },
538
+ * { 'name': 'curly', 'age': 60 }
539
+ * ];
540
+ *
541
+ * _.max(stooges, function(stooge) { return stooge.age; });
542
+ * // => { 'name': 'curly', 'age': 60 };
543
+ */
544
+ var max = iterationFactory(forEachFactoryOptions, maxFactoryOptions);
545
+
546
+ /**
547
+ * Retrieves the minimum value of a `collection`. If `callback` is passed,
548
+ * it will be executed for each value in the `collection` to generate the
549
+ * criterion by which the value is ranked. The `callback` is invoked with 3
550
+ * arguments; for arrays they are (value, index, array) and for objects they
551
+ * are (value, key, object).
552
+ *
553
+ * @static
554
+ * @memberOf _
555
+ * @category Collections
556
+ * @param {Array|Object} collection The collection to iterate over.
557
+ * @param {Function} [callback] The function called per iteration.
558
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
559
+ * @returns {Mixed} Returns the minimum value.
560
+ * @example
561
+ *
562
+ * _.min([10, 5, 100, 2, 1000]);
563
+ * // => 2
564
+ */
565
+ var min = iterationFactory(forEachFactoryOptions, maxFactoryOptions, {
566
+ 'top': maxFactoryOptions.top.replace('-', '').replace('max', 'min'),
567
+ 'inLoop': maxFactoryOptions.inLoop.replace('>=', '<')
568
+ });
569
+
570
+ /**
571
+ * Retrieves the value of a specified property from all values in a `collection`.
572
+ *
573
+ * @static
574
+ * @memberOf _
575
+ * @category Collections
576
+ * @param {Array|Object} collection The collection to iterate over.
577
+ * @param {String} property The property to pluck.
578
+ * @returns {Array} Returns a new array of property values.
579
+ * @example
580
+ *
581
+ * var stooges = [
582
+ * { 'name': 'moe', 'age': 40 },
583
+ * { 'name': 'larry', 'age': 50 },
584
+ * { 'name': 'curly', 'age': 60 }
585
+ * ];
586
+ *
587
+ * _.pluck(stooges, 'name');
588
+ * // => ['moe', 'larry', 'curly']
589
+ */
590
+ var pluck = iterationFactory(mapFactoryOptions, {
591
+ 'args': 'collection,property',
592
+ 'inLoop': {
593
+ 'array': 'result[index]=collection[index][property]',
594
+ 'object': 'result[result.length]=collection[index][property]'
595
+ }
596
+ });
597
+
598
+ /**
599
+ * Boils down a `collection` to a single value. The initial state of the
600
+ * reduction is `accumulator` and each successive step of it should be returned
601
+ * by the `callback`. The `callback` is bound to the `thisArg` value, if one is
602
+ * passed. The `callback` is invoked with 4 arguments; for arrays they are
603
+ * (accumulator, value, index, array) and for objects they are
604
+ * (accumulator, value, key, object).
605
+ *
606
+ * @static
607
+ * @memberOf _
608
+ * @alias foldl, inject
609
+ * @category Collections
610
+ * @param {Array|Object} collection The collection to iterate over.
611
+ * @param {Function} callback The function called per iteration.
612
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
613
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
614
+ * @returns {Mixed} Returns the accumulated value.
615
+ * @example
616
+ *
617
+ * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
618
+ * // => 6
619
+ */
620
+ var reduce = iterationFactory({
621
+ 'args':
622
+ 'collection,callback,accumulator,thisArg',
623
+ 'top':
624
+ 'var initial=arguments.length>2;\n' +
625
+ 'if(thisArg)callback=bind(callback,thisArg)',
626
+ 'init':
627
+ 'accumulator',
628
+ 'beforeLoop': {
629
+ 'array': 'if(!initial)result=collection[++index]'
630
+ },
631
+ 'inLoop': {
632
+ 'array':
633
+ 'result=callback(result,collection[index],index,collection)',
634
+ 'object':
635
+ 'result=initial\n' +
636
+ '?callback(result,collection[index],index,collection)\n' +
637
+ ':(initial=true,collection[index])'
638
+ }
639
+ });
640
+
641
+ /**
642
+ * The right-associative version of `_.reduce`. The `callback` is bound to the
643
+ * `thisArg` value, if one is passed. The `callback` is invoked with 4 arguments;
644
+ * for arrays they are (accumulator, value, index, array) and for objects they
645
+ * are (accumulator, value, key, object).
646
+ *
647
+ * @static
648
+ * @memberOf _
649
+ * @alias foldr
650
+ * @category Collections
651
+ * @param {Array|Object} collection The collection to iterate over.
652
+ * @param {Function} callback The function called per iteration.
653
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
654
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
655
+ * @returns {Mixed} Returns the accumulated value.
656
+ * @example
657
+ *
658
+ * var list = [[0, 1], [2, 3], [4, 5]];
659
+ * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
660
+ * // => [4, 5, 2, 3, 0, 1]
661
+ */
662
+ function reduceRight(collection, callback, result, thisArg) {
663
+ var initial = arguments.length > 2;
664
+ if (collection == undefined) {
665
+ return result;
666
+ }
667
+ if(thisArg) {
668
+ callback = bind(callback, thisArg);
669
+ }
670
+ var length = collection.length;
671
+ if (length === +length) {
672
+ if (length && !initial) {
673
+ result = collection[--length];
674
+ }
675
+ while (length--) {
676
+ result = callback(result, collection[length], length, collection);
677
+ }
678
+ return result;
679
+ }
680
+
681
+ var prop,
682
+ props = keys(collection);
683
+
684
+ length = props.length;
685
+ if (length && !initial) {
686
+ result = collection[props[--length]];
687
+ }
688
+ while (length--) {
689
+ prop = props[length];
690
+ result = callback(result, collection[prop], prop, collection);
691
+ }
692
+ return result;
693
+ }
694
+
695
+ /**
696
+ * The opposite of `_.filter`, this method returns the values of a `collection`
697
+ * that `callback` does **not** return truthy for. The `callback` is invoked
698
+ * with 3 arguments; for arrays they are (value, index, array) and for objects
699
+ * they are (value, key, object).
700
+ *
701
+ * @static
702
+ * @memberOf _
703
+ * @category Collections
704
+ * @param {Array|Object} collection The collection to iterate over.
705
+ * @param {Function} callback The function called per iteration.
706
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
707
+ * @returns {Array} Returns a new array of values that did **not** pass the callback check.
708
+ * @example
709
+ *
710
+ * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
711
+ * // => [1, 3, 5]
712
+ */
713
+ var reject = iterationFactory(forEachFactoryOptions, filterFactoryOptions, {
714
+ 'inLoop': '!' + filterFactoryOptions.inLoop
715
+ });
716
+
717
+ /**
718
+ * Produces a new array of shuffled `collection` values, using a version of the
719
+ * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
720
+ *
721
+ * @static
722
+ * @memberOf _
723
+ * @category Collections
724
+ * @param {Array|Object} collection The collection to shuffle.
725
+ * @returns {Array} Returns a new shuffled array.
726
+ * @example
727
+ *
728
+ * _.shuffle([1, 2, 3, 4, 5, 6]);
729
+ * // => [4, 1, 6, 3, 5, 2]
730
+ */
731
+ function shuffle(collection) {
732
+ var rand,
733
+ result = [];
734
+
735
+ forEach(collection, function(value, index) {
736
+ rand = Math.floor(Math.random() * (index + 1));
737
+ result[index] = result[rand];
738
+ result[rand] = value;
739
+ });
740
+ return result;
741
+ }
742
+
743
+ /**
744
+ * Gets the number of values in the `collection`.
745
+ *
746
+ * @static
747
+ * @memberOf _
748
+ * @category Collections
749
+ * @param {Array|Object} collection The collection inspect.
750
+ * @returns {Number} Returns the number of values in the collection.
751
+ * @example
752
+ *
753
+ * _.size({ 'one': 1, 'two': 2, 'three': 3 });
754
+ * // => 3
755
+ */
756
+ function size(collection) {
757
+ var className = toString.call(collection);
758
+ return className == arrayClass || className == stringClass
759
+ ? collection.length
760
+ : keys(collection).length;
761
+ }
762
+
763
+ /**
764
+ * Produces a new sorted array, ranked in ascending order by the results of
765
+ * running each value of a `collection` through `callback`. The `callback` is
766
+ * invoked with 3 arguments; for arrays they are (value, index, array) and for
767
+ * objects they are (value, key, object). The `callback` argument may also be
768
+ * the name of a property to sort by (e.g. 'length').
769
+ *
770
+ * @static
771
+ * @memberOf _
772
+ * @category Collections
773
+ * @param {Array|Object} collection The collection to iterate over.
774
+ * @param {Function|String} callback The function called per iteration or
775
+ * property name to sort by.
776
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
777
+ * @returns {Array} Returns a new array of sorted values.
778
+ * @example
779
+ *
780
+ * _.sortBy([1, 2, 3, 4, 5, 6], function(num) { return Math.sin(num); });
781
+ * // => [5, 4, 6, 3, 1, 2]
782
+ */
783
+ function sortBy(collection, callback, thisArg) {
784
+ if (!isFunction(callback)) {
785
+ var prop = callback;
786
+ callback = function(collection) { return collection[prop]; };
787
+ } else if (thisArg) {
788
+ callback = bind(callback, thisArg);
789
+ }
790
+ return pluck(map(collection, function(value, index) {
791
+ return {
792
+ 'criteria': callback(value, index, collection),
793
+ 'value': value
794
+ };
795
+ }).sort(function(left, right) {
796
+ var a = left.criteria,
797
+ b = right.criteria;
798
+
799
+ if (a === undefined) {
800
+ return 1;
801
+ }
802
+ if (b === undefined) {
803
+ return -1;
804
+ }
805
+ return a < b ? -1 : a > b ? 1 : 0;
806
+ }), 'value');
807
+ }
808
+
809
+ /**
810
+ * Checks if the `callback` returns truthy for **any** value of a `collection`.
811
+ * The function returns as soon as it finds passing value, and does not iterate
812
+ * over the entire `collection`. The `callback` is invoked with 3 arguments; for
813
+ * arrays they are (value, index, array) and for objects they are
814
+ * (value, key, object).
815
+ *
816
+ * @static
817
+ * @memberOf _
818
+ * @alias any
819
+ * @category Collections
820
+ * @param {Array|Object} collection The collection to iterate over.
821
+ * @param {Function} callback The function called per iteration.
822
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
823
+ * @returns {Boolean} Returns `true` if any value passes the callback check, else `false`.
824
+ * @example
825
+ *
826
+ * _.some([null, 0, 'yes', false]);
827
+ * // => true
828
+ */
829
+ var some = iterationFactory(forEachFactoryOptions, everyFactoryOptions, {
830
+ 'init': 'false',
831
+ 'inLoop': everyFactoryOptions.inLoop.replace('!', '')
832
+ });
833
+
834
+ /**
835
+ * Uses a binary search to determine the smallest index at which the `value`
836
+ * should be inserted into the `collection` in order to maintain the sort order
837
+ * of the `collection`. If `callback` is passed, it will be executed for each
838
+ * value in the `collection` to compute their sort ranking. The `callback` is
839
+ * invoked with 1 argument.
840
+ *
841
+ * @static
842
+ * @memberOf _
843
+ * @category Collections
844
+ * @param {Array} array The array to iterate over.
845
+ * @param {Mixed} value The value to evaluate.
846
+ * @param {Function} [callback] The function called per iteration.
847
+ * @returns {Number} Returns the index at which the value should be inserted
848
+ * into the collection.
849
+ * @example
850
+ *
851
+ * _.sortedIndex([10, 20, 30, 40, 50], 35);
852
+ * // => 3
853
+ */
854
+ function sortedIndex(array, object, callback) {
855
+ var low = 0,
856
+ high = array.length;
857
+
858
+ callback || (callback = identity);
859
+ while (low < high) {
860
+ var mid = (low + high) >> 1;
861
+ callback(array[mid]) < callback(object) ? (low = mid + 1) : (high = mid);
862
+ }
863
+ return low;
864
+ }
865
+
866
+ /**
867
+ * Converts the `collection`, into an array. Useful for converting the
868
+ * `arguments` object.
869
+ *
870
+ * @static
871
+ * @memberOf _
872
+ * @category Collections
873
+ * @param {Array|Object} collection The collection to convert.
874
+ * @returns {Array} Returns the new converted array.
875
+ * @example
876
+ *
877
+ * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
878
+ * // => [2, 3, 4]
879
+ */
880
+ function toArray(collection) {
881
+ if (!collection) {
882
+ return [];
883
+ }
884
+ if (isFunction(collection.toArray)) {
885
+ return collection.toArray();
886
+ }
887
+ var length = collection.length;
888
+ if (length === +length) {
889
+ return slice.call(collection);
890
+ }
891
+ return values(collection);
892
+ }
893
+
894
+ /**
895
+ * Produces an array of enumerable own property values of the `collection`.
896
+ *
897
+ * @static
898
+ * @memberOf _
899
+ * @alias methods
900
+ * @category Collections
901
+ * @param {Array|Object} collection The collection to inspect.
902
+ * @returns {Array} Returns a new array of property values.
903
+ * @example
904
+ *
905
+ * _.values({ 'one': 1, 'two': 2, 'three': 3 });
906
+ * // => [1, 2, 3]
907
+ */
908
+ var values = iterationFactory(mapFactoryOptions, {
909
+ 'args': 'collection',
910
+ 'inLoop': {
911
+ 'array': 'result[index]=collection[index]',
912
+ 'object': 'result[result.length]=collection[index]'
913
+ }
914
+ });
915
+
916
+ /*--------------------------------------------------------------------------*/
917
+
918
+ /**
919
+ * Produces a new array with all falsey values of `array` removed. The values
920
+ * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
921
+ *
922
+ * @static
923
+ * @memberOf _
924
+ * @category Arrays
925
+ * @param {Array} array The array to compact.
926
+ * @returns {Array} Returns a new filtered array.
927
+ * @example
928
+ *
929
+ * _.compact([0, 1, false, 2, '', 3]);
930
+ * // => [1, 2, 3]
931
+ */
932
+ var compact = iterationFactory({
933
+ 'args': 'array',
934
+ 'init': '[]',
935
+ 'inLoop': 'if(array[index])result.push(array[index])'
936
+ });
937
+
938
+ /**
939
+ * Produces a new array of `array` values not present in the other arrays
940
+ * using strict equality for comparisons, i.e. `===`.
941
+ *
942
+ * @static
943
+ * @memberOf _
944
+ * @category Arrays
945
+ * @param {Array} array The array to process.
946
+ * @param {Mixed} [array1, array2, ...] Arrays to check.
947
+ * @returns {Array} Returns a new array of `array` values not present in the
948
+ * other arrays.
949
+ * @example
950
+ *
951
+ * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
952
+ * // => [1, 3, 4]
953
+ */
954
+ var difference = iterationFactory(differenceFactoryOptions);
955
+
956
+ /**
957
+ * Gets the first value of the `array`. Pass `n` to return the first `n` values
958
+ * of the `array`.
959
+ *
960
+ * @static
961
+ * @memberOf _
962
+ * @alias head, take
963
+ * @category Arrays
964
+ * @param {Array} array The array to query.
965
+ * @param {Number} [n] The number of elements to return.
966
+ * @param {Object} [guard] Internally used to allow this method to work with
967
+ * others like `_.map` without using their callback `index` argument for `n`.
968
+ * @returns {Mixed} Returns the first value or an array of the first `n` values
969
+ * of the `array`.
970
+ * @example
971
+ *
972
+ * _.first([5, 4, 3, 2, 1]);
973
+ * // => 5
974
+ */
975
+ function first(array, n, guard) {
976
+ return (n == undefined || guard) ? array[0] : slice.call(array, 0, n);
977
+ }
978
+
979
+ /**
980
+ * Flattens a nested array (the nesting can be to any depth). If `shallow` is
981
+ * truthy, `array` will only be flattened a single level.
982
+ *
983
+ * @static
984
+ * @memberOf _
985
+ * @category Arrays
986
+ * @param {Array} array The array to compact.
987
+ * @param {Boolean} shallow A flag to indicate only flattening a single level.
988
+ * @returns {Array} Returns a new flattened array.
989
+ * @example
990
+ *
991
+ * _.flatten([1, [2], [3, [[4]]]]);
992
+ * // => [1, 2, 3, 4];
993
+ *
994
+ * _.flatten([1, [2], [3, [[4]]]], true);
995
+ * // => [1, 2, 3, [[4]]];
996
+ */
997
+ function flatten(array, shallow) {
998
+ if (shallow) {
999
+ return concat.apply([], array);
1000
+ }
1001
+ return reduce(array, function(accumulator, value) {
1002
+ if (isArray(value)) {
1003
+ push.apply(accumulator, flatten(value));
1004
+ return accumulator;
1005
+ }
1006
+ accumulator.push(value);
1007
+ return accumulator;
1008
+ }, []);
1009
+ }
1010
+
1011
+ /**
1012
+ * Gets the index at which the first occurrence of `value` is found using
1013
+ * strict equality for comparisons, i.e. `===`. If the `array` is already
1014
+ * sorted, passing `true` for `isSorted` will run a faster binary search.
1015
+ *
1016
+ * @static
1017
+ * @memberOf _
1018
+ * @category Arrays
1019
+ * @param {Array} array The array to search.
1020
+ * @param {Mixed} value The value to search for.
1021
+ * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
1022
+ * @returns {Number} Returns the index of the matched value or `-1`.
1023
+ * @example
1024
+ *
1025
+ * _.indexOf([1, 2, 3], 2);
1026
+ * // => 1
1027
+ */
1028
+ function indexOf(array, value, isSorted) {
1029
+ var index, length;
1030
+ if (array == undefined) {
1031
+ return -1;
1032
+ }
1033
+ if (isSorted) {
1034
+ index = sortedIndex(array, value);
1035
+ return array[index] === value ? index : -1;
1036
+ }
1037
+ for (index = 0, length = array.length; index < length; index++) {
1038
+ if (array[index] === value) {
1039
+ return index;
1040
+ }
1041
+ }
1042
+ return -1;
1043
+ }
1044
+
1045
+ /**
1046
+ * Gets all but the last value of the `array`. Pass `n` to exclude the last `n`
1047
+ * values from the result.
1048
+ *
1049
+ * @static
1050
+ * @memberOf _
1051
+ * @category Arrays
1052
+ * @param {Array} array The array to query.
1053
+ * @param {Number} [n] The number of elements to return.
1054
+ * @param {Object} [guard] Internally used to allow this method to work with
1055
+ * others like `_.map` without using their callback `index` argument for `n`.
1056
+ * @returns {Array} Returns all but the last value or `n` values of the `array`.
1057
+ * @example
1058
+ *
1059
+ * _.initial([5, 4, 3, 2, 1]);
1060
+ * // => [5, 4, 3, 2]
1061
+ */
1062
+ function initial(array, n, guard) {
1063
+ return slice.call(array, 0, -((n == undefined || guard) ? 1 : n));
1064
+ }
1065
+
1066
+ /**
1067
+ * Computes the intersection of all the passed-in arrays.
1068
+ *
1069
+ * @static
1070
+ * @memberOf _
1071
+ * @alias intersect
1072
+ * @category Arrays
1073
+ * @param {Mixed} [array1, array2, ...] Arrays to process.
1074
+ * @returns {Array} Returns a new array of unique values, in order, that are
1075
+ * present in **all** of the arrays.
1076
+ * @example
1077
+ *
1078
+ * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
1079
+ * // => [1, 2]
1080
+ */
1081
+ function intersection(array) {
1082
+ var rest = slice.call(arguments, 1);
1083
+ return filter(uniq(array), function(value) {
1084
+ return every(rest, function(other) {
1085
+ return indexOf(other, value) >= 0;
1086
+ });
1087
+ });
1088
+ }
1089
+
1090
+ /**
1091
+ * Gets the last value of the `array`. Pass `n` to return the lasy `n` values
1092
+ * of the `array`.
1093
+ *
1094
+ * @static
1095
+ * @memberOf _
1096
+ * @category Arrays
1097
+ * @param {Array} array The array to query.
1098
+ * @param {Number} [n] The number of elements to return.
1099
+ * @param {Object} [guard] Internally used to allow this method to work with
1100
+ * others like `_.map` without using their callback `index` argument for `n`.
1101
+ * @returns {Array} Returns all but the last value or `n` values of the `array`.
1102
+ * @example
1103
+ *
1104
+ * _.last([5, 4, 3, 2, 1]);
1105
+ * // => 1
1106
+ */
1107
+ function last(array, n, guard) {
1108
+ var length = array.length;
1109
+ return (n == undefined || guard) ? array[length - 1] : slice.call(array, -n || length);
1110
+ }
1111
+
1112
+ /**
1113
+ * Gets the index at which the last occurrence of `value` is found using
1114
+ * strict equality for comparisons, i.e. `===`.
1115
+ *
1116
+ * @static
1117
+ * @memberOf _
1118
+ * @category Arrays
1119
+ * @param {Array} array The array to search.
1120
+ * @param {Mixed} value The value to search for.
1121
+ * @returns {Number} Returns the index of the matched value or `-1`.
1122
+ * @example
1123
+ *
1124
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
1125
+ * // => 4
1126
+ */
1127
+ function lastIndexOf(array, value) {
1128
+ if (array == undefined) {
1129
+ return -1;
1130
+ }
1131
+ var index = array.length;
1132
+ while (index--) {
1133
+ if (array[index] === value) {
1134
+ return index;
1135
+ }
1136
+ }
1137
+ return -1;
1138
+ }
1139
+
1140
+ /**
1141
+ * Creates an array of numbers (positive and/or negative) progressing from
1142
+ * `start` up to but not including `stop`. This method is a port of Python's
1143
+ * `range()` function. See http://docs.python.org/library/functions.html#range.
1144
+ *
1145
+ * @static
1146
+ * @memberOf _
1147
+ * @category Arrays
1148
+ * @param {Number} [start=0] The start of the range.
1149
+ * @param {Number} end The end of the range.
1150
+ * @param {Number} [step=1] The value to increment or descrement by.
1151
+ * @returns {Array} Returns a new range array.
1152
+ * @example
1153
+ *
1154
+ * _.range(10);
1155
+ * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1156
+ *
1157
+ * _.range(1, 11);
1158
+ * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1159
+ *
1160
+ * _.range(0, 30, 5);
1161
+ * // => [0, 5, 10, 15, 20, 25]
1162
+ *
1163
+ * _.range(0, -10, -1);
1164
+ * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
1165
+ *
1166
+ * _.range(0);
1167
+ * // => []
1168
+ */
1169
+ function range(start, end, step) {
1170
+ step || (step = 1);
1171
+ if (arguments.length < 2) {
1172
+ end = start || 0;
1173
+ start = 0;
1174
+ }
1175
+
1176
+ var index = -1,
1177
+ length = Math.max(Math.ceil((end - start) / step), 0),
1178
+ result = Array(length);
1179
+
1180
+ while (++index < length) {
1181
+ result[index] = start;
1182
+ start += step;
1183
+ }
1184
+ return result;
1185
+ }
1186
+
1187
+ /**
1188
+ * The opposite of `_.initial`, this method gets all but the first value of
1189
+ * the `array`. Pass `n` to exclude the first `n` values from the result.
1190
+ *
1191
+ * @static
1192
+ * @memberOf _
1193
+ * @alias tail
1194
+ * @category Arrays
1195
+ * @param {Array} array The array to query.
1196
+ * @param {Number} [n] The number of elements to return.
1197
+ * @param {Object} [guard] Internally used to allow this method to work with
1198
+ * others like `_.map` without using their callback `index` argument for `n`.
1199
+ * @returns {Array} Returns all but the first value or `n` values of the `array`.
1200
+ * @example
1201
+ *
1202
+ * _.rest([5, 4, 3, 2, 1]);
1203
+ * // => [4, 3, 2, 1]
1204
+ */
1205
+ function rest(array, n, guard) {
1206
+ return slice.call(array, (n == undefined || guard) ? 1 : n);
1207
+ }
1208
+
1209
+ /**
1210
+ * Computes the union of the passed-in arrays.
1211
+ *
1212
+ * @static
1213
+ * @memberOf _
1214
+ * @category Arrays
1215
+ * @param {Mixed} [array1, array2, ...] Arrays to process.
1216
+ * @returns {Array} Returns a new array of unique values, in order, that are
1217
+ * present in one or more of the arrays.
1218
+ * @example
1219
+ *
1220
+ * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
1221
+ * // => [1, 2, 3, 101, 10]
1222
+ */
1223
+ function union() {
1224
+ return uniq(flatten(arguments, true));
1225
+ }
1226
+
1227
+ /**
1228
+ * Produces a duplicate-value-free version of the `array` using strict equality
1229
+ * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
1230
+ * for `isSorted` will run a faster algorithm. If `callback` is passed,
1231
+ * each value of `array` is passed through a transformation `callback` before
1232
+ * uniqueness is computed. The `callback` is invoked with 3 arguments;
1233
+ * (value, index, array).
1234
+ *
1235
+ * @static
1236
+ * @memberOf _
1237
+ * @alias unique
1238
+ * @category Arrays
1239
+ * @param {Array} array The array to process.
1240
+ * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
1241
+ * @param {Function} [callback] A
1242
+ * @returns {Array} Returns a duplicate-value-free array.
1243
+ * @example
1244
+ *
1245
+ * _.uniq([1, 2, 1, 3, 1, 4]);
1246
+ * // => [1, 2, 3, 4]
1247
+ */
1248
+ function uniq(array, isSorted, callback) {
1249
+ var initial = callback ? map(array, callback) : array,
1250
+ result = [];
1251
+
1252
+ // the `isSorted` flag is irrelevant if the array only contains two elements.
1253
+ if (array.length < 3) {
1254
+ isSorted = true;
1255
+ }
1256
+ reduce(initial, function(accumulator, value, index) {
1257
+ if (isSorted ? last(accumulator) !== value || !accumulator.length : indexOf(accumulator, value) < 0) {
1258
+ accumulator.push(value);
1259
+ result.push(array[index]);
1260
+ }
1261
+ return accumulator;
1262
+ }, []);
1263
+
1264
+ return result;
1265
+ }
1266
+
1267
+ /**
1268
+ * Produces a new array with all occurrences of the values removed using strict
1269
+ * equality for comparisons, i.e. `===`.
1270
+ *
1271
+ * @static
1272
+ * @memberOf _
1273
+ * @category Arrays
1274
+ * @param {Array} array The array to filter.
1275
+ * @param {Mixed} [value1, value2, ...] Values to remove.
1276
+ * @returns {Array} Returns a new filtered array.
1277
+ * @example
1278
+ *
1279
+ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
1280
+ * // => [2, 3, 4]
1281
+ */
1282
+ var without = iterationFactory(differenceFactoryOptions, {
1283
+ 'top': 'var values=slice.call(arguments,1)',
1284
+ 'init': '[]'
1285
+ });
1286
+
1287
+ /**
1288
+ * Merges together the values of each of the arrays with the value at the
1289
+ * corresponding position. Useful for separate data sources that are coordinated
1290
+ * through matching array indexes. For a matrix of nested arrays, `_.zip.apply(...)`
1291
+ * can transpose the matrix in a similar fashion.
1292
+ *
1293
+ * @static
1294
+ * @memberOf _
1295
+ * @category Arrays
1296
+ * @param {Mixed} [array1, array2, ...] Arrays to process.
1297
+ * @returns {Array} Returns a new array of merged arrays.
1298
+ * @example
1299
+ *
1300
+ * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
1301
+ * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
1302
+ */
1303
+ function zip() {
1304
+ var index = -1,
1305
+ length = max(pluck(arguments, 'length')),
1306
+ result = Array(length);
1307
+
1308
+ while (++index < length) {
1309
+ result[index] = pluck(arguments, index);
1310
+ }
1311
+ return result;
1312
+ }
1313
+
1314
+ /*--------------------------------------------------------------------------*/
1315
+
1316
+ /**
1317
+ * Creates a new function that is restricted to executing only after it is
1318
+ * called a given number of `times`.
1319
+ *
1320
+ * @static
1321
+ * @memberOf _
1322
+ * @category Functions
1323
+ * @param {Number} times The number of times the function must be called before
1324
+ * it is executed.
1325
+ * @param {Function} func The function to restrict.
1326
+ * @returns {Function} Returns the new restricted function.
1327
+ * @example
1328
+ *
1329
+ * var renderNotes = _.after(notes.length, render);
1330
+ * _.forEach(notes, function(note) {
1331
+ * note.asyncSave({ 'success': renderNotes });
1332
+ * });
1333
+ * // renderNotes is run once, after all notes have saved.
1334
+ */
1335
+ function after(times, func) {
1336
+ if (times < 1) {
1337
+ return func();
1338
+ }
1339
+ return function() {
1340
+ if (--times < 1) {
1341
+ return func.apply(this, arguments);
1342
+ }
1343
+ };
1344
+ }
1345
+
1346
+ /**
1347
+ * Creates a new function that, when called, invokes `func` with the `this`
1348
+ * binding of `thisArg` and prepends additional arguments to those passed to
1349
+ * the bound function.
1350
+ *
1351
+ * @static
1352
+ * @memberOf _
1353
+ * @category Functions
1354
+ * @param {Function} func The function to bind.
1355
+ * @param @param {Mixed} [thisArg] The `this` binding of `func`.
1356
+ * @param {Mixed} [arg1, arg2, ...] Arguments to prepend to those passed to the bound function.
1357
+ * @returns {Function} Returns the new bound function.
1358
+ * @example
1359
+ *
1360
+ * var func = function(greeting) { return greeting + ': ' + this.name; };
1361
+ * func = _.bind(func, { 'name': 'moe' }, 'hi');
1362
+ * func();
1363
+ * // => 'hi: moe'
1364
+ */
1365
+ function bind(func, thisArg) {
1366
+ var args = slice.call(arguments, 2),
1367
+ argsLength = args.length;
1368
+
1369
+ return function() {
1370
+ args.length = argsLength;
1371
+ push.apply(args, arguments);
1372
+ return func.apply(thisArg, args);
1373
+ };
1374
+ }
1375
+
1376
+ /**
1377
+ * Binds methods on the `object` to the object, overwriting the non-bound method.
1378
+ * If no method names are provided, all the function properties of the `object`
1379
+ * will be bound.
1380
+ *
1381
+ * @static
1382
+ * @memberOf _
1383
+ * @category Functions
1384
+ * @param {Object} object The object to bind and assign the bound methods to.
1385
+ * @param {Mixed} [methodName1, methodName2, ...] Method names on the object to bind.
1386
+ * @returns {Object} Returns the `object`.
1387
+ * @example
1388
+ *
1389
+ * var buttonView = {
1390
+ * 'label': 'lodash',
1391
+ * 'onClick': function() { alert('clicked: ' + this.label); },
1392
+ * 'onHover': function() { console.log('hovering: ' + this.label); }
1393
+ * };
1394
+ *
1395
+ * _.bindAll(buttonView);
1396
+ * jQuery('#lodash_button').on('click', buttonView.onClick);
1397
+ * // => When the button is clicked, `this.label` will have the correct value
1398
+ */
1399
+ function bindAll(object) {
1400
+ var funcs = arguments,
1401
+ index = 1;
1402
+
1403
+ if (funcs.length == 1) {
1404
+ index = 0;
1405
+ funcs = functions(object);
1406
+ }
1407
+ for (var length = funcs.length; index < length; index++) {
1408
+ object[funcs[index]] = bind(object[funcs[index]], object);
1409
+ }
1410
+ return object;
1411
+ }
1412
+
1413
+ /**
1414
+ * Creates a new function that is the composition of the passed functions,
1415
+ * where each function consumes the return value of the function that follows.
1416
+ * In math terms, composing thefunctions `f()`, `g()`, and `h()` produces `f(g(h()))`.
1417
+ *
1418
+ * @static
1419
+ * @memberOf _
1420
+ * @category Functions
1421
+ * @param {Mixed} [func1, func2, ...] Functions to compose.
1422
+ * @returns {Function} Returns the new composed function.
1423
+ * @example
1424
+ *
1425
+ * var greet = function(name) { return 'hi: ' + name; };
1426
+ * var exclaim = function(statement) { return statement + '!'; };
1427
+ * var welcome = _.compose(exclaim, greet);
1428
+ * welcome('moe');
1429
+ * // => 'hi: moe!'
1430
+ */
1431
+ function compose() {
1432
+ var funcs = arguments;
1433
+ return function() {
1434
+ var args = arguments,
1435
+ length = funcs.length;
1436
+
1437
+ while (length--) {
1438
+ args = [funcs[length].apply(this, args)];
1439
+ }
1440
+ return args[0];
1441
+ };
1442
+ }
1443
+
1444
+ /**
1445
+ * Creates a new function that will postpone its execution until after `wait`
1446
+ * milliseconds have elapsed since the last time it was invoked. Pass `true`
1447
+ * for `immediate` to cause debounce to invoke the function on the leading,
1448
+ * instead of the trailing, edge of the `wait` timeout.
1449
+ *
1450
+ * @static
1451
+ * @memberOf _
1452
+ * @category Functions
1453
+ * @param {Function} func The function to debounce.
1454
+ * @param {Number} wait The number of milliseconds to postone.
1455
+ * @param {Boolean} immediate A flag to indicate execution is on the leading
1456
+ * edge of the timeout.
1457
+ * @returns {Function} Returns the new debounced function.
1458
+ * @example
1459
+ *
1460
+ * var lazyLayout = _.debounce(calculateLayout, 300);
1461
+ * jQuery(window).on('resize', lazyLayout);
1462
+ */
1463
+ function debounce(func, wait, immediate) {
1464
+ var timeout;
1465
+ return function() {
1466
+ var args = arguments,
1467
+ thisArg = this;
1468
+
1469
+ if (immediate && !timeout) {
1470
+ func.apply(thisArg, args);
1471
+ }
1472
+ clearTimeout(timeout);
1473
+ timeout = setTimeout(function() {
1474
+ timeout = undefined;
1475
+ if (!immediate) {
1476
+ func.apply(thisArg, args);
1477
+ }
1478
+ }, wait);
1479
+ };
1480
+ }
1481
+
1482
+ /**
1483
+ * Invokes the `func` function after `wait` milliseconds. Additional arguments
1484
+ * are passed `func` when it is invoked.
1485
+ *
1486
+ * @static
1487
+ * @memberOf _
1488
+ * @category Functions
1489
+ * @param {Function} func The function to delay.
1490
+ * @param {Number} wait The number of milliseconds to delay execution.
1491
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
1492
+ * @returns {Number} Returns the `setTimeout` timeout id.
1493
+ * @example
1494
+ *
1495
+ * var log = _.bind(console.log, console);
1496
+ * _.delay(log, 1000, 'logged later');
1497
+ * // => 'logged later' (Appears after one second.)
1498
+ */
1499
+ function delay(func, wait) {
1500
+ var args = slice.call(arguments, 2);
1501
+ return setTimeout(function() { return func.apply(undefined, args); }, wait);
1502
+ }
1503
+
1504
+ /**
1505
+ * Defers invoking the `func` function until the current call stack has cleared.
1506
+ * Additional arguments are passed to `func` when it is invoked.
1507
+ *
1508
+ * @static
1509
+ * @memberOf _
1510
+ * @category Functions
1511
+ * @param {Function} func The function to defer.
1512
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
1513
+ * @returns {Number} Returns the `setTimeout` timeout id.
1514
+ * @example
1515
+ *
1516
+ * _.defer(function() { alert('deferred'); });
1517
+ * // Returns from the function before the alert runs.
1518
+ */
1519
+ function defer(func) {
1520
+ var args = slice.call(arguments, 1);
1521
+ return setTimeout(function() { return func.apply(undefined, args); }, 1);
1522
+ }
1523
+
1524
+ /**
1525
+ * Creates a new function that memoizes the result of `func`. If `resolver` is
1526
+ * passed, it will be used to determine the cache key for storing the result
1527
+ * based on the arguments passed to the memoized function. By default, the first
1528
+ * argument passed to the memoized function is used as the cache key.
1529
+ *
1530
+ * @static
1531
+ * @memberOf _
1532
+ * @category Functions
1533
+ * @param {Function} func The function to have its output memoized.
1534
+ * @param {Function} [resolver] A function used to resolve the cache key.
1535
+ * @returns {Function} Returns the new memoizing function.
1536
+ * @example
1537
+ *
1538
+ * var fibonacci = _.memoize(function(n) {
1539
+ * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
1540
+ * });
1541
+ */
1542
+ function memoize(func, resolver) {
1543
+ var cache = {};
1544
+ return function() {
1545
+ var prop = resolver ? resolver.apply(this, arguments) : arguments[0];
1546
+ return hasOwnProperty.call(cache, prop)
1547
+ ? cache[prop]
1548
+ : (cache[prop] = func.apply(this, arguments));
1549
+ };
1550
+ }
1551
+
1552
+ /**
1553
+ * Creates a new function that is restricted to one execution. Repeat calls to
1554
+ * the function will return the value of the first call.
1555
+ *
1556
+ * @static
1557
+ * @memberOf _
1558
+ * @category Functions
1559
+ * @param {Function} func The function to restrict.
1560
+ * @returns {Function} Returns the new restricted function.
1561
+ * @example
1562
+ *
1563
+ * var initialize = _.once(createApplication);
1564
+ * initialize();
1565
+ * initialize();
1566
+ * // Application is only created once.
1567
+ */
1568
+ function once(func) {
1569
+ var result,
1570
+ ran = false;
1571
+
1572
+ return function() {
1573
+ if (ran) {
1574
+ return result;
1575
+ }
1576
+ ran = true;
1577
+ result = func.apply(this, arguments);
1578
+ return result;
1579
+ };
1580
+ }
1581
+
1582
+ /**
1583
+ * Creates a new function that, when invoked, will only call the original
1584
+ * function at most once per every `wait` milliseconds.
1585
+ *
1586
+ * @static
1587
+ * @memberOf _
1588
+ * @category Functions
1589
+ * @param {Function} func The function to throttle.
1590
+ * @param {Number} wait The number of milliseconds to throttle executions to.
1591
+ * @returns {Function} Returns the new throttled function.
1592
+ * @example
1593
+ *
1594
+ * var throttled = _.throttle(updatePosition, 100);
1595
+ * jQuery(window).on('scroll', throttled);
1596
+ */
1597
+ function throttle(func, wait) {
1598
+ var args, more, result, thisArg, throttling, timeout,
1599
+ whenDone = debounce(function() { more = throttling = false; }, wait);
1600
+
1601
+ return function() {
1602
+ args = arguments;
1603
+ thisArg = this;
1604
+
1605
+ if (!timeout) {
1606
+ timeout = setTimeout(function() {
1607
+ timeout = undefined;
1608
+ if (more) {
1609
+ func.apply(thisArg, args);
1610
+ }
1611
+ whenDone();
1612
+ }, wait);
1613
+ }
1614
+ if (throttling) {
1615
+ more = true;
1616
+ } else {
1617
+ result = func.apply(thisArg, args);
1618
+ }
1619
+ whenDone();
1620
+ throttling = true;
1621
+ return result;
1622
+ };
1623
+ }
1624
+
1625
+ /**
1626
+ * Create a new function that passes the `func` function to the `wrapper`
1627
+ * function as its first argument. Additional arguments are appended to those
1628
+ * passed to the `wrapper` function.
1629
+ *
1630
+ * @static
1631
+ * @memberOf _
1632
+ * @category Functions
1633
+ * @param {Function} func The function to wrap.
1634
+ * @param {Function} wrapper The wrapper function.
1635
+ * @param {Mixed} [arg1, arg2, ...] Arguments to append to those passed to the wrapper.
1636
+ * @returns {Function} Returns the new function.
1637
+ * @example
1638
+ *
1639
+ * var hello = function(name) { return 'hello: ' + name; };
1640
+ * hello = _.wrap(hello, function(func) {
1641
+ * return 'before, ' + func('moe') + ', after';
1642
+ * });
1643
+ * hello();
1644
+ * // => 'before, hello: moe, after'
1645
+ */
1646
+ function wrap(func, wrapper) {
1647
+ return function() {
1648
+ var args = [func];
1649
+ push.apply(args, arguments);
1650
+ return wrapper.apply(this, args);
1651
+ };
1652
+ }
1653
+
1654
+ /*--------------------------------------------------------------------------*/
1655
+
1656
+ /**
1657
+ * Create a shallow clone of the `value`. Any nested objects or arrays will be
1658
+ * assigned by reference and not cloned.
1659
+ *
1660
+ * @static
1661
+ * @memberOf _
1662
+ * @category Objects
1663
+ * @param {Mixed} value The value to clone.
1664
+ * @returns {Mixed} Returns the cloned `value`.
1665
+ * @example
1666
+ *
1667
+ * _.clone({ 'name': 'moe' });
1668
+ * // => { 'name': 'moe' };
1669
+ */
1670
+ function clone(value) {
1671
+ if (value !== Object(value)) {
1672
+ return value;
1673
+ }
1674
+ return isArray(value) ? value.slice() : extend({}, value);
1675
+ }
1676
+
1677
+ /**
1678
+ * Assigns missing properties in `object` with default values from the defaults
1679
+ * objects. As soon as a property is set, additional defaults of the same
1680
+ * property will be ignored.
1681
+ *
1682
+ * @static
1683
+ * @memberOf _
1684
+ * @category Objects
1685
+ * @param {Object} object The object to populate.
1686
+ * @param {Object} [defaults1, defaults2, ..] The defaults objects to apply to `object`.
1687
+ * @returns {Object} Returns `object`.
1688
+ * @example
1689
+ *
1690
+ * var iceCream = { 'flavor': 'chocolate' };
1691
+ * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'lots' });
1692
+ * // => { 'flavor': 'chocolate', 'sprinkles': 'lots' }
1693
+ */
1694
+ var defaults = iterationFactory(extendFactoryOptions, {
1695
+ 'inLoop': 'if(object[index]==undefined)' + extendFactoryOptions.inLoop
1696
+ });
1697
+
1698
+ /**
1699
+ * Copies enumerable properties from the source objects to the `destination` object.
1700
+ * Subsequent sources will overwrite propery assignments of previous sources.
1701
+ *
1702
+ * @static
1703
+ * @memberOf _
1704
+ * @category Objects
1705
+ * @param {Object} object The destination object.
1706
+ * @param {Object} [source1, source2, ..] The source objects.
1707
+ * @returns {Object} Returns the destination object.
1708
+ * @example
1709
+ *
1710
+ * _.extend({ 'name': 'moe' }, { 'age': 40 });
1711
+ * // => { 'name': 'moe', 'age': 40 }
1712
+ */
1713
+ var extend = iterationFactory(extendFactoryOptions);
1714
+
1715
+ /**
1716
+ * Produces a sorted array of the properties, own and inherited, of `object`
1717
+ * that have function values.
1718
+ *
1719
+ * @static
1720
+ * @memberOf _
1721
+ * @alias methods
1722
+ * @category Objects
1723
+ * @param {Object} object The object to inspect.
1724
+ * @returns {Array} Returns a new array of property names that have function values.
1725
+ * @example
1726
+ *
1727
+ * _.functions(_);
1728
+ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
1729
+ */
1730
+ var functions = iterationFactory(keysFactoryOptions, {
1731
+ 'top': '',
1732
+ 'useHas': false,
1733
+ 'inLoop': 'if(toString.call(object[index])==funcClass)result.push(index)',
1734
+ 'returns': 'result.sort()'
1735
+ });
1736
+
1737
+ /**
1738
+ * Checks if the specified object `property` exists and is a direct property,
1739
+ * instead of an inherited property.
1740
+ *
1741
+ * @static
1742
+ * @memberOf _
1743
+ * @category Objects
1744
+ * @param {Object} object The object to check.
1745
+ * @param {String} property The property to check for.
1746
+ * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
1747
+ * @example
1748
+ *
1749
+ * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
1750
+ * // => true
1751
+ */
1752
+ function has(object, prop) {
1753
+ return hasOwnProperty.call(object, prop);
1754
+ }
1755
+
1756
+ /**
1757
+ * Checks if a `value` is an `arguments` object.
1758
+ *
1759
+ * @static
1760
+ * @memberOf _
1761
+ * @category Objects
1762
+ * @param {Mixed} value The value to check.
1763
+ * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
1764
+ * @example
1765
+ *
1766
+ * (function() { return _.isArguments(arguments); })(1, 2, 3);
1767
+ * // => true
1768
+ *
1769
+ * _.isArguments([1, 2, 3]);
1770
+ * // => false
1771
+ */
1772
+ var isArguments = function isArguments(value) {
1773
+ return toString.call(value) == '[object Arguments]';
1774
+ };
1775
+ // fallback for browser like IE<9 which detect `arguments` as `[object Object]`
1776
+ if (!isArguments(arguments)) {
1777
+ isArguments = function isArguments(value) {
1778
+ return !!(value && hasOwnProperty.call(value, 'callee'));
1779
+ };
1780
+ }
1781
+
1782
+ /**
1783
+ * Checks if a `value` is a boolean (`true` or `false`) value.
1784
+ *
1785
+ * @static
1786
+ * @memberOf _
1787
+ * @category Objects
1788
+ * @param {Mixed} value The value to check.
1789
+ * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
1790
+ * @example
1791
+ *
1792
+ * _.isBoolean(null);
1793
+ * // => false
1794
+ */
1795
+ function isBoolean(value) {
1796
+ return value === true || value === false || toString.call(value) == boolClass;
1797
+ }
1798
+
1799
+ /**
1800
+ * Checks if a `value` is a date.
1801
+ *
1802
+ * @static
1803
+ * @memberOf _
1804
+ * @category Objects
1805
+ * @param {Mixed} value The value to check.
1806
+ * @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
1807
+ * @example
1808
+ *
1809
+ * _.isDate(new Date);
1810
+ * // => true
1811
+ */
1812
+ function isDate(value) {
1813
+ return toString.call(value) == dateClass;
1814
+ }
1815
+
1816
+ /**
1817
+ * Checks if a `value` is a DOM element.
1818
+ *
1819
+ * @static
1820
+ * @memberOf _
1821
+ * @category Objects
1822
+ * @param {Mixed} value The value to check.
1823
+ * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
1824
+ * @example
1825
+ *
1826
+ * _.isElement(document.body);
1827
+ * // => true
1828
+ */
1829
+ function isElement(value) {
1830
+ return !!(value && value.nodeType == 1);
1831
+ }
1832
+
1833
+ /**
1834
+ * Performs a deep comparison between two values to determine if they are
1835
+ * equivalent to each other.
1836
+ *
1837
+ * @static
1838
+ * @memberOf _
1839
+ * @category Objects
1840
+ * @param {Mixed} a The value to compare.
1841
+ * @param {Mixed} b The other value to compare.
1842
+ * @param {Array} [stack] Internally used to keep track of "seen" objects to
1843
+ * avoid circular references.
1844
+ * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
1845
+ * @example
1846
+ *
1847
+ * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
1848
+ * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
1849
+ *
1850
+ * moe == clone;
1851
+ * // => false
1852
+ *
1853
+ * _.isEqual(moe, clone);
1854
+ * // => true
1855
+ */
1856
+ function isEqual(a, b, stack) {
1857
+ stack || (stack = []);
1858
+
1859
+ // exit early for identical values
1860
+ if (a === b) {
1861
+ // treat `+0` vs. `-0` as not equal
1862
+ return a !== 0 || (1 / a == 1 / b);
1863
+ }
1864
+ // a strict comparison is necessary because `null == undefined`
1865
+ if (a == undefined || b == undefined) {
1866
+ return a === b;
1867
+ }
1868
+ // unwrap any wrapped objects
1869
+ if (a._chain) {
1870
+ a = a._wrapped;
1871
+ }
1872
+ if (b._chain) {
1873
+ b = b._wrapped;
1874
+ }
1875
+ // invoke a custom `isEqual` method if one is provided
1876
+ if (a.isEqual && isFunction(a.isEqual)) {
1877
+ return a.isEqual(b);
1878
+ }
1879
+ if (b.isEqual && isFunction(b.isEqual)) {
1880
+ return b.isEqual(a);
1881
+ }
1882
+ // compare [[Class]] names
1883
+ var className = toString.call(a);
1884
+ if (className != toString.call(b)) {
1885
+ return false;
1886
+ }
1887
+ switch (className) {
1888
+ // strings, numbers, dates, and booleans are compared by value
1889
+ case stringClass:
1890
+ // primitives and their corresponding object instances are equivalent;
1891
+ // thus, `'5'` is quivalent to `new String('5')`
1892
+ return a == String(b);
1893
+
1894
+ case numberClass:
1895
+ // treat `NaN` vs. `NaN` as equal
1896
+ return a != +a
1897
+ ? b != +b
1898
+ // but treat `+0` vs. `-0` as not equal
1899
+ : (a == 0 ? (1 / a == 1 / b) : a == +b);
1900
+
1901
+ case boolClass:
1902
+ case dateClass:
1903
+ // coerce dates and booleans to numeric values, dates to milliseconds and booleans to 1 or 0;
1904
+ // treat invalid dates coerced to `NaN` as not equal
1905
+ return +a == +b;
1906
+
1907
+ // regexps are compared by their source and flags
1908
+ case regexpClass:
1909
+ return a.source == b.source &&
1910
+ a.global == b.global &&
1911
+ a.multiline == b.multiline &&
1912
+ a.ignoreCase == b.ignoreCase;
1913
+ }
1914
+ if (typeof a != 'object' || typeof b != 'object') {
1915
+ return false;
1916
+ }
1917
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
1918
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1919
+ var length = stack.length;
1920
+ while (length--) {
1921
+ // Linear search. Performance is inversely proportional to the number of
1922
+ // unique nested structures.
1923
+ if (stack[length] == a) {
1924
+ return true;
1925
+ }
1926
+ }
1927
+
1928
+ var result = true,
1929
+ size = 0;
1930
+
1931
+ // add the first collection to the stack of traversed objects
1932
+ stack.push(a);
1933
+
1934
+ // recursively compare objects and arrays
1935
+ if (className == arrayClass) {
1936
+ // compare array lengths to determine if a deep comparison is necessary
1937
+ size = a.length;
1938
+ result = size == b.length;
1939
+
1940
+ if (result) {
1941
+ // deep compare the contents, ignoring non-numeric properties
1942
+ while (size--) {
1943
+ // ensure commutative equality for sparse arrays
1944
+ if (!(result = size in a == size in b && isEqual(a[size], b[size], stack))) {
1945
+ break;
1946
+ }
1947
+ }
1948
+ }
1949
+ } else {
1950
+ // objects with different constructors are not equivalent
1951
+ if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
1952
+ return false;
1953
+ }
1954
+ // deep compare objects
1955
+ for (var prop in a) {
1956
+ if (hasOwnProperty.call(a, prop)) {
1957
+ // count the expected number of properties
1958
+ size++;
1959
+ // deep compare each member
1960
+ if (!(result = hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], stack))) {
1961
+ break;
1962
+ }
1963
+ }
1964
+ }
1965
+ // ensure that both objects contain the same number of properties
1966
+ if (result) {
1967
+ for (prop in b) {
1968
+ if (hasOwnProperty.call(b, prop) && !(size--)) {
1969
+ break;
1970
+ }
1971
+ }
1972
+ result = !size;
1973
+ }
1974
+ }
1975
+ // remove the first collection from the stack of traversed objects
1976
+ stack.pop();
1977
+ return result;
1978
+ }
1979
+
1980
+ /**
1981
+ * Checks if a `value` is a finite number.
1982
+ *
1983
+ * @static
1984
+ * @memberOf _
1985
+ * @category Objects
1986
+ * @param {Mixed} value The value to check.
1987
+ * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
1988
+ * @example
1989
+ *
1990
+ * _.isFinite(-101);
1991
+ * // => true
1992
+ *
1993
+ * _.isFinite('10');
1994
+ * // => false
1995
+ *
1996
+ * _.isFinite(Infinity);
1997
+ * // => false
1998
+ */
1999
+ function isFinite(value) {
2000
+ return nativeIsFinite(value) && toString.call(value) == numberClass;
2001
+ }
2002
+
2003
+ /**
2004
+ * Checks if a `value` is a function.
2005
+ *
2006
+ * @static
2007
+ * @memberOf _
2008
+ * @category Objects
2009
+ * @param {Mixed} value The value to check.
2010
+ * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
2011
+ * @example
2012
+ *
2013
+ * _.isFunction(''.concat);
2014
+ * // => true
2015
+ */
2016
+ function isFunction(value) {
2017
+ return toString.call(value) == funcClass;
2018
+ }
2019
+
2020
+ /**
2021
+ * Checks if a `value` is an object.
2022
+ *
2023
+ * @static
2024
+ * @memberOf _
2025
+ * @category Objects
2026
+ * @param {Mixed} value The value to check.
2027
+ * @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
2028
+ * @example
2029
+ *
2030
+ * _.isObject({});
2031
+ * // => true
2032
+ *
2033
+ * _.isObject(1);
2034
+ * // => false
2035
+ */
2036
+ function isObject(value) {
2037
+ return value === Object(value);
2038
+ }
2039
+
2040
+ /**
2041
+ * Checks if a `value` is `NaN`.
2042
+ * Note: this is not the same as native `isNaN`, which will return true for
2043
+ * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
2044
+ *
2045
+ * @static
2046
+ * @memberOf _
2047
+ * @category Objects
2048
+ * @param {Mixed} value The value to check.
2049
+ * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
2050
+ * @example
2051
+ *
2052
+ * _.isNaN(NaN);
2053
+ * // => true
2054
+ *
2055
+ * _.isNaN(new Number(NaN));
2056
+ * // => true
2057
+ *
2058
+ * isNaN(undefined);
2059
+ * // => true
2060
+ *
2061
+ * _.isNaN(undefined);
2062
+ * // => false
2063
+ */
2064
+ function isNaN(value) {
2065
+ // `NaN` as a primitive is the only value that is not equal to itself
2066
+ // (perform the [[Class]] check first to avoid errors with some host objects in IE)
2067
+ return toString.call(value) == numberClass && value != +value
2068
+ }
2069
+
2070
+ /**
2071
+ * Checks if a `value` is `null`.
2072
+ *
2073
+ * @static
2074
+ * @memberOf _
2075
+ * @category Objects
2076
+ * @param {Mixed} value The value to check.
2077
+ * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
2078
+ * @example
2079
+ *
2080
+ * _.isNull(null);
2081
+ * // => true
2082
+ *
2083
+ * _.isNull(undefined);
2084
+ * // => false
2085
+ */
2086
+ function isNull(value) {
2087
+ return value === null;
2088
+ }
2089
+
2090
+ /**
2091
+ * Checks if a `value` is a number.
2092
+ *
2093
+ * @static
2094
+ * @memberOf _
2095
+ * @category Objects
2096
+ * @param {Mixed} value The value to check.
2097
+ * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
2098
+ * @example
2099
+ *
2100
+ * _.isNumber(8.4 * 5;
2101
+ * // => true
2102
+ */
2103
+ function isNumber(value) {
2104
+ return toString.call(value) == numberClass;
2105
+ }
2106
+
2107
+ /**
2108
+ * Checks if a `value` is a regular expression.
2109
+ *
2110
+ * @static
2111
+ * @memberOf _
2112
+ * @category Objects
2113
+ * @param {Mixed} value The value to check.
2114
+ * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
2115
+ * @example
2116
+ *
2117
+ * _.isRegExp(/moe/);
2118
+ * // => true
2119
+ */
2120
+ function isRegExp(value) {
2121
+ return toString.call(value) == regexpClass;
2122
+ }
2123
+
2124
+ /**
2125
+ * Checks if a `value` is a string.
2126
+ *
2127
+ * @static
2128
+ * @memberOf _
2129
+ * @category Objects
2130
+ * @param {Mixed} value The value to check.
2131
+ * @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
2132
+ * @example
2133
+ *
2134
+ * _.isString('moe');
2135
+ * // => true
2136
+ */
2137
+ function isString(value) {
2138
+ return toString.call(value) == stringClass;
2139
+ }
2140
+
2141
+ /**
2142
+ * Checks if a `value` is `undefined`.
2143
+ *
2144
+ * @static
2145
+ * @memberOf _
2146
+ * @category Objects
2147
+ * @param {Mixed} value The value to check.
2148
+ * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
2149
+ * @example
2150
+ *
2151
+ * _.isUndefined(void 0);
2152
+ * // => true
2153
+ */
2154
+ function isUndefined(value) {
2155
+ return value === undefined;
2156
+ }
2157
+
2158
+ /**
2159
+ * Produces an array of the `object`'s enumerable own property names.
2160
+ *
2161
+ * @static
2162
+ * @memberOf _
2163
+ * @category Objects
2164
+ * @param {Object} object The object to inspect.
2165
+ * @returns {Array} Returns a new array of property names.
2166
+ * @example
2167
+ *
2168
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
2169
+ * // => ['one', 'two', 'three']
2170
+ */
2171
+ var keys = nativeKeys || iterationFactory(keysFactoryOptions);
2172
+
2173
+ /**
2174
+ * Creates an object composed of the specified properties. Property names may
2175
+ * be specified as individual arguments or as arrays of property names.
2176
+ *
2177
+ * @static
2178
+ * @memberOf _
2179
+ * @category Objects
2180
+ * @param {Object} object The object to pluck.
2181
+ * @param {Object} [prop1, prop2, ..] The properties to pick.
2182
+ * @returns {Object} Returns an object composed of the picked properties.
2183
+ * @example
2184
+ *
2185
+ * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
2186
+ * // => { 'name': 'moe', 'age': 40 }
2187
+ */
2188
+ function pick(object) {
2189
+ var prop,
2190
+ index = -1,
2191
+ props = flatten(slice.call(arguments, 1)),
2192
+ length = props.length,
2193
+ result = {};
2194
+
2195
+ while (++index < length) {
2196
+ prop = props[index];
2197
+ if (prop in object) {
2198
+ result[prop] = object[prop];
2199
+ }
2200
+ }
2201
+ return result;
2202
+ }
2203
+
2204
+ /**
2205
+ * Invokes `interceptor` with the `value` as the first argument, and then returns
2206
+ * `value`. The primary purpose of this method is to "tap into" a method chain,
2207
+ * in order to performoperations on intermediate results within the chain.
2208
+ *
2209
+ * @static
2210
+ * @memberOf _
2211
+ * @category Objects
2212
+ * @param {Mixed} value The value to pass to `callback`.
2213
+ * @param {Function} interceptor The function to invoke.
2214
+ * @returns {Mixed} Returns `value`.
2215
+ * @example
2216
+ *
2217
+ * _.chain([1,2,3,200])
2218
+ * .filter(function(num) { return num % 2 == 0; })
2219
+ * .tap(alert)
2220
+ * .map(function(num) { return num * num })
2221
+ * .value();
2222
+ * // => // [2, 200] (alerted)
2223
+ * // => [4, 40000]
2224
+ */
2225
+ function tap(value, interceptor) {
2226
+ interceptor(value);
2227
+ return value;
2228
+ }
2229
+
2230
+ /*--------------------------------------------------------------------------*/
2231
+
2232
+ /**
2233
+ * Escapes a string for insertion into HTML, replacing `&`, `<`, `>`, `"`, `'`,
2234
+ * and `/` characters.
2235
+ *
2236
+ * @static
2237
+ * @memberOf _
2238
+ * @category Utilities
2239
+ * @param {String} string The string to escape.
2240
+ * @returns {String} Returns the escaped string.
2241
+ * @example
2242
+ *
2243
+ * _.escape('Curly, Larry & Moe');
2244
+ * // => "Curly, Larry &amp; Moe"
2245
+ */
2246
+ function escape(string) {
2247
+ return (string + '')
2248
+ .replace(/&/g, '&amp;')
2249
+ .replace(/</g, '&lt;')
2250
+ .replace(/>/g, '&gt;')
2251
+ .replace(/"/g, '&quot;')
2252
+ .replace(/'/g, '&#x27;')
2253
+ .replace(/\//g,'&#x2F;');
2254
+ }
2255
+
2256
+ /**
2257
+ * This function simply returns the first argument passed to it.
2258
+ * Note: It is used throughout Lo-Dash as a default callback.
2259
+ *
2260
+ * @static
2261
+ * @memberOf _
2262
+ * @category Utilities
2263
+ * @param {Mixed} value Any value.
2264
+ * @returns {Mixed} Returns `value`.
2265
+ * @example
2266
+ *
2267
+ * var moe = { 'name': 'moe' };
2268
+ * moe === _.identity(moe);
2269
+ * // => true
2270
+ */
2271
+ function identity(value) {
2272
+ return value;
2273
+ }
2274
+
2275
+ /**
2276
+ * Adds functions properties of `object` to the `lodash` function and chainable
2277
+ * wrapper.
2278
+ *
2279
+ * @static
2280
+ * @memberOf _
2281
+ * @category Utilities
2282
+ * @param {Object} object The object of function properties to add to `lodash`.
2283
+ * @example
2284
+ *
2285
+ * _.mixin({
2286
+ * 'capitalize': function(string) {
2287
+ * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
2288
+ * }
2289
+ * });
2290
+ *
2291
+ * _.capitalize('curly');
2292
+ * // => 'Curly'
2293
+ *
2294
+ * _('larry').capitalize();
2295
+ * // => 'Larry'
2296
+ */
2297
+ function mixin(object) {
2298
+ forEach(functions(object), function(methodName) {
2299
+ var func = lodash[methodName] = object[methodName];
2300
+
2301
+ lodash.prototype[methodName] = function() {
2302
+ // In Opera < 9.50 and some older/beta Mobile Safari versions using `unshift()`
2303
+ // generically to augment the `arguments` object will pave the value at
2304
+ // index `0` without incrimenting the other values's indexes.
2305
+ // https://github.com/documentcloud/underscore/issues/9
2306
+ var args = slice.call(arguments);
2307
+ unshift.call(args, this._wrapped);
2308
+
2309
+ var result = func.apply(lodash, args);
2310
+ return this._chain ? new Lodash(result).chain() : result;
2311
+ };
2312
+ });
2313
+ }
2314
+
2315
+ /**
2316
+ * Reverts the '_' variable to its previous value and returns a reference to
2317
+ * the `lodash` function.
2318
+ *
2319
+ * @static
2320
+ * @memberOf _
2321
+ * @category Utilities
2322
+ * @returns {Function} Returns the `lodash` function.
2323
+ * @example
2324
+ *
2325
+ * var lodash = _.noConflict();
2326
+ */
2327
+ function noConflict() {
2328
+ window._ = oldDash;
2329
+ return this;
2330
+ }
2331
+
2332
+ /**
2333
+ * Resolves the value of `property` on `object`. If the property is a function
2334
+ * it will be invoked and its result returned, else the property value is returned.
2335
+ *
2336
+ * @static
2337
+ * @memberOf _
2338
+ * @category Utilities
2339
+ * @param {Object} object The object to inspect.
2340
+ * @param {String} property The property to get the result of.
2341
+ * @returns {Mixed} Returns the resolved.
2342
+ * @example
2343
+ *
2344
+ * var object = {
2345
+ * 'cheese': 'crumpets',
2346
+ * 'stuff': function() {
2347
+ * return 'nonsense';
2348
+ * }
2349
+ * };
2350
+ *
2351
+ * _.result(object, 'cheese');
2352
+ * // => 'crumpets'
2353
+ *
2354
+ * _.result(object, 'stuff');
2355
+ * // => 'nonsense'
2356
+ */
2357
+ function result(object, property) {
2358
+ if (object == undefined) {
2359
+ return null;
2360
+ }
2361
+ var value = object[property];
2362
+ return isFunction(value) ? object[property]() : value;
2363
+ }
2364
+
2365
+ /**
2366
+ * Executes the `callback` function `n` times.
2367
+ *
2368
+ * @static
2369
+ * @memberOf _
2370
+ * @category Utilities
2371
+ * @param {Number} n The number of times to execute the callback.
2372
+ * @param {Function} callback The function called per iteration.
2373
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
2374
+ * @example
2375
+ *
2376
+ * _.times(3, function() { genie.grantWish(); });
2377
+ */
2378
+ function times(n, callback, thisArg) {
2379
+ if (thisArg) {
2380
+ callback = bind(callback, thisArg);
2381
+ }
2382
+ for (var index = 0; index < n; index++) {
2383
+ callback(index);
2384
+ }
2385
+ }
2386
+
2387
+ /**
2388
+ * Generates a unique id. If `prefix` is passed, the id will be appended to it.
2389
+ *
2390
+ * @static
2391
+ * @memberOf _
2392
+ * @category Utilities
2393
+ * @param {String} [prefix] The value to prefix the id with.
2394
+ * @returns {Number|String} Returns a numeric id if no prefix is passed, else
2395
+ * a string id may be returned.
2396
+ * @example
2397
+ *
2398
+ * _.uniqueId('contact_');
2399
+ * // => 'contact_104'
2400
+ */
2401
+ function uniqueId(prefix) {
2402
+ var id = idCounter++;
2403
+ return prefix ? prefix + id : id;
2404
+ }
2405
+
2406
+ /*--------------------------------------------------------------------------*/
2407
+
2408
+ /**
2409
+ * A JavaScript micro-templating method, similar to John Resig's implementation.
2410
+ * Lo-Dash templating handles arbitrary delimiters, preserves whitespace, and
2411
+ * correctly escapes quotes within interpolated code.
2412
+ *
2413
+ * @static
2414
+ * @memberOf _
2415
+ * @category Utilities
2416
+ * @param {String} text The template text.
2417
+ * @param {Obect} data The data object used to populate the text.
2418
+ * @param {Object} options The options object.
2419
+ * @returns {Function|String} Returns a compiled function when no `data` object
2420
+ * is given, else it returns the interpolated text.
2421
+ * @example
2422
+ *
2423
+ * // using compiled template
2424
+ * var compiled = _.template('hello: <%= name %>');
2425
+ * compiled({ 'name': 'moe' });
2426
+ * // => 'hello: moe'
2427
+ *
2428
+ * var list = '% _.forEach(people, function(name) { %> <li><%= name %></li> <% }); %>';
2429
+ * _.template(list, { 'people': ['moe', 'curly', 'larry'] });
2430
+ * // => '<li>moe</li><li>curly</li><li>larry</li>'
2431
+ *
2432
+ * var template = _.template('<b><%- value %></b>');
2433
+ * template({ 'value': '<script>' });
2434
+ * // => '<b>&lt;script&gt;</b>'
2435
+ *
2436
+ * // using `print`
2437
+ * var compiled = _.template('<% print("Hello " + epithet); %>');
2438
+ * compiled({ 'epithet': 'stooge' });
2439
+ * // => 'Hello stooge.'
2440
+ *
2441
+ * // using custom template settings
2442
+ * _.templateSettings = {
2443
+ * 'interpolate': /\{\{(.+?)\}\}/g
2444
+ * };
2445
+ *
2446
+ * var template = _.template('Hello {{ name }}!');
2447
+ * template({ 'name': 'Mustache' });
2448
+ * // => 'Hello Mustache!'
2449
+ *
2450
+ *
2451
+ * // using the `variable` option
2452
+ * _.template('<%= data.hasWith %>', { 'hasWith': 'no' }, { 'variable': 'data' });
2453
+ * // => 'no'
2454
+ *
2455
+ * // using the `source` property
2456
+ * <script>
2457
+ * JST.project = <%= _.template(jstText).source %>;
2458
+ * </script>
2459
+ */
2460
+ function template(text, data, options) {
2461
+ options = defaults(options || {}, lodash.templateSettings);
2462
+
2463
+ // Compile the template source, taking care to escape characters that
2464
+ // cannot be included in string literals and then unescape them in code
2465
+ // blocks.
2466
+ var source = "__p+='" + text
2467
+ .replace(reEscaper, function(match) {
2468
+ return '\\' + escapes[match];
2469
+ })
2470
+ .replace(options.escape || reNoMatch, function(match, code) {
2471
+ return "'+\n((__t=(" + unescape(code) + "))==null?'':_.escape(__t))+\n'";
2472
+ })
2473
+ .replace(options.interpolate || reNoMatch, function(match, code) {
2474
+ return "'+\n((__t=(" + unescape(code) + "))==null?'':__t)+\n'";
2475
+ })
2476
+ .replace(options.evaluate || reNoMatch, function(match, code) {
2477
+ return "';\n" + unescape(code) + ";\n__p+='";
2478
+ }) + "';\n";
2479
+
2480
+ // if a variable is not specified, place data values in local scope
2481
+ if (!options.variable) {
2482
+ source = 'with(object||{}){\n' + source + '\n}\n';
2483
+ }
2484
+
2485
+ source = 'var __t,__j=Array.prototype.join,__p="";' +
2486
+ 'function print(){__p+=__j.call(arguments,"")}\n' +
2487
+ source + 'return __p';
2488
+
2489
+ var render = Function(options.variable || 'object', '_', source);
2490
+ if (data) {
2491
+ return render(data, lodash);
2492
+ }
2493
+
2494
+ var template = function(data) {
2495
+ return render.call(this, data, lodash);
2496
+ };
2497
+
2498
+ // provide the compiled function source as a convenience for build time precompilation
2499
+ template.source = 'function(' + (options.variable || 'object') + '){\n' + source + '\n}';
2500
+
2501
+ return template;
2502
+ }
2503
+
2504
+ /*--------------------------------------------------------------------------*/
2505
+
2506
+ /**
2507
+ * Wraps the value in a `lodash` chainable object.
2508
+ *
2509
+ * @static
2510
+ * @memberOf _
2511
+ * @category Chaining
2512
+ * @param {Mixed} value The value to wrap.
2513
+ * @returns {Object} Returns the `lodash` chainable object.
2514
+ * @example
2515
+ *
2516
+ * var stooges = [
2517
+ * { 'name': 'moe', 'age': 40 },
2518
+ * { 'name': 'larry', 'age': 50 },
2519
+ * { 'name': 'curly', 'age': 60 }
2520
+ * ];
2521
+ *
2522
+ * var youngest = _.chain(stooges)
2523
+ * .sortBy(function(stooge) { return stooge.age; })
2524
+ * .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })
2525
+ * .first()
2526
+ * .value();
2527
+ * // => 'moe is 40'
2528
+ */
2529
+ function chain(value) {
2530
+ return new Lodash(value).chain();
2531
+ }
2532
+
2533
+ /**
2534
+ * Extracts the value from a wrapped chainable object.
2535
+ *
2536
+ * @name chain
2537
+ * @memberOf _
2538
+ * @category Chaining
2539
+ * @returns {Mixed} Returns the wrapped object.
2540
+ * @example
2541
+ *
2542
+ * _([1, 2, 3]).value();
2543
+ * // => [1, 2, 3]
2544
+ */
2545
+ function chainWrapper() {
2546
+ this._chain = true;
2547
+ return this;
2548
+ }
2549
+
2550
+ /**
2551
+ * Extracts the value from a wrapped chainable object.
2552
+ *
2553
+ * @memberOf _
2554
+ * @category Chaining
2555
+ * @returns {Mixed} Returns the wrapped object.
2556
+ * @example
2557
+ *
2558
+ * _([1, 2, 3]).value();
2559
+ * // => [1, 2, 3]
2560
+ */
2561
+ function value() {
2562
+ return this._wrapped;
2563
+ }
2564
+
2565
+ /*--------------------------------------------------------------------------*/
2566
+
2567
+ extend(lodash, {
2568
+
2569
+ /**
2570
+ * The semantic version number.
2571
+ *
2572
+ * @static
2573
+ * @memberOf _
2574
+ * @type String
2575
+ */
2576
+ 'VERSION': '0.1.0',
2577
+
2578
+ /**
2579
+ * By default, Lo-Dash uses ERB-style template delimiters, change the
2580
+ * following template settings to use alternative delimiters.
2581
+ *
2582
+ * @static
2583
+ * @memberOf _
2584
+ * @type Object
2585
+ */
2586
+ 'templateSettings': {
2587
+
2588
+ /**
2589
+ * Used to detect `data` property values to be HTML-escaped.
2590
+ *
2591
+ * @static
2592
+ * @memberOf _.templateSettings
2593
+ * @type RegExp
2594
+ */
2595
+ 'escape': /<%-([\s\S]+?)%>/g,
2596
+
2597
+ /**
2598
+ * Used to detect code to be evaluated.
2599
+ *
2600
+ * @static
2601
+ * @memberOf _.templateSettings
2602
+ * @type RegExp
2603
+ */
2604
+ 'evaluate': /<%([\s\S]+?)%>/g,
2605
+
2606
+ /**
2607
+ * Used to detect `data` property values to inject.
2608
+ *
2609
+ * @static
2610
+ * @memberOf _.templateSettings
2611
+ * @type RegExp
2612
+ */
2613
+ 'interpolate': /<%=([\s\S]+?)%>/g
2614
+ },
2615
+
2616
+ // assign static methods
2617
+ 'after': after,
2618
+ 'bind': bind,
2619
+ 'bindAll': bindAll,
2620
+ 'chain': chain,
2621
+ 'clone': clone,
2622
+ 'compact': compact,
2623
+ 'compose': compose,
2624
+ 'contains': contains,
2625
+ 'debounce': debounce,
2626
+ 'defaults': defaults,
2627
+ 'defer': defer,
2628
+ 'delay': delay,
2629
+ 'difference': difference,
2630
+ 'escape': escape,
2631
+ 'every': every,
2632
+ 'extend': extend,
2633
+ 'filter': filter,
2634
+ 'find': find,
2635
+ 'first': first,
2636
+ 'flatten': flatten,
2637
+ 'forEach': forEach,
2638
+ 'functions': functions,
2639
+ 'groupBy': groupBy,
2640
+ 'has': has,
2641
+ 'identity': identity,
2642
+ 'indexOf': indexOf,
2643
+ 'initial': initial,
2644
+ 'intersection': intersection,
2645
+ 'invoke': invoke,
2646
+ 'isArguments': isArguments,
2647
+ 'isArray': isArray,
2648
+ 'isBoolean': isBoolean,
2649
+ 'isDate': isDate,
2650
+ 'isElement': isElement,
2651
+ 'isEmpty': isEmpty,
2652
+ 'isEqual': isEqual,
2653
+ 'isFinite': isFinite,
2654
+ 'isFunction': isFunction,
2655
+ 'isNaN': isNaN,
2656
+ 'isNull': isNull,
2657
+ 'isNumber': isNumber,
2658
+ 'isObject': isObject,
2659
+ 'isRegExp': isRegExp,
2660
+ 'isString': isString,
2661
+ 'isUndefined': isUndefined,
2662
+ 'keys': keys,
2663
+ 'last': last,
2664
+ 'lastIndexOf': lastIndexOf,
2665
+ 'map': map,
2666
+ 'max': max,
2667
+ 'memoize': memoize,
2668
+ 'min': min,
2669
+ 'mixin': mixin,
2670
+ 'noConflict': noConflict,
2671
+ 'once': once,
2672
+ 'pick': pick,
2673
+ 'pluck': pluck,
2674
+ 'range': range,
2675
+ 'reduce': reduce,
2676
+ 'reduceRight': reduceRight,
2677
+ 'reject': reject,
2678
+ 'rest': rest,
2679
+ 'result': result,
2680
+ 'shuffle': shuffle,
2681
+ 'size': size,
2682
+ 'some': some,
2683
+ 'sortBy': sortBy,
2684
+ 'sortedIndex': sortedIndex,
2685
+ 'tap': tap,
2686
+ 'template': template,
2687
+ 'throttle': throttle,
2688
+ 'times': times,
2689
+ 'toArray': toArray,
2690
+ 'union': union,
2691
+ 'uniq': uniq,
2692
+ 'uniqueId': uniqueId,
2693
+ 'values': values,
2694
+ 'without': without,
2695
+ 'wrap': wrap,
2696
+ 'zip': zip,
2697
+
2698
+ // assign aliases
2699
+ 'all': every,
2700
+ 'any': some,
2701
+ 'collect': map,
2702
+ 'detect': find,
2703
+ 'each': forEach,
2704
+ 'foldl': reduce,
2705
+ 'foldr': reduceRight,
2706
+ 'head': first,
2707
+ 'include': contains,
2708
+ 'inject': reduce,
2709
+ 'intersect': intersection,
2710
+ 'methods': functions,
2711
+ 'select': filter,
2712
+ 'tail': rest,
2713
+ 'take': first,
2714
+ 'unique': uniq
2715
+ });
2716
+
2717
+ /*--------------------------------------------------------------------------*/
2718
+
2719
+ // assign private `Lodash` constructor's prototype
2720
+ Lodash.prototype = lodash.prototype;
2721
+
2722
+ // add all of the static functions to `Lodash.prototype`
2723
+ mixin(lodash);
2724
+
2725
+ // add all mutator Array functions to the wrapper.
2726
+ forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
2727
+ var func = ArrayProto[methodName];
2728
+
2729
+ lodash.prototype[methodName] = function() {
2730
+ var value = this._wrapped;
2731
+ func.apply(value, arguments);
2732
+
2733
+ // IE compatibility mode and IE < 9 have buggy Array `shift()` and `splice()`
2734
+ // functions that fail to remove the last element, `object[0]`, of
2735
+ // array-like-objects even though the `length` property is set to `0`.
2736
+ // The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
2737
+ // is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
2738
+ if (value.length === 0) {
2739
+ delete value[0];
2740
+ }
2741
+ return this._chain ? new Lodash(value).chain() : value;
2742
+ };
2743
+ });
2744
+
2745
+ // add all accessor Array functions to the wrapper.
2746
+ forEach(['concat', 'join', 'slice'], function(methodName) {
2747
+ var func = ArrayProto[methodName];
2748
+ Lodash.prototype[methodName] = function() {
2749
+ var result = func.apply(this._wrapped, arguments);
2750
+ return this._chain ? new Lodash(result).chain() : result;
2751
+ };
2752
+ });
2753
+
2754
+ // add `chain` and `value` after calling to `mixin()` to avoid getting wrapped
2755
+ extend(Lodash.prototype, {
2756
+ 'chain': chainWrapper,
2757
+ 'value': value
2758
+ });
2759
+
2760
+ /*--------------------------------------------------------------------------*/
2761
+
2762
+ // expose Lo-Dash
2763
+ if (freeExports) {
2764
+ // in Node.js or RingoJS v0.8.0+
2765
+ if (typeof module == 'object' && module && module.exports == freeExports) {
2766
+ (module.exports = lodash)._ = lodash;
2767
+ }
2768
+ // in Narwhal or RingoJS v0.7.0-
2769
+ else {
2770
+ freeExports._ = lodash;
2771
+ }
2772
+ } else {
2773
+ // in a browser or Rhino
2774
+ window._ = lodash;
2775
+
2776
+ // Expose Lo-Dash as an AMD module, but only for AMD loaders that understand
2777
+ // the issues with loading multiple versions of Lo-Dash in a page that all
2778
+ // might call `define()`. The loader will indicate they have special
2779
+ // allowances for multiple Lo-Dash versions by specifying
2780
+ // `define.amd.lodash=true`. Register as a named module, since Lo-Dash can
2781
+ // be concatenated with other files that may use `define()`, but not use a
2782
+ // proper concatenation script that understands anonymous AMD modules.
2783
+ // Lowercase `lodash` is used because AMD module names are derived from
2784
+ // file names, and Lo-Dash is normally delivered in a lowercase file name.
2785
+ // Do this after assigning Lo-Dash the global so that if an AMD module wants
2786
+ // to call `noConflict()` to hide this version of Lo-Dash, it will work.
2787
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd && define.amd.lodash) {
2788
+ define('lodash', function() {
2789
+ return lodash;
2790
+ });
2791
+ }
2792
+ }
2793
+ }(this));