torba 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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));