react / wstein / node_modules / jest-cli / node_modules / cover / node_modules / underscore.string / test / underscore.js
80681 views// Underscore.js 1.2.11// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.2// Underscore is freely distributable under the MIT license.3// Portions of Underscore are inspired or borrowed from Prototype,4// Oliver Steele's Functional, and John Resig's Micro-Templating.5// For all details and documentation:6// http://documentcloud.github.com/underscore78(function() {910// Baseline setup11// --------------1213// Establish the root object, `window` in the browser, or `global` on the server.14var root = this;1516// Save the previous value of the `_` variable.17var previousUnderscore = root._;1819// Establish the object that gets returned to break out of a loop iteration.20var breaker = {};2122// Save bytes in the minified (but not gzipped) version:23var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;2425// Create quick reference variables for speed access to core prototypes.26var slice = ArrayProto.slice,27unshift = ArrayProto.unshift,28toString = ObjProto.toString,29hasOwnProperty = ObjProto.hasOwnProperty;3031// All **ECMAScript 5** native function implementations that we hope to use32// are declared here.33var34nativeForEach = ArrayProto.forEach,35nativeMap = ArrayProto.map,36nativeReduce = ArrayProto.reduce,37nativeReduceRight = ArrayProto.reduceRight,38nativeFilter = ArrayProto.filter,39nativeEvery = ArrayProto.every,40nativeSome = ArrayProto.some,41nativeIndexOf = ArrayProto.indexOf,42nativeLastIndexOf = ArrayProto.lastIndexOf,43nativeIsArray = Array.isArray,44nativeKeys = Object.keys,45nativeBind = FuncProto.bind;4647// Create a safe reference to the Underscore object for use below.48var _ = function(obj) { return new wrapper(obj); };4950// Export the Underscore object for **Node.js** and **"CommonJS"**, with51// backwards-compatibility for the old `require()` API. If we're not in52// CommonJS, add `_` to the global object.53if (typeof exports !== 'undefined') {54if (typeof module !== 'undefined' && module.exports) {55exports = module.exports = _;56}57exports._ = _;58} else if (typeof define === 'function' && define.amd) {59// Register as a named module with AMD.60define('underscore', function() {61return _;62});63} else {64// Exported as a string, for Closure Compiler "advanced" mode.65root['_'] = _;66}6768// Current version.69_.VERSION = '1.2.1';7071// Collection Functions72// --------------------7374// The cornerstone, an `each` implementation, aka `forEach`.75// Handles objects with the built-in `forEach`, arrays, and raw objects.76// Delegates to **ECMAScript 5**'s native `forEach` if available.77var each = _.each = _.forEach = function(obj, iterator, context) {78if (obj == null) return;79if (nativeForEach && obj.forEach === nativeForEach) {80obj.forEach(iterator, context);81} else if (obj.length === +obj.length) {82for (var i = 0, l = obj.length; i < l; i++) {83if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;84}85} else {86for (var key in obj) {87if (hasOwnProperty.call(obj, key)) {88if (iterator.call(context, obj[key], key, obj) === breaker) return;89}90}91}92};9394// Return the results of applying the iterator to each element.95// Delegates to **ECMAScript 5**'s native `map` if available.96_.map = function(obj, iterator, context) {97var results = [];98if (obj == null) return results;99if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);100each(obj, function(value, index, list) {101results[results.length] = iterator.call(context, value, index, list);102});103return results;104};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 = memo !== void 0;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("Reduce of empty array with no initial value");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) {130if (obj == null) obj = [];131if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {132if (context) iterator = _.bind(iterator, context);133return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);134}135var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();136return _.reduce(reversed, iterator, memo, context);137};138139// Return the first value which passes a truth test. Aliased as `detect`.140_.find = _.detect = function(obj, iterator, context) {141var result;142any(obj, function(value, index, list) {143if (iterator.call(context, value, index, list)) {144result = value;145return true;146}147});148return result;149};150151// Return all the elements that pass a truth test.152// Delegates to **ECMAScript 5**'s native `filter` if available.153// Aliased as `select`.154_.filter = _.select = function(obj, iterator, context) {155var results = [];156if (obj == null) return results;157if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);158each(obj, function(value, index, list) {159if (iterator.call(context, value, index, list)) results[results.length] = value;160});161return results;162};163164// Return all the elements for which a truth test fails.165_.reject = function(obj, iterator, context) {166var results = [];167if (obj == null) return results;168each(obj, function(value, index, list) {169if (!iterator.call(context, value, index, list)) results[results.length] = value;170});171return results;172};173174// Determine whether all of the elements match a truth test.175// Delegates to **ECMAScript 5**'s native `every` if available.176// Aliased as `all`.177_.every = _.all = function(obj, iterator, context) {178var result = true;179if (obj == null) return result;180if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);181each(obj, function(value, index, list) {182if (!(result = result && iterator.call(context, value, index, list))) return breaker;183});184return result;185};186187// Determine if at least one element in the object matches a truth test.188// Delegates to **ECMAScript 5**'s native `some` if available.189// Aliased as `any`.190var any = _.some = _.any = function(obj, iterator, context) {191iterator = iterator || _.identity;192var result = false;193if (obj == null) return result;194if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);195each(obj, function(value, index, list) {196if (result |= iterator.call(context, value, index, list)) return breaker;197});198return !!result;199};200201// Determine if a given value is included in the array or object using `===`.202// Aliased as `contains`.203_.include = _.contains = function(obj, target) {204var found = false;205if (obj == null) return found;206if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;207found = any(obj, function(value) {208return value === target;209});210return found;211};212213// Invoke a method (with arguments) on every item in a collection.214_.invoke = function(obj, method) {215var args = slice.call(arguments, 2);216return _.map(obj, function(value) {217return (method.call ? method || value : value[method]).apply(value, args);218});219};220221// Convenience version of a common use case of `map`: fetching a property.222_.pluck = function(obj, key) {223return _.map(obj, function(value){ return value[key]; });224};225226// Return the maximum element or (element-based computation).227_.max = function(obj, iterator, context) {228if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);229if (!iterator && _.isEmpty(obj)) return -Infinity;230var result = {computed : -Infinity};231each(obj, function(value, index, list) {232var computed = iterator ? iterator.call(context, value, index, list) : value;233computed >= result.computed && (result = {value : value, computed : computed});234});235return result.value;236};237238// Return the minimum element (or element-based computation).239_.min = function(obj, iterator, context) {240if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);241if (!iterator && _.isEmpty(obj)) return Infinity;242var result = {computed : Infinity};243each(obj, function(value, index, list) {244var computed = iterator ? iterator.call(context, value, index, list) : value;245computed < result.computed && (result = {value : value, computed : computed});246});247return result.value;248};249250// Shuffle an array.251_.shuffle = function(obj) {252var shuffled = [], rand;253each(obj, function(value, index, list) {254if (index == 0) {255shuffled[0] = value;256} else {257rand = Math.floor(Math.random() * (index + 1));258shuffled[index] = shuffled[rand];259shuffled[rand] = value;260}261});262return shuffled;263};264265// Sort the object's values by a criterion produced by an iterator.266_.sortBy = function(obj, iterator, context) {267return _.pluck(_.map(obj, function(value, index, list) {268return {269value : value,270criteria : iterator.call(context, value, index, list)271};272}).sort(function(left, right) {273var a = left.criteria, b = right.criteria;274return a < b ? -1 : a > b ? 1 : 0;275}), 'value');276};277278// Groups the object's values by a criterion. Pass either a string attribute279// to group by, or a function that returns the criterion.280_.groupBy = function(obj, val) {281var result = {};282var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };283each(obj, function(value, index) {284var key = iterator(value, index);285(result[key] || (result[key] = [])).push(value);286});287return result;288};289290// Use a comparator function to figure out at what index an object should291// be inserted so as to maintain order. Uses binary search.292_.sortedIndex = function(array, obj, iterator) {293iterator || (iterator = _.identity);294var low = 0, high = array.length;295while (low < high) {296var mid = (low + high) >> 1;297iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;298}299return low;300};301302// Safely convert anything iterable into a real, live array.303_.toArray = function(iterable) {304if (!iterable) return [];305if (iterable.toArray) return iterable.toArray();306if (_.isArray(iterable)) return slice.call(iterable);307if (_.isArguments(iterable)) return slice.call(iterable);308return _.values(iterable);309};310311// Return the number of elements in an object.312_.size = function(obj) {313return _.toArray(obj).length;314};315316// Array Functions317// ---------------318319// Get the first element of an array. Passing **n** will return the first N320// values in the array. Aliased as `head`. The **guard** check allows it to work321// with `_.map`.322_.first = _.head = function(array, n, guard) {323return (n != null) && !guard ? slice.call(array, 0, n) : array[0];324};325326// Returns everything but the last entry of the array. Especcialy useful on327// the arguments object. Passing **n** will return all the values in328// the array, excluding the last N. The **guard** check allows it to work with329// `_.map`.330_.initial = function(array, n, guard) {331return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));332};333334// Get the last element of an array. Passing **n** will return the last N335// values in the array. The **guard** check allows it to work with `_.map`.336_.last = function(array, n, guard) {337return (n != null) && !guard ? slice.call(array, array.length - n) : array[array.length - 1];338};339340// Returns everything but the first entry of the array. Aliased as `tail`.341// Especially useful on the arguments object. Passing an **index** will return342// the rest of the values in the array from that index onward. The **guard**343// check allows it to work with `_.map`.344_.rest = _.tail = function(array, index, guard) {345return slice.call(array, (index == null) || guard ? 1 : index);346};347348// Trim out all falsy values from an array.349_.compact = function(array) {350return _.filter(array, function(value){ return !!value; });351};352353// Return a completely flattened version of an array.354_.flatten = function(array, shallow) {355return _.reduce(array, function(memo, value) {356if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));357memo[memo.length] = value;358return memo;359}, []);360};361362// Return a version of the array that does not contain the specified value(s).363_.without = function(array) {364return _.difference(array, slice.call(arguments, 1));365};366367// Produce a duplicate-free version of the array. If the array has already368// been sorted, you have the option of using a faster algorithm.369// Aliased as `unique`.370_.uniq = _.unique = function(array, isSorted, iterator) {371var initial = iterator ? _.map(array, iterator) : array;372var result = [];373_.reduce(initial, function(memo, el, i) {374if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {375memo[memo.length] = el;376result[result.length] = array[i];377}378return memo;379}, []);380return result;381};382383// Produce an array that contains the union: each distinct element from all of384// the passed-in arrays.385_.union = function() {386return _.uniq(_.flatten(arguments, true));387};388389// Produce an array that contains every item shared between all the390// passed-in arrays. (Aliased as "intersect" for back-compat.)391_.intersection = _.intersect = function(array) {392var rest = slice.call(arguments, 1);393return _.filter(_.uniq(array), function(item) {394return _.every(rest, function(other) {395return _.indexOf(other, item) >= 0;396});397});398};399400// Take the difference between one array and another.401// Only the elements present in just the first array will remain.402_.difference = function(array, other) {403return _.filter(array, function(value){ return !_.include(other, value); });404};405406// Zip together multiple lists into a single array -- elements that share407// an index go together.408_.zip = function() {409var args = slice.call(arguments);410var length = _.max(_.pluck(args, 'length'));411var results = new Array(length);412for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);413return results;414};415416// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),417// we need this function. Return the position of the first occurrence of an418// item in an array, or -1 if the item is not included in the array.419// Delegates to **ECMAScript 5**'s native `indexOf` if available.420// If the array is large and already in sort order, pass `true`421// for **isSorted** to use binary search.422_.indexOf = function(array, item, isSorted) {423if (array == null) return -1;424var i, l;425if (isSorted) {426i = _.sortedIndex(array, item);427return array[i] === item ? i : -1;428}429if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);430for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;431return -1;432};433434// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.435_.lastIndexOf = function(array, item) {436if (array == null) return -1;437if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);438var i = array.length;439while (i--) if (array[i] === item) return i;440return -1;441};442443// Generate an integer Array containing an arithmetic progression. A port of444// the native Python `range()` function. See445// [the Python documentation](http://docs.python.org/library/functions.html#range).446_.range = function(start, stop, step) {447if (arguments.length <= 1) {448stop = start || 0;449start = 0;450}451step = arguments[2] || 1;452453var len = Math.max(Math.ceil((stop - start) / step), 0);454var idx = 0;455var range = new Array(len);456457while(idx < len) {458range[idx++] = start;459start += step;460}461462return range;463};464465// Function (ahem) Functions466// ------------------467468// Reusable constructor function for prototype setting.469var ctor = function(){};470471// Create a function bound to a given object (assigning `this`, and arguments,472// optionally). Binding with arguments is also known as `curry`.473// Delegates to **ECMAScript 5**'s native `Function.bind` if available.474// We check for `func.bind` first, to fail fast when `func` is undefined.475_.bind = function bind(func, context) {476var bound, args;477if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));478if (!_.isFunction(func)) throw new TypeError;479args = slice.call(arguments, 2);480return bound = function() {481if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));482ctor.prototype = func.prototype;483var self = new ctor;484var result = func.apply(self, args.concat(slice.call(arguments)));485if (Object(result) === result) return result;486return self;487};488};489490// Bind all of an object's methods to that object. Useful for ensuring that491// all callbacks defined on an object belong to it.492_.bindAll = function(obj) {493var funcs = slice.call(arguments, 1);494if (funcs.length == 0) funcs = _.functions(obj);495each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });496return obj;497};498499// Memoize an expensive function by storing its results.500_.memoize = function(func, hasher) {501var memo = {};502hasher || (hasher = _.identity);503return function() {504var key = hasher.apply(this, arguments);505return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));506};507};508509// Delays a function for the given number of milliseconds, and then calls510// it with the arguments supplied.511_.delay = function(func, wait) {512var args = slice.call(arguments, 2);513return setTimeout(function(){ return func.apply(func, args); }, wait);514};515516// Defers a function, scheduling it to run after the current call stack has517// cleared.518_.defer = function(func) {519return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));520};521522// Returns a function, that, when invoked, will only be triggered at most once523// during a given window of time.524_.throttle = function(func, wait) {525var context, args, timeout, throttling, more;526var whenDone = _.debounce(function(){ more = throttling = false; }, wait);527return function() {528context = this; args = arguments;529var later = function() {530timeout = null;531if (more) func.apply(context, args);532whenDone();533};534if (!timeout) timeout = setTimeout(later, wait);535if (throttling) {536more = true;537} else {538func.apply(context, args);539}540whenDone();541throttling = true;542};543};544545// Returns a function, that, as long as it continues to be invoked, will not546// be triggered. The function will be called after it stops being called for547// N milliseconds.548_.debounce = function(func, wait) {549var timeout;550return function() {551var context = this, args = arguments;552var later = function() {553timeout = null;554func.apply(context, args);555};556clearTimeout(timeout);557timeout = setTimeout(later, wait);558};559};560561// Returns a function that will be executed at most one time, no matter how562// often you call it. Useful for lazy initialization.563_.once = function(func) {564var ran = false, memo;565return function() {566if (ran) return memo;567ran = true;568return memo = func.apply(this, arguments);569};570};571572// Returns the first function passed as an argument to the second,573// allowing you to adjust arguments, run code before and after, and574// conditionally execute the original function.575_.wrap = function(func, wrapper) {576return function() {577var args = [func].concat(slice.call(arguments));578return wrapper.apply(this, args);579};580};581582// Returns a function that is the composition of a list of functions, each583// consuming the return value of the function that follows.584_.compose = function() {585var funcs = slice.call(arguments);586return function() {587var args = slice.call(arguments);588for (var i = funcs.length - 1; i >= 0; i--) {589args = [funcs[i].apply(this, args)];590}591return args[0];592};593};594595// Returns a function that will only be executed after being called N times.596_.after = function(times, func) {597return function() {598if (--times < 1) { return func.apply(this, arguments); }599};600};601602// Object Functions603// ----------------604605// Retrieve the names of an object's properties.606// Delegates to **ECMAScript 5**'s native `Object.keys`607_.keys = nativeKeys || function(obj) {608if (obj !== Object(obj)) throw new TypeError('Invalid object');609var keys = [];610for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;611return keys;612};613614// Retrieve the values of an object's properties.615_.values = function(obj) {616return _.map(obj, _.identity);617};618619// Return a sorted list of the function names available on the object.620// Aliased as `methods`621_.functions = _.methods = function(obj) {622var names = [];623for (var key in obj) {624if (_.isFunction(obj[key])) names.push(key);625}626return names.sort();627};628629// Extend a given object with all the properties in passed-in object(s).630_.extend = function(obj) {631each(slice.call(arguments, 1), function(source) {632for (var prop in source) {633if (source[prop] !== void 0) obj[prop] = source[prop];634}635});636return obj;637};638639// Fill in a given object with default properties.640_.defaults = function(obj) {641each(slice.call(arguments, 1), function(source) {642for (var prop in source) {643if (obj[prop] == null) obj[prop] = source[prop];644}645});646return obj;647};648649// Create a (shallow-cloned) duplicate of an object.650_.clone = function(obj) {651if (!_.isObject(obj)) return obj;652return _.isArray(obj) ? obj.slice() : _.extend({}, obj);653};654655// Invokes interceptor with the obj, and then returns obj.656// The primary purpose of this method is to "tap into" a method chain, in657// order to perform operations on intermediate results within the chain.658_.tap = function(obj, interceptor) {659interceptor(obj);660return obj;661};662663// Internal recursive comparison function.664function eq(a, b, stack) {665// Identical objects are equal. `0 === -0`, but they aren't identical.666// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.667if (a === b) return a !== 0 || 1 / a == 1 / b;668// A strict comparison is necessary because `null == undefined`.669if ((a == null) || (b == null)) return a === b;670// Unwrap any wrapped objects.671if (a._chain) a = a._wrapped;672if (b._chain) b = b._wrapped;673// Invoke a custom `isEqual` method if one is provided.674if (_.isFunction(a.isEqual)) return a.isEqual(b);675if (_.isFunction(b.isEqual)) return b.isEqual(a);676// Compare object types.677var typeA = typeof a;678if (typeA != typeof b) return false;679// Optimization; ensure that both values are truthy or falsy.680if (!a != !b) return false;681// `NaN` values are equal.682if (_.isNaN(a)) return _.isNaN(b);683// Compare string objects by value.684var isStringA = _.isString(a), isStringB = _.isString(b);685if (isStringA || isStringB) return isStringA && isStringB && String(a) == String(b);686// Compare number objects by value.687var isNumberA = _.isNumber(a), isNumberB = _.isNumber(b);688if (isNumberA || isNumberB) return isNumberA && isNumberB && +a == +b;689// Compare boolean objects by value. The value of `true` is 1; the value of `false` is 0.690var isBooleanA = _.isBoolean(a), isBooleanB = _.isBoolean(b);691if (isBooleanA || isBooleanB) return isBooleanA && isBooleanB && +a == +b;692// Compare dates by their millisecond values.693var isDateA = _.isDate(a), isDateB = _.isDate(b);694if (isDateA || isDateB) return isDateA && isDateB && a.getTime() == b.getTime();695// Compare RegExps by their source patterns and flags.696var isRegExpA = _.isRegExp(a), isRegExpB = _.isRegExp(b);697if (isRegExpA || isRegExpB) {698// Ensure commutative equality for RegExps.699return isRegExpA && isRegExpB &&700a.source == b.source &&701a.global == b.global &&702a.multiline == b.multiline &&703a.ignoreCase == b.ignoreCase;704}705// Ensure that both values are objects.706if (typeA != 'object') return false;707// Arrays or Arraylikes with different lengths are not equal.708if (a.length !== b.length) return false;709// Objects with different constructors are not equal.710if (a.constructor !== b.constructor) return false;711// Assume equality for cyclic structures. The algorithm for detecting cyclic712// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.713var length = stack.length;714while (length--) {715// Linear search. Performance is inversely proportional to the number of716// unique nested structures.717if (stack[length] == a) return true;718}719// Add the first object to the stack of traversed objects.720stack.push(a);721var size = 0, result = true;722// Deep compare objects.723for (var key in a) {724if (hasOwnProperty.call(a, key)) {725// Count the expected number of properties.726size++;727// Deep compare each member.728if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;729}730}731// Ensure that both objects contain the same number of properties.732if (result) {733for (key in b) {734if (hasOwnProperty.call(b, key) && !(size--)) break;735}736result = !size;737}738// Remove the first object from the stack of traversed objects.739stack.pop();740return result;741}742743// Perform a deep comparison to check if two objects are equal.744_.isEqual = function(a, b) {745return eq(a, b, []);746};747748// Is a given array, string, or object empty?749// An "empty" object has no enumerable own-properties.750_.isEmpty = function(obj) {751if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;752for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;753return true;754};755756// Is a given value a DOM element?757_.isElement = function(obj) {758return !!(obj && obj.nodeType == 1);759};760761// Is a given value an array?762// Delegates to ECMA5's native Array.isArray763_.isArray = nativeIsArray || function(obj) {764return toString.call(obj) == '[object Array]';765};766767// Is a given variable an object?768_.isObject = function(obj) {769return obj === Object(obj);770};771772// Is a given variable an arguments object?773if (toString.call(arguments) == '[object Arguments]') {774_.isArguments = function(obj) {775return toString.call(obj) == '[object Arguments]';776};777} else {778_.isArguments = function(obj) {779return !!(obj && hasOwnProperty.call(obj, 'callee'));780};781}782783// Is a given value a function?784_.isFunction = function(obj) {785return toString.call(obj) == '[object Function]';786};787788// Is a given value a string?789_.isString = function(obj) {790return toString.call(obj) == '[object String]';791};792793// Is a given value a number?794_.isNumber = function(obj) {795return toString.call(obj) == '[object Number]';796};797798// Is the given value `NaN`?799_.isNaN = function(obj) {800// `NaN` is the only value for which `===` is not reflexive.801return obj !== obj;802};803804// Is a given value a boolean?805_.isBoolean = function(obj) {806return obj === true || obj === false || toString.call(obj) == '[object Boolean]';807};808809// Is a given value a date?810_.isDate = function(obj) {811return toString.call(obj) == '[object Date]';812};813814// Is the given value a regular expression?815_.isRegExp = function(obj) {816return toString.call(obj) == '[object RegExp]';817};818819// Is a given value equal to null?820_.isNull = function(obj) {821return obj === null;822};823824// Is a given variable undefined?825_.isUndefined = function(obj) {826return obj === void 0;827};828829// Utility Functions830// -----------------831832// Run Underscore.js in *noConflict* mode, returning the `_` variable to its833// previous owner. Returns a reference to the Underscore object.834_.noConflict = function() {835root._ = previousUnderscore;836return this;837};838839// Keep the identity function around for default iterators.840_.identity = function(value) {841return value;842};843844// Run a function **n** times.845_.times = function (n, iterator, context) {846for (var i = 0; i < n; i++) iterator.call(context, i);847};848849// Escape a string for HTML interpolation.850_.escape = function(string) {851return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');852};853854// Add your own custom functions to the Underscore object, ensuring that855// they're correctly added to the OOP wrapper as well.856_.mixin = function(obj) {857each(_.functions(obj), function(name){858addToWrapper(name, _[name] = obj[name]);859});860};861862// Generate a unique integer id (unique within the entire client session).863// Useful for temporary DOM ids.864var idCounter = 0;865_.uniqueId = function(prefix) {866var id = idCounter++;867return prefix ? prefix + id : id;868};869870// By default, Underscore uses ERB-style template delimiters, change the871// following template settings to use alternative delimiters.872_.templateSettings = {873evaluate : /<%([\s\S]+?)%>/g,874interpolate : /<%=([\s\S]+?)%>/g,875escape : /<%-([\s\S]+?)%>/g876};877878// JavaScript micro-templating, similar to John Resig's implementation.879// Underscore templating handles arbitrary delimiters, preserves whitespace,880// and correctly escapes quotes within interpolated code.881_.template = function(str, data) {882var c = _.templateSettings;883var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +884'with(obj||{}){__p.push(\'' +885str.replace(/\\/g, '\\\\')886.replace(/'/g, "\\'")887.replace(c.escape, function(match, code) {888return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";889})890.replace(c.interpolate, function(match, code) {891return "'," + code.replace(/\\'/g, "'") + ",'";892})893.replace(c.evaluate || null, function(match, code) {894return "');" + code.replace(/\\'/g, "'")895.replace(/[\r\n\t]/g, ' ') + "__p.push('";896})897.replace(/\r/g, '\\r')898.replace(/\n/g, '\\n')899.replace(/\t/g, '\\t')900+ "');}return __p.join('');";901var func = new Function('obj', '_', tmpl);902return data ? func(data, _) : function(data) { return func(data, _) };903};904905// The OOP Wrapper906// ---------------907908// If Underscore is called as a function, it returns a wrapped object that909// can be used OO-style. This wrapper holds altered versions of all the910// underscore functions. Wrapped objects may be chained.911var wrapper = function(obj) { this._wrapped = obj; };912913// Expose `wrapper.prototype` as `_.prototype`914_.prototype = wrapper.prototype;915916// Helper function to continue chaining intermediate results.917var result = function(obj, chain) {918return chain ? _(obj).chain() : obj;919};920921// A method to easily add functions to the OOP wrapper.922var addToWrapper = function(name, func) {923wrapper.prototype[name] = function() {924var args = slice.call(arguments);925unshift.call(args, this._wrapped);926return result(func.apply(_, args), this._chain);927};928};929930// Add all of the Underscore functions to the wrapper object.931_.mixin(_);932933// Add all mutator Array functions to the wrapper.934each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {935var method = ArrayProto[name];936wrapper.prototype[name] = function() {937method.apply(this._wrapped, arguments);938return result(this._wrapped, this._chain);939};940});941942// Add all accessor Array functions to the wrapper.943each(['concat', 'join', 'slice'], function(name) {944var method = ArrayProto[name];945wrapper.prototype[name] = function() {946return result(method.apply(this._wrapped, arguments), this._chain);947};948});949950// Start chaining a wrapped Underscore object.951wrapper.prototype.chain = function() {952this._chain = true;953return this;954};955956// Extracts the result from a wrapped and chained object.957wrapper.prototype.value = function() {958return this._wrapped;959};960961}).call(this);962963964