underscore-rails 1.2.0 → 1.2.2

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.
@@ -1,5 +1,5 @@
1
1
  module Underscore
2
2
  module Rails
3
- VERSION = "1.2.0"
3
+ VERSION = "1.2.2"
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- // Underscore.js 1.2.0
1
+ // Underscore.js 1.2.2
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,
@@ -48,19 +48,26 @@
48
48
  // Create a safe reference to the Underscore object for use below.
49
49
  var _ = function(obj) { return new wrapper(obj); };
50
50
 
51
- // Export the Underscore object for **CommonJS**, with backwards-compatibility
52
- // for the old `require()` API. If we're not in CommonJS, add `_` to the
53
- // global object.
54
- if (typeof module !== 'undefined' && module.exports) {
55
- module.exports = _;
56
- _._ = _;
51
+ // Export the Underscore object for **Node.js** and **"CommonJS"**, with
52
+ // backwards-compatibility for the old `require()` API. If we're not in
53
+ // CommonJS, add `_` to the global object.
54
+ if (typeof exports !== 'undefined') {
55
+ if (typeof module !== 'undefined' && module.exports) {
56
+ exports = module.exports = _;
57
+ }
58
+ exports._ = _;
59
+ } else if (typeof define === 'function' && define.amd) {
60
+ // Register as a named module with AMD.
61
+ define('underscore', function() {
62
+ return _;
63
+ });
57
64
  } else {
58
65
  // Exported as a string, for Closure Compiler "advanced" mode.
59
66
  root['_'] = _;
60
67
  }
61
68
 
62
69
  // Current version.
63
- _.VERSION = '1.2.0';
70
+ _.VERSION = '1.2.2';
64
71
 
65
72
  // Collection Functions
66
73
  // --------------------
@@ -187,7 +194,7 @@
187
194
  if (obj == null) return result;
188
195
  if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
189
196
  each(obj, function(value, index, list) {
190
- if (result |= iterator.call(context, value, index, list)) return breaker;
197
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
191
198
  });
192
199
  return !!result;
193
200
  };
@@ -198,8 +205,8 @@
198
205
  var found = false;
199
206
  if (obj == null) return found;
200
207
  if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
201
- any(obj, function(value) {
202
- if (found = value === target) return true;
208
+ found = any(obj, function(value) {
209
+ return value === target;
203
210
  });
204
211
  return found;
205
212
  };
@@ -269,9 +276,11 @@
269
276
  }), 'value');
270
277
  };
271
278
 
