spree_backend 2.4.10 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (405) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree/backend/adjustments.js.coffee +1 -2
  3. data/app/assets/javascripts/spree/backend/admin.js.erb +136 -53
  4. data/app/assets/javascripts/spree/backend/checkouts/edit.js +1 -4
  5. data/app/assets/javascripts/spree/backend/index.html +15 -0
  6. data/app/assets/javascripts/spree/backend/line_items.js.coffee +1 -4
  7. data/app/assets/javascripts/spree/backend/line_items_on_order_edit.js.erb +3 -16
  8. data/app/assets/javascripts/spree/backend/option_type_autocomplete.js.erb +2 -4
  9. data/app/assets/javascripts/spree/backend/option_value_picker.js +44 -0
  10. data/app/assets/javascripts/spree/backend/orders/edit_form.js +2 -3
  11. data/app/assets/javascripts/spree/backend/payments/edit.js.coffee +8 -12
  12. data/app/assets/javascripts/spree/backend/product_picker.js +10 -8
  13. data/app/assets/javascripts/spree/backend/progress.coffee +0 -21
  14. data/app/assets/javascripts/spree/backend/promotions.js +50 -1
  15. data/app/assets/javascripts/spree/backend/select_payments.js.coffee +7 -0
  16. data/app/assets/javascripts/spree/backend/shipments.js.erb +10 -41
  17. data/app/assets/javascripts/spree/backend/spree-select2.js.erb +0 -15
  18. data/app/assets/javascripts/spree/backend/states.js +3 -3
  19. data/app/assets/javascripts/spree/backend/stock_movement.js.coffee +1 -2
  20. data/app/assets/javascripts/spree/backend/stock_transfer.js.coffee +3 -2
  21. data/app/assets/javascripts/spree/backend/taxon_autocomplete.js.erb +2 -4
  22. data/app/assets/javascripts/spree/backend/taxon_tree_menu.js.coffee +4 -4
  23. data/app/assets/javascripts/spree/backend/taxonomy.js.coffee +15 -34
  24. data/app/assets/javascripts/spree/backend/taxons.js.coffee +27 -8
  25. data/app/assets/javascripts/spree/backend/user_picker.js +2 -3
  26. data/app/assets/javascripts/spree/backend/variant_autocomplete.js.coffee.erb +1 -2
  27. data/app/assets/javascripts/spree/backend/variant_management.js.coffee +1 -2
  28. data/app/assets/javascripts/spree/backend.js +13 -15
  29. data/app/assets/stylesheets/spree/backend/components/_buttons.scss +37 -0
  30. data/app/assets/stylesheets/spree/backend/components/_filters.scss +25 -0
  31. data/app/assets/stylesheets/spree/backend/components/_icons.scss +257 -0
  32. data/app/assets/stylesheets/spree/backend/components/_labels.scss +49 -0
  33. data/app/assets/stylesheets/spree/backend/components/_main.scss +5 -0
  34. data/app/assets/stylesheets/spree/backend/components/_navigation.scss +10 -165
  35. data/app/assets/stylesheets/spree/backend/components/_page_header.scss +17 -0
  36. data/app/assets/stylesheets/spree/backend/components/_panels.scss +3 -0
  37. data/app/assets/stylesheets/spree/backend/components/_sidebar.scss +116 -20
  38. data/app/assets/stylesheets/spree/backend/components/_tables.scss +51 -0
  39. data/app/assets/stylesheets/spree/backend/components/_taxon_products_view.scss +70 -0
  40. data/app/assets/stylesheets/spree/backend/components/_variables.scss +12 -0
  41. data/app/assets/stylesheets/spree/backend/components/_wells.scss +3 -0
  42. data/app/assets/stylesheets/spree/backend/global/_variables.scss +37 -0
  43. data/app/assets/stylesheets/spree/backend/plugins/_jquery_ui.scss +109 -0
  44. data/app/{views/spree/admin/payments/source_forms/_check.html.erb → assets/stylesheets/spree/backend/plugins/_js_tree.scss} +0 -0
  45. data/app/assets/stylesheets/spree/backend/plugins/_select2.scss +84 -155
  46. data/app/assets/stylesheets/spree/backend/sections/_account.scss +16 -0
  47. data/app/assets/stylesheets/spree/backend/shared/_base.scss +15 -0
  48. data/app/assets/stylesheets/spree/backend/shared/_forms.scss +25 -287
  49. data/app/assets/stylesheets/spree/backend/shared/_typography.scss +5 -138
  50. data/app/assets/stylesheets/spree/backend/spree_admin.css.scss +26 -0
  51. data/app/assets/stylesheets/spree/backend.css +1 -7
  52. data/app/controllers/spree/admin/base_controller.rb +0 -2
  53. data/app/controllers/spree/admin/customer_returns_controller.rb +1 -1
  54. data/app/controllers/spree/admin/general_settings_controller.rb +5 -12
  55. data/app/controllers/spree/admin/images_controller.rb +33 -17
  56. data/app/controllers/spree/admin/log_entries_controller.rb +2 -2
  57. data/app/controllers/spree/admin/option_types_controller.rb +5 -3
  58. data/app/controllers/spree/admin/orders/customer_details_controller.rb +8 -8
  59. data/app/controllers/spree/admin/orders_controller.rb +4 -5
  60. data/app/controllers/spree/admin/payments_controller.rb +3 -3
  61. data/app/controllers/spree/admin/products_controller.rb +3 -6
  62. data/app/controllers/spree/admin/resource_controller.rb +1 -1
  63. data/app/controllers/spree/admin/root_controller.rb +1 -0
  64. data/app/controllers/spree/admin/search_controller.rb +12 -0
  65. data/app/controllers/spree/admin/state_changes_controller.rb +18 -0
  66. data/app/controllers/spree/admin/stock_locations_controller.rb +4 -13
  67. data/app/controllers/spree/admin/stock_transfers_controller.rb +6 -6
  68. data/app/controllers/spree/admin/tax_categories_controller.rb +0 -13
  69. data/app/controllers/spree/admin/taxonomies_controller.rb +1 -1
  70. data/app/controllers/spree/admin/taxons_controller.rb +53 -36
  71. data/app/controllers/spree/admin/users_controller.rb +44 -41
  72. data/app/controllers/spree/admin/variants_controller.rb +1 -1
  73. data/app/helpers/spree/admin/adjustments_helper.rb +0 -5
  74. data/app/helpers/spree/admin/base_helper.rb +41 -71
  75. data/app/helpers/spree/admin/navigation_helper.rb +96 -28
  76. data/app/helpers/spree/admin/orders_helper.rb +2 -2
  77. data/app/views/kaminari/_first_page.html.erb +11 -0
  78. data/app/views/kaminari/_gap.html.erb +8 -0
  79. data/app/views/kaminari/_last_page.html.erb +11 -0
  80. data/app/views/kaminari/_next_page.html.erb +15 -0
  81. data/app/views/kaminari/_page.html.erb +12 -0
  82. data/app/views/kaminari/_paginator.html.erb +21 -0
  83. data/app/views/kaminari/_prev_page.html.erb +15 -0
  84. data/app/views/spree/admin/adjustments/_adjustment.html.erb +10 -9
  85. data/app/views/spree/admin/adjustments/_adjustments_table.html.erb +19 -15
  86. data/app/views/spree/admin/adjustments/_form.html.erb +11 -15
  87. data/app/views/spree/admin/adjustments/edit.html.erb +9 -12
  88. data/app/views/spree/admin/adjustments/index.html.erb +19 -7
  89. data/app/views/spree/admin/adjustments/new.html.erb +7 -11
  90. data/app/views/spree/admin/countries/_form.html.erb +15 -19
  91. data/app/views/spree/admin/countries/edit.html.erb +4 -12
  92. data/app/views/spree/admin/countries/index.html.erb +6 -18
  93. data/app/views/spree/admin/countries/new.html.erb +3 -5
  94. data/app/views/spree/admin/customer_returns/_reimbursements_table.html.erb +4 -4
  95. data/app/views/spree/admin/customer_returns/_return_item_decision.html.erb +9 -10
  96. data/app/views/spree/admin/customer_returns/_return_item_selection.html.erb +5 -3
  97. data/app/views/spree/admin/customer_returns/edit.html.erb +17 -21
  98. data/app/views/spree/admin/customer_returns/index.html.erb +12 -16
  99. data/app/views/spree/admin/customer_returns/new.html.erb +29 -20
  100. data/app/views/spree/admin/general_settings/edit.html.erb +101 -90
  101. data/app/views/spree/admin/images/_form.html.erb +12 -12
  102. data/app/views/spree/admin/images/edit.html.erb +23 -21
  103. data/app/views/spree/admin/images/index.html.erb +25 -30
  104. data/app/views/spree/admin/images/new.html.erb +13 -11
  105. data/app/views/spree/admin/inventory_units/adjust.html.erb +29 -0
  106. data/app/views/spree/admin/log_entries/index.html.erb +9 -7
  107. data/app/views/spree/admin/option_types/_form.html.erb +10 -10
  108. data/app/views/spree/admin/option_types/_option_value_fields.html.erb +8 -10
  109. data/app/views/spree/admin/option_types/edit.html.erb +28 -23
  110. data/app/views/spree/admin/option_types/index.html.erb +16 -22
  111. data/app/views/spree/admin/option_types/new.html.erb +4 -3
  112. data/app/views/spree/admin/orders/_add_line_item.html.erb +9 -10
  113. data/app/views/spree/admin/orders/_add_product.html.erb +11 -9
  114. data/app/views/spree/admin/orders/_adjustments.html.erb +21 -7
  115. data/app/views/spree/admin/orders/_form.html.erb +23 -10
  116. data/app/views/spree/admin/orders/_line_item.html.erb +18 -6
  117. data/app/views/spree/admin/orders/_line_items.html.erb +45 -45
  118. data/app/views/spree/admin/orders/_line_items_edit_form.html.erb +10 -11
  119. data/app/views/spree/admin/orders/_risk_analysis.html.erb +13 -13
  120. data/app/views/spree/admin/orders/_shipment.html.erb +31 -39
  121. data/app/views/spree/admin/orders/_shipment_manifest.html.erb +23 -17
  122. data/app/views/spree/admin/orders/cart.html.erb +14 -15
  123. data/app/views/spree/admin/orders/customer_details/_form.html.erb +73 -52
  124. data/app/views/spree/admin/orders/customer_details/edit.html.erb +19 -15
  125. data/app/views/spree/admin/orders/edit.html.erb +12 -9
  126. data/app/views/spree/admin/orders/index.html.erb +145 -84
  127. data/app/views/spree/admin/payment_methods/_form.html.erb +26 -30
  128. data/app/views/spree/admin/payment_methods/edit.html.erb +5 -14
  129. data/app/views/spree/admin/payment_methods/index.html.erb +14 -29
  130. data/app/views/spree/admin/payment_methods/new.html.erb +4 -12
  131. data/app/views/spree/admin/payments/_capture_events.html.erb +2 -2
  132. data/app/views/spree/admin/payments/_form.html.erb +27 -30
  133. data/app/views/spree/admin/payments/_list.html.erb +20 -16
  134. data/app/views/spree/admin/payments/credit.html.erb +2 -2
  135. data/app/views/spree/admin/payments/index.html.erb +15 -13
  136. data/app/views/spree/admin/payments/new.html.erb +10 -11
  137. data/app/views/spree/admin/payments/show.html.erb +12 -9
  138. data/app/views/spree/admin/payments/source_forms/_gateway.html.erb +43 -47
  139. data/app/views/spree/admin/payments/source_views/_gateway.html.erb +19 -19
  140. data/app/views/spree/admin/product_properties/_product_property_fields.html.erb +5 -5
  141. data/app/views/spree/admin/product_properties/index.html.erb +5 -17
  142. data/app/views/spree/admin/products/_add_stock_form.html.erb +34 -25
  143. data/app/views/spree/admin/products/_autocomplete.js.erb +18 -7
  144. data/app/views/spree/admin/products/_form.html.erb +145 -150
  145. data/app/views/spree/admin/products/_properties_form.erb +2 -2
  146. data/app/views/spree/admin/products/edit.html.erb +3 -8
  147. data/app/views/spree/admin/products/index.html.erb +42 -63
  148. data/app/views/spree/admin/products/new.html.erb +29 -33
  149. data/app/views/spree/admin/products/stock.html.erb +67 -82
  150. data/app/views/spree/admin/promotion_actions/create.js.erb +1 -2
  151. data/app/views/spree/admin/promotion_actions/destroy.js.erb +1 -1
  152. data/app/views/spree/admin/promotion_categories/_form.html.erb +9 -9
  153. data/app/views/spree/admin/promotion_categories/edit.html.erb +2 -4
  154. data/app/views/spree/admin/promotion_categories/index.html.erb +27 -26
  155. data/app/views/spree/admin/promotion_categories/new.html.erb +1 -3
  156. data/app/views/spree/admin/promotion_rules/create.js.erb +1 -1
  157. data/app/views/spree/admin/promotion_rules/destroy.js.erb +1 -1
  158. data/app/views/spree/admin/promotions/_actions.html.erb +20 -17
  159. data/app/views/spree/admin/promotions/_form.html.erb +40 -39
  160. data/app/views/spree/admin/promotions/_promotion_action.html.erb +6 -6
  161. data/app/views/spree/admin/promotions/_promotion_rule.html.erb +7 -6
  162. data/app/views/spree/admin/promotions/_rules.html.erb +36 -35
  163. data/app/views/spree/admin/promotions/actions/_create_adjustment.html.erb +25 -23
  164. data/app/views/spree/admin/promotions/actions/_create_item_adjustments.html.erb +23 -21
  165. data/app/views/spree/admin/promotions/actions/_create_line_items.html.erb +16 -16
  166. data/app/views/spree/admin/promotions/calculators/_default_fields.html.erb +8 -6
  167. data/app/views/spree/admin/promotions/calculators/tiered_flat_rate/_fields.html.erb +29 -24
  168. data/app/views/spree/admin/promotions/calculators/tiered_percent/_fields.html.erb +29 -23
  169. data/app/views/spree/admin/promotions/edit.html.erb +16 -11
  170. data/app/views/spree/admin/promotions/index.html.erb +34 -58
  171. data/app/views/spree/admin/promotions/new.html.erb +4 -6
  172. data/app/views/spree/admin/promotions/rules/_item_total.html.erb +11 -7
  173. data/app/views/spree/admin/promotions/rules/_landing_page.html.erb +9 -5
  174. data/app/views/spree/admin/promotions/rules/_option_value.html.erb +42 -0
  175. data/app/views/spree/admin/promotions/rules/_product.html.erb +9 -8
  176. data/app/views/spree/admin/promotions/rules/_taxon.html.erb +9 -8
  177. data/app/views/spree/admin/promotions/rules/_user.html.erb +5 -3
  178. data/app/views/spree/admin/properties/_form.html.erb +9 -9
  179. data/app/views/spree/admin/properties/edit.html.erb +3 -9
  180. data/app/views/spree/admin/properties/index.html.erb +42 -52
  181. data/app/views/spree/admin/properties/new.html.erb +10 -9
  182. data/app/views/spree/admin/prototypes/_form.html.erb +25 -28
  183. data/app/views/spree/admin/prototypes/_prototypes.html.erb +4 -8
  184. data/app/views/spree/admin/prototypes/available.js.erb +1 -1
  185. data/app/views/spree/admin/prototypes/edit.html.erb +3 -11
  186. data/app/views/spree/admin/prototypes/index.html.erb +23 -36
  187. data/app/views/spree/admin/prototypes/new.html.erb +8 -7
  188. data/app/views/spree/admin/prototypes/show.html.erb +15 -18
  189. data/app/views/spree/admin/refund_reasons/edit.html.erb +2 -2
  190. data/app/views/spree/admin/refund_reasons/index.html.erb +2 -2
  191. data/app/views/spree/admin/refund_reasons/new.html.erb +1 -1
  192. data/app/views/spree/admin/refunds/edit.html.erb +14 -18
  193. data/app/views/spree/admin/refunds/new.html.erb +19 -27
  194. data/app/views/spree/admin/reimbursement_types/index.html.erb +6 -7
  195. data/app/views/spree/admin/reimbursements/edit.html.erb +25 -31
  196. data/app/views/spree/admin/reimbursements/index.html.erb +4 -10
  197. data/app/views/spree/admin/reimbursements/show.html.erb +32 -36
  198. data/app/views/spree/admin/reports/index.html.erb +4 -4
  199. data/app/views/spree/admin/reports/sales_total.html.erb +6 -11
  200. data/app/views/spree/admin/return_authorization_reasons/edit.html.erb +0 -0
  201. data/app/views/spree/admin/return_authorization_reasons/index.html.erb +2 -2
  202. data/app/views/spree/admin/return_authorization_reasons/new.html.erb +0 -0
  203. data/app/views/spree/admin/return_authorizations/_form.html.erb +20 -20
  204. data/app/views/spree/admin/return_authorizations/edit.html.erb +6 -6
  205. data/app/views/spree/admin/return_authorizations/index.html.erb +12 -12
  206. data/app/views/spree/admin/return_authorizations/new.html.erb +6 -10
  207. data/app/views/spree/admin/search/products.rabl +9 -0
  208. data/app/views/spree/admin/search/users.rabl +21 -21
  209. data/app/views/spree/admin/shared/_address_form.html.erb +22 -22
  210. data/app/views/spree/admin/shared/_alert.html.erb +8 -5
  211. data/app/views/spree/admin/shared/_calculator_fields.html.erb +13 -8
  212. data/app/views/spree/admin/shared/_content_header.html.erb +19 -16
  213. data/app/views/spree/admin/shared/_edit_resource_links.html.erb +3 -3
  214. data/app/views/spree/admin/shared/_error_messages.html.erb +12 -0
  215. data/app/views/spree/admin/shared/_head.html.erb +4 -8
  216. data/app/views/spree/admin/shared/_header.html.erb +27 -8
  217. data/app/views/spree/admin/shared/_index_table_options.html.erb +23 -0
  218. data/app/views/spree/admin/shared/_main_menu.html.erb +35 -0
  219. data/app/views/spree/admin/shared/_new_resource_links.html.erb +3 -3
  220. data/app/views/spree/admin/shared/_order_summary.html.erb +121 -48
  221. data/app/views/spree/admin/shared/_order_tabs.html.erb +55 -7
  222. data/app/views/spree/admin/shared/_product_tabs.html.erb +19 -25
  223. data/app/views/spree/admin/shared/_refunds.html.erb +9 -9
  224. data/app/views/spree/admin/shared/_report_criteria.html.erb +4 -4
  225. data/app/views/spree/admin/shared/_report_order_criteria.html.erb +12 -12
  226. data/app/views/spree/admin/shared/_sidebar.html.erb +1 -6
  227. data/app/views/spree/admin/shared/_table_filter.html.erb +21 -5
  228. data/app/views/spree/admin/shared/named_types/_edit.html.erb +6 -7
  229. data/app/views/spree/admin/shared/named_types/_form.html.erb +10 -14
  230. data/app/views/spree/admin/shared/named_types/_index.html.erb +6 -17
  231. data/app/views/spree/admin/shared/named_types/_new.html.erb +5 -5
  232. data/app/views/spree/admin/shared/sub_menu/_configuration.html.erb +21 -0
  233. data/app/views/spree/admin/shared/sub_menu/_product.html.erb +8 -0
  234. data/app/views/spree/admin/shared/sub_menu/_promotion.html.erb +4 -0
  235. data/app/views/spree/admin/shipping_categories/_form.html.erb +2 -2
  236. data/app/views/spree/admin/shipping_categories/edit.html.erb +4 -14
  237. data/app/views/spree/admin/shipping_categories/index.html.erb +24 -32
  238. data/app/views/spree/admin/shipping_categories/new.html.erb +2 -10
  239. data/app/views/spree/admin/shipping_methods/_form.html.erb +88 -67
  240. data/app/views/spree/admin/shipping_methods/edit.html.erb +6 -19
  241. data/app/views/spree/admin/shipping_methods/index.html.erb +13 -25
  242. data/app/views/spree/admin/shipping_methods/new.html.erb +2 -12
  243. data/app/views/spree/admin/state_changes/index.html.erb +42 -0
  244. data/app/views/spree/admin/states/_form.html.erb +6 -6
  245. data/app/views/spree/admin/states/_state_list.html.erb +6 -11
  246. data/app/views/spree/admin/states/edit.html.erb +3 -11
  247. data/app/views/spree/admin/states/index.html.erb +5 -9
  248. data/app/views/spree/admin/states/new.html.erb +1 -4
  249. data/app/views/spree/admin/states/new.js.erb +2 -2
  250. data/app/views/spree/admin/stock_locations/_form.html.erb +51 -45
  251. data/app/views/spree/admin/stock_locations/_transfer_stock_form.html.erb +15 -15
  252. data/app/views/spree/admin/stock_locations/edit.html.erb +4 -6
  253. data/app/views/spree/admin/stock_locations/index.html.erb +12 -26
  254. data/app/views/spree/admin/stock_locations/new.html.erb +3 -5
  255. data/app/views/spree/admin/stock_movements/_form.html.erb +10 -12
  256. data/app/views/spree/admin/stock_movements/edit.html.erb +4 -4
  257. data/app/views/spree/admin/stock_movements/index.html.erb +9 -15
  258. data/app/views/spree/admin/stock_movements/new.html.erb +3 -3
  259. data/app/views/spree/admin/stock_transfers/_stock_movements.html.erb +17 -22
  260. data/app/views/spree/admin/stock_transfers/index.html.erb +36 -49
  261. data/app/views/spree/admin/stock_transfers/new.html.erb +73 -77
  262. data/app/views/spree/admin/stock_transfers/show.html.erb +21 -29
  263. data/app/views/spree/admin/tax_categories/_form.html.erb +19 -27
  264. data/app/views/spree/admin/tax_categories/edit.html.erb +4 -6
  265. data/app/views/spree/admin/tax_categories/index.html.erb +13 -26
  266. data/app/views/spree/admin/tax_categories/new.html.erb +3 -6
  267. data/app/views/spree/admin/tax_categories/show.html.erb +1 -1
  268. data/app/views/spree/admin/tax_rates/_form.html.erb +34 -25
  269. data/app/views/spree/admin/tax_rates/edit.html.erb +4 -15
  270. data/app/views/spree/admin/tax_rates/index.html.erb +18 -32
  271. data/app/views/spree/admin/tax_rates/new.html.erb +2 -14
  272. data/app/views/spree/admin/taxonomies/_form.html.erb +5 -5
  273. data/app/views/spree/admin/taxonomies/_js_head.html.erb +0 -0
  274. data/app/views/spree/admin/taxonomies/_list.html.erb +9 -12
  275. data/app/views/spree/admin/taxonomies/edit.erb +11 -22
  276. data/app/views/spree/admin/taxonomies/index.html.erb +9 -15
  277. data/app/views/spree/admin/taxonomies/new.html.erb +4 -16
  278. data/app/views/spree/admin/taxons/_form.html.erb +38 -38
  279. data/app/views/spree/admin/taxons/_taxon_table.html.erb +2 -2
  280. data/app/views/spree/admin/taxons/edit.html.erb +5 -13
  281. data/app/views/spree/admin/taxons/index.html.erb +6 -13
  282. data/app/views/spree/admin/trackers/_form.html.erb +17 -23
  283. data/app/views/spree/admin/trackers/edit.html.erb +4 -14
  284. data/app/views/spree/admin/trackers/index.html.erb +9 -15
  285. data/app/views/spree/admin/trackers/new.html.erb +2 -10
  286. data/app/views/spree/admin/users/_addresses_form.html.erb +33 -17
  287. data/app/views/spree/admin/users/_form.html.erb +17 -17
  288. data/app/views/spree/admin/users/_lifetime_stats.html.erb +26 -0
  289. data/app/views/spree/admin/users/_sidebar.html.erb +14 -34
  290. data/app/views/spree/admin/users/_user_page_actions.html.erb +2 -6
  291. data/app/views/spree/admin/users/addresses.html.erb +8 -7
  292. data/app/views/spree/admin/users/edit.html.erb +55 -38
  293. data/app/views/spree/admin/users/index.html.erb +44 -30
  294. data/app/views/spree/admin/users/items.html.erb +13 -24
  295. data/app/views/spree/admin/users/new.html.erb +1 -7
  296. data/app/views/spree/admin/users/orders.html.erb +11 -17
  297. data/app/views/spree/admin/variants/_autocomplete.js.erb +13 -15
  298. data/app/views/spree/admin/variants/_autocomplete_line_items_stock.js.erb +41 -44
  299. data/app/views/spree/admin/variants/_autocomplete_stock.js.erb +46 -51
  300. data/app/views/spree/admin/variants/_form.html.erb +34 -34
  301. data/app/views/spree/admin/variants/_split.js.erb +8 -4
  302. data/app/views/spree/admin/variants/edit.html.erb +2 -4
  303. data/app/views/spree/admin/variants/index.html.erb +14 -33
  304. data/app/views/spree/admin/variants/new.html.erb +8 -6
  305. data/app/views/spree/admin/variants/new.js.erb +1 -1
  306. data/app/views/spree/admin/zones/_country_members.html.erb +14 -8
  307. data/app/views/spree/admin/zones/_form.html.erb +42 -31
  308. data/app/views/spree/admin/zones/_state_members.html.erb +14 -8
  309. data/app/views/spree/admin/zones/edit.html.erb +3 -11
  310. data/app/views/spree/admin/zones/index.html.erb +9 -19
  311. data/app/views/spree/admin/zones/new.html.erb +2 -13
  312. data/app/views/spree/layouts/admin.html.erb +63 -36
  313. data/config/initializers/assets.rb +1 -1
  314. data/config/routes.rb +4 -1
  315. data/lib/spree/backend/engine.rb +3 -0
  316. data/lib/spree_backend.rb +2 -0
  317. data/vendor/assets/javascripts/jquery.cookie.js +115 -39
  318. data/vendor/assets/javascripts/modernizr.js +3 -3
  319. data/vendor/assets/javascripts/underscore-min.js +6 -0
  320. data/vendor/assets/javascripts/underscore-min.map +1 -0
  321. data/vendor/assets/javascripts/velocity.js +3831 -0
  322. data/vendor/assets/stylesheets/animate.css +3158 -0
  323. metadata +85 -96
  324. data/app/assets/javascripts/spree/backend/images/index.js.coffee +0 -16
  325. data/app/assets/javascripts/spree/backend/images/new.js.coffee +0 -7
  326. data/app/assets/javascripts/spree/backend/underscore-min.js +0 -1227
  327. data/app/assets/stylesheets/spree/backend/components/_actions.scss +0 -31
  328. data/app/assets/stylesheets/spree/backend/components/_date-picker.scss +0 -159
  329. data/app/assets/stylesheets/spree/backend/components/_messages.scss +0 -54
  330. data/app/assets/stylesheets/spree/backend/components/_pagination.scss +0 -17
  331. data/app/assets/stylesheets/spree/backend/components/_product_autocomplete.scss +0 -29
  332. data/app/assets/stylesheets/spree/backend/components/_progress.scss +0 -35
  333. data/app/assets/stylesheets/spree/backend/components/_states.scss +0 -34
  334. data/app/assets/stylesheets/spree/backend/components/_table-filter.scss +0 -14
  335. data/app/assets/stylesheets/spree/backend/globals/_functions.scss +0 -25
  336. data/app/assets/stylesheets/spree/backend/globals/_mixins.scss +0 -25
  337. data/app/assets/stylesheets/spree/backend/globals/_variables.scss +0 -171
  338. data/app/assets/stylesheets/spree/backend/globals/_variables_override.scss +0 -7
  339. data/app/assets/stylesheets/spree/backend/hacks/_ie.scss +0 -72
  340. data/app/assets/stylesheets/spree/backend/hacks/_mozilla.scss +0 -33
  341. data/app/assets/stylesheets/spree/backend/hacks/_opera.scss +0 -17
  342. data/app/assets/stylesheets/spree/backend/plugins/_jstree.scss +0 -135
  343. data/app/assets/stylesheets/spree/backend/plugins/_powertip.scss +0 -86
  344. data/app/assets/stylesheets/spree/backend/plugins/_token-input.scss +0 -110
  345. data/app/assets/stylesheets/spree/backend/sections/_adjustments_table.scss +0 -8
  346. data/app/assets/stylesheets/spree/backend/sections/_alerts.scss +0 -27
  347. data/app/assets/stylesheets/spree/backend/sections/_bulk_transfer.scss +0 -8
  348. data/app/assets/stylesheets/spree/backend/sections/_edit_checkouts.scss +0 -72
  349. data/app/assets/stylesheets/spree/backend/sections/_image_settings.scss +0 -3
  350. data/app/assets/stylesheets/spree/backend/sections/_log_entries.scss +0 -17
  351. data/app/assets/stylesheets/spree/backend/sections/_orders.scss +0 -64
  352. data/app/assets/stylesheets/spree/backend/sections/_overview.scss +0 -86
  353. data/app/assets/stylesheets/spree/backend/sections/_products.scss +0 -123
  354. data/app/assets/stylesheets/spree/backend/sections/_promotions.scss +0 -119
  355. data/app/assets/stylesheets/spree/backend/sections/_return_authorizations.scss +0 -24
  356. data/app/assets/stylesheets/spree/backend/sections/_tax_zones.scss +0 -15
  357. data/app/assets/stylesheets/spree/backend/sections/_taxons.scss +0 -21
  358. data/app/assets/stylesheets/spree/backend/sections/_users.scss +0 -5
  359. data/app/assets/stylesheets/spree/backend/shared/_icons.scss +0 -53
  360. data/app/assets/stylesheets/spree/backend/shared/_layout.scss +0 -99
  361. data/app/assets/stylesheets/spree/backend/shared/_tables.scss +0 -214
  362. data/app/assets/stylesheets/spree/backend/spree_admin.scss +0 -45
  363. data/app/views/spree/admin/line_items/create.js.erb +0 -1
  364. data/app/views/spree/admin/line_items/destroy.js.erb +0 -1
  365. data/app/views/spree/admin/option_types/new.js.erb +0 -2
  366. data/app/views/spree/admin/payments/_bill_address_form.html.erb +0 -9
  367. data/app/views/spree/admin/payments/source_views/_check.html.erb +0 -0
  368. data/app/views/spree/admin/products/new.js.erb +0 -7
  369. data/app/views/spree/admin/promotions/_tab.html.erb +0 -1
  370. data/app/views/spree/admin/promotions/rules/_first_order.html.erb +0 -0
  371. data/app/views/spree/admin/promotions/rules/_one_use_per_user.html.erb +0 -0
  372. data/app/views/spree/admin/promotions/rules/_user_logged_in.html.erb +0 -0
  373. data/app/views/spree/admin/properties/filtered.html.erb +0 -1
  374. data/app/views/spree/admin/properties/new.js.erb +0 -2
  375. data/app/views/spree/admin/prototypes/new.js.erb +0 -5
  376. data/app/views/spree/admin/shared/_address.html.erb +0 -6
  377. data/app/views/spree/admin/shared/_configuration_menu.html.erb +0 -28
  378. data/app/views/spree/admin/shared/_menu.html.erb +0 -9
  379. data/app/views/spree/admin/shared/_order_submenu.html.erb +0 -49
  380. data/app/views/spree/admin/shared/_product_sub_menu.html.erb +0 -10
  381. data/app/views/spree/admin/shared/_promotion_sub_menu.html.erb +0 -6
  382. data/app/views/spree/admin/shared/_show_resource_links.html.erb +0 -5
  383. data/app/views/spree/admin/shared/_sub_menu.html.erb +0 -9
  384. data/app/views/spree/admin/shared/_tabs.html.erb +0 -21
  385. data/app/views/spree/admin/taxonomies/_taxon.html.erb +0 -12
  386. data/app/views/spree/admin/taxons/search.rabl +0 -5
  387. data/app/views/spree/admin/variants/update.js.erb +0 -1
  388. data/vendor/assets/images/jquery.alerts/images/help.gif +0 -0
  389. data/vendor/assets/images/jquery.alerts/images/important.gif +0 -0
  390. data/vendor/assets/images/jquery.alerts/images/info.gif +0 -0
  391. data/vendor/assets/images/jquery.alerts/images/title.gif +0 -0
  392. data/vendor/assets/javascripts/css_browser_selector_dev.js +0 -129
  393. data/vendor/assets/javascripts/equalize.js +0 -41
  394. data/vendor/assets/javascripts/jquery.adaptivemenu.js +0 -60
  395. data/vendor/assets/javascripts/jquery.alerts/jquery.alerts.js +0 -235
  396. data/vendor/assets/javascripts/jquery.delayedobserver.js +0 -35
  397. data/vendor/assets/javascripts/jquery.powertip.js +0 -796
  398. data/vendor/assets/javascripts/jquery.vAlign.js +0 -11
  399. data/vendor/assets/javascripts/responsive-tables.js +0 -42
  400. data/vendor/assets/javascripts/spin.js +0 -379
  401. data/vendor/assets/javascripts/trunk8.js +0 -369
  402. data/vendor/assets/stylesheets/jquery.alerts/jquery.alerts.css.erb +0 -57
  403. data/vendor/assets/stylesheets/jquery.alerts/jquery.alerts.spree.css +0 -29
  404. data/vendor/assets/stylesheets/jquery.powertip.css +0 -85
  405. data/vendor/assets/stylesheets/responsive-tables.css +0 -21
