unpoly-rails 0.62.0 → 2.0.0.pre.rc5

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