underscore-source 1.3.1 → 1.3.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 Source
3
- VERSION = "1.3.1"
3
+ VERSION = "1.3.2"
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- // Underscore.js 1.3.1
1
+ // Underscore.js 1.3.2
2
2
  // (c) 2009-2012 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,
@@ -62,7 +62,7 @@
62
62
  }
63
63
 
64
64
  // Current version.
65
- _.VERSION = '1.3.1';
65
+ _.VERSION = '1.3.2';
66
66
 
67
67
  // Collection Functions
68
68
  // --------------------
@@ -180,7 +180,7 @@
180
180
  each(obj, function(value, index, list) {
181
181
  if (!(result = result && iterator.call(context, value, index, list))) return breaker;
182
182
  });
183
- return result;
183
+ return !!result;
184
184
  };
185
185
 
186
186
  // Determine if at least one element in the object matches a truth test.
@@ -224,7 +224,7 @@
224
224
 
225
225
  // Return the maximum element or (element-based computation).
226
226
  _.max = function(obj, iterator, context) {
227
- if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
227
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj);
228
228
  if (!iterator && _.isEmpty(obj)) return -Infinity;
229
229
  var result = {computed : -Infinity};
230
230
  each(obj, function(value, index, list) {
@@ -236,7 +236,7 @@
236
236
 
237
237
  // Return the minimum element (or element-based computation).
238
238
  _.min = function(obj, iterator, context) {
239
- if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
239
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
240
240
  if (!iterator && _.isEmpty(obj)) return Infinity;
241
241
  var result = {computed : Infinity};
242
242
  each(obj, function(value, index, list) {
@@ -250,19 +250,16 @@
250
250
  _.shuffle = function(obj) {
251
251
  var shuffled = [], rand;
252
252
  each(obj, function(value, index, list) {
253
- if (index == 0) {
254
- shuffled[0] = value;
255
- } else {
256
- rand = Math.floor(Math.random() * (index + 1));
257
- shuffled[index] = shuffled[rand];
258
- shuffled[rand] = value;
259
- }
253
+ rand = Math.floor(Math.random() * (index + 1));
254
+ shuffled[index] = shuffled[rand];
255
+ shuffled[rand] = value;
260
256
  });
261
257
  return shuffled;
262
258
  };
263
259
 
264
260
  // Sort the object's values by a criterion produced by an iterator.
265
- _.sortBy = function(obj, iterator, context) {
261
+ _.sortBy = function(obj, val, context) {
262
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
266
263
  return _.pluck(_.map(obj, function(value, index, list) {
267
264
  return {
268
265
  value : value,
@@ -270,6 +267,8 @@
270
267
  };
271
268
  }).sort(function(left, right) {
272
269
  var a = left.criteria, b = right.criteria;
270
+ if (a === void 0) return 1;
271
+ if (b === void 0) return -1;
273
272
  return a < b ? -1 : a > b ? 1 : 0;
274
273
  }), 'value');
275
274
  };
@@ -299,26 +298,26 @@
299
298
  };
300
299
 
301
300
  // Safely convert anything iterable into a real, live array.
302
- _.toArray = function(iterable) {
303
- if (!iterable) return [];
304
- if (iterable.toArray) return iterable.toArray();
305
- if (_.isArray(iterable)) return slice.call(iterable);
306
- if (_.isArguments(iterable)) return slice.call(iterable);
307
- return _.values(iterable);
301
+ _.toArray = function(obj) {
302
+ if (!obj) return [];
303
+ if (_.isArray(obj)) return slice.call(obj);
304
+ if (_.isArguments(obj)) return slice.call(obj);
305
+ if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
306
+ return _.values(obj);
308
307
  };
309
308
 
310
309
  // Return the number of elements in an object.
311
310
  _.size = function(obj) {
312
- return _.toArray(obj).length;
311
+ return _.isArray(obj) ? obj.length : _.keys(obj).length;
313
312
  };
314
313
 
315
314
  // Array Functions
316
315
  // ---------------
317
316
 
318
317
  // Get the first element of an array. Passing **n** will return the first N
319
- // values in the array. Aliased as `head`. The **guard** check allows it to work
320
- // with `_.map`.
321
- _.first = _.head = function(array, n, guard) {
318
+ // values in the array. Aliased as `head` and `take`. The **guard** check
319
+ // allows it to work with `_.map`.
320
+ _.first = _.head = _.take = function(array, n, guard) {
322
321
  return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
323
322
  };
324
323
 
@@ -372,15 +371,17 @@
372
371
  // Aliased as `unique`.
373
372
  _.uniq = _.unique = function(array, isSorted, iterator) {
374
373
  var initial = iterator ? _.map(array, iterator) : array;
375
- var result = [];
376
- _.reduce(initial, function(memo, el, i) {
377
- if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
378
- memo[memo.length] = el;
379
- result[result.length] = array[i];
374
+ var results = [];
375
+ // The `isSorted` flag is irrelevant if the array only contains two elements.
376
+ if (array.length < 3) isSorted = true;
377
+ _.reduce(initial, function (memo, value, index) {
378
+ if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
379
+ memo.push(value);
380
+ results.push(array[index]);
380
381
  }
381
382
  return memo;
382
383
  }, []);
383
- return result;
384
+ return results;
384
385
  };
385
386
 
386
387
  // Produce an array that contains the union: each distinct element from all of
@@ -403,7 +404,7 @@
403
404
  // Take the difference between one array and a number of other arrays.
404
405
  // Only the elements present in just the first array will remain.
405
406
  _.difference = function(array) {
406
- var rest = _.flatten(slice.call(arguments, 1));
407
+ var rest = _.flatten(slice.call(arguments, 1), true);
407
408
  return _.filter(array, function(value){ return !_.include(rest, value); });
408
409
  };
409
410
 
@@ -514,7 +515,7 @@
514
515
  // it with the arguments supplied.
515
516
  _.delay = function(func, wait) {
516
517
  var args = slice.call(arguments, 2);
517
- return setTimeout(function(){ return func.apply(func, args); }, wait);
518
+ return setTimeout(function(){ return func.apply(null, args); }, wait);
518
519
  };
519
520
 
520
521
  // Defers a function, scheduling it to run after the current call stack has
@@ -526,7 +527,7 @@
526
527
  // Returns a function, that, when invoked, will only be triggered at most once
527
528
  // during a given window of time.
528
529
  _.throttle = function(func, wait) {
529
- var context, args, timeout, throttling, more;
530
+ var context, args, timeout, throttling, more, result;
530
531
  var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
531
532
  return function() {
532
533
  context = this; args = arguments;
@@ -539,24 +540,27 @@
539
540
  if (throttling) {
540
541
  more = true;
541
542
  } else {
542
- func.apply(context, args);
543
+ result = func.apply(context, args);
543
544
  }
544
545
  whenDone();
545
546
  throttling = true;
547
+ return result;
546
548
  };
547
549
  };
548
550
 
549
551
  // Returns a function, that, as long as it continues to be invoked, will not
550
552
  // be triggered. The function will be called after it stops being called for
551
- // N milliseconds.
552
- _.debounce = function(func, wait) {
553
+ // N milliseconds. If `immediate` is passed, trigger the function on the
554
+ // leading edge, instead of the trailing.
555
+ _.debounce = function(func, wait, immediate) {
553
556
  var timeout;
554
557
  return function() {
555
558
  var context = this, args = arguments;
556
559
  var later = function() {
557
560
  timeout = null;
558
- func.apply(context, args);
561
+ if (!immediate) func.apply(context, args);
559
562
  };
563
+ if (immediate && !timeout) func.apply(context, args);
560
564
  clearTimeout(timeout);
561
565
  timeout = setTimeout(later, wait);
562
566
  };
@@ -641,6 +645,15 @@
641
645
  return obj;
642
646
  };
643
647
 
648
+ // Return a copy of the object only containing the whitelisted properties.
649
+ _.pick = function(obj) {
650
+ var result = {};
651
+ each(_.flatten(slice.call(arguments, 1)), function(key) {
652
+ if (key in obj) result[key] = obj[key];
653
+ });
654
+ return result;
655
+ };
656
+
644
657
  // Fill in a given object with default properties.
645
658
  _.defaults = function(obj) {
646
659
  each(slice.call(arguments, 1), function(source) {
@@ -761,6 +774,7 @@
761
774
  // Is a given array, string, or object empty?
762
775
  // An "empty" object has no enumerable own-properties.
763
776
  _.isEmpty = function(obj) {
777
+ if (obj == null) return true;
764
778
  if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
765
779
  for (var key in obj) if (_.has(obj, key)) return false;
766
780
  return true;
@@ -807,6 +821,11 @@
807
821
  return toString.call(obj) == '[object Number]';
808
822
  };
809
823
 
824
+ // Is a given object a finite number?
825
+ _.isFinite = function(obj) {
826
+ return _.isNumber(obj) && isFinite(obj);
827
+ };
828
+
810
829
  // Is the given value `NaN`?
811
830
  _.isNaN = function(obj) {
812
831
  // `NaN` is the only value for which `===` is not reflexive.
@@ -868,6 +887,14 @@
868
887
  return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
869
888
  };
870
889
 
890
+ // If the value of the named property is a function then invoke it;
891
+ // otherwise, return it.
892
+ _.result = function(object, property) {
893
+ if (object == null) return null;
894
+ var value = object[property];
895
+ return _.isFunction(value) ? value.call(object) : value;
896
+ };
897
+
871
898
  // Add your own custom functions to the Underscore object, ensuring that
872
899
  // they're correctly added to the OOP wrapper as well.
873
900
  _.mixin = function(obj) {
@@ -897,39 +924,72 @@
897
924
  // guaranteed not to match.
898
925
  var noMatch = /.^/;
899
926
 
927
+ // Certain characters need to be escaped so that they can be put into a
928
+ // string literal.
929
+ var escapes = {
930
+ '\\': '\\',
931
+ "'": "'",
932
+ 'r': '\r',
933
+ 'n': '\n',
934
+ 't': '\t',
935
+ 'u2028': '\u2028',
936
+ 'u2029': '\u2029'
937
+ };
938
+
939
+ for (var p in escapes) escapes[escapes[p]] = p;
940
+ var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
941
+ var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
942
+
900
943
  // Within an interpolation, evaluation, or escaping, remove HTML escaping
901
944
  // that had been previously added.
902
945
  var unescape = function(code) {
903
- return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
946
+ return code.replace(unescaper, function(match, escape) {
947
+ return escapes[escape];
948
+ });
904
949
  };
905
950
 
906
951
  // JavaScript micro-templating, similar to John Resig's implementation.
907
952
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
908
953
  // and correctly escapes quotes within interpolated code.
909
- _.template = function(str, data) {
910
- var c = _.templateSettings;
911
- var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
912
- 'with(obj||{}){__p.push(\'' +
913
- str.replace(/\\/g, '\\\\')
914
- .replace(/'/g, "\\'")
915
- .replace(c.escape || noMatch, function(match, code) {
916
- return "',_.escape(" + unescape(code) + "),'";
917
- })
918
- .replace(c.interpolate || noMatch, function(match, code) {
919
- return "'," + unescape(code) + ",'";
920
- })
921
- .replace(c.evaluate || noMatch, function(match, code) {
922
- return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
923
- })
924
- .replace(/\r/g, '\\r')
925
- .replace(/\n/g, '\\n')
926
- .replace(/\t/g, '\\t')
927
- + "');}return __p.join('');";
928
- var func = new Function('obj', '_', tmpl);
929
- if (data) return func(data, _);
930
- return function(data) {
931
- return func.call(this, data, _);
954
+ _.template = function(text, data, settings) {
955
+ settings = _.extend(_.templateSettings, settings);
956
+
957
+ // Compile the template source, taking care to escape characters that
958
+ // cannot be included in a string literal and then unescape them in code
959
+ // blocks.
960
+ var source = "__p+='" + text
961
+ .replace(escaper, function(match) {
962
+ return '\\' + escapes[match];
963
+ })
964
+ .replace(settings.escape || noMatch, function(match, code) {
965
+ return "'+\n_.escape(" + unescape(code) + ")+\n'";
966
+ })
967
+ .replace(settings.interpolate || noMatch, function(match, code) {
968
+ return "'+\n(" + unescape(code) + ")+\n'";
969
+ })
970
+ .replace(settings.evaluate || noMatch, function(match, code) {
971
+ return "';\n" + unescape(code) + "\n;__p+='";
972
+ }) + "';\n";
973
+
974
+ // If a variable is not specified, place data values in local scope.
975
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
976
+
977
+ source = "var __p='';" +
978
+ "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
979
+ source + "return __p;\n";
980
+
981
+ var render = new Function(settings.variable || 'obj', '_', source);
982
+ if (data) return render(data, _);
983
+ var template = function(data) {
984
+ return render.call(this, data, _);
932
985
  };
986
+
987
+ // Provide the compiled function source as a convenience for build time
988
+ // precompilation.
989
+ template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
990
+ source + '}';
991
+
992
+ return template;
933
993
  };
934
994
 
935
995
  // Add a "chain" function, which will delegate to the wrapper.
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: underscore-source
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.3.1
5
+ version: 1.3.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Daniel X. Moore