fae-railsz 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +5 -0
  3. data/Rakefile +37 -0
  4. data/app/assets/fonts/fae/icons.eot +0 -0
  5. data/app/assets/fonts/fae/icons.svg +56 -0
  6. data/app/assets/fonts/fae/icons.ttf +0 -0
  7. data/app/assets/fonts/fae/icons.woff +0 -0
  8. data/app/assets/fonts/fae/lato-bold-webfont.eot +0 -0
  9. data/app/assets/fonts/fae/lato-bold-webfont.svg +4551 -0
  10. data/app/assets/fonts/fae/lato-bold-webfont.ttf +0 -0
  11. data/app/assets/fonts/fae/lato-bold-webfont.woff +0 -0
  12. data/app/assets/fonts/fae/lato-light-webfont.eot +0 -0
  13. data/app/assets/fonts/fae/lato-light-webfont.svg +4241 -0
  14. data/app/assets/fonts/fae/lato-light-webfont.ttf +0 -0
  15. data/app/assets/fonts/fae/lato-light-webfont.woff +0 -0
  16. data/app/assets/fonts/fae/lato-regular-webfont.eot +0 -0
  17. data/app/assets/fonts/fae/lato-regular-webfont.svg +4241 -0
  18. data/app/assets/fonts/fae/lato-regular-webfont.ttf +0 -0
  19. data/app/assets/fonts/fae/lato-regular-webfont.woff +0 -0
  20. data/app/assets/fonts/fae/selection.json +1334 -0
  21. data/app/assets/images/fae/error_bg.jpg +0 -0
  22. data/app/assets/images/fae/error_sad_face.png +0 -0
  23. data/app/assets/images/fae/icons/alert.svg +9 -0
  24. data/app/assets/images/fae/icons/arrow_down.svg +8 -0
  25. data/app/assets/images/fae/icons/arrow_left.svg +9 -0
  26. data/app/assets/images/fae/icons/arrow_right.svg +9 -0
  27. data/app/assets/images/fae/icons/arrow_stacked.svg +8 -0
  28. data/app/assets/images/fae/icons/arrow_up.svg +8 -0
  29. data/app/assets/images/fae/icons/calendar.svg +17 -0
  30. data/app/assets/images/fae/icons/check.svg +7 -0
  31. data/app/assets/images/fae/icons/checkmark.svg +8 -0
  32. data/app/assets/images/fae/icons/chevron_down.svg +7 -0
  33. data/app/assets/images/fae/icons/chevron_left.svg +10 -0
  34. data/app/assets/images/fae/icons/chevron_right.svg +10 -0
  35. data/app/assets/images/fae/icons/chevron_up.svg +7 -0
  36. data/app/assets/images/fae/icons/delete.svg +8 -0
  37. data/app/assets/images/fae/icons/delete_x.svg +8 -0
  38. data/app/assets/images/fae/icons/edit.svg +11 -0
  39. data/app/assets/images/fae/icons/handle.svg +13 -0
  40. data/app/assets/images/fae/icons/home.svg +10 -0
  41. data/app/assets/images/fae/icons/logout.svg +12 -0
  42. data/app/assets/images/fae/icons/magnifying_glass.svg +10 -0
  43. data/app/assets/images/fae/icons/menu.svg +11 -0
  44. data/app/assets/images/fae/icons/offlink.svg +25 -0
  45. data/app/assets/images/fae/icons/plus.svg +8 -0
  46. data/app/assets/images/fae/icons/pulldown.svg +11 -0
  47. data/app/assets/images/fae/icons/search.svg +11 -0
  48. data/app/assets/images/fae/icons/settings.svg +12 -0
  49. data/app/assets/images/fae/icons/sort.svg +11 -0
  50. data/app/assets/images/fae/icons/support.svg +15 -0
  51. data/app/assets/images/fae/icons/trash.svg +10 -0
  52. data/app/assets/images/fae/icons/trumbowyg.svg +1 -0
  53. data/app/assets/images/fae/icons/user.svg +13 -0
  54. data/app/assets/images/fae/icons/users.svg +19 -0
  55. data/app/assets/images/fae/icons/zoom.svg +12 -0
  56. data/app/assets/images/fae/tutorial_model_location.png +0 -0
  57. data/app/assets/images/fae/youtube_helper.jpg +0 -0
  58. data/app/assets/javascripts/fae/_modals.js +60 -0
  59. data/app/assets/javascripts/fae/_tables.js +403 -0
  60. data/app/assets/javascripts/fae/admin.js.erb +11 -0
  61. data/app/assets/javascripts/fae/application.js +63 -0
  62. data/app/assets/javascripts/fae/fae_init.js +8 -0
  63. data/app/assets/javascripts/fae/form/_ajax.js +380 -0
  64. data/app/assets/javascripts/fae/form/_cancel.js +38 -0
  65. data/app/assets/javascripts/fae/form/_filtering.js +276 -0
  66. data/app/assets/javascripts/fae/form/_form.js +60 -0
  67. data/app/assets/javascripts/fae/form/_slugger.js.erb +100 -0
  68. data/app/assets/javascripts/fae/form/_validator.js +459 -0
  69. data/app/assets/javascripts/fae/form/fae_chosen.js +44 -0
  70. data/app/assets/javascripts/fae/form/fileinputer.js +178 -0
  71. data/app/assets/javascripts/fae/form/hinter.js +111 -0
  72. data/app/assets/javascripts/fae/form/inputs/_checkbox.js +27 -0
  73. data/app/assets/javascripts/fae/form/inputs/_color.js +42 -0
  74. data/app/assets/javascripts/fae/form/inputs/_dates.js +78 -0
  75. data/app/assets/javascripts/fae/form/inputs/_select.js +162 -0
  76. data/app/assets/javascripts/fae/form/inputs/_text.js +118 -0
  77. data/app/assets/javascripts/fae/navigation/_global_search.js +184 -0
  78. data/app/assets/javascripts/fae/navigation/_language.js +89 -0
  79. data/app/assets/javascripts/fae/navigation/_navigation.js +206 -0
  80. data/app/assets/javascripts/fae/navigation/_subnav_highlighter.js +81 -0
  81. data/app/assets/javascripts/fae/navigation/sticky.js +186 -0
  82. data/app/assets/javascripts/fae/vendor/chosen.jquery.min.js +2 -0
  83. data/app/assets/javascripts/fae/vendor/frob_core_helpers.js +587 -0
  84. data/app/assets/javascripts/fae/vendor/fryr.js +437 -0
  85. data/app/assets/javascripts/fae/vendor/jqColorPicker.min.js +4 -0
  86. data/app/assets/javascripts/fae/vendor/jquery.daterangepicker.js +1292 -0
  87. data/app/assets/javascripts/fae/vendor/jquery.multi-select.js +534 -0
  88. data/app/assets/javascripts/fae/vendor/jquery.simplemodal.1.4.4.js +719 -0
  89. data/app/assets/javascripts/fae/vendor/jquery.tablesorter.js +1901 -0
  90. data/app/assets/javascripts/fae/vendor/js.cookie.js +139 -0
  91. data/app/assets/javascripts/fae/vendor/moment.min.js +7 -0
  92. data/app/assets/javascripts/fae/vendor/simplemde.min.js +13 -0
  93. data/app/assets/javascripts/fae/vendor/touch_punch.js +11 -0
  94. data/app/assets/javascripts/fae/vendor/trumbowyg.js.erb +4 -0
  95. data/app/assets/javascripts/fae/vendor/trumbowyg/plugins/upload/trumbowyg.upload.js +223 -0
  96. data/app/assets/javascripts/fae/vendor/trumbowyg/trumbowyg.js +1603 -0
  97. data/app/assets/stylesheets/fae/application.css +8 -0
  98. data/app/assets/stylesheets/fae/base.scss +82 -0
  99. data/app/assets/stylesheets/fae/globals/_fonts.scss +43 -0
  100. data/app/assets/stylesheets/fae/globals/_icons.scss +15 -0
  101. data/app/assets/stylesheets/fae/globals/_plugins.scss +51 -0
  102. data/app/assets/stylesheets/fae/globals/_tags.scss +68 -0
  103. data/app/assets/stylesheets/fae/globals/imports/_extends.scss +53 -0
  104. data/app/assets/stylesheets/fae/globals/imports/_mixins.scss +58 -0
  105. data/app/assets/stylesheets/fae/globals/imports/_variables.scss +165 -0
  106. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine.scss +7 -0
  107. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine_functions.scss +88 -0
  108. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine_mixins.scss +280 -0
  109. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine_variables.scss +30 -0
  110. data/app/assets/stylesheets/fae/globals/layout/_base.scss +48 -0
  111. data/app/assets/stylesheets/fae/globals/layout/_breadcrumbs.scss +45 -0
  112. data/app/assets/stylesheets/fae/globals/layout/_content-header.scss +99 -0
  113. data/app/assets/stylesheets/fae/globals/legacy/_pre-1.3.scss +659 -0
  114. data/app/assets/stylesheets/fae/globals/navigation/_base.scss +22 -0
  115. data/app/assets/stylesheets/fae/globals/navigation/_footer.scss +50 -0
  116. data/app/assets/stylesheets/fae/globals/navigation/_header.scss +149 -0
  117. data/app/assets/stylesheets/fae/globals/navigation/_mobilenav.scss +149 -0
  118. data/app/assets/stylesheets/fae/globals/navigation/_search.scss +76 -0
  119. data/app/assets/stylesheets/fae/globals/navigation/_sidenav.scss +142 -0
  120. data/app/assets/stylesheets/fae/globals/navigation/_utility.scss +95 -0
  121. data/app/assets/stylesheets/fae/modules/_alerts.scss +50 -0
  122. data/app/assets/stylesheets/fae/modules/_buttons.scss +62 -0
  123. data/app/assets/stylesheets/fae/modules/_modal.scss +78 -0
  124. data/app/assets/stylesheets/fae/modules/_toggles.scss +48 -0
  125. data/app/assets/stylesheets/fae/modules/forms/_asset-actions.scss +83 -0
  126. data/app/assets/stylesheets/fae/modules/forms/_base.scss +100 -0
  127. data/app/assets/stylesheets/fae/modules/forms/_checkbox.scss +87 -0
  128. data/app/assets/stylesheets/fae/modules/forms/_colorpicker.scss +57 -0
  129. data/app/assets/stylesheets/fae/modules/forms/_date.scss +335 -0
  130. data/app/assets/stylesheets/fae/modules/forms/_hints.scss +40 -0
  131. data/app/assets/stylesheets/fae/modules/forms/_label.scss +57 -0
  132. data/app/assets/stylesheets/fae/modules/forms/_radio.scss +69 -0
  133. data/app/assets/stylesheets/fae/modules/forms/_select.scss +317 -0
  134. data/app/assets/stylesheets/fae/modules/forms/_simple-mde.scss +29 -0
  135. data/app/assets/stylesheets/fae/modules/forms/_text.scss +62 -0
  136. data/app/assets/stylesheets/fae/modules/forms/_textarea.scss +16 -0
  137. data/app/assets/stylesheets/fae/modules/forms/_validation.scss +63 -0
  138. data/app/assets/stylesheets/fae/modules/tables/_actions.scss +41 -0
  139. data/app/assets/stylesheets/fae/modules/tables/_base.scss +63 -0
  140. data/app/assets/stylesheets/fae/modules/tables/_collapsible.scss +76 -0
  141. data/app/assets/stylesheets/fae/modules/tables/_filters.scss +61 -0
  142. data/app/assets/stylesheets/fae/modules/tables/_image.scss +21 -0
  143. data/app/assets/stylesheets/fae/modules/tables/_pagination.scss +34 -0
  144. data/app/assets/stylesheets/fae/modules/tables/_sorting.scss +58 -0
  145. data/app/assets/stylesheets/fae/modules/tables/_sticky.scss +9 -0
  146. data/app/assets/stylesheets/fae/modules/tables/_tooltips.scss +24 -0
  147. data/app/assets/stylesheets/fae/pages/_error.scss +35 -0
  148. data/app/assets/stylesheets/fae/pages/_help.scss +28 -0
  149. data/app/assets/stylesheets/fae/pages/_home.scss +18 -0
  150. data/app/assets/stylesheets/fae/pages/_login.scss +137 -0
  151. data/app/assets/stylesheets/fae/vendor/chosen.css +377 -0
  152. data/app/assets/stylesheets/fae/vendor/daterangepicker.css +227 -0
  153. data/app/assets/stylesheets/fae/vendor/reset.css +48 -0
  154. data/app/assets/stylesheets/fae/vendor/simplemde.min.css +7 -0
  155. data/app/assets/stylesheets/fae/vendor/trumbowyg.css +584 -0
  156. data/app/controllers/concerns/fae/application_controller_concern.rb +1 -0
  157. data/app/controllers/concerns/fae/asset_cloner.rb +46 -0
  158. data/app/controllers/concerns/fae/cloneable.rb +136 -0
  159. data/app/controllers/fae/application_controller.rb +123 -0
  160. data/app/controllers/fae/base_controller.rb +117 -0
  161. data/app/controllers/fae/files_controller.rb +26 -0
  162. data/app/controllers/fae/images_controller.rb +37 -0
  163. data/app/controllers/fae/nested_base_controller.rb +100 -0
  164. data/app/controllers/fae/options_controller.rb +29 -0
  165. data/app/controllers/fae/pages_controller.rb +44 -0
  166. data/app/controllers/fae/setup_controller.rb +54 -0
  167. data/app/controllers/fae/static_pages_controller.rb +54 -0
  168. data/app/controllers/fae/users_controller.rb +71 -0
  169. data/app/controllers/fae/utilities_controller.rb +61 -0
  170. data/app/helpers/fae/application_helper.rb +114 -0
  171. data/app/helpers/fae/fae_helper.rb +6 -0
  172. data/app/helpers/fae/form_helper.rb +240 -0
  173. data/app/helpers/fae/nested_form_helper.rb +39 -0
  174. data/app/helpers/fae/view_helper.rb +175 -0
  175. data/app/inputs/date_range_input.rb +17 -0
  176. data/app/inputs/radio_collection_input.rb +17 -0
  177. data/app/inputs/symbol_input.rb +5 -0
  178. data/app/models/concerns/fae/assets_validatable.rb +12 -0
  179. data/app/models/concerns/fae/authorization_concern.rb +12 -0
  180. data/app/models/concerns/fae/base_model_concern.rb +105 -0
  181. data/app/models/concerns/fae/change_concern.rb +1 -0
  182. data/app/models/concerns/fae/file_concern.rb +1 -0
  183. data/app/models/concerns/fae/image_concern.rb +1 -0
  184. data/app/models/concerns/fae/navigation_concern.rb +10 -0
  185. data/app/models/concerns/fae/option_concern.rb +1 -0
  186. data/app/models/concerns/fae/page_validatable.rb +26 -0
  187. data/app/models/concerns/fae/paper_trailer.rb +8 -0
  188. data/app/models/concerns/fae/role_concern.rb +1 -0
  189. data/app/models/concerns/fae/sortable.rb +51 -0
  190. data/app/models/concerns/fae/static_page_concern.rb +1 -0
  191. data/app/models/concerns/fae/text_area_concern.rb +1 -0
  192. data/app/models/concerns/fae/text_field_concern.rb +1 -0
  193. data/app/models/concerns/fae/trackable.rb +124 -0
  194. data/app/models/concerns/fae/user_concern.rb +7 -0
  195. data/app/models/fae/authorization.rb +8 -0
  196. data/app/models/fae/change.rb +53 -0
  197. data/app/models/fae/file.rb +24 -0
  198. data/app/models/fae/image.rb +33 -0
  199. data/app/models/fae/navigation.rb +132 -0
  200. data/app/models/fae/option.rb +38 -0
  201. data/app/models/fae/role.rb +18 -0
  202. data/app/models/fae/static_page.rb +109 -0
  203. data/app/models/fae/text_area.rb +14 -0
  204. data/app/models/fae/text_field.rb +14 -0
  205. data/app/models/fae/user.rb +67 -0
  206. data/app/uploaders/fae/file_uploader.rb +26 -0
  207. data/app/uploaders/fae/image_uploader.rb +28 -0
  208. data/app/validators/fae/cross_model_uniqueness_validator.rb +14 -0
  209. data/app/views/devise/confirmations/new.html.slim +13 -0
  210. data/app/views/devise/mailer/confirmation_instructions.html.slim +3 -0
  211. data/app/views/devise/mailer/reset_password_instructions.html.slim +5 -0
  212. data/app/views/devise/mailer/unlock_instructions.html.slim +4 -0
  213. data/app/views/devise/passwords/edit.html.slim +10 -0
  214. data/app/views/devise/passwords/new.html.slim +10 -0
  215. data/app/views/devise/registrations/edit.html.slim +22 -0
  216. data/app/views/devise/registrations/new.html.slim +15 -0
  217. data/app/views/devise/sessions/new.html.slim +7 -0
  218. data/app/views/devise/shared/_links.slim +25 -0
  219. data/app/views/devise/unlocks/new.html.slim +13 -0
  220. data/app/views/fae/application/_breadcrumb.html.slim +19 -0
  221. data/app/views/fae/application/_content_form.html.slim +55 -0
  222. data/app/views/fae/application/_credit.slim +6 -0
  223. data/app/views/fae/application/_file_uploader.html.slim +36 -0
  224. data/app/views/fae/application/_flash_messages.slim +2 -0
  225. data/app/views/fae/application/_global_search_results.html.slim +37 -0
  226. data/app/views/fae/application/_header.slim +50 -0
  227. data/app/views/fae/application/_markdown_helper.slim +41 -0
  228. data/app/views/fae/application/_mobilenav.slim +66 -0
  229. data/app/views/fae/application/_sidenav.slim +23 -0
  230. data/app/views/fae/application/_user_log.html.slim +36 -0
  231. data/app/views/fae/images/_image_uploader.html.slim +66 -0
  232. data/app/views/fae/options/_form.html.slim +16 -0
  233. data/app/views/fae/options/edit.html.slim +1 -0
  234. data/app/views/fae/pages/activity_log.html.slim +32 -0
  235. data/app/views/fae/pages/disabled_environment.html.slim +4 -0
  236. data/app/views/fae/pages/error404.html.slim +7 -0
  237. data/app/views/fae/pages/help.html.slim +35 -0
  238. data/app/views/fae/pages/home.html.slim +36 -0
  239. data/app/views/fae/setup/first_user.html.slim +11 -0
  240. data/app/views/fae/shared/_errors.slim +4 -0
  241. data/app/views/fae/shared/_form_header.html.slim +40 -0
  242. data/app/views/fae/shared/_index_header.html.slim +26 -0
  243. data/app/views/fae/shared/_nested_table.html.slim +49 -0
  244. data/app/views/fae/shared/_recent_changes.html.slim +22 -0
  245. data/app/views/fae/shared/_shared_nested_table.html.slim +46 -0
  246. data/app/views/fae/static_pages/index.html.slim +13 -0
  247. data/app/views/fae/users/_form.html.slim +19 -0
  248. data/app/views/fae/users/edit.html.slim +1 -0
  249. data/app/views/fae/users/index.html.slim +23 -0
  250. data/app/views/fae/users/new.html.slim +1 -0
  251. data/app/views/fae/users/settings.html.slim +1 -0
  252. data/app/views/kaminari/fae/_gap.html.slim +8 -0
  253. data/app/views/kaminari/fae/_next_page.html.slim +9 -0
  254. data/app/views/kaminari/fae/_page.html.slim +15 -0
  255. data/app/views/kaminari/fae/_paginator.html.slim +15 -0
  256. data/app/views/kaminari/fae/_prev_page.html.slim +9 -0
  257. data/app/views/layouts/devise.html.slim +29 -0
  258. data/app/views/layouts/fae/application.html.slim +23 -0
  259. data/app/views/layouts/fae/error.html.slim +11 -0
  260. data/config/deploy.rb +73 -0
  261. data/config/deploy/dev.rb +19 -0
  262. data/config/deploy/prod.rb +19 -0
  263. data/config/deploy/stage.rb +19 -0
  264. data/config/initializers/assets.rb +1 -0
  265. data/config/initializers/carrierwave.rb +3 -0
  266. data/config/initializers/devise.rb +258 -0
  267. data/config/initializers/devise_monkeypatch.rb +11 -0
  268. data/config/initializers/fae_judge.rb +3 -0
  269. data/config/initializers/inflections.rb +16 -0
  270. data/config/initializers/kaminari_config.rb +10 -0
  271. data/config/initializers/simple_form.rb +147 -0
  272. data/config/initializers/time_formats.rb +3 -0
  273. data/config/locales/devise.en.yml +59 -0
  274. data/config/locales/devise.zh-CN.yml +59 -0
  275. data/config/locales/fae.en.yml +10 -0
  276. data/config/locales/fae.zh-CN.yml +10 -0
  277. data/config/locales/simple_form.en.yml +26 -0
  278. data/config/locales/simple_form.zh-CN.yml +26 -0
  279. data/config/routes.rb +46 -0
  280. data/db/migrate/20140809222030_add_user_table.rb +49 -0
  281. data/db/migrate/20140822224029_create_fae_roles.rb +10 -0
  282. data/db/migrate/20141008180718_create_fae_images_table.rb +19 -0
  283. data/db/migrate/20141017194616_create_fae_options.rb +16 -0
  284. data/db/migrate/20141021181327_create_fae_files.rb +17 -0
  285. data/db/migrate/20141021183047_create_fae_text_areas.rb +16 -0
  286. data/db/migrate/20141021184311_create_fae_pages.rb +13 -0
  287. data/db/migrate/20141105214814_create_fae_text_fields.rb +15 -0
  288. data/db/migrate/20150930224821_create_fae_changes.rb +17 -0
  289. data/lib/fae-rails.rb +6 -0
  290. data/lib/fae/concerns/models/base.rb +8 -0
  291. data/lib/fae/engine.rb +37 -0
  292. data/lib/fae/options.rb +35 -0
  293. data/lib/fae/validation_helper_collection.rb +76 -0
  294. data/lib/fae/version.rb +3 -0
  295. data/lib/file_size_validator.rb +71 -0
  296. data/lib/generators/fae/base_generator.rb +156 -0
  297. data/lib/generators/fae/controller_generator.rb +13 -0
  298. data/lib/generators/fae/install_generator.rb +61 -0
  299. data/lib/generators/fae/model_generator.rb +11 -0
  300. data/lib/generators/fae/nested_index_scaffold_generator.rb +36 -0
  301. data/lib/generators/fae/nested_scaffold_generator.rb +51 -0
  302. data/lib/generators/fae/page_generator.rb +65 -0
  303. data/lib/generators/fae/scaffold_generator.rb +15 -0
  304. data/lib/generators/fae/templates/assets/fae.js +6 -0
  305. data/lib/generators/fae/templates/assets/fae.scss +2 -0
  306. data/lib/generators/fae/templates/controllers/nested_index_scaffold_controller.rb +81 -0
  307. data/lib/generators/fae/templates/controllers/nested_scaffold_controller.rb +13 -0
  308. data/lib/generators/fae/templates/controllers/scaffold_controller.rb +13 -0
  309. data/lib/generators/fae/templates/controllers/static_pages_controller.rb +10 -0
  310. data/lib/generators/fae/templates/initializers/fae.rb +63 -0
  311. data/lib/generators/fae/templates/initializers/fae_fine.rb +51 -0
  312. data/lib/generators/fae/templates/initializers/judge.rb +6 -0
  313. data/lib/generators/fae/templates/models/concerns/authorization_concern.rb +27 -0
  314. data/lib/generators/fae/templates/models/concerns/navigation_concern.rb +33 -0
  315. data/lib/generators/fae/templates/models/pages_model.rb +14 -0
  316. data/lib/generators/fae/templates/tasks/fae_tasks.rake +19 -0
  317. data/lib/generators/fae/templates/views/_form.html.slim +18 -0
  318. data/lib/generators/fae/templates/views/_form_index_nested.html.slim +13 -0
  319. data/lib/generators/fae/templates/views/_form_nested.html.slim +17 -0
  320. data/lib/generators/fae/templates/views/edit.html.slim +1 -0
  321. data/lib/generators/fae/templates/views/edit_nested.html.slim +3 -0
  322. data/lib/generators/fae/templates/views/index.html.slim +35 -0
  323. data/lib/generators/fae/templates/views/index_nested.html.slim +8 -0
  324. data/lib/generators/fae/templates/views/new.html.slim +1 -0
  325. data/lib/generators/fae/templates/views/new_nested.html.slim +3 -0
  326. data/lib/generators/fae/templates/views/static_page_form.html.slim +15 -0
  327. data/lib/generators/fae/templates/views/table_nested.html.slim +4 -0
  328. metadata +692 -0
