red_base 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +339 -0
  3. data/README.rdoc +40 -0
  4. data/Rakefile +42 -0
  5. data/app/assets/fonts/DroidNaskh-Bold.ttf +0 -0
  6. data/app/assets/fonts/DroidNaskh-Regular.ttf +0 -0
  7. data/app/assets/fonts/OpenSans-Bold.ttf +0 -0
  8. data/app/assets/fonts/OpenSans-BoldItalic.ttf +0 -0
  9. data/app/assets/fonts/OpenSans-ExtraBold.ttf +0 -0
  10. data/app/assets/fonts/OpenSans-ExtraBoldItalic.ttf +0 -0
  11. data/app/assets/fonts/OpenSans-Italic.ttf +0 -0
  12. data/app/assets/fonts/OpenSans-Light.ttf +0 -0
  13. data/app/assets/fonts/OpenSans-LightItalic.ttf +0 -0
  14. data/app/assets/fonts/OpenSans-Regular.ttf +0 -0
  15. data/app/assets/fonts/OpenSans-Semibold.ttf +0 -0
  16. data/app/assets/fonts/OpenSans-SemiboldItalic.ttf +0 -0
  17. data/app/assets/javascripts/red_base/application.js +20 -0
  18. data/app/assets/javascripts/red_base/dashboard/angular.js +9 -0
  19. data/app/assets/javascripts/red_base/dashboard/app.js +65 -0
  20. data/app/assets/javascripts/red_base/dashboard/application.js.erb +24 -0
  21. data/app/assets/javascripts/red_base/dashboard/functions.js.erb +91 -0
  22. data/app/assets/javascripts/red_base/dashboard/init.js +38 -0
  23. data/app/assets/javascripts/red_base/dashboard/init.js~ +0 -0
  24. data/app/assets/javascripts/red_base/dashboard/lib/angular-animate.js +1226 -0
  25. data/app/assets/javascripts/red_base/dashboard/lib/angular-gettext.js +202 -0
  26. data/app/assets/javascripts/red_base/dashboard/lib/angular-resource.js +578 -0
  27. data/app/assets/javascripts/red_base/dashboard/lib/angular-route.js +880 -0
  28. data/app/assets/javascripts/red_base/dashboard/lib/angular.js +20031 -0
  29. data/app/assets/javascripts/red_base/dashboard/lib/lodash.underscore.js +4893 -0
  30. data/app/assets/javascripts/red_base/dashboard/lib/restangular.js +1066 -0
  31. data/app/assets/javascripts/red_base/dashboard/locale/translations.js +5 -0
  32. data/app/assets/javascripts/red_base/dashboard/modules/anim.js +32 -0
  33. data/app/assets/javascripts/red_base/dashboard/modules/api.js +32 -0
  34. data/app/assets/javascripts/red_base/dashboard/modules/auth/auth.js +34 -0
  35. data/app/assets/javascripts/red_base/dashboard/modules/auth/group.js +174 -0
  36. data/app/assets/javascripts/red_base/dashboard/modules/auth/user.js +122 -0
  37. data/app/assets/javascripts/red_base/dashboard/modules/list-view.js +293 -0
  38. data/app/assets/javascripts/red_base/dashboard/modules/logs.js +41 -0
  39. data/app/assets/javascripts/red_base/dashboard/modules/modules.js +50 -0
  40. data/app/assets/javascripts/red_base/dashboard/modules/nav.js.erb +92 -0
  41. data/app/assets/javascripts/red_base/dashboard/templates/application.handlebars.erb +42 -0
  42. data/app/assets/javascripts/red_base/dashboard/templates/auth/groups/details.handlebars.erb +15 -0
  43. data/app/assets/javascripts/red_base/dashboard/templates/auth/groups/index.handlebars.erb +7 -0
  44. data/app/assets/javascripts/red_base/dashboard/templates/auth/groups/new.handlebars.erb +39 -0
  45. data/app/assets/javascripts/red_base/dashboard/templates/auth/index.handlebars.erb +31 -0
  46. data/app/assets/javascripts/red_base/dashboard/templates/auth/users/details.handlebars.erb +15 -0
  47. data/app/assets/javascripts/red_base/dashboard/templates/auth/users/index.handlebars.erb +11 -0
  48. data/app/assets/javascripts/red_base/dashboard/templates/auth/users/new.handlebars.erb +33 -0
  49. data/app/assets/javascripts/red_base/dashboard/templates/components/list-view.handlebars.erb +59 -0
  50. data/app/assets/javascripts/red_base/dashboard/templates/components/model-form.handlebars.erb +3 -0
  51. data/app/assets/javascripts/red_base/dashboard/templates/modules.handlebars.erb +15 -0
  52. data/app/assets/javascripts/red_base/dashboard/templates/navigation.handlebars.erb +43 -0
  53. data/app/assets/javascripts/red_base/dashboard/templates/widgets.handlebars +23 -0
  54. data/app/assets/javascripts/red_base/dashboard/variables.js.erb +17 -0
  55. data/app/assets/javascripts/red_base/groups.js +2 -0
  56. data/app/assets/javascripts/red_base/home.js +2 -0
  57. data/app/assets/javascripts/red_base/i18n.js +13 -0
  58. data/app/assets/javascripts/red_base/locale/en.json +27 -0
  59. data/app/assets/javascripts/red_base/locale/fa.json +27 -0
  60. data/app/assets/javascripts/red_base/users.js +2 -0
  61. data/app/assets/stylesheets/red_base/base.css.scss +402 -0
  62. data/app/assets/stylesheets/red_base/dashboard/dashboard.css.scss +169 -0
  63. data/app/assets/stylesheets/red_base/dashboard/ltr/application.css +21 -0
  64. data/app/assets/stylesheets/red_base/dashboard/ltr/base.css.scss.erb +28 -0
  65. data/app/assets/stylesheets/red_base/dashboard/ltr/base.css.scss~ +15 -0
  66. data/app/assets/stylesheets/red_base/dashboard/ltr/buttons.css.scss.erb +48 -0
  67. data/app/assets/stylesheets/red_base/dashboard/ltr/direction.css.scss +38 -0
  68. data/app/assets/stylesheets/red_base/dashboard/ltr/foundation_and_overrides.css.scss +1014 -0
  69. data/app/assets/stylesheets/red_base/dashboard/rtl/application.css +21 -0
  70. data/app/assets/stylesheets/red_base/dashboard/rtl/base.css.scss.erb +31 -0
  71. data/app/assets/stylesheets/red_base/dashboard/rtl/base.css.scss~ +1 -0
  72. data/app/assets/stylesheets/red_base/dashboard/rtl/base.css_flymake.scss +25 -0
  73. data/app/assets/stylesheets/red_base/dashboard/rtl/buttons.css.scss.erb +45 -0
  74. data/app/assets/stylesheets/red_base/dashboard/rtl/direction.css.scss +37 -0
  75. data/app/assets/stylesheets/red_base/dashboard/rtl/foundation_and_overrides.css.scss +1014 -0
  76. data/app/assets/stylesheets/red_base/dashboard/sidebar.css.scss +93 -0
  77. data/app/assets/stylesheets/red_base/devise.css.scss +34 -0
  78. data/app/assets/stylesheets/red_base/groups.css +4 -0
  79. data/app/assets/stylesheets/red_base/home.css.scss +14 -0
  80. data/app/assets/stylesheets/red_base/ltr/application.css +20 -0
  81. data/app/assets/stylesheets/red_base/ltr/buttons.css.scss.erb +48 -0
  82. data/app/assets/stylesheets/red_base/ltr/foundation_and_overrides.scss.erb +1012 -0
  83. data/app/assets/stylesheets/red_base/mixins.css.scss +15 -0
  84. data/app/assets/stylesheets/red_base/mixins.css.scss~ +7 -0
  85. data/app/assets/stylesheets/red_base/rtl/application.css +20 -0
  86. data/app/assets/stylesheets/red_base/rtl/buttons.css.scss.erb +48 -0
  87. data/app/assets/stylesheets/red_base/rtl/foundation_and_overrides.scss.erb +1012 -0
  88. data/app/assets/stylesheets/red_base/users.css +4 -0
  89. data/app/assets/stylesheets/red_base/variables.css.scss +100 -0
  90. data/app/controllers/red_base/api/v1/groups_controller.rb +65 -0
  91. data/app/controllers/red_base/api/v1/logs_controller.rb +12 -0
  92. data/app/controllers/red_base/api/v1/permissions_controller.rb +17 -0
  93. data/app/controllers/red_base/api/v1/users_controller.rb +54 -0
  94. data/app/controllers/red_base/api_controller.rb +51 -0
  95. data/app/controllers/red_base/application_controller.rb +34 -0
  96. data/app/controllers/red_base/dashboard_controller.rb +40 -0
  97. data/app/controllers/red_base/home_controller.rb +19 -0
  98. data/app/controllers/red_base/omniauth/callbacks_controller.rb +43 -0
  99. data/app/controllers/red_base/users/omniauth_callbacks_controller.rb~ +2 -0
  100. data/app/helpers/red_base/application_helper.rb +4 -0
  101. data/app/helpers/red_base/dashboard_helper.rb +5 -0
  102. data/app/helpers/red_base/groups_helper.rb +4 -0
  103. data/app/helpers/red_base/home_helper.rb +4 -0
  104. data/app/helpers/red_base/users_helper.rb +4 -0
  105. data/app/models/ability.rb +39 -0
  106. data/app/models/red_base/group.rb +27 -0
  107. data/app/models/red_base/permission.rb +15 -0
  108. data/app/models/red_base/user.rb +77 -0
  109. data/app/views/angularjs_templates/auth/groups/details.html +21 -0
  110. data/app/views/angularjs_templates/auth/groups/index.html +5 -0
  111. data/app/views/angularjs_templates/auth/groups/new.html +40 -0
  112. data/app/views/angularjs_templates/auth/index.html +30 -0
  113. data/app/views/angularjs_templates/auth/users/details.html +28 -0
  114. data/app/views/angularjs_templates/auth/users/index.html +6 -0
  115. data/app/views/angularjs_templates/auth/users/new.html +45 -0
  116. data/app/views/angularjs_templates/index.html +8 -0
  117. data/app/views/angularjs_templates/list-view/index.html +66 -0
  118. data/app/views/angularjs_templates/locale/fa.po +25 -0
  119. data/app/views/angularjs_templates/locale/templates.pot +24 -0
  120. data/app/views/angularjs_templates/logs/index.html +6 -0
  121. data/app/views/angularjs_templates/modules.html +17 -0
  122. data/app/views/angularjs_templates/nav.html.erb +38 -0
  123. data/app/views/angularjs_templates/nav.html.erb~ +43 -0
  124. data/app/views/devise/confirmations/new.html.erb +34 -0
  125. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  126. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  127. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  128. data/app/views/devise/passwords/edit.html.erb +44 -0
  129. data/app/views/devise/passwords/new.html.erb +32 -0
  130. data/app/views/devise/registrations/edit.html.erb +29 -0
  131. data/app/views/devise/registrations/new.html.erb +91 -0
  132. data/app/views/devise/sessions/new.html.erb +98 -0
  133. data/app/views/devise/shared/_links.erb +25 -0
  134. data/app/views/devise/unlocks/new.html.erb +30 -0
  135. data/app/views/layouts/red_base/application.html.erb +90 -0
  136. data/app/views/layouts/red_base/dashboard.html.erb +21 -0
  137. data/app/views/red_base/api/v1/groups/create.json.jbuilder +4 -0
  138. data/app/views/red_base/api/v1/groups/destroy.html.erb +2 -0
  139. data/app/views/red_base/api/v1/groups/destroy.json.jbuilder +1 -0
  140. data/app/views/red_base/api/v1/groups/edit.html.erb +2 -0
  141. data/app/views/red_base/api/v1/groups/index.html.erb +2 -0
  142. data/app/views/red_base/api/v1/groups/index.json.jbuilder +6 -0
  143. data/app/views/red_base/api/v1/groups/new.html.erb +2 -0
  144. data/app/views/red_base/api/v1/groups/show.html.erb +2 -0
  145. data/app/views/red_base/api/v1/groups/show.json.jbuilder +5 -0
  146. data/app/views/red_base/api/v1/groups/update.json.jbuilder +4 -0
  147. data/app/views/red_base/api/v1/logs/index.json.jbuilder +1 -0
  148. data/app/views/red_base/api/v1/permissions/index.json.jbuilder +1 -0
  149. data/app/views/red_base/api/v1/users/create.html.erb +2 -0
  150. data/app/views/red_base/api/v1/users/create.json.jbuilder +1 -0
  151. data/app/views/red_base/api/v1/users/destroy.json.jbuilder +1 -0
  152. data/app/views/red_base/api/v1/users/distroy.html.erb +2 -0
  153. data/app/views/red_base/api/v1/users/edit.html.erb +2 -0
  154. data/app/views/red_base/api/v1/users/index.html.erb +2 -0
  155. data/app/views/red_base/api/v1/users/index.json.jbuilder +4 -0
  156. data/app/views/red_base/api/v1/users/show.html.erb +2 -0
  157. data/app/views/red_base/api/v1/users/show.json.jbuilder +2 -0
  158. data/app/views/red_base/api/v1/users/update.json.jbuilder +1 -0
  159. data/app/views/red_base/dashboard/index.html.erb +37 -0
  160. data/app/views/red_base/home/index.html.erb +119 -0
  161. data/config/initializers/devise.rb +28 -0
  162. data/config/locales/devise.en.yml +59 -0
  163. data/config/locales/devise.fa.yml +56 -0
  164. data/config/locales/fa/LC_MESSAGES/red_base.mo +0 -0
  165. data/config/locales/fa/messages.mo +0 -0
  166. data/config/locales/fa/red_base.po +181 -0
  167. data/config/locales/red_base.pot +181 -0
  168. data/config/routes.rb +33 -0
  169. data/db/migrate/20131013091000_devise_create_red_base_users.rb +64 -0
  170. data/db/migrate/20131020124701_create_red_base_groups.rb +9 -0
  171. data/db/migrate/20131021170923_create_red_base_permissions.rb +10 -0
  172. data/db/migrate/20131123120422_add_permissions_groups_table.rb +8 -0
  173. data/db/seeds.rb +15 -0
  174. data/lib/devise_patch.rb~ +5 -0
  175. data/lib/generators/red_base/USAGE +8 -0
  176. data/lib/generators/red_base/angularjs_resource_generator.rb +74 -0
  177. data/lib/generators/red_base/install_all_generator.rb +38 -0
  178. data/lib/generators/red_base/install_generator.rb +42 -0
  179. data/lib/generators/red_base/install_specs_generator.rb +48 -0
  180. data/lib/generators/red_base/js_scaffold_generator.rb +232 -0
  181. data/lib/generators/red_base/templates/README +41 -0
  182. data/lib/generators/red_base/templates/README~ +4 -0
  183. data/lib/generators/red_base/templates/SPECS +13 -0
  184. data/lib/generators/red_base/templates/angularjs/details.html.erb +20 -0
  185. data/lib/generators/red_base/templates/angularjs/details.html.erb~ +0 -0
  186. data/lib/generators/red_base/templates/angularjs/index.html.erb +59 -0
  187. data/lib/generators/red_base/templates/angularjs/module.js.erb +259 -0
  188. data/lib/generators/red_base/templates/angularjs/new.html.erb +43 -0
  189. data/lib/generators/red_base/templates/api/controller.rb.erb +54 -0
  190. data/lib/generators/red_base/templates/api/controller.rb.erb~ +37 -0
  191. data/lib/generators/red_base/templates/devise.rb +251 -0
  192. data/lib/generators/red_base/templates/devise.rb~ +238 -0
  193. data/lib/generators/red_base/templates/fast_gettext.rb +4 -0
  194. data/lib/generators/red_base/templates/features/api.feature +92 -0
  195. data/lib/generators/red_base/templates/features/api.step.rb +7 -0
  196. data/lib/generators/red_base/templates/features/step_definitions/email_steps.rb +206 -0
  197. data/lib/generators/red_base/templates/features/support/email_spec.rb +1 -0
  198. data/lib/generators/red_base/templates/features/support/env.rb +79 -0
  199. data/lib/generators/red_base/templates/formtastic.rb +76 -0
  200. data/lib/generators/red_base/templates/js_scaffold.README +25 -0
  201. data/lib/generators/red_base/templates/red_base.rb +14 -0
  202. data/lib/generators/red_base/templates/red_base.rb~ +251 -0
  203. data/lib/generators/red_base/templates/seeds.rb +1 -0
  204. data/lib/generators/red_base/templates/spec/factories/groups.rb +5 -0
  205. data/lib/generators/red_base/templates/spec/factories/users.rb +10 -0
  206. data/lib/generators/red_base/templates/spec/spec_helper.rb +69 -0
  207. data/lib/generators/red_base/templates/spec/support/devise.rb +3 -0
  208. data/lib/generators/red_base/templates/views/create.json.jbuilder.erb +2 -0
  209. data/lib/generators/red_base/templates/views/destroy.json.jbuilder.erb +1 -0
  210. data/lib/generators/red_base/templates/views/index.json.jbuilder.erb +10 -0
  211. data/lib/generators/red_base/templates/views/index.json.jbuilder.erb~ +0 -0
  212. data/lib/generators/red_base/templates/views/show.json.jbuilder.erb +6 -0
  213. data/lib/generators/red_base/templates/views/update.json.jbuilder.erb +6 -0
  214. data/lib/generators/red_base/views_generator.rb +41 -0
  215. data/lib/red_base/active_record.rb +78 -0
  216. data/lib/red_base/active_record.rb~ +0 -0
  217. data/lib/red_base/api/groups_api.rb +41 -0
  218. data/lib/red_base/api/permissions_api.rb +24 -0
  219. data/lib/red_base/api/root.rb +15 -0
  220. data/lib/red_base/api/users_api.rb +20 -0
  221. data/lib/red_base/api.rb +61 -0
  222. data/lib/red_base/cucumber/auth.rb +45 -0
  223. data/lib/red_base/cucumber/exceptions.rb +40 -0
  224. data/lib/red_base/cucumber/interaction.rb +43 -0
  225. data/lib/red_base/cucumber/query.rb +28 -0
  226. data/lib/red_base/cucumber/urls.rb +76 -0
  227. data/lib/red_base/cucumber.rb +25 -0
  228. data/lib/red_base/dashboard/controller.rb +42 -0
  229. data/lib/red_base/dashboard/module.rb +45 -0
  230. data/lib/red_base/dashboard/module.rb~ +25 -0
  231. data/lib/red_base/dashboard.rb +60 -0
  232. data/lib/red_base/dashboard.rb~ +18 -0
  233. data/lib/red_base/engine.rb +132 -0
  234. data/lib/red_base/exceptions.rb +26 -0
  235. data/lib/red_base/i18n.rb +35 -0
  236. data/lib/red_base/initialize.rb +7 -0
  237. data/lib/red_base/omniauth/callbacks.rb +58 -0
  238. data/lib/red_base/omniauth/callbakcs.rb~ +7 -0
  239. data/lib/red_base/omniauth.rb +24 -0
  240. data/lib/red_base/omniauth.rb~ +1 -0
  241. data/lib/red_base/plugins.rb +44 -0
  242. data/lib/red_base/version.rb +22 -0
  243. data/lib/red_base.rb +30 -0
  244. data/lib/tasks/grunt/Gruntfile.js +25 -0
  245. data/lib/tasks/red_base_tasks.rake +23 -0
  246. data/spec/dummy/README.rdoc +28 -0
  247. data/spec/dummy/Rakefile +6 -0
  248. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  249. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  250. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  251. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  252. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  253. data/spec/dummy/bin/bundle +3 -0
  254. data/spec/dummy/bin/rails +4 -0
  255. data/spec/dummy/bin/rake +4 -0
  256. data/spec/dummy/config/application.rb +23 -0
  257. data/spec/dummy/config/boot.rb +5 -0
  258. data/spec/dummy/config/database.yml +25 -0
  259. data/spec/dummy/config/environment.rb +5 -0
  260. data/spec/dummy/config/environments/development.rb +29 -0
  261. data/spec/dummy/config/environments/production.rb +80 -0
  262. data/spec/dummy/config/environments/test.rb +36 -0
  263. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  264. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  265. data/spec/dummy/config/initializers/inflections.rb +16 -0
  266. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  267. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  268. data/spec/dummy/config/initializers/session_store.rb +3 -0
  269. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  270. data/spec/dummy/config/locales/en.yml +23 -0
  271. data/spec/dummy/config/routes.rb +4 -0
  272. data/spec/dummy/config.ru +4 -0
  273. data/spec/dummy/public/404.html +58 -0
  274. data/spec/dummy/public/422.html +58 -0
  275. data/spec/dummy/public/500.html +57 -0
  276. data/spec/dummy/public/favicon.ico +0 -0
  277. data/spec/spec_helper.rb +52 -0
  278. metadata +661 -0
