~trobz/web-addons/7.0

« back to all changes in this revision

Viewing changes to web_unleashed/static/lib/underscore/underscore.js

  • Committer: Michel Meyer
  • Date: 2013-11-15 09:56:24 UTC
  • mfrom: (9.2.1 trunk)
  • Revision ID: michel@zazabe.fr-20131115095624-5ugq7ku0xy4adw8l
merge trunk

Show diffs side-by-side

added added

removed removed

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