voom-presenters 0.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (447) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -1
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/ISSUE_TEMPLATE/questions-support.md +10 -0
  6. data/.github/workflows/semantic-release.yml +42 -0
  7. data/.gitignore +3 -2
  8. data/.releaserc +15 -0
  9. data/.ruby-version +2 -1
  10. data/CHANGELOG.md +71 -108
  11. data/CONTRIBUTING.md +60 -0
  12. data/Gemfile +14 -4
  13. data/Gemfile.lock +93 -46
  14. data/Procfile +1 -0
  15. data/README.md +48 -39
  16. data/app/demo/components/avatars.pom +40 -0
  17. data/app/demo/components/cards.pom +11 -4
  18. data/app/demo/components/chips.pom +61 -54
  19. data/app/demo/components/content.pom +96 -16
  20. data/app/demo/components/dialogs.pom +175 -6
  21. data/app/demo/components/file_inputs.pom +38 -2
  22. data/app/demo/components/google_maps.pom +6 -1
  23. data/app/demo/components/headers.pom +80 -20
  24. data/app/demo/components/icons.pom +86 -55
  25. data/app/demo/components/image_lists.pom +100 -0
  26. data/app/demo/components/images.pom +45 -0
  27. data/app/demo/components/layouts.pom +3 -25
  28. data/app/demo/components/lists.pom +24 -4
  29. data/app/demo/components/menus.pom +14 -4
  30. data/app/demo/components/multi_selects.pom +29 -0
  31. data/app/demo/components/nav/menu.pom +39 -7
  32. data/app/demo/components/nav/pattern_menu.pom +2 -2
  33. data/app/demo/components/number_fields.pom +53 -0
  34. data/app/demo/components/padding.pom +96 -0
  35. data/app/demo/components/progress.pom +71 -0
  36. data/app/demo/components/selects.pom +45 -5
  37. data/app/demo/components/sliders.pom +5 -0
  38. data/app/demo/components/tab_bars.pom +15 -0
  39. data/app/demo/components/tables.pom +51 -40
  40. data/app/demo/components/text_areas.pom +23 -16
  41. data/app/demo/components/text_fields.pom +61 -15
  42. data/app/demo/components/toggles.pom +35 -4
  43. data/app/demo/components/tooltips.pom +8 -4
  44. data/app/demo/components/unordered_list.pom +81 -0
  45. data/app/demo/custom_css.pom +37 -0
  46. data/app/demo/events/actions/autocomplete.pom +32 -0
  47. data/app/demo/events/actions/clear.pom +5 -3
  48. data/app/demo/events/actions/dialogs/discard.pom +9 -0
  49. data/app/demo/events/actions/dialogs/show_dialog.pom +4 -2
  50. data/app/demo/events/actions/last_response.pom +40 -0
  51. data/app/demo/events/actions/prompt_if_dirty.pom +54 -0
  52. data/app/demo/events/content_as_form.pom +313 -0
  53. data/app/demo/events/nav/drawer.pom +7 -3
  54. data/app/demo/events/parallel.pom +44 -0
  55. data/app/demo/index.pom +5 -5
  56. data/app/demo/nav/top_nav.pom +10 -4
  57. data/app/demo/patterns/drag_drop.pom +89 -0
  58. data/app/demo/patterns/floating_card.pom +29 -0
  59. data/app/demo/patterns/search_select.pom +9 -7
  60. data/app/demo/plugins/chart.pom +254 -0
  61. data/app/demo/plugins/image_crop.pom +44 -0
  62. data/app/demo/plugins/index.pom +29 -0
  63. data/app/demo/plugins/nav/drawer.pom +19 -0
  64. data/app/demo/shared/context_list.pom +1 -1
  65. data/app/demo/styles.pom +3 -1
  66. data/bin/console +4 -4
  67. data/component-status.yml +15 -15
  68. data/config.ru +20 -10
  69. data/docs/settings.md +81 -0
  70. data/exe/presenters +3 -0
  71. data/lib/hash_ext/traverse.rb +14 -0
  72. data/lib/voom.rb +25 -0
  73. data/lib/voom/container_methods.rb +2 -2
  74. data/lib/voom/engine.rb +5 -0
  75. data/lib/voom/presenters/api/app.rb +31 -11
  76. data/lib/voom/presenters/api/router.rb +3 -49
  77. data/lib/voom/presenters/app.rb +3 -3
  78. data/lib/voom/presenters/cli.rb +28 -0
  79. data/lib/voom/presenters/demo/dragon_drop.rb +48 -0
  80. data/lib/voom/presenters/demo/echo.rb +2 -0
  81. data/lib/voom/presenters/demo/slow.rb +18 -0
  82. data/lib/voom/presenters/dsl/components/actions/autocomplete.rb +15 -0
  83. data/lib/voom/presenters/dsl/components/actions/base.rb +36 -8
  84. data/lib/voom/presenters/dsl/components/actions/clear.rb +0 -2
  85. data/lib/voom/presenters/dsl/components/actions/close_dialog.rb +17 -0
  86. data/lib/voom/presenters/dsl/components/actions/deletes.rb +0 -2
  87. data/lib/voom/presenters/dsl/components/actions/dialog.rb +0 -2
  88. data/lib/voom/presenters/dsl/components/actions/loads.rb +5 -6
  89. data/lib/voom/presenters/dsl/components/actions/navigates.rb +0 -2
  90. data/lib/voom/presenters/dsl/components/actions/post_message.rb +17 -0
  91. data/lib/voom/presenters/dsl/components/actions/posts.rb +5 -2
  92. data/lib/voom/presenters/dsl/components/actions/prompt_if_dirty.rb +15 -0
  93. data/lib/voom/presenters/dsl/components/actions/remove.rb +0 -2
  94. data/lib/voom/presenters/dsl/components/actions/replaces.rb +4 -4
  95. data/lib/voom/presenters/dsl/components/actions/snackbar.rb +0 -2
  96. data/lib/voom/presenters/dsl/components/actions/stepper.rb +0 -2
  97. data/lib/voom/presenters/dsl/components/actions/toggle_disabled.rb +15 -0
  98. data/lib/voom/presenters/dsl/components/actions/toggle_visibility.rb +0 -2
  99. data/lib/voom/presenters/dsl/components/actions/updates.rb +5 -2
  100. data/lib/voom/presenters/dsl/components/avatar.rb +4 -8
  101. data/lib/voom/presenters/dsl/components/badge.rb +0 -2
  102. data/lib/voom/presenters/dsl/components/base.rb +25 -18
  103. data/lib/voom/presenters/dsl/components/button.rb +15 -11
  104. data/lib/voom/presenters/dsl/components/card.rb +49 -36
  105. data/lib/voom/presenters/dsl/components/checkbox.rb +0 -2
  106. data/lib/voom/presenters/dsl/components/chip.rb +5 -7
  107. data/lib/voom/presenters/dsl/components/chipset.rb +33 -0
  108. data/lib/voom/presenters/dsl/components/content.rb +28 -18
  109. data/lib/voom/presenters/dsl/components/datetime_base.rb +0 -2
  110. data/lib/voom/presenters/dsl/components/datetime_field.rb +0 -2
  111. data/lib/voom/presenters/dsl/components/dialog.rb +36 -12
  112. data/lib/voom/presenters/dsl/components/drawer.rb +9 -6
  113. data/lib/voom/presenters/dsl/components/event.rb +106 -65
  114. data/lib/voom/presenters/dsl/components/event_base.rb +1 -3
  115. data/lib/voom/presenters/dsl/components/expansion_panel.rb +0 -3
  116. data/lib/voom/presenters/dsl/components/file_input.rb +18 -6
  117. data/lib/voom/presenters/dsl/components/footer.rb +2 -2
  118. data/lib/voom/presenters/dsl/components/form.rb +2 -17
  119. data/lib/voom/presenters/dsl/components/grid.rb +52 -50
  120. data/lib/voom/presenters/dsl/components/header.rb +17 -1
  121. data/lib/voom/presenters/dsl/components/hidden_field.rb +0 -2
  122. data/lib/voom/presenters/dsl/components/icon.rb +2 -4
  123. data/lib/voom/presenters/dsl/components/icon_base.rb +5 -7
  124. data/lib/voom/presenters/dsl/components/icon_toggle.rb +2 -4
  125. data/lib/voom/presenters/dsl/components/image.rb +61 -13
  126. data/lib/voom/presenters/dsl/components/image_list.rb +43 -0
  127. data/lib/voom/presenters/dsl/components/input.rb +14 -5
  128. data/lib/voom/presenters/dsl/components/link.rb +33 -0
  129. data/lib/voom/presenters/dsl/components/list.rb +6 -13
  130. data/lib/voom/presenters/dsl/components/lists/action.rb +9 -11
  131. data/lib/voom/presenters/dsl/components/lists/actions.rb +0 -3
  132. data/lib/voom/presenters/dsl/components/lists/line.rb +27 -15
  133. data/lib/voom/presenters/dsl/components/menu.rb +51 -9
  134. data/lib/voom/presenters/dsl/components/mixins/append.rb +2 -2
  135. data/lib/voom/presenters/dsl/components/mixins/attaches.rb +0 -2
  136. data/lib/voom/presenters/dsl/components/mixins/avatar.rb +1 -3
  137. data/lib/voom/presenters/dsl/components/mixins/chips.rb +0 -2
  138. data/lib/voom/presenters/dsl/components/mixins/chipset.rb +19 -0
  139. data/lib/voom/presenters/dsl/components/mixins/common.rb +13 -14
  140. data/lib/voom/presenters/dsl/components/mixins/dialogs.rb +0 -2
  141. data/lib/voom/presenters/dsl/components/mixins/event.rb +0 -2
  142. data/lib/voom/presenters/dsl/components/mixins/image_lists.rb +15 -0
  143. data/lib/voom/presenters/dsl/components/mixins/last_response.rb +48 -0
  144. data/lib/voom/presenters/dsl/components/mixins/padding.rb +42 -0
  145. data/lib/voom/presenters/dsl/components/mixins/progress.rb +16 -0
  146. data/lib/voom/presenters/dsl/components/mixins/selects.rb +6 -0
  147. data/lib/voom/presenters/dsl/components/mixins/tab_bars.rb +2 -0
  148. data/lib/voom/presenters/dsl/components/mixins/tables.rb +15 -0
  149. data/lib/voom/presenters/dsl/components/mixins/text_fields.rb +5 -0
  150. data/lib/voom/presenters/dsl/components/mixins/toggles.rb +0 -2
  151. data/lib/voom/presenters/dsl/components/mixins/typography.rb +55 -8
  152. data/lib/voom/presenters/dsl/components/mixins/yield_to.rb +2 -2
  153. data/lib/voom/presenters/dsl/components/multi_select.rb +56 -0
  154. data/lib/voom/presenters/dsl/components/number_field.rb +20 -0
  155. data/lib/voom/presenters/dsl/components/page_title.rb +31 -0
  156. data/lib/voom/presenters/dsl/components/progress.rb +27 -0
  157. data/lib/voom/presenters/dsl/components/radio_button.rb +0 -1
  158. data/lib/voom/presenters/dsl/components/rich_text_area.rb +5 -11
  159. data/lib/voom/presenters/dsl/components/select.rb +18 -9
  160. data/lib/voom/presenters/dsl/components/separator.rb +21 -0
  161. data/lib/voom/presenters/dsl/components/slider.rb +6 -7
  162. data/lib/voom/presenters/dsl/components/stepper.rb +0 -10
  163. data/lib/voom/presenters/dsl/components/switch.rb +0 -2
  164. data/lib/voom/presenters/dsl/components/tab_bar.rb +0 -3
  165. data/lib/voom/presenters/dsl/components/table.rb +39 -20
  166. data/lib/voom/presenters/dsl/components/text_area.rb +1 -3
  167. data/lib/voom/presenters/dsl/components/text_field.rb +54 -11
  168. data/lib/voom/presenters/dsl/components/time_field.rb +0 -2
  169. data/lib/voom/presenters/dsl/components/toggle_base.rb +8 -6
  170. data/lib/voom/presenters/dsl/components/typography.rb +4 -4
  171. data/lib/voom/presenters/dsl/components/unordered_list.rb +50 -0
  172. data/lib/voom/presenters/dsl/definer.rb +0 -4
  173. data/lib/voom/presenters/dsl/definition.rb +6 -5
  174. data/lib/voom/presenters/dsl/protect_from_forgery.rb +43 -0
  175. data/lib/voom/presenters/dsl/user_interface.rb +37 -22
  176. data/lib/voom/presenters/errors.rb +1 -0
  177. data/lib/voom/presenters/errors/invalid_dsl.rb +8 -0
  178. data/lib/voom/presenters/errors/parameter_validation.rb +1 -3
  179. data/lib/voom/presenters/generators/inflectors.rb +59 -0
  180. data/lib/voom/presenters/generators/plugin.rb +115 -0
  181. data/lib/voom/presenters/generators/templates/plugin/.gitignore +12 -0
  182. data/lib/voom/presenters/generators/templates/plugin/Gemfile +6 -0
  183. data/lib/voom/presenters/generators/templates/plugin/LICENSE.txt.tt +21 -0
  184. data/lib/voom/presenters/generators/templates/plugin/README.md +253 -0
  185. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/actions/action.rb.tt +16 -0
  186. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/actions/dsl.rb.tt +22 -0
  187. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/component.rb.tt +18 -0
  188. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/dsl.rb.tt +19 -0
  189. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/helpers/helper.rb.tt +15 -0
  190. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/plugin.rb.tt +9 -0
  191. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/web_client/components/actions/data.rb.tt +17 -0
  192. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/web_client/components/render.rb.tt +23 -0
  193. data/lib/voom/presenters/generators/templates/plugin/presenter_plugin.gemspec.tt +21 -0
  194. data/lib/voom/presenters/generators/templates/plugin/views/assets/css/components/component.css.tt +21 -0
  195. data/lib/voom/presenters/generators/templates/plugin/views/assets/js/components/actions/action.js.tt +15 -0
  196. data/lib/voom/presenters/generators/templates/plugin/views/assets/js/components/component.js.tt +39 -0
  197. data/lib/voom/presenters/generators/templates/plugin/views/components/component.erb.tt +14 -0
  198. data/lib/voom/presenters/generators/templates/plugin/views/components/component_header.erb.tt +20 -0
  199. data/lib/voom/presenters/helpers.rb +2 -8
  200. data/lib/voom/presenters/helpers/inflector.rb +1 -1
  201. data/lib/voom/presenters/helpers/rails.rb +15 -8
  202. data/lib/voom/presenters/helpers/redact.rb +13 -0
  203. data/lib/voom/presenters/helpers/route.rb +12 -5
  204. data/lib/voom/presenters/pluggable.rb +37 -0
  205. data/lib/voom/presenters/plugins.rb +7 -0
  206. data/lib/voom/presenters/plugins/google_maps.rb +24 -0
  207. data/lib/voom/presenters/plugins/google_maps/google_map.erb +10 -0
  208. data/lib/voom/presenters/{dsl/components → plugins/google_maps}/google_map.rb +4 -3
  209. data/lib/voom/presenters/{dsl.rb → registry.rb} +13 -15
  210. data/lib/voom/presenters/router.rb +59 -0
  211. data/lib/voom/presenters/settings.rb +18 -8
  212. data/lib/voom/presenters/version.rb +3 -1
  213. data/lib/voom/presenters/web_client/app.rb +86 -29
  214. data/lib/voom/presenters/web_client/component_decorator_factory.rb +27 -0
  215. data/lib/voom/presenters/web_client/component_html_decorator.rb +50 -0
  216. data/lib/voom/presenters/web_client/component_renderer.rb +49 -0
  217. data/lib/voom/presenters/web_client/custom_css.rb +65 -0
  218. data/lib/voom/presenters/web_client/{markdown_render.rb → custom_render.rb} +5 -3
  219. data/lib/voom/presenters/web_client/helpers/expand_hash.rb +19 -0
  220. data/lib/voom/presenters/web_client/helpers/form_helpers.rb +14 -0
  221. data/lib/voom/presenters/web_client/helpers/padding_helpers.rb +21 -0
  222. data/lib/voom/presenters/web_client/plugin_headers.rb +37 -0
  223. data/lib/voom/presenters/web_client/router.rb +3 -54
  224. data/lib/voom/railtie.rb +37 -0
  225. data/lib/voom/symbol/to_str.rb +3 -3
  226. data/lib/voom/trace.rb +0 -2
  227. data/presenters.gemspec +10 -6
  228. data/public/bundle.css +18256 -0
  229. data/public/bundle.js +60106 -0
  230. data/public/img/demo/avatar.jpg +0 -0
  231. data/public/presenters/custom_css.css +26 -0
  232. data/public/wc.js +52861 -0
  233. data/scripts/build.sh +10 -0
  234. data/views/mdc/.eslintrc.yml +1 -0
  235. data/views/mdc/.nvmrc +1 -0
  236. data/views/mdc/assets/js/app.js +13 -2
  237. data/views/mdc/assets/js/components/base-component.js +147 -12
  238. data/views/mdc/assets/js/components/base-container.js +54 -14
  239. data/views/mdc/assets/js/components/base-toggle.js +56 -0
  240. data/views/mdc/assets/js/components/button.js +74 -5
  241. data/views/mdc/assets/js/components/cards.js +3 -3
  242. data/views/mdc/assets/js/components/checkboxes.js +7 -30
  243. data/views/mdc/assets/js/components/chips.js +76 -12
  244. data/views/mdc/assets/js/components/content.js +5 -4
  245. data/views/mdc/assets/js/components/data-tables.js +11 -34
  246. data/views/mdc/assets/js/components/datetime.js +29 -6
  247. data/views/mdc/assets/js/components/dialogs.js +128 -31
  248. data/views/mdc/assets/js/components/drag_n_drop.js +182 -0
  249. data/views/mdc/assets/js/components/drawer.js +43 -0
  250. data/views/mdc/assets/js/components/events.js +190 -73
  251. data/views/mdc/assets/js/components/events/action_parameter.js +62 -0
  252. data/views/mdc/assets/js/components/events/action_parameter.test.js +62 -0
  253. data/views/mdc/assets/js/components/events/autocomplete.js +94 -0
  254. data/views/mdc/assets/js/components/events/base.js +139 -23
  255. data/views/mdc/assets/js/components/events/clears.js +15 -12
  256. data/views/mdc/assets/js/components/events/close_dialog.js +50 -0
  257. data/views/mdc/assets/js/components/events/dialog.js +32 -14
  258. data/views/mdc/assets/js/components/events/encode.js +8 -0
  259. data/views/mdc/assets/js/components/events/errors.js +175 -92
  260. data/views/mdc/assets/js/components/events/loads.js +50 -11
  261. data/views/mdc/assets/js/components/events/navigates.js +17 -15
  262. data/views/mdc/assets/js/components/events/plugin.js +18 -0
  263. data/views/mdc/assets/js/components/events/post_message.js +21 -0
  264. data/views/mdc/assets/js/components/events/posts.js +147 -65
  265. data/views/mdc/assets/js/components/events/prompt_if_dirty.js +67 -0
  266. data/views/mdc/assets/js/components/events/removes.js +7 -6
  267. data/views/mdc/assets/js/components/events/replaces.js +87 -33
  268. data/views/mdc/assets/js/components/events/snackbar.js +10 -10
  269. data/views/mdc/assets/js/components/events/stepper.js +8 -10
  270. data/views/mdc/assets/js/components/events/toggle_disabled.js +41 -0
  271. data/views/mdc/assets/js/components/events/toggle_visibility.js +57 -15
  272. data/views/mdc/assets/js/components/file-inputs.js +68 -21
  273. data/views/mdc/assets/js/components/form-fields.js +16 -0
  274. data/views/mdc/assets/js/components/forms.js +3 -3
  275. data/views/mdc/assets/js/components/get_event_target.js +15 -0
  276. data/views/mdc/assets/js/components/grid.js +7 -6
  277. data/views/mdc/assets/js/components/header.js +20 -0
  278. data/views/mdc/assets/js/components/hidden-fields.js +19 -8
  279. data/views/mdc/assets/js/components/icon-toggles.js +7 -7
  280. data/views/mdc/assets/js/components/images.js +19 -0
  281. data/views/mdc/assets/js/components/initialize.js +54 -27
  282. data/views/mdc/assets/js/components/lists.js +9 -4
  283. data/views/mdc/assets/js/components/menus.js +60 -13
  284. data/views/mdc/assets/js/components/mixins/dirtyable.js +22 -0
  285. data/views/mdc/assets/js/components/mixins/event-handler.js +7 -7
  286. data/views/mdc/assets/js/components/mixins/visibility-observer.js +22 -21
  287. data/views/mdc/assets/js/components/multi-select.js +75 -0
  288. data/views/mdc/assets/js/components/plugins.js +86 -0
  289. data/views/mdc/assets/js/components/progress.js +31 -0
  290. data/views/mdc/assets/js/components/radios.js +6 -31
  291. data/views/mdc/assets/js/components/rich-text-area.js +217 -33
  292. data/views/mdc/assets/js/components/rich-text-area/horizontal-rule-blot.js +23 -0
  293. data/views/mdc/assets/js/components/root_document.js +5 -0
  294. data/views/mdc/assets/js/components/selects.js +18 -8
  295. data/views/mdc/assets/js/components/sliders.js +23 -12
  296. data/views/mdc/assets/js/components/snackbar.js +11 -8
  297. data/views/mdc/assets/js/components/steppers.js +3 -3
  298. data/views/mdc/assets/js/components/switches.js +6 -29
  299. data/views/mdc/assets/js/components/tab-bars.js +18 -4
  300. data/views/mdc/assets/js/components/text-fields.js +94 -22
  301. data/views/mdc/assets/js/components/tooltip.js +17 -0
  302. data/views/mdc/assets/js/components/typography.js +28 -0
  303. data/views/mdc/assets/js/components/uninitialize.js +7 -0
  304. data/views/mdc/assets/js/wc.js +111 -0
  305. data/views/mdc/assets/scss/app.scss +13 -5
  306. data/views/mdc/assets/scss/components/avatar.scss +51 -7
  307. data/views/mdc/assets/scss/components/button.scss +7 -9
  308. data/views/mdc/assets/scss/components/card.scss +6 -5
  309. data/views/mdc/assets/scss/components/chip.scss +4 -0
  310. data/views/mdc/assets/scss/components/content.scss +25 -0
  311. data/views/mdc/assets/scss/components/data-table.scss +12 -1
  312. data/views/mdc/assets/scss/components/datetime.scss +1 -2
  313. data/views/mdc/assets/scss/components/dialog.scss +7 -2
  314. data/views/mdc/assets/scss/components/drag_n_drop.scss +17 -0
  315. data/views/mdc/assets/scss/components/drawer.scss +82 -0
  316. data/views/mdc/assets/scss/components/expansion-panel.scss +2 -2
  317. data/views/mdc/assets/scss/components/fab.scss +23 -5
  318. data/views/mdc/assets/scss/components/file-input.scss +10 -14
  319. data/views/mdc/assets/scss/components/grid.scss +32 -17
  320. data/views/mdc/assets/scss/components/header.scss +21 -0
  321. data/views/mdc/assets/scss/components/icon-button-toggles.scss +2 -0
  322. data/views/mdc/assets/scss/components/icon.scss +23 -0
  323. data/views/mdc/assets/scss/components/image-list.scss +18 -0
  324. data/views/mdc/assets/scss/components/image.scss +13 -21
  325. data/views/mdc/assets/scss/components/list.scss +9 -3
  326. data/views/mdc/assets/scss/components/menu.scss +13 -3
  327. data/views/mdc/assets/scss/components/multi-select.scss +44 -0
  328. data/views/mdc/assets/scss/components/progress.scss +1 -0
  329. data/views/mdc/assets/scss/components/rich-text-area.scss +38 -2
  330. data/views/mdc/assets/scss/components/select.scss +6 -3
  331. data/views/mdc/assets/scss/components/separator.scss +3 -0
  332. data/views/mdc/assets/scss/components/switch.scss +10 -0
  333. data/views/mdc/assets/scss/components/textfield.scss +8 -4
  334. data/views/mdc/assets/scss/components/tooltip.scss +3 -0
  335. data/views/mdc/assets/scss/components/typography.scss +6 -0
  336. data/views/mdc/assets/scss/components/unordered-lists.scss +17 -0
  337. data/views/mdc/assets/scss/material.blue_grey-orange.min.css +1 -1
  338. data/views/mdc/assets/scss/media.scss +39 -0
  339. data/views/mdc/assets/scss/palette.scss +16 -0
  340. data/views/mdc/assets/scss/styles.scss +39 -1
  341. data/views/mdc/assets/scss/theme.scss +19 -2
  342. data/views/mdc/body/dismissable-drawer.erb +34 -0
  343. data/views/mdc/body/drawer/divider.erb +1 -0
  344. data/views/mdc/body/drawer/item.erb +13 -0
  345. data/views/mdc/body/drawer/label.erb +1 -0
  346. data/views/mdc/body/drawers/menu.erb +1 -1
  347. data/views/mdc/body/footers/menu_item.erb +2 -2
  348. data/views/mdc/body/header.erb +38 -31
  349. data/views/mdc/body/modal-drawer.erb +35 -0
  350. data/views/mdc/body/snackbar.erb +11 -5
  351. data/views/mdc/components/actions/autocomplete.rb +8 -0
  352. data/views/mdc/components/actions/close_dialog.rb +10 -0
  353. data/views/mdc/components/actions/loads.rb +7 -1
  354. data/views/mdc/components/actions/navigates.rb +1 -1
  355. data/views/mdc/components/actions/post.rb +4 -7
  356. data/views/mdc/components/actions/post_message.rb +10 -0
  357. data/views/mdc/components/actions/prompt_if_dirty.rb +17 -0
  358. data/views/mdc/components/actions/replaces.rb +5 -1
  359. data/views/mdc/components/actions/resolver.rb +39 -0
  360. data/views/mdc/components/actions/snackbar.rb +3 -1
  361. data/views/mdc/components/actions/toggle_disabled.rb +10 -0
  362. data/views/mdc/components/avatar.erb +12 -7
  363. data/views/mdc/components/badge.erb +1 -1
  364. data/views/mdc/components/button.erb +2 -3
  365. data/views/mdc/components/buttons/button.erb +12 -12
  366. data/views/mdc/components/buttons/fab.erb +3 -2
  367. data/views/mdc/components/buttons/icon.erb +5 -5
  368. data/views/mdc/components/buttons/image.erb +4 -3
  369. data/views/mdc/components/card.erb +67 -44
  370. data/views/mdc/components/checkbox.erb +32 -35
  371. data/views/mdc/components/chip.erb +38 -30
  372. data/views/mdc/components/chipset.erb +18 -0
  373. data/views/mdc/components/content.erb +35 -14
  374. data/views/mdc/components/datetime.erb +6 -19
  375. data/views/mdc/components/dialog.erb +45 -25
  376. data/views/mdc/components/drag_and_drop/drag_and_drop.rb +16 -0
  377. data/views/mdc/components/event.erb +3 -5
  378. data/views/mdc/components/expansion_panel.erb +8 -6
  379. data/views/mdc/components/file_input.erb +14 -10
  380. data/views/mdc/components/form.erb +4 -19
  381. data/views/mdc/components/grid.erb +20 -17
  382. data/views/mdc/components/hidden_field.erb +3 -4
  383. data/views/mdc/components/icon.erb +7 -5
  384. data/views/mdc/components/icon_toggle.erb +9 -8
  385. data/views/mdc/components/image.erb +23 -5
  386. data/views/mdc/components/image_list.erb +38 -0
  387. data/views/mdc/components/link.erb +3 -13
  388. data/views/mdc/components/list.erb +4 -2
  389. data/views/mdc/components/list/avatar.erb +2 -1
  390. data/views/mdc/components/list/header.erb +5 -3
  391. data/views/mdc/components/list/hidden_field.erb +3 -0
  392. data/views/mdc/components/list/icon.erb +2 -1
  393. data/views/mdc/components/list/line.erb +19 -9
  394. data/views/mdc/components/list/menu.erb +7 -2
  395. data/views/mdc/components/list/separator.erb +1 -1
  396. data/views/mdc/components/menu.erb +14 -6
  397. data/views/mdc/components/multi_select.erb +33 -0
  398. data/views/mdc/components/number_field.erb +38 -0
  399. data/views/mdc/components/page_title.erb +2 -2
  400. data/views/mdc/components/progress.erb +11 -0
  401. data/views/mdc/components/radio_button.erb +5 -6
  402. data/views/mdc/components/render.erb +2 -3
  403. data/views/mdc/components/rich_text_area.erb +13 -10
  404. data/views/mdc/components/select.erb +28 -12
  405. data/views/mdc/components/separator.erb +3 -0
  406. data/views/mdc/components/shared/hint_error_display.erb +9 -0
  407. data/views/mdc/components/shared/input_label.erb +7 -0
  408. data/views/mdc/components/slider.erb +3 -1
  409. data/views/mdc/components/stepper.erb +1 -1
  410. data/views/mdc/components/stepper/step.erb +1 -1
  411. data/views/mdc/components/switch.erb +8 -7
  412. data/views/mdc/components/tab_bar.erb +7 -1
  413. data/views/mdc/components/table.erb +26 -13
  414. data/views/mdc/components/table/checkbox.erb +6 -3
  415. data/views/mdc/components/table/column.erb +18 -0
  416. data/views/mdc/components/table/footer.erb +8 -0
  417. data/views/mdc/components/table/header.erb +5 -4
  418. data/views/mdc/components/table/pagination.erb +2 -6
  419. data/views/mdc/components/table/row.erb +5 -5
  420. data/views/mdc/components/text_area.erb +9 -11
  421. data/views/mdc/components/text_field.erb +29 -37
  422. data/views/mdc/components/tooltip.erb +2 -2
  423. data/views/mdc/components/typography.erb +7 -5
  424. data/views/mdc/components/unordered_list.erb +10 -0
  425. data/views/mdc/components/unordered_list/icon.erb +3 -0
  426. data/views/mdc/components/unordered_list/list_item.erb +7 -0
  427. data/views/mdc/layout.erb +41 -29
  428. data/views/mdc/package-lock.json +2241 -1332
  429. data/views/mdc/package.json +47 -29
  430. data/views/mdc/web.erb +4 -0
  431. data/views/mdc/webpack.config.js +13 -1
  432. metadata +228 -32
  433. data/app/demo/component_status.pom +0 -76
  434. data/lib/voom-presenters.rb +0 -9
  435. data/lib/voom/presenters-engine.rb +0 -44
  436. data/lib/voom/presenters.rb +0 -19
  437. data/public/.gitignore +0 -2
  438. data/scripts/bump.sh +0 -5
  439. data/scripts/changelog.sh +0 -5
  440. data/scripts/deploy-demo.sh +0 -3
  441. data/scripts/release.sh +0 -5
  442. data/scripts/tag.sh +0 -5
  443. data/views/mdc/assets/js/dialog-polyfill.js +0 -738
  444. data/views/mdc/assets/scss/components/icon-toggles.scss +0 -9
  445. data/views/mdc/assets/scss/components/vendor/flatpickr.min.css +0 -13
  446. data/views/mdc/body/drawer.erb +0 -18
  447. data/views/mdc/components/google_map.erb +0 -9
