unpoly-rails 0.61.0 → 2.0.0.pre.rc3

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 (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,1032 +0,0 @@
1
- ###**
2
- Forms
3
- =====
4
-
5
- Unpoly comes with functionality to [submit](/form-up-target) and [validate](/input-up-validate)
6
- forms without leaving the current page. This means you can replace page fragments,
7
- open dialogs with sub-forms, etc. all without losing form state.
8
-
9
- @module up.form
10
- ###
11
- up.form = do ->
12
-
13
- u = up.util
14
- e = up.element
15
-
16
- ###**
17
- Sets default options for form submission and validation.
18
-
19
- @property up.form.config
20
- @param {number} [config.observeDelay=0]
21
- The number of miliseconds to wait before [`up.observe()`](/up.observe) runs the callback
22
- after the input value changes. Use this to limit how often the callback
23
- will be invoked for a fast typist.
24
- @param {Array} [config.validateTargets=['[up-fieldset]:has(&)', 'fieldset:has(&)', 'label:has(&)', 'form:has(&)']]
25
- An array of CSS selectors that are searched around a form field
26
- that wants to [validate](/up.validate). The first matching selector
27
- will be updated with the validation messages from the server.
28
-
29
- By default this looks for a `<fieldset>`, `<label>` or `<form>`
30
- around the validating input field.
31
- @param {string} [config.fields]
32
- An array of CSS selectors that represent form fields, such as `input` or `select`.
33
- @param {string} [config.submitButtons]
34
- An array of CSS selectors that represent submit buttons, such as `input[type=submit]`.
35
- @stable
36
- ###
37
- config = new up.Config
38
- validateTargets: ['[up-fieldset]:has(&)', 'fieldset:has(&)', 'label:has(&)', 'form:has(&)']
39
- fields: ['select', 'input:not([type=submit]):not([type=image])', 'button[type]:not([type=submit])', 'textarea'],
40
- submitButtons: ['input[type=submit]', 'input[type=image]', 'button[type=submit]', 'button:not([type])']
41
- observeDelay: 0
42
-
43
- reset = ->
44
- config.reset()
45
-
46
- ###**
47
- @function up.form.fieldSelector
48
- @internal
49
- ###
50
- fieldSelector = ->
51
- config.fields.join(',')
52
-
53
- ###**
54
- Returns a list of form fields within the given element.
55
-
56
- You can configure what Unpoly considers a form field by adding CSS selectors to the
57
- [`up.form.config.fields`](/up.form.config#config.fields) array.
58
-
59
- If the given element is itself a form field, a list of the given element is returned.
60
-
61
- @function up.form.fields
62
- @return {NodeList<Element>|Array<Element>}
63
- @experimental
64
- ###
65
- findFields = (root) ->
66
- e.subtree(root, fieldSelector())
67
-
68
- # findFields = (rootOrRoots) ->
69
- # rootOrRoots = e.list(rootOrRoots)
70
- # u.flatMap rootOrRoots, (root) -> e.subtree(root, fieldSelector())
71
-
72
- ###***
73
- @function up.form.submissionFields
74
- @internal
75
- ###
76
- findSubmissionFields = (root) ->
77
- fields = findFields(root)
78
- if button = submittingButton(root)
79
- fields = u.toArray(fields)
80
- fields.push(button)
81
- fields
82
-
83
- ###**
84
- @function up.form.submittingButton
85
- @internal
86
- ###
87
- submittingButton = (form) ->
88
- selector = submitButtonSelector()
89
- focusedElement = document.activeElement
90
- if focusedElement && e.matches(focusedElement, selector) && form.contains(focusedElement)
91
- return focusedElement
92
- else
93
- # If no button is focused, we assume the first button in the form.
94
- return e.first(form, selector)
95
-
96
- ###**
97
- @function up.form.submitButtonSelector
98
- @internal
99
- ###
100
- submitButtonSelector = ->
101
- config.submitButtons.join(',')
102
-
103
- ###**
104
- Submits a form via AJAX and updates a page fragment with the response.
105
-
106
- up.submit('form.new-user', { target: '.main' })
107
-
108
- Instead of loading a new page, the form is submitted via AJAX.
109
- The response is parsed for a CSS selector and the matching elements will
110
- replace corresponding elements on the current page.
111
-
112
- The unobtrusive variant of this is the [`form[up-target]`](/form-up-target) selector.
113
- See the documentation for [`form[up-target]`](/form-up-target) for more
114
- information on how AJAX form submissions work in Unpoly.
115
-
116
- Emits the event [`up:form:submit`](/up:form:submit).
117
-
118
- @function up.submit
119
- @param {Element|jQuery|string} formOrSelector
120
- A reference or selector for the form to submit.
121
- If the argument points to an element that is not a form,
122
- Unpoly will search its ancestors for the closest form.
123
- @param {string} [options.url]
124
- The URL where to submit the form.
125
- Defaults to the form's `action` attribute, or to the current URL of the browser window.
126
- @param {string} [options.method='post']
127
- The HTTP method used for the form submission.
128
- Defaults to the form's `up-method`, `data-method` or `method` attribute, or to `'post'`
129
- if none of these attributes are given.
130
- @param {string} [options.target]
131
- The CSS selector to update when the form submission succeeds (server responds with status 200).
132
- Defaults to the form's `up-target` attribute.
133
-
134
- Inside the CSS selector you may refer to the form as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
135
- @param {string} [options.failTarget]
136
- The CSS selector to update when the form submission fails (server responds with non-200 status).
137
- Defaults to the form's `up-fail-target` attribute, or to an auto-generated
138
- selector that matches the form itself.
139
-
140
- Inside the CSS selector you may refer to the form as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
141
- @param {string} [options.fallback]
142
- The selector to update when the original target was not found in the page.
143
- Defaults to the form's `up-fallback` attribute.
144
- @param {boolean|string} [options.history=true]
145
- Successful form submissions will add a history entry and change the browser's
146
- location bar if the form either uses the `GET` method or the response redirected
147
- to another page (this requires the `unpoly-rails` gem).
148
- If you want to prevent history changes in any case, set this to `false`.
149
- If you pass a string, it is used as the URL for the browser history.
150
- @param {string} [options.transition='none']
151
- The transition to use when a successful form submission updates the `options.target` selector.
152
- Defaults to the form's `up-transition` attribute, or to `'none'`.
153
- @param {string} [options.failTransition='none']
154
- The transition to use when a failed form submission updates the `options.failTarget` selector.
155
- Defaults to the form's `up-fail-transition` attribute, or to `options.transition`, or to `'none'`.
156
- @param {number} [options.duration]
157
- The duration of the transition. See [`up.morph()`](/up.morph).
158
- @param {number} [options.delay]
159
- The delay before the transition starts. See [`up.morph()`](/up.morph).
160
- @param {string} [options.easing]
161
- The timing function that controls the transition's acceleration. [`up.morph()`](/up.morph).
162
- @param {Element|string} [options.reveal=true]
163
- Whether to reveal the target fragment after it was replaced.
164
-
165
- You can also pass a CSS selector for the element to reveal.
166
- @param {boolean|string} [options.failReveal=true]
167
- Whether to [reveal](/up.reveal) the target fragment when the server responds with an error.
168
-
169
- You can also pass a CSS selector for the element to reveal.
170
- @param {boolean} [options.restoreScroll]
171
- If set to `true`, this will attempt to [`restore scroll positions`](/up.restoreScroll)
172
- previously seen on the destination URL.
173
- @param {boolean} [options.cache]
174
- Whether to force the use of a cached response (`true`)
175
- or never use the cache (`false`)
176
- or make an educated guess (`undefined`).
177
-
178
- By default only responses to `GET` requests are cached
179
- for a few minutes.
180
- @param {Object} [options.headers={}]
181
- An object of additional header key/value pairs to send along
182
- with the request.
183
- @param {string} [options.layer='auto']
184
- The name of the layer that ought to be updated. Valid values are
185
- `'auto'`, `'page'`, `'modal'` and `'popup'`.
186
-
187
- If set to `'auto'` (default), Unpoly will try to find a match in the form's layer.
188
- @param {string} [options.failLayer='auto']
189
- The name of the layer that ought to be updated if the server sends a non-200 status code.
190
- @return {Promise}
191
- A promise for the successful form submission.
192
- @stable
193
- ###
194
- submit = (formOrSelector, options) ->
195
- options = u.options(options)
196
-
197
- form = e.get(formOrSelector)
198
- form = e.closest(form, 'form')
199
-
200
- target = options.target ? form.getAttribute('up-target') ? 'body'
201
- options.failTarget ?= form.getAttribute('up-fail-target') ? e.toSelector(form)
202
- options.reveal ?= e.booleanOrStringAttr(form, 'up-reveal') ? true
203
- options.failReveal ?= e.booleanOrStringAttr(form, 'up-fail-reveal') ? true
204
- options.fallback ?= form.getAttribute('up-fallback')
205
- options.history ?= e.booleanOrStringAttr(form, 'up-history') ? true
206
- options.transition ?= e.booleanOrStringAttr(form, 'up-transition')
207
- options.failTransition ?= e.booleanOrStringAttr(form, 'up-fail-transition')
208
- options.method ?= u.normalizeMethod(form.getAttribute('up-method') ? form.getAttribute('data-method') ? form.getAttribute('method') ? 'post')
209
- options.cache ?= e.booleanAttr(form, 'up-cache')
210
- options.restoreScroll ?= e.booleanAttr(form, 'up-restore-scroll') # the option supports an object value, but not the attr
211
- options.origin ?= form
212
- options.layer ?= form.getAttribute('up-layer')
213
- options.failLayer ?= form.getAttribute('up-fail-layer')
214
- options.params = up.Params.fromForm(form)
215
- options = u.merge(options, up.motion.animateOptions(options, form))
216
-
217
- if options.validate
218
- options.headers ||= {}
219
- options.transition = false
220
- options.failTransition = false
221
- options.headers[up.protocol.config.validateHeader] = options.validate
222
-
223
- url = options.url ? form.getAttribute('action') ? up.browser.url()
224
-
225
- if options.method == 'GET'
226
- # Only for GET forms, browsers discard all query params from the form's [action] URL.
227
- # The URLs search part will be replaced with the serialized form data.
228
- # See design/query-params-in-form-actions/cases.html for
229
- # a demo of vanilla browser behavior.
230
- url = up.Params.stripURL(url)
231
-
232
- up.event.whenEmitted('up:form:submit', log: 'Submitting form', target: form).then ->
233
- up.feedback.start(form)
234
-
235
- # If we can't update the location URL, fall back to a vanilla form submission.
236
- unless up.browser.canPushState() || options.history == false
237
- # Don't use up.browser.navigate(); It cannot deal with file inputs.
238
- form.submit()
239
- return u.unresolvablePromise()
240
-
241
- promise = up.replace(target, url, options)
242
- u.always promise, -> up.feedback.stop(form)
243
- promise
244
-
245
- ###**
246
- This event is [emitted](/up.emit) when a form is [submitted](/up.submit) through Unpoly.
247
-
248
- The event is emitted on the`<form>` element.
249
-
250
- @event up:form:submit
251
- @param {Element} event.target
252
- The `<form>` element that will be submitted.
253
- @param event.preventDefault()
254
- Event listeners may call this method to prevent the form from being submitted.
255
- @stable
256
- ###
257
-
258
- ###**
259
- Observes form fields and runs a callback when a value changes.
260
-
261
- This is useful for observing text fields while the user is typing.
262
-
263
- The unobtrusive variant of this is the [`[up-observe]`](/up-observe) attribute.
264
-
265
- \#\#\# Example
266
-
267
- The following would print to the console whenever an input field changes:
268
-
269
- up.observe('input.query', function(value) {
270
- console.log('Query is now %o', value)
271
- })
272
-
273
- Instead of a single form field, you can also pass multiple fields,
274
- a `<form>` or any container that contains form fields.
275
- The callback will be run if any of the given fields change:
276
-
277
- up.observe('form', function(value, name) {
278
- console.log('The value of %o is now %o', name, value)
279
- })
280
-
281
- You may also pass the `{ batch: true }` option to receive all
282
- changes since the last callback in a single object:
283
-
284
- up.observe('form', { batch: true }, function(diff) {
285
- console.log('Observed one or more changes: %o', diff)
286
- })
287
-
288
- @function up.observe
289
- @param {string|Element|Array<Element>|jQuery} elements
290
- The form fields that will be observed.
291
-
292
- You can pass one or more fields, a `<form>` or any container that contains form fields.
293
- The callback will be run if any of the given fields change.
294
- @param {boolean} [options.batch=false]
295
- If set to `true`, the `onChange` callback will receive multiple
296
- detected changes in a single diff object as its argument.
297
- @param {number} [options.delay=up.form.config.observeDelay]
298
- The number of miliseconds to wait before executing the callback
299
- after the input value changes. Use this to limit how often the callback
300
- will be invoked for a fast typist.
301
- @param {Function(value, name): string} onChange
302
- The callback to run when the field's value changes.
303
-
304
- If given as a function, it receives two arguments (`value`, `name`).
305
- `value` is a string with the new attribute value and `string` is the name
306
- of the form field that changed.
307
-
308
- If given as a string, it will be evaled as JavaScript code in a context where
309
- (`value`, `name`) are set.
310
- @return {Function()}
311
- A destructor function that removes the observe watch when called.
312
- @stable
313
- ###
314
- observe = (elements, args...) ->
315
- elements = e.list(elements)
316
- fields = u.flatMap(elements, findFields)
317
- callback = u.extractCallback(args) ? observeCallbackFromElement(elements[0]) ? up.fail('up.observe: No change callback given')
318
- options = u.extractOptions(args)
319
- options.delay = options.delay ? e.numberAttr(elements[0], 'up-delay') ? config.observeDelay
320
- observer = new up.FieldObserver(fields, options, callback)
321
- observer.start()
322
- return observer.stop
323
-
324
- observeCallbackFromElement = (element) ->
325
- if rawCallback = element.getAttribute('up-observe')
326
- new Function('value', 'name', rawCallback)
327
-
328
- ###**
329
- [Observes](/up.observe) a field or form and submits the form when a value changes.
330
-
331
- Both the form and the changed field will be assigned a CSS class [`form-up-active`](/form-up-active)
332
- while the autosubmitted form is processing.
333
-
334
- The unobtrusive variant of this is the [`up-autosubmit`](/form-up-autosubmit) attribute.
335
-
336
- @function up.autosubmit
337
- @param {string|Element|jQuery} selectorOrElement
338
- The field or form to observe.
339
- @param {Object} [options]
340
- See options for [`up.observe()`](/up.observe)
341
- @return {Function()}
342
- A destructor function that removes the observe watch when called.
343
- @stable
344
- ###
345
- autosubmit = (selectorOrElement, options) ->
346
- observe(selectorOrElement, options, -> submit(selectorOrElement))
347
-
348
- findValidateTarget = (field, options) ->
349
- option = options.target ? field.getAttribute('up-validate')
350
- option ||= u.findResult config.validateTargets, (defaultTarget) ->
351
- resolvedDefault = e.resolveSelector(defaultTarget, options.origin)
352
- if e.first(resolvedDefault)
353
- # We want to return the selector, *not* the element. If we returned the element
354
- # and derive a selector from that, any :has() expression would be lost.
355
- return resolvedDefault
356
-
357
- unless option
358
- up.fail('Could not find validation target for %o (tried defaults %o)', field, config.validateTargets)
359
-
360
- # resolveSelector() also creates a selector string if given an element
361
- return e.resolveSelector(option, options.origin)
362
-
363
- ###**
364
- Performs a server-side validation of a form field.
365
-
366
- `up.validate()` submits the given field's form with an additional `X-Up-Validate`
367
- HTTP header. Upon seeing this header, the server is expected to validate (but not save)
368
- the form submission and render a new copy of the form with validation errors.
369
-
370
- The unobtrusive variant of this is the [`input[up-validate]`](/input-up-validate) selector.
371
- See the documentation for [`input[up-validate]`](/input-up-validate) for more information
372
- on how server-side validation works in Unpoly.
373
-
374
- \#\#\# Example
375
-
376
- up.validate('input[name=email]', { target: '.email-errors' })
377
-
378
- @function up.validate
379
- @param {string|Element|jQuery} fieldOrSelector
380
-
381
- @param {string|Element|jQuery} [options.target]
382
- @return {Promise}
383
- A promise that is fulfilled when the server-side
384
- validation is received and the form was updated.
385
- @stable
386
- ###
387
- validate = (fieldOrSelector, options) ->
388
- field = e.get(fieldOrSelector)
389
- options = u.options(options)
390
- options.origin = field
391
- options.target = findValidateTarget(field, options)
392
- options.failTarget = options.target
393
- options.reveal ?= e.booleanOrStringAttr(field, 'up-reveal') ? false
394
- options.history = false
395
- # Make sure the X-Up-Validate header is present, so the server-side
396
- # knows that it should not persist the form submission
397
- options.validate = field.getAttribute('name') || ':none'
398
- options = u.merge(options, up.motion.animateOptions(options, field))
399
- promise = up.submit(field, options)
400
- promise
401
-
402
- switcherValues = (field) ->
403
- value = undefined
404
- meta = undefined
405
-
406
- if e.matches(field, 'input[type=checkbox]')
407
- if field.checked
408
- value = field.value
409
- meta = ':checked'
410
- else
411
- meta = ':unchecked'
412
- else if e.matches(field, 'input[type=radio]')
413
- form = closestContainer(field)
414
- groupName = field.getAttribute('name')
415
- checkedButton = form.querySelector("input[type=radio]#{e.attributeSelector('name', groupName)}:checked")
416
- if checkedButton
417
- meta = ':checked'
418
- value = checkedButton.value
419
- else
420
- meta = ':unchecked'
421
- else
422
- value = field.value
423
-
424
- values = []
425
- if u.isPresent(value)
426
- values.push(value)
427
- values.push(':present')
428
- else
429
- values.push(':blank')
430
- if u.isPresent(meta)
431
- values.push(meta)
432
- values
433
-
434
- ###**
435
- Shows or hides a target selector depending on the value.
436
-
437
- See [`input[up-switch]`](/input-up-switch) for more documentation and examples.
438
-
439
- This function does not currently have a very useful API outside
440
- of our use for `up-switch`'s UJS behavior, that's why it's currently
441
- still marked `@internal`.
442
-
443
- @function up.form.switchTargets
444
- @param {Element} switcher
445
- @param {string} [options.target]
446
- The target selectors to switch.
447
- Defaults to an `[up-switch]` attribute on the given field.
448
- @internal
449
- ###
450
- switchTargets = (switcher, options = {}) ->
451
- targetSelector = options.target ? switcher.getAttribute('up-switch')
452
- form = closestContainer(switcher)
453
- u.isPresent(targetSelector) or up.fail("No switch target given for %o", switcher)
454
- fieldValues = switcherValues(switcher)
455
-
456
- u.each e.all(form, targetSelector), (target) ->
457
- switchTarget(target, fieldValues)
458
-
459
- ###**
460
- @internal
461
- ###
462
- switchTarget = (target, fieldValues) ->
463
- fieldValues ||= switcherValues(findSwitcherForTarget(target))
464
-
465
- if hideValues = target.getAttribute('up-hide-for')
466
- hideValues = u.splitValues(hideValues)
467
- show = u.intersect(fieldValues, hideValues).length == 0
468
- else
469
- if showValues = target.getAttribute('up-show-for')
470
- showValues = u.splitValues(showValues)
471
- else
472
- # If the target has neither up-show-for or up-hide-for attributes,
473
- # assume the user wants the target to be visible whenever anything
474
- # is checked or entered.
475
- showValues = [':present', ':checked']
476
- show = u.intersect(fieldValues, showValues).length > 0
477
-
478
- e.toggle(target, show)
479
- target.classList.add('up-switched')
480
-
481
- ###**
482
- @internal
483
- ###
484
- findSwitcherForTarget = (target) ->
485
- form = closestContainer(target)
486
- switchers = e.all(form, '[up-switch]')
487
- switcher = u.find switchers, (switcher) ->
488
- targetSelector = switcher.getAttribute('up-switch')
489
- e.matches(target, targetSelector)
490
- return switcher or u.fail('Could not find [up-switch] field for %o', target)
491
-
492
- closestContainer = (element) ->
493
- e.closest(element, 'form, body')
494
-
495
- ###**
496
- Forms with an `up-target` attribute are [submitted via AJAX](/up.submit)
497
- instead of triggering a full page reload.
498
-
499
- <form method="post" action="/users" up-target=".main">
500
- ...
501
- </form>
502
-
503
- The server response is searched for the selector given in `up-target`.
504
- The selector content is then [replaced](/up.replace) in the current page.
505
-
506
- The programmatic variant of this is the [`up.submit()`](/up.submit) function.
507
-
508
- \#\#\# Failed submission
509
-
510
- When the server was unable to save the form due to invalid params,
511
- it will usually re-render an updated copy of the form with
512
- validation messages.
513
-
514
- For Unpoly to be able to detect a failed form submission,
515
- the form must be re-rendered with a non-200 HTTP status code.
516
- We recommend to use either 400 (bad request) or
517
- 422 (unprocessable entity).
518
-
519
- In Ruby on Rails, you can pass a
520
- [`:status` option to `render`](http://guides.rubyonrails.org/layouts_and_rendering.html#the-status-option)
521
- for this:
522
-
523
- class UsersController < ApplicationController
524
-
525
- def create
526
- user_params = params[:user].permit(:email, :password)
527
- @user = User.new(user_params)
528
- if @user.save?
529
- sign_in @user
530
- else
531
- render 'form', status: :bad_request
532
- end
533
- end
534
-
535
- end
536
-
537
- Note that you can also use
538
- [`input[up-validate]`](/input-up-validate) to perform server-side
539
- validations while the user is completing fields.
540
-
541
- \#\#\# Redirects
542
-
543
- Unpoly requires an additional response headers to detect redirects,
544
- which are otherwise undetectable for an AJAX client.
545
-
546
- After the form's action performs a redirect, the next response should echo
547
- the new request's URL as a response header `X-Up-Location`.
548
-
549
- If you are using Unpoly via the `unpoly-rails` gem, these headers
550
- are set automatically for every request.
551
-
552
- \#\#\# Giving feedback while the form is processing
553
-
554
- The `<form>` element will be assigned a CSS class [`up-active`](/form.up-active) while
555
- the submission is loading.
556
-
557
- You can also [implement a spinner](/up.proxy/#spinners)
558
- by [listening](/up.on) to the [`up:proxy:slow`](/up:proxy:slow)
559
- and [`up:proxy:recover`](/up:proxy:recover) events.
560
-
561
- @selector form[up-target]
562
- @param {string} up-target
563
- The CSS selector to [replace](/up.replace) if the form submission is successful (200 status code).
564
-
565
- Inside the CSS selector you may refer to this form as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
566
- @param {string} [up-fail-target]
567
- The CSS selector to [replace](/up.replace) if the form submission is not successful (non-200 status code).
568
-
569
- Inside the CSS selector you may refer to this form as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
570
-
571
- If omitted, Unpoly will replace the `<form>` tag itself, assuming that the server has echoed the form with validation errors.
572
- @param [up-fallback]
573
- The selector to replace if the server responds with an error.
574
- @param {string} [up-transition]
575
- The animation to use when the form is replaced after a successful submission.
576
- @param {string} [up-fail-transition]
577
- The animation to use when the form is replaced after a failed submission.
578
- @param [up-history]
579
- Whether to push a browser history entry after a successful form submission.
580
-
581
- By default the form's target URL is used. If the form redirects to another URL,
582
- the redirect target will be used.
583
-
584
- Set this to `'false'` to prevent the URL bar from being updated.
585
- Set this to a URL string to update the history with the given URL.
586
- @param {string} [up-method]
587
- The HTTP method to be used to submit the form (`get`, `post`, `put`, `delete`, `patch`).
588
- Alternately you can use an attribute `data-method`
589
- ([Rails UJS](https://github.com/rails/jquery-ujs/wiki/Unobtrusive-scripting-support-for-jQuery))
590
- or `method` (vanilla HTML) for the same purpose.
591
- @param {string} [up-layer='auto']
592
- The name of the layer that ought to be updated. Valid values are
593
- `'auto'`, `'page'`, `'modal'` and `'popup'`.
594
-
595
- If set to `'auto'` (default), Unpoly will try to find a match in the form's layer.
596
- If no match was found in that layer,
597
- Unpoly will search in other layers, starting from the topmost layer.
598
- @param {string} [up-fail-layer='auto']
599
- The name of the layer that ought to be updated if the server sends a
600
- non-200 status code.
601
- @param {string} [up-reveal='true']
602
- Whether to reveal the target element after it was replaced.
603
-
604
- You can also pass a CSS selector for the element to reveal.
605
- Inside the CSS selector you may refer to the form as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
606
- @param {string} [up-fail-reveal='true']
607
- Whether to reveal the target element when the server responds with an error.
608
-
609
- You can also pass a CSS selector for the element to reveal. You may use this, for example,
610
- to reveal the first validation error message:
611
-
612
- <form up-target=".content" up-fail-reveal=".error">
613
- ...
614
- </form>
615
-
616
- Inside the CSS selector you may refer to the form as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
617
- @param {string} [up-restore-scroll='false']
618
- Whether to restore previously known scroll position of all viewports
619
- within the target selector.
620
- @param {string} [up-cache]
621
- Whether to force the use of a cached response (`true`)
622
- or never use the cache (`false`)
623
- or make an educated guess (`undefined`).
624
-
625
- By default only responses to `GET` requests are cached for a few minutes.
626
- @stable
627
- ###
628
- up.on 'submit', 'form[up-target]', (event, form) ->
629
- up.event.consumeAction(event)
630
- u.muteRejection submit(form)
631
-
632
- ###**
633
- When a form field with this attribute is changed, the form is validated on the server
634
- and is updated with validation messages.
635
-
636
- To validate the form, Unpoly will submit the form with an additional `X-Up-Validate` HTTP header.
637
- When seeing this header, the server is expected to validate (but not save)
638
- the form submission and render a new copy of the form with validation errors.
639
-
640
- The programmatic variant of this is the [`up.validate()`](/up.validate) function.
641
-
642
- \#\#\# Example
643
-
644
- Let's look at a standard registration form that asks for an e-mail and password:
645
-
646
- <form action="/users">
647
-
648
- <label>
649
- E-mail: <input type="text" name="email" />
650
- </label>
651
-
652
- <label>
653
- Password: <input type="password" name="password" />
654
- </label>
655
-
656
- <button type="submit">Register</button>
657
-
658
- </form>
659
-
660
- When the user changes the `email` field, we want to validate that
661
- the e-mail address is valid and still available. Also we want to
662
- change the `password` field for the minimum required password length.
663
- We can do this by giving both fields an `up-validate` attribute:
664
-
665
- <form action="/users">
666
-
667
- <label>
668
- E-mail: <input type="text" name="email" up-validate />
669
- </label>
670
-
671
- <label>
672
- Password: <input type="password" name="password" up-validate />
673
- </label>
674
-
675
- <button type="submit">Register</button>
676
-
677
- </form>
678
-
679
- Whenever a field with `up-validate` changes, the form is POSTed to
680
- `/users` with an additional `X-Up-Validate` HTTP header.
681
- When seeing this header, the server is expected to validate (but not save)
682
- the form submission and render a new copy of the form with validation errors.
683
-
684
- In Ruby on Rails the processing action should behave like this:
685
-
686
- class UsersController < ApplicationController
687
-
688
- # This action handles POST /users
689
- def create
690
- user_params = params[:user].permit(:email, :password)
691
- @user = User.new(user_params)
692
- if request.headers['X-Up-Validate']
693
- @user.valid? # run validations, but don't save to the database
694
- render 'form' # render form with error messages
695
- elsif @user.save?
696
- sign_in @user
697
- else
698
- render 'form', status: :bad_request
699
- end
700
- end
701
-
702
- end
703
-
704
- Note that if you're using the `unpoly-rails` gem you can simply say `up.validate?`
705
- instead of manually checking for `request.headers['X-Up-Validate']`.
706
-
707
- The server now renders an updated copy of the form with eventual validation errors:
708
-
709
- <form action="/users">
710
-
711
- <label class="has-error">
712
- E-mail: <input type="text" name="email" value="foo@bar.com" />
713
- Has already been taken!
714
- </label>
715
-
716
- <button type="submit">Register</button>
717
-
718
- </form>
719
-
720
- The `<label>` around the e-mail field is now updated to have the `has-error`
721
- class and display the validation message.
722
-
723
- \#\#\# How validation results are displayed
724
-
725
- Although the server will usually respond to a validation with a complete,
726
- fresh copy of the form, Unpoly will by default not update the entire form.
727
- This is done in order to preserve volatile state such as the scroll position
728
- of `<textarea>` elements.
729
-
730
- By default Unpoly looks for a `<fieldset>`, `<label>` or `<form>`
731
- around the validating input field, or any element with an
732
- `up-fieldset` attribute.
733
- With the Bootstrap bindings, Unpoly will also look
734
- for a container with the `form-group` class.
735
-
736
- You can change this default behavior by setting [`up.form.config.validateTargets`](/up.form.config#config.validateTargets):
737
-
738
- // Always update the entire form containing the current field ("&")
739
- up.form.config.validateTargets = ['form &']
740
-
741
- You can also individually override what to update by setting the `up-validate`
742
- attribute to a CSS selector:
743
-
744
- <input type="text" name="email" up-validate=".email-errors">
745
- <span class="email-errors"></span>
746
-
747
- \#\#\# Updating dependent fields
748
-
749
- The `[up-validate]` behavior is also a great way to partially update a form
750
- when one fields depends on the value of another field.
751
-
752
- Let's say you have a form with one `<select>` to pick a department (sales, engineering, ...)
753
- and another `<select>` to pick an employeee from the selected department:
754
-
755
- <form action="/contracts">
756
- <select name="department">...</select> <!-- options for all departments -->
757
- <select name="employeed">...</select> <!-- options for employees of selected department -->
758
- </form>
759
-
760
- The list of employees needs to be updated as the appartment changes:
761
-
762
- <form action="/contracts">
763
- <select name="department" up-validate="[name=employee]">...</select>
764
- <select name="employee">...</select>
765
- </form>
766
-
767
- In order to update the `department` field in addition to the `employee` field, you could say
768
- `up-validate="&, [name=employee]"`, or simply `up-validate="form"` to update the entire form.
769
-
770
- @selector input[up-validate]
771
- @param {string} up-validate
772
- The CSS selector to update with the server response.
773
-
774
- This defaults to a fieldset or form group around the validating field.
775
- @stable
776
- ###
777
-
778
- ###**
779
- Performs [server-side validation](/input-up-validate) when any fieldset within this form changes.
780
-
781
- You can configure what Unpoly considers a fieldset by adding CSS selectors to the
782
- [`up.form.config.validateTargets`](/up.form.config#config.validateTargets) array.
783
-
784
- @selector form[up-validate]
785
- @stable
786
- ###
787
- up.on 'change', '[up-validate]', (event) ->
788
- field = findFields(event.target)[0]
789
- u.muteRejection validate(field)
790
-
791
- ###**
792
- Show or hide elements when a `<select>` or `<input>` has a given value.
793
-
794
- \#\#\# Example: Select options
795
-
796
- The controlling form field gets an `up-switch` attribute with a selector for the elements to show or hide:
797
-
798
- <select name="advancedness" up-switch=".target">
799
- <option value="basic">Basic parts</option>
800
- <option value="advanced">Advanced parts</option>
801
- <option value="very-advanced">Very advanced parts</option>
802
- </select>
803
-
804
- The target elements can use [`[up-show-for]`](/up-show-for) and [`[up-hide-for]`](/up-hide-for)
805
- attributes to indicate for which values they should be shown or hidden:
806
-
807
- <div class="target" up-show-for="basic">
808
- only shown for advancedness = basic
809
- </div>
810
-
811
- <div class="target" up-hide-for="basic">
812
- hidden for advancedness = basic
813
- </div>
814
-
815
- <div class="target" up-show-for="advanced very-advanced">
816
- shown for advancedness = advanced or very-advanced
817
- </div>
818
-
819
- \#\#\# Example: Text field
820
-
821
- The controlling `<input>` gets an `up-switch` attribute with a selector for the elements to show or hide:
822
-
823
- <input type="text" name="user" up-switch=".target">
824
-
825
- <div class="target" up-show-for="alice">
826
- only shown for user alice
827
- </div>
828
-
829
- You can also use the pseudo-values `:blank` to match an empty input value,
830
- or `:present` to match a non-empty input value:
831
-
832
- <input type="text" name="user" up-switch=".target">
833
-
834
- <div class="target" up-show-for=":blank">
835
- please enter a username
836
- </div>
837
-
838
- \#\#\# Example: Checkbox
839
-
840
- For checkboxes you can match against the pseudo-values `:checked` or `:unchecked`:
841
-
842
- <input type="checkbox" name="flag" up-switch=".target">
843
-
844
- <div class="target" up-show-for=":checked">
845
- only shown when checkbox is checked
846
- </div>
847
-
848
- <div class="target" up-show-for=":cunhecked">
849
- only shown when checkbox is unchecked
850
- </div>
851
-
852
- Of course you can also match against the `value` property of the checkbox element:
853
-
854
- <input type="checkbox" name="flag" value="active" up-switch=".target">
855
-
856
- <div class="target" up-show-for="active">
857
- only shown when checkbox is checked
858
- </div>
859
-
860
- @selector input[up-switch]
861
- @param {string} up-switch
862
- A CSS selector for elements whose visibility depends on this field's value.
863
- @stable
864
- ###
865
-
866
- ###**
867
- Only shows this element if an input field with [`[up-switch]`](/input-up-switch) has one of the given values.
868
-
869
- See [`input[up-switch]`](/input-up-switch) for more documentation and examples.
870
-
871
- @selector [up-show-for]
872
- @param {string} [up-show-for]
873
- A space-separated list of input values for which this element should be shown.
874
- @stable
875
- ###
876
-
877
- ###**
878
- Hides this element if an input field with [`[up-switch]`](/input-up-switch) has one of the given values.
879
-
880
- See [`input[up-switch]`](/input-up-switch) for more documentation and examples.
881
-
882
- @selector [up-hide-for]
883
- @param {string} [up-hide-for]
884
- A space-separated list of input values for which this element should be hidden.
885
- @stable
886
- ###
887
- up.compiler '[up-switch]', (switcher) ->
888
- switchTargets(switcher)
889
-
890
- up.on 'change', '[up-switch]', (event, switcher) ->
891
- switchTargets(switcher)
892
-
893
- up.compiler '[up-show-for]:not(.up-switched), [up-hide-for]:not(.up-switched)', (element) ->
894
- switchTarget(element)
895
-
896
- ###**
897
- Observes this field and runs a callback when a value changes.
898
-
899
- This is useful for observing text fields while the user is typing.
900
- If you want to submit the form after a change see [`input[up-autosubmit]`](/input-up-autosubmit).
901
-
902
- The programmatic variant of this is the [`up.observe()`](/up.observe) function.
903
-
904
- \#\#\# Examples
905
-
906
- The following would run a global `showSuggestions(value)` function
907
- whenever the `<input>` changes:
908
-
909
- <form>
910
- <input name="query" up-observe="showSuggestions(value)">
911
- </form>
912
-
913
- \#\#\# Callback context
914
-
915
- The script given to `up-observe` runs with the following context:
916
-
917
- | Name | Type | Description |
918
- | -------- | --------- | ------------------------------------- |
919
- | `value` | `string` | The current value of the field |
920
- | `this` | `Element` | The form field |
921
- | `$field` | `jQuery` | The form field as a jQuery collection |
922
-
923
- @selector input[up-observe]
924
- @param {string} up-observe
925
- The code to run when the field's value changes.
926
- @param {string} up-delay
927
- The number of miliseconds to wait after a change before the code is run.
928
- @stable
929
- ###
930
-
931
- ###**
932
- Observes this form and runs a callback when any field changes.
933
-
934
- This is useful for observing text fields while the user is typing.
935
- If you want to submit the form after a change see [`input[up-autosubmit]`](/input-up-autosubmit).
936
-
937
- The programmatic variant of this is the [`up.observe()`](/up.observe) function.
938
-
939
- \#\#\# Example
940
-
941
- The would call a function `somethingChanged(value)`
942
- when any `<input>` within the `<form>` changes:
943
-
944
- <form up-observe="somethingChanged(value)">
945
- <input name="foo">
946
- <input name="bar">
947
- </form>
948
-
949
- \#\#\# Callback context
950
-
951
- The script given to `up-observe` runs with the following context:
952
-
953
- | Name | Type | Description |
954
- | -------- | --------- | ------------------------------------- |
955
- | `value` | `string` | The current value of the field |
956
- | `this` | `Element` | The form field |
957
- | `$field` | `jQuery` | The form field as a jQuery collection |
958
-
959
- @selector form[up-observe]
960
- @param {string} up-observe
961
- The code to run when any field's value changes.
962
- @param {string} up-delay
963
- The number of miliseconds to wait after a change before the code is run.
964
- @stable
965
- ###
966
- up.compiler '[up-observe]', (formOrField) -> observe(formOrField)
967
-
968
- ###**
969
- [Observes](/up.observe) this form field and submits the form when its value changes.
970
-
971
- Both the form and the changed field will be assigned a CSS class [`up-active`](/form-up-active)
972
- while the autosubmitted form is loading.
973
-
974
- The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
975
-
976
- \#\#\# Example
977
-
978
- The following would automatically submit the form when the query is changed:
979
-
980
- <form method="GET" action="/search">
981
- <input type="search" name="query" up-autosubmit>
982
- <input type="checkbox" name="archive"> Include archive
983
- </form>
984
-
985
- @selector input[up-autosubmit]
986
- @param {string} up-delay
987
- The number of miliseconds to wait after a change before the form is submitted.
988
- @stable
989
- ###
990
-
991
- ###**
992
- [Observes](/up.observe) this form and submits the form when *any* field changes.
993
-
994
- Both the form and the field will be assigned a CSS class [`up-active`](/form-up-active)
995
- while the autosubmitted form is loading.
996
-
997
- The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
998
-
999
- \#\#\# Example
1000
-
1001
- This will submit the form when either query or checkbox was changed:
1002
-
1003
- <form method="GET" action="/search" up-autosubmit>
1004
- <input type="search" name="query">
1005
- <input type="checkbox" name="archive"> Include archive
1006
- </form>
1007
-
1008
- @selector form[up-autosubmit]
1009
- @param {string} up-delay
1010
- The number of miliseconds to wait after a change before the form is submitted.
1011
- @stable
1012
- ###
1013
- up.compiler '[up-autosubmit]', (formOrField) -> autosubmit(formOrField)
1014
-
1015
- up.compiler '[autofocus]', { batch: true }, (inputs) -> u.last(inputs).focus()
1016
-
1017
- up.on 'up:framework:reset', reset
1018
-
1019
- <% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
1020
- config: config
1021
- submit: submit
1022
- observe: observe
1023
- validate: validate
1024
- autosubmit: autosubmit
1025
- fieldSelector: fieldSelector
1026
- fields: findFields
1027
- submissionFields: findSubmissionFields
1028
-
1029
- up.submit = up.form.submit
1030
- up.observe = up.form.observe
1031
- up.autosubmit = up.form.autosubmit
1032
- up.validate = up.form.validate