/** * @license * Lo-Dash 2.4.1 <http://lodash.com/> * Copyright 2012-2014 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.6.0 <http://underscorejs.org/LICENSE> * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <http://lodash.com/license> */ ;(function() { /** Used as a safe reference for `undefined` in pre ES5 environments */ var undefined; /** Used to compose bitmasks for wrapper metadata */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_FLAG = 4, CURRY_BOUND_FLAG = 8, PARTIAL_FLAG = 16, PARTIAL_RIGHT_FLAG = 32; /** Used as the semantic version number */ var version = '2.4.1'; /** Used as the property name for wrapper metadata */ var expando = '__lodash@' + version + '__'; /** Used to generate unique IDs */ var idCounter = 0; /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** Used to match HTML entities and HTML characters */ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml = /[&<>"']/g; /** Used to match template delimiters */ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; /** * Used to match ES6 template delimiters * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match regexp flags from their coerced string values */ var reFlags = /\w*$/; /** Used to detected named functions */ var reFuncName = /^\s*function[ \n\r\t]+\w/; /** Used to detect hexadecimal string values */ var reHexPrefix = /^0[xX]/; /** Used to match latin-1 supplement letters */ var reLatin1 = /[\xC0-\xFF]/g; /** Used to ensure capturing order of template delimiters */ var reNoMatch = /($^)/; /** * Used to match RegExp special characters. * See this [article on RegExp characters](http://www.regular-expressions.info/characters.html#special) * for more details. */ var reRegExpChars = /[.*+?^${}()|[\]\\]/g; /** Used to detect functions containing a `this` reference */ var reThis = /\bthis\b/; /** Used to match unescaped characters in compiled string literals */ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; /** Used to match words to create compound words */ var reWords = /[a-zA-Z0-9][a-z0-9]*/g; /** Used to detect and test whitespace */ var whitespace = ( // whitespace ' \t\x0B\f\xA0\ufeff' + // line terminators '\n\r\u2028\u2029' + // unicode category "Zs" space separators '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to assign default `context` object properties */ var contextProps = [ 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'isNaN', 'parseInt', 'setTimeout', 'TypeError', 'window', 'WinRTError' ]; /** Used to fix the JScript [[DontEnum]] bug */ var shadowedProps = [ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf' ]; /** Used to make template sourceURLs easier to identify */ var templateCounter = 0; /** `Object#toString` result shortcuts */ var argsClass = '[object Arguments]', arrayClass = '[object Array]', boolClass = '[object Boolean]', dateClass = '[object Date]', errorClass = '[object Error]', funcClass = '[object Function]', numberClass = '[object Number]', objectClass = '[object Object]', regexpClass = '[object RegExp]', stringClass = '[object String]'; /** Used to identify object classifications that `_.clone` supports */ var cloneableClasses = {}; cloneableClasses[funcClass] = false; cloneableClasses[argsClass] = cloneableClasses[arrayClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] = cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; /** Used as an internal `_.debounce` options object by `_.throttle` */ var debounceOptions = { 'leading': false, 'maxWait': 0, 'trailing': false }; /** Used as the property descriptor for wrapper metadata */ var descriptor = { 'configurable': false, 'enumerable': false, 'value': null, 'writable': false }; /** * Used to convert characters to HTML entities. * * Note: Though the ">" character is escaped for symmetry, characters like * ">", "`", and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias' article](http://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. */ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; /** Used to convert HTML entities to characters */ var htmlUnescapes = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'" }; /** * Used to convert latin-1 supplement letters to basic latin (ASCII) letters. * See [Wikipedia](http://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) * for more details. */ var deburredLetters = { '\xC0': 'A', '\xC1': 'A', '\xC2': 'A', '\xC3': 'A', '\xC4': 'A', '\xC5': 'A', '\xE0': 'a', '\xE1': 'a', '\xE2': 'a', '\xE3': 'a', '\xE4': 'a', '\xE5': 'a', '\xC7': 'C', '\xE7': 'c', '\xD0': 'D', '\xF0': 'd', '\xC8': 'E', '\xC9': 'E', '\xCA': 'E', '\xCB': 'E', '\xE8': 'e', '\xE9': 'e', '\xEA': 'e', '\xEB': 'e', '\xCC': 'I', '\xCD': 'I', '\xCE': 'I', '\xCF': 'I', '\xEC': 'i', '\xED': 'i', '\xEE': 'i', '\xEF': 'i', '\xD1': 'N', '\xF1': 'n', '\xD2': 'O', '\xD3': 'O', '\xD4': 'O', '\xD5': 'O', '\xD6': 'O', '\xD8': 'O', '\xF2': 'o', '\xF3': 'o', '\xF4': 'o', '\xF5': 'o', '\xF6': 'o', '\xF8': 'o', '\xD9': 'U', '\xDA': 'U', '\xDB': 'U', '\xDC': 'U', '\xF9': 'u', '\xFA': 'u', '\xFB': 'u', '\xFC': 'u', '\xDD': 'Y', '\xFD': 'y', '\xFF': 'y', '\xC6': 'AE', '\xE6': 'ae', '\xDE': 'Th', '\xFE': 'th', '\xDF': 'ss', '\xD7': ' ', '\xF7': ' ' }; /** Used to determine if values are of the language type Object */ var objectTypes = { 'function': true, 'object': true }; /** Used to escape characters for inclusion in compiled string literals */ var stringEscapes = { '\\': '\\', "'": "'", '\n': 'n', '\r': 'r', '\t': 't', '\u2028': 'u2028', '\u2029': 'u2029' }; /** Used as a reference to the global object */ var root = (objectTypes[typeof window] && window) || this; /** Detect free variable `exports` */ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; /** Detect free variable `module` */ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { root = freeGlobal; } /** Detect the popular CommonJS extension `module.exports` */ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; /*--------------------------------------------------------------------------*/ /** * The base implementation of `compareAscending` used to compare values and * sort them in ascending order without guaranteeing a stable sort. * * @private * @param {*} a The value to compare to `b`. * @param {*} b The value to compare to `a`. * @returns {number} Returns the sort order indicator for `a`. */ function baseCompareAscending(a, b) { if (a !== b) { if (a > b || typeof a == 'undefined') { return 1; } if (a < b || typeof b == 'undefined') { return -1; } } return 0; } /** * The base implementation of `_.indexOf` without support for binary searches. * * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value or `-1`. */ function baseIndexOf(array, value, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0; while (++index < length) { if (array[index] === value) { return index; } } return -1; } /** * An implementation of `_.contains` for cache objects that mimics the return * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. * * @private * @param {Object} cache The cache object to inspect. * @param {*} value The value to search for. * @returns {number} Returns `0` if `value` is found, else `-1`. */ function cacheIndexOf(cache, value) { return cache.has(value) ? 0 : -1; } /** * Used by `_.max` and `_.min` as the default callback when a given * collection is a string value. * * @private * @param {string} value The character to inspect. * @returns {number} Returns the code unit of given character. */ function charAtCallback(value) { return value.charCodeAt(0); } /** * Gets the index of the first character of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the first character not found in `chars`. */ function charsLeftIndex(string, chars) { var index = -1, length = string.length; while (++index < length) { if (chars.indexOf(string.charAt(index)) < 0) { break; } } return index; } /** * Gets the index of the last character of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the last character not found in `chars`. */ function charsRightIndex(string, chars) { var index = string.length; while (index--) { if (chars.indexOf(string.charAt(index)) < 0) { break; } } return index; } /** * Used by `sortBy` to compare transformed elements of a collection and stable * sort them in ascending order. * * @private * @param {Object} a The object to compare to `b`. * @param {Object} b The object to compare to `a`. * @returns {number} Returns the sort order indicator for `a`. */ function compareAscending(a, b) { return baseCompareAscending(a.criteria, b.criteria) || a.index - b.index; } /** * Used by `sortBy` to compare multiple properties of each element in a * collection and stable sort them in ascending order. * * @private * @param {Object} a The object to compare to `b`. * @param {Object} b The object to compare to `a`. * @returns {number} Returns the sort order indicator for `a`. */ function compareMultipleAscending(a, b) { var ac = a.criteria, bc = b.criteria, index = -1, length = ac.length; while (++index < length) { var result = baseCompareAscending(ac[index], bc[index]); if (result) { return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications // that causes it, under certain circumstances, to provided the same value // for `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 // // This also ensures a stable sort in V8 and other engines. // See https://code.google.com/p/v8/issues/detail?id=90 return a.index - b.index; } /** * Creates a function that produces compound words out of the words in a * given string. * * @private * @param {Function} callback The function called to combine each word. * @returns {Function} Returns the new compounder function. */ function createCompounder(callback) { return function(string) { var index = -1, words = string != null && String(string).replace(reLatin1, deburrLetter).match(reWords), length = words ? words.length : 0, result = ''; while (++index < length) { result = callback(result, words[index], index, words); } return result; }; } /** * Used by `createCompounder` to convert latin-1 supplement letters to basic * latin (ASCII) letters. * * @private * @param {string} letter The matched letter to deburr. * @returns {string} Returns the deburred letter. */ function deburrLetter(letter) { return deburredLetters[letter]; } /** * Used by `escape` to convert characters to HTML entities. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeHtmlChar(chr) { return htmlEscapes[chr]; } /** * Used by `template` to escape characters for inclusion in compiled * string literals. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeStringChar(chr) { return '\\' + stringEscapes[chr]; } /** * Checks if `value` is a DOM node in IE < 9. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`. */ function isNode(value) { // IE < 9 presents DOM nodes as `Object` objects except they have `toString` // methods that are `typeof` "string" and still can coerce nodes to strings return typeof value.toString != 'function' && typeof (value + '') == 'string'; } /** * A fallback implementation of `trim` to remove leading and trailing * whitespace or specified characters from `string`. * * @private * @param {string} string The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. */ function shimTrim(string, chars) { string = string == null ? '' : String(string); if (!string) { return string; } if (chars == null) { return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); } chars = String(chars); return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); } /** * A fallback implementation of `trimLeft` to remove leading whitespace or * specified characters from `string`. * * @private * @param {string} string The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. */ function shimTrimLeft(string, chars) { string = string == null ? '' : String(string); if (!string) { return string; } if (chars == null) { return string.slice(trimmedLeftIndex(string)) } chars = String(chars); return string.slice(charsLeftIndex(string, chars)); } /** * A fallback implementation of `trimRight` to remove trailing whitespace or * specified characters from `string`. * * @private * @param {string} string The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. */ function shimTrimRight(string, chars) { string = string == null ? '' : String(string); if (!string) { return string; } if (chars == null) { return string.slice(0, trimmedRightIndex(string) + 1) } chars = String(chars); return string.slice(0, charsRightIndex(string, chars) + 1); } /** * Gets the index of the first non-whitespace character of `string`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the first non-whitespace character. */ function trimmedLeftIndex(string) { var index = -1, length = string.length; while (++index < length) { var c = string.charCodeAt(index); if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { break; } } return index; } /** * Gets the index of the last non-whitespace character of `string`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the last non-whitespace character. */ function trimmedRightIndex(string) { var index = string.length; while (index--) { var c = string.charCodeAt(index); if (!((c <= 160 && (c >= 9 && c <= 13) || c == 32 || c == 160) || c == 5760 || c == 6158 || (c >= 8192 && (c <= 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)))) { break; } } return index; } /** * Used by `unescape` to convert HTML entities to characters. * * @private * @param {string} chr The matched character to unescape. * @returns {string} Returns the unescaped character. */ function unescapeHtmlChar(chr) { return htmlUnescapes[chr]; } /*--------------------------------------------------------------------------*/ /** * Create a new `lodash` function using the given context object. * * @static * @memberOf _ * @category Utilities * @param {Object} [context=root] The context object. * @returns {Function} Returns a new `lodash` function. */ function runInContext(context) { // Avoid issues with some ES3 environments that attempt to use values, named // after built-in constructors like `Object`, for the creation of literals. // ES5 clears this up by stating that literals must use built-in constructors. // See http://es5.github.io/#x11.1.5. context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; /** Native constructor references */ var Array = context.Array, Boolean = context.Boolean, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; /** Used for native method references */ var arrayRef = Array.prototype, errorProto = Error.prototype, objectProto = Object.prototype, stringProto = String.prototype; /** Used to detect DOM support */ var document = (document = context.window) && document.document; /** Used to restore the original `_` reference in `noConflict` */ var oldDash = context._; /** Used to resolve the internal [[Class]] of values */ var toString = objectProto.toString; /** Used to detect if a method is native */ var reNative = RegExp('^' + escapeRegExp(toString) .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method shortcuts */ var ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, fnToString = Function.prototype.toString, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, hasOwnProperty = objectProto.hasOwnProperty, push = arrayRef.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayRef.splice, unshift = arrayRef.unshift; /** Used to set meta data on functions */ var defineProperty = (function() { // IE 8 only accepts DOM elements try { var o = {}, func = isNative(func = Object.defineProperty) && func, result = func(o, o, o) && func; } catch(e) { } return result; }()); /* Native method shortcuts for methods with the same name as other `lodash` methods */ var nativeContains = isNative(nativeContains = stringProto.contains) && nativeContains, nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, nativeIsFinite = context.isFinite, nativeIsNaN = context.isNaN, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, nativeMax = Math.max, nativeMin = Math.min, nativeNow = isNative(nativeNow = Date.now) && nativeNow, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeTrim = isNative(nativeTrim = stringProto.trim) && !nativeTrim.call(whitespace) && nativeTrim, nativeTrimLeft = isNative(nativeTrimLeft = stringProto.trimLeft) && !nativeTrimLeft.call(whitespace) && nativeTrimLeft, nativeTrimRight = isNative(nativeTrimRight = stringProto.trimRight) && !nativeTrimRight.call(whitespace) && nativeTrimRight; /** Used to lookup a built-in constructor by [[Class]] */ var ctorByClass = {}; ctorByClass[arrayClass] = Array; ctorByClass[boolClass] = Boolean; ctorByClass[dateClass] = Date; ctorByClass[funcClass] = Function; ctorByClass[objectClass] = Object; ctorByClass[numberClass] = Number; ctorByClass[regexpClass] = RegExp; ctorByClass[stringClass] = String; /** Used to avoid iterating non-enumerable properties in IE < 9 */ var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true }; nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true }; nonEnumProps[objectClass] = { 'constructor': true }; (function() { var length = shadowedProps.length; while (length--) { var key = shadowedProps[length]; for (var className in nonEnumProps) { if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) { nonEnumProps[className][key] = false; } } } }()); /*--------------------------------------------------------------------------*/ /** * Creates a `lodash` object which wraps the given value to enable intuitive * method chaining. * * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, * and `unshift` * * Chaining is supported in custom builds as long as the `value` method is * implicitly or explicitly included in the build. * * The chainable wrapper functions are: * `after`, `assign`, `at`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, * `compose`, `concat`, `constant`, `countBy`, `create`, `createCallback`, * `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, * `flatten`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, * `invert`, `invoke`, `keys`, `map`, `mapValues`, `matches`, `max`, `memoize`, * `merge`, `min`, `noop`, `object`, `omit`, `once`, `pairs`, `partial`, * `partialRight`, `pick`, `pluck`, `property`, `pull`, `push`, `range`, * `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, * `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, * `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, `xor`, * and `zip` * * The non-chainable wrapper functions are: * `capitalize`, `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, * `findIndex`, `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, * `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, * `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`, * `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `now`, * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, * `size`, `some`, `sortedIndex`, `runInContext`, `template`, `trim`, * `trimLeft`, `trimRight`, `unescape`, `uniqueId`, and `value` * * The wrapper functions `first`, `last`, and `sample` return wrapped values * when `n` is provided, otherwise they return unwrapped values. * * Explicit chaining can be enabled by using the `_.chain` method. * * @name _ * @constructor * @category Chaining * @param {*} value The value to wrap in a `lodash` instance. * @returns {Object} Returns a `lodash` instance. * @example * * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value * wrapped.reduce(function(sum, num) { * return sum + num; * }); * // => 6 * * // returns a wrapped value * var squares = wrapped.map(function(num) { * return num * num; * }); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash(value) { // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__')) ? value : new lodashWrapper(value); } /** * A fast path for creating `lodash` wrapper objects. * * @private * @param {*} value The value to wrap in a `lodash` instance. * @param {boolean} [chainAll=false] A flag to enable chaining for all methods * @returns {Object} Returns a `lodash` instance. */ function lodashWrapper(value, chainAll) { this.__chain__ = !!chainAll; this.__wrapped__ = value; } // ensure `new lodashWrapper` is an instance of `lodash` lodashWrapper.prototype = lodash.prototype; /** * An object used to flag environments features. * * @static * @memberOf _ * @type Object */ var support = lodash.support = {}; (function() { var ctor = function() { this.x = 1; }, object = { '0': 1, 'length': 1 }, props = []; ctor.prototype = { 'valueOf': 1, 'y': 1 }; for (var key in new ctor) { props.push(key); } for (key in arguments) { } /** * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9). * * @memberOf _.support * @type boolean */ support.argsClass = toString.call(arguments) == argsClass; /** * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5). * * @memberOf _.support * @type boolean */ support.argsObject = arguments.constructor == Object && !(arguments instanceof Array); /** * Detect if `name` or `message` properties of `Error.prototype` are * enumerable by default. (IE < 9, Safari < 5.1) * * @memberOf _.support * @type boolean */ support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name'); /** * Detect if `prototype` properties are enumerable by default. * * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 * (if the prototype or a property on the prototype has been set) * incorrectly sets a function's `prototype` property [[Enumerable]] * value to `true`. * * @memberOf _.support * @type boolean */ support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype'); /** * Detect if functions can be decompiled by `Function#toString` * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). * * @memberOf _.support * @type boolean */ support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext); /** * Detect if `Function#name` is supported (all but IE). * * @memberOf _.support * @type boolean */ support.funcNames = typeof Function.name == 'string'; /** * Detect if `arguments` object indexes are non-enumerable * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1). * * @memberOf _.support * @type boolean */ support.nonEnumArgs = key != 0; /** * Detect if properties shadowing those on `Object.prototype` are non-enumerable. * * In IE < 9 an objects own properties, shadowing non-enumerable ones, are * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug). * * @memberOf _.support * @type boolean */ support.nonEnumShadows = !/valueOf/.test(props); /** * Detect if own properties are iterated after inherited properties (all but IE < 9). * * @memberOf _.support * @type boolean */ support.ownLast = props[0] != 'x'; /** * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly. * * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` * and `splice()` functions that fail to remove the last element, `value[0]`, * of array-like objects even though the `length` property is set to `0`. * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. * * @memberOf _.support * @type boolean */ support.spliceObjects = (splice.call(object, 0, 1), !object[0]); /** * Detect lack of support for accessing string characters by index. * * IE < 8 can't access characters by index and IE 8 can only access * characters by index on string literals. * * @memberOf _.support * @type boolean */ support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx'; /** * Detect if the DOM is supported. * * @memberOf _.support * @type boolean */ try { support.dom = document.createDocumentFragment().nodeType === 11; } catch(e) { support.dom = false; } /** * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9) * and that the JS engine errors when attempting to coerce an object to * a string without a `toString` function. * * @memberOf _.support * @type boolean */ try { support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + '')); } catch(e) { support.nodeClass = true; } }(1)); /** * By default, the template delimiters used by Lo-Dash are similar to those in * embedded Ruby (ERB). Change the following template settings to use alternative * delimiters. * * @static * @memberOf _ * @type Object */ lodash.templateSettings = { /** * Used to detect `data` property values to be HTML-escaped. * * @memberOf _.templateSettings * @type RegExp */ 'escape': reEscape, /** * Used to detect code to be evaluated. * * @memberOf _.templateSettings * @type RegExp */ 'evaluate': reEvaluate, /** * Used to detect `data` property values to inject. * * @memberOf _.templateSettings * @type RegExp */ 'interpolate': reInterpolate, /** * Used to reference the data object in the template text. * * @memberOf _.templateSettings * @type string */ 'variable': '', /** * Used to import variables into the compiled template. * * @memberOf _.templateSettings * @type Object */ 'imports': { /** * A reference to the `lodash` function. * * @memberOf _.templateSettings.imports * @type Function */ '_': lodash } }; /*--------------------------------------------------------------------------*/ /** * The template used to create iterator functions. * * @private * @param {Object} data The data object used to populate the text. * @returns {string} Returns the interpolated text. */ var iteratorTemplate = template( // assign the `result` variable an initial value 'var result = <%= init %>;\n' + // exit early if the first argument is not an object "if (!isObject(object)) {\n" + ' return result;\n' + '}' + // add support for iterating over `arguments` objects if needed '<% if (support.nonEnumArgs) { %>\n' + 'var length = object.length;\n' + 'if (length && isArguments(object)) {\n' + ' key = -1;\n' + ' while (++key < length) {\n' + " key += '';\n" + ' <%= loop %>;\n' + ' }\n' + ' return result;\n' + '}' + '<% } %>' + // avoid iterating over `prototype` properties in older Firefox, Opera, and Safari '<% if (support.enumPrototypes) { %>\n' + "var skipProto = typeof object == 'function';\n" + '<% } %>' + // avoid iterating over `Error.prototype` properties in older IE and Safari '<% if (support.enumErrorProps) { %>\n' + 'var skipErrorProps = object === errorProto || object instanceof Error;\n' + '<% } %>' + // define conditions used in the loop '<%' + 'var conditions = [];\n' + "if (support.enumPrototypes) { conditions.push('!(skipProto && key == \\'prototype\\')'); }\n" + "if (support.enumErrorProps) { conditions.push('!(skipErrorProps && (key == \\'message\\' || key == \\'name\\'))'); }" + '%>\n' + // iterate over the object 'for (var key in object) {\n<%' + " if (useHas) { conditions.push('hasOwnProperty.call(object, key)'); }\n" + " if (conditions.length) { %> if (<%= conditions.join(' && ') %>) {\n <% } %>" + ' <%= loop %>;' + ' <% if (conditions.length) { %>\n }<% } %>\n' + '}\n' + // Lo-Dash skips the `constructor` property when it infers it's iterating // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` // attribute of an existing property and the `constructor` property of a // prototype defaults to non-enumerable. '<% if (support.nonEnumShadows) { %>\n' + 'if (object !== objectProto) {\n' + " var ctor = object.constructor,\n" + ' isProto = object === (ctor && ctor.prototype),\n' + ' className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object),\n' + ' nonEnum = nonEnumProps[className];\n' + ' <% for (var index = 0; index < 7; index++) { %>\n' + " key = '<%= shadowedProps[index] %>';\n" + ' if ((!(isProto && nonEnum[key]) && hasOwnProperty.call(object, key))<%' + ' if (!useHas) { %> || (!nonEnum[key] && object[key] !== objectProto[key])<% }' + ' %>) {\n' + ' <%= loop %>;\n' + ' }' + ' <% } %>\n' + '}' + '<% } %>\n' + 'return result;' ); /*--------------------------------------------------------------------------*/ /** * The base implementation of `_.bind` that creates the bound function and * sets its meta data. * * @private * @param {Array} data The metadata array. * @returns {Function} Returns the new bound function. */ function baseBind(data) { var func = data[0], thisArg = data[3], partialArgs = data[4], partialHolders = data[6]; function bound() { // `Function#bind` spec // http://es5.github.io/#x15.3.4.5 if (partialArgs) { // avoid `arguments` object use disqualifying optimizations by // converting it to an array before passing it to `composeArgs` var index = -1, length = arguments.length, args = Array(length); while (++index < length) { args[index] = arguments[index]; } args = composeArgs(partialArgs, partialHolders, args); } // mimic the constructor's `return` behavior // http://es5.github.io/#x13.2.2 if (this instanceof bound) { // ensure `new bound` is an instance of `func` var thisBinding = baseCreate(func.prototype), result = func.apply(thisBinding, args || arguments); return isObject(result) ? result : thisBinding; } return func.apply(thisArg, args || arguments); } setData(bound, data); return bound; } /** * The base implementation of `_.clone` without argument juggling or support * for `thisArg` binding. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep=false] Specify a deep clone. * @param {Function} [callback] The function to customize cloning values. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates clones with source counterparts. * @returns {*} Returns the cloned value. */ function baseClone(value, isDeep, callback, stackA, stackB) { if (callback) { var result = callback(value); if (typeof result != 'undefined') { return result; } } // inspect [[Class]] var isObj = isObject(value); if (isObj) { var className = toString.call(value); if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) { return value; } var ctor = ctorByClass[className]; switch (className) { case boolClass: case dateClass: return new ctor(+value); case numberClass: case stringClass: return new ctor(value); case regexpClass: result = ctor(value.source, reFlags.exec(value)); result.lastIndex = value.lastIndex; return result; } } else { return value; } var isArr = isArray(value); if (isDeep) { // check for circular references and return corresponding clone var initedStack = !stackA; stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == value) { return stackB[length]; } } result = isArr ? ctor(value.length) : {}; } else { result = isArr ? slice(value) : assign({}, value); } // add array properties assigned by `RegExp#exec` if (isArr) { if (hasOwnProperty.call(value, 'index')) { result.index = value.index; } if (hasOwnProperty.call(value, 'input')) { result.input = value.input; } } // exit for shallow clone if (!isDeep) { return result; } // add the source value to the stack of traversed objects // and associate it with its clone stackA.push(value); stackB.push(result); // recursively populate clone (susceptible to call stack limits) (isArr ? baseEach : baseForOwn)(value, function(objValue, key) { result[key] = baseClone(objValue, isDeep, callback, stackA, stackB); }); return result; } /** * The base implementation of `_.create` without support for assigning * properties to the created object. * * @private * @param {Object} prototype The object to inherit from. * @returns {Object} Returns the new object. */ function baseCreate(prototype) { return isObject(prototype) ? nativeCreate(prototype) : {}; } // fallback for environments without `Object.create` if (!nativeCreate) { baseCreate = (function() { function Object() {} return function(prototype) { if (isObject(prototype)) { Object.prototype = prototype; var result = new Object; Object.prototype = null; } return result || context.Object(); }; }()); } /** * The base implementation of `_.createCallback` without support for creating * "_.pluck" or "_.where" style callbacks. * * @private * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. * @param {number} [argCount] The number of arguments the callback accepts. * @returns {Function} Returns a callback function. */ function baseCreateCallback(func, thisArg, argCount) { if (typeof func != 'function') { return identity; } // exit early for no `thisArg` or already bound by `Function#bind` if (typeof thisArg == 'undefined' || !('prototype' in func)) { return func; } var data = func[expando]; if (typeof data == 'undefined') { if (support.funcNames) { data = !func.name; } data = data || !support.funcDecomp; if (!data) { var source = fnToString.call(func); if (!support.funcNames) { data = !reFuncName.test(source); } if (!data) { // checks if `func` references the `this` keyword and stores the result data = reThis.test(source); setData(func, data); } } } // exit early if there are no `this` references or `func` is bound if (data === false || (data !== true && data[1] & BIND_FLAG)) { return func; } switch (argCount) { case 1: return function(value) { return func.call(thisArg, value); }; case 2: return function(a, b) { return func.call(thisArg, a, b); }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); }; case 4: return function(accumulator, value, index, collection) { return func.call(thisArg, accumulator, value, index, collection); }; } return bind(func, thisArg); } /** * The base implementation of `createWrapper` that creates the wrapper and * sets its meta data. * * @private * @param {Array} data The metadata array. * @returns {Function} Returns the new function. */ function baseCreateWrapper(data) { var func = data[0], bitmask = data[1], arity = data[2], thisArg = data[3], partialArgs = data[4], partialRightArgs = data[5], partialHolders = data[6], partialRightHolders = data[7]; var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, key = func; function bound() { var index = -1, length = arguments.length, args = Array(length); while (++index < length) { args[index] = arguments[index]; } if (partialArgs) { args = composeArgs(partialArgs, partialHolders, args); } if (partialRightArgs) { args = composeArgsRight(partialRightArgs, partialRightHolders, args); } if (isCurry && length < arity) { bitmask |= PARTIAL_FLAG; bitmask &= ~PARTIAL_RIGHT_FLAG if (!isCurryBound) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } var newArity = nativeMax(0, arity - length); return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, []]); } var thisBinding = isBind ? thisArg : this; if (isBindKey) { func = thisBinding[key]; } if (this instanceof bound) { thisBinding = baseCreate(func.prototype); var result = func.apply(thisBinding, args); return isObject(result) ? result : thisBinding; } return func.apply(thisBinding, args); } setData(bound, data); return bound; } /** * The base implementation of `_.difference` that accepts a single array * of values to exclude. * * @private * @param {Array} array The array to process. * @param {Array} [values] The array of values to exclude. * @returns {Array} Returns a new array of filtered values. */ function baseDifference(array, values) { var length = array ? array.length : 0; if (!length) { return []; } var index = -1, indexOf = getIndexOf(), prereq = indexOf === baseIndexOf, isLarge = prereq && createCache && values && values.length >= 200, isCommon = prereq && !isLarge, result = [], valuesLength = values ? values.length : 0; if (isLarge) { indexOf = cacheIndexOf; values = createCache(values); } outer: while (++index < length) { var value = array[index]; if (isCommon) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === value) { continue outer; } } result.push(value); } else if (indexOf(values, value) < 0) { result.push(value); } } return result; } /** * The base implementation of `_.forEach` without support for callback * shorthands or `thisArg` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} callback The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEach(collection, callback) { var index = -1, iterable = collection, length = collection ? collection.length : 0; if (typeof length == 'number') { if (support.unindexedChars && isString(iterable)) { iterable = iterable.split(''); } while (++index < length) { if (callback(iterable[index], index, collection) === false) { break; } } } else { baseForOwn(collection, callback); } return collection; } /** * The base implementation of `_.forEachRight` without support for callback * shorthands or `thisArg` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} callback The function called per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEachRight(collection, callback) { var iterable = collection, length = collection ? collection.length : 0; if (typeof length == 'number') { if (support.unindexedChars && isString(iterable)) { iterable = iterable.split(''); } while (length--) { if (callback(iterable[length], length, collection) === false) { break; } } } else { baseForOwnRight(collection, callback); } return collection; } /** * The base implementation of `_.flatten` without support for callback * shorthands or `thisArg` binding. * * @private * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects. * @param {number} [fromIndex=0] The index to start from. * @returns {Array} Returns a new flattened array. */ function baseFlatten(array, isShallow, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array ? array.length : 0, result = []; while (++index < length) { var value = array[index]; if (value && typeof value == 'object' && typeof value.length == 'number' && (isArray(value) || isArguments(value))) { // recursively flatten arrays (susceptible to call stack limits) if (!isShallow) { value = baseFlatten(value, isShallow, isStrict); } var valIndex = -1, valLength = value.length, resIndex = result.length; result.length += valLength; while (++valIndex < valLength) { result[resIndex++] = value[valIndex]; } } else if (!isStrict) { result.push(value); } } return result; } /** * The base implementation of `_.forOwn` without support for callback * shorthands or `thisArg` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} callback The function called per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, callback) { var index = -1, props = keys(object), length = props.length; while (++index < length) { var key = props[index]; if (callback(object[key], key, object) === false) { break; } } return object; } /** * The base implementation of `_.forOwnRight` without support for callback * shorthands or `thisArg` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} callback The function called per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, callback) { var props = keys(object), length = props.length; while (length--) { var key = props[length]; if (callback(object[key], key, object) === false) { break; } } return object; } /** * The base implementation of `_.isEqual`, without support for `thisArg` binding, * that allows partial "_.where" style comparisons. * * @private * @param {*} a The value to compare. * @param {*} b The other value to compare. * @param {Function} [callback] The function to customize comparing values. * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `a` objects. * @param {Array} [stackB=[]] Tracks traversed `b` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { if (callback) { var result = callback(a, b); if (typeof result != 'undefined') { return !!result; } } // exit early for identical values if (a === b) { // treat `+0` vs. `-0` as not equal return a !== 0 || (1 / a == 1 / b); } var type = typeof a, otherType = typeof b; // exit early for unlike primitive values if (a === a && (a == null || b == null || (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { return false; } // compare [[Class]] names var className = toString.call(a), otherClass = toString.call(b); if (className == argsClass) { className = objectClass; } if (otherClass == argsClass) { otherClass = objectClass; } if (className != otherClass) { return false; } switch (className) { case boolClass: case dateClass: // coerce dates and booleans to numbers, dates to milliseconds and booleans // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +a == +b; case numberClass: // treat `NaN` vs. `NaN` as equal return (a != +a) ? b != +b // but treat `-0` vs. `+0` as not equal : (a == 0 ? (1 / a == 1 / b) : a == +b); case regexpClass: case stringClass: // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) // treat string primitives and their corresponding object instances as equal return a == String(b); } var isArr = className == arrayClass; if (!isArr) { // unwrap any `lodash` wrapped values var aWrapped = hasOwnProperty.call(a, '__wrapped__'), bWrapped = hasOwnProperty.call(b, '__wrapped__'); if (aWrapped || bWrapped) { return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); } // exit for functions and DOM nodes if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) { return false; } // in older versions of Opera, `arguments` objects have `Array` constructors var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor, ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor; // non `Object` object instances with different constructors are not equal if (ctorA != ctorB && !(hasOwnProperty.call(a, 'constructor') && hasOwnProperty.call(b, 'constructor')) && !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && ('constructor' in a && 'constructor' in b) ) { return false; } } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) var initedStack = !stackA; stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == a) { return stackB[length] == b; } } var size = 0; result = true; // add `a` and `b` to the stack of traversed objects stackA.push(a); stackB.push(b); // recursively compare objects and arrays (susceptible to call stack limits) if (isArr) { // compare lengths to determine if a deep comparison is necessary length = a.length; size = b.length; result = size == length; if (result || isWhere) { // deep compare the contents, ignoring non-numeric properties while (size--) { var index = length, value = b[size]; if (isWhere) { while (index--) { if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { break; } } } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { break; } } } } else { // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` // which, in this case, is more costly baseForIn(b, function(value, key, b) { if (hasOwnProperty.call(b, key)) { // count the number of properties. size++; // deep compare each property value. return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); } }); if (result && !isWhere) { // ensure both objects have the same number of properties baseForIn(a, function(value, key, a) { if (hasOwnProperty.call(a, key)) { // `size` will be `-1` if `a` has more properties than `b` return (result = --size > -1); } }); } } stackA.pop(); stackB.pop(); return result; } /** * The base implementation of `_.merge` without argument juggling or support * for `thisArg` binding. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} [callback] The function to customize merging properties. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. */ function baseMerge(object, source, callback, stackA, stackB) { (isArray(source) ? baseEach : baseForOwn)(source, function(source, key) { var found, isArr, result = source, value = object[key]; if (source && ((isArr = isArray(source)) || isPlainObject(source))) { // avoid merging previously merged cyclic sources var stackLength = stackA.length; while (stackLength--) { if ((found = stackA[stackLength] == source)) { value = stackB[stackLength]; break; } } if (!found) { var isShallow; if (callback) { result = callback(value, source); if ((isShallow = typeof result != 'undefined')) { value = result; } } if (!isShallow) { value = isArr ? (isArray(value) ? value : []) : (isPlainObject(value) ? value : {}); } // add `source` and associated `value` to the stack of traversed objects stackA.push(source); stackB.push(value); // recursively merge objects and arrays (susceptible to call stack limits) if (!isShallow) { baseMerge(value, source, callback, stackA, stackB); } } } else { if (callback) { result = callback(value, source); if (typeof result == 'undefined') { result = source; } } if (typeof result != 'undefined') { value = result; } } object[key] = value; }); } /** * The base implementation of `_.random` without argument juggling or support * for returning floating-point numbers. * * @private * @param {number} min The minimum possible value. * @param {number} max The maximum possible value. * @returns {number} Returns a random number. */ function baseRandom(min, max) { return min + floor(nativeRandom() * (max - min + 1)); } /** * The base implementation of `_.uniq` without support for callback shorthands * or `thisArg` binding. * * @private * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function} [callback] The function called per iteration. * @returns {Array} Returns a duplicate-value-free array. */ function baseUniq(array, isSorted, callback) { var length = array ? array.length : 0; if (!length) { return []; } var index = -1, indexOf = getIndexOf(), prereq = !isSorted && indexOf === baseIndexOf, isLarge = prereq && createCache && length >= 200, isCommon = prereq && !isLarge, result = []; if (isLarge) { var seen = createCache(); indexOf = cacheIndexOf; } else { seen = (callback && !isSorted) ? [] : result; } outer: while (++index < length) { var value = array[index], computed = callback ? callback(value, index, array) : value; if (isCommon) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { continue outer; } } if (callback) { seen.push(computed); } result.push(value); } else if (isSorted) { if (!index || seen !== computed) { seen = computed; result.push(value); } } else if (indexOf(seen, computed) < 0) { if (callback || isLarge) { seen.push(computed); } result.push(value); } } return result; } /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. * * @private * @param {Array} partialArg An array of arguments to prepend to those provided. * @param {Array} partialHolders An array of `partialArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. * @returns {Array} Returns a new array of composed arguments. */ function composeArgs(partialArgs, partialHolders, args) { var holdersLength = partialHolders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partialArgs.length, result = Array(argsLength + leftLength); while (++leftIndex < leftLength) { result[leftIndex] = partialArgs[leftIndex]; } while (++argsIndex < holdersLength) { result[partialHolders[argsIndex]] = args[argsIndex]; } while (argsLength--) { result[leftIndex++] = args[argsIndex++]; } return result; } /** * This function is like `composeArgs` except that the arguments composition * is tailored for `_.partialRight`. * * @private * @param {Array} partialRightArg An array of arguments to append to those provided. * @param {Array} partialHolders An array of `partialRightArgs` placeholder indexes. * @param {Array|Object} args The provided arguments. * @returns {Array} Returns a new array of composed arguments. */ function composeArgsRight(partialRightArgs, partialRightHolders, args) { var holdersIndex = -1, holdersLength = partialRightHolders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partialRightArgs.length, result = Array(argsLength + rightLength); while (++argsIndex < argsLength) { result[argsIndex] = args[argsIndex]; } var pad = argsIndex; while (++rightIndex < rightLength) { result[pad + rightIndex] = partialRightArgs[rightIndex]; } while (++holdersIndex < holdersLength) { result[pad + partialRightHolders[holdersIndex]] = args[argsIndex++]; } return result; } /** * Creates a function that aggregates a collection, creating an object or * array composed from the results of running each element of the collection * through a callback. The given setter function sets the keys and values * of the composed object or array. * * @private * @param {Function} setter The setter function. * @param {boolean} [retArray=false] A flag to indicate that the aggregator * function should return an array. * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, retArray) { return function(collection, callback, thisArg) { var result = retArray ? [[], []] : {}; callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; setter(result, value, callback(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { setter(result, value, callback(value, key, collection), collection); }); } return result; }; } /** * Creates a cache object to optimize linear searches of large arrays. * * @private * @param {Array} [array=[]] The array to search. * @returns {Object} Returns the cache object. */ var createCache = Set && function(array) { var cache = new Set, length = array ? array.length : 0; cache.push = cache.add; while (length--) { cache.push(array[length]); } return cache; }; /** * Creates the pad required for `string` based on the given padding length. * The `chars` string may be truncated if the number of padding characters * exceeds the padding length. * * @private * @param {string} string The string to create padding for. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the pad for `string`. */ function createPad(string, length, chars) { var strLength = string.length; length = +length || 0; if (strLength >= length) { return ''; } var padLength = length - strLength; chars = chars == null ? ' ' : String(chars); return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); } /** * Creates a function that, when called, either curries or invokes `func` * with an optional `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags to compose. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` * 4 - `_.curry` * 8 - `_.curry` (bound) * 16 - `_.partial` * 32 - `_.partialRight` * @param {number} [arity] The arity of `func`. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partialArgs] An array of arguments to prepend to those * provided to the new function. * @param {Array} [partialRightArgs] An array of arguments to append to those * provided to the new function. * @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes. * @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes. * @returns {Function} Returns the new function. */ function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders) { var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isPartial = bitmask & PARTIAL_FLAG, isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; if (!isBindKey && !isFunction(func)) { throw new TypeError; } if (isPartial && !partialArgs.length) { bitmask &= ~PARTIAL_FLAG; isPartial = partialArgs = false; } if (isPartialRight && !partialRightArgs.length) { bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = partialRightArgs = false; } var data = !isBindKey && func[expando]; if (data && data !== true) { // shallow clone `data` data = slice(data); // clone partial left arguments if (data[4]) { data[4] = slice(data[4]); } // clone partial right arguments if (data[5]) { data[5] = slice(data[5]); } // set arity if provided if (typeof arity == 'number') { data[2] = arity; } // set `thisArg` if not previously bound var bound = data[1] & BIND_FLAG; if (isBind && !bound) { data[3] = thisArg; } // set if currying a bound function if (!isBind && bound) { bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments if (isPartial) { if (data[4]) { push.apply(data[4], partialArgs); } else { data[4] = partialArgs; } } // prepend partial right arguments if (isPartialRight) { if (data[5]) { unshift.apply(data[5], partialRightArgs); } else { data[5] = partialRightArgs; } } // merge flags data[1] |= bitmask; return createWrapper.apply(null, data); } if (arity == null) { arity = isBindKey ? 0 : func.length; } else if (arity < 0) { arity = 0; } if (isPartial) { partialHolders = getHolders(partialArgs); } if (isPartialRight) { partialRightHolders = getHolders(partialRightArgs); } // fast path for `_.bind` data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders]; return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) ? baseBind(data) : baseCreateWrapper(data); } /** * Creates compiled iteration functions. * * @private * @param {Object} [options] The compile options object. * @param {string} [options.args] A comma separated string of iteration function arguments. * @param {string} [options.init] The string representation of the initial `result` value. * @param {string} [options.loop] Code to execute in the object loop. * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop. * @returns {Function} Returns the compiled function. */ function createIterator(options) { options.shadowedProps = shadowedProps; options.support = support; // create the function factory var factory = Function( 'errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto, ' + 'nonEnumProps, stringClass, stringProto, toString', 'return function(' + options.args + ') {\n' + iteratorTemplate(options) + '\n}' ); // return the compiled function return factory( errorClass, errorProto, hasOwnProperty, isArguments, isObject, objectProto, nonEnumProps, stringClass, stringProto, toString ); } /** * Finds the indexes of all placeholder elements in `array`. * * @private * @param {Array} array The array to inspect. * @returns {Array} Returns a new array of placeholder indexes. */ function getHolders(array) { var index = -1, length = array.length, result = []; while (++index < length) { if (array[index] === lodash) { result.push(index); } } return result; } /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this method returns the custom method, otherwise it returns * the `baseIndexOf` function. * * @private * @returns {Function} Returns the "indexOf" function. */ function getIndexOf() { var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result; return result; } /** * Checks if `value` is a native function. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. */ function isNative(value) { return typeof value == 'function' && reNative.test(fnToString.call(value)); } /** * Sets wrapper metadata on a given function. * * @private * @param {Function} func The function to set data on. * @param {Array} value The data array to set. */ var setData = !defineProperty ? noop : function(func, value) { descriptor.value = value; defineProperty(func, expando, descriptor); }; /** * A fallback implementation of `isPlainObject` which checks if `value` is * an object created by the `Object` constructor, assuming objects created * by the `Object` constructor have no inherited enumerable properties and * that there are no `Object.prototype` extensions. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { var ctor, result; // avoid non Object objects, `arguments` objects, and DOM elements if (!(value && toString.call(value) == objectClass) || (!hasOwnProperty.call(value, 'constructor') && (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) || (!support.argsClass && isArguments(value)) || (!support.nodeClass && isNode(value))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first // iterated property is an object's own property then there are no inherited // enumerable properties. if (support.ownLast) { baseForIn(value, function(value, key, object) { result = hasOwnProperty.call(object, key); return false; }); return result !== false; } // In most environments an object's own properties are iterated before // its inherited properties. If the last iterated property is an object's // own property then there are no inherited enumerable properties. baseForIn(value, function(value, key) { result = key; }); return typeof result == 'undefined' || hasOwnProperty.call(value, result); } /*--------------------------------------------------------------------------*/ /** * Checks if `value` is an `arguments` object. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`. * @example * * (function() { return _.isArguments(arguments); })(1, 2, 3); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { return value && typeof value == 'object' && typeof value.length == 'number' && toString.call(value) == argsClass || false; } // fallback for environments that can't detect `arguments` objects by [[Class]] if (!support.argsClass) { isArguments = function(value) { return value && typeof value == 'object' && typeof value.length == 'number' && hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false; }; } /** * The base implementation of `_.forIn` without support for callback * shorthands or `thisArg` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} callback The function called per iteration. * @returns {Object} Returns `object`. */ var baseForIn = createIterator({ 'args': 'object, callback', 'init': 'object', 'loop': 'if (callback(object[key], key, object) === false) {\n return result;\n }', 'useHas': false }); /** * A fallback implementation of `Object.keys` which produces an array of the * given object's own enumerable property names. * * @private * @type Function * @param {Object} object The object to inspect. * @returns {Array} Returns an array of property names. */ var shimKeys = createIterator({ 'args': 'object', 'init': '[]', 'loop': 'result.push(key)', 'useHas': true }); /*--------------------------------------------------------------------------*/ /** * Creates an array with all falsey values removed. The values `false`, `null`, * `0`, `""`, `undefined`, and `NaN` are all falsey. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to compact. * @returns {Array} Returns a new array of filtered values. * @example * * _.compact([0, 1, false, 2, '', 3]); * // => [1, 2, 3] */ function compact(array) { var index = -1, length = array ? array.length : 0, resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (value) { result[resIndex++] = value; } } return result; } /** * Creates an array excluding all values of the provided arrays using strict * equality for comparisons, i.e. `===`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to process. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns a new array of filtered values. * @example * * _.difference([1, 2, 3], [5, 2, 10]); * // => [1, 3] */ function difference(array) { return baseDifference(array, baseFlatten(arguments, true, true, 1)); } /** * Creates a slice of `array` with `n` elements dropped from the beginning. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @returns {Array} Returns the slice of `array`. * @example * * _.drop([1, 2, 3], 1); * // => [2, 3] * * _.drop([1, 2, 3], 2); * // => [3] * * _.drop([1, 2, 3], 5); * // => [] * * _.drop([1, 2, 3], 0); * // => [1, 2, 3] */ var drop = rest; /** * Creates a slice of `array` with `n` elements dropped from the end. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @returns {Array} Returns the slice of `array`. * @example * * _.dropRight([1, 2, 3], 1); * // => [1, 2] * * _.dropRight([1, 2, 3], 2); * // => [1] * * _.dropRight([1, 2, 3], 5); * // => [] * * _.dropRight([1, 2, 3], 0); * // => [1, 2, 3] */ var dropRight = initial; /** * Creates a slice of `array` excluding elements dropped from the end. * Elements will be dropped until the predicate returns falsey. The predicate * is bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function called * per element. * @returns {Array} Returns the slice of `array`. * @example * * _.dropRightWhile([1, 2, 3], function(num) { * return num > 1; * }); * // => [1] * * var characters = [ * { 'name': 'barney', 'employer': 'slate' }, * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.dropRightWhile(characters, 'blocked'), 'name'); * // => ['barney'] * * // using "_.where" callback shorthand * _.pluck(_.dropRightWhile(characters, { 'employer': 'na' }), 'name'); * // => ['barney', 'fred'] */ var dropRightWhile = initial; /** * Creates a slice of `array` excluding elements dropped from the beginning. * Elements will be dropped until the predicate returns falsey. The predicate * is bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function called * per element. * @returns {Array} Returns the slice of `array`. * @example * * _.dropWhile([1, 2, 3], function(num) { * return num < 3; * }); * // => [3] * * var characters = [ * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, * { 'name': 'fred', 'employer': 'slate' }, * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.dropWhile(characters, 'blocked'), 'name'); * // => ['fred', 'pebbles'] * * // using "_.where" callback shorthand * _.pluck(_.dropWhile(characters, { 'employer': 'slate' }), 'name'); * // => ['pebbles'] */ var dropWhile = rest; /** * This method is like `_.find` except that it returns the index of the first * element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40, 'blocked': true }, * { 'name': 'pebbles', 'age': 1 } * ]; * * _.findIndex(characters, function(chr) { * return chr.age < 20; * }); * // => 2 * * // using "_.where" callback shorthand * _.findIndex(characters, { 'age': 36 }); * // => 0 * * // using "_.pluck" callback shorthand * _.findIndex(characters, 'blocked'); * // => 1 */ function findIndex(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0; predicate = lodash.createCallback(predicate, thisArg, 3); while (++index < length) { if (predicate(array[index], index, array)) { return index; } } return -1; } /** * This method is like `_.findIndex` except that it iterates over elements * of a `collection` from right to left. * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var characters = [ * { 'name': 'barney', 'age': 36, 'blocked': true }, * { 'name': 'fred', 'age': 40 }, * { 'name': 'pebbles', 'age': 1, 'blocked': true } * ]; * * _.findLastIndex(characters, function(chr) { * return chr.age > 30; * }); * // => 1 * * // using "_.where" callback shorthand * _.findLastIndex(characters, { 'age': 36 }); * // => 0 * * // using "_.pluck" callback shorthand * _.findLastIndex(characters, 'blocked'); * // => 2 */ function findLastIndex(array, predicate, thisArg) { var length = array ? array.length : 0; predicate = lodash.createCallback(predicate, thisArg, 3); while (length--) { if (predicate(array[length], length, array)) { return length; } } return -1; } /** * Gets the first element of `array`. * * @static * @memberOf _ * @alias head * @category Arrays * @param {Array} array The array to query. * @returns {*} Returns the first element of `array`. * @example * * _.first([1, 2, 3]); * // => 1 * * _.first([]); * // => undefined */ function first(array, predicate, thisArg) { if (typeof predicate != 'number' && predicate != null) { var index = -1, length = array ? array.length : 0, n = 0; predicate = lodash.createCallback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) { n++; } } else { n = predicate; if (n == null || thisArg) { return array ? array[0] : undefined; } } return slice(array, 0, n > 0 ? n : 0); } /** * Flattens a nested array (the nesting can be to any depth). If `isShallow` * is truthy, the array will only be flattened a single level. If a callback * is provided each element of the array is passed through the callback before * flattening. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to flatten. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it will be used to create a "_.pluck" * or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns a new flattened array. * @example * * _.flatten([1, [2], [3, [[4]]]]); * // => [1, 2, 3, 4]; * * // using `isShallow` * _.flatten([1, [2], [3, [[4]]]], true); * // => [1, 2, 3, [[4]]]; * * var characters = [ * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] }, * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } * ]; * * // using "_.pluck" callback shorthand * _.flatten(characters, 'pets'); * // => ['hoppy', 'baby puss', 'dino'] */ function flatten(array, isShallow, callback, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } // juggle arguments var type = typeof isShallow; if (type != 'boolean' && isShallow != null) { thisArg = callback; callback = isShallow; isShallow = false; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[callback] === array) { callback = null; } } if (callback != null) { array = map(array, callback, thisArg); } return baseFlatten(array, isShallow); } /** * Gets the index at which the first occurrence of `value` is found using * strict equality for comparisons, i.e. `===`. If the array is already sorted * providing `true` for `fromIndex` will run a faster binary search. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=0] The index to search from or `true` * to perform a binary search on a sorted array. * @returns {number} Returns the index of the matched value or `-1`. * @example * * _.indexOf([1, 2, 3, 1, 2, 3], 2); * // => 1 * * // using `fromIndex` * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); * // => 4 * * // performing a binary search * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); * // => 2 */ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(0, length + fromIndex) : (fromIndex || 0); } else if (fromIndex) { var index = sortedIndex(array, value); return (length && array[index] === value) ? index : -1; } return baseIndexOf(array, value, fromIndex); } /** * Gets all but the last element of `array`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.initial([1, 2, 3]); * // => [1, 2] */ function initial(array, predicate, thisArg) { var length = array ? array.length : 0; if (typeof predicate != 'number' && predicate != null) { var index = length, n = 0; predicate = lodash.createCallback(predicate, thisArg, 3); while (index-- && predicate(array[index], index, array)) { n++; } } else { n = (predicate == null || thisArg) ? 1 : predicate; } n = length - n; return slice(array, 0, n > 0 ? n : 0); } /** * Creates an array of unique values present in all provided arrays using * strict equality for comparisons, i.e. `===`. * * @static * @memberOf _ * @category Arrays * @param {...Array} [array] The arrays to inspect. * @returns {Array} Returns an array of shared values. * @example * * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); * // => [1, 2] */ function intersection() { var args = [], argsIndex = -1, argsLength = arguments.length, caches = [], indexOf = getIndexOf(), prereq = createCache && indexOf === baseIndexOf, seen = []; while (++argsIndex < argsLength) { var value = arguments[argsIndex]; if (isArray(value) || isArguments(value)) { args.push(value); caches.push(prereq && value.length >= 120 && createCache(argsIndex ? args[argsIndex] : seen)); } } var array = args[0], index = -1, length = array ? array.length : 0, result = []; outer: while (++index < length) { var cache = caches[0]; value = array[index]; if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) { argsIndex = argsLength; (cache || seen).push(value); while (--argsIndex) { cache = caches[argsIndex]; if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { continue outer; } } result.push(value); } } return result; } /** * Gets the last element of `array`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to query. * @returns {*} Returns the last element of `array`. * @example * * _.last([1, 2, 3]); * // => 3 */ function last(array, predicate, thisArg) { var length = array ? array.length : 0; if (typeof predicate != 'number' && predicate != null) { var index = length, n = 0; predicate = lodash.createCallback(predicate, thisArg, 3); while (index-- && predicate(array[index], index, array)) { n++; } } else { n = predicate; if (n == null || thisArg) { return array ? array[length - 1] : undefined; } } n = length - n; return slice(array, n > 0 ? n : 0); } /** * Gets the index at which the last occurrence of `value` is found using strict * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used * as the offset from the end of the collection. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=array.length-1] The index to search from. * @returns {number} Returns the index of the matched value or `-1`. * @example * * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); * // => 4 * * // using `fromIndex` * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); * // => 1 */ function lastIndexOf(array, value, fromIndex) { var index = array ? array.length : 0; if (typeof fromIndex == 'number') { index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; } while (index--) { if (array[index] === value) { return index; } } return -1; } /** * Removes all provided values from `array` using strict equality for * comparisons, i.e. `===`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to modify. * @param {...*} [value] The values to remove. * @returns {Array} Returns `array`. * @example * * var array = [1, 2, 3, 1, 2, 3]; * _.pull(array, 2, 3); * console.log(array); * // => [1, 1] */ function pull(array) { var argsIndex = 0, argsLength = arguments.length, length = array ? array.length : 0; while (++argsIndex < argsLength) { var index = -1, value = arguments[argsIndex]; while (++index < length) { if (array[index] === value) { splice.call(array, index--, 1); length--; } } } return array; } /** * Creates an array of numbers (positive and/or negative) progressing from * `start` up to but not including `end`. If `start` is less than `stop` a * zero-length range is created unless a negative `step` is specified. * * @static * @memberOf _ * @category Arrays * @param {number} [start=0] The start of the range. * @param {number} end The end of the range. * @param {number} [step=1] The value to increment or decrement by. * @returns {Array} Returns a new range array. * @example * * _.range(4); * // => [0, 1, 2, 3] * * _.range(1, 5); * // => [1, 2, 3, 4] * * _.range(0, 20, 5); * // => [0, 5, 10, 15] * * _.range(0, -4, -1); * // => [0, -1, -2, -3] * * _.range(1, 4, 0); * // => [1, 1, 1] * * _.range(0); * // => [] */ function range(start, end, step) { start = +start || 0; step = typeof step == 'number' ? step : (+step || 1); if (end == null) { end = start; start = 0; } // use `Array(length)` so engines like Chakra and V8 avoid slower modes // http://youtu.be/XAqIpGU8ZZk#t=17m25s var index = -1, length = nativeMax(0, ceil((end - start) / (step || 1))), result = Array(length); while (++index < length) { result[index] = start; start += step; } return result; } /** * Removes all elements from an array that the predicate returns truthy for * and returns an array of removed elements. The predicate is bound to `thisArg` * and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to modify. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns a new array of removed elements. * @example * * var array = [1, 2, 3, 4, 5, 6]; * var evens = _.remove(array, function(num) { return num % 2 == 0; }); * * console.log(array); * // => [1, 3, 5] * * console.log(evens); * // => [2, 4, 6] */ function remove(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0, result = []; predicate = lodash.createCallback(predicate, thisArg, 3); while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result.push(value); splice.call(array, index--, 1); length--; } } return result; } /** * Gets all but the first element of `array`. * * @static * @memberOf _ * @alias tail * @category Arrays * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.rest([1, 2, 3]); * // => [2, 3] */ function rest(array, predicate, thisArg) { if (typeof predicate != 'number' && predicate != null) { var index = -1, length = array ? array.length : 0, n = 0; predicate = lodash.createCallback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) { n++; } } else if (predicate == null || thisArg) { n = 1; } else { n = predicate > 0 ? predicate : 0; } return slice(array, n); } /** * Slices `array` from the `start` index up to, but not including, the `end` index. * * Note: This function is used instead of `Array#slice` to support node lists * in IE < 9 and to ensure dense arrays are returned. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to slice. * @param {number} [start=0] The start index. * @param {number} [end=array.length] The end index. * @returns {Array} Returns the new array. */ function slice(array, start, end) { var index = -1, length = array ? array.length : 0; if (typeof start == 'undefined') { start = 0; } else if (start < 0) { start = nativeMax(length + start, 0); } else if (start > length) { start = length; } if (typeof end == 'undefined') { end = length; } else if (end < 0) { end = nativeMax(length + end, 0); } else if (end > length) { end = length; } length = end - start || 0; var result = Array(length); while (++index < length) { result[index] = array[start + index]; } return result; } /** * Uses a binary search to determine the smallest index at which a value * should be inserted into a given sorted array in order to maintain the sort * order of the array. If a callback is provided it will be executed for * `value` and each element of `array` to compute their sort ranking. The * callback is bound to `thisArg` and invoked with one argument; (value). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * _.sortedIndex([20, 30, 50], 40); * // => 2 * * var dict = { * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } * }; * * // using `callback` * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { * return dict.wordToNumber[word]; * }); * // => 2 * * // using `callback` with `thisArg` * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { * return this.wordToNumber[word]; * }, dict); * // => 2 * * // using "_.pluck" callback shorthand * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 2 */ function sortedIndex(array, value, callback, thisArg) { var low = 0, high = array ? array.length : low; // explicitly reference `identity` for better inlining in Firefox callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity; value = callback(value); while (low < high) { var mid = (low + high) >>> 1; (callback(array[mid]) < value) ? (low = mid + 1) : (high = mid); } return low; } /** * Creates a slice of `array` with `n` elements taken from the beginning. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @returns {Array} Returns the slice of `array`. * @example * * _.take([1, 2, 3], 1); * // => [1] * * _.take([1, 2, 3], 2); * // => [1, 2] * * _.take([1, 2, 3], 5); * // => [1, 2, 3] * * _.take([1, 2, 3], 0); * // => [] */ var take = first; /** * Creates a slice of `array` with `n` elements taken from the end. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @returns {Array} Returns the slice of `array`. * @example * * _.takeRight([1, 2, 3], 1); * // => [3] * * _.takeRight([1, 2, 3], 2); * // => [2, 3] * * _.takeRight([1, 2, 3], 5); * // => [1, 2, 3] * * _.takeRight([1, 2, 3], 0); * // => [] */ var takeRight = last; /** * Creates a slice of `array` with elements taken from the end. Elements will * be taken until the predicate returns falsey. The predicate is bound to * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function called * per element. * @returns {Array} Returns the slice of `array`. * @example * * _.takeRightWhile([1, 2, 3], function(num) { * return num > 1; * }); * // => [2, 3] * * var characters = [ * { 'name': 'barney', 'employer': 'slate' }, * { 'name': 'fred', 'employer': 'slate', 'blocked': true }, * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.takeRightWhile(characters, 'blocked'), 'name'); * // => ['fred', 'pebbles'] * * // using "_.where" callback shorthand * _.pluck(_.takeRightWhile(characters, { 'employer': 'na' }), 'name'); * // => ['pebbles'] */ var takeRightWhile = last; /** * Creates a slice of `array` with elements taken from the beginning. Elements * will be taken until the predicate returns falsey. The predicate is bound * to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @type Function * @category Arrays * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=identity] The function called * per element. * @returns {Array} Returns the slice of `array`. * @example * * _.takeWhile([1, 2, 3], function(num) { * return num < 3; * }); * // => [1, 2] * * var characters = [ * { 'name': 'barney', 'employer': 'slate', 'blocked': true }, * { 'name': 'fred', 'employer': 'slate' }, * { 'name': 'pebbles', 'employer': 'na', 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.pluck(_.takeWhile(characters, 'blocked'), 'name'); * // => ['barney'] * * // using "_.where" callback shorthand * _.pluck(_.takeWhile(characters, { 'employer': 'slate' }), 'name'); * // => ['barney', 'fred'] */ var takeWhile = first; /** * Creates an array of unique values, in order, of the provided arrays using * strict equality for comparisons, i.e. `===`. * * @static * @memberOf _ * @category Arrays * @param {...Array} [array] The arrays to inspect. * @returns {Array} Returns an array of combined values. * @example * * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); * // => [1, 2, 3, 5, 4] */ function union() { return baseUniq(baseFlatten(arguments, true, true)); } /** * Creates a duplicate-value-free version of an array using strict equality * for comparisons, i.e. `===`. If the array is sorted, providing * `true` for `isSorted` will use a faster algorithm. If a callback is provided * each element of `array` is passed through the callback before uniqueness * is computed. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, array). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias unique * @category Arrays * @param {Array} array The array to process. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it will be used to create a "_.pluck" * or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns a duplicate-value-free array. * @example * * _.uniq([1, 2, 1, 3, 1]); * // => [1, 2, 3] * * // using `isSorted` * _.uniq([1, 1, 2, 2, 3], true); * // => [1, 2, 3] * * // using `callback` * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); * // => ['A', 'b', 'C'] * * // using `callback` with `thisArg` * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); * // => [1, 2.5, 3] * * // using "_.pluck" callback shorthand * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ function uniq(array, isSorted, callback, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } // juggle arguments var type = typeof isSorted; if (type != 'boolean' && isSorted != null) { thisArg = callback; callback = isSorted; isSorted = false; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[callback] === array) { callback = null; } } if (callback != null) { callback = lodash.createCallback(callback, thisArg, 3); } return baseUniq(array, isSorted, callback); } /** * Creates an array excluding all provided values using strict equality for * comparisons, i.e. `===`. * * @static * @memberOf _ * @category Arrays * @param {Array} array The array to filter. * @param {...*} [value] The values to exclude. * @returns {Array} Returns a new array of filtered values. * @example * * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ function without(array) { return baseDifference(array, slice(arguments, 1)); } /** * Creates an array that is the symmetric difference of the provided arrays. * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for * more details. * * @static * @memberOf _ * @category Arrays * @param {...Array} [array] The arrays to inspect. * @returns {Array} Returns an array of values. * @example * * _.xor([1, 2, 3], [5, 2, 1, 4]); * // => [3, 5, 4] * * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); * // => [1, 4, 5] */ function xor() { var index = -1, length = arguments.length; while (++index < length) { var array = arguments[index]; if (isArray(array) || isArguments(array)) { var result = result ? baseDifference(result, array).concat(baseDifference(array, result)) : array; } } return result ? baseUniq(result) : []; } /** * Creates an array of grouped elements, the first of which contains the first * elements of the given arrays, the second of which contains the second elements * of the given arrays, and so on. If a zipped value is provided its corresponding * unzipped value will be returned. * * @static * @memberOf _ * @alias unzip * @category Arrays * @param {...Array} [array] The arrays to process. * @returns {Array} Returns a new array of grouped elements. * @example * * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] * * _.unzip([['fred', 30, true], ['barney', 40, false]]); * // => [['fred', 'barney'], [30, 40], [true, false]] */ function zip() { var array = arguments.length > 1 ? arguments : arguments[0], index = -1, length = array ? max(pluck(array, 'length')) : 0, result = Array(length < 0 ? 0 : length); while (++index < length) { result[index] = pluck(array, index); } return result; } /** * Creates an object composed from arrays of `keys` and `values`. Provide * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` * or two arrays, one of `keys` and one of corresponding `values`. * * @static * @memberOf _ * @alias object * @category Arrays * @param {Array} keys The array of keys. * @param {Array} [values=[]] The array of values. * @returns {Object} Returns an object composed of the given keys and * corresponding values. * @example * * _.zipObject(['fred', 'barney'], [30, 40]); * // => { 'fred': 30, 'barney': 40 } */ function zipObject(keys, values) { var index = -1, length = keys ? keys.length : 0, result = {}; if (!values && length && !isArray(keys[0])) { values = []; } while (++index < length) { var key = keys[index]; if (values) { result[key] = values[index]; } else if (key) { result[key[0]] = key[1]; } } return result; } /*--------------------------------------------------------------------------*/ /** * Creates a `lodash` object that wraps `value` with explicit method * chaining enabled. * * @static * @memberOf _ * @category Chaining * @param {*} value The value to wrap. * @returns {Object} Returns the wrapper object. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 }, * { 'name': 'pebbles', 'age': 1 } * ]; * * var youngest = _.chain(characters) * .sortBy('age') * .map(function(chr) { return chr.name + ' is ' + chr.age; }) * .first() * .value(); * // => 'pebbles is 1' */ function chain(value) { value = new lodashWrapper(value); value.__chain__ = true; return value; } /** * This method invokes `interceptor` and returns `value`. The interceptor is * bound to `thisArg` and invoked with one argument; (value). The purpose of * this method is to "tap into" a method chain in order to perform operations * on intermediate results within the chain. * * @static * @memberOf _ * @category Chaining * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. * @param {*} [thisArg] The `this` binding of `interceptor`. * @returns {*} Returns `value`. * @example * * _([1, 2, 3, 4]) * .tap(function(array) { array.pop(); }) * .reverse() * .value(); * // => [3, 2, 1] */ function tap(value, interceptor, thisArg) { interceptor.call(thisArg, value); return value; } /** * Enables explicit method chaining on the wrapper object. * * @name chain * @memberOf _ * @category Chaining * @returns {*} Returns the wrapper object. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * // without explicit chaining * _(characters).first(); * // => { 'name': 'barney', 'age': 36 } * * // with explicit chaining * _(characters).chain() * .first() * .pick('age') * .value(); * // => { 'age': 36 } */ function wrapperChain() { this.__chain__ = true; return this; } /** * Produces the `toString` result of the wrapped value. * * @name toString * @memberOf _ * @category Chaining * @returns {string} Returns the string result. * @example * * _([1, 2, 3]).toString(); * // => '1,2,3' */ function wrapperToString() { return String(this.__wrapped__); } /** * Extracts the wrapped value. * * @name valueOf * @memberOf _ * @alias value * @category Chaining * @returns {*} Returns the wrapped value. * @example * * _([1, 2, 3]).valueOf(); * // => [1, 2, 3] */ function wrapperValueOf() { return this.__wrapped__; } /*--------------------------------------------------------------------------*/ /** * Creates an array of elements from the specified indexes, or keys, of the * `collection`. Indexes may be specified as individual arguments or as arrays * of indexes. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {...(number|number[]|string|string[])} [index] The indexes of `collection` * to retrieve, specified as individual indexes or arrays of indexes. * @returns {Array} Returns a new array of elements corresponding to the * provided indexes. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); * // => ['a', 'c', 'e'] * * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ function at(collection, guard) { var args = arguments, index = -1, props = baseFlatten(args, true, false, 1), length = props.length, type = typeof guard; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && args[2] && args[2][guard] === collection) { length = 1; } if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } var result = Array(length); while(++index < length) { result[index] = collection[props[index]]; } return result; } /** * Checks if a given value is present in a collection using strict equality * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the * offset from the end of the collection. * * @static * @memberOf _ * @alias include * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {*} target The value to check for. * @param {number} [fromIndex=0] The index to search from. * @returns {boolean} Returns `true` if the target element is found, else `false`. * @example * * _.contains([1, 2, 3], 1); * // => true * * _.contains([1, 2, 3], 1, 2); * // => false * * _.contains({ 'name': 'fred', 'age': 40 }, 'fred'); * // => true * * _.contains('pebbles', 'eb'); * // => true */ function contains(collection, target, fromIndex) { var length = collection ? collection.length : 0; fromIndex = typeof fromIndex == 'number' ? fromIndex : 0; if (typeof length == 'number') { if (fromIndex >= length) { return false; } if (typeof collection == 'string' || !isArray(collection) && isString(collection)) { return nativeContains ? nativeContains.call(collection, target, fromIndex) : collection.indexOf(target, fromIndex) > -1; } var indexOf = getIndexOf(); fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; return indexOf(collection, target, fromIndex) > -1; } var index = -1, result = false; baseEach(collection, function(value) { if (++index >= fromIndex) { return !(result = value === target); } }); return result; } /** * Creates an object composed of keys generated from the results of running * each element of `collection` through the callback. The corresponding value * of each key is the number of times the key was returned by the callback. * The callback is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); * // => { '4': 1, '6': 2 } * * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1); }); /** * Checks if the predicate returns truthy for **all** elements of a collection. * The predicate is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias all * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if all elements passed the predicate check, * else `false`. * @example * * _.every([true, 1, null, 'yes']); * // => false * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * // using "_.pluck" callback shorthand * _.every(characters, 'age'); * // => true * * // using "_.where" callback shorthand * _.every(characters, { 'age': 36 }); * // => false */ function every(collection, predicate, thisArg) { var result = true; predicate = lodash.createCallback(predicate, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { if (!predicate(collection[index], index, collection)) { return false; } } } else { baseEach(collection, function(value, index, collection) { return (result = !!predicate(value, index, collection)); }); } return result; } /** * Iterates over elements of a collection returning an array of all elements * the predicate returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias select * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns a new array of elements that passed the predicate check. * @example * * var evens = _.filter([1, 2, 3, 4], function(num) { return num % 2 == 0; }); * // => [2, 4] * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40, 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.filter(characters, 'blocked'); * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] * * // using "_.where" callback shorthand * _.filter(characters, { 'age': 36 }); * // => [{ 'name': 'barney', 'age': 36 }] */ function filter(collection, predicate, thisArg) { var result = []; predicate = lodash.createCallback(predicate, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; if (predicate(value, index, collection)) { result.push(value); } } } else { baseEach(collection, function(value, index, collection) { if (predicate(value, index, collection)) { result.push(value); } }); } return result; } /** * Iterates over elements of a collection, returning the first element that * the predicate returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias detect, findWhere * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the found element, else `undefined`. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40, 'blocked': true }, * { 'name': 'pebbles', 'age': 1 } * ]; * * _.find(characters, function(chr) { * return chr.age < 40; * }); * // => { 'name': 'barney', 'age': 36 } * * // using "_.where" callback shorthand * _.find(characters, { 'age': 1 }); * // => { 'name': 'pebbles', 'age': 1 } * * // using "_.pluck" callback shorthand * _.find(characters, 'blocked'); * // => { 'name': 'fred', 'age': 40, 'blocked': true } */ function find(collection, predicate, thisArg) { predicate = lodash.createCallback(predicate, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; if (predicate(value, index, collection)) { return value; } } } else { var result; baseEach(collection, function(value, index, collection) { if (predicate(value, index, collection)) { result = value; return false; } }); return result; } } /** * This method is like `_.find` except that it iterates over elements * of a `collection` from right to left. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the found element, else `undefined`. * @example * * _.findLast([1, 2, 3, 4], function(num) { * return num % 2 == 1; * }); * // => 3 */ function findLast(collection, predicate, thisArg) { var result; predicate = lodash.createCallback(predicate, thisArg, 3); baseEachRight(collection, function(value, index, collection) { if (predicate(value, index, collection)) { result = value; return false; } }); return result; } /** * Iterates over elements of a collection, executing the callback for each * element. The callback is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Callbacks may exit iteration early by * explicitly returning `false`. * * Note: As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * * @static * @memberOf _ * @alias each * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); * // => logs each number and returns '1,2,3' * * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); * // => logs each number and returns the object (property order is not guaranteed across environments) */ function forEach(collection, callback, thisArg) { if (callback && typeof thisArg == 'undefined' && isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { if (callback(collection[index], index, collection) === false) { break; } } } else { baseEach(collection, baseCreateCallback(callback, thisArg, 3)); } return collection; } /** * This method is like `_.forEach` except that it iterates over elements * of a `collection` from right to left. * * @static * @memberOf _ * @alias eachRight * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); * // => logs each number from right to left and returns '3,2,1' */ function forEachRight(collection, callback, thisArg) { if (callback && typeof thisArg == 'undefined' && isArray(collection)) { var length = collection.length; while (length--) { if (callback(collection[length], length, collection) === false) { break; } } } else { baseEachRight(collection, baseCreateCallback(callback, thisArg, 3)); } return collection; } /** * Creates an object composed of keys generated from the results of running * each element of a collection through the callback. The corresponding value * of each key is an array of the elements responsible for generating the key. * The callback is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * * // using "_.pluck" callback shorthand * _.groupBy(['one', 'two', 'three'], 'length'); * // => { '3': ['one', 'two'], '5': ['three'] } */ var groupBy = createAggregator(function(result, value, key) { if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { result[key] = [value]; } }); /** * Creates an object composed of keys generated from the results of running * each element of the collection through the given callback. The corresponding * value of each key is the last element responsible for generating the key. * The callback is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the composed aggregate object. * @example * * var keys = [ * { 'dir': 'left', 'code': 97 }, * { 'dir': 'right', 'code': 100 } * ]; * * _.indexBy(keys, 'dir'); * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } * * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); }); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } * * _.indexBy(keys, function(key) { return this.fromCharCode(key.code); }, String); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } */ var indexBy = createAggregator(function(result, value, key) { result[key] = value; }); /** * Invokes the method named by `methodName` on each element in the `collection` * returning an array of the results of each invoked method. Additional arguments * will be provided to each invoked method. If `methodName` is a function it * will be invoked for, and `this` bound to, each element in the `collection`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. * @param {...*} [args] Arguments to invoke the method with. * @returns {Array} Returns a new array of the results of each invoked method. * @example * * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); * // => [[1, 5, 7], [1, 2, 3]] * * _.invoke([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ function invoke(collection, methodName) { var index = -1, isFunc = typeof methodName == 'function', length = collection ? collection.length : 0, result = Array(typeof length == 'number' ? length : 0); if (arguments.length < 3 && isArray(collection)) { while (++index < length) { var value = collection[index]; result[index] = isFunc ? methodName.call(value) : value[methodName](); } } else { var args = slice(arguments, 2); baseEach(collection, function(value) { result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); }); } return result; } /** * Creates an array of values by running each element in the collection * through the callback. The callback is bound to `thisArg` and invoked with * three arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias collect * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns a new array of the results of each `callback` execution. * @example * * _.map([1, 2, 3], function(num) { return num * 3; }); * // => [3, 6, 9] * * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); * // => [3, 6, 9] (property order is not guaranteed across environments) * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * // using "_.pluck" callback shorthand * _.map(characters, 'name'); * // => ['barney', 'fred'] */ function map(collection, callback, thisArg) { var index = -1, length = collection ? collection.length : 0, result = Array(typeof length == 'number' ? length : 0); callback = lodash.createCallback(callback, thisArg, 3); if (isArray(collection)) { while (++index < length) { result[index] = callback(collection[index], index, collection); } } else { baseEach(collection, function(value, key, collection) { result[++index] = callback(value, key, collection); }); } return result; } /** * Retrieves the maximum value of a collection. If the collection is empty or * falsey `-Infinity` is returned. If a callback is provided it will be executed * for each value in the collection to generate the criterion by which the value * is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it will be used to create a "_.pluck" * or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the maximum value. * @example * * _.max([4, 2, 8, 6]); * // => 8 * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * _.max(characters, function(chr) { return chr.age; }); * // => { 'name': 'fred', 'age': 40 }; * * // using "_.pluck" callback shorthand * _.max(characters, 'age'); * // => { 'name': 'fred', 'age': 40 }; */ function max(collection, callback, thisArg) { var computed = -Infinity, result = computed, type = typeof callback; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[callback] === collection) { callback = null; } if (callback == null && isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; if (value > result) { result = value; } } } else { callback = (callback == null && isString(collection)) ? charAtCallback : lodash.createCallback(callback, thisArg, 3); baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); if (current > computed) { computed = current; result = value; } }); } return result; } /** * Retrieves the minimum value of a collection. If the collection is empty or * falsey `Infinity` is returned. If a callback is provided it will be executed * for each value in the collection to generate the criterion by which the value * is ranked. The callback is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [callback] The function called per iteration. * If a property name or object is provided it will be used to create a "_.pluck" * or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the minimum value. * @example * * _.min([4, 2, 8, 6]); * // => 2 * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * _.min(characters, function(chr) { return chr.age; }); * // => { 'name': 'barney', 'age': 36 }; * * // using "_.pluck" callback shorthand * _.min(characters, 'age'); * // => { 'name': 'barney', 'age': 36 }; */ function min(collection, callback, thisArg) { var computed = Infinity, result = computed, type = typeof callback; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[callback] === collection) { callback = null; } if (callback == null && isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; if (value < result) { result = value; } } } else { callback = (callback == null && isString(collection)) ? charAtCallback : lodash.createCallback(callback, thisArg, 3); baseEach(collection, function(value, index, collection) { var current = callback(value, index, collection); if (current < computed) { computed = current; result = value; } }); } return result; } /** * Creates an array of elements split into two groups, the first of which * contains elements the predicate returns truthy for, while the second of which * contains elements the predicate returns falsey for. The predicate is bound * to `thisArg` and invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns a new array of grouped elements. * @example * * _.partition([1, 2, 3], function(num) { return num % 2; }); * // => [[1, 3], [2]] * * _.partition([1.2, 2.3, 3.4], function(num) { return this.floor(num) % 2; }, Math); * // => [[1, 3], [2]] * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40, 'blocked': true }, * { 'name': 'pebbles', 'age': 1 } * ]; * * // using "_.where" callback shorthand * _.map(_.partition(characters, { 'age': 1 }), function(array) { return _.pluck(array, 'name'); }); * // => [['pebbles'], ['barney', 'fred']] * * // using "_.pluck" callback shorthand * _.map(_.partition(characters, 'blocked'), function(array) { return _.pluck(array, 'name'); }); * // => [['fred'], ['barney', 'pebbles']] */ var partition = createAggregator(function(result, value, key) { result[key ? 0 : 1].push(value); }, true); /** * Retrieves the value of a specified property from all elements in the collection. * * @static * @memberOf _ * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {string} key The name of the property to pluck. * @returns {Array} Returns a new array of property values. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * _.pluck(characters, 'name'); * // => ['barney', 'fred'] */ var pluck = map; /** * Reduces a collection to a value which is the accumulated result of running * each element in the collection through the callback, where each successive * callback execution consumes the return value of the previous execution. If * `accumulator` is not provided the first element of the collection will be * used as the initial `accumulator` value. The callback is bound to `thisArg` * and invoked with four arguments; (accumulator, value, index|key, collection). * * @static * @memberOf _ * @alias foldl, inject * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [accumulator] Initial value of the accumulator. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the accumulated value. * @example * * var sum = _.reduce([1, 2, 3], function(sum, num) { * return sum + num; * }); * // => 6 * * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { * result[key] = num * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } */ function reduce(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; callback = lodash.createCallback(callback, thisArg, 4); if (isArray(collection)) { var index = -1, length = collection.length; if (noaccum && length) { accumulator = collection[++index]; } while (++index < length) { accumulator = callback(accumulator, collection[index], index, collection); } } else { baseEach(collection, function(value, index, collection) { accumulator = noaccum ? (noaccum = false, value) : callback(accumulator, value, index, collection) }); } return accumulator; } /** * This method is like `_.reduce` except that it iterates over elements * of a `collection` from right to left. * * @static * @memberOf _ * @alias foldr * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [accumulator] Initial value of the accumulator. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the accumulated value. * @example * * var list = [[0, 1], [2, 3], [4, 5]]; * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); * // => [4, 5, 2, 3, 0, 1] */ function reduceRight(collection, callback, accumulator, thisArg) { var noaccum = arguments.length < 3; callback = lodash.createCallback(callback, thisArg, 4); baseEachRight(collection, function(value, index, collection) { accumulator = noaccum ? (noaccum = false, value) : callback(accumulator, value, index, collection); }); return accumulator; } /** * The opposite of `_.filter`; this method returns the elements of a collection * the predicate does **not** return truthy for. * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns a new array of elements that failed the predicate check. * @example * * var odds = _.reject([1, 2, 3, 4], function(num) { return num % 2 == 0; }); * // => [1, 3] * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40, 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.reject(characters, 'blocked'); * // => [{ 'name': 'barney', 'age': 36 }] * * // using "_.where" callback shorthand * _.reject(characters, { 'age': 36 }); * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] */ function reject(collection, predicate, thisArg) { predicate = lodash.createCallback(predicate, thisArg, 3); return filter(collection, function(value, index, collection) { return !predicate(value, index, collection); }); } /** * Retrieves a random element or `n` random elements from a collection. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to sample. * @param {number} [n] The number of elements to sample. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {*} Returns the random sample(s) of `collection`. * @example * * _.sample([1, 2, 3, 4]); * // => 2 * * _.sample([1, 2, 3, 4], 2); * // => [3, 1] */ function sample(collection, n, guard) { if (collection && typeof collection.length != 'number') { collection = values(collection); } else if (support.unindexedChars && isString(collection)) { collection = collection.split(''); } if (n == null || guard) { return collection ? collection[baseRandom(0, collection.length - 1)] : undefined; } var result = shuffle(collection); result.length = nativeMin(nativeMax(0, n), result.length); return result; } /** * Creates an array of shuffled values, using a version of the Fisher-Yates * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) * for more details. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to shuffle. * @returns {Array} Returns a new shuffled collection. * @example * * _.shuffle([1, 2, 3, 4]); * // => [4, 1, 3, 2] */ function shuffle(collection) { var index = -1, length = collection ? collection.length : 0, result = Array(typeof length == 'number' ? length : 0); baseEach(collection, function(value) { var rand = baseRandom(0, ++index); result[index] = result[rand]; result[rand] = value; }); return result; } /** * Gets the size of the `collection` by returning `collection.length` for arrays * and array-like objects or the number of own enumerable properties for objects. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to inspect. * @returns {number} Returns `collection.length` or number of own enumerable properties. * @example * * _.size([1, 2]); * // => 2 * * _.size({ 'one': 1, 'two': 2, 'three': 3 }); * // => 3 * * _.size('pebbles'); * // => 7 */ function size(collection) { var length = collection ? collection.length : 0; return typeof length == 'number' ? length : keys(collection).length; } /** * Checks if the predicate returns truthy for **any** element of a collection. * The function returns as soon as it finds a passing value and does not iterate * over the entire collection. The predicate is bound to `thisArg` and invoked * with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @alias any * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if any element passed the predicate check, * else `false`. * @example * * _.some([null, 0, 'yes', false], Boolean); * // => true * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40, 'blocked': true } * ]; * * // using "_.pluck" callback shorthand * _.some(characters, 'blocked'); * // => true * * // using "_.where" callback shorthand * _.some(characters, { 'age': 1 }); * // => false */ function some(collection, predicate, thisArg) { var result; predicate = lodash.createCallback(predicate, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { if (predicate(collection[index], index, collection)) { return true; } } } else { baseEach(collection, function(value, index, collection) { return !(result = predicate(value, index, collection)); }); } return !!result; } /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through the callback. This method * performs a stable sort, that is, it will preserve the original sort order * of equal elements. The callback is bound to `thisArg` and invoked with * three arguments; (value, index|key, collection). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an array of property names is provided for `callback` the collection * will be sorted by each property value. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [callback=identity] The function * called per iteration. If a property name or object is provided it will * be used to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns a new array of sorted elements. * @example * * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); * // => [3, 1, 2] * * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); * // => [3, 1, 2] * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 }, * { 'name': 'barney', 'age': 26 }, * { 'name': 'fred', 'age': 30 } * ]; * * // using "_.pluck" callback shorthand * _.map(_.sortBy(characters, 'age'), _.values); * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]] * * // sorting by multiple properties * _.map(_.sortBy(characters, ['name', 'age']), _.values); * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ function sortBy(collection, callback, thisArg) { var index = -1, multi = callback && isArray(callback), length = collection ? collection.length : 0, result = Array(typeof length == 'number' ? length : 0); if (!multi) { callback = lodash.createCallback(callback, thisArg, 3); } baseEach(collection, function(value, key, collection) { if (multi) { var length = callback.length, criteria = Array(length); while (length--) { criteria[length] = value[callback[length]]; } } else { criteria = callback(value, key, collection); } result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; }); length = result.length; result.sort(multi ? compareMultipleAscending : compareAscending); while (length--) { result[length] = result[length].value; } return result; } /** * Converts the `collection` to an array. * * @static * @memberOf _ * @category Collections * @param {Array|Object|string} collection The collection to convert. * @returns {Array} Returns the new converted array. * @example * * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); * // => [2, 3, 4] */ function toArray(collection) { if (collection && typeof collection.length == 'number') { return (support.unindexedChars && isString(collection)) ? collection.split('') : slice(collection); } return values(collection); } /** * Performs a deep comparison between each element in `collection` and the * `source` object, returning an array of all elements that have equivalent * property values. * * @static * @memberOf _ * @type Function * @category Collections * @param {Array|Object|string} collection The collection to iterate over. * @param {Object} source The object of property values to filter by. * @returns {Array} Returns a new array of elements that have the given properties. * @example * * var characters = [ * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }, * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } * ]; * * _.where(characters, { 'age': 36 }); * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }] * * _.where(characters, { 'pets': ['dino'] }); * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }] */ var where = filter; /*--------------------------------------------------------------------------*/ /** * Creates a function that executes `func`, with the `this` binding and * arguments of the created function, only after being called `n` times. * * @static * @memberOf _ * @category Functions * @param {number} n The number of times the function must be called before * `func` is executed. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var saves = ['profile', 'settings']; * * var done = _.after(saves.length, function() { * console.log('Done saving!'); * }); * * _.forEach(saves, function(type) { * asyncSave({ 'type': type, 'complete': done }); * }); * // => logs 'Done saving!', after all saves have completed */ function after(n, func) { if (!isFunction(func)) { throw new TypeError; } return function() { if (--n < 1) { return func.apply(this, arguments); } }; } /** * Creates a function that, when called, invokes `func` with the `this` * binding of `thisArg` and prepends any additional `bind` arguments to those * provided to the bound function. * * Note: Unlike native `Function#bind` this method does not set the `length` * property of bound functions. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to bind. * @param {*} [thisArg] The `this` binding of `func`. * @param {...*} [args] Arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var func = function(greeting) { * return greeting + ' ' + this.name; * }; * * func = _.bind(func, { 'name': 'fred' }, 'hi'); * func(); * // => 'hi fred' */ function bind(func, thisArg) { if (arguments.length < 3) { return createWrapper(func, BIND_FLAG, null, thisArg); } if (func) { var arity = func[expando] ? func[expando][2] : func.length, partialArgs = slice(arguments, 2); arity -= partialArgs.length; } return createWrapper(func, BIND_FLAG | PARTIAL_FLAG, arity, thisArg, partialArgs); } /** * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays * of method names. If no method names are provided all the function properties * of `object` will be bound. * * Note: This method does not set the `length` property of bound functions. * * @static * @memberOf _ * @category Functions * @param {Object} object The object to bind and assign the bound methods to. * @param {...string} [methodName] The object method names to * bind, specified as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * * var view = { * 'label': 'docs', * 'onClick': function() { console.log('clicked ' + this.label); } * }; * * _.bindAll(view); * jQuery('#docs').on('click', view.onClick); * // => logs 'clicked docs', when the button is clicked */ function bindAll(object) { var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object), index = -1, length = funcs.length; while (++index < length) { var key = funcs[index]; object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } /** * Creates a function that, when called, invokes the method at `object[key]` * and prepends any additional `bindKey` arguments to those provided to the bound * function. This method differs from `_.bind` by allowing bound functions to * reference methods that will be redefined or don't yet exist. * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) * for more details. * * @static * @memberOf _ * @category Functions * @param {Object} object The object the method belongs to. * @param {string} key The key of the method. * @param {...*} [args] Arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var object = { * 'name': 'fred', * 'greet': function(greeting) { * return greeting + ' ' + this.name; * } * }; * * var func = _.bindKey(object, 'greet', 'hi'); * func(); * // => 'hi fred' * * object.greet = function(greeting) { * return greeting + 'ya ' + this.name + '!'; * }; * * func(); * // => 'hiya fred!' */ function bindKey(object, key) { return arguments.length < 3 ? createWrapper(key, BIND_FLAG | BIND_KEY_FLAG, null, object) : createWrapper(key, BIND_FLAG | BIND_KEY_FLAG | PARTIAL_FLAG, null, object, slice(arguments, 2)); } /** * Creates a function that is the composition of the provided functions, * where each function consumes the return value of the function that follows. * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. * Each function is executed with the `this` binding of the composed function. * * @static * @memberOf _ * @category Functions * @param {...Function} [func] Functions to compose. * @returns {Function} Returns the new composed function. * @example * * var realNameMap = { * 'pebbles': 'penelope' * }; * * var format = function(name) { * name = realNameMap[name.toLowerCase()] || name; * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); * }; * * var greet = function(formatted) { * return 'Hiya ' + formatted + '!'; * }; * * var welcome = _.compose(greet, format); * welcome('pebbles'); * // => 'Hiya Penelope!' */ function compose() { var funcs = arguments, funcsLength = funcs.length, length = funcsLength; while (length--) { if (!isFunction(funcs[length])) { throw new TypeError; } } return function() { var length = funcsLength - 1, result = funcs[length].apply(this, arguments); while (length--) { result = funcs[length].call(this, result); } return result; }; } /** * Creates a function which accepts one or more arguments of `func` that when * invoked either executes `func` returning its result, if all `func` arguments * have been provided, or returns a function that accepts one or more of the * remaining `func` arguments, and so on. The arity of `func` can be specified * if `func.length` is not sufficient. * * Note: This method does not set the `length` property of curried functions. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. * @returns {Function} Returns the new curried function. * @example * * var curried = _.curry(function(a, b, c) { * console.log(a + b + c); * }); * * curried(1)(2)(3); * // => 6 * * curried(1, 2)(3); * // => 6 * * curried(1, 2, 3); * // => 6 */ function curry(func, arity) { if (typeof arity != 'number') { arity = +arity || (func ? func.length : 0); } return createWrapper(func, CURRY_FLAG, arity); } /** * Creates a function that will delay the execution of `func` until after * `wait` milliseconds have elapsed since the last time it was invoked. * Provide an options object to indicate that `func` should be invoked on * the leading and/or trailing edge of the `wait` timeout. Subsequent calls * to the debounced function will return the result of the last `func` call. * * Note: If `leading` and `trailing` options are `true` `func` will be called * on the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called. * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * * // avoid costly calculations while the window size is in flux * var lazyLayout = _.debounce(calculateLayout, 150); * jQuery(window).on('resize', lazyLayout); * * // execute `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * }); * * // ensure `batchLog` is executed once after 1 second of debounced calls * var source = new EventSource('/stream'); * source.addEventListener('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 * }, false); */ function debounce(func, wait, options) { var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; if (!isFunction(func)) { throw new TypeError; } wait = wait > 0 ? wait : 0; if (options === true) { var leading = true; trailing = false; } else if (isObject(options)) { leading = options.leading; maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0); trailing = 'trailing' in options ? options.trailing : trailing; } var delayed = function() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { if (maxTimeoutId) { clearTimeout(maxTimeoutId); } var isCalled = trailingCall; maxTimeoutId = timeoutId = trailingCall = undefined; if (isCalled) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { args = thisArg = null; } } } else { timeoutId = setTimeout(delayed, remaining); } }; var maxDelayed = function() { if (timeoutId) { clearTimeout(timeoutId); } maxTimeoutId = timeoutId = trailingCall = undefined; if (trailing || (maxWait !== wait)) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { args = thisArg = null; } } }; return function() { args = arguments; stamp = now(); thisArg = this; trailingCall = trailing && (timeoutId || !leading); if (maxWait === false) { var leadingCall = leading && !timeoutId; } else { if (!maxTimeoutId && !leading) { lastCalled = stamp; } var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; if (isCalled) { if (maxTimeoutId) { maxTimeoutId = clearTimeout(maxTimeoutId); } lastCalled = stamp; result = func.apply(thisArg, args); } else if (!maxTimeoutId) { maxTimeoutId = setTimeout(maxDelayed, remaining); } } if (isCalled && timeoutId) { timeoutId = clearTimeout(timeoutId); } else if (!timeoutId && wait !== maxWait) { timeoutId = setTimeout(delayed, wait); } if (leadingCall) { isCalled = true; result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { args = thisArg = null; } return result; }; } /** * Defers executing the `func` function until the current call stack has cleared. * Additional arguments will be provided to `func` when it is invoked. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to defer. * @param {...*} [args] Arguments to invoke the function with. * @returns {number} Returns the timer id. * @example * * _.defer(function(text) { console.log(text); }, 'deferred'); * // logs 'deferred' after one or more milliseconds */ function defer(func) { if (!isFunction(func)) { throw new TypeError; } var args = slice(arguments, 1); return setTimeout(function() { func.apply(undefined, args); }, 1); } /** * Executes the `func` function after `wait` milliseconds. Additional arguments * will be provided to `func` when it is invoked. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay execution. * @param {...*} [args] Arguments to invoke the function with. * @returns {number} Returns the timer id. * @example * * _.delay(function(text) { console.log(text); }, 1000, 'later'); * // => logs 'later' after one second */ function delay(func, wait) { if (!isFunction(func)) { throw new TypeError; } var args = slice(arguments, 2); return setTimeout(function() { func.apply(undefined, args); }, wait); } /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided it will be used to determine the cache key for storing the result * based on the arguments provided to the memoized function. By default, the * first argument provided to the memoized function is used as the cache key. * The `func` is executed with the `this` binding of the memoized function. * The result cache is exposed as the `cache` property on the memoized function. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to have its output memoized. * @param {Function} [resolver] A function used to resolve the cache key. * @returns {Function} Returns the new memoizing function. * @example * * var fibonacci = _.memoize(function(n) { * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); * }); * * fibonacci(9) * // => 34 * * var data = { * 'fred': { 'name': 'fred', 'age': 40 }, * 'pebbles': { 'name': 'pebbles', 'age': 1 } * }; * * // modifying the result cache * var get = _.memoize(function(name) { return data[name]; }, _.identity); * get('pebbles'); * // => { 'name': 'pebbles', 'age': 1 } * * get.cache.pebbles.name = 'penelope'; * get('pebbles'); * // => { 'name': 'penelope', 'age': 1 } */ function memoize(func, resolver) { if (!isFunction(func)) { throw new TypeError; } var memoized = function() { var cache = memoized.cache, key = resolver ? resolver.apply(this, arguments) : '_' + arguments[0]; return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments)); } memoized.cache = {}; return memoized; } /** * Creates a function that is restricted to execute `func` once. Repeat calls to * the function will return the value of the first call. The `func` is executed * with the `this` binding of the created function. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var initialize = _.once(createApplication); * initialize(); * initialize(); * // `initialize` executes `createApplication` once */ function once(func) { var ran, result; if (!isFunction(func)) { throw new TypeError; } return function() { if (ran) { return result; } ran = true; result = func.apply(this, arguments); // clear the `func` variable so the function may be garbage collected func = null; return result; }; } /** * Creates a function that, when called, invokes `func` with any additional * `partial` arguments prepended to those provided to the new function. This * method is similar to `_.bind` except it does **not** alter the `this` binding. * * Note: This method does not set the `length` property of partially applied * functions. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to partially apply arguments to. * @param {...*} [args] Arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { return greeting + ' ' + name; }; * var hi = _.partial(greet, 'hi'); * hi('fred'); * // => 'hi fred' */ function partial(func) { if (func) { var arity = func[expando] ? func[expando][2] : func.length, partialArgs = slice(arguments, 1); arity -= partialArgs.length; } return createWrapper(func, PARTIAL_FLAG, arity, null, partialArgs); } /** * This method is like `_.partial` except that partially applied arguments * are appended to those provided to the new function. * * Note: This method does not set the `length` property of partially applied * functions. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to partially apply arguments to. * @param {...*} [args] Arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var defaultsDeep = _.partialRight(_.merge, _.defaults); * * var options = { * 'variable': 'data', * 'imports': { 'jq': $ } * }; * * defaultsDeep(options, _.templateSettings); * * options.variable * // => 'data' * * options.imports * // => { '_': _, 'jq': $ } */ function partialRight(func) { if (func) { var arity = func[expando] ? func[expando][2] : func.length, partialRightArgs = slice(arguments, 1); arity -= partialRightArgs.length; } return createWrapper(func, PARTIAL_RIGHT_FLAG, arity, null, null, partialRightArgs); } /** * Creates a function that, when executed, will only call the `func` function * at most once per every `wait` milliseconds. Provide an options object to * indicate that `func` should be invoked on the leading and/or trailing edge * of the `wait` timeout. Subsequent calls to the throttled function will * return the result of the last `func` call. * * Note: If `leading` and `trailing` options are `true` `func` will be called * on the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * * @static * @memberOf _ * @category Functions * @param {Function} func The function to throttle. * @param {number} wait The number of milliseconds to throttle executions to. * @param {Object} [options] The options object. * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout. * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. * @returns {Function} Returns the new throttled function. * @example * * // avoid excessively updating the position while scrolling * var throttled = _.throttle(updatePosition, 100); * jQuery(window).on('scroll', throttled); * * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { * 'trailing': false * })); */ function throttle(func, wait, options) { var leading = true, trailing = true; if (!isFunction(func)) { throw new TypeError; } if (options === false) { leading = false; } else if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } debounceOptions.leading = leading; debounceOptions.maxWait = +wait; debounceOptions.trailing = trailing; return debounce(func, wait, debounceOptions); } /** * Creates a function that provides `value` to the wrapper function as its * first argument. Additional arguments provided to the function are appended * to those provided to the wrapper function. The wrapper is executed with * the `this` binding of the created function. * * @static * @memberOf _ * @category Functions * @param {*} value The value to wrap. * @param {Function} wrapper The wrapper function. * @returns {Function} Returns the new function. * @example * * var p = _.wrap(_.escape, function(func, text) { * return '<p>' + func(text) + '</p>'; * }); * * p('fred, barney, & pebbles'); * // => '<p>fred, barney, & pebbles</p>' */ function wrap(value, wrapper) { return createWrapper(wrapper, PARTIAL_FLAG, null, null, [value]); } /*--------------------------------------------------------------------------*/ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources will overwrite property assignments of previous * sources. If a callback is provided it will be executed to produce the * assigned values. The callback is bound to `thisArg` and invoked with two * arguments; (objectValue, sourceValue). * * @static * @memberOf _ * @alias extend * @category Objects * @param {Object} object The destination object. * @param {...Object} [source] The source objects. * @param {Function} [callback] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. * @example * * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); * // => { 'name': 'fred', 'employer': 'slate' } * * var defaults = _.partialRight(_.assign, function(a, b) { * return typeof a == 'undefined' ? b : a; * }); * * defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ function assign(object, source, guard) { var args = arguments, argsIndex = 0, argsLength = args.length, type = typeof guard; // enables use as a callback for functions like `_.reduce` if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) { argsLength = 2; } // juggle arguments if (argsLength > 3 && typeof args[argsLength - 2] == 'function') { var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2); } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') { callback = args[--argsLength]; } while (++argsIndex < argsLength) { source = args[argsIndex]; if (isObject(source)) { var index = -1, props = keys(source), length = props.length; while (++index < length) { var key = props[index]; object[key] = callback ? callback(object[key], source[key]) : source[key]; } } } return object; } /** * Creates a clone of `value`. If `isDeep` is `true` nested objects will also * be cloned, otherwise they will be assigned by reference. If a callback * is provided it will be executed to produce the cloned values. If the * callback returns `undefined` cloning will be handled by the method instead. * The callback is bound to `thisArg` and invoked with one argument; (value). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) * for more details. * * @static * @memberOf _ * @category Objects * @param {*} value The value to clone. * @param {boolean} [isDeep=false] Specify a deep clone. * @param {Function} [callback] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the cloned value. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * var shallow = _.clone(characters); * shallow[0] === characters[0]; * // => true * * var deep = _.clone(characters, true); * deep[0] === characters[0]; * // => false * * _.mixin({ * 'clone': _.partialRight(_.clone, function(value) { * return _.isElement(value) ? value.cloneNode(false) : undefined; * }) * }); * * var clone = _.clone(document.body); * clone.childNodes.length; * // => 0 */ function clone(value, isDeep, callback, thisArg) { var type = typeof isDeep; // juggle arguments if (type != 'boolean' && isDeep != null) { thisArg = callback; callback = isDeep; isDeep = false; // enables use as a callback for functions like `_.map` if ((type == 'number' || type == 'string') && thisArg && thisArg[callback] === value) { callback = null; } } callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1); return baseClone(value, isDeep, callback); } /** * Creates a deep clone of `value`. If a callback is provided it will be * executed to produce the cloned values. If the callback returns `undefined` * cloning will be handled by the method instead. The callback is bound to * `thisArg` and invoked with one argument; (value). * * Note: This method is loosely based on the structured clone algorithm. Functions * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and * objects created by constructors other than `Object` are cloned to plain `Object` objects. * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) * for more details. * * @static * @memberOf _ * @category Objects * @param {*} value The value to deep clone. * @param {Function} [callback] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the deep cloned value. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * var deep = _.cloneDeep(characters); * deep[0] === characters[0]; * // => false * * var view = { * 'label': 'docs', * 'node': element * }; * * var clone = _.cloneDeep(view, function(value) { * return _.isElement(value) ? value.cloneNode(true) : undefined; * }); * * clone.node == view.node; * // => false */ function cloneDeep(value, callback, thisArg) { callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1); return baseClone(value, true, callback); } /** * Creates an object that inherits from the given `prototype` object. If a * `properties` object is provided its own enumerable properties are assigned * to the created object. * * @static * @memberOf _ * @category Objects * @param {Object} prototype The object to inherit from. * @param {Object} [properties] The properties to assign to the object. * @returns {Object} Returns the new object. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * function Circle() { * Shape.call(this); * } * * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); * * var circle = new Circle; * circle instanceof Circle; * // => true * * circle instanceof Shape; * // => true */ function create(prototype, properties) { var result = baseCreate(prototype); return properties ? assign(result, properties) : result; } /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property will be ignored. * * @static * @memberOf _ * @category Objects * @param {Object} object The destination object. * @param {...Object} [source] The source objects. * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. * @returns {Object} Returns the destination object. * @example * * _.defaults({ 'name': 'barney' }, { 'name': 'fred', 'employer': 'slate' }); * // => { 'name': 'barney', 'employer': 'slate' } */ function defaults(object, source, guard) { var args = arguments, argsIndex = 0, argsLength = args.length, type = typeof guard; // enables use as a callback for functions like `_.reduce` if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) { argsLength = 2; } while (++argsIndex < argsLength) { source = args[argsIndex]; if (isObject(source)) { var index = -1, props = keys(source), length = props.length; while (++index < length) { var key = props[index]; if (typeof object[key] == 'undefined') { object[key] = source[key]; } } } } return object; } /** * This method is like `_.findIndex` except that it returns the key of the * first element the predicate returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the found element, else `undefined`. * @example * * var characters = { * 'barney': { 'age': 36 }, * 'fred': { 'age': 40, 'blocked': true }, * 'pebbles': { 'age': 1 } * }; * * _.findKey(characters, function(chr) { * return chr.age < 40; * }); * // => 'barney' (property order is not guaranteed across environments) * * // using "_.where" callback shorthand * _.findKey(characters, { 'age': 1 }); * // => 'pebbles' * * // using "_.pluck" callback shorthand * _.findKey(characters, 'blocked'); * // => 'fred' */ function findKey(object, predicate, thisArg) { var result; predicate = lodash.createCallback(predicate, thisArg, 3); baseForOwn(object, function(value, key, object) { if (predicate(value, key, object)) { result = key; return false; } }); return result; } /** * This method is like `_.findKey` except that it iterates over elements * of a `collection` in the opposite order. * * If a property name is provided for `predicate` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `predicate` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the found element, else `undefined`. * @example * * var characters = { * 'barney': { 'age': 36, 'blocked': true }, * 'fred': { 'age': 40 }, * 'pebbles': { 'age': 1, 'blocked': true } * }; * * _.findLastKey(characters, function(chr) { * return chr.age < 40; * }); * // => returns `pebbles`, assuming `_.findKey` returns `barney` * * // using "_.where" callback shorthand * _.findLastKey(characters, { 'age': 40 }); * // => 'fred' * * // using "_.pluck" callback shorthand * _.findLastKey(characters, 'blocked'); * // => 'pebbles' */ function findLastKey(object, predicate, thisArg) { var result; predicate = lodash.createCallback(predicate, thisArg, 3); baseForOwnRight(object, function(value, key, object) { if (predicate(value, key, object)) { result = key; return false; } }); return result; } /** * Iterates over own and inherited enumerable properties of an object, * executing the callback for each property. The callback is bound to `thisArg` * and invoked with three arguments; (value, key, object). Callbacks may exit * iteration early by explicitly returning `false`. * * @static * @memberOf _ * @type Function * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns `object`. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * Shape.prototype.move = function(x, y) { * this.x += x; * this.y += y; * }; * * _.forIn(new Shape, function(value, key) { * console.log(key); * }); * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) */ function forIn(object, callback, thisArg) { callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); return baseForIn(object, callback); } /** * This method is like `_.forIn` except that it iterates over elements * of a `collection` in the opposite order. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns `object`. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * Shape.prototype.move = function(x, y) { * this.x += x; * this.y += y; * }; * * _.forInRight(new Shape, function(value, key) { * console.log(key); * }); * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move' */ function forInRight(object, callback, thisArg) { var pairs = []; baseForIn(object, function(value, key) { pairs.push(key, value); }); var length = pairs.length; callback = baseCreateCallback(callback, thisArg, 3); while (length--) { if (callback(pairs[length--], pairs[length], object) === false) { break; } } return object; } /** * Iterates over own enumerable properties of an object, executing the callback * for each property. The callback is bound to `thisArg` and invoked with three * arguments; (value, key, object). Callbacks may exit iteration early by * explicitly returning `false`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns `object`. * @example * * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { * console.log(key); * }); * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) */ function forOwn(object, callback, thisArg) { callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); return baseForOwn(object, callback); } /** * This method is like `_.forOwn` except that it iterates over elements * of a `collection` in the opposite order. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns `object`. * @example * * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { * console.log(key); * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ function forOwnRight(object, callback, thisArg) { var props = keys(object), length = props.length; callback = baseCreateCallback(callback, thisArg, 3); while (length--) { var key = props[length]; if (callback(object[key], key, object) === false) { break; } } return object; } /** * Creates a sorted array of property names of all enumerable properties, * own and inherited, of `object` that have function values. * * @static * @memberOf _ * @alias methods * @category Objects * @param {Object} object The object to inspect. * @returns {Array} Returns an array of property names that have function values. * @example * * _.functions(_); * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] */ function functions(object) { var result = []; baseForIn(object, function(value, key) { if (isFunction(value)) { result.push(key); } }); return result.sort(); } /** * Checks if the specified property name exists as a direct property of `object`, * instead of an inherited property. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to inspect. * @param {string} key The name of the property to check. * @returns {boolean} Returns `true` if key is a direct property, else `false`. * @example * * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); * // => true */ function has(object, key) { return object ? hasOwnProperty.call(object, key) : false; } /** * Creates an object composed of the inverted keys and values of the given * object. If the given object contains duplicate values, subsequent values * will overwrite property assignments of previous values unless `multiValue` * is `true`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to invert. * @param {boolean} [multiValue=false] Allow multiple values per key. * @returns {Object} Returns the created inverted object. * @example * * _.invert({ 'first': 'fred', 'second': 'barney' }); * // => { 'fred': 'first', 'barney': 'second' } * * // without `multiValue` * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }); * // => { 'fred': 'third', 'barney': 'second' } * * // with `multiValue` * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); * // => { 'fred': ['first', 'third'], 'barney': ['second'] } */ function invert(object, multiValue) { var index = -1, props = keys(object), length = props.length, result = {}; while (++index < length) { var key = props[index], value = object[key]; if (multiValue) { if (hasOwnProperty.call(result, value)) { result[value].push(key); } else { result[value] = [key]; } } else { result[value] = key; } } return result; } /** * Checks if `value` is an array. * * @static * @memberOf _ * @type Function * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is an array, else `false`. * @example * * (function() { return _.isArray(arguments); })(); * // => false * * _.isArray([1, 2, 3]); * // => true */ var isArray = nativeIsArray || function(value) { return value && typeof value == 'object' && typeof value.length == 'number' && toString.call(value) == arrayClass || false; }; /** * Checks if `value` is a boolean value. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`. * @example * * _.isBoolean(null); * // => false */ function isBoolean(value) { return value === true || value === false || value && typeof value == 'object' && toString.call(value) == boolClass || false; } /** * Checks if `value` is a date. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a date, else `false`. * @example * * _.isDate(new Date); * // => true */ function isDate(value) { return value && typeof value == 'object' && toString.call(value) == dateClass || false; } /** * Checks if `value` is a DOM element. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); * // => true */ function isElement(value) { return value && typeof value == 'object' && value.nodeType === 1 && (support.nodeClass ? toString.call(value).indexOf('Element') > -1 : isNode(value)) || false; } // fallback for environments without DOM support if (!support.dom) { isElement = function(value) { return value && typeof value == 'object' && value.nodeType === 1 && !isPlainObject(value) || false; }; } /** * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a * length of `0` and objects with no own enumerable properties are considered * "empty". * * @static * @memberOf _ * @category Objects * @param {Array|Object|string} value The value to inspect. * @returns {boolean} Returns `true` if the `value` is empty, else `false`. * @example * * _.isEmpty([1, 2, 3]); * // => false * * _.isEmpty({}); * // => true * * _.isEmpty(''); * // => true */ function isEmpty(value) { var result = true; if (!value) { return result; } var className = toString.call(value), length = value.length; if ((className == arrayClass || className == stringClass || (support.argsClass ? className == argsClass : isArguments(value))) || (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { return !length; } baseForOwn(value, function() { return (result = false); }); return result; } /** * Performs a deep comparison between two values to determine if they are * equivalent to each other. If a callback is provided it will be executed * to compare values. If the callback returns `undefined` comparisons will * be handled by the method instead. The callback is bound to `thisArg` and * invoked with two arguments; (a, b). * * @static * @memberOf _ * @category Objects * @param {*} a The value to compare. * @param {*} b The other value to compare. * @param {Function} [callback] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'name': 'fred' }; * var copy = { 'name': 'fred' }; * * object == copy; * // => false * * _.isEqual(object, copy); * // => true * * var words = ['hello', 'goodbye']; * var otherWords = ['hi', 'goodbye']; * * _.isEqual(words, otherWords, function(a, b) { * var reGreet = /^(?:hello|hi)$/i, * aGreet = _.isString(a) && reGreet.test(a), * bGreet = _.isString(b) && reGreet.test(b); * * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; * }); * // => true */ function isEqual(a, b, callback, thisArg) { callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2); if (!callback) { // exit early for identical values if (a === b) { // treat `-0` vs. `+0` as not equal return a !== 0 || (1 / a == 1 / b); } var type = typeof a, otherType = typeof b; // exit early for unlike primitive values if (a === a && (a == null || b == null || (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { return false; } } return baseIsEqual(a, b, callback); } /** * Checks if `value` is, or can be coerced to, a finite number. * * Note: This method is not the same as native `isFinite` which will return * `true` for booleans and empty strings. See the [ES5 spec](http://es5.github.io/#x15.1.2.5) * for more details. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is finite, else `false`. * @example * * _.isFinite(-101); * // => true * * _.isFinite('10'); * // => true * * _.isFinite(true); * // => false * * _.isFinite(''); * // => false * * _.isFinite(Infinity); * // => false */ function isFinite(value) { return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); } /** * Checks if `value` is a function. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a function, else `false`. * @example * * _.isFunction(_); * // => true */ function isFunction(value) { return typeof value == 'function'; } // fallback for older versions of Chrome and Safari if (isFunction(/x/)) { isFunction = function(value) { return typeof value == 'function' && toString.call(value) == funcClass; }; } /** * Checks if `value` is the language type of Object. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(1); * // => false */ function isObject(value) { // check if the value is the ECMAScript language type of Object // http://es5.github.io/#x8 // and avoid a V8 bug // https://code.google.com/p/v8/issues/detail?id=2291 var type = typeof value; return value && (type == 'function' || type == 'object') || false; } /** * Checks if `value` is `NaN`. * * Note: This method is not the same as native `isNaN` which will return `true` * for `undefined` and other non-numeric values. See the [ES5 spec](http://es5.github.io/#x15.1.2.4) * for more details. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`. * @example * * _.isNaN(NaN); * // => true * * _.isNaN(new Number(NaN)); * // => true * * isNaN(undefined); * // => true * * _.isNaN(undefined); * // => false */ function isNaN(value) { // `NaN` as a primitive is the only value that is not equal to itself // (perform the [[Class]] check first to avoid errors with some host objects in IE) return isNumber(value) && value != +value; } /** * Checks if `value` is `null`. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is `null`, else `false`. * @example * * _.isNull(null); * // => true * * _.isNull(undefined); * // => false */ function isNull(value) { return value === null; } /** * Checks if `value` is a number. * * Note: `NaN` is considered a number. See the [ES5 spec](http://es5.github.io/#x8.5) * for more details. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a number, else `false`. * @example * * _.isNumber(8.4 * 5); * // => true */ function isNumber(value) { var type = typeof value; return type == 'number' || value && type == 'object' && toString.call(value) == numberClass || false; } /** * Checks if `value` is an object created by the `Object` constructor. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * _.isPlainObject(new Shape); * // => false * * _.isPlainObject([1, 2, 3]); * // => false * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true */ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) { return false; } var valueOf = value.valueOf, objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); return objProto ? (value == objProto || getPrototypeOf(value) == objProto) : shimIsPlainObject(value); }; /** * Checks if `value` is a regular expression. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`. * @example * * _.isRegExp(/fred/); * // => true */ function isRegExp(value) { var type = typeof value; return value && (type == 'function' || type == 'object') && toString.call(value) == regexpClass || false; } /** * Checks if `value` is a string. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is a string, else `false`. * @example * * _.isString('fred'); * // => true */ function isString(value) { return typeof value == 'string' || value && typeof value == 'object' && toString.call(value) == stringClass || false; } /** * Checks if `value` is `undefined`. * * @static * @memberOf _ * @category Objects * @param {*} value The value to check. * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`. * @example * * _.isUndefined(void 0); * // => true */ function isUndefined(value) { return typeof value == 'undefined'; } /** * Creates an array composed of the own enumerable property names of `object`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to inspect. * @returns {Array} Returns an array of property names. * @example * * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) */ var keys = !nativeKeys ? shimKeys : function(object) { if (!isObject(object)) { return []; } if ((support.enumPrototypes && typeof object == 'function') || (support.nonEnumArgs && object.length && isArguments(object))) { return shimKeys(object); } return nativeKeys(object); }; /** * Creates an object with the same keys as `object` and values generated by * running each own enumerable property of `object` through the callback. * The callback is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * If a property name is provided for `callback` the created "_.pluck" style * callback will return the property value of the given element. * * If an object is provided for `callback` the created "_.where" style callback * will return `true` for elements that have the properties of the given object, * else `false`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to iterate over. * @param {Function|Object|string} [callback=identity] The function called * per iteration. If a property name or object is provided it will be used * to create a "_.pluck" or "_.where" style callback, respectively. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns a new object with values of the results of each `callback` execution. * @example * * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); * // => { 'a': 3, 'b': 6, 'c': 9 } * * var characters = { * 'fred': { 'name': 'fred', 'age': 40 }, * 'pebbles': { 'name': 'pebbles', 'age': 1 } * }; * * // using "_.pluck" callback shorthand * _.mapValues(characters, 'age'); * // => { 'fred': 40, 'pebbles': 1 } */ function mapValues(object, callback, thisArg) { var result = {}; callback = lodash.createCallback(callback, thisArg, 3); baseForOwn(object, function(value, key, object) { result[key] = callback(value, key, object); }); return result; } /** * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources * will overwrite property assignments of previous sources. If a callback is * provided it will be executed to produce the merged values of the destination * and source properties. If the callback returns `undefined` merging will * be handled by the method instead. The callback is bound to `thisArg` and * invoked with two arguments; (objectValue, sourceValue). * * @static * @memberOf _ * @category Objects * @param {Object} object The destination object. * @param {...Object} [source] The source objects. * @param {Function} [callback] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Object} Returns the destination object. * @example * * var names = { * 'characters': [ * { 'name': 'barney' }, * { 'name': 'fred' } * ] * }; * * var ages = { * 'characters': [ * { 'age': 36 }, * { 'age': 40 } * ] * }; * * _.merge(names, ages); * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } * * var food = { * 'fruits': ['apple'], * 'vegetables': ['beet'] * }; * * var otherFood = { * 'fruits': ['banana'], * 'vegetables': ['carrot'] * }; * * _.merge(food, otherFood, function(a, b) { * return _.isArray(a) ? a.concat(b) : undefined; * }); * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } */ function merge(object, source, guard) { if (!isObject(object)) { return object; } var args = arguments, length = args.length, type = typeof guard; // enables use as a callback for functions like `_.reduce` if ((type == 'number' || type == 'string') && args[3] && args[3][guard] === source) { length = 2; } // juggle arguments if (length > 3 && typeof args[length - 2] == 'function') { var callback = baseCreateCallback(args[--length - 1], args[length--], 2); } else if (length > 2 && typeof args[length - 1] == 'function') { callback = args[--length]; } var sources = slice(arguments, 1, length), index = -1, stackA = [], stackB = []; while (++index < length) { baseMerge(object, sources[index], callback, stackA, stackB); } return object; } /** * Creates a shallow clone of `object` excluding the specified properties. * Property names may be specified as individual arguments or as arrays of * property names. If a predicate is provided it will be executed for each * property of `object` omitting the properties the predicate returns truthy * for. The predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static * @memberOf _ * @category Objects * @param {Object} object The source object. * @param {Function|...string|string[]} [predicate] The function called per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Object} Returns an object without the omitted properties. * @example * * _.omit({ 'name': 'fred', 'age': 40 }, 'age'); * // => { 'name': 'fred' } * * _.omit({ 'name': 'fred', 'age': 40 }, function(value) { * return typeof value == 'number'; * }); * // => { 'name': 'fred' } */ function omit(object, predicate, thisArg) { var result = {}; if (typeof predicate != 'function') { var omitProps = baseFlatten(arguments, true, false, 1), length = omitProps.length; while (length--) { omitProps[length] = String(omitProps[length]); } var props = []; baseForIn(object, function(value, key) { props.push(key); }); var index = -1; props = baseDifference(props, omitProps); length = props.length; while (++index < length) { var key = props[index]; result[key] = object[key]; } } else { predicate = lodash.createCallback(predicate, thisArg, 3); baseForIn(object, function(value, key, object) { if (!predicate(value, key, object)) { result[key] = value; } }); } return result; } /** * Creates a two dimensional array of a given object's key-value pairs, * i.e. `[[key1, value1], [key2, value2]]`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to inspect. * @returns {Array} Returns new array of key-value pairs. * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) */ function pairs(object) { var index = -1, props = keys(object), length = props.length, result = Array(length); while (++index < length) { var key = props[index]; result[index] = [key, object[key]]; } return result; } /** * Creates a shallow clone of `object` composed of the specified properties. * Property names may be specified as individual arguments or as arrays of * property names. If a predicate is provided it will be executed for each * property of `object` picking the properties the predicate returns truthy * for. The predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static * @memberOf _ * @category Objects * @param {Object} object The source object. * @param {Function|...string|string[]} [predicate] The function called per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Object} Returns an object composed of the picked properties. * @example * * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); * // => { 'name': 'fred' } * * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { * return key.charAt(0) != '_'; * }); * // => { 'name': 'fred' } */ function pick(object, predicate, thisArg) { var result = {}; if (typeof predicate != 'function') { var index = -1, props = baseFlatten(arguments, true, false, 1), length = isObject(object) ? props.length : 0; while (++index < length) { var key = props[index]; if (key in object) { result[key] = object[key]; } } } else { predicate = lodash.createCallback(predicate, thisArg, 3); baseForIn(object, function(value, key, object) { if (predicate(value, key, object)) { result[key] = value; } }); } return result; } /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own * enumerable properties through a callback, with each callback execution * potentially mutating the `accumulator` object. The callback is bound to * `thisArg` and invoked with four arguments; (accumulator, value, key, object). * Callbacks may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ * @category Objects * @param {Array|Object} object The object to iterate over. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [accumulator] The custom accumulator value. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {*} Returns the accumulated value. * @example * * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8], function(result, num) { * num *= num; * if (num % 2) { * return result.push(num) < 3; * } * }); * // => [1, 9, 25] * * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { * result[key] = num * 3; * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ function transform(object, callback, accumulator, thisArg) { var isArr = isArray(object); if (accumulator == null) { if (isArr) { accumulator = []; } else { var ctor = object && object.constructor, proto = ctor && ctor.prototype; accumulator = baseCreate(proto); } } if (callback) { callback = lodash.createCallback(callback, thisArg, 4); (isArr ? baseEach : baseForOwn)(object, function(value, index, object) { return callback(accumulator, value, index, object); }); } return accumulator; } /** * Creates an array composed of the own enumerable property values of `object`. * * @static * @memberOf _ * @category Objects * @param {Object} object The object to inspect. * @returns {Array} Returns an array of property values. * @example * * _.values({ 'one': 1, 'two': 2, 'three': 3 }); * // => [1, 2, 3] (property order is not guaranteed across environments) */ function values(object) { var index = -1, props = keys(object), length = props.length, result = Array(length); while (++index < length) { result[index] = object[props[index]]; } return result; } /*--------------------------------------------------------------------------*/ /** * Converts `string` to camel case. * See [Wikipedia](http://en.wikipedia.org/wiki/CamelCase) for more details. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to camel case. * @returns {string} Returns the camel cased string. * @example * * _.camelCase('Hello world'); * // => 'helloWorld' * * _.camelCase('hello-world'); * // => 'helloWorld' * * _.camelCase('hello_world'); * // => 'helloWorld' */ var camelCase = createCompounder(function(result, word, index) { return result + word.charAt(0)[index ? 'toUpperCase' : 'toLowerCase']() + word.slice(1); }); /** * Capitalizes the first character of `string`. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to capitalize. * @returns {string} Returns the capitalized string. * @example * * _.capitalize('fred'); * // => 'Fred' */ function capitalize(string) { if (string == null) { return ''; } string = String(string); return string.charAt(0).toUpperCase() + string.slice(1); } /** * Checks if `string` ends with a given target string. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=string.length] The position to search from. * @returns {boolean} Returns `true` if the given string ends with the * target string, else `false`. * @example * * _.endsWith('abc', 'c'); * // => true * * _.endsWith('abc', 'b'); * // => false * * _.endsWith('abc', 'b', 2); * // => true */ function endsWith(string, target, position) { string = string == null ? '' : String(string); target = String(target); var length = string.length; position = (typeof position == 'number' ? nativeMin(nativeMax(position, 0), length) : length) - target.length; return position >= 0 && string.indexOf(target, position) == position; } /** * Converts the characters "&", "<", ">", '"', and "'" in `string` to * their corresponding HTML entities. * * Note: No other characters are escaped. To escape additional characters * use a third-party library like [_he_](http://mths.be/he). * * When working with HTML you should always quote attribute values to reduce * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) * for more details. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escape('fred, barney, & pebbles'); * // => 'fred, barney, & pebbles' */ function escape(string) { return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); } /** * Escapes the RegExp special characters "\", "^", "$", ".", "|", "?", "*", * "+", "(", ")", "[", "]", "{" and "}" in `string`. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escapeRegExp('[lodash](http://lodash.com)'); * // => '\[lodash\]\(http://lodash\.com\)' */ function escapeRegExp(string) { return string == null ? '' : String(string).replace(reRegExpChars, '\\$&'); } /** * Converts `string` to kebab case (a.k.a. spinal case). * See [Wikipedia](http://en.wikipedia.org/wiki/Letter_case#Computers) for * more details. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to kebab case. * @returns {string} Returns the kebab cased string. * @example * * _.kebabCase('Hello world'); * // => 'hello-world' * * _.kebabCase('helloWorld'); * // => 'hello-world' * * _.kebabCase('hello_world'); * // => 'hello-world' */ var kebabCase = createCompounder(function(result, word, index) { return result + (index ? '-' : '') + word.toLowerCase(); }); /** * Pads `string` on the left and right sides if it is shorter then the given * padding length. The `chars` string may be truncated if the number of padding * characters can't be evenly divided by the padding length. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.pad('abc', 8); * // => ' abc ' * * _.pad('abc', 8, '_-'); * // => '_-abc_-_' * * _.pad('abc', 3); * // => 'abc' */ function pad(string, length, chars) { string = string == null ? '' : String(string); length = +length || 0; var strLength = string.length; if (strLength >= length) { return string; } var mid = (length - strLength) / 2, leftLength = floor(mid), rightLength = ceil(mid); chars = createPad('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; } /** * Pads `string` on the left side if it is shorter then the given padding * length. The `chars` string may be truncated if the number of padding * characters exceeds the padding length. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padLeft('abc', 6); * // => ' abc' * * _.padLeft('abc', 6, '_-'); * // => '_-_abc' * * _.padLeft('abc', 3); * // => 'abc' */ function padLeft(string, length, chars) { string = string == null ? '' : String(string); return createPad(string, length, chars) + string; } /** * Pads `string` on the right side if it is shorter then the given padding * length. The `chars` string may be truncated if the number of padding * characters exceeds the padding length. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padRight('abc', 6); * // => 'abc ' * * _.padRight('abc', 6, '_-'); * // => 'abc_-_' * * _.padRight('abc', 3); * // => 'abc' */ function padRight(string, length, chars) { string = string == null ? '' : String(string); return string + createPad(string, length, chars); } /** * Repeats the given string `n` times. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to repeat. * @param {number} [n=0] The number of times to repeat the string. * @returns {string} Returns the repeated string. * @example * * _.repeat('*', 3); * // => '***' * * _.repeat('abc', 2); * // => 'abcabc' * * _.repeat('abc', 0); * // => '' */ function repeat(string, n) { var result = ''; n = +n || 0; if (n < 1 || string == null) { return result; } string = String(string); do { if (n % 2) { result += string; } n = floor(n / 2); string += string; } while (n > 0); return result; } /** * Converts `string` to snake case. * See [Wikipedia](http://en.wikipedia.org/wiki/Snake_case) for more details. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to snake case. * @returns {string} Returns the snake cased string. * @example * * _.snakeCase('Hello world'); * // => 'hello_world' * * _.snakeCase('hello-world'); * // => 'hello_world' * * _.snakeCase('helloWorld'); * // => 'hello_world' */ var snakeCase = createCompounder(function(result, word, index) { return result + (index ? '_' : '') + word.toLowerCase(); }); /** * Checks if `string` starts with a given target string. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=0] The position to search from. * @returns {boolean} Returns `true` if the given string starts with the * target string, else `false`. * @example * * _.startsWith('abc', 'a'); * // => true * * _.startsWith('abc', 'b'); * // => false * * _.startsWith('abc', 'b', 1); * // => true */ function startsWith(string, target, position) { string = string == null ? '' : String(string); position = typeof position == 'number' ? nativeMin(nativeMax(position, 0), string.length) : 0; return string.lastIndexOf(target, position) == position; } /** * Creates a compiled template function that can interpolate data properties * in "interpolate" delimiters, HTML-escaped interpolated data properties in * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. If * a data object is provided the interpolated template string will be returned. * Data properties may be accessed as free variables in the template. If a * settings object is provided it will override `_.templateSettings` for the * template. * * Note: In the development build, `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * * For more information on precompiling templates see * [Lo-Dash's custom builds documentation](http://lodash.com/custom-builds). * * For more information on Chrome extension sandboxes see * [Chrome's extensions documentation](http://developer.chrome.com/stable/extensions/sandboxingEval.html). * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The template string. * @param {Object} [data] The data object used to populate the template string. * @param {Object} [options] The options object. * @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter. * @param {Object} [options.imports] An object to import into the template as local variables. * @param {RegExp} [options.interpolate] The "interpolate" delimiter. * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. * @param {string} [options.variable] The data object variable name. * @returns {Function|string} Returns the interpolated string if a data object * is provided, else it returns a template function. * @example * * // using the "interpolate" delimiter to create a compiled template * var compiled = _.template('hello <%= name %>'); * compiled({ 'name': 'fred' }); * // => 'hello fred' * * // using the HTML "escape" delimiter to escape data property values * _.template('<b><%- value %></b>', { 'value': '<script>' }); * // => '<b><script></b>' * * // using the "evaluate" delimiter to execute JavaScript and generate HTML * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>'; * _.template(list, { 'people': ['fred', 'barney'] }); * // => '<li>fred</li><li>barney</li>' * * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter * _.template('hello ${ name }', { 'name': 'pebbles' }); * // => 'hello pebbles' * * // using the internal `print` function in "evaluate" delimiters * _.template('<% print("hello " + name); %>!', { 'name': 'barney' }); * // => 'hello barney!' * * // using a custom template delimiters * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g; * _.template('hello {{ name }}!', { 'name': 'mustache' }); * // => 'hello mustache!' * * // using the `imports` option to import jQuery * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>'; * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } }); * // => '<li>fred</li><li>barney</li>' * * // using the `sourceURL` option to specify a custom sourceURL for the template * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' }); * compiled(data); * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector * * // using the `variable` option to ensure a with-statement isn't used in the compiled template * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' }); * compiled.source; * // => function(data) { * var __t, __p = '', __e = _.escape; * __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!'; * return __p; * } * * // using the `source` property to inline compiled templates for meaningful * // line numbers in error messages and a stack trace * fs.writeFileSync(path.join(cwd, 'jst.js'), '\ * var JST = {\ * "main": ' + _.template(mainText).source + '\ * };\ * '); */ function template(string, data, options) { // based on John Resig's `tmpl` implementation // http://ejohn.org/blog/javascript-micro-templating/ // and Laura Doktorova's doT.js // https://github.com/olado/doT var settings = lodash.templateSettings; string = String(string == null ? '' : string); // avoid missing dependencies when `iteratorTemplate` is not defined options = iteratorTemplate ? defaults({}, options, settings) : settings; var imports = iteratorTemplate && defaults({}, options.imports, settings.imports), importsKeys = iteratorTemplate ? keys(imports) : ['_'], importsValues = iteratorTemplate ? values(imports) : [lodash]; var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; // compile the regexp to match each delimiter var reDelimiters = RegExp( (options.escape || reNoMatch).source + '|' + interpolate.source + '|' + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' + (options.evaluate || reNoMatch).source + '|$' , 'g'); string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { interpolateValue || (interpolateValue = esTemplateValue); // escape characters that cannot be included in string literals source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // replace delimiters with snippets if (escapeValue) { isEscaping = true; source += "' +\n__e(" + escapeValue + ") +\n'"; } if (evaluateValue) { isEvaluating = true; source += "';\n" + evaluateValue + ";\n__p += '"; } if (interpolateValue) { source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; } index = offset + match.length; // the JS engine embedded in Adobe products requires returning the `match` // string in order to produce the correct `offset` value return match; }); source += "';\n"; // if `variable` is not specified, wrap a with-statement around the generated // code to add the data object to the top of the scope chain var variable = options.variable; if (!variable) { source = 'with (obj) {\n' + source + '\n}\n'; } // cleanup code by stripping empty strings source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) .replace(reEmptyStringMiddle, '$1') .replace(reEmptyStringTrailing, '$1;'); // frame code as the function body source = 'function(' + (variable || 'obj') + ') {\n' + (variable ? '' : 'obj || (obj = {});\n' ) + "var __t, __p = ''" + (isEscaping ? ', __e = _.escape' : '' ) + (isEvaluating ? ', __j = Array.prototype.join;\n' + "function print() { __p += __j.call(arguments, '') }\n" : ';\n' ) + source + 'return __p\n}'; // Use a sourceURL for easier debugging. // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/'; try { var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues); } catch(e) { e.source = source; throw e; } if (data) { return result(data); } // provide the compiled function's source by its `toString` method, in // supported environments, or the `source` property as a convenience for // inlining compiled templates during the build process result.source = source; return result; } /** * Removes leading and trailing whitespace or specified characters from `string`. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example * * _.trim(' fred '); * // => 'fred' * * _.trim('-_-fred-_-', '_-'); * // => 'fred' */ var trim = !nativeTrim ? shimTrim : function(string, chars) { if (string == null) { return ''; } return chars == null ? nativeTrim.call(string) : shimTrim(string, chars); }; /** * Removes leading whitespace or specified characters from `string`. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example * * _.trimLeft(' fred '); * // => 'fred ' * * _.trimLeft('-_-fred-_-', '_-'); * // => 'fred-_-' */ var trimLeft = !nativeTrimLeft ? shimTrimLeft : function(string, chars) { if (string == null) { return ''; } return chars == null ? nativeTrimLeft.call(string) : shimTrimLeft(string, chars); }; /** * Removes trailing whitespace or specified characters from `string`. * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to trim. * @param {string} [chars=whitespace] The characters to trim. * @returns {string} Returns the trimmed string. * @example * * _.trimRight(' fred '); * // => ' fred' * * _.trimRight('-_-fred-_-', '_-'); * // => '-_-fred' */ var trimRight = !nativeTrimRight ? shimTrimRight : function(string, chars) { if (string == null) { return ''; } return chars == null ? nativeTrimRight.call(string) : shimTrimRight(string, chars); }; /** * Truncates `string` if it is longer than the given maximum string length. * The last characters of the truncated string will be replaced with the * omission string which defaults to "...". * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to trim. * @param {Object|number} [options] The options object or maximum string length. * @param {number} [options.length=30] The maximum string length. * @param {string} [options.omission='...'] The string used to indicate text is omitted. * @param {RegExp|string} [options.separator] The separator pattern to truncate to. * @returns {string} Returns the truncated string. * @example * * _.truncate('hi-diddly-ho there, neighborino'); * // => 'hi-diddly-ho there, neighbo...' * * _.truncate('hi-diddly-ho there, neighborino', 24); * // => 'hi-diddly-ho there, n...' * * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' }); * // => 'hi-diddly-ho there,...' * * _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ }); * //=> 'hi-diddly-ho there...' * * _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' }); * // => 'hi-diddly-ho there, neig [...]' */ function truncate(string, options) { var length = 30, omission = '...'; if (options && isObject(options)) { var separator = 'separator' in options ? options.separator : separator; length = 'length' in options ? +options.length || 0 : length; omission = 'omission' in options ? String(options.omission) : omission; } else if (options != null) { length = +options || 0; } string = string == null ? '' : String(string); if (length > string.length) { return string; } var end = length - omission.length; if (end < 1) { return omission; } var result = string.slice(0, end); if (separator == null) { return result + omission; } if (isRegExp(separator)) { if (string.slice(end).search(separator)) { var match, newEnd, substring = string.slice(0, end); if (!separator.global) { separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g'); } separator.lastIndex = 0; while ((match = separator.exec(substring))) { newEnd = match.index; } result = result.slice(0, newEnd == null ? end : newEnd); } } else if (string.indexOf(separator, end) != end) { var index = result.lastIndexOf(separator); if (index > -1) { result = result.slice(0, index); } } return result + omission; } /** * The inverse of `_.escape`; this method converts the HTML entities * `&`, `<`, `>`, `"`, and `'` in `string` to their * corresponding characters. * * Note: No other HTML entities are unescaped. To unescape additional HTML * entities use a third-party library like [_he_](http://mths.be/he). * * @static * @memberOf _ * @category Strings * @param {string} [string=''] The string to unescape. * @returns {string} Returns the unescaped string. * @example * * _.unescape('fred, barney & pebbles'); * // => 'fred, barney & pebbles' */ function unescape(string) { if (string == null) { return ''; } string = String(string); return string.indexOf(';') < 0 ? string : string.replace(reEscapedHtml, unescapeHtmlChar); } /*--------------------------------------------------------------------------*/ /** * Creates a function that returns `value`. * * @static * @memberOf _ * @category Utilities * @param {*} value The value to return from the new function. * @returns {Function} Returns the new function. * @example * * var object = { 'name': 'fred' }; * var getter = _.constant(object); * getter() === object; * // => true */ function constant(value) { return function() { return value; }; } /** * Produces a callback bound to an optional `thisArg`. If `func` is a property * name the created callback will return the property value for a given element. * If `func` is an object the created callback will return `true` for elements * that contain the equivalent object properties, otherwise it will return `false`. * * @static * @memberOf _ * @alias callback * @category Utilities * @param {*} [func=identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of the created callback. * @param {number} [argCount] The number of arguments the callback accepts. * @returns {Function} Returns a callback function. * @example * * var characters = [ * { 'name': 'barney', 'age': 36 }, * { 'name': 'fred', 'age': 40 } * ]; * * // wrap to create custom callback shorthands * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) { * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback); * return !match ? func(callback, thisArg) : function(object) { * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; * }; * }); * * _.filter(characters, 'age__gt38'); * // => [{ 'name': 'fred', 'age': 40 }] */ function createCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function' || func == null) { return (typeof thisArg == 'undefined' || !('prototype' in func)) && func || baseCreateCallback(func, thisArg, argCount); } // handle "_.pluck" and "_.where" style callback shorthands return type != 'object' ? property(func) : matches(func); } /** * This method returns the first argument provided to it. * * @static * @memberOf _ * @category Utilities * @param {*} value Any value. * @returns {*} Returns `value`. * @example * * var object = { 'name': 'fred' }; * _.identity(object) === object; * // => true */ function identity(value) { return value; } /** * Creates a "_.where" style predicate function which performs a deep comparison * between a given object and the `source` object, returning `true` if the given * object has equivalent property values, else `false`. * * @static * @memberOf _ * @category Utilities * @param {Object} source The object of property values to match. * @returns {Function} Returns the new function. * @example * * var characters = [ * { 'name': 'fred', 'age': 40 }, * { 'name': 'barney', 'age': 36 } * ]; * * var matchesAge = _.matches({ 'age': 36 }); * * _.filter(characters, matchesAge); * // => [{ 'name': 'barney', 'age': 36 }] * * _.find(characters, matchesAge); * // => { 'name': 'barney', 'age': 36 } */ function matches(source) { source || (source = {}); var props = keys(source), key = props[0], a = source[key]; // fast path the common case of providing an object with a single // property containing a primitive value if (props.length == 1 && a === a && !isObject(a)) { return function(object) { if (!hasOwnProperty.call(object, key)) { return false; } // treat `-0` vs. `+0` as not equal var b = object[key]; return a === b && (a !== 0 || (1 / a == 1 / b)); }; } return function(object) { var length = props.length, result = false; while (length--) { var key = props[length]; if (!(result = hasOwnProperty.call(object, key) && baseIsEqual(object[key], source[key], null, true))) { break; } } return result; }; } /** * Adds function properties of a source object to the destination object. * If `object` is a function methods will be added to its prototype as well. * * @static * @memberOf _ * @category Utilities * @param {Function|Object} [object=lodash] object The destination object. * @param {Object} source The object of functions to add. * @param {Object} [options] The options object. * @param {boolean} [options.chain=true] Specify whether the functions added * are chainable. * @example * * function vowels(string) { * return _.filter(string, function(v) { * return /[aeiou]/i.test(v); * }); * } * * _.mixin({ 'vowels': vowels }); * _.vowels('fred'); * // => ['e'] * * _('fred').vowels().value(); * // => ['e'] * * _.mixin({ 'vowels': vowels }, { 'chain': false }); * _('fred').vowels(); * // => ['e'] */ function mixin(object, source, options) { var chain = true, methodNames = source && functions(source); if (!source || (!options && !methodNames.length)) { if (options == null) { options = source; } source = object; object = lodash; methodNames = functions(source); } if (options === false) { chain = false; } else if (isObject(options) && 'chain' in options) { chain = options.chain; } var index = -1, isFunc = isFunction(object), length = methodNames ? methodNames.length : 0; while (++index < length) { var methodName = methodNames[index], func = object[methodName] = source[methodName]; if (isFunc) { object.prototype[methodName] = (function(func) { return function() { var chainAll = this.__chain__, value = this.__wrapped__, args = [value]; push.apply(args, arguments); var result = func.apply(object, args); if (chain || chainAll) { if (value === result && isObject(result)) { return this; } result = new object(result); result.__chain__ = chainAll; } return result; }; }(func)); } } } /** * Reverts the '_' variable to its previous value and returns a reference to * the `lodash` function. * * @static * @memberOf _ * @category Utilities * @returns {Function} Returns the `lodash` function. * @example * * var lodash = _.noConflict(); */ function noConflict() { context._ = oldDash; return this; } /** * A no-operation function. * * @static * @memberOf _ * @category Utilities * @example * * var object = { 'name': 'fred' }; * _.noop(object) === undefined; * // => true */ function noop() { // no operation performed } /** * Gets the number of milliseconds that have elapsed since the Unix epoch * (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ * @category Utilities * @example * * var stamp = _.now(); * _.defer(function() { console.log(_.now() - stamp); }); * // => logs the number of milliseconds it took for the deferred function to be called */ var now = nativeNow || function() { return new Date().getTime(); }; /** * Converts `value` to an integer of the specified radix. If `radix` is * `undefined` or `0` a `radix` of `10` is used unless the `value` is a * hexadecimal, in which case a `radix` of `16` is used. * * Note: This method avoids differences in native ES3 and ES5 `parseInt` * implementations. See the [ES5 spec](http://es5.github.io/#E) * for more details. * * @static * @memberOf _ * @category Utilities * @param {string} value The value to parse. * @param {number} [radix] The radix used to interpret the value to parse. * @returns {number} Returns the new integer value. * @example * * _.parseInt('08'); * // => 8 */ var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) { // Firefox < 21 and Opera < 15 follow ES3 for `parseInt` and // Chrome fails to trim leading <BOM> whitespace characters. // See https://code.google.com/p/v8/issues/detail?id=3109 value = trim(value); return nativeParseInt(value, +radix || (reHexPrefix.test(value) ? 16 : 10)); }; /** * Creates a "_.pluck" style function which returns the `key` value of a * given object. * * @static * @memberOf _ * @category Utilities * @param {string} key The name of the property to retrieve. * @returns {Function} Returns the new function. * @example * * var characters = [ * { 'name': 'fred', 'age': 40 }, * { 'name': 'barney', 'age': 36 } * ]; * * var getName = _.property('name'); * * _.map(characters, getName); * // => ['barney', 'fred'] * * _.sortBy(characters, getName); * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] */ function property(key) { return function(object) { return object[key]; }; } /** * Produces a random number between `min` and `max` (inclusive). If only one * argument is provided a number between `0` and the given number will be * returned. If `floating` is truthy or either `min` or `max` are floats a * floating-point number will be returned instead of an integer. * * @static * @memberOf _ * @category Utilities * @param {number} [min=0] The minimum possible value. * @param {number} [max=1] The maximum possible value. * @param {boolean} [floating=false] Specify returning a floating-point number. * @returns {number} Returns a random number. * @example * * _.random(0, 5); * // => an integer between 0 and 5 * * _.random(5); * // => also an integer between 0 and 5 * * _.random(5, true); * // => a floating-point number between 0 and 5 * * _.random(1.2, 5.2); * // => a floating-point number between 1.2 and 5.2 */ function random(min, max, floating) { var noMin = min == null, noMax = max == null; if (floating == null) { if (noMax && typeof min == 'boolean') { floating = min; min = 1; } else if (typeof max == 'boolean') { floating = max; noMax = true; } } if (noMin && noMax) { max = 1; noMax = false; } min = +min || 0; if (noMax) { max = min; min = 0; } else { max = +max || 0; } if (floating || min % 1 || max % 1) { var rand = nativeRandom(); return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max); } return baseRandom(min, max); } /** * Resolves the value of property `key` on `object`. If `key` is a function * it will be invoked with the `this` binding of `object` and its result * returned, else the property value is returned. If `object` is `null` or * `undefined` then `undefined` is returned. If a default value is provided * it will be returned if the property value resolves to `undefined`. * * @static * @memberOf _ * @category Utilities * @param {Object} object The object to inspect. * @param {string} key The name of the property to resolve. * @param {*} [defaultValue] The value returned if the property value * resolves to `undefined`. * @returns {*} Returns the resolved value. * @example * * var object = { * 'name': 'fred', * 'age': function() { * return 40; * } * }; * * _.result(object, 'name'); * // => 'fred' * * _.result(object, 'age'); * // => 40 * * _.result(object, 'employer', 'slate'); * // => 'slate' */ function result(object, key, defaultValue) { var value = object == null ? undefined : object[key]; if (typeof value == 'undefined') { return defaultValue; } return isFunction(value) ? object[key]() : value; } /** * Executes the callback `n` times, returning an array of the results * of each callback execution. The callback is bound to `thisArg` and invoked * with one argument; (index). * * @static * @memberOf _ * @category Utilities * @param {number} n The number of times to execute the callback. * @param {Function} [callback=identity] The function called per iteration. * @param {*} [thisArg] The `this` binding of `callback`. * @returns {Array} Returns an array of the results of each `callback` execution. * @example * * var diceRolls = _.times(3, _.partial(_.random, 1, 6)); * // => [3, 6, 4] * * _.times(3, function(n) { mage.castSpell(n); }); * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively * * _.times(3, function(n) { this.cast(n); }, mage); * // => also calls `mage.castSpell(n)` three times */ function times(n, callback, thisArg) { n = (n = +n) > -1 ? n : 0; var index = -1, result = Array(n); callback = baseCreateCallback(callback, thisArg, 1); while (++index < n) { result[index] = callback(index); } return result; } /** * Generates a unique ID. If `prefix` is provided the ID will be appended to it. * * @static * @memberOf _ * @category Utilities * @param {string} [prefix] The value to prefix the ID with. * @returns {string} Returns the unique ID. * @example * * _.uniqueId('contact_'); * // => 'contact_104' * * _.uniqueId(); * // => '105' */ function uniqueId(prefix) { var id = ++idCounter; return String(prefix == null ? '' : prefix) + id; } /*--------------------------------------------------------------------------*/ // add functions that return wrapped values when chaining lodash.after = after; lodash.assign = assign; lodash.at = at; lodash.bind = bind; lodash.bindAll = bindAll; lodash.bindKey = bindKey; lodash.chain = chain; lodash.compact = compact; lodash.compose = compose; lodash.constant = constant; lodash.countBy = countBy; lodash.create = create; lodash.createCallback = createCallback; lodash.curry = curry; lodash.debounce = debounce; lodash.defaults = defaults; lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; lodash.drop = drop; lodash.dropRight = dropRight; lodash.dropRightWhile = dropRightWhile; lodash.dropWhile = dropWhile; lodash.filter = filter; lodash.flatten = flatten; lodash.forEach = forEach; lodash.forEachRight = forEachRight; lodash.forIn = forIn; lodash.forInRight = forInRight; lodash.forOwn = forOwn; lodash.forOwnRight = forOwnRight; lodash.functions = functions; lodash.groupBy = groupBy; lodash.indexBy = indexBy; lodash.initial = initial; lodash.intersection = intersection; lodash.invert = invert; lodash.invoke = invoke; lodash.keys = keys; lodash.map = map; lodash.mapValues = mapValues; lodash.matches = matches; lodash.max = max; lodash.memoize = memoize; lodash.merge = merge; lodash.min = min; lodash.omit = omit; lodash.once = once; lodash.pairs = pairs; lodash.partial = partial; lodash.partialRight = partialRight; lodash.partition = partition; lodash.pick = pick; lodash.pluck = pluck; lodash.property = property; lodash.pull = pull; lodash.range = range; lodash.reject = reject; lodash.remove = remove; lodash.rest = rest; lodash.shuffle = shuffle; lodash.slice = slice; lodash.sortBy = sortBy; lodash.tap = tap; lodash.throttle = throttle; lodash.times = times; lodash.toArray = toArray; lodash.transform = transform; lodash.union = union; lodash.uniq = uniq; lodash.values = values; lodash.where = where; lodash.without = without; lodash.wrap = wrap; lodash.xor = xor; lodash.zip = zip; lodash.zipObject = zipObject; // add aliases lodash.callback = createCallback; lodash.collect = map; lodash.each = forEach; lodash.eachRight = forEachRight; lodash.extend = assign; lodash.methods = functions; lodash.object = zipObject; lodash.select = filter; lodash.tail = rest; lodash.unique = uniq; lodash.unzip = zip; // add functions to `lodash.prototype` mixin(assign({}, lodash)); /*--------------------------------------------------------------------------*/ // add functions that return unwrapped values when chaining lodash.camelCase = camelCase; lodash.capitalize = capitalize; lodash.clone = clone; lodash.cloneDeep = cloneDeep; lodash.contains = contains; lodash.endsWith = endsWith; lodash.escape = escape; lodash.escapeRegExp = escapeRegExp; lodash.every = every; lodash.find = find; lodash.findIndex = findIndex; lodash.findKey = findKey; lodash.findLast = findLast; lodash.findLastIndex = findLastIndex; lodash.findLastKey = findLastKey; lodash.has = has; lodash.identity = identity; lodash.indexOf = indexOf; lodash.isArguments = isArguments; lodash.isArray = isArray; lodash.isBoolean = isBoolean; lodash.isDate = isDate; lodash.isElement = isElement; lodash.isEmpty = isEmpty; lodash.isEqual = isEqual; lodash.isFinite = isFinite; lodash.isFunction = isFunction; lodash.isNaN = isNaN; lodash.isNull = isNull; lodash.isNumber = isNumber; lodash.isObject = isObject; lodash.isPlainObject = isPlainObject; lodash.isRegExp = isRegExp; lodash.isString = isString; lodash.isUndefined = isUndefined; lodash.kebabCase = kebabCase; lodash.lastIndexOf = lastIndexOf; lodash.mixin = mixin; lodash.noConflict = noConflict; lodash.noop = noop; lodash.now = now; lodash.pad = pad; lodash.padLeft = padLeft; lodash.padRight = padRight; lodash.parseInt = parseInt; lodash.random = random; lodash.reduce = reduce; lodash.reduceRight = reduceRight; lodash.repeat = repeat; lodash.result = result; lodash.runInContext = runInContext; lodash.size = size; lodash.some = some; lodash.sortedIndex = sortedIndex; lodash.snakeCase = snakeCase; lodash.startsWith = startsWith; lodash.template = template; lodash.trim = trim; lodash.trimLeft = trimLeft; lodash.trimRight = trimRight; lodash.truncate = truncate; lodash.unescape = unescape; lodash.uniqueId = uniqueId; // add aliases lodash.all = every; lodash.any = some; lodash.detect = find; lodash.findWhere = find; lodash.foldl = reduce; lodash.foldr = reduceRight; lodash.include = contains; lodash.inject = reduce; mixin(function() { var source = {} baseForOwn(lodash, function(func, methodName) { if (!lodash.prototype[methodName]) { source[methodName] = func; } }); return source; }(), false); /*--------------------------------------------------------------------------*/ // add functions capable of returning wrapped and unwrapped values when chaining lodash.first = first; lodash.last = last; lodash.sample = sample; lodash.take = first; lodash.takeRight = last; lodash.takeRightWhile = last; lodash.takeWhile = first; // add aliases lodash.head = first; baseForOwn(lodash, function(func, methodName) { var callbackable = methodName !== 'sample'; if (!lodash.prototype[methodName]) { lodash.prototype[methodName]= function(n, guard) { var chainAll = this.__chain__, result = func(this.__wrapped__, n, guard); return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function'))) ? result : new lodashWrapper(result, chainAll); }; } }); /*--------------------------------------------------------------------------*/ /** * The semantic version number. * * @static * @memberOf _ * @type string */ lodash.VERSION = version; // add "Chaining" functions to the wrapper lodash.prototype.chain = wrapperChain; lodash.prototype.toString = wrapperToString; lodash.prototype.value = wrapperValueOf; lodash.prototype.valueOf = wrapperValueOf; // add `Array` functions that return unwrapped values baseEach(['join', 'pop', 'shift'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { var chainAll = this.__chain__, result = func.apply(this.__wrapped__, arguments); return chainAll ? new lodashWrapper(result, chainAll) : result; }; }); // add `Array` functions that return the existing wrapped value baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { func.apply(this.__wrapped__, arguments); return this; }; }); // add `Array` functions that return new wrapped values baseEach(['concat', 'splice'], function(methodName) { var func = arrayRef[methodName]; lodash.prototype[methodName] = function() { return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__); }; }); // avoid array-like object bugs with `Array#shift` and `Array#splice` // in IE < 9, Firefox < 10, Narwhal, and RingoJS if (!support.spliceObjects) { baseEach(['pop', 'shift', 'splice'], function(methodName) { var func = arrayRef[methodName], isSplice = methodName == 'splice'; lodash.prototype[methodName] = function() { var chainAll = this.__chain__, value = this.__wrapped__, result = func.apply(value, arguments); if (value.length === 0) { delete value[0]; } return (chainAll || isSplice) ? new lodashWrapper(result, chainAll) : result; }; }); } // add pseudo private property to be used and removed during the build process lodash._baseForIn = baseForIn; lodash._iteratorTemplate = iteratorTemplate; lodash._shimKeys = shimKeys; return lodash; } /*--------------------------------------------------------------------------*/ // export Lo-Dash var _ = runInContext(); // some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { // Expose Lo-Dash to the global object even when an AMD loader is present in // case Lo-Dash is loaded with a RequireJS shim config. // See http://requirejs.org/docs/api.html#config-shim root._ = _; // define as an anonymous module so, through path mapping, it can be // referenced as the "underscore" module define(function() { return _; }); } // check for `exports` after `define` in case a build optimizer adds an `exports` object else if (freeExports && freeModule) { // in Node.js or RingoJS if (moduleExports) { (freeModule.exports = _)._ = _; } // in Narwhal or Rhino -require else { freeExports._ = _; } } else { // in a browser or Rhino root._ = _; } }.call(this));