releaf-core 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ });