unpoly-rails 0.61.0 → 2.0.0.pre.rc3

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

Potentially problematic release.


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

Files changed (340) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +94 -1
  4. data/README.md +3 -11
  5. data/README_RAILS.md +295 -14
  6. data/dist/unpoly-bootstrap3.css +9 -14
  7. data/dist/unpoly-bootstrap3.js +4 -18
  8. data/dist/unpoly-bootstrap3.min.css +1 -1
  9. data/dist/unpoly-bootstrap3.min.js +1 -1
  10. data/dist/unpoly-bootstrap4.css +9 -0
  11. data/dist/unpoly-bootstrap4.js +16 -0
  12. data/dist/unpoly-bootstrap4.min.css +1 -0
  13. data/dist/unpoly-bootstrap4.min.js +1 -0
  14. data/dist/unpoly-bootstrap5.css +9 -0
  15. data/dist/unpoly-bootstrap5.js +14 -0
  16. data/dist/unpoly-bootstrap5.min.css +1 -0
  17. data/dist/unpoly-bootstrap5.min.js +1 -0
  18. data/dist/unpoly-migrate.js +1213 -0
  19. data/dist/unpoly-migrate.min.js +1 -0
  20. data/dist/unpoly.css +109 -140
  21. data/dist/unpoly.js +15439 -10434
  22. data/dist/unpoly.min.css +1 -1
  23. data/dist/unpoly.min.js +6 -4
  24. data/lib/unpoly-rails.rb +9 -3
  25. data/lib/unpoly/rails/change.rb +372 -0
  26. data/lib/unpoly/rails/change/cache.rb +26 -0
  27. data/lib/unpoly/rails/change/context.rb +80 -0
  28. data/lib/unpoly/rails/change/field.rb +117 -0
  29. data/lib/unpoly/rails/change/field_definition.rb +74 -0
  30. data/lib/unpoly/rails/change/layer.rb +60 -0
  31. data/lib/unpoly/rails/controller.rb +47 -0
  32. data/lib/unpoly/rails/error.rb +5 -0
  33. data/lib/unpoly/rails/request_echo_headers.rb +2 -2
  34. data/lib/unpoly/rails/version.rb +1 -1
  35. data/lib/unpoly/tasks.rb +45 -0
  36. metadata +43 -314
  37. data/.gitignore +0 -10
  38. data/.ruby-version +0 -2
  39. data/Gemfile +0 -8
  40. data/Gemfile.lock +0 -45
  41. data/Rakefile +0 -144
  42. data/bower.json +0 -27
  43. data/design/animation-ghosting.txt +0 -72
  44. data/design/design.txt +0 -34
  45. data/design/draft.html.erb +0 -48
  46. data/design/draft.rb +0 -9
  47. data/design/es6.js +0 -32
  48. data/design/ghost-debugging.txt +0 -118
  49. data/design/homepage.txt +0 -236
  50. data/design/ie11.txt +0 -9
  51. data/design/measure_import_node.js +0 -330
  52. data/design/measure_jquery/element_list.js +0 -41
  53. data/design/measure_jquery/up.on_vs_addEventListener.js +0 -56
  54. data/design/positioning.txt +0 -28
  55. data/design/query-params-in-form-actions/cases.html +0 -125
  56. data/design/rename.txt +0 -0
  57. data/design/test_rejected_promise.txt +0 -5
  58. data/design/unpoly errors.txt +0 -19
  59. data/lib/assets/javascripts/unpoly-bootstrap3.coffee +0 -2
  60. data/lib/assets/javascripts/unpoly-bootstrap3/feedback-ext.coffee +0 -5
  61. data/lib/assets/javascripts/unpoly-bootstrap3/form-ext.coffee +0 -1
  62. data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.coffee +0 -14
  63. data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +0 -5
  64. data/lib/assets/javascripts/unpoly.coffee +0 -28
  65. data/lib/assets/javascripts/unpoly/browser.coffee.erb +0 -236
  66. data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +0 -36
  67. data/lib/assets/javascripts/unpoly/classes/cache.coffee +0 -127
  68. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +0 -93
  69. data/lib/assets/javascripts/unpoly/classes/config.coffee +0 -9
  70. data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +0 -118
  71. data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +0 -39
  72. data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +0 -116
  73. data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +0 -86
  74. data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +0 -111
  75. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +0 -80
  76. data/lib/assets/javascripts/unpoly/classes/focus_follower.coffee +0 -29
  77. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +0 -56
  78. data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +0 -46
  79. data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +0 -157
  80. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +0 -543
  81. data/lib/assets/javascripts/unpoly/classes/record.coffee +0 -22
  82. data/lib/assets/javascripts/unpoly/classes/rect.js +0 -21
  83. data/lib/assets/javascripts/unpoly/classes/request.coffee +0 -246
  84. data/lib/assets/javascripts/unpoly/classes/response.coffee +0 -157
  85. data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +0 -102
  86. data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +0 -67
  87. data/lib/assets/javascripts/unpoly/classes/selector.coffee +0 -60
  88. data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +0 -26
  89. data/lib/assets/javascripts/unpoly/classes/store/session.coffee +0 -59
  90. data/lib/assets/javascripts/unpoly/classes/tether.coffee +0 -105
  91. data/lib/assets/javascripts/unpoly/classes/url_set.coffee +0 -32
  92. data/lib/assets/javascripts/unpoly/cookie.coffee +0 -56
  93. data/lib/assets/javascripts/unpoly/element.coffee.erb +0 -1126
  94. data/lib/assets/javascripts/unpoly/event.coffee.erb +0 -438
  95. data/lib/assets/javascripts/unpoly/feedback.coffee +0 -353
  96. data/lib/assets/javascripts/unpoly/form.coffee.erb +0 -1032
  97. data/lib/assets/javascripts/unpoly/fragment.coffee.erb +0 -924
  98. data/lib/assets/javascripts/unpoly/framework.coffee +0 -67
  99. data/lib/assets/javascripts/unpoly/history.coffee +0 -268
  100. data/lib/assets/javascripts/unpoly/legacy.coffee +0 -60
  101. data/lib/assets/javascripts/unpoly/link.coffee.erb +0 -622
  102. data/lib/assets/javascripts/unpoly/log.coffee +0 -248
  103. data/lib/assets/javascripts/unpoly/modal.coffee.erb +0 -825
  104. data/lib/assets/javascripts/unpoly/motion.coffee.erb +0 -668
  105. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
  106. data/lib/assets/javascripts/unpoly/popup.coffee.erb +0 -515
  107. data/lib/assets/javascripts/unpoly/protocol.coffee +0 -298
  108. data/lib/assets/javascripts/unpoly/proxy.coffee +0 -672
  109. data/lib/assets/javascripts/unpoly/radio.coffee +0 -60
  110. data/lib/assets/javascripts/unpoly/rails.coffee +0 -24
  111. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +0 -477
  112. data/lib/assets/javascripts/unpoly/toast.coffee +0 -67
  113. data/lib/assets/javascripts/unpoly/tooltip.coffee +0 -276
  114. data/lib/assets/javascripts/unpoly/util.coffee.erb +0 -1676
  115. data/lib/assets/javascripts/unpoly/viewport.coffee.erb +0 -806
  116. data/lib/assets/stylesheets/unpoly-bootstrap3.sass +0 -1
  117. data/lib/assets/stylesheets/unpoly-bootstrap3/modal-ext.sass +0 -27
  118. data/lib/assets/stylesheets/unpoly.sass +0 -1
  119. data/lib/assets/stylesheets/unpoly/close.sass +0 -2
  120. data/lib/assets/stylesheets/unpoly/dom.sass +0 -5
  121. data/lib/assets/stylesheets/unpoly/layout.sass +0 -2
  122. data/lib/assets/stylesheets/unpoly/link.sass +0 -2
  123. data/lib/assets/stylesheets/unpoly/modal.sass +0 -116
  124. data/lib/assets/stylesheets/unpoly/popup.sass +0 -7
  125. data/lib/assets/stylesheets/unpoly/toast.sass +0 -33
  126. data/lib/assets/stylesheets/unpoly/tooltip.sass +0 -62
  127. data/lib/unpoly/rails/inspector.rb +0 -149
  128. data/lib/unpoly/rails/inspector_accessor.rb +0 -30
  129. data/package.json +0 -38
  130. data/spec_app/.firefox-version +0 -1
  131. data/spec_app/.gitignore +0 -17
  132. data/spec_app/.rspec +0 -2
  133. data/spec_app/Gemfile +0 -32
  134. data/spec_app/Gemfile.lock +0 -233
  135. data/spec_app/README.rdoc +0 -28
  136. data/spec_app/Rakefile +0 -6
  137. data/spec_app/app/assets/images/.keep +0 -0
  138. data/spec_app/app/assets/images/favicon.png +0 -0
  139. data/spec_app/app/assets/images/grid.png +0 -0
  140. data/spec_app/app/assets/javascripts/bootstrap_manifest.coffee +0 -6
  141. data/spec_app/app/assets/javascripts/integration_test.coffee +0 -6
  142. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +0 -6
  143. data/spec_app/app/assets/stylesheets/_helpers.sass +0 -5
  144. data/spec_app/app/assets/stylesheets/bootstrap_manifest.sass +0 -2
  145. data/spec_app/app/assets/stylesheets/integration_test.sass +0 -88
  146. data/spec_app/app/assets/stylesheets/jasmine_specs.sass +0 -20
  147. data/spec_app/app/controllers/application_controller.rb +0 -14
  148. data/spec_app/app/controllers/binding_test_controller.rb +0 -51
  149. data/spec_app/app/controllers/compiler_test_controller.rb +0 -5
  150. data/spec_app/app/controllers/css_test_controller.rb +0 -5
  151. data/spec_app/app/controllers/error_test_controller.rb +0 -5
  152. data/spec_app/app/controllers/form_test/basics_controller.rb +0 -14
  153. data/spec_app/app/controllers/form_test/redirects_controller.rb +0 -17
  154. data/spec_app/app/controllers/form_test/uploads_controller.rb +0 -15
  155. data/spec_app/app/controllers/hash_test_controller.rb +0 -5
  156. data/spec_app/app/controllers/method_test_controller.rb +0 -16
  157. data/spec_app/app/controllers/motion_test_controller.rb +0 -5
  158. data/spec_app/app/controllers/pages_controller.rb +0 -9
  159. data/spec_app/app/controllers/replace_test_controller.rb +0 -5
  160. data/spec_app/app/controllers/reveal_test_controller.rb +0 -5
  161. data/spec_app/app/controllers/scroll_test_controller.rb +0 -5
  162. data/spec_app/app/helpers/application_helper.rb +0 -2
  163. data/spec_app/app/mailers/.keep +0 -0
  164. data/spec_app/app/models/concerns/.keep +0 -0
  165. data/spec_app/app/views/compiler_test/timestamp.erb +0 -9
  166. data/spec_app/app/views/css_test/modal.erb +0 -47
  167. data/spec_app/app/views/css_test/modal_contents.erb +0 -5
  168. data/spec_app/app/views/css_test/modal_contents_wide.erb +0 -5
  169. data/spec_app/app/views/css_test/popup.erb +0 -81
  170. data/spec_app/app/views/css_test/popup_contents.erb +0 -5
  171. data/spec_app/app/views/css_test/tooltip.erb +0 -48
  172. data/spec_app/app/views/error_test/trigger.erb +0 -80
  173. data/spec_app/app/views/error_test/unexpected_response.erb +0 -3
  174. data/spec_app/app/views/form_test/basics/new.erb +0 -60
  175. data/spec_app/app/views/form_test/redirects/new.erb +0 -27
  176. data/spec_app/app/views/form_test/redirects/target.erb +0 -4
  177. data/spec_app/app/views/form_test/submission_result.erb +0 -30
  178. data/spec_app/app/views/form_test/uploads/new.erb +0 -44
  179. data/spec_app/app/views/hash_test/unpoly.erb +0 -30
  180. data/spec_app/app/views/hash_test/vanilla.erb +0 -13
  181. data/spec_app/app/views/layouts/integration_test.erb +0 -22
  182. data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +0 -20
  183. data/spec_app/app/views/method_test/form_target.erb +0 -17
  184. data/spec_app/app/views/method_test/page1.erb +0 -11
  185. data/spec_app/app/views/method_test/page2.erb +0 -6
  186. data/spec_app/app/views/motion_test/animations.erb +0 -16
  187. data/spec_app/app/views/motion_test/transitions.erb +0 -13
  188. data/spec_app/app/views/pages/start.erb +0 -79
  189. data/spec_app/app/views/replace_test/_nav.erb +0 -6
  190. data/spec_app/app/views/replace_test/page1.erb +0 -14
  191. data/spec_app/app/views/replace_test/page2.erb +0 -14
  192. data/spec_app/app/views/replace_test/table.erb +0 -16
  193. data/spec_app/app/views/reveal_test/long1.erb +0 -17
  194. data/spec_app/app/views/reveal_test/long2.erb +0 -17
  195. data/spec_app/app/views/reveal_test/within_document_viewport.erb +0 -24
  196. data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +0 -28
  197. data/spec_app/app/views/scroll_test/long1.erb +0 -30
  198. data/spec_app/bin/bundle +0 -3
  199. data/spec_app/bin/rails +0 -8
  200. data/spec_app/bin/rake +0 -8
  201. data/spec_app/bin/setup +0 -29
  202. data/spec_app/bin/spring +0 -18
  203. data/spec_app/config.ru +0 -4
  204. data/spec_app/config/application.rb +0 -28
  205. data/spec_app/config/boot.rb +0 -3
  206. data/spec_app/config/database.yml +0 -25
  207. data/spec_app/config/environment.rb +0 -5
  208. data/spec_app/config/environments/development.rb +0 -41
  209. data/spec_app/config/environments/production.rb +0 -79
  210. data/spec_app/config/environments/test.rb +0 -42
  211. data/spec_app/config/initializers/assets.rb +0 -19
  212. data/spec_app/config/initializers/backtrace_silencers.rb +0 -7
  213. data/spec_app/config/initializers/bower_rails.rb +0 -16
  214. data/spec_app/config/initializers/cookies_serializer.rb +0 -3
  215. data/spec_app/config/initializers/filter_parameter_logging.rb +0 -4
  216. data/spec_app/config/initializers/inflections.rb +0 -16
  217. data/spec_app/config/initializers/mime_types.rb +0 -4
  218. data/spec_app/config/initializers/session_store.rb +0 -3
  219. data/spec_app/config/initializers/wrap_parameters.rb +0 -14
  220. data/spec_app/config/locales/en.yml +0 -23
  221. data/spec_app/config/routes.rb +0 -30
  222. data/spec_app/config/secrets.yml +0 -22
  223. data/spec_app/db/schema.rb +0 -23
  224. data/spec_app/db/seeds.rb +0 -7
  225. data/spec_app/lib/assets/.keep +0 -0
  226. data/spec_app/lib/tasks/.keep +0 -0
  227. data/spec_app/lib/tasks/cucumber.rake +0 -65
  228. data/spec_app/log/.keep +0 -0
  229. data/spec_app/public/404.html +0 -67
  230. data/spec_app/public/422.html +0 -67
  231. data/spec_app/public/500.html +0 -66
  232. data/spec_app/public/favicon.ico +0 -0
  233. data/spec_app/public/robots.txt +0 -5
  234. data/spec_app/script/cucumber +0 -10
  235. data/spec_app/spec/controllers/binding_test_controller_spec.rb +0 -248
  236. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +0 -20
  237. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +0 -103
  238. data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +0 -21
  239. data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +0 -2
  240. data/spec_app/spec/javascripts/helpers/fixture.js.coffee +0 -25
  241. data/spec_app/spec/javascripts/helpers/index.js.coffee +0 -1
  242. data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +0 -1
  243. data/spec_app/spec/javascripts/helpers/knife.js.coffee +0 -69
  244. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +0 -25
  245. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +0 -8
  246. data/spec_app/spec/javascripts/helpers/mock_clock.js.coffee +0 -2
  247. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +0 -24
  248. data/spec_app/spec/javascripts/helpers/promise_state.js +0 -18
  249. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +0 -12
  250. data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +0 -8
  251. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +0 -23
  252. data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +0 -2
  253. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +0 -25
  254. data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +0 -5
  255. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +0 -12
  256. data/spec_app/spec/javascripts/helpers/spec_util.coffee +0 -47
  257. data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +0 -8
  258. data/spec_app/spec/javascripts/helpers/to_be_array.coffee +0 -5
  259. data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +0 -9
  260. data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +0 -8
  261. data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +0 -9
  262. data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +0 -8
  263. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +0 -8
  264. data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +0 -8
  265. data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +0 -8
  266. data/spec_app/spec/javascripts/helpers/to_be_jquery.js.coffee +0 -5
  267. data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +0 -8
  268. data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +0 -8
  269. data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +0 -11
  270. data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +0 -9
  271. data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +0 -8
  272. data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +0 -11
  273. data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +0 -8
  274. data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +0 -7
  275. data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +0 -7
  276. data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +0 -10
  277. data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +0 -10
  278. data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +0 -8
  279. data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +0 -15
  280. data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +0 -8
  281. data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +0 -16
  282. data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +0 -9
  283. data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -18
  284. data/spec_app/spec/javascripts/helpers/to_match_list.coffee +0 -14
  285. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +0 -8
  286. data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +0 -13
  287. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +0 -14
  288. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +0 -200
  289. data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +0 -5
  290. data/spec_app/spec/javascripts/support/jasmine.yml +0 -51
  291. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +0 -150
  292. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +0 -82
  293. data/spec_app/spec/javascripts/up/classes/config_spec.coffee +0 -24
  294. data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +0 -45
  295. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +0 -34
  296. data/spec_app/spec/javascripts/up/classes/params_spec.coffee +0 -557
  297. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +0 -50
  298. data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +0 -51
  299. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +0 -70
  300. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +0 -114
  301. data/spec_app/spec/javascripts/up/element_spec.coffee +0 -897
  302. data/spec_app/spec/javascripts/up/event_spec.js.coffee +0 -530
  303. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +0 -401
  304. data/spec_app/spec/javascripts/up/form_spec.js.coffee +0 -1488
  305. data/spec_app/spec/javascripts/up/fragment_spec.js.coffee +0 -2589
  306. data/spec_app/spec/javascripts/up/history_spec.js.coffee +0 -340
  307. data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +0 -4
  308. data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +0 -27
  309. data/spec_app/spec/javascripts/up/link_spec.js.coffee +0 -1093
  310. data/spec_app/spec/javascripts/up/log_spec.js.coffee +0 -119
  311. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +0 -917
  312. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +0 -582
  313. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +0 -507
  314. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +0 -39
  315. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +0 -1137
  316. data/spec_app/spec/javascripts/up/radio_spec.js.coffee +0 -212
  317. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +0 -118
  318. data/spec_app/spec/javascripts/up/spec_spec.js.coffee +0 -9
  319. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +0 -304
  320. data/spec_app/spec/javascripts/up/toast_spec.js.coffee +0 -37
  321. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +0 -163
  322. data/spec_app/spec/javascripts/up/util_spec.js.coffee +0 -1420
  323. data/spec_app/spec/javascripts/up/viewport_spec.js.coffee +0 -655
  324. data/spec_app/spec/spec_helper.rb +0 -62
  325. data/spec_app/test/controllers/.keep +0 -0
  326. data/spec_app/test/fixtures/.keep +0 -0
  327. data/spec_app/test/helpers/.keep +0 -0
  328. data/spec_app/test/integration/.keep +0 -0
  329. data/spec_app/test/mailers/.keep +0 -0
  330. data/spec_app/test/models/.keep +0 -0
  331. data/spec_app/test/test_helper.rb +0 -10
  332. data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +0 -1159
  333. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.bower.json +0 -43
  334. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.gitignore +0 -6
  335. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.npmignore +0 -10
  336. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.pairs +0 -6
  337. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.travis.yml +0 -56
  338. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/jasmine-ajax.js +0 -790
  339. data/spec_app/vendor/assets/.keep +0 -0
  340. data/unpoly-rails.gemspec +0 -24
