unpoly-rails 0.61.1 → 2.0.0.pre.rc4

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 +85 -2
  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 +15368 -10444
  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 -56
  78. data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +0 -46
  79. data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +0 -157
  80. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +0 -543
  81. data/lib/assets/javascripts/unpoly/classes/record.coffee +0 -22
  82. data/lib/assets/javascripts/unpoly/classes/rect.js +0 -21
  83. data/lib/assets/javascripts/unpoly/classes/request.coffee +0 -246
  84. data/lib/assets/javascripts/unpoly/classes/response.coffee +0 -157
  85. data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +0 -102
  86. data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +0 -67
  87. data/lib/assets/javascripts/unpoly/classes/selector.coffee +0 -60
  88. data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +0 -26
  89. data/lib/assets/javascripts/unpoly/classes/store/session.coffee +0 -59
  90. data/lib/assets/javascripts/unpoly/classes/tether.coffee +0 -105
  91. data/lib/assets/javascripts/unpoly/classes/url_set.coffee +0 -32
  92. data/lib/assets/javascripts/unpoly/cookie.coffee +0 -56
  93. data/lib/assets/javascripts/unpoly/element.coffee.erb +0 -1126
  94. data/lib/assets/javascripts/unpoly/event.coffee.erb +0 -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 -927
  98. data/lib/assets/javascripts/unpoly/framework.coffee +0 -67
  99. data/lib/assets/javascripts/unpoly/history.coffee +0 -268
  100. data/lib/assets/javascripts/unpoly/legacy.coffee +0 -60
  101. data/lib/assets/javascripts/unpoly/link.coffee.erb +0 -622
  102. data/lib/assets/javascripts/unpoly/log.coffee +0 -248
  103. data/lib/assets/javascripts/unpoly/modal.coffee.erb +0 -825
  104. data/lib/assets/javascripts/unpoly/motion.coffee.erb +0 -668
  105. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
  106. data/lib/assets/javascripts/unpoly/popup.coffee.erb +0 -515
  107. data/lib/assets/javascripts/unpoly/protocol.coffee +0 -298
  108. data/lib/assets/javascripts/unpoly/proxy.coffee +0 -672
  109. data/lib/assets/javascripts/unpoly/radio.coffee +0 -60
  110. data/lib/assets/javascripts/unpoly/rails.coffee +0 -24
  111. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +0 -477
  112. data/lib/assets/javascripts/unpoly/toast.coffee +0 -67
  113. data/lib/assets/javascripts/unpoly/tooltip.coffee +0 -276
  114. data/lib/assets/javascripts/unpoly/util.coffee.erb +0 -1676
  115. data/lib/assets/javascripts/unpoly/viewport.coffee.erb +0 -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 -2598
  306. data/spec_app/spec/javascripts/up/history_spec.js.coffee +0 -340
  307. data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +0 -4
  308. data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +0 -27
  309. data/spec_app/spec/javascripts/up/link_spec.js.coffee +0 -1093
  310. data/spec_app/spec/javascripts/up/log_spec.js.coffee +0 -119
  311. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +0 -917
  312. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +0 -582
  313. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +0 -507
  314. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +0 -39
  315. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +0 -1137
  316. data/spec_app/spec/javascripts/up/radio_spec.js.coffee +0 -212
  317. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +0 -118
  318. data/spec_app/spec/javascripts/up/spec_spec.js.coffee +0 -9
  319. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +0 -304
  320. data/spec_app/spec/javascripts/up/toast_spec.js.coffee +0 -37
  321. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +0 -163
  322. data/spec_app/spec/javascripts/up/util_spec.js.coffee +0 -1420
  323. data/spec_app/spec/javascripts/up/viewport_spec.js.coffee +0 -655
  324. data/spec_app/spec/spec_helper.rb +0 -62
  325. data/spec_app/test/controllers/.keep +0 -0
  326. data/spec_app/test/fixtures/.keep +0 -0
  327. data/spec_app/test/helpers/.keep +0 -0
  328. data/spec_app/test/integration/.keep +0 -0
  329. data/spec_app/test/mailers/.keep +0 -0
  330. data/spec_app/test/models/.keep +0 -0
  331. data/spec_app/test/test_helper.rb +0 -10
  332. data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +0 -1159
  333. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.bower.json +0 -43
  334. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.gitignore +0 -6
  335. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.npmignore +0 -10
  336. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.pairs +0 -6
  337. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.travis.yml +0 -56
  338. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/jasmine-ajax.js +0 -790
  339. data/spec_app/vendor/assets/.keep +0 -0
  340. data/unpoly-rails.gemspec +0 -24
