UNPKG

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