underscore-source 1.1.7 → 1.2.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 +141 -49
- metadata +1 -1
@@ -1,4 +1,4 @@
|
|
1
|
-
// Underscore.js 1.
|
1
|
+
// Underscore.js 1.2.0
|
2
2
|
// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
|
3
3
|
// Underscore is freely distributable under the MIT license.
|
4
4
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
@@ -60,7 +60,7 @@
|
|
60
60
|
}
|
61
61
|
|
62
62
|
// Current version.
|
63
|
-
_.VERSION = '1.
|
63
|
+
_.VERSION = '1.2.0';
|
64
64
|
|
65
65
|
// Collection Functions
|
66
66
|
// --------------------
|
@@ -220,6 +220,7 @@
|
|
220
220
|
// Return the maximum element or (element-based computation).
|
221
221
|
_.max = function(obj, iterator, context) {
|
222
222
|
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
223
|
+
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
223
224
|
var result = {computed : -Infinity};
|
224
225
|
each(obj, function(value, index, list) {
|
225
226
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
@@ -231,6 +232,7 @@
|
|
231
232
|
// Return the minimum element (or element-based computation).
|
232
233
|
_.min = function(obj, iterator, context) {
|
233
234
|
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
235
|
+
if (!iterator && _.isEmpty(obj)) return Infinity;
|
234
236
|
var result = {computed : Infinity};
|
235
237
|
each(obj, function(value, index, list) {
|
236
238
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
@@ -239,6 +241,21 @@
|
|
239
241
|
return result.value;
|
240
242
|
};
|
241
243
|
|
244
|
+
// Shuffle an array.
|
245
|
+
_.shuffle = function(obj) {
|
246
|
+
var shuffled = [], rand;
|
247
|
+
each(obj, function(value, index, list) {
|
248
|
+
if (index == 0) {
|
249
|
+
shuffled[0] = value;
|
250
|
+
} else {
|
251
|
+
rand = Math.floor(Math.random() * (index + 1));
|
252
|
+
shuffled[index] = shuffled[rand];
|
253
|
+
shuffled[rand] = value;
|
254
|
+
}
|
255
|
+
});
|
256
|
+
return shuffled;
|
257
|
+
};
|
258
|
+
|
242
259
|
// Sort the object's values by a criterion produced by an iterator.
|
243
260
|
_.sortBy = function(obj, iterator, context) {
|
244
261
|
return _.pluck(_.map(obj, function(value, index, list) {
|
@@ -298,6 +315,20 @@
|
|
298
315
|
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
299
316
|
};
|
300
317
|
|
318
|
+
// Returns everything but the last entry of the array. Especcialy useful on
|
319
|
+
// the arguments object. Passing **n** will return all the values in
|
320
|
+
// the array, excluding the last N. The **guard** check allows it to work with
|
321
|
+
// `_.map`.
|
322
|
+
_.initial = function(array, n, guard) {
|
323
|
+
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
|
324
|
+
};
|
325
|
+
|
326
|
+
// Get the last element of an array. Passing **n** will return the last N
|
327
|
+
// values in the array. The **guard** check allows it to work with `_.map`.
|
328
|
+
_.last = function(array, n, guard) {
|
329
|
+
return (n != null) && !guard ? slice.call(array, array.length - n) : array[array.length - 1];
|
330
|
+
};
|
331
|
+
|
301
332
|
// Returns everything but the first entry of the array. Aliased as `tail`.
|
302
333
|
// Especially useful on the arguments object. Passing an **index** will return
|
303
334
|
// the rest of the values in the array from that index onward. The **guard**
|
@@ -306,11 +337,6 @@
|
|
306
337
|
return slice.call(array, (index == null) || guard ? 1 : index);
|
307
338
|
};
|
308
339
|
|
309
|
-
// Get the last element of an array.
|
310
|
-
_.last = function(array) {
|
311
|
-
return array[array.length - 1];
|
312
|
-
};
|
313
|
-
|
314
340
|
// Trim out all falsy values from an array.
|
315
341
|
_.compact = function(array) {
|
316
342
|
return _.filter(array, function(value){ return !!value; });
|
@@ -333,11 +359,17 @@
|
|
333
359
|
// Produce a duplicate-free version of the array. If the array has already
|
334
360
|
// been sorted, you have the option of using a faster algorithm.
|
335
361
|
// Aliased as `unique`.
|
336
|
-
_.uniq = _.unique = function(array, isSorted) {
|
337
|
-
|
338
|
-
|
362
|
+
_.uniq = _.unique = function(array, isSorted, iterator) {
|
363
|
+
var initial = iterator ? _.map(array, iterator) : array;
|
364
|
+
var result = [];
|
365
|
+
_.reduce(initial, function(memo, el, i) {
|
366
|
+
if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
|
367
|
+
memo[memo.length] = el;
|
368
|
+
result[result.length] = array[i];
|
369
|
+
}
|
339
370
|
return memo;
|
340
371
|
}, []);
|
372
|
+
return result;
|
341
373
|
};
|
342
374
|
|
343
375
|
// Produce an array that contains the union: each distinct element from all of
|
@@ -391,7 +423,6 @@
|
|
391
423
|
return -1;
|
392
424
|
};
|
393
425
|
|
394
|
-
|
395
426
|
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
396
427
|
_.lastIndexOf = function(array, item) {
|
397
428
|
if (array == null) return -1;
|
@@ -538,7 +569,6 @@
|
|
538
569
|
};
|
539
570
|
};
|
540
571
|
|
541
|
-
|
542
572
|
// Object Functions
|
543
573
|
// ----------------
|
544
574
|
|
@@ -599,44 +629,97 @@
|
|
599
629
|
return obj;
|
600
630
|
};
|
601
631
|
|
602
|
-
//
|
603
|
-
|
604
|
-
//
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
if (
|
609
|
-
//
|
610
|
-
|
611
|
-
|
612
|
-
|
632
|
+
// Internal recursive comparison function.
|
633
|
+
function eq(a, b, stack) {
|
634
|
+
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
635
|
+
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
636
|
+
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
637
|
+
// A strict comparison is necessary because `null == undefined`.
|
638
|
+
if (a == null) return a === b;
|
639
|
+
// Compare object types.
|
640
|
+
var typeA = typeof a;
|
641
|
+
if (typeA != typeof b) return false;
|
642
|
+
// Optimization; ensure that both values are truthy or falsy.
|
643
|
+
if (!a != !b) return false;
|
644
|
+
// `NaN` values are equal.
|
645
|
+
if (_.isNaN(a)) return _.isNaN(b);
|
646
|
+
// Compare string objects by value.
|
647
|
+
var isStringA = _.isString(a), isStringB = _.isString(b);
|
648
|
+
if (isStringA || isStringB) return isStringA && isStringB && String(a) == String(b);
|
649
|
+
// Compare number objects by value.
|
650
|
+
var isNumberA = _.isNumber(a), isNumberB = _.isNumber(b);
|
651
|
+
if (isNumberA || isNumberB) return isNumberA && isNumberB && +a == +b;
|
652
|
+
// Compare boolean objects by value. The value of `true` is 1; the value of `false` is 0.
|
653
|
+
var isBooleanA = _.isBoolean(a), isBooleanB = _.isBoolean(b);
|
654
|
+
if (isBooleanA || isBooleanB) return isBooleanA && isBooleanB && +a == +b;
|
655
|
+
// Compare dates by their millisecond values.
|
656
|
+
var isDateA = _.isDate(a), isDateB = _.isDate(b);
|
657
|
+
if (isDateA || isDateB) return isDateA && isDateB && a.getTime() == b.getTime();
|
658
|
+
// Compare RegExps by their source patterns and flags.
|
659
|
+
var isRegExpA = _.isRegExp(a), isRegExpB = _.isRegExp(b);
|
660
|
+
if (isRegExpA || isRegExpB) {
|
661
|
+
// Ensure commutative equality for RegExps.
|
662
|
+
return isRegExpA && isRegExpB &&
|
663
|
+
a.source == b.source &&
|
664
|
+
a.global == b.global &&
|
665
|
+
a.multiline == b.multiline &&
|
666
|
+
a.ignoreCase == b.ignoreCase;
|
667
|
+
}
|
668
|
+
// Ensure that both values are objects.
|
669
|
+
if (typeA != 'object') return false;
|
613
670
|
// Unwrap any wrapped objects.
|
614
671
|
if (a._chain) a = a._wrapped;
|
615
672
|
if (b._chain) b = b._wrapped;
|
616
|
-
//
|
617
|
-
if (a.isEqual) return a.isEqual(b);
|
618
|
-
|
619
|
-
//
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
673
|
+
// Invoke a custom `isEqual` method if one is provided.
|
674
|
+
if (_.isFunction(a.isEqual)) return a.isEqual(b);
|
675
|
+
// Assume equality for cyclic structures. The algorithm for detecting cyclic structures is
|
676
|
+
// adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
677
|
+
var length = stack.length;
|
678
|
+
while (length--) {
|
679
|
+
// Linear search. Performance is inversely proportional to the number of unique nested
|
680
|
+
// structures.
|
681
|
+
if (stack[length] == a) return true;
|
682
|
+
}
|
683
|
+
// Add the first object to the stack of traversed objects.
|
684
|
+
stack.push(a);
|
685
|
+
var size = 0, result = true;
|
686
|
+
if (a.length === +a.length || b.length === +b.length) {
|
687
|
+
// Compare object lengths to determine if a deep comparison is necessary.
|
688
|
+
size = a.length;
|
689
|
+
result = size == b.length;
|
690
|
+
if (result) {
|
691
|
+
// Deep compare array-like object contents, ignoring non-numeric properties.
|
692
|
+
while (size--) {
|
693
|
+
// Ensure commutative equality for sparse arrays.
|
694
|
+
if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
|
695
|
+
}
|
696
|
+
}
|
697
|
+
} else {
|
698
|
+
// Deep compare objects.
|
699
|
+
for (var key in a) {
|
700
|
+
if (hasOwnProperty.call(a, key)) {
|
701
|
+
// Count the expected number of properties.
|
702
|
+
size++;
|
703
|
+
// Deep compare each member.
|
704
|
+
if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
|
705
|
+
}
|
706
|
+
}
|
707
|
+
// Ensure that both objects contain the same number of properties.
|
708
|
+
if (result) {
|
709
|
+
for (key in b) {
|
710
|
+
if (hasOwnProperty.call(b, key) && !size--) break;
|
711
|
+
}
|
712
|
+
result = !size;
|
713
|
+
}
|
714
|
+
}
|
715
|
+
// Remove the first object from the stack of traversed objects.
|
716
|
+
stack.pop();
|
717
|
+
return result;
|
718
|
+
}
|
719
|
+
|
720
|
+
// Perform a deep comparison to check if two objects are equal.
|
721
|
+
_.isEqual = function(a, b) {
|
722
|
+
return eq(a, b, []);
|
640
723
|
};
|
641
724
|
|
642
725
|
// Is a given array or object empty?
|
@@ -690,7 +773,7 @@
|
|
690
773
|
|
691
774
|
// Is a given value a boolean?
|
692
775
|
_.isBoolean = function(obj) {
|
693
|
-
return obj === true || obj === false;
|
776
|
+
return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
|
694
777
|
};
|
695
778
|
|
696
779
|
// Is a given value a date?
|
@@ -733,6 +816,11 @@
|
|
733
816
|
for (var i = 0; i < n; i++) iterator.call(context, i);
|
734
817
|
};
|
735
818
|
|
819
|
+
// Escape a string for HTML interpolation.
|
820
|
+
_.escape = function(string) {
|
821
|
+
return (''+string).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
822
|
+
};
|
823
|
+
|
736
824
|
// Add your own custom functions to the Underscore object, ensuring that
|
737
825
|
// they're correctly added to the OOP wrapper as well.
|
738
826
|
_.mixin = function(obj) {
|
@@ -753,7 +841,8 @@
|
|
753
841
|
// following template settings to use alternative delimiters.
|
754
842
|
_.templateSettings = {
|
755
843
|
evaluate : /<%([\s\S]+?)%>/g,
|
756
|
-
interpolate : /<%=([\s\S]+?)%>/g
|
844
|
+
interpolate : /<%=([\s\S]+?)%>/g,
|
845
|
+
escape : /<%-([\s\S]+?)%>/g
|
757
846
|
};
|
758
847
|
|
759
848
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
@@ -765,6 +854,9 @@
|
|
765
854
|
'with(obj||{}){__p.push(\'' +
|
766
855
|
str.replace(/\\/g, '\\\\')
|
767
856
|
.replace(/'/g, "\\'")
|
857
|
+
.replace(c.escape, function(match, code) {
|
858
|
+
return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
|
859
|
+
})
|
768
860
|
.replace(c.interpolate, function(match, code) {
|
769
861
|
return "'," + code.replace(/\\'/g, "'") + ",'";
|
770
862
|
})
|