@@ -1,248 +0,0 @@
1
- ###**
2
- Logging
3
- =======
4
-
5
- Unpoly can print debugging information to the developer console, e.g.:
6
-
7
- - Which [events](/up.event) are called
8
- - When we're [making requests to the network](/up.proxy)
9
- - Which [compilers](/up.syntax) are applied to which elements
10
-
11
- You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12
- The output can be configured using the [`up.log.config`](/up.log.config) property.
13
-
14
- @module up.log
15
- ###
16
- up.log = do ->
17
-
18
- u = up.util
19
- b = up.browser
20
-
21
- sessionStore = new up.store.Session('up.log')
22
-
23
- ###**
24
- Configures the logging output on the developer console.
25
-
26
- @property up.log.config
27
- @param {boolean} [options.enabled=false]
28
- Whether Unpoly will print debugging information to the developer console.
29
-
30
- Debugging information includes which elements are being [compiled](/up.syntax)
31
- and which [events](/up.event) are being emitted.
32
- Note that errors will always be printed, regardless of this setting.
33
- @param {boolean} [options.collapse=false]
34
- Whether debugging information is printed as a collapsed tree.
35
-
36
- Set this to `true` if you are overwhelmed by the debugging information Unpoly
37
- prints to the developer console.
38
- @param {string} [options.prefix='[UP] ']
39
- A string to prepend to Unpoly's logging messages so you can distinguish it from your own messages.
40
- @stable
41
- ###
42
- config = new up.Config
43
- prefix: '[UP] '
44
- enabled: sessionStore.get('enabled')
45
- collapse: false
46
-
47
- reset = ->
48
- config.reset()
49
-
50
- prefix = (message) ->
51
- "#{config.prefix}#{message}"
52
-
53
- ###**
54
- A cross-browser way to interact with `console.log`, `console.error`, etc.
55
-
56
- This function falls back to `console.log` if the output stream is not implemented.
57
- It also prints substitution strings (e.g. `console.log("From %o to %o", "a", "b")`)
58
- as a single string if the browser console does not support substitution strings.
59
-
60
- \#\#\# Example
61
-
62
- up.browser.puts('log', 'Hi world')
63
- up.browser.puts('error', 'There was an error in %o', obj)
64
-
65
- @function up.browser.puts
66
- @internal
67
- ###
68
- callConsole = (stream, args...) ->
69
- console[stream](args...)
70
-
71
- CONSOLE_PLACEHOLDERS = /\%[odisf]/g
72
-
73
- stringifyArg = (arg) ->
74
- maxLength = 200
75
- closer = ''
76
-
77
- if u.isString(arg)
78
- string = arg.replace(/[\n\r\t ]+/g, ' ')
79
- string = string.replace(/^[\n\r\t ]+/, '')
80
- string = string.replace(/[\n\r\t ]$/, '')
81
- string = "\"#{string}\""
82
- closer = '"'
83
- else if u.isUndefined(arg)
84
- # JSON.stringify(undefined) is actually undefined
85
- string = 'undefined'
86
- else if u.isNumber(arg) || u.isFunction(arg)
87
- string = arg.toString()
88
- else if u.isArray(arg)
89
- string = "[#{u.map(arg, stringifyArg).join(', ')}]"
90
- closer = ']'
91
- else if u.isJQuery(arg)
92
- string = "$(#{u.map(arg, stringifyArg).join(', ')})"
93
- closer = ')'
94
- else if u.isElement(arg)
95
- string = "<#{arg.tagName.toLowerCase()}"
96
- for attr in ['id', 'name', 'class']
97
- if value = arg.getAttribute(attr)
98
- string += " #{attr}=\"#{value}\""
99
- string += ">"
100
- closer = '>'
101
- else # object
102
- string = JSON.stringify(arg)
103
- if string.length > maxLength
104
- string = "#{string.substr(0, maxLength)} …"
105
- string += closer
106
- string
107
-
108
- ###**
109
- See https://developer.mozilla.org/en-US/docs/Web/API/Console#Using_string_substitutions
110
-
111
- @function up.browser.sprintf
112
- @internal
113
- ###
114
- sprintf = (message, args...) ->
115
- sprintfWithFormattedArgs(u.identity, message, args...)
116
-
117
- ###**
118
- @function up.browser.sprintfWithFormattedArgs
119
- @internal
120
- ###
121
- sprintfWithFormattedArgs = (formatter, message, args...) ->
122
- return '' if u.isBlank(message)
123
-
124
- i = 0
125
- message.replace CONSOLE_PLACEHOLDERS, ->
126
- arg = args[i]
127
- arg = formatter(stringifyArg(arg))
128
- i += 1
129
- arg
130
-
131
- ###**
132
- Prints a debugging message to the browser console.
133
-
134
- @function up.log.debug
135
- @param {string} message
136
- @param {Array} ...args
137
- @internal
138
- ###
139
- debug = (message, args...) ->
140
- if config.enabled && message
141
- console.debug(prefix(message), args...)
142
-
143
- ###**
144
- Prints a logging message to the browser console.
145
-
146
- @function up.puts
147
- @param {string} message
148
- @param {Array} ...args
149
- @internal
150
- ###
151
- puts = (message, args...) ->
152
- if config.enabled && message
153
- console.log(prefix(message), args...)
154
-
155
- ###**
156
- @function up.warn
157
- @internal
158
- ###
159
- warn = (message, args...) ->
160
- if message
161
- console.warn(prefix(message), args...)
162
-
163
- ###**
164
- - Makes sure the group always closes
165
- - Does not make a group if the message is nil
166
-
167
- @function up.log.group
168
- @internal
169
- ###
170
- group = (message, args...) ->
171
- block = args.pop() # Coffeescript copies the arguments array
172
- if config.enabled && message
173
- fn = if config.collapse then 'groupCollapsed' else 'group'
174
- console[fn](prefix(message), args...)
175
- try
176
- block()
177
- finally
178
- console.groupEnd() if message
179
- else
180
- block()
181
-
182
- ###**
183
- @function up.log.error
184
- @internal
185
- ###
186
- error = (message, args...) ->
187
- if message
188
- console.error(prefix(message), args...)
189
-
190
- printBanner = ->
191
- # The ASCII art looks broken in code since we need to escape backslashes
192
- banner = " __ _____ ___ ___ / /_ __\n" +
193
- "/ // / _ \\/ _ \\/ _ \\/ / // / #{up.version}\n" +
194
- "\\___/_//_/ .__/\\___/_/\\_. / \n" +
195
- " / / / /\n" +
196
- "\n"
197
- if config.enabled
198
- banner += "Call `up.log.disable()` to disable logging for this session."
199
- else
200
- banner += "Call `up.log.enable()` to enable logging for this session."
201
- console.log(banner)
202
-
203
- up.on 'up:framework:booted', printBanner
204
- up.on 'up:framework:reset', reset
205
-
206
- setEnabled = (value) ->
207
- sessionStore.set('enabled', value)
208
- config.enabled = value
209
-
210
- ###**
211
- Makes future Unpoly events print vast amounts of debugging information to the developer console.
212
-
213
- Debugging information includes which elements are being [compiled](/up.syntax)
214
- and which [events](/up.event) are being emitted.
215
-
216
- @function up.log.enable
217
- @stable
218
- ###
219
- enable = ->
220
- setEnabled(true)
221
-
222
- ###**
223
- Prevents future Unpoly events from printing vast amounts of debugging information to the developer console.
224
-
225
- Errors will still be printed, even with logging disabled.
226
-
227
- @function up.log.disable
228
- @stable
229
- ###
230
- disable = ->
231
- setEnabled(false)
232
-
233
- puts: puts
234
- sprintf: sprintf
235
- sprintfWithFormattedArgs: sprintfWithFormattedArgs
236
- puts: puts
237
- debug: debug
238
- error: error
239
- warn: warn
240
- group: group
241
- config: config
242
- enable: enable
243
- disable: disable
244
- isEnabled: -> config.enabled
245
-
246
- up.puts = up.log.puts
247
- up.warn = up.log.warn
248
-
@@ -1,825 +0,0 @@
1
- ###**
2
- Modal dialogs
3
- =============
4
-
5
- Instead of [linking to a page fragment](/up.link), you can choose to show a fragment
6
- in a modal dialog. The existing page will remain open in the background.
7
-
8
- To open a modal, add an [`[up-modal]`](/a-up-modal) attribute to a link:
9
-
10
- <a href="/blogs" up-modal=".blog-list">Switch blog</a>
11
-
12
- When this link is clicked, Unpoly will request the path `/blogs` and extract
13
- an element matching the selector `.blog-list` from the response. The matching element
14
- will then be placed in a modal dialog.
15
-
16
-
17
- \#\#\# Closing behavior
18
-
19
- By default the dialog automatically closes
20
- *when a link inside a modal changes a fragment behind the modal*.
21
- This is useful to have the dialog interact with the page that
22
- opened it, e.g. by updating parts of a larger form.
23
-
24
- To disable this behavior, give the opening link an [`up-sticky`](/a-up-modal#up-sticky) attribute:
25
-
26
-
27
- \#\#\# Customizing the dialog design
28
-
29
- Dialogs have a minimal default design:
30
-
31
- - Contents are displayed in a white box with a subtle box shadow
32
- - The box will grow to fit the dialog contents, but never grow larger than the screen
33
- - The box is placed over a semi-transparent backdrop to dim the rest of the page
34
- - There is a button to close the dialog in the top-right corner
35
-
36
- The easiest way to change how the dialog looks is to override the
37
- [default CSS styles](https://github.com/unpoly/unpoly/blob/master/lib/assets/stylesheets/unpoly/modal.sass).
38
-
39
- By default the dialog uses the following DOM structure:
40
-
41
- <div class="up-modal">
42
- <div class="up-modal-backdrop">
43
- <div class="up-modal-viewport">
44
- <div class="up-modal-dialog">
45
- <div class="up-modal-content">
46
- <!-- the matching element will be placed here -->
47
- </div>
48
- <div class="up-modal-close" up-close>X</div>
49
- </div>
50
- </div>
51
- </div>
52
-
53
- You can change this structure by setting [`up.modal.config.template`](/up.modal.config#config.template) to a new template string
54
- or function.
55
-
56
-
57
- @module up.modal
58
- ###
59
- up.modal = do ->
60
-
61
- u = up.util
62
- e = up.element
63
-
64
- ###**
65
- Sets default options for future modals.
66
-
67
- @property up.modal.config
68
- @param {string} [config.history=true]
69
- Whether opening a modal will add a browser history entry.
70
- @param {number} [config.width]
71
- The width of the dialog as a CSS value like `'400px'` or `'50%'`.
72
-
73
- Defaults to `undefined`, meaning that the dialog will grow to fit its contents
74
- until it reaches `config.maxWidth`. Leaving this as `undefined` will
75
- also allow you to control the width using CSS on `.up-modal-dialog´.
76
- @param {number} [config.maxWidth]
77
- The width of the dialog as a CSS value like `'400px'` or `50%`.
78
- You can set this to `undefined` to make the dialog fit its contents.
79
- Be aware however, that e.g. Bootstrap stretches input elements
80
- to `width: 100%`, meaning the dialog will also stretch to the full
81
- width of the screen.
82
- @param {number} [config.height='auto']
83
- The height of the dialog in pixels.
84
- Defaults to `undefined`, meaning that the dialog will grow to fit its contents.
85
- @param {string|Function(config): string} [config.template]
86
- A string containing the HTML structure of the modal.
87
- You can supply an alternative template string, but make sure that it
88
- defines tag with the classes `up-modal`, `up-modal-dialog` and `up-modal-content`.
89
-
90
- You can also supply a function that returns a HTML string.
91
- The function will be called with the modal options (merged from these defaults
92
- and any per-open overrides) whenever a modal opens.
93
- @param {string} [config.closeLabel='×']
94
- The label of the button that closes the dialog.
95
- @param {boolean} [config.closable=true]
96
- When `true`, the modal will render a close icon and close when the user
97
- clicks on the backdrop or presses Escape.
98
-
99
- When `false`, you need to either supply an element with `[up-close]` or
100
- close the modal manually with `up.modal.close()`.
101
- @param {string} [config.openAnimation='fade-in']
102
- The animation used to open the viewport around the dialog.
103
- @param {string} [config.closeAnimation='fade-out']
104
- The animation used to close the viewport the dialog.
105
- @param {string} [config.backdropOpenAnimation='fade-in']
106
- The animation used to open the backdrop that dims the page below the dialog.
107
- @param {string} [config.backdropCloseAnimation='fade-out']
108
- The animation used to close the backdrop that dims the page below the dialog.
109
- @param {number} [config.openDuration]
110
- The duration of the open animation (in milliseconds).
111
- @param {number} [config.closeDuration]
112
- The duration of the close animation (in milliseconds).
113
- @param {string} [config.openEasing]
114
- The timing function controlling the acceleration of the opening animation.
115
- @param {string} [config.closeEasing]
116
- The timing function controlling the acceleration of the closing animation.
117
- @param {boolean} [options.sticky=false]
118
- If set to `true`, the modal remains
119
- open even it changes the page in the background.
120
- @param {string} [options.flavor='default']
121
- The default [flavor](/up.modal.flavors).
122
- @stable
123
- ###
124
- config = new up.Config
125
- maxWidth: null
126
- width: null
127
- height: null
128
- history: true
129
- openAnimation: 'fade-in'
130
- closeAnimation: 'fade-out'
131
- openDuration: null
132
- closeDuration: null
133
- openEasing: null
134
- closeEasing: null
135
- backdropOpenAnimation: 'fade-in'
136
- backdropCloseAnimation: 'fade-out'
137
- closeLabel: '×'
138
- closable: true
139
- sticky: false
140
- flavor: 'default'
141
- position: null
142
- template: (options) ->
143
- """
144
- <div class="up-modal">
145
- <div class="up-modal-backdrop"></div>
146
- <div class="up-modal-viewport">
147
- <div class="up-modal-dialog">
148
- <div class="up-modal-content"></div>
149
- <div class="up-modal-close" up-close>#{options.closeLabel}</div>
150
- </div>
151
- </div>
152
- </div>
153
- """
154
-
155
- ###**
156
- Define modal variants with their own default configuration, CSS or HTML template.
157
-
158
- \#\#\# Example
159
-
160
- Unpoly's [`[up-drawer]`](/a-up-drawer) is implemented as a modal flavor:
161
-
162
- up.modal.flavors.drawer = {
163
- openAnimation: 'move-from-right',
164
- closeAnimation: 'move-to-right'
165
- }
166
-
167
- Modals with that flavor will have a container with an `up-flavor` attribute:
168
-
169
- <div class='up-modal' up-flavor='drawer'>
170
- ...
171
- </div>
172
-
173
- We can target the `up-flavor` attribute to override the default dialog styles:
174
-
175
- .up-modal[up-flavor='drawer'] {
176
-
177
- .up-modal-dialog {
178
- margin: 0; // Remove margin so drawer starts at the screen edge
179
- max-width: 350px; // Set drawer size
180
- }
181
-
182
- .up-modal-content {
183
- min-height: 100vh; // Stretch background to full window height
184
- }
185
- }
186
-
187
- @property up.modal.flavors
188
- @param {Object} flavors
189
- An object where the keys are flavor names (e.g. `'drawer') and
190
- the values are the respective default configurations.
191
- @experimental
192
- ###
193
- flavors = new up.Config
194
- default: {}
195
-
196
- ###**
197
- Returns the source URL for the fragment displayed in the current modal overlay,
198
- or `undefined` if no modal is currently open.
199
-
200
- @function up.modal.url
201
- @return {string}
202
- the source URL
203
- @stable
204
- ###
205
-
206
- ###**
207
- Returns the URL of the page behind the modal overlay.
208
-
209
- @function up.modal.coveredUrl
210
- @return {string}
211
- @experimental
212
- ###
213
-
214
- state = new up.Config
215
- phase: 'closed' # can be 'opening', 'opened', 'closing' and 'closed'
216
- anchorElement: null # the element to which the tooltip is anchored
217
- modalElement: null # the modal container
218
- sticky: null
219
- closable: null
220
- flavor: null
221
- url: null
222
- coveredUrl: null
223
- coveredTitle: null
224
- position: null
225
-
226
- bodyShifter = new up.BodyShifter()
227
-
228
- chain = new up.DivertibleChain()
229
-
230
- reset = ->
231
- e.remove(state.modalElement) if state.modalElement
232
- bodyShifter.unshift()
233
- state.reset()
234
- chain.reset()
235
- config.reset()
236
- flavors.reset()
237
-
238
- templateHtml = ->
239
- template = flavorDefault('template')
240
- u.evalOption(template, closeLabel: flavorDefault('closeLabel'))
241
-
242
- discardHistory = ->
243
- state.coveredTitle = null
244
- state.coveredUrl = null
245
-
246
- part = (name) ->
247
- selector = ".up-modal-#{name}"
248
- state.modalElement.querySelector(selector)
249
-
250
- createHiddenFrame = (target, options) ->
251
- html = templateHtml()
252
- state.modalElement = modalElement = e.createFromHtml(html)
253
- modalElement.setAttribute('up-flavor', state.flavor)
254
- modalElement.setAttribute('up-position', state.position) if u.isPresent(state.position)
255
-
256
- dialogStyles = u.only(options, 'width', 'maxWidth', 'height')
257
- e.setStyle(part('dialog'), dialogStyles)
258
-
259
- unless state.closable
260
- closeElement = part('close')
261
- e.remove(closeElement)
262
-
263
- contentElement = part('content')
264
- # Create an empty element that will match the
265
- # selector that is being replaced.
266
- up.fragment.createPlaceholder(target, contentElement)
267
- e.hide(modalElement)
268
- document.body.appendChild(modalElement)
269
-
270
- unveilFrame = ->
271
- e.show(state.modalElement)
272
-
273
- ###**
274
- Returns whether a modal is currently open.
275
-
276
- This also returns `true` if the modal is in an opening or closing animation.
277
-
278
- @function up.modal.isOpen
279
- @return {boolean}
280
- @stable
281
- ###
282
- isOpen = ->
283
- state.phase == 'opened' || state.phase == 'opening'
284
-
285
- ###**
286
- Opens the given link's destination in a modal overlay:
287
-
288
- var link = document.querySelector('a')
289
- up.modal.follow(link)
290
-
291
- Any option attributes for [`a[up-modal]`](/a-up-modal) will be honored.
292
-
293
- Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
294
-
295
- @function up.modal.follow
296
- @param {Element|jQuery|string} linkOrSelector
297
- The link to follow.
298
- @param {string} [options.target]
299
- The selector to extract from the response and open in a modal dialog.
300
- @param {number} [options.width]
301
- The width of the dialog in pixels.
302
- By [default](/up.modal.config) the dialog will grow to fit its contents.
303
- @param {number} [options.height]
304
- The width of the dialog in pixels.
305
- By [default](/up.modal.config) the dialog will grow to fit its contents.
306
- @param {boolean} [options.sticky=false]
307
- If set to `true`, the modal remains
308
- open even it changes the page in the background.
309
- @param {boolean} [config.closable=true]
310
- When `true`, the modal will render a close icon and close when the user
311
- clicks on the backdrop or presses Escape.
312
-
313
- When `false`, you need to either supply an element with `[up-close]` or
314
- close the modal manually with `up.modal.close()`.
315
- @param {string} [options.confirm]
316
- A message that will be displayed in a cancelable confirmation dialog
317
- before the modal is being opened.
318
- @param {string} [options.method="GET"]
319
- Override the request method.
320
- @param {boolean} [options.history=true]
321
- Whether to add a browser history entry for the modal's source URL.
322
- @param {string} [options.animation]
323
- The animation to use when opening the modal.
324
- @param {number} [options.duration]
325
- The duration of the animation. See [`up.animate()`](/up.animate).
326
- @param {number} [options.delay]
327
- The delay before the animation starts. See [`up.animate()`](/up.animate).
328
- @param {string} [options.easing]
329
- The timing function that controls the animation's acceleration. [`up.animate()`](/up.animate).
330
- @return {Promise}
331
- A promise that will be fulfilled when the modal has been loaded and
332
- the opening animation has completed.
333
- @stable
334
- ###
335
- followAsap = (linkOrSelector, options) ->
336
- options = u.options(options)
337
- options.link = e.get(linkOrSelector)
338
- openAsap(options)
339
-
340
- preloadNow = (link, options) ->
341
- options = u.options(options)
342
- options.link = link
343
- options.preload = true
344
- # Use openNow() and not openAsap() so (1) we don't close a currently open modal
345
- # and (2) our pending AJAX request does not prevent other modals from opening
346
- openNow(options)
347
-
348
- ###**
349
- Opens a modal for the given URL.
350
-
351
- \#\#\# Example
352
-
353
- up.modal.visit('/foo', { target: '.list' })
354
-
355
- This will request `/foo`, extract the `.list` selector from the response
356
- and open the selected container in a modal dialog.
357
-
358
- Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
359
-
360
- @function up.modal.visit
361
- @param {string} url
362
- The URL to load.
363
- @param {string} options.target
364
- The CSS selector to extract from the response.
365
- The extracted content will be placed into the dialog window.
366
- @param {Object} options
367
- See options for [`up.modal.follow()`](/up.modal.follow).
368
- @return {Promise}
369
- A promise that will be fulfilled when the modal has been loaded and the opening
370
- animation has completed.
371
- @stable
372
- ###
373
- visitAsap = (url, options) ->
374
- options = u.options(options)
375
- options.url = url
376
- openAsap(options)
377
-
378
- ###**
379
- [Extracts](/up.extract) the given CSS selector from the given HTML string and
380
- opens the results in a modal.
381
-
382
- \#\#\# Example
383
-
384
- var html = 'before <div class="content">inner</div> after';
385
- up.modal.extract('.content', html)
386
-
387
- The would open a modal with the following contents:
388
-
389
- <div class="content">inner</div>
390
-
391
- Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
392
-
393
- @function up.modal.extract
394
- @param {string} selector
395
- The CSS selector to extract from the HTML.
396
- @param {string} html
397
- The HTML containing the modal content.
398
- @param {Object} options
399
- See options for [`up.modal.follow()`](/up.modal.follow).
400
- @return {Promise}
401
- A promise that will be fulfilled when the modal has been opened and the opening
402
- animation has completed.
403
- @stable
404
- ###
405
- extractAsap = (selector, html, options) ->
406
- options = u.options(options)
407
- options.html = html
408
- options.history ?= false
409
- options.target = selector
410
- openAsap(options)
411
-
412
- openAsap = (options) ->
413
- chain.asap closeNow, (-> openNow(options))
414
-
415
- openNow = (options) ->
416
- options = u.options(options)
417
- link = u.pluckKey(options, 'link') || e.none()
418
- url = u.pluckKey(options, 'url') ? link.getAttribute('up-href') ? link.getAttribute('href')
419
- html = u.pluckKey(options, 'html')
420
- target = u.pluckKey(options, 'target') ? link.getAttribute('up-modal')
421
- validateTarget(target)
422
- options.flavor ?= link.getAttribute('up-flavor') ? config.flavor
423
- options.position ?= link.getAttribute('up-position') ? flavorDefault('position', options.flavor)
424
- options.position = u.evalOption(options.position, { link })
425
- options.width ?= link.getAttribute('up-width') ? flavorDefault('width', options.flavor)
426
- options.maxWidth ?= link.getAttribute('up-max-width') ? flavorDefault('maxWidth', options.flavor)
427
- options.height ?= link.getAttribute('up-height') ? flavorDefault('height')
428
- options.animation ?= link.getAttribute('up-animation') ? flavorDefault('openAnimation', options.flavor)
429
- options.animation = u.evalOption(options.animation, position: options.position)
430
- options.backdropAnimation ?= link.getAttribute('up-backdrop-animation') ? flavorDefault('backdropOpenAnimation', options.flavor)
431
- options.backdropAnimation = u.evalOption(options.backdropAnimation, position: options.position)
432
- options.sticky ?= e.booleanAttr(link, 'up-sticky') ? flavorDefault('sticky', options.flavor)
433
- options.closable ?= e.booleanAttr(link, 'up-closable') ? flavorDefault('closable', options.flavor)
434
- options.confirm ?= link.getAttribute('up-confirm')
435
- options.method = up.link.followMethod(link, options)
436
- options.layer = 'modal'
437
- options.failTarget ?= link.getAttribute('up-fail-target')
438
- options.failLayer ?= link.getAttribute('up-fail-layer') ? 'auto'
439
-
440
- animateOptions = up.motion.animateOptions(options, link, duration: flavorDefault('openDuration', options.flavor), easing: flavorDefault('openEasing', options.flavor))
441
-
442
- # Although we usually fall back to full page loads if a browser doesn't support pushState,
443
- # in the case of modals we assume that the developer would rather see a dialog
444
- # without an URL update.
445
- options.history ?= e.booleanOrStringAttr(link, 'up-history') ? flavorDefault('history', options.flavor)
446
- options.history = false unless up.browser.canPushState()
447
-
448
- # This will prevent up.replace() from looking for fallbacks, since
449
- # it knows the target will always exist.
450
- options.provideTarget = -> createHiddenFrame(target, options)
451
-
452
- if options.preload
453
- return up.replace(target, url, options)
454
-
455
- up.browser.whenConfirmed(options).then ->
456
- up.event.whenEmitted('up:modal:open', url: url, log: 'Opening modal').then ->
457
- state.phase = 'opening'
458
- state.flavor = options.flavor
459
- state.sticky = options.sticky
460
- state.closable = options.closable
461
- state.position = options.position
462
- if options.history
463
- state.coveredUrl = up.browser.url()
464
- state.coveredTitle = document.title
465
- extractOptions = u.merge(options, animation: false)
466
- if html
467
- promise = up.extract(target, html, extractOptions)
468
- else
469
- promise = up.replace(target, url, extractOptions)
470
- promise = promise.then ->
471
- bodyShifter.shift()
472
- unveilFrame()
473
- animate(options.animation, options.backdropAnimation, animateOptions)
474
- promise = promise.then ->
475
- state.phase = 'opened'
476
- up.emit('up:modal:opened', log: 'Modal opened')
477
- promise
478
-
479
- validateTarget = (target) ->
480
- if u.isBlank(target)
481
- up.fail('Cannot open a modal without a target selector')
482
- else if target == 'body'
483
- up.fail('Cannot open the <body> in a modal')
484
-
485
- ###**
486
- This event is [emitted](/up.emit) when a modal dialog is starting to open.
487
-
488
- @event up:modal:open
489
- @param event.preventDefault()
490
- Event listeners may call this method to prevent the modal from opening.
491
- @stable
492
- ###
493
-
494
- ###**
495
- This event is [emitted](/up.emit) when a modal dialog has finished opening.
496
-
497
- @event up:modal:opened
498
- @stable
499
- ###
500
-
501
- ###**
502
- Closes a currently opened modal overlay.
503
-
504
- Does nothing if no modal is currently open.
505
-
506
- Emits events [`up:modal:close`](/up:modal:close) and [`up:modal:closed`](/up:modal:closed).
507
-
508
- @function up.modal.close
509
- @param {Object} options
510
- See options for [`up.animate()`](/up.animate)
511
- @return {Promise}
512
- A promise that will be fulfilled once the modal's close
513
- animation has finished.
514
- @stable
515
- ###
516
- closeAsap = (options) ->
517
- chain.asap -> closeNow(options)
518
-
519
- closeNow = (options) ->
520
- options = u.options(options)
521
-
522
- unless isOpen()
523
- return Promise.resolve()
524
-
525
- viewportCloseAnimation = options.animation ? flavorDefault('closeAnimation')
526
- viewportCloseAnimation = u.evalOption(viewportCloseAnimation, position: state.position)
527
- backdropCloseAnimation = options.backdropAnimation ? flavorDefault('backdropCloseAnimation')
528
- backdropCloseAnimation = u.evalOption(backdropCloseAnimation, position: state.position)
529
- animateOptions = up.motion.animateOptions(options, duration: flavorDefault('closeDuration'), easing: flavorDefault('closeEasing'))
530
-
531
- destroyOptions = u.options(
532
- u.except(options, 'animation', 'duration', 'easing', 'delay'),
533
- history: state.coveredUrl,
534
- title: state.coveredTitle
535
- )
536
-
537
- up.event.whenEmitted(state.modalElement, 'up:modal:close', log: 'Closing modal').then ->
538
- state.phase = 'closing'
539
- # the current URL must be deleted *before* calling up.destroy,
540
- # since up.feedback listens to up:fragment:destroyed and then
541
- # re-assigns .up-current classes.
542
- state.url = null
543
- state.coveredUrl = null
544
- state.coveredTitle = null
545
-
546
- promise = animate(viewportCloseAnimation, backdropCloseAnimation, animateOptions)
547
-
548
- promise = promise.then ->
549
- up.destroy(state.modalElement, destroyOptions)
550
-
551
- promise = promise.then ->
552
- bodyShifter.unshift()
553
- state.phase = 'closed'
554
- state.modalElement = null
555
- state.flavor = null
556
- state.sticky = null
557
- state.closable = null
558
- state.position = null
559
- up.emit('up:modal:closed', log: 'Modal closed')
560
-
561
- promise
562
-
563
- markAsAnimating = (isAnimating = true) ->
564
- e.toggleClass(state.modalElement, 'up-modal-animating', isAnimating)
565
-
566
- animate = (viewportAnimation, backdropAnimation, animateOptions) ->
567
- # If we're not animating the dialog, don't animate the backdrop either
568
- if up.motion.isNone(viewportAnimation)
569
- Promise.resolve()
570
- else
571
- markAsAnimating()
572
-
573
- promise = Promise.all([
574
- up.animate(part('viewport'), viewportAnimation, animateOptions),
575
- up.animate(part('backdrop'), backdropAnimation, animateOptions)
576
- ])
577
- promise = promise.then -> markAsAnimating(false)
578
- promise
579
-
580
- ###**
581
- This event is [emitted](/up.emit) when a modal dialog
582
- is starting to [close](/up.modal.close).
583
-
584
- @event up:modal:close
585
- @param event.preventDefault()
586
- Event listeners may call this method to prevent the modal from closing.
587
- @stable
588
- ###
589
-
590
- ###**
591
- This event is [emitted](/up.emit) when a modal dialog
592
- is done [closing](/up.modal.close).
593
-
594
- @event up:modal:closed
595
- @stable
596
- ###
597
-
598
- autoclose = ->
599
- unless state.sticky
600
- discardHistory()
601
- closeAsap()
602
-
603
- ###**
604
- Returns whether the given element or selector is contained
605
- within the current modal.
606
-
607
- @function up.modal.contains
608
- @param {string} elementOrSelector
609
- The element to test
610
- @return {boolean}
611
- @stable
612
- ###
613
- contains = (elementOrSelector) ->
614
- element = e.get(elementOrSelector)
615
- !!e.closest(element, '.up-modal')
616
-
617
- flavor = (name, overrideConfig = {}) ->
618
- up.legacy.warn('up.modal.flavor() is deprecated. Use the up.modal.flavors property instead.')
619
- u.assign(flavorOverrides(name), overrideConfig)
620
-
621
- ###**
622
- Returns a config object for the given flavor.
623
- Properties in that config should be preferred to the defaults in
624
- [`/up.modal.config`](/up.modal.config).
625
-
626
- @function flavorOverrides
627
- @internal
628
- ###
629
- flavorOverrides = (flavor) ->
630
- flavors[flavor] ||= {}
631
-
632
- ###**
633
- Returns the config option for the current flavor.
634
-
635
- @function flavorDefault
636
- @internal
637
- ###
638
- flavorDefault = (key, flavorName = state.flavor) ->
639
- value = flavorOverrides(flavorName)[key] if flavorName
640
- value = config[key] if u.isMissing(value)
641
- value
642
-
643
- ###**
644
- Clicking this link will load the destination via AJAX and open
645
- the given selector in a modal dialog.
646
-
647
- \#\#\# Example
648
-
649
- <a href="/blogs" up-modal=".blog-list">Switch blog</a>
650
-
651
- Clicking would request the path `/blog` and select `.blog-list` from
652
- the HTML response. Unpoly will dim the page
653
- and place the matching `.blog-list` tag in
654
- a modal dialog.
655
-
656
- @selector a[up-modal]
657
- @param {string} up-modal
658
- The CSS selector that will be extracted from the response and displayed in a modal dialog.
659
- @param {string} [up-confirm]
660
- A message that will be displayed in a cancelable confirmation dialog
661
- before the modal is opened.
662
- @param {string} [up-method='GET']
663
- Override the request method.
664
- @param {string} [up-sticky]
665
- If set to `"true"`, the modal remains
666
- open even if the page changes in the background.
667
- @param {boolean} [up-closable]
668
- When `true`, the modal will render a close icon and close when the user
669
- clicks on the backdrop or presses Escape.
670
-
671
- When `false`, you need to either supply an element with `[up-close]` or
672
- close the modal manually with `up.modal.close()`.
673
- @param {string} [up-animation]
674
- The animation to use when opening the viewport containing the dialog.
675
- @param {string} [up-backdrop-animation]
676
- The animation to use when opening the backdrop that dims the page below the dialog.
677
- @param {string} [up-height]
678
- The width of the dialog in pixels.
679
- By [default](/up.modal.config) the dialog will grow to fit its contents.
680
- @param {string} [up-width]
681
- The width of the dialog in pixels.
682
- By [default](/up.modal.config) the dialog will grow to fit its contents.
683
- @param {string} [up-history]
684
- Whether to push an entry to the browser history for the modal's source URL.
685
-
686
- Set this to `'false'` to prevent the URL bar from being updated.
687
- Set this to a URL string to update the history with the given URL.
688
-
689
- @stable
690
- ###
691
- up.link.addFollowVariant '[up-modal]',
692
- # Don't just pass the `follow` function reference so we can stub it in tests
693
- follow: (link, options) -> followAsap(link, options)
694
- preload: (link, options) -> preloadNow(link, options)
695
-
696
- # Close the modal when someone clicks outside the dialog (but not on a modal opener).
697
- # We register the event on .up-modal, which covers the *entire* viewport, not just
698
- # the dialog area.
699
- #
700
- # Note that we cannot listen to clicks on .up-modal-backdrop, which is a sister element
701
- # of .up-modal-viewport. Since the user will effectively click on the viewport, not
702
- # the backdrop, backdrop will not receive a bubbling event.
703
- up.on('click', '.up-modal', (event) ->
704
- return unless state.closable
705
-
706
- target = event.target
707
- unless e.closest(target, '.up-modal-dialog') || e.closest(target, '[up-modal]')
708
- up.event.consumeAction(event)
709
- u.muteRejection closeAsap()
710
- )
711
-
712
- up.on('up:fragment:inserted', (event, fragment) ->
713
- if contains(fragment)
714
- if newSource = fragment.getAttribute('up-source')
715
- state.url = newSource
716
- else if event.origin && contains(event.origin) && !up.popup.contains(fragment)
717
- u.muteRejection autoclose()
718
- )
719
-
720
- # Close the pop-up overlay when the user presses ESC.
721
- up.event.onEscape ->
722
- if state.closable
723
- u.muteRejection closeAsap()
724
-
725
- ###**
726
- When this element is clicked, closes a currently open dialog.
727
-
728
- Does nothing if no modal is currently open.
729
-
730
- To make a link that closes the current modal, but follows to
731
- a fallback destination if no modal is open:
732
-
733
- <a href="/fallback" up-close>Okay</a>
734
-
735
- @selector .up-modal [up-close]
736
- @stable
737
- ###
738
- up.on('click', '.up-modal [up-close]', (event) ->
739
- u.muteRejection closeAsap()
740
- # If the user closes the modal by clicking on the background, we want to halt the event chain here.
741
- # The event should not trigger anything else. The user needs to click again for another interaction.
742
- # Also only prevent the default when we actually closed a modal.
743
- # This way we can have buttons that close a modal when within a modal, but link to a destination if not.
744
- up.event.consumeAction(event)
745
- )
746
-
747
- ###**
748
- Clicking this link will load the destination via AJAX and open
749
- the given selector in a modal drawer that slides in from the edge of the screen.
750
-
751
- You can configure drawers using the [`up.modal.flavors.drawer`](/up.modal.flavors.drawer) property.
752
-
753
- \#\#\# Example
754
-
755
- <a href="/blogs" up-drawer=".blog-list">Switch blog</a>
756
-
757
- Clicking would request the path `/blog` and select `.blog-list` from
758
- the HTML response. Unpoly will dim the page
759
- and place the matching `.blog-list` tag will be placed in
760
- a modal drawer.
761
-
762
- @selector a[up-drawer]
763
- @param {string} up-drawer
764
- The CSS selector to extract from the response and open in the drawer.
765
- @param {string} [up-position='auto']
766
- The side from which the drawer slides in.
767
-
768
- Valid values are `'left'`, `'right'` and `'auto'`. If set to `'auto'`, the
769
- drawer will slide in from left if the opening link is on the left half of the screen.
770
- Otherwise it will slide in from the right.
771
- @stable
772
- ###
773
- up.macro 'a[up-drawer], [up-href][up-drawer]', (link) ->
774
- target = link.getAttribute('up-drawer')
775
- e.setAttrs link,
776
- 'up-modal': target
777
- 'up-flavor': 'drawer'
778
-
779
- ###**
780
- Sets default options for future drawers.
781
-
782
- @property up.modal.flavors.drawer
783
- @param {Object} config
784
- Default options for future drawers.
785
-
786
- See [`up.modal.config`](/up.modal.config) for available options.
787
- @experimental
788
- ###
789
- flavors.drawer =
790
- openAnimation: (options) ->
791
- switch options.position
792
- when 'left' then 'move-from-left'
793
- when 'right' then 'move-from-right'
794
- closeAnimation: (options) ->
795
- switch options.position
796
- when 'left' then 'move-to-left'
797
- when 'right' then 'move-to-right'
798
- position: (options) ->
799
- if u.isPresent(options.link)
800
- u.horizontalScreenHalf(options.link)
801
- else
802
- # In case the drawer was opened programmatically through Javascript,
803
- # we might now know the link that was clicked on.
804
- 'left'
805
-
806
- # When the user uses the back button we will usually restore <body> or a base container.
807
- # We close any open modal because it probably won't match the restored state.
808
- up.on 'up:history:restore', ->
809
- u.muteRejection closeAsap()
810
-
811
- # The framework is reset between tests
812
- up.on 'up:framework:reset', reset
813
-
814
- <% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
815
- visit: visitAsap
816
- follow: followAsap
817
- extract: extractAsap
818
- close: closeAsap
819
- url: -> state.url
820
- coveredUrl: -> state.coveredUrl
821
- config: config
822
- flavors: flavors
823
- contains: contains
824
- isOpen: isOpen
825
- flavor: flavor # deprecated