unpoly-rails 1.0.3 → 2.0.0.pre.rc2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

Files changed (344) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +43 -25
  4. data/README.md +5 -6
  5. data/README_RAILS.md +295 -14
  6. data/dist/unpoly-bootstrap3.css +9 -14
  7. data/dist/unpoly-bootstrap3.js +4 -18
  8. data/dist/unpoly-bootstrap3.min.css +1 -1
  9. data/dist/unpoly-bootstrap3.min.js +1 -1
  10. data/dist/unpoly-bootstrap4.css +9 -0
  11. data/dist/unpoly-bootstrap4.js +16 -0
  12. data/dist/unpoly-bootstrap4.min.css +1 -0
  13. data/dist/unpoly-bootstrap4.min.js +1 -0
  14. data/dist/unpoly-bootstrap5.css +9 -0
  15. data/dist/unpoly-bootstrap5.js +14 -0
  16. data/dist/unpoly-bootstrap5.min.css +1 -0
  17. data/dist/unpoly-bootstrap5.min.js +1 -0
  18. data/dist/unpoly-migrate.js +1213 -0
  19. data/dist/unpoly-migrate.min.js +1 -0
  20. data/dist/unpoly.css +109 -140
  21. data/dist/unpoly.js +15376 -10484
  22. data/dist/unpoly.min.css +1 -1
  23. data/dist/unpoly.min.js +6 -4
  24. data/lib/unpoly/rails/change/cache.rb +26 -0
  25. data/lib/unpoly/rails/change/context.rb +80 -0
  26. data/lib/unpoly/rails/change/field.rb +117 -0
  27. data/lib/unpoly/rails/change/field_definition.rb +74 -0
  28. data/lib/unpoly/rails/change/layer.rb +60 -0
  29. data/lib/unpoly/rails/change.rb +372 -0
  30. data/lib/unpoly/rails/controller.rb +47 -0
  31. data/lib/unpoly/rails/error.rb +5 -0
  32. data/lib/unpoly/rails/request_echo_headers.rb +2 -2
  33. data/lib/unpoly/rails/version.rb +1 -1
  34. data/lib/unpoly/tasks.rb +45 -0
  35. data/lib/unpoly-rails.rb +9 -3
  36. metadata +42 -316
  37. data/.gitignore +0 -10
  38. data/.ruby-version +0 -1
  39. data/Gemfile +0 -7
  40. data/Gemfile.lock +0 -39
  41. data/Rakefile +0 -154
  42. data/bower.json +0 -27
  43. data/design/animation-ghosting.txt +0 -72
  44. data/design/design.txt +0 -34
  45. data/design/draft.html.erb +0 -48
  46. data/design/draft.rb +0 -9
  47. data/design/es6.js +0 -32
  48. data/design/ghost-debugging.txt +0 -118
  49. data/design/homepage.txt +0 -236
  50. data/design/ie11.txt +0 -9
  51. data/design/measure_import_node.js +0 -330
  52. data/design/measure_jquery/element_list.js +0 -41
  53. data/design/measure_jquery/up.on_vs_addEventListener.js +0 -56
  54. data/design/positioning.txt +0 -28
  55. data/design/query-params-in-form-actions/cases.html +0 -125
  56. data/design/rename.txt +0 -0
  57. data/design/test_rejected_promise.txt +0 -5
  58. data/design/unpoly errors.txt +0 -19
  59. data/lib/assets/javascripts/unpoly/browser.coffee.erb +0 -240
  60. data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +0 -45
  61. data/lib/assets/javascripts/unpoly/classes/cache.coffee +0 -127
  62. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +0 -93
  63. data/lib/assets/javascripts/unpoly/classes/config.coffee +0 -9
  64. data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +0 -118
  65. data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +0 -39
  66. data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +0 -116
  67. data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +0 -86
  68. data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +0 -111
  69. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +0 -80
  70. data/lib/assets/javascripts/unpoly/classes/focus_follower.coffee +0 -29
  71. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +0 -64
  72. data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +0 -46
  73. data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +0 -157
  74. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +0 -544
  75. data/lib/assets/javascripts/unpoly/classes/record.coffee +0 -22
  76. data/lib/assets/javascripts/unpoly/classes/rect.js +0 -21
  77. data/lib/assets/javascripts/unpoly/classes/request.coffee +0 -247
  78. data/lib/assets/javascripts/unpoly/classes/response.coffee +0 -157
  79. data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +0 -102
  80. data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +0 -67
  81. data/lib/assets/javascripts/unpoly/classes/selector.coffee +0 -60
  82. data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +0 -26
  83. data/lib/assets/javascripts/unpoly/classes/store/session.coffee +0 -59
  84. data/lib/assets/javascripts/unpoly/classes/tether.coffee +0 -105
  85. data/lib/assets/javascripts/unpoly/classes/url_set.coffee +0 -32
  86. data/lib/assets/javascripts/unpoly/cookie.coffee +0 -56
  87. data/lib/assets/javascripts/unpoly/element.coffee.erb +0 -1129
  88. data/lib/assets/javascripts/unpoly/event.coffee.erb +0 -445
  89. data/lib/assets/javascripts/unpoly/feedback.coffee +0 -353
  90. data/lib/assets/javascripts/unpoly/form.coffee.erb +0 -1084
  91. data/lib/assets/javascripts/unpoly/fragment.coffee.erb +0 -928
  92. data/lib/assets/javascripts/unpoly/framework.coffee +0 -65
  93. data/lib/assets/javascripts/unpoly/history.coffee +0 -268
  94. data/lib/assets/javascripts/unpoly/legacy.coffee +0 -60
  95. data/lib/assets/javascripts/unpoly/link.coffee.erb +0 -622
  96. data/lib/assets/javascripts/unpoly/log.coffee +0 -253
  97. data/lib/assets/javascripts/unpoly/modal.coffee.erb +0 -827
  98. data/lib/assets/javascripts/unpoly/motion.coffee.erb +0 -668
  99. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
  100. data/lib/assets/javascripts/unpoly/popup.coffee.erb +0 -515
  101. data/lib/assets/javascripts/unpoly/protocol.coffee +0 -300
  102. data/lib/assets/javascripts/unpoly/proxy.coffee +0 -672
  103. data/lib/assets/javascripts/unpoly/radio.coffee +0 -60
  104. data/lib/assets/javascripts/unpoly/rails.coffee +0 -24
  105. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +0 -476
  106. data/lib/assets/javascripts/unpoly/toast.coffee +0 -67
  107. data/lib/assets/javascripts/unpoly/tooltip.coffee +0 -276
  108. data/lib/assets/javascripts/unpoly/util.coffee.erb +0 -1677
  109. data/lib/assets/javascripts/unpoly/viewport.coffee.erb +0 -830
  110. data/lib/assets/javascripts/unpoly-bootstrap3/feedback-ext.coffee +0 -5
  111. data/lib/assets/javascripts/unpoly-bootstrap3/form-ext.coffee +0 -1
  112. data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.coffee +0 -14
  113. data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +0 -5
  114. data/lib/assets/javascripts/unpoly-bootstrap3.coffee +0 -2
  115. data/lib/assets/javascripts/unpoly.coffee +0 -28
  116. data/lib/assets/stylesheets/unpoly/close.sass +0 -2
  117. data/lib/assets/stylesheets/unpoly/dom.sass +0 -5
  118. data/lib/assets/stylesheets/unpoly/layout.sass +0 -2
  119. data/lib/assets/stylesheets/unpoly/link.sass +0 -2
  120. data/lib/assets/stylesheets/unpoly/modal.sass +0 -116
  121. data/lib/assets/stylesheets/unpoly/popup.sass +0 -7
  122. data/lib/assets/stylesheets/unpoly/toast.sass +0 -33
  123. data/lib/assets/stylesheets/unpoly/tooltip.sass +0 -62
  124. data/lib/assets/stylesheets/unpoly-bootstrap3/modal-ext.sass +0 -27
  125. data/lib/assets/stylesheets/unpoly-bootstrap3.sass +0 -1
  126. data/lib/assets/stylesheets/unpoly.sass +0 -1
  127. data/lib/unpoly/rails/inspector.rb +0 -149
  128. data/lib/unpoly/rails/inspector_accessor.rb +0 -30
  129. data/package.json +0 -38
  130. data/spec_app/.firefox-version +0 -1
  131. data/spec_app/.gitignore +0 -17
  132. data/spec_app/.rspec +0 -2
  133. data/spec_app/Gemfile +0 -29
  134. data/spec_app/Gemfile.lock +0 -223
  135. data/spec_app/README.rdoc +0 -28
  136. data/spec_app/Rakefile +0 -6
  137. data/spec_app/app/assets/images/.keep +0 -0
  138. data/spec_app/app/assets/images/favicon.png +0 -0
  139. data/spec_app/app/assets/images/grid.png +0 -0
  140. data/spec_app/app/assets/javascripts/bootstrap_manifest.coffee +0 -6
  141. data/spec_app/app/assets/javascripts/integration_test.coffee +0 -5
  142. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +0 -6
  143. data/spec_app/app/assets/stylesheets/_helpers.sass +0 -5
  144. data/spec_app/app/assets/stylesheets/bootstrap_manifest.sass +0 -2
  145. data/spec_app/app/assets/stylesheets/integration_test.sass +0 -88
  146. data/spec_app/app/assets/stylesheets/jasmine_specs.sass +0 -20
  147. data/spec_app/app/controllers/application_controller.rb +0 -14
  148. data/spec_app/app/controllers/binding_test_controller.rb +0 -51
  149. data/spec_app/app/controllers/boot_test_controller.rb +0 -31
  150. data/spec_app/app/controllers/compiler_test_controller.rb +0 -5
  151. data/spec_app/app/controllers/css_test_controller.rb +0 -5
  152. data/spec_app/app/controllers/error_test_controller.rb +0 -5
  153. data/spec_app/app/controllers/form_test/basics_controller.rb +0 -14
  154. data/spec_app/app/controllers/form_test/redirects_controller.rb +0 -17
  155. data/spec_app/app/controllers/form_test/uploads_controller.rb +0 -15
  156. data/spec_app/app/controllers/hash_test_controller.rb +0 -5
  157. data/spec_app/app/controllers/method_test_controller.rb +0 -16
  158. data/spec_app/app/controllers/motion_test_controller.rb +0 -5
  159. data/spec_app/app/controllers/pages_controller.rb +0 -17
  160. data/spec_app/app/controllers/replace_test_controller.rb +0 -5
  161. data/spec_app/app/controllers/reveal_test_controller.rb +0 -5
  162. data/spec_app/app/controllers/scroll_test_controller.rb +0 -5
  163. data/spec_app/app/helpers/application_helper.rb +0 -11
  164. data/spec_app/app/mailers/.keep +0 -0
  165. data/spec_app/app/models/concerns/.keep +0 -0
  166. data/spec_app/app/views/boot_test/defer.erb +0 -18
  167. data/spec_app/app/views/boot_test/module.erb +0 -18
  168. data/spec_app/app/views/boot_test/sync.erb +0 -17
  169. data/spec_app/app/views/compiler_test/timestamp.erb +0 -10
  170. data/spec_app/app/views/css_test/modal.erb +0 -47
  171. data/spec_app/app/views/css_test/modal_contents.erb +0 -5
  172. data/spec_app/app/views/css_test/modal_contents_wide.erb +0 -5
  173. data/spec_app/app/views/css_test/popup.erb +0 -81
  174. data/spec_app/app/views/css_test/popup_contents.erb +0 -5
  175. data/spec_app/app/views/css_test/tooltip.erb +0 -48
  176. data/spec_app/app/views/error_test/trigger.erb +0 -80
  177. data/spec_app/app/views/error_test/unexpected_response.erb +0 -3
  178. data/spec_app/app/views/form_test/basics/new.erb +0 -60
  179. data/spec_app/app/views/form_test/redirects/new.erb +0 -27
  180. data/spec_app/app/views/form_test/redirects/target.erb +0 -6
  181. data/spec_app/app/views/form_test/submission_result.erb +0 -30
  182. data/spec_app/app/views/form_test/uploads/new.erb +0 -44
  183. data/spec_app/app/views/hash_test/unpoly.erb +0 -30
  184. data/spec_app/app/views/hash_test/vanilla.erb +0 -13
  185. data/spec_app/app/views/layouts/integration_test.erb +0 -22
  186. data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +0 -20
  187. data/spec_app/app/views/method_test/form_target.erb +0 -17
  188. data/spec_app/app/views/method_test/page1.erb +0 -11
  189. data/spec_app/app/views/method_test/page2.erb +0 -6
  190. data/spec_app/app/views/motion_test/animations.erb +0 -16
  191. data/spec_app/app/views/motion_test/transitions.erb +0 -13
  192. data/spec_app/app/views/pages/start.erb +0 -82
  193. data/spec_app/app/views/replace_test/_nav.erb +0 -6
  194. data/spec_app/app/views/replace_test/page1.erb +0 -14
  195. data/spec_app/app/views/replace_test/page2.erb +0 -14
  196. data/spec_app/app/views/replace_test/table.erb +0 -16
  197. data/spec_app/app/views/reveal_test/long1.erb +0 -17
  198. data/spec_app/app/views/reveal_test/long2.erb +0 -17
  199. data/spec_app/app/views/reveal_test/within_document_viewport.erb +0 -24
  200. data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +0 -28
  201. data/spec_app/app/views/scroll_test/long1.erb +0 -30
  202. data/spec_app/bin/bundle +0 -3
  203. data/spec_app/bin/rails +0 -8
  204. data/spec_app/bin/rake +0 -8
  205. data/spec_app/bin/setup +0 -29
  206. data/spec_app/bin/spring +0 -18
  207. data/spec_app/config/application.rb +0 -28
  208. data/spec_app/config/boot.rb +0 -3
  209. data/spec_app/config/database.yml +0 -25
  210. data/spec_app/config/environment.rb +0 -5
  211. data/spec_app/config/environments/development.rb +0 -41
  212. data/spec_app/config/environments/production.rb +0 -79
  213. data/spec_app/config/environments/test.rb +0 -42
  214. data/spec_app/config/initializers/assets.rb +0 -19
  215. data/spec_app/config/initializers/backtrace_silencers.rb +0 -7
  216. data/spec_app/config/initializers/bower_rails.rb +0 -16
  217. data/spec_app/config/initializers/cookies_serializer.rb +0 -3
  218. data/spec_app/config/initializers/filter_parameter_logging.rb +0 -4
  219. data/spec_app/config/initializers/inflections.rb +0 -16
  220. data/spec_app/config/initializers/mime_types.rb +0 -4
  221. data/spec_app/config/initializers/session_store.rb +0 -3
  222. data/spec_app/config/initializers/wrap_parameters.rb +0 -14
  223. data/spec_app/config/locales/en.yml +0 -23
  224. data/spec_app/config/routes.rb +0 -33
  225. data/spec_app/config/secrets.yml +0 -22
  226. data/spec_app/config.ru +0 -4
  227. data/spec_app/db/schema.rb +0 -23
  228. data/spec_app/db/seeds.rb +0 -7
  229. data/spec_app/lib/assets/.keep +0 -0
  230. data/spec_app/lib/tasks/.keep +0 -0
  231. data/spec_app/lib/tasks/cucumber.rake +0 -65
  232. data/spec_app/log/.keep +0 -0
  233. data/spec_app/public/404.html +0 -67
  234. data/spec_app/public/422.html +0 -67
  235. data/spec_app/public/500.html +0 -66
  236. data/spec_app/public/favicon.ico +0 -0
  237. data/spec_app/public/robots.txt +0 -5
  238. data/spec_app/script/cucumber +0 -10
  239. data/spec_app/spec/controllers/binding_test_controller_spec.rb +0 -248
  240. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +0 -20
  241. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +0 -103
  242. data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +0 -21
  243. data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +0 -2
  244. data/spec_app/spec/javascripts/helpers/fixture.js.coffee +0 -25
  245. data/spec_app/spec/javascripts/helpers/index.js.coffee +0 -1
  246. data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +0 -1
  247. data/spec_app/spec/javascripts/helpers/knife.js.coffee +0 -69
  248. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +0 -25
  249. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +0 -8
  250. data/spec_app/spec/javascripts/helpers/mock_clock.js.coffee +0 -2
  251. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +0 -24
  252. data/spec_app/spec/javascripts/helpers/promise_state.js +0 -18
  253. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +0 -12
  254. data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +0 -8
  255. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +0 -23
  256. data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +0 -2
  257. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +0 -25
  258. data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +0 -5
  259. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +0 -12
  260. data/spec_app/spec/javascripts/helpers/spec_util.coffee +0 -47
  261. data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +0 -8
  262. data/spec_app/spec/javascripts/helpers/to_be_array.coffee +0 -5
  263. data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +0 -9
  264. data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +0 -8
  265. data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +0 -9
  266. data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +0 -8
  267. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +0 -8
  268. data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +0 -8
  269. data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +0 -8
  270. data/spec_app/spec/javascripts/helpers/to_be_jquery.js.coffee +0 -5
  271. data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +0 -8
  272. data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +0 -8
  273. data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +0 -11
  274. data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +0 -9
  275. data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +0 -8
  276. data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +0 -11
  277. data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +0 -8
  278. data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +0 -7
  279. data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +0 -7
  280. data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +0 -10
  281. data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +0 -10
  282. data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +0 -8
  283. data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +0 -15
  284. data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +0 -8
  285. data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +0 -16
  286. data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +0 -9
  287. data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -18
  288. data/spec_app/spec/javascripts/helpers/to_match_list.coffee +0 -14
  289. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +0 -8
  290. data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +0 -13
  291. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +0 -14
  292. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +0 -200
  293. data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +0 -5
  294. data/spec_app/spec/javascripts/support/jasmine.yml +0 -51
  295. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +0 -150
  296. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +0 -82
  297. data/spec_app/spec/javascripts/up/classes/config_spec.coffee +0 -24
  298. data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +0 -45
  299. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +0 -34
  300. data/spec_app/spec/javascripts/up/classes/params_spec.coffee +0 -557
  301. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +0 -50
  302. data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +0 -51
  303. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +0 -70
  304. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +0 -114
  305. data/spec_app/spec/javascripts/up/element_spec.coffee +0 -897
  306. data/spec_app/spec/javascripts/up/event_spec.js.coffee +0 -530
  307. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +0 -401
  308. data/spec_app/spec/javascripts/up/form_spec.js.coffee +0 -1527
  309. data/spec_app/spec/javascripts/up/fragment_spec.js.coffee +0 -2624
  310. data/spec_app/spec/javascripts/up/history_spec.js.coffee +0 -340
  311. data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +0 -4
  312. data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +0 -27
  313. data/spec_app/spec/javascripts/up/link_spec.js.coffee +0 -1098
  314. data/spec_app/spec/javascripts/up/log_spec.js.coffee +0 -119
  315. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +0 -939
  316. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +0 -582
  317. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +0 -508
  318. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +0 -39
  319. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +0 -1145
  320. data/spec_app/spec/javascripts/up/radio_spec.js.coffee +0 -212
  321. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +0 -118
  322. data/spec_app/spec/javascripts/up/spec_spec.js.coffee +0 -9
  323. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +0 -304
  324. data/spec_app/spec/javascripts/up/toast_spec.js.coffee +0 -37
  325. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +0 -163
  326. data/spec_app/spec/javascripts/up/util_spec.js.coffee +0 -1434
  327. data/spec_app/spec/javascripts/up/viewport_spec.js.coffee +0 -655
  328. data/spec_app/spec/spec_helper.rb +0 -62
  329. data/spec_app/test/controllers/.keep +0 -0
  330. data/spec_app/test/fixtures/.keep +0 -0
  331. data/spec_app/test/helpers/.keep +0 -0
  332. data/spec_app/test/integration/.keep +0 -0
  333. data/spec_app/test/mailers/.keep +0 -0
  334. data/spec_app/test/models/.keep +0 -0
  335. data/spec_app/test/test_helper.rb +0 -10
  336. data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +0 -1159
  337. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.bower.json +0 -43
  338. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.gitignore +0 -6
  339. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.npmignore +0 -10
  340. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.pairs +0 -6
  341. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.travis.yml +0 -56
  342. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/jasmine-ajax.js +0 -790
  343. data/spec_app/vendor/assets/.keep +0 -0
  344. data/unpoly-rails.gemspec +0 -24
