unpoly-rails 1.0.3 → 2.0.0.pre.rc2

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

Potentially problematic release.


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

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