cardboard_cms 0.1.4

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 (360) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +42 -0
  5. data/Gemfile.lock +324 -0
  6. data/Guardfile +23 -0
  7. data/LICENSE.txt +677 -0
  8. data/README.md +370 -0
  9. data/Rakefile +23 -0
  10. data/app/assets/images/cardboard/.gitkeep +0 -0
  11. data/app/assets/images/cardboard/bg.png +0 -0
  12. data/app/assets/images/cardboard/calendar.png +0 -0
  13. data/app/assets/images/cardboard/lorem-ipsum-coffe-mug.jpg +0 -0
  14. data/app/assets/javascripts/cardboard.js +1 -0
  15. data/app/assets/javascripts/cardboard/admin.js +62 -0
  16. data/app/assets/javascripts/cardboard/content_sidebar.js +27 -0
  17. data/app/assets/javascripts/cardboard/datepicker.js +19 -0
  18. data/app/assets/javascripts/cardboard/main_sidebar.js +32 -0
  19. data/app/assets/javascripts/cardboard/rich_text.js +81 -0
  20. data/app/assets/javascripts/cardboard/search_filter.js +28 -0
  21. data/app/assets/stylesheets/cardboard.css.scss +2 -0
  22. data/app/assets/stylesheets/cardboard/_bootstrap-select.css.scss +183 -0
  23. data/app/assets/stylesheets/cardboard/_content.css.scss +35 -0
  24. data/app/assets/stylesheets/cardboard/_content_sidebar.css.scss +96 -0
  25. data/app/assets/stylesheets/cardboard/_framework.css.scss +129 -0
  26. data/app/assets/stylesheets/cardboard/_main_sidebar.css.scss +38 -0
  27. data/app/assets/stylesheets/cardboard/_main_topbar.css.scss +62 -0
  28. data/app/assets/stylesheets/cardboard/_resources.css.scss +28 -0
  29. data/app/assets/stylesheets/cardboard/_rich_text.css.scss +6 -0
  30. data/app/assets/stylesheets/cardboard/_variables.scss +326 -0
  31. data/app/assets/stylesheets/cardboard/admin.css.scss +63 -0
  32. data/app/controllers/cardboard/application_controller.rb +45 -0
  33. data/app/controllers/cardboard/dashboard_controller.rb +9 -0
  34. data/app/controllers/cardboard/my_account_controller.rb +27 -0
  35. data/app/controllers/cardboard/pages_controller.rb +34 -0
  36. data/app/controllers/cardboard/resource_controller.rb +61 -0
  37. data/app/controllers/cardboard/settings_controller.rb +28 -0
  38. data/app/controllers/cardboard/super_user_controller.rb +8 -0
  39. data/app/controllers/pages_controller.rb +29 -0
  40. data/app/decorators/controllers/application_controller_decorator.rb +9 -0
  41. data/app/decorators/lib/cardboard/user_class_decorator.rb +32 -0
  42. data/app/helpers/cardboard/application_helper.rb +4 -0
  43. data/app/helpers/cardboard/public_helper.rb +53 -0
  44. data/app/helpers/cardboard/resource_helper.rb +80 -0
  45. data/app/inputs/date_picker_input.rb +10 -0
  46. data/app/inputs/date_time_input.rb +7 -0
  47. data/app/inputs/image_input.rb +3 -0
  48. data/app/inputs/rich_text_input.rb +6 -0
  49. data/app/models/cardboard/field.rb +67 -0
  50. data/app/models/cardboard/field/boolean.rb +29 -0
  51. data/app/models/cardboard/field/date.rb +24 -0
  52. data/app/models/cardboard/field/decimal.rb +25 -0
  53. data/app/models/cardboard/field/external_link.rb +4 -0
  54. data/app/models/cardboard/field/file.rb +19 -0
  55. data/app/models/cardboard/field/image.rb +33 -0
  56. data/app/models/cardboard/field/integer.rb +26 -0
  57. data/app/models/cardboard/field/resource_link.rb +4 -0
  58. data/app/models/cardboard/field/rich_text.rb +21 -0
  59. data/app/models/cardboard/field/string.rb +16 -0
  60. data/app/models/cardboard/field/text.rb +15 -0
  61. data/app/models/cardboard/page.rb +253 -0
  62. data/app/models/cardboard/page_part.rb +79 -0
  63. data/app/models/cardboard/setting.rb +46 -0
  64. data/app/views/cardboard/dashboard/index.html.slim +1 -0
  65. data/app/views/cardboard/fields/_base_input.html.slim +1 -0
  66. data/app/views/cardboard/fields/_boolean.html.slim +4 -0
  67. data/app/views/cardboard/fields/_date.html.slim +1 -0
  68. data/app/views/cardboard/fields/_external_link.html.slim +2 -0
  69. data/app/views/cardboard/fields/_file.html.slim +12 -0
  70. data/app/views/cardboard/fields/_image.html.slim +11 -0
  71. data/app/views/cardboard/fields/_resource_link.html.slim +2 -0
  72. data/app/views/cardboard/fields/_rich_text.html.slim +3 -0
  73. data/app/views/cardboard/fields/_string.html.slim +1 -0
  74. data/app/views/cardboard/my_account/edit.html.slim +29 -0
  75. data/app/views/cardboard/pages/_error.html.slim +7 -0
  76. data/app/views/cardboard/pages/_seo.html.slim +6 -0
  77. data/app/views/cardboard/pages/_sidebar.html.slim +17 -0
  78. data/app/views/cardboard/pages/_subpart_fields.html.slim +20 -0
  79. data/app/views/cardboard/pages/_url_field.html.slim +20 -0
  80. data/app/views/cardboard/pages/edit.html.slim +43 -0
  81. data/app/views/cardboard/pages/index.html.slim +2 -0
  82. data/app/views/cardboard/pages/show.html.slim +9 -0
  83. data/app/views/cardboard/resources/_advanced_search.html.slim +40 -0
  84. data/app/views/cardboard/resources/_search_button.html.slim +2 -0
  85. data/app/views/cardboard/resources/_search_helper.html.slim +17 -0
  86. data/app/views/cardboard/resources/_simple_search.html.slim +6 -0
  87. data/app/views/cardboard/rich_editor/_links_modal.html.slim +39 -0
  88. data/app/views/cardboard/settings/index.html.slim +8 -0
  89. data/app/views/cardboard/super_user/index.html.slim +10 -0
  90. data/app/views/layouts/cardboard/_flash_message.html.slim +6 -0
  91. data/app/views/layouts/cardboard/_head.html.slim +16 -0
  92. data/app/views/layouts/cardboard/_main_sidebar.html.slim +12 -0
  93. data/app/views/layouts/cardboard/_main_topbar.html.slim +32 -0
  94. data/app/views/layouts/cardboard/application.html.slim +28 -0
  95. data/cardboard.gemspec +57 -0
  96. data/config/initializers/dragonfly.rb +27 -0
  97. data/config/initializers/ranker_mapper_finder_bugfix.rb +43 -0
  98. data/config/initializers/simple_form.rb +142 -0
  99. data/config/initializers/simple_form_bootstrap.rb +45 -0
  100. data/config/locales/simple_form.en.yml +26 -0
  101. data/config/routes.rb +53 -0
  102. data/doc/apple-touch-icon.png +0 -0
  103. data/doc/classes/Cardboard.html +190 -0
  104. data/doc/classes/Cardboard/AdminController.html +134 -0
  105. data/doc/classes/Cardboard/AdminHelper.html +307 -0
  106. data/doc/classes/Cardboard/ApplicationController.html +76 -0
  107. data/doc/classes/Cardboard/ApplicationHelper.html +70 -0
  108. data/doc/classes/Cardboard/DashboardController.html +131 -0
  109. data/doc/classes/Cardboard/Field.html +283 -0
  110. data/doc/classes/Cardboard/Field/Boolean.html +218 -0
  111. data/doc/classes/Cardboard/Field/Date.html +218 -0
  112. data/doc/classes/Cardboard/Field/Decimal.html +218 -0
  113. data/doc/classes/Cardboard/Field/ExternalLink.html +76 -0
  114. data/doc/classes/Cardboard/Field/File.html +131 -0
  115. data/doc/classes/Cardboard/Field/Image.html +181 -0
  116. data/doc/classes/Cardboard/Field/Integer.html +218 -0
  117. data/doc/classes/Cardboard/Field/ResourceLink.html +76 -0
  118. data/doc/classes/Cardboard/Field/RichText.html +131 -0
  119. data/doc/classes/Cardboard/Field/String.html +131 -0
  120. data/doc/classes/Cardboard/Page.html +1184 -0
  121. data/doc/classes/Cardboard/PagePart.html +304 -0
  122. data/doc/classes/Cardboard/PagesController.html +186 -0
  123. data/doc/classes/Cardboard/PublicHelper.html +252 -0
  124. data/doc/classes/Cardboard/Setting.html +240 -0
  125. data/doc/classes/Cardboard/SettingsController.html +184 -0
  126. data/doc/classes/Cardboard/SuperUserController.html +130 -0
  127. data/doc/classes/Cardboard/UsersController.html +191 -0
  128. data/doc/classes/DatePickerInput.html +132 -0
  129. data/doc/classes/ImageInput.html +76 -0
  130. data/doc/classes/Object.html +211 -0
  131. data/doc/classes/PagesController.html +145 -0
  132. data/doc/classes/RichTextInput.html +132 -0
  133. data/doc/created.rid +31 -0
  134. data/doc/css/github.css +129 -0
  135. data/doc/css/main.css +333 -0
  136. data/doc/css/panel.css +384 -0
  137. data/doc/css/reset.css +48 -0
  138. data/doc/favicon.ico +0 -0
  139. data/doc/files/app/controllers/cardboard/admin_controller_rb.html +79 -0
  140. data/doc/files/app/controllers/cardboard/application_controller_rb.html +84 -0
  141. data/doc/files/app/controllers/cardboard/dashboard_controller_rb.html +84 -0
  142. data/doc/files/app/controllers/cardboard/pages_controller_rb.html +84 -0
  143. data/doc/files/app/controllers/cardboard/settings_controller_rb.html +84 -0
  144. data/doc/files/app/controllers/cardboard/super_user_controller_rb.html +84 -0
  145. data/doc/files/app/controllers/cardboard/users_controller_rb.html +84 -0
  146. data/doc/files/app/controllers/pages_controller_rb.html +79 -0
  147. data/doc/files/app/decorators/controllers/application_controller_decorator_rb.html +68 -0
  148. data/doc/files/app/decorators/lib/cardboard/user_class_decorator_rb.html +68 -0
  149. data/doc/files/app/helpers/cardboard/admin_helper_rb.html +84 -0
  150. data/doc/files/app/helpers/cardboard/application_helper_rb.html +84 -0
  151. data/doc/files/app/helpers/cardboard/public_helper_rb.html +84 -0
  152. data/doc/files/app/inputs/date_picker_input_rb.html +79 -0
  153. data/doc/files/app/inputs/image_input_rb.html +79 -0
  154. data/doc/files/app/inputs/rich_text_input_rb.html +79 -0
  155. data/doc/files/app/models/cardboard/field/boolean_rb.html +84 -0
  156. data/doc/files/app/models/cardboard/field/date_rb.html +84 -0
  157. data/doc/files/app/models/cardboard/field/decimal_rb.html +84 -0
  158. data/doc/files/app/models/cardboard/field/external_link_rb.html +84 -0
  159. data/doc/files/app/models/cardboard/field/file_rb.html +84 -0
  160. data/doc/files/app/models/cardboard/field/image_rb.html +84 -0
  161. data/doc/files/app/models/cardboard/field/integer_rb.html +84 -0
  162. data/doc/files/app/models/cardboard/field/resource_link_rb.html +84 -0
  163. data/doc/files/app/models/cardboard/field/rich_text_rb.html +84 -0
  164. data/doc/files/app/models/cardboard/field/string_rb.html +84 -0
  165. data/doc/files/app/models/cardboard/field_rb.html +84 -0
  166. data/doc/files/app/models/cardboard/page_part_rb.html +84 -0
  167. data/doc/files/app/models/cardboard/page_rb.html +84 -0
  168. data/doc/files/app/models/cardboard/setting_rb.html +84 -0
  169. data/doc/i/arrows.png +0 -0
  170. data/doc/i/results_bg.png +0 -0
  171. data/doc/i/tree_bg.png +0 -0
  172. data/doc/index.html +13 -0
  173. data/doc/js/highlight.pack.js +1 -0
  174. data/doc/js/jquery-1.3.2.min.js +19 -0
  175. data/doc/js/jquery-effect.js +593 -0
  176. data/doc/js/main.js +24 -0
  177. data/doc/js/navigation.js +142 -0
  178. data/doc/js/search_index.js +1 -0
  179. data/doc/js/searchdoc.js +449 -0
  180. data/doc/js/searcher.js +228 -0
  181. data/doc/panel/index.html +73 -0
  182. data/doc/panel/links.html +66 -0
  183. data/doc/panel/tree.js +1 -0
  184. data/lib/cardboard/application.rb +67 -0
  185. data/lib/cardboard/engine.rb +83 -0
  186. data/lib/cardboard/helpers/seed.rb +80 -0
  187. data/lib/cardboard/helpers/settings.rb +58 -0
  188. data/lib/cardboard/version.rb +3 -0
  189. data/lib/cardboard_cms.rb +34 -0
  190. data/lib/generators/cardboard/assets/assets_generator.rb +18 -0
  191. data/lib/generators/cardboard/install/install_generator.rb +96 -0
  192. data/lib/generators/cardboard/install/templates/cardboard.rb.erb +53 -0
  193. data/lib/generators/cardboard/install/templates/cardboard.yml +29 -0
  194. data/lib/generators/cardboard/install/templates/index.html.erb +0 -0
  195. data/lib/generators/cardboard/install/templates/migrations/1_create_cardboard_fields.rb +21 -0
  196. data/lib/generators/cardboard/install/templates/migrations/2_create_cardboard_page_parts.rb +17 -0
  197. data/lib/generators/cardboard/install/templates/migrations/3_create_cardboard_pages.rb +18 -0
  198. data/lib/generators/cardboard/install/templates/migrations/4_create_cardboard_settings.rb +14 -0
  199. data/lib/generators/cardboard/resource/resource_generator.rb +52 -0
  200. data/lib/generators/cardboard/resource/templates/admin_controller.rb +9 -0
  201. data/lib/generators/cardboard/resource/templates/slim/_fields.html.slim +5 -0
  202. data/lib/generators/cardboard/resource/templates/slim/edit.html.slim +4 -0
  203. data/lib/generators/cardboard/resource/templates/slim/index.html.slim +18 -0
  204. data/lib/generators/cardboard/resource/templates/slim/new.html.slim +4 -0
  205. data/lib/tasks/cardboard_tasks.rake +22 -0
  206. data/lib/templates/erb/scaffold/_form.html.erb +13 -0
  207. data/script/rails +8 -0
  208. data/test/dummy/README.rdoc +261 -0
  209. data/test/dummy/Rakefile +7 -0
  210. data/test/dummy/app/assets/images/defaults/CrashTest.jpg +0 -0
  211. data/test/dummy/app/assets/javascripts/admins.js +2 -0
  212. data/test/dummy/app/assets/javascripts/application.js +5 -0
  213. data/test/dummy/app/assets/javascripts/beans.js +2 -0
  214. data/test/dummy/app/assets/javascripts/cardboard.js +1 -0
  215. data/test/dummy/app/assets/javascripts/icescreams.js +2 -0
  216. data/test/dummy/app/assets/javascripts/main.js +2 -0
  217. data/test/dummy/app/assets/javascripts/news_posts.js +2 -0
  218. data/test/dummy/app/assets/javascripts/pianos.js +2 -0
  219. data/test/dummy/app/assets/stylesheets/admins.css.scss +3 -0
  220. data/test/dummy/app/assets/stylesheets/application.css.scss +9 -0
  221. data/test/dummy/app/assets/stylesheets/beans.css.scss +3 -0
  222. data/test/dummy/app/assets/stylesheets/cardboard.css.scss +5 -0
  223. data/test/dummy/app/assets/stylesheets/icescreams.css.scss +3 -0
  224. data/test/dummy/app/assets/stylesheets/main.css +4 -0
  225. data/test/dummy/app/assets/stylesheets/news_posts.css.scss +3 -0
  226. data/test/dummy/app/assets/stylesheets/pianos.css.scss +3 -0
  227. data/test/dummy/app/assets/stylesheets/scaffolds.css.scss +69 -0
  228. data/test/dummy/app/controllers/application_controller.rb +3 -0
  229. data/test/dummy/app/controllers/cardboard/pianos_controller.rb +6 -0
  230. data/test/dummy/app/controllers/pianos_controller.rb +83 -0
  231. data/test/dummy/app/helpers/application_helper.rb +9 -0
  232. data/test/dummy/app/helpers/cardboard/pianos_helper.rb +7 -0
  233. data/test/dummy/app/mailers/.gitkeep +0 -0
  234. data/test/dummy/app/models/.gitkeep +0 -0
  235. data/test/dummy/app/models/admin_user.rb +28 -0
  236. data/test/dummy/app/models/piano.rb +3 -0
  237. data/test/dummy/app/views/cardboard/pianos/_fields.html.slim +5 -0
  238. data/test/dummy/app/views/cardboard/pianos/edit.html.slim +6 -0
  239. data/test/dummy/app/views/cardboard/pianos/index.html.slim +18 -0
  240. data/test/dummy/app/views/cardboard/pianos/new.html.slim +6 -0
  241. data/test/dummy/app/views/cardboard/pianos/show.html.slim +11 -0
  242. data/test/dummy/app/views/layouts/application.html.slim +24 -0
  243. data/test/dummy/app/views/main/index.html.slim +1 -0
  244. data/test/dummy/app/views/pages/about-us.html.slim +1 -0
  245. data/test/dummy/app/views/pages/home.html.slim +3 -0
  246. data/test/dummy/app/views/pianos/_form.html.erb +25 -0
  247. data/test/dummy/app/views/pianos/edit.html.erb +6 -0
  248. data/test/dummy/app/views/pianos/index.html.erb +25 -0
  249. data/test/dummy/app/views/pianos/new.html.erb +5 -0
  250. data/test/dummy/app/views/pianos/show.html.erb +15 -0
  251. data/test/dummy/config.ru +4 -0
  252. data/test/dummy/config/application.rb +50 -0
  253. data/test/dummy/config/boot.rb +10 -0
  254. data/test/dummy/config/cardboard.yml +126 -0
  255. data/test/dummy/config/database.yml +17 -0
  256. data/test/dummy/config/environment.rb +5 -0
  257. data/test/dummy/config/environments/development.rb +24 -0
  258. data/test/dummy/config/environments/production.rb +70 -0
  259. data/test/dummy/config/environments/test.rb +33 -0
  260. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  261. data/test/dummy/config/initializers/cardboard.rb +53 -0
  262. data/test/dummy/config/initializers/devise.rb +240 -0
  263. data/test/dummy/config/initializers/inflections.rb +15 -0
  264. data/test/dummy/config/initializers/mime_types.rb +5 -0
  265. data/test/dummy/config/initializers/secret_token.rb +8 -0
  266. data/test/dummy/config/initializers/session_store.rb +8 -0
  267. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  268. data/test/dummy/config/locales/devise.en.yml +59 -0
  269. data/test/dummy/config/locales/en.yml +5 -0
  270. data/test/dummy/config/routes.rb +16 -0
  271. data/test/dummy/db/migrate/20130403142235_create_pianos.rb +10 -0
  272. data/test/dummy/db/migrate/20130417134832_add_devise_to_admin_users.rb +53 -0
  273. data/test/dummy/db/migrate/20130426021522_create_news_posts.rb +10 -0
  274. data/test/dummy/db/migrate/20130501195423_create_icescreams.rb +10 -0
  275. data/test/dummy/db/migrate/20130502165540_create_beans.rb +12 -0
  276. data/test/dummy/db/migrate/20130522151358_create_cardboard_fields.rb +21 -0
  277. data/test/dummy/db/migrate/20130522151359_create_cardboard_page_parts.rb +17 -0
  278. data/test/dummy/db/migrate/20130522151400_create_cardboard_pages.rb +18 -0
  279. data/test/dummy/db/migrate/20130522151401_create_cardboard_settings.rb +14 -0
  280. data/test/dummy/db/migrate/20130607132558_create_admins.rb +9 -0
  281. data/test/dummy/db/schema.rb +129 -0
  282. data/test/dummy/db/seeds.rb +2 -0
  283. data/test/dummy/lib/assets/.gitkeep +0 -0
  284. data/test/dummy/log/.gitkeep +0 -0
  285. data/test/dummy/public/404.html +26 -0
  286. data/test/dummy/public/422.html +26 -0
  287. data/test/dummy/public/500.html +25 -0
  288. data/test/dummy/public/favicon.ico +0 -0
  289. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_39_10_816_404_no_file.png +0 -0
  290. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_39_10_816_404_no_file.png.meta +2 -0
  291. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_39_17_87_404_no_file.png +0 -0
  292. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_39_17_87_404_no_file.png.meta +2 -0
  293. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_39_34_680_404_no_file.png +0 -0
  294. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_39_34_680_404_no_file.png.meta +2 -0
  295. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_44_00_698_404_no_file.png +0 -0
  296. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_44_00_698_404_no_file.png.meta +2 -0
  297. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_46_49_55_6152message_in_a_bottle.jpeg +0 -0
  298. data/test/dummy/public/system/dragonfly/development/2013/04/16/10_46_49_55_6152message_in_a_bottle.jpeg.meta +2 -0
  299. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_10_30_773_404_no_file.png +0 -0
  300. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_10_30_773_404_no_file.png.meta +2 -0
  301. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_10_38_856_airport_shuttles_20130207_1647.csv +8 -0
  302. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_10_38_856_airport_shuttles_20130207_1647.csv.meta +2 -0
  303. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_12_12_144_1361696555_GMail_Android_R.png +0 -0
  304. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_12_12_144_1361696555_GMail_Android_R.png.meta +2 -0
  305. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_16_40_989_404_no_file.png +0 -0
  306. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_16_40_989_404_no_file.png.meta +2 -0
  307. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_19_19_40_6152message_in_a_bottle.jpeg +0 -0
  308. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_19_19_40_6152message_in_a_bottle.jpeg.meta +2 -0
  309. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_21_21_825_6152message_in_a_bottle.jpeg +0 -0
  310. data/test/dummy/public/system/dragonfly/development/2013/04/16/14_21_21_825_6152message_in_a_bottle.jpeg.meta +2 -0
  311. data/test/dummy/public/system/dragonfly/development/2013/04/16/15_46_33_341_bio.jpg +0 -0
  312. data/test/dummy/public/system/dragonfly/development/2013/04/16/15_46_33_341_bio.jpg.meta +2 -0
  313. data/test/dummy/public/system/dragonfly/development/2013/04/16/15_52_55_892_404_no_file.png +0 -0
  314. data/test/dummy/public/system/dragonfly/development/2013/04/16/15_52_55_892_404_no_file.png.meta +2 -0
  315. data/test/dummy/public/system/dragonfly/development/2013/04/16/15_52_56_30_404_no_file.png +0 -0
  316. data/test/dummy/public/system/dragonfly/development/2013/04/16/15_52_56_30_404_no_file.png.meta +2 -0
  317. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_24_04_585_Sky_3920445.jpg +0 -0
  318. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_24_04_585_Sky_3920445.jpg.meta +2 -0
  319. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_25_41_111_Sky_3920445.jpg +0 -0
  320. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_25_41_111_Sky_3920445.jpg.meta +2 -0
  321. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_27_16_937_Sky_3920445.jpg +0 -0
  322. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_27_16_937_Sky_3920445.jpg.meta +2 -0
  323. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_27_57_585_Sky_3920445.jpg +0 -0
  324. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_27_57_585_Sky_3920445.jpg.meta +2 -0
  325. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_28_24_991_Sky_3920445.jpg +0 -0
  326. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_28_24_991_Sky_3920445.jpg.meta +2 -0
  327. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_33_30_610_Sky_3920445.jpg +0 -0
  328. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_33_30_610_Sky_3920445.jpg.meta +2 -0
  329. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_35_18_437_Sky_3920445.jpg +0 -0
  330. data/test/dummy/public/system/dragonfly/development/2013/04/17/15_35_18_437_Sky_3920445.jpg.meta +2 -0
  331. data/test/dummy/public/system/dragonfly/development/2013/04/17/16_45_07_162_Vehicle_Types.jpg +0 -0
  332. data/test/dummy/public/system/dragonfly/development/2013/04/17/16_45_07_162_Vehicle_Types.jpg.meta +2 -0
  333. data/test/dummy/public/system/dragonfly/development/2013/04/18/22_27_35_733_hall.jpg +0 -0
  334. data/test/dummy/public/system/dragonfly/development/2013/04/18/22_27_35_733_hall.jpg.meta +2 -0
  335. data/test/dummy/public/system/dragonfly/development/2013/04/18/22_29_15_808_fluidicon.png +0 -0
  336. data/test/dummy/public/system/dragonfly/development/2013/04/18/22_29_15_808_fluidicon.png.meta +2 -0
  337. data/test/dummy/public/system/dragonfly/development/2013/04/18/22_29_15_989_fluidicon.png +0 -0
  338. data/test/dummy/public/system/dragonfly/development/2013/04/18/22_29_15_989_fluidicon.png.meta +2 -0
  339. data/test/dummy/public/system/dragonfly/development/2013/04/19/09_54_44_881_hall3.jpg +0 -0
  340. data/test/dummy/public/system/dragonfly/development/2013/04/19/09_54_44_881_hall3.jpg.meta +2 -0
  341. data/test/dummy/public/system/dragonfly/development/2013/04/19/09_54_45_450_hall3.jpg +0 -0
  342. data/test/dummy/public/system/dragonfly/development/2013/04/19/09_54_45_450_hall3.jpg.meta +2 -0
  343. data/test/dummy/script/rails +6 -0
  344. data/test/dummy/test/fixtures/admins.yml +7 -0
  345. data/test/dummy/test/functional/admins_controller_test.rb +49 -0
  346. data/test/dummy/test/unit/admin_test.rb +7 -0
  347. data/test/dummy/test/unit/helpers/admins_helper_test.rb +4 -0
  348. data/test/factories.rb +47 -0
  349. data/test/integration/page_editing_test.rb +77 -0
  350. data/test/integration/seeding_test.rb +96 -0
  351. data/test/models/field_test.rb +102 -0
  352. data/test/models/page_test.rb +105 -0
  353. data/test/test_helper.rb +40 -0
  354. data/vendor/assets/javascripts/cardboard/bootstrap-select.js +590 -0
  355. data/vendor/assets/javascripts/cardboard/jquery.livesearch.js +48 -0
  356. data/vendor/assets/javascripts/cardboard/jquery.pjax.js +822 -0
  357. data/vendor/assets/javascripts/cardboard/jquery.wysihtml5_size_matters.js.coffee +44 -0
  358. data/vendor/assets/javascripts/cardboard/jquery.wysihtml5imgresizer.js +320 -0
  359. data/vendor/assets/javascripts/cardboard/wysihtml5-0.4.0pre.js +9579 -0
  360. metadata +1011 -0
