react / wstein / node_modules / jest-cli / node_modules / jasmine-only / vendor / js / underscore.js
80677 views// Underscore.js 1.4.41// ===================23// > http://underscorejs.org4// > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.5// > Underscore may be freely distributed under the MIT license.67// Baseline setup8// --------------9(function() {1011// Establish the root object, `window` in the browser, or `global` on the server.12var root = this;1314// Save the previous value of the `_` variable.15var previousUnderscore = root._;1617// Establish the object that gets returned to break out of a loop iteration.18var breaker = {};1920// Save bytes in the minified (but not gzipped) version:21var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;2223// Create quick reference variables for speed access to core prototypes.24var push = ArrayProto.push,25slice = ArrayProto.slice,26concat = ArrayProto.concat,27toString = ObjProto.toString,28hasOwnProperty = ObjProto.hasOwnProperty;2930// All **ECMAScript 5** native function implementations that we hope to use31// are declared here.32var33nativeForEach = ArrayProto.forEach,34nativeMap = ArrayProto.map,35nativeReduce = ArrayProto.reduce,36nativeReduceRight = ArrayProto.reduceRight,37nativeFilter = ArrayProto.filter,38nativeEvery = ArrayProto.every,39nativeSome = ArrayProto.some,40nativeIndexOf = ArrayProto.indexOf,41nativeLastIndexOf = ArrayProto.lastIndexOf,42nativeIsArray = Array.isArray,43nativeKeys = Object.keys,44nativeBind = FuncProto.bind;4546// Create a safe reference to the Underscore object for use below.47var _ = function(obj) {48if (obj instanceof _) return obj;49if (!(this instanceof _)) return new _(obj);50this._wrapped = obj;51};5253// Export the Underscore object for **Node.js**, with54// backwards-compatibility for the old `require()` API. If we're in55// the browser, add `_` as a global object via a string identifier,56// for Closure Compiler "advanced" mode.57if (typeof exports !== 'undefined') {58if (typeof module !== 'undefined' && module.exports) {59exports = module.exports = _;60}61exports._ = _;62} else {63root._ = _;64}6566// Current version.67_.VERSION = '1.4.4';6869// Collection Functions70// --------------------7172// The cornerstone, an `each` implementation, aka `forEach`.73// Handles objects with the built-in `forEach`, arrays, and raw objects.74// Delegates to **ECMAScript 5**'s native `forEach` if available.75var each = _.each = _.forEach = function(obj, iterator, context) {76if (obj == null) return;77if (nativeForEach && obj.forEach === nativeForEach) {78obj.forEach(iterator, context);79} else if (obj.length === +obj.length) {80for (var i = 0, l = obj.length; i < l; i++) {81if (iterator.call(context, obj[i], i, obj) === breaker) return;82}83} else {84for (var key in obj) {85if (_.has(obj, key)) {86if (iterator.call(context, obj[key], key, obj) === breaker) return;87}88}89}90};9192// 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) {95var results = [];96if (obj == null) return results;97if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);98each(obj, function(value, index, list) {99results[results.length] = iterator.call(context, value, index, list);100});101return results;102};103104var reduceError = 'Reduce of empty array with no initial value';105106// **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) {109var initial = arguments.length > 2;110if (obj == null) obj = [];111if (nativeReduce && obj.reduce === nativeReduce) {112if (context) iterator = _.bind(iterator, context);113return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);114}115each(obj, function(value, index, list) {116if (!initial) {117memo = value;118initial = true;119} else {120memo = iterator.call(context, memo, value, index, list);121}122});123if (!initial) throw new TypeError(reduceError);124return memo;125};126127// 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) {130var initial = arguments.length > 2;131if (obj == null) obj = [];132if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {133if (context) iterator = _.bind(iterator, context);134return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);135}136var length = obj.length;137if (length !== +length) {138var keys = _.keys(obj);139length = keys.length;140}141each(obj, function(value, index, list) {142index = keys ? keys[--length] : --length;143if (!initial) {144memo = obj[index];145initial = true;146} else {147memo = iterator.call(context, memo, obj[index], index, list);148}149});150if (!initial) throw new TypeError(reduceError);151return memo;152};153154// Return the first value which passes a truth test. Aliased as `detect`.155_.find = _.detect = function(obj, iterator, context) {156var result;157any(obj, function(value, index, list) {158if (iterator.call(context, value, index, list)) {159result = value;160return true;161}162});163return result;164};165166// 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) {170var results = [];171if (obj == null) return results;172if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);173each(obj, function(value, index, list) {174if (iterator.call(context, value, index, list)) results[results.length] = value;175});176return results;177};178179// Return all the elements for which a truth test fails.180_.reject = function(obj, iterator, context) {181return _.filter(obj, function(value, index, list) {182return !iterator.call(context, value, index, list);183}, context);184};185186// 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) {190iterator || (iterator = _.identity);191var result = true;192if (obj == null) return result;193if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);194each(obj, function(value, index, list) {195if (!(result = result && iterator.call(context, value, index, list))) return breaker;196});197return !!result;198};199200// 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`.203var any = _.some = _.any = function(obj, iterator, context) {204iterator || (iterator = _.identity);205var result = false;206if (obj == null) return result;207if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);208each(obj, function(value, index, list) {209if (result || (result = iterator.call(context, value, index, list))) return breaker;210});211return !!result;212};213214// Determine if the array or object contains a given value (using `===`).215// Aliased as `include`.216_.contains = _.include = function(obj, target) {217if (obj == null) return false;218if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;219return any(obj, function(value) {220return value === target;221});222};223224// Invoke a method (with arguments) on every item in a collection.225_.invoke = function(obj, method) {226var args = slice.call(arguments, 2);227var isFunc = _.isFunction(method);228return _.map(obj, function(value) {229return (isFunc ? method : value[method]).apply(value, args);230});231};232233// Convenience version of a common use case of `map`: fetching a property.234_.pluck = function(obj, key) {235return _.map(obj, function(value){ return value[key]; });236};237238// Convenience version of a common use case of `filter`: selecting only objects239// containing specific `key:value` pairs.240_.where = function(obj, attrs, first) {241if (_.isEmpty(attrs)) return first ? null : [];242return _[first ? 'find' : 'filter'](obj, function(value) {243for (var key in attrs) {244if (attrs[key] !== value[key]) return false;245}246return true;247});248};249250// Convenience version of a common use case of `find`: getting the first object251// containing specific `key:value` pairs.252_.findWhere = function(obj, attrs) {253return _.where(obj, attrs, true);254};255256// Return the maximum element or (element-based computation).257// Can't optimize arrays of integers longer than 65,535 elements.258// See: https://bugs.webkit.org/show_bug.cgi?id=80797259_.max = function(obj, iterator, context) {260if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {261return Math.max.apply(Math, obj);262}263if (!iterator && _.isEmpty(obj)) return -Infinity;264var result = {computed : -Infinity, value: -Infinity};265each(obj, function(value, index, list) {266var computed = iterator ? iterator.call(context, value, index, list) : value;267computed >= result.computed && (result = {value : value, computed : computed});268});269return result.value;270};271272// Return the minimum element (or element-based computation).273_.min = function(obj, iterator, context) {274if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {275return Math.min.apply(Math, obj);276}277if (!iterator && _.isEmpty(obj)) return Infinity;278var result = {computed : Infinity, value: Infinity};279each(obj, function(value, index, list) {280var computed = iterator ? iterator.call(context, value, index, list) : value;281computed < result.computed && (result = {value : value, computed : computed});282});283return result.value;284};285286// Shuffle an array.287_.shuffle = function(obj) {288var rand;289var index = 0;290var shuffled = [];291each(obj, function(value) {292rand = _.random(index++);293shuffled[index - 1] = shuffled[rand];294shuffled[rand] = value;295});296return shuffled;297};298299// An internal function to generate lookup iterators.300var lookupIterator = function(value) {301return _.isFunction(value) ? value : function(obj){ return obj[value]; };302};303304// Sort the object's values by a criterion produced by an iterator.305_.sortBy = function(obj, value, context) {306var iterator = lookupIterator(value);307return _.pluck(_.map(obj, function(value, index, list) {308return {309value : value,310index : index,311criteria : iterator.call(context, value, index, list)312};313}).sort(function(left, right) {314var a = left.criteria;315var b = right.criteria;316if (a !== b) {317if (a > b || a === void 0) return 1;318if (a < b || b === void 0) return -1;319}320return left.index < right.index ? -1 : 1;321}), 'value');322};323324// An internal function used for aggregate "group by" operations.325var group = function(obj, value, context, behavior) {326var result = {};327var iterator = lookupIterator(value || _.identity);328each(obj, function(value, index) {329var key = iterator.call(context, value, index, obj);330behavior(result, key, value);331});332return result;333};334335// Groups the object's values by a criterion. Pass either a string attribute336// to group by, or a function that returns the criterion.337_.groupBy = function(obj, value, context) {338return group(obj, value, context, function(result, key, value) {339(_.has(result, key) ? result[key] : (result[key] = [])).push(value);340});341};342343// Counts instances of an object that group by a certain criterion. Pass344// either a string attribute to count by, or a function that returns the345// criterion.346_.countBy = function(obj, value, context) {347return group(obj, value, context, function(result, key) {348if (!_.has(result, key)) result[key] = 0;349result[key]++;350});351};352353// Use a comparator function to figure out the smallest index at which354// an object should be inserted so as to maintain order. Uses binary search.355_.sortedIndex = function(array, obj, iterator, context) {356iterator = iterator == null ? _.identity : lookupIterator(iterator);357var value = iterator.call(context, obj);358var low = 0, high = array.length;359while (low < high) {360var mid = (low + high) >>> 1;361iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;362}363return low;364};365366// Safely convert anything iterable into a real, live array.367_.toArray = function(obj) {368if (!obj) return [];369if (_.isArray(obj)) return slice.call(obj);370if (obj.length === +obj.length) return _.map(obj, _.identity);371return _.values(obj);372};373374// Return the number of elements in an object.375_.size = function(obj) {376if (obj == null) return 0;377return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;378};379380// Array Functions381// ---------------382383// Get the first element of an array. Passing **n** will return the first N384// values in the array. Aliased as `head` and `take`. The **guard** check385// allows it to work with `_.map`.386_.first = _.head = _.take = function(array, n, guard) {387if (array == null) return void 0;388return (n != null) && !guard ? slice.call(array, 0, n) : array[0];389};390391// Returns everything but the last entry of the array. Especially useful on392// the arguments object. Passing **n** will return all the values in393// the array, excluding the last N. The **guard** check allows it to work with394// `_.map`.395_.initial = function(array, n, guard) {396return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));397};398399// Get the last element of an array. Passing **n** will return the last N400// values in the array. The **guard** check allows it to work with `_.map`.401_.last = function(array, n, guard) {402if (array == null) return void 0;403if ((n != null) && !guard) {404return slice.call(array, Math.max(array.length - n, 0));405} else {406return array[array.length - 1];407}408};409410// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.411// Especially useful on the arguments object. Passing an **n** will return412// the rest N values in the array. The **guard**413// check allows it to work with `_.map`.414_.rest = _.tail = _.drop = function(array, n, guard) {415return slice.call(array, (n == null) || guard ? 1 : n);416};417418// Trim out all falsy values from an array.419_.compact = function(array) {420return _.filter(array, _.identity);421};422423// Internal implementation of a recursive `flatten` function.424var flatten = function(input, shallow, output) {425each(input, function(value) {426if (_.isArray(value)) {427shallow ? push.apply(output, value) : flatten(value, shallow, output);428} else {429output.push(value);430}431});432return output;433};434435// Return a completely flattened version of an array.436_.flatten = function(array, shallow) {437return flatten(array, shallow, []);438};439440// Return a version of the array that does not contain the specified value(s).441_.without = function(array) {442return _.difference(array, slice.call(arguments, 1));443};444445// Produce a duplicate-free version of the array. If the array has already446// been sorted, you have the option of using a faster algorithm.447// Aliased as `unique`.448_.uniq = _.unique = function(array, isSorted, iterator, context) {449if (_.isFunction(isSorted)) {450context = iterator;451iterator = isSorted;452isSorted = false;453}454var initial = iterator ? _.map(array, iterator, context) : array;455var results = [];456var seen = [];457each(initial, function(value, index) {458if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {459seen.push(value);460results.push(array[index]);461}462});463return results;464};465466// Produce an array that contains the union: each distinct element from all of467// the passed-in arrays.468_.union = function() {469return _.uniq(concat.apply(ArrayProto, arguments));470};471472// Produce an array that contains every item shared between all the473// passed-in arrays.474_.intersection = function(array) {475var rest = slice.call(arguments, 1);476return _.filter(_.uniq(array), function(item) {477return _.every(rest, function(other) {478return _.indexOf(other, item) >= 0;479});480});481};482483// Take the difference between one array and a number of other arrays.484// Only the elements present in just the first array will remain.485_.difference = function(array) {486var rest = concat.apply(ArrayProto, slice.call(arguments, 1));487return _.filter(array, function(value){ return !_.contains(rest, value); });488};489490// Zip together multiple lists into a single array -- elements that share491// an index go together.492_.zip = function() {493var args = slice.call(arguments);494var length = _.max(_.pluck(args, 'length'));495var results = new Array(length);496for (var i = 0; i < length; i++) {497results[i] = _.pluck(args, "" + i);498}499return results;500};501502// Converts lists into objects. Pass either a single array of `[key, value]`503// pairs, or two parallel arrays of the same length -- one of keys, and one of504// the corresponding values.505_.object = function(list, values) {506if (list == null) return {};507var result = {};508for (var i = 0, l = list.length; i < l; i++) {509if (values) {510result[list[i]] = values[i];511} else {512result[list[i][0]] = list[i][1];513}514}515return result;516};517518// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),519// we need this function. Return the position of the first occurrence of an520// item in an array, or -1 if the item is not included in the array.521// Delegates to **ECMAScript 5**'s native `indexOf` if available.522// If the array is large and already in sort order, pass `true`523// for **isSorted** to use binary search.524_.indexOf = function(array, item, isSorted) {525if (array == null) return -1;526var i = 0, l = array.length;527if (isSorted) {528if (typeof isSorted == 'number') {529i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);530} else {531i = _.sortedIndex(array, item);532return array[i] === item ? i : -1;533}534}535if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);536for (; i < l; i++) if (array[i] === item) return i;537return -1;538};539540// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.541_.lastIndexOf = function(array, item, from) {542if (array == null) return -1;543var hasIndex = from != null;544if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {545return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);546}547var i = (hasIndex ? from : array.length);548while (i--) if (array[i] === item) return i;549return -1;550};551552// Generate an integer Array containing an arithmetic progression. A port of553// the native Python `range()` function. See554// [the Python documentation](http://docs.python.org/library/functions.html#range).555_.range = function(start, stop, step) {556if (arguments.length <= 1) {557stop = start || 0;558start = 0;559}560step = arguments[2] || 1;561562var len = Math.max(Math.ceil((stop - start) / step), 0);563var idx = 0;564var range = new Array(len);565566while(idx < len) {567range[idx++] = start;568start += step;569}570571return range;572};573574// Function (ahem) Functions575// ------------------576577// Create a function bound to a given object (assigning `this`, and arguments,578// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if579// available.580_.bind = function(func, context) {581if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));582var args = slice.call(arguments, 2);583return function() {584return func.apply(context, args.concat(slice.call(arguments)));585};586};587588// Partially apply a function by creating a version that has had some of its589// arguments pre-filled, without changing its dynamic `this` context.590_.partial = function(func) {591var args = slice.call(arguments, 1);592return function() {593return func.apply(this, args.concat(slice.call(arguments)));594};595};596597// Bind all of an object's methods to that object. Useful for ensuring that598// all callbacks defined on an object belong to it.599_.bindAll = function(obj) {600var funcs = slice.call(arguments, 1);601if (funcs.length === 0) funcs = _.functions(obj);602each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });603return obj;604};605606// Memoize an expensive function by storing its results.607_.memoize = function(func, hasher) {608var memo = {};609hasher || (hasher = _.identity);610return function() {611var key = hasher.apply(this, arguments);612return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));613};614};615616// Delays a function for the given number of milliseconds, and then calls617// it with the arguments supplied.618_.delay = function(func, wait) {619var args = slice.call(arguments, 2);620return setTimeout(function(){ return func.apply(null, args); }, wait);621};622623// Defers a function, scheduling it to run after the current call stack has624// cleared.625_.defer = function(func) {626return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));627};628629// Returns a function, that, when invoked, will only be triggered at most once630// during a given window of time.631_.throttle = function(func, wait) {632var context, args, timeout, result;633var previous = 0;634var later = function() {635previous = new Date;636timeout = null;637result = func.apply(context, args);638};639return function() {640var now = new Date;641var remaining = wait - (now - previous);642context = this;643args = arguments;644if (remaining <= 0) {645clearTimeout(timeout);646timeout = null;647previous = now;648result = func.apply(context, args);649} else if (!timeout) {650timeout = setTimeout(later, remaining);651}652return result;653};654};655656// Returns a function, that, as long as it continues to be invoked, will not657// be triggered. The function will be called after it stops being called for658// N milliseconds. If `immediate` is passed, trigger the function on the659// leading edge, instead of the trailing.660_.debounce = function(func, wait, immediate) {661var timeout, result;662return function() {663var context = this, args = arguments;664var later = function() {665timeout = null;666if (!immediate) result = func.apply(context, args);667};668var callNow = immediate && !timeout;669clearTimeout(timeout);670timeout = setTimeout(later, wait);671if (callNow) result = func.apply(context, args);672return result;673};674};675676// Returns a function that will be executed at most one time, no matter how677// often you call it. Useful for lazy initialization.678_.once = function(func) {679var ran = false, memo;680return function() {681if (ran) return memo;682ran = true;683memo = func.apply(this, arguments);684func = null;685return memo;686};687};688689// Returns the first function passed as an argument to the second,690// allowing you to adjust arguments, run code before and after, and691// conditionally execute the original function.692_.wrap = function(func, wrapper) {693return function() {694var args = [func];695push.apply(args, arguments);696return wrapper.apply(this, args);697};698};699700// Returns a function that is the composition of a list of functions, each701// consuming the return value of the function that follows.702_.compose = function() {703var funcs = arguments;704return function() {705var args = arguments;706for (var i = funcs.length - 1; i >= 0; i--) {707args = [funcs[i].apply(this, args)];708}709return args[0];710};711};712713// Returns a function that will only be executed after being called N times.714_.after = function(times, func) {715if (times <= 0) return func();716return function() {717if (--times < 1) {718return func.apply(this, arguments);719}720};721};722723// Object Functions724// ----------------725726// Retrieve the names of an object's properties.727// Delegates to **ECMAScript 5**'s native `Object.keys`728_.keys = nativeKeys || function(obj) {729if (obj !== Object(obj)) throw new TypeError('Invalid object');730var keys = [];731for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;732return keys;733};734735// Retrieve the values of an object's properties.736_.values = function(obj) {737var values = [];738for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);739return values;740};741742// Convert an object into a list of `[key, value]` pairs.743_.pairs = function(obj) {744var pairs = [];745for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);746return pairs;747};748749// Invert the keys and values of an object. The values must be serializable.750_.invert = function(obj) {751var result = {};752for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;753return result;754};755756// Return a sorted list of the function names available on the object.757// Aliased as `methods`758_.functions = _.methods = function(obj) {759var names = [];760for (var key in obj) {761if (_.isFunction(obj[key])) names.push(key);762}763return names.sort();764};765766// Extend a given object with all the properties in passed-in object(s).767_.extend = function(obj) {768each(slice.call(arguments, 1), function(source) {769if (source) {770for (var prop in source) {771obj[prop] = source[prop];772}773}774});775return obj;776};777778// Return a copy of the object only containing the whitelisted properties.779_.pick = function(obj) {780var copy = {};781var keys = concat.apply(ArrayProto, slice.call(arguments, 1));782each(keys, function(key) {783if (key in obj) copy[key] = obj[key];784});785return copy;786};787788// Return a copy of the object without the blacklisted properties.789_.omit = function(obj) {790var copy = {};791var keys = concat.apply(ArrayProto, slice.call(arguments, 1));792for (var key in obj) {793if (!_.contains(keys, key)) copy[key] = obj[key];794}795return copy;796};797798// Fill in a given object with default properties.799_.defaults = function(obj) {800each(slice.call(arguments, 1), function(source) {801if (source) {802for (var prop in source) {803if (obj[prop] == null) obj[prop] = source[prop];804}805}806});807return obj;808};809810// Create a (shallow-cloned) duplicate of an object.811_.clone = function(obj) {812if (!_.isObject(obj)) return obj;813return _.isArray(obj) ? obj.slice() : _.extend({}, obj);814};815816// Invokes interceptor with the obj, and then returns obj.817// The primary purpose of this method is to "tap into" a method chain, in818// order to perform operations on intermediate results within the chain.819_.tap = function(obj, interceptor) {820interceptor(obj);821return obj;822};823824// Internal recursive comparison function for `isEqual`.825var eq = function(a, b, aStack, bStack) {826// Identical objects are equal. `0 === -0`, but they aren't identical.827// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.828if (a === b) return a !== 0 || 1 / a == 1 / b;829// A strict comparison is necessary because `null == undefined`.830if (a == null || b == null) return a === b;831// Unwrap any wrapped objects.832if (a instanceof _) a = a._wrapped;833if (b instanceof _) b = b._wrapped;834// Compare `[[Class]]` names.835var className = toString.call(a);836if (className != toString.call(b)) return false;837switch (className) {838// Strings, numbers, dates, and booleans are compared by value.839case '[object String]':840// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is841// equivalent to `new String("5")`.842return a == String(b);843case '[object Number]':844// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for845// other numeric values.846return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);847case '[object Date]':848case '[object Boolean]':849// Coerce dates and booleans to numeric primitive values. Dates are compared by their850// millisecond representations. Note that invalid dates with millisecond representations851// of `NaN` are not equivalent.852return +a == +b;853// RegExps are compared by their source patterns and flags.854case '[object RegExp]':855return a.source == b.source &&856a.global == b.global &&857a.multiline == b.multiline &&858a.ignoreCase == b.ignoreCase;859}860if (typeof a != 'object' || typeof b != 'object') return false;861// Assume equality for cyclic structures. The algorithm for detecting cyclic862// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.863var length = aStack.length;864while (length--) {865// Linear search. Performance is inversely proportional to the number of866// unique nested structures.867if (aStack[length] == a) return bStack[length] == b;868}869// Add the first object to the stack of traversed objects.870aStack.push(a);871bStack.push(b);872var size = 0, result = true;873// Recursively compare objects and arrays.874if (className == '[object Array]') {875// Compare array lengths to determine if a deep comparison is necessary.876size = a.length;877result = size == b.length;878if (result) {879// Deep compare the contents, ignoring non-numeric properties.880while (size--) {881if (!(result = eq(a[size], b[size], aStack, bStack))) break;882}883}884} else {885// Objects with different constructors are not equivalent, but `Object`s886// from different frames are.887var aCtor = a.constructor, bCtor = b.constructor;888if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&889_.isFunction(bCtor) && (bCtor instanceof bCtor))) {890return false;891}892// Deep compare objects.893for (var key in a) {894if (_.has(a, key)) {895// Count the expected number of properties.896size++;897// Deep compare each member.898if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;899}900}901// Ensure that both objects contain the same number of properties.902if (result) {903for (key in b) {904if (_.has(b, key) && !(size--)) break;905}906result = !size;907}908}909// Remove the first object from the stack of traversed objects.910aStack.pop();911bStack.pop();912return result;913};914915// Perform a deep comparison to check if two objects are equal.916_.isEqual = function(a, b) {917return eq(a, b, [], []);918};919920// Is a given array, string, or object empty?921// An "empty" object has no enumerable own-properties.922_.isEmpty = function(obj) {923if (obj == null) return true;924if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;925for (var key in obj) if (_.has(obj, key)) return false;926return true;927};928929// Is a given value a DOM element?930_.isElement = function(obj) {931return !!(obj && obj.nodeType === 1);932};933934// Is a given value an array?935// Delegates to ECMA5's native Array.isArray936_.isArray = nativeIsArray || function(obj) {937return toString.call(obj) == '[object Array]';938};939940// Is a given variable an object?941_.isObject = function(obj) {942return obj === Object(obj);943};944945// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.946each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {947_['is' + name] = function(obj) {948return toString.call(obj) == '[object ' + name + ']';949};950});951952// Define a fallback version of the method in browsers (ahem, IE), where953// there isn't any inspectable "Arguments" type.954if (!_.isArguments(arguments)) {955_.isArguments = function(obj) {956return !!(obj && _.has(obj, 'callee'));957};958}959960// Optimize `isFunction` if appropriate.961if (typeof (/./) !== 'function') {962_.isFunction = function(obj) {963return typeof obj === 'function';964};965}966967// Is a given object a finite number?968_.isFinite = function(obj) {969return isFinite(obj) && !isNaN(parseFloat(obj));970};971972// Is the given value `NaN`? (NaN is the only number which does not equal itself).973_.isNaN = function(obj) {974return _.isNumber(obj) && obj != +obj;975};976977// Is a given value a boolean?978_.isBoolean = function(obj) {979return obj === true || obj === false || toString.call(obj) == '[object Boolean]';980};981982// Is a given value equal to null?983_.isNull = function(obj) {984return obj === null;985};986987// Is a given variable undefined?988_.isUndefined = function(obj) {989return obj === void 0;990};991992// Shortcut function for checking if an object has a given property directly993// on itself (in other words, not on a prototype).994_.has = function(obj, key) {995return hasOwnProperty.call(obj, key);996};997998// Utility Functions999// -----------------10001001// Run Underscore.js in *noConflict* mode, returning the `_` variable to its1002// previous owner. Returns a reference to the Underscore object.1003_.noConflict = function() {1004root._ = previousUnderscore;1005return this;1006};10071008// Keep the identity function around for default iterators.1009_.identity = function(value) {1010return value;1011};10121013// Run a function **n** times.1014_.times = function(n, iterator, context) {1015var accum = Array(n);1016for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);1017return accum;1018};10191020// Return a random integer between min and max (inclusive).1021_.random = function(min, max) {1022if (max == null) {1023max = min;1024min = 0;1025}1026return min + Math.floor(Math.random() * (max - min + 1));1027};10281029// List of HTML entities for escaping.1030var entityMap = {1031escape: {1032'&': '&',1033'<': '<',1034'>': '>',1035'"': '"',1036"'": ''',1037'/': '/'1038}1039};1040entityMap.unescape = _.invert(entityMap.escape);10411042// Regexes containing the keys and values listed immediately above.1043var entityRegexes = {1044escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),1045unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')1046};10471048// Functions for escaping and unescaping strings to/from HTML interpolation.1049_.each(['escape', 'unescape'], function(method) {1050_[method] = function(string) {1051if (string == null) return '';1052return ('' + string).replace(entityRegexes[method], function(match) {1053return entityMap[method][match];1054});1055};1056});10571058// If the value of the named property is a function then invoke it;1059// otherwise, return it.1060_.result = function(object, property) {1061if (object == null) return null;1062var value = object[property];1063return _.isFunction(value) ? value.call(object) : value;1064};10651066// Add your own custom functions to the Underscore object.1067_.mixin = function(obj) {1068each(_.functions(obj), function(name){1069var func = _[name] = obj[name];1070_.prototype[name] = function() {1071var args = [this._wrapped];1072push.apply(args, arguments);1073return result.call(this, func.apply(_, args));1074};1075});1076};10771078// Generate a unique integer id (unique within the entire client session).1079// Useful for temporary DOM ids.1080var idCounter = 0;1081_.uniqueId = function(prefix) {1082var id = ++idCounter + '';1083return prefix ? prefix + id : id;1084};10851086// By default, Underscore uses ERB-style template delimiters, change the1087// following template settings to use alternative delimiters.1088_.templateSettings = {1089evaluate : /<%([\s\S]+?)%>/g,1090interpolate : /<%=([\s\S]+?)%>/g,1091escape : /<%-([\s\S]+?)%>/g1092};10931094// When customizing `templateSettings`, if you don't want to define an1095// interpolation, evaluation or escaping regex, we need one that is1096// guaranteed not to match.1097var noMatch = /(.)^/;10981099// Certain characters need to be escaped so that they can be put into a1100// string literal.1101var escapes = {1102"'": "'",1103'\\': '\\',1104'\r': 'r',1105'\n': 'n',1106'\t': 't',1107'\u2028': 'u2028',1108'\u2029': 'u2029'1109};11101111var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;11121113// JavaScript micro-templating, similar to John Resig's implementation.1114// Underscore templating handles arbitrary delimiters, preserves whitespace,1115// and correctly escapes quotes within interpolated code.1116_.template = function(text, data, settings) {1117var render;1118settings = _.defaults({}, settings, _.templateSettings);11191120// Combine delimiters into one regular expression via alternation.1121var matcher = new RegExp([1122(settings.escape || noMatch).source,1123(settings.interpolate || noMatch).source,1124(settings.evaluate || noMatch).source1125].join('|') + '|$', 'g');11261127// Compile the template source, escaping string literals appropriately.1128var index = 0;1129var source = "__p+='";1130text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {1131source += text.slice(index, offset)1132.replace(escaper, function(match) { return '\\' + escapes[match]; });11331134if (escape) {1135source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";1136}1137if (interpolate) {1138source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";1139}1140if (evaluate) {1141source += "';\n" + evaluate + "\n__p+='";1142}1143index = offset + match.length;1144return match;1145});1146source += "';\n";11471148// If a variable is not specified, place data values in local scope.1149if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';11501151source = "var __t,__p='',__j=Array.prototype.join," +1152"print=function(){__p+=__j.call(arguments,'');};\n" +1153source + "return __p;\n";11541155try {1156render = new Function(settings.variable || 'obj', '_', source);1157} catch (e) {1158e.source = source;1159throw e;1160}11611162if (data) return render(data, _);1163var template = function(data) {1164return render.call(this, data, _);1165};11661167// Provide the compiled function source as a convenience for precompilation.1168template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';11691170return template;1171};11721173// Add a "chain" function, which will delegate to the wrapper.1174_.chain = function(obj) {1175return _(obj).chain();1176};11771178// OOP1179// ---------------1180// If Underscore is called as a function, it returns a wrapped object that1181// can be used OO-style. This wrapper holds altered versions of all the1182// underscore functions. Wrapped objects may be chained.11831184// Helper function to continue chaining intermediate results.1185var result = function(obj) {1186return this._chain ? _(obj).chain() : obj;1187};11881189// Add all of the Underscore functions to the wrapper object.1190_.mixin(_);11911192// Add all mutator Array functions to the wrapper.1193each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {1194var method = ArrayProto[name];1195_.prototype[name] = function() {1196var obj = this._wrapped;1197method.apply(obj, arguments);1198if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];1199return result.call(this, obj);1200};1201});12021203// Add all accessor Array functions to the wrapper.1204each(['concat', 'join', 'slice'], function(name) {1205var method = ArrayProto[name];1206_.prototype[name] = function() {1207return result.call(this, method.apply(this._wrapped, arguments));1208};1209});12101211_.extend(_.prototype, {12121213// Start chaining a wrapped Underscore object.1214chain: function() {1215this._chain = true;1216return this;1217},12181219// Extracts the result from a wrapped and chained object.1220value: function() {1221return this._wrapped;1222}12231224});12251226}).call(this);122712281229