character 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +4 -0
  3. data/README.md +20 -0
  4. data/Rakefile +7 -0
  5. data/app/controllers/character/posts_controller.rb +27 -0
  6. data/app/models/character/post.rb +20 -0
  7. data/character.gemspec +24 -0
  8. data/lib/character.rb +3 -0
  9. data/lib/character/engine.rb +5 -0
  10. data/lib/character/routing.rb +11 -0
  11. data/lib/character/version.rb +3 -0
  12. data/lib/generators/character/install_generator.rb +42 -0
  13. data/lib/generators/character/templates/README +1 -0
  14. data/lib/generators/character/templates/admin/character.rb +3 -0
  15. data/vendor/assets/fonts/general_foundicons.eot +0 -0
  16. data/vendor/assets/fonts/general_foundicons.svg +15 -0
  17. data/vendor/assets/fonts/general_foundicons.ttf +0 -0
  18. data/vendor/assets/fonts/general_foundicons.woff +0 -0
  19. data/vendor/assets/javascripts/backbone.js +1431 -0
  20. data/vendor/assets/javascripts/character/index.js.coffee +53 -0
  21. data/vendor/assets/javascripts/character/models/post.js.coffee +39 -0
  22. data/vendor/assets/javascripts/character/views/app.js.coffee +81 -0
  23. data/vendor/assets/javascripts/character/views/editor.js.coffee +231 -0
  24. data/vendor/assets/javascripts/character/views/editor_settings.js.coffee +44 -0
  25. data/vendor/assets/javascripts/character/views/index.js.coffee +116 -0
  26. data/vendor/assets/javascripts/character/views/preview.js.coffee +49 -0
  27. data/vendor/assets/javascripts/jquery.smartresize.js +30 -0
  28. data/vendor/assets/javascripts/lodash.js +4258 -0
  29. data/vendor/assets/javascripts/showdown.js +62 -0
  30. data/vendor/assets/javascripts/underscore.string.js +600 -0
  31. data/vendor/assets/stylesheets/character/_base.css.scss +84 -0
  32. data/vendor/assets/stylesheets/character/_icons.css.scss.erb +96 -0
  33. data/vendor/assets/stylesheets/character/_view_editor.css.scss +115 -0
  34. data/vendor/assets/stylesheets/character/_view_index.css.scss +73 -0
  35. data/vendor/assets/stylesheets/character/_view_preview.css.scss +49 -0
  36. data/vendor/assets/stylesheets/character/index.css.scss +32 -0
  37. metadata +103 -0