@@ -0,0 +1,3831 @@
1
+ /*! VelocityJS.org (1.1.0). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */
2
+
3
+ /*************************
4
+ Velocity jQuery Shim
5
+ *************************/
6
+
7
+ /*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */
8
+
9
+ /* This file contains the jQuery functions that Velocity relies on, thereby removing Velocity's dependency on a full copy of jQuery, and allowing it to work in any environment. */
10
+ /* These shimmed functions are only used if jQuery isn't present. If both this shim and jQuery are loaded, Velocity defaults to jQuery proper. */
11
+ /* Browser support: Using this shim instead of jQuery proper removes support for IE8. */
12
+
13
+ ;(function (window) {
14
+ /***************
15
+ Setup
16
+ ***************/
17
+
18
+ /* If jQuery is already loaded, there's no point in loading this shim. */
19
+ if (window.jQuery) {
20
+ return;
21
+ }
22
+
23
+ /* jQuery base. */
24
+ var $ = function (selector, context) {
25
+ return new $.fn.init(selector, context);
26
+ };
27
+
28
+ /********************
29
+ Private Methods
30
+ ********************/
31
+
32
+ /* jQuery */
33
+ $.isWindow = function (obj) {
34
+ /* jshint eqeqeq: false */
35
+ return obj != null && obj == obj.window;
36
+ };
37
+
38
+ /* jQuery */
39
+ $.type = function (obj) {
40
+ if (obj == null) {
41
+ return obj + "";
42
+ }
43
+
44
+ return typeof obj === "object" || typeof obj === "function" ?
45
+ class2type[toString.call(obj)] || "object" :
46
+ typeof obj;
47
+ };
48
+
49
+ /* jQuery */
50
+ $.isArray = Array.isArray || function (obj) {
51
+ return $.type(obj) === "array";
52
+ };
53
+
54
+ /* jQuery */
55
+ function isArraylike (obj) {
56
+ var length = obj.length,
57
+ type = $.type(obj);
58
+
59
+ if (type === "function" || $.isWindow(obj)) {
60
+ return false;
61
+ }
62
+
63
+ if (obj.nodeType === 1 && length) {
64
+ return true;
65
+ }
66
+
67
+ return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj;
68
+ }
69
+
70
+ /***************
71
+ $ Methods
72
+ ***************/
73
+
74
+ /* jQuery: Support removed for IE<9. */
75
+ $.isPlainObject = function (obj) {
76
+ var key;
77
+
78
+ if (!obj || $.type(obj) !== "object" || obj.nodeType || $.isWindow(obj)) {
79
+ return false;
80
+ }
81
+
82
+ try {
83
+ if (obj.constructor &&
84
+ !hasOwn.call(obj, "constructor") &&
85
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
86
+ return false;
87
+ }
88
+ } catch (e) {
89
+ return false;
90
+ }
91
+
92
+ for (key in obj) {}
93
+
94
+ return key === undefined || hasOwn.call(obj, key);
95
+ };
96
+
97
+ /* jQuery */
98
+ $.each = function(obj, callback, args) {
99
+ var value,
100
+ i = 0,
101
+ length = obj.length,
102
+ isArray = isArraylike(obj);
103
+
104
+ if (args) {
105
+ if (isArray) {
106
+ for (; i < length; i++) {
107
+ value = callback.apply(obj[i], args);
108
+
109
+ if (value === false) {
110
+ break;
111
+ }
112
+ }
113
+ } else {
114
+ for (i in obj) {
115
+ value = callback.apply(obj[i], args);
116
+
117
+ if (value === false) {
118
+ break;
119
+ }
120
+ }
121
+ }
122
+
123
+ } else {
124
+ if (isArray) {
125
+ for (; i < length; i++) {
126
+ value = callback.call(obj[i], i, obj[i]);
127
+
128
+ if (value === false) {
129
+ break;
130
+ }
131
+ }
132
+ } else {
133
+ for (i in obj) {
134
+ value = callback.call(obj[i], i, obj[i]);
135
+
136
+ if (value === false) {
137
+ break;
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ return obj;
144
+ };
145
+
146
+ /* Custom */
147
+ $.data = function (node, key, value) {
148
+ /* $.getData() */
149
+ if (value === undefined) {
150
+ var id = node[$.expando],
151
+ store = id && cache[id];
152
+
153
+ if (key === undefined) {
154
+ return store;
155
+ } else if (store) {
156
+ if (key in store) {
157
+ return store[key];
158
+ }
159
+ }
160
+ /* $.setData() */
161
+ } else if (key !== undefined) {
162
+ var id = node[$.expando] || (node[$.expando] = ++$.uuid);
163
+
164
+ cache[id] = cache[id] || {};
165
+ cache[id][key] = value;
166
+
167
+ return value;
168
+ }
169
+ };
170
+
171
+ /* Custom */
172
+ $.removeData = function (node, keys) {
173
+ var id = node[$.expando],
174
+ store = id && cache[id];
175
+
176
+ if (store) {
177
+ $.each(keys, function(_, key) {
178
+ delete store[key];
179
+ });
180
+ }
181
+ };
182
+
183
+ /* jQuery */
184
+ $.extend = function () {
185
+ var src, copyIsArray, copy, name, options, clone,
186
+ target = arguments[0] || {},
187
+ i = 1,
188
+ length = arguments.length,
189
+ deep = false;
190
+
191
+ if (typeof target === "boolean") {
192
+ deep = target;
193
+
194
+ target = arguments[i] || {};
195
+ i++;
196
+ }
197
+
198
+ if (typeof target !== "object" && $.type(target) !== "function") {
199
+ target = {};
200
+ }
201
+
202
+ if (i === length) {
203
+ target = this;
204
+ i--;
205
+ }
206
+
207
+ for (; i < length; i++) {
208
+ if ((options = arguments[i]) != null) {
209
+ for (name in options) {
210
+ src = target[name];
211
+ copy = options[name];
212
+
213
+ if (target === copy) {
214
+ continue;
215
+ }
216
+
217
+ if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
218
+ if (copyIsArray) {
219
+ copyIsArray = false;
220
+ clone = src && $.isArray(src) ? src : [];
221
+
222
+ } else {
223
+ clone = src && $.isPlainObject(src) ? src : {};
224
+ }
225
+
226
+ target[name] = $.extend(deep, clone, copy);
227
+
228
+ } else if (copy !== undefined) {
229
+ target[name] = copy;
230
+ }
231
+ }
232
+ }
233
+ }
234
+
235
+ return target;
236
+ };
237
+
238
+ /* jQuery 1.4.3 */
239
+ $.queue = function (elem, type, data) {
240
+ function $makeArray (arr, results) {
241
+ var ret = results || [];
242
+
243
+ if (arr != null) {
244
+ if (isArraylike(Object(arr))) {
245
+ /* $.merge */
246
+ (function(first, second) {
247
+ var len = +second.length,
248
+ j = 0,
249
+ i = first.length;
250
+
251
+ while (j < len) {
252
+ first[i++] = second[j++];
253
+ }
254
+
255
+ if (len !== len) {
256
+ while (second[j] !== undefined) {
257
+ first[i++] = second[j++];
258
+ }
259
+ }
260
+
261
+ first.length = i;
262
+
263
+ return first;
264
+ })(ret, typeof arr === "string" ? [arr] : arr);
265
+ } else {
266
+ [].push.call(ret, arr);
267
+ }
268
+ }
269
+
270
+ return ret;
271
+ }
272
+
273
+ if (!elem) {
274
+ return;
275
+ }
276
+
277
+ type = (type || "fx") + "queue";
278
+
279
+ var q = $.data(elem, type);
280
+
281
+ if (!data) {
282
+ return q || [];
283
+ }
284
+
285
+ if (!q || $.isArray(data)) {
286
+ q = $.data(elem, type, $makeArray(data));
287
+ } else {
288
+ q.push(data);
289
+ }
290
+
291
+ return q;
292
+ };
293
+
294
+ /* jQuery 1.4.3 */
295
+ $.dequeue = function (elems, type) {
296
+ /* Custom: Embed element iteration. */
297
+ $.each(elems.nodeType ? [ elems ] : elems, function(i, elem) {
298
+ type = type || "fx";
299
+
300
+ var queue = $.queue(elem, type),
301
+ fn = queue.shift();
302
+
303
+ if (fn === "inprogress") {
304
+ fn = queue.shift();
305
+ }
306
+
307
+ if (fn) {
308
+ if (type === "fx") {
309
+ queue.unshift("inprogress");
310
+ }
311
+
312
+ fn.call(elem, function() {
313
+ $.dequeue(elem, type);
314
+ });
315
+ }
316
+ });
317
+ };
318
+
319
+ /******************
320
+ $.fn Methods
321
+ ******************/
322
+
323
+ /* jQuery */
324
+ $.fn = $.prototype = {
325
+ init: function (selector) {
326
+ /* Just return the element wrapped inside an array; don't proceed with the actual jQuery node wrapping process. */
327
+ if (selector.nodeType) {
328
+ this[0] = selector;
329
+
330
+ return this;
331
+ } else {
332
+ throw new Error("Not a DOM node.");
333
+ }
334
+ },
335
+
336
+ offset: function () {
337
+ /* jQuery altered code: Dropped disconnected DOM node checking. */
338
+ var box = this[0].getBoundingClientRect ? this[0].getBoundingClientRect() : { top: 0, left: 0 };
339
+
340
+ return {
341
+ top: box.top + (window.pageYOffset || document.scrollTop || 0) - (document.clientTop || 0),
342
+ left: box.left + (window.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || 0)
343
+ };
344
+ },
345
+
346
+ position: function () {
347
+ /* jQuery */
348
+ function offsetParent() {
349
+ var offsetParent = this.offsetParent || document;
350
+
351
+ while (offsetParent && (!offsetParent.nodeType.toLowerCase === "html" && offsetParent.style.position === "static")) {
352
+ offsetParent = offsetParent.offsetParent;
353
+ }
354
+
355
+ return offsetParent || document;
356
+ }
357
+
358
+ /* Zepto */
359
+ var elem = this[0],
360
+ offsetParent = offsetParent.apply(elem),
361
+ offset = this.offset(),
362
+ parentOffset = /^(?:body|html)$/i.test(offsetParent.nodeName) ? { top: 0, left: 0 } : $(offsetParent).offset()
363
+
364
+ offset.top -= parseFloat(elem.style.marginTop) || 0;
365
+ offset.left -= parseFloat(elem.style.marginLeft) || 0;
366
+
367
+ if (offsetParent.style) {
368
+ parentOffset.top += parseFloat(offsetParent.style.borderTopWidth) || 0
369
+ parentOffset.left += parseFloat(offsetParent.style.borderLeftWidth) || 0
370
+ }
371
+
372
+ return {
373
+ top: offset.top - parentOffset.top,
374
+ left: offset.left - parentOffset.left
375
+ };
376
+ }
377
+ };
378
+
379
+ /**********************
380
+ Private Variables
381
+ **********************/
382
+
383
+ /* For $.data() */
384
+ var cache = {};
385
+ $.expando = "velocity" + (new Date().getTime());
386
+ $.uuid = 0;
387
+
388
+ /* For $.queue() */
389
+ var class2type = {},
390
+ hasOwn = class2type.hasOwnProperty,
391
+ toString = class2type.toString;
392
+
393
+ var types = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
394
+ for (var i = 0; i < types.length; i++) {
395
+ class2type["[object " + types[i] + "]"] = types[i].toLowerCase();
396
+ }
397
+
398
+ /* Makes $(node) possible, without having to call init. */
399
+ $.fn.init.prototype = $.fn;
400
+
401
+ /* Globalize Velocity onto the window, and assign its Utilities property. */
402
+ window.Velocity = { Utilities: $ };
403
+ })(window);
404
+
405
+ /******************
406
+ Velocity.js
407
+ ******************/
408
+
409
+ ;(function (factory) {
410
+ /* CommonJS module. */
411
+ if (typeof module === "object" && typeof module.exports === "object") {
412
+ module.exports = factory();
413
+ /* AMD module. */
414
+ } else if (typeof define === "function" && define.amd) {
415
+ define(factory);
416
+ /* Browser globals. */
417
+ } else {
418
+ factory();
419
+ }
420
+ }(function() {
421
+ return function (global, window, document, undefined) {
422
+
423
+ /***************
424
+ Summary
425
+ ***************/
426
+
427
+ /*
428
+ - CSS: CSS stack that works independently from the rest of Velocity.
429
+ - animate(): Core animation method that iterates over the targeted elements and queues the incoming call onto each element individually.
430
+ - Pre-Queueing: Prepare the element for animation by instantiating its data cache and processing the call's options.
431
+ - Queueing: The logic that runs once the call has reached its point of execution in the element's $.queue() stack.
432
+ Most logic is placed here to avoid risking it becoming stale (if the element's properties have changed).
433
+ - Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
434
+ - tick(): The single requestAnimationFrame loop responsible for tweening all in-progress calls.
435
+ - completeCall(): Handles the cleanup process for each Velocity call.
436
+ */
437
+
438
+ /*********************
439
+ Helper Functions
440
+ *********************/
441
+
442
+ /* IE detection. Gist: https://gist.github.com/julianshapiro/9098609 */
443
+ var IE = (function() {
444
+ if (document.documentMode) {
445
+ return document.documentMode;
446
+ } else {
447
+ for (var i = 7; i > 4; i--) {
448
+ var div = document.createElement("div");
449
+
450
+ div.innerHTML = "<!--[if IE " + i + "]><span></span><![endif]-->";
451
+
452
+ if (div.getElementsByTagName("span").length) {
453
+ div = null;
454
+
455
+ return i;
456
+ }
457
+ }
458
+ }
459
+
460
+ return undefined;
461
+ })();
462
+
463
+ /* rAF shim. Gist: https://gist.github.com/julianshapiro/9497513 */
464
+ var rAFShim = (function() {
465
+ var timeLast = 0;
466
+
467
+ return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
468
+ var timeCurrent = (new Date()).getTime(),
469
+ timeDelta;
470
+
471
+ /* Dynamically set delay on a per-tick basis to match 60fps. */
472
+ /* Technique by Erik Moller. MIT license: https://gist.github.com/paulirish/1579671 */
473
+ timeDelta = Math.max(0, 16 - (timeCurrent - timeLast));
474
+ timeLast = timeCurrent + timeDelta;
475
+
476
+ return setTimeout(function() { callback(timeCurrent + timeDelta); }, timeDelta);
477
+ };
478
+ })();
479
+
480
+ /* Array compacting. Copyright Lo-Dash. MIT License: https://github.com/lodash/lodash/blob/master/LICENSE.txt */
481
+ function compactSparseArray (array) {
482
+ var index = -1,
483
+ length = array ? array.length : 0,
484
+ result = [];
485
+
486
+ while (++index < length) {
487
+ var value = array[index];
488
+
489
+ if (value) {
490
+ result.push(value);
491
+ }
492
+ }
493
+
494
+ return result;
495
+ }
496
+
497
+ function sanitizeElements (elements) {
498
+ /* Unwrap jQuery/Zepto objects. */
499
+ if (Type.isWrapped(elements)) {
500
+ elements = [].slice.call(elements);
501
+ /* Wrap a single element in an array so that $.each() can iterate with the element instead of its node's children. */
502
+ } else if (Type.isNode(elements)) {
503
+ elements = [ elements ];
504
+ }
505
+
506
+ return elements;
507
+ }
508
+
509
+ var Type = {
510
+ isString: function (variable) {
511
+ return (typeof variable === "string");
512
+ },
513
+ isArray: Array.isArray || function (variable) {
514
+ return Object.prototype.toString.call(variable) === "[object Array]";
515
+ },
516
+ isFunction: function (variable) {
517
+ return Object.prototype.toString.call(variable) === "[object Function]";
518
+ },
519
+ isNode: function (variable) {
520
+ return variable && variable.nodeType;
521
+ },
522
+ /* Copyright Martin Bohm. MIT License: https://gist.github.com/Tomalak/818a78a226a0738eaade */
523
+ isNodeList: function (variable) {
524
+ return typeof variable === "object" &&
525
+ /^\[object (HTMLCollection|NodeList|Object)\]$/.test(Object.prototype.toString.call(variable)) &&
526
+ variable.length !== undefined &&
527
+ (variable.length === 0 || (typeof variable[0] === "object" && variable[0].nodeType > 0));
528
+ },
529
+ /* Determine if variable is a wrapped jQuery or Zepto element. */
530
+ isWrapped: function (variable) {
531
+ return variable && (variable.jquery || (window.Zepto && window.Zepto.zepto.isZ(variable)));
532
+ },
533
+ isSVG: function (variable) {
534
+ return window.SVGElement && (variable instanceof window.SVGElement);
535
+ },
536
+ isEmptyObject: function (variable) {
537
+ for (var name in variable) {
538
+ return false;
539
+ }
540
+
541
+ return true;
542
+ }
543
+ };
544
+
545
+ /*****************
546
+ Dependencies
547
+ *****************/
548
+
549
+ var $,
550
+ isJQuery = false;
551
+
552
+ if (global.fn && global.fn.jquery) {
553
+ $ = global;
554
+ isJQuery = true;
555
+ } else {
556
+ $ = window.Velocity.Utilities;
557
+ }
558
+
559
+ if (IE <= 8 && !isJQuery) {
560
+ throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");
561
+ } else if (IE <= 7) {
562
+ /* Revert to jQuery's $.animate(), and lose Velocity's extra features. */
563
+ jQuery.fn.velocity = jQuery.fn.animate;
564
+
565
+ /* Now that $.fn.velocity is aliased, abort this Velocity declaration. */
566
+ return;
567
+ }
568
+
569
+ /*****************
570
+ Constants
571
+ *****************/
572
+
573
+ var DURATION_DEFAULT = 400,
574
+ EASING_DEFAULT = "swing";
575
+
576
+ /*************
577
+ State
578
+ *************/
579
+
580
+ /* Note: The global object also doubles as a publicly-accessible data store for the purposes of unit testing. */
581
+ /* Note: Alias the lowercase and uppercase variants of "velocity" to minimize user confusion due to the lowercase nature of the $.fn extension. */
582
+ var Velocity = {
583
+ /* Container for page-wide Velocity state data. */
584
+ State: {
585
+ /* Detect mobile devices to determine if mobileHA should be turned on. */
586
+ isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
587
+ /* The mobileHA option's behavior changes on older Android devices (Gingerbread, versions 2.3.3-2.3.7). */
588
+ isAndroid: /Android/i.test(navigator.userAgent),
589
+ isGingerbread: /Android 2\.3\.[3-7]/i.test(navigator.userAgent),
590
+ isChrome: window.chrome,
591
+ isFirefox: /Firefox/i.test(navigator.userAgent),
592
+ /* Create a cached element for re-use when checking for CSS property prefixes. */
593
+ prefixElement: document.createElement("div"),
594
+ /* Cache every prefix match to avoid repeating lookups. */
595
+ prefixMatches: {},
596
+ /* Cache the anchor used for animating window scrolling. */
597
+ scrollAnchor: null,
598
+ /* Cache the property names associated with the scroll anchor. */
599
+ scrollPropertyLeft: null,
600
+ scrollPropertyTop: null,
601
+ /* Keep track of whether our RAF tick is running. */
602
+ isTicking: false,
603
+ /* Container for every in-progress call to Velocity. */
604
+ calls: []
605
+ },
606
+ /* Velocity's custom CSS stack. Made global for unit testing. */
607
+ CSS: { /* Defined below. */ },
608
+ /* Defined by Velocity's optional jQuery shim. */
609
+ Utilities: $,
610
+ /* Container for the user's custom animation redirects that are referenced by name in place of a properties map object. */
611
+ Redirects: { /* Manually registered by the user. */ },
612
+ Easings: { /* Defined below. */ },
613
+ /* Attempt to use ES6 Promises by default. Users can override this with a third-party promises library. */
614
+ Promise: window.Promise,
615
+ /* Page-wide option defaults, which can be overriden by the user. */
616
+ defaults: {
617
+ queue: "",
618
+ duration: DURATION_DEFAULT,
619
+ easing: EASING_DEFAULT,
620
+ begin: undefined,
621
+ complete: undefined,
622
+ progress: undefined,
623
+ display: undefined,
624
+ visibility: undefined,
625
+ loop: false,
626
+ delay: false,
627
+ mobileHA: true,
628
+ /* Set to false to prevent property values from being cached between consecutive Velocity-initiated chain calls. */
629
+ _cacheValues: true
630
+ },
631
+ /* A design goal of Velocity is to cache data wherever possible in order to avoid DOM requerying.
632
+ Accordingly, each element has a data cache instantiated on it. */
633
+ init: function (element) {
634
+ $.data(element, "velocity", {
635
+ /* Store whether this is an SVG element, since its properties are retrieved and updated differently than standard HTML elements. */
636
+ isSVG: Type.isSVG(element),
637
+ /* Keep track of whether the element is currently being animated by Velocity.
638
+ This is used to ensure that property values are not transferred between non-consecutive (stale) calls. */
639
+ isAnimating: false,
640
+ /* A reference to the element's live computedStyle object. Learn more here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
641
+ computedStyle: null,
642
+ /* Tween data is cached for each animation on the element so that data can be passed across calls --
643
+ in particular, end values are used as subsequent start values in consecutive Velocity calls. */
644
+ tweensContainer: null,
645
+ /* The full root property values of each CSS hook being animated on this element are cached so that:
646
+ 1) Concurrently-animating hooks sharing the same root can have their root values' merged into one while tweening.
647
+ 2) Post-hook-injection root values can be transferred over to consecutively chained Velocity calls as starting root values. */
648
+ rootPropertyValueCache: {},
649
+ /* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */
650
+ transformCache: {}
651
+ });
652
+ },
653
+ /* A parallel to jQuery's $.css(), used for getting/setting Velocity's hooked CSS properties. */
654
+ hook: null, /* Defined below. */
655
+ /* Velocity-wide animation time remapping for testing purposes. */
656
+ mock: false,
657
+ version: { major: 1, minor: 1, patch: 0 },
658
+ /* Set to 1 or 2 (most verbose) to output debug info to console. */
659
+ debug: false
660
+ };
661
+
662
+ /* Retrieve the appropriate scroll anchor and property name for the browser: https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY */
663
+ if (window.pageYOffset !== undefined) {
664
+ Velocity.State.scrollAnchor = window;
665
+ Velocity.State.scrollPropertyLeft = "pageXOffset";
666
+ Velocity.State.scrollPropertyTop = "pageYOffset";
667
+ } else {
668
+ Velocity.State.scrollAnchor = document.documentElement || document.body.parentNode || document.body;
669
+ Velocity.State.scrollPropertyLeft = "scrollLeft";
670
+ Velocity.State.scrollPropertyTop = "scrollTop";
671
+ }
672
+
673
+ /* Shorthand alias for jQuery's $.data() utility. */
674
+ function Data (element) {
675
+ /* Hardcode a reference to the plugin name. */
676
+ var response = $.data(element, "velocity");
677
+
678
+ /* jQuery <=1.4.2 returns null instead of undefined when no match is found. We normalize this behavior. */
679
+ return response === null ? undefined : response;
680
+ };
681
+
682
+ /**************
683
+ Easing
684
+ **************/
685
+
686
+ /* Step easing generator. */
687
+ function generateStep (steps) {
688
+ return function (p) {
689
+ return Math.round(p * steps) * (1 / steps);
690
+ };
691
+ }
692
+
693
+ /* Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */
694
+ function generateBezier (mX1, mY1, mX2, mY2) {
695
+ var NEWTON_ITERATIONS = 4,
696
+ NEWTON_MIN_SLOPE = 0.001,
697
+ SUBDIVISION_PRECISION = 0.0000001,
698
+ SUBDIVISION_MAX_ITERATIONS = 10,
699
+ kSplineTableSize = 11,
700
+ kSampleStepSize = 1.0 / (kSplineTableSize - 1.0),
701
+ float32ArraySupported = "Float32Array" in window;
702
+
703
+ /* Must contain four arguments. */
704
+ if (arguments.length !== 4) {
705
+ return false;
706
+ }
707
+
708
+ /* Arguments must be numbers. */
709
+ for (var i = 0; i < 4; ++i) {
710
+ if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) {
711
+ return false;
712
+ }
713
+ }
714
+
715
+ /* X values must be in the [0, 1] range. */
716
+ mX1 = Math.min(mX1, 1);
717
+ mX2 = Math.min(mX2, 1);
718
+ mX1 = Math.max(mX1, 0);
719
+ mX2 = Math.max(mX2, 0);
720
+
721
+ var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
722
+
723
+ function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
724
+ function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
725
+ function C (aA1) { return 3.0 * aA1; }
726
+
727
+ function calcBezier (aT, aA1, aA2) {
728
+ return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
729
+ }
730
+
731
+ function getSlope (aT, aA1, aA2) {
732
+ return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
733
+ }
734
+
735
+ function newtonRaphsonIterate (aX, aGuessT) {
736
+ for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
737
+ var currentSlope = getSlope(aGuessT, mX1, mX2);
738
+
739
+ if (currentSlope === 0.0) return aGuessT;
740
+
741
+ var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
742
+ aGuessT -= currentX / currentSlope;
743
+ }
744
+
745
+ return aGuessT;
746
+ }
747
+
748
+ function calcSampleValues () {
749
+ for (var i = 0; i < kSplineTableSize; ++i) {
750
+ mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
751
+ }
752
+ }
753
+
754
+ function binarySubdivide (aX, aA, aB) {
755
+ var currentX, currentT, i = 0;
756
+
757
+ do {
758
+ currentT = aA + (aB - aA) / 2.0;
759
+ currentX = calcBezier(currentT, mX1, mX2) - aX;
760
+ if (currentX > 0.0) {
761
+ aB = currentT;
762
+ } else {
763
+ aA = currentT;
764
+ }
765
+ } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
766
+
767
+ return currentT;
768
+ }
769
+
770
+ function getTForX (aX) {
771
+ var intervalStart = 0.0,
772
+ currentSample = 1,
773
+ lastSample = kSplineTableSize - 1;
774
+
775
+ for (; currentSample != lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
776
+ intervalStart += kSampleStepSize;
777
+ }
778
+
779
+ --currentSample;
780
+
781
+ var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample+1] - mSampleValues[currentSample]),
782
+ guessForT = intervalStart + dist * kSampleStepSize,
783
+ initialSlope = getSlope(guessForT, mX1, mX2);
784
+
785
+ if (initialSlope >= NEWTON_MIN_SLOPE) {
786
+ return newtonRaphsonIterate(aX, guessForT);
787
+ } else if (initialSlope == 0.0) {
788
+ return guessForT;
789
+ } else {
790
+ return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);
791
+ }
792
+ }
793
+
794
+ var _precomputed = false;
795
+
796
+ function precompute() {
797
+ _precomputed = true;
798
+ if (mX1 != mY1 || mX2 != mY2) calcSampleValues();
799
+ }
800
+
801
+ var f = function (aX) {
802
+ if (!_precomputed) precompute();
803
+ if (mX1 === mY1 && mX2 === mY2) return aX;
804
+ if (aX === 0) return 0;
805
+ if (aX === 1) return 1;
806
+
807
+ return calcBezier(getTForX(aX), mY1, mY2);
808
+ };
809
+
810
+ f.getControlPoints = function() { return [{ x: mX1, y: mY1 }, { x: mX2, y: mY2 }]; };
811
+
812
+ var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")";
813
+ f.toString = function () { return str; };
814
+
815
+ return f;
816
+ }
817
+
818
+ /* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */
819
+ /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass
820
+ then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */
821
+ var generateSpringRK4 = (function () {
822
+ function springAccelerationForState (state) {
823
+ return (-state.tension * state.x) - (state.friction * state.v);
824
+ }
825
+
826
+ function springEvaluateStateWithDerivative (initialState, dt, derivative) {
827
+ var state = {
828
+ x: initialState.x + derivative.dx * dt,
829
+ v: initialState.v + derivative.dv * dt,
830
+ tension: initialState.tension,
831
+ friction: initialState.friction
832
+ };
833
+
834
+ return { dx: state.v, dv: springAccelerationForState(state) };
835
+ }
836
+
837
+ function springIntegrateState (state, dt) {
838
+ var a = {
839
+ dx: state.v,
840
+ dv: springAccelerationForState(state)
841
+ },
842
+ b = springEvaluateStateWithDerivative(state, dt * 0.5, a),
843
+ c = springEvaluateStateWithDerivative(state, dt * 0.5, b),
844
+ d = springEvaluateStateWithDerivative(state, dt, c),
845
+ dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),
846
+ dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);
847
+
848
+ state.x = state.x + dxdt * dt;
849
+ state.v = state.v + dvdt * dt;
850
+
851
+ return state;
852
+ }
853
+
854
+ return function springRK4Factory (tension, friction, duration) {
855
+
856
+ var initState = {
857
+ x: -1,
858
+ v: 0,
859
+ tension: null,
860
+ friction: null
861
+ },
862
+ path = [0],
863
+ time_lapsed = 0,
864
+ tolerance = 1 / 10000,
865
+ DT = 16 / 1000,
866
+ have_duration, dt, last_state;
867
+
868
+ tension = parseFloat(tension) || 500;
869
+ friction = parseFloat(friction) || 20;
870
+ duration = duration || null;
871
+
872
+ initState.tension = tension;
873
+ initState.friction = friction;
874
+
875
+ have_duration = duration !== null;
876
+
877
+ /* Calculate the actual time it takes for this animation to complete with the provided conditions. */
878
+ if (have_duration) {
879
+ /* Run the simulation without a duration. */
880
+ time_lapsed = springRK4Factory(tension, friction);
881
+ /* Compute the adjusted time delta. */
882
+ dt = time_lapsed / duration * DT;
883
+ } else {
884
+ dt = DT;
885
+ }
886
+
887
+ while (true) {
888
+ /* Next/step function .*/
889
+ last_state = springIntegrateState(last_state || initState, dt);
890
+ /* Store the position. */
891
+ path.push(1 + last_state.x);
892
+ time_lapsed += 16;
893
+ /* If the change threshold is reached, break. */
894
+ if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {
895
+ break;
896
+ }
897
+ }
898
+
899
+ /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the
900
+ computed path and returns a snapshot of the position according to a given percentComplete. */
901
+ return !have_duration ? time_lapsed : function(percentComplete) { return path[ (percentComplete * (path.length - 1)) | 0 ]; };
902
+ };
903
+ }());
904
+
905
+ /* jQuery easings. */
906
+ Velocity.Easings = {
907
+ linear: function(p) { return p; },
908
+ swing: function(p) { return 0.5 - Math.cos( p * Math.PI ) / 2 },
909
+ /* Bonus "spring" easing, which is a less exaggerated version of easeInOutElastic. */
910
+ spring: function(p) { return 1 - (Math.cos(p * 4.5 * Math.PI) * Math.exp(-p * 6)); }
911
+ };
912
+
913
+ /* CSS3 and Robert Penner easings. */
914
+ $.each(
915
+ [
916
+ [ "ease", [ 0.25, 0.1, 0.25, 1.0 ] ],
917
+ [ "ease-in", [ 0.42, 0.0, 1.00, 1.0 ] ],
918
+ [ "ease-out", [ 0.00, 0.0, 0.58, 1.0 ] ],
919
+ [ "ease-in-out", [ 0.42, 0.0, 0.58, 1.0 ] ],
920
+ [ "easeInSine", [ 0.47, 0, 0.745, 0.715 ] ],
921
+ [ "easeOutSine", [ 0.39, 0.575, 0.565, 1 ] ],
922
+ [ "easeInOutSine", [ 0.445, 0.05, 0.55, 0.95 ] ],
923
+ [ "easeInQuad", [ 0.55, 0.085, 0.68, 0.53 ] ],
924
+ [ "easeOutQuad", [ 0.25, 0.46, 0.45, 0.94 ] ],
925
+ [ "easeInOutQuad", [ 0.455, 0.03, 0.515, 0.955 ] ],
926
+ [ "easeInCubic", [ 0.55, 0.055, 0.675, 0.19 ] ],
927
+ [ "easeOutCubic", [ 0.215, 0.61, 0.355, 1 ] ],
928
+ [ "easeInOutCubic", [ 0.645, 0.045, 0.355, 1 ] ],
929
+ [ "easeInQuart", [ 0.895, 0.03, 0.685, 0.22 ] ],
930
+ [ "easeOutQuart", [ 0.165, 0.84, 0.44, 1 ] ],
931
+ [ "easeInOutQuart", [ 0.77, 0, 0.175, 1 ] ],
932
+ [ "easeInQuint", [ 0.755, 0.05, 0.855, 0.06 ] ],
933
+ [ "easeOutQuint", [ 0.23, 1, 0.32, 1 ] ],
934
+ [ "easeInOutQuint", [ 0.86, 0, 0.07, 1 ] ],
935
+ [ "easeInExpo", [ 0.95, 0.05, 0.795, 0.035 ] ],
936
+ [ "easeOutExpo", [ 0.19, 1, 0.22, 1 ] ],
937
+ [ "easeInOutExpo", [ 1, 0, 0, 1 ] ],
938
+ [ "easeInCirc", [ 0.6, 0.04, 0.98, 0.335 ] ],
939
+ [ "easeOutCirc", [ 0.075, 0.82, 0.165, 1 ] ],
940
+ [ "easeInOutCirc", [ 0.785, 0.135, 0.15, 0.86 ] ]
941
+ ], function(i, easingArray) {
942
+ Velocity.Easings[easingArray[0]] = generateBezier.apply(null, easingArray[1]);
943
+ });
944
+
945
+ /* Determine the appropriate easing type given an easing input. */
946
+ function getEasing(value, duration) {
947
+ var easing = value;
948
+
949
+ /* The easing option can either be a string that references a pre-registered easing,
950
+ or it can be a two-/four-item array of integers to be converted into a bezier/spring function. */
951
+ if (Type.isString(value)) {
952
+ /* Ensure that the easing has been assigned to jQuery's Velocity.Easings object. */
953
+ if (!Velocity.Easings[value]) {
954
+ easing = false;
955
+ }
956
+ } else if (Type.isArray(value) && value.length === 1) {
957
+ easing = generateStep.apply(null, value);
958
+ } else if (Type.isArray(value) && value.length === 2) {
959
+ /* springRK4 must be passed the animation's duration. */
960
+ /* Note: If the springRK4 array contains non-numbers, generateSpringRK4() returns an easing
961
+ function generated with default tension and friction values. */
962
+ easing = generateSpringRK4.apply(null, value.concat([ duration ]));
963
+ } else if (Type.isArray(value) && value.length === 4) {
964
+ /* Note: If the bezier array contains non-numbers, generateBezier() returns false. */
965
+ easing = generateBezier.apply(null, value);
966
+ } else {
967
+ easing = false;
968
+ }
969
+
970
+ /* Revert to the Velocity-wide default easing type, or fall back to "swing" (which is also jQuery's default)
971
+ if the Velocity-wide default has been incorrectly modified. */
972
+ if (easing === false) {
973
+ if (Velocity.Easings[Velocity.defaults.easing]) {
974
+ easing = Velocity.defaults.easing;
975
+ } else {
976
+ easing = EASING_DEFAULT;
977
+ }
978
+ }
979
+
980
+ return easing;
981
+ }
982
+
983
+ /*****************
984
+ CSS Stack
985
+ *****************/
986
+
987
+ /* The CSS object is a highly condensed and performant CSS stack that fully replaces jQuery's.
988
+ It handles the validation, getting, and setting of both standard CSS properties and CSS property hooks. */
989
+ /* Note: A "CSS" shorthand is aliased so that our code is easier to read. */
990
+ var CSS = Velocity.CSS = {
991
+
992
+ /*************
993
+ RegEx
994
+ *************/
995
+
996
+ RegEx: {
997
+ isHex: /^#([A-f\d]{3}){1,2}$/i,
998
+ /* Unwrap a property value's surrounding text, e.g. "rgba(4, 3, 2, 1)" ==> "4, 3, 2, 1" and "rect(4px 3px 2px 1px)" ==> "4px 3px 2px 1px". */
999
+ valueUnwrap: /^[A-z]+\((.*)\)$/i,
1000
+ wrappedValueAlreadyExtracted: /[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,
1001
+ /* Split a multi-value property into an array of subvalues, e.g. "rgba(4, 3, 2, 1) 4px 3px 2px 1px" ==> [ "rgba(4, 3, 2, 1)", "4px", "3px", "2px", "1px" ]. */
1002
+ valueSplit: /([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/ig
1003
+ },
1004
+
1005
+ /************
1006
+ Lists
1007
+ ************/
1008
+
1009
+ Lists: {
1010
+ colors: [ "fill", "stroke", "stopColor", "color", "backgroundColor", "borderColor", "borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor", "outlineColor" ],
1011
+ transformsBase: [ "translateX", "translateY", "scale", "scaleX", "scaleY", "skewX", "skewY", "rotateZ" ],
1012
+ transforms3D: [ "transformPerspective", "translateZ", "scaleZ", "rotateX", "rotateY" ]
1013
+ },
1014
+
1015
+ /************
1016
+ Hooks
1017
+ ************/
1018
+
1019
+ /* Hooks allow a subproperty (e.g. "boxShadowBlur") of a compound-value CSS property
1020
+ (e.g. "boxShadow: X Y Blur Spread Color") to be animated as if it were a discrete property. */
1021
+ /* Note: Beyond enabling fine-grained property animation, hooking is necessary since Velocity only
1022
+ tweens properties with single numeric values; unlike CSS transitions, Velocity does not interpolate compound-values. */
1023
+ Hooks: {
1024
+ /********************
1025
+ Registration
1026
+ ********************/
1027
+
1028
+ /* Templates are a concise way of indicating which subproperties must be individually registered for each compound-value CSS property. */
1029
+ /* Each template consists of the compound-value's base name, its constituent subproperty names, and those subproperties' default values. */
1030
+ templates: {
1031
+ "textShadow": [ "Color X Y Blur", "black 0px 0px 0px" ],
1032
+ /* Todo: Add support for inset boxShadows. (webkit places it last whereas IE places it first.) */
1033
+ "boxShadow": [ "Color X Y Blur Spread", "black 0px 0px 0px 0px" ],
1034
+ "clip": [ "Top Right Bottom Left", "0px 0px 0px 0px" ],
1035
+ "backgroundPosition": [ "X Y", "0% 0%" ],
1036
+ "transformOrigin": [ "X Y Z", "50% 50% 0px" ],
1037
+ "perspectiveOrigin": [ "X Y", "50% 50%" ]
1038
+ },
1039
+
1040
+ /* A "registered" hook is one that has been converted from its template form into a live,
1041
+ tweenable property. It contains data to associate it with its root property. */
1042
+ registered: {
1043
+ /* Note: A registered hook looks like this ==> textShadowBlur: [ "textShadow", 3 ],
1044
+ which consists of the subproperty's name, the associated root property's name,
1045
+ and the subproperty's position in the root's value. */
1046
+ },
1047
+ /* Convert the templates into individual hooks then append them to the registered object above. */
1048
+ register: function () {
1049
+ /* Color hooks registration: Colors are defaulted to white -- as opposed to black -- since colors that are
1050
+ currently set to "transparent" default to their respective template below when color-animated,
1051
+ and white is typically a closer match to transparent than black is. An exception is made for text ("color"),
1052
+ which is almost always set closer to black than white. */
1053
+ for (var i = 0; i < CSS.Lists.colors.length; i++) {
1054
+ var rgbComponents = (CSS.Lists.colors[i] === "color") ? "0 0 0 1" : "255 255 255 1";
1055
+ CSS.Hooks.templates[CSS.Lists.colors[i]] = [ "Red Green Blue Alpha", rgbComponents ];
1056
+ }
1057
+
1058
+ var rootProperty,
1059
+ hookTemplate,
1060
+ hookNames;
1061
+
1062
+ /* In IE, color values inside compound-value properties are positioned at the end the value instead of at the beginning.
1063
+ Thus, we re-arrange the templates accordingly. */
1064
+ if (IE) {
1065
+ for (rootProperty in CSS.Hooks.templates) {
1066
+ hookTemplate = CSS.Hooks.templates[rootProperty];
1067
+ hookNames = hookTemplate[0].split(" ");
1068
+
1069
+ var defaultValues = hookTemplate[1].match(CSS.RegEx.valueSplit);
1070
+
1071
+ if (hookNames[0] === "Color") {
1072
+ /* Reposition both the hook's name and its default value to the end of their respective strings. */
1073
+ hookNames.push(hookNames.shift());
1074
+ defaultValues.push(defaultValues.shift());
1075
+
1076
+ /* Replace the existing template for the hook's root property. */
1077
+ CSS.Hooks.templates[rootProperty] = [ hookNames.join(" "), defaultValues.join(" ") ];
1078
+ }
1079
+ }
1080
+ }
1081
+
1082
+ /* Hook registration. */
1083
+ for (rootProperty in CSS.Hooks.templates) {
1084
+ hookTemplate = CSS.Hooks.templates[rootProperty];
1085
+ hookNames = hookTemplate[0].split(" ");
1086
+
1087
+ for (var i in hookNames) {
1088
+ var fullHookName = rootProperty + hookNames[i],
1089
+ hookPosition = i;
1090
+
1091
+ /* For each hook, register its full name (e.g. textShadowBlur) with its root property (e.g. textShadow)
1092
+ and the hook's position in its template's default value string. */
1093
+ CSS.Hooks.registered[fullHookName] = [ rootProperty, hookPosition ];
1094
+ }
1095
+ }
1096
+ },
1097
+
1098
+ /*****************************
1099
+ Injection and Extraction
1100
+ *****************************/
1101
+
1102
+ /* Look up the root property associated with the hook (e.g. return "textShadow" for "textShadowBlur"). */
1103
+ /* Since a hook cannot be set directly (the browser won't recognize it), style updating for hooks is routed through the hook's root property. */
1104
+ getRoot: function (property) {
1105
+ var hookData = CSS.Hooks.registered[property];
1106
+
1107
+ if (hookData) {
1108
+ return hookData[0];
1109
+ } else {
1110
+ /* If there was no hook match, return the property name untouched. */
1111
+ return property;
1112
+ }
1113
+ },
1114
+ /* Convert any rootPropertyValue, null or otherwise, into a space-delimited list of hook values so that
1115
+ the targeted hook can be injected or extracted at its standard position. */
1116
+ cleanRootPropertyValue: function(rootProperty, rootPropertyValue) {
1117
+ /* If the rootPropertyValue is wrapped with "rgb()", "clip()", etc., remove the wrapping to normalize the value before manipulation. */
1118
+ if (CSS.RegEx.valueUnwrap.test(rootPropertyValue)) {
1119
+ rootPropertyValue = rootPropertyValue.match(CSS.RegEx.valueUnwrap)[1];
1120
+ }
1121
+
1122
+ /* If rootPropertyValue is a CSS null-value (from which there's inherently no hook value to extract),
1123
+ default to the root's default value as defined in CSS.Hooks.templates. */
1124
+ /* Note: CSS null-values include "none", "auto", and "transparent". They must be converted into their
1125
+ zero-values (e.g. textShadow: "none" ==> textShadow: "0px 0px 0px black") for hook manipulation to proceed. */
1126
+ if (CSS.Values.isCSSNullValue(rootPropertyValue)) {
1127
+ rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
1128
+ }
1129
+
1130
+ return rootPropertyValue;
1131
+ },
1132
+ /* Extracted the hook's value from its root property's value. This is used to get the starting value of an animating hook. */
1133
+ extractValue: function (fullHookName, rootPropertyValue) {
1134
+ var hookData = CSS.Hooks.registered[fullHookName];
1135
+
1136
+ if (hookData) {
1137
+ var hookRoot = hookData[0],
1138
+ hookPosition = hookData[1];
1139
+
1140
+ rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);
1141
+
1142
+ /* Split rootPropertyValue into its constituent hook values then grab the desired hook at its standard position. */
1143
+ return rootPropertyValue.toString().match(CSS.RegEx.valueSplit)[hookPosition];
1144
+ } else {
1145
+ /* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
1146
+ return rootPropertyValue;
1147
+ }
1148
+ },
1149
+ /* Inject the hook's value into its root property's value. This is used to piece back together the root property
1150
+ once Velocity has updated one of its individually hooked values through tweening. */
1151
+ injectValue: function (fullHookName, hookValue, rootPropertyValue) {
1152
+ var hookData = CSS.Hooks.registered[fullHookName];
1153
+
1154
+ if (hookData) {
1155
+ var hookRoot = hookData[0],
1156
+ hookPosition = hookData[1],
1157
+ rootPropertyValueParts,
1158
+ rootPropertyValueUpdated;
1159
+
1160
+ rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);
1161
+
1162
+ /* Split rootPropertyValue into its individual hook values, replace the targeted value with hookValue,
1163
+ then reconstruct the rootPropertyValue string. */
1164
+ rootPropertyValueParts = rootPropertyValue.toString().match(CSS.RegEx.valueSplit);
1165
+ rootPropertyValueParts[hookPosition] = hookValue;
1166
+ rootPropertyValueUpdated = rootPropertyValueParts.join(" ");
1167
+
1168
+ return rootPropertyValueUpdated;
1169
+ } else {
1170
+ /* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
1171
+ return rootPropertyValue;
1172
+ }
1173
+ }
1174
+ },
1175
+
1176
+ /*******************
1177
+ Normalizations
1178
+ *******************/
1179
+
1180
+ /* Normalizations standardize CSS property manipulation by pollyfilling browser-specific implementations (e.g. opacity)
1181
+ and reformatting special properties (e.g. clip, rgba) to look like standard ones. */
1182
+ Normalizations: {
1183
+ /* Normalizations are passed a normalization target (either the property's name, its extracted value, or its injected value),
1184
+ the targeted element (which may need to be queried), and the targeted property value. */
1185
+ registered: {
1186
+ clip: function (type, element, propertyValue) {
1187
+ switch (type) {
1188
+ case "name":
1189
+ return "clip";
1190
+ /* Clip needs to be unwrapped and stripped of its commas during extraction. */
1191
+ case "extract":
1192
+ var extracted;
1193
+
1194
+ /* If Velocity also extracted this value, skip extraction. */
1195
+ if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
1196
+ extracted = propertyValue;
1197
+ } else {
1198
+ /* Remove the "rect()" wrapper. */
1199
+ extracted = propertyValue.toString().match(CSS.RegEx.valueUnwrap);
1200
+
1201
+ /* Strip off commas. */
1202
+ extracted = extracted ? extracted[1].replace(/,(\s+)?/g, " ") : propertyValue;
1203
+ }
1204
+
1205
+ return extracted;
1206
+ /* Clip needs to be re-wrapped during injection. */
1207
+ case "inject":
1208
+ return "rect(" + propertyValue + ")";
1209
+ }
1210
+ },
1211
+
1212
+ blur: function(type, element, propertyValue) {
1213
+ switch (type) {
1214
+ case "name":
1215
+ return "-webkit-filter";
1216
+ case "extract":
1217
+ var extracted = parseFloat(propertyValue);
1218
+
1219
+ /* If extracted is NaN, meaning the value isn't already extracted. */
1220
+ if (!(extracted || extracted === 0)) {
1221
+ var blurComponent = propertyValue.toString().match(/blur\(([0-9]+[A-z]+)\)/i);
1222
+
1223
+ /* If the filter string had a blur component, return just the blur value and unit type. */
1224
+ if (blurComponent) {
1225
+ extracted = blurComponent[1];
1226
+ /* If the component doesn't exist, default blur to 0. */
1227
+ } else {
1228
+ extracted = 0;
1229
+ }
1230
+ }
1231
+
1232
+ return extracted;
1233
+ /* Blur needs to be re-wrapped during injection. */
1234
+ case "inject":
1235
+ /* For the blur effect to be fully de-applied, it needs to be set to "none" instead of 0. */
1236
+ if (!parseFloat(propertyValue)) {
1237
+ return "none";
1238
+ } else {
1239
+ return "blur(" + propertyValue + ")";
1240
+ }
1241
+ }
1242
+ },
1243
+
1244
+ /* <=IE8 do not support the standard opacity property. They use filter:alpha(opacity=INT) instead. */
1245
+ opacity: function (type, element, propertyValue) {
1246
+ if (IE <= 8) {
1247
+ switch (type) {
1248
+ case "name":
1249
+ return "filter";
1250
+ case "extract":
1251
+ /* <=IE8 return a "filter" value of "alpha(opacity=\d{1,3})".
1252
+ Extract the value and convert it to a decimal value to match the standard CSS opacity property's formatting. */
1253
+ var extracted = propertyValue.toString().match(/alpha\(opacity=(.*)\)/i);
1254
+
1255
+ if (extracted) {
1256
+ /* Convert to decimal value. */
1257
+ propertyValue = extracted[1] / 100;
1258
+ } else {
1259
+ /* When extracting opacity, default to 1 since a null value means opacity hasn't been set. */
1260
+ propertyValue = 1;
1261
+ }
1262
+
1263
+ return propertyValue;
1264
+ case "inject":
1265
+ /* Opacified elements are required to have their zoom property set to a non-zero value. */
1266
+ element.style.zoom = 1;
1267
+
1268
+ /* Setting the filter property on elements with certain font property combinations can result in a
1269
+ highly unappealing ultra-bolding effect. There's no way to remedy this throughout a tween, but dropping the
1270
+ value altogether (when opacity hits 1) at leasts ensures that the glitch is gone post-tweening. */
1271
+ if (parseFloat(propertyValue) >= 1) {
1272
+ return "";
1273
+ } else {
1274
+ /* As per the filter property's spec, convert the decimal value to a whole number and wrap the value. */
1275
+ return "alpha(opacity=" + parseInt(parseFloat(propertyValue) * 100, 10) + ")";
1276
+ }
1277
+ }
1278
+ /* With all other browsers, normalization is not required; return the same values that were passed in. */
1279
+ } else {
1280
+ switch (type) {
1281
+ case "name":
1282
+ return "opacity";
1283
+ case "extract":
1284
+ return propertyValue;
1285
+ case "inject":
1286
+ return propertyValue;
1287
+ }
1288
+ }
1289
+ }
1290
+ },
1291
+
1292
+ /*****************************
1293
+ Batched Registrations
1294
+ *****************************/
1295
+
1296
+ /* Note: Batched normalizations extend the CSS.Normalizations.registered object. */
1297
+ register: function () {
1298
+
1299
+ /*****************
1300
+ Transforms
1301
+ *****************/
1302
+
1303
+ /* Transforms are the subproperties contained by the CSS "transform" property. Transforms must undergo normalization
1304
+ so that they can be referenced in a properties map by their individual names. */
1305
+ /* Note: When transforms are "set", they are actually assigned to a per-element transformCache. When all transform
1306
+ setting is complete complete, CSS.flushTransformCache() must be manually called to flush the values to the DOM.
1307
+ Transform setting is batched in this way to improve performance: the transform style only needs to be updated
1308
+ once when multiple transform subproperties are being animated simultaneously. */
1309
+ /* Note: IE9 and Android Gingerbread have support for 2D -- but not 3D -- transforms. Since animating unsupported
1310
+ transform properties results in the browser ignoring the *entire* transform string, we prevent these 3D values
1311
+ from being normalized for these browsers so that tweening skips these properties altogether
1312
+ (since it will ignore them as being unsupported by the browser.) */
1313
+ if (!(IE <= 9) && !Velocity.State.isGingerbread) {
1314
+ /* Note: Since the standalone CSS "perspective" property and the CSS transform "perspective" subproperty
1315
+ share the same name, the latter is given a unique token within Velocity: "transformPerspective". */
1316
+ CSS.Lists.transformsBase = CSS.Lists.transformsBase.concat(CSS.Lists.transforms3D);
1317
+ }
1318
+
1319
+ for (var i = 0; i < CSS.Lists.transformsBase.length; i++) {
1320
+ /* Wrap the dynamically generated normalization function in a new scope so that transformName's value is
1321
+ paired with its respective function. (Otherwise, all functions would take the final for loop's transformName.) */
1322
+ (function() {
1323
+ var transformName = CSS.Lists.transformsBase[i];
1324
+
1325
+ CSS.Normalizations.registered[transformName] = function (type, element, propertyValue) {
1326
+ switch (type) {
1327
+ /* The normalized property name is the parent "transform" property -- the property that is actually set in CSS. */
1328
+ case "name":
1329
+ return "transform";
1330
+ /* Transform values are cached onto a per-element transformCache object. */
1331
+ case "extract":
1332
+ /* If this transform has yet to be assigned a value, return its null value. */
1333
+ if (Data(element) === undefined || Data(element).transformCache[transformName] === undefined) {
1334
+ /* Scale CSS.Lists.transformsBase default to 1 whereas all other transform properties default to 0. */
1335
+ return /^scale/i.test(transformName) ? 1 : 0;
1336
+ /* When transform values are set, they are wrapped in parentheses as per the CSS spec.
1337
+ Thus, when extracting their values (for tween calculations), we strip off the parentheses. */
1338
+ } else {
1339
+ return Data(element).transformCache[transformName].replace(/[()]/g, "");
1340
+ }
1341
+ case "inject":
1342
+ var invalid = false;
1343
+
1344
+ /* If an individual transform property contains an unsupported unit type, the browser ignores the *entire* transform property.
1345
+ Thus, protect users from themselves by skipping setting for transform values supplied with invalid unit types. */
1346
+ /* Switch on the base transform type; ignore the axis by removing the last letter from the transform's name. */
1347
+ switch (transformName.substr(0, transformName.length - 1)) {
1348
+ /* Whitelist unit types for each transform. */
1349
+ case "translate":
1350
+ invalid = !/(%|px|em|rem|vw|vh|\d)$/i.test(propertyValue);
1351
+ break;
1352
+ /* Since an axis-free "scale" property is supported as well, a little hack is used here to detect it by chopping off its last letter. */
1353
+ case "scal":
1354
+ case "scale":
1355
+ /* Chrome on Android has a bug in which scaled elements blur if their initial scale
1356
+ value is below 1 (which can happen with forcefeeding). Thus, we detect a yet-unset scale property
1357
+ and ensure that its first value is always 1. More info: http://stackoverflow.com/questions/10417890/css3-animations-with-transform-causes-blurred-elements-on-webkit/10417962#10417962 */
1358
+ if (Velocity.State.isAndroid && Data(element).transformCache[transformName] === undefined && propertyValue < 1) {
1359
+ propertyValue = 1;
1360
+ }
1361
+
1362
+ invalid = !/(\d)$/i.test(propertyValue);
1363
+ break;
1364
+ case "skew":
1365
+ invalid = !/(deg|\d)$/i.test(propertyValue);
1366
+ break;
1367
+ case "rotate":
1368
+ invalid = !/(deg|\d)$/i.test(propertyValue);
1369
+ break;
1370
+ }
1371
+
1372
+ if (!invalid) {
1373
+ /* As per the CSS spec, wrap the value in parentheses. */
1374
+ Data(element).transformCache[transformName] = "(" + propertyValue + ")";
1375
+ }
1376
+
1377
+ /* Although the value is set on the transformCache object, return the newly-updated value for the calling code to process as normal. */
1378
+ return Data(element).transformCache[transformName];
1379
+ }
1380
+ };
1381
+ })();
1382
+ }
1383
+
1384
+ /*************
1385
+ Colors
1386
+ *************/
1387
+
1388
+ /* Since Velocity only animates a single numeric value per property, color animation is achieved by hooking the individual RGBA components of CSS color properties.
1389
+ Accordingly, color values must be normalized (e.g. "#ff0000", "red", and "rgb(255, 0, 0)" ==> "255 0 0 1") so that their components can be injected/extracted by CSS.Hooks logic. */
1390
+ for (var i = 0; i < CSS.Lists.colors.length; i++) {
1391
+ /* Wrap the dynamically generated normalization function in a new scope so that colorName's value is paired with its respective function.
1392
+ (Otherwise, all functions would take the final for loop's colorName.) */
1393
+ (function () {
1394
+ var colorName = CSS.Lists.colors[i];
1395
+
1396
+ /* Note: In IE<=8, which support rgb but not rgba, color properties are reverted to rgb by stripping off the alpha component. */
1397
+ CSS.Normalizations.registered[colorName] = function(type, element, propertyValue) {
1398
+ switch (type) {
1399
+ case "name":
1400
+ return colorName;
1401
+ /* Convert all color values into the rgb format. (Old IE can return hex values and color names instead of rgb/rgba.) */
1402
+ case "extract":
1403
+ var extracted;
1404
+
1405
+ /* If the color is already in its hookable form (e.g. "255 255 255 1") due to having been previously extracted, skip extraction. */
1406
+ if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
1407
+ extracted = propertyValue;
1408
+ } else {
1409
+ var converted,
1410
+ colorNames = {
1411
+ black: "rgb(0, 0, 0)",
1412
+ blue: "rgb(0, 0, 255)",
1413
+ gray: "rgb(128, 128, 128)",
1414
+ green: "rgb(0, 128, 0)",
1415
+ red: "rgb(255, 0, 0)",
1416
+ white: "rgb(255, 255, 255)"
1417
+ };
1418
+
1419
+ /* Convert color names to rgb. */
1420
+ if (/^[A-z]+$/i.test(propertyValue)) {
1421
+ if (colorNames[propertyValue] !== undefined) {
1422
+ converted = colorNames[propertyValue]
1423
+ } else {
1424
+ /* If an unmatched color name is provided, default to black. */
1425
+ converted = colorNames.black;
1426
+ }
1427
+ /* Convert hex values to rgb. */
1428
+ } else if (CSS.RegEx.isHex.test(propertyValue)) {
1429
+ converted = "rgb(" + CSS.Values.hexToRgb(propertyValue).join(" ") + ")";
1430
+ /* If the provided color doesn't match any of the accepted color formats, default to black. */
1431
+ } else if (!(/^rgba?\(/i.test(propertyValue))) {
1432
+ converted = colorNames.black;
1433
+ }
1434
+
1435
+ /* Remove the surrounding "rgb/rgba()" string then replace commas with spaces and strip
1436
+ repeated spaces (in case the value included spaces to begin with). */
1437
+ extracted = (converted || propertyValue).toString().match(CSS.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g, " ");
1438
+ }
1439
+
1440
+ /* So long as this isn't <=IE8, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
1441
+ if (!(IE <= 8) && extracted.split(" ").length === 3) {
1442
+ extracted += " 1";
1443
+ }
1444
+
1445
+ return extracted;
1446
+ case "inject":
1447
+ /* If this is IE<=8 and an alpha component exists, strip it off. */
1448
+ if (IE <= 8) {
1449
+ if (propertyValue.split(" ").length === 4) {
1450
+ propertyValue = propertyValue.split(/\s+/).slice(0, 3).join(" ");
1451
+ }
1452
+ /* Otherwise, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
1453
+ } else if (propertyValue.split(" ").length === 3) {
1454
+ propertyValue += " 1";
1455
+ }
1456
+
1457
+ /* Re-insert the browser-appropriate wrapper("rgb/rgba()"), insert commas, and strip off decimal units
1458
+ on all values but the fourth (R, G, and B only accept whole numbers). */
1459
+ return (IE <= 8 ? "rgb" : "rgba") + "(" + propertyValue.replace(/\s+/g, ",").replace(/\.(\d)+(?=,)/g, "") + ")";
1460
+ }
1461
+ };
1462
+ })();
1463
+ }
1464
+ }
1465
+ },
1466
+
1467
+ /************************
1468
+ CSS Property Names
1469
+ ************************/
1470
+
1471
+ Names: {
1472
+ /* Camelcase a property name into its JavaScript notation (e.g. "background-color" ==> "backgroundColor").
1473
+ Camelcasing is used to normalize property names between and across calls. */
1474
+ camelCase: function (property) {
1475
+ return property.replace(/-(\w)/g, function (match, subMatch) {
1476
+ return subMatch.toUpperCase();
1477
+ });
1478
+ },
1479
+
1480
+ /* For SVG elements, some properties (namely, dimensional ones) are GET/SET via the element's HTML attributes (instead of via CSS styles). */
1481
+ SVGAttribute: function (property) {
1482
+ var SVGAttributes = "width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";
1483
+
1484
+ /* Certain browsers require an SVG transform to be applied as an attribute. (Otherwise, application via CSS is preferable due to 3D support.) */
1485
+ if (IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) {
1486
+ SVGAttributes += "|transform";
1487
+ }
1488
+
1489
+ return new RegExp("^(" + SVGAttributes + ")$", "i").test(property);
1490
+ },
1491
+
1492
+ /* Determine whether a property should be set with a vendor prefix. */
1493
+ /* If a prefixed version of the property exists, return it. Otherwise, return the original property name.
1494
+ If the property is not at all supported by the browser, return a false flag. */
1495
+ prefixCheck: function (property) {
1496
+ /* If this property has already been checked, return the cached value. */
1497
+ if (Velocity.State.prefixMatches[property]) {
1498
+ return [ Velocity.State.prefixMatches[property], true ];
1499
+ } else {
1500
+ var vendors = [ "", "Webkit", "Moz", "ms", "O" ];
1501
+
1502
+ for (var i = 0, vendorsLength = vendors.length; i < vendorsLength; i++) {
1503
+ var propertyPrefixed;
1504
+
1505
+ if (i === 0) {
1506
+ propertyPrefixed = property;
1507
+ } else {
1508
+ /* Capitalize the first letter of the property to conform to JavaScript vendor prefix notation (e.g. webkitFilter). */
1509
+ propertyPrefixed = vendors[i] + property.replace(/^\w/, function(match) { return match.toUpperCase(); });
1510
+ }
1511
+
1512
+ /* Check if the browser supports this property as prefixed. */
1513
+ if (Type.isString(Velocity.State.prefixElement.style[propertyPrefixed])) {
1514
+ /* Cache the match. */
1515
+ Velocity.State.prefixMatches[property] = propertyPrefixed;
1516
+
1517
+ return [ propertyPrefixed, true ];
1518
+ }
1519
+ }
1520
+
1521
+ /* If the browser doesn't support this property in any form, include a false flag so that the caller can decide how to proceed. */
1522
+ return [ property, false ];
1523
+ }
1524
+ }
1525
+ },
1526
+
1527
+ /************************
1528
+ CSS Property Values
1529
+ ************************/
1530
+
1531
+ Values: {
1532
+ /* Hex to RGB conversion. Copyright Tim Down: http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb */
1533
+ hexToRgb: function (hex) {
1534
+ var shortformRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i,
1535
+ longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
1536
+ rgbParts;
1537
+
1538
+ hex = hex.replace(shortformRegex, function (m, r, g, b) {
1539
+ return r + r + g + g + b + b;
1540
+ });
1541
+
1542
+ rgbParts = longformRegex.exec(hex);
1543
+
1544
+ return rgbParts ? [ parseInt(rgbParts[1], 16), parseInt(rgbParts[2], 16), parseInt(rgbParts[3], 16) ] : [ 0, 0, 0 ];
1545
+ },
1546
+
1547
+ isCSSNullValue: function (value) {
1548
+ /* The browser defaults CSS values that have not been set to either 0 or one of several possible null-value strings.
1549
+ Thus, we check for both falsiness and these special strings. */
1550
+ /* Null-value checking is performed to default the special strings to 0 (for the sake of tweening) or their hook
1551
+ templates as defined as CSS.Hooks (for the sake of hook injection/extraction). */
1552
+ /* Note: Chrome returns "rgba(0, 0, 0, 0)" for an undefined color whereas IE returns "transparent". */
1553
+ return (value == 0 || /^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(value));
1554
+ },
1555
+
1556
+ /* Retrieve a property's default unit type. Used for assigning a unit type when one is not supplied by the user. */
1557
+ getUnitType: function (property) {
1558
+ if (/^(rotate|skew)/i.test(property)) {
1559
+ return "deg";
1560
+ } else if (/(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(property)) {
1561
+ /* The above properties are unitless. */
1562
+ return "";
1563
+ } else {
1564
+ /* Default to px for all other properties. */
1565
+ return "px";
1566
+ }
1567
+ },
1568
+
1569
+ /* HTML elements default to an associated display type when they're not set to display:none. */
1570
+ /* Note: This function is used for correctly setting the non-"none" display value in certain Velocity redirects, such as fadeIn/Out. */
1571
+ getDisplayType: function (element) {
1572
+ var tagName = element && element.tagName.toString().toLowerCase();
1573
+
1574
+ if (/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(tagName)) {
1575
+ return "inline";
1576
+ } else if (/^(li)$/i.test(tagName)) {
1577
+ return "list-item";
1578
+ } else if (/^(tr)$/i.test(tagName)) {
1579
+ return "table-row";
1580
+ /* Default to "block" when no match is found. */
1581
+ } else {
1582
+ return "block";
1583
+ }
1584
+ },
1585
+
1586
+ /* The class add/remove functions are used to temporarily apply a "velocity-animating" class to elements while they're animating. */
1587
+ addClass: function (element, className) {
1588
+ if (element.classList) {
1589
+ element.classList.add(className);
1590
+ } else {
1591
+ element.className += (element.className.length ? " " : "") + className;
1592
+ }
1593
+ },
1594
+
1595
+ removeClass: function (element, className) {
1596
+ if (element.classList) {
1597
+ element.classList.remove(className);
1598
+ } else {
1599
+ element.className = element.className.toString().replace(new RegExp("(^|\\s)" + className.split(" ").join("|") + "(\\s|$)", "gi"), " ");
1600
+ }
1601
+ }
1602
+ },
1603
+
1604
+ /****************************
1605
+ Style Getting & Setting
1606
+ ****************************/
1607
+
1608
+ /* The singular getPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
1609
+ getPropertyValue: function (element, property, rootPropertyValue, forceStyleLookup) {
1610
+ /* Get an element's computed property value. */
1611
+ /* Note: Retrieving the value of a CSS property cannot simply be performed by checking an element's
1612
+ style attribute (which only reflects user-defined values). Instead, the browser must be queried for a property's
1613
+ *computed* value. You can read more about getComputedStyle here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
1614
+ function computePropertyValue (element, property) {
1615
+ /* When box-sizing isn't set to border-box, height and width style values are incorrectly computed when an
1616
+ element's scrollbars are visible (which expands the element's dimensions). Thus, we defer to the more accurate
1617
+ offsetHeight/Width property, which includes the total dimensions for interior, border, padding, and scrollbar.
1618
+ We subtract border and padding to get the sum of interior + scrollbar. */
1619
+ var computedValue = 0;
1620
+
1621
+ /* IE<=8 doesn't support window.getComputedStyle, thus we defer to jQuery, which has an extensive array
1622
+ of hacks to accurately retrieve IE8 property values. Re-implementing that logic here is not worth bloating the
1623
+ codebase for a dying browser. The performance repercussions of using jQuery here are minimal since
1624
+ Velocity is optimized to rarely (and sometimes never) query the DOM. Further, the $.css() codepath isn't that slow. */
1625
+ if (IE <= 8) {
1626
+ computedValue = $.css(element, property); /* GET */
1627
+ /* All other browsers support getComputedStyle. The returned live object reference is cached onto its
1628
+ associated element so that it does not need to be refetched upon every GET. */
1629
+ } else {
1630
+ /* Browsers do not return height and width values for elements that are set to display:"none". Thus, we temporarily
1631
+ toggle display to the element type's default value. */
1632
+ var toggleDisplay = false;
1633
+
1634
+ if (/^(width|height)$/.test(property) && CSS.getPropertyValue(element, "display") === 0) {
1635
+ toggleDisplay = true;
1636
+ CSS.setPropertyValue(element, "display", CSS.Values.getDisplayType(element));
1637
+ }
1638
+
1639
+ function revertDisplay () {
1640
+ if (toggleDisplay) {
1641
+ CSS.setPropertyValue(element, "display", "none");
1642
+ }
1643
+ }
1644
+
1645
+ if (!forceStyleLookup) {
1646
+ if (property === "height" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
1647
+ var contentBoxHeight = element.offsetHeight - (parseFloat(CSS.getPropertyValue(element, "borderTopWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderBottomWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingTop")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingBottom")) || 0);
1648
+ revertDisplay();
1649
+
1650
+ return contentBoxHeight;
1651
+ } else if (property === "width" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
1652
+ var contentBoxWidth = element.offsetWidth - (parseFloat(CSS.getPropertyValue(element, "borderLeftWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderRightWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingLeft")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingRight")) || 0);
1653
+ revertDisplay();
1654
+
1655
+ return contentBoxWidth;
1656
+ }
1657
+ }
1658
+
1659
+ var computedStyle;
1660
+
1661
+ /* For elements that Velocity hasn't been called on directly (e.g. when Velocity queries the DOM on behalf
1662
+ of a parent of an element its animating), perform a direct getComputedStyle lookup since the object isn't cached. */
1663
+ if (Data(element) === undefined) {
1664
+ computedStyle = window.getComputedStyle(element, null); /* GET */
1665
+ /* If the computedStyle object has yet to be cached, do so now. */
1666
+ } else if (!Data(element).computedStyle) {
1667
+ computedStyle = Data(element).computedStyle = window.getComputedStyle(element, null); /* GET */
1668
+ /* If computedStyle is cached, use it. */
1669
+ } else {
1670
+ computedStyle = Data(element).computedStyle;
1671
+ }
1672
+
1673
+ /* IE and Firefox do not return a value for the generic borderColor -- they only return individual values for each border side's color.
1674
+ As a polyfill for querying individual border side colors, just return the top border's color. */
1675
+ if ((IE || Velocity.State.isFirefox) && property === "borderColor") {
1676
+ property = "borderTopColor";
1677
+ }
1678
+
1679
+ /* IE9 has a bug in which the "filter" property must be accessed from computedStyle using the getPropertyValue method
1680
+ instead of a direct property lookup. The getPropertyValue method is slower than a direct lookup, which is why we avoid it by default. */
1681
+ if (IE === 9 && property === "filter") {
1682
+ computedValue = computedStyle.getPropertyValue(property); /* GET */
1683
+ } else {
1684
+ computedValue = computedStyle[property];
1685
+ }
1686
+
1687
+ /* Fall back to the property's style value (if defined) when computedValue returns nothing,
1688
+ which can happen when the element hasn't been painted. */
1689
+ if (computedValue === "" || computedValue === null) {
1690
+ computedValue = element.style[property];
1691
+ }
1692
+
1693
+ revertDisplay();
1694
+ }
1695
+
1696
+ /* For top, right, bottom, and left (TRBL) values that are set to "auto" on elements of "fixed" or "absolute" position,
1697
+ defer to jQuery for converting "auto" to a numeric value. (For elements with a "static" or "relative" position, "auto" has the same
1698
+ effect as being set to 0, so no conversion is necessary.) */
1699
+ /* An example of why numeric conversion is necessary: When an element with "position:absolute" has an untouched "left"
1700
+ property, which reverts to "auto", left's value is 0 relative to its parent element, but is often non-zero relative
1701
+ to its *containing* (not parent) element, which is the nearest "position:relative" ancestor or the viewport (and always the viewport in the case of "position:fixed"). */
1702
+ if (computedValue === "auto" && /^(top|right|bottom|left)$/i.test(property)) {
1703
+ var position = computePropertyValue(element, "position"); /* GET */
1704
+
1705
+ /* For absolute positioning, jQuery's $.position() only returns values for top and left;
1706
+ right and bottom will have their "auto" value reverted to 0. */
1707
+ /* Note: A jQuery object must be created here since jQuery doesn't have a low-level alias for $.position().
1708
+ Not a big deal since we're currently in a GET batch anyway. */
1709
+ if (position === "fixed" || (position === "absolute" && /top|left/i.test(property))) {
1710
+ /* Note: jQuery strips the pixel unit from its returned values; we re-add it here to conform with computePropertyValue's behavior. */
1711
+ computedValue = $(element).position()[property] + "px"; /* GET */
1712
+ }
1713
+ }
1714
+
1715
+ return computedValue;
1716
+ }
1717
+
1718
+ var propertyValue;
1719
+
1720
+ /* If this is a hooked property (e.g. "clipLeft" instead of the root property of "clip"),
1721
+ extract the hook's value from a normalized rootPropertyValue using CSS.Hooks.extractValue(). */
1722
+ if (CSS.Hooks.registered[property]) {
1723
+ var hook = property,
1724
+ hookRoot = CSS.Hooks.getRoot(hook);
1725
+
1726
+ /* If a cached rootPropertyValue wasn't passed in (which Velocity always attempts to do in order to avoid requerying the DOM),
1727
+ query the DOM for the root property's value. */
1728
+ if (rootPropertyValue === undefined) {
1729
+ /* Since the browser is now being directly queried, use the official post-prefixing property name for this lookup. */
1730
+ rootPropertyValue = CSS.getPropertyValue(element, CSS.Names.prefixCheck(hookRoot)[0]); /* GET */
1731
+ }
1732
+
1733
+ /* If this root has a normalization registered, peform the associated normalization extraction. */
1734
+ if (CSS.Normalizations.registered[hookRoot]) {
1735
+ rootPropertyValue = CSS.Normalizations.registered[hookRoot]("extract", element, rootPropertyValue);
1736
+ }
1737
+
1738
+ /* Extract the hook's value. */
1739
+ propertyValue = CSS.Hooks.extractValue(hook, rootPropertyValue);
1740
+
1741
+ /* If this is a normalized property (e.g. "opacity" becomes "filter" in <=IE8) or "translateX" becomes "transform"),
1742
+ normalize the property's name and value, and handle the special case of transforms. */
1743
+ /* Note: Normalizing a property is mutually exclusive from hooking a property since hook-extracted values are strictly
1744
+ numerical and therefore do not require normalization extraction. */
1745
+ } else if (CSS.Normalizations.registered[property]) {
1746
+ var normalizedPropertyName,
1747
+ normalizedPropertyValue;
1748
+
1749
+ normalizedPropertyName = CSS.Normalizations.registered[property]("name", element);
1750
+
1751
+ /* Transform values are calculated via normalization extraction (see below), which checks against the element's transformCache.
1752
+ At no point do transform GETs ever actually query the DOM; initial stylesheet values are never processed.
1753
+ This is because parsing 3D transform matrices is not always accurate and would bloat our codebase;
1754
+ thus, normalization extraction defaults initial transform values to their zero-values (e.g. 1 for scaleX and 0 for translateX). */
1755
+ if (normalizedPropertyName !== "transform") {
1756
+ normalizedPropertyValue = computePropertyValue(element, CSS.Names.prefixCheck(normalizedPropertyName)[0]); /* GET */
1757
+
1758
+ /* If the value is a CSS null-value and this property has a hook template, use that zero-value template so that hooks can be extracted from it. */
1759
+ if (CSS.Values.isCSSNullValue(normalizedPropertyValue) && CSS.Hooks.templates[property]) {
1760
+ normalizedPropertyValue = CSS.Hooks.templates[property][1];
1761
+ }
1762
+ }
1763
+
1764
+ propertyValue = CSS.Normalizations.registered[property]("extract", element, normalizedPropertyValue);
1765
+ }
1766
+
1767
+ /* If a (numeric) value wasn't produced via hook extraction or normalization, query the DOM. */
1768
+ if (!/^[\d-]/.test(propertyValue)) {
1769
+ /* For SVG elements, dimensional properties (which SVGAttribute() detects) are tweened via
1770
+ their HTML attribute values instead of their CSS style values. */
1771
+ if (Data(element) && Data(element).isSVG && CSS.Names.SVGAttribute(property)) {
1772
+ /* Since the height/width attribute values must be set manually, they don't reflect computed values.
1773
+ Thus, we use use getBBox() to ensure we always get values for elements with undefined height/width attributes. */
1774
+ if (/^(height|width)$/i.test(property)) {
1775
+ propertyValue = element.getBBox()[property];
1776
+ /* Otherwise, access the attribute value directly. */
1777
+ } else {
1778
+ propertyValue = element.getAttribute(property);
1779
+ }
1780
+ } else {
1781
+ propertyValue = computePropertyValue(element, CSS.Names.prefixCheck(property)[0]); /* GET */
1782
+ }
1783
+ }
1784
+
1785
+ /* Since property lookups are for animation purposes (which entails computing the numeric delta between start and end values),
1786
+ convert CSS null-values to an integer of value 0. */
1787
+ if (CSS.Values.isCSSNullValue(propertyValue)) {
1788
+ propertyValue = 0;
1789
+ }
1790
+
1791
+ if (Velocity.debug >= 2) console.log("Get " + property + ": " + propertyValue);
1792
+
1793
+ return propertyValue;
1794
+ },
1795
+
1796
+ /* The singular setPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
1797
+ setPropertyValue: function(element, property, propertyValue, rootPropertyValue, scrollData) {
1798
+ var propertyName = property;
1799
+
1800
+ /* In order to be subjected to call options and element queueing, scroll animation is routed through Velocity as if it were a standard CSS property. */
1801
+ if (property === "scroll") {
1802
+ /* If a container option is present, scroll the container instead of the browser window. */
1803
+ if (scrollData.container) {
1804
+ scrollData.container["scroll" + scrollData.direction] = propertyValue;
1805
+ /* Otherwise, Velocity defaults to scrolling the browser window. */
1806
+ } else {
1807
+ if (scrollData.direction === "Left") {
1808
+ window.scrollTo(propertyValue, scrollData.alternateValue);
1809
+ } else {
1810
+ window.scrollTo(scrollData.alternateValue, propertyValue);
1811
+ }
1812
+ }
1813
+ } else {
1814
+ /* Transforms (translateX, rotateZ, etc.) are applied to a per-element transformCache object, which is manually flushed via flushTransformCache().
1815
+ Thus, for now, we merely cache transforms being SET. */
1816
+ if (CSS.Normalizations.registered[property] && CSS.Normalizations.registered[property]("name", element) === "transform") {
1817
+ /* Perform a normalization injection. */
1818
+ /* Note: The normalization logic handles the transformCache updating. */
1819
+ CSS.Normalizations.registered[property]("inject", element, propertyValue);
1820
+
1821
+ propertyName = "transform";
1822
+ propertyValue = Data(element).transformCache[property];
1823
+ } else {
1824
+ /* Inject hooks. */
1825
+ if (CSS.Hooks.registered[property]) {
1826
+ var hookName = property,
1827
+ hookRoot = CSS.Hooks.getRoot(property);
1828
+
1829
+ /* If a cached rootPropertyValue was not provided, query the DOM for the hookRoot's current value. */
1830
+ rootPropertyValue = rootPropertyValue || CSS.getPropertyValue(element, hookRoot); /* GET */
1831
+
1832
+ propertyValue = CSS.Hooks.injectValue(hookName, propertyValue, rootPropertyValue);
1833
+ property = hookRoot;
1834
+ }
1835
+
1836
+ /* Normalize names and values. */
1837
+ if (CSS.Normalizations.registered[property]) {
1838
+ propertyValue = CSS.Normalizations.registered[property]("inject", element, propertyValue);
1839
+ property = CSS.Normalizations.registered[property]("name", element);
1840
+ }
1841
+
1842
+ /* Assign the appropriate vendor prefix before performing an official style update. */
1843
+ propertyName = CSS.Names.prefixCheck(property)[0];
1844
+
1845
+ /* A try/catch is used for IE<=8, which throws an error when "invalid" CSS values are set, e.g. a negative width.
1846
+ Try/catch is avoided for other browsers since it incurs a performance overhead. */
1847
+ if (IE <= 8) {
1848
+ try {
1849
+ element.style[propertyName] = propertyValue;
1850
+ } catch (error) { if (Velocity.debug) console.log("Browser does not support [" + propertyValue + "] for [" + propertyName + "]"); }
1851
+ /* SVG elements have their dimensional properties (width, height, x, y, cx, etc.) applied directly as attributes instead of as styles. */
1852
+ /* Note: IE8 does not support SVG elements, so it's okay that we skip it for SVG animation. */
1853
+ } else if (Data(element) && Data(element).isSVG && CSS.Names.SVGAttribute(property)) {
1854
+ /* Note: For SVG attributes, vendor-prefixed property names are never used. */
1855
+ /* Note: Not all CSS properties can be animated via attributes, but the browser won't throw an error for unsupported properties. */
1856
+ element.setAttribute(property, propertyValue);
1857
+ } else {
1858
+ element.style[propertyName] = propertyValue;
1859
+ }
1860
+
1861
+ if (Velocity.debug >= 2) console.log("Set " + property + " (" + propertyName + "): " + propertyValue);
1862
+ }
1863
+ }
1864
+
1865
+ /* Return the normalized property name and value in case the caller wants to know how these values were modified before being applied to the DOM. */
1866
+ return [ propertyName, propertyValue ];
1867
+ },
1868
+
1869
+ /* To increase performance by batching transform updates into a single SET, transforms are not directly applied to an element until flushTransformCache() is called. */
1870
+ /* Note: Velocity applies transform properties in the same order that they are chronogically introduced to the element's CSS styles. */
1871
+ flushTransformCache: function(element) {
1872
+ var transformString = "";
1873
+
1874
+ /* Certain browsers require that SVG transforms be applied as an attribute. However, the SVG transform attribute takes a modified version of CSS's transform string
1875
+ (units are dropped and, except for skewX/Y, subproperties are merged into their master property -- e.g. scaleX and scaleY are merged into scale(X Y). */
1876
+ if ((IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) && Data(element).isSVG) {
1877
+ /* Since transform values are stored in their parentheses-wrapped form, we use a helper function to strip out their numeric values.
1878
+ Further, SVG transform properties only take unitless (representing pixels) values, so it's okay that parseFloat() strips the unit suffixed to the float value. */
1879
+ function getTransformFloat (transformProperty) {
1880
+ return parseFloat(CSS.getPropertyValue(element, transformProperty));
1881
+ }
1882
+
1883
+ /* Create an object to organize all the transforms that we'll apply to the SVG element. To keep the logic simple,
1884
+ we process *all* transform properties -- even those that may not be explicitly applied (since they default to their zero-values anyway). */
1885
+ var SVGTransforms = {
1886
+ translate: [ getTransformFloat("translateX"), getTransformFloat("translateY") ],
1887
+ skewX: [ getTransformFloat("skewX") ], skewY: [ getTransformFloat("skewY") ],
1888
+ /* If the scale property is set (non-1), use that value for the scaleX and scaleY values
1889
+ (this behavior mimics the result of animating all these properties at once on HTML elements). */
1890
+ scale: getTransformFloat("scale") !== 1 ? [ getTransformFloat("scale"), getTransformFloat("scale") ] : [ getTransformFloat("scaleX"), getTransformFloat("scaleY") ],
1891
+ /* Note: SVG's rotate transform takes three values: rotation degrees followed by the X and Y values
1892
+ defining the rotation's origin point. We ignore the origin values (default them to 0). */
1893
+ rotate: [ getTransformFloat("rotateZ"), 0, 0 ]
1894
+ };
1895
+
1896
+ /* Iterate through the transform properties in the user-defined property map order.
1897
+ (This mimics the behavior of non-SVG transform animation.) */
1898
+ $.each(Data(element).transformCache, function(transformName) {
1899
+ /* Except for with skewX/Y, revert the axis-specific transform subproperties to their axis-free master
1900
+ properties so that they match up with SVG's accepted transform properties. */
1901
+ if (/^translate/i.test(transformName)) {
1902
+ transformName = "translate";
1903
+ } else if (/^scale/i.test(transformName)) {
1904
+ transformName = "scale";
1905
+ } else if (/^rotate/i.test(transformName)) {
1906
+ transformName = "rotate";
1907
+ }
1908
+
1909
+ /* Check that we haven't yet deleted the property from the SVGTransforms container. */
1910
+ if (SVGTransforms[transformName]) {
1911
+ /* Append the transform property in the SVG-supported transform format. As per the spec, surround the space-delimited values in parentheses. */
1912
+ transformString += transformName + "(" + SVGTransforms[transformName].join(" ") + ")" + " ";
1913
+
1914
+ /* After processing an SVG transform property, delete it from the SVGTransforms container so we don't
1915
+ re-insert the same master property if we encounter another one of its axis-specific properties. */
1916
+ delete SVGTransforms[transformName];
1917
+ }
1918
+ });
1919
+ } else {
1920
+ var transformValue,
1921
+ perspective;
1922
+
1923
+ /* Transform properties are stored as members of the transformCache object. Concatenate all the members into a string. */
1924
+ $.each(Data(element).transformCache, function(transformName) {
1925
+ transformValue = Data(element).transformCache[transformName];
1926
+
1927
+ /* Transform's perspective subproperty must be set first in order to take effect. Store it temporarily. */
1928
+ if (transformName === "transformPerspective") {
1929
+ perspective = transformValue;
1930
+ return true;
1931
+ }
1932
+
1933
+ /* IE9 only supports one rotation type, rotateZ, which it refers to as "rotate". */
1934
+ if (IE === 9 && transformName === "rotateZ") {
1935
+ transformName = "rotate";
1936
+ }
1937
+
1938
+ transformString += transformName + transformValue + " ";
1939
+ });
1940
+
1941
+ /* If present, set the perspective subproperty first. */
1942
+ if (perspective) {
1943
+ transformString = "perspective" + perspective + " " + transformString;
1944
+ }
1945
+ }
1946
+
1947
+ CSS.setPropertyValue(element, "transform", transformString);
1948
+ }
1949
+ };
1950
+
1951
+ /* Register hooks and normalizations. */
1952
+ CSS.Hooks.register();
1953
+ CSS.Normalizations.register();
1954
+
1955
+ /* Allow hook setting in the same fashion as jQuery's $.css(). */
1956
+ Velocity.hook = function (elements, arg2, arg3) {
1957
+ var value = undefined;
1958
+
1959
+ elements = sanitizeElements(elements);
1960
+
1961
+ $.each(elements, function(i, element) {
1962
+ /* Initialize Velocity's per-element data cache if this element hasn't previously been animated. */
1963
+ if (Data(element) === undefined) {
1964
+ Velocity.init(element);
1965
+ }
1966
+
1967
+ /* Get property value. If an element set was passed in, only return the value for the first element. */
1968
+ if (arg3 === undefined) {
1969
+ if (value === undefined) {
1970
+ value = Velocity.CSS.getPropertyValue(element, arg2);
1971
+ }
1972
+ /* Set property value. */
1973
+ } else {
1974
+ /* sPV returns an array of the normalized propertyName/propertyValue pair used to update the DOM. */
1975
+ var adjustedSet = Velocity.CSS.setPropertyValue(element, arg2, arg3);
1976
+
1977
+ /* Transform properties don't automatically set. They have to be flushed to the DOM. */
1978
+ if (adjustedSet[0] === "transform") {
1979
+ Velocity.CSS.flushTransformCache(element);
1980
+ }
1981
+
1982
+ value = adjustedSet;
1983
+ }
1984
+ });
1985
+
1986
+ return value;
1987
+ };
1988
+
1989
+ /*****************
1990
+ Animation
1991
+ *****************/
1992
+
1993
+ var animate = function() {
1994
+
1995
+ /******************
1996
+ Call Chain
1997
+ ******************/
1998
+
1999
+ /* Logic for determining what to return to the call stack when exiting out of Velocity. */
2000
+ function getChain () {
2001
+ /* If we are using the utility function, attempt to return this call's promise. If no promise library was detected,
2002
+ default to null instead of returning the targeted elements so that utility function's return value is standardized. */
2003
+ if (isUtility) {
2004
+ return promiseData.promise || null;
2005
+ /* Otherwise, if we're using $.fn, return the jQuery-/Zepto-wrapped element set. */
2006
+ } else {
2007
+ return elementsWrapped;
2008
+ }
2009
+ }
2010
+
2011
+ /*************************
2012
+ Arguments Assignment
2013
+ *************************/
2014
+
2015
+ /* To allow for expressive CoffeeScript code, Velocity supports an alternative syntax in which "properties" and "options"
2016
+ objects are defined on a container object that's passed in as Velocity's sole argument. */
2017
+ /* Note: Some browsers automatically populate arguments with a "properties" object. We detect it by checking for its default "names" property. */
2018
+ var syntacticSugar = (arguments[0] && (($.isPlainObject(arguments[0].properties) && !arguments[0].properties.names) || Type.isString(arguments[0].properties))),
2019
+ /* Whether Velocity was called via the utility function (as opposed to on a jQuery/Zepto object). */
2020
+ isUtility,
2021
+ /* When Velocity is called via the utility function ($.Velocity()/Velocity()), elements are explicitly
2022
+ passed in as the first parameter. Thus, argument positioning varies. We normalize them here. */
2023
+ elementsWrapped,
2024
+ argumentIndex;
2025
+
2026
+ var elements,
2027
+ propertiesMap,
2028
+ options;
2029
+
2030
+ /* Detect jQuery/Zepto elements being animated via the $.fn method. */
2031
+ if (Type.isWrapped(this)) {
2032
+ isUtility = false;
2033
+
2034
+ argumentIndex = 0;
2035
+ elements = this;
2036
+ elementsWrapped = this;
2037
+ /* Otherwise, raw elements are being animated via the utility function. */
2038
+ } else {
2039
+ isUtility = true;
2040
+
2041
+ argumentIndex = 1;
2042
+ elements = syntacticSugar ? arguments[0].elements : arguments[0];
2043
+ }
2044
+
2045
+ elements = sanitizeElements(elements);
2046
+
2047
+ if (!elements) {
2048
+ return;
2049
+ }
2050
+
2051
+ if (syntacticSugar) {
2052
+ propertiesMap = arguments[0].properties;
2053
+ options = arguments[0].options;
2054
+ } else {
2055
+ propertiesMap = arguments[argumentIndex];
2056
+ options = arguments[argumentIndex + 1];
2057
+ }
2058
+
2059
+ /* The length of the element set (in the form of a nodeList or an array of elements) is defaulted to 1 in case a
2060
+ single raw DOM element is passed in (which doesn't contain a length property). */
2061
+ var elementsLength = elements.length,
2062
+ elementsIndex = 0;
2063
+
2064
+ /***************************
2065
+ Argument Overloading
2066
+ ***************************/
2067
+
2068
+ /* Support is included for jQuery's argument overloading: $.animate(propertyMap [, duration] [, easing] [, complete]).
2069
+ Overloading is detected by checking for the absence of an object being passed into options. */
2070
+ /* Note: The stop action does not accept animation options, and is therefore excluded from this check. */
2071
+ if (propertiesMap !== "stop" && !$.isPlainObject(options)) {
2072
+ /* The utility function shifts all arguments one position to the right, so we adjust for that offset. */
2073
+ var startingArgumentPosition = argumentIndex + 1;
2074
+
2075
+ options = {};
2076
+
2077
+ /* Iterate through all options arguments */
2078
+ for (var i = startingArgumentPosition; i < arguments.length; i++) {
2079
+ /* Treat a number as a duration. Parse it out. */
2080
+ /* Note: The following RegEx will return true if passed an array with a number as its first item.
2081
+ Thus, arrays are skipped from this check. */
2082
+ if (!Type.isArray(arguments[i]) && (/^(fast|normal|slow)$/i.test(arguments[i]) || /^\d/.test(arguments[i]))) {
2083
+ options.duration = arguments[i];
2084
+ /* Treat strings and arrays as easings. */
2085
+ } else if (Type.isString(arguments[i]) || Type.isArray(arguments[i])) {
2086
+ options.easing = arguments[i];
2087
+ /* Treat a function as a complete callback. */
2088
+ } else if (Type.isFunction(arguments[i])) {
2089
+ options.complete = arguments[i];
2090
+ }
2091
+ }
2092
+ }
2093
+
2094
+ /***************
2095
+ Promises
2096
+ ***************/
2097
+
2098
+ var promiseData = {
2099
+ promise: null,
2100
+ resolver: null,
2101
+ rejecter: null
2102
+ };
2103
+
2104
+ /* If this call was made via the utility function (which is the default method of invocation when jQuery/Zepto are not being used), and if
2105
+ promise support was detected, create a promise object for this call and store references to its resolver and rejecter methods. The resolve
2106
+ method is used when a call completes naturally or is prematurely stopped by the user. In both cases, completeCall() handles the associated
2107
+ call cleanup and promise resolving logic. The reject method is used when an invalid set of arguments is passed into a Velocity call. */
2108
+ /* Note: Velocity employs a call-based queueing architecture, which means that stopping an animating element actually stops the full call that
2109
+ triggered it -- not that one element exclusively. Similarly, there is one promise per call, and all elements targeted by a Velocity call are
2110
+ grouped together for the purposes of resolving and rejecting a promise. */
2111
+ if (isUtility && Velocity.Promise) {
2112
+ promiseData.promise = new Velocity.Promise(function (resolve, reject) {
2113
+ promiseData.resolver = resolve;
2114
+ promiseData.rejecter = reject;
2115
+ });
2116
+ }
2117
+
2118
+ /*********************
2119
+ Action Detection
2120
+ *********************/
2121
+
2122
+ /* Velocity's behavior is categorized into "actions": Elements can either be specially scrolled into view,
2123
+ or they can be started, stopped, or reversed. If a literal or referenced properties map is passed in as Velocity's
2124
+ first argument, the associated action is "start". Alternatively, "scroll", "reverse", or "stop" can be passed in instead of a properties map. */
2125
+ var action;
2126
+
2127
+ switch (propertiesMap) {
2128
+ case "scroll":
2129
+ action = "scroll";
2130
+ break;
2131
+
2132
+ case "reverse":
2133
+ action = "reverse";
2134
+ break;
2135
+
2136
+ case "stop":
2137
+ /*******************
2138
+ Action: Stop
2139
+ *******************/
2140
+
2141
+ /* Clear the currently-active delay on each targeted element. */
2142
+ $.each(elements, function(i, element) {
2143
+ if (Data(element) && Data(element).delayTimer) {
2144
+ /* Stop the timer from triggering its cached next() function. */
2145
+ clearTimeout(Data(element).delayTimer.setTimeout);
2146
+
2147
+ /* Manually call the next() function so that the subsequent queue items can progress. */
2148
+ if (Data(element).delayTimer.next) {
2149
+ Data(element).delayTimer.next();
2150
+ }
2151
+
2152
+ delete Data(element).delayTimer;
2153
+ }
2154
+ });
2155
+
2156
+ var callsToStop = [];
2157
+
2158
+ /* When the stop action is triggered, the elements' currently active call is immediately stopped. The active call might have
2159
+ been applied to multiple elements, in which case all of the call's elements will be subjected to stopping. When an element
2160
+ is stopped, the next item in its animation queue is immediately triggered. */
2161
+ /* An additional argument may be passed in to clear an element's remaining queued calls. Either true (which defaults to the "fx" queue)
2162
+ or a custom queue string can be passed in. */
2163
+ /* Note: The stop command runs prior to Queueing since its behavior is intended to take effect *immediately*,
2164
+ regardless of the element's current queue state. */
2165
+
2166
+ /* Iterate through every active call. */
2167
+ $.each(Velocity.State.calls, function(i, activeCall) {
2168
+ /* Inactive calls are set to false by the logic inside completeCall(). Skip them. */
2169
+ if (activeCall) {
2170
+ /* Iterate through the active call's targeted elements. */
2171
+ $.each(activeCall[1], function(k, activeElement) {
2172
+ var queueName = Type.isString(options) ? options : "";
2173
+
2174
+ if (options !== undefined && activeCall[2].queue !== queueName) {
2175
+ return true;
2176
+ }
2177
+
2178
+ /* Iterate through the calls targeted by the stop command. */
2179
+ $.each(elements, function(l, element) {
2180
+ /* Check that this call was applied to the target element. */
2181
+ if (element === activeElement) {
2182
+ /* Optionally clear the remaining queued calls. */
2183
+ if (options !== undefined) {
2184
+ /* Iterate through the items in the element's queue. */
2185
+ $.each($.queue(element, queueName), function(_, item) {
2186
+ /* The queue array can contain an "inprogress" string, which we skip. */
2187
+ if (Type.isFunction(item)) {
2188
+ /* Pass the item's callback a flag indicating that we want to abort from the queue call.
2189
+ (Specifically, the queue will resolve the call's associated promise then abort.) */
2190
+ item(null, true);
2191
+ }
2192
+ });
2193
+
2194
+ /* Clearing the $.queue() array is achieved by resetting it to []. */
2195
+ $.queue(element, queueName, []);
2196
+ }
2197
+
2198
+ if (Data(element) && queueName === "") {
2199
+ /* Since "reverse" uses cached start values (the previous call's endValues),
2200
+ these values must be changed to reflect the final value that the elements were actually tweened to. */
2201
+ $.each(Data(element).tweensContainer, function(m, activeTween) {
2202
+ activeTween.endValue = activeTween.currentValue;
2203
+ });
2204
+ }
2205
+
2206
+ callsToStop.push(i);
2207
+ }
2208
+ });
2209
+ });
2210
+ }
2211
+ });
2212
+
2213
+ /* Prematurely call completeCall() on each matched active call, passing an additional flag to indicate
2214
+ that the complete callback and display:none setting should be skipped since we're completing prematurely. */
2215
+ $.each(callsToStop, function(i, j) {
2216
+ completeCall(j, true);
2217
+ });
2218
+
2219
+ if (promiseData.promise) {
2220
+ /* Immediately resolve the promise associated with this stop call since stop runs synchronously. */
2221
+ promiseData.resolver(elements);
2222
+ }
2223
+
2224
+ /* Since we're stopping, and not proceeding with queueing, exit out of Velocity. */
2225
+ return getChain();
2226
+
2227
+ default:
2228
+ /* Treat a non-empty plain object as a literal properties map. */
2229
+ if ($.isPlainObject(propertiesMap) && !Type.isEmptyObject(propertiesMap)) {
2230
+ action = "start";
2231
+
2232
+ /****************
2233
+ Redirects
2234
+ ****************/
2235
+
2236
+ /* Check if a string matches a registered redirect (see Redirects above). */
2237
+ } else if (Type.isString(propertiesMap) && Velocity.Redirects[propertiesMap]) {
2238
+ var opts = $.extend({}, options),
2239
+ durationOriginal = opts.duration,
2240
+ delayOriginal = opts.delay || 0;
2241
+
2242
+ /* If the backwards option was passed in, reverse the element set so that elements animate from the last to the first. */
2243
+ if (opts.backwards === true) {
2244
+ elements = $.extend(true, [], elements).reverse();
2245
+ }
2246
+
2247
+ /* Individually trigger the redirect for each element in the set to prevent users from having to handle iteration logic in their redirect. */
2248
+ $.each(elements, function(elementIndex, element) {
2249
+ /* If the stagger option was passed in, successively delay each element by the stagger value (in ms). Retain the original delay value. */
2250
+ if (parseFloat(opts.stagger)) {
2251
+ opts.delay = delayOriginal + (parseFloat(opts.stagger) * elementIndex);
2252
+ } else if (Type.isFunction(opts.stagger)) {
2253
+ opts.delay = delayOriginal + opts.stagger.call(element, elementIndex, elementsLength);
2254
+ }
2255
+
2256
+ /* If the drag option was passed in, successively increase/decrease (depending on the presense of opts.backwards)
2257
+ the duration of each element's animation, using floors to prevent producing very short durations. */
2258
+ if (opts.drag) {
2259
+ /* Default the duration of UI pack effects (callouts and transitions) to 1000ms instead of the usual default duration of 400ms. */
2260
+ opts.duration = parseFloat(durationOriginal) || (/^(callout|transition)/.test(propertiesMap) ? 1000 : DURATION_DEFAULT);
2261
+
2262
+ /* For each element, take the greater duration of: A) animation completion percentage relative to the original duration,
2263
+ B) 75% of the original duration, or C) a 200ms fallback (in case duration is already set to a low value).
2264
+ The end result is a baseline of 75% of the redirect's duration that increases/decreases as the end of the element set is approached. */
2265
+ opts.duration = Math.max(opts.duration * (opts.backwards ? 1 - elementIndex/elementsLength : (elementIndex + 1) / elementsLength), opts.duration * 0.75, 200);
2266
+ }
2267
+
2268
+ /* Pass in the call's opts object so that the redirect can optionally extend it. It defaults to an empty object instead of null to
2269
+ reduce the opts checking logic required inside the redirect. */
2270
+ Velocity.Redirects[propertiesMap].call(element, element, opts || {}, elementIndex, elementsLength, elements, promiseData.promise ? promiseData : undefined);
2271
+ });
2272
+
2273
+ /* Since the animation logic resides within the redirect's own code, abort the remainder of this call.
2274
+ (The performance overhead up to this point is virtually non-existant.) */
2275
+ /* Note: The jQuery call chain is kept intact by returning the complete element set. */
2276
+ return getChain();
2277
+ } else {
2278
+ var abortError = "Velocity: First argument (" + propertiesMap + ") was not a property map, a known action, or a registered redirect. Aborting.";
2279
+
2280
+ if (promiseData.promise) {
2281
+ promiseData.rejecter(new Error(abortError));
2282
+ } else {
2283
+ console.log(abortError);
2284
+ }
2285
+
2286
+ return getChain();
2287
+ }
2288
+ }
2289
+
2290
+ /**************************
2291
+ Call-Wide Variables
2292
+ **************************/
2293
+
2294
+ /* A container for CSS unit conversion ratios (e.g. %, rem, and em ==> px) that is used to cache ratios across all elements
2295
+ being animated in a single Velocity call. Calculating unit ratios necessitates DOM querying and updating, and is therefore
2296
+ avoided (via caching) wherever possible. This container is call-wide instead of page-wide to avoid the risk of using stale
2297
+ conversion metrics across Velocity animations that are not immediately consecutively chained. */
2298
+ var callUnitConversionData = {
2299
+ lastParent: null,
2300
+ lastPosition: null,
2301
+ lastFontSize: null,
2302
+ lastPercentToPxWidth: null,
2303
+ lastPercentToPxHeight: null,
2304
+ lastEmToPx: null,
2305
+ remToPx: null,
2306
+ vwToPx: null,
2307
+ vhToPx: null
2308
+ };
2309
+
2310
+ /* A container for all the ensuing tween data and metadata associated with this call. This container gets pushed to the page-wide
2311
+ Velocity.State.calls array that is processed during animation ticking. */
2312
+ var call = [];
2313
+
2314
+ /************************
2315
+ Element Processing
2316
+ ************************/
2317
+
2318
+ /* Element processing consists of three parts -- data processing that cannot go stale and data processing that *can* go stale (i.e. third-party style modifications):
2319
+ 1) Pre-Queueing: Element-wide variables, including the element's data storage, are instantiated. Call options are prepared. If triggered, the Stop action is executed.
2320
+ 2) Queueing: The logic that runs once this call has reached its point of execution in the element's $.queue() stack. Most logic is placed here to avoid risking it becoming stale.
2321
+ 3) Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
2322
+ */
2323
+
2324
+ function processElement () {
2325
+
2326
+ /*************************
2327
+ Part I: Pre-Queueing
2328
+ *************************/
2329
+
2330
+ /***************************
2331
+ Element-Wide Variables
2332
+ ***************************/
2333
+
2334
+ var element = this,
2335
+ /* The runtime opts object is the extension of the current call's options and Velocity's page-wide option defaults. */
2336
+ opts = $.extend({}, Velocity.defaults, options),
2337
+ /* A container for the processed data associated with each property in the propertyMap.
2338
+ (Each property in the map produces its own "tween".) */
2339
+ tweensContainer = {},
2340
+ elementUnitConversionData;
2341
+
2342
+ /******************
2343
+ Element Init
2344
+ ******************/
2345
+
2346
+ if (Data(element) === undefined) {
2347
+ Velocity.init(element);
2348
+ }
2349
+
2350
+ /******************
2351
+ Option: Delay
2352
+ ******************/
2353
+
2354
+ /* Since queue:false doesn't respect the item's existing queue, we avoid injecting its delay here (it's set later on). */
2355
+ /* Note: Velocity rolls its own delay function since jQuery doesn't have a utility alias for $.fn.delay()
2356
+ (and thus requires jQuery element creation, which we avoid since its overhead includes DOM querying). */
2357
+ if (parseFloat(opts.delay) && opts.queue !== false) {
2358
+ $.queue(element, opts.queue, function(next) {
2359
+ /* This is a flag used to indicate to the upcoming completeCall() function that this queue entry was initiated by Velocity. See completeCall() for further details. */
2360
+ Velocity.velocityQueueEntryFlag = true;
2361
+
2362
+ /* The ensuing queue item (which is assigned to the "next" argument that $.queue() automatically passes in) will be triggered after a setTimeout delay.
2363
+ The setTimeout is stored so that it can be subjected to clearTimeout() if this animation is prematurely stopped via Velocity's "stop" command. */
2364
+ Data(element).delayTimer = {
2365
+ setTimeout: setTimeout(next, parseFloat(opts.delay)),
2366
+ next: next
2367
+ };
2368
+ });
2369
+ }
2370
+
2371
+ /*********************
2372
+ Option: Duration
2373
+ *********************/
2374
+
2375
+ /* Support for jQuery's named durations. */
2376
+ switch (opts.duration.toString().toLowerCase()) {
2377
+ case "fast":
2378
+ opts.duration = 200;
2379
+ break;
2380
+
2381
+ case "normal":
2382
+ opts.duration = DURATION_DEFAULT;
2383
+ break;
2384
+
2385
+ case "slow":
2386
+ opts.duration = 600;
2387
+ break;
2388
+
2389
+ default:
2390
+ /* Remove the potential "ms" suffix and default to 1 if the user is attempting to set a duration of 0 (in order to produce an immediate style change). */
2391
+ opts.duration = parseFloat(opts.duration) || 1;
2392
+ }
2393
+
2394
+ /************************
2395
+ Global Option: Mock
2396
+ ************************/
2397
+
2398
+ if (Velocity.mock !== false) {
2399
+ /* In mock mode, all animations are forced to 1ms so that they occur immediately upon the next rAF tick.
2400
+ Alternatively, a multiplier can be passed in to time remap all delays and durations. */
2401
+ if (Velocity.mock === true) {
2402
+ opts.duration = opts.delay = 1;
2403
+ } else {
2404
+ opts.duration *= parseFloat(Velocity.mock) || 1;
2405
+ opts.delay *= parseFloat(Velocity.mock) || 1;
2406
+ }
2407
+ }
2408
+
2409
+ /*******************
2410
+ Option: Easing
2411
+ *******************/
2412
+
2413
+ opts.easing = getEasing(opts.easing, opts.duration);
2414
+
2415
+ /**********************
2416
+ Option: Callbacks
2417
+ **********************/
2418
+
2419
+ /* Callbacks must functions. Otherwise, default to null. */
2420
+ if (opts.begin && !Type.isFunction(opts.begin)) {
2421
+ opts.begin = null;
2422
+ }
2423
+
2424
+ if (opts.progress && !Type.isFunction(opts.progress)) {
2425
+ opts.progress = null;
2426
+ }
2427
+
2428
+ if (opts.complete && !Type.isFunction(opts.complete)) {
2429
+ opts.complete = null;
2430
+ }
2431
+
2432
+ /*********************************
2433
+ Option: Display & Visibility
2434
+ *********************************/
2435
+
2436
+ /* Refer to Velocity's documentation (VelocityJS.org/#displayAndVisibility) for a description of the display and visibility options' behavior. */
2437
+ /* Note: We strictly check for undefined instead of falsiness because display accepts an empty string value. */
2438
+ if (opts.display !== undefined && opts.display !== null) {
2439
+ opts.display = opts.display.toString().toLowerCase();
2440
+
2441
+ /* Users can pass in a special "auto" value to instruct Velocity to set the element to its default display value. */
2442
+ if (opts.display === "auto") {
2443
+ opts.display = Velocity.CSS.Values.getDisplayType(element);
2444
+ }
2445
+ }
2446
+
2447
+ if (opts.visibility !== undefined && opts.visibility !== null) {
2448
+ opts.visibility = opts.visibility.toString().toLowerCase();
2449
+ }
2450
+
2451
+ /**********************
2452
+ Option: mobileHA
2453
+ **********************/
2454
+
2455
+ /* When set to true, and if this is a mobile device, mobileHA automatically enables hardware acceleration (via a null transform hack)
2456
+ on animating elements. HA is removed from the element at the completion of its animation. */
2457
+ /* Note: Android Gingerbread doesn't support HA. If a null transform hack (mobileHA) is in fact set, it will prevent other tranform subproperties from taking effect. */
2458
+ /* Note: You can read more about the use of mobileHA in Velocity's documentation: VelocityJS.org/#mobileHA. */
2459
+ opts.mobileHA = (opts.mobileHA && Velocity.State.isMobile && !Velocity.State.isGingerbread);
2460
+
2461
+ /***********************
2462
+ Part II: Queueing
2463
+ ***********************/
2464
+
2465
+ /* When a set of elements is targeted by a Velocity call, the set is broken up and each element has the current Velocity call individually queued onto it.
2466
+ In this way, each element's existing queue is respected; some elements may already be animating and accordingly should not have this current Velocity call triggered immediately. */
2467
+ /* In each queue, tween data is processed for each animating property then pushed onto the call-wide calls array. When the last element in the set has had its tweens processed,
2468
+ the call array is pushed to Velocity.State.calls for live processing by the requestAnimationFrame tick. */
2469
+ function buildQueue (next) {
2470
+
2471
+ /*******************
2472
+ Option: Begin
2473
+ *******************/
2474
+
2475
+ /* The begin callback is fired once per call -- not once per elemenet -- and is passed the full raw DOM element set as both its context and its first argument. */
2476
+ if (opts.begin && elementsIndex === 0) {
2477
+ /* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
2478
+ try {
2479
+ opts.begin.call(elements, elements);
2480
+ } catch (error) {
2481
+ setTimeout(function() { throw error; }, 1);
2482
+ }
2483
+ }
2484
+
2485
+ /*****************************************
2486
+ Tween Data Construction (for Scroll)
2487
+ *****************************************/
2488
+
2489
+ /* Note: In order to be subjected to chaining and animation options, scroll's tweening is routed through Velocity as if it were a standard CSS property animation. */
2490
+ if (action === "scroll") {
2491
+ /* The scroll action uniquely takes an optional "offset" option -- specified in pixels -- that offsets the targeted scroll position. */
2492
+ var scrollDirection = (/^x$/i.test(opts.axis) ? "Left" : "Top"),
2493
+ scrollOffset = parseFloat(opts.offset) || 0,
2494
+ scrollPositionCurrent,
2495
+ scrollPositionCurrentAlternate,
2496
+ scrollPositionEnd;
2497
+
2498
+ /* Scroll also uniquely takes an optional "container" option, which indicates the parent element that should be scrolled --
2499
+ as opposed to the browser window itself. This is useful for scrolling toward an element that's inside an overflowing parent element. */
2500
+ if (opts.container) {
2501
+ /* Ensure that either a jQuery object or a raw DOM element was passed in. */
2502
+ if (Type.isWrapped(opts.container) || Type.isNode(opts.container)) {
2503
+ /* Extract the raw DOM element from the jQuery wrapper. */
2504
+ opts.container = opts.container[0] || opts.container;
2505
+ /* Note: Unlike other properties in Velocity, the browser's scroll position is never cached since it so frequently changes
2506
+ (due to the user's natural interaction with the page). */
2507
+ scrollPositionCurrent = opts.container["scroll" + scrollDirection]; /* GET */
2508
+
2509
+ /* $.position() values are relative to the container's currently viewable area (without taking into account the container's true dimensions
2510
+ -- say, for example, if the container was not overflowing). Thus, the scroll end value is the sum of the child element's position *and*
2511
+ the scroll container's current scroll position. */
2512
+ /* Note: jQuery does not offer a utility alias for $.position(), so we have to incur jQuery object conversion here.
2513
+ This syncs up with an ensuing batch of GETs, so it fortunately does not trigger layout thrashing. */
2514
+ scrollPositionEnd = (scrollPositionCurrent + $(element).position()[scrollDirection.toLowerCase()]) + scrollOffset; /* GET */
2515
+ /* If a value other than a jQuery object or a raw DOM element was passed in, default to null so that this option is ignored. */
2516
+ } else {
2517
+ opts.container = null;
2518
+ }
2519
+ } else {
2520
+ /* If the window itself is being scrolled -- not a containing element -- perform a live scroll position lookup using
2521
+ the appropriate cached property names (which differ based on browser type). */
2522
+ scrollPositionCurrent = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + scrollDirection]]; /* GET */
2523
+ /* When scrolling the browser window, cache the alternate axis's current value since window.scrollTo() doesn't let us change only one value at a time. */
2524
+ scrollPositionCurrentAlternate = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + (scrollDirection === "Left" ? "Top" : "Left")]]; /* GET */
2525
+
2526
+ /* Unlike $.position(), $.offset() values are relative to the browser window's true dimensions -- not merely its currently viewable area --
2527
+ and therefore end values do not need to be compounded onto current values. */
2528
+ scrollPositionEnd = $(element).offset()[scrollDirection.toLowerCase()] + scrollOffset; /* GET */
2529
+ }
2530
+
2531
+ /* Since there's only one format that scroll's associated tweensContainer can take, we create it manually. */
2532
+ tweensContainer = {
2533
+ scroll: {
2534
+ rootPropertyValue: false,
2535
+ startValue: scrollPositionCurrent,
2536
+ currentValue: scrollPositionCurrent,
2537
+ endValue: scrollPositionEnd,
2538
+ unitType: "",
2539
+ easing: opts.easing,
2540
+ scrollData: {
2541
+ container: opts.container,
2542
+ direction: scrollDirection,
2543
+ alternateValue: scrollPositionCurrentAlternate
2544
+ }
2545
+ },
2546
+ element: element
2547
+ };
2548
+
2549
+ if (Velocity.debug) console.log("tweensContainer (scroll): ", tweensContainer.scroll, element);
2550
+
2551
+ /******************************************
2552
+ Tween Data Construction (for Reverse)
2553
+ ******************************************/
2554
+
2555
+ /* Reverse acts like a "start" action in that a property map is animated toward. The only difference is
2556
+ that the property map used for reverse is the inverse of the map used in the previous call. Thus, we manipulate
2557
+ the previous call to construct our new map: use the previous map's end values as our new map's start values. Copy over all other data. */
2558
+ /* Note: Reverse can be directly called via the "reverse" parameter, or it can be indirectly triggered via the loop option. (Loops are composed of multiple reverses.) */
2559
+ /* Note: Reverse calls do not need to be consecutively chained onto a currently-animating element in order to operate on cached values;
2560
+ there is no harm to reverse being called on a potentially stale data cache since reverse's behavior is simply defined
2561
+ as reverting to the element's values as they were prior to the previous *Velocity* call. */
2562
+ } else if (action === "reverse") {
2563
+ /* Abort if there is no prior animation data to reverse to. */
2564
+ if (!Data(element).tweensContainer) {
2565
+ /* Dequeue the element so that this queue entry releases itself immediately, allowing subsequent queue entries to run. */
2566
+ $.dequeue(element, opts.queue);
2567
+
2568
+ return;
2569
+ } else {
2570
+ /*********************
2571
+ Options Parsing
2572
+ *********************/
2573
+
2574
+ /* If the element was hidden via the display option in the previous call,
2575
+ revert display to "auto" prior to reversal so that the element is visible again. */
2576
+ if (Data(element).opts.display === "none") {
2577
+ Data(element).opts.display = "auto";
2578
+ }
2579
+
2580
+ if (Data(element).opts.visibility === "hidden") {
2581
+ Data(element).opts.visibility = "visible";
2582
+ }
2583
+
2584
+ /* If the loop option was set in the previous call, disable it so that "reverse" calls aren't recursively generated.
2585
+ Further, remove the previous call's callback options; typically, users do not want these to be refired. */
2586
+ Data(element).opts.loop = false;
2587
+ Data(element).opts.begin = null;
2588
+ Data(element).opts.complete = null;
2589
+
2590
+ /* Since we're extending an opts object that has already been extended with the defaults options object,
2591
+ we remove non-explicitly-defined properties that are auto-assigned values. */
2592
+ if (!options.easing) {
2593
+ delete opts.easing;
2594
+ }
2595
+
2596
+ if (!options.duration) {
2597
+ delete opts.duration;
2598
+ }
2599
+
2600
+ /* The opts object used for reversal is an extension of the options object optionally passed into this
2601
+ reverse call plus the options used in the previous Velocity call. */
2602
+ opts = $.extend({}, Data(element).opts, opts);
2603
+
2604
+ /*************************************
2605
+ Tweens Container Reconstruction
2606
+ *************************************/
2607
+
2608
+ /* Create a deepy copy (indicated via the true flag) of the previous call's tweensContainer. */
2609
+ var lastTweensContainer = $.extend(true, {}, Data(element).tweensContainer);
2610
+
2611
+ /* Manipulate the previous tweensContainer by replacing its end values and currentValues with its start values. */
2612
+ for (var lastTween in lastTweensContainer) {
2613
+ /* In addition to tween data, tweensContainers contain an element property that we ignore here. */
2614
+ if (lastTween !== "element") {
2615
+ var lastStartValue = lastTweensContainer[lastTween].startValue;
2616
+
2617
+ lastTweensContainer[lastTween].startValue = lastTweensContainer[lastTween].currentValue = lastTweensContainer[lastTween].endValue;
2618
+ lastTweensContainer[lastTween].endValue = lastStartValue;
2619
+
2620
+ /* Easing is the only option that embeds into the individual tween data (since it can be defined on a per-property basis).
2621
+ Accordingly, every property's easing value must be updated when an options object is passed in with a reverse call.
2622
+ The side effect of this extensibility is that all per-property easing values are forcefully reset to the new value. */
2623
+ if (!Type.isEmptyObject(options)) {
2624
+ lastTweensContainer[lastTween].easing = opts.easing;
2625
+ }
2626
+
2627
+ if (Velocity.debug) console.log("reverse tweensContainer (" + lastTween + "): " + JSON.stringify(lastTweensContainer[lastTween]), element);
2628
+ }
2629
+ }
2630
+
2631
+ tweensContainer = lastTweensContainer;
2632
+ }
2633
+
2634
+ /*****************************************
2635
+ Tween Data Construction (for Start)
2636
+ *****************************************/
2637
+
2638
+ } else if (action === "start") {
2639
+
2640
+ /*************************
2641
+ Value Transferring
2642
+ *************************/
2643
+
2644
+ /* If this queue entry follows a previous Velocity-initiated queue entry *and* if this entry was created
2645
+ while the element was in the process of being animated by Velocity, then this current call is safe to use
2646
+ the end values from the prior call as its start values. Velocity attempts to perform this value transfer
2647
+ process whenever possible in order to avoid requerying the DOM. */
2648
+ /* If values aren't transferred from a prior call and start values were not forcefed by the user (more on this below),
2649
+ then the DOM is queried for the element's current values as a last resort. */
2650
+ /* Note: Conversely, animation reversal (and looping) *always* perform inter-call value transfers; they never requery the DOM. */
2651
+ var lastTweensContainer;
2652
+
2653
+ /* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale)
2654
+ to transfer over end values to use as start values. If it's set to true and there is a previous
2655
+ Velocity call to pull values from, do so. */
2656
+ if (Data(element).tweensContainer && Data(element).isAnimating === true) {
2657
+ lastTweensContainer = Data(element).tweensContainer;
2658
+ }
2659
+
2660
+ /***************************
2661
+ Tween Data Calculation
2662
+ ***************************/
2663
+
2664
+ /* This function parses property data and defaults endValue, easing, and startValue as appropriate. */
2665
+ /* Property map values can either take the form of 1) a single value representing the end value,
2666
+ or 2) an array in the form of [ endValue, [, easing] [, startValue] ].
2667
+ The optional third parameter is a forcefed startValue to be used instead of querying the DOM for
2668
+ the element's current value. Read Velocity's docmentation to learn more about forcefeeding: VelocityJS.org/#forcefeeding */
2669
+ function parsePropertyValue (valueData, skipResolvingEasing) {
2670
+ var endValue = undefined,
2671
+ easing = undefined,
2672
+ startValue = undefined;
2673
+
2674
+ /* Handle the array format, which can be structured as one of three potential overloads:
2675
+ A) [ endValue, easing, startValue ], B) [ endValue, easing ], or C) [ endValue, startValue ] */
2676
+ if (Type.isArray(valueData)) {
2677
+ /* endValue is always the first item in the array. Don't bother validating endValue's value now
2678
+ since the ensuing property cycling logic does that. */
2679
+ endValue = valueData[0];
2680
+
2681
+ /* Two-item array format: If the second item is a number, function, or hex string, treat it as a
2682
+ start value since easings can only be non-hex strings or arrays. */
2683
+ if ((!Type.isArray(valueData[1]) && /^[\d-]/.test(valueData[1])) || Type.isFunction(valueData[1]) || CSS.RegEx.isHex.test(valueData[1])) {
2684
+ startValue = valueData[1];
2685
+ /* Two or three-item array: If the second item is a non-hex string or an array, treat it as an easing. */
2686
+ } else if ((Type.isString(valueData[1]) && !CSS.RegEx.isHex.test(valueData[1])) || Type.isArray(valueData[1])) {
2687
+ easing = skipResolvingEasing ? valueData[1] : getEasing(valueData[1], opts.duration);
2688
+
2689
+ /* Don't bother validating startValue's value now since the ensuing property cycling logic inherently does that. */
2690
+ if (valueData[2] !== undefined) {
2691
+ startValue = valueData[2];
2692
+ }
2693
+ }
2694
+ /* Handle the single-value format. */
2695
+ } else {
2696
+ endValue = valueData;
2697
+ }
2698
+
2699
+ /* Default to the call's easing if a per-property easing type was not defined. */
2700
+ if (!skipResolvingEasing) {
2701
+ easing = easing || opts.easing;
2702
+ }
2703
+
2704
+ /* If functions were passed in as values, pass the function the current element as its context,
2705
+ plus the element's index and the element set's size as arguments. Then, assign the returned value. */
2706
+ if (Type.isFunction(endValue)) {
2707
+ endValue = endValue.call(element, elementsIndex, elementsLength);
2708
+ }
2709
+
2710
+ if (Type.isFunction(startValue)) {
2711
+ startValue = startValue.call(element, elementsIndex, elementsLength);
2712
+ }
2713
+
2714
+ /* Allow startValue to be left as undefined to indicate to the ensuing code that its value was not forcefed. */
2715
+ return [ endValue || 0, easing, startValue ];
2716
+ }
2717
+
2718
+ /* Cycle through each property in the map, looking for shorthand color properties (e.g. "color" as opposed to "colorRed"). Inject the corresponding
2719
+ colorRed, colorGreen, and colorBlue RGB component tweens into the propertiesMap (which Velocity understands) and remove the shorthand property. */
2720
+ $.each(propertiesMap, function(property, value) {
2721
+ /* Find shorthand color properties that have been passed a hex string. */
2722
+ if (RegExp("^" + CSS.Lists.colors.join("$|^") + "$").test(property)) {
2723
+ /* Parse the value data for each shorthand. */
2724
+ var valueData = parsePropertyValue(value, true),
2725
+ endValue = valueData[0],
2726
+ easing = valueData[1],
2727
+ startValue = valueData[2];
2728
+
2729
+ if (CSS.RegEx.isHex.test(endValue)) {
2730
+ /* Convert the hex strings into their RGB component arrays. */
2731
+ var colorComponents = [ "Red", "Green", "Blue" ],
2732
+ endValueRGB = CSS.Values.hexToRgb(endValue),
2733
+ startValueRGB = startValue ? CSS.Values.hexToRgb(startValue) : undefined;
2734
+
2735
+ /* Inject the RGB component tweens into propertiesMap. */
2736
+ for (var i = 0; i < colorComponents.length; i++) {
2737
+ var dataArray = [ endValueRGB[i] ];
2738
+
2739
+ if (easing) {
2740
+ dataArray.push(easing);
2741
+ }
2742
+
2743
+ if (startValueRGB !== undefined) {
2744
+ dataArray.push(startValueRGB[i]);
2745
+ }
2746
+
2747
+ propertiesMap[property + colorComponents[i]] = dataArray;
2748
+ }
2749
+
2750
+ /* Remove the intermediary shorthand property entry now that we've processed it. */
2751
+ delete propertiesMap[property];
2752
+ }
2753
+ }
2754
+ });
2755
+
2756
+ /* Create a tween out of each property, and append its associated data to tweensContainer. */
2757
+ for (var property in propertiesMap) {
2758
+
2759
+ /**************************
2760
+ Start Value Sourcing
2761
+ **************************/
2762
+
2763
+ /* Parse out endValue, easing, and startValue from the property's data. */
2764
+ var valueData = parsePropertyValue(propertiesMap[property]),
2765
+ endValue = valueData[0],
2766
+ easing = valueData[1],
2767
+ startValue = valueData[2];
2768
+
2769
+ /* Now that the original property name's format has been used for the parsePropertyValue() lookup above,
2770
+ we force the property to its camelCase styling to normalize it for manipulation. */
2771
+ property = CSS.Names.camelCase(property);
2772
+
2773
+ /* In case this property is a hook, there are circumstances where we will intend to work on the hook's root property and not the hooked subproperty. */
2774
+ var rootProperty = CSS.Hooks.getRoot(property),
2775
+ rootPropertyValue = false;
2776
+
2777
+ /* Properties that are not supported by the browser (and do not have an associated normalization) will
2778
+ inherently produce no style changes when set, so they are skipped in order to decrease animation tick overhead.
2779
+ Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */
2780
+ /* Note: Since SVG elements have some of their properties directly applied as HTML attributes,
2781
+ there is no way to check for their explicit browser support, and so we skip skip this check for them. */
2782
+ if (!Data(element).isSVG && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) {
2783
+ if (Velocity.debug) console.log("Skipping [" + rootProperty + "] due to a lack of browser support.");
2784
+
2785
+ continue;
2786
+ }
2787
+
2788
+ /* If the display option is being set to a non-"none" (e.g. "block") and opacity (filter on IE<=8) is being
2789
+ animated to an endValue of non-zero, the user's intention is to fade in from invisible, thus we forcefeed opacity
2790
+ a startValue of 0 if its startValue hasn't already been sourced by value transferring or prior forcefeeding. */
2791
+ if (((opts.display !== undefined && opts.display !== null && opts.display !== "none") || (opts.visibility !== undefined && opts.visibility !== "hidden")) && /opacity|filter/.test(property) && !startValue && endValue !== 0) {
2792
+ startValue = 0;
2793
+ }
2794
+
2795
+ /* If values have been transferred from the previous Velocity call, extract the endValue and rootPropertyValue
2796
+ for all of the current call's properties that were *also* animated in the previous call. */
2797
+ /* Note: Value transferring can optionally be disabled by the user via the _cacheValues option. */
2798
+ if (opts._cacheValues && lastTweensContainer && lastTweensContainer[property]) {
2799
+ if (startValue === undefined) {
2800
+ startValue = lastTweensContainer[property].endValue + lastTweensContainer[property].unitType;
2801
+ }
2802
+
2803
+ /* The previous call's rootPropertyValue is extracted from the element's data cache since that's the
2804
+ instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue
2805
+ attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */
2806
+ rootPropertyValue = Data(element).rootPropertyValueCache[rootProperty];
2807
+ /* If values were not transferred from a previous Velocity call, query the DOM as needed. */
2808
+ } else {
2809
+ /* Handle hooked properties. */
2810
+ if (CSS.Hooks.registered[property]) {
2811
+ if (startValue === undefined) {
2812
+ rootPropertyValue = CSS.getPropertyValue(element, rootProperty); /* GET */
2813
+ /* Note: The following getPropertyValue() call does not actually trigger a DOM query;
2814
+ getPropertyValue() will extract the hook from rootPropertyValue. */
2815
+ startValue = CSS.getPropertyValue(element, property, rootPropertyValue);
2816
+ /* If startValue is already defined via forcefeeding, do not query the DOM for the root property's value;
2817
+ just grab rootProperty's zero-value template from CSS.Hooks. This overwrites the element's actual
2818
+ root property value (if one is set), but this is acceptable since the primary reason users forcefeed is
2819
+ to avoid DOM queries, and thus we likewise avoid querying the DOM for the root property's value. */
2820
+ } else {
2821
+ /* Grab this hook's zero-value template, e.g. "0px 0px 0px black". */
2822
+ rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
2823
+ }
2824
+ /* Handle non-hooked properties that haven't already been defined via forcefeeding. */
2825
+ } else if (startValue === undefined) {
2826
+ startValue = CSS.getPropertyValue(element, property); /* GET */
2827
+ }
2828
+ }
2829
+
2830
+ /**************************
2831
+ Value Data Extraction
2832
+ **************************/
2833
+
2834
+ var separatedValue,
2835
+ endValueUnitType,
2836
+ startValueUnitType,
2837
+ operator = false;
2838
+
2839
+ /* Separates a property value into its numeric value and its unit type. */
2840
+ function separateValue (property, value) {
2841
+ var unitType,
2842
+ numericValue;
2843
+
2844
+ numericValue = (value || "0")
2845
+ .toString()
2846
+ .toLowerCase()
2847
+ /* Match the unit type at the end of the value. */
2848
+ .replace(/[%A-z]+$/, function(match) {
2849
+ /* Grab the unit type. */
2850
+ unitType = match;
2851
+
2852
+ /* Strip the unit type off of value. */
2853
+ return "";
2854
+ });
2855
+
2856
+ /* If no unit type was supplied, assign one that is appropriate for this property (e.g. "deg" for rotateZ or "px" for width). */
2857
+ if (!unitType) {
2858
+ unitType = CSS.Values.getUnitType(property);
2859
+ }
2860
+
2861
+ return [ numericValue, unitType ];
2862
+ }
2863
+
2864
+ /* Separate startValue. */
2865
+ separatedValue = separateValue(property, startValue);
2866
+ startValue = separatedValue[0];
2867
+ startValueUnitType = separatedValue[1];
2868
+
2869
+ /* Separate endValue, and extract a value operator (e.g. "+=", "-=") if one exists. */
2870
+ separatedValue = separateValue(property, endValue);
2871
+ endValue = separatedValue[0].replace(/^([+-\/*])=/, function(match, subMatch) {
2872
+ operator = subMatch;
2873
+
2874
+ /* Strip the operator off of the value. */
2875
+ return "";
2876
+ });
2877
+ endValueUnitType = separatedValue[1];
2878
+
2879
+ /* Parse float values from endValue and startValue. Default to 0 if NaN is returned. */
2880
+ startValue = parseFloat(startValue) || 0;
2881
+ endValue = parseFloat(endValue) || 0;
2882
+
2883
+ /***************************************
2884
+ Property-Specific Value Conversion
2885
+ ***************************************/
2886
+
2887
+ /* Custom support for properties that don't actually accept the % unit type, but where pollyfilling is trivial and relatively foolproof. */
2888
+ if (endValueUnitType === "%") {
2889
+ /* A %-value fontSize/lineHeight is relative to the parent's fontSize (as opposed to the parent's dimensions),
2890
+ which is identical to the em unit's behavior, so we piggyback off of that. */
2891
+ if (/^(fontSize|lineHeight)$/.test(property)) {
2892
+ /* Convert % into an em decimal value. */
2893
+ endValue = endValue / 100;
2894
+ endValueUnitType = "em";
2895
+ /* For scaleX and scaleY, convert the value into its decimal format and strip off the unit type. */
2896
+ } else if (/^scale/.test(property)) {
2897
+ endValue = endValue / 100;
2898
+ endValueUnitType = "";
2899
+ /* For RGB components, take the defined percentage of 255 and strip off the unit type. */
2900
+ } else if (/(Red|Green|Blue)$/i.test(property)) {
2901
+ endValue = (endValue / 100) * 255;
2902
+ endValueUnitType = "";
2903
+ }
2904
+ }
2905
+
2906
+ /***************************
2907
+ Unit Ratio Calculation
2908
+ ***************************/
2909
+
2910
+ /* When queried, the browser returns (most) CSS property values in pixels. Therefore, if an endValue with a unit type of
2911
+ %, em, or rem is animated toward, startValue must be converted from pixels into the same unit type as endValue in order
2912
+ for value manipulation logic (increment/decrement) to proceed. Further, if the startValue was forcefed or transferred
2913
+ from a previous call, startValue may also not be in pixels. Unit conversion logic therefore consists of two steps:
2914
+ 1) Calculating the ratio of %/em/rem/vh/vw relative to pixels
2915
+ 2) Converting startValue into the same unit of measurement as endValue based on these ratios. */
2916
+ /* Unit conversion ratios are calculated by inserting a sibling node next to the target node, copying over its position property,
2917
+ setting values with the target unit type then comparing the returned pixel value. */
2918
+ /* Note: Even if only one of these unit types is being animated, all unit ratios are calculated at once since the overhead
2919
+ of batching the SETs and GETs together upfront outweights the potential overhead
2920
+ of layout thrashing caused by re-querying for uncalculated ratios for subsequently-processed properties. */
2921
+ /* Todo: Shift this logic into the calls' first tick instance so that it's synced with RAF. */
2922
+ function calculateUnitRatios () {
2923
+
2924
+ /************************
2925
+ Same Ratio Checks
2926
+ ************************/
2927
+
2928
+ /* The properties below are used to determine whether the element differs sufficiently from this call's
2929
+ previously iterated element to also differ in its unit conversion ratios. If the properties match up with those
2930
+ of the prior element, the prior element's conversion ratios are used. Like most optimizations in Velocity,
2931
+ this is done to minimize DOM querying. */
2932
+ var sameRatioIndicators = {
2933
+ myParent: element.parentNode || document.body, /* GET */
2934
+ position: CSS.getPropertyValue(element, "position"), /* GET */
2935
+ fontSize: CSS.getPropertyValue(element, "fontSize") /* GET */
2936
+ },
2937
+ /* Determine if the same % ratio can be used. % is based on the element's position value and its parent's width and height dimensions. */
2938
+ samePercentRatio = ((sameRatioIndicators.position === callUnitConversionData.lastPosition) && (sameRatioIndicators.myParent === callUnitConversionData.lastParent)),
2939
+ /* Determine if the same em ratio can be used. em is relative to the element's fontSize. */
2940
+ sameEmRatio = (sameRatioIndicators.fontSize === callUnitConversionData.lastFontSize);
2941
+
2942
+ /* Store these ratio indicators call-wide for the next element to compare against. */
2943
+ callUnitConversionData.lastParent = sameRatioIndicators.myParent;
2944
+ callUnitConversionData.lastPosition = sameRatioIndicators.position;
2945
+ callUnitConversionData.lastFontSize = sameRatioIndicators.fontSize;
2946
+
2947
+ /***************************
2948
+ Element-Specific Units
2949
+ ***************************/
2950
+
2951
+ /* Note: IE8 rounds to the nearest pixel when returning CSS values, thus we perform conversions using a measurement
2952
+ of 100 (instead of 1) to give our ratios a precision of at least 2 decimal values. */
2953
+ var measurement = 100,
2954
+ unitRatios = {};
2955
+
2956
+ if (!sameEmRatio || !samePercentRatio) {
2957
+ var dummy = Data(element).isSVG ? document.createElementNS("http://www.w3.org/2000/svg", "rect") : document.createElement("div");
2958
+
2959
+ Velocity.init(dummy);
2960
+ sameRatioIndicators.myParent.appendChild(dummy);
2961
+
2962
+ /* To accurately and consistently calculate conversion ratios, the element's cascaded overflow and box-sizing are stripped.
2963
+ Similarly, since width/height can be artificially constrained by their min-/max- equivalents, these are controlled for as well. */
2964
+ /* Note: Overflow must be also be controlled for per-axis since the overflow property overwrites its per-axis values. */
2965
+ $.each([ "overflow", "overflowX", "overflowY" ], function(i, property) {
2966
+ Velocity.CSS.setPropertyValue(dummy, property, "hidden");
2967
+ });
2968
+ Velocity.CSS.setPropertyValue(dummy, "position", sameRatioIndicators.position);
2969
+ Velocity.CSS.setPropertyValue(dummy, "fontSize", sameRatioIndicators.fontSize);
2970
+ Velocity.CSS.setPropertyValue(dummy, "boxSizing", "content-box");
2971
+
2972
+ /* width and height act as our proxy properties for measuring the horizontal and vertical % ratios. */
2973
+ $.each([ "minWidth", "maxWidth", "width", "minHeight", "maxHeight", "height" ], function(i, property) {
2974
+ Velocity.CSS.setPropertyValue(dummy, property, measurement + "%");
2975
+ });
2976
+ /* paddingLeft arbitrarily acts as our proxy property for the em ratio. */
2977
+ Velocity.CSS.setPropertyValue(dummy, "paddingLeft", measurement + "em");
2978
+
2979
+ /* Divide the returned value by the measurement to get the ratio between 1% and 1px. Default to 1 since working with 0 can produce Infinite. */
2980
+ unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth = (parseFloat(CSS.getPropertyValue(dummy, "width", null, true)) || 1) / measurement; /* GET */
2981
+ unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight = (parseFloat(CSS.getPropertyValue(dummy, "height", null, true)) || 1) / measurement; /* GET */
2982
+ unitRatios.emToPx = callUnitConversionData.lastEmToPx = (parseFloat(CSS.getPropertyValue(dummy, "paddingLeft")) || 1) / measurement; /* GET */
2983
+
2984
+ sameRatioIndicators.myParent.removeChild(dummy);
2985
+ } else {
2986
+ unitRatios.emToPx = callUnitConversionData.lastEmToPx;
2987
+ unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth;
2988
+ unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight;
2989
+ }
2990
+
2991
+ /***************************
2992
+ Element-Agnostic Units
2993
+ ***************************/
2994
+
2995
+ /* Whereas % and em ratios are determined on a per-element basis, the rem unit only needs to be checked
2996
+ once per call since it's exclusively dependant upon document.body's fontSize. If this is the first time
2997
+ that calculateUnitRatios() is being run during this call, remToPx will still be set to its default value of null,
2998
+ so we calculate it now. */
2999
+ if (callUnitConversionData.remToPx === null) {
3000
+ /* Default to browsers' default fontSize of 16px in the case of 0. */
3001
+ callUnitConversionData.remToPx = parseFloat(CSS.getPropertyValue(document.body, "fontSize")) || 16; /* GET */
3002
+ }
3003
+
3004
+ /* Similarly, viewport units are %-relative to the window's inner dimensions. */
3005
+ if (callUnitConversionData.vwToPx === null) {
3006
+ callUnitConversionData.vwToPx = parseFloat(window.innerWidth) / 100; /* GET */
3007
+ callUnitConversionData.vhToPx = parseFloat(window.innerHeight) / 100; /* GET */
3008
+ }
3009
+
3010
+ unitRatios.remToPx = callUnitConversionData.remToPx;
3011
+ unitRatios.vwToPx = callUnitConversionData.vwToPx;
3012
+ unitRatios.vhToPx = callUnitConversionData.vhToPx;
3013
+
3014
+ if (Velocity.debug >= 1) console.log("Unit ratios: " + JSON.stringify(unitRatios), element);
3015
+
3016
+ return unitRatios;
3017
+ }
3018
+
3019
+ /********************
3020
+ Unit Conversion
3021
+ ********************/
3022
+
3023
+ /* The * and / operators, which are not passed in with an associated unit, inherently use startValue's unit. Skip value and unit conversion. */
3024
+ if (/[\/*]/.test(operator)) {
3025
+ endValueUnitType = startValueUnitType;
3026
+ /* If startValue and endValue differ in unit type, convert startValue into the same unit type as endValue so that if endValueUnitType
3027
+ is a relative unit (%, em, rem), the values set during tweening will continue to be accurately relative even if the metrics they depend
3028
+ on are dynamically changing during the course of the animation. Conversely, if we always normalized into px and used px for setting values, the px ratio
3029
+ would become stale if the original unit being animated toward was relative and the underlying metrics change during the animation. */
3030
+ /* Since 0 is 0 in any unit type, no conversion is necessary when startValue is 0 -- we just start at 0 with endValueUnitType. */
3031
+ } else if ((startValueUnitType !== endValueUnitType) && startValue !== 0) {
3032
+ /* Unit conversion is also skipped when endValue is 0, but *startValueUnitType* must be used for tween values to remain accurate. */
3033
+ /* Note: Skipping unit conversion here means that if endValueUnitType was originally a relative unit, the animation won't relatively
3034
+ match the underlying metrics if they change, but this is acceptable since we're animating toward invisibility instead of toward visibility,
3035
+ which remains past the point of the animation's completion. */
3036
+ if (endValue === 0) {
3037
+ endValueUnitType = startValueUnitType;
3038
+ } else {
3039
+ /* By this point, we cannot avoid unit conversion (it's undesirable since it causes layout thrashing).
3040
+ If we haven't already, we trigger calculateUnitRatios(), which runs once per element per call. */
3041
+ elementUnitConversionData = elementUnitConversionData || calculateUnitRatios();
3042
+
3043
+ /* The following RegEx matches CSS properties that have their % values measured relative to the x-axis. */
3044
+ /* Note: W3C spec mandates that all of margin and padding's properties (even top and bottom) are %-relative to the *width* of the parent element. */
3045
+ var axis = (/margin|padding|left|right|width|text|word|letter/i.test(property) || /X$/.test(property) || property === "x") ? "x" : "y";
3046
+
3047
+ /* In order to avoid generating n^2 bespoke conversion functions, unit conversion is a two-step process:
3048
+ 1) Convert startValue into pixels. 2) Convert this new pixel value into endValue's unit type. */
3049
+ switch (startValueUnitType) {
3050
+ case "%":
3051
+ /* Note: translateX and translateY are the only properties that are %-relative to an element's own dimensions -- not its parent's dimensions.
3052
+ Velocity does not include a special conversion process to account for this behavior. Therefore, animating translateX/Y from a % value
3053
+ to a non-% value will produce an incorrect start value. Fortunately, this sort of cross-unit conversion is rarely done by users in practice. */
3054
+ startValue *= (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
3055
+ break;
3056
+
3057
+ case "px":
3058
+ /* px acts as our midpoint in the unit conversion process; do nothing. */
3059
+ break;
3060
+
3061
+ default:
3062
+ startValue *= elementUnitConversionData[startValueUnitType + "ToPx"];
3063
+ }
3064
+
3065
+ /* Invert the px ratios to convert into to the target unit. */
3066
+ switch (endValueUnitType) {
3067
+ case "%":
3068
+ startValue *= 1 / (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
3069
+ break;
3070
+
3071
+ case "px":
3072
+ /* startValue is already in px, do nothing; we're done. */
3073
+ break;
3074
+
3075
+ default:
3076
+ startValue *= 1 / elementUnitConversionData[endValueUnitType + "ToPx"];
3077
+ }
3078
+ }
3079
+ }
3080
+
3081
+ /*********************
3082
+ Relative Values
3083
+ *********************/
3084
+
3085
+ /* Operator logic must be performed last since it requires unit-normalized start and end values. */
3086
+ /* Note: Relative *percent values* do not behave how most people think; while one would expect "+=50%"
3087
+ to increase the property 1.5x its current value, it in fact increases the percent units in absolute terms:
3088
+ 50 points is added on top of the current % value. */
3089
+ switch (operator) {
3090
+ case "+":
3091
+ endValue = startValue + endValue;
3092
+ break;
3093
+
3094
+ case "-":
3095
+ endValue = startValue - endValue;
3096
+ break;
3097
+
3098
+ case "*":
3099
+ endValue = startValue * endValue;
3100
+ break;
3101
+
3102
+ case "/":
3103
+ endValue = startValue / endValue;
3104
+ break;
3105
+ }
3106
+
3107
+ /**************************
3108
+ tweensContainer Push
3109
+ **************************/
3110
+
3111
+ /* Construct the per-property tween object, and push it to the element's tweensContainer. */
3112
+ tweensContainer[property] = {
3113
+ rootPropertyValue: rootPropertyValue,
3114
+ startValue: startValue,
3115
+ currentValue: startValue,
3116
+ endValue: endValue,
3117
+ unitType: endValueUnitType,
3118
+ easing: easing
3119
+ };
3120
+
3121
+ if (Velocity.debug) console.log("tweensContainer (" + property + "): " + JSON.stringify(tweensContainer[property]), element);
3122
+ }
3123
+
3124
+ /* Along with its property data, store a reference to the element itself onto tweensContainer. */
3125
+ tweensContainer.element = element;
3126
+ }
3127
+
3128
+ /*****************
3129
+ Call Push
3130
+ *****************/
3131
+
3132
+ /* Note: tweensContainer can be empty if all of the properties in this call's property map were skipped due to not
3133
+ being supported by the browser. The element property is used for checking that the tweensContainer has been appended to. */
3134
+ if (tweensContainer.element) {
3135
+ /* Apply the "velocity-animating" indicator class. */
3136
+ CSS.Values.addClass(element, "velocity-animating");
3137
+
3138
+ /* The call array houses the tweensContainers for each element being animated in the current call. */
3139
+ call.push(tweensContainer);
3140
+
3141
+ /* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */
3142
+ if (opts.queue === "") {
3143
+ Data(element).tweensContainer = tweensContainer;
3144
+ Data(element).opts = opts;
3145
+ }
3146
+
3147
+ /* Switch on the element's animating flag. */
3148
+ Data(element).isAnimating = true;
3149
+
3150
+ /* Once the final element in this call's element set has been processed, push the call array onto
3151
+ Velocity.State.calls for the animation tick to immediately begin processing. */
3152
+ if (elementsIndex === elementsLength - 1) {
3153
+ /* To speed up iterating over this array, it is compacted (falsey items -- calls that have completed -- are removed)
3154
+ when its length has ballooned to a point that can impact tick performance. This only becomes necessary when animation
3155
+ has been continuous with many elements over a long period of time; whenever all active calls are completed, completeCall() clears Velocity.State.calls. */
3156
+ if (Velocity.State.calls.length > 10000) {
3157
+ Velocity.State.calls = compactSparseArray(Velocity.State.calls);
3158
+ }
3159
+
3160
+ /* Add the current call plus its associated metadata (the element set and the call's options) onto the global call container.
3161
+ Anything on this call container is subjected to tick() processing. */
3162
+ Velocity.State.calls.push([ call, elements, opts, null, promiseData.resolver ]);
3163
+
3164
+ /* If the animation tick isn't running, start it. (Velocity shuts it off when there are no active calls to process.) */
3165
+ if (Velocity.State.isTicking === false) {
3166
+ Velocity.State.isTicking = true;
3167
+
3168
+ /* Start the tick loop. */
3169
+ tick();
3170
+ }
3171
+ } else {
3172
+ elementsIndex++;
3173
+ }
3174
+ }
3175
+ }
3176
+
3177
+ /* When the queue option is set to false, the call skips the element's queue and fires immediately. */
3178
+ if (opts.queue === false) {
3179
+ /* Since this buildQueue call doesn't respect the element's existing queue (which is where a delay option would have been appended),
3180
+ we manually inject the delay property here with an explicit setTimeout. */
3181
+ if (opts.delay) {
3182
+ setTimeout(buildQueue, opts.delay);
3183
+ } else {
3184
+ buildQueue();
3185
+ }
3186
+ /* Otherwise, the call undergoes element queueing as normal. */
3187
+ /* Note: To interoperate with jQuery, Velocity uses jQuery's own $.queue() stack for queuing logic. */
3188
+ } else {
3189
+ $.queue(element, opts.queue, function(next, clearQueue) {
3190
+ /* If the clearQueue flag was passed in by the stop command, resolve this call's promise. (Promises can only be resolved once,
3191
+ so it's fine if this is repeatedly triggered for each element in the associated call.) */
3192
+ if (clearQueue === true) {
3193
+ if (promiseData.promise) {
3194
+ promiseData.resolver(elements);
3195
+ }
3196
+
3197
+ /* Do not continue with animation queueing. */
3198
+ return true;
3199
+ }
3200
+
3201
+ /* This flag indicates to the upcoming completeCall() function that this queue entry was initiated by Velocity.
3202
+ See completeCall() for further details. */
3203
+ Velocity.velocityQueueEntryFlag = true;
3204
+
3205
+ buildQueue(next);
3206
+ });
3207
+ }
3208
+
3209
+ /*********************
3210
+ Auto-Dequeuing
3211
+ *********************/
3212
+
3213
+ /* As per jQuery's $.queue() behavior, to fire the first non-custom-queue entry on an element, the element
3214
+ must be dequeued if its queue stack consists *solely* of the current call. (This can be determined by checking
3215
+ for the "inprogress" item that jQuery prepends to active queue stack arrays.) Regardless, whenever the element's
3216
+ queue is further appended with additional items -- including $.delay()'s or even $.animate() calls, the queue's
3217
+ first entry is automatically fired. This behavior contrasts that of custom queues, which never auto-fire. */
3218
+ /* Note: When an element set is being subjected to a non-parallel Velocity call, the animation will not begin until
3219
+ each one of the elements in the set has reached the end of its individually pre-existing queue chain. */
3220
+ /* Note: Unfortunately, most people don't fully grasp jQuery's powerful, yet quirky, $.queue() function.
3221
+ Lean more here: http://stackoverflow.com/questions/1058158/can-somebody-explain-jquery-queue-to-me */
3222
+ if ((opts.queue === "" || opts.queue === "fx") && $.queue(element)[0] !== "inprogress") {
3223
+ $.dequeue(element);
3224
+ }
3225
+ }
3226
+
3227
+ /**************************
3228
+ Element Set Iteration
3229
+ **************************/
3230
+
3231
+ /* If the "nodeType" property exists on the elements variable, we're animating a single element.
3232
+ Place it in an array so that $.each() can iterate over it. */
3233
+ $.each(elements, function(i, element) {
3234
+ /* Ensure each element in a set has a nodeType (is a real element) to avoid throwing errors. */
3235
+ if (Type.isNode(element)) {
3236
+ processElement.call(element);
3237
+ }
3238
+ });
3239
+
3240
+ /******************
3241
+ Option: Loop
3242
+ ******************/
3243
+
3244
+ /* The loop option accepts an integer indicating how many times the element should loop between the values in the
3245
+ current call's properties map and the element's property values prior to this call. */
3246
+ /* Note: The loop option's logic is performed here -- after element processing -- because the current call needs
3247
+ to undergo its queue insertion prior to the loop option generating its series of constituent "reverse" calls,
3248
+ which chain after the current call. Two reverse calls (two "alternations") constitute one loop. */
3249
+ var opts = $.extend({}, Velocity.defaults, options),
3250
+ reverseCallsCount;
3251
+
3252
+ opts.loop = parseInt(opts.loop);
3253
+ reverseCallsCount = (opts.loop * 2) - 1;
3254
+
3255
+ if (opts.loop) {
3256
+ /* Double the loop count to convert it into its appropriate number of "reverse" calls.
3257
+ Subtract 1 from the resulting value since the current call is included in the total alternation count. */
3258
+ for (var x = 0; x < reverseCallsCount; x++) {
3259
+ /* Since the logic for the reverse action occurs inside Queueing and therefore this call's options object
3260
+ isn't parsed until then as well, the current call's delay option must be explicitly passed into the reverse
3261
+ call so that the delay logic that occurs inside *Pre-Queueing* can process it. */
3262
+ var reverseOptions = {
3263
+ delay: opts.delay,
3264
+ progress: opts.progress
3265
+ };
3266
+
3267
+ /* If a complete callback was passed into this call, transfer it to the loop redirect's final "reverse" call
3268
+ so that it's triggered when the entire redirect is complete (and not when the very first animation is complete). */
3269
+ if (x === reverseCallsCount - 1) {
3270
+ reverseOptions.display = opts.display;
3271
+ reverseOptions.visibility = opts.visibility;
3272
+ reverseOptions.complete = opts.complete;
3273
+ }
3274
+
3275
+ animate(elements, "reverse", reverseOptions);
3276
+ }
3277
+ }
3278
+
3279
+ /***************
3280
+ Chaining
3281
+ ***************/
3282
+
3283
+ /* Return the elements back to the call chain, with wrapped elements taking precedence in case Velocity was called via the $.fn. extension. */
3284
+ return getChain();
3285
+ };
3286
+
3287
+ /* Turn Velocity into the animation function, extended with the pre-existing Velocity object. */
3288
+ Velocity = $.extend(animate, Velocity);
3289
+ /* For legacy support, also expose the literal animate method. */
3290
+ Velocity.animate = animate;
3291
+
3292
+ /**************
3293
+ Timing
3294
+ **************/
3295
+
3296
+ /* Ticker function. */
3297
+ var ticker = window.requestAnimationFrame || rAFShim;
3298
+
3299
+ /* Inactive browser tabs pause rAF, which results in all active animations immediately sprinting to their completion states when the tab refocuses.
3300
+ To get around this, we dynamically switch rAF to setTimeout (which the browser *doesn't* pause) when the tab loses focus. We skip this for mobile
3301
+ devices to avoid wasting battery power on inactive tabs. */
3302
+ /* Note: Tab focus detection doesn't work on older versions of IE, but that's okay since they don't support rAF to begin with. */
3303
+ if (!Velocity.State.isMobile && document.hidden !== undefined) {
3304
+ document.addEventListener("visibilitychange", function() {
3305
+ /* Reassign the rAF function (which the global tick() function uses) based on the tab's focus state. */
3306
+ if (document.hidden) {
3307
+ ticker = function(callback) {
3308
+ /* The tick function needs a truthy first argument in order to pass its internal timestamp check. */
3309
+ return setTimeout(function() { callback(true) }, 16);
3310
+ };
3311
+
3312
+ /* The rAF loop has been paused by the browser, so we manually restart the tick. */
3313
+ tick();
3314
+ } else {
3315
+ ticker = window.requestAnimationFrame || rAFShim;
3316
+ }
3317
+ });
3318
+ }
3319
+
3320
+ /************
3321
+ Tick
3322
+ ************/
3323
+
3324
+ /* Note: All calls to Velocity are pushed to the Velocity.State.calls array, which is fully iterated through upon each tick. */
3325
+ function tick (timestamp) {
3326
+ /* An empty timestamp argument indicates that this is the first tick occurence since ticking was turned on.
3327
+ We leverage this metadata to fully ignore the first tick pass since RAF's initial pass is fired whenever
3328
+ the browser's next tick sync time occurs, which results in the first elements subjected to Velocity
3329
+ calls being animated out of sync with any elements animated immediately thereafter. In short, we ignore
3330
+ the first RAF tick pass so that elements being immediately consecutively animated -- instead of simultaneously animated
3331
+ by the same Velocity call -- are properly batched into the same initial RAF tick and consequently remain in sync thereafter. */
3332
+ if (timestamp) {
3333
+ /* We ignore RAF's high resolution timestamp since it can be significantly offset when the browser is
3334
+ under high stress; we opt for choppiness over allowing the browser to drop huge chunks of frames. */
3335
+ var timeCurrent = (new Date).getTime();
3336
+
3337
+ /********************
3338
+ Call Iteration
3339
+ ********************/
3340
+
3341
+ /* Iterate through each active call. */
3342
+ for (var i = 0, callsLength = Velocity.State.calls.length; i < callsLength; i++) {
3343
+ /* When a Velocity call is completed, its Velocity.State.calls entry is set to false. Continue on to the next call. */
3344
+ if (!Velocity.State.calls[i]) {
3345
+ continue;
3346
+ }
3347
+
3348
+ /************************
3349
+ Call-Wide Variables
3350
+ ************************/
3351
+
3352
+ var callContainer = Velocity.State.calls[i],
3353
+ call = callContainer[0],
3354
+ opts = callContainer[2],
3355
+ timeStart = callContainer[3],
3356
+ firstTick = !!timeStart;
3357
+
3358
+ /* If timeStart is undefined, then this is the first time that this call has been processed by tick().
3359
+ We assign timeStart now so that its value is as close to the real animation start time as possible.
3360
+ (Conversely, had timeStart been defined when this call was added to Velocity.State.calls, the delay
3361
+ between that time and now would cause the first few frames of the tween to be skipped since
3362
+ percentComplete is calculated relative to timeStart.) */
3363
+ /* Further, subtract 16ms (the approximate resolution of RAF) from the current time value so that the
3364
+ first tick iteration isn't wasted by animating at 0% tween completion, which would produce the
3365
+ same style value as the element's current value. */
3366
+ if (!timeStart) {
3367
+ timeStart = Velocity.State.calls[i][3] = timeCurrent - 16;
3368
+ }
3369
+
3370
+ /* The tween's completion percentage is relative to the tween's start time, not the tween's start value
3371
+ (which would result in unpredictable tween durations since JavaScript's timers are not particularly accurate).
3372
+ Accordingly, we ensure that percentComplete does not exceed 1. */
3373
+ var percentComplete = Math.min((timeCurrent - timeStart) / opts.duration, 1);
3374
+
3375
+ /**********************
3376
+ Element Iteration
3377
+ **********************/
3378
+
3379
+ /* For every call, iterate through each of the elements in its set. */
3380
+ for (var j = 0, callLength = call.length; j < callLength; j++) {
3381
+ var tweensContainer = call[j],
3382
+ element = tweensContainer.element;
3383
+
3384
+ /* Check to see if this element has been deleted midway through the animation by checking for the
3385
+ continued existence of its data cache. If it's gone, skip animating this element. */
3386
+ if (!Data(element)) {
3387
+ continue;
3388
+ }
3389
+
3390
+ var transformPropertyExists = false;
3391
+
3392
+ /**********************************
3393
+ Display & Visibility Toggling
3394
+ **********************************/
3395
+
3396
+ /* If the display option is set to non-"none", set it upfront so that the element can become visible before tweening begins.
3397
+ (Otherwise, display's "none" value is set in completeCall() once the animation has completed.) */
3398
+ if (opts.display !== undefined && opts.display !== null && opts.display !== "none") {
3399
+ if (opts.display === "flex") {
3400
+ var flexValues = [ "-webkit-box", "-moz-box", "-ms-flexbox", "-webkit-flex" ];
3401
+
3402
+ $.each(flexValues, function(i, flexValue) {
3403
+ CSS.setPropertyValue(element, "display", flexValue);
3404
+ });
3405
+ }
3406
+
3407
+ CSS.setPropertyValue(element, "display", opts.display);
3408
+ }
3409
+
3410
+ /* Same goes with the visibility option, but its "none" equivalent is "hidden". */
3411
+ if (opts.visibility !== undefined && opts.visibility !== "hidden") {
3412
+ CSS.setPropertyValue(element, "visibility", opts.visibility);
3413
+ }
3414
+
3415
+ /************************
3416
+ Property Iteration
3417
+ ************************/
3418
+
3419
+ /* For every element, iterate through each property. */
3420
+ for (var property in tweensContainer) {
3421
+ /* Note: In addition to property tween data, tweensContainer contains a reference to its associated element. */
3422
+ if (property !== "element") {
3423
+ var tween = tweensContainer[property],
3424
+ currentValue,
3425
+ /* Easing can either be a pre-genereated function or a string that references a pre-registered easing
3426
+ on the Velocity.Easings object. In either case, return the appropriate easing *function*. */
3427
+ easing = Type.isString(tween.easing) ? Velocity.Easings[tween.easing] : tween.easing;
3428
+
3429
+ /******************************
3430
+ Current Value Calculation
3431
+ ******************************/
3432
+
3433
+ /* If this is the last tick pass (if we've reached 100% completion for this tween),
3434
+ ensure that currentValue is explicitly set to its target endValue so that it's not subjected to any rounding. */
3435
+ if (percentComplete === 1) {
3436
+ currentValue = tween.endValue;
3437
+ /* Otherwise, calculate currentValue based on the current delta from startValue. */
3438
+ } else {
3439
+ currentValue = tween.startValue + ((tween.endValue - tween.startValue) * easing(percentComplete));
3440
+
3441
+ /* If no value change is occurring, don't proceed with DOM updating. */
3442
+ if (!firstTick && (currentValue === tween.currentValue)) {
3443
+ continue;
3444
+ }
3445
+ }
3446
+
3447
+ tween.currentValue = currentValue;
3448
+
3449
+ /******************
3450
+ Hooks: Part I
3451
+ ******************/
3452
+
3453
+ /* For hooked properties, the newly-updated rootPropertyValueCache is cached onto the element so that it can be used
3454
+ for subsequent hooks in this call that are associated with the same root property. If we didn't cache the updated
3455
+ rootPropertyValue, each subsequent update to the root property in this tick pass would reset the previous hook's
3456
+ updates to rootPropertyValue prior to injection. A nice performance byproduct of rootPropertyValue caching is that
3457
+ subsequently chained animations using the same hookRoot but a different hook can use this cached rootPropertyValue. */
3458
+ if (CSS.Hooks.registered[property]) {
3459
+ var hookRoot = CSS.Hooks.getRoot(property),
3460
+ rootPropertyValueCache = Data(element).rootPropertyValueCache[hookRoot];
3461
+
3462
+ if (rootPropertyValueCache) {
3463
+ tween.rootPropertyValue = rootPropertyValueCache;
3464
+ }
3465
+ }
3466
+
3467
+ /*****************
3468
+ DOM Update
3469
+ *****************/
3470
+
3471
+ /* setPropertyValue() returns an array of the property name and property value post any normalization that may have been performed. */
3472
+ /* Note: To solve an IE<=8 positioning bug, the unit type is dropped when setting a property value of 0. */
3473
+ var adjustedSetData = CSS.setPropertyValue(element, /* SET */
3474
+ property,
3475
+ tween.currentValue + (parseFloat(currentValue) === 0 ? "" : tween.unitType),
3476
+ tween.rootPropertyValue,
3477
+ tween.scrollData);
3478
+
3479
+ /*******************
3480
+ Hooks: Part II
3481
+ *******************/
3482
+
3483
+ /* Now that we have the hook's updated rootPropertyValue (the post-processed value provided by adjustedSetData), cache it onto the element. */
3484
+ if (CSS.Hooks.registered[property]) {
3485
+ /* Since adjustedSetData contains normalized data ready for DOM updating, the rootPropertyValue needs to be re-extracted from its normalized form. ?? */
3486
+ if (CSS.Normalizations.registered[hookRoot]) {
3487
+ Data(element).rootPropertyValueCache[hookRoot] = CSS.Normalizations.registered[hookRoot]("extract", null, adjustedSetData[1]);
3488
+ } else {
3489
+ Data(element).rootPropertyValueCache[hookRoot] = adjustedSetData[1];
3490
+ }
3491
+ }
3492
+
3493
+ /***************
3494
+ Transforms
3495
+ ***************/
3496
+
3497
+ /* Flag whether a transform property is being animated so that flushTransformCache() can be triggered once this tick pass is complete. */
3498
+ if (adjustedSetData[0] === "transform") {
3499
+ transformPropertyExists = true;
3500
+ }
3501
+ }
3502
+ }
3503
+
3504
+ /****************
3505
+ mobileHA
3506
+ ****************/
3507
+
3508
+ /* If mobileHA is enabled, set the translate3d transform to null to force hardware acceleration.
3509
+ It's safe to override this property since Velocity doesn't actually support its animation (hooks are used in its place). */
3510
+ if (opts.mobileHA) {
3511
+ /* Don't set the null transform hack if we've already done so. */
3512
+ if (Data(element).transformCache.translate3d === undefined) {
3513
+ /* All entries on the transformCache object are later concatenated into a single transform string via flushTransformCache(). */
3514
+ Data(element).transformCache.translate3d = "(0px, 0px, 0px)";
3515
+
3516
+ transformPropertyExists = true;
3517
+ }
3518
+ }
3519
+
3520
+ if (transformPropertyExists) {
3521
+ CSS.flushTransformCache(element);
3522
+ }
3523
+ }
3524
+
3525
+ /* The non-"none" display value is only applied to an element once -- when its associated call is first ticked through.
3526
+ Accordingly, it's set to false so that it isn't re-processed by this call in the next tick. */
3527
+ if (opts.display !== undefined && opts.display !== "none") {
3528
+ Velocity.State.calls[i][2].display = false;
3529
+ }
3530
+ if (opts.visibility !== undefined && opts.visibility !== "hidden") {
3531
+ Velocity.State.calls[i][2].visibility = false;
3532
+ }
3533
+
3534
+
3535
+ /* Pass the elements and the timing data (percentComplete, msRemaining, and timeStart) into the progress callback. */
3536
+ if (opts.progress) {
3537
+ opts.progress.call(callContainer[1],
3538
+ callContainer[1],
3539
+ percentComplete,
3540
+ Math.max(0, (timeStart + opts.duration) - timeCurrent),
3541
+ timeStart);
3542
+ }
3543
+
3544
+ /* If this call has finished tweening, pass its index to completeCall() to handle call cleanup. */
3545
+ if (percentComplete === 1) {
3546
+ completeCall(i);
3547
+ }
3548
+ }
3549
+ }
3550
+
3551
+ /* Note: completeCall() sets the isTicking flag to false when the last call on Velocity.State.calls has completed. */
3552
+ if (Velocity.State.isTicking) {
3553
+ ticker(tick);
3554
+ }
3555
+ }
3556
+
3557
+ /**********************
3558
+ Call Completion
3559
+ **********************/
3560
+
3561
+ /* Note: Unlike tick(), which processes all active calls at once, call completion is handled on a per-call basis. */
3562
+ function completeCall (callIndex, isStopped) {
3563
+ /* Ensure the call exists. */
3564
+ if (!Velocity.State.calls[callIndex]) {
3565
+ return false;
3566
+ }
3567
+
3568
+ /* Pull the metadata from the call. */
3569
+ var call = Velocity.State.calls[callIndex][0],
3570
+ elements = Velocity.State.calls[callIndex][1],
3571
+ opts = Velocity.State.calls[callIndex][2],
3572
+ resolver = Velocity.State.calls[callIndex][4];
3573
+
3574
+ var remainingCallsExist = false;
3575
+
3576
+ /*************************
3577
+ Element Finalization
3578
+ *************************/
3579
+
3580
+ for (var i = 0, callLength = call.length; i < callLength; i++) {
3581
+ var element = call[i].element;
3582
+
3583
+ /* If the user set display to "none" (intending to hide the element), set it now that the animation has completed. */
3584
+ /* Note: display:none isn't set when calls are manually stopped (via Velocity("stop"). */
3585
+ /* Note: Display gets ignored with "reverse" calls and infinite loops, since this behavior would be undesirable. */
3586
+ if (!isStopped && !opts.loop) {
3587
+ if (opts.display === "none") {
3588
+ CSS.setPropertyValue(element, "display", opts.display);
3589
+ }
3590
+
3591
+ if (opts.visibility === "hidden") {
3592
+ CSS.setPropertyValue(element, "visibility", opts.visibility);
3593
+ }
3594
+ }
3595
+
3596
+ /* If the element's queue is empty (if only the "inprogress" item is left at position 0) or if its queue is about to run
3597
+ a non-Velocity-initiated entry, turn off the isAnimating flag. A non-Velocity-initiatied queue entry's logic might alter
3598
+ an element's CSS values and thereby cause Velocity's cached value data to go stale. To detect if a queue entry was initiated by Velocity,
3599
+ we check for the existence of our special Velocity.queueEntryFlag declaration, which minifiers won't rename since the flag
3600
+ is assigned to jQuery's global $ object and thus exists out of Velocity's own scope. */
3601
+ if (opts.loop !== true && ($.queue(element)[1] === undefined || !/\.velocityQueueEntryFlag/i.test($.queue(element)[1]))) {
3602
+ /* The element may have been deleted. Ensure that its data cache still exists before acting on it. */
3603
+ if (Data(element)) {
3604
+ Data(element).isAnimating = false;
3605
+ /* Clear the element's rootPropertyValueCache, which will become stale. */
3606
+ Data(element).rootPropertyValueCache = {};
3607
+
3608
+ var transformHAPropertyExists = false;
3609
+ /* If any 3D transform subproperty is at its default value (regardless of unit type), remove it. */
3610
+ $.each(CSS.Lists.transforms3D, function(i, transformName) {
3611
+ var defaultValue = /^scale/.test(transformName) ? 1 : 0,
3612
+ currentValue = Data(element).transformCache[transformName];
3613
+
3614
+ if (Data(element).transformCache[transformName] !== undefined && new RegExp("^\\(" + defaultValue + "[^.]").test(currentValue)) {
3615
+ transformHAPropertyExists = true;
3616
+
3617
+ delete Data(element).transformCache[transformName];
3618
+ }
3619
+ });
3620
+
3621
+ /* Mobile devices have hardware acceleration removed at the end of the animation in order to avoid hogging the GPU's memory. */
3622
+ if (opts.mobileHA) {
3623
+ transformHAPropertyExists = true;
3624
+ delete Data(element).transformCache.translate3d;
3625
+ }
3626
+
3627
+ /* Flush the subproperty removals to the DOM. */
3628
+ if (transformHAPropertyExists) {
3629
+ CSS.flushTransformCache(element);
3630
+ }
3631
+
3632
+ /* Remove the "velocity-animating" indicator class. */
3633
+ CSS.Values.removeClass(element, "velocity-animating");
3634
+ }
3635
+ }
3636
+
3637
+ /*********************
3638
+ Option: Complete
3639
+ *********************/
3640
+
3641
+ /* Complete is fired once per call (not once per element) and is passed the full raw DOM element set as both its context and its first argument. */
3642
+ /* Note: Callbacks aren't fired when calls are manually stopped (via Velocity("stop"). */
3643
+ if (!isStopped && opts.complete && !opts.loop && (i === callLength - 1)) {
3644
+ /* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
3645
+ try {
3646
+ opts.complete.call(elements, elements);
3647
+ } catch (error) {
3648
+ setTimeout(function() { throw error; }, 1);
3649
+ }
3650
+ }
3651
+
3652
+ /**********************
3653
+ Promise Resolving
3654
+ **********************/
3655
+
3656
+ /* Note: Infinite loops don't return promises. */
3657
+ if (resolver && opts.loop !== true) {
3658
+ resolver(elements);
3659
+ }
3660
+
3661
+ /****************************
3662
+ Option: Loop (Infinite)
3663
+ ****************************/
3664
+
3665
+ if (opts.loop === true && !isStopped) {
3666
+ /* If a rotateX/Y/Z property is being animated to 360 deg with loop:true, swap tween start/end values to enable
3667
+ continuous iterative rotation looping. (Otherise, the element would just rotate back and forth.) */
3668
+ $.each(Data(element).tweensContainer, function(propertyName, tweenContainer) {
3669
+ if (/^rotate/.test(propertyName) && parseFloat(tweenContainer.endValue) === 360) {
3670
+ tweenContainer.endValue = 0;
3671
+ tweenContainer.startValue = 360;
3672
+ }
3673
+ });
3674
+
3675
+ Velocity(element, "reverse", { loop: true, delay: opts.delay });
3676
+ }
3677
+
3678
+ /***************
3679
+ Dequeueing
3680
+ ***************/
3681
+
3682
+ /* Fire the next call in the queue so long as this call's queue wasn't set to false (to trigger a parallel animation),
3683
+ which would have already caused the next call to fire. Note: Even if the end of the animation queue has been reached,
3684
+ $.dequeue() must still be called in order to completely clear jQuery's animation queue. */
3685
+ if (opts.queue !== false) {
3686
+ $.dequeue(element, opts.queue);
3687
+ }
3688
+ }
3689
+
3690
+ /************************
3691
+ Calls Array Cleanup
3692
+ ************************/
3693
+
3694
+ /* Since this call is complete, set it to false so that the rAF tick skips it. This array is later compacted via compactSparseArray().
3695
+ (For performance reasons, the call is set to false instead of being deleted from the array: http://www.html5rocks.com/en/tutorials/speed/v8/) */
3696
+ Velocity.State.calls[callIndex] = false;
3697
+
3698
+ /* Iterate through the calls array to determine if this was the final in-progress animation.
3699
+ If so, set a flag to end ticking and clear the calls array. */
3700
+ for (var j = 0, callsLength = Velocity.State.calls.length; j < callsLength; j++) {
3701
+ if (Velocity.State.calls[j] !== false) {
3702
+ remainingCallsExist = true;
3703
+
3704
+ break;
3705
+ }
3706
+ }
3707
+
3708
+ if (remainingCallsExist === false) {
3709
+ /* tick() will detect this flag upon its next iteration and subsequently turn itself off. */
3710
+ Velocity.State.isTicking = false;
3711
+
3712
+ /* Clear the calls array so that its length is reset. */
3713
+ delete Velocity.State.calls;
3714
+ Velocity.State.calls = [];
3715
+ }
3716
+ }
3717
+
3718
+ /******************
3719
+ Frameworks
3720
+ ******************/
3721
+
3722
+ /* Both jQuery and Zepto allow their $.fn object to be extended to allow wrapped elements to be subjected to plugin calls.
3723
+ If either framework is loaded, register a "velocity" extension pointing to Velocity's core animate() method. Velocity
3724
+ also registers itself onto a global container (window.jQuery || window.Zepto || window) so that certain features are
3725
+ accessible beyond just a per-element scope. This master object contains an .animate() method, which is later assigned to $.fn
3726
+ (if jQuery or Zepto are present). Accordingly, Velocity can both act on wrapped DOM elements and stand alone for targeting raw DOM elements. */
3727
+ global.Velocity = Velocity;
3728
+
3729
+ if (global !== window) {
3730
+ /* Assign the element function to Velocity's core animate() method. */
3731
+ global.fn.velocity = animate;
3732
+ /* Assign the object function's defaults to Velocity's global defaults object. */
3733
+ global.fn.velocity.defaults = Velocity.defaults;
3734
+ }
3735
+
3736
+ /***********************
3737
+ Packaged Redirects
3738
+ ***********************/
3739
+
3740
+ /* slideUp, slideDown */
3741
+ $.each([ "Down", "Up" ], function(i, direction) {
3742
+ Velocity.Redirects["slide" + direction] = function (element, options, elementsIndex, elementsSize, elements, promiseData) {
3743
+ var opts = $.extend({}, options),
3744
+ begin = opts.begin,
3745
+ complete = opts.complete,
3746
+ computedValues = { height: "", marginTop: "", marginBottom: "", paddingTop: "", paddingBottom: "" },
3747
+ inlineValues = {};
3748
+
3749
+ if (opts.display === undefined) {
3750
+ /* Show the element before slideDown begins and hide the element after slideUp completes. */
3751
+ /* Note: Inline elements cannot have dimensions animated, so they're reverted to inline-block. */
3752
+ opts.display = (direction === "Down" ? (Velocity.CSS.Values.getDisplayType(element) === "inline" ? "inline-block" : "block") : "none");
3753
+ }
3754
+
3755
+ opts.begin = function() {
3756
+ /* If the user passed in a begin callback, fire it now. */
3757
+ begin && begin.call(elements, elements);
3758
+
3759
+ /* Cache the elements' original vertical dimensional property values so that we can animate back to them. */
3760
+ for (var property in computedValues) {
3761
+ /* Cache all inline values, we reset to upon animation completion. */
3762
+ inlineValues[property] = element.style[property];
3763
+
3764
+ /* For slideDown, use forcefeeding to animate all vertical properties from 0. For slideUp,
3765
+ use forcefeeding to start from computed values and animate down to 0. */
3766
+ var propertyValue = Velocity.CSS.getPropertyValue(element, property);
3767
+ computedValues[property] = (direction === "Down") ? [ propertyValue, 0 ] : [ 0, propertyValue ];
3768
+ }
3769
+
3770
+ /* Force vertical overflow content to clip so that sliding works as expected. */
3771
+ inlineValues.overflow = element.style.overflow;
3772
+ element.style.overflow = "hidden";
3773
+ }
3774
+
3775
+ opts.complete = function() {
3776
+ /* Reset element to its pre-slide inline values once its slide animation is complete. */
3777
+ for (var property in inlineValues) {
3778
+ element.style[property] = inlineValues[property];
3779
+ }
3780
+
3781
+ /* If the user passed in a complete callback, fire it now. */
3782
+ complete && complete.call(elements, elements);
3783
+ promiseData && promiseData.resolver(elements);
3784
+ };
3785
+
3786
+ Velocity(element, computedValues, opts);
3787
+ };
3788
+ });
3789
+
3790
+ /* fadeIn, fadeOut */
3791
+ $.each([ "In", "Out" ], function(i, direction) {
3792
+ Velocity.Redirects["fade" + direction] = function (element, options, elementsIndex, elementsSize, elements, promiseData) {
3793
+ var opts = $.extend({}, options),
3794
+ propertiesMap = { opacity: (direction === "In") ? 1 : 0 },
3795
+ originalComplete = opts.complete;
3796
+
3797
+ /* Since redirects are triggered individually for each element in the animated set, avoid repeatedly triggering
3798
+ callbacks by firing them only when the final element has been reached. */
3799
+ if (elementsIndex !== elementsSize - 1) {
3800
+ opts.complete = opts.begin = null;
3801
+ } else {
3802
+ opts.complete = function() {
3803
+ if (originalComplete) {
3804
+ originalComplete.call(elements, elements);
3805
+ }
3806
+
3807
+ promiseData && promiseData.resolver(elements);
3808
+ }
3809
+ }
3810
+
3811
+ /* If a display was passed in, use it. Otherwise, default to "none" for fadeOut or the element-specific default for fadeIn. */
3812
+ /* Note: We allow users to pass in "null" to skip display setting altogether. */
3813
+ if (opts.display === undefined) {
3814
+ opts.display = (direction === "In" ? "auto" : "none");
3815
+ }
3816
+
3817
+ Velocity(this, propertiesMap, opts);
3818
+ };
3819
+ });
3820
+
3821
+ return Velocity;
3822
+ }((window.jQuery || window.Zepto || window), window, document);
3823
+ }));
3824
+
3825
+ /******************
3826
+ Known Issues
3827
+ ******************/
3828
+
3829
+ /* The CSS spec mandates that the translateX/Y/Z transforms are %-relative to the element itself -- not its parent.
3830
+ Velocity, however, doesn't make this distinction. Thus, converting to or from the % unit with these subproperties
3831
+ will produce an inaccurate conversion value. The same issue exists with the cx/cy attributes of SVG circles and ellipses. */