incline 0.1.5

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 (303) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +186 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +208 -0
  7. data/Rakefile +37 -0
  8. data/app/assets/fonts/incline/.keep +0 -0
  9. data/app/assets/images/incline/.keep +0 -0
  10. data/app/assets/images/incline/barcode-B.svg +181 -0
  11. data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
  12. data/app/assets/javascripts/incline/application.js +30 -0
  13. data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
  14. data/app/assets/javascripts/incline/datatables.js +22193 -0
  15. data/app/assets/javascripts/incline/escapeHtml.js +10 -0
  16. data/app/assets/javascripts/incline/inline_actions.js +479 -0
  17. data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
  18. data/app/assets/javascripts/incline/jquery.number.js +764 -0
  19. data/app/assets/javascripts/incline/regexMask.js +27 -0
  20. data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
  21. data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
  22. data/app/assets/stylesheets/incline/application.css +18 -0
  23. data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
  24. data/app/assets/stylesheets/incline/custom.scss +279 -0
  25. data/app/assets/stylesheets/incline/datatables.css +494 -0
  26. data/app/assets/stylesheets/incline/datepicker3.css +790 -0
  27. data/app/assets/stylesheets/incline/select2.css +484 -0
  28. data/app/controllers/incline/access_groups_controller.rb +127 -0
  29. data/app/controllers/incline/access_test_controller.rb +30 -0
  30. data/app/controllers/incline/account_activations_controller.rb +28 -0
  31. data/app/controllers/incline/application_controller.rb +11 -0
  32. data/app/controllers/incline/contact_controller.rb +34 -0
  33. data/app/controllers/incline/password_resets_controller.rb +113 -0
  34. data/app/controllers/incline/security_controller.rb +100 -0
  35. data/app/controllers/incline/sessions_controller.rb +50 -0
  36. data/app/controllers/incline/users_controller.rb +304 -0
  37. data/app/controllers/incline/welcome_controller.rb +19 -0
  38. data/app/helpers/incline/.keep +0 -0
  39. data/app/mailers/incline/application_mailer_base.rb +11 -0
  40. data/app/mailers/incline/contact_form.rb +19 -0
  41. data/app/mailers/incline/user_mailer.rb +45 -0
  42. data/app/models/incline/access_group.rb +121 -0
  43. data/app/models/incline/access_group_group_member.rb +12 -0
  44. data/app/models/incline/access_group_user_member.rb +10 -0
  45. data/app/models/incline/action_group.rb +12 -0
  46. data/app/models/incline/action_security.rb +222 -0
  47. data/app/models/incline/contact_message.rb +37 -0
  48. data/app/models/incline/disable_info.rb +20 -0
  49. data/app/models/incline/password_reset.rb +14 -0
  50. data/app/models/incline/password_reset_request.rb +14 -0
  51. data/app/models/incline/user.rb +437 -0
  52. data/app/models/incline/user_login_history.rb +30 -0
  53. data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
  54. data/app/views/incline/access_groups/_form.html.erb +19 -0
  55. data/app/views/incline/access_groups/_list.html.erb +60 -0
  56. data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
  57. data/app/views/incline/access_groups/edit.html.erb +2 -0
  58. data/app/views/incline/access_groups/index.html.erb +6 -0
  59. data/app/views/incline/access_groups/index.json.jbuilder +16 -0
  60. data/app/views/incline/access_groups/new.html.erb +2 -0
  61. data/app/views/incline/access_groups/show.html.erb +9 -0
  62. data/app/views/incline/access_groups/show.json.jbuilder +11 -0
  63. data/app/views/incline/contact/new.html.erb +22 -0
  64. data/app/views/incline/contact_form/contact.html.erb +16 -0
  65. data/app/views/incline/contact_form/contact.text.erb +13 -0
  66. data/app/views/incline/password_resets/edit.html.erb +16 -0
  67. data/app/views/incline/password_resets/new.html.erb +12 -0
  68. data/app/views/incline/security/_details.json.jbuilder +7 -0
  69. data/app/views/incline/security/_form.html.erb +20 -0
  70. data/app/views/incline/security/_list.html.erb +89 -0
  71. data/app/views/incline/security/_messages.json.jbuilder +6 -0
  72. data/app/views/incline/security/edit.html.erb +2 -0
  73. data/app/views/incline/security/index.html.erb +6 -0
  74. data/app/views/incline/security/index.json.jbuilder +16 -0
  75. data/app/views/incline/security/show.html.erb +31 -0
  76. data/app/views/incline/security/show.json.jbuilder +11 -0
  77. data/app/views/incline/sessions/new.html.erb +26 -0
  78. data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
  79. data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
  80. data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
  81. data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
  82. data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
  83. data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
  84. data/app/views/incline/users/_details.json.jbuilder +32 -0
  85. data/app/views/incline/users/_form.html.erb +21 -0
  86. data/app/views/incline/users/_list.html.erb +102 -0
  87. data/app/views/incline/users/_messages.json.jbuilder +6 -0
  88. data/app/views/incline/users/disable_confirm.html.erb +19 -0
  89. data/app/views/incline/users/edit.html.erb +5 -0
  90. data/app/views/incline/users/index.html.erb +6 -0
  91. data/app/views/incline/users/index.json.jbuilder +16 -0
  92. data/app/views/incline/users/new.html.erb +5 -0
  93. data/app/views/incline/users/show.html.erb +12 -0
  94. data/app/views/incline/users/show.json.jbuilder +11 -0
  95. data/app/views/incline/welcome/home.html.erb +5 -0
  96. data/app/views/layouts/application.html.erb +1 -0
  97. data/app/views/layouts/incline/_account_menu.html.erb +18 -0
  98. data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  99. data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  100. data/app/views/layouts/incline/_footer.html.erb +13 -0
  101. data/app/views/layouts/incline/_header.html.erb +21 -0
  102. data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
  103. data/app/views/layouts/incline/_incline_app.html.erb +25 -0
  104. data/app/views/layouts/incline/_messages.html.erb +3 -0
  105. data/app/views/layouts/incline/_shim.html.erb +3 -0
  106. data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
  107. data/app/views/layouts/incline/application.html.erb +1 -0
  108. data/app/views/layouts/mailer.html.erb +2 -0
  109. data/app/views/layouts/mailer.text.erb +2 -0
  110. data/bin/rails +12 -0
  111. data/bin/test_scaffold.sh +10 -0
  112. data/config/routes.rb +61 -0
  113. data/db/migrate/20170511230126_create_incline_users.rb +26 -0
  114. data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
  115. data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
  116. data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
  117. data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
  118. data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
  119. data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
  120. data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
  121. data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
  122. data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
  123. data/db/seeds.rb +81 -0
  124. data/exe/new_incline_app +42 -0
  125. data/lib/generators/incline/install_generator.rb +259 -0
  126. data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
  127. data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
  128. data/lib/generators/incline/templates/incline_application.css +17 -0
  129. data/lib/generators/incline/templates/incline_application.html.erb +1 -0
  130. data/lib/generators/incline/templates/incline_application.js +12 -0
  131. data/lib/generators/incline/templates/incline_database.yml +25 -0
  132. data/lib/generators/incline/templates/incline_email.yml +20 -0
  133. data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
  134. data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
  135. data/lib/generators/incline/templates/incline_users.yml +64 -0
  136. data/lib/generators/incline/templates/incline_version.rb +3 -0
  137. data/lib/incline/auth_engine_base.rb +52 -0
  138. data/lib/incline/data_tables_request.rb +336 -0
  139. data/lib/incline/date_time_formats.rb +6 -0
  140. data/lib/incline/engine.rb +212 -0
  141. data/lib/incline/errors.rb +15 -0
  142. data/lib/incline/extensions/action_controller_base.rb +526 -0
  143. data/lib/incline/extensions/action_mailer_base.rb +66 -0
  144. data/lib/incline/extensions/action_view_base.rb +489 -0
  145. data/lib/incline/extensions/active_record_base.rb +308 -0
  146. data/lib/incline/extensions/application.rb +137 -0
  147. data/lib/incline/extensions/application_configuration.rb +50 -0
  148. data/lib/incline/extensions/connection_adapter.rb +55 -0
  149. data/lib/incline/extensions/date_time_value.rb +123 -0
  150. data/lib/incline/extensions/date_value.rb +77 -0
  151. data/lib/incline/extensions/decimal_value.rb +55 -0
  152. data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
  153. data/lib/incline/extensions/float_value.rb +59 -0
  154. data/lib/incline/extensions/form_builder.rb +617 -0
  155. data/lib/incline/extensions/integer_value.rb +54 -0
  156. data/lib/incline/extensions/jbuilder_generator.rb +38 -0
  157. data/lib/incline/extensions/jbuilder_template.rb +39 -0
  158. data/lib/incline/extensions/main_app.rb +40 -0
  159. data/lib/incline/extensions/numeric.rb +63 -0
  160. data/lib/incline/extensions/object.rb +31 -0
  161. data/lib/incline/extensions/resource_route_generator.rb +53 -0
  162. data/lib/incline/extensions/session.rb +113 -0
  163. data/lib/incline/extensions/string.rb +50 -0
  164. data/lib/incline/extensions/test_case.rb +764 -0
  165. data/lib/incline/extensions/time_zone_converter.rb +40 -0
  166. data/lib/incline/global_status.rb +236 -0
  167. data/lib/incline/helpers/route_hash_formatter.rb +46 -0
  168. data/lib/incline/json_log_formatter.rb +96 -0
  169. data/lib/incline/json_logger.rb +17 -0
  170. data/lib/incline/log.rb +153 -0
  171. data/lib/incline/number_formats.rb +17 -0
  172. data/lib/incline/recaptcha.rb +346 -0
  173. data/lib/incline/user_manager.rb +212 -0
  174. data/lib/incline/validators/email_validator.rb +45 -0
  175. data/lib/incline/validators/ip_address_validator.rb +32 -0
  176. data/lib/incline/validators/recaptcha_validator.rb +37 -0
  177. data/lib/incline/validators/safe_name_validator.rb +31 -0
  178. data/lib/incline/version.rb +3 -0
  179. data/lib/incline/work_path.rb +75 -0
  180. data/lib/incline.rb +197 -0
  181. data/lib/tasks/incline_tasks.rake +4 -0
  182. data/lib/templates/erb/scaffold/_form.html.erb +43 -0
  183. data/lib/templates/erb/scaffold/_list.html.erb +81 -0
  184. data/lib/templates/erb/scaffold/edit.html.erb +1 -0
  185. data/lib/templates/erb/scaffold/index.html.erb +6 -0
  186. data/lib/templates/erb/scaffold/new.html.erb +1 -0
  187. data/lib/templates/erb/scaffold/show.html.erb +34 -0
  188. data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
  189. data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
  190. data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
  191. data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
  192. data/test/controllers/incline/access_groups_controller_test.rb +65 -0
  193. data/test/controllers/incline/access_test_controller_test.rb +53 -0
  194. data/test/controllers/incline/contact_controller_test.rb +32 -0
  195. data/test/controllers/incline/security_controller_test.rb +39 -0
  196. data/test/controllers/incline/welcome_controller_test.rb +16 -0
  197. data/test/dummy/README.rdoc +28 -0
  198. data/test/dummy/Rakefile +6 -0
  199. data/test/dummy/app/assets/images/.keep +0 -0
  200. data/test/dummy/app/assets/javascripts/application.js +12 -0
  201. data/test/dummy/app/assets/stylesheets/application.css +17 -0
  202. data/test/dummy/app/controllers/application_controller.rb +5 -0
  203. data/test/dummy/app/controllers/concerns/.keep +0 -0
  204. data/test/dummy/app/helpers/application_helper.rb +2 -0
  205. data/test/dummy/app/mailers/.keep +0 -0
  206. data/test/dummy/app/models/.keep +0 -0
  207. data/test/dummy/app/models/concerns/.keep +0 -0
  208. data/test/dummy/app/views/layouts/application.html.erb +1 -0
  209. data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  210. data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  211. data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
  212. data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
  213. data/test/dummy/bin/bundle +3 -0
  214. data/test/dummy/bin/rails +4 -0
  215. data/test/dummy/bin/rake +4 -0
  216. data/test/dummy/bin/setup +29 -0
  217. data/test/dummy/config/application.rb +38 -0
  218. data/test/dummy/config/boot.rb +5 -0
  219. data/test/dummy/config/database.yml +34 -0
  220. data/test/dummy/config/email.yml +24 -0
  221. data/test/dummy/config/environment.rb +5 -0
  222. data/test/dummy/config/environments/development.rb +45 -0
  223. data/test/dummy/config/environments/production.rb +85 -0
  224. data/test/dummy/config/environments/test.rb +44 -0
  225. data/test/dummy/config/initializers/assets.rb +11 -0
  226. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  227. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  228. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  229. data/test/dummy/config/initializers/inflections.rb +16 -0
  230. data/test/dummy/config/initializers/mime_types.rb +4 -0
  231. data/test/dummy/config/initializers/session_store.rb +3 -0
  232. data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  233. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  234. data/test/dummy/config/locales/en.yml +23 -0
  235. data/test/dummy/config/routes.rb +6 -0
  236. data/test/dummy/config.ru +4 -0
  237. data/test/dummy/db/schema.rb +108 -0
  238. data/test/dummy/lib/assets/.keep +0 -0
  239. data/test/dummy/log/.keep +0 -0
  240. data/test/dummy/public/404.html +67 -0
  241. data/test/dummy/public/422.html +67 -0
  242. data/test/dummy/public/500.html +66 -0
  243. data/test/dummy/public/favicon.ico +0 -0
  244. data/test/extensions/action_controller_base_extensions_test.rb +21 -0
  245. data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
  246. data/test/extensions/action_view_base_extensions_test.rb +267 -0
  247. data/test/extensions/active_record_extensions_test.rb +173 -0
  248. data/test/extensions/application_configuration_extensions_test.rb +46 -0
  249. data/test/extensions/application_extensions_test.rb +23 -0
  250. data/test/extensions/connection_adapter_extensions_test.rb +54 -0
  251. data/test/extensions/date_time_value_extensions_test.rb +104 -0
  252. data/test/extensions/date_value_extensions_test.rb +102 -0
  253. data/test/extensions/decimal_value_extensions_test.rb +85 -0
  254. data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
  255. data/test/extensions/float_value_extensions_test.rb +78 -0
  256. data/test/extensions/form_builder_extensions_test.rb +28 -0
  257. data/test/extensions/integer_value_extensions_test.rb +78 -0
  258. data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
  259. data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
  260. data/test/extensions/main_app_extensions_test.rb +55 -0
  261. data/test/extensions/numeric_extensions_test.rb +76 -0
  262. data/test/extensions/object_extensions_test.rb +104 -0
  263. data/test/extensions/session_extensions_test.rb +69 -0
  264. data/test/extensions/string_extensions_test.rb +32 -0
  265. data/test/extensions/test_case_extensions_test.rb +538 -0
  266. data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
  267. data/test/fixtures/incline/access_group_group_members.yml +1 -0
  268. data/test/fixtures/incline/access_group_user_members.yml +1 -0
  269. data/test/fixtures/incline/access_groups.yml +13 -0
  270. data/test/fixtures/incline/action_groups.yml +6 -0
  271. data/test/fixtures/incline/action_securities.yml +18 -0
  272. data/test/fixtures/incline/user_login_histories.yml +1 -0
  273. data/test/fixtures/incline/users.yml +64 -0
  274. data/test/incline_test.rb +63 -0
  275. data/test/integration/incline/users_edit_test.rb +180 -0
  276. data/test/integration/incline/users_login_test.rb +105 -0
  277. data/test/integration/incline/users_signup_test.rb +147 -0
  278. data/test/integration/navigation_test.rb +11 -0
  279. data/test/lib/data_tables_request_test.rb +245 -0
  280. data/test/lib/date_time_formats_test.rb +111 -0
  281. data/test/lib/global_status_test.rb +89 -0
  282. data/test/lib/json_log_formatter_test.rb +43 -0
  283. data/test/lib/log_test.rb +36 -0
  284. data/test/lib/recaptcha_test.rb +75 -0
  285. data/test/lib/user_manager_test.rb +47 -0
  286. data/test/lib/work_path_test.rb +18 -0
  287. data/test/models/incline/access_group_group_member_test.rb +30 -0
  288. data/test/models/incline/access_group_test.rb +60 -0
  289. data/test/models/incline/access_group_user_member_test.rb +29 -0
  290. data/test/models/incline/action_group_test.rb +27 -0
  291. data/test/models/incline/action_security_test.rb +176 -0
  292. data/test/models/incline/contact_message_test.rb +66 -0
  293. data/test/models/incline/disable_info_test.rb +29 -0
  294. data/test/models/incline/password_reset_request_test.rb +35 -0
  295. data/test/models/incline/password_reset_test.rb +51 -0
  296. data/test/models/incline/user_login_history_test.rb +31 -0
  297. data/test/models/incline/user_test.rb +91 -0
  298. data/test/test_helper.rb +42 -0
  299. data/test/validators/email_validator_test.rb +102 -0
  300. data/test/validators/ip_address_validator_test.rb +107 -0
  301. data/test/validators/recaptcha_validator_test.rb +57 -0
  302. data/test/validators/safe_name_validator_test.rb +101 -0
  303. metadata +584 -0