@@ -1,56 +0,0 @@
1
- ####**
2
- #Cookies
3
- #=======
4
- #
5
- #class up.cookies
6
- ####
7
- #up.cookie = (->
8
- # u = up.util
9
- #
10
- # escape = encodeURIComponent
11
- # unescape = decodeURIComponent
12
- #
13
- # lastRaw = undefined
14
- # lastParsed = {}
15
- #
16
- # all = ->
17
- # currentRaw = document.cookie
18
- # if u.isUndefined(lastRaw) || lastRaw != currentRaw
19
- # lastParsed = parse()
20
- # lastRaw = currentRaw
21
- # lastParsed
22
- #
23
- # parse = ->
24
- # hash = {}
25
- # pairs = u.splitValues(document.cookie, ';')
26
- # for pair in pairs
27
- # parts = u.splitValues(pair, '=')
28
- # name = unescape(parts[0])
29
- # value = unescape(parts[1])
30
- # hash[name] = value
31
- # hash
32
- #
33
- # remove = (name) ->
34
- # set(name, '', 'expires=Thu, 01-Jan-70 00:00:01 GMT; path=/')
35
- #
36
- # get = (name) ->
37
- # all()[name]
38
- #
39
- # set = (name, value, meta) ->
40
- # str = escape(name) + '=' + escape(value)
41
- # str += ';' + meta if meta
42
- # document.cookie = str
43
- # lastRaw = undefined
44
- #
45
- # pop = (name) ->
46
- # value = get(name)
47
- # if u.isPresent(value)
48
- # remove(name)
49
- # value
50
- #
51
- # all: all
52
- # get: get
53
- # set: set
54
- # remove: remove
55
- # pop: pop
56
- #)()
@@ -1,1126 +0,0 @@
1
- #= require ./classes/selector
2
-
3
- ###**
4
- DOM helpers
5
- ===========
6
-
7
- The `up.element` module offers functions for DOM manipulation and traversal.
8
-
9
- It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_obj_all.asp) and works across all [supported browsers](/up.browser).
10
-
11
- @module up.element
12
- ###
13
- up.element = do ->
14
-
15
- u = up.util
16
-
17
- ###**
18
- Returns a null-object that mostly behaves like an `Element`.
19
-
20
- @function up.element.none()
21
- @internal
22
- ###
23
- NONE = { getAttribute: -> undefined }
24
-
25
- ###**
26
- Matches all elements that have a descendant matching the given selector.
27
-
28
- \#\#\# Example
29
-
30
- `up.element.all('div:has(span)')` matches all `<div>` elements with at least one `<span>` among its descendants:
31
-
32
- ```html
33
- <div>
34
- <span>Will be matched</span>
35
- </div>
36
- <div>
37
- Will NOT be matched
38
- </div>
39
- <div>
40
- <span>Will be matched</span>
41
- </div>
42
- ```
43
-
44
- \#\#\# Compatibility
45
-
46
- `:has()` is supported by all Unpoly functions (like `up.element.all()`) and
47
- selectors (like `a[up-target]`).
48
-
49
- As a [level 4 CSS selector](https://drafts.csswg.org/selectors-4/#relational),
50
- `:has()` [has yet to be implemented](https://caniuse.com/#feat=css-has)
51
- in native browser functions like [`document.querySelectorAll()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll).
52
-
53
- You can also use [`:has()` in jQuery](https://api.jquery.com/has-selector/).
54
-
55
- @selector :has()
56
- @experimental
57
- ###
58
-
59
- parseSelector = (selector) ->
60
- up.Selector.parse(selector)
61
-
62
- ###**
63
- Returns the first descendant element matching the given selector.
64
-
65
- It is similar to [`element.querySelector()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector),
66
- but also supports the [`:has()`](/has) selector.
67
-
68
- @function up.element.first
69
- @param {Element} [parent=document]
70
- The parent element whose descendants to search.
71
-
72
- If omitted, all elements in the `document` will be searched.
73
- @param {string} selector
74
- The CSS selector to match.
75
- @return {Element|undefined|null}
76
- The first element matching the selector.
77
-
78
- Returns `null` or `undefined` if no element macthes.
79
- @experimental
80
- ###
81
- first = (args...) ->
82
- selector = args.pop()
83
- parent = args[0] ? document
84
- parseSelector(selector).descendant(parent)
85
-
86
- ###**
87
- Returns all descendant elements matching the given selector.
88
-
89
- @function up.element.all
90
- @param {Element} [parent=document]
91
- The parent element whose descendants to search.
92
-
93
- If omitted, all elements in the `document` will be searched.
94
- @param {string} selector
95
- The CSS selector to match.
96
- @return {NodeList<Element>|Array<Element>}
97
- A list of all elements matching the selector.
98
-
99
- Returns an empty list if there are no matches.
100
- @experimental
101
- ###
102
- all = (args...) ->
103
- selector = args.pop()
104
- parent = args[0] ? document
105
- parseSelector(selector).descendants(parent)
106
-
107
- ###**
108
- Returns a list of the given parent's descendants matching the given selector.
109
- The list will also include the parent element if it matches the selector itself.
110
-
111
- @function up.element.subtree
112
- @param {Element} parent
113
- The parent element for the search.
114
- @param {string} selector
115
- The CSS selector to match.
116
- @return {NodeList<Element>|Array<Element>}
117
- A list of all matching elements.
118
- @experimental
119
- ###
120
- subtree = (root, selector) ->
121
- parseSelector(selector).subtree(root)
122
-
123
- ###**
124
- Returns the first element that matches the selector by testing the element itself
125
- and traversing up through its ancestors in the DOM tree.
126
-
127
- @function up.element.closest
128
- @param {Element} element
129
- The element on which to start the search.
130
- @param {string}
131
- The CSS selector to match.
132
- @return {Element|null|undefined} element
133
- The matching element.
134
-
135
- Returns `null` or `undefined` if no element matches.
136
- @experimental
137
- ###
138
- closest = (element, selector) ->
139
- parseSelector(selector).closest(element)
140
-
141
- ###**
142
- Returns whether the given element matches the given CSS selector.
143
-
144
- @function up.element.matches
145
- @param {Element} element
146
- The element to check.
147
- @param {string} selector
148
- The CSS selector to match.
149
- @return {boolean}
150
- Whether `element` matches `selector`.
151
- @experimental
152
- ###
153
- matches = (element, selector) ->
154
- parseSelector(selector).matches(element)
155
-
156
- ###**
157
- @function up.element.ancestor
158
- @internal
159
- ###
160
- ancestor = (element, selector) ->
161
- parseSelector(selector).ancestor(element)
162
-
163
- ###**
164
- Casts the given value to a native [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element).
165
-
166
- This is useful when working with jQuery values, or to allow callers to pass CSS selectors
167
- instead of elements.
168
-
169
- \#\#\# Casting rules
170
-
171
- - If given an element, returns that element.
172
- - If given a CSS selector string, returns the [first element matching](/up.element.first) that selector.
173
- - If given a jQuery collection , returns the first element in the collection.
174
- Throws an error if the collection contains more than one element.
175
- - If given any other argument (`undefined`, `null`, `document`, `window`…), returns the argument unchanged.
176
-
177
- @function up.element.get
178
- @param {Element|jQuery|string} value
179
- The value to cast.
180
- @return {Element}
181
- The obtained `Element`.
182
- @experimental
183
- ###
184
- getOne = (value) ->
185
- if u.isElement(value) # Return an element before we run any other expensive checks
186
- value
187
- else if u.isString(value)
188
- first(value)
189
- else if u.isJQuery(value)
190
- if value.length > 1
191
- up.fail('up.element.get(): Cannot cast multiple elements (%o) to a single element', value)
192
- value[0]
193
- else
194
- # undefined, null, Window, Document, DocumentFragment, ...
195
- value
196
-
197
- ###**
198
- Composes a list of elements from the given arguments.
199
-
200
- \#\#\# Casting rules
201
-
202
- - If given a string, returns the all elements matching that string.
203
- - If given any other argument, returns the argument [wrapped as a list](/up.util.wrapList).
204
-
205
- \#\#\# Example
206
-
207
- ```javascript
208
- $jquery = $('.jquery') // returns jQuery (2) [div.jquery, div.jquery]
209
- nodeList = document.querySelectorAll('.node') // returns NodeList (2) [div.node, div.node]
210
- element = document.querySelector('.element') // returns Element div.element
211
- selector = '.selector' // returns String '.selector'
212
-
213
- elements = up.element.list($jquery, nodeList, undefined, element, selector)
214
- // returns [div.jquery, div.jquery, div.node, div.node, div.element, div.selector]
215
- ```
216
-
217
- @function up.element.list
218
- @param {Array<jQuery|Element|Array<Element>|String|undefined|null>} ...args
219
- @return {Array<Element>}
220
- @internal
221
- ###
222
- getList = (args...) ->
223
- u.flatMap args, valueToList
224
-
225
- valueToList = (value) ->
226
- if u.isString(value)
227
- all(value)
228
- else
229
- u.wrapList(value)
230
-
231
- # assertIsElement = (element) ->
232
- # unless u.isElement(element)
233
- # up.fail('Not an element: %o', element)
234
-
235
- ###**
236
- Removes the given element from the DOM tree.
237
-
238
- If you don't need IE11 support you may also use the built-in
239
- [`Element#remove()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove) to the same effect.
240
-
241
- @function up.element.remove
242
- @param {Element} element
243
- The element to remove.
244
- @experimental
245
- ###
246
- remove = (element) ->
247
- if element.remove
248
- element.remove()
249
- # IE does not support Element#remove()
250
- else if parent = element.parentNode
251
- parent.removeChild(element)
252
-
253
- ###**
254
- Hides the given element.
255
-
256
- The element is hidden by setting an [inline style](https://www.codecademy.com/articles/html-inline-styles)
257
- of `{ display: none }`.
258
-
259
- Also see `up.element.show()`.
260
-
261
- @function up.element.hide
262
- @param {Element} element
263
- @experimental
264
- ###
265
- hide = (element) ->
266
- element.style.display = 'none'
267
-
268
- ###**
269
- Shows the given element.
270
-
271
- Also see `up.element.hide()`.
272
-
273
- \#\#\# Limitations
274
-
275
- The element is shown by setting an [inline style](https://www.codecademy.com/articles/html-inline-styles)
276
- of `{ display: '' }`.
277
-
278
- You might have CSS rules causing the element to remain hidden after calling `up.element.show(element)`.
279
- Unpoly will not handle such cases in order to keep this function performant. As a workaround, you may
280
- manually set the `element.style.display` property. Also see discussion
281
- in jQuery issues [#88](https://github.com/jquery/jquery.com/issues/88),
282
- [#2057](https://github.com/jquery/jquery/issues/2057) and
283
- [this WHATWG mailing list post](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Apr/0094.html).
284
-
285
- @function up.element.show
286
- @experimental
287
- ###
288
- show = (element) ->
289
- element.style.display = ''
290
-
291
- ###**
292
- Display or hide the given element, depending on its current visibility.
293
-
294
- @function up.element.toggle
295
- @param {Element} element
296
- @param {Boolean} [newVisible]
297
- Pass `true` to show the element or `false` to hide it.
298
-
299
- If omitted, the element will be hidden if shown and shown if hidden.
300
- @experimental
301
- ###
302
- toggle = (element, newVisible) ->
303
- newVisible ?= !isVisible(element)
304
- if newVisible
305
- show(element)
306
- else
307
- hide(element)
308
-
309
- # trace = (fn) ->
310
- # (args...) ->
311
- # console.debug("Calling %o with %o", fn, args)
312
- # fn(args...)
313
-
314
- ###**
315
- Adds or removes the given class from the given element.
316
-
317
- If you don't need IE11 support you may also use the built-in
318
- [`Element#classList.toggle(className)`](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList) to the same effect.
319
-
320
- @function up.element.toggleClass
321
- @param {Element} element
322
- The element for which to add or remove the class.
323
- @param {String} className
324
- A boolean value to determine whether the class should be added or removed.
325
- @param {String} state
326
- If omitted, the class will be added if missing and removed if present.
327
- @experimental
328
- ###
329
- toggleClass = (element, klass, newPresent) ->
330
- list = element.classList
331
- newPresent ?= !list.contains(klass)
332
- if newPresent
333
- list.add(klass)
334
- else
335
- list.remove(klass)
336
-
337
- ###**
338
- Sets all key/values from the given object as attributes on the given element.
339
-
340
- \#\#\# Example
341
-
342
- up.element.setAttrs(element, { title: 'Tooltip', tabindex: 1 })
343
-
344
- @function up.element.setAttrs
345
- @param {Element} element
346
- The element on which to set attributes.
347
- @param {object} attributes
348
- An object of attributes to set.
349
- @experimental
350
- ###
351
- setAttrs = (element, attributes) ->
352
- for key, value of attributes
353
- element.setAttribute(key, value)
354
-
355
- ###**
356
- @function up.element.metaContent
357
- @internal
358
- ###
359
- metaContent = (name) ->
360
- selector = "meta" + attributeSelector('name', name)
361
- first(selector)?.getAttribute('content')
362
-
363
- ###**
364
- @function up.element.insertBefore
365
- @internal
366
- ###
367
- insertBefore = (existingElement, newElement) ->
368
- existingElement.insertAdjacentElement('beforebegin', newElement)
369
-
370
- # insertAfter = (existingElement, newElement) ->
371
- # existingElement.insertAdjacentElement('afterend', newElement)
372
-
373
- ###**
374
- Replaces the given old element with the given new element.
375
-
376
- The old element will be removed from the DOM tree.
377
-
378
- If you don't need IE11 support you may also use the built-in
379
- [`Element#replaceWith()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith) to the same effect.
380
-
381
- @function up.element.replace
382
- @param {Element} oldElement
383
- @param {Element} newElement
384
- @experimental
385
- ###
386
- replace = (oldElement, newElement) ->
387
- oldElement.parentElement.replaceChild(newElement, oldElement)
388
-
389
- ###**
390
- Creates an element matching the given CSS selector.
391
-
392
- The created element will not yet be attached to the DOM tree.
393
- Attach it with [`Element#appendChild()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)
394
- or use `up.element.affix()` to create an attached element.
395
-
396
- \#\#\# Examples
397
-
398
- To create an element with a given tag name:
399
-
400
- element = up.element.createFromSelector('span')
401
- // element is <span></span>
402
-
403
- To create an element with a given class:
404
-
405
- element = up.element.createFromSelector('.klass')
406
- // element is <div class="klass"></div>
407
-
408
- To create an element with a given ID:
409
-
410
- element = up.element.createFromSelector('#foo')
411
- // element is <div id="foo"></div>
412
-
413
- To create an element with a given boolean attribute:
414
-
415
- element = up.element.createFromSelector('[attr]')
416
- // element is <div attr></div>
417
-
418
- To create an element with a given attribute value:
419
-
420
- element = up.element.createFromSelector('[attr="value"]')
421
- // element is <div attr="value"></div>
422
-
423
- You may also pass an object of attribute names/values as a second argument:
424
-
425
- element = up.element.createFromSelector('div', { attr: 'value' })
426
- // element is <div attr="value"></div>
427
-
428
- You may set the element's inner text by passing a `{ text }` option:
429
-
430
- element = up.element.createFromSelector('div', { text: 'inner text' })
431
- // element is <div>inner text</div>
432
-
433
- You may set inline styles by passing an object of CSS properties as a second argument:
434
-
435
- element = up.element.createFromSelector('div', { style: { color: 'red' }})
436
- // element is <div style="color: red"></div>
437
-
438
- @function up.element.createFromSelector
439
- @param {string} selector
440
- The CSS selector from which to create an element.
441
- @param {Object} [attrs]
442
- An object of attributes to set on the created element.
443
- @param {Object} [attrs.text]
444
- The [text content](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) of the created element.
445
- @param {Object} [attrs.style]
446
- An object of CSS properties that will be set as the inline style
447
- of the created element.
448
- @return {Element}
449
- The created element.
450
- @experimental
451
- ###
452
- createFromSelector = (selector, attrs) ->
453
- # Extract attribute values before we do anything else.
454
- # Attribute values might contain spaces, and then we would incorrectly
455
- # split depths at that space.
456
- attrValues = []
457
- selectorWithoutAttrValues = selector.replace /\[([\w-]+)(?:=(["'])?([^"'\]]*?)\2)?\]/g, (_match, attrName, _quote, attrValue) ->
458
- attrValues.push(attrValue || '')
459
- "[#{attrName}]"
460
-
461
- depths = selectorWithoutAttrValues.split(/[ >]+/)
462
- rootElement = undefined
463
- depthElement = undefined
464
- previousElement = undefined
465
-
466
- for depthSelector in depths
467
- tagName = undefined
468
-
469
- depthSelector = depthSelector.replace /^[\w-]+/, (match) ->
470
- tagName = match
471
- ''
472
-
473
- depthElement = document.createElement(tagName || 'div')
474
- rootElement ||= depthElement
475
-
476
- depthSelector = depthSelector.replace /\#([\w-]+)/, (_match, id) ->
477
- depthElement.id = id
478
- ''
479
-
480
- depthSelector = depthSelector.replace /\.([\w-]+)/g, (_match, className) ->
481
- depthElement.classList.add(className)
482
- ''
483
-
484
- # If we have stripped out attrValues at the beginning of the function,
485
- # they have been replaced with the attribute name only (as "[name]").
486
- if attrValues.length
487
- depthSelector = depthSelector.replace /\[([\w-]+)\]/g, (_match, attrName) ->
488
- depthElement.setAttribute(attrName, attrValues.shift())
489
- ''
490
-
491
- unless depthSelector == ''
492
- throw new Error('Cannot parse selector: ' + selector)
493
-
494
- previousElement?.appendChild(depthElement)
495
- previousElement = depthElement
496
-
497
- if attrs
498
- if classValue = u.pluckKey(attrs, 'class')
499
- for klass in u.wrapList(classValue)
500
- rootElement.classList.add(klass)
501
- if styleValue = u.pluckKey(attrs, 'style')
502
- setInlineStyle(rootElement, styleValue)
503
- if textValue = u.pluckKey(attrs, 'text')
504
- rootElement.innerText = textValue
505
- setAttrs(rootElement, attrs)
506
-
507
- rootElement
508
-
509
- ###**
510
- Creates an element matching the given CSS selector and attaches it to the given parent element.
511
-
512
- To create a detached element from a selector,
513
- see `up.element.createFromSelector()`.
514
-
515
- \#\#\# Example
516
-
517
- element = up.element.affix(document.body, '.klass')
518
- element.parentElement // returns document.body
519
- element.className // returns 'klass'
520
-
521
- @function up.element.affix
522
- @params {Element} parent
523
- The parent to which to attach the created element.
524
- @params {string} selector
525
- The CSS selector from which to create an element.
526
- @params {Object} attrs
527
- An object of attributes to set on the created element.
528
- @param {Object} attrs.text
529
- The [text content](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) of the created element.
530
- @param {Object} attrs.style
531
- An object of CSS properties that will be set as the inline style
532
- of the created element.
533
- @return {Element}
534
- The created element.
535
- @experimental
536
- ###
537
- affix = (parent, selector, attributes) ->
538
- element = createFromSelector(selector, attributes)
539
- parent.appendChild(element)
540
- element
541
-
542
- ###**
543
- Returns a CSS selector that matches the given element as good as possible.
544
-
545
- To build the selector, the following element properties are used in decreasing
546
- order of priority:
547
-
548
- - The element's `[up-id]` attribute
549
- - The element's `[id]` attribute
550
- - The element's `[name]` attribute
551
- - The element's `[class]` names
552
- - The element's [`[aria-label]`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) attribute
553
- - The element's tag name
554
-
555
- \#\#\# Example
556
-
557
- element = document.createElement('span')
558
- element.className = 'klass'
559
- selector = up.element.toSelector(element) // returns '.klass'
560
-
561
- @function up.element.toSelector
562
- @param {string|Element|jQuery}
563
- The element for which to create a selector.
564
- @experimental
565
- ###
566
- toSelector = (element) ->
567
- return element if u.isString(element)
568
-
569
- # resolveSelector() might be called with jQuery collections
570
- element = getOne(element)
571
-
572
- selector = undefined
573
-
574
- if isSingleton(element)
575
- selector = elementTagName(element)
576
- else if upId = element.getAttribute("up-id")
577
- selector = attributeSelector('up-id', upId)
578
- else if id = element.getAttribute("id")
579
- if id.match(/^[a-z0-9\-_]+$/i)
580
- selector = "##{id}"
581
- else
582
- selector = attributeSelector('id', id)
583
- else if name = element.getAttribute("name")
584
- selector = elementTagName(element) + attributeSelector('name', name)
585
- else if classes = u.presence(nonUpClasses(element))
586
- selector = ''
587
- for klass in classes
588
- selector += ".#{klass}"
589
- else if ariaLabel = element.getAttribute("aria-label")
590
- selector = attributeSelector('aria-label', ariaLabel)
591
- else
592
- selector = elementTagName(element)
593
-
594
- return selector
595
-
596
- ###**
597
- Sets an unique identifier for this element.
598
-
599
- This identifier is used by `up.element.toSelector()`
600
- to create a CSS selector that matches this element precisely.
601
-
602
- If the element already has other attributes that make a good identifier,
603
- like a `[id]`, `[class]` or `[aria-label]`, it is not necessary to
604
- set `[up-id]`.
605
-
606
- \#\#\# Example
607
-
608
- Take this element:
609
-
610
- <a href="/">Homepage</a>
611
-
612
- Unpoly cannot generate a good CSS selector for this element:
613
-
614
- up.element.toSelector(element)
615
- // returns 'a'
616
-
617
- We can improve this by assigning an `[up-id]`:
618
-
619
- <a href="/" up-id="link-to-home">Open user 4</a>
620
-
621
- The attribute value is used to create a better selector:
622
-
623
- up.element.toSelector(element)
624
- // returns '[up-id="link-to-home"]'
625
-
626
- @selector [up-id]
627
- @param {string} up-id
628
- A string that uniquely identifies this element.
629
- @stable
630
- ###
631
-
632
- ###**
633
- @function up.element.isSingleton
634
- @internal
635
- ###
636
- isSingleton = (element) ->
637
- matches(element, 'html, body, head, title')
638
-
639
- elementTagName = (element) ->
640
- element.tagName.toLowerCase()
641
-
642
- ###**
643
- @function up.element.attributeSelector
644
- @internal
645
- ###
646
- attributeSelector = (attribute, value) ->
647
- value = value.replace(/"/g, '\\"')
648
- "[#{attribute}=\"#{value}\"]"
649
-
650
- nonUpClasses = (element) ->
651
- classString = element.className
652
- classes = u.splitValues(classString)
653
- u.reject classes, (klass) -> klass.match(/^up-/)
654
-
655
- ###**
656
- @function up.element.createDocumentFromHtml
657
- @internal
658
- ###
659
- createDocumentFromHtml = (html) ->
660
- # IE9 cannot set innerHTML on a <html> or <head> element.
661
- parser = new DOMParser()
662
- return parser.parseFromString(html, 'text/html')
663
-
664
- ###**
665
- Creates an element from the given HTML fragment.
666
-
667
- \#\#\# Example
668
-
669
- element = up.element.createFromHtml('<div class="foo"><span>text</span></div>')
670
- element.className // returns 'foo'
671
- element.children[0] // returns <span> element
672
- element.children[0].textContent // returns 'text'
673
-
674
- @function up.element.createFromHtml
675
- @experimental
676
- ###
677
- createFromHtml = (html) ->
678
- doc = createDocumentFromHtml(html)
679
- return doc.body.children[0]
680
-
681
- ###**
682
- @function up.element.root
683
- @internal
684
- ###
685
- getRoot = ->
686
- document.documentElement
687
-
688
- ###**
689
- Forces the browser to paint the given element now.
690
-
691
- @function up.element.paint
692
- @internal
693
- ###
694
- paint = (element) ->
695
- element.offsetHeight
696
-
697
- ###**
698
- @function up.element.concludeCssTransition
699
- @internal
700
- ###
701
- concludeCssTransition = (element) ->
702
- undo = setTemporaryStyle(element, transition: 'none')
703
- # Browsers need to paint at least one frame without a transition to stop the
704
- # animation. In theory we could just wait until the next paint, but in case
705
- # someone will set another transition after us, let's force a repaint here.
706
- paint(element)
707
- return undo
708
-
709
- ###**
710
- Returns whether the given element has a CSS transition set.
711
-
712
- @function up.element.hasCssTransition
713
- @return {boolean}
714
- @internal
715
- ###
716
- hasCssTransition = (elementOrStyleHash) ->
717
- if u.isOptions(elementOrStyleHash)
718
- styleHash = elementOrStyleHash
719
- else
720
- styleHash = computedStyle(elementOrStyleHash)
721
-
722
- prop = styleHash.transitionProperty
723
- duration = styleHash.transitionDuration
724
- # The default transition for elements is actually "all 0s ease 0s"
725
- # instead of "none", although that has the same effect as "none".
726
- noTransition = (prop == 'none' || (prop == 'all' && duration == 0))
727
- not noTransition
728
-
729
- ###**
730
- @function up.element.fixedToAbsolute
731
- @internal
732
- ###
733
- fixedToAbsolute = (element) ->
734
- elementRectAsFixed = element.getBoundingClientRect()
735
-
736
- # Set the position to 'absolute' so it gains an offsetParent
737
- element.style.position = 'absolute'
738
-
739
- offsetParentRect = element.offsetParent.getBoundingClientRect()
740
-
741
- setInlineStyle element,
742
- left: elementRectAsFixed.left - computedStyleNumber(element, 'margin-left') - offsetParentRect.left
743
- top: elementRectAsFixed.top - computedStyleNumber(element, 'margin-top') - offsetParentRect.top
744
- right: ''
745
- bottom: ''
746
-
747
- ###**
748
- On the given element, set attributes that are still missing.
749
-
750
- @function up.element.setMissingAttrs
751
- @internal
752
- ###
753
- setMissingAttrs = (element, attrs) ->
754
- for key, value of attrs
755
- if u.isMissing(element.getAttribute(key))
756
- element.setAttribute(key, value)
757
-
758
- ###**
759
- @function up.element.unwrap
760
- @internal
761
- ###
762
- unwrap = (wrapper) ->
763
- parent = wrapper.parentNode;
764
- wrappedNodes = u.toArray(wrapper.childNodes)
765
- u.each wrappedNodes, (wrappedNode) ->
766
- parent.insertBefore(wrappedNode, wrapper)
767
- parent.removeChild(wrapper)
768
-
769
- # ###**
770
- # Returns the value of the given attribute on the given element, if the value is [present](/up.util.isPresent).
771
- #
772
- # Returns `undefined` if the attribute is not set, or if it is set to an empty string.
773
- #
774
- # @function up.element.presentAttr
775
- # @param {Element} element
776
- # The element from which to retrieve the attribute value.
777
- # @param {String} attribute
778
- # The attribute name.
779
- # @return {string|undefined}
780
- # The attribute value, if present.
781
- # @experimental
782
- # ###
783
- # presentAttr = (element, attribute) ->
784
- # value = element.getAttribute(attribute)
785
- # u.presence(value)
786
-
787
- ###**
788
- Returns the value of the given attribute on the given element, cast as a boolean value.
789
-
790
- If the attribute value cannot be cast to `true` or `false`, `undefined` is returned.
791
-
792
- \#\#\# Casting rules
793
-
794
- This function deviates from the
795
- [HTML Standard for boolean attributes](https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes)
796
- in order to allow `undefined` values. When an attribute is missing, Unpoly considers the value to be `undefined`
797
- (where the standard would assume `false`).
798
-
799
- Unpoly also allows `"true"` and `"false"` as attribute values.
800
-
801
- The table below shows return values for `up.element.booleanAttr(element, 'foo')` given different elements:
802
-
803
- | Element | Return value |
804
- |---------------------|--------------|
805
- | `<div foo>` | `true` |
806
- | `<div foo="foo">` | `true` |
807
- | `<div foo="true">` | `true` |
808
- | `<div foo="">` | `true` |
809
- | `<div foo="false">` | `false` |
810
- | `<div>` | `undefined` |
811
- | `<div foo="bar">` | `undefined` |
812
-
813
- @function up.element.booleanAttr
814
- @param {Element} element
815
- The element from which to retrieve the attribute value.
816
- @param {String} attribute
817
- The attribute name.
818
- @return {boolean|undefined}
819
- The cast attribute value.
820
- @experimental
821
- ###
822
- booleanAttr = (element, attribute, pass) ->
823
- value = element.getAttribute(attribute)
824
- switch value
825
- when 'false'
826
- false
827
- when 'true', '', attribute
828
- true
829
- else
830
- value if pass
831
-
832
- ###**
833
- Returns the given attribute value cast as boolean.
834
-
835
- If the attribute value cannot be cast, returns the attribute value unchanged.
836
-
837
- @internal
838
- ###
839
- booleanOrStringAttr = (element, attribute) ->
840
- booleanAttr(element, attribute, true)
841
-
842
- ###**
843
- Returns the value of the given attribute on the given element, cast to a number.
844
-
845
- If the attribute value cannot be cast to a number, `undefined` is returned.
846
-
847
- @function up.element.numberAttr
848
- @param {Element} element
849
- The element from which to retrieve the attribute value.
850
- @param {String} attribute
851
- The attribute name.
852
- @return {number|undefined}
853
- The cast attribute value.
854
- @experimental
855
- ###
856
- numberAttr = (element, attribute) ->
857
- value = element.getAttribute(attribute)
858
- if value?.match(/^[\d\.]+$/)
859
- parseFloat(value)
860
-
861
- ###**
862
- Reads the given attribute from the element, parsed as [JSON](https://www.json.org/).
863
-
864
- Returns `undefined` if the attribute value is [blank](/up.util.isBlank).
865
-
866
- Throws a `SyntaxError` if the attribute value is an invalid JSON string.
867
-
868
- @function up.element.jsonAttr
869
- @param {Element} element
870
- The element from which to retrieve the attribute value.
871
- @param {String} attribute
872
- The attribute name.
873
- @return {Object|undefined}
874
- The cast attribute value.
875
- @experimental
876
- ###
877
- jsonAttr = (element, attribute) ->
878
- # The document does not respond to #getAttribute()
879
- if json = element.getAttribute?(attribute)?.trim()
880
- JSON.parse(json)
881
-
882
- ###**
883
- Temporarily sets the inline CSS styles on the given element.
884
-
885
- Returns a function that restores the original inline styles when called.
886
-
887
- \#\#\# Example
888
-
889
- element = document.querySelector('div')
890
- unhide = up.element.setTemporaryStyle(element, { 'visibility': 'hidden' })
891
- // do things while element is invisible
892
- unhide()
893
- // element is visible again
894
-
895
- @function up.element.setTemporaryStyle
896
- @param {Element} element
897
- The element to style.
898
- @param {Object} styles
899
- An object of CSS property names and values.
900
- @return {Function()}
901
- A function that restores the original inline styles when called.
902
- @internal
903
- ###
904
- setTemporaryStyle = (element, newStyles, block) ->
905
- oldStyles = inlineStyle(element, Object.keys(newStyles))
906
- setInlineStyle(element, newStyles)
907
- return -> setInlineStyle(element, oldStyles)
908
-
909
- ###**
910
- Receives [computed CSS styles](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
911
- for the given element.
912
-
913
- \#\#\# Examples
914
-
915
- When requesting a single CSS property, its value will be returned as a string:
916
-
917
- value = up.element.style(element, 'font-size')
918
- // value is '16px'
919
-
920
- When requesting multiple CSS properties, the function returns an object of property names and values:
921
-
922
- value = up.element.style(element, ['font-size', 'margin-top'])
923
- // value is { 'font-size': '16px', 'margin-top': '10px' }
924
-
925
- @function up.element.style
926
- @param {Element} element
927
- @param {String|Array} propOrProps
928
- One or more CSS property names in kebab-case or camelCase.
929
- @return {string|object}
930
- @experimental
931
- ###
932
- computedStyle = (element, props) ->
933
- style = window.getComputedStyle(element)
934
- extractFromStyleObject(style, props)
935
-
936
- ###**
937
- Receives a [computed CSS property value](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
938
- for the given element, casted as a number.
939
-
940
- The value is casted by removing the property's [unit](https://www.w3schools.com/cssref/css_units.asp) (which is usually `px` for computed properties).
941
- The result is then parsed as a floating point number.
942
-
943
- Returns `undefined` if the property value is missing, or if it cannot
944
- be parsed as a number.
945
-
946
- \#\#\# Examples
947
-
948
- When requesting a single CSS property, its value will be returned as a string:
949
-
950
- value = up.element.style(element, 'font-size')
951
- // value is '16px'
952
-
953
- value = up.element.styleNumber(element, 'font-size')
954
- // value is 16
955
-
956
- @function up.element.styleNumber
957
- @param {Element} element
958
- @param {String} prop
959
- A single property name in kebab-case or camelCase.
960
- @return {number|undefined}
961
- @experimental
962
- ###
963
- computedStyleNumber = (element, prop) ->
964
- rawValue = computedStyle(element, prop)
965
- if u.isGiven(rawValue)
966
- parseFloat(rawValue)
967
- else
968
- undefined
969
-
970
- ###**
971
- Gets the given inline style(s) from the given element's `[style]` attribute.
972
-
973
- @function up.element.inlineStyle
974
- @param {Element} element
975
- @param {String|Array} propOrProps
976
- One or more CSS property names in kebab-case or camelCase.
977
- @return {string|object}
978
- @internal
979
- ###
980
- inlineStyle = (element, props) ->
981
- style = element.style
982
- extractFromStyleObject(style, props)
983
-
984
- extractFromStyleObject = (style, keyOrKeys) ->
985
- if u.isString(keyOrKeys)
986
- style[keyOrKeys]
987
- else # array
988
- u.only(style, keyOrKeys...)
989
-
990
- ###**
991
- Sets the given CSS properties as inline styles on the given element.
992
-
993
- @function up.element.setStyle
994
- @param {Element} element
995
- @param {Object} props
996
- One or more CSS properties with kebab-case keys or camelCase keys.
997
- @return {string|object}
998
- @experimental
999
- ###
1000
- setInlineStyle = (element, props) ->
1001
- style = element.style
1002
- for key, value of props
1003
- value = normalizeStyleValueForWrite(key, value)
1004
- style[key] = value
1005
-
1006
- normalizeStyleValueForWrite = (key, value) ->
1007
- if u.isMissing(value)
1008
- value = ''
1009
- else if CSS_LENGTH_PROPS.has(key.toLowerCase().replace(/-/, ''))
1010
- value = cssLength(value)
1011
- value
1012
-
1013
- CSS_LENGTH_PROPS = u.arrayToSet [
1014
- 'top', 'right', 'bottom', 'left',
1015
- 'padding', 'paddingtop', 'paddingright', 'paddingbottom', 'paddingleft',
1016
- 'margin', 'margintop', 'marginright', 'marginbottom', 'marginleft',
1017
- 'borderwidth', 'bordertopwidth', 'borderrightwidth', 'borderbottomwidth', 'borderleftwidth'
1018
- 'width', 'height',
1019
- 'maxwidth', 'maxheight',
1020
- 'minwidth', 'minheight',
1021
- ]
1022
-
1023
- ###**
1024
- Converts the given value to a CSS length value, adding a `px` unit if required.
1025
-
1026
- @function cssLength
1027
- @internal
1028
- ###
1029
- cssLength = (obj) ->
1030
- if u.isNumber(obj) || (u.isString(obj) && /^\d+$/.test(obj))
1031
- obj.toString() + "px"
1032
- else
1033
- obj
1034
-
1035
- ###**
1036
- Resolves the given CSS selector (which might contain `&` references)
1037
- to a full CSS selector without ampersands.
1038
-
1039
- If passed an `Element` or `jQuery` element, returns a CSS selector string
1040
- for that element.
1041
-
1042
- @function up.element.resolveSelector
1043
- @param {string|Element|jQuery} selectorOrElement
1044
- @param {string|Element|jQuery} origin
1045
- The element that this selector resolution is relative to.
1046
- That element's selector will be substituted for `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
1047
- @return {string}
1048
- @internal
1049
- ###
1050
- resolveSelector = (selectorOrElement, origin) ->
1051
- if u.isString(selectorOrElement)
1052
- selector = selectorOrElement
1053
- if u.contains(selector, '&')
1054
- if u.isPresent(origin) # isPresent returns false for empty jQuery collection
1055
- originSelector = toSelector(origin)
1056
- selector = selector.replace(/\&/, originSelector)
1057
- else
1058
- up.fail("Found origin reference (%s) in selector %s, but no origin was given", '&', selector)
1059
- else
1060
- selector = toSelector(selectorOrElement)
1061
- selector
1062
-
1063
- ###**
1064
- Returns whether the given element is currently visible.
1065
-
1066
- An element is considered visible if it consumes space in the document.
1067
- Elements with `{ visibility: hidden }` or `{ opacity: 0 }` are considered visible, since they still consume space in the layout.
1068
-
1069
- Elements not attached to the DOM are considered hidden.
1070
-
1071
- @function up.element.isVisible
1072
- @param {Element} element
1073
- The element to check.
1074
- @experimental
1075
- ###
1076
- isVisible = (element) ->
1077
- # From https://github.com/jquery/jquery/blame/9cb162f6b62b6d4403060a0f0d2065d3ae96bbcc/src/css/hiddenVisibleSelectors.js#L12
1078
- !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length)
1079
-
1080
- <% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
1081
- # also document :has()!
1082
- first: first # same as document.querySelector
1083
- all: all # same as document.querySelectorAll
1084
- subtree: subtree # practical
1085
- closest: closest # needed for IE11
1086
- matches: matches # needed for IE11
1087
- ancestor: ancestor # not practical. we use it to implement closest
1088
- get: getOne # practical for code that also works with jQuery
1089
- list: getList # practical for composing multiple collections, or wrapping.
1090
- remove: remove # needed for IE11
1091
- toggle: toggle # practical
1092
- toggleClass: toggleClass # practical
1093
- hide: hide # practical
1094
- show: show # practical
1095
- metaContent: metaContent # internal
1096
- replace: replace # needed for IE11
1097
- insertBefore: insertBefore # internal shortcut, people can use insertAdjacentElement and i don't want to support insertAfter when I don't need it.
1098
- createFromSelector: createFromSelector # practical for element creation.
1099
- setAttrs: setAttrs # practical
1100
- affix: affix # practical for element creation
1101
- toSelector: toSelector # practical
1102
- isSingleton: isSingleton # internal
1103
- attributeSelector: attributeSelector # internal
1104
- createDocumentFromHtml: createDocumentFromHtml # internal
1105
- createFromHtml: createFromHtml # practical for element creation
1106
- root: getRoot # internal
1107
- paint: paint # internal
1108
- concludeCssTransition: concludeCssTransition # internal
1109
- hasCssTransition: hasCssTransition # internal
1110
- fixedToAbsolute: fixedToAbsolute # internal
1111
- setMissingAttrs: setMissingAttrs # internal
1112
- unwrap: unwrap # practical for jQuery migration
1113
- # presentAttr: presentAttr # experimental
1114
- booleanAttr: booleanAttr # it's practical, but i cannot find a good name. people might expect it to cast to number, too. but i don't need that for my own code. maybe booleanAttr?
1115
- numberAttr: numberAttr # practical
1116
- jsonAttr: jsonAttr # practical
1117
- booleanOrStringAttr: booleanOrStringAttr
1118
- setTemporaryStyle: setTemporaryStyle # practical
1119
- style: computedStyle # practical.
1120
- styleNumber: computedStyleNumber # practical.
1121
- inlineStyle: inlineStyle # internal
1122
- setStyle: setInlineStyle # practical.
1123
- resolveSelector: resolveSelector # internal
1124
- none: -> NONE # internal
1125
- isVisible: isVisible # practical
1126
-