ui_alchemy-rails 1.0.11 → 1.0.12

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 UIAlchemy
2
2
  module Rails
3
- VERSION = "1.0.11"
3
+ VERSION = "1.0.12"
4
4
  end
5
5
  end
@@ -1,10 +1,7 @@
1
- // Underscore.js 1.3.1
2
- // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
3
- // Underscore is freely distributable under the MIT license.
4
- // Portions of Underscore are inspired or borrowed from Prototype,
5
- // Oliver Steele's Functional, and John Resig's Micro-Templating.
6
- // For all details and documentation:
7
- // http://documentcloud.github.com/underscore
1
+ // Underscore.js 1.5.1
2
+ // http://underscorejs.org
3
+ // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
4
+ // Underscore may be freely distributed under the MIT license.
8
5
 
9
6
  (function() {
10
7
 
@@ -24,10 +21,12 @@
24
21
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
25
22
 
26
23
  // Create quick reference variables for speed access to core prototypes.
27
- var slice = ArrayProto.slice,
28
- unshift = ArrayProto.unshift,
29
- toString = ObjProto.toString,
30
- hasOwnProperty = ObjProto.hasOwnProperty;
24
+ var
25
+ push = ArrayProto.push,
26
+ slice = ArrayProto.slice,
27
+ concat = ArrayProto.concat,
28
+ toString = ObjProto.toString,
29
+ hasOwnProperty = ObjProto.hasOwnProperty;
31
30
 
32
31
  // All **ECMAScript 5** native function implementations that we hope to use
33
32
  // are declared here.
@@ -46,7 +45,11 @@
46
45
  nativeBind = FuncProto.bind;
47
46
 
48
47
  // Create a safe reference to the Underscore object for use below.
49
- var _ = function(obj) { return new wrapper(obj); };
48
+ var _ = function(obj) {
49
+ if (obj instanceof _) return obj;
50
+ if (!(this instanceof _)) return new _(obj);
51
+ this._wrapped = obj;
52
+ };
50
53
 
51
54
  // Export the Underscore object for **Node.js**, with
52
55
  // backwards-compatibility for the old `require()` API. If we're in
@@ -58,11 +61,11 @@
58
61
  }
59
62
  exports._ = _;
60
63
  } else {
61
- root['_'] = _;
64
+ root._ = _;
62
65
  }
63
66
 
64
67
  // Current version.
65
- _.VERSION = '1.3.1';
68
+ _.VERSION = '1.5.1';
66
69
 
67
70
  // Collection Functions
68
71
  // --------------------
@@ -76,7 +79,7 @@
76
79
  obj.forEach(iterator, context);
77
80
  } else if (obj.length === +obj.length) {
78
81
  for (var i = 0, l = obj.length; i < l; i++) {
79
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
82
+ if (iterator.call(context, obj[i], i, obj) === breaker) return;
80
83
  }
81
84
  } else {
82
85
  for (var key in obj) {
@@ -94,12 +97,13 @@
94
97
  if (obj == null) return results;
95
98
  if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
96
99
  each(obj, function(value, index, list) {
97
- results[results.length] = iterator.call(context, value, index, list);
100
+ results.push(iterator.call(context, value, index, list));
98
101
  });
99
- if (obj.length === +obj.length) results.length = obj.length;
100
102
  return results;
101
103
  };
102
104
 
105
+ var reduceError = 'Reduce of empty array with no initial value';
106
+
103
107
  // **Reduce** builds up a single result from a list of values, aka `inject`,
104
108
  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
105
109
  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
@@ -117,7 +121,7 @@
117
121
  memo = iterator.call(context, memo, value, index, list);
118
122
  }
119
123
  });
120
- if (!initial) throw new TypeError('Reduce of empty array with no initial value');
124
+ if (!initial) throw new TypeError(reduceError);
121
125
  return memo;
122
126
  };
123
127
 
@@ -130,9 +134,22 @@
130
134
  if (context) iterator = _.bind(iterator, context);
131
135
  return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
132
136
  }
133
- var reversed = _.toArray(obj).reverse();
134
- if (context && !initial) iterator = _.bind(iterator, context);
135
- return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
137
+ var length = obj.length;
138
+ if (length !== +length) {
139
+ var keys = _.keys(obj);
140
+ length = keys.length;
141
+ }
142
+ each(obj, function(value, index, list) {
143
+ index = keys ? keys[--length] : --length;
144
+ if (!initial) {
145
+ memo = obj[index];
146
+ initial = true;
147
+ } else {
148
+ memo = iterator.call(context, memo, obj[index], index, list);
149
+ }
150
+ });
151
+ if (!initial) throw new TypeError(reduceError);
152
+ return memo;
136
153
  };
137
154
 
138
155
  // Return the first value which passes a truth test. Aliased as `detect`.
@@ -155,32 +172,30 @@
155
172
  if (obj == null) return results;
156
173
  if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
157
174
  each(obj, function(value, index, list) {
158
- if (iterator.call(context, value, index, list)) results[results.length] = value;
175
+ if (iterator.call(context, value, index, list)) results.push(value);
159
176
  });
160
177
  return results;
161
178
  };
162
179
 
163
180
  // Return all the elements for which a truth test fails.
164
181
  _.reject = function(obj, iterator, context) {
165
- var results = [];
166
- if (obj == null) return results;
167
- each(obj, function(value, index, list) {
168
- if (!iterator.call(context, value, index, list)) results[results.length] = value;
169
- });
170
- return results;
182
+ return _.filter(obj, function(value, index, list) {
183
+ return !iterator.call(context, value, index, list);
184
+ }, context);
171
185
  };
172
186
 
173
187
  // Determine whether all of the elements match a truth test.
174
188
  // Delegates to **ECMAScript 5**'s native `every` if available.
175
189
  // Aliased as `all`.