@@ -1,17 +1,19 @@
1
1
  export class VNavigates {
2
- constructor(options, params, event) {
3
- this.target = options.target;
4
- this.params = params;
5
- this.event = event;
6
- }
2
+ constructor(options, params, event, root) {
3
+ this.direction = params.direction;
4
+ }
7
5
 
8
- call(results) {
9
- var promiseObj = new Promise(function (resolve) {
10
- console.log("Navigating back");
11
- results.push({action: 'navigates', statusCode: 200});
12
- history.back();
13
- resolve(results);
14
- });
15
- return promiseObj;
16
- }
17
- }
6
+ call(results) {
7
+ const direction = this.direction;
8
+ return new Promise(function(resolve) {
9
+ results.push({action: 'navigates', statusCode: 200});
10
+ resolve(results);
11
+ switch (direction) {
12
+ case 'back':
13
+ window.history.back();
14
+ case 'forward':
15
+ window.history.forward();
16
+ }
17
+ });
18
+ }
19
+ }
@@ -0,0 +1,18 @@
1
+ export class VPluginEventAction {
2
+ constructor(actionType, options, params, event, root) {
3
+ this.actionType = actionType;
4
+ this.options = options;
5
+ this.params = params;
6
+ this.event = event;
7
+ this.root = root;
8
+ }
9
+
10
+ call(results) {
11
+ const actionType = this.actionType;
12
+ const options = this.options;
13
+ const params = this.params;
14
+ const event = this.event;
15
+ return document.defaultView[actionType](options, params, event,
16
+ results);
17
+ }
18
+ }
@@ -0,0 +1,21 @@
1
+ export class VPostMessage {
2
+ constructor(options, params, event, root) {
3
+ this.params = params;
4
+ this.event = event;
5
+ this.root = root;
6
+ }
7
+
8
+ call(results) {
9
+ return new Promise((resolve) => {
10
+ console.log('Post Message: ' + this.params.message);
11
+ window.parent.postMessage(this.params.message, '*');
12
+ results.push({
13
+ action: 'close_frame',
14
+ statusCode: 200,
15
+ });
16
+
17
+ // Otherwise, proceed with the next action:
18
+ return resolve(results);
19
+ });
20
+ }
21
+ }
@@ -1,22 +1,77 @@
1
- import {VSnackbar} from '../snackbar';
2
1
  import {VBase} from './base';
