underscore-source 0.5.7 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/underscore-source/version.rb +1 -1
- data/vendor/assets/javascripts/underscore.js +131 -89
- metadata +1 -1
@@ -7,7 +7,6 @@
|
|
7
7
|
// http://documentcloud.github.com/underscore
|
8
8
|
|
9
9
|
(function() {
|
10
|
-
|
11
10
|
// ------------------------- Baseline setup ---------------------------------
|
12
11
|
|
13
12
|
// Establish the root object, "window" in the browser, or "global" on the server.
|
@@ -16,44 +15,64 @@
|
|
16
15
|
// Save the previous value of the "_" variable.
|
17
16
|
var previousUnderscore = root._;
|
18
17
|
|
19
|
-
// If Underscore is called as a function, it returns a wrapped object that
|
20
|
-
// can be used OO-style. This wrapper holds altered versions of all the
|
21
|
-
// underscore functions. Wrapped objects may be chained.
|
22
|
-
var wrapper = function(obj) { this._wrapped = obj; };
|
23
|
-
|
24
18
|
// Establish the object that gets thrown to break out of a loop iteration.
|
25
19
|
var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__';
|
26
20
|
|
21
|
+
// Quick regexp-escaping function, because JS doesn't have RegExp.escape().
|
22
|
+
var escapeRegExp = function(s) { return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); };
|
23
|
+
|
24
|
+
// Save bytes in the minified (but not gzipped) version:
|
25
|
+
var ArrayProto = Array.prototype, ObjProto = Object.prototype;
|
26
|
+
|
27
|
+
// Create quick reference variables for speed access to core prototypes.
|
28
|
+
var slice = ArrayProto.slice,
|
29
|
+
unshift = ArrayProto.unshift,
|
30
|
+
toString = ObjProto.toString,
|
31
|
+
hasOwnProperty = ObjProto.hasOwnProperty,
|
32
|
+
propertyIsEnumerable = ObjProto.propertyIsEnumerable;
|
33
|
+
|
34
|
+
// All ECMA5 native implementations we hope to use are declared here.
|
35
|
+
var
|
36
|
+
nativeForEach = ArrayProto.forEach,
|
37
|
+
nativeMap = ArrayProto.map,
|
38
|
+
nativeReduce = ArrayProto.reduce,
|
39
|
+
nativeReduceRight = ArrayProto.reduceRight,
|
40
|
+
nativeFilter = ArrayProto.filter,
|
41
|
+
nativeEvery = ArrayProto.every,
|
42
|
+
nativeSome = ArrayProto.some,
|
43
|
+
nativeIndexOf = ArrayProto.indexOf,
|
44
|
+
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
45
|
+
nativeIsArray = Array.isArray,
|
46
|
+
nativeKeys = Object.keys;
|
47
|
+
|
27
48
|
// Create a safe reference to the Underscore object for reference below.
|
28
|
-
var _ =
|
49
|
+
var _ = function(obj) { return new wrapper(obj); };
|
29
50
|
|
30
51
|
// Export the Underscore object for CommonJS.
|
31
52
|
if (typeof exports !== 'undefined') exports._ = _;
|
32
53
|
|
33
|
-
//
|
34
|
-
|
35
|
-
unshift = Array.prototype.unshift,
|
36
|
-
toString = Object.prototype.toString,
|
37
|
-
hasOwnProperty = Object.prototype.hasOwnProperty,
|
38
|
-
propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
54
|
+
// Export underscore to global scope.
|
55
|
+
root._ = _;
|
39
56
|
|
40
57
|
// Current version.
|
41
|
-
_.VERSION = '0.
|
58
|
+
_.VERSION = '0.6.0';
|
42
59
|
|
43
60
|
// ------------------------ Collection Functions: ---------------------------
|
44
61
|
|
45
62
|
// The cornerstone, an each implementation.
|
46
63
|
// Handles objects implementing forEach, arrays, and raw objects.
|
47
|
-
|
64
|
+
// Delegates to JavaScript 1.6's native forEach if available.
|
65
|
+
var each = _.forEach = function(obj, iterator, context) {
|
48
66
|
var index = 0;
|
49
67
|
try {
|
50
|
-
if (obj.forEach) {
|
68
|
+
if (nativeForEach && obj.forEach === nativeForEach) {
|
51
69
|
obj.forEach(iterator, context);
|
52
|
-
} else if (_.
|
53
|
-
for (var i=0, l=obj.length; i<l; i++) iterator.call(context, obj[i], i, obj);
|
70
|
+
} else if (_.isNumber(obj.length)) {
|
71
|
+
for (var i = 0, l = obj.length; i < l; i++) iterator.call(context, obj[i], i, obj);
|
54
72
|
} else {
|
55
|
-
var
|
56
|
-
|
73
|
+
for (var key in obj) {
|
74
|
+
if (hasOwnProperty.call(obj, key)) iterator.call(context, obj[key], key, obj);
|
75
|
+
}
|
57
76
|
}
|
58
77
|
} catch(e) {
|
59
78
|
if (e != breaker) throw e;
|
@@ -61,42 +80,39 @@
|
|
61
80
|
return obj;
|
62
81
|
};
|
63
82
|
|
64
|
-
// Return the results of applying the iterator to each element.
|
65
|
-
// 1.6's
|
83
|
+
// Return the results of applying the iterator to each element.
|
84
|
+
// Delegates to JavaScript 1.6's native map if available.
|
66
85
|
_.map = function(obj, iterator, context) {
|
67
|
-
if (
|
86
|
+
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
68
87
|
var results = [];
|
69
|
-
|
88
|
+
each(obj, function(value, index, list) {
|
70
89
|
results.push(iterator.call(context, value, index, list));
|
71
90
|
});
|
72
91
|
return results;
|
73
92
|
};
|
74
93
|
|
75
|
-
// Reduce builds up a single result from a list of values
|
76
|
-
//
|
94
|
+
// Reduce builds up a single result from a list of values, aka inject, or foldl.
|
95
|
+
// Delegates to JavaScript 1.8's native reduce if available.
|
77
96
|
_.reduce = function(obj, memo, iterator, context) {
|
78
|
-
if (
|
79
|
-
|
97
|
+
if (nativeReduce && obj.reduce === nativeReduce) return obj.reduce(_.bind(iterator, context), memo);
|
98
|
+
each(obj, function(value, index, list) {
|
80
99
|
memo = iterator.call(context, memo, value, index, list);
|
81
100
|
});
|
82
101
|
return memo;
|
83
102
|
};
|
84
103
|
|
85
104
|
// The right-associative version of reduce, also known as foldr. Uses
|
86
|
-
// JavaScript 1.8's
|
105
|
+
// Delegates to JavaScript 1.8's native reduceRight if available.
|
87
106
|
_.reduceRight = function(obj, memo, iterator, context) {
|
88
|
-
if (
|
107
|
+
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) return obj.reduceRight(_.bind(iterator, context), memo);
|
89
108
|
var reversed = _.clone(_.toArray(obj)).reverse();
|
90
|
-
_.
|
91
|
-
memo = iterator.call(context, memo, value, index, obj);
|
92
|
-
});
|
93
|
-
return memo;
|
109
|
+
return _.reduce(reversed, memo, iterator, context);
|
94
110
|
};
|
95
111
|
|
96
112
|
// Return the first value which passes a truth test.
|
97
113
|
_.detect = function(obj, iterator, context) {
|
98
114
|
var result;
|
99
|
-
|
115
|
+
each(obj, function(value, index, list) {
|
100
116
|
if (iterator.call(context, value, index, list)) {
|
101
117
|
result = value;
|
102
118
|
_.breakLoop();
|
@@ -105,12 +121,12 @@
|
|
105
121
|
return result;
|
106
122
|
};
|
107
123
|
|
108
|
-
// Return all the elements that pass a truth test.
|
109
|
-
// filter
|
110
|
-
_.
|
111
|
-
if (
|
124
|
+
// Return all the elements that pass a truth test.
|
125
|
+
// Delegates to JavaScript 1.6's native filter if available.
|
126
|
+
_.filter = function(obj, iterator, context) {
|
127
|
+
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
112
128
|
var results = [];
|
113
|
-
|
129
|
+
each(obj, function(value, index, list) {
|
114
130
|
iterator.call(context, value, index, list) && results.push(value);
|
115
131
|
});
|
116
132
|
return results;
|
@@ -119,42 +135,41 @@
|
|
119
135
|
// Return all the elements for which a truth test fails.
|
120
136
|
_.reject = function(obj, iterator, context) {
|
121
137
|
var results = [];
|
122
|
-
|
138
|
+
each(obj, function(value, index, list) {
|
123
139
|
!iterator.call(context, value, index, list) && results.push(value);
|
124
140
|
});
|
125
141
|
return results;
|
126
142
|
};
|
127
143
|
|
128
|
-
// Determine whether all of the elements match a truth test.
|
129
|
-
// JavaScript 1.6's every
|
130
|
-
_.
|
144
|
+
// Determine whether all of the elements match a truth test.
|
145
|
+
// Delegates to JavaScript 1.6's native every if available.
|
146
|
+
_.every = function(obj, iterator, context) {
|
131
147
|
iterator = iterator || _.identity;
|
132
|
-
if (
|
148
|
+
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
133
149
|
var result = true;
|
134
|
-
|
150
|
+
each(obj, function(value, index, list) {
|
135
151
|
if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
|
136
152
|
});
|
137
153
|
return result;
|
138
154
|
};
|
139
155
|
|
140
|
-
// Determine if at least one element in the object matches a truth test.
|
141
|
-
// JavaScript 1.6's some
|
142
|
-
_.
|
156
|
+
// Determine if at least one element in the object matches a truth test.
|
157
|
+
// Delegates to JavaScript 1.6's native some if available.
|
158
|
+
_.some = function(obj, iterator, context) {
|
143
159
|
iterator = iterator || _.identity;
|
144
|
-
if (
|
160
|
+
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
145
161
|
var result = false;
|
146
|
-
|
162
|
+
each(obj, function(value, index, list) {
|
147
163
|
if (result = iterator.call(context, value, index, list)) _.breakLoop();
|
148
164
|
});
|
149
165
|
return result;
|
150
166
|
};
|
151
167
|
|
152
|
-
// Determine if a given value is included in the array or object
|
153
|
-
// based on '==='.
|
168
|
+
// Determine if a given value is included in the array or object using '==='.
|
154
169
|
_.include = function(obj, target) {
|
155
|
-
if (
|
170
|
+
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
156
171
|
var found = false;
|
157
|
-
|
172
|
+
each(obj, function(value) {
|
158
173
|
if (found = value === target) _.breakLoop();
|
159
174
|
});
|
160
175
|
return found;
|
@@ -177,7 +192,7 @@
|
|
177
192
|
_.max = function(obj, iterator, context) {
|
178
193
|
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
179
194
|
var result = {computed : -Infinity};
|
180
|
-
|
195
|
+
each(obj, function(value, index, list) {
|
181
196
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
182
197
|
computed >= result.computed && (result = {value : value, computed : computed});
|
183
198
|
});
|
@@ -188,7 +203,7 @@
|
|
188
203
|
_.min = function(obj, iterator, context) {
|
189
204
|
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
190
205
|
var result = {computed : Infinity};
|
191
|
-
|
206
|
+
each(obj, function(value, index, list) {
|
192
207
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
193
208
|
computed < result.computed && (result = {value : value, computed : computed});
|
194
209
|
});
|
@@ -258,7 +273,7 @@
|
|
258
273
|
|
259
274
|
// Trim out all falsy values from an array.
|
260
275
|
_.compact = function(array) {
|
261
|
-
return _.
|
276
|
+
return _.filter(array, function(value){ return !!value; });
|
262
277
|
};
|
263
278
|
|
264
279
|
// Return a completely flattened version of an array.
|
@@ -273,7 +288,7 @@
|
|
273
288
|
// Return a version of the array that does not contain the specified value(s).
|
274
289
|
_.without = function(array) {
|
275
290
|
var values = _.rest(arguments);
|
276
|
-
return _.
|
291
|
+
return _.filter(array, function(value){ return !_.include(values, value); });
|
277
292
|
};
|
278
293
|
|
279
294
|
// Produce a duplicate-free version of the array. If the array has already
|
@@ -289,8 +304,8 @@
|
|
289
304
|
// passed-in arrays.
|
290
305
|
_.intersect = function(array) {
|
291
306
|
var rest = _.rest(arguments);
|
292
|
-
return _.
|
293
|
-
return _.
|
307
|
+
return _.filter(_.uniq(array), function(item) {
|
308
|
+
return _.every(rest, function(other) {
|
294
309
|
return _.indexOf(other, item) >= 0;
|
295
310
|
});
|
296
311
|
});
|
@@ -302,23 +317,24 @@
|
|
302
317
|
var args = _.toArray(arguments);
|
303
318
|
var length = _.max(_.pluck(args, 'length'));
|
304
319
|
var results = new Array(length);
|
305
|
-
for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
|
320
|
+
for (var i = 0; i < length; i++) results[i] = _.pluck(args, String(i));
|
306
321
|
return results;
|
307
322
|
};
|
308
323
|
|
309
324
|
// If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
310
325
|
// we need this function. Return the position of the first occurence of an
|
311
326
|
// item in an array, or -1 if the item is not included in the array.
|
327
|
+
// Delegates to JavaScript 1.8's native indexOf if available.
|
312
328
|
_.indexOf = function(array, item) {
|
313
|
-
if (array.indexOf) return array.indexOf(item);
|
314
|
-
for (var i=0, l=array.length; i<l; i++) if (array[i] === item) return i;
|
329
|
+
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
330
|
+
for (var i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
|
315
331
|
return -1;
|
316
332
|
};
|
317
333
|
|
318
|
-
|
319
|
-
// if
|
334
|
+
|
335
|
+
// Delegates to JavaScript 1.6's native lastIndexOf if available.
|
320
336
|
_.lastIndexOf = function(array, item) {
|
321
|
-
if (array.lastIndexOf) return array.lastIndexOf(item);
|
337
|
+
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
322
338
|
var i = array.length;
|
323
339
|
while (i--) if (array[i] === item) return i;
|
324
340
|
return -1;
|
@@ -347,7 +363,7 @@
|
|
347
363
|
_.bind = function(func, obj) {
|
348
364
|
var args = _.rest(arguments, 2);
|
349
365
|
return function() {
|
350
|
-
return func.apply(obj ||
|
366
|
+
return func.apply(obj || {}, args.concat(_.toArray(arguments)));
|
351
367
|
};
|
352
368
|
};
|
353
369
|
|
@@ -356,7 +372,7 @@
|
|
356
372
|
_.bindAll = function(obj) {
|
357
373
|
var funcs = _.rest(arguments);
|
358
374
|
if (funcs.length == 0) funcs = _.functions(obj);
|
359
|
-
|
375
|
+
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
360
376
|
return obj;
|
361
377
|
};
|
362
378
|
|
@@ -399,8 +415,9 @@
|
|
399
415
|
// ------------------------- Object Functions: ------------------------------
|
400
416
|
|
401
417
|
// Retrieve the names of an object's properties.
|
402
|
-
|
403
|
-
|
418
|
+
// Delegates to ECMA5's native Object.keys
|
419
|
+
_.keys = nativeKeys || function(obj) {
|
420
|
+
if (_.isArray(obj)) return _.range(0, obj.length);
|
404
421
|
var keys = [];
|
405
422
|
for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
|
406
423
|
return keys;
|
@@ -411,9 +428,9 @@
|
|
411
428
|
return _.map(obj, _.identity);
|
412
429
|
};
|
413
430
|
|
414
|
-
// Return a sorted list of the function names available
|
431
|
+
// Return a sorted list of the function names available on the object.
|
415
432
|
_.functions = function(obj) {
|
416
|
-
return _.
|
433
|
+
return _.filter(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
|
417
434
|
};
|
418
435
|
|
419
436
|
// Extend a given object with all of the properties in a source object.
|
@@ -473,7 +490,9 @@
|
|
473
490
|
|
474
491
|
// Is a given array or object empty?
|
475
492
|
_.isEmpty = function(obj) {
|
476
|
-
|
493
|
+
if (_.isArray(obj)) return obj.length === 0;
|
494
|
+
for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
|
495
|
+
return true;
|
477
496
|
};
|
478
497
|
|
479
498
|
// Is a given value a DOM element?
|
@@ -482,7 +501,8 @@
|
|
482
501
|
};
|
483
502
|
|
484
503
|
// Is a given value an array?
|
485
|
-
|
504
|
+
// Delegates to ECMA5's native Array.isArray
|
505
|
+
_.isArray = nativeIsArray || function(obj) {
|
486
506
|
return !!(obj && obj.concat && obj.unshift);
|
487
507
|
};
|
488
508
|
|
@@ -546,11 +566,24 @@
|
|
546
566
|
return value;
|
547
567
|
};
|
548
568
|
|
569
|
+
// Run a function n times.
|
570
|
+
_.times = function (n, iterator, context) {
|
571
|
+
for (var i = 0; i < n; i++) iterator.call(context, i);
|
572
|
+
};
|
573
|
+
|
549
574
|
// Break out of the middle of an iteration.
|
550
575
|
_.breakLoop = function() {
|
551
576
|
throw breaker;
|
552
577
|
};
|
553
578
|
|
579
|
+
// Add your own custom functions to the Underscore object, ensuring that
|
580
|
+
// they're correctly added to the OOP wrapper as well.
|
581
|
+
_.mixin = function(obj) {
|
582
|
+
each(_.functions(obj), function(name){
|
583
|
+
addToWrapper(name, _[name] = obj[name]);
|
584
|
+
});
|
585
|
+
};
|
586
|
+
|
554
587
|
// Generate a unique integer id (unique within the entire client session).
|
555
588
|
// Useful for temporary DOM ids.
|
556
589
|
var idCounter = 0;
|
@@ -570,13 +603,15 @@
|
|
570
603
|
// JavaScript templating a-la ERB, pilfered from John Resig's
|
571
604
|
// "Secrets of the JavaScript Ninja", page 83.
|
572
605
|
// Single-quote fix from Rick Strahl's version.
|
606
|
+
// With alterations for arbitrary delimiters.
|
573
607
|
_.template = function(str, data) {
|
574
608
|
var c = _.templateSettings;
|
609
|
+
var endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g");
|
575
610
|
var fn = new Function('obj',
|
576
611
|
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
577
612
|
'with(obj){p.push(\'' +
|
578
613
|
str.replace(/[\r\t\n]/g, " ")
|
579
|
-
.replace(
|
614
|
+
.replace(endMatch,"\t")
|
580
615
|
.split("'").join("\\'")
|
581
616
|
.split("\t").join("'")
|
582
617
|
.replace(c.interpolate, "',$1,'")
|
@@ -588,36 +623,43 @@
|
|
588
623
|
|
589
624
|
// ------------------------------- Aliases ----------------------------------
|
590
625
|
|
591
|
-
_.
|
626
|
+
_.each = _.forEach;
|
592
627
|
_.foldl = _.inject = _.reduce;
|
593
628
|
_.foldr = _.reduceRight;
|
594
|
-
_.
|
595
|
-
_.
|
596
|
-
_.
|
629
|
+
_.select = _.filter;
|
630
|
+
_.all = _.every;
|
631
|
+
_.any = _.some;
|
597
632
|
_.head = _.first;
|
598
633
|
_.tail = _.rest;
|
599
634
|
_.methods = _.functions;
|
600
635
|
|
601
636
|
// ------------------------ Setup the OOP Wrapper: --------------------------
|
602
637
|
|
638
|
+
// If Underscore is called as a function, it returns a wrapped object that
|
639
|
+
// can be used OO-style. This wrapper holds altered versions of all the
|
640
|
+
// underscore functions. Wrapped objects may be chained.
|
641
|
+
var wrapper = function(obj) { this._wrapped = obj; };
|
642
|
+
|
603
643
|
// Helper function to continue chaining intermediate results.
|
604
644
|
var result = function(obj, chain) {
|
605
645
|
return chain ? _(obj).chain() : obj;
|
606
646
|
};
|
607
647
|
|
608
|
-
//
|
609
|
-
|
610
|
-
var method = _[name];
|
648
|
+
// A method to easily add functions to the OOP wrapper.
|
649
|
+
var addToWrapper = function(name, func) {
|
611
650
|
wrapper.prototype[name] = function() {
|
612
651
|
var args = _.toArray(arguments);
|
613
652
|
unshift.call(args, this._wrapped);
|
614
|
-
return result(
|
653
|
+
return result(func.apply(_, args), this._chain);
|
615
654
|
};
|
616
|
-
}
|
655
|
+
};
|
656
|
+
|
657
|
+
// Add all of the Underscore functions to the wrapper object.
|
658
|
+
_.mixin(_);
|
617
659
|
|
618
660
|
// Add all mutator Array functions to the wrapper.
|
619
|
-
|
620
|
-
var method =
|
661
|
+
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
662
|
+
var method = ArrayProto[name];
|
621
663
|
wrapper.prototype[name] = function() {
|
622
664
|
method.apply(this._wrapped, arguments);
|
623
665
|
return result(this._wrapped, this._chain);
|
@@ -625,8 +667,8 @@
|
|
625
667
|
});
|
626
668
|
|
627
669
|
// Add all accessor Array functions to the wrapper.
|
628
|
-
|
629
|
-
var method =
|
670
|
+
each(['concat', 'join', 'slice'], function(name) {
|
671
|
+
var method = ArrayProto[name];
|
630
672
|
wrapper.prototype[name] = function() {
|
631
673
|
return result(method.apply(this._wrapped, arguments), this._chain);
|
632
674
|
};
|