releaf-core 0.2.1

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 (288) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +24 -0
  3. data/app/assets/fonts/releaf/RobotoRegular_normal_400.ttf +0 -0
  4. data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff +0 -0
  5. data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff2 +0 -0
  6. data/app/assets/images/releaf/icons/apple-touch-icon-114x114-precomposed.png +0 -0
  7. data/app/assets/images/releaf/icons/apple-touch-icon-152x152-precomposed.png +0 -0
  8. data/app/assets/images/releaf/icons/apple-touch-icon-72x72-precomposed.png +0 -0
  9. data/app/assets/images/releaf/icons/favicon.ico +0 -0
  10. data/app/assets/images/releaf/icons/favicon.png +0 -0
  11. data/app/assets/images/releaf/icons/msapplication-tile-144x144.png +0 -0
  12. data/app/assets/images/releaf/logo-login.png +0 -0
  13. data/app/assets/images/releaf/logo.png +0 -0
  14. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/hidpi/mediaembed.png +0 -0
  15. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/mediaembed.png +0 -0
  16. data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/en.js +12 -0
  17. data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/es.js +12 -0
  18. data/app/assets/javascripts/ckeditor/plugins/mediaembed/plugin.js +63 -0
  19. data/app/assets/javascripts/releaf/3rd_party/jquery-ui-timepicker-addon.js +1882 -0
  20. data/app/assets/javascripts/releaf/3rd_party/jquery.magnific-popup.min.js +4 -0
  21. data/app/assets/javascripts/releaf/application.js +13 -0
  22. data/app/assets/javascripts/releaf/include/ajax.js +66 -0
  23. data/app/assets/javascripts/releaf/include/ajaxbox.js +179 -0
  24. data/app/assets/javascripts/releaf/include/dialogs.js +13 -0
  25. data/app/assets/javascripts/releaf/include/field.type_associated_set.js +32 -0
  26. data/app/assets/javascripts/releaf/include/field.type_date_or_datetime_or_time.js +73 -0
  27. data/app/assets/javascripts/releaf/include/field.type_richtext.js +188 -0
  28. data/app/assets/javascripts/releaf/include/loader.js +45 -0
  29. data/app/assets/javascripts/releaf/include/localization.js +213 -0
  30. data/app/assets/javascripts/releaf/include/nested_fields.js +295 -0
  31. data/app/assets/javascripts/releaf/include/notifications.js +267 -0
  32. data/app/assets/javascripts/releaf/include/pagination.js +19 -0
  33. data/app/assets/javascripts/releaf/include/profile_settings.js +28 -0
  34. data/app/assets/javascripts/releaf/include/remote_validator.js +437 -0
  35. data/app/assets/javascripts/releaf/include/search.js +140 -0
  36. data/app/assets/javascripts/releaf/include/sidebar.js +149 -0
  37. data/app/assets/javascripts/releaf/include/sortable.js +69 -0
  38. data/app/assets/javascripts/releaf/include/toolbox.js +221 -0
  39. data/app/assets/javascripts/releaf/include/url_builder.js +193 -0
  40. data/app/assets/stylesheets/releaf/application.scss +9 -0
  41. data/app/assets/stylesheets/releaf/environment/extras.scss +11 -0
  42. data/app/assets/stylesheets/releaf/environment/functions/units.scss +12 -0
  43. data/app/assets/stylesheets/releaf/environment/functions.scss +1 -0
  44. data/app/assets/stylesheets/releaf/environment/mixins/blocks.scss +133 -0
  45. data/app/assets/stylesheets/releaf/environment/mixins/elements.scss +64 -0
  46. data/app/assets/stylesheets/releaf/environment/mixins/text.scss +61 -0
  47. data/app/assets/stylesheets/releaf/environment/mixins.scss +3 -0
  48. data/app/assets/stylesheets/releaf/environment/variables/colors.scss +93 -0
  49. data/app/assets/stylesheets/releaf/environment/variables/dimensions.scss +0 -0
  50. data/app/assets/stylesheets/releaf/environment/variables/magnific-popup.scss +6 -0
  51. data/app/assets/stylesheets/releaf/environment/variables.scss +5 -0
  52. data/app/assets/stylesheets/releaf/environment.scss +4 -0
  53. data/app/assets/stylesheets/releaf/layout/base.scss +32 -0
  54. data/app/assets/stylesheets/releaf/layout/breadcrumbs.scss +47 -0
  55. data/app/assets/stylesheets/releaf/layout/buttons.scss +107 -0
  56. data/app/assets/stylesheets/releaf/layout/deprecated.scss +29 -0
  57. data/app/assets/stylesheets/releaf/layout/dialogs.scss +138 -0
  58. data/app/assets/stylesheets/releaf/layout/errors.scss +28 -0
  59. data/app/assets/stylesheets/releaf/layout/extras.scss +10 -0
  60. data/app/assets/stylesheets/releaf/layout/fields.scss +305 -0
  61. data/app/assets/stylesheets/releaf/layout/fonts.scss +16 -0
  62. data/app/assets/stylesheets/releaf/layout/footer.scss +80 -0
  63. data/app/assets/stylesheets/releaf/layout/forms.scss +23 -0
  64. data/app/assets/stylesheets/releaf/layout/header.scss +55 -0
  65. data/app/assets/stylesheets/releaf/layout/icons.scss +4 -0
  66. data/app/assets/stylesheets/releaf/layout/images.scss +4 -0
  67. data/app/assets/stylesheets/releaf/layout/links.scss +7 -0
  68. data/app/assets/stylesheets/releaf/layout/localization.scss +79 -0
  69. data/app/assets/stylesheets/releaf/layout/main.scss +43 -0
  70. data/app/assets/stylesheets/releaf/layout/notifications.scss +67 -0
  71. data/app/assets/stylesheets/releaf/layout/pagination.scss +18 -0
  72. data/app/assets/stylesheets/releaf/layout/search.scss +70 -0
  73. data/app/assets/stylesheets/releaf/layout/sections.scss +138 -0
  74. data/app/assets/stylesheets/releaf/layout/sidebar.scss +306 -0
  75. data/app/assets/stylesheets/releaf/layout/tables.scss +99 -0
  76. data/app/assets/stylesheets/releaf/layout/text.scss +31 -0
  77. data/app/assets/stylesheets/releaf/layout/toolboxes.scss +69 -0
  78. data/app/assets/stylesheets/releaf/layout.scss +35 -0
  79. data/app/assets/stylesheets/releaf/vendor/magnific-popup/main.scss +596 -0
  80. data/app/assets/stylesheets/releaf/vendor/magnific-popup/settings.scss +45 -0
  81. data/app/builders/releaf/builders/association_reflector.rb +58 -0
  82. data/app/builders/releaf/builders/base.rb +80 -0
  83. data/app/builders/releaf/builders/collection.rb +8 -0
  84. data/app/builders/releaf/builders/confirm_destroy_dialog_builder.rb +25 -0
  85. data/app/builders/releaf/builders/confirm_dialog_builder.rb +54 -0
  86. data/app/builders/releaf/builders/edit_builder.rb +66 -0
  87. data/app/builders/releaf/builders/form_builder.rb +594 -0
  88. data/app/builders/releaf/builders/index_builder.rb +118 -0
  89. data/app/builders/releaf/builders/orderer.rb +5 -0
  90. data/app/builders/releaf/builders/page/header_builder.rb +70 -0
  91. data/app/builders/releaf/builders/page/layout_builder.rb +155 -0
  92. data/app/builders/releaf/builders/page/menu_builder.rb +140 -0
  93. data/app/builders/releaf/builders/pagination_builder.rb +107 -0
  94. data/app/builders/releaf/builders/refused_destroy_dialog_builder.rb +68 -0
  95. data/app/builders/releaf/builders/resource.rb +9 -0
  96. data/app/builders/releaf/builders/resource_dialog.rb +8 -0
  97. data/app/builders/releaf/builders/resource_view.rb +54 -0
  98. data/app/builders/releaf/builders/show_builder.rb +3 -0
  99. data/app/builders/releaf/builders/table_builder.rb +280 -0
  100. data/app/builders/releaf/builders/tags/releaf_associated_set_field.rb +40 -0
  101. data/app/builders/releaf/builders/template.rb +8 -0
  102. data/app/builders/releaf/builders/toolbox.rb +23 -0
  103. data/app/builders/releaf/builders/toolbox_builder.rb +27 -0
  104. data/app/builders/releaf/builders/view.rb +132 -0
  105. data/app/builders/releaf/builders.rb +38 -0
  106. data/app/builders/releaf/core/settings/form_builder.rb +21 -0
  107. data/app/builders/releaf/core/settings/table_builder.rb +11 -0
  108. data/app/controllers/concerns/releaf/breadcrumbs.rb +42 -0
  109. data/app/controllers/concerns/releaf/richtext_attachments.rb +20 -0
  110. data/app/controllers/releaf/base_controller.rb +458 -0
  111. data/app/controllers/releaf/core/errors_controller.rb +5 -0
  112. data/app/controllers/releaf/core/settings_controller.rb +50 -0
  113. data/app/helpers/releaf/application_helper.rb +53 -0
  114. data/app/helpers/releaf/button_helper.rb +50 -0
  115. data/app/helpers/releaf/javascript_helper.rb +75 -0
  116. data/app/lib/releaf/core/assets_resolver.rb +58 -0
  117. data/app/lib/releaf/core/default_searchable_fields.rb +43 -0
  118. data/app/lib/releaf/core/error_formatter.rb +103 -0
  119. data/app/lib/releaf/core/item_orderer.rb +102 -0
  120. data/app/lib/releaf/core/resource_base.rb +66 -0
  121. data/app/lib/releaf/core/resource_fields.rb +6 -0
  122. data/app/lib/releaf/core/resource_params.rb +47 -0
  123. data/app/lib/releaf/core/resource_table_fields.rb +10 -0
  124. data/app/lib/releaf/core/resource_utilities.rb +36 -0
  125. data/app/lib/releaf/core/responders/access_denied_responder.rb +9 -0
  126. data/app/lib/releaf/core/responders/after_save_responder.rb +28 -0
  127. data/app/lib/releaf/core/responders/confirm_destroy_responder.rb +13 -0
  128. data/app/lib/releaf/core/responders/destroy_responder.rb +10 -0
  129. data/app/lib/releaf/core/responders/error_responder.rb +9 -0
  130. data/app/lib/releaf/core/responders/feature_disabled_responder.rb +9 -0
  131. data/app/lib/releaf/core/responders/page_not_found_responder.rb +9 -0
  132. data/app/lib/releaf/core/responders.rb +31 -0
  133. data/app/lib/releaf/core/search.rb +147 -0
  134. data/app/lib/releaf/core/template_field_type_mapper.rb +127 -0
  135. data/app/models/releaf/richtext_attachment.rb +6 -0
  136. data/app/models/releaf/settings.rb +27 -0
  137. data/app/views/layouts/releaf/admin.html.erb +1 -0
  138. data/app/views/releaf/base/confirm_destroy.ruby +1 -0
  139. data/app/views/releaf/base/create_releaf_richtext_attachment.haml +1 -0
  140. data/app/views/releaf/base/edit.ruby +1 -0
  141. data/app/views/releaf/base/index.ruby +1 -0
  142. data/app/views/releaf/base/new.ruby +1 -0
  143. data/app/views/releaf/base/refused_destroy.ruby +1 -0
  144. data/app/views/releaf/base/show.ruby +1 -0
  145. data/app/views/releaf/base/toolbox.ruby +1 -0
  146. data/app/views/releaf/error_pages/_error.html.haml +10 -0
  147. data/app/views/releaf/error_pages/access_denied.html.haml +1 -0
  148. data/app/views/releaf/error_pages/feature_disabled.html.haml +1 -0
  149. data/app/views/releaf/error_pages/page_not_found.html.haml +2 -0
  150. data/lib/generators/dummy/install_generator.rb +18 -0
  151. data/lib/generators/dummy/templates/builders/admin/books/form_builder.rb +13 -0
  152. data/lib/generators/dummy/templates/builders/admin/books/index_builder.rb +30 -0
  153. data/lib/generators/dummy/templates/builders/admin/books/table_builder.rb +7 -0
  154. data/lib/generators/dummy/templates/builders/admin/nodes/form_builder.rb +7 -0
  155. data/lib/generators/dummy/templates/config/routes.rb +19 -0
  156. data/lib/generators/dummy/templates/controllers/admin/authors_controller.rb +12 -0
  157. data/lib/generators/dummy/templates/controllers/admin/books_controller.rb +17 -0
  158. data/lib/generators/dummy/templates/controllers/admin/chapters_controller.rb +3 -0
  159. data/lib/generators/dummy/templates/controllers/admin/publishers_controller.rb +3 -0
  160. data/lib/generators/dummy/templates/controllers/application_controller.rb +39 -0
  161. data/lib/generators/dummy/templates/controllers/concerns/.keep +0 -0
  162. data/lib/generators/dummy/templates/controllers/concerns/node_controller.rb +37 -0
  163. data/lib/generators/dummy/templates/controllers/contacts_controller.rb +3 -0
  164. data/lib/generators/dummy/templates/controllers/home_pages_controller.rb +3 -0
  165. data/lib/generators/dummy/templates/controllers/text_pages_controller.rb +3 -0
  166. data/lib/generators/dummy/templates/initializers/releaf.rb +35 -0
  167. data/lib/generators/dummy/templates/migrations/create_authors.rb +14 -0
  168. data/lib/generators/dummy/templates/migrations/create_banners.rb +11 -0
  169. data/lib/generators/dummy/templates/migrations/create_book_sequels.rb +14 -0
  170. data/lib/generators/dummy/templates/migrations/create_books.rb +27 -0
  171. data/lib/generators/dummy/templates/migrations/create_bundles.rb +7 -0
  172. data/lib/generators/dummy/templates/migrations/create_chapters.rb +13 -0
  173. data/lib/generators/dummy/templates/migrations/create_home_pages.rb +9 -0
  174. data/lib/generators/dummy/templates/migrations/create_node_extra_fields.rb +5 -0
  175. data/lib/generators/dummy/templates/migrations/create_publishers.rb +8 -0
  176. data/lib/generators/dummy/templates/migrations/create_text_pages.rb +9 -0
  177. data/lib/generators/dummy/templates/models/author.rb +10 -0
  178. data/lib/generators/dummy/templates/models/banner.rb +5 -0
  179. data/lib/generators/dummy/templates/models/book.rb +19 -0
  180. data/lib/generators/dummy/templates/models/book_sequel.rb +4 -0
  181. data/lib/generators/dummy/templates/models/bundle.rb +17 -0
  182. data/lib/generators/dummy/templates/models/chapter.rb +7 -0
  183. data/lib/generators/dummy/templates/models/home_page.rb +5 -0
  184. data/lib/generators/dummy/templates/models/node.rb +10 -0
  185. data/lib/generators/dummy/templates/models/publisher.rb +9 -0
  186. data/lib/generators/dummy/templates/models/text_page.rb +5 -0
  187. data/lib/generators/dummy/templates/views/contacts/show.html.haml +1 -0
  188. data/lib/generators/dummy/templates/views/home_pages/show.haml +1 -0
  189. data/lib/generators/dummy/templates/views/layouts/application.html.haml +22 -0
  190. data/lib/generators/dummy/templates/views/text_pages/show.haml +1 -0
  191. data/lib/generators/releaf/install_generator.rb +93 -0
  192. data/lib/generators/releaf/templates/initializers/haml.rb +1 -0
  193. data/lib/generators/releaf/templates/initializers/releaf.rb +30 -0
  194. data/lib/generators/releaf/templates/migrations/create_releaf_nodes.rb +28 -0
  195. data/lib/generators/releaf/templates/migrations/create_releaf_permissions.rb +12 -0
  196. data/lib/generators/releaf/templates/migrations/create_releaf_richtext_attachments.rb +12 -0
  197. data/lib/generators/releaf/templates/migrations/create_releaf_roles.rb +9 -0
  198. data/lib/generators/releaf/templates/migrations/create_releaf_settings.rb +17 -0
  199. data/lib/generators/releaf/templates/migrations/create_releaf_translations.rb +21 -0
  200. data/lib/generators/releaf/templates/migrations/create_releaf_users.rb +52 -0
  201. data/lib/generators/releaf/templates/models/node.rb +3 -0
  202. data/lib/generators/releaf/templates/seeds/seeds.rb +54 -0
  203. data/lib/releaf/core/application.rb +17 -0
  204. data/lib/releaf/core/builders_autoload.rb +27 -0
  205. data/lib/releaf/core/component.rb +9 -0
  206. data/lib/releaf/core/configuration.rb +101 -0
  207. data/lib/releaf/core/engine.rb +35 -0
  208. data/lib/releaf/core/exceptions.rb +38 -0
  209. data/lib/releaf/core/route_mapper.rb +59 -0
  210. data/lib/releaf/core/settings_ui_component.rb +7 -0
  211. data/lib/releaf/core/validation_error_codes.rb +36 -0
  212. data/lib/releaf/version.rb +3 -0
  213. data/lib/releaf-core.rb +14 -0
  214. data/lib/tasks/releaf_tasks.rake +4 -0
  215. data/releaf-core.gemspec +35 -0
  216. data/spec/builders/builders/association_reflector_spec.rb +138 -0
  217. data/spec/builders/builders/base_spec.rb +276 -0
  218. data/spec/builders/builders/collection_spec.rb +18 -0
  219. data/spec/builders/builders/confirm_destroy_dialog_builder_spec.rb +71 -0
  220. data/spec/builders/builders/confirm_dialog_builder_spec.rb +105 -0
  221. data/spec/builders/builders/edit_builder_spec.rb +215 -0
  222. data/spec/builders/builders/form_builder_spec.rb +562 -0
  223. data/spec/builders/builders/index_builder_spec.rb +345 -0
  224. data/spec/builders/builders/orderer_spec.rb +22 -0
  225. data/spec/builders/builders/page/header_builder_spec.rb +143 -0
  226. data/spec/builders/builders/page/layout_builder_spec.rb +73 -0
  227. data/spec/builders/builders/page/menu_builder_spec.rb +160 -0
  228. data/spec/builders/builders/pagination_builder_spec.rb +330 -0
  229. data/spec/builders/builders/resource_dialog_spec.rb +21 -0
  230. data/spec/builders/builders/resource_view_spec.rb +158 -0
  231. data/spec/builders/builders/show_builder_spec.rb +7 -0
  232. data/spec/builders/builders/table_builder_spec.rb +638 -0
  233. data/spec/builders/builders/template_spec.rb +12 -0
  234. data/spec/builders/builders/toolbox_builder_spec.rb +67 -0
  235. data/spec/builders/builders/toolbox_spec.rb +48 -0
  236. data/spec/builders/builders/view_spec.rb +281 -0
  237. data/spec/builders/builders_spec.rb +134 -0
  238. data/spec/builders/core/settings/form_builder_spec.rb +69 -0
  239. data/spec/builders/core/settings/table_builder_spec.rb +21 -0
  240. data/spec/controllers/concerns/releaf/richtext_attachments_spec.rb +51 -0
  241. data/spec/controllers/releaf/base_controller_spec.rb +447 -0
  242. data/spec/controllers/releaf/core/settings_controller_spec.rb +31 -0
  243. data/spec/features/ajaxbox_spec.rb +111 -0
  244. data/spec/features/authorization_spec.rb +50 -0
  245. data/spec/features/dragonfly_integration_spec.rb +24 -0
  246. data/spec/features/edit_actions_spec.rb +142 -0
  247. data/spec/features/errors_spec.rb +29 -0
  248. data/spec/features/index_actions_spec.rb +85 -0
  249. data/spec/features/index_table_spec.rb +32 -0
  250. data/spec/features/menu_spec.rb +71 -0
  251. data/spec/features/richtext_attachments_spec.rb +64 -0
  252. data/spec/features/richtext_embed_spec.rb +29 -0
  253. data/spec/features/richtext_spec.rb +19 -0
  254. data/spec/features/search_spec.rb +825 -0
  255. data/spec/features/settings_spec.rb +38 -0
  256. data/spec/features/title_spec.rb +13 -0
  257. data/spec/fixtures/common_fields.yml +17 -0
  258. data/spec/fixtures/cs.png +0 -0
  259. data/spec/fixtures/time.formats.xlsx +0 -0
  260. data/spec/fixtures/unicorn.jpg +0 -0
  261. data/spec/helpers/application_helper_spec.rb +75 -0
  262. data/spec/helpers/button_helper_spec.rb +146 -0
  263. data/spec/lib/releaf/core/application_spec.rb +42 -0
  264. data/spec/lib/releaf/core/assets_resolver_spec.rb +113 -0
  265. data/spec/lib/releaf/core/configuration_spec.rb +230 -0
  266. data/spec/lib/releaf/core/default_searchable_fields_spec.rb +161 -0
  267. data/spec/lib/releaf/core/error_formatter_spec.rb +242 -0
  268. data/spec/lib/releaf/core/item_orderer_spec.rb +142 -0
  269. data/spec/lib/releaf/core/resource_base_spec.rb +174 -0
  270. data/spec/lib/releaf/core/resource_fields_spec.rb +12 -0
  271. data/spec/lib/releaf/core/resource_params_spec.rb +117 -0
  272. data/spec/lib/releaf/core/resource_table_fields_spec.rb +18 -0
  273. data/spec/lib/releaf/core/resource_utilities_spec.rb +87 -0
  274. data/spec/lib/releaf/core/responders/access_denied_responder_spec.rb +12 -0
  275. data/spec/lib/releaf/core/responders/after_save_responder_spec.rb +102 -0
  276. data/spec/lib/releaf/core/responders/confirm_destroy_responder_spec.rb +26 -0
  277. data/spec/lib/releaf/core/responders/destroy_responder_spec.rb +30 -0
  278. data/spec/lib/releaf/core/responders/error_responder_spec.rb +26 -0
  279. data/spec/lib/releaf/core/responders/feature_disabled_responder_spec.rb +12 -0
  280. data/spec/lib/releaf/core/responders/page_not_found_responder_spec.rb +12 -0
  281. data/spec/lib/releaf/core/responders_spec.rb +60 -0
  282. data/spec/lib/releaf/core/template_field_type_mapper_spec.rb +311 -0
  283. data/spec/lib/validation_error_codes_spec.rb +56 -0
  284. data/spec/misc/factories_spec.rb +43 -0
  285. data/spec/models/settings_spec.rb +58 -0
  286. data/spec/routing/route_mapper_spec.rb +185 -0
  287. data/spec/rspec_helpers/test_helpers_spec.rb +20 -0
  288. metadata +657 -0