3
2
  import appConfig from '../../config';
3
+ import {expandParams} from './action_parameter';
4
+ import {encode} from './encode';
5
+ import {getEventTarget} from '../get_event_target';
4
6
 
5
7
  // Replaces a given element with the contents of the call to the url.
6
8
  // parameters are appended.
7
9
  export class VPosts extends VBase {
8
- constructor(options, url, params, method, event) {
9
- super(options);
10
+ constructor(options, url, params, method, event, root) {
11
+ super(options, root);
10
12
  this.url = url;
11
13
  this.params = params;
12
14
  this.method = method;
13
15
  this.event = event;
16
+ this.headers = options.headers;
14
17
  }
15
18
 
16
- call(results) {
19
+ call(results, eventParams) {
17
20
  this.clearErrors();
18
- let errors = this.validate();
19
21
  let method = this.method;
22
+
23
+ const ev = new CustomEvent('V:postStarted', {
24
+ bubbles: true,
25
+ cancelable: false,
26
+ detail: this,
27
+ composed: true,
28
+ });
29
+
30
+ this.dispatchLifecycleEvent(this.event, ev);
31
+
32
+ // Manually build the FormData.
33
+ // Passing in a <form> element (if available) would skip over
34
+ // unchecked toggle elements, which would be unexpected if the user
35
+ // has specified a value for the toggle's `off_value` attribute.
36
+ const formData = new FormData();
37
+
38
+ // NB: `inputValues` will appropriately handle `input_tag`.
39
+ for (const [name, value] of this.inputValues()) {
40
+ formData.append(name, value);
41
+ }
42
+
43
+ if (eventParams){
44
+ for (const [name, value] of Object.entries(eventParams)) {
45
+ formData.append(name, value);
46
+ }
47
+ }
48
+
49
+ // Add CSRF authenticity token if present
50
+ const csrf_meta_token = document.querySelector('meta[name=csrf-token]');
51
+ const csrf_meta_param = document.querySelector('meta[name=csrf-param]');
52
+ if (csrf_meta_token && csrf_meta_param) {
53
+ formData.append(csrf_meta_param.content, csrf_meta_token.content);
54
+ }
55
+
56
+ // Add params from presenter:
57
+ const expandedParams = expandParams(results, this.params);
58
+
59
+ for (const [name, value] of Object.entries(expandedParams)) {
60
+ formData.append(name, encode(value));
61
+ }
62
+
63
+ const paramCount = Array.from(formData).length;
64
+
65
+ if (paramCount < 1) {
66
+ console.warn(
67
+ 'Creating request with no data!'
68
+ + ' Are you sure you\'ve hooked everything up correctly?',
69
+ );
70
+ }
71
+
72
+ let errors = this.validate(formData);
73
+ console.log('Validation errors');
74
+ console.dir(errors);
20
75
  if (errors.length > 0) {
21
76
  return new Promise(function(_, reject) {
22
77
  results.push({
@@ -30,37 +85,34 @@ export class VPosts extends VBase {
30
85
  });
31
86
  }
32
87
 
33
- var FD = null;
34
- var form = this.form();
35
- if (form) {
36
- FD = new FormData(form);
37
- }
38
- else {
39
- FD = new FormData();
40
- }
41
- // Add params from presenter
42
- for (var name in this.params) {
43
- FD.append(name, this.params[name]);
44
- }
45
-
46
- var inputValues = this.inputValues(form);
47
- for (var input of inputValues) {
48
- FD.append(input[0], input[1]);
49
- }
50
-
51
- var httpRequest = new XMLHttpRequest();
52
- var url = this.url;
88
+ const httpRequest = new XMLHttpRequest();
89
+ const url = this.url;
90
+ const callHeaders = this.headers;
91
+ const root = this.root;
92
+ const vEvent = this;
53
93
  if (!httpRequest) {
54
94
  throw new Error(
55
95
  'Cannot talk to server! Please upgrade your browser to one that supports XMLHttpRequest.');
56
96
  }
57
97
 
58
- let snackbarCallback = function(contentType, response) {
59
- const snackbar = document.querySelector('.mdc-snackbar').vComponent;
60
- if (contentType && contentType.indexOf('application/json') !== -1) {
61
- const messages = JSON.parse(response).messages;
62
- if (snackbar && messages && messages.snackbar) {
98
+ if (formData.has('rich_text_payload')) {
99
+ callHeaders['X-Rich-Text-Payload'] = true;
100
+ }
101
+
102
+ const snackbarCallback = function(contentType, response) {
103
+ const element = root.querySelector('.mdc-snackbar');
104
+
105
+ if (!(element && element.vComponent)) {
106
+ return;
107
+ }
108
+
109
+ const snackbar = element.vComponent;
110
+
111
+ if (contentType && contentType.includes('application/json')) {
112
+ const messages = JSON.parse(response).message;
113
+ if (messages && messages.snackbar) {
63
114
  const message = messages.snackbar.join('<br/>');
115
+
64
116
  if (message !== '') {
65
117
  snackbar.display(message);
66
118
  }
@@ -68,60 +120,75 @@ export class VPosts extends VBase {
68
120
  }
69
121
  };
70
122
 
71
- return new Promise(function(resolve, reject) {
72
- httpRequest.onreadystatechange = function(event) {
123
+ return new Promise((resolve, reject) => {
124
+ httpRequest.onreadystatechange = (event) => {
73
125
  if (httpRequest.readyState === XMLHttpRequest.DONE) {
74
- const contentType = this.getResponseHeader('content-type');
75
- console.log(httpRequest.status + ':' + contentType);
126
+ const contentType = httpRequest.getResponseHeader('content-type');
127
+ console.debug(httpRequest.status + ':' + contentType);
128
+
129
+ const result = {
130
+ action: 'posts',
131
+ method: httpRequest.method,
132
+ statusCode: httpRequest.status,
133
+ contentType: contentType,
134
+ content: httpRequest.responseText,
135
+ responseURL: httpRequest.responseURL,
136
+ };
137
+
138
+
139
+ var postFailed = httpRequest.status >= 400;
140
+ const ev = new CustomEvent(postFailed ? 'V:postFailed' : 'V:postSucceeded', {
141
+ bubbles: true,
142
+ cancelable: false,
143
+ detail: {event: vEvent, result: result},
144
+ composed: true,
145
+ });
146
+ this.dispatchLifecycleEvent(this.event, ev);
147
+
76
148
  if (httpRequest.status >= 200 && httpRequest.status < 300) {
77
- results.push({
78
- action: 'posts',
79
- method: this.method,
80
- statusCode: httpRequest.status,
81
- contentType: contentType,
82
- content: httpRequest.responseText,
83
- responseURL: httpRequest.responseURL,
84
- });
149
+ results.push(result);
85
150
  snackbarCallback(contentType,
86
151
  httpRequest.responseText);
87
152
  resolve(results);
153
+ }
88
154
  // Response is an html error page
89
- } else if (contentType && contentType.indexOf('text/html') !== -1){
90
- document.open(contentType);
91
- document.write(httpRequest.responseText);
92
- document.close();
93
- results.push({
94
- action: 'posts',
95
- method: this.method,
96
- statusCode: httpRequest.status,
97
- contentType: contentType,
98
- content: httpRequest.responseText,
99
- responseURL: httpRequest.responseURL,
100
- });
155
+ else if (contentType && contentType.indexOf('text/html') !== -1) {
156
+ root.open(contentType);
157
+ root.write(httpRequest.responseText);
158
+ root.close();
159
+ results.push(result);
101
160
  resolve(results);
102
- } else {
103
- results.push({
104
- action: 'posts',
105
- method: this.method,
106
- statusCode: httpRequest.status,
107
- contentType: contentType,
108
- content: httpRequest.responseText,
109
- });
161
+ }
162
+ else {
163
+ results.push(result);
110
164
  reject(results);
111
165
  }
166
+ const evFinished = new CustomEvent('V:postFinished', {
167
+ bubbles: true,
168
+ cancelable: false,
169
+ detail: {event: vEvent, result: result},
170
+ composed: true,
171
+ });
172
+ this.dispatchLifecycleEvent(this.event, evFinished);
112
173
  }
113
174
  };
114
175
  // Set up our request
115
176
  httpRequest.open(method, url);
116
177
 
117
- const headers = appConfig.get('request.headers.POST', {});
178
+ const configHeaders = appConfig.get('request.headers.POST', {});
118
179
 
119
- for (const [key, value] of Object.entries(headers)) {
180
+ for (const [key, value] of Object.entries(configHeaders)) {
120
181
  httpRequest.setRequestHeader(key, value);
121
182
  }
122
183
 
184
+ if (callHeaders) {
185
+ for (const [key, value] of Object.entries(callHeaders)) {
186
+ httpRequest.setRequestHeader(key, value);
187
+ }
188
+ }
189
+
123
190
  // Send our FormData object; HTTP headers are set automatically
124
- httpRequest.send(FD);
191
+ httpRequest.send(formData);
125
192
  });
126
193
  }
127
194
 
@@ -136,4 +203,19 @@ export class VPosts extends VBase {
136
203
  }
137
204
  return null;
138
205
  }
206
+
207
+ dispatchLifecycleEvent(domEvent, lifecycleEvent) {
208
+ let target = getEventTarget(domEvent);
209
+
210
+ if (!target || !target.isConnected) {
211
+ // If an action has hidden `target` or its parent (via e.g.
212
+ // `hides :some_element`), it will no longer be connected to the DOM
213
+ // and its dispatched lifecycle events won't make it up to the root.
214
+ // Instead, dispatch straight from the root instead of bubbling up
215
+ // from the DOM event's target.
216
+ target = this.root;
217
+ }
218
+
219
+ return target.dispatchEvent(lifecycleEvent);
220
+ }
139
221
  }
@@ -0,0 +1,67 @@
1
+ import {VBase} from './base';
2
+ import {VDialog} from './dialog';
3
+
4
+ const HALT_PATTERNS = [/close/i, /halt/i, /stay/i, /stop/i, /cancel/i];
5
+
6
+ /**
7
+ * shouldHalt determines whether the specified action should halt execution
8
+ * of further actions.
9
+ * @param {string} action
10
+ * @return {bool}
11
+ */
12
+ function shouldHalt(action) {
13
+ for (const pattern of HALT_PATTERNS) {
14
+ if (pattern.test(action)) {
15
+ return true;
16
+ }
17
+ }
18
+
19
+ return false;
20
+ }
21
+
22
+ export class VPromptIfDirty extends VBase {
23
+ constructor(options, params, event, root) {
24
+ super(options, root);
25
+
26
+ this.targetId = options.target;
27
+ this.params = params;
28
+ this.event = event;
29
+ this.dialog = new VDialog(this.options, this.params, this.event, root);
30
+ }
31
+
32
+ call(results) {
33
+ // We're in a dirty state if any dirtyable inputs are dirty:
34
+ const dirty = this.inputComponents()
35
+ .filter((comp) => comp.isDirty)
36
+ .map((comp) => comp.isDirty())
37
+ .some(Boolean);
38
+
39
+ results.push({
40
+ action: 'prompt_if_dirty',
41
+ statusCode: 412,
42
+ squelch: true,
43
+ dirty: dirty,
44
+ });
45
+
46
+ // If everything's clean, skip the dialog entirely and proceed:
47
+ if (!dirty) {
48
+ return new Promise((resolve, _) => resolve(results));
49
+ }
50
+
51
+ // Otherwise, invoke the specified dialog and capture its result:
52
+ return new Promise((resolve, reject) => {
53
+ return this.dialog.call(results).then((results) => {
54
+ const result = results.pop();
55
+ const action = result.dialogAction;
56
+
57
+ // If the dialog's result indicates halting, bail out:
58
+ if (shouldHalt(action)) {
59
+ return reject(results);
60
+ }
61
+
62
+ // Otherwise, proceed with the next action:
63
+ return resolve(results);
64
+ });
65
+ });
66
+ }
67
+ }
@@ -1,20 +1,21 @@
1
1
  export class VRemoves {
2
- constructor(options, params, event) {
2
+ constructor(options, params, event, root) {
3
3
  this.target = options.target;
4
4
  this.ids = params.ids;
5
5
  this.event = event;
6
+ this.root = root;
6
7
  }
7
8
 
8
9
  call(results) {
9
- let ids = this.ids;
10
- var promiseObj = new Promise(function (resolve) {
10
+ const ids = this.ids;
11
+ const root = this.root;
12
+ return new Promise(function(resolve) {
11
13
  results.push({action: 'removes', statusCode: 200});
12
- for (const id of ids){
13
- let elem = document.getElementById(id);
14
+ for (const id of ids) {
15
+ const elem = root.getElementById(id);
14
16
  elem.parentNode.removeChild(elem);
15
17
  }
16
18
  resolve(results);
17
19
  });
18
- return promiseObj;
19
20
  }
20
21
  }
@@ -1,81 +1,135 @@
1
- import {VSnackbar} from '../snackbar';
1
+ import {expandParams} from './action_parameter';
2
2
  import {VBase} from './base';
3
3
  import {initialize} from '../initialize';
4
+ import {uninitialize} from '../uninitialize';
5
+
6
+ const MOUSE_DELAY_AMOUNT = 0; // ms
7
+ const KEYBOARD_DELAY_AMOUNT = 500; // ms
8
+
9
+ // Create a NodeList from raw HTML.
10
+ // Whitespace is trimmed to avoid creating superfluous text nodes.
11
+ function htmlToNodes(html, root = document) {
12
+ const template = document.createElement('template');
13
+
14
+ template.innerHTML = html.trim();
15
+
16
+ return template.content.children;
17
+ }
18
+
19
+ function assertXHRSupport() {
20
+ if (typeof window.XMLHttpRequest !== 'function') {
21
+ throw new Error('Support for XMLHttpRequest is required');
22
+ }
23
+ }
24
+
25
+ function delayAmount(event) {
26
+ if (typeof window['InputEvent'] === 'function') {
27
+ return event instanceof InputEvent ? KEYBOARD_DELAY_AMOUNT : MOUSE_DELAY_AMOUNT;
28
+ }
29
+
30
+ return event instanceof MouseEvent ? MOUSE_DELAY_AMOUNT : KEYBOARD_DELAY_AMOUNT;
31
+ }
4
32
 
5
33
  // Replaces a given element with the contents of the call to the url.
6
34
  // parameters are appended.
7
35
  export class VReplaces extends VBase {
8
- constructor(options, url, params, event) {
9
- super(options);
36
+ constructor(options, url, params, event, root) {
37
+ super(options, root);
38
+
39
+ assertXHRSupport();
40
+
10
41
  this.element_id = options.target;
11
42
  this.url = url;
12
43
  this.params = params;
13
44
  this.event = event;
14
45
  }
15
46
 
16
- call(results) {
47
+ call(results, eventParams=[]) {
17
48
  this.clearErrors();
18
- console.log('The event: '+this.event);
19
- var httpRequest = new XMLHttpRequest();
20
- if (!httpRequest) {
21
- throw new Error('Cannot talk to server! Please upgrade your browser to one that supports XMLHttpRequest.');
22
- }
23
- var elementId = this.element_id;
24
- var nodeToReplace = document.getElementById(elementId);
25
- var url = this.buildURL(this.url, this.params, this.inputValues(), [['grid_nesting', this.options.grid_nesting]]);
26
- let delayAmt = this.event instanceof InputEvent ? 500 : 0;
27
-
28
- var promiseObj = new Promise(function (resolve, reject) {
49
+
50
+ const httpRequest = new XMLHttpRequest();
51
+ const root = this.root;
52
+ const elementId = this.element_id;
53
+ const nodeToReplace = root.getElementById(elementId);
54
+ const expandedParams = expandParams(results, this.params);
55
+
56
+ const inputVals = this.inputValues().filter((vals) => {
57
+ return this.options.ignore_input_values.indexOf(vals[0]) == -1;
58
+ });
59
+ const paramsCollection = [expandedParams, eventParams, inputVals, [['grid_nesting', this.options.grid_nesting]]];
60
+
61
+ const url = this.buildURL(this.url, ...paramsCollection);
62
+ const delayAmt = delayAmount(this.event);
63
+
64
+ return new Promise(function(resolve, reject) {
29
65
  if (!nodeToReplace) {
30
66
  let msg = 'Unable to located node: \'' + elementId + '\'' +
31
- ' This usually the result of issuing a replaces action and specifying a element id that does not currently exist on the page.';
67
+ ' This usually the result of issuing a replaces action ' +
68
+ 'and specifying a element id that does not currently ' +
69
+ 'exist on the page.';
32
70
  console.error(msg);
33
71
  results.push({
34
72
  action: 'replaces',
35
73
  statusCode: 500,
36
74
  contentType: 'v/errors',
37
- content: {exception: msg}
75
+ content: {exception: msg},
38
76
  });
39
77
  reject(results);
40
78
  }
41
79
  else {
42
80
  clearTimeout(nodeToReplace.vTimeout);
43
- nodeToReplace.vTimeout = setTimeout(function(){
44
- httpRequest.onreadystatechange = function () {
81
+ nodeToReplace.vTimeout = setTimeout(function() {
82
+ httpRequest.onreadystatechange = function() {
45
83
  if (httpRequest.readyState === XMLHttpRequest.DONE) {
46
- console.log(httpRequest.status + ':' + this.getResponseHeader('content-type'));
84
+ console.debug(httpRequest.status + ':' +
85
+ this.getResponseHeader('content-type'));
47
86
  if (httpRequest.status === 200) {
48
- let nodeToReplace = document.getElementById(elementId);
49
- nodeToReplace.outerHTML = httpRequest.responseText;
50
- var newNode = document.getElementById(elementId);
51
- initialize(newNode);
87
+ // NodeList.childNodes is "live", meaning DOM
88
+ // changes to its entries will mutate the list
89
+ // itself.
90
+ // (see: https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
91
+ // Array.from clones the entries, creating a
92
+ // "dead" list.
93
+ const newNodes = Array.from(htmlToNodes(
94
+ httpRequest.responseText,
95
+ root
96
+ ));
97
+
98
+ uninitialize(nodeToReplace);
99
+
100
+ nodeToReplace.replaceWith(...newNodes);
101
+
102
+ for (const node of newNodes) {
103
+ initialize(node);
104
+ }
52
105
 
53
106
  results.push({
54
107
  action: 'replaces',
55
108
  statusCode: httpRequest.status,
56
- contentType: this.getResponseHeader('content-type'),
57
- content: httpRequest.responseText
109
+ contentType: this.getResponseHeader(
110
+ 'content-type'),
111
+ content: httpRequest.responseText,
58
112
  });
59
113
  resolve(results);
60
- } else {
114
+ }
115
+ else {
61
116
  results.push({
62
117
  action: 'replaces',
63
118
  statusCode: httpRequest.status,
64
- contentType: this.getResponseHeader('content-type'),
65
- content: httpRequest.responseText
119
+ contentType: this.getResponseHeader(
120
+ 'content-type'),
121
+ content: httpRequest.responseText,
66
122
  });
67
123
  reject(results);
68
124
  }
69
125
  }
70
- }
71
- console.log('GET:' + url);
126
+ };
127
+ console.debug('GET:' + url);
72
128
  httpRequest.open('GET', url, true);
73
129
  httpRequest.setRequestHeader('X-NO-LAYOUT', true);
74
130
  httpRequest.send();
75
131
  }, delayAmt);
76
132
  }
77
133
  });
78
- return promiseObj;
79
134
  }
80
-
81
135
  }