underscore-source 0.4.0 → 0.4.1

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 = "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