@@ -0,0 +1,10 @@
1
+
2
+ function escapeHTML(unsafe)
3
+ {
4
+ return unsafe
5
+ .replace(/&/g,'&')
6
+ .replace(/</g, '&lt;')
7
+ .replace(/>/g, '&gt;')
8
+ .replace(/"/g, '&quot;')
9
+ .replace(/'/g, '&#039;');
10
+ }
@@ -0,0 +1,479 @@
1
+ // Data Tables Helper Methods
2
+ // (C) 2017 Beau Barker (beau@barkerest.com)
3
+
4
+ /*
5
+ * JSON format:
6
+ * {
7
+ * // (optional) set to true to indicate an invalid request to the server, default is false.
8
+ * "invalidRequest": false,
9
+ * // (optional) an array of messages to display to the user.
10
+ * "messages": [
11
+ * {
12
+ * // (required) "info", "warning", "danger", "success"
13
+ * "type": "info",
14
+ * // (required) the message to display.
15
+ * "text": "The action was successful."
16
+ * }
17
+ * ],
18
+ * // (optional) an array of data to update the data table with.
19
+ * "data": [
20
+ * {
21
+ * // (required) the unique ID for this row.
22
+ * "DT_RowId": "my_model_1",
23
+ * // (required) the "show" path for the model.
24
+ * "DT_Path": "/incline/my_model/1",
25
+ * // (optional) "update" or "remove", default is "update".
26
+ * "DT_RowAction": "update",
27
+ * // (optional) "info", "warning", "danger", "success"
28
+ * "DT_RowClass": "info",
29
+ *
30
+ * // then model details such as:
31
+ * "name": "John Doe",
32
+ * "age": 35,
33
+ * "email": "jdoe@example.com",
34
+ * "occupation": "Mechanic"
35
+ * }
36
+ * ]
37
+ * }
38
+ */
39
+
40
+
41
+ var inclineInline = {
42
+ action: function(path, method) {
43
+ if (!(method)) method = 'get';
44
+ if (path.indexOf('?') >= 0) {
45
+ path += '&inline=1';
46
+ } else {
47
+ path += '?inline=1';
48
+ }
49
+ $.ajax({
50
+ method: method.toUpperCase(),
51
+ url: path,
52
+ dataType: 'json',
53
+ success: function (data, status, xhr) {
54
+ inclineInline._handle_json_result(data);
55
+ },
56
+ error: function (xhr, status, error) {
57
+ inclineInline._handle_error(status, error);
58
+ }
59
+ });
60
+ },
61
+
62
+ form: function(req_path, req_method) {
63
+ if (!(req_method)) req_method = 'get';
64
+ if (req_path.indexOf('?') >= 0) {
65
+ req_path += '&inline=1';
66
+ } else {
67
+ req_path += '?inline=1';
68
+ }
69
+
70
+ // first request should return HTML.
71
+ $.ajax({
72
+ method: req_method.toUpperCase(),
73
+ url: req_path,
74
+ dataType: 'html',
75
+ success: function (data, status, xhr) {
76
+ inclineInline._handle_form_response(data, status, xhr);
77
+ },
78
+ error: function (xhr, status, error) {
79
+ inclineInline._handle_error(status, error);
80
+ }
81
+ });
82
+ },
83
+
84
+ _handle_json_result: function(data) {
85
+ var ts = Math.round((new Date().getTime() / 100) % 864000, 0);
86
+ var i;
87
+ if (data.invalidRequest) {
88
+ // Should probably come up with a more informative alert.
89
+ this._handle_error('invalid request', 'invalid request');
90
+ } else {
91
+ // build alerts that clear after 5 seconds.
92
+ if (data.messages) {
93
+ var messageCount = data.messages.length;
94
+ var alertDiv = $('#incline_dynamic_alerts');
95
+ for (i = 0; i < messageCount; i++) {
96
+ var message = data.messages[i];
97
+ var html = '<div id="alert-' + ts.toString() + '" class="alert alert-' + escapeHTML(message.type) + ' alert-dismissible fade in" role="alert">' +
98
+ '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
99
+ escapeHTML(message.text) +
100
+ '</div>';
101
+ var close = '$(\'#alert-' + ts.toString() + '\').alert(\'close\');';
102
+ alertDiv.prepend(html);
103
+ window.setTimeout(close, 5000);
104
+ ts++;
105
+ }
106
+ }
107
+ // update rows in the data table.
108
+ if (data.data) {
109
+ var dataCount = data.data.length;
110
+ for (i = 0; i < dataCount; i++) {
111
+ var item = data.data[i];
112
+ var row = $('#' + item.DT_RowId);
113
+ if (row.length > 0) {
114
+ var table = row.parents('table');
115
+ if ($.fn.dataTable.isDataTable(table))
116
+ {
117
+ var table_id = table.attr('id');
118
+ table = table.dataTable().api();
119
+ if (item.DT_RowAction === 'remove') {
120
+ table.row('#' + item.DT_RowId).remove(); // remove the row from the DT.
121
+ table.draw('page'); // refresh the current page.
122
+ } else {
123
+ table.row('#' + item.DT_RowId).data(item); // refresh the row in the DT.
124
+ inclineInline._go_to_record(item); // find and hilight the record.
125
+ }
126
+ }
127
+ } else if (dataCount == 1) {
128
+ // no row found and there is only one record returned, focus on that record.
129
+ inclineInline._go_to_record(item);
130
+ }
131
+ }
132
+ }
133
+ }
134
+ },
135
+
136
+ _handle_form_response: function (data, status, xhr) {
137
+ var type = xhr.getResponseHeader('Content-Type').toLowerCase().trim();
138
+ if (type.indexOf(';') >= 0)
139
+ type = type.substring(0, type.indexOf(';')).trim();
140
+
141
+ if (type === 'application/json') {
142
+ // json response
143
+ this._destroy_dialog();
144
+ this._handle_json_result(data);
145
+ } else if (type === 'text/html') {
146
+ // html response
147
+ this._set_dialog(data);
148
+ } else {
149
+ // unsupported response
150
+ this._destroy_dialog();
151
+ this._handle_error('invalid response', 'invalid response');
152
+ }
153
+ },
154
+
155
+ _handle_error: function (status, error) {
156
+ this._destroy_dialog(); // no matter what, the dialog should be destroyed.
157
+
158
+ // Should probably come up with more informative error alerts.
159
+ if (status === 'error') {
160
+ alert(error);
161
+ } else {
162
+ alert(status);
163
+ }
164
+ },
165
+
166
+ _dialog: false,
167
+
168
+ _create_dialog: function () {
169
+ if (!(this._dialog))
170
+ {
171
+ var body = $('body');
172
+ var modal = $('<div class="modal fade" id="incline_inline_form" tabindex="-1" role="dialog" aria-labelledby="incline_inline_form_title" style="display: none;">' +
173
+ '<div class="modal-dialog" role="document">' +
174
+ '<div class="modal-content">' +
175
+ '<div class="modal-header">' +
176
+ '<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
177
+ '<h4 class="modal-title" id="incline_inline_form_title"></h4>' +
178
+ '</div>' +
179
+ '<div class="modal-body" id="incline_inline_form_body"></div>' +
180
+ '<div class="modal-footer" id="incline_inline_form_footer"></div>' +
181
+ '</div></div></div>');
182
+
183
+ body.prepend(modal);
184
+ modal = $('#incline_inline_form');
185
+ modal.on('hidden.bs.modal', function (e) {
186
+ modal.remove();
187
+ inclineInline._dialog = false;
188
+ });
189
+ this._dialog = true;
190
+ }
191
+ },
192
+
193
+ _set_dialog: function (html) {
194
+ var title;
195
+ var body;
196
+ var footer;
197
+ var tmp;
198
+ var dup;
199
+ var panel;
200
+ var panel_parent;
201
+ var align_regex = /^(.*\s)?(row(\s.*)?|col-(xs|sm|md|lg)-.*)$/;
202
+ var panel_regex = /^(.*\s)?panel(\s.*)?$/;
203
+
204
+ // add html to DOM under a hidden div for processing.
205
+ tmp = $('<div></div>').css('display','none');
206
+ $('body').append(tmp);
207
+ tmp.html(html);
208
+ html = tmp;
209
+
210
+ this._create_dialog();
211
+
212
+ // get the parts of the modal to update.
213
+ title = $('#incline_inline_form_title');
214
+ body = $('#incline_inline_form_body');
215
+ footer = $('#incline_inline_form_footer');
216
+
217
+ // reset
218
+ title.text('');
219
+ body.empty();
220
+ footer.empty();
221
+
222
+ tmp = html.find('form');
223
+ if (tmp.length == 1) { // support one and only one form in the resulting HTML.
224
+ // we have a form in the html that needs to be modified accordingly.
225
+ var form_method = tmp.attr('method');
226
+ var form_url = tmp.attr('action');
227
+ var form_id = tmp.attr('id');
228
+
229
+ // make sure the inline parameter is set.
230
+ tmp.append('<input type="hidden" name="inline" value="1" />');
231
+
232
+ // override submit to make sure the submission occurs via ajax.
233
+ tmp.submit(function (e) {
234
+ var form_data = $('#' + form_id).serialize();
235
+ e.preventDefault();
236
+
237
+ // prevent double submission.
238
+ tmp.find('input,button,select,textarea').prop('disabled', true);
239
+
240
+ $.ajax({
241
+ type: form_method.toUpperCase(),
242
+ url: form_url,
243
+ data: form_data,
244
+ success: function(data, status, xhr) {
245
+ inclineInline._handle_form_response(data, status, xhr);
246
+ },
247
+ error: function(xhr, status, error) {
248
+ inclineInline._handle_error(status, error);
249
+ }
250
+ });
251
+ });
252
+ }
253
+
254
+ // cancel links and buttons
255
+ tmp = html.find('a,button,input[type=button]').filter(function() { return $(this).text().toLowerCase() === 'cancel'; });
256
+ if (tmp.length > 0) {
257
+ tmp.click(function (e) {
258
+ e.preventDefault();
259
+ inclineInline._destroy_dialog();
260
+ });
261
+ }
262
+
263
+ // global title recognition, first H1 or H2 element.
264
+ tmp = html.find('h1');
265
+ if (tmp.length < 1) tmp = html.find('h2');
266
+ if (tmp.length > 0) {
267
+ tmp = tmp.first();
268
+ title.text(tmp.text());
269
+ // only remove if there is no additional HTML markup.
270
+ if (tmp.html() === tmp.text())
271
+ {
272
+ tmp.remove();
273
+ }
274
+ }
275
+
276
+ // put the error messages in place.
277
+ tmp = html.find('#error_explanation');
278
+ if (tmp.length > 0) {
279
+ tmp.detach();
280
+ body.prepend(tmp);
281
+ }
282
+
283
+ // put the alert messages in place.
284
+ tmp = html.find('.alert');
285
+ if (tmp.length > 0) {
286
+ tmp.detach();
287
+ body.prepend(tmp);
288
+ }
289
+
290
+ // remove outside alignment DIVs.
291
+ while ((tmp = html.children()) && tmp.length == 1 && align_regex.test(tmp.attr('class'))) {
292
+ tmp.detach();
293
+ html.append(tmp.children());
294
+ }
295
+
296
+ // If the html has one child and that child is a form, then look inside the form.
297
+ panel_parent = html;
298
+ panel = panel_parent.children();
299
+ if (panel.length == 1 && panel[0].tagName.toUpperCase() === 'FORM') {
300
+ panel_parent = panel;
301
+ panel = panel_parent.children(':not(input[type=hidden])'); // ignore hidden inputs
302
+ }
303
+
304
+ // now if there is only one child and that child is a panel, we can rip it apart.
305
+ if (panel.length == 1 && panel[0].tagName.toUpperCase() === 'DIV' && panel_regex.test(panel.attr('class'))) {
306
+ panel.detach();
307
+
308
+ if ((tmp = panel.children('.panel-heading')) && tmp.length > 0) {
309
+ title.text(tmp.text());
310
+ }
311
+
312
+ tmp = panel.children('table,.panel-body');
313
+ if (tmp.length > 0) {
314
+ tmp.removeClass('panel-body');
315
+ tmp.detach();
316
+ panel_parent.append(tmp);
317
+ }
318
+
319
+ tmp = panel.children('.panel-footer');
320
+ if (tmp.length > 0) {
321
+ tmp.removeClass('panel-footer');
322
+ tmp.detach();
323
+ // now we have a conundrum.
324
+ if (panel_parent[0].tagName.toUpperCase() === 'FORM') {
325
+ // since the footer might contain controls for the form, we need it to be in the form.
326
+ panel_parent.append(tmp);
327
+ } else {
328
+ // or the form doesn't wrap the footer, so we can just use the footer.
329
+ footer.append(tmp.children());
330
+ }
331
+ }
332
+ }
333
+
334
+ // we are done modifying the HTML and we can add it.
335
+ html.detach();
336
+ body.append(html.contents());
337
+
338
+ // footer should only be visible if it has contents.
339
+ if (footer.children().length > 0 || footer.text() !== '') {
340
+ footer.show();
341
+ } else {
342
+ footer.hide();
343
+ }
344
+
345
+ // make sure the dialog is visible.
346
+ tmp = $('#incline_inline_form');
347
+ if (tmp.is(':hidden')) {
348
+ tmp.modal('show');
349
+ tmp.on('shown.bs.modal', function () {
350
+ activateClassedItems(tmp);
351
+ });
352
+ } else {
353
+ // make sure the classed items are activated.
354
+ activateClassedItems(tmp);
355
+ }
356
+ },
357
+
358
+ _destroy_dialog: function () {
359
+ if (this._dialog) {
360
+ var dlg = $('#incline_inline_form');
361
+ if (dlg.length > 0) {
362
+ if (dlg.is(':hidden')) {
363
+ dlg.remove();
364
+ } else {
365
+ dlg.modal('hide');
366
+ }
367
+ }
368
+ this._dialog = false;
369
+ }
370
+ },
371
+
372
+ _go_to_record: function (data) {
373
+ var table = $('table.dataTable');
374
+ var params;
375
+ var i;
376
+ var row_id = '#' + data.DT_RowId;
377
+
378
+ if (table.length < 1) return;
379
+
380
+ table = table.dataTable().api();
381
+
382
+ i = data.DT_RowId.lastIndexOf('_');
383
+
384
+ params = table.ajax.params();
385
+ params.draw = -1;
386
+ params.locate_id = data.DT_RowId.substring(i + 1);
387
+
388
+ $.ajax({
389
+ url: data.DT_Path + '/locate',
390
+ method: 'POST',
391
+ dataType: 'json',
392
+ data: params,
393
+ success: function(data) {
394
+ var recNum = data.record;
395
+ if (recNum > -1) {
396
+ var pageLen = table.page.len();
397
+ var pageNum;
398
+
399
+ if (pageLen < 1) return;
400
+
401
+ // avoid division by zero.
402
+ if (recNum === 0) {
403
+ pageNum = 0;
404
+ } else {
405
+ pageNum = Math.floor(recNum / pageLen);
406
+ }
407
+
408
+ // set the page number and refresh the datatable only if we are on a different page or the row isn't visible.
409
+ if (table.page() != pageNum || $(row_id).length < 1) {
410
+ table.page(pageNum).draw('page');
411
+ }
412
+
413
+ // hilite the row (give DOM a quick chance to update).
414
+ window.setTimeout(function() { inclineInline._hilite_fade(row_id); }, 250 );
415
+ }
416
+ }
417
+ });
418
+
419
+ },
420
+
421
+ _hilite_fade: function (selector) {
422
+ // 2s hilite pulse from any bg color to yellow and then back.
423
+ $(selector).addClass('cell-fade').addClass('cell-hilite');
424
+ window.setTimeout(function() {
425
+ $(selector).removeClass('cell-hilite');
426
+ window.setTimeout(function() {
427
+ $(selector).removeClass('cell-fade');
428
+ }, 1000);
429
+ }, 1000);
430
+ },
431
+ };
432
+
433
+ /*
434
+ * Generates an AJAX request to load an HTML fragment from the server.
435
+ * When the HTML fragment is returned, it is displayed in a modal dialog over the current page.
436
+ * If a form is present in the returned HTML, the 'submit' event is hooked to submit inline via AJAX.
437
+ * If the form submission returns HTML, the returned HTML overwrites the previous HTML.
438
+ * If the form submission returns JSON, the JSON is is used to update the page.
439
+ */
440
+ function inlineForm(req_path,req_method) {
441
+ inclineInline.form(req_path, req_method);
442
+ }
443
+
444
+ /*
445
+ * Generates an AJAX request to the server and expects a JSON result.
446
+ * The JSON is used to update the page.
447
+ */
448
+ function inlineAction(path, method) {
449
+ inclineInline.action(path, method);
450
+ }
451
+
452
+ (function ($){
453
+ // inlineAction should return JSON data.
454
+ // If "invalidRequest" is set in the response then an alert is generated.
455
+ // Otherwise, if "messages" are set in the response then we display them.
456
+ $.fn.inlineAction = function () {
457
+ var item = $(this);
458
+ var path = item.attr('href');
459
+ var method = item.attr('data-method');
460
+ if (!(method)) method = 'get';
461
+
462
+ item.click(function (e) {
463
+ e.preventDefault();
464
+ inclineInline.action(path, method);
465
+ });
466
+ };
467
+ $.fn.inlineForm = function () {
468
+ var item =$(this);
469
+ var path = item.attr('href');
470
+ var method = item.attr('data-method');
471
+ if (!(method)) method = 'get';
472
+
473
+ item.click(function (e) {
474
+ e.preventDefault();
475
+ inclineInline.form(path, method);
476
+ });
477
+ };
478
+ })(jQuery);
479
+
@@ -0,0 +1,112 @@
1
+ /*
2
+ * @name DoubleScroll
3
+ * @desc displays scroll bar on top and on the bottom of the div
4
+ * @requires jQuery
5
+ *
6
+ * @author Pawel Suwala - http://suwala.eu/
7
+ * @author Antoine Vianey - http://www.astek.fr/
8
+ * @version 0.4 (18-06-2014)
9
+ *
10
+ * Dual licensed under the MIT and GPL licenses:
11
+ * http://www.opensource.org/licenses/mit-license.php
12
+ * http://www.gnu.org/licenses/gpl.html
13
+ *
14
+ * Usage:
15
+ * https://github.com/avianey/jqDoubleScroll
16
+ */
17
+
18
+ jQuery.fn.doubleScroll = function(userOptions) {
19
+ var $ = jQuery;
20
+ // Default options
21
+ var options = {
22
+ contentElement: undefined, // Widest element, if not specified first child element will be used
23
+ scrollCss: {
24
+ 'overflow-x': 'auto',
25
+ 'overflow-y': 'hidden'
26
+ },
27
+ contentCss: {
28
+ 'overflow-x': 'auto',
29
+ 'overflow-y': 'hidden'
30
+ },
31
+ onlyIfScroll: true, // top scrollbar is not shown if the bottom one is not present
32
+ resetOnWindowResize: false, // recompute the top ScrollBar requirements when the window is resized
33
+ timeToWaitForResize: 30 // wait for the last update event (usefull when browser fire resize event constantly during ressing)
34
+ };
35
+ $.extend(true, options, userOptions);
36
+ // do not modify
37
+ // internal stuff
38
+ $.extend(options, {
39
+ topScrollBarMarkup: '<div class="doubleScroll-scroll-wrapper" style="height: 20px;"><div class="doubleScroll-scroll" style="height: 20px;"></div></div>',
40
+ topScrollBarWrapperSelector: '.doubleScroll-scroll-wrapper',
41
+ topScrollBarInnerSelector: '.doubleScroll-scroll'
42
+ });
43
+
44
+ var _showScrollBar = function($self, options) {
45
+
46
+ if (options.onlyIfScroll && $self.get(0).scrollWidth <= $self.width()) {
47
+ // content doesn't scroll
48
+ // remove any existing occurrence...
49
+ $self.prev(options.topScrollBarWrapperSelector).remove();
50
+ return;
51
+ }
52
+
53
+ // add div that will act as an upper scroll only if not already added to the DOM
54
+ var $topScrollBar = $self.prev(options.topScrollBarWrapperSelector);
55
+ if ($topScrollBar.length == 0) {
56
+
57
+ // creating the scrollbar
58
+ // added before in the DOM
59
+ $topScrollBar = $(options.topScrollBarMarkup);
60
+ $self.before($topScrollBar);
61
+
62
+ // apply the css
63
+ $topScrollBar.css(options.scrollCss);
64
+ $self.css(options.contentCss);
65
+
66
+ // bind upper scroll to bottom scroll
67
+ $topScrollBar.bind('scroll.doubleScroll', function() {
68
+ $self.scrollLeft($topScrollBar.scrollLeft());
69
+ });
70
+
71
+ // bind bottom scroll to upper scroll
72
+ var selfScrollHandler = function() {
73
+ $topScrollBar.scrollLeft($self.scrollLeft());
74
+ };
75
+ $self.bind('scroll.doubleScroll', selfScrollHandler);
76
+ }
77
+
78
+ // find the content element (should be the widest one)
79
+ var $contentElement;
80
+ if (options.contentElement !== undefined && $self.find(options.contentElement).length !== 0) {
81
+ $contentElement = $self.find(options.contentElement);
82
+ } else {
83
+ $contentElement = $self.find('>:first-child');
84
+ }
85
+
86
+ // set the width of the wrappers
87
+ $(options.topScrollBarInnerSelector, $topScrollBar).width($contentElement.outerWidth());
88
+ $topScrollBar.width($self.width());
89
+ $topScrollBar.scrollLeft($self.scrollLeft());
90
+
91
+ };
92
+
93
+ return this.each(function() {
94
+ var $self = $(this);
95
+ _showScrollBar($self, options);
96
+
97
+ // bind the resize handler
98
+ // do it once
99
+ if (options.resetOnWindowResize) {
100
+ var id;
101
+ var handler = function(e) {
102
+ _showScrollBar($self, options);
103
+ };
104
+ $(window).bind('resize.doubleScroll', function() {
105
+ // adding/removing/replacing the scrollbar might resize the window
106
+ // so the resizing flag will avoid the infinite loop here...
107
+ clearTimeout(id);
108
+ id = setTimeout(handler, options.timeToWaitForResize);
109
+ });
110
+ }
111
+ });
112
+ };