@@ -1,116 +0,0 @@
1
- u = up.util
2
- e = up.element
3
-
4
- class up.EventListener
5
-
6
- constructor: (@element, @eventName, @selector, @callback, options = {}) ->
7
- { @jQuery } = options
8
- @key = @constructor.key(@eventName, @selector, @callback)
9
- @isDefault = up.framework.isBooting()
10
-
11
- bind: ->
12
- map = (@element.upEventListeners ||= {})
13
- if map[@key]
14
- up.fail('up.on(): The %o callback %o cannot be registered more than once', @eventName, @callback)
15
- map[@key] = this
16
- @element.addEventListener(@eventName, @nativeCallback)
17
-
18
- unbind: =>
19
- if map = @element.upEventListeners
20
- delete map[@key]
21
- @element.removeEventListener(@eventName, @nativeCallback)
22
-
23
- nativeCallback: (event) =>
24
- # 1. Since we're listing on `document`, event.currentTarget is now `document`.
25
- # 2. event.target is the element that received an event, which might be a
26
- # child of `selector`.
27
- # 3. There is only a single event bubbling up the DOM, so we are only called once.
28
-
29
- element = event.target
30
- element = e.closest(element, @selector) if @selector
31
-
32
- if element
33
- elementArg = if @jQuery then up.browser.jQuery(element) else element
34
- args = [event, elementArg]
35
-
36
- # Do not retrieve and parse [up-data] unless the listener function
37
- # expects a third argument. Note that we must pass data for an argument
38
- # count of 0, since then the function might take varargs.
39
- expectedArgCount = @callback.length
40
-
41
- unless expectedArgCount == 1 || expectedArgCount == 2
42
- data = up.syntax.data(element)
43
- args.push(data)
44
-
45
- @callback.apply(element, args)
46
-
47
- ###
48
- Parses the following arg variants into an object:
49
-
50
- - [elements, eventNames, selector, callback]
51
- - [elements, eventNames, callback]
52
- - [ eventNames, selector, callback]
53
- - [ eventNames, callback]
54
-
55
- @function up.EventListener#parseArgs
56
- @internal
57
- ###
58
- @parseArgs = (args) ->
59
- args = u.copy(args)
60
-
61
- # A callback function is given in all arg variants.
62
- callback = args.pop()
63
- # Give the callback function a numeric identifier so it
64
- # can become part of the upEventListeners key.
65
- callback.upUid ||= u.uid()
66
-
67
- # The user can pass an element (or the document, or the window) as the
68
- # first argument. If omitted, the listener will bind to the document.
69
- if args[0].addEventListener
70
- elements = [args.shift()]
71
- else if u.isJQuery(args[0]) || (u.isList(args[0]) && args[0][0].addEventListener)
72
- elements = args.shift()
73
- else
74
- elements = [document]
75
-
76
- # Event names are given in all arg variants
77
- eventNames = u.splitValues(args.shift())
78
- # eventNames = u.map(eventNames, up.legacy.fixEventName)
79
-
80
- # A selector is given if the user wants to delegate events.
81
- # It might be undefined.
82
- selector = args[0]
83
-
84
- { elements, eventNames, selector, callback }
85
-
86
- @bind: (args, options) ->
87
- parsed = @parseArgs(args)
88
- unbindFns = []
89
-
90
- for element in parsed.elements
91
- for eventName in parsed.eventNames
92
- listener = new @(element, eventName, parsed.selector, parsed.callback, options)
93
- listener.bind()
94
- unbindFns.push(listener.unbind)
95
-
96
- u.sequence(unbindFns)
97
-
98
- @key: (eventName, selector, callback) ->
99
- [eventName, selector, callback.upUid].join('|')
100
-
101
- @unbind: (args) ->
102
- parsed = @parseArgs(args)
103
- for element in parsed.elements
104
- map = element.upEventListeners
105
- for eventName in parsed.eventNames
106
- key = @key(eventName, parsed.selector, parsed.callback)
107
- if map && (listener = map[key])
108
- listener.unbind()
109
-
110
- @unbindNonDefault: (element) ->
111
- if map = element.upEventListeners
112
- listeners = u.values(map)
113
- for listener in listeners
114
- # Calling unbind() also removes the listener from element.upEventListeners
115
- unless listener.isDefault
116
- listener.unbind()
@@ -1,86 +0,0 @@
1
- u = up.util
2
-
3
- class up.ExtractCascade
4
-
5
- constructor: (selectorOrElement, options) ->
6
- @options = u.options(options, humanizedTarget: 'selector', layer: 'auto')
7
- @options.transition ?= @options.animation
8
- @options.hungry ?= true
9
-
10
- @candidates = @buildCandidates(selectorOrElement)
11
- @plans = u.map @candidates, (candidate, i) =>
12
- planOptions = u.copy(@options)
13
- if i > 0
14
- # If we're using a fallback (any candidate that's not the first),
15
- # the original transition might no longer be appropriate.
16
- planOptions.transition = up.fragment.config.fallbackTransition ? @options.transition
17
- new up.ExtractPlan(candidate, planOptions)
18
-
19
- buildCandidates: (selector) ->
20
- candidates = [selector, @options.fallback, up.fragment.config.fallbacks]
21
- candidates = u.flatten(candidates)
22
- # Remove undefined, null and false from the list
23
- candidates = u.filter(candidates, u.isTruthy)
24
- candidates = u.uniq(candidates)
25
-
26
- if @options.fallback == false || @options.provideTarget
27
- # Use the first defined candidate, but not `selector` since that
28
- # might be an undefined options.failTarget
29
- candidates = [candidates[0]]
30
- candidates
31
-
32
- oldPlan: =>
33
- @detectPlan('oldExists')
34
-
35
- newPlan: =>
36
- @detectPlan('newExists')
37
-
38
- matchingPlan: =>
39
- @detectPlan('matchExists')
40
-
41
- detectPlan: (checker) =>
42
- u.find @plans, (plan) -> plan[checker]()
43
-
44
- bestPreflightSelector: =>
45
- if @options.provideTarget
46
- # We know that the target will be created right before swapping,
47
- # so just assume the first plan will work.
48
- plan = @plans[0]
49
- else
50
- plan = @oldPlan()
51
-
52
- if plan
53
- plan.resolveNesting()
54
- plan.selector()
55
- else
56
- @oldPlanNotFound()
57
-
58
- bestMatchingSteps: =>
59
- if plan = @matchingPlan()
60
- # Only when we have a match in the required selectors, we
61
- # append the optional steps for [up-hungry] elements.
62
- plan.addHungrySteps()
63
- plan.resolveNesting()
64
- plan.steps
65
- else
66
- @matchingPlanNotFound()
67
-
68
- matchingPlanNotFound: =>
69
- # The job of this method is to simply throw an error.
70
- # However, we will investigate the reasons for the failure
71
- # so we can provide a more helpful error message.
72
- if @newPlan()
73
- @oldPlanNotFound()
74
- else
75
- if @oldPlan()
76
- message = "Could not find #{@options.humanizedTarget} in response"
77
- else
78
- message = "Could not match #{@options.humanizedTarget} in current page and response"
79
- if @options.inspectResponse
80
- inspectAction = { label: 'Open response', callback: @options.inspectResponse }
81
- up.fail(["#{message} (tried %o)", @candidates], action: inspectAction)
82
-
83
- oldPlanNotFound: =>
84
- layerProse = @options.layer
85
- layerProse = 'page, modal or popup' if layerProse == 'auto'
86
- up.fail("Could not find #{@options.humanizedTarget} in current #{layerProse} (tried %o)", @candidates)
@@ -1,111 +0,0 @@
1
- u = up.util
2
- e = up.element
3
-
4
- class up.ExtractPlan
5
-
6
- constructor: (selector, options) ->
7
- @reveal = options.reveal
8
- @origin = options.origin
9
- @hungry = options.hungry
10
- @transition = options.transition
11
- @response = options.response
12
- @oldLayer = options.layer
13
- originalSelector = e.resolveSelector(selector, @origin)
14
- @parseSteps(originalSelector)
15
-
16
- findOld: =>
17
- u.each @steps, (step) =>
18
- step.oldElement = up.fragment.first(step.selector, layer: @oldLayer)
19
-
20
- findNew: =>
21
- u.each @steps, (step) =>
22
- # The response has no layers. It's always just the page.
23
- step.newElement = @response.first(step.selector)
24
-
25
- oldExists: =>
26
- @findOld()
27
- u.every @steps, (step) -> step.oldElement
28
-
29
- newExists: =>
30
- @findNew()
31
- u.every @steps, (step) -> step.newElement
32
-
33
- matchExists: =>
34
- @oldExists() && @newExists()
35
-
36
- addSteps: (steps) =>
37
- @steps = @steps.concat(steps)
38
-
39
- resolveNesting: =>
40
- return if @steps.length < 2
41
-
42
- compressed = u.copy(@steps)
43
-
44
- # When two replacements target the same element, we would process
45
- # the same content twice. We never want that, so we only keep the first step.
46
- compressed = u.uniqBy(compressed, (step) -> step.oldElement)
47
-
48
- compressed = u.filter compressed, (candidateStep, candidateIndex) =>
49
- u.every compressed, (rivalStep, rivalIndex) =>
50
- if rivalIndex == candidateIndex
51
- true
52
- else
53
- candidateElement = candidateStep.oldElement
54
- rivalElement = rivalStep.oldElement
55
- rivalStep.pseudoClass || !rivalElement.contains(candidateElement)
56
-
57
- # If we revealed before, we should reveal now
58
- compressed[0].reveal = @steps[0].reveal
59
- @steps = compressed
60
-
61
- selector: =>
62
- u.map(@steps, 'expression').join(', ')
63
-
64
- parseSteps: (originalSelector) =>
65
- comma = /\ *,\ */
66
-
67
- @steps = []
68
-
69
- disjunction = originalSelector.split(comma)
70
-
71
- u.each disjunction, (expression, i) =>
72
- expressionParts = expression.match(/^(.+?)(?:\:(before|after))?$/)
73
- expressionParts or up.fail('Could not parse selector literal "%s"', expression)
74
- selector = expressionParts[1]
75
- if selector == 'html'
76
- # If someone really asked us to replace the <html> root, the best
77
- # we can do is replace the <body>.
78
- selector = 'body'
79
-
80
- pseudoClass = expressionParts[2]
81
-
82
- # When extracting multiple selectors, we only want to reveal the first element.
83
- # So we set the { reveal } option to false for the next iteration.
84
- doReveal = if i == 0 then @reveal else false
85
-
86
- @steps.push
87
- expression: expression
88
- selector: selector
89
- pseudoClass: pseudoClass
90
- transition: @transition
91
- origin: @origin
92
- reveal: doReveal
93
-
94
- addHungrySteps: =>
95
- hungrySteps = []
96
- if @hungry
97
- hungries = e.all(up.radio.hungrySelector())
98
- transition = up.radio.config.hungryTransition ? @transition
99
- for hungry in hungries
100
- selector = e.toSelector(hungry)
101
- if newHungry = @response.first(selector)
102
- hungrySteps.push
103
- selector: selector
104
- oldElement: hungry
105
- newElement: newHungry
106
- transition: transition
107
- reveal: false # we never auto-reveal a hungry element
108
- origin: null # don't let the hungry element auto-close a non-sticky modal or popup
109
-
110
- @addSteps(hungrySteps)
111
-
@@ -1,80 +0,0 @@
1
- u = up.util
2
- e = up.element
3
-
4
- class up.FieldObserver
5
-
6
- constructor: (fieldOrFields, options, @callback) ->
7
- @fields = e.list(fieldOrFields)
8
- @delay = options.delay
9
- @batch = options.batch
10
-
11
- start: =>
12
- @scheduledValues = null
13
- @processedValues = @readFieldValues()
14
- @currentTimer = undefined
15
- @callbackRunning = false
16
- # Although (depending on the browser) we only need/receive either input or change,
17
- # we always bind to both events in case another script manually triggers it.
18
- @unbind = up.on(@fields, 'input change', @check)
19
-
20
- stop: =>
21
- @unbind()
22
- @cancelTimer()
23
-
24
- cancelTimer: =>
25
- clearTimeout(@currentTimer)
26
- @currentTimer = undefined
27
-
28
- scheduleTimer: =>
29
- @cancelTimer()
30
- @currentTimer = u.timer @delay, =>
31
- @currentTimer = undefined
32
- @requestCallback()
33
-
34
- scheduleValues: (values) =>
35
- @scheduledValues = values
36
- @scheduleTimer()
37
-
38
- isNewValues: (values) =>
39
- !u.isEqual(values, @processedValues) && !u.isEqual(@scheduledValues, values)
40
-
41
- requestCallback: =>
42
- if @scheduledValues != null && !@currentTimer && !@callbackRunning
43
- diff = @changedValues(@processedValues, @scheduledValues)
44
- @processedValues = @scheduledValues
45
- @scheduledValues = null
46
- @callbackRunning = true
47
-
48
- callbackReturnValues = []
49
- if @batch
50
- callbackReturnValues.push(@callback(diff))
51
- else
52
- for name, value of diff
53
- callbackReturnValues.push(@callback(value, name))
54
-
55
- # Promise.all() will wait for any promises that might be
56
- # contained in the `callbackReturnValues` array.
57
- callbacksDone = Promise.all(callbackReturnValues)
58
-
59
- u.always callbacksDone, =>
60
- @callbackRunning = false
61
- @requestCallback()
62
-
63
- changedValues: (previous, next) ->
64
- changes = {}
65
- keys = Object.keys(previous)
66
- keys = keys.concat(Object.keys(next))
67
- keys = u.uniq(keys)
68
- for key in keys
69
- previousValue = previous[key]
70
- nextValue = next[key]
71
- unless u.isEqual(previousValue, nextValue)
72
- changes[key] = nextValue
73
- changes
74
-
75
- readFieldValues: =>
76
- up.Params.fromFields(@fields).toObject()
77
-
78
- check: =>
79
- values = @readFieldValues()
80
- @scheduleValues(values) if @isNewValues(values)
@@ -1,29 +0,0 @@
1
- ## Working example for this: https://codepen.io/anon/pen/MBVewo
2
- #class up.FocusFollower
3
- #
4
- # constructor: ->
5
- # @discardDelay = 80
6
- # fieldSelector = up.form.fieldSelector()
7
- # $(document).on('focusin', fieldSelector, @fieldFocused)
8
- # $(document).on('focusout', fieldSelector, @fieldBlurred)
9
- # @reset()
10
- #
11
- # reset: ->
12
- # clearTimeout(@discardTimer)
13
- # @field = undefined
14
- #
15
- # fieldFocused: (event) =>
16
- # clearTimeout(@discardTimer)
17
- # @field = event.currentTarget
18
- #
19
- # fieldBlurred: (event) =>
20
- # clearTimeout(@discardTimer)
21
- # @discardTimer = u.timer(@discardDelay, @discardField)
22
- #
23
- # discardField: =>
24
- # @field = undefined
25
- #
26
- # lastField: ->
27
- # if u.isDetached(@field)
28
- # @discardField()
29
- # @field
@@ -1,64 +0,0 @@
1
- u = up.util
2
- e = up.element
3
-
4
- class up.FollowVariant
5
-
6
- constructor: (selector, options) ->
7
- # @followLink() will wrap @followNow() with event submission and [up-active] feedback
8
- @followNow = options.follow
9
- @preloadLink = options.preload
10
- @selectors = u.splitValues(selector, ',')
11
-
12
- onClick: (event, link) =>
13
- if up.link.shouldProcessEvent(event, link)
14
- # Instant links should not have a `click` event.
15
- # This would trigger the browsers default follow-behavior and possibly activate JS libs.
16
- # A11Y: We also need to check whether the [up-instant] behavior did trigger on mousedown.
17
- # Keyboard navigation will not necessarily trigger a mousedown event.
18
- if e.matches(link, '[up-instant]') && link.upInstantSupported
19
- up.event.halt(event)
20
- link.upInstantSupported = false
21
- return # return undefined since u.muteRejection() will try to call catch() on a given value
22
- else
23
- up.event.consumeAction(event)
24
- @followLink(link)
25
- else
26
- # For tests
27
- up.link.allowDefault(event)
28
-
29
- onMousedown: (event, link) =>
30
- if up.link.shouldProcessEvent(event, link)
31
- # A11Y: Keyboard navigation will not necessarily trigger a mousedown event.
32
- # We also don't want to listen to the enter key, since some screen readers
33
- # use the enter key for something else.
34
- link.upInstantSupported = true
35
- up.event.consumeAction(event)
36
- @followLink(link)
37
-
38
- fullSelector: (additionalClause = '') =>
39
- parts = []
40
- @selectors.forEach (variantSelector) ->
41
- for tagSelector in ['a', '[up-href]']
42
- parts.push "#{tagSelector}#{variantSelector}#{additionalClause}"
43
- parts.join(', ')
44
-
45
- registerEvents: ->
46
- up.on 'click', @fullSelector(), (args...) =>
47
- u.muteRejection @onClick(args...)
48
- up.on 'mousedown', @fullSelector('[up-instant]'), (args...) =>
49
- u.muteRejection @onMousedown(args...)
50
-
51
- followLink: (link, options = {}) =>
52
- promise = up.event.whenEmitted('up:link:follow', log: 'Following link', target: link)
53
- promise = promise.then =>
54
- up.feedback.start(link) unless options.preload
55
- @followNow(link, options)
56
- unless options.preload
57
- # Make sure we always remove .up-active, even if the follow fails or the user
58
- # does not confirm an [up-confirm] link. However, don't re-assign promise
59
- # to the result of up.always() since that would change the state of promise.
60
- u.always promise, -> up.feedback.stop(link)
61
- promise
62
-
63
- matchesLink: (link) =>
64
- e.matches(link, @fullSelector())
@@ -1,46 +0,0 @@
1
- u = up.util
2
- e = up.element
3
-
4
- class up.HtmlParser
5
-
6
- constructor: (@html) ->
7
- @wrapNoscriptInHtml()
8
- @parsedDoc = e.createDocumentFromHtml(@html)
9
-
10
- title: ->
11
- @parsedDoc.querySelector("head title")?.textContent
12
-
13
- first: (selector) ->
14
- e.first(@parsedDoc, selector)
15
-
16
- prepareForInsertion: (element) ->
17
- @unwrapNoscriptInElement(element)
18
-
19
- wrapNoscriptInHtml: ->
20
- # We wrap <noscript> tags into a <div> for two reasons:
21
- #
22
- # (1) IE11 and Edge cannot find <noscript> tags with jQuery or querySelector() or
23
- # getElementsByTagName() when the tag was created by DOMParser. This is a bug.
24
- # https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12453464/
25
- #
26
- # (2) The children of a <nonscript> tag are expected to be a verbatim text node
27
- # in a scripting-capable browser. However, due to rules in the DOMParser spec,
28
- # the children are parsed into actual DOM nodes. This confuses libraries that
29
- # work with <noscript> tags, such as lazysizes.
30
- # http://w3c.github.io/DOM-Parsing/#dom-domparser-parsefromstring
31
- #
32
- # We will unwrap the wrapped <noscript> tags when a fragment is requested with
33
- # #first(), and only in the requested fragment.
34
- noscriptPattern = /<noscript[^>]*>((.|\s)*?)<\/noscript>/ig
35
- @html = @html.replace noscriptPattern, (match, content) =>
36
- @didWrapNoscript = true
37
- '<div class="up-noscript" data-html="' + u.escapeHtml(content) + '"></div>'
38
-
39
- unwrapNoscriptInElement: (element) ->
40
- return unless @didWrapNoscript
41
- wrappedNoscripts = element.querySelectorAll('.up-noscript')
42
- for wrappedNoscript in wrappedNoscripts
43
- wrappedContent = wrappedNoscript.getAttribute('data-html')
44
- noscript = document.createElement('noscript')
45
- noscript.textContent = wrappedContent
46
- wrappedNoscript.parentNode.replaceChild(noscript, wrappedNoscript)
@@ -1,157 +0,0 @@
1
- u = up.util
2
- e = up.element
3
-
4
- class up.MotionController
5
-
6
- constructor: (name) ->
7
- @activeClass = "up-#{name}"
8
- @dataKey = "up-#{name}-finished"
9
- @selector = ".#{@activeClass}"
10
- @finishEvent = "up:#{name}:finish"
11
- @finishCount = 0
12
- @clusterCount = 0
13
-
14
- ###**
15
- Finishes all animations in the given elements' ancestors and
16
- descendants, then calls the given function.
17
-
18
- The function is expected to return a promise that is fulfilled when
19
- the animation ends. The function is also expected to listen to
20
- `this.finishEvent` and instantly skip to the last frame
21
- when the event is observed.
22
-
23
- The animation is tracked so it can be
24
- [`finished`](/up.MotionController.finish) later.
25
-
26
- @method startFunction
27
- @param {Element|List<Element>} cluster
28
- A list of elements that will be affected by the motion.
29
- @param {Function(): Promise} startMotion
30
- @param {Object} [memory.trackMotion=true]
31
- @return {Promise}
32
- A promise that is fulfilled when the animation ends.
33
- ###
34
- startFunction: (cluster, startMotion, memory = {}) =>
35
- cluster = e.list(cluster)
36
-
37
- # Some motions might reject after starting. E.g. a scrolling animation
38
- # will reject when the user scrolls manually during the animation. For
39
- # the purpose of this controller, we just want to know when the animation
40
- # has setteld, regardless of whether it was resolved or rejected.
41
- mutedAnimator = -> u.muteRejection(startMotion())
42
-
43
- # Callers can pass an options hash `memory` in which we store a { trackMotion }
44
- # property. With this we can prevent tracking the same motion multiple times.
45
- # This is an issue when composing a transition from two animations, or when
46
- # using another transition from within a transition function.
47
- memory.trackMotion = memory.trackMotion ? up.motion.isEnabled()
48
- if memory.trackMotion is false
49
- # Since we don't want recursive tracking or finishing, we could run
50
- # the animator() now. However, since the else branch is async, we push
51
- # the animator into the microtask queue to be async as well.
52
- u.microtask(mutedAnimator)
53
- else
54
- memory.trackMotion = false
55
- @finish(cluster).then =>
56
- promise = @whileForwardingFinishEvent(cluster, mutedAnimator)
57
- promise = promise.then => @unmarkCluster(cluster)
58
- # Attach the modified promise to the cluster's elements
59
- @markCluster(cluster, promise)
60
- promise
61
-
62
- ###*
63
- Finishes all animations in the given elements' ancestors and
64
- descendants, then calls `motion.start()`.
65
-
66
- Also listens to `this.finishEvent` on the given elements.
67
- When this event is observed, calls `motion.finish()`.
68
-
69
- @method startMotion
70
- @param {Element|List<Element>} cluster
71
- @param {up.Motion} motion
72
- @param {Object} [memory.trackMotion=true]
73
- ###
74
- startMotion: (cluster, motion, memory = {}) ->
75
- start = -> motion.start()
76
- finish = -> motion.finish()
77
- unbindFinish = up.on(cluster, @finishEvent, finish)
78
- promise = @startFunction(cluster, start, memory)
79
- promise = promise.then(unbindFinish)
80
- promise
81
-
82
- ###**
83
- @method finish
84
- @param {List<Element>} [elements]
85
- If no element is given, finishes all animations in the documnet.
86
- If an element is given, only finishes animations in its subtree and ancestors.
87
- @return {Promise} A promise that is fulfilled when animations have finished.
88
- ###
89
- finish: (elements) =>
90
- @finishCount++
91
- return Promise.resolve() if @clusterCount == 0 || !up.motion.isEnabled()
92
- elements = @expandFinishRequest(elements)
93
- allFinished = u.map(elements, @finishOneElement)
94
- Promise.all(allFinished)
95
-
96
- expandFinishRequest: (elements) =>
97
- if elements
98
- u.flatMap elements, (el) =>
99
- e.list(e.closest(el, @selector), e.all(el, @selector))
100
- else
101
- # If no reference elements were given, we finish every matching
102
- # element on the screen.
103
- e.all(@selector)
104
-
105
- isActive: (element) =>
106
- element.classList.contains(@activeClass)
107
-
108
- finishOneElement: (element) =>
109
- # Animating code is expected to listen to this event, fast-forward
110
- # the animation and resolve their promise. All built-ins like
111
- # `up.animate`, `up.morph`, or `up.scroll` behave that way.
112
- @emitFinishEvent(element)
113
-
114
- # If animating code ignores the event, we cannot force the animation to
115
- # finish from here. We will wait for the animation to end naturally before
116
- # starting the next animation.
117
- @whenElementFinished(element)
118
-
119
- emitFinishEvent: (element, eventAttrs = {}) =>
120
- eventAttrs = u.merge({ target: element, log: false }, eventAttrs)
121
- up.emit(@finishEvent, eventAttrs)
122
-
123
- whenElementFinished: (element) =>
124
- # There are some cases related to element ghosting where an element
125
- # has the class, but not the data value. In that case simply return
126
- # a resolved promise.
127
- element[@dataKey] || Promise.resolve()
128
-
129
- markCluster: (cluster, promise) =>
130
- @clusterCount++
131
- for element in cluster
132
- element.classList.add(@activeClass)
133
- element[@dataKey] = promise
134
-
135
- unmarkCluster: (cluster) =>
136
- @clusterCount--
137
- for element in cluster
138
- element.classList.remove(@activeClass)
139
- delete element[@dataKey]
140
-
141
- whileForwardingFinishEvent: (cluster, fn) =>
142
- return fn() if cluster.length < 2
143
- doForward = (event) =>
144
- unless event.forwarded
145
- u.each cluster, (element) =>
146
- if element != event.target && @isActive(element)
147
- @emitFinishEvent(element, forwarded: true)
148
-
149
- # Forward the finish event to the ghost that is actually animating
150
- unbindFinish = up.on(cluster, @finishEvent, doForward)
151
- # Our own pseudo-animation finishes when the actual animation on $ghost finishes
152
- fn().then(unbindFinish)
153
-
154
- reset: =>
155
- @finish().then =>
156
- @finishCount = 0
157
- @clusterCount = 0