@@ -0,0 +1,60 @@
1
+ /* global Fae */
2
+
3
+ /**
4
+ * Fae form
5
+ * @namespace form
6
+ * @memberof Fae
7
+ */
8
+ Fae.form = {
9
+ ready: function() {
10
+ // Mutate DOM to support two column labels for all standard inputs
11
+ this.makeTwoColumnLabels();
12
+
13
+ this.dates.init();
14
+ this.color.init();
15
+ this.text.init();
16
+ this.select.init();
17
+ this.checkbox.init();
18
+ this.validator.init();
19
+ this.cancel.init();
20
+ this.ajax.init();
21
+ this.filtering.init();
22
+ this.slugger.init();
23
+
24
+ // input type=file customization
25
+ // This doesn't work in IE. It's not worth figuring out why by this point. IE9 gets plain file uploader.
26
+ if (!FCH.IE9) {
27
+ $('.input.file').fileinputer();
28
+ }
29
+
30
+ // make all the hint areas
31
+ $('.hint').hinter();
32
+ },
33
+
34
+ makeTwoColumnLabels: function() {
35
+ $('.input label').each(function() {
36
+ var $element = $(this);
37
+
38
+ // Bail if we cannot find any helper_text
39
+ if (!$element.find('.helper_text').length) {
40
+ $element.addClass('has_no_helper_text');
41
+ }
42
+
43
+ // If present, get all DOM nodes w/ contents(), but ignore the .helper_text
44
+ var label_inner = $element.contents().filter(function() {
45
+ return !$(this).hasClass('helper_text');
46
+ });
47
+ var helper_text = $element.find('.helper_text');
48
+
49
+ // Replace existing label w/ newly wrapped elements, sans .helper_text
50
+ label_inner = $('<div class="label_inner" />').html(label_inner);
51
+ $element.html(label_inner);
52
+
53
+ // But then add .helper_text as a sibling
54
+ $element.append(helper_text);
55
+
56
+ // Ensure that we mark this input as having two column label support
57
+ $element.addClass('label--two_col');
58
+ });
59
+ }
60
+ };
@@ -0,0 +1,100 @@
1
+ /* global Fae */
2
+
3
+ 'use strict';
4
+
5
+ /**
6
+ * Fae form
7
+ * @namespace form
8
+ * @memberof Fae
9
+ */
10
+ Fae.form.slugger = {
11
+ init: function() {
12
+ this.addListener();
13
+ },
14
+
15
+ /**
16
+ * Attach listeners to inputs and update slug fields with original safe values from the original inputs
17
+ */
18
+ addListener: function() {
19
+ var _this = this;
20
+
21
+ $('.slug').each(function() {
22
+ var $form = $(this).closest('form');
23
+ var $sluggers = $form.find('.slugger');
24
+ var $slug = $form.find('.slug');
25
+ var $select_slugger = $('.select.slugger');
26
+
27
+ if ($slug.val() !== '') {
28
+ $sluggers.removeClass('slugger');
29
+
30
+ } else {
31
+ // If it's a text field, listen for type input
32
+ $sluggers.keyup(function(){
33
+ var text = _this._digestSlug( $sluggers );
34
+ $slug.val( text );
35
+ });
36
+
37
+ // If it's a select field, listen for the change
38
+ if ($select_slugger.length) {
39
+ $select_slugger.change(function(){
40
+ var text = _this._digestSlug( $sluggers );
41
+ $slug.val( text );
42
+ });
43
+
44
+ };
45
+ }
46
+ });
47
+ },
48
+
49
+ /**
50
+ * Convert a group of selects or text fields into one slug string
51
+ * @access protected
52
+ * @param {jQuery} $sluggers - Input or inputs that should be converted into a URL-safe string
53
+ * @return {String}
54
+ */
55
+ _digestSlug: function($sluggers) {
56
+ var slug_text = []
57
+
58
+ $sluggers.each(function() {
59
+ var $this = $(this);
60
+
61
+ if ($this.val().length) {
62
+
63
+ if ($this.is('input')) {
64
+ slug_text.push( $this.val() );
65
+
66
+ } else {
67
+ slug_text.push( $this.find('option:selected').text() );
68
+
69
+ }
70
+ }
71
+ });
72
+
73
+ // Combine all active slug fields for the query
74
+ slug_text = slug_text.join(' ');
75
+
76
+ // Strip accented characters
77
+ var from = 'àáâãäæåçèéêëęēėìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ';
78
+ var to = 'aaaaaaaceeeeeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY';
79
+
80
+ // Loop through all accented characters and replace with non-accents
81
+ for (var i = 0; i < from.length; i++) {
82
+ slug_text = slug_text.replace( new RegExp(from.charAt(i), 'g'), to.charAt(i) );
83
+ }
84
+
85
+ // Remove leading and trailing spaces
86
+ // Make them lowercase
87
+ // Remove slashes, quotes or periods
88
+ // Replace white spaces with a Fae.slug_separator
89
+ // Remove leading and trailing dashes
90
+ slug_text = slug_text
91
+ .trim()
92
+ .toLowerCase()
93
+ .replace(/[^<%= Fae.slug_separator %>\w\s]/g, '')
94
+ .replace(/[<%= Fae.slug_separator %>\s]+/g, '<%= Fae.slug_separator %>')
95
+ .replace(/(^<%= Fae.slug_separator %>)|(<%= Fae.slug_separator %>$)/g, '');
96
+
97
+ return slug_text;
98
+ }
99
+
100
+ };
@@ -0,0 +1,459 @@
1
+ /* global Fae, judge, FCH */
2
+
3
+ /**
4
+ * Fae form validator
5
+ * @namespace form.validator
6
+ * @memberof form
7
+ */
8
+ Fae.form.validator = {
9
+
10
+ is_valid: '',
11
+ validations_called: 0,
12
+ validations_returned: 0,
13
+ validation_test_count: 0,
14
+
15
+ init: function () {
16
+ // validate all forms except the login form
17
+ if ($('form').not('#login_form').length) {
18
+ this.password_confirmation_validation.init();
19
+ this.passwordPresenceConditional();
20
+ this.bindValidationEvents();
21
+ this.formValidate();
22
+ this.length_counter.init();
23
+ }
24
+ },
25
+
26
+ /**
27
+ * Validate the entire form on submit and stop it if the form is invalid
28
+ */
29
+ formValidate: function () {
30
+ var _this = this;
31
+
32
+ FCH.$document.on('submit', 'form:not([data-remote=true])', function (e) {
33
+ var $this = $(this);
34
+
35
+ if ($this.data('passed_validation') !== 'true') {
36
+
37
+ // pause form submission
38
+ e.preventDefault();
39
+
40
+ // set defaults
41
+ _this.is_valid = true;
42
+ _this.validations_called = 0;
43
+ _this.validations_returned = 0;
44
+ _this.validation_test_count = 0;
45
+
46
+ // Scope the data-validation only to the form submitted
47
+ $('[data-validate]', $this).each(function () {
48
+ if ($(this).data('validate').length) {
49
+ _this.validations_called++;
50
+ _this._judgeIt($(this));
51
+ }
52
+ });
53
+
54
+ // Catch visible errors for image/file inputs hitting the fae config file size limiter
55
+ $('.input.file', $this).each(function () {
56
+ if ($(this).hasClass('field_with_errors')) {
57
+ _this.is_valid = false;
58
+ }
59
+ });
60
+
61
+ _this.testValidation($this);
62
+
63
+ }
64
+
65
+ });
66
+ },
67
+
68
+ /**
69
+ * Tests a forms validation after all validation checks have responded
70
+ * Polls validations responses every 50ms to allow uniqueness AJAX calls to complete
71
+ */
72
+ testValidation: function($this) {
73
+ var _this = this;
74
+ _this.validation_test_count++;
75
+
76
+ setTimeout(function(){
77
+
78
+ // if all the validation checks have returned a response
79
+ if (_this.validations_called === _this.validations_returned) {
80
+
81
+ if (_this.is_valid) {
82
+ // if form is valid, submit it
83
+ $this.data('passed_validation', 'true');
84
+
85
+ $this.submit();
86
+ } else {
87
+ // otherwise scroll to the top to display alerts
88
+ Fae.navigation.language.checkForHiddenErrors();
89
+ FCH.smoothScroll($('#js-main-header'), 500, 100, 0);
90
+
91
+ if ($(".field_with_errors").length) {
92
+ $('.alert').slideDown('fast').delay(3000).slideUp('fast');
93
+ }
94
+ }
95
+
96
+ } else {
97
+ // check again if it hasn't run more than 50 times
98
+ // (to prevent against infinite loop)
99
+ if (_this.validation_test_count < 50) {
100
+ _this.testValidation($this);
101
+ }
102
+ }
103
+
104
+ }, 50);
105
+
106
+ },
107
+
108
+ /**
109
+ * Bind validation events based on input type
110
+ */
111
+ bindValidationEvents: function ($scope) {
112
+ var _this = this;
113
+
114
+ if (typeof($scope) === 'undefined'){
115
+ $scope = $('body');
116
+ }
117
+
118
+ $scope.find('[data-validate]').each(function () {
119
+ var $this = $(this);
120
+
121
+ if ($this.data('validate').length) {
122
+ if ($this.is('input:not(.hasDatepicker), textarea')) {
123
+ // normal inputs validate on blur
124
+ $this.blur(function () {
125
+ _this._judgeIt($this);
126
+ });
127
+
128
+ } else if ($this.hasClass('hasDatepicker')) {
129
+ // date pickers need a little delay
130
+ $this.blur(function () {
131
+ setTimeout(function(){ _this._judgeIt($this); }, 500);
132
+ });
133
+
134
+ } else if ($this.is('select')) {
135
+ // selects validate on change
136
+ $this.change(function () {
137
+ _this._judgeIt($this);
138
+ });
139
+ }
140
+ }
141
+ });
142
+ },
143
+
144
+
145
+ /**
146
+ * Initialize Judge on a field
147
+ * @protected
148
+ * @param {jQuery} $input - field to be validated
149
+ */
150
+ _judgeIt: function ($input) {
151
+ var _this = this;
152
+
153
+ judge.validate($input[0], {
154
+ valid: function () {
155
+ _this.validations_returned++;
156
+ _this._createSuccessClass($input);
157
+ },
158
+ invalid: function (input, messages) {
159
+ _this.validations_returned++;
160
+ messages = _this._removeIgnoredErrors(messages);
161
+ if (messages.length) {
162
+ _this.is_valid = false;
163
+ _this._createOrReplaceError($input, messages);
164
+ }
165
+ }
166
+ });
167
+ },
168
+
169
+ /**
170
+ * Strips out ignored error messages
171
+ * @protected
172
+ * @param messages - array of error messages from Judge
173
+ */
174
+ _removeIgnoredErrors: function (messages) {
175
+ // Ignored error messages from Judge:
176
+ // 'Judge validation for Release#name not allowed'
177
+ // 'Slug Request error: 0'
178
+ var ignored_error_substrings = ['Judge validation', 'Request error'];
179
+
180
+ // loop through messages
181
+ for (var i = 0; i < messages.length; i++) {
182
+ // loop through ignored errors
183
+ for (var j = 0; j < ignored_error_substrings.length; j++) {
184
+ // if the substring exists in the error message
185
+ if (messages[i].indexOf(ignored_error_substrings[j]) > -1) {
186
+ // log it in the console and remove message
187
+ window.console && console.log('Ignoring error: ', messages[i]);
188
+ messages.splice(i, 1);
189
+ break;
190
+ }
191
+ }
192
+ }
193
+
194
+ return messages;
195
+ },
196
+
197
+ /**
198
+ * Adds and removes the appropriate classes to display the success styles
199
+ * @protected
200
+ * @param {jQuery} $input - Input field (can be a chosen object)
201
+ */
202
+ _createSuccessClass: function ($input) {
203
+ var $styled_input = this._setTargetInput($input);
204
+ $styled_input.addClass('valid').removeClass('invalid');
205
+
206
+ $input.parent().removeClass('field_with_errors').children('.error').remove();
207
+ },
208
+
209
+ /**
210
+ * Adds and removes the appropriate classes to display the error styles
211
+ * @protected
212
+ * @param {jQuery} $input - Input field
213
+ * @param {Array} messages - Error messages to display
214
+ */
215
+ _createOrReplaceError: function ($input, messages) {
216
+ var $styled_input = this._setTargetInput($input);
217
+ $styled_input.addClass('invalid').removeClass('valid');
218
+
219
+ var $wrapper = $input.closest('.input');
220
+ if ($wrapper.children('.error').length) {
221
+ $wrapper.children('.error').text(messages.join(', '));
222
+ } else {
223
+ $wrapper.addClass('field_with_errors').append("<span class='error'>" + messages.join(', ') + "</span>");
224
+ }
225
+ },
226
+
227
+ /**
228
+ * A DRY method for setting the element that should take the .valid or .invalid style
229
+ * @protected
230
+ * @param {jQuery} $input - Input field for a chosen object
231
+ * @return {jQuery} The chosen container
232
+ */
233
+ _setTargetInput: function ($input) {
234
+ var $styled_input = $input;
235
+
236
+ // If field is a chosen input
237
+ if ( $input.next('.chosen-container').length ) {
238
+ if ($input.next('.chosen-container').find('.chosen-single').length) {
239
+ $styled_input = $input.next('.chosen-container').find('.chosen-single');
240
+
241
+ } else if ($input.next('.chosen-container').find('.chosen-choices').length) {
242
+ $styled_input = $input.next('.chosen-container').find('.chosen-choices');
243
+
244
+ }
245
+ } else if ($input.hasClass('mde-enabled')) {
246
+ $styled_input = $input.siblings('.editor-toolbar, .CodeMirror-wrap');
247
+
248
+ }
249
+
250
+ return $styled_input;
251
+ },
252
+
253
+ /**
254
+ * Removes a field's Judge validation
255
+ * @param {jQuery} $field - Input fields
256
+ * @param {String} kind - Type of validation (e.g. 'presence' or 'confirmation')
257
+ */
258
+ stripValidation: function($field, kind) {
259
+ var validations = $field.data('validate');
260
+
261
+ for (var i = 0; i < validations.length; i++) {
262
+ // validation items can be strings or JSON objects
263
+ // let's convert the strings to JSON so we're dealing with consistent types
264
+ if (typeof validations[i] == 'string' || validations[i] instanceof String) {
265
+ validations[i] = JSON.parse(validations[i]);
266
+ }
267
+
268
+ // if the kind matches, remove it from the array
269
+ if (validations[i]['kind'] === kind) {
270
+ validations.splice(i, 1);
271
+ }
272
+
273
+ // convert JSON back to a string
274
+ validations[i] = JSON.stringify(validations[i]);
275
+ }
276
+ $field.attr('data-validate', '[' + validations + ']');
277
+ },
278
+
279
+ /**
280
+ * Password Confirmation Validation
281
+ * @description Judge validates confirmation on the original field. This is a hack to remove Judge's validation and add it to the confirmation field
282
+ * @namespace
283
+ * @memberof! validator
284
+ */
285
+ password_confirmation_validation: {
286
+ init: function() {
287
+ var _this = this;
288
+
289
+ _this.$password_field = $('#user_password');
290
+ _this.$password_confirmation_field = $('#user_password_confirmation');
291
+
292
+ if (_this.$password_confirmation_field.length) {
293
+ Fae.form.validator.stripValidation(_this.$password_field, 'confirmation');
294
+ _this.addCustomValidation();
295
+ }
296
+ },
297
+
298
+ /**
299
+ * Validate password on blur and form submit; halt form execution if invalid
300
+ */
301
+ addCustomValidation: function() {
302
+ var _this = this;
303
+
304
+ /**
305
+ * Displays success or error depending on password validation
306
+ * @private
307
+ * @param {Object} self - The password_confirmation_validation object
308
+ * @see {@link validator.password_confirmation_validation.addCustomValidation addCustomValidation}
309
+ */
310
+ function validateConfirmation() {
311
+ var validator = Fae.form.validator;
312
+
313
+ if (_this.$password_field.val() === _this.$password_confirmation_field.val()) {
314
+ validator._createSuccessClass(_this.$password_confirmation_field);
315
+ } else {
316
+ var message = ['must match Password'];
317
+ validator.is_valid = false;
318
+ validator._createOrReplaceError(_this.$password_confirmation_field, message);
319
+ }
320
+ }
321
+
322
+ this.$password_confirmation_field.on('blur', validateConfirmation);
323
+
324
+ $('form').on('submit', function(ev) {
325
+ _this.is_valid = true;
326
+ validateConfirmation();
327
+
328
+ if (!_this.is_valid) {
329
+ ev.preventDefault();
330
+ }
331
+ });
332
+ }
333
+ },
334
+
335
+ /**
336
+ * Judge always read the `on: :create` validations, so we need to strip the password presence validation on the user edit form
337
+ */
338
+ passwordPresenceConditional: function() {
339
+ var $edit_user_password = $('.edit_user #user_password');
340
+ if ($edit_user_password.length) {
341
+ this.stripValidation($edit_user_password, 'presence');
342
+ }
343
+ },
344
+
345
+ /**
346
+ * Length Counter
347
+ * @namespace
348
+ * @memberof! validator
349
+ */
350
+ length_counter: {
351
+
352
+ init: function(){
353
+ this.findLengthValidations();
354
+ },
355
+
356
+ /**
357
+ * Add counter text to fields that validate based on character counts
358
+ */
359
+ findLengthValidations: function() {
360
+ var _this = this;
361
+
362
+ $('[data-validate]').each(function () {
363
+ var $this = $(this);
364
+
365
+ if ($this.data('validate').length ) {
366
+ var validations = $this.data('validate');
367
+
368
+ $.grep(validations, function(item){
369
+ if (item.kind === 'length'){
370
+ $this.data('length-max', item.options.maximum);
371
+ _this._setupCounter($this);
372
+ }
373
+ });
374
+ }
375
+ });
376
+ },
377
+
378
+ /**
379
+ * Sets up the counter
380
+ * @access protected
381
+ * @param {jQuery} $elem - Input field being counted
382
+ */
383
+ _setupCounter: function($elem) {
384
+ var _this = this;
385
+
386
+ _this._createCounterDiv($elem);
387
+ _this.updateCounter($elem);
388
+
389
+ $elem
390
+ .keyup(function() {
391
+ _this.updateCounter($elem);
392
+ })
393
+ .keypress(function(e) {
394
+ if (_this._charactersLeft($elem) <= 0) {
395
+ if (e.keyCode !== 8 && e.keyCode !== 46) {
396
+ e.preventDefault();
397
+ }
398
+ }
399
+ });
400
+ },
401
+
402
+ /**
403
+ * Creates counter HTML
404
+ * @protected
405
+ * @param {jQuery} $elem - Input field to evaluate
406
+ */
407
+ _createCounterDiv: function($elem) {
408
+ if ($elem.siblings('.counter').length === 0) {
409
+ var text = "Maximum Characters: " + $elem.data('length-max');
410
+ text += " / <span class='characters-left'></span>";
411
+
412
+ var $counter_div = $('<div />', {
413
+ class: 'counter',
414
+ html: '<p>' + text + '</p>'
415
+ });
416
+
417
+ $elem.parent().append( $counter_div );
418
+ }
419
+ },
420
+
421
+ /**
422
+ * Updates the counter count and class
423
+ * @param {jQuery} $elem - Input field to evaluate
424
+ */
425
+ updateCounter: function($elem) {
426
+ var $count_span = $elem.siblings('.counter').find('.characters-left');
427
+ if ($count_span.length) {
428
+ var current = this._charactersLeft($elem);
429
+ var text;
430
+
431
+ if (current >= 0) {
432
+ text = 'Characters Left: ';
433
+ $count_span.removeClass('overCount');
434
+ } else {
435
+ text = 'Characters Over: ';
436
+ $count_span.addClass('overCount');
437
+ }
438
+
439
+ $count_span.text(text + Math.abs(current));
440
+ }
441
+ },
442
+
443
+ /**
444
+ * Calculate character's left
445
+ * @protected
446
+ * @param {jQuery} $elem - Input field being counted
447
+ * @return {integer} The number of characters left
448
+ */
449
+ _charactersLeft: function($elem) {
450
+ var input_value = $elem.val();
451
+ var current = $elem.data('length-max') - input_value.length;
452
+ // Rails counts a newline as two characters, so let's make up for it here
453
+ current -= (input_value.match(/\n/g) || []).length;
454
+
455
+ return current;
456
+ }
457
+ }
458
+
459
+ };