272
- // Groups the object's values by a criterion produced by an iterator
273
- _.groupBy = function(obj, iterator) {
279
+ // Groups the object's values by a criterion. Pass either a string attribute
280
+ // to group by, or a function that returns the criterion.
281
+ _.groupBy = function(obj, val) {
274
282
  var result = {};
283
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
275
284
  each(obj, function(value, index) {
276
285
  var key = iterator(value, index);
277
286
  (result[key] || (result[key] = [])).push(value);
@@ -326,7 +335,11 @@
326
335
  // Get the last element of an array. Passing **n** will return the last N
327
336
  // values in the array. The **guard** check allows it to work with `_.map`.
328
337
  _.last = function(array, n, guard) {
329
- return (n != null) && !guard ? slice.call(array, array.length - n) : array[array.length - 1];
338
+ if ((n != null) && !guard) {
339
+ return slice.call(array, Math.max(array.length - n, 0));
340
+ } else {
341
+ return array[array.length - 1];
342
+ }
330
343
  };
331
344
 
332
345
  // Returns everything but the first entry of the array. Aliased as `tail`.
@@ -343,9 +356,9 @@
343
356
  };
344
357
 
345
358
  // Return a completely flattened version of an array.
346
- _.flatten = function(array) {
359
+ _.flatten = function(array, shallow) {
347
360
  return _.reduce(array, function(memo, value) {
348
- if (_.isArray(value)) return memo.concat(_.flatten(value));
361
+ if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
349
362
  memo[memo.length] = value;
350
363
  return memo;
351
364
  }, []);
@@ -375,7 +388,7 @@
375
388
  // Produce an array that contains the union: each distinct element from all of
376
389
  // the passed-in arrays.
377
390
  _.union = function() {
378
- return _.uniq(_.flatten(arguments));
391
+ return _.uniq(_.flatten(arguments, true));
379
392
  };
380
393
 
381
394
  // Produce an array that contains every item shared between all the
@@ -457,15 +470,25 @@
457
470
  // Function (ahem) Functions
458
471
  // ------------------
459
472
 
473
+ // Reusable constructor function for prototype setting.
474
+ var ctor = function(){};
475
+
460
476
  // Create a function bound to a given object (assigning `this`, and arguments,
461
477
  // optionally). Binding with arguments is also known as `curry`.
462
478
  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
463
479
  // We check for `func.bind` first, to fail fast when `func` is undefined.
464
- _.bind = function(func, obj) {
480
+ _.bind = function bind(func, context) {
481
+ var bound, args;
465
482
  if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
466
- var args = slice.call(arguments, 2);
467
- return function() {
468
- return func.apply(obj, args.concat(slice.call(arguments)));
483
+ if (!_.isFunction(func)) throw new TypeError;
484
+ args = slice.call(arguments, 2);
485
+ return bound = function() {
486
+ if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
487
+ ctor.prototype = func.prototype;
488
+ var self = new ctor;
489
+ var result = func.apply(self, args.concat(slice.call(arguments)));
490
+ if (Object(result) === result) return result;
491
+ return self;
469
492
  };
470
493
  };
471
494
 
@@ -501,31 +524,43 @@
501
524
  return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
502
525
  };
503
526
 
504
- // Internal function used to implement `_.throttle` and `_.debounce`.
505
- var limit = function(func, wait, debounce) {
506
- var timeout;
527
+ // Returns a function, that, when invoked, will only be triggered at most once
528
+ // during a given window of time.
529
+ _.throttle = function(func, wait) {
530
+ var context, args, timeout, throttling, more;
531
+ var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
507
532
  return function() {
508
- var context = this, args = arguments;
509
- var throttler = function() {
533
+ context = this; args = arguments;
534
+ var later = function() {
510
535
  timeout = null;
511
- func.apply(context, args);
536
+ if (more) func.apply(context, args);
537
+ whenDone();
512
538
  };
513
- if (debounce) clearTimeout(timeout);
514
- if (debounce || !timeout) timeout = setTimeout(throttler, wait);
539
+ if (!timeout) timeout = setTimeout(later, wait);
540
+ if (throttling) {
541
+ more = true;
542
+ } else {
543
+ func.apply(context, args);
544
+ }
545
+ whenDone();
546
+ throttling = true;
515
547
  };
516
548
  };
517
549
 
518
- // Returns a function, that, when invoked, will only be triggered at most once
519
- // during a given window of time.
520
- _.throttle = function(func, wait) {
521
- return limit(func, wait, false);
522
- };
523
-
524
550
  // Returns a function, that, as long as it continues to be invoked, will not
525
551
  // be triggered. The function will be called after it stops being called for
526
552
  // N milliseconds.
527
553
  _.debounce = function(func, wait) {
528
- return limit(func, wait, true);
554
+ var timeout;
555
+ return function() {
556
+ var context = this, args = arguments;
557
+ var later = function() {
558
+ timeout = null;
559
+ func.apply(context, args);
560
+ };
561
+ clearTimeout(timeout);
562
+ timeout = setTimeout(later, wait);
563
+ };
529
564
  };
530
565
 
531
566
  // Returns a function that will be executed at most one time, no matter how
@@ -564,6 +599,7 @@
564
599
 
565
600
  // Returns a function that will only be executed after being called N times.
566
601
  _.after = function(times, func) {
602
+ if (times <= 0) return func();
567
603
  return function() {
568
604
  if (--times < 1) { return func.apply(this, arguments); }
569
605
  };
@@ -618,6 +654,7 @@
618
654
 
619
655
  // Create a (shallow-cloned) duplicate of an object.
620
656
  _.clone = function(obj) {
657
+ if (!_.isObject(obj)) return obj;
621
658
  return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
622
659
  };
623
660
 
@@ -635,66 +672,68 @@
635
672
  // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
636
673
  if (a === b) return a !== 0 || 1 / a == 1 / b;
637
674
  // 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;
675
+ if (a == null || b == null) return a === b;
670
676
  // Unwrap any wrapped objects.
671
677
  if (a._chain) a = a._wrapped;
672
678
  if (b._chain) b = b._wrapped;
673
679
  // Invoke a custom `isEqual` method if one is provided.
674
680
  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`.
681
+ if (_.isFunction(b.isEqual)) return b.isEqual(a);
682
+ // Compare `[[Class]]` names.
683
+ var className = toString.call(a);
684
+ if (className != toString.call(b)) return false;
685
+ switch (className) {
686
+ // Strings, numbers, dates, and booleans are compared by value.
687
+ case '[object String]':
688
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
689
+ // equivalent to `new String("5")`.
690
+ return String(a) == String(b);
691
+ case '[object Number]':
692
+ a = +a;
693
+ b = +b;
694
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
695
+ // other numeric values.
696
+ return a != a ? b != b : (a == 0 ? 1 / a == 1 / b : a == b);
697
+ case '[object Date]':
698
+ case '[object Boolean]':
699
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
700
+ // millisecond representations. Note that invalid dates with millisecond representations
701
+ // of `NaN` are not equivalent.
702
+ return +a == +b;
703
+ // RegExps are compared by their source patterns and flags.
704
+ case '[object RegExp]':
705
+ return a.source == b.source &&
706
+ a.global == b.global &&
707
+ a.multiline == b.multiline &&
708
+ a.ignoreCase == b.ignoreCase;
709
+ }
710
+ if (typeof a != 'object' || typeof b != 'object') return false;
711
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
712
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
677
713
  var length = stack.length;
678
714
  while (length--) {
679
- // Linear search. Performance is inversely proportional to the number of unique nested
680
- // structures.
715
+ // Linear search. Performance is inversely proportional to the number of
716
+ // unique nested structures.
681
717
  if (stack[length] == a) return true;
682
718
  }
683
719
  // Add the first object to the stack of traversed objects.
684
720
  stack.push(a);
685
721
  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.
722
+ // Recursively compare objects and arrays.
723
+ if (className == '[object Array]') {
724
+ // Compare array lengths to determine if a deep comparison is necessary.
688
725
  size = a.length;
689
726
  result = size == b.length;
690
727
  if (result) {
691
- // Deep compare array-like object contents, ignoring non-numeric properties.
728
+ // Deep compare the contents, ignoring non-numeric properties.
692
729
  while (size--) {
693
730
  // Ensure commutative equality for sparse arrays.
694
731
  if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
695
732
  }
696
733
  }
697
734
  } else {
735
+ // Objects with different constructors are not equivalent.
736
+ if ("constructor" in a != "constructor" in b || a.constructor != b.constructor) return false;
698
737
  // Deep compare objects.
699
738
  for (var key in a) {
700
739
  if (hasOwnProperty.call(a, key)) {
@@ -707,7 +746,7 @@
707
746
  // Ensure that both objects contain the same number of properties.
708
747
  if (result) {
709
748
  for (key in b) {
710
- if (hasOwnProperty.call(b, key) && !size--) break;
749
+ if (hasOwnProperty.call(b, key) && !(size--)) break;
711
750
  }
712
751
  result = !size;
713
752
  }
@@ -722,7 +761,8 @@
722
761
  return eq(a, b, []);
723
762
  };
724
763
 
725
- // Is a given array or object empty?
764
+ // Is a given array, string, or object empty?
765
+ // An "empty" object has no enumerable own-properties.
726
766
  _.isEmpty = function(obj) {
727
767
  if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
728
768
  for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
@@ -737,7 +777,7 @@
737
777
  // Is a given value an array?
738
778
  // Delegates to ECMA5's native Array.isArray
739
779
  _.isArray = nativeIsArray || function(obj) {
740
- return toString.call(obj) === '[object Array]';
780
+ return toString.call(obj) == '[object Array]';
741
781
  };
742
782
 
743
783
  // Is a given variable an object?
@@ -746,28 +786,34 @@
746
786
  };
747
787
 
748
788
  // Is a given variable an arguments object?
749
- _.isArguments = function(obj) {
750
- return !!(obj && hasOwnProperty.call(obj, 'callee'));
751
- };
789
+ if (toString.call(arguments) == '[object Arguments]') {
790
+ _.isArguments = function(obj) {
791
+ return toString.call(obj) == '[object Arguments]';
792
+ };
793
+ } else {
794
+ _.isArguments = function(obj) {
795
+ return !!(obj && hasOwnProperty.call(obj, 'callee'));
796
+ };
797
+ }
752
798
 
753
799
  // Is a given value a function?
754
800
  _.isFunction = function(obj) {
755
- return !!(obj && obj.constructor && obj.call && obj.apply);
801
+ return toString.call(obj) == '[object Function]';
756
802
  };
757
803
 
758
804
  // Is a given value a string?
759
805
  _.isString = function(obj) {
760
- return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
806
+ return toString.call(obj) == '[object String]';
761
807
  };
762
808
 
763
809
  // Is a given value a number?
764
810
  _.isNumber = function(obj) {
765
- return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
811
+ return toString.call(obj) == '[object Number]';
766
812
  };
767
813
 
768
- // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
769
- // that does not equal itself.
814
+ // Is the given value `NaN`?
770
815
  _.isNaN = function(obj) {
816
+ // `NaN` is the only value for which `===` is not reflexive.
771
817
  return obj !== obj;
772
818
  };
773
819
 
@@ -778,12 +824,12 @@
778
824
 
779
825
  // Is a given value a date?
780
826
  _.isDate = function(obj) {
781
- return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
827
+ return toString.call(obj) == '[object Date]';
782
828
  };
783
829
 
784
830
  // Is the given value a regular expression?
785
831
  _.isRegExp = function(obj) {
786
- return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
832
+ return toString.call(obj) == '[object RegExp]';
787
833
  };
788
834
 
789
835
  // Is a given value equal to null?
@@ -818,7 +864,7 @@
818
864
 
819
865
  // Escape a string for HTML interpolation.
820
866
  _.escape = function(string) {
821
- return (''+string).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
867
+ return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
822
868
  };
823
869
 
824
870
  // Add your own custom functions to the Underscore object, ensuring that
@@ -862,14 +908,14 @@
862
908
  })
863
909
  .replace(c.evaluate || null, function(match, code) {
864
910
  return "');" + code.replace(/\\'/g, "'")
865
- .replace(/[\r\n\t]/g, ' ') + "__p.push('";
911
+ .replace(/[\r\n\t]/g, ' ') + ";__p.push('";
866
912
  })
867
913
  .replace(/\r/g, '\\r')
868
914
  .replace(/\n/g, '\\n')
869
915
  .replace(/\t/g, '\\t')
870
916
  + "');}return __p.join('');";
871
- var func = new Function('obj', tmpl);
872
- return data ? func(data) : func;
917
+ var func = new Function('obj', '_', tmpl);
918
+ return data ? func(data, _) : function(data) { return func(data, _) };
873
919
  };
874
920
 
875
921
  // The OOP Wrapper
@@ -928,4 +974,4 @@
928
974
  return this._wrapped;
929
975
  };
930
976
 
931
- })();
977
+ }).call(this);
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: underscore-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-24 00:00:00.000000000Z
12
+ date: 2011-11-25 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description:
15
15
  email:
@@ -51,3 +51,4 @@ signing_key:
51
51
  specification_version: 3
52
52
  summary: underscore.js asset pipeline provider/wrapper
53
53
  test_files: []
54
+ has_rdoc: