underscore-source 0.4.0 → 0.4.1

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 = "0.4.0"
3
+ VERSION = "0.4.1"
4
4
  end
5
5
  end
@@ -1,39 +1,39 @@
1
1
  // Underscore.js
2
2
  // (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
3
3
  // Underscore is freely distributable under the terms of the MIT license.
4
- // Portions of Underscore are inspired by or borrowed from Prototype.js,
4
+ // Portions of Underscore are inspired by or borrowed from Prototype.js,
5
5
  // Oliver Steele's Functional, and John Resig's Micro-Templating.
6
6
  // For all details and documentation:
7
7
  // http://documentcloud.github.com/underscore/
8
8
 
9
9
  (function() {
10
-
10
+
11
11
  /*------------------------- Baseline setup ---------------------------------*/
12
-
12
+
13
13
  // Establish the root object, "window" in the browser, or "global" on the server.
14
14
  var root = this;
15
-
15
+
16
16
  // Save the previous value of the "_" variable.
17
17
  var previousUnderscore = root._;
18
-
18
+
19
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
20
+ // can be used OO-style. This wrapper holds altered versions of all the
21
21
  // underscore functions. Wrapped objects may be chained.
22
22
  var wrapper = function(obj) { this._wrapped = obj; };
23
-
23
+
24
24
  // Create a safe reference to the Underscore object for reference below.
25
25
  var _ = root._ = function(obj) { return new wrapper(obj); };
26
-
26
+
27
27
  // Export the Underscore object for CommonJS.
28
28
  if (typeof exports !== 'undefined') _ = exports;
29
-
29
+
30
30
  // Current version.
31
- _.VERSION = '0.4.0';
32
-
31
+ _.VERSION = '0.4.1';
32
+
33
33
  /*------------------------ Collection Functions: ---------------------------*/
34
-
34
+
35
35
  // The cornerstone, an each implementation.
36
- // Handles objects implementing forEach, each, arrays, and raw objects.
36
+ // Handles objects implementing forEach, arrays, and raw objects.
37
37
  _.each = function(obj, iterator, context) {
38
38
  var index = 0;
39
39
  try {
@@ -41,8 +41,6 @@
41
41
  obj.forEach(iterator, context);
42
42
  } else if (obj.length) {
43
43
  for (var i=0, l = obj.length; i<l; i++) iterator.call(context, obj[i], i, obj);
44
- } else if (obj.each) {
45
- obj.each(function(value) { iterator.call(context, value, index++, obj); });
46
44
  } else {
47
45
  for (var key in obj) if (Object.prototype.hasOwnProperty.call(obj, key)) {
48
46
  iterator.call(context, obj[key], key, obj);
@@ -53,7 +51,7 @@
53
51
  }
54
52
  return obj;
55
53
  };
56
-
54
+
57
55
  // Return the results of applying the iterator to each element. Use JavaScript
58
56
  // 1.6's version of map, if possible.
59
57
  _.map = function(obj, iterator, context) {
@@ -64,7 +62,7 @@
64
62
  });
65
63
  return results;
66
64
  };
67
-
65
+
68
66
  // Reduce builds up a single result from a list of values. Also known as
69
67
  // inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
70
68
  _.reduce = function(obj, memo, iterator, context) {
@@ -74,8 +72,8 @@
74
72
  });
75
73
  return memo;
76
74
  };
77
-
78
- // The right-associative version of reduce, also known as foldr. Uses
75
+
76
+ // The right-associative version of reduce, also known as foldr. Uses
79
77
  // JavaScript 1.8's version of reduceRight, if available.
80
78
  _.reduceRight = function(obj, memo, iterator, context) {
81
79
  if (obj && obj.reduceRight) return obj.reduceRight(_.bind(iterator, context), memo);
@@ -85,19 +83,19 @@
85
83
  });
86
84
  return memo;
87
85
  };
88
-
86
+
89
87
  // Return the first value which passes a truth test.
90
88
  _.detect = function(obj, iterator, context) {
91
89
  var result;
92
90
  _.each(obj, function(value, index, list) {
93
91
  if (iterator.call(context, value, index, list)) {
94
92
  result = value;
95
- throw '__break__';
93
+ _.breakLoop();
96
94
  }
97
95
  });
98
96
  return result;
99
97
  };
100
-
98
+
101
99
  // Return all the elements that pass a truth test. Use JavaScript 1.6's
102
100
  // filter(), if it exists.
103
101
  _.select = function(obj, iterator, context) {
@@ -108,7 +106,7 @@
108
106
  });
109
107
  return results;
110
108
  };
111
-
109
+
112
110
  // Return all the elements for which a truth test fails.
113
111
  _.reject = function(obj, iterator, context) {
114
112
  var results = [];
@@ -117,7 +115,7 @@
117
115
  });
118
116
  return results;
119
117
  };
120
-
118
+
121
119
  // Determine whether all of the elements match a truth test. Delegate to
122
120
  // JavaScript 1.6's every(), if it is present.
123
121
  _.all = function(obj, iterator, context) {
@@ -125,11 +123,11 @@
125
123
  if (obj.every) return obj.every(iterator, context);
126
124
  var result = true;
127
125
  _.each(obj, function(value, index, list) {
128
- if (!(result = result && iterator.call(context, value, index, list))) throw '__break__';
126
+ if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
129
127
  });
130
128
  return result;
131
129
  };
132
-
130
+
133
131
  // Determine if at least one element in the object matches a truth test. Use
134
132
  // JavaScript 1.6's some(), if it exists.
135
133
  _.any = function(obj, iterator, context) {
@@ -137,24 +135,22 @@
137
135
  if (obj.some) return obj.some(iterator, context);
138
136
  var result = false;
139
137
  _.each(obj, function(value, index, list) {
140
- if (result = iterator.call(context, value, index, list)) throw '__break__';
138
+ if (result = iterator.call(context, value, index, list)) _.breakLoop();
141
139
  });
142
140
  return result;
143
141
  };
144
-
145
- // Determine if a given value is included in the array or object,
142
+
143
+ // Determine if a given value is included in the array or object,
146
144
  // based on '==='.
147
145
  _.include = function(obj, target) {
148
146
  if (_.isArray(obj)) return _.indexOf(obj, target) != -1;
149
147
  var found = false;
150
148
  _.each(obj, function(value) {
151
- if (found = value === target) {
152
- throw '__break__';
153
- }
149
+ if (found = value === target) _.breakLoop();
154
150
  });
155
151
  return found;
156
152
  };
157
-
153
+
158
154
  // Invoke a method with arguments on every item in a collection.
159
155
  _.invoke = function(obj, method) {
160
156
  var args = _.toArray(arguments).slice(2);
@@ -162,12 +158,12 @@
162
158
  return (method ? value[method] : value).apply(value, args);
163
159
  });
164
160
  };
165
-
161
+
166
162
  // Convenience version of a common use case of map: fetching a property.
167
163
  _.pluck = function(obj, key) {
168
164
  return _.map(obj, function(value){ return value[key]; });
169
165
  };
170
-
166
+
171
167
  // Return the maximum item or (item-based computation).
172
168
  _.max = function(obj, iterator, context) {
173
169
  if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
@@ -178,7 +174,7 @@
178
174
  });
179
175
  return result.value;
180
176
  };
181
-
177
+
182
178
  // Return the minimum element (or element-based computation).
183
179
  _.min = function(obj, iterator, context) {
184
180
  if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
@@ -189,7 +185,7 @@
189
185
  });
190
186
  return result.value;
191
187
  };
192
-
188
+
193
189
  // Sort the object's values by a criteria produced by an iterator.
194
190
  _.sortBy = function(obj, iterator, context) {
195
191
  return _.pluck(_.map(obj, function(value, index, list) {
@@ -202,7 +198,7 @@
202
198
  return a < b ? -1 : a > b ? 1 : 0;
203
199
  }), 'value');
204
200
  };
205
-
201
+
206
202
  // Use a comparator function to figure out at what index an object should
207
203
  // be inserted so as to maintain order. Uses binary search.
208
204
  _.sortedIndex = function(array, obj, iterator) {
@@ -214,36 +210,36 @@
214
210
  }
215
211
  return low;
216
212
  };
217
-
213
+
218
214
  // Convert anything iterable into a real, live array.
219
215
  _.toArray = function(iterable) {
220
216
  if (!iterable) return [];
221
217
  if (_.isArray(iterable)) return iterable;
222
218
  return _.map(iterable, function(val){ return val; });
223
219
  };
224
-
220
+
225
221
  // Return the number of elements in an object.
226
222
  _.size = function(obj) {
227
223
  return _.toArray(obj).length;
228
224
  };
229
-
225
+
230
226
  /*-------------------------- Array Functions: ------------------------------*/
231
-
227
+
232
228
  // Get the first element of an array.
233
229
  _.first = function(array) {
234
230
  return array[0];
235
231
  };
236
-
232
+
237
233
  // Get the last element of an array.
238
234
  _.last = function(array) {
239
235
  return array[array.length - 1];
240
236
  };
241
-
237
+
242
238
  // Trim out all falsy values from an array.
243
239
  _.compact = function(array) {
244
240
  return _.select(array, function(value){ return !!value; });
245
241
  };
246
-
242
+
247
243
  // Return a completely flattened version of an array.
248
244
  _.flatten = function(array) {
249
245
  return _.reduce(array, [], function(memo, value) {
@@ -252,13 +248,13 @@
252
248
  return memo;
253
249
  });
254
250
  };
255
-
251
+
256
252
  // Return a version of the array that does not contain the specified value(s).
257
253
  _.without = function(array) {
258
254
  var values = array.slice.call(arguments, 0);
259
255
  return _.select(array, function(value){ return !_.include(values, value); });
260
256
  };
261
-
257
+
262
258
  // Produce a duplicate-free version of the array. If the array has already
263
259
  // been sorted, you have the option of using a faster algorithm.
264
260
  _.uniq = function(array, isSorted) {
@@ -267,18 +263,18 @@
267
263
  return memo;
268
264
  });
269
265
  };
270
-
271
- // Produce an array that contains every item shared between all the
266
+
267
+ // Produce an array that contains every item shared between all the
272
268
  // passed-in arrays.
273
269
  _.intersect = function(array) {
274
270
  var rest = _.toArray(arguments).slice(1);
275
271
  return _.select(_.uniq(array), function(item) {
276
- return _.all(rest, function(other) {
272
+ return _.all(rest, function(other) {
277
273
  return _.indexOf(other, item) >= 0;
278
274
  });
279
275
  });
280
276
  };
281
-
277
+
282
278
  // Zip together multiple lists into a single array -- elements that share
283
279
  // an index go together.
284
280
  _.zip = function() {
@@ -288,16 +284,16 @@
288
284
  for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
289
285
  return results;
290
286
  };
291
-
292
- // If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
293
- // we need this function. Return the position of the first occurence of an
287
+
288
+ // If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
289
+ // we need this function. Return the position of the first occurence of an
294
290
  // item in an array, or -1 if the item is not included in the array.
295
291
  _.indexOf = function(array, item) {
296
292
  if (array.indexOf) return array.indexOf(item);
297
293
  for (i=0, l=array.length; i<l; i++) if (array[i] === item) return i;
298
294
  return -1;
299
295
  };
300
-
296
+
301
297
  // Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
302
298
  // if possible.
303
299
  _.lastIndexOf = function(array, item) {
@@ -306,21 +302,21 @@
306
302
  while (i--) if (array[i] === item) return i;
307
303
  return -1;
308
304
  };
309
-
305
+
310
306
  /* ----------------------- Function Functions: -----------------------------*/
311
-
307
+
312
308
  // Create a function bound to a given object (assigning 'this', and arguments,
313
309
  // optionally). Binding with arguments is also known as 'curry'.
314
310
  _.bind = function(func, context) {
315
- if (!context) return func;
311
+ context = context || root;
316
312
  var args = _.toArray(arguments).slice(2);
317
313
  return function() {
318
314
  var a = args.concat(_.toArray(arguments));
319
315
  return func.apply(context, a);
320
316
  };
321
317
  };
322
-
323
- // Bind all of an object's methods to that object. Useful for ensuring that
318
+
319
+ // Bind all of an object's methods to that object. Useful for ensuring that
324
320
  // all callbacks defined on an object belong to it.
325
321
  _.bindAll = function() {
326
322
  var args = _.toArray(arguments);
@@ -329,22 +325,22 @@
329
325
  context[methodName] = _.bind(context[methodName], context);
330
326
  });
331
327
  };
332
-
328
+
333
329
  // Delays a function for the given number of milliseconds, and then calls
334
330
  // it with the arguments supplied.
335
331
  _.delay = function(func, wait) {
336
332
  var args = _.toArray(arguments).slice(2);
337
333
  return setTimeout(function(){ return func.apply(func, args); }, wait);
338
334
  };
339
-
340
- // Defers a function, scheduling it to run after the current call stack has
335
+
336
+ // Defers a function, scheduling it to run after the current call stack has
341
337
  // cleared.
342
338
  _.defer = function(func) {
343
339
  return _.delay.apply(_, [func, 1].concat(_.toArray(arguments).slice(1)));
344
340
  };
345
-
346
- // Returns the first function passed as an argument to the second,
347
- // allowing you to adjust arguments, run code before and after, and
341
+
342
+ // Returns the first function passed as an argument to the second,
343
+ // allowing you to adjust arguments, run code before and after, and
348
344
  // conditionally execute the original function.
349
345
  _.wrap = function(func, wrapper) {
350
346
  return function() {
@@ -352,7 +348,7 @@
352
348
  return wrapper.apply(wrapper, args);
353
349
  };
354
350
  };
355
-
351
+
356
352
  // Returns a function that is the composition of a list of functions, each
357
353
  // consuming the return value of the function that follows.
358
354
  _.compose = function() {
@@ -364,31 +360,31 @@
364
360
  return arguments[0];
365
361
  };
366
362
  };
367
-
363
+
368
364
  /* ------------------------- Object Functions: ---------------------------- */
369
-
365
+
370
366
  // Retrieve the names of an object's properties.
371
367
  _.keys = function(obj) {
372
368
  return _.map(obj, function(value, key){ return key; });
373
369
  };
374
-
370
+
375
371
  // Retrieve the values of an object's properties.
376
372
  _.values = function(obj) {
377
373
  return _.map(obj, _.identity);
378
374
  };
379
-
375
+
380
376
  // Extend a given object with all of the properties in a source object.
381
377
  _.extend = function(destination, source) {
382
378
  for (var property in source) destination[property] = source[property];
383
379
  return destination;
384
380
  };
385
-
381
+
386
382
  // Create a (shallow-cloned) duplicate of an object.
387
383
  _.clone = function(obj) {
388
384
  if (_.isArray(obj)) return obj.slice(0);
389
385
  return _.extend({}, obj);
390
386
  };
391
-
387
+
392
388
  // Perform a deep comparison to check if two objects are equal.
393
389
  _.isEqual = function(a, b) {
394
390
  // Check object identity.
@@ -410,41 +406,51 @@
410
406
  for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
411
407
  return true;
412
408
  };
413
-
409
+
410
+ // Is a given array or object empty?
411
+ _.isEmpty = function(obj) {
412
+ return (_.isArray(obj) ? obj : _.values(obj)).length == 0;
413
+ };
414
+
414
415
  // Is a given value a DOM element?
415
416
  _.isElement = function(obj) {
416
417
  return !!(obj && obj.nodeType == 1);
417
418
  };
418
-
419
+
419
420
  // Is a given value a real Array?
420
421
  _.isArray = function(obj) {
421
422
  return Object.prototype.toString.call(obj) == '[object Array]';
422
423
  };
423
-
424
+
424
425
  // Is a given value a Function?
425
426
  _.isFunction = function(obj) {
426
427
  return Object.prototype.toString.call(obj) == '[object Function]';
427
428
  };
428
-
429
+
429
430
  // Is a given variable undefined?
430
431
  _.isUndefined = function(obj) {
431
432
  return typeof obj == 'undefined';
432
433
  };
433
-
434
+
434
435
  /* -------------------------- Utility Functions: -------------------------- */
435
-
436
+
436
437
  // Run Underscore.js in noConflict mode, returning the '_' variable to its
437
438
  // previous owner. Returns a reference to the Underscore object.
438
439
  _.noConflict = function() {
439
440
  root._ = previousUnderscore;
440
441
  return this;
441
442
  };
442
-
443
+
443
444
  // Keep the identity function around for default iterators.