@@ -0,0 +1,267 @@
1
+ jQuery(function()
2
+ {
3
+ var body = jQuery('body');
4
+
5
+ var container = body.children('.notifications').first();
6
+
7
+ var icon_base_class = 'icon fa';
8
+
9
+ var icons_by_type =
10
+ {
11
+ info : 'fa-info',
12
+ success : 'fa-check',
13
+ error : 'fa-times-circle'
14
+ };
15
+
16
+
17
+ var notifications = {};
18
+
19
+ var close_icon = jQuery('<i />').addClass('fa fa-times');
20
+ var close_button = jQuery('<button type="button" />').addClass('close button only-icon').append(close_icon).attr('title', container.attr('data-close-text'));
21
+ close_button.click(function()
22
+ {
23
+ var notification_id = jQuery(this).closest('.notification').attr('data-id');
24
+ body.trigger('notificationremove', notification_id );
25
+
26
+ });
27
+
28
+ var get_params = function( custom_params )
29
+ {
30
+ var random_id;
31
+ do
32
+ {
33
+ random_id = Math.random().toString(16).slice(2);
34
+ } while (typeof notifications[random_id] !== 'undefined');
35
+
36
+ // set defaults and then override with custom_params
37
+ var params =
38
+ {
39
+ id : random_id,
40
+ type : 'info',
41
+ closable : true,
42
+ // default closable notifications to automatic closing after a timeout;
43
+ // default non-closable notifications to never close automatically
44
+ duration : (('closable' in custom_params) && !custom_params.closable) ? null : 5,
45
+ message : '',
46
+ html : null,
47
+ icon : (('type' in custom_params) && (custom_params.type in icons_by_type)) ? icons_by_type[ custom_params.type ] : icons_by_type.info
48
+ };
49
+
50
+ jQuery.extend( params, custom_params );
51
+
52
+ return params;
53
+ };
54
+
55
+ var get_notification_ids = function( params )
56
+ {
57
+ var notification_ids = [];
58
+
59
+ if (typeof params === 'string')
60
+ {
61
+ // locate notification by id
62
+ notification_ids.push( params );
63
+ }
64
+ else if (typeof params === 'object')
65
+ {
66
+ // match multiple notifications by params
67
+ jQuery.each(notifications, function(notification_id, notification)
68
+ {
69
+ var notification_params = notification.data('params');
70
+
71
+ var all_params_match = true;
72
+
73
+ jQuery.each(params, function(param, value)
74
+ {
75
+ if ((typeof notification_params[param] === 'undefined') || (notification_params[param] !== value))
76
+ {
77
+ all_params_match = false;
78
+ return false;
79
+ }
80
+ });
81
+ if (all_params_match)
82
+ {
83
+ notification_ids.push(notification_id);
84
+ }
85
+ });
86
+ }
87
+
88
+ return notification_ids;
89
+ };
90
+
91
+ body.on('notificationsinit', function()
92
+ {
93
+
94
+ body.on('notificationadd', function(e, custom_params)
95
+ {
96
+ // adds or updates a notification
97
+
98
+ var notification;
99
+ var params = get_params( custom_params );
100
+ var is_new = false;
101
+
102
+ if (typeof notifications[params.id] === 'undefined')
103
+ {
104
+ is_new = true;
105
+
106
+ notification = jQuery('<div />').addClass('notification').attr('data-id', params.id);
107
+
108
+ notification.append(jQuery('<i />'));
109
+
110
+ notification.append(jQuery('<div />').addClass('content'));
111
+
112
+ notifications[params.id] = notification;
113
+ notification.hide();
114
+ notification.appendTo( container );
115
+
116
+ }
117
+
118
+ notification = notifications[params.id];
119
+
120
+ notification.data('params', params);
121
+
122
+ notification.attr('data-type', params.type);
123
+
124
+ notification.children('i').removeClass().addClass(icon_base_class + ' ' + params.icon);
125
+
126
+ // check whether notification already have close button added
127
+ if (params.closable && notification.find('.close').length === 0)
128
+ {
129
+ notification.append( close_button.clone(true) );
130
+ }
131
+ else if(!params.closable)
132
+ {
133
+ notification.find('.close').remove();
134
+ }
135
+
136
+ if (typeof params.html !== 'string')
137
+ {
138
+ params.html = jQuery('<div />').addClass('message').text( params.message );
139
+ }
140
+
141
+ notification.find('.content').html( params.html );
142
+
143
+ if (is_new)
144
+ {
145
+ notification.fadeIn('slow', function()
146
+ {
147
+ body.trigger('notificationadded', { notification : notification });
148
+ });
149
+ }
150
+ else
151
+ {
152
+ body.trigger('notificationupdated', { notification : notification });
153
+ }
154
+
155
+ });
156
+
157
+ body.on('notificationremove', function(e, params)
158
+ {
159
+ // removes single or multiple notifications
160
+
161
+ var removable_notification_ids = get_notification_ids( params );
162
+
163
+ jQuery.each( removable_notification_ids, function( index, notification_id)
164
+ {
165
+ if (typeof notifications[notification_id] === 'undefined')
166
+ {
167
+ return;
168
+ }
169
+
170
+ var notification = notifications[notification_id];
171
+
172
+ var timer = notification.data('removal-timer');
173
+ clearTimeout( timer );
174
+
175
+ notification.fadeOut('fast', function()
176
+ {
177
+ notification.css({ opacity: 0 }).show().slideUp( 'fast', function()
178
+ {
179
+ notification.remove();
180
+ });
181
+ });
182
+
183
+ delete( notifications[notification_id] );
184
+ });
185
+
186
+ });
187
+
188
+ body.on('notificationremovedelayed', function(e, removal_params)
189
+ {
190
+ // sets up removal timer for a single notification
191
+ // accepts id and duration in removal_params
192
+
193
+ var notification_id = removal_params.id;
194
+
195
+ if (typeof notifications[notification_id] === 'undefined')
196
+ {
197
+ return;
198
+ }
199
+
200
+ var notification = notifications[notification_id];
201
+
202
+ notification.data('removal-timer', setTimeout( function()
203
+ {
204
+ body.trigger('notificationremove', notification_id);
205
+ }, removal_params.duration * 1000));
206
+
207
+ });
208
+
209
+ body.on('notificationadded notificationupdated', function(e, event_params)
210
+ {
211
+ if (!('notification' in event_params))
212
+ {
213
+ return;
214
+ }
215
+ var notification = event_params.notification;
216
+
217
+ var params = notification.data('params');
218
+
219
+ var timer = notification.data('removal-timer');
220
+ clearTimeout( timer );
221
+
222
+ if (params.duration)
223
+ {
224
+ var removal_params =
225
+ {
226
+ id : params.id,
227
+ duration : params.duration
228
+ };
229
+ body.trigger('notificationremovedelayed', removal_params);
230
+
231
+ }
232
+
233
+ });
234
+
235
+ body.on('notificationaddflash', '.flash', function()
236
+ {
237
+ // convert .flash notice to notification
238
+ var params =
239
+ {
240
+ type : jQuery(this).attr('data-type'),
241
+ message : jQuery(this).text().trim()
242
+ };
243
+
244
+ var id = jQuery(this).attr('data-id');
245
+ if (typeof id !== 'undefined')
246
+ {
247
+ params.id = id;
248
+ }
249
+
250
+ body.trigger('notificationadd', params);
251
+ jQuery(this).remove();
252
+
253
+ });
254
+
255
+ });
256
+
257
+ body.trigger('notificationsinit');
258
+
259
+ // attach notificationaddflash to all loaded content
260
+ body.on('contentloaded', function(e)
261
+ {
262
+ jQuery(e.target).find('.flash').trigger('notificationaddflash');
263
+ });
264
+
265
+
266
+
267
+ });
@@ -0,0 +1,19 @@
1
+ /* global UrlBuilder */
2
+
3
+ jQuery(function()
4
+ {
5
+ var body = jQuery('body');
6
+ body.on('contentloaded', function(e)
7
+ {
8
+ jQuery(e.target).find('.pagination select[name="page"]').on('change', function()
9
+ {
10
+ var val = jQuery(this).val();
11
+ if (val)
12
+ {
13
+ var url = new UrlBuilder().add({page: val}).getUrl();
14
+ window.location.href = url;
15
+ }
16
+ });
17
+ });
18
+
19
+ });
@@ -0,0 +1,28 @@
1
+ jQuery(function(){
2
+
3
+ var body = jQuery('body');
4
+
5
+ var settings_url = jQuery('header .profile').data('settings-url');
6
+ body.on('settingssave', function( event, key_or_settings, value )
7
+ {
8
+ if (!settings_url)
9
+ {
10
+ return;
11
+ }
12
+
13
+ var settings = key_or_settings;
14
+ if (typeof settings === "string")
15
+ {
16
+ settings = {};
17
+ settings[key_or_settings] = value;
18
+ }
19
+
20
+ jQuery.ajax
21
+ ({
22
+ url: settings_url,
23
+ data: { "settings": settings},
24
+ type: 'POST',
25
+ dataType: 'json'
26
+ });
27
+ });
28
+ });
@@ -0,0 +1,437 @@
1
+ var RemoteValidator = function( form )
2
+ {
3
+ // self
4
+ var v = this;
5
+ var body = jQuery('body');
6
+ // selector for field input matching
7
+ var input_selector = 'input[type!="hidden"],textarea,select';
8
+ var submit_elements_selector = 'input[type="submit"], input[type="image"], button';
9
+
10
+ v.form = form;
11
+ v.clicked_button = null;
12
+
13
+ v.form.on('click.rails', submit_elements_selector, function( event ) {
14
+ var target = jQuery( event.target );
15
+
16
+ // webkit sends inner button elements as event targets instead of the button
17
+ // so catch if the click is inside a button element and change the target if needed
18
+ var closest_button = target.closest('button');
19
+ if (closest_button.length > 0)
20
+ {
21
+ target = closest_button;
22
+ }
23
+
24
+ // register only submit buttons - buttons with type="submit" or without type attribute at all
25
+ // direct target[0].type property is used because of inconsistent attr() method return values
26
+ // between older and newer jQuery versions
27
+ if (target.is( 'button' ) && target[0].type !== 'submit' )
28
+ {
29
+ return;
30
+ }
31
+ v.clicked_button = target;
32
+ });
33
+
34
+ v.form.on( 'ajax:beforeSend', function( event, xhr )
35
+ {
36
+ xhr.validation_id = 'v' + new Date().getTime() + Math.random();
37
+ v.form.attr( 'data-validation-id', xhr.validation_id );
38
+
39
+ if (v.clicked_button)
40
+ {
41
+ v.clicked_button.trigger('loadingstart');
42
+ }
43
+ });
44
+
45
+ v.form.on('ajax:complete', function( event, xhr )
46
+ {
47
+ var json_response;
48
+ var event_params =
49
+ {
50
+ validation_id: xhr.validation_id
51
+ };
52
+
53
+ switch (xhr.status)
54
+ {
55
+ case 303:
56
+ // validation + saving ok
57
+ try {
58
+ json_response = jQuery.parseJSON(xhr.responseText);
59
+ }
60
+ catch(error)
61
+ {
62
+ v.form.trigger( 'validation:fail', [ v, event_params ] );
63
+ break;
64
+ }
65
+ event_params.response = json_response;
66
+ v.form.trigger( 'validation:ok', [ v, event_params ] );
67
+ break;
68
+
69
+ case 200:
70
+ // validation ok
71
+ event_params.response = xhr;
72
+ v.form.trigger( 'validation:ok', [ v, event_params ] );
73
+ break;
74
+
75
+ case 422:
76
+ // validation returned errors
77
+ try {
78
+ json_response = jQuery.parseJSON(xhr.responseText);
79
+ }
80
+ catch(error)
81
+ {
82
+ v.form.trigger( 'validation:fail', [ v, event_params ] );
83
+ break;
84
+ }
85
+ event_params.response = json_response;
86
+
87
+ var errors = [];
88
+ jQuery.each( json_response.errors, function( fieldName, fieldErrors )
89
+ {
90
+ jQuery.each( fieldErrors, function( index, error )
91
+ {
92
+ var error_object = {
93
+ message : error.message,
94
+ fullMessage : error.full_message,
95
+ errorCode : error.error_code,
96
+ fieldName : fieldName
97
+ };
98
+ if('data' in error)
99
+ {
100
+ error_object.data = error.data;
101
+ }
102
+ errors.push(error_object);
103
+ });
104
+ });
105
+
106
+ jQuery.each( errors, function( index, error )
107
+ {
108
+ var field = null;
109
+
110
+ var eventTarget = null;
111
+
112
+ field = v.form.find( '[name="' + error.fieldName + '"],[name="' + error.fieldName + '[]"]' ).filter(':not([type="hidden"])').first();
113
+
114
+ event_params.error = error;
115
+
116
+ if (field && field.length > 0)
117
+ {
118
+ eventTarget = field;
119
+ }
120
+ else
121
+ {
122
+ eventTarget = v.form;
123
+ }
124
+
125
+ eventTarget.trigger( 'validation:error', [ v, event_params ] );
126
+
127
+ });
128
+
129
+ break;
130
+
131
+ default:
132
+ // something wrong in the received response
133
+ v.form.trigger( 'validation:fail', [ v, event_params ] );
134
+ break;
135
+ }
136
+ v.form.trigger( 'validation:end', [ v, event_params ] );
137
+ });
138
+
139
+ v.form.on( 'validation:ok', function( event, v, event_params )
140
+ {
141
+ if (!event_params || !event_params.response)
142
+ {
143
+ return;
144
+ }
145
+
146
+ if ('url' in event_params.response)
147
+ {
148
+ // json redirect url received
149
+ event.preventDefault(); // prevent validator's built in submit_form on ok
150
+ document.location.href = event_params.response.url;
151
+ }
152
+ else if ('getResponseHeader' in event_params.response)
153
+ {
154
+ event.preventDefault(); // prevent validator's built in submit_form on ok
155
+ body.trigger('contentreplace', [ event_params.response, "> header" ]);
156
+ body.trigger('contentreplace', [ event_params.response, "> aside" ]);
157
+ body.trigger('contentreplace', [ event_params.response, "> main" ]);
158
+ }
159
+ });
160
+
161
+ v.form.on( 'validation:error', function( event, v, event_params )
162
+ {
163
+ var error_node = null;
164
+ var error = event_params.error;
165
+ var target = jQuery(event.target);
166
+ var form = (target.is('form')) ? target : target.closest('form');
167
+
168
+ if (target.is(input_selector))
169
+ {
170
+ var field_box = target.parents('.field').first();
171
+ if (field_box.length !== 1)
172
+ {
173
+ return;
174
+ }
175
+
176
+ var wrap = (field_box.is('.i18n')) ? target.closest('.localization') : field_box;
177
+
178
+ var error_box = wrap.find('.error-box');
179
+
180
+ if (error_box.length < 1)
181
+ {
182
+ error_box = jQuery('<div class="error-box"><div class="error"></div></div>');
183
+ error_box.appendTo( wrap.find('.value').first() );
184
+ }
185
+
186
+
187
+ error_node = error_box.find('.error');
188
+ error_node.attr('data-validation-id', event_params.validation_id );
189
+ error_node.text( error.message );
190
+
191
+ field_box.addClass('has-error');
192
+
193
+ if (field_box.is('.i18n'))
194
+ {
195
+ wrap.addClass('has-error');
196
+ }
197
+ }
198
+ else if (target.is('form'))
199
+ {
200
+ var form_error_box = form.find('.form-error-box');
201
+ if (form_error_box.length < 1)
202
+ {
203
+ var form_error_box_container = form.find('.body').first();
204
+ if (form_error_box_container.length < 1)
205
+ {
206
+ form_error_box_container = form;
207
+ }
208
+ form_error_box = jQuery('<div class="form-error-box"></div>');
209
+ form_error_box.prependTo( form_error_box_container );
210
+ }
211
+
212
+ // reuse error node if it has the same text
213
+ form_error_box.find('.error').each(function()
214
+ {
215
+ if (error_node)
216
+ {
217
+ return;
218
+ }
219
+ if (jQuery(this).text() === error.message)
220
+ {
221
+ error_node = jQuery(this);
222
+ }
223
+ });
224
+
225
+ var new_error_node = !error_node;
226
+
227
+ if (!error_node)
228
+ {
229
+ error_node = jQuery('<div class="error"></div>');
230
+ }
231
+
232
+ error_node.attr('data-validation-id', event_params.validation_id);
233
+ error_node.text( error.fullMessage );
234
+
235
+ if (new_error_node)
236
+ {
237
+ error_node.appendTo( form_error_box );
238
+ }
239
+
240
+ form.addClass('has-error');
241
+
242
+ // Scroll to form_error_box
243
+ form_error_box.parent().scrollTop(form_error_box.offset().top - form_error_box.parent().offset().top + form_error_box.parent().scrollTop());
244
+
245
+ }
246
+
247
+ form.find('.button.loading').trigger('loadingend');
248
+ });
249
+
250
+ v.form.on( 'validation:end', function( event, v, event_params )
251
+ {
252
+ // remove all errors left from earlier validations
253
+
254
+ var last_validation_id = form.attr( 'data-validation-id' );
255
+
256
+ if (event_params.validation_id !== last_validation_id)
257
+ {
258
+ // do not go further if this is not the last validation
259
+ return;
260
+ }
261
+
262
+ event_params.except_validation_id = last_validation_id;
263
+
264
+ form.trigger('validation:clearerrors', [ v, event_params ]);
265
+
266
+
267
+ // if error fields still exist, focus to first visible
268
+
269
+ // locate first input inside visible error fields,
270
+ // but for i18n fields exclude inputs inside .localization without .has-error
271
+
272
+ var focus_target = form.find('.field.has-error').filter(':visible').find(input_selector).not('.localization:not(.has-error) *').first();
273
+
274
+ focus_target.trigger('focusprepare');
275
+
276
+ focus_target.focus();
277
+
278
+ });
279
+
280
+ v.form.on( 'validation:clearerrors', function( event, v, event_params )
281
+ {
282
+
283
+ // trigger this to clear existing errors in form
284
+ // optional event_params.except_validation_id can be used
285
+ // to preserve errors created by that specific validation
286
+
287
+ var except_validation_id = (event_params && ('except_validation_id' in event_params)) ? event_params.except_validation_id : null;
288
+
289
+ // remove field errors
290
+ form.find('.field.has-error').each(function()
291
+ {
292
+ var error_boxes;
293
+ var field = jQuery(this);
294
+
295
+ // in case of i18n fields there may be multiple error boxes inside a single field
296
+ error_boxes = field.find( '.error-box' );
297
+
298
+ error_boxes.each(function()
299
+ {
300
+ var error_box = jQuery(this);
301
+
302
+ var error_node = error_box.find('.error');
303
+
304
+ if (!except_validation_id || error_node.attr('data-validation-id') !== except_validation_id)
305
+ {
306
+ if (field.is('.i18n'))
307
+ {
308
+ error_box.closest('.localization').removeClass('has-error');
309
+ }
310
+ error_box.remove();
311
+ }
312
+ });
313
+
314
+ // see if any error boxes are left in the field.
315
+ error_boxes = field.find( '.error-box' );
316
+
317
+ if (error_boxes.length < 1)
318
+ {
319
+ field.removeClass('has-error');
320
+ }
321
+ });
322
+
323
+
324
+ // remove form errors
325
+ if (form.hasClass('has-error'))
326
+ {
327
+ var form_error_box = form.find('.form-error-box');
328
+ var form_errors_remain = false;
329
+
330
+ form_error_box.find('.error').each(function()
331
+ {
332
+ var error_node = jQuery(this);
333
+ if (!except_validation_id || error_node.attr('data-validation-id') !== except_validation_id)
334
+ {
335
+ error_node.remove();
336
+ }
337
+ else
338
+ {
339
+ form_errors_remain = true;
340
+ }
341
+ });
342
+
343
+ if (!form_errors_remain)
344
+ {
345
+ form_error_box.remove();
346
+ form.removeClass('has-error');
347
+ }
348
+ }
349
+ });
350
+
351
+ jQuery( document ).on( 'validation:ok validation:error validation:fail', 'form', function( event, validator )
352
+ {
353
+ if (validator !== v || event.isDefaultPrevented() || !v.form[0])
354
+ {
355
+ return;
356
+ }
357
+
358
+ switch (event.type)
359
+ {
360
+ case 'validation:ok': // validation passed
361
+
362
+ v.submit_form();
363
+
364
+ break;
365
+
366
+ case 'validation:error': // validation error
367
+
368
+ v.clicked_button = null;
369
+
370
+ break;
371
+
372
+ case 'validation:fail': // fail (internal validation failure, not a user error)
373
+
374
+ v.submit_form();
375
+
376
+ break;
377
+ }
378
+ });
379
+ };
380
+
381
+ RemoteValidator.prototype.submit_form = function()
382
+ {
383
+ var v = this;
384
+
385
+ // add originally clicked submit button to form as a hidden field
386
+ if (v.clicked_button)
387
+ {
388
+ var button = v.clicked_button.first();
389
+ var name = button.attr('name');
390
+ if (name)
391
+ {
392
+ var input = v.form.find('input[type="hidden"][name="' + name + '"]');
393
+ if (input.length < 1)
394
+ {
395
+ input = jQuery('<input />').attr('type', 'hidden').attr('name', button.attr('name'));
396
+ input.appendTo(v.form);
397
+ }
398
+ input.val(button.val());
399
+ }
400
+ }
401
+ v.form[0].submit();
402
+ };
403
+
404
+ jQuery(function(){
405
+ // define validation handlers
406
+ jQuery( document ).on( 'validation:init', 'form', function( event )
407
+ {
408
+ if (event.isDefaultPrevented())
409
+ {
410
+ return;
411
+ }
412
+
413
+ var form = jQuery(event.target);
414
+
415
+ if (form.data( 'validator' ))
416
+ {
417
+ // multiple validators on a single form are not supported
418
+ // a validator already exists. return
419
+ return;
420
+ }
421
+
422
+ form.data( 'validator', new RemoteValidator(form));
423
+
424
+ // validation initalized finished, add data attribute for it (used by automatized test, etc)
425
+ form.attr("data-remote-validation-initialized", true);
426
+
427
+ });
428
+
429
+ // attach remote validation to any new default forms after any content load
430
+ jQuery('body').on('contentloaded', function( event )
431
+ {
432
+ var block = jQuery(event.target);
433
+ var forms = (block.is('form[data-remote-validation]')) ? block : block.find('form[data-remote-validation]');
434
+
435
+ forms.trigger('validation:init');
436
+ });
437
+ });