underscore-source 1.3.1 → 1.3.2

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