176
190
  _.every = _.all = function(obj, iterator, context) {
191
+ iterator || (iterator = _.identity);
177
192
  var result = true;
178
193
  if (obj == null) return result;
179
194
  if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
180
195
  each(obj, function(value, index, list) {
181
196
  if (!(result = result && iterator.call(context, value, index, list))) return breaker;
182
197
  });
183
- return result;
198
+ return !!result;
184
199
  };
185
200
 
186
201
  // Determine if at least one element in the object matches a truth test.
@@ -197,23 +212,22 @@
197
212
  return !!result;
198
213
  };
199
214
 
200
- // Determine if a given value is included in the array or object using `===`.
201
- // Aliased as `contains`.
202
- _.include = _.contains = function(obj, target) {
203
- var found = false;
204
- if (obj == null) return found;
215
+ // Determine if the array or object contains a given value (using `===`).
216
+ // Aliased as `include`.
217
+ _.contains = _.include = function(obj, target) {
218
+ if (obj == null) return false;
205
219
  if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
206
- found = any(obj, function(value) {
220
+ return any(obj, function(value) {
207
221
  return value === target;
208
222
  });
209
- return found;
210
223
  };
211
224
 
212
225
  // Invoke a method (with arguments) on every item in a collection.
213
226
  _.invoke = function(obj, method) {
214
227
  var args = slice.call(arguments, 2);
228
+ var isFunc = _.isFunction(method);
215
229
  return _.map(obj, function(value) {
216
- return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
230
+ return (isFunc ? method : value[method]).apply(value, args);
217
231
  });
218
232
  };
219
233
 
@@ -222,23 +236,47 @@
222
236
  return _.map(obj, function(value){ return value[key]; });
223
237
  };
224
238
 
239
+ // Convenience version of a common use case of `filter`: selecting only objects
240
+ // containing specific `key:value` pairs.
241
+ _.where = function(obj, attrs, first) {
242
+ if (_.isEmpty(attrs)) return first ? void 0 : [];
243
+ return _[first ? 'find' : 'filter'](obj, function(value) {
244
+ for (var key in attrs) {
245
+ if (attrs[key] !== value[key]) return false;
246
+ }
247
+ return true;
248
+ });
249
+ };
250
+
251
+ // Convenience version of a common use case of `find`: getting the first object
252
+ // containing specific `key:value` pairs.
253
+ _.findWhere = function(obj, attrs) {
254
+ return _.where(obj, attrs, true);
255
+ };
256
+
225
257
  // Return the maximum element or (element-based computation).
258
+ // Can't optimize arrays of integers longer than 65,535 elements.
259
+ // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
226
260
  _.max = function(obj, iterator, context) {
227
- if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
261
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
262
+ return Math.max.apply(Math, obj);
263
+ }
228
264
  if (!iterator && _.isEmpty(obj)) return -Infinity;
229
- var result = {computed : -Infinity};
265
+ var result = {computed : -Infinity, value: -Infinity};
230
266
  each(obj, function(value, index, list) {
231
267
  var computed = iterator ? iterator.call(context, value, index, list) : value;
232
- computed >= result.computed && (result = {value : value, computed : computed});
268
+ computed > result.computed && (result = {value : value, computed : computed});
233
269
  });
234
270
  return result.value;
235
271
  };
236
272
 
237
273
  // Return the minimum element (or element-based computation).
238
274
  _.min = function(obj, iterator, context) {
239
- if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
275
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
276
+ return Math.min.apply(Math, obj);
277
+ }
240
278
  if (!iterator && _.isEmpty(obj)) return Infinity;
241
- var result = {computed : Infinity};
279
+ var result = {computed : Infinity, value: Infinity};
242
280
  each(obj, function(value, index, list) {
243
281
  var computed = iterator ? iterator.call(context, value, index, list) : value;
244
282
  computed < result.computed && (result = {value : value, computed : computed});
@@ -248,81 +286,110 @@
248
286
 
249
287
  // Shuffle an array.
250
288
  _.shuffle = function(obj) {
251
- var shuffled = [], rand;
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
- }
289
+ var rand;
290
+ var index = 0;
291
+ var shuffled = [];
292
+ each(obj, function(value) {
293
+ rand = _.random(index++);
294
+ shuffled[index - 1] = shuffled[rand];
295
+ shuffled[rand] = value;
260
296
  });
261
297
  return shuffled;
262
298
  };
263
299
 
300
+ // An internal function to generate lookup iterators.
301
+ var lookupIterator = function(value) {
302
+ return _.isFunction(value) ? value : function(obj){ return obj[value]; };
303
+ };
304
+
264
305
  // Sort the object's values by a criterion produced by an iterator.
265
- _.sortBy = function(obj, iterator, context) {
306
+ _.sortBy = function(obj, value, context) {
307
+ var iterator = lookupIterator(value);
266
308
  return _.pluck(_.map(obj, function(value, index, list) {
267
309
  return {
268
310
  value : value,
311
+ index : index,
269
312
  criteria : iterator.call(context, value, index, list)
270
313
  };
271
314
  }).sort(function(left, right) {
272
- var a = left.criteria, b = right.criteria;
273
- return a < b ? -1 : a > b ? 1 : 0;
315
+ var a = left.criteria;
316
+ var b = right.criteria;
317
+ if (a !== b) {
318
+ if (a > b || a === void 0) return 1;
319
+ if (a < b || b === void 0) return -1;
320
+ }
321
+ return left.index < right.index ? -1 : 1;
274
322
  }), 'value');
275
323
  };
276
324
 
277
- // Groups the object's values by a criterion. Pass either a string attribute
278
- // to group by, or a function that returns the criterion.
279
- _.groupBy = function(obj, val) {
325
+ // An internal function used for aggregate "group by" operations.
326
+ var group = function(obj, value, context, behavior) {
280
327
  var result = {};
281
- var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
328
+ var iterator = lookupIterator(value == null ? _.identity : value);
282
329
  each(obj, function(value, index) {
283
- var key = iterator(value, index);
284
- (result[key] || (result[key] = [])).push(value);
330
+ var key = iterator.call(context, value, index, obj);
331
+ behavior(result, key, value);
285
332
  });
286
333
  return result;
287
334
  };
288
335
 
289
- // Use a comparator function to figure out at what index an object should
290
- // be inserted so as to maintain order. Uses binary search.
291
- _.sortedIndex = function(array, obj, iterator) {
292
- iterator || (iterator = _.identity);
336
+ // Groups the object's values by a criterion. Pass either a string attribute
337
+ // to group by, or a function that returns the criterion.
338
+ _.groupBy = function(obj, value, context) {
339
+ return group(obj, value, context, function(result, key, value) {
340
+ (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
341
+ });
342
+ };
343
+
344
+ // Counts instances of an object that group by a certain criterion. Pass
345
+ // either a string attribute to count by, or a function that returns the
346
+ // criterion.
347
+ _.countBy = function(obj, value, context) {
348
+ return group(obj, value, context, function(result, key) {
349
+ if (!_.has(result, key)) result[key] = 0;
350
+ result[key]++;
351
+ });
352
+ };
353
+
354
+ // Use a comparator function to figure out the smallest index at which
355
+ // an object should be inserted so as to maintain order. Uses binary search.
356
+ _.sortedIndex = function(array, obj, iterator, context) {
357
+ iterator = iterator == null ? _.identity : lookupIterator(iterator);
358
+ var value = iterator.call(context, obj);
293
359
  var low = 0, high = array.length;
294
360
  while (low < high) {
295
- var mid = (low + high) >> 1;
296
- iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
361
+ var mid = (low + high) >>> 1;
362
+ iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
297
363
  }
298
364
  return low;
299
365
  };
300
366
 
301
- // 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);
367
+ // Safely create a real, live array from anything iterable.
368
+ _.toArray = function(obj) {
369
+ if (!obj) return [];
370
+ if (_.isArray(obj)) return slice.call(obj);
371
+ if (obj.length === +obj.length) return _.map(obj, _.identity);
372
+ return _.values(obj);
308
373
  };
309
374
 
310
375
  // Return the number of elements in an object.
311
376
  _.size = function(obj) {
312
- return _.toArray(obj).length;
377
+ if (obj == null) return 0;
378
+ return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
313
379
  };
314
380
 
315
381
  // Array Functions
316
382
  // ---------------
317
383
 
318
384
  // 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) {
385
+ // values in the array. Aliased as `head` and `take`. The **guard** check
386
+ // allows it to work with `_.map`.
387
+ _.first = _.head = _.take = function(array, n, guard) {
388
+ if (array == null) return void 0;
322
389
  return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
323
390
  };
324
391
 
325
- // Returns everything but the last entry of the array. Especcialy useful on
392
+ // Returns everything but the last entry of the array. Especially useful on
326
393
  // the arguments object. Passing **n** will return all the values in
327
394
  // the array, excluding the last N. The **guard** check allows it to work with
328
395
  // `_.map`.
@@ -333,6 +400,7 @@
333
400
  // Get the last element of an array. Passing **n** will return the last N
334
401
  // values in the array. The **guard** check allows it to work with `_.map`.
335
402
  _.last = function(array, n, guard) {
403
+ if (array == null) return void 0;
336
404
  if ((n != null) && !guard) {
337
405
  return slice.call(array, Math.max(array.length - n, 0));
338
406
  } else {
@@ -340,26 +408,37 @@
340
408
  }
341
409
  };
342
410
 
343
- // Returns everything but the first entry of the array. Aliased as `tail`.
344
- // Especially useful on the arguments object. Passing an **index** will return
345
- // the rest of the values in the array from that index onward. The **guard**
411
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
412
+ // Especially useful on the arguments object. Passing an **n** will return
413
+ // the rest N values in the array. The **guard**
346
414
  // check allows it to work with `_.map`.
347
- _.rest = _.tail = function(array, index, guard) {
348
- return slice.call(array, (index == null) || guard ? 1 : index);
415
+ _.rest = _.tail = _.drop = function(array, n, guard) {
416
+ return slice.call(array, (n == null) || guard ? 1 : n);
349
417
  };
350
418
 
351
419
  // Trim out all falsy values from an array.
352
420
  _.compact = function(array) {
353
- return _.filter(array, function(value){ return !!value; });
421
+ return _.filter(array, _.identity);
422
+ };
423
+
424
+ // Internal implementation of a recursive `flatten` function.
425
+ var flatten = function(input, shallow, output) {
426
+ if (shallow && _.every(input, _.isArray)) {
427
+ return concat.apply(output, input);
428
+ }
429
+ each(input, function(value) {
430
+ if (_.isArray(value) || _.isArguments(value)) {
431
+ shallow ? push.apply(output, value) : flatten(value, shallow, output);
432
+ } else {
433
+ output.push(value);
434
+ }
435
+ });
436
+ return output;
354
437
  };
355
438
 
356
439
  // Return a completely flattened version of an array.
357
440
  _.flatten = function(array, shallow) {
358
- return _.reduce(array, function(memo, value) {
359
- if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
360
- memo[memo.length] = value;
361
- return memo;
362
- }, []);
441
+ return flatten(array, shallow, []);
363
442
  };
364
443
 
365
444
  // Return a version of the array that does not contain the specified value(s).
@@ -370,17 +449,22 @@
370
449
  // Produce a duplicate-free version of the array. If the array has already
371
450
  // been sorted, you have the option of using a faster algorithm.
372
451
  // Aliased as `unique`.
373
- _.uniq = _.unique = function(array, isSorted, iterator) {
374
- 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];
452
+ _.uniq = _.unique = function(array, isSorted, iterator, context) {
453
+ if (_.isFunction(isSorted)) {
454
+ context = iterator;
455
+ iterator = isSorted;
456
+ isSorted = false;
457
+ }
458
+ var initial = iterator ? _.map(array, iterator, context) : array;
459
+ var results = [];
460
+ var seen = [];
461
+ each(initial, function(value, index) {
462
+ if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
463
+ seen.push(value);
464
+ results.push(array[index]);
380
465
  }
381
- return memo;
382
- }, []);
383
- return result;
466
+ });
467
+ return results;
384
468
  };
385
469
 
386
470
  // Produce an array that contains the union: each distinct element from all of
@@ -390,8 +474,8 @@
390
474
  };
391
475
 
392
476
  // Produce an array that contains every item shared between all the
393
- // passed-in arrays. (Aliased as "intersect" for back-compat.)
394
- _.intersection = _.intersect = function(array) {
477
+ // passed-in arrays.
478
+ _.intersection = function(array) {
395
479
  var rest = slice.call(arguments, 1);
396
480
  return _.filter(_.uniq(array), function(item) {
397
481
  return _.every(rest, function(other) {
@@ -403,20 +487,37 @@
403
487
  // Take the difference between one array and a number of other arrays.
404
488
  // Only the elements present in just the first array will remain.
405
489
  _.difference = function(array) {
406
- var rest = _.flatten(slice.call(arguments, 1));
407
- return _.filter(array, function(value){ return !_.include(rest, value); });
490
+ var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
491
+ return _.filter(array, function(value){ return !_.contains(rest, value); });
408
492
  };
409
493
 
410
494
  // Zip together multiple lists into a single array -- elements that share
411
495
  // an index go together.
412
496
  _.zip = function() {
413
- var args = slice.call(arguments);
414
- var length = _.max(_.pluck(args, 'length'));
497
+ var length = _.max(_.pluck(arguments, "length").concat(0));
415
498
  var results = new Array(length);
416
- for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
499
+ for (var i = 0; i < length; i++) {
500
+ results[i] = _.pluck(arguments, '' + i);
501
+ }
417
502
  return results;
418
503
  };
419
504
 
505
+ // Converts lists into objects. Pass either a single array of `[key, value]`
506
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
507
+ // the corresponding values.
508
+ _.object = function(list, values) {
509
+ if (list == null) return {};
510
+ var result = {};
511
+ for (var i = 0, l = list.length; i < l; i++) {
512
+ if (values) {
513
+ result[list[i]] = values[i];
514
+ } else {
515
+ result[list[i][0]] = list[i][1];
516
+ }
517
+ }
518
+ return result;
519
+ };
520
+
420
521
  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
421
522
  // we need this function. Return the position of the first occurrence of an
422
523
  // item in an array, or -1 if the item is not included in the array.
@@ -425,22 +526,29 @@
425
526
  // for **isSorted** to use binary search.
426
527
  _.indexOf = function(array, item, isSorted) {
427
528
  if (array == null) return -1;
428
- var i, l;
529
+ var i = 0, l = array.length;
429
530
  if (isSorted) {
430
- i = _.sortedIndex(array, item);
431
- return array[i] === item ? i : -1;
531
+ if (typeof isSorted == 'number') {
532
+ i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
533
+ } else {
534
+ i = _.sortedIndex(array, item);
535
+ return array[i] === item ? i : -1;
536
+ }
432
537
  }
433
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
434
- for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
538
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
539
+ for (; i < l; i++) if (array[i] === item) return i;
435
540
  return -1;
436
541
  };
437
542
 
438
543
  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
439
- _.lastIndexOf = function(array, item) {
544
+ _.lastIndexOf = function(array, item, from) {
440
545
  if (array == null) return -1;
441
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
442
- var i = array.length;
443
- while (i--) if (i in array && array[i] === item) return i;
546
+ var hasIndex = from != null;
547
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
548
+ return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
549
+ }
550
+ var i = (hasIndex ? from : array.length);
551
+ while (i--) if (array[i] === item) return i;
444
552
  return -1;
445
553
  };
446
554
 
@@ -473,29 +581,38 @@
473
581
  var ctor = function(){};
474
582
 
475
583
  // Create a function bound to a given object (assigning `this`, and arguments,
476
- // optionally). Binding with arguments is also known as `curry`.
477
- // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
478
- // We check for `func.bind` first, to fail fast when `func` is undefined.
479
- _.bind = function bind(func, context) {
480
- var bound, args;
481
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
584
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
585
+ // available.
586
+ _.bind = function(func, context) {
587
+ var args, bound;
588
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
482
589
  if (!_.isFunction(func)) throw new TypeError;
483
590
  args = slice.call(arguments, 2);
484
591
  return bound = function() {
485
592
  if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
486
593
  ctor.prototype = func.prototype;
487
594
  var self = new ctor;
595
+ ctor.prototype = null;
488
596
  var result = func.apply(self, args.concat(slice.call(arguments)));
489
597
  if (Object(result) === result) return result;
490
598
  return self;
491
599
  };
492
600
  };
493
601
 
602
+ // Partially apply a function by creating a version that has had some of its
603
+ // arguments pre-filled, without changing its dynamic `this` context.
604
+ _.partial = function(func) {
605
+ var args = slice.call(arguments, 1);
606
+ return function() {
607
+ return func.apply(this, args.concat(slice.call(arguments)));
608
+ };
609
+ };
610
+
494
611
  // Bind all of an object's methods to that object. Useful for ensuring that
495
612
  // all callbacks defined on an object belong to it.
496
613
  _.bindAll = function(obj) {
497
614
  var funcs = slice.call(arguments, 1);
498
- if (funcs.length == 0) funcs = _.functions(obj);
615
+ if (funcs.length === 0) throw new Error("bindAll must be passed function names");
499
616
  each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
500
617
  return obj;
501
618
  };
@@ -514,7 +631,7 @@
514
631
  // it with the arguments supplied.
515
632
  _.delay = function(func, wait) {
516
633
  var args = slice.call(arguments, 2);
517
- return setTimeout(function(){ return func.apply(func, args); }, wait);
634
+ return setTimeout(function(){ return func.apply(null, args); }, wait);
518
635
  };
519
636
 
520
637
  // Defers a function, scheduling it to run after the current call stack has
@@ -524,41 +641,56 @@
524
641
  };
525
642
 
526
643
  // Returns a function, that, when invoked, will only be triggered at most once
527
- // during a given window of time.
528
- _.throttle = function(func, wait) {
529
- var context, args, timeout, throttling, more;
530
- var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
644
+ // during a given window of time. Normally, the throttled function will run
645
+ // as much as it can, without ever going more than once per `wait` duration;
646
+ // but if you'd like to disable the execution on the leading edge, pass
647
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
648
+ _.throttle = function(func, wait, options) {
649
+ var context, args, result;
650
+ var timeout = null;
651
+ var previous = 0;
652
+ options || (options = {});
653
+ var later = function() {
654
+ previous = options.leading === false ? 0 : new Date;
655
+ timeout = null;
656
+ result = func.apply(context, args);
657
+ };
531
658
  return function() {
532
- context = this; args = arguments;
533
- var later = function() {
659
+ var now = new Date;
660
+ if (!previous && options.leading === false) previous = now;
661
+ var remaining = wait - (now - previous);
662
+ context = this;
663
+ args = arguments;
664
+ if (remaining <= 0) {
665
+ clearTimeout(timeout);
534
666
  timeout = null;
535
- if (more) func.apply(context, args);
536
- whenDone();
537
- };
538
- if (!timeout) timeout = setTimeout(later, wait);
539
- if (throttling) {
540
- more = true;
541
- } else {
542
- func.apply(context, args);
667
+ previous = now;
668
+ result = func.apply(context, args);
669
+ } else if (!timeout && options.trailing !== false) {
670
+ timeout = setTimeout(later, remaining);
543
671
  }
544
- whenDone();
545
- throttling = true;
672
+ return result;
546
673
  };
547
674
  };
548
675
 
549
676
  // Returns a function, that, as long as it continues to be invoked, will not
550
677
  // be triggered. The function will be called after it stops being called for
551
- // N milliseconds.
552
- _.debounce = function(func, wait) {
553
- var timeout;
678
+ // N milliseconds. If `immediate` is passed, trigger the function on the
679
+ // leading edge, instead of the trailing.
680
+ _.debounce = function(func, wait, immediate) {
681
+ var result;
682
+ var timeout = null;
554
683
  return function() {
555
684
  var context = this, args = arguments;
556
685
  var later = function() {
557
686
  timeout = null;
558
- func.apply(context, args);
687
+ if (!immediate) result = func.apply(context, args);
559
688
  };
689
+ var callNow = immediate && !timeout;
560
690
  clearTimeout(timeout);
561
691
  timeout = setTimeout(later, wait);
692
+ if (callNow) result = func.apply(context, args);
693
+ return result;
562
694
  };
563
695
  };
564
696
 
@@ -569,7 +701,9 @@
569
701
  return function() {
570
702
  if (ran) return memo;
571
703
  ran = true;
572
- return memo = func.apply(this, arguments);
704
+ memo = func.apply(this, arguments);
705
+ func = null;
706
+ return memo;
573
707
  };
574
708
  };
575
709
 
@@ -578,7 +712,8 @@
578
712
  // conditionally execute the original function.
579
713
  _.wrap = function(func, wrapper) {
580
714
  return function() {
581
- var args = [func].concat(slice.call(arguments, 0));
715
+ var args = [func];
716
+ push.apply(args, arguments);
582
717
  return wrapper.apply(this, args);
583
718
  };
584
719
  };
@@ -598,9 +733,10 @@
598
733
 
599
734
  // Returns a function that will only be executed after being called N times.
600
735
  _.after = function(times, func) {
601
- if (times <= 0) return func();
602
736
  return function() {
603
- if (--times < 1) { return func.apply(this, arguments); }
737
+ if (--times < 1) {
738
+ return func.apply(this, arguments);
739
+ }
604
740
  };
605
741
  };
606
742
 
@@ -612,13 +748,29 @@
612
748
  _.keys = nativeKeys || function(obj) {
613
749
  if (obj !== Object(obj)) throw new TypeError('Invalid object');
614
750
  var keys = [];
615
- for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
751
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
616
752
  return keys;
617
753
  };
618
754
 
619
755
  // Retrieve the values of an object's properties.
620
756
  _.values = function(obj) {
621
- return _.map(obj, _.identity);
757
+ var values = [];
758
+ for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
759
+ return values;
760
+ };
761
+
762
+ // Convert an object into a list of `[key, value]` pairs.
763
+ _.pairs = function(obj) {
764
+ var pairs = [];
765
+ for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
766
+ return pairs;
767
+ };
768
+
769
+ // Invert the keys and values of an object. The values must be serializable.
770
+ _.invert = function(obj) {
771
+ var result = {};
772
+ for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
773
+ return result;
622
774
  };
623
775
 
624
776
  // Return a sorted list of the function names available on the object.
@@ -634,18 +786,42 @@
634
786
  // Extend a given object with all the properties in passed-in object(s).
635
787
  _.extend = function(obj) {
636
788
  each(slice.call(arguments, 1), function(source) {
637
- for (var prop in source) {
638
- obj[prop] = source[prop];
789
+ if (source) {
790
+ for (var prop in source) {
791
+ obj[prop] = source[prop];
792
+ }
639
793
  }
640
794
  });
641
795
  return obj;
642
796
  };
643
797
 
798
+ // Return a copy of the object only containing the whitelisted properties.
799
+ _.pick = function(obj) {
800
+ var copy = {};
801
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
802
+ each(keys, function(key) {
803
+ if (key in obj) copy[key] = obj[key];
804
+ });
805
+ return copy;
806
+ };
807
+
808
+ // Return a copy of the object without the blacklisted properties.
809
+ _.omit = function(obj) {
810
+ var copy = {};
811
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
812
+ for (var key in obj) {
813
+ if (!_.contains(keys, key)) copy[key] = obj[key];
814
+ }
815
+ return copy;
816
+ };
817
+
644
818
  // Fill in a given object with default properties.
645
819
  _.defaults = function(obj) {
646
820
  each(slice.call(arguments, 1), function(source) {
647
- for (var prop in source) {
648
- if (obj[prop] == null) obj[prop] = source[prop];
821
+ if (source) {
822
+ for (var prop in source) {
823
+ if (obj[prop] === void 0) obj[prop] = source[prop];
824
+ }
649
825
  }
650
826
  });
651
827
  return obj;
@@ -665,19 +841,16 @@
665
841
  return obj;
666
842
  };
667
843
 
668
- // Internal recursive comparison function.
669
- function eq(a, b, stack) {
844
+ // Internal recursive comparison function for `isEqual`.
845
+ var eq = function(a, b, aStack, bStack) {
670
846
  // Identical objects are equal. `0 === -0`, but they aren't identical.
671
- // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
847
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
672
848
  if (a === b) return a !== 0 || 1 / a == 1 / b;
673
849
  // A strict comparison is necessary because `null == undefined`.
674
850
  if (a == null || b == null) return a === b;
675
851
  // Unwrap any wrapped objects.
676
- if (a._chain) a = a._wrapped;
677
- if (b._chain) b = b._wrapped;
678
- // Invoke a custom `isEqual` method if one is provided.
679
- if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
680
- if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
852
+ if (a instanceof _) a = a._wrapped;
853
+ if (b instanceof _) b = b._wrapped;
681
854
  // Compare `[[Class]]` names.
682
855
  var className = toString.call(a);
683
856
  if (className != toString.call(b)) return false;
@@ -707,14 +880,22 @@
707
880
  if (typeof a != 'object' || typeof b != 'object') return false;
708
881
  // Assume equality for cyclic structures. The algorithm for detecting cyclic
709
882
  // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
710
- var length = stack.length;
883
+ var length = aStack.length;
711
884
  while (length--) {
712
885
  // Linear search. Performance is inversely proportional to the number of
713
886
  // unique nested structures.
714
- if (stack[length] == a) return true;
887
+ if (aStack[length] == a) return bStack[length] == b;
888
+ }
889
+ // Objects with different constructors are not equivalent, but `Object`s
890
+ // from different frames are.
891
+ var aCtor = a.constructor, bCtor = b.constructor;
892
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
893
+ _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
894
+ return false;
715
895
  }
716
896
  // Add the first object to the stack of traversed objects.
717
- stack.push(a);
897
+ aStack.push(a);
898
+ bStack.push(b);
718
899
  var size = 0, result = true;
719
900
  // Recursively compare objects and arrays.
720
901
  if (className == '[object Array]') {
@@ -724,20 +905,17 @@
724
905
  if (result) {
725
906
  // Deep compare the contents, ignoring non-numeric properties.
726
907
  while (size--) {
727
- // Ensure commutative equality for sparse arrays.
728
- if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
908
+ if (!(result = eq(a[size], b[size], aStack, bStack))) break;
729
909
  }
730
910
  }
731
911
  } else {
732
- // Objects with different constructors are not equivalent.
733
- if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
734
912
  // Deep compare objects.
735
913
  for (var key in a) {
736
914
  if (_.has(a, key)) {
737
915
  // Count the expected number of properties.
738
916
  size++;
739
917
  // Deep compare each member.
740
- if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
918
+ if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
741
919
  }
742
920
  }
743
921
  // Ensure that both objects contain the same number of properties.
@@ -749,18 +927,20 @@
749
927
  }
750
928
  }
751
929
  // Remove the first object from the stack of traversed objects.
752
- stack.pop();
930
+ aStack.pop();
931
+ bStack.pop();
753
932
  return result;
754
- }
933
+ };
755
934
 
756
935
  // Perform a deep comparison to check if two objects are equal.
757
936
  _.isEqual = function(a, b) {
758
- return eq(a, b, []);
937
+ return eq(a, b, [], []);
759
938
  };
760
939
 
761
940
  // Is a given array, string, or object empty?
762
941
  // An "empty" object has no enumerable own-properties.
763
942
  _.isEmpty = function(obj) {
943
+ if (obj == null) return true;
764
944
  if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
765
945
  for (var key in obj) if (_.has(obj, key)) return false;
766
946
  return true;
@@ -768,7 +948,7 @@
768
948
 
769
949
  // Is a given value a DOM element?
770
950
  _.isElement = function(obj) {
771
- return !!(obj && obj.nodeType == 1);
951
+ return !!(obj && obj.nodeType === 1);
772
952
  };
773
953
 
774
954
  // Is a given value an array?
@@ -782,35 +962,36 @@
782
962
  return obj === Object(obj);
783
963
  };
784
964
 
785
- // Is a given variable an arguments object?
786
- _.isArguments = function(obj) {
787
- return toString.call(obj) == '[object Arguments]';
788
- };
965
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
966
+ each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
967
+ _['is' + name] = function(obj) {
968
+ return toString.call(obj) == '[object ' + name + ']';
969
+ };
970
+ });
971
+
972
+ // Define a fallback version of the method in browsers (ahem, IE), where
973
+ // there isn't any inspectable "Arguments" type.
789
974
  if (!_.isArguments(arguments)) {
790
975
  _.isArguments = function(obj) {
791
976
  return !!(obj && _.has(obj, 'callee'));
792
977
  };
793
978
  }
794
979
 
795
- // Is a given value a function?
796
- _.isFunction = function(obj) {
797
- return toString.call(obj) == '[object Function]';
798
- };
799
-
800
- // Is a given value a string?
801
- _.isString = function(obj) {
802
- return toString.call(obj) == '[object String]';
803
- };
980
+ // Optimize `isFunction` if appropriate.
981
+ if (typeof (/./) !== 'function') {
982
+ _.isFunction = function(obj) {
983
+ return typeof obj === 'function';
984
+ };
985
+ }
804
986
 
805
- // Is a given value a number?
806
- _.isNumber = function(obj) {
807
- return toString.call(obj) == '[object Number]';
987
+ // Is a given object a finite number?
988
+ _.isFinite = function(obj) {
989
+ return isFinite(obj) && !isNaN(parseFloat(obj));
808
990
  };
809
991
 
810
- // Is the given value `NaN`?
992
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
811
993
  _.isNaN = function(obj) {
812
- // `NaN` is the only value for which `===` is not reflexive.
813
- return obj !== obj;
994
+ return _.isNumber(obj) && obj != +obj;
814
995
  };
815
996
 
816
997
  // Is a given value a boolean?
@@ -818,16 +999,6 @@
818
999
  return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
819
1000
  };
820
1001
 
821
- // Is a given value a date?
822
- _.isDate = function(obj) {
823
- return toString.call(obj) == '[object Date]';
824
- };
825
-
826
- // Is the given value a regular expression?
827
- _.isRegExp = function(obj) {
828
- return toString.call(obj) == '[object RegExp]';
829
- };
830
-
831
1002
  // Is a given value equal to null?
832
1003
  _.isNull = function(obj) {
833
1004
  return obj === null;
@@ -838,7 +1009,8 @@
838
1009
  return obj === void 0;
839
1010
  };
840
1011
 
841
- // Has own property?
1012
+ // Shortcut function for checking if an object has a given property directly
1013
+ // on itself (in other words, not on a prototype).
842
1014
  _.has = function(obj, key) {
843
1015
  return hasOwnProperty.call(obj, key);
844
1016
  };
@@ -859,20 +1031,67 @@
859
1031
  };
860
1032
 
861
1033
  // Run a function **n** times.
862
- _.times = function (n, iterator, context) {
863
- for (var i = 0; i < n; i++) iterator.call(context, i);
1034
+ _.times = function(n, iterator, context) {
1035
+ var accum = Array(Math.max(0, n));
1036
+ for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
1037
+ return accum;
1038
+ };
1039
+
1040
+ // Return a random integer between min and max (inclusive).
1041
+ _.random = function(min, max) {
1042
+ if (max == null) {
1043
+ max = min;
1044
+ min = 0;
1045
+ }
1046
+ return min + Math.floor(Math.random() * (max - min + 1));
1047
+ };
1048
+
1049
+ // List of HTML entities for escaping.
1050
+ var entityMap = {
1051
+ escape: {
1052
+ '&': '&amp;',
1053
+ '<': '&lt;',
1054
+ '>': '&gt;',
1055
+ '"': '&quot;',
1056
+ "'": '&#x27;',
1057
+ '/': '&#x2F;'
1058
+ }
864
1059
  };
1060
+ entityMap.unescape = _.invert(entityMap.escape);
1061
+
1062
+ // Regexes containing the keys and values listed immediately above.
1063
+ var entityRegexes = {
1064
+ escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
1065
+ unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
1066
+ };
1067
+
1068
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
1069
+ _.each(['escape', 'unescape'], function(method) {
1070
+ _[method] = function(string) {
1071
+ if (string == null) return '';
1072
+ return ('' + string).replace(entityRegexes[method], function(match) {
1073
+ return entityMap[method][match];
1074
+ });
1075
+ };
1076
+ });
865
1077
 
866
- // Escape a string for HTML interpolation.
867
- _.escape = function(string) {
868
- return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
1078
+ // If the value of the named `property` is a function then invoke it with the
1079
+ // `object` as context; otherwise, return it.
1080
+ _.result = function(object, property) {
1081
+ if (object == null) return void 0;
1082
+ var value = object[property];
1083
+ return _.isFunction(value) ? value.call(object) : value;
869
1084
  };
870
1085
 
871
- // Add your own custom functions to the Underscore object, ensuring that
872
- // they're correctly added to the OOP wrapper as well.
1086
+ // Add your own custom functions to the Underscore object.
873
1087
  _.mixin = function(obj) {
874
1088
  each(_.functions(obj), function(name){
875
- addToWrapper(name, _[name] = obj[name]);
1089
+ var func = _[name] = obj[name];
1090
+ _.prototype[name] = function() {
1091
+ var args = [this._wrapped];
1092
+ push.apply(args, arguments);
1093
+ return result.call(this, func.apply(_, args));
1094
+ };
876
1095
  });
877
1096
  };
878
1097
 
@@ -880,7 +1099,7 @@
880
1099
  // Useful for temporary DOM ids.
881
1100
  var idCounter = 0;
882
1101
  _.uniqueId = function(prefix) {
883
- var id = idCounter++;
1102
+ var id = ++idCounter + '';
884
1103
  return prefix ? prefix + id : id;
885
1104
  };
886
1105
 
@@ -895,41 +1114,80 @@
895
1114
  // When customizing `templateSettings`, if you don't want to define an
896
1115
  // interpolation, evaluation or escaping regex, we need one that is
897
1116
  // guaranteed not to match.
898
- var noMatch = /.^/;
1117
+ var noMatch = /(.)^/;
899
1118
 
900
- // Within an interpolation, evaluation, or escaping, remove HTML escaping
901
- // that had been previously added.
902
- var unescape = function(code) {
903
- return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
1119
+ // Certain characters need to be escaped so that they can be put into a
1120
+ // string literal.
1121
+ var escapes = {
1122
+ "'": "'",
1123
+ '\\': '\\',
1124
+ '\r': 'r',
1125
+ '\n': 'n',
1126
+ '\t': 't',
1127
+ '\u2028': 'u2028',
1128
+ '\u2029': 'u2029'
904
1129
  };
905
1130
 
1131
+ var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
1132
+
906
1133
  // JavaScript micro-templating, similar to John Resig's implementation.
907
1134
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
908
1135
  // 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, _);
1136
+ _.template = function(text, data, settings) {
1137
+ var render;
1138
+ settings = _.defaults({}, settings, _.templateSettings);
1139
+
1140
+ // Combine delimiters into one regular expression via alternation.
1141
+ var matcher = new RegExp([
1142
+ (settings.escape || noMatch).source,
1143
+ (settings.interpolate || noMatch).source,
1144
+ (settings.evaluate || noMatch).source
1145
+ ].join('|') + '|$', 'g');
1146
+
1147
+ // Compile the template source, escaping string literals appropriately.
1148
+ var index = 0;
1149
+ var source = "__p+='";
1150
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
1151
+ source += text.slice(index, offset)
1152
+ .replace(escaper, function(match) { return '\\' + escapes[match]; });
1153
+
1154
+ if (escape) {
1155
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
1156
+ }
1157
+ if (interpolate) {
1158
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
1159
+ }
1160
+ if (evaluate) {
1161
+ source += "';\n" + evaluate + "\n__p+='";
1162
+ }
1163
+ index = offset + match.length;
1164
+ return match;
1165
+ });
1166
+ source += "';\n";
1167
+
1168
+ // If a variable is not specified, place data values in local scope.
1169
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
1170
+
1171
+ source = "var __t,__p='',__j=Array.prototype.join," +
1172
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
1173
+ source + "return __p;\n";
1174
+
1175
+ try {
1176
+ render = new Function(settings.variable || 'obj', '_', source);
1177
+ } catch (e) {
1178
+ e.source = source;
1179
+ throw e;
1180
+ }
1181
+
1182
+ if (data) return render(data, _);
1183
+ var template = function(data) {
1184
+ return render.call(this, data, _);
932
1185
  };
1186
+
1187
+ // Provide the compiled function source as a convenience for precompilation.
1188
+ template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
1189
+
1190
+ return template;
933
1191
  };
934
1192
 
935
1193
  // Add a "chain" function, which will delegate to the wrapper.
@@ -937,29 +1195,15 @@
937
1195
  return _(obj).chain();
938
1196
  };
939
1197
 
940
- // The OOP Wrapper
1198
+ // OOP
941
1199
  // ---------------
942
-
943
1200
  // If Underscore is called as a function, it returns a wrapped object that
944
1201
  // can be used OO-style. This wrapper holds altered versions of all the
945
1202
  // underscore functions. Wrapped objects may be chained.
946
- var wrapper = function(obj) { this._wrapped = obj; };
947
-
948
- // Expose `wrapper.prototype` as `_.prototype`
949
- _.prototype = wrapper.prototype;
950
1203
 
951
1204
  // Helper function to continue chaining intermediate results.
952
- var result = function(obj, chain) {
953
- return chain ? _(obj).chain() : obj;
954
- };
955
-
956
- // A method to easily add functions to the OOP wrapper.
957
- var addToWrapper = function(name, func) {
958
- wrapper.prototype[name] = function() {
959
- var args = slice.call(arguments);
960
- unshift.call(args, this._wrapped);
961
- return result(func.apply(_, args), this._chain);
962
- };
1205
+ var result = function(obj) {
1206
+ return this._chain ? _(obj).chain() : obj;
963
1207
  };
964
1208
 
965
1209
  // Add all of the Underscore functions to the wrapper object.
@@ -968,32 +1212,35 @@
968
1212
  // Add all mutator Array functions to the wrapper.
969
1213
  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
970
1214
  var method = ArrayProto[name];
971
- wrapper.prototype[name] = function() {
972
- var wrapped = this._wrapped;
973
- method.apply(wrapped, arguments);
974
- var length = wrapped.length;
975
- if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
976
- return result(wrapped, this._chain);
1215
+ _.prototype[name] = function() {
1216
+ var obj = this._wrapped;
1217
+ method.apply(obj, arguments);
1218
+ if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
1219
+ return result.call(this, obj);
977
1220
  };
978
1221
  });
979
1222
 
980
1223
  // Add all accessor Array functions to the wrapper.
981
1224
  each(['concat', 'join', 'slice'], function(name) {
982
1225
  var method = ArrayProto[name];
983
- wrapper.prototype[name] = function() {
984
- return result(method.apply(this._wrapped, arguments), this._chain);
1226
+ _.prototype[name] = function() {
1227
+ return result.call(this, method.apply(this._wrapped, arguments));
985
1228
  };
986
1229
  });
987
1230
 
988
- // Start chaining a wrapped Underscore object.
989
- wrapper.prototype.chain = function() {
990
- this._chain = true;
991
- return this;
992
- };
1231
+ _.extend(_.prototype, {
993
1232
 
994
- // Extracts the result from a wrapped and chained object.
995
- wrapper.prototype.value = function() {
996
- return this._wrapped;
997
- };
1233
+ // Start chaining a wrapped Underscore object.
1234
+ chain: function() {
1235
+ this._chain = true;
1236
+ return this;
1237
+ },
1238
+
1239
+ // Extracts the result from a wrapped and chained object.
1240
+ value: function() {
1241
+ return this._wrapped;
1242
+ }
1243
+
1244
+ });
998
1245
 
999
1246
  }).call(this);