@@ -0,0 +1,96 @@
1
+ require "test_helper"
2
+
3
+ describe "Seeding" do
4
+ before do
5
+ DatabaseCleaner.clean
6
+ @file_hash = {
7
+ pages: {
8
+ home:{
9
+ title: "Welcome",
10
+ position: 0,
11
+ parts:{
12
+ intro:{
13
+ position: 1,
14
+ fields:{
15
+ text:{
16
+ type: "string",
17
+ default: "default text",
18
+ label: "ok",
19
+ required: "true",
20
+ hint: "this is a hint",
21
+ placeholder: "Text"
22
+ }
23
+ }
24
+ },
25
+ slideshow:{
26
+ repeatable: true,
27
+ position: 0,
28
+ fields:{
29
+ image:{
30
+ type: "image",
31
+ default: "CrashTest.jpg"
32
+ },
33
+ desc:{
34
+ type: "string"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ },
40
+ about_us:{
41
+ parts:{
42
+ about:{
43
+ fields:{
44
+ description:{
45
+ type: "rich_text"
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }.with_indifferent_access
53
+ end
54
+ describe 'Pages' do
55
+ before do
56
+ Cardboard::Seed.populate_pages(@file_hash)
57
+ @page = Cardboard::Page.root
58
+ @part = @page.parts.first
59
+ @last_part = @page.parts.last
60
+ end
61
+ it 'Should add pages' do
62
+ assert_equal "home", @page.identifier
63
+ assert_equal 2, Cardboard::Page.count
64
+ end
65
+ it 'Should add parts' do
66
+ assert_equal "slideshow", @part.identifier
67
+ assert_equal "intro", @last_part.identifier
68
+ end
69
+ it 'Should add fields' do
70
+ refute_nil @page.get("intro").fields.where(identifier: "text")
71
+ end
72
+ describe 'Modified yml file' do
73
+ before do
74
+ @file_hash[:pages].delete(:about_us)
75
+ @file_hash[:pages][:home][:parts].delete(:slideshow)
76
+ @file_hash[:pages][:home][:parts][:intro][:fields].delete(:text)
77
+ Cardboard::Seed.populate_pages(@file_hash)
78
+ @page = Cardboard::Page.root
79
+ @part = @page.parts.first
80
+ end
81
+ it 'Should remove old pages' do
82
+ assert_nil Cardboard::Page.where(:identifier => "about_us").first
83
+ assert_equal 1, Cardboard::Page.count
84
+ end
85
+ it 'Should remove old parts' do
86
+ assert_nil @page.get("slideshow")
87
+ refute_nil @page.get("intro")
88
+ end
89
+ it 'Should remove old fields' do
90
+ assert_nil @page.get("intro").attr("text")
91
+ end
92
+ end
93
+ end
94
+ describe 'Settings' do
95
+ end
96
+ end
@@ -0,0 +1,102 @@
1
+ require 'test_helper'
2
+
3
+ #TODO: get, seo, parent_url_options
4
+
5
+ describe Cardboard::Field do
6
+ before do
7
+ @part = build :page_part
8
+ end
9
+
10
+ it "should accept valid boolean values" do
11
+ @field = build :boolean_field
12
+ assert_equal true, @field.save
13
+ assert_equal true, @field.update_attributes(:value => "")
14
+ ["t", "1", "true", true].each do |val|
15
+ assert_equal true, @field.update_attributes(:value => val)
16
+ assert_equal true, @field.value
17
+ end
18
+ [nil,"f", "0", "false", false].each do |val|
19
+ assert_equal true, @field.update_attributes(:value => val)
20
+ assert_equal false, @field.value
21
+ end
22
+ assert_equal false, @field.update_attributes(:value => "somehting_bad")
23
+ end
24
+
25
+ it "should accept valid date values" do
26
+ @field = build :date_field
27
+ assert_equal true, @field.save
28
+ assert_equal true, @field.update_attributes(value: "1900-01-01")
29
+ assert_equal Time.new('1900', '01', '01', '12', '00'), @field.value #chronic dates are at noon by default
30
+ end
31
+ it "should not accept invalid date values" do
32
+ @field = build :date_field
33
+ @field.required = true
34
+ assert_equal true, @field.save
35
+ assert_equal false, @field.update_attributes(:value => "")
36
+ assert_equal false, @field.update_attributes(:value => "something")
37
+ end
38
+
39
+ it "should accept valid decimal numbers" do
40
+ @field = build :decimal_field
41
+ assert_equal true, @field.save
42
+ assert_equal true, @field.update_attributes(:value => 1.23)
43
+ assert_equal 1.23, @field.value
44
+ assert_equal true, @field.update_attributes(:value => "1.23")
45
+ assert_equal 1.23, @field.value
46
+ end
47
+ it "should not accept invalid decimal numbers" do
48
+ @field = build :decimal_field
49
+ @field.required = true
50
+ assert_equal true, @field.save
51
+ assert_equal false, @field.update_attributes(:value => "")
52
+ assert_equal false, @field.update_attributes(:value => "something")
53
+ end
54
+
55
+ it "should not accept invalid files" do
56
+ @field = build :file_field
57
+ @field.required = true
58
+ assert_equal true, @field.save
59
+
60
+ assert_equal false, @field.update_attributes(:value => "")
61
+ assert_equal nil, @field.value_uid
62
+ #TODO: test file validations
63
+ end
64
+
65
+ it "should not accept invalid images" do
66
+ @field = build :image_field
67
+ @field.required = true
68
+ assert_equal true, @field.save
69
+
70
+ assert_equal false, @field.update_attributes(:value => "")
71
+ assert_equal nil, @field.value_uid
72
+ #TODO: test image validations
73
+ end
74
+
75
+ it "should accept valid integer numbers" do
76
+ @field = build :integer_field
77
+ assert_equal true, @field.save
78
+ @field.required = true
79
+ assert_equal false, @field.update_attributes(:value => "")
80
+ assert_equal false, @field.update_attributes(:value => 1.23)
81
+ assert_equal true, @field.update_attributes(:value => "123")
82
+ assert_equal 123, @field.value
83
+ end
84
+
85
+ it "should accept valid rich text" do
86
+ @field = build :rich_text_field
87
+ assert_equal true, @field.save
88
+ @field.required = true
89
+ assert_equal true, @field.update_attributes(:value => "something<script>alert('bad')</script>")
90
+ assert_equal "something", @field.value
91
+ end
92
+
93
+ it "should accept valid string" do
94
+ @field = build :string_field
95
+ assert_equal true, @field.save
96
+ @field.required = true
97
+ assert_equal true, @field.update_attributes(:value => "something")
98
+ assert_equal "something", @field.value
99
+ assert_equal false, @field.update_attributes(:value => "")
100
+ end
101
+
102
+ end
@@ -0,0 +1,105 @@
1
+ require 'test_helper'
2
+
3
+ #TODO: get, parent_url_options
4
+
5
+ describe Cardboard::Page do
6
+ before do
7
+ @page = build(:page)
8
+ end
9
+
10
+ it 'Must be valid' do
11
+ @page.valid?.must_equal true
12
+ end
13
+
14
+ describe 'Persisted record' do
15
+ before do
16
+ @page.save
17
+ end
18
+
19
+ it 'Must find Page with url' do
20
+ Cardboard::Page.find_by_url(@page.url).must_equal @page
21
+ end
22
+
23
+ it 'Must be found with old url after changing slug' do
24
+ old_url = @page.url
25
+ @page.update_attribute :slug, 'test'
26
+ Cardboard::Page.find_by_url(old_url).must_equal @page
27
+ Cardboard::Page.find_by_url(old_url).using_slug_backup?.must_equal true
28
+ Cardboard::Page.find_by_url(@page.url).must_equal @page
29
+ Cardboard::Page.find_by_url(@page.url).using_slug_backup?.must_equal false
30
+ end
31
+
32
+ describe 'SEO' do
33
+ before do
34
+ @page.update_attribute :position_position, 1
35
+ @page.update_attribute :meta_seo, {'title' => 'Test Title'}
36
+ @subpages = create_list :page, 2, path: @page.url
37
+ @root_sibling = create :page, position_position: 2
38
+ end
39
+
40
+ it 'inherits SEO information from parent' do
41
+ @subpages.first.seo['title'].must_equal @page.seo['title']
42
+ end
43
+
44
+ it 'inherits SEO information from root' do
45
+ @root_sibling.seo['title'].must_equal Cardboard::Page.root.seo['title']
46
+ end
47
+
48
+ it 'allows to override inherited properties' do
49
+ @subpages.first.update_attribute :meta_seo, {'title' => 'Non root title'}
50
+ @subpages.first.seo['title'].wont_equal @page.seo['title']
51
+ @subpages.first.seo['title'].must_equal 'Non root title'
52
+ end
53
+ end
54
+
55
+ describe 'Children' do
56
+ before do
57
+ @subpages = create_list(:page, 2, path: @page.url)
58
+ end
59
+
60
+ it 'Must included newly created child' do
61
+ @subpage = create :page, parent: @page
62
+ @page.children.must_include @subpage
63
+ end
64
+
65
+ it 'Get the parent of a page' do
66
+ @subpages.first.parent.must_equal @page
67
+ end
68
+
69
+ it 'Get the children of a page' do
70
+ @page.children.must_include @subpages.first
71
+ @page.children.must_include @subpages.second
72
+ end
73
+
74
+ it 'Get the siblings of a page' do
75
+ @subpages.first.siblings.must_include @subpages.second
76
+ @subpages.second.siblings.must_include @subpages.first
77
+ end
78
+
79
+ it 'Preorder of results' do
80
+ DatabaseCleaner.clean
81
+
82
+ page1 = create :page, position_position: 1
83
+ page2 = create :page, position_position: 2
84
+ subpage1 = create :page, parent: page1, position_position: 1
85
+ subpage2 = create :page, parent_id: page1.identifier, position_position: 2
86
+ subpage3 = create :page, parent_url: subpage2.parent_url, position_position: 3
87
+ subpage4 = create :page, parent_url: page2.url
88
+
89
+ Cardboard::Page.arrange.must_equal({
90
+ page1 => {
91
+ subpage1 => {},
92
+ subpage2 => {},
93
+ subpage3 => {}
94
+ },
95
+ page2 => {subpage4 => {}}
96
+ })
97
+
98
+ Cardboard::Page.root.must_equal page1
99
+ Cardboard::Page.root.depth.must_equal 0
100
+ subpage1.depth.must_equal 1
101
+ end
102
+ end
103
+ end
104
+ end
105
+
@@ -0,0 +1,40 @@
1
+ require 'simplecov'
2
+ SimpleCov.start 'rails'
3
+
4
+ ENV["RAILS_ENV"] = "test"
5
+ require File.expand_path('../dummy/config/environment', __FILE__)
6
+ require "rails/test_help"
7
+
8
+ require 'faker'
9
+ require 'database_cleaner'
10
+ require "minitest/autorun"
11
+ require "minitest/rails"
12
+ require "minitest/rails/capybara"
13
+ require 'minitest/unit'
14
+ require 'minitest/mock'
15
+ require Cardboard::Engine.root.join('lib/cardboard/helpers/seed.rb')
16
+
17
+ require File.expand_path('../factories.rb', __FILE__)
18
+
19
+ begin; require 'turn/autorun'; rescue LoadError; end
20
+
21
+ DatabaseCleaner.strategy = :truncation
22
+
23
+ # Uncomment if you want awesome colorful output
24
+ # require "minitest/pride"
25
+
26
+ class ActiveSupport::TestCase
27
+ include FactoryGirl::Syntax::Methods
28
+ end
29
+
30
+ class ActionDispatch::IntegrationTest
31
+ include Rails.application.routes.url_helpers
32
+ include Capybara::DSL
33
+
34
+ include Warden::Test::Helpers
35
+ Warden.test_mode!
36
+
37
+ def cardboard
38
+ Cardboard::Engine.routes.url_helpers
39
+ end
40
+ end
@@ -0,0 +1,590 @@
1
+ !function($) {
2
+
3
+ "use strict";
4
+
5
+ var Selectpicker = function(element, options, e) {
6
+ if (e) {
7
+ e.stopPropagation();
8
+ e.preventDefault();
9
+ }
10
+ this.$element = $(element);
11
+ this.$newElement = null;
12
+ this.button = null;
13
+
14
+ //Merge defaults, options and data-attributes to make our options
15
+ this.options = $.extend({}, $.fn.selectpicker.defaults, this.$element.data(), typeof options == 'object' && options);
16
+
17
+ //If we have no title yet, check the attribute 'title' (this is missed by jq as its not a data-attribute
18
+ if(this.options.title==null)
19
+ this.options.title = this.$element.attr('title');
20
+
21
+ //Expose public methods
22
+ this.val = Selectpicker.prototype.val;
23
+ this.render = Selectpicker.prototype.render;
24
+ this.refresh = Selectpicker.prototype.refresh;
25
+ this.selectAll = Selectpicker.prototype.selectAll;
26
+ this.deselectAll = Selectpicker.prototype.deselectAll;
27
+ this.init();
28
+ };
29
+
30
+ Selectpicker.prototype = {
31
+
32
+ constructor: Selectpicker,
33
+
34
+ init: function (e) {
35
+ if (!this.options.container) {
36
+ this.$element.hide();
37
+ } else {
38
+ this.$element.css('visibility','hidden');
39
+ };
40
+ this.multiple = this.$element.prop('multiple');
41
+ var id = this.$element.attr('id');
42
+ this.$newElement = this.createView()
43
+ this.$element.after(this.$newElement);
44
+
45
+ if (this.options.container) {
46
+ this.selectPosition();
47
+ }
48
+ this.button = this.$newElement.find('> button');
49
+ if (id !== undefined) {
50
+ var _this = this;
51
+ this.button.attr('data-id', id);
52
+ $('label[for="' + id + '"]').click(function(){
53
+ _this.button.focus();
54
+ })
55
+ }
56
+ if (this.$element.attr('class')) {
57
+ this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker/gi, ''));
58
+ }
59
+
60
+ //If we are multiple, then add the show-tick class by default
61
+ if(this.multiple) {
62
+ this.$newElement.addClass('show-tick');
63
+ }
64
+ this.button.addClass(this.options.style);
65
+ this.checkDisabled();
66
+ this.checkTabIndex();
67
+ this.clickListener();
68
+
69
+ this.render();
70
+ this.setSize();
71
+ },
72
+
73
+ createDropdown: function() {
74
+ var drop =
75
+ "<div class='btn-group bootstrap-select'>" +
76
+ "<button type='button' class='btn dropdown-toggle' data-toggle='dropdown'>" +
77
+ "<div class='filter-option pull-left'></div>&nbsp;" +
78
+ "<div class='caret'></div>" +
79
+ "</button>" +
80
+ "<ul class='dropdown-menu' role='menu'>" +
81
+ "</ul>" +
82
+ "</div>";
83
+
84
+ return $(drop);
85
+ },
86
+
87
+
88
+ createView: function() {
89
+ var $drop = this.createDropdown();
90
+ var $li = this.createLi();
91
+ $drop.find('ul').append($li);
92
+ return $drop;
93
+ },
94
+
95
+ reloadLi: function() {
96
+ //Remove all children.
97
+ this.destroyLi();
98
+ //Re build
99
+ var $li = this.createLi();
100
+ this.$newElement.find('ul').append( $li );
101
+ },
102
+
103
+ destroyLi:function() {
104
+ this.$newElement.find('li').remove();
105
+ },
106
+
107
+ createLi: function() {
108
+
109
+ var _this = this;
110
+ var _liA = [];
111
+ var _liHtml = '';
112
+
113
+
114
+ this.$element.find('option').each(function(index) {
115
+ var $this = $(this);
116
+
117
+ //Get the class and text for the option
118
+ var optionClass = $this.attr("class") || '';
119
+ var text = $this.text();
120
+ var subtext = $this.data('subtext') !== undefined ? '<small class="muted">' + $this.data('subtext') + '</small>' : '';
121
+ var icon = $this.data('icon') !== undefined ? '<i class="'+$this.data('icon')+'"></i> ' : '';
122
+ if (icon !== '' && ($this.is(':disabled') || $this.parent().is(':disabled'))) {
123
+ icon = '<span>'+icon+'</span>';
124
+ }
125
+
126
+ //Prepend any icon and append any subtext to the main text.
127
+ text = icon + '<span class="text">' + text + subtext + '</span>';
128
+
129
+ if (_this.options.hideDisabled && ($this.is(':disabled') || $this.parent().is(':disabled'))) {
130
+ _liA.push('<a style="min-height: 0; padding: 0"></a>');
131
+ } else if ($this.parent().is('optgroup') && $this.data('divider') != true) {
132
+ if ($this.index() == 0) {
133
+ //Get the opt group label
134
+ var label = $this.parent().attr('label');
135
+ var labelSubtext = $this.parent().data('subtext') !== undefined ? '<small class="muted">'+$this.parent().data('subtext')+'</small>' : '';
136
+ var labelIcon = $this.parent().data('icon') ? '<i class="'+$this.parent().data('icon')+'"></i> ' : '';
137
+ label = labelIcon + '<span class="text">' + label + labelSubtext + '</span>';
138
+
139
+ if ($this[0].index != 0) {
140
+ _liA.push(
141
+ '<div class="div-contain"><div class="divider"></div></div>'+
142
+ '<dt>'+label+'</dt>'+
143
+ _this.createA(text, "opt " + optionClass )
144
+ );
145
+ } else {
146
+ _liA.push(
147
+ '<dt>'+label+'</dt>'+
148
+ _this.createA(text, "opt " + optionClass ));
149
+ }
150
+ } else {
151
+ _liA.push( _this.createA(text, "opt " + optionClass ) );
152
+ }
153
+ } else if ($this.data('divider') == true) {
154
+ _liA.push('<div class="div-contain"><div class="divider"></div></div>');
155
+ } else if ($(this).data('hidden') == true) {
156
+ _liA.push('');
157
+ } else {
158
+ _liA.push( _this.createA(text, optionClass ) );
159
+ }
160
+ });
161
+
162
+ $.each(_liA, function(i, item){
163
+ _liHtml += "<li rel=" + i + ">" + item + "</li>";
164
+ });
165
+
166
+ //If we are not multiple, and we dont have a selected item, and we dont have a title, select the first element so something is set in the button
167
+ if(!this.multiple && this.$element.find('option:selected').length==0 && !_this.options.title) {
168
+ this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
169
+ }
170
+
171
+ return $(_liHtml);
172
+ },
173
+
174
+ createA:function(text, classes) {
175
+ return '<a tabindex="0" class="'+classes+'">' +
176
+ text +
177
+ '<i class="icon-ok check-mark"></i>' +
178
+ '</a>';
179
+ },
180
+
181
+ render:function() {
182
+ var _this = this;
183
+
184
+ //Update the LI to match the SELECT
185
+ this.$element.find('option').each(function(index) {
186
+ _this.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled') );
187
+ _this.setSelected(index, $(this).is(':selected') );
188
+ });
189
+
190
+ var selectedItems = this.$element.find('option:selected').map(function(index,value) {
191
+ var subtext;
192
+ if (_this.options.showSubtext && $(this).attr('data-subtext') && !_this.multiple) {
193
+ subtext = ' <small class="muted">'+$(this).data('subtext') +'</small>';
194
+ } else {
195
+ subtext = '';
196
+ }
197
+ if($(this).attr('title')!=undefined) {
198
+ return $(this).attr('title');
199
+ } else {
200
+ return $(this).text() + subtext;
201
+ }
202
+ }).toArray();
203
+
204
+ //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
205
+ //Convert all the values into a comma delimited string
206
+ var title = !this.multiple ? selectedItems[0] : selectedItems.join(", "),
207
+ separator = _this.options.separatorText || _this.options.defaultSeparatorText,
208
+ selected = _this.options.selectedText || _this.options.defaultSelectedText;
209
+
210
+ //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
211
+ if(_this.multiple && _this.options.selectedTextFormat.indexOf('count') > -1) {
212
+ var max = _this.options.selectedTextFormat.split(">");
213
+ var notDisabled = this.options.hideDisabled ? ':not([disabled])' : '';
214
+ if( (max.length>1 && selectedItems.length > max[1]) || (max.length==1 && selectedItems.length>=2)) {
215
+ title = _this.options.countSelectedText.replace('{0}', selectedItems.length).replace('{1}', this.$element.find('option:not([data-divider="true"]):not([data-hidden="true"])'+notDisabled).length);
216
+ }
217
+ }
218
+
219
+ //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
220
+ if(!title) {
221
+ title = _this.options.title != undefined ? _this.options.title : _this.options.noneSelectedText;
222
+ }
223
+
224
+ var subtext;
225
+ if (this.options.showSubtext && this.$element.find('option:selected').attr('data-subtext')) {
226
+ subtext = ' <small class="muted">'+this.$element.find('option:selected').data('subtext') +'</small>';
227
+ } else {
228
+ subtext = '';
229
+ }
230
+
231
+ var icon = this.$element.find('option:selected').data('icon') || '';
232
+ if(icon.length) {
233
+ icon = '<i class="' + icon + '"></i> ';
234
+ }
235
+
236
+ _this.$newElement.find('.filter-option').html(icon + title + subtext);
237
+ },
238
+
239
+ setSize:function() {
240
+ if(this.options.container) {
241
+ // Show $newElement before perfoming size calculations
242
+ this.$newElement.toggle(this.$element.parent().is(':visible'));
243
+ }
244
+ var _this = this;
245
+ var menu = this.$newElement.find('.dropdown-menu');
246
+ var menuA = menu.find('li > a');
247
+ var liHeight = this.$newElement.addClass('open').find('.dropdown-menu li > a').outerHeight();
248
+ this.$newElement.removeClass('open');
249
+ var divHeight = menu.find('li .divider').outerHeight(true);
250
+ var selectOffset_top = this.$newElement.offset().top;
251
+ var selectHeight = this.$newElement.outerHeight();
252
+ var menuPadding = parseInt(menu.css('padding-top')) + parseInt(menu.css('padding-bottom')) + parseInt(menu.css('border-top-width')) + parseInt(menu.css('border-bottom-width'));
253
+ var notDisabled = this.options.hideDisabled ? ':not(.disabled)' : '';
254
+ var menuHeight;
255
+ if (this.options.size == 'auto') {
256
+ var getSize = function() {
257
+ var selectOffset_top_scroll = selectOffset_top - $(window).scrollTop();
258
+ var windowHeight = window.innerHeight;
259
+ var menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2;
260
+ var selectOffset_bot = windowHeight - selectOffset_top_scroll - selectHeight - menuExtras;
261
+ var minHeight;
262
+ menuHeight = selectOffset_bot;
263
+ if (_this.$newElement.hasClass('dropup')) {
264
+ menuHeight = selectOffset_top_scroll - menuExtras;
265
+ }
266
+ if ((menu.find('li').length + menu.find('dt').length) > 3) {
267
+ minHeight = liHeight*3 + menuExtras - 2;
268
+ } else {
269
+ minHeight = 0;
270
+ }
271
+ menu.css({'max-height' : menuHeight + 'px', 'overflow-y' : 'auto', 'min-height' : minHeight + 'px'});
272
+ }
273
+ getSize();
274
+ $(window).resize(getSize);
275
+ $(window).scroll(getSize);
276
+ } else if (this.options.size && this.options.size != 'auto' && menu.find('li'+notDisabled).length > this.options.size) {
277
+ var optIndex = menu.find("li"+notDisabled+" > *").filter(':not(.div-contain)').slice(0,this.options.size).last().parent().index();
278
+ var divLength = menu.find("li").slice(0,optIndex + 1).find('.div-contain').length;
279
+ menuHeight = liHeight*this.options.size + divLength*divHeight + menuPadding;
280
+ menu.css({'max-height' : menuHeight + 'px', 'overflow-y' : 'auto'});
281
+ }
282
+
283
+ //Set width of select
284
+ if (this.options.width == 'auto') {
285
+ this.$newElement.find('.dropdown-menu').css('min-width','0');
286
+ var ulWidth = this.$newElement.find('.dropdown-menu').css('width');
287
+ this.$newElement.css('width',ulWidth);
288
+ if (this.options.container) {
289
+ this.$element.css('width',ulWidth);
290
+ }
291
+ } else if (this.options.width) {
292
+ if (this.options.container) {
293
+ // Note: options.width can be %
294
+ this.$element.css('width', this.options.width);
295
+ // Set pixel width of $newElement based on $element's pixel width
296
+ this.$newElement.width(this.$element.outerWidth());
297
+ } else {
298
+ this.$newElement.css('width',this.options.width);
299
+ }
300
+ } else if(this.options.container) {
301
+ // Set width of $newElement based on $element
302
+ this.$newElement.width(this.$element.outerWidth());
303
+ }
304
+ },
305
+
306
+ selectPosition:function() {
307
+ var containerOffset = $(this.options.container).offset();
308
+ var eltOffset = this.$element.offset();
309
+ if(containerOffset && eltOffset) {
310
+ var selectElementTop = eltOffset.top - containerOffset.top;
311
+ var selectElementLeft = eltOffset.left - containerOffset.left;
312
+ this.$newElement.appendTo(this.options.container);
313
+ this.$newElement.css({'position':'absolute', 'top':selectElementTop+'px', 'left':selectElementLeft+'px'});
314
+ }
315
+ },
316
+
317
+ refresh:function() {
318
+ this.reloadLi();
319
+ this.render();
320
+ this.setSize();
321
+ this.checkDisabled();
322
+ if (this.options.container) {
323
+ this.selectPosition();
324
+ }
325
+ },
326
+
327
+ setSelected:function(index, selected) {
328
+ if(selected) {
329
+ this.$newElement.find('li').eq(index).addClass('selected');
330
+ } else {
331
+ this.$newElement.find('li').eq(index).removeClass('selected');
332
+ }
333
+ },
334
+
335
+ setDisabled:function(index, disabled) {
336
+ if(disabled) {
337
+ this.$newElement.find('li').eq(index).addClass('disabled').find('a').attr('href','#').attr('tabindex',-1);
338
+ } else {
339
+ this.$newElement.find('li').eq(index).removeClass('disabled').find('a').removeAttr('href').attr('tabindex',0);
340
+ }
341
+ },
342
+
343
+ isDisabled: function() {
344
+ return this.$element.is(':disabled') || this.$element.attr('readonly');
345
+ },
346
+
347
+ checkDisabled: function() {
348
+ if (this.isDisabled()) {
349
+ this.button.addClass('disabled');
350
+ this.button.click(function(e) {
351
+ e.preventDefault();
352
+ });
353
+ this.button.attr('tabindex','-1');
354
+ } else if (!this.isDisabled() && this.button.hasClass('disabled')) {
355
+ this.button.removeClass('disabled');
356
+ this.button.click(function() {
357
+ return true;
358
+ });
359
+ this.button.removeAttr('tabindex');
360
+ }
361
+ },
362
+
363
+ checkTabIndex: function() {
364
+ if (this.$element.is('[tabindex]')) {
365
+ var tabindex = this.$element.attr("tabindex");
366
+ this.button.attr('tabindex', tabindex);
367
+ }
368
+ },
369
+
370
+ clickListener: function() {
371
+ var _this = this;
372
+
373
+ $('body').on('touchstart.dropdown', '.dropdown-menu', function (e) { e.stopPropagation(); });
374
+
375
+ this.$newElement.on('click', 'li a', function(e){
376
+ var clickedIndex = $(this).parent().index(),
377
+ $this = $(this).parent(),
378
+ $select = $this.parents('.bootstrap-select'),
379
+ prevValue = _this.$element.val();
380
+
381
+ //Dont close on multi choice menu
382
+ if(_this.multiple) {
383
+ e.stopPropagation();
384
+ }
385
+
386
+ e.preventDefault();
387
+
388
+ //Dont run if we have been disabled
389
+ if (_this.$element.not(':disabled') && !$(this).parent().hasClass('disabled')){
390
+ //Deselect all others if not multi select box
391
+ if (!_this.multiple) {
392
+ _this.$element.find('option').prop('selected', false);
393
+ _this.$element.find('option').eq(clickedIndex).prop('selected', true);
394
+ }
395
+ //Else toggle the one we have chosen if we are multi select.
396
+ else {
397
+ var selected = _this.$element.find('option').eq(clickedIndex).prop('selected');
398
+
399
+ if(selected) {
400
+ _this.$element.find('option').eq(clickedIndex).prop('selected', false);
401
+ } else {
402
+ _this.$element.find('option').eq(clickedIndex).prop('selected', true);
403
+ }
404
+ }
405
+
406
+ $select.find('button').focus();
407
+
408
+ // Trigger select 'change'
409
+ if (prevValue != _this.$element.val()) {
410
+ _this.$element.trigger('change');
411
+ }
412
+
413
+ _this.render();
414
+ }
415
+
416
+ });
417
+
418
+ this.$newElement.on('click', 'li.disabled a, li dt, li .div-contain', function(e) {
419
+ e.preventDefault();
420
+ e.stopPropagation();
421
+ var $select = $(this).parent().parents('.bootstrap-select');
422
+ $select.find('button').focus();
423
+ });
424
+
425
+ this.$element.on('change', function(e) {
426
+ _this.render();
427
+ });
428
+ },
429
+
430
+ val:function(value) {
431
+
432
+ if(value!=undefined) {
433
+ this.$element.val( value );
434
+
435
+ this.$element.trigger('change');
436
+ return this.$element;
437
+ } else {
438
+ return this.$element.val();
439
+ }
440
+ },
441
+
442
+ selectAll:function() {
443
+ this.$element.find('option').prop('selected', true).attr('selected', 'selected');
444
+ this.render();
445
+ },
446
+
447
+ deselectAll:function() {
448
+ this.$element.find('option').prop('selected', false).removeAttr('selected');
449
+ this.render();
450
+ },
451
+
452
+ keydown: function (e) {
453
+ var $this,
454
+ $items,
455
+ $parent,
456
+ index,
457
+ next,
458
+ first,
459
+ last,
460
+ prev,
461
+ nextPrev
462
+
463
+ $this = $(this);
464
+
465
+ $parent = $this.parent();
466
+
467
+ $items = $('[role=menu] li:not(.divider):visible a', $parent);
468
+
469
+ if (!$items.length) return;
470
+
471
+ if (/(38|40)/.test(e.keyCode)) {
472
+
473
+ index = $items.index($items.filter(':focus'));
474
+
475
+ first = $items.parent(':not(.disabled)').first().index();
476
+ last = $items.parent(':not(.disabled)').last().index();
477
+ next = $items.eq(index).parent().nextAll(':not(.disabled)').eq(0).index();
478
+ prev = $items.eq(index).parent().prevAll(':not(.disabled)').eq(0).index();
479
+ nextPrev = $items.eq(next).parent().prevAll(':not(.disabled)').eq(0).index();
480
+
481
+ if (e.keyCode == 38) {
482
+ if (index != nextPrev && index > prev) index = prev;
483
+ if (index < first) index = first;
484
+ }
485
+
486
+ if (e.keyCode == 40) {
487
+ if (index != nextPrev && index < next) index = next;
488
+ if (index > last) index = last;
489
+ }
490
+
491
+ $items.eq(index).focus()
492
+ } else {
493
+ var keyCodeMap = {
494
+ 48:"0", 49:"1", 50:"2", 51:"3", 52:"4", 53:"5", 54:"6", 55:"7", 56:"8", 57:"9", 59:";",
495
+ 65:"a", 66:"b", 67:"c", 68:"d", 69:"e", 70:"f", 71:"g", 72:"h", 73:"i", 74:"j", 75:"k", 76:"l",
496
+ 77:"m", 78:"n", 79:"o", 80:"p", 81:"q", 82:"r", 83:"s", 84:"t", 85:"u", 86:"v", 87:"w", 88:"x", 89:"y", 90:"z",
497
+ 96:"0", 97:"1", 98:"2", 99:"3", 100:"4", 101:"5", 102:"6", 103:"7", 104:"8", 105:"9"
498
+ }
499
+
500
+ var keyIndex = [];
501
+
502
+ $items.each(function() {
503
+ if ($(this).parent().is(':not(.disabled)')) {
504
+ if ($.trim($(this).text().toLowerCase()).substring(0,1) == keyCodeMap[e.keyCode]) {
505
+ keyIndex.push($(this).parent().index());
506
+ }
507
+ }
508
+ });
509
+
510
+ var count = $(document).data('keycount');
511
+ count++;
512
+ $(document).data('keycount',count);
513
+
514
+ var prevKey = $.trim($(':focus').text().toLowerCase()).substring(0,1);
515
+
516
+ if (prevKey != keyCodeMap[e.keyCode]) {
517
+ count = 1;
518
+ $(document).data('keycount',count);
519
+ } else if (count >= keyIndex.length) {
520
+ $(document).data('keycount',0);
521
+ }
522
+
523
+ $items.eq(keyIndex[count - 1]).focus();
524
+ }
525
+
526
+ if (/(13)/.test(e.keyCode)) {
527
+ $(':focus').click();
528
+ $parent.addClass('open');
529
+ $(document).data('keycount',0);
530
+ }
531
+ }
532
+ };
533
+
534
+ $.fn.selectpicker = function(option, event) {
535
+ //get the args of the outer function..
536
+ var args = arguments;
537
+ var value;
538
+ var chain = this.each(function () {
539
+ if ($(this).is('select')) {
540
+ var $this = $(this),
541
+ data = $this.data('selectpicker'),
542
+ options = typeof option == 'object' && option;
543
+
544
+ if (!data) {
545
+ $this.data('selectpicker', (data = new Selectpicker(this, options, event)));
546
+ } else if(options){
547
+ for(var i in options) {
548
+ data.options[i]=options[i];
549
+ }
550
+ }
551
+
552
+ if (typeof option == 'string') {
553
+ //Copy the value of option, as once we shift the arguments
554
+ //it also shifts the value of option.
555
+ var property = option;
556
+ if(data[property] instanceof Function) {
557
+ [].shift.apply(args);
558
+ value = data[property].apply(data, args);
559
+ } else {
560
+ value = data.options[property];
561
+ }
562
+ }
563
+ }
564
+ });
565
+
566
+ if(value!=undefined) {
567
+ return value;
568
+ } else {
569
+ return chain;
570
+ }
571
+ };
572
+
573
+ $.fn.selectpicker.defaults = {
574
+ style: null,
575
+ size: 'auto',
576
+ title: null,
577
+ selectedTextFormat : 'values',
578
+ noneSelectedText : 'Nothing selected',
579
+ countSelectedText: '{0} of {1} selected',
580
+ width: null,
581
+ container: false,
582
+ hideDisabled: false,
583
+ showSubtext: false
584
+ }
585
+
586
+ $(document)
587
+ .data('keycount', 0)
588
+ .on('keydown', '[data-toggle=dropdown], [role=menu]' , Selectpicker.prototype.keydown)
589
+
590
+ }(window.jQuery);