@@ -0,0 +1,116 @@
1
+ ##############################
2
+ ### CHARACTER :: IndexView ###
3
+ ##############################
4
+
5
+ class PostIndexItemView extends Backbone.View
6
+ tagName: 'li'
7
+
8
+ render: ->
9
+ post = @model.toJSON()
10
+ id = @model.id
11
+ views = if post.published then post.views else ''
12
+ date = @model.date_formatted()
13
+
14
+ image = @model.featured_image()
15
+ img_tag = if image then """<img class='featured' src='#{image}' />""" else ''
16
+
17
+ html = """<a href='#/preview/#{id}'>
18
+ #{img_tag}
19
+ <div class='left'>
20
+ <span class='title'>#{post.title}</span>
21
+ <span class='meta'>#{@model.state()}</span>
22
+ </div>
23
+ <div class='right'>
24
+ <span class='date'>#{date}</span>
25
+ <span class='views'>#{views}</span>
26
+ </div>
27
+ </a>"""
28
+ $(this.el).html html
29
+ return this
30
+
31
+
32
+ class IndexView extends Backbone.View
33
+ tagName: 'div'
34
+ className: 'chr-panel left index'
35
+ id: 'blog_index'
36
+
37
+
38
+ render: ->
39
+ html = """<section class='container'>
40
+ <header>
41
+ <span class='title'>Posts</span>
42
+ <span class='buttons'>
43
+ <a href='#/new' title='Create new post' class='foundicon-add-doc'></a>
44
+ <!--<span class='split'></span><a href='#' title='Search for post' class='foundicon-search'></a>-->
45
+ </span>
46
+ </header>
47
+ <ul id='list'></ul>
48
+ </section>"""
49
+ $(this.el).html html
50
+ return this
51
+
52
+
53
+ render_item: (post) ->
54
+ item = new PostIndexItemView model: post
55
+ html = item.render().el
56
+ $(@list).append html
57
+
58
+ @item_views[post.id] = item
59
+
60
+ render_items_placeholder: ->
61
+ html = """<li class='placeholder'>Hey there! You don't have any posts yet, so go ahead and create the first one!</li>"""
62
+ $(@list).append html
63
+
64
+ render_items: ->
65
+ posts = window.posts.toArray()
66
+ if posts.length > 0
67
+ @render_item(post) for post in posts
68
+ else
69
+ @render_items_placeholder()
70
+
71
+
72
+ initialize: ->
73
+ html = @render().el
74
+ $('#main').append(html)
75
+
76
+ @list = document.getElementById('list')
77
+ @item_views = {}
78
+
79
+ @render_items()
80
+
81
+
82
+ scroll_to_active: ->
83
+ if window.index_scroll_y > 0
84
+ window.scroll(0, window.index_scroll_y)
85
+ else
86
+ top_offset = $('#blog_index a.active').offset().top
87
+ if top_offset - window.scrollY > $(window).height()
88
+ window.scroll(0, top_offset - 100)
89
+
90
+
91
+ set_active: (id) ->
92
+ @unset_active()
93
+ $("#blog_index a[href='#/preview/#{id}']").addClass('active')
94
+ @scroll_to_active()
95
+
96
+
97
+ unset_active: ->
98
+ $('#blog_index a.active').removeClass('active')
99
+
100
+
101
+ lock: ->
102
+ window.index_scroll_y = window.scrollY
103
+ $(@el).css('top', -window.scrollY + 40).addClass('fixed') # 40 is an active admin header height
104
+
105
+
106
+ unlock: ->
107
+ $(@el).css('top', '').removeClass('fixed')
108
+ window.scroll(0, window.index_scroll_y)
109
+
110
+
111
+ window.IndexView = IndexView
112
+
113
+
114
+
115
+
116
+
@@ -0,0 +1,49 @@
1
+ ####################################
2
+ ### CHARACTER :: PostPreviewView ###
3
+ ####################################
4
+
5
+ class PostPreviewView extends Backbone.View
6
+ tagName: 'div'
7
+ className: 'chr-panel right quickview'
8
+ id: 'blog_quickview'
9
+
10
+
11
+ delete_post: (e) ->
12
+ e.preventDefault()
13
+ if confirm('Do you really want to remove this post?')
14
+ # this event could be probably tighted to collection event or model destory event
15
+ window.app.index_view.item_views[@model.id].remove()
16
+ @model.destroy()
17
+ router.navigate('#/', {trigger: true})
18
+
19
+
20
+ events:
21
+ 'click #delete_post': 'delete_post'
22
+
23
+ render: ->
24
+ post = @model.toJSON()
25
+ state = @model.state()
26
+ id = @model.id
27
+
28
+ html = """<section class='container'>
29
+ <header>
30
+ <span class='title'>#{state}</span>
31
+ <span class='buttons'>
32
+ <a href='#' title='Delete this post' class='foundicon-trash' id='delete_post'></a>
33
+ <span class='split'></span>
34
+ <a href='#/edit/#{id}' title='Edit this post' class='foundicon-edit'></a>
35
+ <span class='split'></span>
36
+ <a href='#/' title='Close Preview' class='foundicon-remove'></a>
37
+ </span>
38
+ </header>
39
+
40
+ <article>
41
+ <section class='content'>
42
+ #{post.html}
43
+ </section>
44
+ </article>
45
+ </section>"""
46
+ $(this.el).html html
47
+ return this
48
+
49
+ window.PostPreviewView = PostPreviewView
@@ -0,0 +1,30 @@
1
+ /*
2
+ * Smartresize
3
+ */
4
+ (function($,sr){
5
+
6
+ // debouncing function from John Hann
7
+ // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
8
+ var debounce = function (func, threshold, execAsap) {
9
+ var timeout;
10
+
11
+ return function debounced () {
12
+ var obj = this, args = arguments;
13
+ function delayed () {
14
+ if (!execAsap)
15
+ func.apply(obj, args);
16
+ timeout = null;
17
+ };
18
+
19
+ if (timeout)
20
+ clearTimeout(timeout);
21
+ else if (execAsap)
22
+ func.apply(obj, args);
23
+
24
+ timeout = setTimeout(delayed, threshold || 100);
25
+ };
26
+ }
27
+ // smartresize
28
+ jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };
29
+
30
+ })(jQuery,'smartresize');
@@ -0,0 +1,4258 @@
1
+ /*!
2
+ * Lo-Dash v0.9.2 <http://lodash.com>
3
+ * (c) 2012 John-David Dalton <http://allyoucanleet.com/>
4
+ * Based on Underscore.js 1.4.2 <http://underscorejs.org>
5
+ * (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
6
+ * Available under MIT license <http://lodash.com/license>
7
+ */
8
+ ;(function(window, undefined) {
9
+
10
+ /** Detect free variable `exports` */
11
+ var freeExports = typeof exports == 'object' && exports;
12
+
13
+ /** Detect free variable `global` and use it as `window` */
14
+ var freeGlobal = typeof global == 'object' && global;
15
+ if (freeGlobal.global === freeGlobal) {
16
+ window = freeGlobal;
17
+ }
18
+
19
+ /** Used for array and object method references */
20
+ var arrayRef = [],
21
+ // avoid a Closure Compiler bug by creatively creating an object
22
+ objectRef = new function(){};
23
+
24
+ /** Used to generate unique IDs */
25
+ var idCounter = 0;
26
+
27
+ /** Used internally to indicate various things */
28
+ var indicatorObject = objectRef;
29
+
30
+ /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
31
+ var largeArraySize = 30;
32
+
33
+ /** Used to restore the original `_` reference in `noConflict` */
34
+ var oldDash = window._;
35
+
36
+ /** Used to detect template delimiter values that require a with-statement */
37
+ var reComplexDelimiter = /[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
38
+
39
+ /** Used to match HTML entities */
40
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g;
41
+
42
+ /** Used to match empty string literals in compiled template source */
43
+ var reEmptyStringLeading = /\b__p \+= '';/g,
44
+ reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
45
+ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
46
+
47
+ /** Used to match regexp flags from their coerced string values */
48
+ var reFlags = /\w*$/;
49
+
50
+ /** Used to insert the data object variable into compiled template source */
51
+ var reInsertVariable = /(?:__e|__t = )\(\s*(?![\d\s"']|this\.)/g;
52
+
53
+ /** Used to detect if a method is native */
54
+ var reNative = RegExp('^' +
55
+ (objectRef.valueOf + '')
56
+ .replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')
57
+ .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
58
+ );
59
+
60
+ /**
61
+ * Used to match ES6 template delimiters
62
+ * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
63
+ */
64
+ var reEsTemplate = /\$\{((?:(?=\\?)\\?[\s\S])*?)}/g;
65
+
66
+ /** Used to match "interpolate" template delimiters */
67
+ var reInterpolate = /<%=([\s\S]+?)%>/g;
68
+
69
+ /** Used to ensure capturing order of template delimiters */
70
+ var reNoMatch = /($^)/;
71
+
72
+ /** Used to match HTML characters */
73
+ var reUnescapedHtml = /[&<>"']/g;
74
+
75
+ /** Used to match unescaped characters in compiled string literals */
76
+ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
77
+
78
+ /** Used to fix the JScript [[DontEnum]] bug */
79
+ var shadowed = [
80
+ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
81
+ 'toLocaleString', 'toString', 'valueOf'
82
+ ];
83
+
84
+ /** Used to make template sourceURLs easier to identify */
85
+ var templateCounter = 0;
86
+
87
+ /** Native method shortcuts */
88
+ var ceil = Math.ceil,
89
+ concat = arrayRef.concat,
90
+ floor = Math.floor,
91
+ getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
92
+ hasOwnProperty = objectRef.hasOwnProperty,
93
+ push = arrayRef.push,
94
+ propertyIsEnumerable = objectRef.propertyIsEnumerable,
95
+ slice = arrayRef.slice,
96
+ toString = objectRef.toString;
97
+
98
+ /* Native method shortcuts for methods with the same name as other `lodash` methods */
99
+ var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
100
+ nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
101
+ nativeIsFinite = window.isFinite,
102
+ nativeIsNaN = window.isNaN,
103
+ nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
104
+ nativeMax = Math.max,
105
+ nativeMin = Math.min,
106
+ nativeRandom = Math.random;
107
+
108
+ /** `Object#toString` result shortcuts */
109
+ var argsClass = '[object Arguments]',
110
+ arrayClass = '[object Array]',
111
+ boolClass = '[object Boolean]',
112
+ dateClass = '[object Date]',
113
+ funcClass = '[object Function]',
114
+ numberClass = '[object Number]',
115
+ objectClass = '[object Object]',
116
+ regexpClass = '[object RegExp]',
117
+ stringClass = '[object String]';
118
+
119
+ /**
120
+ * Detect the JScript [[DontEnum]] bug:
121
+ *
122
+ * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
123
+ * made non-enumerable as well.
124
+ */
125
+ var hasDontEnumBug;
126
+
127
+ /** Detect if own properties are iterated after inherited properties (IE < 9) */
128
+ var iteratesOwnLast;
129
+
130
+ /**
131
+ * Detect if `Array#shift` and `Array#splice` augment array-like objects
132
+ * incorrectly:
133
+ *
134
+ * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
135
+ * and `splice()` functions that fail to remove the last element, `value[0]`,
136
+ * of array-like objects even though the `length` property is set to `0`.
137
+ * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
138
+ * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
139
+ */
140
+ var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
141
+ arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
142
+
143
+ /** Detect if an `arguments` object's indexes are non-enumerable (IE < 9) */
144
+ var noArgsEnum = true;
145
+
146
+ (function() {
147
+ var props = [];
148
+ function ctor() { this.x = 1; }
149
+ ctor.prototype = { 'valueOf': 1, 'y': 1 };
150
+ for (var prop in new ctor) { props.push(prop); }
151
+ for (prop in arguments) { noArgsEnum = !prop; }
152
+
153
+ hasDontEnumBug = !/valueOf/.test(props);
154
+ iteratesOwnLast = props[0] != 'x';
155
+ }(1));
156
+
157
+ /** Detect if an `arguments` object's [[Class]] is unresolvable (Firefox < 4, IE < 9) */
158
+ var noArgsClass = !isArguments(arguments);
159
+
160
+ /** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */
161
+ var noArraySliceOnStrings = slice.call('x')[0] != 'x';
162
+
163
+ /**
164
+ * Detect lack of support for accessing string characters by index:
165
+ *
166
+ * IE < 8 can't access characters by index and IE 8 can only access
167
+ * characters by index on string literals.
168
+ */
169
+ var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
170
+
171
+ /**
172
+ * Detect if a node's [[Class]] is unresolvable (IE < 9)
173
+ * and that the JS engine won't error when attempting to coerce an object to
174
+ * a string without a `toString` property value of `typeof` "function".
175
+ */
176
+ try {
177
+ var noNodeClass = ({ 'toString': 0 } + '', toString.call(window.document || 0) == objectClass);
178
+ } catch(e) { }
179
+
180
+ /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
181
+ var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
182
+
183
+ /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
184
+ var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
185
+
186
+ /**
187
+ * Detect if sourceURL syntax is usable without erroring:
188
+ *
189
+ * The JS engine in Adobe products, like InDesign, will throw a syntax error
190
+ * when it encounters a single line comment beginning with the `@` symbol.
191
+ *
192
+ * The JS engine in Narwhal will generate the function `function anonymous(){//}`
193
+ * and throw a syntax error.
194
+ *
195
+ * Avoid comments beginning `@` symbols in IE because they are part of its
196
+ * non-standard conditional compilation support.
197
+ * http://msdn.microsoft.com/en-us/library/121hztk3(v=vs.94).aspx
198
+ */
199
+ try {
200
+ var useSourceURL = (Function('//@')(), !window.attachEvent);
201
+ } catch(e) { }
202
+
203
+ /** Used to identify object classifications that `_.clone` supports */
204
+ var cloneableClasses = {};
205
+ cloneableClasses[argsClass] = cloneableClasses[funcClass] = false;
206
+ cloneableClasses[arrayClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] =
207
+ cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] =
208
+ cloneableClasses[stringClass] = true;
209
+
210
+ /** Used to determine if values are of the language type Object */
211
+ var objectTypes = {
212
+ 'boolean': false,
213
+ 'function': true,
214
+ 'object': true,
215
+ 'number': false,
216
+ 'string': false,
217
+ 'undefined': false
218
+ };
219
+
220
+ /** Used to escape characters for inclusion in compiled string literals */
221
+ var stringEscapes = {
222
+ '\\': '\\',
223
+ "'": "'",
224
+ '\n': 'n',
225
+ '\r': 'r',
226
+ '\t': 't',
227
+ '\u2028': 'u2028',
228
+ '\u2029': 'u2029'
229
+ };
230
+
231
+ /*--------------------------------------------------------------------------*/
232
+
233
+ /**
234
+ * The `lodash` function.
235
+ *
236
+ * @name _
237
+ * @constructor
238
+ * @category Chaining
239
+ * @param {Mixed} value The value to wrap in a `lodash` instance.
240
+ * @returns {Object} Returns a `lodash` instance.
241
+ */
242
+ function lodash(value) {
243
+ // exit early if already wrapped
244
+ if (value && value.__wrapped__) {
245
+ return value;
246
+ }
247
+ // allow invoking `lodash` without the `new` operator
248
+ if (!(this instanceof lodash)) {
249
+ return new lodash(value);
250
+ }
251
+ this.__wrapped__ = value;
252
+ }
253
+
254
+ /**
255
+ * By default, the template delimiters used by Lo-Dash are similar to those in
256
+ * embedded Ruby (ERB). Change the following template settings to use alternative
257
+ * delimiters.
258
+ *
259
+ * @static
260
+ * @memberOf _
261
+ * @type Object
262
+ */
263
+ lodash.templateSettings = {
264
+
265
+ /**
266
+ * Used to detect `data` property values to be HTML-escaped.
267
+ *
268
+ * @static
269
+ * @memberOf _.templateSettings
270
+ * @type RegExp
271
+ */
272
+ 'escape': /<%-([\s\S]+?)%>/g,
273
+
274
+ /**
275
+ * Used to detect code to be evaluated.
276
+ *
277
+ * @static
278
+ * @memberOf _.templateSettings
279
+ * @type RegExp
280
+ */
281
+ 'evaluate': /<%([\s\S]+?)%>/g,
282
+
283
+ /**
284
+ * Used to detect `data` property values to inject.
285
+ *
286
+ * @static
287
+ * @memberOf _.templateSettings
288
+ * @type RegExp
289
+ */
290
+ 'interpolate': reInterpolate,
291
+
292
+ /**
293
+ * Used to reference the data object in the template text.
294
+ *
295
+ * @static
296
+ * @memberOf _.templateSettings
297
+ * @type String
298
+ */
299
+ 'variable': ''
300
+ };
301
+
302
+ /*--------------------------------------------------------------------------*/
303
+
304
+ /**
305
+ * The template used to create iterator functions.
306
+ *
307
+ * @private
308
+ * @param {Obect} data The data object used to populate the text.
309
+ * @returns {String} Returns the interpolated text.
310
+ */
311
+ var iteratorTemplate = template(
312
+ // conditional strict mode
313
+ '<% if (obj.useStrict) { %>\'use strict\';\n<% } %>' +
314
+
315
+ // the `iteratee` may be reassigned by the `top` snippet
316
+ 'var index, value, iteratee = <%= firstArg %>, ' +
317
+ // assign the `result` variable an initial value
318
+ 'result = <%= firstArg %>;\n' +
319
+ // exit early if the first argument is falsey
320
+ 'if (!<%= firstArg %>) return result;\n' +
321
+ // add code before the iteration branches
322
+ '<%= top %>;\n' +
323
+
324
+ // array-like iteration:
325
+ '<% if (arrayLoop) { %>' +
326
+ 'var length = iteratee.length; index = -1;\n' +
327
+ 'if (typeof length == \'number\') {' +
328
+
329
+ // add support for accessing string characters by index if needed
330
+ ' <% if (noCharByIndex) { %>\n' +
331
+ ' if (isString(iteratee)) {\n' +
332
+ ' iteratee = iteratee.split(\'\')\n' +
333
+ ' }' +
334
+ ' <% } %>\n' +
335
+
336
+ // iterate over the array-like value
337
+ ' while (++index < length) {\n' +
338
+ ' value = iteratee[index];\n' +
339
+ ' <%= arrayLoop %>\n' +
340
+ ' }\n' +
341
+ '}\n' +
342
+ 'else {' +
343
+
344
+ // object iteration:
345
+ // add support for iterating over `arguments` objects if needed
346
+ ' <% } else if (noArgsEnum) { %>\n' +
347
+ ' var length = iteratee.length; index = -1;\n' +
348
+ ' if (length && isArguments(iteratee)) {\n' +
349
+ ' while (++index < length) {\n' +
350
+ ' value = iteratee[index += \'\'];\n' +
351
+ ' <%= objectLoop %>\n' +
352
+ ' }\n' +
353
+ ' } else {' +
354
+ ' <% } %>' +
355
+
356
+ // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
357
+ // (if the prototype or a property on the prototype has been set)
358
+ // incorrectly sets a function's `prototype` property [[Enumerable]]
359
+ // value to `true`. Because of this Lo-Dash standardizes on skipping
360
+ // the the `prototype` property of functions regardless of its
361
+ // [[Enumerable]] value.
362
+ ' <% if (!hasDontEnumBug) { %>\n' +
363
+ ' var skipProto = typeof iteratee == \'function\' && \n' +
364
+ ' propertyIsEnumerable.call(iteratee, \'prototype\');\n' +
365
+ ' <% } %>' +
366
+
367
+ // iterate own properties using `Object.keys` if it's fast
368
+ ' <% if (isKeysFast && useHas) { %>\n' +
369
+ ' var ownIndex = -1,\n' +
370
+ ' ownProps = objectTypes[typeof iteratee] ? nativeKeys(iteratee) : [],\n' +
371
+ ' length = ownProps.length;\n\n' +
372
+ ' while (++ownIndex < length) {\n' +
373
+ ' index = ownProps[ownIndex];\n' +
374
+ ' <% if (!hasDontEnumBug) { %>if (!(skipProto && index == \'prototype\')) {\n <% } %>' +
375
+ ' value = iteratee[index];\n' +
376
+ ' <%= objectLoop %>\n' +
377
+ ' <% if (!hasDontEnumBug) { %>}\n<% } %>' +
378
+ ' }' +
379
+
380
+ // else using a for-in loop
381
+ ' <% } else { %>\n' +
382
+ ' for (index in iteratee) {<%' +
383
+ ' if (!hasDontEnumBug || useHas) { %>\n if (<%' +
384
+ ' if (!hasDontEnumBug) { %>!(skipProto && index == \'prototype\')<% }' +
385
+ ' if (!hasDontEnumBug && useHas) { %> && <% }' +
386
+ ' if (useHas) { %>hasOwnProperty.call(iteratee, index)<% }' +
387
+ ' %>) {' +
388
+ ' <% } %>\n' +
389
+ ' value = iteratee[index];\n' +
390
+ ' <%= objectLoop %>;' +
391
+ ' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' +
392
+ ' }' +
393
+ ' <% } %>' +
394
+
395
+ // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
396
+ // existing property and the `constructor` property of a prototype
397
+ // defaults to non-enumerable, Lo-Dash skips the `constructor`
398
+ // property when it infers it's iterating over a `prototype` object.
399
+ ' <% if (hasDontEnumBug) { %>\n\n' +
400
+ ' var ctor = iteratee.constructor;\n' +
401
+ ' <% for (var k = 0; k < 7; k++) { %>\n' +
402
+ ' index = \'<%= shadowed[k] %>\';\n' +
403
+ ' if (<%' +
404
+ ' if (shadowed[k] == \'constructor\') {' +
405
+ ' %>!(ctor && ctor.prototype === iteratee) && <%' +
406
+ ' } %>hasOwnProperty.call(iteratee, index)) {\n' +
407
+ ' value = iteratee[index];\n' +
408
+ ' <%= objectLoop %>\n' +
409
+ ' }' +
410
+ ' <% } %>' +
411
+ ' <% } %>' +
412
+ ' <% if (arrayLoop || noArgsEnum) { %>\n}<% } %>\n' +
413
+
414
+ // add code to the bottom of the iteration function
415
+ '<%= bottom %>;\n' +
416
+ // finally, return the `result`
417
+ 'return result'
418
+ );
419
+
420
+ /**
421
+ * Reusable iterator options shared by `forEach`, `forIn`, and `forOwn`.
422
+ */
423
+ var forEachIteratorOptions = {
424
+ 'args': 'collection, callback, thisArg',
425
+ 'top': 'callback = createCallback(callback, thisArg)',
426
+ 'arrayLoop': 'if (callback(value, index, collection) === false) return result',
427
+ 'objectLoop': 'if (callback(value, index, collection) === false) return result'
428
+ };
429
+
430
+ /** Reusable iterator options for `defaults`, and `extend` */
431
+ var extendIteratorOptions = {
432
+ 'useHas': false,
433
+ 'args': 'object',
434
+ 'top':
435
+ 'for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {\n' +
436
+ ' if (iteratee = arguments[argsIndex]) {',
437
+ 'objectLoop': 'result[index] = value',
438
+ 'bottom': ' }\n}'
439
+ };
440
+
441
+ /** Reusable iterator options for `forIn` and `forOwn` */
442
+ var forOwnIteratorOptions = {
443
+ 'arrayLoop': null
444
+ };
445
+
446
+ /*--------------------------------------------------------------------------*/
447
+
448
+ /**
449
+ * Creates a function optimized to search large arrays for a given `value`,
450
+ * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
451
+ *
452
+ * @private
453
+ * @param {Array} array The array to search.
454
+ * @param {Mixed} value The value to search for.
455
+ * @param {Number} [fromIndex=0] The index to search from.
456
+ * @param {Number} [largeSize=30] The length at which an array is considered large.
457
+ * @returns {Boolean} Returns `true` if `value` is found, else `false`.
458
+ */
459
+ function cachedContains(array, fromIndex, largeSize) {
460
+ fromIndex || (fromIndex = 0);
461
+
462
+ var length = array.length,
463
+ isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
464
+
465
+ if (isLarge) {
466
+ var cache = {},
467
+ index = fromIndex - 1;
468
+
469
+ while (++index < length) {
470
+ // manually coerce `value` to a string because `hasOwnProperty`, in some
471
+ // older versions of Firefox, coerces objects incorrectly
472
+ var key = array[index] + '';
473
+ (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
474
+ }
475
+ }
476
+ return function(value) {
477
+ if (isLarge) {
478
+ var key = value + '';
479
+ return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
480
+ }
481
+ return indexOf(array, value, fromIndex) > -1;
482
+ }
483
+ }
484
+
485
+ /**
486
+ * Used by `_.max` and `_.min` as the default `callback` when a given
487
+ * `collection` is a string value.
488
+ *
489
+ * @private
490
+ * @param {String} value The character to inspect.
491
+ * @returns {Number} Returns the code unit of given character.
492
+ */
493
+ function charAtCallback(value) {
494
+ return value.charCodeAt(0);
495
+ }
496
+
497
+ /**
498
+ * Used by `sortBy` to compare transformed `collection` values, stable sorting
499
+ * them in ascending order.
500
+ *
501
+ * @private
502
+ * @param {Object} a The object to compare to `b`.
503
+ * @param {Object} b The object to compare to `a`.
504
+ * @returns {Number} Returns the sort order indicator of `1` or `-1`.
505
+ */
506
+ function compareAscending(a, b) {
507
+ var ai = a.index,
508
+ bi = b.index;
509
+
510
+ a = a.criteria;
511
+ b = b.criteria;
512
+
513
+ // ensure a stable sort in V8 and other engines
514
+ // http://code.google.com/p/v8/issues/detail?id=90
515
+ if (a !== b) {
516
+ if (a > b || a === undefined) {
517
+ return 1;
518
+ }
519
+ if (a < b || b === undefined) {
520
+ return -1;
521
+ }
522
+ }
523
+ return ai < bi ? -1 : 1;
524
+ }
525
+
526
+ /**
527
+ * Creates a function that, when called, invokes `func` with the `this`
528
+ * binding of `thisArg` and prepends any `partailArgs` to the arguments passed
529
+ * to the bound function.
530
+ *
531
+ * @private
532
+ * @param {Function|String} func The function to bind or the method name.
533
+ * @param {Mixed} [thisArg] The `this` binding of `func`.
534
+ * @param {Array} partialArgs An array of arguments to be partially applied.
535
+ * @returns {Function} Returns the new bound function.
536
+ */
537
+ function createBound(func, thisArg, partialArgs) {
538
+ var isFunc = isFunction(func),
539
+ isPartial = !partialArgs,
540
+ methodName = func;
541
+
542
+ // juggle arguments
543
+ if (isPartial) {
544
+ partialArgs = thisArg;
545
+ }
546
+
547
+ function bound() {
548
+ // `Function#bind` spec
549
+ // http://es5.github.com/#x15.3.4.5
550
+ var args = arguments,
551
+ thisBinding = isPartial ? this : thisArg;
552
+
553
+ if (!isFunc) {
554
+ func = thisArg[methodName];
555
+ }
556
+ if (partialArgs.length) {
557
+ args = args.length
558
+ ? partialArgs.concat(slice.call(args))
559
+ : partialArgs;
560
+ }
561
+ if (this instanceof bound) {
562
+ // get `func` instance if `bound` is invoked in a `new` expression
563
+ noop.prototype = func.prototype;
564
+ thisBinding = new noop;
565
+
566
+ // mimic the constructor's `return` behavior
567
+ // http://es5.github.com/#x13.2.2
568
+ var result = func.apply(thisBinding, args);
569
+ return isObject(result)
570
+ ? result
571
+ : thisBinding
572
+ }
573
+ return func.apply(thisBinding, args);
574
+ }
575
+ return bound;
576
+ }
577
+
578
+ /**
579
+ * Produces an iteration callback bound to an optional `thisArg`. If `func` is
580
+ * a property name, the callback will return the property value for a given element.
581
+ *
582
+ * @private
583
+ * @param {Function|String} [func=identity|property] The function called per
584
+ * iteration or property name to query.
585
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
586
+ * @returns {Function} Returns a callback function.
587
+ */
588
+ function createCallback(func, thisArg) {
589
+ if (!func) {
590
+ return identity;
591
+ }
592
+ if (typeof func != 'function') {
593
+ return function(object) {
594
+ return object[func];
595
+ };
596
+ }
597
+ if (thisArg !== undefined) {
598
+ return function(value, index, object) {
599
+ return func.call(thisArg, value, index, object);
600
+ };
601
+ }
602
+ return func;
603
+ }
604
+
605
+ /**
606
+ * Creates compiled iteration functions.
607
+ *
608
+ * @private
609
+ * @param {Object} [options1, options2, ...] The compile options object(s).
610
+ * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
611
+ * args - A string of comma separated arguments the iteration function will accept.
612
+ * top - A string of code to execute before the iteration branches.
613
+ * arrayLoop - A string of code to execute in the array loop.
614
+ * objectLoop - A string of code to execute in the object loop.
615
+ * bottom - A string of code to execute after the iteration branches.
616
+ *
617
+ * @returns {Function} Returns the compiled function.
618
+ */
619
+ function createIterator() {
620
+ var data = {
621
+ 'arrayLoop': '',
622
+ 'bottom': '',
623
+ 'hasDontEnumBug': hasDontEnumBug,
624
+ 'isKeysFast': isKeysFast,
625
+ 'objectLoop': '',
626
+ 'noArgsEnum': noArgsEnum,
627
+ 'noCharByIndex': noCharByIndex,
628
+ 'shadowed': shadowed,
629
+ 'top': '',
630
+ 'useHas': true
631
+ };
632
+
633
+ // merge options into a template data object
634
+ for (var object, index = 0; object = arguments[index]; index++) {
635
+ for (var key in object) {
636
+ data[key] = object[key];
637
+ }
638
+ }
639
+ var args = data.args;
640
+ data.firstArg = /^[^,]+/.exec(args)[0];
641
+
642
+ // create the function factory
643
+ var factory = Function(
644
+ 'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
645
+ 'nativeKeys, propertyIsEnumerable',
646
+ 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
647
+ );
648
+ // return the compiled function
649
+ return factory(
650
+ createCallback, hasOwnProperty, isArguments, isString, objectTypes,
651
+ nativeKeys, propertyIsEnumerable
652
+ );
653
+ }
654
+
655
+ /**
656
+ * Used by `template` to escape characters for inclusion in compiled
657
+ * string literals.
658
+ *
659
+ * @private
660
+ * @param {String} match The matched character to escape.
661
+ * @returns {String} Returns the escaped character.
662
+ */
663
+ function escapeStringChar(match) {
664
+ return '\\' + stringEscapes[match];
665
+ }
666
+
667
+ /**
668
+ * Used by `escape` to convert characters to HTML entities.
669
+ *
670
+ * @private
671
+ * @param {String} match The matched character to escape.
672
+ * @returns {String} Returns the escaped character.
673
+ */
674
+ function escapeHtmlChar(match) {
675
+ return htmlEscapes[match];
676
+ }
677
+
678
+ /**
679
+ * A no-operation function.
680
+ *
681
+ * @private
682
+ */
683
+ function noop() {
684
+ // no operation performed
685
+ }
686
+
687
+ /**
688
+ * Used by `unescape` to convert HTML entities to characters.
689
+ *
690
+ * @private
691
+ * @param {String} match The matched character to unescape.
692
+ * @returns {String} Returns the unescaped character.
693
+ */
694
+ function unescapeHtmlChar(match) {
695
+ return htmlUnescapes[match];
696
+ }
697
+
698
+ /*--------------------------------------------------------------------------*/
699
+
700
+ /**
701
+ * Checks if `value` is an `arguments` object.
702
+ *
703
+ * @static
704
+ * @memberOf _
705
+ * @category Objects
706
+ * @param {Mixed} value The value to check.
707
+ * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
708
+ * @example
709
+ *
710
+ * (function() { return _.isArguments(arguments); })(1, 2, 3);
711
+ * // => true
712
+ *
713
+ * _.isArguments([1, 2, 3]);
714
+ * // => false
715
+ */
716
+ function isArguments(value) {
717
+ return toString.call(value) == argsClass;
718
+ }
719
+ // fallback for browsers that can't detect `arguments` objects by [[Class]]
720
+ if (noArgsClass) {
721
+ isArguments = function(value) {
722
+ return value ? hasOwnProperty.call(value, 'callee') : false;
723
+ };
724
+ }
725
+
726
+ /**
727
+ * Iterates over `object`'s own and inherited enumerable properties, executing
728
+ * the `callback` for each property. The `callback` is bound to `thisArg` and
729
+ * invoked with three arguments; (value, key, object). Callbacks may exit iteration
730
+ * early by explicitly returning `false`.
731
+ *
732
+ * @static
733
+ * @memberOf _
734
+ * @category Objects
735
+ * @param {Object} object The object to iterate over.
736
+ * @param {Function} callback The function called per iteration.
737
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
738
+ * @returns {Object} Returns `object`.
739
+ * @example
740
+ *
741
+ * function Dog(name) {
742
+ * this.name = name;
743
+ * }
744
+ *
745
+ * Dog.prototype.bark = function() {
746
+ * alert('Woof, woof!');
747
+ * };
748
+ *
749
+ * _.forIn(new Dog('Dagny'), function(value, key) {
750
+ * alert(key);
751
+ * });
752
+ * // => alerts 'name' and 'bark' (order is not guaranteed)
753
+ */
754
+ var forIn = createIterator(forEachIteratorOptions, forOwnIteratorOptions, {
755
+ 'useHas': false
756
+ });
757
+
758
+ /**
759
+ * Iterates over `object`'s own enumerable properties, executing the `callback`
760
+ * for each property. The `callback` is bound to `thisArg` and invoked with three
761
+ * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
762
+ * returning `false`.
763
+ *
764
+ * @static
765
+ * @memberOf _
766
+ * @category Objects
767
+ * @param {Object} object The object to iterate over.
768
+ * @param {Function} callback The function called per iteration.
769
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
770
+ * @returns {Object} Returns `object`.
771
+ * @example
772
+ *
773
+ * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
774
+ * alert(key);
775
+ * });
776
+ * // => alerts '0', '1', and 'length' (order is not guaranteed)
777
+ */
778
+ var forOwn = createIterator(forEachIteratorOptions, forOwnIteratorOptions);
779
+
780
+ /**
781
+ * A fallback implementation of `isPlainObject` that checks if a given `value`
782
+ * is an object created by the `Object` constructor, assuming objects created
783
+ * by the `Object` constructor have no inherited enumerable properties and that
784
+ * there are no `Object.prototype` extensions.
785
+ *
786
+ * @private
787
+ * @param {Mixed} value The value to check.
788
+ * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
789
+ */
790
+ function shimIsPlainObject(value) {
791
+ // avoid non-objects and false positives for `arguments` objects
792
+ var result = false;
793
+ if (!(value && typeof value == 'object') || isArguments(value)) {
794
+ return result;
795
+ }
796
+ // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
797
+ // methods that are `typeof` "string" and still can coerce nodes to strings.
798
+ // Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
799
+ var ctor = value.constructor;
800
+ if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
801
+ (!isFunction(ctor) || ctor instanceof ctor)) {
802
+ // IE < 9 iterates inherited properties before own properties. If the first
803
+ // iterated property is an object's own property then there are no inherited
804
+ // enumerable properties.
805
+ if (iteratesOwnLast) {
806
+ forIn(value, function(value, key, object) {
807
+ result = !hasOwnProperty.call(object, key);
808
+ return false;
809
+ });
810
+ return result === false;
811
+ }
812
+ // In most environments an object's own properties are iterated before
813
+ // its inherited properties. If the last iterated property is an object's
814
+ // own property then there are no inherited enumerable properties.
815
+ forIn(value, function(value, key) {
816
+ result = key;
817
+ });
818
+ return result === false || hasOwnProperty.call(value, result);
819
+ }
820
+ return result;
821
+ }
822
+
823
+ /**
824
+ * A fallback implementation of `Object.keys` that produces an array of the
825
+ * given object's own enumerable property names.
826
+ *
827
+ * @private
828
+ * @param {Object} object The object to inspect.
829
+ * @returns {Array} Returns a new array of property names.
830
+ */
831
+ function shimKeys(object) {
832
+ var result = [];
833
+ forOwn(object, function(value, key) {
834
+ result.push(key);
835
+ });
836
+ return result;
837
+ }
838
+
839
+ /**
840
+ * Used to convert characters to HTML entities:
841
+ *
842
+ * Though the `>` character is escaped for symmetry, characters like `>` and `/`
843
+ * don't require escaping in HTML and have no special meaning unless they're part
844
+ * of a tag or an unquoted attribute value.
845
+ * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
846
+ */
847
+ var htmlEscapes = {
848
+ '&': '&amp;',
849
+ '<': '&lt;',
850
+ '>': '&gt;',
851
+ '"': '&quot;',
852
+ "'": '&#x27;'
853
+ };
854
+
855
+ /** Used to convert HTML entities to characters */
856
+ var htmlUnescapes = invert(htmlEscapes);
857
+
858
+ /*--------------------------------------------------------------------------*/
859
+
860
+ /**
861
+ * Creates a clone of `value`. If `deep` is `true`, all nested objects will
862
+ * also be cloned otherwise they will be assigned by reference. Functions, DOM
863
+ * nodes, `arguments` objects, and objects created by constructors other than
864
+ * `Object` are **not** cloned.
865
+ *
866
+ * @static
867
+ * @memberOf _
868
+ * @category Objects
869
+ * @param {Mixed} value The value to clone.
870
+ * @param {Boolean} deep A flag to indicate a deep clone.
871
+ * @param- {Object} [guard] Internally used to allow this method to work with
872
+ * others like `_.map` without using their callback `index` argument for `deep`.
873
+ * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
874
+ * @param- {Array} [stackB=[]] Internally used to associate clones with their
875
+ * source counterparts.
876
+ * @returns {Mixed} Returns the cloned `value`.
877
+ * @example
878
+ *
879
+ * var stooges = [
880
+ * { 'name': 'moe', 'age': 40 },
881
+ * { 'name': 'larry', 'age': 50 },
882
+ * { 'name': 'curly', 'age': 60 }
883
+ * ];
884
+ *
885
+ * _.clone({ 'name': 'moe' });
886
+ * // => { 'name': 'moe' }
887
+ *
888
+ * var shallow = _.clone(stooges);
889
+ * shallow[0] === stooges[0];
890
+ * // => true
891
+ *
892
+ * var deep = _.clone(stooges, true);
893
+ * shallow[0] === stooges[0];
894
+ * // => false
895
+ */
896
+ function clone(value, deep, guard, stackA, stackB) {
897
+ if (value == null) {
898
+ return value;
899
+ }
900
+ if (guard) {
901
+ deep = false;
902
+ }
903
+ // inspect [[Class]]
904
+ var isObj = isObject(value);
905
+ if (isObj) {
906
+ // don't clone `arguments` objects, functions, or non-object Objects
907
+ var className = toString.call(value);
908
+ if (!cloneableClasses[className] || (noArgsClass && isArguments(value))) {
909
+ return value;
910
+ }
911
+ var isArr = className == arrayClass;
912
+ isObj = isArr || (className == objectClass ? isPlainObject(value) : isObj);
913
+ }
914
+ // shallow clone
915
+ if (!isObj || !deep) {
916
+ // don't clone functions
917
+ return isObj
918
+ ? (isArr ? slice.call(value) : extend({}, value))
919
+ : value;
920
+ }
921
+
922
+ var ctor = value.constructor;
923
+ switch (className) {
924
+ case boolClass:
925
+ case dateClass:
926
+ return new ctor(+value);
927
+
928
+ case numberClass:
929
+ case stringClass:
930
+ return new ctor(value);
931
+
932
+ case regexpClass:
933
+ return ctor(value.source, reFlags.exec(value));
934
+ }
935
+ // check for circular references and return corresponding clone
936
+ stackA || (stackA = []);
937
+ stackB || (stackB = []);
938
+
939
+ var length = stackA.length;
940
+ while (length--) {
941
+ if (stackA[length] == value) {
942
+ return stackB[length];
943
+ }
944
+ }
945
+ // init cloned object
946
+ var result = isArr ? ctor(value.length) : {};
947
+
948
+ // add the source value to the stack of traversed objects
949
+ // and associate it with its clone
950
+ stackA.push(value);
951
+ stackB.push(result);
952
+
953
+ // recursively populate clone (susceptible to call stack limits)
954
+ (isArr ? forEach : forOwn)(value, function(objValue, key) {
955
+ result[key] = clone(objValue, deep, null, stackA, stackB);
956
+ });
957
+
958
+ return result;
959
+ }
960
+
961
+ /**
962
+ * Assigns enumerable properties of the default object(s) to the `destination`
963
+ * object for all `destination` properties that resolve to `null`/`undefined`.
964
+ * Once a property is set, additional defaults of the same property will be
965
+ * ignored.
966
+ *
967
+ * @static
968
+ * @memberOf _
969
+ * @category Objects
970
+ * @param {Object} object The destination object.
971
+ * @param {Object} [default1, default2, ...] The default objects.
972
+ * @returns {Object} Returns the destination object.
973
+ * @example
974
+ *
975
+ * var iceCream = { 'flavor': 'chocolate' };
976
+ * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' });
977
+ * // => { 'flavor': 'chocolate', 'sprinkles': 'rainbow' }
978
+ */
979
+ var defaults = createIterator(extendIteratorOptions, {
980
+ 'objectLoop': 'if (result[index] == null) ' + extendIteratorOptions.objectLoop
981
+ });
982
+
983
+ /**
984
+ * Assigns enumerable properties of the source object(s) to the `destination`
985
+ * object. Subsequent sources will overwrite propery assignments of previous
986
+ * sources.
987
+ *
988
+ * @static
989
+ * @memberOf _
990
+ * @category Objects
991
+ * @param {Object} object The destination object.
992
+ * @param {Object} [source1, source2, ...] The source objects.
993
+ * @returns {Object} Returns the destination object.
994
+ * @example
995
+ *
996
+ * _.extend({ 'name': 'moe' }, { 'age': 40 });
997
+ * // => { 'name': 'moe', 'age': 40 }
998
+ */
999
+ var extend = createIterator(extendIteratorOptions);
1000
+
1001
+ /**
1002
+ * Creates a sorted array of all enumerable properties, own and inherited,
1003
+ * of `object` that have function values.
1004
+ *
1005
+ * @static
1006
+ * @memberOf _
1007
+ * @alias methods
1008
+ * @category Objects
1009
+ * @param {Object} object The object to inspect.
1010
+ * @returns {Array} Returns a new array of property names that have function values.
1011
+ * @example
1012
+ *
1013
+ * _.functions(_);
1014
+ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
1015
+ */
1016
+ function functions(object) {
1017
+ var result = [];
1018
+ forIn(object, function(value, key) {
1019
+ if (isFunction(value)) {
1020
+ result.push(key);
1021
+ }
1022
+ });
1023
+ return result.sort();
1024
+ }
1025
+
1026
+ /**
1027
+ * Checks if the specified object `property` exists and is a direct property,
1028
+ * instead of an inherited property.
1029
+ *
1030
+ * @static
1031
+ * @memberOf _
1032
+ * @category Objects
1033
+ * @param {Object} object The object to check.
1034
+ * @param {String} property The property to check for.
1035
+ * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
1036
+ * @example
1037
+ *
1038
+ * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
1039
+ * // => true
1040
+ */
1041
+ function has(object, property) {
1042
+ return object ? hasOwnProperty.call(object, property) : false;
1043
+ }
1044
+
1045
+ /**
1046
+ * Creates an object composed of the inverted keys and values of the given `object`.
1047
+ *
1048
+ * @static
1049
+ * @memberOf _
1050
+ * @category Objects
1051
+ * @param {Object} object The object to invert.
1052
+ * @returns {Object} Returns the created inverted object.
1053
+ * @example
1054
+ *
1055
+ * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
1056
+ * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
1057
+ */
1058
+ function invert(object) {
1059
+ var result = {};
1060
+ forOwn(object, function(value, key) {
1061
+ result[value] = key;
1062
+ });
1063
+ return result;
1064
+ }
1065
+
1066
+ /**
1067
+ * Checks if `value` is an array.
1068
+ *
1069
+ * @static
1070
+ * @memberOf _
1071
+ * @category Objects
1072
+ * @param {Mixed} value The value to check.
1073
+ * @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
1074
+ * @example
1075
+ *
1076
+ * (function() { return _.isArray(arguments); })();
1077
+ * // => false
1078
+ *
1079
+ * _.isArray([1, 2, 3]);
1080
+ * // => true
1081
+ */
1082
+ var isArray = nativeIsArray || function(value) {
1083
+ return toString.call(value) == arrayClass;
1084
+ };
1085
+
1086
+ /**
1087
+ * Checks if `value` is a boolean (`true` or `false`) value.
1088
+ *
1089
+ * @static
1090
+ * @memberOf _
1091
+ * @category Objects
1092
+ * @param {Mixed} value The value to check.
1093
+ * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
1094
+ * @example
1095
+ *
1096
+ * _.isBoolean(null);
1097
+ * // => false
1098
+ */
1099
+ function isBoolean(value) {
1100
+ return value === true || value === false || toString.call(value) == boolClass;
1101
+ }
1102
+
1103
+ /**
1104
+ * Checks if `value` is a date.
1105
+ *
1106
+ * @static
1107
+ * @memberOf _
1108
+ * @category Objects
1109
+ * @param {Mixed} value The value to check.
1110
+ * @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
1111
+ * @example
1112
+ *
1113
+ * _.isDate(new Date);
1114
+ * // => true
1115
+ */
1116
+ function isDate(value) {
1117
+ return toString.call(value) == dateClass;
1118
+ }
1119
+
1120
+ /**
1121
+ * Checks if `value` is a DOM element.
1122
+ *
1123
+ * @static
1124
+ * @memberOf _
1125
+ * @category Objects
1126
+ * @param {Mixed} value The value to check.
1127
+ * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
1128
+ * @example
1129
+ *
1130
+ * _.isElement(document.body);
1131
+ * // => true
1132
+ */
1133
+ function isElement(value) {
1134
+ return value ? value.nodeType === 1 : false;
1135
+ }
1136
+
1137
+ /**
1138
+ * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
1139
+ * length of `0` and objects with no own enumerable properties are considered
1140
+ * "empty".
1141
+ *
1142
+ * @static
1143
+ * @memberOf _
1144
+ * @category Objects
1145
+ * @param {Array|Object|String} value The value to inspect.
1146
+ * @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
1147
+ * @example
1148
+ *
1149
+ * _.isEmpty([1, 2, 3]);
1150
+ * // => false
1151
+ *
1152
+ * _.isEmpty({});
1153
+ * // => true
1154
+ *
1155
+ * _.isEmpty('');
1156
+ * // => true
1157
+ */
1158
+ function isEmpty(value) {
1159
+ var result = true;
1160
+ if (!value) {
1161
+ return result;
1162
+ }
1163
+ var className = toString.call(value),
1164
+ length = value.length;
1165
+
1166
+ if ((className == arrayClass || className == stringClass ||
1167
+ className == argsClass || (noArgsClass && isArguments(value))) ||
1168
+ (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
1169
+ return !length;
1170
+ }
1171
+ forOwn(value, function() {
1172
+ return (result = false);
1173
+ });
1174
+ return result;
1175
+ }
1176
+
1177
+ /**
1178
+ * Performs a deep comparison between two values to determine if they are
1179
+ * equivalent to each other.
1180
+ *
1181
+ * @static
1182
+ * @memberOf _
1183
+ * @category Objects
1184
+ * @param {Mixed} a The value to compare.
1185
+ * @param {Mixed} b The other value to compare.
1186
+ * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
1187
+ * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
1188
+ * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
1189
+ * @example
1190
+ *
1191
+ * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
1192
+ * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
1193
+ *
1194
+ * moe == clone;
1195
+ * // => false
1196
+ *
1197
+ * _.isEqual(moe, clone);
1198
+ * // => true
1199
+ */
1200
+ function isEqual(a, b, stackA, stackB) {
1201
+ // exit early for identical values
1202
+ if (a === b) {
1203
+ // treat `+0` vs. `-0` as not equal
1204
+ return a !== 0 || (1 / a == 1 / b);
1205
+ }
1206
+ // a strict comparison is necessary because `null == undefined`
1207
+ if (a == null || b == null) {
1208
+ return a === b;
1209
+ }
1210
+ // compare [[Class]] names
1211
+ var className = toString.call(a);
1212
+ if (className != toString.call(b)) {
1213
+ return false;
1214
+ }
1215
+ switch (className) {
1216
+ case boolClass:
1217
+ case dateClass:
1218
+ // coerce dates and booleans to numbers, dates to milliseconds and booleans
1219
+ // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
1220
+ return +a == +b;
1221
+
1222
+ case numberClass:
1223
+ // treat `NaN` vs. `NaN` as equal
1224
+ return a != +a
1225
+ ? b != +b
1226
+ // but treat `+0` vs. `-0` as not equal
1227
+ : (a == 0 ? (1 / a == 1 / b) : a == +b);
1228
+
1229
+ case regexpClass:
1230
+ case stringClass:
1231
+ // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
1232
+ // treat string primitives and their corresponding object instances as equal
1233
+ return a == b + '';
1234
+ }
1235
+ // exit early, in older browsers, if `a` is array-like but not `b`
1236
+ var isArr = className == arrayClass || className == argsClass;
1237
+ if (noArgsClass && !isArr && (isArr = isArguments(a)) && !isArguments(b)) {
1238
+ return false;
1239
+ }
1240
+ if (!isArr) {
1241
+ // unwrap any `lodash` wrapped values
1242
+ if (a.__wrapped__ || b.__wrapped__) {
1243
+ return isEqual(a.__wrapped__ || a, b.__wrapped__ || b);
1244
+ }
1245
+ // exit for functions and DOM nodes
1246
+ if (className != objectClass || (noNodeClass && (
1247
+ (typeof a.toString != 'function' && typeof (a + '') == 'string') ||
1248
+ (typeof b.toString != 'function' && typeof (b + '') == 'string')))) {
1249
+ return false;
1250
+ }
1251
+ var ctorA = a.constructor,
1252
+ ctorB = b.constructor;
1253
+
1254
+ // non `Object` object instances with different constructors are not equal
1255
+ if (ctorA != ctorB && !(
1256
+ isFunction(ctorA) && ctorA instanceof ctorA &&
1257
+ isFunction(ctorB) && ctorB instanceof ctorB
1258
+ )) {
1259
+ return false;
1260
+ }
1261
+ }
1262
+ // assume cyclic structures are equal
1263
+ // the algorithm for detecting cyclic structures is adapted from ES 5.1
1264
+ // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
1265
+ stackA || (stackA = []);
1266
+ stackB || (stackB = []);
1267
+
1268
+ var length = stackA.length;
1269
+ while (length--) {
1270
+ if (stackA[length] == a) {
1271
+ return stackB[length] == b;
1272
+ }
1273
+ }
1274
+
1275
+ var index = -1,
1276
+ result = true,
1277
+ size = 0;
1278
+
1279
+ // add `a` and `b` to the stack of traversed objects
1280
+ stackA.push(a);
1281
+ stackB.push(b);
1282
+
1283
+ // recursively compare objects and arrays (susceptible to call stack limits)
1284
+ if (isArr) {
1285
+ // compare lengths to determine if a deep comparison is necessary
1286
+ size = a.length;
1287
+ result = size == b.length;
1288
+
1289
+ if (result) {
1290
+ // deep compare the contents, ignoring non-numeric properties
1291
+ while (size--) {
1292
+ if (!(result = isEqual(a[size], b[size], stackA, stackB))) {
1293
+ break;
1294
+ }
1295
+ }
1296
+ }
1297
+ return result;
1298
+ }
1299
+ // deep compare objects
1300
+ for (var key in a) {
1301
+ if (hasOwnProperty.call(a, key)) {
1302
+ // count the number of properties.
1303
+ size++;
1304
+ // deep compare each property value.
1305
+ if (!(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) {
1306
+ return false;
1307
+ }
1308
+ }
1309
+ }
1310
+ // ensure both objects have the same number of properties
1311
+ for (key in b) {
1312
+ // The JS engine in Adobe products, like InDesign, has a bug that causes
1313
+ // `!size--` to throw an error so it must be wrapped in parentheses.
1314
+ // https://github.com/documentcloud/underscore/issues/355
1315
+ if (hasOwnProperty.call(b, key) && !(size--)) {
1316
+ // `size` will be `-1` if `b` has more properties than `a`
1317
+ return false;
1318
+ }
1319
+ }
1320
+ // handle JScript [[DontEnum]] bug
1321
+ if (hasDontEnumBug) {
1322
+ while (++index < 7) {
1323
+ key = shadowed[index];
1324
+ if (hasOwnProperty.call(a, key) &&
1325
+ !(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) {
1326
+ return false;
1327
+ }
1328
+ }
1329
+ }
1330
+ return true;
1331
+ }
1332
+
1333
+ /**
1334
+ * Checks if `value` is, or can be coerced to, a finite number.
1335
+ *
1336
+ * Note: This is not the same as native `isFinite`, which will return true for
1337
+ * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
1338
+ *
1339
+ * @deprecated
1340
+ * @static
1341
+ * @memberOf _
1342
+ * @category Objects
1343
+ * @param {Mixed} value The value to check.
1344
+ * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
1345
+ * @example
1346
+ *
1347
+ * _.isFinite(-101);
1348
+ * // => true
1349
+ *
1350
+ * _.isFinite('10');
1351
+ * // => true
1352
+ *
1353
+ * _.isFinite(true);
1354
+ * // => false
1355
+ *
1356
+ * _.isFinite('');
1357
+ * // => false
1358
+ *
1359
+ * _.isFinite(Infinity);
1360
+ * // => false
1361
+ */
1362
+ function isFinite(value) {
1363
+ return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
1364
+ }
1365
+
1366
+ /**
1367
+ * Checks if `value` is a function.
1368
+ *
1369
+ * @static
1370
+ * @memberOf _
1371
+ * @category Objects
1372
+ * @param {Mixed} value The value to check.
1373
+ * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
1374
+ * @example
1375
+ *
1376
+ * _.isFunction(_);
1377
+ * // => true
1378
+ */
1379
+ function isFunction(value) {
1380
+ return typeof value == 'function';
1381
+ }
1382
+ // fallback for older versions of Chrome and Safari
1383
+ if (isFunction(/x/)) {
1384
+ isFunction = function(value) {
1385
+ return toString.call(value) == funcClass;
1386
+ };
1387
+ }
1388
+
1389
+ /**
1390
+ * Checks if `value` is the language type of Object.
1391
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1392
+ *
1393
+ * @static
1394
+ * @memberOf _
1395
+ * @category Objects
1396
+ * @param {Mixed} value The value to check.
1397
+ * @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
1398
+ * @example
1399
+ *
1400
+ * _.isObject({});
1401
+ * // => true
1402
+ *
1403
+ * _.isObject([1, 2, 3]);
1404
+ * // => true
1405
+ *
1406
+ * _.isObject(1);
1407
+ * // => false
1408
+ */
1409
+ function isObject(value) {
1410
+ // check if the value is the ECMAScript language type of Object
1411
+ // http://es5.github.com/#x8
1412
+ // and avoid a V8 bug
1413
+ // http://code.google.com/p/v8/issues/detail?id=2291
1414
+ return value ? objectTypes[typeof value] : false;
1415
+ }
1416
+
1417
+ /**
1418
+ * Checks if `value` is `NaN`.
1419
+ *
1420
+ * Note: This is not the same as native `isNaN`, which will return true for
1421
+ * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
1422
+ *
1423
+ * @deprecated
1424
+ * @static
1425
+ * @memberOf _
1426
+ * @category Objects
1427
+ * @param {Mixed} value The value to check.
1428
+ * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
1429
+ * @example
1430
+ *
1431
+ * _.isNaN(NaN);
1432
+ * // => true
1433
+ *
1434
+ * _.isNaN(new Number(NaN));
1435
+ * // => true
1436
+ *
1437
+ * isNaN(undefined);
1438
+ * // => true
1439
+ *
1440
+ * _.isNaN(undefined);
1441
+ * // => false
1442
+ */
1443
+ function isNaN(value) {
1444
+ // `NaN` as a primitive is the only value that is not equal to itself
1445
+ // (perform the [[Class]] check first to avoid errors with some host objects in IE)
1446
+ return toString.call(value) == numberClass && value != +value
1447
+ }
1448
+
1449
+ /**
1450
+ * Checks if `value` is `null`.
1451
+ *
1452
+ * @deprecated
1453
+ * @static
1454
+ * @memberOf _
1455
+ * @category Objects
1456
+ * @param {Mixed} value The value to check.
1457
+ * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
1458
+ * @example
1459
+ *
1460
+ * _.isNull(null);
1461
+ * // => true
1462
+ *
1463
+ * _.isNull(undefined);
1464
+ * // => false
1465
+ */
1466
+ function isNull(value) {
1467
+ return value === null;
1468
+ }
1469
+
1470
+ /**
1471
+ * Checks if `value` is a number.
1472
+ *
1473
+ * @static
1474
+ * @memberOf _
1475
+ * @category Objects
1476
+ * @param {Mixed} value The value to check.
1477
+ * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
1478
+ * @example
1479
+ *
1480
+ * _.isNumber(8.4 * 5);
1481
+ * // => true
1482
+ */
1483
+ function isNumber(value) {
1484
+ return toString.call(value) == numberClass;
1485
+ }
1486
+
1487
+ /**
1488
+ * Checks if a given `value` is an object created by the `Object` constructor.
1489
+ *
1490
+ * @static
1491
+ * @memberOf _
1492
+ * @category Objects
1493
+ * @param {Mixed} value The value to check.
1494
+ * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
1495
+ * @example
1496
+ *
1497
+ * function Stooge(name, age) {
1498
+ * this.name = name;
1499
+ * this.age = age;
1500
+ * }
1501
+ *
1502
+ * _.isPlainObject(new Stooge('moe', 40));
1503
+ * // => false
1504
+ *
1505
+ * _.isPlainObject([1, 2, 3]);
1506
+ * // => false
1507
+ *
1508
+ * _.isPlainObject({ 'name': 'moe', 'age': 40 });
1509
+ * // => true
1510
+ */
1511
+ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
1512
+ if (!(value && typeof value == 'object')) {
1513
+ return false;
1514
+ }
1515
+ var valueOf = value.valueOf,
1516
+ objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
1517
+
1518
+ return objProto
1519
+ ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
1520
+ : shimIsPlainObject(value);
1521
+ };
1522
+
1523
+ /**
1524
+ * Checks if `value` is a regular expression.
1525
+ *
1526
+ * @static
1527
+ * @memberOf _
1528
+ * @category Objects
1529
+ * @param {Mixed} value The value to check.
1530
+ * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
1531
+ * @example
1532
+ *
1533
+ * _.isRegExp(/moe/);
1534
+ * // => true
1535
+ */
1536
+ function isRegExp(value) {
1537
+ return toString.call(value) == regexpClass;
1538
+ }
1539
+
1540
+ /**
1541
+ * Checks if `value` is a string.
1542
+ *
1543
+ * @static
1544
+ * @memberOf _
1545
+ * @category Objects
1546
+ * @param {Mixed} value The value to check.
1547
+ * @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
1548
+ * @example
1549
+ *
1550
+ * _.isString('moe');
1551
+ * // => true
1552
+ */
1553
+ function isString(value) {
1554
+ return toString.call(value) == stringClass;
1555
+ }
1556
+
1557
+ /**
1558
+ * Checks if `value` is `undefined`.
1559
+ *
1560
+ * @deprecated
1561
+ * @static
1562
+ * @memberOf _
1563
+ * @category Objects
1564
+ * @param {Mixed} value The value to check.
1565
+ * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
1566
+ * @example
1567
+ *
1568
+ * _.isUndefined(void 0);
1569
+ * // => true
1570
+ */
1571
+ function isUndefined(value) {
1572
+ return value === undefined;
1573
+ }
1574
+
1575
+ /**
1576
+ * Creates an array composed of the own enumerable property names of `object`.
1577
+ *
1578
+ * @static
1579
+ * @memberOf _
1580
+ * @category Objects
1581
+ * @param {Object} object The object to inspect.
1582
+ * @returns {Array} Returns a new array of property names.
1583
+ * @example
1584
+ *
1585
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
1586
+ * // => ['one', 'two', 'three'] (order is not guaranteed)
1587
+ */
1588
+ var keys = !nativeKeys ? shimKeys : function(object) {
1589
+ // avoid iterating over the `prototype` property
1590
+ return typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype')
1591
+ ? shimKeys(object)
1592
+ : (isObject(object) ? nativeKeys(object) : []);
1593
+ };
1594
+
1595
+ /**
1596
+ * Merges enumerable properties of the source object(s) into the `destination`
1597
+ * object. Subsequent sources will overwrite propery assignments of previous
1598
+ * sources.
1599
+ *
1600
+ * @static
1601
+ * @memberOf _
1602
+ * @category Objects
1603
+ * @param {Object} object The destination object.
1604
+ * @param {Object} [source1, source2, ...] The source objects.
1605
+ * @param- {Object} [indicator] Internally used to indicate that the `stack`
1606
+ * argument is an array of traversed objects instead of another source object.
1607
+ * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
1608
+ * @param- {Array} [stackB=[]] Internally used to associate values with their
1609
+ * source counterparts.
1610
+ * @returns {Object} Returns the destination object.
1611
+ * @example
1612
+ *
1613
+ * var stooges = [
1614
+ * { 'name': 'moe' },
1615
+ * { 'name': 'larry' }
1616
+ * ];
1617
+ *
1618
+ * var ages = [
1619
+ * { 'age': 40 },
1620
+ * { 'age': 50 }
1621
+ * ];
1622
+ *
1623
+ * _.merge(stooges, ages);
1624
+ * // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }]
1625
+ */
1626
+ function merge(object, source, indicator) {
1627
+ var args = arguments,
1628
+ index = 0,
1629
+ length = 2,
1630
+ stackA = args[3],
1631
+ stackB = args[4];
1632
+
1633
+ if (indicator !== objectRef) {
1634
+ stackA = [];
1635
+ stackB = [];
1636
+ length = args.length;
1637
+ }
1638
+ while (++index < length) {
1639
+ forOwn(args[index], function(source, key) {
1640
+ var found, isArr, value;
1641
+ if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
1642
+ // avoid merging previously merged cyclic sources
1643
+ var stackLength = stackA.length;
1644
+ while (stackLength--) {
1645
+ found = stackA[stackLength] == source;
1646
+ if (found) {
1647
+ break;
1648
+ }
1649
+ }
1650
+ if (found) {
1651
+ object[key] = stackB[stackLength];
1652
+ }
1653
+ else {
1654
+ // add `source` and associated `value` to the stack of traversed objects
1655
+ stackA.push(source);
1656
+ stackB.push(value = (value = object[key], isArr)
1657
+ ? (isArray(value) ? value : [])
1658
+ : (isPlainObject(value) ? value : {})
1659
+ );
1660
+ // recursively merge objects and arrays (susceptible to call stack limits)
1661
+ object[key] = merge(value, source, objectRef, stackA, stackB);
1662
+ }
1663
+ } else if (source != null) {
1664
+ object[key] = source;
1665
+ }
1666
+ });
1667
+ }
1668
+ return object;
1669
+ }
1670
+
1671
+ /**
1672
+ * Creates a shallow clone of `object` excluding the specified properties.
1673
+ * Property names may be specified as individual arguments or as arrays of
1674
+ * property names. If `callback` is passed, it will be executed for each property
1675
+ * in the `object`, omitting the properties `callback` returns truthy for. The
1676
+ * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
1677
+ *
1678
+ * @static
1679
+ * @memberOf _
1680
+ * @category Objects
1681
+ * @param {Object} object The source object.
1682
+ * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
1683
+ * or the function called per iteration.
1684
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1685
+ * @returns {Object} Returns an object without the omitted properties.
1686
+ * @example
1687
+ *
1688
+ * _.omit({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
1689
+ * // => { 'name': 'moe', 'age': 40 }
1690
+ *
1691
+ * _.omit({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
1692
+ * return key.charAt(0) == '_';
1693
+ * });
1694
+ * // => { 'name': 'moe' }
1695
+ */
1696
+ function omit(object, callback, thisArg) {
1697
+ var isFunc = typeof callback == 'function',
1698
+ result = {};
1699
+
1700
+ if (isFunc) {
1701
+ callback = createCallback(callback, thisArg);
1702
+ } else {
1703
+ var props = concat.apply(arrayRef, arguments);
1704
+ }
1705
+ forIn(object, function(value, key, object) {
1706
+ if (isFunc
1707
+ ? !callback(value, key, object)
1708
+ : indexOf(props, key, 1) < 0
1709
+ ) {
1710
+ result[key] = value;
1711
+ }
1712
+ });
1713
+ return result;
1714
+ }
1715
+
1716
+ /**
1717
+ * Creates a two dimensional array of the given object's key-value pairs,
1718
+ * i.e. `[[key1, value1], [key2, value2]]`.
1719
+ *
1720
+ * @static
1721
+ * @memberOf _
1722
+ * @category Objects
1723
+ * @param {Object} object The object to inspect.
1724
+ * @returns {Array} Returns new array of key-value pairs.
1725
+ * @example
1726
+ *
1727
+ * _.pairs({ 'moe': 30, 'larry': 40, 'curly': 50 });
1728
+ * // => [['moe', 30], ['larry', 40], ['curly', 50]] (order is not guaranteed)
1729
+ */
1730
+ function pairs(object) {
1731
+ var result = [];
1732
+ forOwn(object, function(value, key) {
1733
+ result.push([key, value]);
1734
+ });
1735
+ return result;
1736
+ }
1737
+
1738
+ /**
1739
+ * Creates a shallow clone of `object` composed of the specified properties.
1740
+ * Property names may be specified as individual arguments or as arrays of
1741
+ * property names. If `callback` is passed, it will be executed for each property
1742
+ * in the `object`, picking the properties `callback` returns truthy for. The
1743
+ * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
1744
+ *
1745
+ * @static
1746
+ * @memberOf _
1747
+ * @category Objects
1748
+ * @param {Object} object The source object.
1749
+ * @param {Function|String} callback|[prop1, prop2, ...] The properties to pick
1750
+ * or the function called per iteration.
1751
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1752
+ * @returns {Object} Returns an object composed of the picked properties.
1753
+ * @example
1754
+ *
1755
+ * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
1756
+ * // => { 'name': 'moe', 'age': 40 }
1757
+ *
1758
+ * _.pick({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
1759
+ * return key.charAt(0) != '_';
1760
+ * });
1761
+ * // => { 'name': 'moe' }
1762
+ */
1763
+ function pick(object, callback, thisArg) {
1764
+ var result = {};
1765
+ if (typeof callback != 'function') {
1766
+ var index = 0,
1767
+ props = concat.apply(arrayRef, arguments),
1768
+ length = props.length;
1769
+
1770
+ while (++index < length) {
1771
+ var key = props[index];
1772
+ if (key in object) {
1773
+ result[key] = object[key];
1774
+ }
1775
+ }
1776
+ } else {
1777
+ callback = createCallback(callback, thisArg);
1778
+ forIn(object, function(value, key, object) {
1779
+ if (callback(value, key, object)) {
1780
+ result[key] = value;
1781
+ }
1782
+ });
1783
+ }
1784
+ return result;
1785
+ }
1786
+
1787
+ /**
1788
+ * Creates an array composed of the own enumerable property values of `object`.
1789
+ *
1790
+ * @static
1791
+ * @memberOf _
1792
+ * @category Objects
1793
+ * @param {Object} object The object to inspect.
1794
+ * @returns {Array} Returns a new array of property values.
1795
+ * @example
1796
+ *
1797
+ * _.values({ 'one': 1, 'two': 2, 'three': 3 });
1798
+ * // => [1, 2, 3]
1799
+ */
1800
+ function values(object) {
1801
+ var result = [];
1802
+ forOwn(object, function(value) {
1803
+ result.push(value);
1804
+ });
1805
+ return result;
1806
+ }
1807
+
1808
+ /*--------------------------------------------------------------------------*/
1809
+
1810
+ /**
1811
+ * Checks if a given `target` element is present in a `collection` using strict
1812
+ * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
1813
+ * as the offset from the end of the collection.
1814
+ *
1815
+ * @static
1816
+ * @memberOf _
1817
+ * @alias include
1818
+ * @category Collections
1819
+ * @param {Array|Object|String} collection The collection to iterate over.
1820
+ * @param {Mixed} target The value to check for.
1821
+ * @param {Number} [fromIndex=0] The index to search from.
1822
+ * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
1823
+ * @example
1824
+ *
1825
+ * _.contains([1, 2, 3], 1);
1826
+ * // => true
1827
+ *
1828
+ * _.contains([1, 2, 3], 1, 2);
1829
+ * // => false
1830
+ *
1831
+ * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
1832
+ * // => true
1833
+ *
1834
+ * _.contains('curly', 'ur');
1835
+ * // => true
1836
+ */
1837
+ function contains(collection, target, fromIndex) {
1838
+ var index = -1,
1839
+ length = collection ? collection.length : 0;
1840
+
1841
+ fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
1842
+ if (typeof length == 'number') {
1843
+ return (isString(collection)
1844
+ ? collection.indexOf(target, fromIndex)
1845
+ : indexOf(collection, target, fromIndex)
1846
+ ) > -1;
1847
+ }
1848
+ return some(collection, function(value) {
1849
+ return ++index >= fromIndex && value === target;
1850
+ });
1851
+ }
1852
+
1853
+ /**
1854
+ * Creates an object composed of keys returned from running each element of
1855
+ * `collection` through a `callback`. The corresponding value of each key is
1856
+ * the number of times the key was returned by `callback`. The `callback` is
1857
+ * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
1858
+ * The `callback` argument may also be the name of a property to count by (e.g. 'length').
1859
+ *
1860
+ * @static
1861
+ * @memberOf _
1862
+ * @category Collections
1863
+ * @param {Array|Object|String} collection The collection to iterate over.
1864
+ * @param {Function|String} callback|property The function called per iteration
1865
+ * or property name to count by.
1866
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1867
+ * @returns {Object} Returns the composed aggregate object.
1868
+ * @example
1869
+ *
1870
+ * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
1871
+ * // => { '4': 1, '6': 2 }
1872
+ *
1873
+ * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
1874
+ * // => { '4': 1, '6': 2 }
1875
+ *
1876
+ * _.countBy(['one', 'two', 'three'], 'length');
1877
+ * // => { '3': 2, '5': 1 }
1878
+ */
1879
+ function countBy(collection, callback, thisArg) {
1880
+ var result = {};
1881
+ callback = createCallback(callback, thisArg);
1882
+ forEach(collection, function(value, key, collection) {
1883
+ key = callback(value, key, collection);
1884
+ (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
1885
+ });
1886
+ return result;
1887
+ }
1888
+
1889
+ /**
1890
+ * Checks if the `callback` returns a truthy value for **all** elements of a
1891
+ * `collection`. The `callback` is bound to `thisArg` and invoked with three
1892
+ * arguments; (value, index|key, collection).
1893
+ *
1894
+ * @static
1895
+ * @memberOf _
1896
+ * @alias all
1897
+ * @category Collections
1898
+ * @param {Array|Object|String} collection The collection to iterate over.
1899
+ * @param {Function} [callback=identity] The function called per iteration.
1900
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1901
+ * @returns {Boolean} Returns `true` if all elements pass the callback check,
1902
+ * else `false`.
1903
+ * @example
1904
+ *
1905
+ * _.every([true, 1, null, 'yes'], Boolean);
1906
+ * // => false
1907
+ */
1908
+ function every(collection, callback, thisArg) {
1909
+ var result = true;
1910
+ callback = createCallback(callback, thisArg);
1911
+
1912
+ if (isArray(collection)) {
1913
+ var index = -1,
1914
+ length = collection.length;
1915
+
1916
+ while (++index < length) {
1917
+ if (!(result = !!callback(collection[index], index, collection))) {
1918
+ break;
1919
+ }
1920
+ }
1921
+ } else {
1922
+ forEach(collection, function(value, index, collection) {
1923
+ return (result = !!callback(value, index, collection));
1924
+ });
1925
+ }
1926
+ return result;
1927
+ }
1928
+
1929
+ /**
1930
+ * Examines each element in a `collection`, returning an array of all elements
1931
+ * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
1932
+ * invoked with three arguments; (value, index|key, collection).
1933
+ *
1934
+ * @static
1935
+ * @memberOf _
1936
+ * @alias select
1937
+ * @category Collections
1938
+ * @param {Array|Object|String} collection The collection to iterate over.
1939
+ * @param {Function} [callback=identity] The function called per iteration.
1940
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1941
+ * @returns {Array} Returns a new array of elements that passed the callback check.
1942
+ * @example
1943
+ *
1944
+ * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
1945
+ * // => [2, 4, 6]
1946
+ */
1947
+ function filter(collection, callback, thisArg) {
1948
+ var result = [];
1949
+ callback = createCallback(callback, thisArg);
1950
+ forEach(collection, function(value, index, collection) {
1951
+ if (callback(value, index, collection)) {
1952
+ result.push(value);
1953
+ }
1954
+ });
1955
+ return result;
1956
+ }
1957
+
1958
+ /**
1959
+ * Examines each element in a `collection`, returning the first one the `callback`
1960
+ * returns truthy for. The function returns as soon as it finds an acceptable
1961
+ * element, and does not iterate over the entire `collection`. The `callback` is
1962
+ * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
1963
+ *
1964
+ * @static
1965
+ * @memberOf _
1966
+ * @alias detect
1967
+ * @category Collections
1968
+ * @param {Array|Object|String} collection The collection to iterate over.
1969
+ * @param {Function} callback The function called per iteration.
1970
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1971
+ * @returns {Mixed} Returns the element that passed the callback check,
1972
+ * else `undefined`.
1973
+ * @example
1974
+ *
1975
+ * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
1976
+ * // => 2
1977
+ */
1978
+ function find(collection, callback, thisArg) {
1979
+ var result;
1980
+ callback = createCallback(callback, thisArg);
1981
+ forEach(collection, function(value, index, collection) {
1982
+ if (callback(value, index, collection)) {
1983
+ result = value;
1984
+ return false;
1985
+ }
1986
+ });
1987
+ return result;
1988
+ }
1989
+
1990
+ /**
1991
+ * Iterates over a `collection`, executing the `callback` for each element in
1992
+ * the `collection`. The `callback` is bound to `thisArg` and invoked with three
1993
+ * arguments; (value, index|key, collection). Callbacks may exit iteration early
1994
+ * by explicitly returning `false`.
1995
+ *
1996
+ * @static
1997
+ * @memberOf _
1998
+ * @alias each
1999
+ * @category Collections
2000
+ * @param {Array|Object|String} collection The collection to iterate over.
2001
+ * @param {Function} callback The function called per iteration.
2002
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2003
+ * @returns {Array|Object|String} Returns `collection`.
2004
+ * @example
2005
+ *
2006
+ * _([1, 2, 3]).forEach(alert).join(',');
2007
+ * // => alerts each number and returns '1,2,3'
2008
+ *
2009
+ * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
2010
+ * // => alerts each number (order is not guaranteed)
2011
+ */
2012
+ var forEach = createIterator(forEachIteratorOptions);
2013
+
2014
+ /**
2015
+ * Creates an object composed of keys returned from running each element of
2016
+ * `collection` through a `callback`. The corresponding value of each key is an
2017
+ * array of elements passed to `callback` that returned the key. The `callback`
2018
+ * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2019
+ * The `callback` argument may also be the name of a property to group by (e.g. 'length').
2020
+ *
2021
+ * @static
2022
+ * @memberOf _
2023
+ * @category Collections
2024
+ * @param {Array|Object|String} collection The collection to iterate over.
2025
+ * @param {Function|String} callback|property The function called per iteration
2026
+ * or property name to group by.
2027
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2028
+ * @returns {Object} Returns the composed aggregate object.
2029
+ * @example
2030
+ *
2031
+ * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
2032
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
2033
+ *
2034
+ * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
2035
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
2036
+ *
2037
+ * _.groupBy(['one', 'two', 'three'], 'length');
2038
+ * // => { '3': ['one', 'two'], '5': ['three'] }
2039
+ */
2040
+ function groupBy(collection, callback, thisArg) {
2041
+ var result = {};
2042
+ callback = createCallback(callback, thisArg);
2043
+ forEach(collection, function(value, key, collection) {
2044
+ key = callback(value, key, collection);
2045
+ (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
2046
+ });
2047
+ return result;
2048
+ }
2049
+
2050
+ /**
2051
+ * Invokes the method named by `methodName` on each element in the `collection`,
2052
+ * returning an array of the results of each invoked method. Additional arguments
2053
+ * will be passed to each invoked method. If `methodName` is a function it will
2054
+ * be invoked for, and `this` bound to, each element in the `collection`.
2055
+ *
2056
+ * @static
2057
+ * @memberOf _
2058
+ * @category Collections
2059
+ * @param {Array|Object|String} collection The collection to iterate over.
2060
+ * @param {Function|String} methodName The name of the method to invoke or
2061
+ * the function invoked per iteration.
2062
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
2063
+ * @returns {Array} Returns a new array of the results of each invoked method.
2064
+ * @example
2065
+ *
2066
+ * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
2067
+ * // => [[1, 5, 7], [1, 2, 3]]
2068
+ *
2069
+ * _.invoke([123, 456], String.prototype.split, '');
2070
+ * // => [['1', '2', '3'], ['4', '5', '6']]
2071
+ */
2072
+ function invoke(collection, methodName) {
2073
+ var args = slice.call(arguments, 2),
2074
+ isFunc = typeof methodName == 'function',
2075
+ result = [];
2076
+
2077
+ forEach(collection, function(value) {
2078
+ result.push((isFunc ? methodName : value[methodName]).apply(value, args));
2079
+ });
2080
+ return result;
2081
+ }
2082
+
2083
+ /**
2084
+ * Creates an array of values by running each element in the `collection`
2085
+ * through a `callback`. The `callback` is bound to `thisArg` and invoked with
2086
+ * three arguments; (value, index|key, collection).
2087
+ *
2088
+ * @static
2089
+ * @memberOf _
2090
+ * @alias collect
2091
+ * @category Collections
2092
+ * @param {Array|Object|String} collection The collection to iterate over.
2093
+ * @param {Function} [callback=identity] The function called per iteration.
2094
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2095
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
2096
+ * @example
2097
+ *
2098
+ * _.map([1, 2, 3], function(num) { return num * 3; });
2099
+ * // => [3, 6, 9]
2100
+ *
2101
+ * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
2102
+ * // => [3, 6, 9] (order is not guaranteed)
2103
+ */
2104
+ function map(collection, callback, thisArg) {
2105
+ var index = -1,
2106
+ length = collection ? collection.length : 0,
2107
+ result = Array(typeof length == 'number' ? length : 0);
2108
+
2109
+ callback = createCallback(callback, thisArg);
2110
+ if (isArray(collection)) {
2111
+ while (++index < length) {
2112
+ result[index] = callback(collection[index], index, collection);
2113
+ }
2114
+ } else {
2115
+ forEach(collection, function(value, key, collection) {
2116
+ result[++index] = callback(value, key, collection);
2117
+ });
2118
+ }
2119
+ return result;
2120
+ }
2121
+
2122
+ /**
2123
+ * Retrieves the maximum value of an `array`. If `callback` is passed,
2124
+ * it will be executed for each value in the `array` to generate the
2125
+ * criterion by which the value is ranked. The `callback` is bound to
2126
+ * `thisArg` and invoked with three arguments; (value, index, collection).
2127
+ *
2128
+ * @static
2129
+ * @memberOf _
2130
+ * @category Collections
2131
+ * @param {Array|Object|String} collection The collection to iterate over.
2132
+ * @param {Function} [callback] The function called per iteration.
2133
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2134
+ * @returns {Mixed} Returns the maximum value.
2135
+ * @example
2136
+ *
2137
+ * var stooges = [
2138
+ * { 'name': 'moe', 'age': 40 },
2139
+ * { 'name': 'larry', 'age': 50 },
2140
+ * { 'name': 'curly', 'age': 60 }
2141
+ * ];
2142
+ *
2143
+ * _.max(stooges, function(stooge) { return stooge.age; });
2144
+ * // => { 'name': 'curly', 'age': 60 };
2145
+ */
2146
+ function max(collection, callback, thisArg) {
2147
+ var computed = -Infinity,
2148
+ index = -1,
2149
+ length = collection ? collection.length : 0,
2150
+ result = computed;
2151
+
2152
+ if (callback || !isArray(collection)) {
2153
+ callback = !callback && isString(collection)
2154
+ ? charAtCallback
2155
+ : createCallback(callback, thisArg);
2156
+
2157
+ forEach(collection, function(value, index, collection) {
2158
+ var current = callback(value, index, collection);
2159
+ if (current > computed) {
2160
+ computed = current;
2161
+ result = value;
2162
+ }
2163
+ });
2164
+ } else {
2165
+ while (++index < length) {
2166
+ if (collection[index] > result) {
2167
+ result = collection[index];
2168
+ }
2169
+ }
2170
+ }
2171
+ return result;
2172
+ }
2173
+
2174
+ /**
2175
+ * Retrieves the minimum value of an `array`. If `callback` is passed,
2176
+ * it will be executed for each value in the `array` to generate the
2177
+ * criterion by which the value is ranked. The `callback` is bound to `thisArg`
2178
+ * and invoked with three arguments; (value, index, collection).
2179
+ *
2180
+ * @static
2181
+ * @memberOf _
2182
+ * @category Collections
2183
+ * @param {Array|Object|String} collection The collection to iterate over.
2184
+ * @param {Function} [callback] The function called per iteration.
2185
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2186
+ * @returns {Mixed} Returns the minimum value.
2187
+ * @example
2188
+ *
2189
+ * _.min([10, 5, 100, 2, 1000]);
2190
+ * // => 2
2191
+ */
2192
+ function min(collection, callback, thisArg) {
2193
+ var computed = Infinity,
2194
+ index = -1,
2195
+ length = collection ? collection.length : 0,
2196
+ result = computed;
2197
+
2198
+ if (callback || !isArray(collection)) {
2199
+ callback = !callback && isString(collection)
2200
+ ? charAtCallback
2201
+ : createCallback(callback, thisArg);
2202
+
2203
+ forEach(collection, function(value, index, collection) {
2204
+ var current = callback(value, index, collection);
2205
+ if (current < computed) {
2206
+ computed = current;
2207
+ result = value;
2208
+ }
2209
+ });
2210
+ } else {
2211
+ while (++index < length) {
2212
+ if (collection[index] < result) {
2213
+ result = collection[index];
2214
+ }
2215
+ }
2216
+ }
2217
+ return result;
2218
+ }
2219
+
2220
+ /**
2221
+ * Retrieves the value of a specified property from all elements in
2222
+ * the `collection`.
2223
+ *
2224
+ * @static
2225
+ * @memberOf _
2226
+ * @category Collections
2227
+ * @param {Array|Object|String} collection The collection to iterate over.
2228
+ * @param {String} property The property to pluck.
2229
+ * @returns {Array} Returns a new array of property values.
2230
+ * @example
2231
+ *
2232
+ * var stooges = [
2233
+ * { 'name': 'moe', 'age': 40 },
2234
+ * { 'name': 'larry', 'age': 50 },
2235
+ * { 'name': 'curly', 'age': 60 }
2236
+ * ];
2237
+ *
2238
+ * _.pluck(stooges, 'name');
2239
+ * // => ['moe', 'larry', 'curly']
2240
+ */
2241
+ function pluck(collection, property) {
2242
+ var result = [];
2243
+ forEach(collection, function(value) {
2244
+ result.push(value[property]);
2245
+ });
2246
+ return result;
2247
+ }
2248
+
2249
+ /**
2250
+ * Boils down a `collection` to a single value. The initial state of the
2251
+ * reduction is `accumulator` and each successive step of it should be returned
2252
+ * by the `callback`. The `callback` is bound to `thisArg` and invoked with 4
2253
+ * arguments; for arrays they are (accumulator, value, index|key, collection).
2254
+ *
2255
+ * @static
2256
+ * @memberOf _
2257
+ * @alias foldl, inject
2258
+ * @category Collections
2259
+ * @param {Array|Object|String} collection The collection to iterate over.
2260
+ * @param {Function} callback The function called per iteration.
2261
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
2262
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2263
+ * @returns {Mixed} Returns the accumulated value.
2264
+ * @example
2265
+ *
2266
+ * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
2267
+ * // => 6
2268
+ */
2269
+ function reduce(collection, callback, accumulator, thisArg) {
2270
+ var noaccum = arguments.length < 3;
2271
+ callback = createCallback(callback, thisArg);
2272
+ forEach(collection, function(value, index, collection) {
2273
+ accumulator = noaccum
2274
+ ? (noaccum = false, value)
2275
+ : callback(accumulator, value, index, collection)
2276
+ });
2277
+ return accumulator;
2278
+ }
2279
+
2280
+ /**
2281
+ * The right-associative version of `_.reduce`.
2282
+ *
2283
+ * @static
2284
+ * @memberOf _
2285
+ * @alias foldr
2286
+ * @category Collections
2287
+ * @param {Array|Object|String} collection The collection to iterate over.
2288
+ * @param {Function} callback The function called per iteration.
2289
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
2290
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2291
+ * @returns {Mixed} Returns the accumulated value.
2292
+ * @example
2293
+ *
2294
+ * var list = [[0, 1], [2, 3], [4, 5]];
2295
+ * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
2296
+ * // => [4, 5, 2, 3, 0, 1]
2297
+ */
2298
+ function reduceRight(collection, callback, accumulator, thisArg) {
2299
+ var iteratee = collection,
2300
+ length = collection ? collection.length : 0,
2301
+ noaccum = arguments.length < 3;
2302
+
2303
+ if (typeof length != 'number') {
2304
+ var props = keys(collection);
2305
+ length = props.length;
2306
+ } else if (noCharByIndex && isString(collection)) {
2307
+ iteratee = collection.split('');
2308
+ }
2309
+ forEach(collection, function(value, index, collection) {
2310
+ index = props ? props[--length] : --length;
2311
+ accumulator = noaccum
2312
+ ? (noaccum = false, iteratee[index])
2313
+ : callback.call(thisArg, accumulator, iteratee[index], index, collection);
2314
+ });
2315
+ return accumulator;
2316
+ }
2317
+
2318
+ /**
2319
+ * The opposite of `_.filter`, this method returns the values of a
2320
+ * `collection` that `callback` does **not** return truthy for.
2321
+ *
2322
+ * @static
2323
+ * @memberOf _
2324
+ * @category Collections
2325
+ * @param {Array|Object|String} collection The collection to iterate over.
2326
+ * @param {Function} [callback=identity] The function called per iteration.
2327
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2328
+ * @returns {Array} Returns a new array of elements that did **not** pass the
2329
+ * callback check.
2330
+ * @example
2331
+ *
2332
+ * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2333
+ * // => [1, 3, 5]
2334
+ */
2335
+ function reject(collection, callback, thisArg) {
2336
+ callback = createCallback(callback, thisArg);
2337
+ return filter(collection, function(value, index, collection) {
2338
+ return !callback(value, index, collection);
2339
+ });
2340
+ }
2341
+
2342
+ /**
2343
+ * Creates an array of shuffled `array` values, using a version of the
2344
+ * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
2345
+ *
2346
+ * @static
2347
+ * @memberOf _
2348
+ * @category Collections
2349
+ * @param {Array|Object|String} collection The collection to shuffle.
2350
+ * @returns {Array} Returns a new shuffled collection.
2351
+ * @example
2352
+ *
2353
+ * _.shuffle([1, 2, 3, 4, 5, 6]);
2354
+ * // => [4, 1, 6, 3, 5, 2]
2355
+ */
2356
+ function shuffle(collection) {
2357
+ var index = -1,
2358
+ result = Array(collection ? collection.length : 0);
2359
+
2360
+ forEach(collection, function(value) {
2361
+ var rand = floor(nativeRandom() * (++index + 1));
2362
+ result[index] = result[rand];
2363
+ result[rand] = value;
2364
+ });
2365
+ return result;
2366
+ }
2367
+
2368
+ /**
2369
+ * Gets the size of the `collection` by returning `collection.length` for arrays
2370
+ * and array-like objects or the number of own enumerable properties for objects.
2371
+ *
2372
+ * @static
2373
+ * @memberOf _
2374
+ * @category Collections
2375
+ * @param {Array|Object|String} collection The collection to inspect.
2376
+ * @returns {Number} Returns `collection.length` or number of own enumerable properties.
2377
+ * @example
2378
+ *
2379
+ * _.size([1, 2]);
2380
+ * // => 2
2381
+ *
2382
+ * _.size({ 'one': 1, 'two': 2, 'three': 3 });
2383
+ * // => 3
2384
+ *
2385
+ * _.size('curly');
2386
+ * // => 5
2387
+ */
2388
+ function size(collection) {
2389
+ var length = collection ? collection.length : 0;
2390
+ return typeof length == 'number' ? length : keys(collection).length;
2391
+ }
2392
+
2393
+ /**
2394
+ * Checks if the `callback` returns a truthy value for **any** element of a
2395
+ * `collection`. The function returns as soon as it finds passing value, and
2396
+ * does not iterate over the entire `collection`. The `callback` is bound to
2397
+ * `thisArg` and invoked with three arguments; (value, index|key, collection).
2398
+ *
2399
+ * @static
2400
+ * @memberOf _
2401
+ * @alias any
2402
+ * @category Collections
2403
+ * @param {Array|Object|String} collection The collection to iterate over.
2404
+ * @param {Function} [callback=identity] The function called per iteration.
2405
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2406
+ * @returns {Boolean} Returns `true` if any element passes the callback check,
2407
+ * else `false`.
2408
+ * @example
2409
+ *
2410
+ * _.some([null, 0, 'yes', false]);
2411
+ * // => true
2412
+ */
2413
+ function some(collection, callback, thisArg) {
2414
+ var result;
2415
+ callback = createCallback(callback, thisArg);
2416
+
2417
+ if (isArray(collection)) {
2418
+ var index = -1,
2419
+ length = collection.length;
2420
+
2421
+ while (++index < length) {
2422
+ if (result = callback(collection[index], index, collection)) {
2423
+ break;
2424
+ }
2425
+ }
2426
+ } else {
2427
+ forEach(collection, function(value, index, collection) {
2428
+ return !(result = callback(value, index, collection));
2429
+ });
2430
+ }
2431
+ return !!result;
2432
+ }
2433
+
2434
+ /**
2435
+ * Creates an array, stable sorted in ascending order by the results of
2436
+ * running each element of `collection` through a `callback`. The `callback`
2437
+ * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2438
+ * The `callback` argument may also be the name of a property to sort by (e.g. 'length').
2439
+ *
2440
+ * @static
2441
+ * @memberOf _
2442
+ * @category Collections
2443
+ * @param {Array|Object|String} collection The collection to iterate over.
2444
+ * @param {Function|String} callback|property The function called per iteration
2445
+ * or property name to sort by.
2446
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2447
+ * @returns {Array} Returns a new array of sorted elements.
2448
+ * @example
2449
+ *
2450
+ * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
2451
+ * // => [3, 1, 2]
2452
+ *
2453
+ * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
2454
+ * // => [3, 1, 2]
2455
+ *
2456
+ * _.sortBy(['larry', 'brendan', 'moe'], 'length');
2457
+ * // => ['moe', 'larry', 'brendan']
2458
+ */
2459
+ function sortBy(collection, callback, thisArg) {
2460
+ var result = [];
2461
+ callback = createCallback(callback, thisArg);
2462
+ forEach(collection, function(value, index, collection) {
2463
+ result.push({
2464
+ 'criteria': callback(value, index, collection),
2465
+ 'index': index,
2466
+ 'value': value
2467
+ });
2468
+ });
2469
+
2470
+ var length = result.length;
2471
+ result.sort(compareAscending);
2472
+ while (length--) {
2473
+ result[length] = result[length].value;
2474
+ }
2475
+ return result;
2476
+ }
2477
+
2478
+ /**
2479
+ * Converts the `collection`, to an array.
2480
+ *
2481
+ * @static
2482
+ * @memberOf _
2483
+ * @category Collections
2484
+ * @param {Array|Object|String} collection The collection to convert.
2485
+ * @returns {Array} Returns the new converted array.
2486
+ * @example
2487
+ *
2488
+ * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
2489
+ * // => [2, 3, 4]
2490
+ */
2491
+ function toArray(collection) {
2492
+ if (collection && typeof collection.length == 'number') {
2493
+ return (noArraySliceOnStrings ? isString(collection) : typeof collection == 'string')
2494
+ ? collection.split('')
2495
+ : slice.call(collection);
2496
+ }
2497
+ return values(collection);
2498
+ }
2499
+
2500
+ /**
2501
+ * Examines each element in a `collection`, returning an array of all elements
2502
+ * that contain the given `properties`.
2503
+ *
2504
+ * @static
2505
+ * @memberOf _
2506
+ * @category Collections
2507
+ * @param {Array|Object|String} collection The collection to iterate over.
2508
+ * @param {Object} properties The object of property values to filter by.
2509
+ * @returns {Array} Returns a new array of elements that contain the given `properties`.
2510
+ * @example
2511
+ *
2512
+ * var stooges = [
2513
+ * { 'name': 'moe', 'age': 40 },
2514
+ * { 'name': 'larry', 'age': 50 },
2515
+ * { 'name': 'curly', 'age': 60 }
2516
+ * ];
2517
+ *
2518
+ * _.where(stooges, { 'age': 40 });
2519
+ * // => [{ 'name': 'moe', 'age': 40 }]
2520
+ */
2521
+ function where(collection, properties) {
2522
+ var props = [];
2523
+ forIn(properties, function(value, prop) {
2524
+ props.push(prop);
2525
+ });
2526
+ return filter(collection, function(object) {
2527
+ var length = props.length;
2528
+ while (length--) {
2529
+ var result = object[props[length]] === properties[props[length]];
2530
+ if (!result) {
2531
+ break;
2532
+ }
2533
+ }
2534
+ return !!result;
2535
+ });
2536
+ }
2537
+
2538
+ /*--------------------------------------------------------------------------*/
2539
+
2540
+ /**
2541
+ * Creates an array with all falsey values of `array` removed. The values
2542
+ * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
2543
+ *
2544
+ * @static
2545
+ * @memberOf _
2546
+ * @category Arrays
2547
+ * @param {Array} array The array to compact.
2548
+ * @returns {Array} Returns a new filtered array.
2549
+ * @example
2550
+ *
2551
+ * _.compact([0, 1, false, 2, '', 3]);
2552
+ * // => [1, 2, 3]
2553
+ */
2554
+ function compact(array) {
2555
+ var index = -1,
2556
+ length = array ? array.length : 0,
2557
+ result = [];
2558
+
2559
+ while (++index < length) {
2560
+ var value = array[index];
2561
+ if (value) {
2562
+ result.push(value);
2563
+ }
2564
+ }
2565
+ return result;
2566
+ }
2567
+
2568
+ /**
2569
+ * Creates an array of `array` elements not present in the other arrays
2570
+ * using strict equality for comparisons, i.e. `===`.
2571
+ *
2572
+ * @static
2573
+ * @memberOf _
2574
+ * @category Arrays
2575
+ * @param {Array} array The array to process.
2576
+ * @param {Array} [array1, array2, ...] Arrays to check.
2577
+ * @returns {Array} Returns a new array of `array` elements not present in the
2578
+ * other arrays.
2579
+ * @example
2580
+ *
2581
+ * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
2582
+ * // => [1, 3, 4]
2583
+ */
2584
+ function difference(array) {
2585
+ var index = -1,
2586
+ length = array ? array.length : 0,
2587
+ flattened = concat.apply(arrayRef, arguments),
2588
+ contains = cachedContains(flattened, length),
2589
+ result = [];
2590
+
2591
+ while (++index < length) {
2592
+ var value = array[index];
2593
+ if (!contains(value)) {
2594
+ result.push(value);
2595
+ }
2596
+ }
2597
+ return result;
2598
+ }
2599
+
2600
+ /**
2601
+ * Gets the first element of the `array`. Pass `n` to return the first `n`
2602
+ * elements of the `array`.
2603
+ *
2604
+ * @static
2605
+ * @memberOf _
2606
+ * @alias head, take
2607
+ * @category Arrays
2608
+ * @param {Array} array The array to query.
2609
+ * @param {Number} [n] The number of elements to return.
2610
+ * @param- {Object} [guard] Internally used to allow this method to work with
2611
+ * others like `_.map` without using their callback `index` argument for `n`.
2612
+ * @returns {Mixed} Returns the first element or an array of the first `n`
2613
+ * elements of `array`.
2614
+ * @example
2615
+ *
2616
+ * _.first([5, 4, 3, 2, 1]);
2617
+ * // => 5
2618
+ */
2619
+ function first(array, n, guard) {
2620
+ if (array) {
2621
+ return (n == null || guard) ? array[0] : slice.call(array, 0, n);
2622
+ }
2623
+ }
2624
+
2625
+ /**
2626
+ * Flattens a nested array (the nesting can be to any depth). If `shallow` is
2627
+ * truthy, `array` will only be flattened a single level.
2628
+ *
2629
+ * @static
2630
+ * @memberOf _
2631
+ * @category Arrays
2632
+ * @param {Array} array The array to compact.
2633
+ * @param {Boolean} shallow A flag to indicate only flattening a single level.
2634
+ * @returns {Array} Returns a new flattened array.
2635
+ * @example
2636
+ *
2637
+ * _.flatten([1, [2], [3, [[4]]]]);
2638
+ * // => [1, 2, 3, 4];
2639
+ *
2640
+ * _.flatten([1, [2], [3, [[4]]]], true);
2641
+ * // => [1, 2, 3, [[4]]];
2642
+ */
2643
+ function flatten(array, shallow) {
2644
+ var index = -1,
2645
+ length = array ? array.length : 0,
2646
+ result = [];
2647
+
2648
+ while (++index < length) {
2649
+ var value = array[index];
2650
+
2651
+ // recursively flatten arrays (susceptible to call stack limits)
2652
+ if (isArray(value)) {
2653
+ push.apply(result, shallow ? value : flatten(value));
2654
+ } else {
2655
+ result.push(value);
2656
+ }
2657
+ }
2658
+ return result;
2659
+ }
2660
+
2661
+ /**
2662
+ * Gets the index at which the first occurrence of `value` is found using
2663
+ * strict equality for comparisons, i.e. `===`. If the `array` is already
2664
+ * sorted, passing `true` for `fromIndex` will run a faster binary search.
2665
+ *
2666
+ * @static
2667
+ * @memberOf _
2668
+ * @category Arrays
2669
+ * @param {Array} array The array to search.
2670
+ * @param {Mixed} value The value to search for.
2671
+ * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
2672
+ * perform a binary search on a sorted `array`.
2673
+ * @returns {Number} Returns the index of the matched value or `-1`.
2674
+ * @example
2675
+ *
2676
+ * _.indexOf([1, 2, 3, 1, 2, 3], 2);
2677
+ * // => 1
2678
+ *
2679
+ * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
2680
+ * // => 4
2681
+ *
2682
+ * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
2683
+ * // => 2
2684
+ */
2685
+ function indexOf(array, value, fromIndex) {
2686
+ var index = -1,
2687
+ length = array ? array.length : 0;
2688
+
2689
+ if (typeof fromIndex == 'number') {
2690
+ index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
2691
+ } else if (fromIndex) {
2692
+ index = sortedIndex(array, value);
2693
+ return array[index] === value ? index : -1;
2694
+ }
2695
+ while (++index < length) {
2696
+ if (array[index] === value) {
2697
+ return index;
2698
+ }
2699
+ }
2700
+ return -1;
2701
+ }
2702
+
2703
+ /**
2704
+ * Gets all but the last element of `array`. Pass `n` to exclude the last `n`
2705
+ * elements from the result.
2706
+ *
2707
+ * @static
2708
+ * @memberOf _
2709
+ * @category Arrays
2710
+ * @param {Array} array The array to query.
2711
+ * @param {Number} [n=1] The number of elements to exclude.
2712
+ * @param- {Object} [guard] Internally used to allow this method to work with
2713
+ * others like `_.map` without using their callback `index` argument for `n`.
2714
+ * @returns {Array} Returns all but the last element or `n` elements of `array`.
2715
+ * @example
2716
+ *
2717
+ * _.initial([3, 2, 1]);
2718
+ * // => [3, 2]
2719
+ */
2720
+ function initial(array, n, guard) {
2721
+ return array
2722
+ ? slice.call(array, 0, -((n == null || guard) ? 1 : n))
2723
+ : [];
2724
+ }
2725
+
2726
+ /**
2727
+ * Computes the intersection of all the passed-in arrays using strict equality
2728
+ * for comparisons, i.e. `===`.
2729
+ *
2730
+ * @static
2731
+ * @memberOf _
2732
+ * @category Arrays
2733
+ * @param {Array} [array1, array2, ...] Arrays to process.
2734
+ * @returns {Array} Returns a new array of unique elements, in order, that are
2735
+ * present in **all** of the arrays.
2736
+ * @example
2737
+ *
2738
+ * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
2739
+ * // => [1, 2]
2740
+ */
2741
+ function intersection(array) {
2742
+ var args = arguments,
2743
+ argsLength = args.length,
2744
+ cache = {},
2745
+ result = [];
2746
+
2747
+ forEach(array, function(value) {
2748
+ if (indexOf(result, value) < 0) {
2749
+ var length = argsLength;
2750
+ while (--length) {
2751
+ if (!(cache[length] || (cache[length] = cachedContains(args[length])))(value)) {
2752
+ return;
2753
+ }
2754
+ }
2755
+ result.push(value);
2756
+ }
2757
+ });
2758
+ return result;
2759
+ }
2760
+
2761
+ /**
2762
+ * Gets the last element of the `array`. Pass `n` to return the last `n`
2763
+ * elements of the `array`.
2764
+ *
2765
+ * @static
2766
+ * @memberOf _
2767
+ * @category Arrays
2768
+ * @param {Array} array The array to query.
2769
+ * @param {Number} [n] The number of elements to return.
2770
+ * @param- {Object} [guard] Internally used to allow this method to work with
2771
+ * others like `_.map` without using their callback `index` argument for `n`.
2772
+ * @returns {Mixed} Returns the last element or an array of the last `n`
2773
+ * elements of `array`.
2774
+ * @example
2775
+ *
2776
+ * _.last([3, 2, 1]);
2777
+ * // => 1
2778
+ */
2779
+ function last(array, n, guard) {
2780
+ if (array) {
2781
+ var length = array.length;
2782
+ return (n == null || guard) ? array[length - 1] : slice.call(array, -n || length);
2783
+ }
2784
+ }
2785
+
2786
+ /**
2787
+ * Gets the index at which the last occurrence of `value` is found using strict
2788
+ * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
2789
+ * as the offset from the end of the collection.
2790
+ *
2791
+ * @static
2792
+ * @memberOf _
2793
+ * @category Arrays
2794
+ * @param {Array} array The array to search.
2795
+ * @param {Mixed} value The value to search for.
2796
+ * @param {Number} [fromIndex=array.length-1] The index to search from.
2797
+ * @returns {Number} Returns the index of the matched value or `-1`.
2798
+ * @example
2799
+ *
2800
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
2801
+ * // => 4
2802
+ *
2803
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
2804
+ * // => 1
2805
+ */
2806
+ function lastIndexOf(array, value, fromIndex) {
2807
+ var index = array ? array.length : 0;
2808
+ if (typeof fromIndex == 'number') {
2809
+ index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
2810
+ }
2811
+ while (index--) {
2812
+ if (array[index] === value) {
2813
+ return index;
2814
+ }
2815
+ }
2816
+ return -1;
2817
+ }
2818
+
2819
+ /**
2820
+ * Creates an object composed from arrays of `keys` and `values`. Pass either
2821
+ * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
2822
+ * two arrays, one of `keys` and one of corresponding `values`.
2823
+ *
2824
+ * @static
2825
+ * @memberOf _
2826
+ * @category Arrays
2827
+ * @param {Array} keys The array of keys.
2828
+ * @param {Array} [values=[]] The array of values.
2829
+ * @returns {Object} Returns an object composed of the given keys and
2830
+ * corresponding values.
2831
+ * @example
2832
+ *
2833
+ * _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
2834
+ * // => { 'moe': 30, 'larry': 40, 'curly': 50 }
2835
+ */
2836
+ function object(keys, values) {
2837
+ var index = -1,
2838
+ length = keys ? keys.length : 0,
2839
+ result = {};
2840
+
2841
+ while (++index < length) {
2842
+ var key = keys[index];
2843
+ if (values) {
2844
+ result[key] = values[index];
2845
+ } else {
2846
+ result[key[0]] = key[1];
2847
+ }
2848
+ }
2849
+ return result;
2850
+ }
2851
+
2852
+ /**
2853
+ * Creates an array of numbers (positive and/or negative) progressing from
2854
+ * `start` up to but not including `stop`. This method is a port of Python's
2855
+ * `range()` function. See http://docs.python.org/library/functions.html#range.
2856
+ *
2857
+ * @static
2858
+ * @memberOf _
2859
+ * @category Arrays
2860
+ * @param {Number} [start=0] The start of the range.
2861
+ * @param {Number} end The end of the range.
2862
+ * @param {Number} [step=1] The value to increment or descrement by.
2863
+ * @returns {Array} Returns a new range array.
2864
+ * @example
2865
+ *
2866
+ * _.range(10);
2867
+ * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2868
+ *
2869
+ * _.range(1, 11);
2870
+ * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2871
+ *
2872
+ * _.range(0, 30, 5);
2873
+ * // => [0, 5, 10, 15, 20, 25]
2874
+ *
2875
+ * _.range(0, -10, -1);
2876
+ * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
2877
+ *
2878
+ * _.range(0);
2879
+ * // => []
2880
+ */
2881
+ function range(start, end, step) {
2882
+ start = +start || 0;
2883
+ step = +step || 1;
2884
+
2885
+ if (end == null) {
2886
+ end = start;
2887
+ start = 0;
2888
+ }
2889
+ // use `Array(length)` so V8 will avoid the slower "dictionary" mode
2890
+ // http://www.youtube.com/watch?v=XAqIpGU8ZZk#t=16m27s
2891
+ var index = -1,
2892
+ length = nativeMax(0, ceil((end - start) / step)),
2893
+ result = Array(length);
2894
+
2895
+ while (++index < length) {
2896
+ result[index] = start;
2897
+ start += step;
2898
+ }
2899
+ return result;
2900
+ }
2901
+
2902
+ /**
2903
+ * The opposite of `_.initial`, this method gets all but the first value of
2904
+ * `array`. Pass `n` to exclude the first `n` values from the result.
2905
+ *
2906
+ * @static
2907
+ * @memberOf _
2908
+ * @alias drop, tail
2909
+ * @category Arrays
2910
+ * @param {Array} array The array to query.
2911
+ * @param {Number} [n=1] The number of elements to exclude.
2912
+ * @param- {Object} [guard] Internally used to allow this method to work with
2913
+ * others like `_.map` without using their callback `index` argument for `n`.
2914
+ * @returns {Array} Returns all but the first value or `n` values of `array`.
2915
+ * @example
2916
+ *
2917
+ * _.rest([3, 2, 1]);
2918
+ * // => [2, 1]
2919
+ */
2920
+ function rest(array, n, guard) {
2921
+ return array
2922
+ ? slice.call(array, (n == null || guard) ? 1 : n)
2923
+ : [];
2924
+ }
2925
+
2926
+ /**
2927
+ * Uses a binary search to determine the smallest index at which the `value`
2928
+ * should be inserted into `array` in order to maintain the sort order of the
2929
+ * sorted `array`. If `callback` is passed, it will be executed for `value` and
2930
+ * each element in `array` to compute their sort ranking. The `callback` is
2931
+ * bound to `thisArg` and invoked with one argument; (value). The `callback`
2932
+ * argument may also be the name of a property to order by.
2933
+ *
2934
+ * @static
2935
+ * @memberOf _
2936
+ * @category Arrays
2937
+ * @param {Array} array The array to iterate over.
2938
+ * @param {Mixed} value The value to evaluate.
2939
+ * @param {Function|String} [callback=identity|property] The function called
2940
+ * per iteration or property name to order by.
2941
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2942
+ * @returns {Number} Returns the index at which the value should be inserted
2943
+ * into `array`.
2944
+ * @example
2945
+ *
2946
+ * _.sortedIndex([20, 30, 50], 40);
2947
+ * // => 2
2948
+ *
2949
+ * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
2950
+ * // => 2
2951
+ *
2952
+ * var dict = {
2953
+ * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
2954
+ * };
2955
+ *
2956
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
2957
+ * return dict.wordToNumber[word];
2958
+ * });
2959
+ * // => 2
2960
+ *
2961
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
2962
+ * return this.wordToNumber[word];
2963
+ * }, dict);
2964
+ * // => 2
2965
+ */
2966
+ function sortedIndex(array, value, callback, thisArg) {
2967
+ var low = 0,
2968
+ high = array ? array.length : low;
2969
+
2970
+ // explicitly reference `identity` for better engine inlining
2971
+ callback = callback ? createCallback(callback, thisArg) : identity;
2972
+ value = callback(value);
2973
+ while (low < high) {
2974
+ var mid = (low + high) >>> 1;
2975
+ callback(array[mid]) < value
2976
+ ? low = mid + 1
2977
+ : high = mid;
2978
+ }
2979
+ return low;
2980
+ }
2981
+
2982
+ /**
2983
+ * Computes the union of the passed-in arrays using strict equality for
2984
+ * comparisons, i.e. `===`.
2985
+ *
2986
+ * @static
2987
+ * @memberOf _
2988
+ * @category Arrays
2989
+ * @param {Array} [array1, array2, ...] Arrays to process.
2990
+ * @returns {Array} Returns a new array of unique values, in order, that are
2991
+ * present in one or more of the arrays.
2992
+ * @example
2993
+ *
2994
+ * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
2995
+ * // => [1, 2, 3, 101, 10]
2996
+ */
2997
+ function union() {
2998
+ return uniq(concat.apply(arrayRef, arguments));
2999
+ }
3000
+
3001
+ /**
3002
+ * Creates a duplicate-value-free version of the `array` using strict equality
3003
+ * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
3004
+ * for `isSorted` will run a faster algorithm. If `callback` is passed, each
3005
+ * element of `array` is passed through a callback` before uniqueness is computed.
3006
+ * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
3007
+ *
3008
+ * @static
3009
+ * @memberOf _
3010
+ * @alias unique
3011
+ * @category Arrays
3012
+ * @param {Array} array The array to process.
3013
+ * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
3014
+ * @param {Function} [callback=identity] The function called per iteration.
3015
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3016
+ * @returns {Array} Returns a duplicate-value-free array.
3017
+ * @example
3018
+ *
3019
+ * _.uniq([1, 2, 1, 3, 1]);
3020
+ * // => [1, 2, 3]
3021
+ *
3022
+ * _.uniq([1, 1, 2, 2, 3], true);
3023
+ * // => [1, 2, 3]
3024
+ *
3025
+ * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
3026
+ * // => [1, 2, 3]
3027
+ *
3028
+ * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
3029
+ * // => [1, 2, 3]
3030
+ */
3031
+ function uniq(array, isSorted, callback, thisArg) {
3032
+ var index = -1,
3033
+ length = array ? array.length : 0,
3034
+ result = [],
3035
+ seen = result;
3036
+
3037
+ // juggle arguments
3038
+ if (typeof isSorted == 'function') {
3039
+ thisArg = callback;
3040
+ callback = isSorted;
3041
+ isSorted = false;
3042
+ }
3043
+ // init value cache for large arrays
3044
+ var isLarge = !isSorted && length > 74;
3045
+ if (isLarge) {
3046
+ var cache = {};
3047
+ }
3048
+ if (callback) {
3049
+ seen = [];
3050
+ callback = createCallback(callback, thisArg);
3051
+ }
3052
+ while (++index < length) {
3053
+ var value = array[index],
3054
+ computed = callback ? callback(value, index, array) : value;
3055
+
3056
+ if (isLarge) {
3057
+ // manually coerce `computed` to a string because `hasOwnProperty`, in
3058
+ // some older versions of Firefox, coerces objects incorrectly
3059
+ seen = hasOwnProperty.call(cache, computed + '') ? cache[computed] : (cache[computed] = []);
3060
+ }
3061
+ if (isSorted
3062
+ ? !index || seen[seen.length - 1] !== computed
3063
+ : indexOf(seen, computed) < 0
3064
+ ) {
3065
+ if (callback || isLarge) {
3066
+ seen.push(computed);
3067
+ }
3068
+ result.push(value);
3069
+ }
3070
+ }
3071
+ return result;
3072
+ }
3073
+
3074
+ /**
3075
+ * Creates an array with all occurrences of the passed values removed using
3076
+ * strict equality for comparisons, i.e. `===`.
3077
+ *
3078
+ * @static
3079
+ * @memberOf _
3080
+ * @category Arrays
3081
+ * @param {Array} array The array to filter.
3082
+ * @param {Mixed} [value1, value2, ...] Values to remove.
3083
+ * @returns {Array} Returns a new filtered array.
3084
+ * @example
3085
+ *
3086
+ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
3087
+ * // => [2, 3, 4]
3088
+ */
3089
+ function without(array) {
3090
+ var index = -1,
3091
+ length = array ? array.length : 0,
3092
+ contains = cachedContains(arguments, 1, 20),
3093
+ result = [];
3094
+
3095
+ while (++index < length) {
3096
+ var value = array[index];
3097
+ if (!contains(value)) {
3098
+ result.push(value);
3099
+ }
3100
+ }
3101
+ return result;
3102
+ }
3103
+
3104
+ /**
3105
+ * Groups the elements of each array at their corresponding indexes. Useful for
3106
+ * separate data sources that are coordinated through matching array indexes.
3107
+ * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
3108
+ * in a similar fashion.
3109
+ *
3110
+ * @static
3111
+ * @memberOf _
3112
+ * @category Arrays
3113
+ * @param {Array} [array1, array2, ...] Arrays to process.
3114
+ * @returns {Array} Returns a new array of grouped elements.
3115
+ * @example
3116
+ *
3117
+ * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
3118
+ * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
3119
+ */
3120
+ function zip(array) {
3121
+ var index = -1,
3122
+ length = array ? max(pluck(arguments, 'length')) : 0,
3123
+ result = Array(length);
3124
+
3125
+ while (++index < length) {
3126
+ result[index] = pluck(arguments, index);
3127
+ }
3128
+ return result;
3129
+ }
3130
+
3131
+ /*--------------------------------------------------------------------------*/
3132
+
3133
+ /**
3134
+ * Creates a function that is restricted to executing `func` only after it is
3135
+ * called `n` times. The `func` is executed with the `this` binding of the
3136
+ * created function.
3137
+ *
3138
+ * @static
3139
+ * @memberOf _
3140
+ * @category Functions
3141
+ * @param {Number} n The number of times the function must be called before
3142
+ * it is executed.
3143
+ * @param {Function} func The function to restrict.
3144
+ * @returns {Function} Returns the new restricted function.
3145
+ * @example
3146
+ *
3147
+ * var renderNotes = _.after(notes.length, render);
3148
+ * _.forEach(notes, function(note) {
3149
+ * note.asyncSave({ 'success': renderNotes });
3150
+ * });
3151
+ * // `renderNotes` is run once, after all notes have saved
3152
+ */
3153
+ function after(n, func) {
3154
+ if (n < 1) {
3155
+ return func();
3156
+ }
3157
+ return function() {
3158
+ if (--n < 1) {
3159
+ return func.apply(this, arguments);
3160
+ }
3161
+ };
3162
+ }
3163
+
3164
+ /**
3165
+ * Creates a function that, when called, invokes `func` with the `this`
3166
+ * binding of `thisArg` and prepends any additional `bind` arguments to those
3167
+ * passed to the bound function.
3168
+ *
3169
+ * @static
3170
+ * @memberOf _
3171
+ * @category Functions
3172
+ * @param {Function} func The function to bind.
3173
+ * @param {Mixed} [thisArg] The `this` binding of `func`.
3174
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
3175
+ * @returns {Function} Returns the new bound function.
3176
+ * @example
3177
+ *
3178
+ * var func = function(greeting) {
3179
+ * return greeting + ' ' + this.name;
3180
+ * };
3181
+ *
3182
+ * func = _.bind(func, { 'name': 'moe' }, 'hi');
3183
+ * func();
3184
+ * // => 'hi moe'
3185
+ */
3186
+ function bind(func, thisArg) {
3187
+ // use `Function#bind` if it exists and is fast
3188
+ // (in V8 `Function#bind` is slower except when partially applied)
3189
+ return isBindFast || (nativeBind && arguments.length > 2)
3190
+ ? nativeBind.call.apply(nativeBind, arguments)
3191
+ : createBound(func, thisArg, slice.call(arguments, 2));
3192
+ }
3193
+
3194
+ /**
3195
+ * Binds methods on `object` to `object`, overwriting the existing method.
3196
+ * If no method names are provided, all the function properties of `object`
3197
+ * will be bound.
3198
+ *
3199
+ * @static
3200
+ * @memberOf _
3201
+ * @category Functions
3202
+ * @param {Object} object The object to bind and assign the bound methods to.
3203
+ * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
3204
+ * @returns {Object} Returns `object`.
3205
+ * @example
3206
+ *
3207
+ * var buttonView = {
3208
+ * 'label': 'lodash',
3209
+ * 'onClick': function() { alert('clicked: ' + this.label); }
3210
+ * };
3211
+ *
3212
+ * _.bindAll(buttonView);
3213
+ * jQuery('#lodash_button').on('click', buttonView.onClick);
3214
+ * // => When the button is clicked, `this.label` will have the correct value
3215
+ */
3216
+ function bindAll(object) {
3217
+ var funcs = arguments,
3218
+ index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
3219
+ length = funcs.length;
3220
+
3221
+ while (++index < length) {
3222
+ var key = funcs[index];
3223
+ object[key] = bind(object[key], object);
3224
+ }
3225
+ return object;
3226
+ }
3227
+
3228
+ /**
3229
+ * Creates a function that is the composition of the passed functions,
3230
+ * where each function consumes the return value of the function that follows.
3231
+ * In math terms, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
3232
+ * Each function is executed with the `this` binding of the composed function.
3233
+ *
3234
+ * @static
3235
+ * @memberOf _
3236
+ * @category Functions
3237
+ * @param {Function} [func1, func2, ...] Functions to compose.
3238
+ * @returns {Function} Returns the new composed function.
3239
+ * @example
3240
+ *
3241
+ * var greet = function(name) { return 'hi: ' + name; };
3242
+ * var exclaim = function(statement) { return statement + '!'; };
3243
+ * var welcome = _.compose(exclaim, greet);
3244
+ * welcome('moe');
3245
+ * // => 'hi: moe!'
3246
+ */
3247
+ function compose() {
3248
+ var funcs = arguments;
3249
+ return function() {
3250
+ var args = arguments,
3251
+ length = funcs.length;
3252
+
3253
+ while (length--) {
3254
+ args = [funcs[length].apply(this, args)];
3255
+ }
3256
+ return args[0];
3257
+ };
3258
+ }
3259
+
3260
+ /**
3261
+ * Creates a function that will delay the execution of `func` until after
3262
+ * `wait` milliseconds have elapsed since the last time it was invoked. Pass
3263
+ * `true` for `immediate` to cause debounce to invoke `func` on the leading,
3264
+ * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
3265
+ * the debounced function will return the result of the last `func` call.
3266
+ *
3267
+ * @static
3268
+ * @memberOf _
3269
+ * @category Functions
3270
+ * @param {Function} func The function to debounce.
3271
+ * @param {Number} wait The number of milliseconds to delay.
3272
+ * @param {Boolean} immediate A flag to indicate execution is on the leading
3273
+ * edge of the timeout.
3274
+ * @returns {Function} Returns the new debounced function.
3275
+ * @example
3276
+ *
3277
+ * var lazyLayout = _.debounce(calculateLayout, 300);
3278
+ * jQuery(window).on('resize', lazyLayout);
3279
+ */
3280
+ function debounce(func, wait, immediate) {
3281
+ var args,
3282
+ result,
3283
+ thisArg,
3284
+ timeoutId;
3285
+
3286
+ function delayed() {
3287
+ timeoutId = null;
3288
+ if (!immediate) {
3289
+ result = func.apply(thisArg, args);
3290
+ }
3291
+ }
3292
+ return function() {
3293
+ var isImmediate = immediate && !timeoutId;
3294
+ args = arguments;
3295
+ thisArg = this;
3296
+
3297
+ clearTimeout(timeoutId);
3298
+ timeoutId = setTimeout(delayed, wait);
3299
+
3300
+ if (isImmediate) {
3301
+ result = func.apply(thisArg, args);
3302
+ }
3303
+ return result;
3304
+ };
3305
+ }
3306
+
3307
+ /**
3308
+ * Executes the `func` function after `wait` milliseconds. Additional arguments
3309
+ * will be passed to `func` when it is invoked.
3310
+ *
3311
+ * @static
3312
+ * @memberOf _
3313
+ * @category Functions
3314
+ * @param {Function} func The function to delay.
3315
+ * @param {Number} wait The number of milliseconds to delay execution.
3316
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
3317
+ * @returns {Number} Returns the `setTimeout` timeout id.
3318
+ * @example
3319
+ *
3320
+ * var log = _.bind(console.log, console);
3321
+ * _.delay(log, 1000, 'logged later');
3322
+ * // => 'logged later' (Appears after one second.)
3323
+ */
3324
+ function delay(func, wait) {
3325
+ var args = slice.call(arguments, 2);
3326
+ return setTimeout(function() { func.apply(undefined, args); }, wait);
3327
+ }
3328
+
3329
+ /**
3330
+ * Defers executing the `func` function until the current call stack has cleared.
3331
+ * Additional arguments will be passed to `func` when it is invoked.
3332
+ *
3333
+ * @static
3334
+ * @memberOf _
3335
+ * @category Functions
3336
+ * @param {Function} func The function to defer.
3337
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
3338
+ * @returns {Number} Returns the `setTimeout` timeout id.
3339
+ * @example
3340
+ *
3341
+ * _.defer(function() { alert('deferred'); });
3342
+ * // returns from the function before `alert` is called
3343
+ */
3344
+ function defer(func) {
3345
+ var args = slice.call(arguments, 1);
3346
+ return setTimeout(function() { func.apply(undefined, args); }, 1);
3347
+ }
3348
+
3349
+ /**
3350
+ * Creates a function that, when called, invokes `object[methodName]` and
3351
+ * prepends any additional `lateBind` arguments to those passed to the bound
3352
+ * function. This method differs from `_.bind` by allowing bound functions to
3353
+ * reference methods that will be redefined or don't yet exist.
3354
+ *
3355
+ * @static
3356
+ * @memberOf _
3357
+ * @category Functions
3358
+ * @param {Object} object The object the method belongs to.
3359
+ * @param {String} methodName The method name.
3360
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
3361
+ * @returns {Function} Returns the new bound function.
3362
+ * @example
3363
+ *
3364
+ * var object = {
3365
+ * 'name': 'moe',
3366
+ * 'greet': function(greeting) {
3367
+ * return greeting + ' ' + this.name;
3368
+ * }
3369
+ * };
3370
+ *
3371
+ * var func = _.lateBind(object, 'greet', 'hi');
3372
+ * func();
3373
+ * // => 'hi moe'
3374
+ *
3375
+ * object.greet = function(greeting) {
3376
+ * return greeting + ', ' + this.name + '!';
3377
+ * };
3378
+ *
3379
+ * func();
3380
+ * // => 'hi, moe!'
3381
+ */
3382
+ function lateBind(object, methodName) {
3383
+ return createBound(methodName, object, slice.call(arguments, 2));
3384
+ }
3385
+
3386
+ /**
3387
+ * Creates a function that memoizes the result of `func`. If `resolver` is
3388
+ * passed, it will be used to determine the cache key for storing the result
3389
+ * based on the arguments passed to the memoized function. By default, the first
3390
+ * argument passed to the memoized function is used as the cache key. The `func`
3391
+ * is executed with the `this` binding of the memoized function.
3392
+ *
3393
+ * @static
3394
+ * @memberOf _
3395
+ * @category Functions
3396
+ * @param {Function} func The function to have its output memoized.
3397
+ * @param {Function} [resolver] A function used to resolve the cache key.
3398
+ * @returns {Function} Returns the new memoizing function.
3399
+ * @example
3400
+ *
3401
+ * var fibonacci = _.memoize(function(n) {
3402
+ * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
3403
+ * });
3404
+ */
3405
+ function memoize(func, resolver) {
3406
+ var cache = {};
3407
+ return function() {
3408
+ var key = resolver ? resolver.apply(this, arguments) : arguments[0];
3409
+ return hasOwnProperty.call(cache, key)
3410
+ ? cache[key]
3411
+ : (cache[key] = func.apply(this, arguments));
3412
+ };
3413
+ }
3414
+
3415
+ /**
3416
+ * Creates a function that is restricted to execute `func` once. Repeat calls to
3417
+ * the function will return the value of the first call. The `func` is executed
3418
+ * with the `this` binding of the created function.
3419
+ *
3420
+ * @static
3421
+ * @memberOf _
3422
+ * @category Functions
3423
+ * @param {Function} func The function to restrict.
3424
+ * @returns {Function} Returns the new restricted function.
3425
+ * @example
3426
+ *
3427
+ * var initialize = _.once(createApplication);
3428
+ * initialize();
3429
+ * initialize();
3430
+ * // Application is only created once.
3431
+ */
3432
+ function once(func) {
3433
+ var result,
3434
+ ran = false;
3435
+
3436
+ return function() {
3437
+ if (ran) {
3438
+ return result;
3439
+ }
3440
+ ran = true;
3441
+ result = func.apply(this, arguments);
3442
+
3443
+ // clear the `func` variable so the function may be garbage collected
3444
+ func = null;
3445
+ return result;
3446
+ };
3447
+ }
3448
+
3449
+ /**
3450
+ * Creates a function that, when called, invokes `func` with any additional
3451
+ * `partial` arguments prepended to those passed to the new function. This
3452
+ * method is similar to `bind`, except it does **not** alter the `this` binding.
3453
+ *
3454
+ * @static
3455
+ * @memberOf _
3456
+ * @category Functions
3457
+ * @param {Function} func The function to partially apply arguments to.
3458
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
3459
+ * @returns {Function} Returns the new partially applied function.
3460
+ * @example
3461
+ *
3462
+ * var greet = function(greeting, name) { return greeting + ': ' + name; };
3463
+ * var hi = _.partial(greet, 'hi');
3464
+ * hi('moe');
3465
+ * // => 'hi: moe'
3466
+ */
3467
+ function partial(func) {
3468
+ return createBound(func, slice.call(arguments, 1));
3469
+ }
3470
+
3471
+ /**
3472
+ * Creates a function that, when executed, will only call the `func`
3473
+ * function at most once per every `wait` milliseconds. If the throttled
3474
+ * function is invoked more than once during the `wait` timeout, `func` will
3475
+ * also be called on the trailing edge of the timeout. Subsequent calls to the
3476
+ * throttled function will return the result of the last `func` call.
3477
+ *
3478
+ * @static
3479
+ * @memberOf _
3480
+ * @category Functions
3481
+ * @param {Function} func The function to throttle.
3482
+ * @param {Number} wait The number of milliseconds to throttle executions to.
3483
+ * @returns {Function} Returns the new throttled function.
3484
+ * @example
3485
+ *
3486
+ * var throttled = _.throttle(updatePosition, 100);
3487
+ * jQuery(window).on('scroll', throttled);
3488
+ */
3489
+ function throttle(func, wait) {
3490
+ var args,
3491
+ result,
3492
+ thisArg,
3493
+ timeoutId,
3494
+ lastCalled = 0;
3495
+
3496
+ function trailingCall() {
3497
+ lastCalled = new Date;
3498
+ timeoutId = null;
3499
+ result = func.apply(thisArg, args);
3500
+ }
3501
+ return function() {
3502
+ var now = new Date,
3503
+ remaining = wait - (now - lastCalled);
3504
+
3505
+ args = arguments;
3506
+ thisArg = this;
3507
+
3508
+ if (remaining <= 0) {
3509
+ clearTimeout(timeoutId);
3510
+ lastCalled = now;
3511
+ result = func.apply(thisArg, args);
3512
+ }
3513
+ else if (!timeoutId) {
3514
+ timeoutId = setTimeout(trailingCall, remaining);
3515
+ }
3516
+ return result;
3517
+ };
3518
+ }
3519
+
3520
+ /**
3521
+ * Creates a function that passes `value` to the `wrapper` function as its
3522
+ * first argument. Additional arguments passed to the function are appended
3523
+ * to those passed to the `wrapper` function. The `wrapper` is executed with
3524
+ * the `this` binding of the created function.
3525
+ *
3526
+ * @static
3527
+ * @memberOf _
3528
+ * @category Functions
3529
+ * @param {Mixed} value The value to wrap.
3530
+ * @param {Function} wrapper The wrapper function.
3531
+ * @returns {Function} Returns the new function.
3532
+ * @example
3533
+ *
3534
+ * var hello = function(name) { return 'hello ' + name; };
3535
+ * hello = _.wrap(hello, function(func) {
3536
+ * return 'before, ' + func('moe') + ', after';
3537
+ * });
3538
+ * hello();
3539
+ * // => 'before, hello moe, after'
3540
+ */
3541
+ function wrap(value, wrapper) {
3542
+ return function() {
3543
+ var args = [value];
3544
+ push.apply(args, arguments);
3545
+ return wrapper.apply(this, args);
3546
+ };
3547
+ }
3548
+
3549
+ /*--------------------------------------------------------------------------*/
3550
+
3551
+ /**
3552
+ * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
3553
+ * corresponding HTML entities.
3554
+ *
3555
+ * @static
3556
+ * @memberOf _
3557
+ * @category Utilities
3558
+ * @param {String} string The string to escape.
3559
+ * @returns {String} Returns the escaped string.
3560
+ * @example
3561
+ *
3562
+ * _.escape('Moe, Larry & Curly');
3563
+ * // => "Moe, Larry &amp; Curly"
3564
+ */
3565
+ function escape(string) {
3566
+ return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
3567
+ }
3568
+
3569
+ /**
3570
+ * This function returns the first argument passed to it.
3571
+ *
3572
+ * Note: It is used throughout Lo-Dash as a default callback.
3573
+ *
3574
+ * @static
3575
+ * @memberOf _
3576
+ * @category Utilities
3577
+ * @param {Mixed} value Any value.
3578
+ * @returns {Mixed} Returns `value`.
3579
+ * @example
3580
+ *
3581
+ * var moe = { 'name': 'moe' };
3582
+ * moe === _.identity(moe);
3583
+ * // => true
3584
+ */
3585
+ function identity(value) {
3586
+ return value;
3587
+ }
3588
+
3589
+ /**
3590
+ * Adds functions properties of `object` to the `lodash` function and chainable
3591
+ * wrapper.
3592
+ *
3593
+ * @static
3594
+ * @memberOf _
3595
+ * @category Utilities
3596
+ * @param {Object} object The object of function properties to add to `lodash`.
3597
+ * @example
3598
+ *
3599
+ * _.mixin({
3600
+ * 'capitalize': function(string) {
3601
+ * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
3602
+ * }
3603
+ * });
3604
+ *
3605
+ * _.capitalize('larry');
3606
+ * // => 'Larry'
3607
+ *
3608
+ * _('curly').capitalize();
3609
+ * // => 'Curly'
3610
+ */
3611
+ function mixin(object) {
3612
+ forEach(functions(object), function(methodName) {
3613
+ var func = lodash[methodName] = object[methodName];
3614
+
3615
+ lodash.prototype[methodName] = function() {
3616
+ var args = [this.__wrapped__];
3617
+ push.apply(args, arguments);
3618
+
3619
+ var result = func.apply(lodash, args);
3620
+ if (this.__chain__) {
3621
+ result = new lodash(result);
3622
+ result.__chain__ = true;
3623
+ }
3624
+ return result;
3625
+ };
3626
+ });
3627
+ }
3628
+
3629
+ /**
3630
+ * Reverts the '_' variable to its previous value and returns a reference to
3631
+ * the `lodash` function.
3632
+ *
3633
+ * @static
3634
+ * @memberOf _
3635
+ * @category Utilities
3636
+ * @returns {Function} Returns the `lodash` function.
3637
+ * @example
3638
+ *
3639
+ * var lodash = _.noConflict();
3640
+ */
3641
+ function noConflict() {
3642
+ window._ = oldDash;
3643
+ return this;
3644
+ }
3645
+
3646
+ /**
3647
+ * Produces a random number between `min` and `max` (inclusive). If only one
3648
+ * argument is passed, a number between `0` and the given number will be returned.
3649
+ *
3650
+ * @static
3651
+ * @memberOf _
3652
+ * @category Utilities
3653
+ * @param {Number} [min=0] The minimum possible value.
3654
+ * @param {Number} [max=1] The maximum possible value.
3655
+ * @returns {Number} Returns a random number.
3656
+ * @example
3657
+ *
3658
+ * _.random(0, 5);
3659
+ * // => a number between 1 and 5
3660
+ *
3661
+ * _.random(5);
3662
+ * // => also a number between 1 and 5
3663
+ */
3664
+ function random(min, max) {
3665
+ if (min == null && max == null) {
3666
+ max = 1;
3667
+ }
3668
+ min = +min || 0;
3669
+ if (max == null) {
3670
+ max = min;
3671
+ min = 0;
3672
+ }
3673
+ return min + floor(nativeRandom() * ((+max || 0) - min + 1));
3674
+ }
3675
+
3676
+ /**
3677
+ * Resolves the value of `property` on `object`. If `property` is a function
3678
+ * it will be invoked and its result returned, else the property value is
3679
+ * returned. If `object` is falsey, then `null` is returned.
3680
+ *
3681
+ * @deprecated
3682
+ * @static
3683
+ * @memberOf _
3684
+ * @category Utilities
3685
+ * @param {Object} object The object to inspect.
3686
+ * @param {String} property The property to get the value of.
3687
+ * @returns {Mixed} Returns the resolved value.
3688
+ * @example
3689
+ *
3690
+ * var object = {
3691
+ * 'cheese': 'crumpets',
3692
+ * 'stuff': function() {
3693
+ * return 'nonsense';
3694
+ * }
3695
+ * };
3696
+ *
3697
+ * _.result(object, 'cheese');
3698
+ * // => 'crumpets'
3699
+ *
3700
+ * _.result(object, 'stuff');
3701
+ * // => 'nonsense'
3702
+ */
3703
+ function result(object, property) {
3704
+ // based on Backbone's private `getValue` function
3705
+ // https://github.com/documentcloud/backbone/blob/0.9.2/backbone.js#L1419-1424
3706
+ var value = object ? object[property] : null;
3707
+ return isFunction(value) ? object[property]() : value;
3708
+ }
3709
+
3710
+ /**
3711
+ * A micro-templating method that handles arbitrary delimiters, preserves
3712
+ * whitespace, and correctly escapes quotes within interpolated code.
3713
+ *
3714
+ * Note: In the development build `_.template` utilizes sourceURLs for easier
3715
+ * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
3716
+ *
3717
+ * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
3718
+ * build and avoiding `_.template` use, or loading Lo-Dash in a sandboxed page.
3719
+ * See http://developer.chrome.com/trunk/extensions/sandboxingEval.html
3720
+ *
3721
+ * @static
3722
+ * @memberOf _
3723
+ * @category Utilities
3724
+ * @param {String} text The template text.
3725
+ * @param {Obect} data The data object used to populate the text.
3726
+ * @param {Object} options The options object.
3727
+ * escape - The "escape" delimiter regexp.
3728
+ * evaluate - The "evaluate" delimiter regexp.
3729
+ * interpolate - The "interpolate" delimiter regexp.
3730
+ * sourceURL - The sourceURL of the template's compiled source.
3731
+ * variable - The data object variable name.
3732
+ *
3733
+ * @returns {Function|String} Returns a compiled function when no `data` object
3734
+ * is given, else it returns the interpolated text.
3735
+ * @example
3736
+ *
3737
+ * // using a compiled template
3738
+ * var compiled = _.template('hello <%= name %>');
3739
+ * compiled({ 'name': 'moe' });
3740
+ * // => 'hello moe'
3741
+ *
3742
+ * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
3743
+ * _.template(list, { 'people': ['moe', 'larry', 'curly'] });
3744
+ * // => '<li>moe</li><li>larry</li><li>curly</li>'
3745
+ *
3746
+ * // using the "escape" delimiter to escape HTML in data property values
3747
+ * _.template('<b><%- value %></b>', { 'value': '<script>' });
3748
+ * // => '<b>&lt;script&gt;</b>'
3749
+ *
3750
+ * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
3751
+ * _.template('hello ${ name }', { 'name': 'curly' });
3752
+ * // => 'hello curly'
3753
+ *
3754
+ * // using the internal `print` function in "evaluate" delimiters
3755
+ * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
3756
+ * // => 'hello stooge!'
3757
+ *
3758
+ * // using custom template delimiters
3759
+ * _.templateSettings = {
3760
+ * 'interpolate': /{{([\s\S]+?)}}/g
3761
+ * };
3762
+ *
3763
+ * _.template('hello {{ name }}!', { 'name': 'mustache' });
3764
+ * // => 'hello mustache!'
3765
+ *
3766
+ * // using the `sourceURL` option to specify a custom sourceURL for the template
3767
+ * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
3768
+ * compiled(data);
3769
+ * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
3770
+ *
3771
+ * // using the `variable` option to ensure a with-statement isn't used in the compiled template
3772
+ * var compiled = _.template('hello <%= data.name %>!', null, { 'variable': 'data' });
3773
+ * compiled.source;
3774
+ * // => function(data) {
3775
+ * var __t, __p = '', __e = _.escape;
3776
+ * __p += 'hello ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
3777
+ * return __p;
3778
+ * }
3779
+ *
3780
+ * // using the `source` property to inline compiled templates for meaningful
3781
+ * // line numbers in error messages and a stack trace
3782
+ * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
3783
+ * var JST = {\
3784
+ * "main": ' + _.template(mainText).source + '\
3785
+ * };\
3786
+ * ');
3787
+ */
3788
+ function template(text, data, options) {
3789
+ // based on John Resig's `tmpl` implementation
3790
+ // http://ejohn.org/blog/javascript-micro-templating/
3791
+ // and Laura Doktorova's doT.js
3792
+ // https://github.com/olado/doT
3793
+ text || (text = '');
3794
+ options || (options = {});
3795
+
3796
+ var isEvaluating,
3797
+ result,
3798
+ settings = lodash.templateSettings,
3799
+ index = 0,
3800
+ interpolate = options.interpolate || settings.interpolate || reNoMatch,
3801
+ source = "__p += '",
3802
+ variable = options.variable || settings.variable,
3803
+ hasVariable = variable;
3804
+
3805
+ // compile regexp to match each delimiter
3806
+ var reDelimiters = RegExp(
3807
+ (options.escape || settings.escape || reNoMatch).source + '|' +
3808
+ interpolate.source + '|' +
3809
+ (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
3810
+ (options.evaluate || settings.evaluate || reNoMatch).source + '|$'
3811
+ , 'g');
3812
+
3813
+ text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
3814
+ interpolateValue || (interpolateValue = esTemplateValue);
3815
+
3816
+ // escape characters that cannot be included in string literals
3817
+ source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
3818
+
3819
+ // replace delimiters with snippets
3820
+ source +=
3821
+ escapeValue ? "' +\n__e(" + escapeValue + ") +\n'" :
3822
+ evaluateValue ? "';\n" + evaluateValue + ";\n__p += '" :
3823
+ interpolateValue ? "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'" : '';
3824
+
3825
+ isEvaluating || (isEvaluating = evaluateValue || reComplexDelimiter.test(escapeValue || interpolateValue));
3826
+ index = offset + match.length;
3827
+ });
3828
+
3829
+ source += "';\n";
3830
+
3831
+ // if `variable` is not specified and the template contains "evaluate"
3832
+ // delimiters, wrap a with-statement around the generated code to add the
3833
+ // data object to the top of the scope chain
3834
+ if (!hasVariable) {
3835
+ variable = 'obj';
3836
+ if (isEvaluating) {
3837
+ source = 'with (' + variable + ') {\n' + source + '\n}\n';
3838
+ }
3839
+ else {
3840
+ // avoid a with-statement by prepending data object references to property names
3841
+ var reDoubleVariable = RegExp('(\\(\\s*)' + variable + '\\.' + variable + '\\b', 'g');
3842
+ source = source
3843
+ .replace(reInsertVariable, '$&' + variable + '.')
3844
+ .replace(reDoubleVariable, '$1__d');
3845
+ }
3846
+ }
3847
+
3848
+ // cleanup code by stripping empty strings
3849
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
3850
+ .replace(reEmptyStringMiddle, '$1')
3851
+ .replace(reEmptyStringTrailing, '$1;');
3852
+
3853
+ // frame code as the function body
3854
+ source = 'function(' + variable + ') {\n' +
3855
+ (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
3856
+ 'var __t, __p = \'\', __e = _.escape' +
3857
+ (isEvaluating
3858
+ ? ', __j = Array.prototype.join;\n' +
3859
+ 'function print() { __p += __j.call(arguments, \'\') }\n'
3860
+ : (hasVariable ? '' : ', __d = ' + variable + '.' + variable + ' || ' + variable) + ';\n'
3861
+ ) +
3862
+ source +
3863
+ 'return __p\n}';
3864
+
3865
+ // use a sourceURL for easier debugging
3866
+ // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
3867
+ var sourceURL = useSourceURL
3868
+ ? '\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']')
3869
+ : '';
3870
+
3871
+ try {
3872
+ result = Function('_', 'return ' + source + sourceURL)(lodash);
3873
+ } catch(e) {
3874
+ e.source = source;
3875
+ throw e;
3876
+ }
3877
+
3878
+ if (data) {
3879
+ return result(data);
3880
+ }
3881
+ // provide the compiled function's source via its `toString` method, in
3882
+ // supported environments, or the `source` property as a convenience for
3883
+ // inlining compiled templates during the build process
3884
+ result.source = source;
3885
+ return result;
3886
+ }
3887
+
3888
+ /**
3889
+ * Executes the `callback` function `n` times, returning an array of the results
3890
+ * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
3891
+ * with one argument; (index).
3892
+ *
3893
+ * @static
3894
+ * @memberOf _
3895
+ * @category Utilities
3896
+ * @param {Number} n The number of times to execute the callback.
3897
+ * @param {Function} callback The function called per iteration.
3898
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3899
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
3900
+ * @example
3901
+ *
3902
+ * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
3903
+ * // => [3, 6, 4]
3904
+ *
3905
+ * _.times(3, function(n) { mage.castSpell(n); });
3906
+ * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
3907
+ *
3908
+ * _.times(3, function(n) { this.cast(n); }, mage);
3909
+ * // => also calls `mage.castSpell(n)` three times
3910
+ */
3911
+ function times(n, callback, thisArg) {
3912
+ n = +n || 0;
3913
+ var index = -1,
3914
+ result = Array(n);
3915
+
3916
+ while (++index < n) {
3917
+ result[index] = callback.call(thisArg, index);
3918
+ }
3919
+ return result;
3920
+ }
3921
+
3922
+ /**
3923
+ * The opposite of `_.escape`, this method converts the HTML entities
3924
+ * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#x27;` in `string` to their
3925
+ * corresponding characters.
3926
+ *
3927
+ * @static
3928
+ * @memberOf _
3929
+ * @category Utilities
3930
+ * @param {String} string The string to unescape.
3931
+ * @returns {String} Returns the unescaped string.
3932
+ * @example
3933
+ *
3934
+ * _.unescape('Moe, Larry &amp; Curly');
3935
+ * // => "Moe, Larry & Curly"
3936
+ */
3937
+ function unescape(string) {
3938
+ return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
3939
+ }
3940
+
3941
+ /**
3942
+ * Generates a unique id. If `prefix` is passed, the id will be appended to it.
3943
+ *
3944
+ * @static
3945
+ * @memberOf _
3946
+ * @category Utilities
3947
+ * @param {String} [prefix] The value to prefix the id with.
3948
+ * @returns {Number|String} Returns a numeric id if no prefix is passed, else
3949
+ * a string id may be returned.
3950
+ * @example
3951
+ *
3952
+ * _.uniqueId('contact_');
3953
+ * // => 'contact_104'
3954
+ */
3955
+ function uniqueId(prefix) {
3956
+ var id = idCounter++;
3957
+ return prefix ? prefix + id : id;
3958
+ }
3959
+
3960
+ /*--------------------------------------------------------------------------*/
3961
+
3962
+ /**
3963
+ * Wraps the value in a `lodash` wrapper object.
3964
+ *
3965
+ * @static
3966
+ * @memberOf _
3967
+ * @category Chaining
3968
+ * @param {Mixed} value The value to wrap.
3969
+ * @returns {Object} Returns the wrapper object.
3970
+ * @example
3971
+ *
3972
+ * var stooges = [
3973
+ * { 'name': 'moe', 'age': 40 },
3974
+ * { 'name': 'larry', 'age': 50 },
3975
+ * { 'name': 'curly', 'age': 60 }
3976
+ * ];
3977
+ *
3978
+ * var youngest = _.chain(stooges)
3979
+ * .sortBy(function(stooge) { return stooge.age; })
3980
+ * .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })
3981
+ * .first()
3982
+ * .value();
3983
+ * // => 'moe is 40'
3984
+ */
3985
+ function chain(value) {
3986
+ value = new lodash(value);
3987
+ value.__chain__ = true;
3988
+ return value;
3989
+ }
3990
+
3991
+ /**
3992
+ * Invokes `interceptor` with the `value` as the first argument, and then
3993
+ * returns `value`. The purpose of this method is to "tap into" a method chain,
3994
+ * in order to perform operations on intermediate results within the chain.
3995
+ *
3996
+ * @static
3997
+ * @memberOf _
3998
+ * @category Chaining
3999
+ * @param {Mixed} value The value to pass to `interceptor`.
4000
+ * @param {Function} interceptor The function to invoke.
4001
+ * @returns {Mixed} Returns `value`.
4002
+ * @example
4003
+ *
4004
+ * _.chain([1, 2, 3, 200])
4005
+ * .filter(function(num) { return num % 2 == 0; })
4006
+ * .tap(alert)
4007
+ * .map(function(num) { return num * num })
4008
+ * .value();
4009
+ * // => // [2, 200] (alerted)
4010
+ * // => [4, 40000]
4011
+ */
4012
+ function tap(value, interceptor) {
4013
+ interceptor(value);
4014
+ return value;
4015
+ }
4016
+
4017
+ /**
4018
+ * Enables method chaining on the wrapper object.
4019
+ *
4020
+ * @name chain
4021
+ * @deprecated
4022
+ * @memberOf _
4023
+ * @category Chaining
4024
+ * @returns {Mixed} Returns the wrapper object.
4025
+ * @example
4026
+ *
4027
+ * _([1, 2, 3]).value();
4028
+ * // => [1, 2, 3]
4029
+ */
4030
+ function wrapperChain() {
4031
+ this.__chain__ = true;
4032
+ return this;
4033
+ }
4034
+
4035
+ /**
4036
+ * Extracts the wrapped value.
4037
+ *
4038
+ * @name value
4039
+ * @memberOf _
4040
+ * @category Chaining
4041
+ * @returns {Mixed} Returns the wrapped value.
4042
+ * @example
4043
+ *
4044
+ * _([1, 2, 3]).value();
4045
+ * // => [1, 2, 3]
4046
+ */
4047
+ function wrapperValue() {
4048
+ return this.__wrapped__;
4049
+ }
4050
+
4051
+ /*--------------------------------------------------------------------------*/
4052
+
4053
+ /**
4054
+ * The semantic version number.
4055
+ *
4056
+ * @static
4057
+ * @memberOf _
4058
+ * @type String
4059
+ */
4060
+ lodash.VERSION = '0.9.2';
4061
+
4062
+ // assign static methods
4063
+ lodash.after = after;
4064
+ lodash.bind = bind;
4065
+ lodash.bindAll = bindAll;
4066
+ lodash.chain = chain;
4067
+ lodash.clone = clone;
4068
+ lodash.compact = compact;
4069
+ lodash.compose = compose;
4070
+ lodash.contains = contains;
4071
+ lodash.countBy = countBy;
4072
+ lodash.debounce = debounce;
4073
+ lodash.defaults = defaults;
4074
+ lodash.defer = defer;
4075
+ lodash.delay = delay;
4076
+ lodash.difference = difference;
4077
+ lodash.escape = escape;
4078
+ lodash.every = every;
4079
+ lodash.extend = extend;
4080
+ lodash.filter = filter;
4081
+ lodash.find = find;
4082
+ lodash.first = first;
4083
+ lodash.flatten = flatten;
4084
+ lodash.forEach = forEach;
4085
+ lodash.forIn = forIn;
4086
+ lodash.forOwn = forOwn;
4087
+ lodash.functions = functions;
4088
+ lodash.groupBy = groupBy;
4089
+ lodash.has = has;
4090
+ lodash.identity = identity;
4091
+ lodash.indexOf = indexOf;
4092
+ lodash.initial = initial;
4093
+ lodash.intersection = intersection;
4094
+ lodash.invert = invert;
4095
+ lodash.invoke = invoke;
4096
+ lodash.isArguments = isArguments;
4097
+ lodash.isArray = isArray;
4098
+ lodash.isBoolean = isBoolean;
4099
+ lodash.isDate = isDate;
4100
+ lodash.isElement = isElement;
4101
+ lodash.isEmpty = isEmpty;
4102
+ lodash.isEqual = isEqual;
4103
+ lodash.isFinite = isFinite;
4104
+ lodash.isFunction = isFunction;
4105
+ lodash.isNaN = isNaN;
4106
+ lodash.isNull = isNull;
4107
+ lodash.isNumber = isNumber;
4108
+ lodash.isObject = isObject;
4109
+ lodash.isPlainObject = isPlainObject;
4110
+ lodash.isRegExp = isRegExp;
4111
+ lodash.isString = isString;
4112
+ lodash.isUndefined = isUndefined;
4113
+ lodash.keys = keys;
4114
+ lodash.last = last;
4115
+ lodash.lastIndexOf = lastIndexOf;
4116
+ lodash.lateBind = lateBind;
4117
+ lodash.map = map;
4118
+ lodash.max = max;
4119
+ lodash.memoize = memoize;
4120
+ lodash.merge = merge;
4121
+ lodash.min = min;
4122
+ lodash.mixin = mixin;
4123
+ lodash.noConflict = noConflict;
4124
+ lodash.object = object;
4125
+ lodash.omit = omit;
4126
+ lodash.once = once;
4127
+ lodash.pairs = pairs;
4128
+ lodash.partial = partial;
4129
+ lodash.pick = pick;
4130
+ lodash.pluck = pluck;
4131
+ lodash.random = random;
4132
+ lodash.range = range;
4133
+ lodash.reduce = reduce;
4134
+ lodash.reduceRight = reduceRight;
4135
+ lodash.reject = reject;
4136
+ lodash.rest = rest;
4137
+ lodash.result = result;
4138
+ lodash.shuffle = shuffle;
4139
+ lodash.size = size;
4140
+ lodash.some = some;
4141
+ lodash.sortBy = sortBy;
4142
+ lodash.sortedIndex = sortedIndex;
4143
+ lodash.tap = tap;
4144
+ lodash.template = template;
4145
+ lodash.throttle = throttle;
4146
+ lodash.times = times;
4147
+ lodash.toArray = toArray;
4148
+ lodash.unescape = unescape;
4149
+ lodash.union = union;
4150
+ lodash.uniq = uniq;
4151
+ lodash.uniqueId = uniqueId;
4152
+ lodash.values = values;
4153
+ lodash.where = where;
4154
+ lodash.without = without;
4155
+ lodash.wrap = wrap;
4156
+ lodash.zip = zip;
4157
+
4158
+ // assign aliases
4159
+ lodash.all = every;
4160
+ lodash.any = some;
4161
+ lodash.collect = map;
4162
+ lodash.detect = find;
4163
+ lodash.drop = rest;
4164
+ lodash.each = forEach;
4165
+ lodash.foldl = reduce;
4166
+ lodash.foldr = reduceRight;
4167
+ lodash.head = first;
4168
+ lodash.include = contains;
4169
+ lodash.inject = reduce;
4170
+ lodash.methods = functions;
4171
+ lodash.select = filter;
4172
+ lodash.tail = rest;
4173
+ lodash.take = first;
4174
+ lodash.unique = uniq;
4175
+
4176
+ // add pseudo private property to be used and removed during the build process
4177
+ lodash._iteratorTemplate = iteratorTemplate;
4178
+
4179
+ /*--------------------------------------------------------------------------*/
4180
+
4181
+ // add all static functions to `lodash.prototype`
4182
+ mixin(lodash);
4183
+
4184
+ // add `lodash.prototype.chain` after calling `mixin()` to avoid overwriting
4185
+ // it with the wrapped `lodash.chain`
4186
+ lodash.prototype.chain = wrapperChain;
4187
+ lodash.prototype.value = wrapperValue;
4188
+
4189
+ // add all mutator Array functions to the wrapper.
4190
+ forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
4191
+ var func = arrayRef[methodName];
4192
+
4193
+ lodash.prototype[methodName] = function() {
4194
+ var value = this.__wrapped__;
4195
+ func.apply(value, arguments);
4196
+
4197
+ // avoid array-like object bugs with `Array#shift` and `Array#splice` in
4198
+ // Firefox < 10 and IE < 9
4199
+ if (hasObjectSpliceBug && value.length === 0) {
4200
+ delete value[0];
4201
+ }
4202
+ if (this.__chain__) {
4203
+ value = new lodash(value);
4204
+ value.__chain__ = true;
4205
+ }
4206
+ return value;
4207
+ };
4208
+ });
4209
+
4210
+ // add all accessor Array functions to the wrapper.
4211
+ forEach(['concat', 'join', 'slice'], function(methodName) {
4212
+ var func = arrayRef[methodName];
4213
+
4214
+ lodash.prototype[methodName] = function() {
4215
+ var value = this.__wrapped__,
4216
+ result = func.apply(value, arguments);
4217
+
4218
+ if (this.__chain__) {
4219
+ result = new lodash(result);
4220
+ result.__chain__ = true;
4221
+ }
4222
+ return result;
4223
+ };
4224
+ });
4225
+
4226
+ /*--------------------------------------------------------------------------*/
4227
+
4228
+ // expose Lo-Dash
4229
+ // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
4230
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
4231
+ // Expose Lo-Dash to the global object even when an AMD loader is present in
4232
+ // case Lo-Dash was injected by a third-party script and not intended to be
4233
+ // loaded as a module. The global assignment can be reverted in the Lo-Dash
4234
+ // module via its `noConflict()` method.
4235
+ window._ = lodash;
4236
+
4237
+ // define as an anonymous module so, through path mapping, it can be
4238
+ // referenced as the "underscore" module
4239
+ define(function() {
4240
+ return lodash;
4241
+ });
4242
+ }
4243
+ // check for `exports` after `define` in case a build optimizer adds an `exports` object
4244
+ else if (freeExports) {
4245
+ // in Node.js or RingoJS v0.8.0+
4246
+ if (typeof module == 'object' && module && module.exports == freeExports) {
4247
+ (module.exports = lodash)._ = lodash;
4248
+ }
4249
+ // in Narwhal or RingoJS v0.7.0-
4250
+ else {
4251
+ freeExports._ = lodash;
4252
+ }
4253
+ }
4254
+ else {
4255
+ // in a browser or Rhino
4256
+ window._ = lodash;
4257
+ }
4258
+ }(this));