444
- _.identity = function(value) {
445
+ _.identity = function(value) {
445
446
  return value;
446
447
  };
447
-
448
+
449
+ // Break out of the middle of an iteration.
450
+ _.breakLoop = function() {
451
+ throw "__break__";
452
+ };
453
+
448
454
  // Generate a unique integer id (unique within the entire client session).
449
455
  // Useful for temporary DOM ids.
450
456
  var idCounter = 0;
@@ -452,32 +458,32 @@
452
458
  var id = idCounter++;
453
459
  return prefix ? prefix + id : id;
454
460
  };
455
-
461
+
456
462
  // Return a sorted list of the function names available in Underscore.
457
463
  _.functions = function() {
458
464
  var functions = [];
459
465
  for (var key in _) if (Object.prototype.hasOwnProperty.call(_, key)) functions.push(key);
460
466
  return _.without(functions, 'VERSION', 'prototype', 'noConflict').sort();
461
467
  };
462
-
463
- // JavaScript templating a-la ERB, pilfered from John Resig's
468
+
469
+ // JavaScript templating a-la ERB, pilfered from John Resig's
464
470
  // "Secrets of the JavaScript Ninja", page 83.
465
471
  _.template = function(str, data) {
466
- var fn = new Function('obj',
472
+ var fn = new Function('obj',
467
473
  'var p=[],print=function(){p.push.apply(p,arguments);};' +
468
474
  'with(obj){p.push(\'' +
469
475
  str
470
- .replace(/[\r\t\n]/g, " ")
471
- .split("<%").join("\t")
472
- .replace(/((^|%>)[^\t]*)'/g, "$1\r")
473
- .replace(/\t=(.*?)%>/g, "',$1,'")
474
- .split("\t").join("');")
475
- .split("%>").join("p.push('")
476
- .split("\r").join("\\'")
476
+ .replace(/[\r\t\n]/g, " ")
477
+ .split("<%").join("\t")
478
+ .replace(/((^|%>)[^\t]*)'/g, "$1\r")
479
+ .replace(/\t=(.*?)%>/g, "',$1,'")
480
+ .split("\t").join("');")
481
+ .split("%>").join("p.push('")
482
+ .split("\r").join("\\'")
477
483
  + "');}return p.join('');");
478
- return data ? fn(data) : fn;
484
+ return data ? fn(data) : fn;
479
485
  };
480
-
486
+
481
487
  /*------------------------------- Aliases ----------------------------------*/
482
488
 
483
489
  _.forEach = _.each;
@@ -487,24 +493,43 @@
487
493
  _.every = _.all;
488
494
  _.some = _.any;
489
495
  _.methods = _.functions;
490
-
496
+
491
497
  /*------------------------ Setup the OOP Wrapper: --------------------------*/
492
-
498
+
499
+ // Helper function to continue chaining intermediate results.
500
+ var result = function(obj, chain) {
501
+ return chain ? _(obj).chain() : obj;
502
+ };
503
+
493
504
  // Add all of the Underscore functions to the wrapper object.
494
505
  _.each(_.functions(), function(name) {
495
506
  wrapper.prototype[name] = function() {
496
507
  Array.prototype.unshift.call(arguments, this._wrapped);
497
- var result = _[name].apply(_, arguments);
498
- return this._chain ? _(result).chain() : result;
508
+ return result(_[name].apply(_, arguments), this._chain);
499
509
  };
500
510
  });
501
-
511
+
512
+ // Add all mutator Array functions to the wrapper.
513
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
514
+ wrapper.prototype[name] = function() {
515
+ Array.prototype[name].apply(this._wrapped, arguments);
516
+ return result(this._wrapped, this._chain);
517
+ };
518
+ });
519
+
520
+ // Add all accessor Array functions to the wrapper.
521
+ _.each(['concat', 'join', 'slice'], function(name) {
522
+ wrapper.prototype[name] = function() {
523
+ return result(Array.prototype[name].apply(this._wrapped, arguments), this._chain);
524
+ };
525
+ });
526
+
502
527
  // Start chaining a wrapped Underscore object.
503
528
  wrapper.prototype.chain = function() {
504
529
  this._chain = true;
505
530
  return this;
506
531
  };
507
-
532
+
508
533
  // Extracts the result from a wrapped and chained object.
509
534
  wrapper.prototype.get = function() {
510
535
  return this._wrapped;
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: underscore-source
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.0
5
+ version: 0.4.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Daniel X. Moore