unpoly-rails 0.61.0 → 2.0.0.pre.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (340) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +94 -1
  4. data/README.md +3 -11
  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 +15439 -10434
  22. data/dist/unpoly.min.css +1 -1
  23. data/dist/unpoly.min.js +6 -4
  24. data/lib/unpoly-rails.rb +9 -3
  25. data/lib/unpoly/rails/change.rb +372 -0
  26. data/lib/unpoly/rails/change/cache.rb +26 -0
  27. data/lib/unpoly/rails/change/context.rb +80 -0
  28. data/lib/unpoly/rails/change/field.rb +117 -0
  29. data/lib/unpoly/rails/change/field_definition.rb +74 -0
  30. data/lib/unpoly/rails/change/layer.rb +60 -0
  31. data/lib/unpoly/rails/controller.rb +47 -0
  32. data/lib/unpoly/rails/error.rb +5 -0
  33. data/lib/unpoly/rails/request_echo_headers.rb +2 -2
  34. data/lib/unpoly/rails/version.rb +1 -1
  35. data/lib/unpoly/tasks.rb +45 -0
  36. metadata +43 -314
  37. data/.gitignore +0 -10
  38. data/.ruby-version +0 -2
  39. data/Gemfile +0 -8
  40. data/Gemfile.lock +0 -45
  41. data/Rakefile +0 -144
  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-bootstrap3.coffee +0 -2
  60. data/lib/assets/javascripts/unpoly-bootstrap3/feedback-ext.coffee +0 -5
  61. data/lib/assets/javascripts/unpoly-bootstrap3/form-ext.coffee +0 -1
  62. data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.coffee +0 -14
  63. data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +0 -5
  64. data/lib/assets/javascripts/unpoly.coffee +0 -28
  65. data/lib/assets/javascripts/unpoly/browser.coffee.erb +0 -236
  66. data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +0 -36
  67. data/lib/assets/javascripts/unpoly/classes/cache.coffee +0 -127
  68. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +0 -93
  69. data/lib/assets/javascripts/unpoly/classes/config.coffee +0 -9
  70. data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +0 -118
  71. data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +0 -39
  72. data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +0 -116
  73. data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +0 -86
  74. data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +0 -111
  75. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +0 -80
  76. data/lib/assets/javascripts/unpoly/classes/focus_follower.coffee +0 -29
  77. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +0 -56
  78. data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +0 -46
  79. data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +0 -157
  80. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +0 -543
  81. data/lib/assets/javascripts/unpoly/classes/record.coffee +0 -22
  82. data/lib/assets/javascripts/unpoly/classes/rect.js +0 -21
  83. data/lib/assets/javascripts/unpoly/classes/request.coffee +0 -246
  84. data/lib/assets/javascripts/unpoly/classes/response.coffee +0 -157
  85. data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +0 -102
  86. data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +0 -67
  87. data/lib/assets/javascripts/unpoly/classes/selector.coffee +0 -60
  88. data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +0 -26
  89. data/lib/assets/javascripts/unpoly/classes/store/session.coffee +0 -59
  90. data/lib/assets/javascripts/unpoly/classes/tether.coffee +0 -105
  91. data/lib/assets/javascripts/unpoly/classes/url_set.coffee +0 -32
  92. data/lib/assets/javascripts/unpoly/cookie.coffee +0 -56
  93. data/lib/assets/javascripts/unpoly/element.coffee.erb +0 -1126
  94. data/lib/assets/javascripts/unpoly/event.coffee.erb +0 -438
  95. data/lib/assets/javascripts/unpoly/feedback.coffee +0 -353
  96. data/lib/assets/javascripts/unpoly/form.coffee.erb +0 -1032
  97. data/lib/assets/javascripts/unpoly/fragment.coffee.erb +0 -924
  98. data/lib/assets/javascripts/unpoly/framework.coffee +0 -67
  99. data/lib/assets/javascripts/unpoly/history.coffee +0 -268
  100. data/lib/assets/javascripts/unpoly/legacy.coffee +0 -60
  101. data/lib/assets/javascripts/unpoly/link.coffee.erb +0 -622
  102. data/lib/assets/javascripts/unpoly/log.coffee +0 -248
  103. data/lib/assets/javascripts/unpoly/modal.coffee.erb +0 -825
  104. data/lib/assets/javascripts/unpoly/motion.coffee.erb +0 -668
  105. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
  106. data/lib/assets/javascripts/unpoly/popup.coffee.erb +0 -515
  107. data/lib/assets/javascripts/unpoly/protocol.coffee +0 -298
  108. data/lib/assets/javascripts/unpoly/proxy.coffee +0 -672
  109. data/lib/assets/javascripts/unpoly/radio.coffee +0 -60
  110. data/lib/assets/javascripts/unpoly/rails.coffee +0 -24
  111. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +0 -477
  112. data/lib/assets/javascripts/unpoly/toast.coffee +0 -67
  113. data/lib/assets/javascripts/unpoly/tooltip.coffee +0 -276
  114. data/lib/assets/javascripts/unpoly/util.coffee.erb +0 -1676
  115. data/lib/assets/javascripts/unpoly/viewport.coffee.erb +0 -806
  116. data/lib/assets/stylesheets/unpoly-bootstrap3.sass +0 -1
  117. data/lib/assets/stylesheets/unpoly-bootstrap3/modal-ext.sass +0 -27
  118. data/lib/assets/stylesheets/unpoly.sass +0 -1
  119. data/lib/assets/stylesheets/unpoly/close.sass +0 -2
  120. data/lib/assets/stylesheets/unpoly/dom.sass +0 -5
  121. data/lib/assets/stylesheets/unpoly/layout.sass +0 -2
  122. data/lib/assets/stylesheets/unpoly/link.sass +0 -2
  123. data/lib/assets/stylesheets/unpoly/modal.sass +0 -116
  124. data/lib/assets/stylesheets/unpoly/popup.sass +0 -7
  125. data/lib/assets/stylesheets/unpoly/toast.sass +0 -33
  126. data/lib/assets/stylesheets/unpoly/tooltip.sass +0 -62
  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 -32
  134. data/spec_app/Gemfile.lock +0 -233
  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 -6
  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/compiler_test_controller.rb +0 -5
  150. data/spec_app/app/controllers/css_test_controller.rb +0 -5
  151. data/spec_app/app/controllers/error_test_controller.rb +0 -5
  152. data/spec_app/app/controllers/form_test/basics_controller.rb +0 -14
  153. data/spec_app/app/controllers/form_test/redirects_controller.rb +0 -17
  154. data/spec_app/app/controllers/form_test/uploads_controller.rb +0 -15
  155. data/spec_app/app/controllers/hash_test_controller.rb +0 -5
  156. data/spec_app/app/controllers/method_test_controller.rb +0 -16
  157. data/spec_app/app/controllers/motion_test_controller.rb +0 -5
  158. data/spec_app/app/controllers/pages_controller.rb +0 -9
  159. data/spec_app/app/controllers/replace_test_controller.rb +0 -5
  160. data/spec_app/app/controllers/reveal_test_controller.rb +0 -5
  161. data/spec_app/app/controllers/scroll_test_controller.rb +0 -5
  162. data/spec_app/app/helpers/application_helper.rb +0 -2
  163. data/spec_app/app/mailers/.keep +0 -0
  164. data/spec_app/app/models/concerns/.keep +0 -0
  165. data/spec_app/app/views/compiler_test/timestamp.erb +0 -9
  166. data/spec_app/app/views/css_test/modal.erb +0 -47
  167. data/spec_app/app/views/css_test/modal_contents.erb +0 -5
  168. data/spec_app/app/views/css_test/modal_contents_wide.erb +0 -5
  169. data/spec_app/app/views/css_test/popup.erb +0 -81
  170. data/spec_app/app/views/css_test/popup_contents.erb +0 -5
  171. data/spec_app/app/views/css_test/tooltip.erb +0 -48
  172. data/spec_app/app/views/error_test/trigger.erb +0 -80
  173. data/spec_app/app/views/error_test/unexpected_response.erb +0 -3
  174. data/spec_app/app/views/form_test/basics/new.erb +0 -60
  175. data/spec_app/app/views/form_test/redirects/new.erb +0 -27
  176. data/spec_app/app/views/form_test/redirects/target.erb +0 -4
  177. data/spec_app/app/views/form_test/submission_result.erb +0 -30
  178. data/spec_app/app/views/form_test/uploads/new.erb +0 -44
  179. data/spec_app/app/views/hash_test/unpoly.erb +0 -30
  180. data/spec_app/app/views/hash_test/vanilla.erb +0 -13
  181. data/spec_app/app/views/layouts/integration_test.erb +0 -22
  182. data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +0 -20
  183. data/spec_app/app/views/method_test/form_target.erb +0 -17
  184. data/spec_app/app/views/method_test/page1.erb +0 -11
  185. data/spec_app/app/views/method_test/page2.erb +0 -6
  186. data/spec_app/app/views/motion_test/animations.erb +0 -16
  187. data/spec_app/app/views/motion_test/transitions.erb +0 -13
  188. data/spec_app/app/views/pages/start.erb +0 -79
  189. data/spec_app/app/views/replace_test/_nav.erb +0 -6
  190. data/spec_app/app/views/replace_test/page1.erb +0 -14
  191. data/spec_app/app/views/replace_test/page2.erb +0 -14
  192. data/spec_app/app/views/replace_test/table.erb +0 -16
  193. data/spec_app/app/views/reveal_test/long1.erb +0 -17
  194. data/spec_app/app/views/reveal_test/long2.erb +0 -17
  195. data/spec_app/app/views/reveal_test/within_document_viewport.erb +0 -24
  196. data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +0 -28
  197. data/spec_app/app/views/scroll_test/long1.erb +0 -30
  198. data/spec_app/bin/bundle +0 -3
  199. data/spec_app/bin/rails +0 -8
  200. data/spec_app/bin/rake +0 -8
  201. data/spec_app/bin/setup +0 -29
  202. data/spec_app/bin/spring +0 -18
  203. data/spec_app/config.ru +0 -4
  204. data/spec_app/config/application.rb +0 -28
  205. data/spec_app/config/boot.rb +0 -3
  206. data/spec_app/config/database.yml +0 -25
  207. data/spec_app/config/environment.rb +0 -5
  208. data/spec_app/config/environments/development.rb +0 -41
  209. data/spec_app/config/environments/production.rb +0 -79
  210. data/spec_app/config/environments/test.rb +0 -42
  211. data/spec_app/config/initializers/assets.rb +0 -19
  212. data/spec_app/config/initializers/backtrace_silencers.rb +0 -7
  213. data/spec_app/config/initializers/bower_rails.rb +0 -16
  214. data/spec_app/config/initializers/cookies_serializer.rb +0 -3
  215. data/spec_app/config/initializers/filter_parameter_logging.rb +0 -4
  216. data/spec_app/config/initializers/inflections.rb +0 -16
  217. data/spec_app/config/initializers/mime_types.rb +0 -4
  218. data/spec_app/config/initializers/session_store.rb +0 -3
  219. data/spec_app/config/initializers/wrap_parameters.rb +0 -14
  220. data/spec_app/config/locales/en.yml +0 -23
  221. data/spec_app/config/routes.rb +0 -30
  222. data/spec_app/config/secrets.yml +0 -22
  223. data/spec_app/db/schema.rb +0 -23
  224. data/spec_app/db/seeds.rb +0 -7
  225. data/spec_app/lib/assets/.keep +0 -0
  226. data/spec_app/lib/tasks/.keep +0 -0
  227. data/spec_app/lib/tasks/cucumber.rake +0 -65
  228. data/spec_app/log/.keep +0 -0
  229. data/spec_app/public/404.html +0 -67
  230. data/spec_app/public/422.html +0 -67
  231. data/spec_app/public/500.html +0 -66
  232. data/spec_app/public/favicon.ico +0 -0
  233. data/spec_app/public/robots.txt +0 -5
  234. data/spec_app/script/cucumber +0 -10
  235. data/spec_app/spec/controllers/binding_test_controller_spec.rb +0 -248
  236. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +0 -20
  237. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +0 -103
  238. data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +0 -21
  239. data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +0 -2
  240. data/spec_app/spec/javascripts/helpers/fixture.js.coffee +0 -25
  241. data/spec_app/spec/javascripts/helpers/index.js.coffee +0 -1
  242. data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +0 -1
  243. data/spec_app/spec/javascripts/helpers/knife.js.coffee +0 -69
  244. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +0 -25
  245. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +0 -8
  246. data/spec_app/spec/javascripts/helpers/mock_clock.js.coffee +0 -2
  247. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +0 -24
  248. data/spec_app/spec/javascripts/helpers/promise_state.js +0 -18
  249. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +0 -12
  250. data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +0 -8
  251. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +0 -23
  252. data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +0 -2
  253. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +0 -25
  254. data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +0 -5
  255. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +0 -12
  256. data/spec_app/spec/javascripts/helpers/spec_util.coffee +0 -47
  257. data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +0 -8
  258. data/spec_app/spec/javascripts/helpers/to_be_array.coffee +0 -5
  259. data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +0 -9
  260. data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +0 -8
  261. data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +0 -9
  262. data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +0 -8
  263. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +0 -8
  264. data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +0 -8
  265. data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +0 -8
  266. data/spec_app/spec/javascripts/helpers/to_be_jquery.js.coffee +0 -5
  267. data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +0 -8
  268. data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +0 -8
  269. data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +0 -11
  270. data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +0 -9
  271. data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +0 -8
  272. data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +0 -11
  273. data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +0 -8
  274. data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +0 -7
  275. data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +0 -7
  276. data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +0 -10
  277. data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +0 -10
  278. data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +0 -8
  279. data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +0 -15
  280. data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +0 -8
  281. data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +0 -16
  282. data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +0 -9
  283. data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -18
  284. data/spec_app/spec/javascripts/helpers/to_match_list.coffee +0 -14
  285. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +0 -8
  286. data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +0 -13
  287. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +0 -14
  288. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +0 -200
  289. data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +0 -5
  290. data/spec_app/spec/javascripts/support/jasmine.yml +0 -51
  291. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +0 -150
  292. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +0 -82
  293. data/spec_app/spec/javascripts/up/classes/config_spec.coffee +0 -24
  294. data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +0 -45
  295. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +0 -34
  296. data/spec_app/spec/javascripts/up/classes/params_spec.coffee +0 -557
  297. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +0 -50
  298. data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +0 -51
  299. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +0 -70
  300. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +0 -114
  301. data/spec_app/spec/javascripts/up/element_spec.coffee +0 -897
  302. data/spec_app/spec/javascripts/up/event_spec.js.coffee +0 -530
  303. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +0 -401
  304. data/spec_app/spec/javascripts/up/form_spec.js.coffee +0 -1488
  305. data/spec_app/spec/javascripts/up/fragment_spec.js.coffee +0 -2589
  306. data/spec_app/spec/javascripts/up/history_spec.js.coffee +0 -340
  307. data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +0 -4
  308. data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +0 -27
  309. data/spec_app/spec/javascripts/up/link_spec.js.coffee +0 -1093
  310. data/spec_app/spec/javascripts/up/log_spec.js.coffee +0 -119
  311. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +0 -917
  312. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +0 -582
  313. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +0 -507
  314. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +0 -39
  315. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +0 -1137
  316. data/spec_app/spec/javascripts/up/radio_spec.js.coffee +0 -212
  317. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +0 -118
  318. data/spec_app/spec/javascripts/up/spec_spec.js.coffee +0 -9
  319. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +0 -304
  320. data/spec_app/spec/javascripts/up/toast_spec.js.coffee +0 -37
  321. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +0 -163
  322. data/spec_app/spec/javascripts/up/util_spec.js.coffee +0 -1420
  323. data/spec_app/spec/javascripts/up/viewport_spec.js.coffee +0 -655
  324. data/spec_app/spec/spec_helper.rb +0 -62
  325. data/spec_app/test/controllers/.keep +0 -0
  326. data/spec_app/test/fixtures/.keep +0 -0
  327. data/spec_app/test/helpers/.keep +0 -0
  328. data/spec_app/test/integration/.keep +0 -0
  329. data/spec_app/test/mailers/.keep +0 -0
  330. data/spec_app/test/models/.keep +0 -0
  331. data/spec_app/test/test_helper.rb +0 -10
  332. data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +0 -1159
  333. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.bower.json +0 -43
  334. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.gitignore +0 -6
  335. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.npmignore +0 -10
  336. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.pairs +0 -6
  337. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.travis.yml +0 -56
  338. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/jasmine-ajax.js +0 -790
  339. data/spec_app/vendor/assets/.keep +0 -0
  340. data/unpoly-rails.gemspec +0 -24
@@ -1,924 +0,0 @@
1
- ###**
2
- Fragment update API
3
- ===================
4
-
5
- The `up.fragment` module exposes a high-level Javascript API to [update](/up.replace) or
6
- [destroy](/up.destroy) page fragments.
7
-
8
- Fragments are [compiled](/up.compiler) elements that can be updated from a server URL.
9
- They also exist on a layer (page, modal, popup).
10
-
11
- Most of Unpoly's functionality (like [fragment links](/up.link) or [modals](/up.modal))
12
- is built from `up.fragment` functions. You may use them to extend Unpoly from your
13
- [custom Javascript](/up.syntax).
14
-
15
- @module up.fragment
16
- ###
17
- up.fragment = do ->
18
-
19
- u = up.util
20
- e = up.element
21
-
22
- ###**
23
- Configures defaults for fragment insertion.
24
-
25
- @property up.fragment.config
26
- @param {string} [options.fallbacks=['body']]
27
- When a fragment updates cannot find the requested element, Unpoly will try this list of alternative selectors.
28
-
29
- The first selector that matches an element in the current page (or response) will be used.
30
- If the response contains none of the selectors, an error message will be shown.
31
-
32
- It is recommend to always keep `'body'` as the last selector in the last in the case
33
- your server or load balancer renders an error message that does not contain your
34
- application layout.
35
- @param {string} [options.fallbackTransition=null]
36
- The transition to use when using a [fallback target](/#options.fallbacks).
37
-
38
- By default this is not set and the original replacement's transition is used.
39
- @stable
40
- ###
41
- config = new up.Config
42
- fallbacks: ['body']
43
- fallbackTransition: null
44
-
45
- reset = ->
46
- config.reset()
47
-
48
- setSource = (element, sourceUrl) ->
49
- unless sourceUrl is false
50
- sourceUrl = u.normalizeUrl(sourceUrl) if u.isPresent(sourceUrl)
51
- element.setAttribute("up-source", sourceUrl)
52
-
53
- ###**
54
- Returns the URL the given element was retrieved from.
55
-
56
- @method up.fragment.source
57
- @param {string|Element|jQuery} selectorOrElement
58
- @experimental
59
- ###
60
- source = (selectorOrElement) ->
61
- element = e.get(selectorOrElement)
62
- if element = e.closest(element, '[up-source]')
63
- element.getAttribute("up-source")
64
- else
65
- up.browser.url()
66
-
67
- ###**
68
- Replaces elements on the current page with corresponding elements
69
- from a new page fetched from the server.
70
-
71
- The current and new elements must both match the given CSS selector.
72
-
73
- The unobtrusive variant of this is the [`a[up-target]`](/a-up-target) selector.
74
-
75
- \#\#\# Example
76
-
77
- Let's say your curent HTML looks like this:
78
-
79
- <div class="one">old one</div>
80
- <div class="two">old two</div>
81
-
82
- We now replace the second `<div>`:
83
-
84
- up.replace('.two', '/new')
85
-
86
- The server renders a response for `/new`:
87
-
88
- <div class="one">new one</div>
89
- <div class="two">new two</div>
90
-
91
- Unpoly looks for the selector `.two` in the response and [implants](/up.extract) it into
92
- the current page. The current page now looks like this:
93
-
94
- <div class="one">old one</div>
95
- <div class="two">new two</div>
96
-
97
- Note how only `.two` has changed. The update for `.one` was
98
- discarded, since it didn't match the selector.
99
-
100
- \#\#\# Appending or prepending instead of replacing
101
-
102
- By default Unpoly will replace the given selector with the same
103
- selector from a freshly fetched page. Instead of replacing you
104
- can *append* the loaded content to the existing content by using the
105
- `:after` pseudo selector. In the same fashion, you can use `:before`
106
- to indicate that you would like the *prepend* the loaded content.
107
-
108
- A practical example would be a paginated list of items:
109
-
110
- <ul class="tasks">
111
- <li>Wash car</li>
112
- <li>Purchase supplies</li>
113
- <li>Fix tent</li>
114
- </ul>
115
-
116
- In order to append more items from a URL, replace into
117
- the `.tasks:after` selector:
118
-
119
- up.replace('.tasks:after', '/page/2')
120
-
121
- \#\#\# Setting the window title from the server
122
-
123
- If the `replace` call changes history, the document title will be set
124
- to the contents of a `<title>` tag in the response.
125
-
126
- The server can also change the document title by setting
127
- an `X-Up-Title` header in the response.
128
-
129
- \#\#\# Optimizing response rendering
130
-
131
- The server is free to optimize Unpoly requests by only rendering the HTML fragment
132
- that is being updated. The request's `X-Up-Target` header will contain
133
- the CSS selector for the updating fragment.
134
-
135
- If you are using the `unpoly-rails` gem you can also access the selector via
136
- `up.target` in all controllers, views and helpers.
137
-
138
- \#\#\# Events
139
-
140
- Unpoly will emit [`up:fragment:destroyed`](/up:fragment:destroyed) on the element
141
- that was replaced and [`up:fragment:inserted`](/up:fragment:inserted) on the new
142
- element that replaces it.
143
-
144
- @function up.replace
145
- @param {string|Element|jQuery} selectorOrElement
146
- The CSS selector to update. You can also pass a DOM element or jQuery element
147
- here, in which case a selector will be inferred from the element's class and ID.
148
- @param {string} url
149
- The URL to fetch from the server.
150
- @param {string} [options.failTarget]
151
- The CSS selector to update if the server sends a non-200 status code.
152
- @param {string} [options.fallback]
153
- The selector to update when the original target was not found in the page.
154
- @param {string} [options.title]
155
- The document title after the replacement.
156
-
157
- If the call pushes an history entry and this option is missing, the title is extracted from the response's `<title>` tag.
158
- You can also pass `false` to explicitly prevent the title from being updated.
159
- @param {string} [options.method='get']
160
- The HTTP method to use for the request.
161
- @param {Object|FormData|string|Array} [options.params]
162
- [Parameters](/up.Params) that should be sent as the request's payload.
163
- @param {string} [options.transition='none']
164
- @param {string|boolean} [options.history=true]
165
- If a string is given, it is used as the URL the browser's location bar and history.
166
- If omitted or true, the `url` argument will be used.
167
- If set to `false`, the history will remain unchanged.
168
- @param {boolean|string} [options.source=true]
169
- @param {boolean|string} [options.reveal=false]
170
- Whether to [reveal](/up.reveal) the new fragment.
171
-
172
- You can also pass a CSS selector for the element to reveal.
173
- @param {boolean|string} [options.failReveal=false]
174
- Whether to [reveal](/up.reveal) the new fragment when the server responds with an error.
175
-
176
- You can also pass a CSS selector for the element to reveal.
177
- @param {number} [options.revealPadding]
178
-
179
- @param {boolean} [options.restoreScroll=false]
180
- If set to true, Unpoly will try to restore the scroll position
181
- of all the viewports around or below the updated element. The position
182
- will be reset to the last known top position before a previous
183
- history change for the current URL.
184
- @param {boolean} [options.cache]
185
- Whether to use a [cached response](/up.proxy) if available.
186
- @param {string} [options.historyMethod='push']
187
- @param {Object} [options.headers={}]
188
- An object of additional header key/value pairs to send along
189
- with the request.
190
- @param {Element|jQuery} [options.origin]
191
- The element that triggered the replacement.
192
-
193
- The element's selector will be substituted for the `&` shorthand in the target selector ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
194
- @param {string} [options.layer='auto']
195
- The name of the layer that ought to be updated. Valid values are
196
- `'auto'`, `'page'`, `'modal'` and `'popup'`.
197
-
198
- If set to `'auto'` (default), Unpoly will try to find a match in the
199
- same layer as the element that triggered the replacement (see `options.origin`).
200
- If that element is not known, or no match was found in that layer,
201
- Unpoly will search in other layers, starting from the topmost layer.
202
- @param {string} [options.failLayer='auto']
203
- The name of the layer that ought to be updated if the server sends a non-200 status code.
204
- @param {boolean} [options.keep=true]
205
- Whether this replacement will preserve [`[up-keep]`](/up-keep) elements.
206
- @param {boolean} [options.hungry=true]
207
- Whether this replacement will update [`[up-hungry]`](/up-hungry) elements.
208
-
209
- @return {Promise}
210
- A promise that will be fulfilled when the page has been updated.
211
- @stable
212
- ###
213
- replace = (selectorOrElement, url, options) ->
214
- options = u.options(options)
215
-
216
- options.inspectResponse = fullLoad = -> up.browser.navigate(url, u.only(options, 'method', 'params'))
217
-
218
- if !up.browser.canPushState() && options.history != false
219
- fullLoad() unless options.preload
220
- return u.unresolvablePromise()
221
-
222
- successOptions = u.merge options,
223
- humanizedTarget: 'target'
224
-
225
- failureOptions = u.merge options,
226
- humanizedTarget: 'failure target'
227
- provideTarget: undefined # don't provide a target if we're targeting the failTarget
228
- restoreScroll: false
229
-
230
- u.renameKey(failureOptions, 'failTransition', 'transition')
231
- u.renameKey(failureOptions, 'failLayer', 'layer')
232
- u.renameKey(failureOptions, 'failReveal', 'reveal')
233
-
234
- try
235
- improvedTarget = bestPreflightSelector(selectorOrElement, successOptions)
236
- improvedFailTarget = bestPreflightSelector(options.failTarget, failureOptions)
237
- catch error
238
- # Since we're an async function, we should not throw exceptions but return a rejected promise.
239
- # http://2ality.com/2016/03/promise-rejections-vs-exceptions.html
240
- return Promise.reject(error)
241
-
242
- requestAttrs = u.only options,
243
- 'method',
244
- 'data', # deprecated
245
- 'params',
246
- 'cache',
247
- 'preload',
248
- 'headers',
249
- 'timeout'
250
- u.assign requestAttrs,
251
- url: url
252
- target: improvedTarget
253
- failTarget: improvedFailTarget
254
-
255
- request = new up.Request(requestAttrs)
256
-
257
- onSuccess = (response) ->
258
- processResponse(true, improvedTarget, request, response, successOptions)
259
-
260
- onFailure = (response) ->
261
- rejection = -> Promise.reject(response)
262
- if response.isFatalError()
263
- rejection()
264
- else
265
- promise = processResponse(false, improvedFailTarget, request, response, failureOptions)
266
- # Although processResponse() we will perform a successful replacement of options.failTarget,
267
- # we still want to reject the promise that's returned to our API client.
268
- u.always(promise, rejection)
269
-
270
- promise = up.request(request)
271
- promise = promise.then(onSuccess, onFailure) unless options.preload
272
- promise
273
-
274
- ###**
275
- @internal
276
- ###
277
- processResponse = (isSuccess, selector, request, response, options) ->
278
- sourceUrl = response.url
279
- historyUrl = sourceUrl
280
-
281
- if hash = request.hash
282
- options.hash = hash
283
- historyUrl += hash
284
-
285
- isReloadable = (response.method == 'GET')
286
-
287
- if isSuccess
288
- if isReloadable # e.g. GET returns 200 OK
289
- options.history = historyUrl unless options.history is false || u.isString(options.history)
290
- options.source = sourceUrl unless options.source is false || u.isString(options.source)
291
- else # e.g. POST returns 200 OK
292
- # We allow the developer to pass GETable URLs as { history } and { source } options.
293
- options.history = false unless u.isString(options.history)
294
- options.source = 'keep' unless u.isString(options.source)
295
- else
296
- if isReloadable # e.g. GET returns 500 Internal Server Error
297
- options.history = historyUrl unless options.history is false
298
- options.source = sourceUrl unless options.source is false
299
- else # e.g. POST returns 500 Internal Server Error
300
- options.history = false
301
- options.source = 'keep'
302
-
303
- if shouldExtractTitle(options) && response.title
304
- options.title = response.title
305
-
306
- extract(selector, response.text, options)
307
-
308
- shouldExtractTitle = (options) ->
309
- not (options.title is false || u.isString(options.title) || (options.history is false && options.title isnt true))
310
-
311
- ###**
312
- Updates a selector on the current page with the
313
- same selector from the given HTML string.
314
-
315
- \#\#\# Example
316
-
317
- Let's say your curent HTML looks like this:
318
-
319
- <div class="one">old one</div>
320
- <div class="two">old two</div>
321
-
322
- We now replace the second `<div>`, using an HTML string
323
- as the source:
324
-
325
- html = '<div class="one">new one</div>' +
326
- '<div class="two">new two</div>';
327
-
328
- up.extract('.two', html)
329
-
330
- Unpoly looks for the selector `.two` in the strings and updates its
331
- contents in the current page. The current page now looks like this:
332
-
333
- <div class="one">old one</div>
334
- <div class="two">new two</div>
335
-
336
- Note how only `.two` has changed. The update for `.one` was
337
- discarded, since it didn't match the selector.
338
-
339
- @function up.extract
340
- @param {string|Element|jQuery} selectorOrElement
341
- @param {string} html
342
- @param {Object} [options]
343
- See options for [`up.replace()`](/up.replace).
344
- @return {Promise}
345
- A promise that will be fulfilled then the selector was updated
346
- and all animation has finished.
347
- @stable
348
- ###
349
- extract = (selectorOrElement, html, options) ->
350
- up.log.group 'Extracting %s from %d bytes of HTML', selectorOrElement, html?.length, ->
351
- options = u.options options,
352
- historyMethod: 'push'
353
- keep: true
354
- layer: 'auto'
355
-
356
- up.viewport.saveScroll() unless options.saveScroll == false
357
-
358
- u.rejectOnError ->
359
- # Allow callers to create the targeted element right before we swap.
360
- options.provideTarget?()
361
- responseDoc = new up.HtmlParser(html)
362
- extractSteps = bestMatchingSteps(selectorOrElement, responseDoc, options)
363
-
364
- if shouldExtractTitle(options) && responseTitle = responseDoc.title()
365
- options.title = responseTitle
366
- updateHistoryAndTitle(options)
367
-
368
- swapPromises = []
369
-
370
- for step in extractSteps
371
- up.log.group 'Swapping fragment %s', step.selector, ->
372
- # Note that we must copy the options hash instead of changing it in-place, since the
373
- # async swapElements() is scheduled for the next microtask and we must not change the options
374
- # for the previous iteration.
375
- swapOptions = u.merge(options, u.only(step, 'origin', 'reveal'))
376
- responseDoc.prepareForInsertion(step.newElement)
377
- swapPromise = swapElements(step.oldElement, step.newElement, step.pseudoClass, step.transition, swapOptions)
378
- swapPromises.push(swapPromise)
379
-
380
- # Delay all further links in the promise chain until all fragments have been swapped
381
- Promise.all(swapPromises)
382
-
383
- bestPreflightSelector = (selectorOrElement, options) ->
384
- cascade = new up.ExtractCascade(selectorOrElement, options)
385
- cascade.bestPreflightSelector()
386
-
387
- bestMatchingSteps = (selectorOrElement, response, options) ->
388
- options = u.merge(options, { response })
389
- cascade = new up.ExtractCascade(selectorOrElement, options)
390
- cascade.bestMatchingSteps()
391
-
392
- updateHistoryAndTitle = (options) ->
393
- options = u.options(options, historyMethod: 'push')
394
- up.history[options.historyMethod](options.history) if options.history
395
- document.title = options.title if u.isString(options.title)
396
-
397
- swapElements = (oldElement, newElement, pseudoClass, transition, options) ->
398
- transition ||= 'none'
399
-
400
- # When the server responds with an error, or when the request method is not
401
- # reloadable (not GET), we keep the same source as before.
402
- if options.source == 'keep'
403
- options = u.merge(options, source: source(oldElement))
404
-
405
- # Remember where the element came from in case someone needs to up.reload(newElement) later.
406
- setSource(newElement, options.source)
407
-
408
- if pseudoClass
409
- # Text nodes are wrapped in a .up-insertion container so we can
410
- # animate them and measure their position/size for scrolling.
411
- # This is not possible for container-less text nodes.
412
- wrapper = e.createFromSelector('.up-insertion')
413
- while childNode = newElement.firstChild
414
- wrapper.appendChild(childNode)
415
-
416
- # Note that since we're prepending/appending instead of replacing,
417
- # newElement will not actually be inserted into the DOM, only its children.
418
- if pseudoClass == 'before'
419
- oldElement.insertAdjacentElement('afterbegin', wrapper)
420
- else
421
- oldElement.insertAdjacentElement('beforeend', wrapper)
422
-
423
- for child in wrapper.children
424
- hello(child, options)
425
-
426
- # Reveal element that was being prepended/appended.
427
- # Since we will animate (not morph) it's OK to allow animation of scrolling
428
- # if options.scrollBehavior is given.
429
- promise = up.viewport.scrollAfterInsertFragment(wrapper, options)
430
-
431
- # Since we're adding content instead of replacing, we'll only
432
- # animate newElement instead of morphing between oldElement and newElement
433
- promise = u.always(promise, up.animate(wrapper, transition, options))
434
-
435
- # Remove the wrapper now that is has served it purpose
436
- promise = promise.then -> e.unwrap(wrapper)
437
-
438
- return promise
439
-
440
- else if keepPlan = findKeepPlan(oldElement, newElement, options)
441
- # Since we're keeping the element that was requested to be swapped,
442
- # there is nothing left to do here, except notify event listeners.
443
- emitFragmentKept(keepPlan)
444
- return Promise.resolve()
445
-
446
- else
447
- # This needs to happen before prepareClean() below.
448
- # Otherwise we would collect destructors for elements we want to keep.
449
- options.keepPlans = transferKeepableElements(oldElement, newElement, options)
450
-
451
- parent = oldElement.parentNode
452
-
453
- morphOptions = u.merge options,
454
- beforeStart: ->
455
- markElementAsDestroying(oldElement)
456
- afterInsert: ->
457
- up.hello(newElement, options)
458
- beforeDetach: ->
459
- up.syntax.clean(oldElement)
460
- afterDetach: ->
461
- e.remove(oldElement) # clean up jQuery data
462
- emitFragmentDestroyed(oldElement, parent: parent, log: false)
463
-
464
- return up.morph(oldElement, newElement, transition, morphOptions)
465
-
466
-
467
- # This will find all [up-keep] descendants in oldElement, overwrite their partner
468
- # element in newElement and leave a visually identical clone in oldElement for a later transition.
469
- # Returns an array of keepPlans.
470
- transferKeepableElements = (oldElement, newElement, options) ->
471
- keepPlans = []
472
- if options.keep
473
- for keepable in oldElement.querySelectorAll('[up-keep]')
474
- if plan = findKeepPlan(keepable, newElement, u.merge(options, descendantsOnly: true))
475
- # plan.oldElement is now keepable
476
-
477
- # Replace keepable with its clone so it looks good in a transition between
478
- # oldElement and newElement. Note that keepable will still point to the same element
479
- # after the replacement, which is now detached.
480
- keepableClone = keepable.cloneNode(true)
481
- e.replace(keepable, keepableClone)
482
-
483
- # Since we're going to swap the entire oldElement and newElement containers afterwards,
484
- # replace the matching element with keepable so it will eventually return to the DOM.
485
- e.replace(plan.newElement, keepable)
486
- keepPlans.push(plan)
487
- keepPlans
488
-
489
-
490
- findKeepPlan = (element, newElement, options) ->
491
- if options.keep
492
- keepable = element
493
- if partnerSelector = e.booleanOrStringAttr(keepable, 'up-keep')
494
- u.isString(partnerSelector) or partnerSelector = '&'
495
- partnerSelector = e.resolveSelector(partnerSelector, keepable)
496
- if options.descendantsOnly
497
- partner = e.first(newElement, partnerSelector)
498
- else
499
- partner = e.subtree(newElement, partnerSelector)[0]
500
- if partner && e.matches(partner, '[up-keep]')
501
- plan =
502
- oldElement: keepable # the element that should be kept
503
- newElement: partner # the element that would have replaced it but now does not
504
- newData: up.syntax.data(partner) # the parsed up-data attribute of the element we will discard
505
-
506
- keepEventArgs =
507
- target: keepable
508
- newFragment: partner
509
- newData: plan.newData
510
- log: ['Keeping element %o', keepable]
511
-
512
- if up.event.nobodyPrevents('up:fragment:keep', keepEventArgs)
513
- plan
514
-
515
- ###**
516
- Elements with an `up-keep` attribute will be persisted during
517
- [fragment updates](/a-up-target).
518
-
519
- For example:
520
-
521
- <audio up-keep src="song.mp3"></audio>
522
-
523
- The element you're keeping should have an umambiguous class name, ID or `up-id`
524
- attribute so Unpoly can find its new position within the page update.
525
-
526
- Emits events [`up:fragment:keep`](/up:fragment:keep) and [`up:fragment:kept`](/up:fragment:kept).
527
-
528
- \#\#\# Controlling if an element will be kept
529
-
530
- Unpoly will **only** keep an existing element if:
531
-
532
- - The existing element has an `up-keep` attribute
533
- - The response contains an element matching the CSS selector of the existing element
534
- - The matching element *also* has an `up-keep` attribute
535
- - The [`up:fragment:keep`](/up:fragment:keep) event that is [emitted](/up.emit) on the existing element
536
- is not prevented by a event listener.
537
-
538
- Let's say we want only keep an `<audio>` element as long as it plays
539
- the same song (as identified by the tag's `src` attribute).
540
-
541
- On the client we can achieve this by listening to an `up:keep:fragment` event
542
- and preventing it if the `src` attribute of the old and new element differ:
543
-
544
- up.compiler('audio', function(element) {
545
- element.addEventListener('up:fragment:keep', function(event) {
546
- if element.getAttribute('src') !== event.newElement.getAttribute('src') {
547
- event.preventDefault()
548
- }
549
- })
550
- })
551
-
552
- If we don't want to solve this on the client, we can achieve the same effect
553
- on the server. By setting the value of the `up-keep` attribute we can
554
- define the CSS selector used for matching elements.
555
-
556
- <audio up-keep="audio[src='song.mp3']" src="song.mp3"></audio>
557
-
558
- Now, if a response no longer contains an `<audio src="song.mp3">` tag, the existing
559
- element will be destroyed and replaced by a fragment from the response.
560
-
561
- @selector [up-keep]
562
- @stable
563
- ###
564
-
565
- ###**
566
- This event is [emitted](/up.emit) before an existing element is [kept](/up-keep) during
567
- a page update.
568
-
569
- Event listeners can call `event.preventDefault()` on an `up:fragment:keep` event
570
- to prevent the element from being persisted. If the event is prevented, the element
571
- will be replaced by a fragment from the response.
572
-
573
- @event up:fragment:keep
574
- @param event.preventDefault()
575
- Event listeners may call this method to prevent the element from being preserved.
576
- @param {Element} event.target
577
- The fragment that will be kept.
578
- @param {Element} event.newFragment
579
- The discarded element.
580
- @param {Object} event.newData
581
- The value of the [`up-data`](/up-data) attribute of the discarded element,
582
- parsed as a JSON object.
583
- @stable
584
- ###
585
-
586
- ###**
587
- This event is [emitted](/up.emit) when an existing element has been [kept](/up-keep)
588
- during a page update.
589
-
590
- Event listeners can inspect the discarded update through `event.newElement`
591
- and `event.newData` and then modify the preserved element when necessary.
592
-
593
- @event up:fragment:kept
594
- @param {Element} event.target
595
- The fragment that has been kept.
596
- @param {Element} event.newFragment
597
- The discarded fragment.
598
- @param {Object} event.newData
599
- The value of the [`up-data`](/up-data) attribute of the discarded fragment,
600
- parsed as a JSON object.
601
- @stable
602
- ###
603
-
604
- ###**
605
- Compiles a page fragment that has been inserted into the DOM
606
- by external code.
607
-
608
- **As long as you manipulate the DOM using Unpoly, you will never
609
- need to call this method.** You only need to use `up.hello()` if the
610
- DOM is manipulated without Unpoly' involvement, e.g. by setting
611
- the `innerHTML` property or calling jQuery methods like
612
- `html`, `insertAfter` or `appendTo`:
613
-
614
- element = document.createElement('div')
615
- element.innerHTML = '... HTML that needs to be activated ...'
616
- up.hello(element)
617
-
618
- This function emits the [`up:fragment:inserted`](/up:fragment:inserted)
619
- event.
620
-
621
- @function up.hello
622
- @param {string|Element|jQuery} selectorOrElement
623
- @param {string|Element|jQuery} [options.origin]
624
- @param {string|Element|jQuery} [options.kept]
625
- @return {Element}
626
- The compiled element
627
- @stable
628
- ###
629
- hello = (selectorOrElement, options) ->
630
- element = e.get(selectorOrElement)
631
- options = u.options(options, keepPlans: [])
632
- keptElements = []
633
- for plan in options.keepPlans
634
- emitFragmentKept(plan)
635
- keptElements.push(plan.oldElement)
636
- up.syntax.compile(element, skip: keptElements)
637
- emitFragmentInserted(element, options)
638
- element
639
-
640
- ###**
641
- When any page fragment has been [inserted or updated](/up.replace),
642
- this event is [emitted](/up.emit) on the fragment.
643
-
644
- If you're looking to run code when a new fragment matches
645
- a selector, use `up.compiler()` instead.
646
-
647
- \#\#\# Example
648
-
649
- up.on('up:fragment:inserted', function(event, fragment) {
650
- console.log("Looks like we have a new %o!", fragment)
651
- })
652
-
653
- @event up:fragment:inserted
654
- @param {Element} event.target
655
- The fragment that has been inserted or updated.
656
- @stable
657
- ###
658
- emitFragmentInserted = (element, options) ->
659
- up.emit element, 'up:fragment:inserted',
660
- log: ['Inserted fragment %o', element]
661
- origin: options.origin
662
-
663
- emitFragmentKept = (keepPlan) ->
664
- keptElement = keepPlan.oldElement
665
- eventAttrs =
666
- target: keptElement,
667
- newFragment: keepPlan.newElement
668
- newData: keepPlan.newData
669
- log: ['Kept fragment %o', keptElement]
670
-
671
- up.emit('up:fragment:kept', eventAttrs)
672
-
673
- emitFragmentDestroyed = (fragment, options) ->
674
- if shouldLogDestruction(fragment, options)
675
- log = ['Destroyed fragment %o', fragment]
676
- parent = options.parent or up.fail("Missing { parent } option")
677
- up.emit(parent, 'up:fragment:destroyed', { fragment, parent, log })
678
-
679
- isRealElement = (element) ->
680
- !e.closest(element, '.up-destroying')
681
-
682
- ###**
683
- Returns the first element matching the given selector, but
684
- ignores elements that are being [destroyed](/up.destroy) or that are being
685
- removed by a [transition](/up.morph).
686
-
687
- Returns `undefined` if no element matches these conditions.
688
-
689
- \#\#\# Example
690
-
691
- To select the first element with the selector `.foo`:
692
-
693
- var fooInModal = up.fragment.first('.foo')
694
-
695
- You may also pass a `{ layer }` option to only match elements witin a layer:
696
-
697
- var fooInModal = up.fragment.first('.foo', { layer: 'modal' })
698
-
699
- You may also pass a root element as a first argument:
700
-
701
- var container = up.fragment.first('.container')
702
- var fooInContainer = up.fragment.first(container, '.foo')
703
-
704
- \#\#\# Similar features
705
-
706
- - The [`.up-destroying`](/up-destroying) class is assigned to elements during their removal animation.
707
- - The [`up.element.first()`](/up.element.first) function simply returns the first element matching a selector
708
- without further filtering.
709
-
710
- @function up.fragment.first
711
- @param {Element|jQuery} [root=document]
712
- The root element for the search. Only the root's children will be matched.
713
-
714
- May be omitted to search through all elements in the `document`.
715
- @param {string} selector
716
- The selector to match
717
- @param {string} [options.layer='auto']
718
- The name of the layer in which to find the element.
719
-
720
- Valid values are `'auto'`, `'page'`, `'modal'` and `'popup'`.
721
- @param {string|Element|jQuery} [options.origin]
722
- An second element or selector that can be referenced as `&` in the first selector:
723
-
724
- var input = document.querySelector('input.email')
725
- up.fragment.first('fieldset:has(&)', { origin: input }) // returns the <fieldset> containing input
726
- @return {Element|undefined}
727
- The first element that is neither a ghost or being destroyed,
728
- or `undefined` if no such element was found.
729
- @experimental
730
- ###
731
- first = (args...) ->
732
- options = u.extractOptions(args)
733
- selector = args.pop()
734
- root = args[0] || document
735
- layer = options.layer ? 'auto'
736
- origin = options.origin
737
-
738
- selector = e.resolveSelector(selector, origin)
739
- if layer == 'auto'
740
- firstInPriority(root, selector, origin)
741
- else
742
- firstInLayer(root, selector, layer)
743
-
744
- firstInPriority = (parent, selector, origin) ->
745
- layers = ['popup', 'modal', 'page']
746
- if origin
747
- originLayer = layerOf(origin)
748
- # Make the origin's layer the top priority
749
- u.remove(layers, originLayer)
750
- layers.unshift(originLayer)
751
- u.findResult layers, (layer) ->
752
- return firstInLayer(parent, selector, layer)
753
-
754
- firstInLayer = (parent, selector, layer) ->
755
- elements = e.all(parent, selector)
756
- return u.findResult elements, (element) ->
757
- if isRealElement(element) && matchesLayer(element, layer)
758
- return element
759
-
760
- ###**
761
- @function up.fragment.layerOf
762
- @internal
763
- ###
764
- layerOf = (element) ->
765
- if up.popup.contains(element)
766
- 'popup'
767
- else if up.modal.contains(element)
768
- 'modal'
769
- else
770
- 'page'
771
-
772
- matchesLayer = (element, layer) ->
773
- !layer || layerOf(element) == layer
774
-
775
- ###**
776
- @function up.fragment.createPlaceHolder
777
- @internal
778
- ###
779
- createPlaceholder = (selector, container = document.body) ->
780
- e.affix(container, selector, class: 'up-placeholder')
781
-
782
- ###**
783
- Destroys the given element or selector.
784
-
785
- Takes care that all [`up.compiler()`](/up.compiler) destructors, if any, are called.
786
-
787
- The element is removed from the DOM.
788
- Note that if you choose to animate the element removal using `options.animate`,
789
- the element won't be removed until after the animation has completed.
790
-
791
- Emits events [`up:fragment:destroyed`](/up:fragment:destroyed).
792
-
793
- @function up.destroy
794
- @param {string|Element|jQuery} selectorOrElement
795
- @param {string} [options.history]
796
- A URL that will be pushed as a new history entry when the element begins destruction.
797
- @param {string} [options.title]
798
- The document title to set when the element begins destruction.
799
- @param {string|Function(element, options): Promise} [options.animation='none']
800
- The animation to use before the element is removed from the DOM.
801
- @param {number} [options.duration]
802
- The duration of the animation. See [`up.animate()`](/up.animate).
803
- @param {number} [options.delay]
804
- The delay before the animation starts. See [`up.animate()`](/up.animate).
805
- @param {string} [options.easing]
806
- The timing function that controls the animation's acceleration. [`up.animate()`](/up.animate).
807
- @return {Promise}
808
- A promise that will be fulfilled once the element has been removed from the DOM.
809
- @stable
810
- ###
811
- destroy = (selectorOrElement, options) ->
812
- element = e.get(selectorOrElement)
813
- options = u.options(options, animation: false)
814
-
815
- unless element
816
- return Promise.resolve()
817
-
818
- markElementAsDestroying(element)
819
-
820
- updateHistoryAndTitle(options)
821
-
822
- animate = ->
823
- animateOptions = up.motion.animateOptions(options)
824
- up.motion.animate(element, options.animation, animateOptions)
825
-
826
- wipe = ->
827
- parent = element.parentNode
828
- up.syntax.clean(element)
829
- e.remove(element)
830
- emitFragmentDestroyed(element, { parent: parent, log: options.log })
831
-
832
- animate().then(wipe)
833
-
834
- shouldLogDestruction = (element, options) ->
835
- # Don't log destruction for elements that are either Unpoly internals or frequently destroyed
836
- options.log != false && !e.matches(element, '.up-placeholder, .up-tooltip, .up-modal, .up-popup')
837
-
838
- ###**
839
- Elements are assigned the `.up-destroying` class before they are [destroyed](/up.destroy)
840
- or while they are being removed by a [transition](/up.morph).
841
-
842
- If the removal is animated, the class is assigned before the animation starts.
843
-
844
- To select an element while ignoring elements that are being destroyed,
845
- see the [`up.fragment.first()`](/up.fragment.first) function.
846
-
847
- @selector .up-destroying
848
- @stable
849
- ###
850
- markElementAsDestroying = (element) ->
851
- element.classList.add('up-destroying')
852
-
853
- ###**
854
- This event is [emitted](/up.emit) after a page fragment was [destroyed](/up.destroy) and removed from the DOM.
855
-
856
- If the destruction is animated, this event is emitted after the animation has ended.
857
-
858
- The event is emitted on the parent element of the fragment that was removed.
859
-
860
- @event up:fragment:destroyed
861
- @param {Element} event.fragment
862
- The detached element that has been removed from the DOM.
863
- @param {Element} event.parent
864
- The former parent element of the fragment that has now been detached from the DOM.
865
- @param {Element} event.target
866
- The former parent element of the fragment that has now been detached from the DOM.
867
- @stable
868
- ###
869
-
870
- ###**
871
- Replaces the given element with a fresh copy fetched from the server.
872
-
873
- \#\#\# Example
874
-
875
- up.on('new-mail', function() { up.reload('.inbox') })
876
-
877
- Unpoly remembers the URL from which a fragment was loaded, so you
878
- don't usually need to give an URL when reloading.
879
-
880
- @function up.reload
881
- @param {string|Element|jQuery} selectorOrElement
882
- @param {Object} [options]
883
- See options for [`up.replace()`](/up.replace)
884
- @param {string} [options.url]
885
- The URL from which to reload the fragment.
886
- This defaults to the URL from which the fragment was originally loaded.
887
- @stable
888
- ###
889
- reload = (selectorOrElement, options) ->
890
- options = u.options(options, cache: false)
891
- sourceUrl = options.url || source(selectorOrElement)
892
- replace(selectorOrElement, sourceUrl, options)
893
-
894
- up.on 'up:app:boot', ->
895
- body = document.body
896
- setSource(body, up.browser.url())
897
- hello(body)
898
-
899
- up.on 'up:framework:reset', reset
900
-
901
- <% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
902
- createPlaceholder: createPlaceholder
903
- replace: replace
904
- reload: reload
905
- destroy: destroy
906
- extract: extract
907
- first: first
908
- source: source
909
- hello: hello
910
- config: config
911
- layerOf: layerOf
912
-
913
- up.replace = up.fragment.replace
914
- up.extract = up.fragment.extract
915
- up.reload = up.fragment.reload
916
- up.destroy = up.fragment.destroy
917
- up.hello = up.fragment.hello
918
-
919
- up.first = (args...) ->
920
- up.legacy.warn('up.first() has been renamed to up.fragment.first()')
921
- up.fragment.first(args...)
922
-
923
- up.legacy.renamedModule 'flow', 'fragment'
924
- up.legacy.renamedModule 'dom', 'fragment'