faalis 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +339 -0
  3. data/README.md +45 -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/images/faalis/select2-spinner.gif +0 -0
  18. data/app/assets/images/faalis/select2.png +0 -0
  19. data/app/assets/images/faalis/select2x2.png +0 -0
  20. data/app/assets/javascripts/faalis/application.js +20 -0
  21. data/app/assets/javascripts/faalis/dashboard/angular.js +9 -0
  22. data/app/assets/javascripts/faalis/dashboard/app.js +75 -0
  23. data/app/assets/javascripts/faalis/dashboard/application.js.erb +21 -0
  24. data/app/assets/javascripts/faalis/dashboard/functions.js.erb +91 -0
  25. data/app/assets/javascripts/faalis/dashboard/init.js +38 -0
  26. data/app/assets/javascripts/faalis/dashboard/lib/angular-animate.js +1226 -0
  27. data/app/assets/javascripts/faalis/dashboard/lib/angular-gettext.js +202 -0
  28. data/app/assets/javascripts/faalis/dashboard/lib/angular-resource.js +578 -0
  29. data/app/assets/javascripts/faalis/dashboard/lib/angular-route.js +880 -0
  30. data/app/assets/javascripts/faalis/dashboard/lib/angular.js +20031 -0
  31. data/app/assets/javascripts/faalis/dashboard/lib/lodash.underscore.js +4893 -0
  32. data/app/assets/javascripts/faalis/dashboard/lib/ng-grid.js +3260 -0
  33. data/app/assets/javascripts/faalis/dashboard/lib/ng-quick-date.js +297 -0
  34. data/app/assets/javascripts/faalis/dashboard/lib/restangular.js +1066 -0
  35. data/app/assets/javascripts/faalis/dashboard/lib/select2.js +3255 -0
  36. data/app/assets/javascripts/faalis/dashboard/lib/ui.select2.js +217 -0
  37. data/app/assets/javascripts/faalis/dashboard/locale/translations.js +5 -0
  38. data/app/assets/javascripts/faalis/dashboard/modules/anim.js +32 -0
  39. data/app/assets/javascripts/faalis/dashboard/modules/api.js +32 -0
  40. data/app/assets/javascripts/faalis/dashboard/modules/auth/auth.js +34 -0
  41. data/app/assets/javascripts/faalis/dashboard/modules/auth/group.js +174 -0
  42. data/app/assets/javascripts/faalis/dashboard/modules/auth/profile.js +59 -0
  43. data/app/assets/javascripts/faalis/dashboard/modules/auth/user.js +123 -0
  44. data/app/assets/javascripts/faalis/dashboard/modules/errors.js +47 -0
  45. data/app/assets/javascripts/faalis/dashboard/modules/filter.js +44 -0
  46. data/app/assets/javascripts/faalis/dashboard/modules/list-view.js +310 -0
  47. data/app/assets/javascripts/faalis/dashboard/modules/logs.js +41 -0
  48. data/app/assets/javascripts/faalis/dashboard/modules/modules.js +50 -0
  49. data/app/assets/javascripts/faalis/dashboard/modules/nav.js.erb +97 -0
  50. data/app/assets/javascripts/faalis/dashboard/templates/application.handlebars.erb +42 -0
  51. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/details.handlebars.erb +15 -0
  52. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/index.handlebars.erb +7 -0
  53. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/new.handlebars.erb +39 -0
  54. data/app/assets/javascripts/faalis/dashboard/templates/auth/index.handlebars.erb +31 -0
  55. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/details.handlebars.erb +15 -0
  56. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/index.handlebars.erb +11 -0
  57. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/new.handlebars.erb +33 -0
  58. data/app/assets/javascripts/faalis/dashboard/templates/components/list-view.handlebars.erb +59 -0
  59. data/app/assets/javascripts/faalis/dashboard/templates/components/model-form.handlebars.erb +3 -0
  60. data/app/assets/javascripts/faalis/dashboard/templates/modules.handlebars.erb +15 -0
  61. data/app/assets/javascripts/faalis/dashboard/templates/navigation.handlebars.erb +43 -0
  62. data/app/assets/javascripts/faalis/dashboard/templates/widgets.handlebars +23 -0
  63. data/app/assets/javascripts/faalis/dashboard/variables.js.erb +17 -0
  64. data/app/assets/javascripts/faalis/groups.js +2 -0
  65. data/app/assets/javascripts/faalis/home.js +2 -0
  66. data/app/assets/javascripts/faalis/i18n.js +13 -0
  67. data/app/assets/javascripts/faalis/locale/en.json +27 -0
  68. data/app/assets/javascripts/faalis/locale/fa.json +27 -0
  69. data/app/assets/javascripts/faalis/users.js +2 -0
  70. data/app/assets/stylesheets/faalis/base.css.scss +264 -0
  71. data/app/assets/stylesheets/faalis/dashboard/dashboard.css.scss +226 -0
  72. data/app/assets/stylesheets/faalis/dashboard/list_view.css.scss +169 -0
  73. data/app/assets/stylesheets/faalis/dashboard/ltr/application.css +26 -0
  74. data/app/assets/stylesheets/faalis/dashboard/ltr/base.css.scss.erb +28 -0
  75. data/app/assets/stylesheets/faalis/dashboard/ltr/buttons.css.scss.erb +48 -0
  76. data/app/assets/stylesheets/faalis/dashboard/ltr/direction.css.scss +38 -0
  77. data/app/assets/stylesheets/faalis/dashboard/ltr/foundation_and_overrides.css.scss +1014 -0
  78. data/app/assets/stylesheets/faalis/dashboard/ng-grid.css.scss +442 -0
  79. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date-default-theme.css.scss +20 -0
  80. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date.css.scss +19 -0
  81. data/app/assets/stylesheets/faalis/dashboard/rtl/application.css +26 -0
  82. data/app/assets/stylesheets/faalis/dashboard/rtl/base.css.scss.erb +31 -0
  83. data/app/assets/stylesheets/faalis/dashboard/rtl/base.css_flymake.scss +25 -0
  84. data/app/assets/stylesheets/faalis/dashboard/rtl/buttons.css.scss.erb +45 -0
  85. data/app/assets/stylesheets/faalis/dashboard/rtl/direction.css.scss +37 -0
  86. data/app/assets/stylesheets/faalis/dashboard/rtl/foundation_and_overrides.css.scss +1014 -0
  87. data/app/assets/stylesheets/faalis/dashboard/select2.css.scss.erb +618 -0
  88. data/app/assets/stylesheets/faalis/dashboard/sidebar.css.scss +93 -0
  89. data/app/assets/stylesheets/faalis/devise.css.scss +34 -0
  90. data/app/assets/stylesheets/faalis/groups.css +4 -0
  91. data/app/assets/stylesheets/faalis/home.css.scss +14 -0
  92. data/app/assets/stylesheets/faalis/ltr/application.css +20 -0
  93. data/app/assets/stylesheets/faalis/ltr/buttons.css.scss.erb +48 -0
  94. data/app/assets/stylesheets/faalis/ltr/foundation_and_overrides.scss.erb +1012 -0
  95. data/app/assets/stylesheets/faalis/mixins.css.scss +15 -0
  96. data/app/assets/stylesheets/faalis/rtl/application.css +20 -0
  97. data/app/assets/stylesheets/faalis/rtl/buttons.css.scss.erb +48 -0
  98. data/app/assets/stylesheets/faalis/rtl/foundation_and_overrides.scss.erb +1012 -0
  99. data/app/assets/stylesheets/faalis/users.css +4 -0
  100. data/app/assets/stylesheets/faalis/variables.css.scss +102 -0
  101. data/app/controllers/faalis/api/v1/groups_controller.rb +75 -0
  102. data/app/controllers/faalis/api/v1/logs_controller.rb +12 -0
  103. data/app/controllers/faalis/api/v1/permissions_controller.rb +17 -0
  104. data/app/controllers/faalis/api/v1/profiles_controller.rb +42 -0
  105. data/app/controllers/faalis/api/v1/users_controller.rb +75 -0
  106. data/app/controllers/faalis/api_controller.rb +51 -0
  107. data/app/controllers/faalis/application_controller.rb +34 -0
  108. data/app/controllers/faalis/dashboard_controller.rb +44 -0
  109. data/app/controllers/faalis/home_controller.rb +19 -0
  110. data/app/controllers/faalis/omniauth/callbacks_controller.rb +43 -0
  111. data/app/helpers/faalis/application_helper.rb +4 -0
  112. data/app/helpers/faalis/dashboard_helper.rb +5 -0
  113. data/app/helpers/faalis/groups_helper.rb +4 -0
  114. data/app/helpers/faalis/home_helper.rb +4 -0
  115. data/app/helpers/faalis/users_helper.rb +4 -0
  116. data/app/models/ability.rb +42 -0
  117. data/app/models/faalis/group.rb +27 -0
  118. data/app/models/faalis/permission.rb +15 -0
  119. data/app/models/faalis/user.rb +81 -0
  120. data/app/views/angularjs_templates/#index.html# +8 -0
  121. data/app/views/angularjs_templates/auth/groups/details.html +21 -0
  122. data/app/views/angularjs_templates/auth/groups/index.html +5 -0
  123. data/app/views/angularjs_templates/auth/groups/new.html +41 -0
  124. data/app/views/angularjs_templates/auth/index.html +30 -0
  125. data/app/views/angularjs_templates/auth/profile/edit.html +54 -0
  126. data/app/views/angularjs_templates/auth/users/details.html +28 -0
  127. data/app/views/angularjs_templates/auth/users/index.html +6 -0
  128. data/app/views/angularjs_templates/auth/users/new.html +56 -0
  129. data/app/views/angularjs_templates/filter/index.html +15 -0
  130. data/app/views/angularjs_templates/index.html +8 -0
  131. data/app/views/angularjs_templates/list-view/index.html +81 -0
  132. data/app/views/angularjs_templates/locale/fa.po +25 -0
  133. data/app/views/angularjs_templates/locale/templates.pot +24 -0
  134. data/app/views/angularjs_templates/logs/index.html +6 -0
  135. data/app/views/angularjs_templates/modules.html +17 -0
  136. data/app/views/angularjs_templates/nav.html.erb +38 -0
  137. data/app/views/devise/confirmations/new.html.erb +34 -0
  138. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  139. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  140. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  141. data/app/views/devise/passwords/edit.html.erb +44 -0
  142. data/app/views/devise/passwords/new.html.erb +32 -0
  143. data/app/views/devise/registrations/edit.html.erb +29 -0
  144. data/app/views/devise/registrations/new.html.erb +91 -0
  145. data/app/views/devise/sessions/new.html.erb +98 -0
  146. data/app/views/devise/shared/_links.erb +25 -0
  147. data/app/views/devise/unlocks/new.html.erb +30 -0
  148. data/app/views/faalis/api/v1/groups/create.json.jbuilder +4 -0
  149. data/app/views/faalis/api/v1/groups/destroy.html.erb +2 -0
  150. data/app/views/faalis/api/v1/groups/destroy.json.jbuilder +1 -0
  151. data/app/views/faalis/api/v1/groups/edit.html.erb +2 -0
  152. data/app/views/faalis/api/v1/groups/index.html.erb +2 -0
  153. data/app/views/faalis/api/v1/groups/index.json.jbuilder +6 -0
  154. data/app/views/faalis/api/v1/groups/new.html.erb +2 -0
  155. data/app/views/faalis/api/v1/groups/show.html.erb +2 -0
  156. data/app/views/faalis/api/v1/groups/show.json.jbuilder +5 -0
  157. data/app/views/faalis/api/v1/groups/update.json.jbuilder +4 -0
  158. data/app/views/faalis/api/v1/logs/index.json.jbuilder +1 -0
  159. data/app/views/faalis/api/v1/permissions/index.json.jbuilder +1 -0
  160. data/app/views/faalis/api/v1/users/create.html.erb +2 -0
  161. data/app/views/faalis/api/v1/users/create.json.jbuilder +1 -0
  162. data/app/views/faalis/api/v1/users/destroy.json.jbuilder +1 -0
  163. data/app/views/faalis/api/v1/users/distroy.html.erb +2 -0
  164. data/app/views/faalis/api/v1/users/edit.html.erb +2 -0
  165. data/app/views/faalis/api/v1/users/index.html.erb +2 -0
  166. data/app/views/faalis/api/v1/users/index.json.jbuilder +4 -0
  167. data/app/views/faalis/api/v1/users/show.html.erb +2 -0
  168. data/app/views/faalis/api/v1/users/show.json.jbuilder +2 -0
  169. data/app/views/faalis/api/v1/users/update.json.jbuilder +1 -0
  170. data/app/views/faalis/dashboard/index.html.erb +37 -0
  171. data/app/views/faalis/dashboard/login_required_page.html.erb +5 -0
  172. data/app/views/faalis/home/index.html.erb +119 -0
  173. data/app/views/layouts/faalis/application.html.erb +90 -0
  174. data/app/views/layouts/faalis/dashboard.html.erb +21 -0
  175. data/config/initializers/devise.rb +28 -0
  176. data/config/locales/devise.en.yml +59 -0
  177. data/config/locales/devise.fa.yml +56 -0
  178. data/config/locales/fa/LC_MESSAGES/faalis.mo +0 -0
  179. data/config/locales/fa/faalis.po +181 -0
  180. data/config/locales/fa/messages.mo +0 -0
  181. data/config/locales/faalis.pot +181 -0
  182. data/config/routes.rb +36 -0
  183. data/db/migrate/20131013091000_devise_create_red_base_users.rb +64 -0
  184. data/db/migrate/20131020124701_create_red_base_groups.rb +9 -0
  185. data/db/migrate/20131021170923_create_red_base_permissions.rb +10 -0
  186. data/db/migrate/20131123120422_add_permissions_groups_table.rb +8 -0
  187. data/db/seeds.rb +15 -0
  188. data/lib/faalis.rb +30 -0
  189. data/lib/faalis/active_record.rb +64 -0
  190. data/lib/faalis/api.rb +61 -0
  191. data/lib/faalis/api/groups_api.rb +41 -0
  192. data/lib/faalis/api/permissions_api.rb +24 -0
  193. data/lib/faalis/api/root.rb +15 -0
  194. data/lib/faalis/api/users_api.rb +20 -0
  195. data/lib/faalis/cucumber.rb +25 -0
  196. data/lib/faalis/cucumber/auth.rb +45 -0
  197. data/lib/faalis/cucumber/exceptions.rb +40 -0
  198. data/lib/faalis/cucumber/interaction.rb +43 -0
  199. data/lib/faalis/cucumber/query.rb +28 -0
  200. data/lib/faalis/cucumber/urls.rb +76 -0
  201. data/lib/faalis/dashboard.rb +60 -0
  202. data/lib/faalis/dashboard/controller.rb +42 -0
  203. data/lib/faalis/dashboard/module.rb +45 -0
  204. data/lib/faalis/engine.rb +128 -0
  205. data/lib/faalis/exceptions.rb +26 -0
  206. data/lib/faalis/i18n.rb +35 -0
  207. data/lib/faalis/initialize.rb +7 -0
  208. data/lib/faalis/omniauth.rb +24 -0
  209. data/lib/faalis/omniauth/callbacks.rb +58 -0
  210. data/lib/faalis/plugins.rb +44 -0
  211. data/lib/faalis/version.rb +22 -0
  212. data/lib/faalis_plugin.rb +476 -0
  213. data/lib/generators/faalis/USAGE +8 -0
  214. data/lib/generators/faalis/angularjs_resource_generator.rb +74 -0
  215. data/lib/generators/faalis/install_all_generator.rb +38 -0
  216. data/lib/generators/faalis/install_generator.rb +42 -0
  217. data/lib/generators/faalis/install_specs_generator.rb +48 -0
  218. data/lib/generators/faalis/js_scaffold_generator.rb +273 -0
  219. data/lib/generators/faalis/templates/README +41 -0
  220. data/lib/generators/faalis/templates/SPECS +13 -0
  221. data/lib/generators/faalis/templates/angularjs/details.html.erb +20 -0
  222. data/lib/generators/faalis/templates/angularjs/index.html.erb +62 -0
  223. data/lib/generators/faalis/templates/angularjs/module.js.erb +309 -0
  224. data/lib/generators/faalis/templates/angularjs/new.html.erb +105 -0
  225. data/lib/generators/faalis/templates/api/controller.rb.erb +56 -0
  226. data/lib/generators/faalis/templates/devise.rb +251 -0
  227. data/lib/generators/faalis/templates/faalis.rb +14 -0
  228. data/lib/generators/faalis/templates/fast_gettext.rb +4 -0
  229. data/lib/generators/faalis/templates/features/api.feature +92 -0
  230. data/lib/generators/faalis/templates/features/api.step.rb +7 -0
  231. data/lib/generators/faalis/templates/features/step_definitions/email_steps.rb +206 -0
  232. data/lib/generators/faalis/templates/features/support/email_spec.rb +1 -0
  233. data/lib/generators/faalis/templates/features/support/env.rb +79 -0
  234. data/lib/generators/faalis/templates/formtastic.rb +76 -0
  235. data/lib/generators/faalis/templates/js_scaffold.README +25 -0
  236. data/lib/generators/faalis/templates/seeds.rb +1 -0
  237. data/lib/generators/faalis/templates/spec/factories/groups.rb +5 -0
  238. data/lib/generators/faalis/templates/spec/factories/users.rb +10 -0
  239. data/lib/generators/faalis/templates/spec/spec_helper.rb +69 -0
  240. data/lib/generators/faalis/templates/spec/support/devise.rb +3 -0
  241. data/lib/generators/faalis/templates/views/create.json.jbuilder.erb +2 -0
  242. data/lib/generators/faalis/templates/views/destroy.json.jbuilder.erb +1 -0
  243. data/lib/generators/faalis/templates/views/index.json.jbuilder.erb +10 -0
  244. data/lib/generators/faalis/templates/views/show.json.jbuilder.erb +7 -0
  245. data/lib/generators/faalis/templates/views/update.json.jbuilder.erb +6 -0
  246. data/lib/generators/faalis/views_generator.rb +41 -0
  247. data/lib/tasks/faalis_tasks.rake +23 -0
  248. data/lib/tasks/grunt/Gruntfile.js +25 -0
  249. data/spec/dummy/README.rdoc +28 -0
  250. data/spec/dummy/Rakefile +6 -0
  251. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  252. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  253. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  254. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  255. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  256. data/spec/dummy/bin/bundle +3 -0
  257. data/spec/dummy/bin/rails +4 -0
  258. data/spec/dummy/bin/rake +4 -0
  259. data/spec/dummy/config.ru +4 -0
  260. data/spec/dummy/config/application.rb +23 -0
  261. data/spec/dummy/config/boot.rb +5 -0
  262. data/spec/dummy/config/database.yml +25 -0
  263. data/spec/dummy/config/environment.rb +5 -0
  264. data/spec/dummy/config/environments/development.rb +29 -0
  265. data/spec/dummy/config/environments/production.rb +80 -0
  266. data/spec/dummy/config/environments/test.rb +36 -0
  267. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  268. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  269. data/spec/dummy/config/initializers/inflections.rb +16 -0
  270. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  271. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  272. data/spec/dummy/config/initializers/session_store.rb +3 -0
  273. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  274. data/spec/dummy/config/locales/en.yml +23 -0
  275. data/spec/dummy/config/routes.rb +4 -0
  276. data/spec/dummy/db/test.sqlite3 +0 -0
  277. data/spec/dummy/log/development.log +0 -0
  278. data/spec/dummy/log/test.log +15 -0
  279. data/spec/dummy/public/404.html +58 -0
  280. data/spec/dummy/public/422.html +58 -0
  281. data/spec/dummy/public/500.html +57 -0
  282. data/spec/dummy/public/favicon.ico +0 -0
  283. data/spec/dummy/tmp/ember-rails/ember-data.js +10204 -0
  284. data/spec/dummy/tmp/ember-rails/ember.js +36991 -0
  285. data/spec/spec_helper.rb +52 -0
  286. metadata +678 -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));