@@ -0,0 +1,4893 @@
1
+ /**
2
+ * @license
3
+ * Lo-Dash 2.3.0 (Custom Build) <http://lodash.com/>
4
+ * Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js`
5
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
6
+ * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
7
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
8
+ * Available under MIT license <http://lodash.com/license>
9
+ */
10
+ ;(function() {
11
+
12
+ /** Used as a safe reference for `undefined` in pre ES5 environments */
13
+ var undefined;
14
+
15
+ /** Used to generate unique IDs */
16
+ var idCounter = 0;
17
+
18
+ /** Used internally to indicate various things */
19
+ var indicatorObject = {};
20
+
21
+ /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
22
+ var keyPrefix = +new Date + '';
23
+
24
+ /** Used to match "interpolate" template delimiters */
25
+ var reInterpolate = /<%=([\s\S]+?)%>/g;
26
+
27
+ /** Used to ensure capturing order of template delimiters */
28
+ var reNoMatch = /($^)/;
29
+
30
+ /** Used to match unescaped characters in compiled string literals */
31
+ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
32
+
33
+ /** `Object#toString` result shortcuts */
34
+ var argsClass = '[object Arguments]',
35
+ arrayClass = '[object Array]',
36
+ boolClass = '[object Boolean]',
37
+ dateClass = '[object Date]',
38
+ funcClass = '[object Function]',
39
+ numberClass = '[object Number]',
40
+ objectClass = '[object Object]',
41
+ regexpClass = '[object RegExp]',
42
+ stringClass = '[object String]';
43
+
44
+ /** Used to determine if values are of the language type Object */
45
+ var objectTypes = {
46
+ 'boolean': false,
47
+ 'function': true,
48
+ 'object': true,
49
+ 'number': false,
50
+ 'string': false,
51
+ 'undefined': false
52
+ };
53
+
54
+ /** Used to escape characters for inclusion in compiled string literals */
55
+ var stringEscapes = {
56
+ '\\': '\\',
57
+ "'": "'",
58
+ '\n': 'n',
59
+ '\r': 'r',
60
+ '\t': 't',
61
+ '\u2028': 'u2028',
62
+ '\u2029': 'u2029'
63
+ };
64
+
65
+ /** Used as a reference to the global object */
66
+ var root = (objectTypes[typeof window] && window) || this;
67
+
68
+ /** Detect free variable `exports` */
69
+ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
70
+
71
+ /** Detect free variable `module` */
72
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
73
+
74
+ /** Detect the popular CommonJS extension `module.exports` */
75
+ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
76
+
77
+ /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
78
+ var freeGlobal = objectTypes[typeof global] && global;
79
+ if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
80
+ root = freeGlobal;
81
+ }
82
+
83
+ /*--------------------------------------------------------------------------*/
84
+
85
+ /**
86
+ * The base implementation of `_.indexOf` without support for binary searches
87
+ * or `fromIndex` constraints.
88
+ *
89
+ * @private
90
+ * @param {Array} array The array to search.
91
+ * @param {*} value The value to search for.
92
+ * @param {number} [fromIndex=0] The index to search from.
93
+ * @returns {number} Returns the index of the matched value or `-1`.
94
+ */
95
+ function baseIndexOf(array, value, fromIndex) {
96
+ var index = (fromIndex || 0) - 1,
97
+ length = array ? array.length : 0;
98
+
99
+ while (++index < length) {
100
+ if (array[index] === value) {
101
+ return index;
102
+ }
103
+ }
104
+ return -1;
105
+ }
106
+
107
+ /**
108
+ * Used by `sortBy` to compare transformed `collection` elements, stable sorting
109
+ * them in ascending order.
110
+ *
111
+ * @private
112
+ * @param {Object} a The object to compare to `b`.
113
+ * @param {Object} b The object to compare to `a`.
114
+ * @returns {number} Returns the sort order indicator of `1` or `-1`.
115
+ */
116
+ function compareAscending(a, b) {
117
+ var ac = a.criteria,
118
+ bc = b.criteria;
119
+
120
+ // ensure a stable sort in V8 and other engines
121
+ // http://code.google.com/p/v8/issues/detail?id=90
122
+ if (ac !== bc) {
123
+ if (ac > bc || typeof ac == 'undefined') {
124
+ return 1;
125
+ }
126
+ if (ac < bc || typeof bc == 'undefined') {
127
+ return -1;
128
+ }
129
+ }
130
+ // The JS engine embedded in Adobe applications like InDesign has a buggy
131
+ // `Array#sort` implementation that causes it, under certain circumstances,
132
+ // to return the same value for `a` and `b`.
133
+ // See https://github.com/jashkenas/underscore/pull/1247
134
+ return a.index - b.index;
135
+ }
136
+
137
+ /**
138
+ * Used by `template` to escape characters for inclusion in compiled
139
+ * string literals.
140
+ *
141
+ * @private
142
+ * @param {string} match The matched character to escape.
143
+ * @returns {string} Returns the escaped character.
144
+ */
145
+ function escapeStringChar(match) {
146
+ return '\\' + stringEscapes[match];
147
+ }
148
+
149
+ /**
150
+ * Slices the `collection` from the `start` index up to, but not including,
151
+ * the `end` index.
152
+ *
153
+ * Note: This function is used instead of `Array#slice` to support node lists
154
+ * in IE < 9 and to ensure dense arrays are returned.
155
+ *
156
+ * @private
157
+ * @param {Array|Object|string} collection The collection to slice.
158
+ * @param {number} start The start index.
159
+ * @param {number} end The end index.
160
+ * @returns {Array} Returns the new array.
161
+ */
162
+ function slice(array, start, end) {
163
+ start || (start = 0);
164
+ if (typeof end == 'undefined') {
165
+ end = array ? array.length : 0;
166
+ }
167
+ var index = -1,
168
+ length = end - start || 0,
169
+ result = Array(length < 0 ? 0 : length);
170
+
171
+ while (++index < length) {
172
+ result[index] = array[start + index];
173
+ }
174
+ return result;
175
+ }
176
+
177
+ /*--------------------------------------------------------------------------*/
178
+
179
+ /**
180
+ * Used for `Array` method references.
181
+ *
182
+ * Normally `Array.prototype` would suffice, however, using an array literal
183
+ * avoids issues in Narwhal.
184
+ */
185
+ var arrayRef = [];
186
+
187
+ /** Used for native method references */
188
+ var objectProto = Object.prototype;
189
+
190
+ /** Used to restore the original `_` reference in `noConflict` */
191
+ var oldDash = root._;
192
+
193
+ /** Used to resolve the internal [[Class]] of values */
194
+ var toString = objectProto.toString;
195
+
196
+ /** Used to detect if a method is native */
197
+ var reNative = RegExp('^' +
198
+ String(toString)
199
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
200
+ .replace(/toString| for [^\]]+/g, '.*?') + '$'
201
+ );
202
+
203
+ /** Native method shortcuts */
204
+ var ceil = Math.ceil,
205
+ floor = Math.floor,
206
+ hasOwnProperty = objectProto.hasOwnProperty,
207
+ now = reNative.test(now = Date.now) && now || function() { return +new Date; },
208
+ push = arrayRef.push,
209
+ propertyIsEnumerable = objectProto.propertyIsEnumerable;
210
+
211
+ /* Native method shortcuts for methods with the same name as other `lodash` methods */
212
+ var nativeCreate = reNative.test(nativeCreate = Object.create) && nativeCreate,
213
+ nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
214
+ nativeIsFinite = root.isFinite,
215
+ nativeIsNaN = root.isNaN,
216
+ nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
217
+ nativeMax = Math.max,
218
+ nativeMin = Math.min,
219
+ nativeRandom = Math.random;
220
+
221
+ /*--------------------------------------------------------------------------*/
222
+
223
+ /**
224
+ * Creates a `lodash` object which wraps the given value to enable intuitive
225
+ * method chaining.
226
+ *
227
+ * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
228
+ * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
229
+ * and `unshift`
230
+ *
231
+ * Chaining is supported in custom builds as long as the `value` method is
232
+ * implicitly or explicitly included in the build.
233
+ *
234
+ * The chainable wrapper functions are:
235
+ * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
236
+ * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
237
+ * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
238
+ * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
239
+ * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
240
+ * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
241
+ * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
242
+ * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
243
+ * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
244
+ * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
245
+ * and `zip`
246
+ *
247
+ * The non-chainable wrapper functions are:
248
+ * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
249
+ * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
250
+ * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
251
+ * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
252
+ * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
253
+ * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
254
+ * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
255
+ * `template`, `unescape`, `uniqueId`, and `value`
256
+ *
257
+ * The wrapper functions `first` and `last` return wrapped values when `n` is
258
+ * provided, otherwise they return unwrapped values.
259
+ *
260
+ * Explicit chaining can be enabled by using the `_.chain` method.
261
+ *
262
+ * @name _
263
+ * @constructor
264
+ * @category Chaining
265
+ * @param {*} value The value to wrap in a `lodash` instance.
266
+ * @returns {Object} Returns a `lodash` instance.
267
+ * @example
268
+ *
269
+ * var wrapped = _([1, 2, 3]);
270
+ *
271
+ * // returns an unwrapped value
272
+ * wrapped.reduce(function(sum, num) {
273
+ * return sum + num;
274
+ * });
275
+ * // => 6
276
+ *
277
+ * // returns a wrapped value
278
+ * var squares = wrapped.map(function(num) {
279
+ * return num * num;
280
+ * });
281
+ *
282
+ * _.isArray(squares);
283
+ * // => false
284
+ *
285
+ * _.isArray(squares.value());
286
+ * // => true
287
+ */
288
+ function lodash(value) {
289
+ return (value instanceof lodash)
290
+ ? value
291
+ : new lodashWrapper(value);
292
+ }
293
+
294
+ /**
295
+ * A fast path for creating `lodash` wrapper objects.
296
+ *
297
+ * @private
298
+ * @param {*} value The value to wrap in a `lodash` instance.
299
+ * @param {boolean} chainAll A flag to enable chaining for all methods
300
+ * @returns {Object} Returns a `lodash` instance.
301
+ */
302
+ function lodashWrapper(value, chainAll) {
303
+ this.__chain__ = !!chainAll;
304
+ this.__wrapped__ = value;
305
+ }
306
+ // ensure `new lodashWrapper` is an instance of `lodash`
307
+ lodashWrapper.prototype = lodash.prototype;
308
+
309
+ /**
310
+ * An object used to flag environments features.
311
+ *
312
+ * @static
313
+ * @memberOf _
314
+ * @type Object
315
+ */
316
+ var support = {};
317
+
318
+ (function() {
319
+ var object = { '0': 1, 'length': 1 };
320
+
321
+ /**
322
+ * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly.
323
+ *
324
+ * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
325
+ * and `splice()` functions that fail to remove the last element, `value[0]`,
326
+ * of array-like objects even though the `length` property is set to `0`.
327
+ * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
328
+ * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
329
+ *
330
+ * @memberOf _.support
331
+ * @type boolean
332
+ */
333
+ support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]);
334
+ }(1));
335
+
336
+ /**
337
+ * By default, the template delimiters used by Lo-Dash are similar to those in
338
+ * embedded Ruby (ERB). Change the following template settings to use alternative
339
+ * delimiters.
340
+ *
341
+ * @static
342
+ * @memberOf _
343
+ * @type Object
344
+ */
345
+ lodash.templateSettings = {
346
+
347
+ /**
348
+ * Used to detect `data` property values to be HTML-escaped.
349
+ *
350
+ * @memberOf _.templateSettings
351
+ * @type RegExp
352
+ */
353
+ 'escape': /<%-([\s\S]+?)%>/g,
354
+
355
+ /**
356
+ * Used to detect code to be evaluated.
357
+ *
358
+ * @memberOf _.templateSettings
359
+ * @type RegExp
360
+ */
361
+ 'evaluate': /<%([\s\S]+?)%>/g,
362
+
363
+ /**
364
+ * Used to detect `data` property values to inject.
365
+ *
366
+ * @memberOf _.templateSettings
367
+ * @type RegExp
368
+ */
369
+ 'interpolate': reInterpolate,
370
+
371
+ /**
372
+ * Used to reference the data object in the template text.
373
+ *
374
+ * @memberOf _.templateSettings
375
+ * @type string
376
+ */
377
+ 'variable': ''
378
+ };
379
+
380
+ /*--------------------------------------------------------------------------*/
381
+
382
+ /**
383
+ * The base implementation of `_.bind` that creates the bound function and
384
+ * sets its meta data.
385
+ *
386
+ * @private
387
+ * @param {Array} bindData The bind data array.
388
+ * @returns {Function} Returns the new bound function.
389
+ */
390
+ function baseBind(bindData) {
391
+ var func = bindData[0],
392
+ partialArgs = bindData[2],
393
+ thisArg = bindData[4];
394
+
395
+ function bound() {
396
+ // `Function#bind` spec
397
+ // http://es5.github.io/#x15.3.4.5
398
+ if (partialArgs) {
399
+ var args = partialArgs.slice();
400
+ push.apply(args, arguments);
401
+ }
402
+ // mimic the constructor's `return` behavior
403
+ // http://es5.github.io/#x13.2.2
404
+ if (this instanceof bound) {
405
+ // ensure `new bound` is an instance of `func`
406
+ var thisBinding = baseCreate(func.prototype),
407
+ result = func.apply(thisBinding, args || arguments);
408
+ return isObject(result) ? result : thisBinding;
409
+ }
410
+ return func.apply(thisArg, args || arguments);
411
+ }
412
+ return bound;
413
+ }
414
+
415
+ /**
416
+ * The base implementation of `_.create` without support for assigning
417
+ * properties to the created object.
418
+ *
419
+ * @private
420
+ * @param {Object} prototype The object to inherit from.
421
+ * @returns {Object} Returns the new object.
422
+ */
423
+ function baseCreate(prototype, properties) {
424
+ return isObject(prototype) ? nativeCreate(prototype) : {};
425
+ }
426
+ // fallback for browsers without `Object.create`
427
+ if (!nativeCreate) {
428
+ baseCreate = (function() {
429
+ function Object() {}
430
+ return function(prototype) {
431
+ if (isObject(prototype)) {
432
+ Object.prototype = prototype;
433
+ var result = new Object;
434
+ Object.prototype = null;
435
+ }
436
+ return result || root.Object();
437
+ };
438
+ }());
439
+ }
440
+
441
+ /**
442
+ * The base implementation of `_.createCallback` without support for creating
443
+ * "_.pluck" or "_.where" style callbacks.
444
+ *
445
+ * @private
446
+ * @param {*} [func=identity] The value to convert to a callback.
447
+ * @param {*} [thisArg] The `this` binding of the created callback.
448
+ * @param {number} [argCount] The number of arguments the callback accepts.
449
+ * @returns {Function} Returns a callback function.
450
+ */
451
+ function baseCreateCallback(func, thisArg, argCount) {
452
+ if (typeof func != 'function') {
453
+ return identity;
454
+ }
455
+ // exit early for no `thisArg` or already bound by `Function#bind`
456
+ if (typeof thisArg == 'undefined' || !('prototype' in func)) {
457
+ return func;
458
+ }
459
+ switch (argCount) {
460
+ case 1: return function(value) {
461
+ return func.call(thisArg, value);
462
+ };
463
+ case 2: return function(a, b) {
464
+ return func.call(thisArg, a, b);
465
+ };
466
+ case 3: return function(value, index, collection) {
467
+ return func.call(thisArg, value, index, collection);
468
+ };
469
+ case 4: return function(accumulator, value, index, collection) {
470
+ return func.call(thisArg, accumulator, value, index, collection);
471
+ };
472
+ }
473
+ return bind(func, thisArg);
474
+ }
475
+
476
+ /**
477
+ * The base implementation of `createWrapper` that creates the wrapper and
478
+ * sets its meta data.
479
+ *
480
+ * @private
481
+ * @param {Array} bindData The bind data array.
482
+ * @returns {Function} Returns the new function.
483
+ */
484
+ function baseCreateWrapper(bindData) {
485
+ var func = bindData[0],
486
+ bitmask = bindData[1],
487
+ partialArgs = bindData[2],
488
+ partialRightArgs = bindData[3],
489
+ thisArg = bindData[4],
490
+ arity = bindData[5];
491
+
492
+ var isBind = bitmask & 1,
493
+ isBindKey = bitmask & 2,
494
+ isCurry = bitmask & 4,
495
+ isCurryBound = bitmask & 8,
496
+ key = func;
497
+
498
+ function bound() {
499
+ var thisBinding = isBind ? thisArg : this;
500
+ if (partialArgs) {
501
+ var args = partialArgs.slice();
502
+ push.apply(args, arguments);
503
+ }
504
+ if (partialRightArgs || isCurry) {
505
+ args || (args = slice(arguments));
506
+ if (partialRightArgs) {
507
+ push.apply(args, partialRightArgs);
508
+ }
509
+ if (isCurry && args.length < arity) {
510
+ bitmask |= 16 & ~32;
511
+ return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
512
+ }
513
+ }
514
+ args || (args = arguments);
515
+ if (isBindKey) {
516
+ func = thisBinding[key];
517
+ }
518
+ if (this instanceof bound) {
519
+ thisBinding = baseCreate(func.prototype);
520
+ var result = func.apply(thisBinding, args);
521
+ return isObject(result) ? result : thisBinding;
522
+ }
523
+ return func.apply(thisBinding, args);
524
+ }
525
+ return bound;
526
+ }
527
+
528
+ /**
529
+ * The base implementation of `_.difference` that accepts a single array
530
+ * of values to exclude.
531
+ *
532
+ * @private
533
+ * @param {Array} array The array to process.
534
+ * @param {Array} [values] The array of values to exclude.
535
+ * @returns {Array} Returns a new array of filtered values.
536
+ */
537
+ function baseDifference(array, values) {
538
+ var index = -1,
539
+ indexOf = getIndexOf(),
540
+ length = array ? array.length : 0,
541
+ result = [];
542
+
543
+ while (++index < length) {
544
+ var value = array[index];
545
+ if (indexOf(values, value) < 0) {
546
+ result.push(value);
547
+ }
548
+ }
549
+ return result;
550
+ }
551
+
552
+ /**
553
+ * The base implementation of `_.flatten` without support for callback
554
+ * shorthands or `thisArg` binding.
555
+ *
556
+ * @private
557
+ * @param {Array} array The array to flatten.
558
+ * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
559
+ * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
560
+ * @param {number} [fromIndex=0] The index to start from.
561
+ * @returns {Array} Returns a new flattened array.
562
+ */
563
+ function baseFlatten(array, isShallow, isStrict, fromIndex) {
564
+ var index = (fromIndex || 0) - 1,
565
+ length = array ? array.length : 0,
566
+ result = [];
567
+
568
+ while (++index < length) {
569
+ var value = array[index];
570
+
571
+ if (value && typeof value == 'object' && typeof value.length == 'number'
572
+ && (isArray(value) || isArguments(value))) {
573
+ // recursively flatten arrays (susceptible to call stack limits)
574
+ if (!isShallow) {
575
+ value = baseFlatten(value, isShallow, isStrict);
576
+ }
577
+ var valIndex = -1,
578
+ valLength = value.length,
579
+ resIndex = result.length;
580
+
581
+ result.length += valLength;
582
+ while (++valIndex < valLength) {
583
+ result[resIndex++] = value[valIndex];
584
+ }
585
+ } else if (!isStrict) {
586
+ result.push(value);
587
+ }
588
+ }
589
+ return result;
590
+ }
591
+
592
+ /**
593
+ * The base implementation of `_.isEqual`, without support for `thisArg` binding,
594
+ * that allows partial "_.where" style comparisons.
595
+ *
596
+ * @private
597
+ * @param {*} a The value to compare.
598
+ * @param {*} b The other value to compare.
599
+ * @param {Function} [callback] The function to customize comparing values.
600
+ * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
601
+ * @param {Array} [stackA=[]] Tracks traversed `a` objects.
602
+ * @param {Array} [stackB=[]] Tracks traversed `b` objects.
603
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
604
+ */
605
+ function baseIsEqual(a, b, stackA, stackB) {
606
+ if (a === b) {
607
+ return a !== 0 || (1 / a == 1 / b);
608
+ }
609
+ var type = typeof a,
610
+ otherType = typeof b;
611
+
612
+ if (a === a &&
613
+ !(a && objectTypes[type]) &&
614
+ !(b && objectTypes[otherType])) {
615
+ return false;
616
+ }
617
+ if (a == null || b == null) {
618
+ return a === b;
619
+ }
620
+ var className = toString.call(a),
621
+ otherClass = toString.call(b);
622
+
623
+ if (className != otherClass) {
624
+ return false;
625
+ }
626
+ switch (className) {
627
+ case boolClass:
628
+ case dateClass:
629
+ return +a == +b;
630
+
631
+ case numberClass:
632
+ return a != +a
633
+ ? b != +b
634
+ : (a == 0 ? (1 / a == 1 / b) : a == +b);
635
+
636
+ case regexpClass:
637
+ case stringClass:
638
+ return a == String(b);
639
+ }
640
+ var isArr = className == arrayClass;
641
+ if (!isArr) {
642
+ var aWrapped = a instanceof lodash,
643
+ bWrapped = b instanceof lodash;
644
+
645
+ if (aWrapped || bWrapped) {
646
+ return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, stackA, stackB);
647
+ }
648
+ if (className != objectClass) {
649
+ return false;
650
+ }
651
+ var ctorA = a.constructor,
652
+ ctorB = b.constructor;
653
+
654
+ if (ctorA != ctorB &&
655
+ !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
656
+ ('constructor' in a && 'constructor' in b)
657
+ ) {
658
+ return false;
659
+ }
660
+ }
661
+ stackA || (stackA = []);
662
+ stackB || (stackB = []);
663
+
664
+ var length = stackA.length;
665
+ while (length--) {
666
+ if (stackA[length] == a) {
667
+ return stackB[length] == b;
668
+ }
669
+ }
670
+ var result = true,
671
+ size = 0;
672
+
673
+ stackA.push(a);
674
+ stackB.push(b);
675
+
676
+ if (isArr) {
677
+ size = b.length;
678
+ result = size == a.length;
679
+
680
+ if (result) {
681
+ while (size--) {
682
+ if (!(result = baseIsEqual(a[size], b[size], stackA, stackB))) {
683
+ break;
684
+ }
685
+ }
686
+ }
687
+ return result;
688
+ }
689
+ forIn(b, function(value, key, b) {
690
+ if (hasOwnProperty.call(b, key)) {
691
+ size++;
692
+ return !(result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, stackA, stackB)) && indicatorObject;
693
+ }
694
+ });
695
+
696
+ if (result) {
697
+ forIn(a, function(value, key, a) {
698
+ if (hasOwnProperty.call(a, key)) {
699
+ return !(result = --size > -1) && indicatorObject;
700
+ }
701
+ });
702
+ }
703
+ return result;
704
+ }
705
+
706
+ /**
707
+ * The base implementation of `_.random` without argument juggling or support
708
+ * for returning floating-point numbers.
709
+ *
710
+ * @private
711
+ * @param {number} min The minimum possible value.
712
+ * @param {number} max The maximum possible value.
713
+ * @returns {number} Returns a random number.
714
+ */
715
+ function baseRandom(min, max) {
716
+ return min + floor(nativeRandom() * (max - min + 1));
717
+ }
718
+
719
+ /**
720
+ * The base implementation of `_.uniq` without support for callback shorthands
721
+ * or `thisArg` binding.
722
+ *
723
+ * @private
724
+ * @param {Array} array The array to process.
725
+ * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
726
+ * @param {Function} [callback] The function called per iteration.
727
+ * @returns {Array} Returns a duplicate-value-free array.
728
+ */
729
+ function baseUniq(array, isSorted, callback) {
730
+ var index = -1,
731
+ indexOf = getIndexOf(),
732
+ length = array ? array.length : 0,
733
+ result = [],
734
+ seen = callback ? [] : result;
735
+
736
+ while (++index < length) {
737
+ var value = array[index],
738
+ computed = callback ? callback(value, index, array) : value;
739
+
740
+ if (isSorted
741
+ ? !index || seen[seen.length - 1] !== computed
742
+ : indexOf(seen, computed) < 0
743
+ ) {
744
+ if (callback) {
745
+ seen.push(computed);
746
+ }
747
+ result.push(value);
748
+ }
749
+ }
750
+ return result;
751
+ }
752
+
753
+ /**
754
+ * Creates a function that aggregates a collection, creating an object composed
755
+ * of keys generated from the results of running each element of the collection
756
+ * through a callback. The given `setter` function sets the keys and values
757
+ * of the composed object.
758
+ *
759
+ * @private
760
+ * @param {Function} setter The setter function.
761
+ * @returns {Function} Returns the new aggregator function.
762
+ */
763
+ function createAggregator(setter) {
764
+ return function(collection, callback, thisArg) {
765
+ var result = {};
766
+ callback = createCallback(callback, thisArg, 3);
767
+
768
+ var index = -1,
769
+ length = collection ? collection.length : 0;
770
+
771
+ if (typeof length == 'number') {
772
+ while (++index < length) {
773
+ var value = collection[index];
774
+ setter(result, value, callback(value, index, collection), collection);
775
+ }
776
+ } else {
777
+ forOwn(collection, function(value, key, collection) {
778
+ setter(result, value, callback(value, key, collection), collection);
779
+ });
780
+ }
781
+ return result;
782
+ };
783
+ }
784
+
785
+ /**
786
+ * Creates a function that, when called, either curries or invokes `func`
787
+ * with an optional `this` binding and partially applied arguments.
788
+ *
789
+ * @private
790
+ * @param {Function|string} func The function or method name to reference.
791
+ * @param {number} bitmask The bitmask of method flags to compose.
792
+ * The bitmask may be composed of the following flags:
793
+ * 1 - `_.bind`
794
+ * 2 - `_.bindKey`
795
+ * 4 - `_.curry`
796
+ * 8 - `_.curry` (bound)
797
+ * 16 - `_.partial`
798
+ * 32 - `_.partialRight`
799
+ * @param {Array} [partialArgs] An array of arguments to prepend to those
800
+ * provided to the new function.
801
+ * @param {Array} [partialRightArgs] An array of arguments to append to those
802
+ * provided to the new function.
803
+ * @param {*} [thisArg] The `this` binding of `func`.
804
+ * @param {number} [arity] The arity of `func`.
805
+ * @returns {Function} Returns the new function.
806
+ */
807
+ function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
808
+ var isBind = bitmask & 1,
809
+ isBindKey = bitmask & 2,
810
+ isCurry = bitmask & 4,
811
+ isCurryBound = bitmask & 8,
812
+ isPartial = bitmask & 16,
813
+ isPartialRight = bitmask & 32;
814
+
815
+ if (!isBindKey && !isFunction(func)) {
816
+ throw new TypeError;
817
+ }
818
+ if (isPartial && !partialArgs.length) {
819
+ bitmask &= ~16;
820
+ isPartial = partialArgs = false;
821
+ }
822
+ if (isPartialRight && !partialRightArgs.length) {
823
+ bitmask &= ~32;
824
+ isPartialRight = partialRightArgs = false;
825
+ }
826
+ // fast path for `_.bind`
827
+ var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
828
+ return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
829
+ }
830
+
831
+ /**
832
+ * Used by `escape` to convert characters to HTML entities.
833
+ *
834
+ * @private
835
+ * @param {string} match The matched character to escape.
836
+ * @returns {string} Returns the escaped character.
837
+ */
838
+ function escapeHtmlChar(match) {
839
+ return htmlEscapes[match];
840
+ }
841
+
842
+ /**
843
+ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
844
+ * customized, this method returns the custom method, otherwise it returns
845
+ * the `baseIndexOf` function.
846
+ *
847
+ * @private
848
+ * @returns {Function} Returns the "indexOf" function.
849
+ */
850
+ function getIndexOf() {
851
+ var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
852
+ return result;
853
+ }
854
+
855
+ /**
856
+ * Used by `unescape` to convert HTML entities to characters.
857
+ *
858
+ * @private
859
+ * @param {string} match The matched character to unescape.
860
+ * @returns {string} Returns the unescaped character.
861
+ */
862
+ function unescapeHtmlChar(match) {
863
+ return htmlUnescapes[match];
864
+ }
865
+
866
+ /*--------------------------------------------------------------------------*/
867
+
868
+ /**
869
+ * Checks if `value` is an `arguments` object.
870
+ *
871
+ * @static
872
+ * @memberOf _
873
+ * @category Objects
874
+ * @param {*} value The value to check.
875
+ * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
876
+ * @example
877
+ *
878
+ * (function() { return _.isArguments(arguments); })(1, 2, 3);
879
+ * // => true
880
+ *
881
+ * _.isArguments([1, 2, 3]);
882
+ * // => false
883
+ */
884
+ function isArguments(value) {
885
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
886
+ toString.call(value) == argsClass || false;
887
+ }
888
+ // fallback for browsers that can't detect `arguments` objects by [[Class]]
889
+ if (!isArguments(arguments)) {
890
+ isArguments = function(value) {
891
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
892
+ hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false;
893
+ };
894
+ }
895
+
896
+ /**
897
+ * Checks if `value` is an array.
898
+ *
899
+ * @static
900
+ * @memberOf _
901
+ * @type Function
902
+ * @category Objects
903
+ * @param {*} value The value to check.
904
+ * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
905
+ * @example
906
+ *
907
+ * (function() { return _.isArray(arguments); })();
908
+ * // => false
909
+ *
910
+ * _.isArray([1, 2, 3]);
911
+ * // => true
912
+ */
913
+ var isArray = nativeIsArray || function(value) {
914
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
915
+ toString.call(value) == arrayClass || false;
916
+ };
917
+
918
+ /**
919
+ * A fallback implementation of `Object.keys` which produces an array of the
920
+ * given object's own enumerable property names.
921
+ *
922
+ * @private
923
+ * @type Function
924
+ * @param {Object} object The object to inspect.
925
+ * @returns {Array} Returns an array of property names.
926
+ */
927
+ var shimKeys = function(object) {
928
+ var index, iterable = object, result = [];
929
+ if (!iterable) return result;
930
+ if (!(objectTypes[typeof object])) return result;
931
+ for (index in iterable) {
932
+ if (hasOwnProperty.call(iterable, index)) {
933
+ result.push(index);
934
+ }
935
+ }
936
+ return result
937
+ };
938
+
939
+ /**
940
+ * Creates an array composed of the own enumerable property names of an object.
941
+ *
942
+ * @static
943
+ * @memberOf _
944
+ * @category Objects
945
+ * @param {Object} object The object to inspect.
946
+ * @returns {Array} Returns an array of property names.
947
+ * @example
948
+ *
949
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
950
+ * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
951
+ */
952
+ var keys = !nativeKeys ? shimKeys : function(object) {
953
+ if (!isObject(object)) {
954
+ return [];
955
+ }
956
+ return nativeKeys(object);
957
+ };
958
+
959
+ /**
960
+ * Used to convert characters to HTML entities:
961
+ *
962
+ * Though the `>` character is escaped for symmetry, characters like `>` and `/`
963
+ * don't require escaping in HTML and have no special meaning unless they're part
964
+ * of a tag or an unquoted attribute value.
965
+ * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
966
+ */
967
+ var htmlEscapes = {
968
+ '&': '&amp;',
969
+ '<': '&lt;',
970
+ '>': '&gt;',
971
+ '"': '&quot;',
972
+ "'": '&#x27;'
973
+ };
974
+
975
+ /** Used to convert HTML entities to characters */
976
+ var htmlUnescapes = invert(htmlEscapes);
977
+
978
+ /** Used to match HTML entities and HTML characters */
979
+ var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
980
+ reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
981
+
982
+ /*--------------------------------------------------------------------------*/
983
+
984
+ /**
985
+ * Assigns own enumerable properties of source object(s) to the destination
986
+ * object. Subsequent sources will overwrite property assignments of previous
987
+ * sources. If a callback is provided it will be executed to produce the
988
+ * assigned values. The callback is bound to `thisArg` and invoked with two
989
+ * arguments; (objectValue, sourceValue).
990
+ *
991
+ * @static
992
+ * @memberOf _
993
+ * @type Function
994
+ * @alias extend
995
+ * @category Objects
996
+ * @param {Object} object The destination object.
997
+ * @param {...Object} [source] The source objects.
998
+ * @param {Function} [callback] The function to customize assigning values.
999
+ * @param {*} [thisArg] The `this` binding of `callback`.
1000
+ * @returns {Object} Returns the destination object.
1001
+ * @example
1002
+ *
1003
+ * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
1004
+ * // => { 'name': 'fred', 'employer': 'slate' }
1005
+ *
1006
+ * var defaults = _.partialRight(_.assign, function(a, b) {
1007
+ * return typeof a == 'undefined' ? b : a;
1008
+ * });
1009
+ *
1010
+ * var object = { 'name': 'barney' };
1011
+ * defaults(object, { 'name': 'fred', 'employer': 'slate' });
1012
+ * // => { 'name': 'barney', 'employer': 'slate' }
1013
+ */
1014
+ function assign(object) {
1015
+ if (!object) {
1016
+ return object;
1017
+ }
1018
+ for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
1019
+ var iterable = arguments[argsIndex];
1020
+ if (iterable) {
1021
+ for (var key in iterable) {
1022
+ object[key] = iterable[key];
1023
+ }
1024
+ }
1025
+ }
1026
+ return object;
1027
+ }
1028
+
1029
+ /**
1030
+ * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
1031
+ * be cloned, otherwise they will be assigned by reference. If a callback
1032
+ * is provided it will be executed to produce the cloned values. If the
1033
+ * callback returns `undefined` cloning will be handled by the method instead.
1034
+ * The callback is bound to `thisArg` and invoked with one argument; (value).
1035
+ *
1036
+ * @static
1037
+ * @memberOf _
1038
+ * @category Objects
1039
+ * @param {*} value The value to clone.
1040
+ * @param {boolean} [isDeep=false] Specify a deep clone.
1041
+ * @param {Function} [callback] The function to customize cloning values.
1042
+ * @param {*} [thisArg] The `this` binding of `callback`.
1043
+ * @returns {*} Returns the cloned value.
1044
+ * @example
1045
+ *
1046
+ * var characters = [
1047
+ * { 'name': 'barney', 'age': 36 },
1048
+ * { 'name': 'fred', 'age': 40 }
1049
+ * ];
1050
+ *
1051
+ * var shallow = _.clone(characters);
1052
+ * shallow[0] === characters[0];
1053
+ * // => true
1054
+ *
1055
+ * var deep = _.clone(characters, true);
1056
+ * deep[0] === characters[0];
1057
+ * // => false
1058
+ *
1059
+ * _.mixin({
1060
+ * 'clone': _.partialRight(_.clone, function(value) {
1061
+ * return _.isElement(value) ? value.cloneNode(false) : undefined;
1062
+ * })
1063
+ * });
1064
+ *
1065
+ * var clone = _.clone(document.body);
1066
+ * clone.childNodes.length;
1067
+ * // => 0
1068
+ */
1069
+ function clone(value) {
1070
+ return isObject(value)
1071
+ ? (isArray(value) ? slice(value) : assign({}, value))
1072
+ : value;
1073
+ }
1074
+
1075
+ /**
1076
+ * Assigns own enumerable properties of source object(s) to the destination
1077
+ * object for all destination properties that resolve to `undefined`. Once a
1078
+ * property is set, additional defaults of the same property will be ignored.
1079
+ *
1080
+ * @static
1081
+ * @memberOf _
1082
+ * @type Function
1083
+ * @category Objects
1084
+ * @param {Object} object The destination object.
1085
+ * @param {...Object} [source] The source objects.
1086
+ * @param- {Object} [guard] Allows working with `_.reduce` without using its
1087
+ * `key` and `object` arguments as sources.
1088
+ * @returns {Object} Returns the destination object.
1089
+ * @example
1090
+ *
1091
+ * var object = { 'name': 'barney' };
1092
+ * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
1093
+ * // => { 'name': 'barney', 'employer': 'slate' }
1094
+ */
1095
+ function defaults(object) {
1096
+ if (!object) {
1097
+ return object;
1098
+ }
1099
+ for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
1100
+ var iterable = arguments[argsIndex];
1101
+ if (iterable) {
1102
+ for (var key in iterable) {
1103
+ if (typeof object[key] == 'undefined') {
1104
+ object[key] = iterable[key];
1105
+ }
1106
+ }
1107
+ }
1108
+ }
1109
+ return object;
1110
+ }
1111
+
1112
+ /**
1113
+ * Iterates over own and inherited enumerable properties of an object,
1114
+ * executing the callback for each property. The callback is bound to `thisArg`
1115
+ * and invoked with three arguments; (value, key, object). Callbacks may exit
1116
+ * iteration early by explicitly returning `false`.
1117
+ *
1118
+ * @static
1119
+ * @memberOf _
1120
+ * @type Function
1121
+ * @category Objects
1122
+ * @param {Object} object The object to iterate over.
1123
+ * @param {Function} [callback=identity] The function called per iteration.
1124
+ * @param {*} [thisArg] The `this` binding of `callback`.
1125
+ * @returns {Object} Returns `object`.
1126
+ * @example
1127
+ *
1128
+ * function Shape() {
1129
+ * this.x = 0;
1130
+ * this.y = 0;
1131
+ * }
1132
+ *
1133
+ * Shape.prototype.move = function(x, y) {
1134
+ * this.x += x;
1135
+ * this.y += y;
1136
+ * };
1137
+ *
1138
+ * _.forIn(new Shape, function(value, key) {
1139
+ * console.log(key);
1140
+ * });
1141
+ * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
1142
+ */
1143
+ var forIn = function(collection, callback) {
1144
+ var index, iterable = collection, result = iterable;
1145
+ if (!iterable) return result;
1146
+ if (!objectTypes[typeof iterable]) return result;
1147
+ for (index in iterable) {
1148
+ if (callback(iterable[index], index, collection) === indicatorObject) return result;
1149
+ }
1150
+ return result
1151
+ };
1152
+
1153
+ /**
1154
+ * Iterates over own enumerable properties of an object, executing the callback
1155
+ * for each property. The callback is bound to `thisArg` and invoked with three
1156
+ * arguments; (value, key, object). Callbacks may exit iteration early by
1157
+ * explicitly returning `false`.
1158
+ *
1159
+ * @static
1160
+ * @memberOf _
1161
+ * @type Function
1162
+ * @category Objects
1163
+ * @param {Object} object The object to iterate over.
1164
+ * @param {Function} [callback=identity] The function called per iteration.
1165
+ * @param {*} [thisArg] The `this` binding of `callback`.
1166
+ * @returns {Object} Returns `object`.
1167
+ * @example
1168
+ *
1169
+ * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
1170
+ * console.log(key);
1171
+ * });
1172
+ * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
1173
+ */
1174
+ var forOwn = function(collection, callback) {
1175
+ var index, iterable = collection, result = iterable;
1176
+ if (!iterable) return result;
1177
+ if (!objectTypes[typeof iterable]) return result;
1178
+ for (index in iterable) {
1179
+ if (hasOwnProperty.call(iterable, index)) {
1180
+ if (callback(iterable[index], index, collection) === indicatorObject) return result;
1181
+ }
1182
+ }
1183
+ return result
1184
+ };
1185
+
1186
+ /**
1187
+ * Creates a sorted array of property names of all enumerable properties,
1188
+ * own and inherited, of `object` that have function values.
1189
+ *
1190
+ * @static
1191
+ * @memberOf _
1192
+ * @alias methods
1193
+ * @category Objects
1194
+ * @param {Object} object The object to inspect.
1195
+ * @returns {Array} Returns an array of property names that have function values.
1196
+ * @example
1197
+ *
1198
+ * _.functions(_);
1199
+ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
1200
+ */
1201
+ function functions(object) {
1202
+ var result = [];
1203
+ forIn(object, function(value, key) {
1204
+ if (isFunction(value)) {
1205
+ result.push(key);
1206
+ }
1207
+ });
1208
+ return result.sort();
1209
+ }
1210
+
1211
+ /**
1212
+ * Checks if the specified object `property` exists and is a direct property,
1213
+ * instead of an inherited property.
1214
+ *
1215
+ * @static
1216
+ * @memberOf _
1217
+ * @category Objects
1218
+ * @param {Object} object The object to check.
1219
+ * @param {string} property The property to check for.
1220
+ * @returns {boolean} Returns `true` if key is a direct property, else `false`.
1221
+ * @example
1222
+ *
1223
+ * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
1224
+ * // => true
1225
+ */
1226
+ function has(object, property) {
1227
+ return object ? hasOwnProperty.call(object, property) : false;
1228
+ }
1229
+
1230
+ /**
1231
+ * Creates an object composed of the inverted keys and values of the given object.
1232
+ *
1233
+ * @static
1234
+ * @memberOf _
1235
+ * @category Objects
1236
+ * @param {Object} object The object to invert.
1237
+ * @returns {Object} Returns the created inverted object.
1238
+ * @example
1239
+ *
1240
+ * _.invert({ 'first': 'fred', 'second': 'barney' });
1241
+ * // => { 'fred': 'first', 'barney': 'second' }
1242
+ */
1243
+ function invert(object) {
1244
+ var index = -1,
1245
+ props = keys(object),
1246
+ length = props.length,
1247
+ result = {};
1248
+
1249
+ while (++index < length) {
1250
+ var key = props[index];
1251
+ result[object[key]] = key;
1252
+ }
1253
+ return result;
1254
+ }
1255
+
1256
+ /**
1257
+ * Checks if `value` is a boolean value.
1258
+ *
1259
+ * @static
1260
+ * @memberOf _
1261
+ * @category Objects
1262
+ * @param {*} value The value to check.
1263
+ * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
1264
+ * @example
1265
+ *
1266
+ * _.isBoolean(null);
1267
+ * // => false
1268
+ */
1269
+ function isBoolean(value) {
1270
+ return value === true || value === false ||
1271
+ value && typeof value == 'object' && toString.call(value) == boolClass || false;
1272
+ }
1273
+
1274
+ /**
1275
+ * Checks if `value` is a date.
1276
+ *
1277
+ * @static
1278
+ * @memberOf _
1279
+ * @category Objects
1280
+ * @param {*} value The value to check.
1281
+ * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
1282
+ * @example
1283
+ *
1284
+ * _.isDate(new Date);
1285
+ * // => true
1286
+ */
1287
+ function isDate(value) {
1288
+ return value && typeof value == 'object' && toString.call(value) == dateClass || false;
1289
+ }
1290
+
1291
+ /**
1292
+ * Checks if `value` is a DOM element.
1293
+ *
1294
+ * @static
1295
+ * @memberOf _
1296
+ * @category Objects
1297
+ * @param {*} value The value to check.
1298
+ * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
1299
+ * @example
1300
+ *
1301
+ * _.isElement(document.body);
1302
+ * // => true
1303
+ */
1304
+ function isElement(value) {
1305
+ return value && value.nodeType === 1 || false;
1306
+ }
1307
+
1308
+ /**
1309
+ * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
1310
+ * length of `0` and objects with no own enumerable properties are considered
1311
+ * "empty".
1312
+ *
1313
+ * @static
1314
+ * @memberOf _
1315
+ * @category Objects
1316
+ * @param {Array|Object|string} value The value to inspect.
1317
+ * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
1318
+ * @example
1319
+ *
1320
+ * _.isEmpty([1, 2, 3]);
1321
+ * // => false
1322
+ *
1323
+ * _.isEmpty({});
1324
+ * // => true
1325
+ *
1326
+ * _.isEmpty('');
1327
+ * // => true
1328
+ */
1329
+ function isEmpty(value) {
1330
+ if (!value) {
1331
+ return true;
1332
+ }
1333
+ if (isArray(value) || isString(value)) {
1334
+ return !value.length;
1335
+ }
1336
+ for (var key in value) {
1337
+ if (hasOwnProperty.call(value, key)) {
1338
+ return false;
1339
+ }
1340
+ }
1341
+ return true;
1342
+ }
1343
+
1344
+ /**
1345
+ * Performs a deep comparison between two values to determine if they are
1346
+ * equivalent to each other. If a callback is provided it will be executed
1347
+ * to compare values. If the callback returns `undefined` comparisons will
1348
+ * be handled by the method instead. The callback is bound to `thisArg` and
1349
+ * invoked with two arguments; (a, b).
1350
+ *
1351
+ * @static
1352
+ * @memberOf _
1353
+ * @category Objects
1354
+ * @param {*} a The value to compare.
1355
+ * @param {*} b The other value to compare.
1356
+ * @param {Function} [callback] The function to customize comparing values.
1357
+ * @param {*} [thisArg] The `this` binding of `callback`.
1358
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
1359
+ * @example
1360
+ *
1361
+ * var object = { 'name': 'fred' };
1362
+ * var copy = { 'name': 'fred' };
1363
+ *
1364
+ * object == copy;
1365
+ * // => false
1366
+ *
1367
+ * _.isEqual(object, copy);
1368
+ * // => true
1369
+ *
1370
+ * var words = ['hello', 'goodbye'];
1371
+ * var otherWords = ['hi', 'goodbye'];
1372
+ *
1373
+ * _.isEqual(words, otherWords, function(a, b) {
1374
+ * var reGreet = /^(?:hello|hi)$/i,
1375
+ * aGreet = _.isString(a) && reGreet.test(a),
1376
+ * bGreet = _.isString(b) && reGreet.test(b);
1377
+ *
1378
+ * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
1379
+ * });
1380
+ * // => true
1381
+ */
1382
+ function isEqual(a, b) {
1383
+ return baseIsEqual(a, b);
1384
+ }
1385
+
1386
+ /**
1387
+ * Checks if `value` is, or can be coerced to, a finite number.
1388
+ *
1389
+ * Note: This is not the same as native `isFinite` which will return true for
1390
+ * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
1391
+ *
1392
+ * @static
1393
+ * @memberOf _
1394
+ * @category Objects
1395
+ * @param {*} value The value to check.
1396
+ * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
1397
+ * @example
1398
+ *
1399
+ * _.isFinite(-101);
1400
+ * // => true
1401
+ *
1402
+ * _.isFinite('10');
1403
+ * // => true
1404
+ *
1405
+ * _.isFinite(true);
1406
+ * // => false
1407
+ *
1408
+ * _.isFinite('');
1409
+ * // => false
1410
+ *
1411
+ * _.isFinite(Infinity);
1412
+ * // => false
1413
+ */
1414
+ function isFinite(value) {
1415
+ return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
1416
+ }
1417
+
1418
+ /**
1419
+ * Checks if `value` is a function.
1420
+ *
1421
+ * @static
1422
+ * @memberOf _
1423
+ * @category Objects
1424
+ * @param {*} value The value to check.
1425
+ * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
1426
+ * @example
1427
+ *
1428
+ * _.isFunction(_);
1429
+ * // => true
1430
+ */
1431
+ function isFunction(value) {
1432
+ return typeof value == 'function';
1433
+ }
1434
+ // fallback for older versions of Chrome and Safari
1435
+ if (isFunction(/x/)) {
1436
+ isFunction = function(value) {
1437
+ return typeof value == 'function' && toString.call(value) == funcClass;
1438
+ };
1439
+ }
1440
+
1441
+ /**
1442
+ * Checks if `value` is the language type of Object.
1443
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1444
+ *
1445
+ * @static
1446
+ * @memberOf _
1447
+ * @category Objects
1448
+ * @param {*} value The value to check.
1449
+ * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
1450
+ * @example
1451
+ *
1452
+ * _.isObject({});
1453
+ * // => true
1454
+ *
1455
+ * _.isObject([1, 2, 3]);
1456
+ * // => true
1457
+ *
1458
+ * _.isObject(1);
1459
+ * // => false
1460
+ */
1461
+ function isObject(value) {
1462
+ // check if the value is the ECMAScript language type of Object
1463
+ // http://es5.github.io/#x8
1464
+ // and avoid a V8 bug
1465
+ // http://code.google.com/p/v8/issues/detail?id=2291
1466
+ return !!(value && objectTypes[typeof value]);
1467
+ }
1468
+
1469
+ /**
1470
+ * Checks if `value` is `NaN`.
1471
+ *
1472
+ * Note: This is not the same as native `isNaN` which will return `true` for
1473
+ * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
1474
+ *
1475
+ * @static
1476
+ * @memberOf _
1477
+ * @category Objects
1478
+ * @param {*} value The value to check.
1479
+ * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
1480
+ * @example
1481
+ *
1482
+ * _.isNaN(NaN);
1483
+ * // => true
1484
+ *
1485
+ * _.isNaN(new Number(NaN));
1486
+ * // => true
1487
+ *
1488
+ * isNaN(undefined);
1489
+ * // => true
1490
+ *
1491
+ * _.isNaN(undefined);
1492
+ * // => false
1493
+ */
1494
+ function isNaN(value) {
1495
+ // `NaN` as a primitive is the only value that is not equal to itself
1496
+ // (perform the [[Class]] check first to avoid errors with some host objects in IE)
1497
+ return isNumber(value) && value != +value;
1498
+ }
1499
+
1500
+ /**
1501
+ * Checks if `value` is `null`.
1502
+ *
1503
+ * @static
1504
+ * @memberOf _
1505
+ * @category Objects
1506
+ * @param {*} value The value to check.
1507
+ * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
1508
+ * @example
1509
+ *
1510
+ * _.isNull(null);
1511
+ * // => true
1512
+ *
1513
+ * _.isNull(undefined);
1514
+ * // => false
1515
+ */
1516
+ function isNull(value) {
1517
+ return value === null;
1518
+ }
1519
+
1520
+ /**
1521
+ * Checks if `value` is a number.
1522
+ *
1523
+ * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
1524
+ *
1525
+ * @static
1526
+ * @memberOf _
1527
+ * @category Objects
1528
+ * @param {*} value The value to check.
1529
+ * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
1530
+ * @example
1531
+ *
1532
+ * _.isNumber(8.4 * 5);
1533
+ * // => true
1534
+ */
1535
+ function isNumber(value) {
1536
+ return typeof value == 'number' ||
1537
+ value && typeof value == 'object' && toString.call(value) == numberClass || false;
1538
+ }
1539
+
1540
+ /**
1541
+ * Checks if `value` is a regular expression.
1542
+ *
1543
+ * @static
1544
+ * @memberOf _
1545
+ * @category Objects
1546
+ * @param {*} value The value to check.
1547
+ * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
1548
+ * @example
1549
+ *
1550
+ * _.isRegExp(/fred/);
1551
+ * // => true
1552
+ */
1553
+ function isRegExp(value) {
1554
+ return value && objectTypes[typeof value] && toString.call(value) == regexpClass || false;
1555
+ }
1556
+
1557
+ /**
1558
+ * Checks if `value` is a string.
1559
+ *
1560
+ * @static
1561
+ * @memberOf _
1562
+ * @category Objects
1563
+ * @param {*} value The value to check.
1564
+ * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
1565
+ * @example
1566
+ *
1567
+ * _.isString('fred');
1568
+ * // => true
1569
+ */
1570
+ function isString(value) {
1571
+ return typeof value == 'string' ||
1572
+ value && typeof value == 'object' && toString.call(value) == stringClass || false;
1573
+ }
1574
+
1575
+ /**
1576
+ * Checks if `value` is `undefined`.
1577
+ *
1578
+ * @static
1579
+ * @memberOf _
1580
+ * @category Objects
1581
+ * @param {*} value The value to check.
1582
+ * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
1583
+ * @example
1584
+ *
1585
+ * _.isUndefined(void 0);
1586
+ * // => true
1587
+ */
1588
+ function isUndefined(value) {
1589
+ return typeof value == 'undefined';
1590
+ }
1591
+
1592
+ /**
1593
+ * Creates a shallow clone of `object` excluding the specified properties.
1594
+ * Property names may be specified as individual arguments or as arrays of
1595
+ * property names. If a callback is provided it will be executed for each
1596
+ * property of `object` omitting the properties the callback returns truey
1597
+ * for. The callback is bound to `thisArg` and invoked with three arguments;
1598
+ * (value, key, object).
1599
+ *
1600
+ * @static
1601
+ * @memberOf _
1602
+ * @category Objects
1603
+ * @param {Object} object The source object.
1604
+ * @param {Function|...string|string[]} [callback] The properties to omit or the
1605
+ * function called per iteration.
1606
+ * @param {*} [thisArg] The `this` binding of `callback`.
1607
+ * @returns {Object} Returns an object without the omitted properties.
1608
+ * @example
1609
+ *
1610
+ * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
1611
+ * // => { 'name': 'fred' }
1612
+ *
1613
+ * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
1614
+ * return typeof value == 'number';
1615
+ * });
1616
+ * // => { 'name': 'fred' }
1617
+ */
1618
+ function omit(object) {
1619
+ var props = [];
1620
+ forIn(object, function(value, key) {
1621
+ props.push(key);
1622
+ });
1623
+ props = baseDifference(props, baseFlatten(arguments, true, false, 1));
1624
+
1625
+ var index = -1,
1626
+ length = props.length,
1627
+ result = {};
1628
+
1629
+ while (++index < length) {
1630
+ var key = props[index];
1631
+ result[key] = object[key];
1632
+ }
1633
+ return result;
1634
+ }
1635
+
1636
+ /**
1637
+ * Creates a two dimensional array of an object's key-value pairs,
1638
+ * i.e. `[[key1, value1], [key2, value2]]`.
1639
+ *
1640
+ * @static
1641
+ * @memberOf _
1642
+ * @category Objects
1643
+ * @param {Object} object The object to inspect.
1644
+ * @returns {Array} Returns new array of key-value pairs.
1645
+ * @example
1646
+ *
1647
+ * _.pairs({ 'barney': 36, 'fred': 40 });
1648
+ * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
1649
+ */
1650
+ function pairs(object) {
1651
+ var index = -1,
1652
+ props = keys(object),
1653
+ length = props.length,
1654
+ result = Array(length);
1655
+
1656
+ while (++index < length) {
1657
+ var key = props[index];
1658
+ result[index] = [key, object[key]];
1659
+ }
1660
+ return result;
1661
+ }
1662
+
1663
+ /**
1664
+ * Creates a shallow clone of `object` composed of the specified properties.
1665
+ * Property names may be specified as individual arguments or as arrays of
1666
+ * property names. If a callback is provided it will be executed for each
1667
+ * property of `object` picking the properties the callback returns truey
1668
+ * for. The callback is bound to `thisArg` and invoked with three arguments;
1669
+ * (value, key, object).
1670
+ *
1671
+ * @static
1672
+ * @memberOf _
1673
+ * @category Objects
1674
+ * @param {Object} object The source object.
1675
+ * @param {Function|...string|string[]} [callback] The function called per
1676
+ * iteration or property names to pick, specified as individual property
1677
+ * names or arrays of property names.
1678
+ * @param {*} [thisArg] The `this` binding of `callback`.
1679
+ * @returns {Object} Returns an object composed of the picked properties.
1680
+ * @example
1681
+ *
1682
+ * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
1683
+ * // => { 'name': 'fred' }
1684
+ *
1685
+ * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
1686
+ * return key.charAt(0) != '_';
1687
+ * });
1688
+ * // => { 'name': 'fred' }
1689
+ */
1690
+ function pick(object) {
1691
+ var index = -1,
1692
+ props = baseFlatten(arguments, true, false, 1),
1693
+ length = props.length,
1694
+ result = {};
1695
+
1696
+ while (++index < length) {
1697
+ var key = props[index];
1698
+ if (key in object) {
1699
+ result[key] = object[key];
1700
+ }
1701
+ }
1702
+ return result;
1703
+ }
1704
+
1705
+ /**
1706
+ * Creates an array composed of the own enumerable property values of `object`.
1707
+ *
1708
+ * @static
1709
+ * @memberOf _
1710
+ * @category Objects
1711
+ * @param {Object} object The object to inspect.
1712
+ * @returns {Array} Returns an array of property values.
1713
+ * @example
1714
+ *
1715
+ * _.values({ 'one': 1, 'two': 2, 'three': 3 });
1716
+ * // => [1, 2, 3] (property order is not guaranteed across environments)
1717
+ */
1718
+ function values(object) {
1719
+ var index = -1,
1720
+ props = keys(object),
1721
+ length = props.length,
1722
+ result = Array(length);
1723
+
1724
+ while (++index < length) {
1725
+ result[index] = object[props[index]];
1726
+ }
1727
+ return result;
1728
+ }
1729
+
1730
+ /*--------------------------------------------------------------------------*/
1731
+
1732
+ /**
1733
+ * Checks if a given value is present in a collection using strict equality
1734
+ * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
1735
+ * offset from the end of the collection.
1736
+ *
1737
+ * @static
1738
+ * @memberOf _
1739
+ * @alias include
1740
+ * @category Collections
1741
+ * @param {Array|Object|string} collection The collection to iterate over.
1742
+ * @param {*} target The value to check for.
1743
+ * @param {number} [fromIndex=0] The index to search from.
1744
+ * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
1745
+ * @example
1746
+ *
1747
+ * _.contains([1, 2, 3], 1);
1748
+ * // => true
1749
+ *
1750
+ * _.contains([1, 2, 3], 1, 2);
1751
+ * // => false
1752
+ *
1753
+ * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
1754
+ * // => true
1755
+ *
1756
+ * _.contains('pebbles', 'eb');
1757
+ * // => true
1758
+ */
1759
+ function contains(collection, target) {
1760
+ var indexOf = getIndexOf(),
1761
+ length = collection ? collection.length : 0,
1762
+ result = false;
1763
+ if (length && typeof length == 'number') {
1764
+ result = indexOf(collection, target) > -1;
1765
+ } else {
1766
+ forOwn(collection, function(value) {
1767
+ return (result = value === target) && indicatorObject;
1768
+ });
1769
+ }
1770
+ return result;
1771
+ }
1772
+
1773
+ /**
1774
+ * Creates an object composed of keys generated from the results of running
1775
+ * each element of `collection` through the callback. The corresponding value
1776
+ * of each key is the number of times the key was returned by the callback.
1777
+ * The callback is bound to `thisArg` and invoked with three arguments;
1778
+ * (value, index|key, collection).
1779
+ *
1780
+ * If a property name is provided for `callback` the created "_.pluck" style
1781
+ * callback will return the property value of the given element.
1782
+ *
1783
+ * If an object is provided for `callback` the created "_.where" style callback
1784
+ * will return `true` for elements that have the properties of the given object,
1785
+ * else `false`.
1786
+ *
1787
+ * @static
1788
+ * @memberOf _
1789
+ * @category Collections
1790
+ * @param {Array|Object|string} collection The collection to iterate over.
1791
+ * @param {Function|Object|string} [callback=identity] The function called
1792
+ * per iteration. If a property name or object is provided it will be used
1793
+ * to create a "_.pluck" or "_.where" style callback, respectively.
1794
+ * @param {*} [thisArg] The `this` binding of `callback`.
1795
+ * @returns {Object} Returns the composed aggregate object.
1796
+ * @example
1797
+ *
1798
+ * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
1799
+ * // => { '4': 1, '6': 2 }
1800
+ *
1801
+ * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
1802
+ * // => { '4': 1, '6': 2 }
1803
+ *
1804
+ * _.countBy(['one', 'two', 'three'], 'length');
1805
+ * // => { '3': 2, '5': 1 }
1806
+ */
1807
+ var countBy = createAggregator(function(result, value, key) {
1808
+ (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
1809
+ });
1810
+
1811
+ /**
1812
+ * Checks if the given callback returns truey value for **all** elements of
1813
+ * a collection. The callback is bound to `thisArg` and invoked with three
1814
+ * arguments; (value, index|key, collection).
1815
+ *
1816
+ * If a property name is provided for `callback` the created "_.pluck" style
1817
+ * callback will return the property value of the given element.
1818
+ *
1819
+ * If an object is provided for `callback` the created "_.where" style callback
1820
+ * will return `true` for elements that have the properties of the given object,
1821
+ * else `false`.
1822
+ *
1823
+ * @static
1824
+ * @memberOf _
1825
+ * @alias all
1826
+ * @category Collections
1827
+ * @param {Array|Object|string} collection The collection to iterate over.
1828
+ * @param {Function|Object|string} [callback=identity] The function called
1829
+ * per iteration. If a property name or object is provided it will be used
1830
+ * to create a "_.pluck" or "_.where" style callback, respectively.
1831
+ * @param {*} [thisArg] The `this` binding of `callback`.
1832
+ * @returns {boolean} Returns `true` if all elements passed the callback check,
1833
+ * else `false`.
1834
+ * @example
1835
+ *
1836
+ * _.every([true, 1, null, 'yes']);
1837
+ * // => false
1838
+ *
1839
+ * var characters = [
1840
+ * { 'name': 'barney', 'age': 36 },
1841
+ * { 'name': 'fred', 'age': 40 }
1842
+ * ];
1843
+ *
1844
+ * // using "_.pluck" callback shorthand
1845
+ * _.every(characters, 'age');
1846
+ * // => true
1847
+ *
1848
+ * // using "_.where" callback shorthand
1849
+ * _.every(characters, { 'age': 36 });
1850
+ * // => false
1851
+ */
1852
+ function every(collection, callback, thisArg) {
1853
+ var result = true;
1854
+ callback = createCallback(callback, thisArg, 3);
1855
+
1856
+ var index = -1,
1857
+ length = collection ? collection.length : 0;
1858
+
1859
+ if (typeof length == 'number') {
1860
+ while (++index < length) {
1861
+ if (!(result = !!callback(collection[index], index, collection))) {
1862
+ break;
1863
+ }
1864
+ }
1865
+ } else {
1866
+ forOwn(collection, function(value, index, collection) {
1867
+ return !(result = !!callback(value, index, collection)) && indicatorObject;
1868
+ });
1869
+ }
1870
+ return result;
1871
+ }
1872
+
1873
+ /**
1874
+ * Iterates over elements of a collection, returning an array of all elements
1875
+ * the callback returns truey for. The callback is bound to `thisArg` and
1876
+ * invoked with three arguments; (value, index|key, collection).
1877
+ *
1878
+ * If a property name is provided for `callback` the created "_.pluck" style
1879
+ * callback will return the property value of the given element.
1880
+ *
1881
+ * If an object is provided for `callback` the created "_.where" style callback
1882
+ * will return `true` for elements that have the properties of the given object,
1883
+ * else `false`.
1884
+ *
1885
+ * @static
1886
+ * @memberOf _
1887
+ * @alias select
1888
+ * @category Collections
1889
+ * @param {Array|Object|string} collection The collection to iterate over.
1890
+ * @param {Function|Object|string} [callback=identity] The function called
1891
+ * per iteration. If a property name or object is provided it will be used
1892
+ * to create a "_.pluck" or "_.where" style callback, respectively.
1893
+ * @param {*} [thisArg] The `this` binding of `callback`.
1894
+ * @returns {Array} Returns a new array of elements that passed the callback check.
1895
+ * @example
1896
+ *
1897
+ * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
1898
+ * // => [2, 4, 6]
1899
+ *
1900
+ * var characters = [
1901
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
1902
+ * { 'name': 'fred', 'age': 40, 'blocked': true }
1903
+ * ];
1904
+ *
1905
+ * // using "_.pluck" callback shorthand
1906
+ * _.filter(characters, 'blocked');
1907
+ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
1908
+ *
1909
+ * // using "_.where" callback shorthand
1910
+ * _.filter(characters, { 'age': 36 });
1911
+ * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
1912
+ */
1913
+ function filter(collection, callback, thisArg) {
1914
+ var result = [];
1915
+ callback = createCallback(callback, thisArg, 3);
1916
+
1917
+ var index = -1,
1918
+ length = collection ? collection.length : 0;
1919
+
1920
+ if (typeof length == 'number') {
1921
+ while (++index < length) {
1922
+ var value = collection[index];
1923
+ if (callback(value, index, collection)) {
1924
+ result.push(value);
1925
+ }
1926
+ }
1927
+ } else {
1928
+ forOwn(collection, function(value, index, collection) {
1929
+ if (callback(value, index, collection)) {
1930
+ result.push(value);
1931
+ }
1932
+ });
1933
+ }
1934
+ return result;
1935
+ }
1936
+
1937
+ /**
1938
+ * Iterates over elements of a collection, returning the first element that
1939
+ * the callback returns truey for. The callback is bound to `thisArg` and
1940
+ * invoked with three arguments; (value, index|key, collection).
1941
+ *
1942
+ * If a property name is provided for `callback` the created "_.pluck" style
1943
+ * callback will return the property value of the given element.
1944
+ *
1945
+ * If an object is provided for `callback` the created "_.where" style callback
1946
+ * will return `true` for elements that have the properties of the given object,
1947
+ * else `false`.
1948
+ *
1949
+ * @static
1950
+ * @memberOf _
1951
+ * @alias detect, findWhere
1952
+ * @category Collections
1953
+ * @param {Array|Object|string} collection The collection to iterate over.
1954
+ * @param {Function|Object|string} [callback=identity] The function called
1955
+ * per iteration. If a property name or object is provided it will be used
1956
+ * to create a "_.pluck" or "_.where" style callback, respectively.
1957
+ * @param {*} [thisArg] The `this` binding of `callback`.
1958
+ * @returns {*} Returns the found element, else `undefined`.
1959
+ * @example
1960
+ *
1961
+ * var characters = [
1962
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
1963
+ * { 'name': 'fred', 'age': 40, 'blocked': true },
1964
+ * { 'name': 'pebbles', 'age': 1, 'blocked': false }
1965
+ * ];
1966
+ *
1967
+ * _.find(characters, function(chr) {
1968
+ * return chr.age < 40;
1969
+ * });
1970
+ * // => { 'name': 'barney', 'age': 36, 'blocked': false }
1971
+ *
1972
+ * // using "_.where" callback shorthand
1973
+ * _.find(characters, { 'age': 1 });
1974
+ * // => { 'name': 'pebbles', 'age': 1, 'blocked': false }
1975
+ *
1976
+ * // using "_.pluck" callback shorthand
1977
+ * _.find(characters, 'blocked');
1978
+ * // => { 'name': 'fred', 'age': 40, 'blocked': true }
1979
+ */
1980
+ function find(collection, callback, thisArg) {
1981
+ callback = createCallback(callback, thisArg, 3);
1982
+
1983
+ var index = -1,
1984
+ length = collection ? collection.length : 0;
1985
+
1986
+ if (typeof length == 'number') {
1987
+ while (++index < length) {
1988
+ var value = collection[index];
1989
+ if (callback(value, index, collection)) {
1990
+ return value;
1991
+ }
1992
+ }
1993
+ } else {
1994
+ var result;
1995
+ forOwn(collection, function(value, index, collection) {
1996
+ if (callback(value, index, collection)) {
1997
+ result = value;
1998
+ return indicatorObject;
1999
+ }
2000
+ });
2001
+ return result;
2002
+ }
2003
+ }
2004
+
2005
+ /**
2006
+ * Examines each element in a `collection`, returning the first that
2007
+ * has the given properties. When checking `properties`, this method
2008
+ * performs a deep comparison between values to determine if they are
2009
+ * equivalent to each other.
2010
+ *
2011
+ * @static
2012
+ * @memberOf _
2013
+ * @category Collections
2014
+ * @param {Array|Object|string} collection The collection to iterate over.
2015
+ * @param {Object} properties The object of property values to filter by.
2016
+ * @returns {*} Returns the found element, else `undefined`.
2017
+ * @example
2018
+ *
2019
+ * var food = [
2020
+ * { 'name': 'apple', 'organic': false, 'type': 'fruit' },
2021
+ * { 'name': 'banana', 'organic': true, 'type': 'fruit' },
2022
+ * { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
2023
+ * ];
2024
+ *
2025
+ * _.findWhere(food, { 'type': 'vegetable' });
2026
+ * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
2027
+ */
2028
+ function findWhere(object, properties) {
2029
+ return where(object, properties, true);
2030
+ }
2031
+
2032
+ /**
2033
+ * Iterates over elements of a collection, executing the callback for each
2034
+ * element. The callback is bound to `thisArg` and invoked with three arguments;
2035
+ * (value, index|key, collection). Callbacks may exit iteration early by
2036
+ * explicitly returning `false`.
2037
+ *
2038
+ * Note: As with other "Collections" methods, objects with a `length` property
2039
+ * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
2040
+ * may be used for object iteration.
2041
+ *
2042
+ * @static
2043
+ * @memberOf _
2044
+ * @alias each
2045
+ * @category Collections
2046
+ * @param {Array|Object|string} collection The collection to iterate over.
2047
+ * @param {Function} [callback=identity] The function called per iteration.
2048
+ * @param {*} [thisArg] The `this` binding of `callback`.
2049
+ * @returns {Array|Object|string} Returns `collection`.
2050
+ * @example
2051
+ *
2052
+ * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
2053
+ * // => logs each number and returns '1,2,3'
2054
+ *
2055
+ * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
2056
+ * // => logs each number and returns the object (property order is not guaranteed across environments)
2057
+ */
2058
+ function forEach(collection, callback, thisArg) {
2059
+ var index = -1,
2060
+ length = collection ? collection.length : 0;
2061
+
2062
+ callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
2063
+ if (typeof length == 'number') {
2064
+ while (++index < length) {
2065
+ if (callback(collection[index], index, collection) === indicatorObject) {
2066
+ break;
2067
+ }
2068
+ }
2069
+ } else {
2070
+ forOwn(collection, callback);
2071
+ }
2072
+ }
2073
+
2074
+ /**
2075
+ * This method is like `_.forEach` except that it iterates over elements
2076
+ * of a `collection` from right to left.
2077
+ *
2078
+ * @static
2079
+ * @memberOf _
2080
+ * @alias eachRight
2081
+ * @category Collections
2082
+ * @param {Array|Object|string} collection The collection to iterate over.
2083
+ * @param {Function} [callback=identity] The function called per iteration.
2084
+ * @param {*} [thisArg] The `this` binding of `callback`.
2085
+ * @returns {Array|Object|string} Returns `collection`.
2086
+ * @example
2087
+ *
2088
+ * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
2089
+ * // => logs each number from right to left and returns '3,2,1'
2090
+ */
2091
+ function forEachRight(collection, callback) {
2092
+ var length = collection ? collection.length : 0;
2093
+ if (typeof length == 'number') {
2094
+ while (length--) {
2095
+ if (callback(collection[length], length, collection) === false) {
2096
+ break;
2097
+ }
2098
+ }
2099
+ } else {
2100
+ var props = keys(collection);
2101
+ length = props.length;
2102
+ forOwn(collection, function(value, key, collection) {
2103
+ key = props ? props[--length] : --length;
2104
+ return callback(collection[key], key, collection) === false && indicatorObject;
2105
+ });
2106
+ }
2107
+ }
2108
+
2109
+ /**
2110
+ * Creates an object composed of keys generated from the results of running
2111
+ * each element of a collection through the callback. The corresponding value
2112
+ * of each key is an array of the elements responsible for generating the key.
2113
+ * The callback is bound to `thisArg` and invoked with three arguments;
2114
+ * (value, index|key, collection).
2115
+ *
2116
+ * If a property name is provided for `callback` the created "_.pluck" style
2117
+ * callback will return the property value of the given element.
2118
+ *
2119
+ * If an object is provided for `callback` the created "_.where" style callback
2120
+ * will return `true` for elements that have the properties of the given object,
2121
+ * else `false`
2122
+ *
2123
+ * @static
2124
+ * @memberOf _
2125
+ * @category Collections
2126
+ * @param {Array|Object|string} collection The collection to iterate over.
2127
+ * @param {Function|Object|string} [callback=identity] The function called
2128
+ * per iteration. If a property name or object is provided it will be used
2129
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2130
+ * @param {*} [thisArg] The `this` binding of `callback`.
2131
+ * @returns {Object} Returns the composed aggregate object.
2132
+ * @example
2133
+ *
2134
+ * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
2135
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
2136
+ *
2137
+ * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
2138
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
2139
+ *
2140
+ * // using "_.pluck" callback shorthand
2141
+ * _.groupBy(['one', 'two', 'three'], 'length');
2142
+ * // => { '3': ['one', 'two'], '5': ['three'] }
2143
+ */
2144
+ var groupBy = createAggregator(function(result, value, key) {
2145
+ (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
2146
+ });
2147
+
2148
+ /**
2149
+ * Creates an object composed of keys generated from the results of running
2150
+ * each element of the collection through the given callback. The corresponding
2151
+ * value of each key is the last element responsible for generating the key.
2152
+ * The callback is bound to `thisArg` and invoked with three arguments;
2153
+ * (value, index|key, collection).
2154
+ *
2155
+ * If a property name is provided for `callback` the created "_.pluck" style
2156
+ * callback will return the property value of the given element.
2157
+ *
2158
+ * If an object is provided for `callback` the created "_.where" style callback
2159
+ * will return `true` for elements that have the properties of the given object,
2160
+ * else `false`.
2161
+ *
2162
+ * @static
2163
+ * @memberOf _
2164
+ * @category Collections
2165
+ * @param {Array|Object|string} collection The collection to iterate over.
2166
+ * @param {Function|Object|string} [callback=identity] The function called
2167
+ * per iteration. If a property name or object is provided it will be used
2168
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2169
+ * @param {*} [thisArg] The `this` binding of `callback`.
2170
+ * @returns {Object} Returns the composed aggregate object.
2171
+ * @example
2172
+ *
2173
+ * var keys = [
2174
+ * { 'dir': 'left', 'code': 97 },
2175
+ * { 'dir': 'right', 'code': 100 }
2176
+ * ];
2177
+ *
2178
+ * _.indexBy(keys, 'dir');
2179
+ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
2180
+ *
2181
+ * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
2182
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
2183
+ *
2184
+ * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
2185
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
2186
+ */
2187
+ var indexBy = createAggregator(function(result, value, key) {
2188
+ result[key] = value;
2189
+ });
2190
+
2191
+ /**
2192
+ * Invokes the method named by `methodName` on each element in the `collection`
2193
+ * returning an array of the results of each invoked method. Additional arguments
2194
+ * will be provided to each invoked method. If `methodName` is a function it
2195
+ * will be invoked for, and `this` bound to, each element in the `collection`.
2196
+ *
2197
+ * @static
2198
+ * @memberOf _
2199
+ * @category Collections
2200
+ * @param {Array|Object|string} collection The collection to iterate over.
2201
+ * @param {Function|string} methodName The name of the method to invoke or
2202
+ * the function invoked per iteration.
2203
+ * @param {...*} [arg] Arguments to invoke the method with.
2204
+ * @returns {Array} Returns a new array of the results of each invoked method.
2205
+ * @example
2206
+ *
2207
+ * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
2208
+ * // => [[1, 5, 7], [1, 2, 3]]
2209
+ *
2210
+ * _.invoke([123, 456], String.prototype.split, '');
2211
+ * // => [['1', '2', '3'], ['4', '5', '6']]
2212
+ */
2213
+ function invoke(collection, methodName) {
2214
+ var args = slice(arguments, 2),
2215
+ index = -1,
2216
+ isFunc = typeof methodName == 'function',
2217
+ length = collection ? collection.length : 0,
2218
+ result = Array(typeof length == 'number' ? length : 0);
2219
+
2220
+ forEach(collection, function(value) {
2221
+ result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
2222
+ });
2223
+ return result;
2224
+ }
2225
+
2226
+ /**
2227
+ * Creates an array of values by running each element in the collection
2228
+ * through the callback. The callback is bound to `thisArg` and invoked with
2229
+ * three arguments; (value, index|key, collection).
2230
+ *
2231
+ * If a property name is provided for `callback` the created "_.pluck" style
2232
+ * callback will return the property value of the given element.
2233
+ *
2234
+ * If an object is provided for `callback` the created "_.where" style callback
2235
+ * will return `true` for elements that have the properties of the given object,
2236
+ * else `false`.
2237
+ *
2238
+ * @static
2239
+ * @memberOf _
2240
+ * @alias collect
2241
+ * @category Collections
2242
+ * @param {Array|Object|string} collection The collection to iterate over.
2243
+ * @param {Function|Object|string} [callback=identity] The function called
2244
+ * per iteration. If a property name or object is provided it will be used
2245
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2246
+ * @param {*} [thisArg] The `this` binding of `callback`.
2247
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
2248
+ * @example
2249
+ *
2250
+ * _.map([1, 2, 3], function(num) { return num * 3; });
2251
+ * // => [3, 6, 9]
2252
+ *
2253
+ * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
2254
+ * // => [3, 6, 9] (property order is not guaranteed across environments)
2255
+ *
2256
+ * var characters = [
2257
+ * { 'name': 'barney', 'age': 36 },
2258
+ * { 'name': 'fred', 'age': 40 }
2259
+ * ];
2260
+ *
2261
+ * // using "_.pluck" callback shorthand
2262
+ * _.map(characters, 'name');
2263
+ * // => ['barney', 'fred']
2264
+ */
2265
+ function map(collection, callback, thisArg) {
2266
+ var index = -1,
2267
+ length = collection ? collection.length : 0;
2268
+
2269
+ callback = createCallback(callback, thisArg, 3);
2270
+ if (typeof length == 'number') {
2271
+ var result = Array(length);
2272
+ while (++index < length) {
2273
+ result[index] = callback(collection[index], index, collection);
2274
+ }
2275
+ } else {
2276
+ result = [];
2277
+ forOwn(collection, function(value, key, collection) {
2278
+ result[++index] = callback(value, key, collection);
2279
+ });
2280
+ }
2281
+ return result;
2282
+ }
2283
+
2284
+ /**
2285
+ * Retrieves the maximum value of a collection. If the collection is empty or
2286
+ * falsey `-Infinity` is returned. If a callback is provided it will be executed
2287
+ * for each value in the collection to generate the criterion by which the value
2288
+ * is ranked. The callback is bound to `thisArg` and invoked with three
2289
+ * arguments; (value, index, collection).
2290
+ *
2291
+ * If a property name is provided for `callback` the created "_.pluck" style
2292
+ * callback will return the property value of the given element.
2293
+ *
2294
+ * If an object is provided for `callback` the created "_.where" style callback
2295
+ * will return `true` for elements that have the properties of the given object,
2296
+ * else `false`.
2297
+ *
2298
+ * @static
2299
+ * @memberOf _
2300
+ * @category Collections
2301
+ * @param {Array|Object|string} collection The collection to iterate over.
2302
+ * @param {Function|Object|string} [callback=identity] The function called
2303
+ * per iteration. If a property name or object is provided it will be used
2304
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2305
+ * @param {*} [thisArg] The `this` binding of `callback`.
2306
+ * @returns {*} Returns the maximum value.
2307
+ * @example
2308
+ *
2309
+ * _.max([4, 2, 8, 6]);
2310
+ * // => 8
2311
+ *
2312
+ * var characters = [
2313
+ * { 'name': 'barney', 'age': 36 },
2314
+ * { 'name': 'fred', 'age': 40 }
2315
+ * ];
2316
+ *
2317
+ * _.max(characters, function(chr) { return chr.age; });
2318
+ * // => { 'name': 'fred', 'age': 40 };
2319
+ *
2320
+ * // using "_.pluck" callback shorthand
2321
+ * _.max(characters, 'age');
2322
+ * // => { 'name': 'fred', 'age': 40 };
2323
+ */
2324
+ function max(collection, callback, thisArg) {
2325
+ var computed = -Infinity,
2326
+ result = computed;
2327
+
2328
+ // allows working with functions like `_.map` without using
2329
+ // their `index` argument as a callback
2330
+ if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
2331
+ callback = null;
2332
+ }
2333
+ var index = -1,
2334
+ length = collection ? collection.length : 0;
2335
+
2336
+ if (callback == null && typeof length == 'number') {
2337
+ while (++index < length) {
2338
+ var value = collection[index];
2339
+ if (value > result) {
2340
+ result = value;
2341
+ }
2342
+ }
2343
+ } else {
2344
+ callback = createCallback(callback, thisArg, 3);
2345
+
2346
+ forEach(collection, function(value, index, collection) {
2347
+ var current = callback(value, index, collection);
2348
+ if (current > computed) {
2349
+ computed = current;
2350
+ result = value;
2351
+ }
2352
+ });
2353
+ }
2354
+ return result;
2355
+ }
2356
+
2357
+ /**
2358
+ * Retrieves the minimum value of a collection. If the collection is empty or
2359
+ * falsey `Infinity` is returned. If a callback is provided it will be executed
2360
+ * for each value in the collection to generate the criterion by which the value
2361
+ * is ranked. The callback is bound to `thisArg` and invoked with three
2362
+ * arguments; (value, index, collection).
2363
+ *
2364
+ * If a property name is provided for `callback` the created "_.pluck" style
2365
+ * callback will return the property value of the given element.
2366
+ *
2367
+ * If an object is provided for `callback` the created "_.where" style callback
2368
+ * will return `true` for elements that have the properties of the given object,
2369
+ * else `false`.
2370
+ *
2371
+ * @static
2372
+ * @memberOf _
2373
+ * @category Collections
2374
+ * @param {Array|Object|string} collection The collection to iterate over.
2375
+ * @param {Function|Object|string} [callback=identity] The function called
2376
+ * per iteration. If a property name or object is provided it will be used
2377
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2378
+ * @param {*} [thisArg] The `this` binding of `callback`.
2379
+ * @returns {*} Returns the minimum value.
2380
+ * @example
2381
+ *
2382
+ * _.min([4, 2, 8, 6]);
2383
+ * // => 2
2384
+ *
2385
+ * var characters = [
2386
+ * { 'name': 'barney', 'age': 36 },
2387
+ * { 'name': 'fred', 'age': 40 }
2388
+ * ];
2389
+ *
2390
+ * _.min(characters, function(chr) { return chr.age; });
2391
+ * // => { 'name': 'barney', 'age': 36 };
2392
+ *
2393
+ * // using "_.pluck" callback shorthand
2394
+ * _.min(characters, 'age');
2395
+ * // => { 'name': 'barney', 'age': 36 };
2396
+ */
2397
+ function min(collection, callback, thisArg) {
2398
+ var computed = Infinity,
2399
+ result = computed;
2400
+
2401
+ // allows working with functions like `_.map` without using
2402
+ // their `index` argument as a callback
2403
+ if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
2404
+ callback = null;
2405
+ }
2406
+ var index = -1,
2407
+ length = collection ? collection.length : 0;
2408
+
2409
+ if (callback == null && typeof length == 'number') {
2410
+ while (++index < length) {
2411
+ var value = collection[index];
2412
+ if (value < result) {
2413
+ result = value;
2414
+ }
2415
+ }
2416
+ } else {
2417
+ callback = createCallback(callback, thisArg, 3);
2418
+
2419
+ forEach(collection, function(value, index, collection) {
2420
+ var current = callback(value, index, collection);
2421
+ if (current < computed) {
2422
+ computed = current;
2423
+ result = value;
2424
+ }
2425
+ });
2426
+ }
2427
+ return result;
2428
+ }
2429
+
2430
+ /**
2431
+ * Retrieves the value of a specified property from all elements in the collection.
2432
+ *
2433
+ * @static
2434
+ * @memberOf _
2435
+ * @type Function
2436
+ * @category Collections
2437
+ * @param {Array|Object|string} collection The collection to iterate over.
2438
+ * @param {string} property The property to pluck.
2439
+ * @returns {Array} Returns a new array of property values.
2440
+ * @example
2441
+ *
2442
+ * var characters = [
2443
+ * { 'name': 'barney', 'age': 36 },
2444
+ * { 'name': 'fred', 'age': 40 }
2445
+ * ];
2446
+ *
2447
+ * _.pluck(characters, 'name');
2448
+ * // => ['barney', 'fred']
2449
+ */
2450
+ function pluck(collection, property) {
2451
+ var index = -1,
2452
+ length = collection ? collection.length : 0;
2453
+
2454
+ if (typeof length == 'number') {
2455
+ var result = Array(length);
2456
+ while (++index < length) {
2457
+ result[index] = collection[index][property];
2458
+ }
2459
+ }
2460
+ return result || map(collection, property);
2461
+ }
2462
+
2463
+ /**
2464
+ * Reduces a collection to a value which is the accumulated result of running
2465
+ * each element in the collection through the callback, where each successive
2466
+ * callback execution consumes the return value of the previous execution. If
2467
+ * `accumulator` is not provided the first element of the collection will be
2468
+ * used as the initial `accumulator` value. The callback is bound to `thisArg`
2469
+ * and invoked with four arguments; (accumulator, value, index|key, collection).
2470
+ *
2471
+ * @static
2472
+ * @memberOf _
2473
+ * @alias foldl, inject
2474
+ * @category Collections
2475
+ * @param {Array|Object|string} collection The collection to iterate over.
2476
+ * @param {Function} [callback=identity] The function called per iteration.
2477
+ * @param {*} [accumulator] Initial value of the accumulator.
2478
+ * @param {*} [thisArg] The `this` binding of `callback`.
2479
+ * @returns {*} Returns the accumulated value.
2480
+ * @example
2481
+ *
2482
+ * var sum = _.reduce([1, 2, 3], function(sum, num) {
2483
+ * return sum + num;
2484
+ * });
2485
+ * // => 6
2486
+ *
2487
+ * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
2488
+ * result[key] = num * 3;
2489
+ * return result;
2490
+ * }, {});
2491
+ * // => { 'a': 3, 'b': 6, 'c': 9 }
2492
+ */
2493
+ function reduce(collection, callback, accumulator, thisArg) {
2494
+ if (!collection) return accumulator;
2495
+ var noaccum = arguments.length < 3;
2496
+ callback = createCallback(callback, thisArg, 4);
2497
+
2498
+ var index = -1,
2499
+ length = collection.length;
2500
+
2501
+ if (typeof length == 'number') {
2502
+ if (noaccum) {
2503
+ accumulator = collection[++index];
2504
+ }
2505
+ while (++index < length) {
2506
+ accumulator = callback(accumulator, collection[index], index, collection);
2507
+ }
2508
+ } else {
2509
+ forOwn(collection, function(value, index, collection) {
2510
+ accumulator = noaccum
2511
+ ? (noaccum = false, value)
2512
+ : callback(accumulator, value, index, collection)
2513
+ });
2514
+ }
2515
+ return accumulator;
2516
+ }
2517
+
2518
+ /**
2519
+ * This method is like `_.reduce` except that it iterates over elements
2520
+ * of a `collection` from right to left.
2521
+ *
2522
+ * @static
2523
+ * @memberOf _
2524
+ * @alias foldr
2525
+ * @category Collections
2526
+ * @param {Array|Object|string} collection The collection to iterate over.
2527
+ * @param {Function} [callback=identity] The function called per iteration.
2528
+ * @param {*} [accumulator] Initial value of the accumulator.
2529
+ * @param {*} [thisArg] The `this` binding of `callback`.
2530
+ * @returns {*} Returns the accumulated value.
2531
+ * @example
2532
+ *
2533
+ * var list = [[0, 1], [2, 3], [4, 5]];
2534
+ * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
2535
+ * // => [4, 5, 2, 3, 0, 1]
2536
+ */
2537
+ function reduceRight(collection, callback, accumulator, thisArg) {
2538
+ var noaccum = arguments.length < 3;
2539
+ callback = createCallback(callback, thisArg, 4);
2540
+ forEachRight(collection, function(value, index, collection) {
2541
+ accumulator = noaccum
2542
+ ? (noaccum = false, value)
2543
+ : callback(accumulator, value, index, collection);
2544
+ });
2545
+ return accumulator;
2546
+ }
2547
+
2548
+ /**
2549
+ * The opposite of `_.filter` this method returns the elements of a
2550
+ * collection that the callback does **not** return truey for.
2551
+ *
2552
+ * If a property name is provided for `callback` the created "_.pluck" style
2553
+ * callback will return the property value of the given element.
2554
+ *
2555
+ * If an object is provided for `callback` the created "_.where" style callback
2556
+ * will return `true` for elements that have the properties of the given object,
2557
+ * else `false`.
2558
+ *
2559
+ * @static
2560
+ * @memberOf _
2561
+ * @category Collections
2562
+ * @param {Array|Object|string} collection The collection to iterate over.
2563
+ * @param {Function|Object|string} [callback=identity] The function called
2564
+ * per iteration. If a property name or object is provided it will be used
2565
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2566
+ * @param {*} [thisArg] The `this` binding of `callback`.
2567
+ * @returns {Array} Returns a new array of elements that failed the callback check.
2568
+ * @example
2569
+ *
2570
+ * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2571
+ * // => [1, 3, 5]
2572
+ *
2573
+ * var characters = [
2574
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
2575
+ * { 'name': 'fred', 'age': 40, 'blocked': true }
2576
+ * ];
2577
+ *
2578
+ * // using "_.pluck" callback shorthand
2579
+ * _.reject(characters, 'blocked');
2580
+ * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
2581
+ *
2582
+ * // using "_.where" callback shorthand
2583
+ * _.reject(characters, { 'age': 36 });
2584
+ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
2585
+ */
2586
+ function reject(collection, callback, thisArg) {
2587
+ callback = createCallback(callback, thisArg, 3);
2588
+ return filter(collection, function(value, index, collection) {
2589
+ return !callback(value, index, collection);
2590
+ });
2591
+ }
2592
+
2593
+ /**
2594
+ * Retrieves a random element or `n` random elements from a collection.
2595
+ *
2596
+ * @static
2597
+ * @memberOf _
2598
+ * @category Collections
2599
+ * @param {Array|Object|string} collection The collection to sample.
2600
+ * @param {number} [n] The number of elements to sample.
2601
+ * @param- {Object} [guard] Allows working with functions like `_.map`
2602
+ * without using their `index` arguments as `n`.
2603
+ * @returns {Array} Returns the random sample(s) of `collection`.
2604
+ * @example
2605
+ *
2606
+ * _.sample([1, 2, 3, 4]);
2607
+ * // => 2
2608
+ *
2609
+ * _.sample([1, 2, 3, 4], 2);
2610
+ * // => [3, 1]
2611
+ */
2612
+ function sample(collection, n, guard) {
2613
+ if (collection && typeof collection.length != 'number') {
2614
+ collection = values(collection);
2615
+ }
2616
+ if (n == null || guard) {
2617
+ return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
2618
+ }
2619
+ var result = shuffle(collection);
2620
+ result.length = nativeMin(nativeMax(0, n), result.length);
2621
+ return result;
2622
+ }
2623
+
2624
+ /**
2625
+ * Creates an array of shuffled values, using a version of the Fisher-Yates
2626
+ * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
2627
+ *
2628
+ * @static
2629
+ * @memberOf _
2630
+ * @category Collections
2631
+ * @param {Array|Object|string} collection The collection to shuffle.
2632
+ * @returns {Array} Returns a new shuffled collection.
2633
+ * @example
2634
+ *
2635
+ * _.shuffle([1, 2, 3, 4, 5, 6]);
2636
+ * // => [4, 1, 6, 3, 5, 2]
2637
+ */
2638
+ function shuffle(collection) {
2639
+ var index = -1,
2640
+ length = collection ? collection.length : 0,
2641
+ result = Array(typeof length == 'number' ? length : 0);
2642
+
2643
+ forEach(collection, function(value) {
2644
+ var rand = baseRandom(0, ++index);
2645
+ result[index] = result[rand];
2646
+ result[rand] = value;
2647
+ });
2648
+ return result;
2649
+ }
2650
+
2651
+ /**
2652
+ * Gets the size of the `collection` by returning `collection.length` for arrays
2653
+ * and array-like objects or the number of own enumerable properties for objects.
2654
+ *
2655
+ * @static
2656
+ * @memberOf _
2657
+ * @category Collections
2658
+ * @param {Array|Object|string} collection The collection to inspect.
2659
+ * @returns {number} Returns `collection.length` or number of own enumerable properties.
2660
+ * @example
2661
+ *
2662
+ * _.size([1, 2]);
2663
+ * // => 2
2664
+ *
2665
+ * _.size({ 'one': 1, 'two': 2, 'three': 3 });
2666
+ * // => 3
2667
+ *
2668
+ * _.size('pebbles');
2669
+ * // => 5
2670
+ */
2671
+ function size(collection) {
2672
+ var length = collection ? collection.length : 0;
2673
+ return typeof length == 'number' ? length : keys(collection).length;
2674
+ }
2675
+
2676
+ /**
2677
+ * Checks if the callback returns a truey value for **any** element of a
2678
+ * collection. The function returns as soon as it finds a passing value and
2679
+ * does not iterate over the entire collection. The callback is bound to
2680
+ * `thisArg` and invoked with three arguments; (value, index|key, collection).
2681
+ *
2682
+ * If a property name is provided for `callback` the created "_.pluck" style
2683
+ * callback will return the property value of the given element.
2684
+ *
2685
+ * If an object is provided for `callback` the created "_.where" style callback
2686
+ * will return `true` for elements that have the properties of the given object,
2687
+ * else `false`.
2688
+ *
2689
+ * @static
2690
+ * @memberOf _
2691
+ * @alias any
2692
+ * @category Collections
2693
+ * @param {Array|Object|string} collection The collection to iterate over.
2694
+ * @param {Function|Object|string} [callback=identity] The function called
2695
+ * per iteration. If a property name or object is provided it will be used
2696
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2697
+ * @param {*} [thisArg] The `this` binding of `callback`.
2698
+ * @returns {boolean} Returns `true` if any element passed the callback check,
2699
+ * else `false`.
2700
+ * @example
2701
+ *
2702
+ * _.some([null, 0, 'yes', false], Boolean);
2703
+ * // => true
2704
+ *
2705
+ * var characters = [
2706
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
2707
+ * { 'name': 'fred', 'age': 40, 'blocked': true }
2708
+ * ];
2709
+ *
2710
+ * // using "_.pluck" callback shorthand
2711
+ * _.some(characters, 'blocked');
2712
+ * // => true
2713
+ *
2714
+ * // using "_.where" callback shorthand
2715
+ * _.some(characters, { 'age': 1 });
2716
+ * // => false
2717
+ */
2718
+ function some(collection, callback, thisArg) {
2719
+ var result;
2720
+ callback = createCallback(callback, thisArg, 3);
2721
+
2722
+ var index = -1,
2723
+ length = collection ? collection.length : 0;
2724
+
2725
+ if (typeof length == 'number') {
2726
+ while (++index < length) {
2727
+ if ((result = callback(collection[index], index, collection))) {
2728
+ break;
2729
+ }
2730
+ }
2731
+ } else {
2732
+ forOwn(collection, function(value, index, collection) {
2733
+ return (result = callback(value, index, collection)) && indicatorObject;
2734
+ });
2735
+ }
2736
+ return !!result;
2737
+ }
2738
+
2739
+ /**
2740
+ * Creates an array of elements, sorted in ascending order by the results of
2741
+ * running each element in a collection through the callback. This method
2742
+ * performs a stable sort, that is, it will preserve the original sort order
2743
+ * of equal elements. The callback is bound to `thisArg` and invoked with
2744
+ * three arguments; (value, index|key, collection).
2745
+ *
2746
+ * If a property name is provided for `callback` the created "_.pluck" style
2747
+ * callback will return the property value of the given element.
2748
+ *
2749
+ * If an object is provided for `callback` the created "_.where" style callback
2750
+ * will return `true` for elements that have the properties of the given object,
2751
+ * else `false`.
2752
+ *
2753
+ * @static
2754
+ * @memberOf _
2755
+ * @category Collections
2756
+ * @param {Array|Object|string} collection The collection to iterate over.
2757
+ * @param {Function|Object|string} [callback=identity] The function called
2758
+ * per iteration. If a property name or object is provided it will be used
2759
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2760
+ * @param {*} [thisArg] The `this` binding of `callback`.
2761
+ * @returns {Array} Returns a new array of sorted elements.
2762
+ * @example
2763
+ *
2764
+ * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
2765
+ * // => [3, 1, 2]
2766
+ *
2767
+ * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
2768
+ * // => [3, 1, 2]
2769
+ *
2770
+ * // using "_.pluck" callback shorthand
2771
+ * _.sortBy(['banana', 'strawberry', 'apple'], 'length');
2772
+ * // => ['apple', 'banana', 'strawberry']
2773
+ */
2774
+ function sortBy(collection, callback, thisArg) {
2775
+ var index = -1,
2776
+ length = collection ? collection.length : 0,
2777
+ result = Array(typeof length == 'number' ? length : 0);
2778
+
2779
+ callback = createCallback(callback, thisArg, 3);
2780
+ forEach(collection, function(value, key, collection) {
2781
+ result[++index] = {
2782
+ 'criteria': callback(value, key, collection),
2783
+ 'index': index,
2784
+ 'value': value
2785
+ };
2786
+ });
2787
+
2788
+ length = result.length;
2789
+ result.sort(compareAscending);
2790
+ while (length--) {
2791
+ result[length] = result[length].value;
2792
+ }
2793
+ return result;
2794
+ }
2795
+
2796
+ /**
2797
+ * Converts the `collection` to an array.
2798
+ *
2799
+ * @static
2800
+ * @memberOf _
2801
+ * @category Collections
2802
+ * @param {Array|Object|string} collection The collection to convert.
2803
+ * @returns {Array} Returns the new converted array.
2804
+ * @example
2805
+ *
2806
+ * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
2807
+ * // => [2, 3, 4]
2808
+ */
2809
+ function toArray(collection) {
2810
+ if (isArray(collection)) {
2811
+ return slice(collection);
2812
+ }
2813
+ if (collection && typeof collection.length == 'number') {
2814
+ return map(collection);
2815
+ }
2816
+ return values(collection);
2817
+ }
2818
+
2819
+ /**
2820
+ * Performs a deep comparison of each element in a `collection` to the given
2821
+ * `properties` object, returning an array of all elements that have equivalent
2822
+ * property values.
2823
+ *
2824
+ * @static
2825
+ * @memberOf _
2826
+ * @type Function
2827
+ * @category Collections
2828
+ * @param {Array|Object|string} collection The collection to iterate over.
2829
+ * @param {Object} properties The object of property values to filter by.
2830
+ * @returns {Array} Returns a new array of elements that have the given properties.
2831
+ * @example
2832
+ *
2833
+ * var characters = [
2834
+ * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
2835
+ * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
2836
+ * ];
2837
+ *
2838
+ * _.where(characters, { 'age': 36 });
2839
+ * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
2840
+ *
2841
+ * _.where(characters, { 'pets': ['dino'] });
2842
+ * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
2843
+ */
2844
+ function where(collection, properties, first) {
2845
+ return (first && isEmpty(properties))
2846
+ ? undefined
2847
+ : (first ? find : filter)(collection, properties);
2848
+ }
2849
+
2850
+ /*--------------------------------------------------------------------------*/
2851
+
2852
+ /**
2853
+ * Creates an array with all falsey values removed. The values `false`, `null`,
2854
+ * `0`, `""`, `undefined`, and `NaN` are all falsey.
2855
+ *
2856
+ * @static
2857
+ * @memberOf _
2858
+ * @category Arrays
2859
+ * @param {Array} array The array to compact.
2860
+ * @returns {Array} Returns a new array of filtered values.
2861
+ * @example
2862
+ *
2863
+ * _.compact([0, 1, false, 2, '', 3]);
2864
+ * // => [1, 2, 3]
2865
+ */
2866
+ function compact(array) {
2867
+ var index = -1,
2868
+ length = array ? array.length : 0,
2869
+ result = [];
2870
+
2871
+ while (++index < length) {
2872
+ var value = array[index];
2873
+ if (value) {
2874
+ result.push(value);
2875
+ }
2876
+ }
2877
+ return result;
2878
+ }
2879
+
2880
+ /**
2881
+ * Creates an array excluding all values of the provided arrays using strict
2882
+ * equality for comparisons, i.e. `===`.
2883
+ *
2884
+ * @static
2885
+ * @memberOf _
2886
+ * @category Arrays
2887
+ * @param {Array} array The array to process.
2888
+ * @param {...Array} [values] The arrays of values to exclude.
2889
+ * @returns {Array} Returns a new array of filtered values.
2890
+ * @example
2891
+ *
2892
+ * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
2893
+ * // => [1, 3, 4]
2894
+ */
2895
+ function difference(array) {
2896
+ return baseDifference(array, baseFlatten(arguments, true, true, 1));
2897
+ }
2898
+
2899
+ /**
2900
+ * Gets the first element or first `n` elements of an array. If a callback
2901
+ * is provided elements at the beginning of the array are returned as long
2902
+ * as the callback returns truey. The callback is bound to `thisArg` and
2903
+ * invoked with three arguments; (value, index, array).
2904
+ *
2905
+ * If a property name is provided for `callback` the created "_.pluck" style
2906
+ * callback will return the property value of the given element.
2907
+ *
2908
+ * If an object is provided for `callback` the created "_.where" style callback
2909
+ * will return `true` for elements that have the properties of the given object,
2910
+ * else `false`.
2911
+ *
2912
+ * @static
2913
+ * @memberOf _
2914
+ * @alias head, take
2915
+ * @category Arrays
2916
+ * @param {Array} array The array to query.
2917
+ * @param {Function|Object|number|string} [callback] The function called
2918
+ * per element or the number of elements to return. If a property name or
2919
+ * object is provided it will be used to create a "_.pluck" or "_.where"
2920
+ * style callback, respectively.
2921
+ * @param {*} [thisArg] The `this` binding of `callback`.
2922
+ * @returns {*} Returns the first element(s) of `array`.
2923
+ * @example
2924
+ *
2925
+ * _.first([1, 2, 3]);
2926
+ * // => 1
2927
+ *
2928
+ * _.first([1, 2, 3], 2);
2929
+ * // => [1, 2]
2930
+ *
2931
+ * _.first([1, 2, 3], function(num) {
2932
+ * return num < 3;
2933
+ * });
2934
+ * // => [1, 2]
2935
+ *
2936
+ * var characters = [
2937
+ * { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
2938
+ * { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
2939
+ * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
2940
+ * ];
2941
+ *
2942
+ * // using "_.pluck" callback shorthand
2943
+ * _.first(characters, 'blocked');
2944
+ * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
2945
+ *
2946
+ * // using "_.where" callback shorthand
2947
+ * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
2948
+ * // => ['barney', 'fred']
2949
+ */
2950
+ function first(array, callback, thisArg) {
2951
+ var n = 0,
2952
+ length = array ? array.length : 0;
2953
+
2954
+ if (typeof callback != 'number' && callback != null) {
2955
+ var index = -1;
2956
+ callback = createCallback(callback, thisArg, 3);
2957
+ while (++index < length && callback(array[index], index, array)) {
2958
+ n++;
2959
+ }
2960
+ } else {
2961
+ n = callback;
2962
+ if (n == null || thisArg) {
2963
+ return array ? array[0] : undefined;
2964
+ }
2965
+ }
2966
+ return slice(array, 0, nativeMin(nativeMax(0, n), length));
2967
+ }
2968
+
2969
+ /**
2970
+ * Flattens a nested array (the nesting can be to any depth). If `isShallow`
2971
+ * is truey, the array will only be flattened a single level. If a callback
2972
+ * is provided each element of the array is passed through the callback before
2973
+ * flattening. The callback is bound to `thisArg` and invoked with three
2974
+ * arguments; (value, index, array).
2975
+ *
2976
+ * If a property name is provided for `callback` the created "_.pluck" style
2977
+ * callback will return the property value of the given element.
2978
+ *
2979
+ * If an object is provided for `callback` the created "_.where" style callback
2980
+ * will return `true` for elements that have the properties of the given object,
2981
+ * else `false`.
2982
+ *
2983
+ * @static
2984
+ * @memberOf _
2985
+ * @category Arrays
2986
+ * @param {Array} array The array to flatten.
2987
+ * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
2988
+ * @param {Function|Object|string} [callback=identity] The function called
2989
+ * per iteration. If a property name or object is provided it will be used
2990
+ * to create a "_.pluck" or "_.where" style callback, respectively.
2991
+ * @param {*} [thisArg] The `this` binding of `callback`.
2992
+ * @returns {Array} Returns a new flattened array.
2993
+ * @example
2994
+ *
2995
+ * _.flatten([1, [2], [3, [[4]]]]);
2996
+ * // => [1, 2, 3, 4];
2997
+ *
2998
+ * _.flatten([1, [2], [3, [[4]]]], true);
2999
+ * // => [1, 2, 3, [[4]]];
3000
+ *
3001
+ * var characters = [
3002
+ * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
3003
+ * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
3004
+ * ];
3005
+ *
3006
+ * // using "_.pluck" callback shorthand
3007
+ * _.flatten(characters, 'pets');
3008
+ * // => ['hoppy', 'baby puss', 'dino']
3009
+ */
3010
+ function flatten(array, isShallow) {
3011
+ return baseFlatten(array, isShallow);
3012
+ }
3013
+
3014
+ /**
3015
+ * Gets the index at which the first occurrence of `value` is found using
3016
+ * strict equality for comparisons, i.e. `===`. If the array is already sorted
3017
+ * providing `true` for `fromIndex` will run a faster binary search.
3018
+ *
3019
+ * @static
3020
+ * @memberOf _
3021
+ * @category Arrays
3022
+ * @param {Array} array The array to search.
3023
+ * @param {*} value The value to search for.
3024
+ * @param {boolean|number} [fromIndex=0] The index to search from or `true`
3025
+ * to perform a binary search on a sorted array.
3026
+ * @returns {number} Returns the index of the matched value or `-1`.
3027
+ * @example
3028
+ *
3029
+ * _.indexOf([1, 2, 3, 1, 2, 3], 2);
3030
+ * // => 1
3031
+ *
3032
+ * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
3033
+ * // => 4
3034
+ *
3035
+ * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
3036
+ * // => 2
3037
+ */
3038
+ function indexOf(array, value, fromIndex) {
3039
+ if (typeof fromIndex == 'number') {
3040
+ var length = array ? array.length : 0;
3041
+ fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
3042
+ } else if (fromIndex) {
3043
+ var index = sortedIndex(array, value);
3044
+ return array[index] === value ? index : -1;
3045
+ }
3046
+ return baseIndexOf(array, value, fromIndex);
3047
+ }
3048
+
3049
+ /**
3050
+ * Gets all but the last element or last `n` elements of an array. If a
3051
+ * callback is provided elements at the end of the array are excluded from
3052
+ * the result as long as the callback returns truey. The callback is bound
3053
+ * to `thisArg` and invoked with three arguments; (value, index, array).
3054
+ *
3055
+ * If a property name is provided for `callback` the created "_.pluck" style
3056
+ * callback will return the property value of the given element.
3057
+ *
3058
+ * If an object is provided for `callback` the created "_.where" style callback
3059
+ * will return `true` for elements that have the properties of the given object,
3060
+ * else `false`.
3061
+ *
3062
+ * @static
3063
+ * @memberOf _
3064
+ * @category Arrays
3065
+ * @param {Array} array The array to query.
3066
+ * @param {Function|Object|number|string} [callback=1] The function called
3067
+ * per element or the number of elements to exclude. If a property name or
3068
+ * object is provided it will be used to create a "_.pluck" or "_.where"
3069
+ * style callback, respectively.
3070
+ * @param {*} [thisArg] The `this` binding of `callback`.
3071
+ * @returns {Array} Returns a slice of `array`.
3072
+ * @example
3073
+ *
3074
+ * _.initial([1, 2, 3]);
3075
+ * // => [1, 2]
3076
+ *
3077
+ * _.initial([1, 2, 3], 2);
3078
+ * // => [1]
3079
+ *
3080
+ * _.initial([1, 2, 3], function(num) {
3081
+ * return num > 1;
3082
+ * });
3083
+ * // => [1]
3084
+ *
3085
+ * var characters = [
3086
+ * { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
3087
+ * { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
3088
+ * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
3089
+ * ];
3090
+ *
3091
+ * // using "_.pluck" callback shorthand
3092
+ * _.initial(characters, 'blocked');
3093
+ * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }]
3094
+ *
3095
+ * // using "_.where" callback shorthand
3096
+ * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
3097
+ * // => ['barney', 'fred']
3098
+ */
3099
+ function initial(array, callback, thisArg) {
3100
+ var n = 0,
3101
+ length = array ? array.length : 0;
3102
+
3103
+ if (typeof callback != 'number' && callback != null) {
3104
+ var index = length;
3105
+ callback = createCallback(callback, thisArg, 3);
3106
+ while (index-- && callback(array[index], index, array)) {
3107
+ n++;
3108
+ }
3109
+ } else {
3110
+ n = (callback == null || thisArg) ? 1 : callback || n;
3111
+ }
3112
+ return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
3113
+ }
3114
+
3115
+ /**
3116
+ * Creates an array of unique values present in all provided arrays using
3117
+ * strict equality for comparisons, i.e. `===`.
3118
+ *
3119
+ * @static
3120
+ * @memberOf _
3121
+ * @category Arrays
3122
+ * @param {...Array} [array] The arrays to inspect.
3123
+ * @returns {Array} Returns an array of composite values.
3124
+ * @example
3125
+ *
3126
+ * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
3127
+ * // => [1, 2]
3128
+ */
3129
+ function intersection(array) {
3130
+ var args = arguments,
3131
+ argsLength = args.length,
3132
+ index = -1,
3133
+ indexOf = getIndexOf(),
3134
+ length = array ? array.length : 0,
3135
+ result = [];
3136
+
3137
+ outer:
3138
+ while (++index < length) {
3139
+ var value = array[index];
3140
+ if (indexOf(result, value) < 0) {
3141
+ var argsIndex = argsLength;
3142
+ while (--argsIndex) {
3143
+ if (indexOf(args[argsIndex], value) < 0) {
3144
+ continue outer;
3145
+ }
3146
+ }
3147
+ result.push(value);
3148
+ }
3149
+ }
3150
+ return result;
3151
+ }
3152
+
3153
+ /**
3154
+ * Gets the last element or last `n` elements of an array. If a callback is
3155
+ * provided elements at the end of the array are returned as long as the
3156
+ * callback returns truey. The callback is bound to `thisArg` and invoked
3157
+ * with three arguments; (value, index, array).
3158
+ *
3159
+ * If a property name is provided for `callback` the created "_.pluck" style
3160
+ * callback will return the property value of the given element.
3161
+ *
3162
+ * If an object is provided for `callback` the created "_.where" style callback
3163
+ * will return `true` for elements that have the properties of the given object,
3164
+ * else `false`.
3165
+ *
3166
+ * @static
3167
+ * @memberOf _
3168
+ * @category Arrays
3169
+ * @param {Array} array The array to query.
3170
+ * @param {Function|Object|number|string} [callback] The function called
3171
+ * per element or the number of elements to return. If a property name or
3172
+ * object is provided it will be used to create a "_.pluck" or "_.where"
3173
+ * style callback, respectively.
3174
+ * @param {*} [thisArg] The `this` binding of `callback`.
3175
+ * @returns {*} Returns the last element(s) of `array`.
3176
+ * @example
3177
+ *
3178
+ * _.last([1, 2, 3]);
3179
+ * // => 3
3180
+ *
3181
+ * _.last([1, 2, 3], 2);
3182
+ * // => [2, 3]
3183
+ *
3184
+ * _.last([1, 2, 3], function(num) {
3185
+ * return num > 1;
3186
+ * });
3187
+ * // => [2, 3]
3188
+ *
3189
+ * var characters = [
3190
+ * { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
3191
+ * { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
3192
+ * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
3193
+ * ];
3194
+ *
3195
+ * // using "_.pluck" callback shorthand
3196
+ * _.pluck(_.last(characters, 'blocked'), 'name');
3197
+ * // => ['fred', 'pebbles']
3198
+ *
3199
+ * // using "_.where" callback shorthand
3200
+ * _.last(characters, { 'employer': 'na' });
3201
+ * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
3202
+ */
3203
+ function last(array, callback, thisArg) {
3204
+ var n = 0,
3205
+ length = array ? array.length : 0;
3206
+
3207
+ if (typeof callback != 'number' && callback != null) {
3208
+ var index = length;
3209
+ callback = createCallback(callback, thisArg, 3);
3210
+ while (index-- && callback(array[index], index, array)) {
3211
+ n++;
3212
+ }
3213
+ } else {
3214
+ n = callback;
3215
+ if (n == null || thisArg) {
3216
+ return array ? array[length - 1] : undefined;
3217
+ }
3218
+ }
3219
+ return slice(array, nativeMax(0, length - n));
3220
+ }
3221
+
3222
+ /**
3223
+ * Gets the index at which the last occurrence of `value` is found using strict
3224
+ * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
3225
+ * as the offset from the end of the collection.
3226
+ *
3227
+ * If a property name is provided for `callback` the created "_.pluck" style
3228
+ * callback will return the property value of the given element.
3229
+ *
3230
+ * If an object is provided for `callback` the created "_.where" style callback
3231
+ * will return `true` for elements that have the properties of the given object,
3232
+ * else `false`.
3233
+ *
3234
+ * @static
3235
+ * @memberOf _
3236
+ * @category Arrays
3237
+ * @param {Array} array The array to search.
3238
+ * @param {*} value The value to search for.
3239
+ * @param {number} [fromIndex=array.length-1] The index to search from.
3240
+ * @returns {number} Returns the index of the matched value or `-1`.
3241
+ * @example
3242
+ *
3243
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
3244
+ * // => 4
3245
+ *
3246
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
3247
+ * // => 1
3248
+ */
3249
+ function lastIndexOf(array, value, fromIndex) {
3250
+ var index = array ? array.length : 0;
3251
+ if (typeof fromIndex == 'number') {
3252
+ index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
3253
+ }
3254
+ while (index--) {
3255
+ if (array[index] === value) {
3256
+ return index;
3257
+ }
3258
+ }
3259
+ return -1;
3260
+ }
3261
+
3262
+ /**
3263
+ * Creates an array of numbers (positive and/or negative) progressing from
3264
+ * `start` up to but not including `end`. If `start` is less than `stop` a
3265
+ * zero-length range is created unless a negative `step` is specified.
3266
+ *
3267
+ * @static
3268
+ * @memberOf _
3269
+ * @category Arrays
3270
+ * @param {number} [start=0] The start of the range.
3271
+ * @param {number} end The end of the range.
3272
+ * @param {number} [step=1] The value to increment or decrement by.
3273
+ * @returns {Array} Returns a new range array.
3274
+ * @example
3275
+ *
3276
+ * _.range(4);
3277
+ * // => [0, 1, 2, 3]
3278
+ *
3279
+ * _.range(1, 5);
3280
+ * // => [1, 2, 3, 4]
3281
+ *
3282
+ * _.range(0, 20, 5);
3283
+ * // => [0, 5, 10, 15]
3284
+ *
3285
+ * _.range(0, -4, -1);
3286
+ * // => [0, -1, -2, -3]
3287
+ *
3288
+ * _.range(1, 4, 0);
3289
+ * // => [1, 1, 1]
3290
+ *
3291
+ * _.range(0);
3292
+ * // => []
3293
+ */
3294
+ function range(start, end, step) {
3295
+ start = +start || 0;
3296
+ step = (+step || 1);
3297
+
3298
+ if (end == null) {
3299
+ end = start;
3300
+ start = 0;
3301
+ }
3302
+ // use `Array(length)` so engines like Chakra and V8 avoid slower modes
3303
+ // http://youtu.be/XAqIpGU8ZZk#t=17m25s
3304
+ var index = -1,
3305
+ length = nativeMax(0, ceil((end - start) / step)),
3306
+ result = Array(length);
3307
+
3308
+ while (++index < length) {
3309
+ result[index] = start;
3310
+ start += step;
3311
+ }
3312
+ return result;
3313
+ }
3314
+
3315
+ /**
3316
+ * The opposite of `_.initial` this method gets all but the first element or
3317
+ * first `n` elements of an array. If a callback function is provided elements
3318
+ * at the beginning of the array are excluded from the result as long as the
3319
+ * callback returns truey. The callback is bound to `thisArg` and invoked
3320
+ * with three arguments; (value, index, array).
3321
+ *
3322
+ * If a property name is provided for `callback` the created "_.pluck" style
3323
+ * callback will return the property value of the given element.
3324
+ *
3325
+ * If an object is provided for `callback` the created "_.where" style callback
3326
+ * will return `true` for elements that have the properties of the given object,
3327
+ * else `false`.
3328
+ *
3329
+ * @static
3330
+ * @memberOf _
3331
+ * @alias drop, tail
3332
+ * @category Arrays
3333
+ * @param {Array} array The array to query.
3334
+ * @param {Function|Object|number|string} [callback=1] The function called
3335
+ * per element or the number of elements to exclude. If a property name or
3336
+ * object is provided it will be used to create a "_.pluck" or "_.where"
3337
+ * style callback, respectively.
3338
+ * @param {*} [thisArg] The `this` binding of `callback`.
3339
+ * @returns {Array} Returns a slice of `array`.
3340
+ * @example
3341
+ *
3342
+ * _.rest([1, 2, 3]);
3343
+ * // => [2, 3]
3344
+ *
3345
+ * _.rest([1, 2, 3], 2);
3346
+ * // => [3]
3347
+ *
3348
+ * _.rest([1, 2, 3], function(num) {
3349
+ * return num < 3;
3350
+ * });
3351
+ * // => [3]
3352
+ *
3353
+ * var characters = [
3354
+ * { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
3355
+ * { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
3356
+ * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
3357
+ * ];
3358
+ *
3359
+ * // using "_.pluck" callback shorthand
3360
+ * _.pluck(_.rest(characters, 'blocked'), 'name');
3361
+ * // => ['fred', 'pebbles']
3362
+ *
3363
+ * // using "_.where" callback shorthand
3364
+ * _.rest(characters, { 'employer': 'slate' });
3365
+ * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
3366
+ */
3367
+ function rest(array, callback, thisArg) {
3368
+ if (typeof callback != 'number' && callback != null) {
3369
+ var n = 0,
3370
+ index = -1,
3371
+ length = array ? array.length : 0;
3372
+
3373
+ callback = createCallback(callback, thisArg, 3);
3374
+ while (++index < length && callback(array[index], index, array)) {
3375
+ n++;
3376
+ }
3377
+ } else {
3378
+ n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
3379
+ }
3380
+ return slice(array, n);
3381
+ }
3382
+
3383
+ /**
3384
+ * Uses a binary search to determine the smallest index at which a value
3385
+ * should be inserted into a given sorted array in order to maintain the sort
3386
+ * order of the array. If a callback is provided it will be executed for
3387
+ * `value` and each element of `array` to compute their sort ranking. The
3388
+ * callback is bound to `thisArg` and invoked with one argument; (value).
3389
+ *
3390
+ * If a property name is provided for `callback` the created "_.pluck" style
3391
+ * callback will return the property value of the given element.
3392
+ *
3393
+ * If an object is provided for `callback` the created "_.where" style callback
3394
+ * will return `true` for elements that have the properties of the given object,
3395
+ * else `false`.
3396
+ *
3397
+ * @static
3398
+ * @memberOf _
3399
+ * @category Arrays
3400
+ * @param {Array} array The array to inspect.
3401
+ * @param {*} value The value to evaluate.
3402
+ * @param {Function|Object|string} [callback=identity] The function called
3403
+ * per iteration. If a property name or object is provided it will be used
3404
+ * to create a "_.pluck" or "_.where" style callback, respectively.
3405
+ * @param {*} [thisArg] The `this` binding of `callback`.
3406
+ * @returns {number} Returns the index at which `value` should be inserted
3407
+ * into `array`.
3408
+ * @example
3409
+ *
3410
+ * _.sortedIndex([20, 30, 50], 40);
3411
+ * // => 2
3412
+ *
3413
+ * // using "_.pluck" callback shorthand
3414
+ * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
3415
+ * // => 2
3416
+ *
3417
+ * var dict = {
3418
+ * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
3419
+ * };
3420
+ *
3421
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
3422
+ * return dict.wordToNumber[word];
3423
+ * });
3424
+ * // => 2
3425
+ *
3426
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
3427
+ * return this.wordToNumber[word];
3428
+ * }, dict);
3429
+ * // => 2
3430
+ */
3431
+ function sortedIndex(array, value, callback, thisArg) {
3432
+ var low = 0,
3433
+ high = array ? array.length : low;
3434
+
3435
+ // explicitly reference `identity` for better inlining in Firefox
3436
+ callback = callback ? createCallback(callback, thisArg, 1) : identity;
3437
+ value = callback(value);
3438
+
3439
+ while (low < high) {
3440
+ var mid = (low + high) >>> 1;
3441
+ (callback(array[mid]) < value)
3442
+ ? low = mid + 1
3443
+ : high = mid;
3444
+ }
3445
+ return low;
3446
+ }
3447
+
3448
+ /**
3449
+ * Creates an array of unique values, in order, of the provided arrays using
3450
+ * strict equality for comparisons, i.e. `===`.
3451
+ *
3452
+ * @static
3453
+ * @memberOf _
3454
+ * @category Arrays
3455
+ * @param {...Array} [array] The arrays to inspect.
3456
+ * @returns {Array} Returns an array of composite values.
3457
+ * @example
3458
+ *
3459
+ * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
3460
+ * // => [1, 2, 3, 101, 10]
3461
+ */
3462
+ function union(array) {
3463
+ return baseUniq(baseFlatten(arguments, true, true));
3464
+ }
3465
+
3466
+ /**
3467
+ * Creates a duplicate-value-free version of an array using strict equality
3468
+ * for comparisons, i.e. `===`. If the array is sorted, providing
3469
+ * `true` for `isSorted` will use a faster algorithm. If a callback is provided
3470
+ * each element of `array` is passed through the callback before uniqueness
3471
+ * is computed. The callback is bound to `thisArg` and invoked with three
3472
+ * arguments; (value, index, array).
3473
+ *
3474
+ * If a property name is provided for `callback` the created "_.pluck" style
3475
+ * callback will return the property value of the given element.
3476
+ *
3477
+ * If an object is provided for `callback` the created "_.where" style callback
3478
+ * will return `true` for elements that have the properties of the given object,
3479
+ * else `false`.
3480
+ *
3481
+ * @static
3482
+ * @memberOf _
3483
+ * @alias unique
3484
+ * @category Arrays
3485
+ * @param {Array} array The array to process.
3486
+ * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
3487
+ * @param {Function|Object|string} [callback=identity] The function called
3488
+ * per iteration. If a property name or object is provided it will be used
3489
+ * to create a "_.pluck" or "_.where" style callback, respectively.
3490
+ * @param {*} [thisArg] The `this` binding of `callback`.
3491
+ * @returns {Array} Returns a duplicate-value-free array.
3492
+ * @example
3493
+ *
3494
+ * _.uniq([1, 2, 1, 3, 1]);
3495
+ * // => [1, 2, 3]
3496
+ *
3497
+ * _.uniq([1, 1, 2, 2, 3], true);
3498
+ * // => [1, 2, 3]
3499
+ *
3500
+ * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
3501
+ * // => ['A', 'b', 'C']
3502
+ *
3503
+ * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
3504
+ * // => [1, 2.5, 3]
3505
+ *
3506
+ * // using "_.pluck" callback shorthand
3507
+ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
3508
+ * // => [{ 'x': 1 }, { 'x': 2 }]
3509
+ */
3510
+ function uniq(array, isSorted, callback, thisArg) {
3511
+ // juggle arguments
3512
+ if (typeof isSorted != 'boolean' && isSorted != null) {
3513
+ thisArg = callback;
3514
+ callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
3515
+ isSorted = false;
3516
+ }
3517
+ if (callback != null) {
3518
+ callback = createCallback(callback, thisArg, 3);
3519
+ }
3520
+ return baseUniq(array, isSorted, callback);
3521
+ }
3522
+
3523
+ /**
3524
+ * Creates an array excluding all provided values using strict equality for
3525
+ * comparisons, i.e. `===`.
3526
+ *
3527
+ * @static
3528
+ * @memberOf _
3529
+ * @category Arrays
3530
+ * @param {Array} array The array to filter.
3531
+ * @param {...*} [value] The values to exclude.
3532
+ * @returns {Array} Returns a new array of filtered values.
3533
+ * @example
3534
+ *
3535
+ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
3536
+ * // => [2, 3, 4]
3537
+ */
3538
+ function without(array) {
3539
+ return baseDifference(array, slice(arguments, 1));
3540
+ }
3541
+
3542
+ /**
3543
+ * Creates an array of grouped elements, the first of which contains the first
3544
+ * elements of the given arrays, the second of which contains the second
3545
+ * elements of the given arrays, and so on.
3546
+ *
3547
+ * @static
3548
+ * @memberOf _
3549
+ * @alias unzip
3550
+ * @category Arrays
3551
+ * @param {...Array} [array] Arrays to process.
3552
+ * @returns {Array} Returns a new array of grouped elements.
3553
+ * @example
3554
+ *
3555
+ * _.zip(['fred', 'barney'], [30, 40], [true, false]);
3556
+ * // => [['fred', 30, true], ['barney', 40, false]]
3557
+ */
3558
+ function zip() {
3559
+ var index = -1,
3560
+ length = max(pluck(arguments, 'length')),
3561
+ result = Array(length < 0 ? 0 : length);
3562
+
3563
+ while (++index < length) {
3564
+ result[index] = pluck(arguments, index);
3565
+ }
3566
+ return result;
3567
+ }
3568
+
3569
+ /**
3570
+ * Creates an object composed from arrays of `keys` and `values`. Provide
3571
+ * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
3572
+ * or two arrays, one of `keys` and one of corresponding `values`.
3573
+ *
3574
+ * @static
3575
+ * @memberOf _
3576
+ * @alias object
3577
+ * @category Arrays
3578
+ * @param {Array} keys The array of keys.
3579
+ * @param {Array} [values=[]] The array of values.
3580
+ * @returns {Object} Returns an object composed of the given keys and
3581
+ * corresponding values.
3582
+ * @example
3583
+ *
3584
+ * _.zipObject(['fred', 'barney'], [30, 40]);
3585
+ * // => { 'fred': 30, 'barney': 40 }
3586
+ */
3587
+ function zipObject(keys, values) {
3588
+ var index = -1,
3589
+ length = keys ? keys.length : 0,
3590
+ result = {};
3591
+
3592
+ while (++index < length) {
3593
+ var key = keys[index];
3594
+ if (values) {
3595
+ result[key] = values[index];
3596
+ } else if (key) {
3597
+ result[key[0]] = key[1];
3598
+ }
3599
+ }
3600
+ return result;
3601
+ }
3602
+
3603
+ /*--------------------------------------------------------------------------*/
3604
+
3605
+ /**
3606
+ * Creates a function that executes `func`, with the `this` binding and
3607
+ * arguments of the created function, only after being called `n` times.
3608
+ *
3609
+ * @static
3610
+ * @memberOf _
3611
+ * @category Functions
3612
+ * @param {number} n The number of times the function must be called before
3613
+ * `func` is executed.
3614
+ * @param {Function} func The function to restrict.
3615
+ * @returns {Function} Returns the new restricted function.
3616
+ * @example
3617
+ *
3618
+ * var saves = ['profile', 'settings'];
3619
+ *
3620
+ * var done = _.after(saves.length, function() {
3621
+ * console.log('Done saving!');
3622
+ * });
3623
+ *
3624
+ * _.forEach(saves, function(type) {
3625
+ * asyncSave({ 'type': type, 'complete': done });
3626
+ * });
3627
+ * // => logs 'Done saving!', after all saves have completed
3628
+ */
3629
+ function after(n, func) {
3630
+ if (!isFunction(func)) {
3631
+ throw new TypeError;
3632
+ }
3633
+ return function() {
3634
+ if (--n < 1) {
3635
+ return func.apply(this, arguments);
3636
+ }
3637
+ };
3638
+ }
3639
+
3640
+ /**
3641
+ * Creates a function that, when called, invokes `func` with the `this`
3642
+ * binding of `thisArg` and prepends any additional `bind` arguments to those
3643
+ * provided to the bound function.
3644
+ *
3645
+ * @static
3646
+ * @memberOf _
3647
+ * @category Functions
3648
+ * @param {Function} func The function to bind.
3649
+ * @param {*} [thisArg] The `this` binding of `func`.
3650
+ * @param {...*} [arg] Arguments to be partially applied.
3651
+ * @returns {Function} Returns the new bound function.
3652
+ * @example
3653
+ *
3654
+ * var func = function(greeting) {
3655
+ * return greeting + ' ' + this.name;
3656
+ * };
3657
+ *
3658
+ * func = _.bind(func, { 'name': 'fred' }, 'hi');
3659
+ * func();
3660
+ * // => 'hi fred'
3661
+ */
3662
+ function bind(func, thisArg) {
3663
+ return arguments.length > 2
3664
+ ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
3665
+ : createWrapper(func, 1, null, null, thisArg);
3666
+ }
3667
+
3668
+ /**
3669
+ * Binds methods of an object to the object itself, overwriting the existing
3670
+ * method. Method names may be specified as individual arguments or as arrays
3671
+ * of method names. If no method names are provided all the function properties
3672
+ * of `object` will be bound.
3673
+ *
3674
+ * @static
3675
+ * @memberOf _
3676
+ * @category Functions
3677
+ * @param {Object} object The object to bind and assign the bound methods to.
3678
+ * @param {...string} [methodName] The object method names to
3679
+ * bind, specified as individual method names or arrays of method names.
3680
+ * @returns {Object} Returns `object`.
3681
+ * @example
3682
+ *
3683
+ * var view = {
3684
+ * 'label': 'docs',
3685
+ * 'onClick': function() { console.log('clicked ' + this.label); }
3686
+ * };
3687
+ *
3688
+ * _.bindAll(view);
3689
+ * jQuery('#docs').on('click', view.onClick);
3690
+ * // => logs 'clicked docs', when the button is clicked
3691
+ */
3692
+ function bindAll(object) {
3693
+ var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
3694
+ index = -1,
3695
+ length = funcs.length;
3696
+
3697
+ while (++index < length) {
3698
+ var key = funcs[index];
3699
+ object[key] = createWrapper(object[key], 1, null, null, object);
3700
+ }
3701
+ return object;
3702
+ }
3703
+
3704
+ /**
3705
+ * Creates a function that is the composition of the provided functions,
3706
+ * where each function consumes the return value of the function that follows.
3707
+ * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
3708
+ * Each function is executed with the `this` binding of the composed function.
3709
+ *
3710
+ * @static
3711
+ * @memberOf _
3712
+ * @category Functions
3713
+ * @param {...Function} [func] Functions to compose.
3714
+ * @returns {Function} Returns the new composed function.
3715
+ * @example
3716
+ *
3717
+ * var realNameMap = {
3718
+ * 'pebbles': 'penelope'
3719
+ * };
3720
+ *
3721
+ * var format = function(name) {
3722
+ * name = realNameMap[name.toLowerCase()] || name;
3723
+ * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
3724
+ * };
3725
+ *
3726
+ * var greet = function(formatted) {
3727
+ * return 'Hiya ' + formatted + '!';
3728
+ * };
3729
+ *
3730
+ * var welcome = _.compose(greet, format);
3731
+ * welcome('pebbles');
3732
+ * // => 'Hiya Penelope!'
3733
+ */
3734
+ function compose() {
3735
+ var funcs = arguments,
3736
+ length = funcs.length;
3737
+
3738
+ while (length--) {
3739
+ if (!isFunction(funcs[length])) {
3740
+ throw new TypeError;
3741
+ }
3742
+ }
3743
+ return function() {
3744
+ var args = arguments,
3745
+ length = funcs.length;
3746
+
3747
+ while (length--) {
3748
+ args = [funcs[length].apply(this, args)];
3749
+ }
3750
+ return args[0];
3751
+ };
3752
+ }
3753
+
3754
+ /**
3755
+ * Produces a callback bound to an optional `thisArg`. If `func` is a property
3756
+ * name the created callback will return the property value for a given element.
3757
+ * If `func` is an object the created callback will return `true` for elements
3758
+ * that contain the equivalent object properties, otherwise it will return `false`.
3759
+ *
3760
+ * @static
3761
+ * @memberOf _
3762
+ * @category Functions
3763
+ * @param {*} [func=identity] The value to convert to a callback.
3764
+ * @param {*} [thisArg] The `this` binding of the created callback.
3765
+ * @param {number} [argCount] The number of arguments the callback accepts.
3766
+ * @returns {Function} Returns a callback function.
3767
+ * @example
3768
+ *
3769
+ * var characters = [
3770
+ * { 'name': 'barney', 'age': 36 },
3771
+ * { 'name': 'fred', 'age': 40 }
3772
+ * ];
3773
+ *
3774
+ * // wrap to create custom callback shorthands
3775
+ * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
3776
+ * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
3777
+ * return !match ? func(callback, thisArg) : function(object) {
3778
+ * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
3779
+ * };
3780
+ * });
3781
+ *
3782
+ * _.filter(characters, 'age__gt38');
3783
+ * // => [{ 'name': 'fred', 'age': 40 }]
3784
+ */
3785
+ function createCallback(func, thisArg, argCount) {
3786
+ var type = typeof func;
3787
+ if (func == null || type == 'function') {
3788
+ return baseCreateCallback(func, thisArg, argCount);
3789
+ }
3790
+ // handle "_.pluck" style callback shorthands
3791
+ if (type != 'object') {
3792
+ return function(object) {
3793
+ return object[func];
3794
+ };
3795
+ }
3796
+ var props = keys(func);
3797
+ return function(object) {
3798
+ var length = props.length,
3799
+ result = false;
3800
+
3801
+ while (length--) {
3802
+ if (!(result = object[props[length]] === func[props[length]])) {
3803
+ break;
3804
+ }
3805
+ }
3806
+ return result;
3807
+ };
3808
+ }
3809
+
3810
+ /**
3811
+ * Creates a function that will delay the execution of `func` until after
3812
+ * `wait` milliseconds have elapsed since the last time it was invoked.
3813
+ * Provide an options object to indicate that `func` should be invoked on
3814
+ * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
3815
+ * to the debounced function will return the result of the last `func` call.
3816
+ *
3817
+ * Note: If `leading` and `trailing` options are `true` `func` will be called
3818
+ * on the trailing edge of the timeout only if the the debounced function is
3819
+ * invoked more than once during the `wait` timeout.
3820
+ *
3821
+ * @static
3822
+ * @memberOf _
3823
+ * @category Functions
3824
+ * @param {Function} func The function to debounce.
3825
+ * @param {number} wait The number of milliseconds to delay.
3826
+ * @param {Object} [options] The options object.
3827
+ * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
3828
+ * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
3829
+ * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
3830
+ * @returns {Function} Returns the new debounced function.
3831
+ * @example
3832
+ *
3833
+ * // avoid costly calculations while the window size is in flux
3834
+ * var lazyLayout = _.debounce(calculateLayout, 150);
3835
+ * jQuery(window).on('resize', lazyLayout);
3836
+ *
3837
+ * // execute `sendMail` when the click event is fired, debouncing subsequent calls
3838
+ * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
3839
+ * 'leading': true,
3840
+ * 'trailing': false
3841
+ * });
3842
+ *
3843
+ * // ensure `batchLog` is executed once after 1 second of debounced calls
3844
+ * var source = new EventSource('/stream');
3845
+ * source.addEventListener('message', _.debounce(batchLog, 250, {
3846
+ * 'maxWait': 1000
3847
+ * }, false);
3848
+ */
3849
+ function debounce(func, wait, options) {
3850
+ var args,
3851
+ maxTimeoutId,
3852
+ result,
3853
+ stamp,
3854
+ thisArg,
3855
+ timeoutId,
3856
+ trailingCall,
3857
+ lastCalled = 0,
3858
+ maxWait = false,
3859
+ trailing = true;
3860
+
3861
+ if (!isFunction(func)) {
3862
+ throw new TypeError;
3863
+ }
3864
+ wait = nativeMax(0, wait) || 0;
3865
+ if (options === true) {
3866
+ var leading = true;
3867
+ trailing = false;
3868
+ } else if (isObject(options)) {
3869
+ leading = options.leading;
3870
+ maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
3871
+ trailing = 'trailing' in options ? options.trailing : trailing;
3872
+ }
3873
+ var delayed = function() {
3874
+ var remaining = wait - (now() - stamp);
3875
+ if (remaining <= 0) {
3876
+ if (maxTimeoutId) {
3877
+ clearTimeout(maxTimeoutId);
3878
+ }
3879
+ var isCalled = trailingCall;
3880
+ maxTimeoutId = timeoutId = trailingCall = undefined;
3881
+ if (isCalled) {
3882
+ lastCalled = now();
3883
+ result = func.apply(thisArg, args);
3884
+ if (!timeoutId && !maxTimeoutId) {
3885
+ args = thisArg = null;
3886
+ }
3887
+ }
3888
+ } else {
3889
+ timeoutId = setTimeout(delayed, remaining);
3890
+ }
3891
+ };
3892
+
3893
+ var maxDelayed = function() {
3894
+ if (timeoutId) {
3895
+ clearTimeout(timeoutId);
3896
+ }
3897
+ maxTimeoutId = timeoutId = trailingCall = undefined;
3898
+ if (trailing || (maxWait !== wait)) {
3899
+ lastCalled = now();
3900
+ result = func.apply(thisArg, args);
3901
+ if (!timeoutId && !maxTimeoutId) {
3902
+ args = thisArg = null;
3903
+ }
3904
+ }
3905
+ };
3906
+
3907
+ return function() {
3908
+ args = arguments;
3909
+ stamp = now();
3910
+ thisArg = this;
3911
+ trailingCall = trailing && (timeoutId || !leading);
3912
+
3913
+ if (maxWait === false) {
3914
+ var leadingCall = leading && !timeoutId;
3915
+ } else {
3916
+ if (!maxTimeoutId && !leading) {
3917
+ lastCalled = stamp;
3918
+ }
3919
+ var remaining = maxWait - (stamp - lastCalled),
3920
+ isCalled = remaining <= 0;
3921
+
3922
+ if (isCalled) {
3923
+ if (maxTimeoutId) {
3924
+ maxTimeoutId = clearTimeout(maxTimeoutId);
3925
+ }
3926
+ lastCalled = stamp;
3927
+ result = func.apply(thisArg, args);
3928
+ }
3929
+ else if (!maxTimeoutId) {
3930
+ maxTimeoutId = setTimeout(maxDelayed, remaining);
3931
+ }
3932
+ }
3933
+ if (isCalled && timeoutId) {
3934
+ timeoutId = clearTimeout(timeoutId);
3935
+ }
3936
+ else if (!timeoutId && wait !== maxWait) {
3937
+ timeoutId = setTimeout(delayed, wait);
3938
+ }
3939
+ if (leadingCall) {
3940
+ isCalled = true;
3941
+ result = func.apply(thisArg, args);
3942
+ }
3943
+ if (isCalled && !timeoutId && !maxTimeoutId) {
3944
+ args = thisArg = null;
3945
+ }
3946
+ return result;
3947
+ };
3948
+ }
3949
+
3950
+ /**
3951
+ * Defers executing the `func` function until the current call stack has cleared.
3952
+ * Additional arguments will be provided to `func` when it is invoked.
3953
+ *
3954
+ * @static
3955
+ * @memberOf _
3956
+ * @category Functions
3957
+ * @param {Function} func The function to defer.
3958
+ * @param {...*} [arg] Arguments to invoke the function with.
3959
+ * @returns {number} Returns the timer id.
3960
+ * @example
3961
+ *
3962
+ * _.defer(function() { console.log('deferred'); });
3963
+ * // returns from the function before 'deferred' is logged
3964
+ */
3965
+ function defer(func) {
3966
+ if (!isFunction(func)) {
3967
+ throw new TypeError;
3968
+ }
3969
+ var args = slice(arguments, 1);
3970
+ return setTimeout(function() { func.apply(undefined, args); }, 1);
3971
+ }
3972
+
3973
+ /**
3974
+ * Executes the `func` function after `wait` milliseconds. Additional arguments
3975
+ * will be provided to `func` when it is invoked.
3976
+ *
3977
+ * @static
3978
+ * @memberOf _
3979
+ * @category Functions
3980
+ * @param {Function} func The function to delay.
3981
+ * @param {number} wait The number of milliseconds to delay execution.
3982
+ * @param {...*} [arg] Arguments to invoke the function with.
3983
+ * @returns {number} Returns the timer id.
3984
+ * @example
3985
+ *
3986
+ * var log = _.bind(console.log, console);
3987
+ * _.delay(log, 1000, 'logged later');
3988
+ * // => 'logged later' (Appears after one second.)
3989
+ */
3990
+ function delay(func, wait) {
3991
+ if (!isFunction(func)) {
3992
+ throw new TypeError;
3993
+ }
3994
+ var args = slice(arguments, 2);
3995
+ return setTimeout(function() { func.apply(undefined, args); }, wait);
3996
+ }
3997
+
3998
+ /**
3999
+ * Creates a function that memoizes the result of `func`. If `resolver` is
4000
+ * provided it will be used to determine the cache key for storing the result
4001
+ * based on the arguments provided to the memoized function. By default, the
4002
+ * first argument provided to the memoized function is used as the cache key.
4003
+ * The `func` is executed with the `this` binding of the memoized function.
4004
+ * The result cache is exposed as the `cache` property on the memoized function.
4005
+ *
4006
+ * @static
4007
+ * @memberOf _
4008
+ * @category Functions
4009
+ * @param {Function} func The function to have its output memoized.
4010
+ * @param {Function} [resolver] A function used to resolve the cache key.
4011
+ * @returns {Function} Returns the new memoizing function.
4012
+ * @example
4013
+ *
4014
+ * var fibonacci = _.memoize(function(n) {
4015
+ * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
4016
+ * });
4017
+ *
4018
+ * fibonacci(9)
4019
+ * // => 34
4020
+ *
4021
+ * var data = {
4022
+ * 'fred': { 'name': 'fred', 'age': 40 },
4023
+ * 'pebbles': { 'name': 'pebbles', 'age': 1 }
4024
+ * };
4025
+ *
4026
+ * // modifying the result cache
4027
+ * var get = _.memoize(function(name) { return data[name]; }, _.identity);
4028
+ * get('pebbles');
4029
+ * // => { 'name': 'pebbles', 'age': 1 }
4030
+ *
4031
+ * get.cache.pebbles.name = 'penelope';
4032
+ * get('pebbles');
4033
+ * // => { 'name': 'penelope', 'age': 1 }
4034
+ */
4035
+ function memoize(func, resolver) {
4036
+ var cache = {};
4037
+ return function() {
4038
+ var key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
4039
+ return hasOwnProperty.call(cache, key)
4040
+ ? cache[key]
4041
+ : (cache[key] = func.apply(this, arguments));
4042
+ };
4043
+ }
4044
+
4045
+ /**
4046
+ * Creates a function that is restricted to execute `func` once. Repeat calls to
4047
+ * the function will return the value of the first call. The `func` is executed
4048
+ * with the `this` binding of the created function.
4049
+ *
4050
+ * @static
4051
+ * @memberOf _
4052
+ * @category Functions
4053
+ * @param {Function} func The function to restrict.
4054
+ * @returns {Function} Returns the new restricted function.
4055
+ * @example
4056
+ *
4057
+ * var initialize = _.once(createApplication);
4058
+ * initialize();
4059
+ * initialize();
4060
+ * // `initialize` executes `createApplication` once
4061
+ */
4062
+ function once(func) {
4063
+ var ran,
4064
+ result;
4065
+
4066
+ if (!isFunction(func)) {
4067
+ throw new TypeError;
4068
+ }
4069
+ return function() {
4070
+ if (ran) {
4071
+ return result;
4072
+ }
4073
+ ran = true;
4074
+ result = func.apply(this, arguments);
4075
+
4076
+ // clear the `func` variable so the function may be garbage collected
4077
+ func = null;
4078
+ return result;
4079
+ };
4080
+ }
4081
+
4082
+ /**
4083
+ * Creates a function that, when called, invokes `func` with any additional
4084
+ * `partial` arguments prepended to those provided to the new function. This
4085
+ * method is similar to `_.bind` except it does **not** alter the `this` binding.
4086
+ *
4087
+ * @static
4088
+ * @memberOf _
4089
+ * @category Functions
4090
+ * @param {Function} func The function to partially apply arguments to.
4091
+ * @param {...*} [arg] Arguments to be partially applied.
4092
+ * @returns {Function} Returns the new partially applied function.
4093
+ * @example
4094
+ *
4095
+ * var greet = function(greeting, name) { return greeting + ' ' + name; };
4096
+ * var hi = _.partial(greet, 'hi');
4097
+ * hi('fred');
4098
+ * // => 'hi fred'
4099
+ */
4100
+ function partial(func) {
4101
+ return createWrapper(func, 16, slice(arguments, 1));
4102
+ }
4103
+
4104
+ /**
4105
+ * Creates a function that, when executed, will only call the `func` function
4106
+ * at most once per every `wait` milliseconds. Provide an options object to
4107
+ * indicate that `func` should be invoked on the leading and/or trailing edge
4108
+ * of the `wait` timeout. Subsequent calls to the throttled function will
4109
+ * return the result of the last `func` call.
4110
+ *
4111
+ * Note: If `leading` and `trailing` options are `true` `func` will be called
4112
+ * on the trailing edge of the timeout only if the the throttled function is
4113
+ * invoked more than once during the `wait` timeout.
4114
+ *
4115
+ * @static
4116
+ * @memberOf _
4117
+ * @category Functions
4118
+ * @param {Function} func The function to throttle.
4119
+ * @param {number} wait The number of milliseconds to throttle executions to.
4120
+ * @param {Object} [options] The options object.
4121
+ * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
4122
+ * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
4123
+ * @returns {Function} Returns the new throttled function.
4124
+ * @example
4125
+ *
4126
+ * // avoid excessively updating the position while scrolling
4127
+ * var throttled = _.throttle(updatePosition, 100);
4128
+ * jQuery(window).on('scroll', throttled);
4129
+ *
4130
+ * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
4131
+ * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
4132
+ * 'trailing': false
4133
+ * }));
4134
+ */
4135
+ function throttle(func, wait, options) {
4136
+ var leading = true,
4137
+ trailing = true;
4138
+
4139
+ if (!isFunction(func)) {
4140
+ throw new TypeError;
4141
+ }
4142
+ if (options === false) {
4143
+ leading = false;
4144
+ } else if (isObject(options)) {
4145
+ leading = 'leading' in options ? options.leading : leading;
4146
+ trailing = 'trailing' in options ? options.trailing : trailing;
4147
+ }
4148
+ options = {};
4149
+ options.leading = leading;
4150
+ options.maxWait = wait;
4151
+ options.trailing = trailing;
4152
+
4153
+ return debounce(func, wait, options);
4154
+ }
4155
+
4156
+ /**
4157
+ * Creates a function that provides `value` to the wrapper function as its
4158
+ * first argument. Additional arguments provided to the function are appended
4159
+ * to those provided to the wrapper function. The wrapper is executed with
4160
+ * the `this` binding of the created function.
4161
+ *
4162
+ * @static
4163
+ * @memberOf _
4164
+ * @category Functions
4165
+ * @param {*} value The value to wrap.
4166
+ * @param {Function} wrapper The wrapper function.
4167
+ * @returns {Function} Returns the new function.
4168
+ * @example
4169
+ *
4170
+ * var p = _.wrap(_.escape, function(func, text) {
4171
+ * return '<p>' + func(text) + '</p>';
4172
+ * });
4173
+ *
4174
+ * p('Fred, Wilma, & Pebbles');
4175
+ * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
4176
+ */
4177
+ function wrap(value, wrapper) {
4178
+ return createWrapper(wrapper, 16, [value]);
4179
+ }
4180
+
4181
+ /*--------------------------------------------------------------------------*/
4182
+
4183
+ /**
4184
+ * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
4185
+ * corresponding HTML entities.
4186
+ *
4187
+ * @static
4188
+ * @memberOf _
4189
+ * @category Utilities
4190
+ * @param {string} string The string to escape.
4191
+ * @returns {string} Returns the escaped string.
4192
+ * @example
4193
+ *
4194
+ * _.escape('Fred, Wilma, & Pebbles');
4195
+ * // => 'Fred, Wilma, &amp; Pebbles'
4196
+ */
4197
+ function escape(string) {
4198
+ return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
4199
+ }
4200
+
4201
+ /**
4202
+ * This method returns the first argument provided to it.
4203
+ *
4204
+ * @static
4205
+ * @memberOf _
4206
+ * @category Utilities
4207
+ * @param {*} value Any value.
4208
+ * @returns {*} Returns `value`.
4209
+ * @example
4210
+ *
4211
+ * var object = { 'name': 'fred' };
4212
+ * _.identity(object) === object;
4213
+ * // => true
4214
+ */
4215
+ function identity(value) {
4216
+ return value;
4217
+ }
4218
+
4219
+ /**
4220
+ * Adds function properties of a source object to the `lodash` function and
4221
+ * chainable wrapper.
4222
+ *
4223
+ * @static
4224
+ * @memberOf _
4225
+ * @category Utilities
4226
+ * @param {Object} object The object of function properties to add to `lodash`.
4227
+ * @param {Object} object The object of function properties to add to `lodash`.
4228
+ * @example
4229
+ *
4230
+ * _.mixin({
4231
+ * 'capitalize': function(string) {
4232
+ * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
4233
+ * }
4234
+ * });
4235
+ *
4236
+ * _.capitalize('fred');
4237
+ * // => 'Fred'
4238
+ *
4239
+ * _('fred').capitalize();
4240
+ * // => 'Fred'
4241
+ */
4242
+ function mixin(object) {
4243
+ forEach(functions(object), function(methodName) {
4244
+ var func = lodash[methodName] = object[methodName];
4245
+
4246
+ lodash.prototype[methodName] = function() {
4247
+ var args = [this.__wrapped__];
4248
+ push.apply(args, arguments);
4249
+
4250
+ var result = func.apply(lodash, args);
4251
+ return this.__chain__
4252
+ ? new lodashWrapper(result, true)
4253
+ : result;
4254
+ };
4255
+ });
4256
+ }
4257
+
4258
+ /**
4259
+ * Reverts the '_' variable to its previous value and returns a reference to
4260
+ * the `lodash` function.
4261
+ *
4262
+ * @static
4263
+ * @memberOf _
4264
+ * @category Utilities
4265
+ * @returns {Function} Returns the `lodash` function.
4266
+ * @example
4267
+ *
4268
+ * var lodash = _.noConflict();
4269
+ */
4270
+ function noConflict() {
4271
+ root._ = oldDash;
4272
+ return this;
4273
+ }
4274
+
4275
+ /**
4276
+ * A no-operation function.
4277
+ *
4278
+ * @static
4279
+ * @memberOf _
4280
+ * @category Utilities
4281
+ * @example
4282
+ *
4283
+ * var object = { 'name': 'fred' };
4284
+ * _.noop(object) === undefined;
4285
+ * // => true
4286
+ */
4287
+ function noop() {
4288
+ // no operation performed
4289
+ }
4290
+
4291
+ /**
4292
+ * Produces a random number between `min` and `max` (inclusive). If only one
4293
+ * argument is provided a number between `0` and the given number will be
4294
+ * returned. If `floating` is truey or either `min` or `max` are floats a
4295
+ * floating-point number will be returned instead of an integer.
4296
+ *
4297
+ * @static
4298
+ * @memberOf _
4299
+ * @category Utilities
4300
+ * @param {number} [min=0] The minimum possible value.
4301
+ * @param {number} [max=1] The maximum possible value.
4302
+ * @param {boolean} [floating=false] Specify returning a floating-point number.
4303
+ * @returns {number} Returns a random number.
4304
+ * @example
4305
+ *
4306
+ * _.random(0, 5);
4307
+ * // => an integer between 0 and 5
4308
+ *
4309
+ * _.random(5);
4310
+ * // => also an integer between 0 and 5
4311
+ *
4312
+ * _.random(5, true);
4313
+ * // => a floating-point number between 0 and 5
4314
+ *
4315
+ * _.random(1.2, 5.2);
4316
+ * // => a floating-point number between 1.2 and 5.2
4317
+ */
4318
+ function random(min, max) {
4319
+ if (min == null && max == null) {
4320
+ max = 1;
4321
+ }
4322
+ min = +min || 0;
4323
+ if (max == null) {
4324
+ max = min;
4325
+ min = 0;
4326
+ } else {
4327
+ max = +max || 0;
4328
+ }
4329
+ return min + floor(nativeRandom() * (max - min + 1));
4330
+ }
4331
+
4332
+ /**
4333
+ * Resolves the value of `property` on `object`. If `property` is a function
4334
+ * it will be invoked with the `this` binding of `object` and its result returned,
4335
+ * else the property value is returned. If `object` is falsey then `undefined`
4336
+ * is returned.
4337
+ *
4338
+ * @static
4339
+ * @memberOf _
4340
+ * @category Utilities
4341
+ * @param {Object} object The object to inspect.
4342
+ * @param {string} property The property to get the value of.
4343
+ * @returns {*} Returns the resolved value.
4344
+ * @example
4345
+ *
4346
+ * var object = {
4347
+ * 'cheese': 'crumpets',
4348
+ * 'stuff': function() {
4349
+ * return 'nonsense';
4350
+ * }
4351
+ * };
4352
+ *
4353
+ * _.result(object, 'cheese');
4354
+ * // => 'crumpets'
4355
+ *
4356
+ * _.result(object, 'stuff');
4357
+ * // => 'nonsense'
4358
+ */
4359
+ function result(object, property) {
4360
+ if (object) {
4361
+ var value = object[property];
4362
+ return isFunction(value) ? object[property]() : value;
4363
+ }
4364
+ }
4365
+
4366
+ /**
4367
+ * A micro-templating method that handles arbitrary delimiters, preserves
4368
+ * whitespace, and correctly escapes quotes within interpolated code.
4369
+ *
4370
+ * Note: In the development build, `_.template` utilizes sourceURLs for easier
4371
+ * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
4372
+ *
4373
+ * For more information on precompiling templates see:
4374
+ * http://lodash.com/custom-builds
4375
+ *
4376
+ * For more information on Chrome extension sandboxes see:
4377
+ * http://developer.chrome.com/stable/extensions/sandboxingEval.html
4378
+ *
4379
+ * @static
4380
+ * @memberOf _
4381
+ * @category Utilities
4382
+ * @param {string} text The template text.
4383
+ * @param {Object} data The data object used to populate the text.
4384
+ * @param {Object} [options] The options object.
4385
+ * @param {RegExp} [options.escape] The "escape" delimiter.
4386
+ * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
4387
+ * @param {Object} [options.imports] An object to import into the template as local variables.
4388
+ * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
4389
+ * @param {string} [sourceURL] The sourceURL of the template's compiled source.
4390
+ * @param {string} [variable] The data object variable name.
4391
+ * @returns {Function|string} Returns a compiled function when no `data` object
4392
+ * is given, else it returns the interpolated text.
4393
+ * @example
4394
+ *
4395
+ * // using the "interpolate" delimiter to create a compiled template
4396
+ * var compiled = _.template('hello <%= name %>');
4397
+ * compiled({ 'name': 'fred' });
4398
+ * // => 'hello fred'
4399
+ *
4400
+ * // using the "escape" delimiter to escape HTML in data property values
4401
+ * _.template('<b><%- value %></b>', { 'value': '<script>' });
4402
+ * // => '<b>&lt;script&gt;</b>'
4403
+ *
4404
+ * // using the "evaluate" delimiter to generate HTML
4405
+ * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
4406
+ * _.template(list, { 'people': ['fred', 'barney'] });
4407
+ * // => '<li>fred</li><li>barney</li>'
4408
+ *
4409
+ * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
4410
+ * _.template('hello ${ name }', { 'name': 'pebbles' });
4411
+ * // => 'hello pebbles'
4412
+ *
4413
+ * // using the internal `print` function in "evaluate" delimiters
4414
+ * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
4415
+ * // => 'hello barney!'
4416
+ *
4417
+ * // using a custom template delimiters
4418
+ * _.templateSettings = {
4419
+ * 'interpolate': /{{([\s\S]+?)}}/g
4420
+ * };
4421
+ *
4422
+ * _.template('hello {{ name }}!', { 'name': 'mustache' });
4423
+ * // => 'hello mustache!'
4424
+ *
4425
+ * // using the `imports` option to import jQuery
4426
+ * var list = '<% $.each(people, function(name) { %><li><%- name %></li><% }); %>';
4427
+ * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { '$': jQuery } });
4428
+ * // => '<li>fred</li><li>barney</li>'
4429
+ *
4430
+ * // using the `sourceURL` option to specify a custom sourceURL for the template
4431
+ * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
4432
+ * compiled(data);
4433
+ * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
4434
+ *
4435
+ * // using the `variable` option to ensure a with-statement isn't used in the compiled template
4436
+ * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
4437
+ * compiled.source;
4438
+ * // => function(data) {
4439
+ * var __t, __p = '', __e = _.escape;
4440
+ * __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
4441
+ * return __p;
4442
+ * }
4443
+ *
4444
+ * // using the `source` property to inline compiled templates for meaningful
4445
+ * // line numbers in error messages and a stack trace
4446
+ * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
4447
+ * var JST = {\
4448
+ * "main": ' + _.template(mainText).source + '\
4449
+ * };\
4450
+ * ');
4451
+ */
4452
+ function template(text, data, options) {
4453
+ var _ = lodash,
4454
+ settings = _.templateSettings;
4455
+
4456
+ text = String(text || '');
4457
+ options = defaults({}, options, settings);
4458
+
4459
+ var index = 0,
4460
+ source = "__p += '",
4461
+ variable = options.variable;
4462
+
4463
+ var reDelimiters = RegExp(
4464
+ (options.escape || reNoMatch).source + '|' +
4465
+ (options.interpolate || reNoMatch).source + '|' +
4466
+ (options.evaluate || reNoMatch).source + '|$'
4467
+ , 'g');
4468
+
4469
+ text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) {
4470
+ source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
4471
+ if (escapeValue) {
4472
+ source += "' +\n_.escape(" + escapeValue + ") +\n'";
4473
+ }
4474
+ if (evaluateValue) {
4475
+ source += "';\n" + evaluateValue + ";\n__p += '";
4476
+ }
4477
+ if (interpolateValue) {
4478
+ source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
4479
+ }
4480
+ index = offset + match.length;
4481
+ return match;
4482
+ });
4483
+
4484
+ source += "';\n";
4485
+ if (!variable) {
4486
+ variable = 'obj';
4487
+ source = 'with (' + variable + ' || {}) {\n' + source + '\n}\n';
4488
+ }
4489
+ source = 'function(' + variable + ') {\n' +
4490
+ "var __t, __p = '', __j = Array.prototype.join;\n" +
4491
+ "function print() { __p += __j.call(arguments, '') }\n" +
4492
+ source +
4493
+ 'return __p\n}';
4494
+
4495
+ try {
4496
+ var result = Function('_', 'return ' + source)(_);
4497
+ } catch(e) {
4498
+ e.source = source;
4499
+ throw e;
4500
+ }
4501
+ if (data) {
4502
+ return result(data);
4503
+ }
4504
+ result.source = source;
4505
+ return result;
4506
+ }
4507
+
4508
+ /**
4509
+ * Executes the callback `n` times, returning an array of the results
4510
+ * of each callback execution. The callback is bound to `thisArg` and invoked
4511
+ * with one argument; (index).
4512
+ *
4513
+ * @static
4514
+ * @memberOf _
4515
+ * @category Utilities
4516
+ * @param {number} n The number of times to execute the callback.
4517
+ * @param {Function} callback The function called per iteration.
4518
+ * @param {*} [thisArg] The `this` binding of `callback`.
4519
+ * @returns {Array} Returns an array of the results of each `callback` execution.
4520
+ * @example
4521
+ *
4522
+ * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
4523
+ * // => [3, 6, 4]
4524
+ *
4525
+ * _.times(3, function(n) { mage.castSpell(n); });
4526
+ * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
4527
+ *
4528
+ * _.times(3, function(n) { this.cast(n); }, mage);
4529
+ * // => also calls `mage.castSpell(n)` three times
4530
+ */
4531
+ function times(n, callback, thisArg) {
4532
+ n = (n = +n) > -1 ? n : 0;
4533
+ var index = -1,
4534
+ result = Array(n);
4535
+
4536
+ callback = baseCreateCallback(callback, thisArg, 1);
4537
+ while (++index < n) {
4538
+ result[index] = callback(index);
4539
+ }
4540
+ return result;
4541
+ }
4542
+
4543
+ /**
4544
+ * The inverse of `_.escape` this method converts the HTML entities
4545
+ * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
4546
+ * corresponding characters.
4547
+ *
4548
+ * @static
4549
+ * @memberOf _
4550
+ * @category Utilities
4551
+ * @param {string} string The string to unescape.
4552
+ * @returns {string} Returns the unescaped string.
4553
+ * @example
4554
+ *
4555
+ * _.unescape('Fred, Barney &amp; Pebbles');
4556
+ * // => 'Fred, Barney & Pebbles'
4557
+ */
4558
+ function unescape(string) {
4559
+ return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
4560
+ }
4561
+
4562
+ /**
4563
+ * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
4564
+ *
4565
+ * @static
4566
+ * @memberOf _
4567
+ * @category Utilities
4568
+ * @param {string} [prefix] The value to prefix the ID with.
4569
+ * @returns {string} Returns the unique ID.
4570
+ * @example
4571
+ *
4572
+ * _.uniqueId('contact_');
4573
+ * // => 'contact_104'
4574
+ *
4575
+ * _.uniqueId();
4576
+ * // => '105'
4577
+ */
4578
+ function uniqueId(prefix) {
4579
+ var id = ++idCounter + '';
4580
+ return prefix ? prefix + id : id;
4581
+ }
4582
+
4583
+ /*--------------------------------------------------------------------------*/
4584
+
4585
+ /**
4586
+ * Creates a `lodash` object that wraps the given value with explicit
4587
+ * method chaining enabled.
4588
+ *
4589
+ * @static
4590
+ * @memberOf _
4591
+ * @category Chaining
4592
+ * @param {*} value The value to wrap.
4593
+ * @returns {Object} Returns the wrapper object.
4594
+ * @example
4595
+ *
4596
+ * var characters = [
4597
+ * { 'name': 'barney', 'age': 36 },
4598
+ * { 'name': 'fred', 'age': 40 },
4599
+ * { 'name': 'pebbles', 'age': 1 }
4600
+ * ];
4601
+ *
4602
+ * var youngest = _.chain(characters)
4603
+ * .sortBy('age')
4604
+ * .map(function(chr) { return chr.name + ' is ' + chr.age; })
4605
+ * .first()
4606
+ * .value();
4607
+ * // => 'pebbles is 1'
4608
+ */
4609
+ function chain(value) {
4610
+ value = new lodashWrapper(value);
4611
+ value.__chain__ = true;
4612
+ return value;
4613
+ }
4614
+
4615
+ /**
4616
+ * Invokes `interceptor` with the `value` as the first argument and then
4617
+ * returns `value`. The purpose of this method is to "tap into" a method
4618
+ * chain in order to perform operations on intermediate results within
4619
+ * the chain.
4620
+ *
4621
+ * @static
4622
+ * @memberOf _
4623
+ * @category Chaining
4624
+ * @param {*} value The value to provide to `interceptor`.
4625
+ * @param {Function} interceptor The function to invoke.
4626
+ * @returns {*} Returns `value`.
4627
+ * @example
4628
+ *
4629
+ * _([1, 2, 3, 4])
4630
+ * .tap(function(array) { array.pop(); })
4631
+ * .reverse()
4632
+ * .value();
4633
+ * // => [3, 2, 1]
4634
+ */
4635
+ function tap(value, interceptor) {
4636
+ interceptor(value);
4637
+ return value;
4638
+ }
4639
+
4640
+ /**
4641
+ * Enables explicit method chaining on the wrapper object.
4642
+ *
4643
+ * @name chain
4644
+ * @memberOf _
4645
+ * @category Chaining
4646
+ * @returns {*} Returns the wrapper object.
4647
+ * @example
4648
+ *
4649
+ * var characters = [
4650
+ * { 'name': 'barney', 'age': 36 },
4651
+ * { 'name': 'fred', 'age': 40 }
4652
+ * ];
4653
+ *
4654
+ * // without explicit chaining
4655
+ * _(characters).first();
4656
+ * // => { 'name': 'barney', 'age': 36 }
4657
+ *
4658
+ * // with explicit chaining
4659
+ * _(characters).chain()
4660
+ * .first()
4661
+ * .pick('age')
4662
+ * .value()
4663
+ * // => { 'age': 36 }
4664
+ */
4665
+ function wrapperChain() {
4666
+ this.__chain__ = true;
4667
+ return this;
4668
+ }
4669
+
4670
+ /**
4671
+ * Extracts the wrapped value.
4672
+ *
4673
+ * @name valueOf
4674
+ * @memberOf _
4675
+ * @alias value
4676
+ * @category Chaining
4677
+ * @returns {*} Returns the wrapped value.
4678
+ * @example
4679
+ *
4680
+ * _([1, 2, 3]).valueOf();
4681
+ * // => [1, 2, 3]
4682
+ */
4683
+ function wrapperValueOf() {
4684
+ return this.__wrapped__;
4685
+ }
4686
+
4687
+ /*--------------------------------------------------------------------------*/
4688
+
4689
+ // add functions that return wrapped values when chaining
4690
+ lodash.after = after;
4691
+ lodash.bind = bind;
4692
+ lodash.bindAll = bindAll;
4693
+ lodash.chain = chain;
4694
+ lodash.compact = compact;
4695
+ lodash.compose = compose;
4696
+ lodash.countBy = countBy;
4697
+ lodash.debounce = debounce;
4698
+ lodash.defaults = defaults;
4699
+ lodash.defer = defer;
4700
+ lodash.delay = delay;
4701
+ lodash.difference = difference;
4702
+ lodash.filter = filter;
4703
+ lodash.flatten = flatten;
4704
+ lodash.forEach = forEach;
4705
+ lodash.functions = functions;
4706
+ lodash.groupBy = groupBy;
4707
+ lodash.indexBy = indexBy;
4708
+ lodash.initial = initial;
4709
+ lodash.intersection = intersection;
4710
+ lodash.invert = invert;
4711
+ lodash.invoke = invoke;
4712
+ lodash.keys = keys;
4713
+ lodash.map = map;
4714
+ lodash.max = max;
4715
+ lodash.memoize = memoize;
4716
+ lodash.min = min;
4717
+ lodash.omit = omit;
4718
+ lodash.once = once;
4719
+ lodash.pairs = pairs;
4720
+ lodash.partial = partial;
4721
+ lodash.pick = pick;
4722
+ lodash.pluck = pluck;
4723
+ lodash.range = range;
4724
+ lodash.reject = reject;
4725
+ lodash.rest = rest;
4726
+ lodash.shuffle = shuffle;
4727
+ lodash.sortBy = sortBy;
4728
+ lodash.tap = tap;
4729
+ lodash.throttle = throttle;
4730
+ lodash.times = times;
4731
+ lodash.toArray = toArray;
4732
+ lodash.union = union;
4733
+ lodash.uniq = uniq;
4734
+ lodash.values = values;
4735
+ lodash.where = where;
4736
+ lodash.without = without;
4737
+ lodash.wrap = wrap;
4738
+ lodash.zip = zip;
4739
+
4740
+ // add aliases
4741
+ lodash.collect = map;
4742
+ lodash.drop = rest;
4743
+ lodash.each = forEach;
4744
+ lodash.extend = assign;
4745
+ lodash.methods = functions;
4746
+ lodash.object = zipObject;
4747
+ lodash.select = filter;
4748
+ lodash.tail = rest;
4749
+ lodash.unique = uniq;
4750
+
4751
+ /*--------------------------------------------------------------------------*/
4752
+
4753
+ // add functions that return unwrapped values when chaining
4754
+ lodash.clone = clone;
4755
+ lodash.contains = contains;
4756
+ lodash.escape = escape;
4757
+ lodash.every = every;
4758
+ lodash.find = find;
4759
+ lodash.has = has;
4760
+ lodash.identity = identity;
4761
+ lodash.indexOf = indexOf;
4762
+ lodash.isArguments = isArguments;
4763
+ lodash.isArray = isArray;
4764
+ lodash.isBoolean = isBoolean;
4765
+ lodash.isDate = isDate;
4766
+ lodash.isElement = isElement;
4767
+ lodash.isEmpty = isEmpty;
4768
+ lodash.isEqual = isEqual;
4769
+ lodash.isFinite = isFinite;
4770
+ lodash.isFunction = isFunction;
4771
+ lodash.isNaN = isNaN;
4772
+ lodash.isNull = isNull;
4773
+ lodash.isNumber = isNumber;
4774
+ lodash.isObject = isObject;
4775
+ lodash.isRegExp = isRegExp;
4776
+ lodash.isString = isString;
4777
+ lodash.isUndefined = isUndefined;
4778
+ lodash.lastIndexOf = lastIndexOf;
4779
+ lodash.mixin = mixin;
4780
+ lodash.noConflict = noConflict;
4781
+ lodash.random = random;
4782
+ lodash.reduce = reduce;
4783
+ lodash.reduceRight = reduceRight;
4784
+ lodash.result = result;
4785
+ lodash.size = size;
4786
+ lodash.some = some;
4787
+ lodash.sortedIndex = sortedIndex;
4788
+ lodash.template = template;
4789
+ lodash.unescape = unescape;
4790
+ lodash.uniqueId = uniqueId;
4791
+
4792
+ // add aliases
4793
+ lodash.all = every;
4794
+ lodash.any = some;
4795
+ lodash.detect = find;
4796
+ lodash.findWhere = findWhere;
4797
+ lodash.foldl = reduce;
4798
+ lodash.foldr = reduceRight;
4799
+ lodash.include = contains;
4800
+ lodash.inject = reduce;
4801
+
4802
+ /*--------------------------------------------------------------------------*/
4803
+
4804
+ // add functions capable of returning wrapped and unwrapped values when chaining
4805
+ lodash.first = first;
4806
+ lodash.last = last;
4807
+ lodash.sample = sample;
4808
+
4809
+ // add aliases
4810
+ lodash.take = first;
4811
+ lodash.head = first;
4812
+
4813
+ /*--------------------------------------------------------------------------*/
4814
+
4815
+ // add functions to `lodash.prototype`
4816
+ mixin(lodash);
4817
+
4818
+ /**
4819
+ * The semantic version number.
4820
+ *
4821
+ * @static
4822
+ * @memberOf _
4823
+ * @type string
4824
+ */
4825
+ lodash.VERSION = '2.3.0';
4826
+
4827
+ // add "Chaining" functions to the wrapper
4828
+ lodash.prototype.chain = wrapperChain;
4829
+ lodash.prototype.value = wrapperValueOf;
4830
+
4831
+ // add `Array` mutator functions to the wrapper
4832
+ forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
4833
+ var func = arrayRef[methodName];
4834
+ lodash.prototype[methodName] = function() {
4835
+ var value = this.__wrapped__;
4836
+ func.apply(value, arguments);
4837
+
4838
+ // avoid array-like object bugs with `Array#shift` and `Array#splice`
4839
+ // in Firefox < 10 and IE < 9
4840
+ if (!support.spliceObjects && value.length === 0) {
4841
+ delete value[0];
4842
+ }
4843
+ return this;
4844
+ };
4845
+ });
4846
+
4847
+ // add `Array` accessor functions to the wrapper
4848
+ forEach(['concat', 'join', 'slice'], function(methodName) {
4849
+ var func = arrayRef[methodName];
4850
+ lodash.prototype[methodName] = function() {
4851
+ var value = this.__wrapped__,
4852
+ result = func.apply(value, arguments);
4853
+
4854
+ if (this.__chain__) {
4855
+ result = new lodashWrapper(result);
4856
+ result.__chain__ = true;
4857
+ }
4858
+ return result;
4859
+ };
4860
+ });
4861
+
4862
+ /*--------------------------------------------------------------------------*/
4863
+
4864
+ // some AMD build optimizers like r.js check for condition patterns like the following:
4865
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
4866
+ // Expose Lo-Dash to the global object even when an AMD loader is present in
4867
+ // case Lo-Dash was injected by a third-party script and not intended to be
4868
+ // loaded as a module. The global assignment can be reverted in the Lo-Dash
4869
+ // module by its `noConflict()` method.
4870
+ root._ = lodash;
4871
+
4872
+ // define as an anonymous module so, through path mapping, it can be
4873
+ // referenced as the "underscore" module
4874
+ define(function() {
4875
+ return lodash;
4876
+ });
4877
+ }
4878
+ // check for `exports` after `define` in case a build optimizer adds an `exports` object
4879
+ else if (freeExports && freeModule) {
4880
+ // in Node.js or RingoJS
4881
+ if (moduleExports) {
4882
+ (freeModule.exports = lodash)._ = lodash;
4883
+ }
4884
+ // in Narwhal or Rhino -require
4885
+ else {
4886
+ freeExports._ = lodash;
4887
+ }
4888
+ }
4889
+ else {
4890
+ // in a browser or Rhino
4891
+ root._ = lodash;
4892
+ }
4893
+ }.call(this));