elucid-rails_admin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (348) hide show
  1. data/Gemfile +54 -0
  2. data/LICENSE.md +20 -0
  3. data/README.md +1334 -0
  4. data/Rakefile +14 -0
  5. data/app/assets/images/rails_admin/aristo/images/bg_fallback.png +0 -0
  6. data/app/assets/images/rails_admin/aristo/images/icon_sprite.png +0 -0
  7. data/app/assets/images/rails_admin/aristo/images/progress_bar.gif +0 -0
  8. data/app/assets/images/rails_admin/aristo/images/slider_handles.png +0 -0
  9. data/app/assets/images/rails_admin/aristo/images/ui-icons_222222_256x240.png +0 -0
  10. data/app/assets/images/rails_admin/aristo/images/ui-icons_454545_256x240.png +0 -0
  11. data/app/assets/images/rails_admin/bullet_black.png +0 -0
  12. data/app/assets/images/rails_admin/bullet_white.png +0 -0
  13. data/app/assets/images/rails_admin/calendar.png +0 -0
  14. data/app/assets/images/rails_admin/clock.png +0 -0
  15. data/app/assets/images/rails_admin/colorpicker/colorpicker_background.png +0 -0
  16. data/app/assets/images/rails_admin/colorpicker/colorpicker_hex.png +0 -0
  17. data/app/assets/images/rails_admin/colorpicker/colorpicker_hsb_b.png +0 -0
  18. data/app/assets/images/rails_admin/colorpicker/colorpicker_hsb_h.png +0 -0
  19. data/app/assets/images/rails_admin/colorpicker/colorpicker_hsb_s.png +0 -0
  20. data/app/assets/images/rails_admin/colorpicker/colorpicker_indic.gif +0 -0
  21. data/app/assets/images/rails_admin/colorpicker/colorpicker_overlay.png +0 -0
  22. data/app/assets/images/rails_admin/colorpicker/colorpicker_rgb_b.png +0 -0
  23. data/app/assets/images/rails_admin/colorpicker/colorpicker_rgb_g.png +0 -0
  24. data/app/assets/images/rails_admin/colorpicker/colorpicker_rgb_r.png +0 -0
  25. data/app/assets/images/rails_admin/colorpicker/colorpicker_select.gif +0 -0
  26. data/app/assets/images/rails_admin/colorpicker/colorpicker_submit.png +0 -0
  27. data/app/assets/images/rails_admin/colorpicker/custom_background.png +0 -0
  28. data/app/assets/images/rails_admin/colorpicker/custom_hex.png +0 -0
  29. data/app/assets/images/rails_admin/colorpicker/custom_hsb_b.png +0 -0
  30. data/app/assets/images/rails_admin/colorpicker/custom_hsb_h.png +0 -0
  31. data/app/assets/images/rails_admin/colorpicker/custom_hsb_s.png +0 -0
  32. data/app/assets/images/rails_admin/colorpicker/custom_indic.gif +0 -0
  33. data/app/assets/images/rails_admin/colorpicker/custom_rgb_b.png +0 -0
  34. data/app/assets/images/rails_admin/colorpicker/custom_rgb_g.png +0 -0
  35. data/app/assets/images/rails_admin/colorpicker/custom_rgb_r.png +0 -0
  36. data/app/assets/images/rails_admin/colorpicker/custom_submit.png +0 -0
  37. data/app/assets/images/rails_admin/colorpicker/select.png +0 -0
  38. data/app/assets/images/rails_admin/colorpicker/select2.png +0 -0
  39. data/app/assets/images/rails_admin/colorpicker/slider.png +0 -0
  40. data/app/assets/images/rails_admin/logo.png +0 -0
  41. data/app/assets/images/rails_admin/magnifier.png +0 -0
  42. data/app/assets/images/rails_admin/multiselect/icon_sprite.png +0 -0
  43. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-n-dark.png +0 -0
  44. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-n-light.png +0 -0
  45. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-s-dark.png +0 -0
  46. data/app/assets/images/rails_admin/multiselect/ui-icon-circle-triangle-s-light.png +0 -0
  47. data/app/assets/javascripts/rails_admin/custom/ui.js +1 -0
  48. data/app/assets/javascripts/rails_admin/jquery-ui-1.8.16.custom.js +5019 -0
  49. data/app/assets/javascripts/rails_admin/jquery.colorpicker.js +484 -0
  50. data/app/assets/javascripts/rails_admin/jquery.ui.timepicker.js +1219 -0
  51. data/app/assets/javascripts/rails_admin/ra.datetimepicker.js +67 -0
  52. data/app/assets/javascripts/rails_admin/ra.filter-box.js +119 -0
  53. data/app/assets/javascripts/rails_admin/ra.filtering-multiselect.js +280 -0
  54. data/app/assets/javascripts/rails_admin/ra.filtering-select.js +181 -0
  55. data/app/assets/javascripts/rails_admin/ra.remote-form.js +147 -0
  56. data/app/assets/javascripts/rails_admin/rails_admin.js.erb +17 -0
  57. data/app/assets/javascripts/rails_admin/themes/default/ui.js +1 -0
  58. data/app/assets/javascripts/rails_admin/ui.js.coffee +30 -0
  59. data/app/assets/stylesheets/rails_admin/aristo/images/bg_fallback.png +0 -0
  60. data/app/assets/stylesheets/rails_admin/aristo/images/icon_sprite.png +0 -0
  61. data/app/assets/stylesheets/rails_admin/aristo/images/progress_bar.gif +0 -0
  62. data/app/assets/stylesheets/rails_admin/aristo/images/slider_handles.png +0 -0
  63. data/app/assets/stylesheets/rails_admin/aristo/images/ui-icons_222222_256x240.png +0 -0
  64. data/app/assets/stylesheets/rails_admin/aristo/images/ui-icons_454545_256x240.png +0 -0
  65. data/app/assets/stylesheets/rails_admin/aristo/jquery-ui-1.8.7.custom.css.scss +733 -0
  66. data/app/assets/stylesheets/rails_admin/base/README +2 -0
  67. data/app/assets/stylesheets/rails_admin/base/mixins.css.scss +1 -0
  68. data/app/assets/stylesheets/rails_admin/base/theming.css.scss +102 -0
  69. data/app/assets/stylesheets/rails_admin/base/variables.css.scss +1 -0
  70. data/app/assets/stylesheets/rails_admin/custom/README +3 -0
  71. data/app/assets/stylesheets/rails_admin/custom/mixins.css.scss +9 -0
  72. data/app/assets/stylesheets/rails_admin/custom/theming.css.scss +11 -0
  73. data/app/assets/stylesheets/rails_admin/custom/variables.css.scss +11 -0
  74. data/app/assets/stylesheets/rails_admin/imports.css.scss.erb +51 -0
  75. data/app/assets/stylesheets/rails_admin/jquery.colorpicker.css.scss +180 -0
  76. data/app/assets/stylesheets/rails_admin/jquery.ui.timepicker.css.scss +53 -0
  77. data/app/assets/stylesheets/rails_admin/ra.calendar-additions.css.scss +25 -0
  78. data/app/assets/stylesheets/rails_admin/ra.filtering-multiselect.css.scss +85 -0
  79. data/app/assets/stylesheets/rails_admin/rails_admin.css +4 -0
  80. data/app/assets/stylesheets/rails_admin/themes/README +11 -0
  81. data/app/assets/stylesheets/rails_admin/themes/default/mixins.css.scss +1 -0
  82. data/app/assets/stylesheets/rails_admin/themes/default/theming.css.scss +1 -0
  83. data/app/assets/stylesheets/rails_admin/themes/default/variables.css.scss +1 -0
  84. data/app/controllers/rails_admin/application_controller.rb +62 -0
  85. data/app/controllers/rails_admin/history_controller.rb +26 -0
  86. data/app/controllers/rails_admin/main_controller.rb +371 -0
  87. data/app/helpers/rails_admin/application_helper.rb +65 -0
  88. data/app/helpers/rails_admin/form_builder.rb +52 -0
  89. data/app/helpers/rails_admin/main_helper.rb +100 -0
  90. data/app/models/rails_admin/history.rb +64 -0
  91. data/app/views/kaminari/twitter-bootstrap/_gap.html.haml +2 -0
  92. data/app/views/kaminari/twitter-bootstrap/_next_page.html.haml +4 -0
  93. data/app/views/kaminari/twitter-bootstrap/_page.html.haml +4 -0
  94. data/app/views/kaminari/twitter-bootstrap/_paginator.html.haml +10 -0
  95. data/app/views/kaminari/twitter-bootstrap/_prev_page.html.haml +4 -0
  96. data/app/views/layouts/rails_admin/_navigation.html.haml +19 -0
  97. data/app/views/layouts/rails_admin/_secondary_navigation.html.haml +9 -0
  98. data/app/views/layouts/rails_admin/application.html.haml +41 -0
  99. data/app/views/rails_admin/history/_dashboard.html.haml +10 -0
  100. data/app/views/rails_admin/history/show.html.haml +42 -0
  101. data/app/views/rails_admin/main/_delete_notice.html.haml +19 -0
  102. data/app/views/rails_admin/main/_form_colorpicker.html.haml +26 -0
  103. data/app/views/rails_admin/main/_form_datetime.html.haml +7 -0
  104. data/app/views/rails_admin/main/_form_enumeration.html.haml +5 -0
  105. data/app/views/rails_admin/main/_form_field.html.haml +1 -0
  106. data/app/views/rails_admin/main/_form_file_upload.html.haml +19 -0
  107. data/app/views/rails_admin/main/_form_filtering_multiselect.html.haml +57 -0
  108. data/app/views/rails_admin/main/_form_filtering_select.html.haml +47 -0
  109. data/app/views/rails_admin/main/_form_polymorphic_association.html.haml +36 -0
  110. data/app/views/rails_admin/main/_form_text.html.haml +13 -0
  111. data/app/views/rails_admin/main/_models_links.html.haml +31 -0
  112. data/app/views/rails_admin/main/_object_links.html.haml +23 -0
  113. data/app/views/rails_admin/main/_submit_buttons.html.haml +12 -0
  114. data/app/views/rails_admin/main/bulk_delete.html.haml +6 -0
  115. data/app/views/rails_admin/main/dashboard.html.haml +31 -0
  116. data/app/views/rails_admin/main/delete.html.haml +13 -0
  117. data/app/views/rails_admin/main/edit.html.haml +2 -0
  118. data/app/views/rails_admin/main/export.html.haml +70 -0
  119. data/app/views/rails_admin/main/index.html.haml +98 -0
  120. data/app/views/rails_admin/main/new.html.haml +2 -0
  121. data/app/views/rails_admin/main/show.html.haml +14 -0
  122. data/config/initializers/active_record_extensions.rb +19 -0
  123. data/config/initializers/devise_patch.rb +9 -0
  124. data/config/initializers/haml.rb +3 -0
  125. data/config/locales/devise.bg.yml +42 -0
  126. data/config/locales/devise.de.yml +39 -0
  127. data/config/locales/devise.en.yml +39 -0
  128. data/config/locales/devise.es.yml +39 -0
  129. data/config/locales/devise.fi.yml +39 -0
  130. data/config/locales/devise.fr.yml +78 -0
  131. data/config/locales/devise.hr.yml +49 -0
  132. data/config/locales/devise.it.yml +39 -0
  133. data/config/locales/devise.lt.yml +39 -0
  134. data/config/locales/devise.mn.yml +39 -0
  135. data/config/locales/devise.nb.yml +43 -0
  136. data/config/locales/devise.pt-BR.yml +39 -0
  137. data/config/locales/devise.pt-PT.yml +39 -0
  138. data/config/locales/devise.ro.yml +46 -0
  139. data/config/locales/devise.ru.yml +39 -0
  140. data/config/locales/devise.sv.yml +39 -0
  141. data/config/locales/devise.tr.yml +39 -0
  142. data/config/locales/devise.uk.yml +39 -0
  143. data/config/locales/devise.zh-CN.yml +39 -0
  144. data/config/locales/devise.zh_cn.yml +39 -0
  145. data/config/locales/rails_admin.bg.yml +104 -0
  146. data/config/locales/rails_admin.da.yml +99 -0
  147. data/config/locales/rails_admin.de.yml +110 -0
  148. data/config/locales/rails_admin.en.yml +114 -0
  149. data/config/locales/rails_admin.es.yml +112 -0
  150. data/config/locales/rails_admin.fi.yml +107 -0
  151. data/config/locales/rails_admin.fr.yml +110 -0
  152. data/config/locales/rails_admin.hr.yml +81 -0
  153. data/config/locales/rails_admin.it.yml +109 -0
  154. data/config/locales/rails_admin.ja.yml +110 -0
  155. data/config/locales/rails_admin.lt.yml +102 -0
  156. data/config/locales/rails_admin.lv.yml +100 -0
  157. data/config/locales/rails_admin.mn.yml +103 -0
  158. data/config/locales/rails_admin.nb.yml +110 -0
  159. data/config/locales/rails_admin.nl.yml +135 -0
  160. data/config/locales/rails_admin.pl.yml +111 -0
  161. data/config/locales/rails_admin.pt-BR.yml +109 -0
  162. data/config/locales/rails_admin.pt-PT.yml +109 -0
  163. data/config/locales/rails_admin.ro.yml +113 -0
  164. data/config/locales/rails_admin.ru.yml +109 -0
  165. data/config/locales/rails_admin.sv.yml +103 -0
  166. data/config/locales/rails_admin.tr.yml +103 -0
  167. data/config/locales/rails_admin.uk.yml +100 -0
  168. data/config/locales/rails_admin.zh-CN.yml +114 -0
  169. data/config/locales/rails_admin.zh_cn.yml +107 -0
  170. data/config/routes.rb +28 -0
  171. data/lib/generators/rails_admin/install_generator.rb +83 -0
  172. data/lib/generators/rails_admin/templates/drop.rb +18 -0
  173. data/lib/generators/rails_admin/templates/initializer.erb +150 -0
  174. data/lib/generators/rails_admin/templates/migration.rb +18 -0
  175. data/lib/generators/rails_admin/uninstall_generator.rb +22 -0
  176. data/lib/generators/rails_admin/utils.rb +30 -0
  177. data/lib/rails_admin.rb +57 -0
  178. data/lib/rails_admin/abstract_model.rb +73 -0
  179. data/lib/rails_admin/abstract_object.rb +28 -0
  180. data/lib/rails_admin/adapters/active_record.rb +359 -0
  181. data/lib/rails_admin/config.rb +287 -0
  182. data/lib/rails_admin/config/base.rb +111 -0
  183. data/lib/rails_admin/config/fields.rb +99 -0
  184. data/lib/rails_admin/config/fields/association.rb +101 -0
  185. data/lib/rails_admin/config/fields/base.rb +273 -0
  186. data/lib/rails_admin/config/fields/factories/carrierwave.rb +16 -0
  187. data/lib/rails_admin/config/fields/factories/devise.rb +31 -0
  188. data/lib/rails_admin/config/fields/factories/dragonfly.rb +20 -0
  189. data/lib/rails_admin/config/fields/factories/enum.rb +11 -0
  190. data/lib/rails_admin/config/fields/factories/paperclip.rb +26 -0
  191. data/lib/rails_admin/config/fields/factories/password.rb +17 -0
  192. data/lib/rails_admin/config/fields/group.rb +63 -0
  193. data/lib/rails_admin/config/fields/groupable.rb +25 -0
  194. data/lib/rails_admin/config/fields/types.rb +26 -0
  195. data/lib/rails_admin/config/fields/types/all.rb +22 -0
  196. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +51 -0
  197. data/lib/rails_admin/config/fields/types/boolean.rb +29 -0
  198. data/lib/rails_admin/config/fields/types/carrierwave.rb +32 -0
  199. data/lib/rails_admin/config/fields/types/color.rb +37 -0
  200. data/lib/rails_admin/config/fields/types/date.rb +24 -0
  201. data/lib/rails_admin/config/fields/types/datetime.rb +160 -0
  202. data/lib/rails_admin/config/fields/types/decimal.rb +14 -0
  203. data/lib/rails_admin/config/fields/types/dragonfly.rb +51 -0
  204. data/lib/rails_admin/config/fields/types/enum.rb +35 -0
  205. data/lib/rails_admin/config/fields/types/file_upload.rb +54 -0
  206. data/lib/rails_admin/config/fields/types/float.rb +14 -0
  207. data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +14 -0
  208. data/lib/rails_admin/config/fields/types/has_many_association.rb +42 -0
  209. data/lib/rails_admin/config/fields/types/has_one_association.rb +31 -0
  210. data/lib/rails_admin/config/fields/types/integer.rb +24 -0
  211. data/lib/rails_admin/config/fields/types/paperclip.rb +38 -0
  212. data/lib/rails_admin/config/fields/types/password.rb +41 -0
  213. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +78 -0
  214. data/lib/rails_admin/config/fields/types/string.rb +34 -0
  215. data/lib/rails_admin/config/fields/types/text.rb +39 -0
  216. data/lib/rails_admin/config/fields/types/time.rb +31 -0
  217. data/lib/rails_admin/config/fields/types/timestamp.rb +18 -0
  218. data/lib/rails_admin/config/has_fields.rb +112 -0
  219. data/lib/rails_admin/config/has_groups.rb +39 -0
  220. data/lib/rails_admin/config/hideable.rb +28 -0
  221. data/lib/rails_admin/config/model.rb +89 -0
  222. data/lib/rails_admin/config/proxy.rb +40 -0
  223. data/lib/rails_admin/config/sections.rb +51 -0
  224. data/lib/rails_admin/config/sections/create.rb +11 -0
  225. data/lib/rails_admin/config/sections/export.rb +18 -0
  226. data/lib/rails_admin/config/sections/list.rb +55 -0
  227. data/lib/rails_admin/config/sections/navigation.rb +21 -0
  228. data/lib/rails_admin/config/sections/show.rb +50 -0
  229. data/lib/rails_admin/config/sections/update.rb +11 -0
  230. data/lib/rails_admin/engine.rb +15 -0
  231. data/lib/rails_admin/extension.rb +23 -0
  232. data/lib/rails_admin/extensions/cancan.rb +5 -0
  233. data/lib/rails_admin/extensions/cancan/authorization_adapter.rb +71 -0
  234. data/lib/rails_admin/generic_support.rb +15 -0
  235. data/lib/rails_admin/i18n_support.rb +43 -0
  236. data/lib/rails_admin/support/core_extensions.rb +44 -0
  237. data/lib/rails_admin/support/csv_converter.rb +109 -0
  238. data/lib/rails_admin/version.rb +6 -0
  239. data/lib/tasks/prepare_ci_env.rake +27 -0
  240. data/lib/tasks/rails_admin.rake +18 -0
  241. data/spec/ci.sh +2 -0
  242. data/spec/controllers/application_controller_spec.rb +30 -0
  243. data/spec/controllers/main_controller_spec.rb +86 -0
  244. data/spec/database_helpers.rb +15 -0
  245. data/spec/dummy_app/Gemfile +52 -0
  246. data/spec/dummy_app/README +256 -0
  247. data/spec/dummy_app/Rakefile +7 -0
  248. data/spec/dummy_app/app/controllers/application_controller.rb +3 -0
  249. data/spec/dummy_app/app/helpers/application_helper.rb +2 -0
  250. data/spec/dummy_app/app/locales/models.en.yml +8 -0
  251. data/spec/dummy_app/app/models/abstract.rb +5 -0
  252. data/spec/dummy_app/app/models/ball.rb +8 -0
  253. data/spec/dummy_app/app/models/cms.rb +5 -0
  254. data/spec/dummy_app/app/models/cms/basic_page.rb +7 -0
  255. data/spec/dummy_app/app/models/cms/unscoped_page.rb +3 -0
  256. data/spec/dummy_app/app/models/comment.rb +3 -0
  257. data/spec/dummy_app/app/models/division.rb +8 -0
  258. data/spec/dummy_app/app/models/draft.rb +11 -0
  259. data/spec/dummy_app/app/models/fan.rb +5 -0
  260. data/spec/dummy_app/app/models/field_test.rb +13 -0
  261. data/spec/dummy_app/app/models/league.rb +10 -0
  262. data/spec/dummy_app/app/models/player.rb +15 -0
  263. data/spec/dummy_app/app/models/rel_test.rb +6 -0
  264. data/spec/dummy_app/app/models/team.rb +25 -0
  265. data/spec/dummy_app/app/models/user.rb +21 -0
  266. data/spec/dummy_app/app/uploaders/carrierwave_uploader.rb +53 -0
  267. data/spec/dummy_app/app/views/layouts/application.html.erb +13 -0
  268. data/spec/dummy_app/config.ru +4 -0
  269. data/spec/dummy_app/config/application.rb +47 -0
  270. data/spec/dummy_app/config/boot.rb +6 -0
  271. data/spec/dummy_app/config/database.yml +22 -0
  272. data/spec/dummy_app/config/environment.rb +5 -0
  273. data/spec/dummy_app/config/environments/development.rb +27 -0
  274. data/spec/dummy_app/config/environments/production.rb +51 -0
  275. data/spec/dummy_app/config/environments/test.rb +39 -0
  276. data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
  277. data/spec/dummy_app/config/initializers/devise.rb +142 -0
  278. data/spec/dummy_app/config/initializers/inflections.rb +10 -0
  279. data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
  280. data/spec/dummy_app/config/initializers/quiet_assets.rb +10 -0
  281. data/spec/dummy_app/config/initializers/rails_admin.rb +10 -0
  282. data/spec/dummy_app/config/initializers/secret_token.rb +7 -0
  283. data/spec/dummy_app/config/initializers/session_store.rb +8 -0
  284. data/spec/dummy_app/config/routes.rb +8 -0
  285. data/spec/dummy_app/db/migrate/00000000000001_create_divisions_migration.rb +13 -0
  286. data/spec/dummy_app/db/migrate/00000000000002_create_drafts_migration.rb +19 -0
  287. data/spec/dummy_app/db/migrate/00000000000003_create_leagues_migration.rb +12 -0
  288. data/spec/dummy_app/db/migrate/00000000000004_create_players_migration.rb +20 -0
  289. data/spec/dummy_app/db/migrate/00000000000005_create_teams_migration.rb +22 -0
  290. data/spec/dummy_app/db/migrate/00000000000006_devise_create_users.rb +19 -0
  291. data/spec/dummy_app/db/migrate/00000000000007_create_histories_table.rb +16 -0
  292. data/spec/dummy_app/db/migrate/00000000000008_create_fans_migration.rb +12 -0
  293. data/spec/dummy_app/db/migrate/00000000000009_create_fans_teams_migration.rb +11 -0
  294. data/spec/dummy_app/db/migrate/00000000000010_add_revenue_to_team_migration.rb +9 -0
  295. data/spec/dummy_app/db/migrate/00000000000011_add_suspended_to_player_migration.rb +9 -0
  296. data/spec/dummy_app/db/migrate/00000000000012_add_avatar_columns_to_user.rb +16 -0
  297. data/spec/dummy_app/db/migrate/00000000000013_add_roles_to_user.rb +9 -0
  298. data/spec/dummy_app/db/migrate/00000000000014_add_color_to_team_migration.rb +9 -0
  299. data/spec/dummy_app/db/migrate/20101223222233_create_rel_tests.rb +15 -0
  300. data/spec/dummy_app/db/migrate/20110103205808_create_comments.rb +15 -0
  301. data/spec/dummy_app/db/migrate/20110123042530_rename_histories_to_rails_admin_histories.rb +9 -0
  302. data/spec/dummy_app/db/migrate/20110224184303_create_field_tests.rb +22 -0
  303. data/spec/dummy_app/db/migrate/20110328193014_create_cms_basic_pages.rb +14 -0
  304. data/spec/dummy_app/db/migrate/20110329183136_remove_league_id_from_teams.rb +9 -0
  305. data/spec/dummy_app/db/migrate/20110607152842_add_format_to_field_test.rb +9 -0
  306. data/spec/dummy_app/db/migrate/20110714095433_create_balls.rb +12 -0
  307. data/spec/dummy_app/db/migrate/20110831090841_add_protected_field_and_restricted_field_to_field_tests.rb +6 -0
  308. data/spec/dummy_app/db/migrate/20110901131551_change_division_primary_key.rb +19 -0
  309. data/spec/dummy_app/db/migrate/20110901142530_rename_league_id_foreign_key_on_divisions.rb +5 -0
  310. data/spec/dummy_app/db/migrate/20110901150912_set_primary_key_not_null_for_divisions.rb +21 -0
  311. data/spec/dummy_app/db/migrate/20110901154834_change_length_for_rails_admin_histories.rb +9 -0
  312. data/spec/dummy_app/db/migrate/20111103174459_create_unscoped_pages.rb +9 -0
  313. data/spec/dummy_app/db/migrate/20111108143642_add_dragonfly_and_carrierwave_to_field_tests.rb +7 -0
  314. data/spec/dummy_app/db/seeds.rb +18 -0
  315. data/spec/dummy_app/doc/README_FOR_APP +2 -0
  316. data/spec/dummy_app/public/404.html +0 -0
  317. data/spec/dummy_app/public/favicon.ico +0 -0
  318. data/spec/dummy_app/script/rails +6 -0
  319. data/spec/factories.rb +62 -0
  320. data/spec/generator_helpers.rb +30 -0
  321. data/spec/generators/install_generator_spec.rb +85 -0
  322. data/spec/generators/uninstall_generator_spec.rb +35 -0
  323. data/spec/lib/abstract_object_spec.rb +119 -0
  324. data/spec/lib/rails_admin_spec.rb +153 -0
  325. data/spec/requests/authorization/cancan_spec.rb +260 -0
  326. data/spec/requests/basic/bulk_action/rails_admin_basic_bulk_action_spec.rb +25 -0
  327. data/spec/requests/basic/bulk_destroy/rails_admin_basic_bulk_destroy_spec.rb +55 -0
  328. data/spec/requests/basic/create/rails_admin_basic_create_spec.rb +143 -0
  329. data/spec/requests/basic/create/rails_admin_namespaced_model_create_spec.rb +24 -0
  330. data/spec/requests/basic/delete/rails_admin_basic_delete_spec.rb +35 -0
  331. data/spec/requests/basic/destroy/rails_admin_basic_destroy_spec.rb +56 -0
  332. data/spec/requests/basic/edit/rails_admin_basic_edit_spec.rb +98 -0
  333. data/spec/requests/basic/export/rails_admin_basic_export_spec.rb +84 -0
  334. data/spec/requests/basic/list/rails_admin_basic_list_spec.rb +401 -0
  335. data/spec/requests/basic/new/rails_admin_basic_new_spec.rb +74 -0
  336. data/spec/requests/basic/new/rails_admin_namespaced_model_new_spec.rb +31 -0
  337. data/spec/requests/basic/show/rails_admin_basic_show_spec.rb +83 -0
  338. data/spec/requests/basic/update/rails_admin_basic_update_spec.rb +169 -0
  339. data/spec/requests/config/edit/rails_admin_config_edit_spec.rb +744 -0
  340. data/spec/requests/config/list/rails_admin_config_list_spec.rb +549 -0
  341. data/spec/requests/config/navigation/rails_admin_config_navigation_spec.rb +107 -0
  342. data/spec/requests/config/rails_admin_config_spec.rb +180 -0
  343. data/spec/requests/config/show/rails_admin_config_show_spec.rb +275 -0
  344. data/spec/requests/history/rails_admin_history_spec.rb +57 -0
  345. data/spec/requests/rails_admin_spec.rb +103 -0
  346. data/spec/requests/relation_spec.rb +26 -0
  347. data/spec/spec_helper.rb +88 -0
  348. metadata +717 -0
@@ -0,0 +1,1219 @@
1
+ /*
2
+ * jQuery UI Timepicker 0.2.5
3
+ *
4
+ * Copyright 2010-2011, Francois Gelinas
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://fgelinas.com/code/timepicker
9
+ *
10
+ * Depends:
11
+ * jquery.ui.core.js
12
+ * jquery.ui.position.js (only if position settngs are used)
13
+ *
14
+ * Change version 0.1.0 - moved the t-rex up here
15
+ *
16
+ ____
17
+ ___ .-~. /_"-._
18
+ `-._~-. / /_ "~o\ :Y
19
+ \ \ / : \~x. ` ')
20
+ ] Y / | Y< ~-.__j
21
+ / ! _.--~T : l l< /.-~
22
+ / / ____.--~ . ` l /~\ \<|Y
23
+ / / .-~~" /| . ',-~\ \L|
24
+ / / / .^ \ Y~Y \.^>/l_ "--'
25
+ / Y .-"( . l__ j_j l_/ /~_.-~ .
26
+ Y l / \ ) ~~~." / `/"~ / \.__/l_
27
+ | \ _.-" ~-{__ l : l._Z~-.___.--~
28
+ | ~---~ / ~~"---\_ ' __[>
29
+ l . _.^ ___ _>-y~
30
+ \ \ . .-~ .-~ ~>--" /
31
+ \ ~---" / ./ _.-'
32
+ "-.,_____.,_ _.--~\ _.-~
33
+ ~~ ( _} -Row
34
+ `. ~(
35
+ ) \
36
+ /,`--'~\--'~\
37
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38
+ ->T-Rex<-
39
+ */
40
+
41
+ (function ($, undefined) {
42
+
43
+ $.extend($.ui, { timepicker: { version: "0.2.5"} });
44
+
45
+ var PROP_NAME = 'timepicker';
46
+ var tpuuid = new Date().getTime();
47
+
48
+ /* Time picker manager.
49
+ Use the singleton instance of this class, $.timepicker, to interact with the time picker.
50
+ Settings for (groups of) time pickers are maintained in an instance object,
51
+ allowing multiple different settings on the same page. */
52
+
53
+ function Timepicker() {
54
+ this.debug = true; // Change this to true to start debugging
55
+ this._curInst = null; // The current instance in use
56
+ this._isInline = false; // true if the instance is displayed inline
57
+ this._disabledInputs = []; // List of time picker inputs that have been disabled
58
+ this._timepickerShowing = false; // True if the popup picker is showing , false if not
59
+ this._inDialog = false; // True if showing within a "dialog", false if not
60
+ this._dialogClass = 'ui-timepicker-dialog'; // The name of the dialog marker class
61
+ this._mainDivId = 'ui-timepicker-div'; // The ID of the main timepicker division
62
+ this._inlineClass = 'ui-timepicker-inline'; // The name of the inline marker class
63
+ this._currentClass = 'ui-timepicker-current'; // The name of the current hour / minutes marker class
64
+ this._dayOverClass = 'ui-timepicker-days-cell-over'; // The name of the day hover marker class
65
+
66
+ this.regional = []; // Available regional settings, indexed by language code
67
+ this.regional[''] = { // Default regional settings
68
+ hourText: 'Hour', // Display text for hours section
69
+ minuteText: 'Minute', // Display text for minutes link
70
+ amPmText: ['AM', 'PM'] // Display text for AM PM
71
+ };
72
+ this._defaults = { // Global defaults for all the time picker instances
73
+ showOn: 'focus', // 'focus' for popup on focus,
74
+ // 'button' for trigger button, or 'both' for either (not yet implemented)
75
+ button: null, // 'button' element that will trigger the timepicker
76
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
77
+ showOptions: {}, // Options for enhanced animations
78
+ appendText: '', // Display text following the input box, e.g. showing the format
79
+
80
+ beforeShow: null, // Define a callback function executed before the timepicker is shown
81
+ onSelect: null, // Define a callback function when a hour / minutes is selected
82
+ onClose: null, // Define a callback function when the timepicker is closed
83
+
84
+ timeSeparator: ':', // The character to use to separate hours and minutes.
85
+ periodSeparator: ' ', // The character to use to separate the time from the time period.
86
+ showPeriod: false, // Define whether or not to show AM/PM with selected time
87
+ showPeriodLabels: true, // Show the AM/PM labels on the left of the time picker
88
+ showLeadingZero: true, // Define whether or not to show a leading zero for hours < 10. [true/false]
89
+ showMinutesLeadingZero: true, // Define whether or not to show a leading zero for minutes < 10.
90
+ altField: '', // Selector for an alternate field to store selected time into
91
+ defaultTime: 'now', // Used as default time when input field is empty or for inline timePicker
92
+ // (set to 'now' for the current time, '' for no highlighted time)
93
+ myPosition: 'left top', // Position of the dialog relative to the input.
94
+ // see the position utility for more info : http://jqueryui.com/demos/position/
95
+ atPosition: 'left bottom', // Position of the input element to match
96
+ // Note : if the position utility is not loaded, the timepicker will attach left top to left bottom
97
+ //NEW: 2011-02-03
98
+ onHourShow: null, // callback for enabling / disabling on selectable hours ex : function(hour) { return true; }
99
+ onMinuteShow: null, // callback for enabling / disabling on time selection ex : function(hour,minute) { return true; }
100
+ // 2011-03-22 - v 0.0.9
101
+ zIndex: null, // specify zIndex
102
+
103
+ hours: {
104
+ starts: 0, // first displayed hour
105
+ ends: 23 // last displayed hour
106
+ },
107
+ minutes: {
108
+ starts: 0, // first displayed minute
109
+ ends: 55, // last displayed minute
110
+ interval: 5 // interval of displayed minutes
111
+ },
112
+ rows: 4, // number of rows for the input tables, minimum 2, makes more sense if you use multiple of 2
113
+ // 2011-08-05 0.2.4
114
+ showHours: true, // display the hours section of the dialog
115
+ showMinutes: true // display the minute section of the dialog
116
+
117
+ };
118
+ $.extend(this._defaults, this.regional['']);
119
+
120
+ this.tpDiv = $('<div id="' + this._mainDivId + '" class="ui-timepicker ui-widget ui-helper-clearfix ui-corner-all " style="display: none"></div>');
121
+ }
122
+
123
+ $.extend(Timepicker.prototype, {
124
+ /* Class name added to elements to indicate already configured with a time picker. */
125
+ markerClassName: 'hasTimepicker',
126
+
127
+ /* Debug logging (if enabled). */
128
+ log: function () {
129
+ if (this.debug)
130
+ console.log.apply('', arguments);
131
+ },
132
+
133
+ // TODO rename to "widget" when switching to widget factory
134
+ _widgetTimepicker: function () {
135
+ return this.tpDiv;
136
+ },
137
+
138
+ /* Override the default settings for all instances of the time picker.
139
+ @param settings object - the new settings to use as defaults (anonymous object)
140
+ @return the manager object */
141
+ setDefaults: function (settings) {
142
+ extendRemove(this._defaults, settings || {});
143
+ return this;
144
+ },
145
+
146
+ /* Attach the time picker to a jQuery selection.
147
+ @param target element - the target input field or division or span
148
+ @param settings object - the new settings to use for this time picker instance (anonymous) */
149
+ _attachTimepicker: function (target, settings) {
150
+ // check for settings on the control itself - in namespace 'time:'
151
+ var inlineSettings = null;
152
+ for (var attrName in this._defaults) {
153
+ var attrValue = target.getAttribute('time:' + attrName);
154
+ if (attrValue) {
155
+ inlineSettings = inlineSettings || {};
156
+ try {
157
+ inlineSettings[attrName] = eval(attrValue);
158
+ } catch (err) {
159
+ inlineSettings[attrName] = attrValue;
160
+ }
161
+ }
162
+ }
163
+ var nodeName = target.nodeName.toLowerCase();
164
+ var inline = (nodeName == 'div' || nodeName == 'span');
165
+
166
+ if (!target.id) {
167
+ this.uuid += 1;
168
+ target.id = 'tp' + this.uuid;
169
+ }
170
+ var inst = this._newInst($(target), inline);
171
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
172
+ if (nodeName == 'input') {
173
+ this._connectTimepicker(target, inst);
174
+ // init inst.hours and inst.minutes from the input value
175
+ this._setTimeFromField(inst);
176
+ } else if (inline) {
177
+ this._inlineTimepicker(target, inst);
178
+ }
179
+
180
+
181
+ },
182
+
183
+ /* Create a new instance object. */
184
+ _newInst: function (target, inline) {
185
+ var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
186
+ return {
187
+ id: id, input: target, // associated target
188
+ inline: inline, // is timepicker inline or not :
189
+ tpDiv: (!inline ? this.tpDiv : // presentation div
190
+ $('<div class="' + this._inlineClass + ' ui-timepicker ui-widget ui-helper-clearfix"></div>'))
191
+ };
192
+ },
193
+
194
+ /* Attach the time picker to an input field. */
195
+ _connectTimepicker: function (target, inst) {
196
+ var input = $(target);
197
+ inst.append = $([]);
198
+ inst.trigger = $([]);
199
+ if (input.hasClass(this.markerClassName)) { return; }
200
+ this._attachments(input, inst);
201
+ input.addClass(this.markerClassName).
202
+ keydown(this._doKeyDown).
203
+ keyup(this._doKeyUp).
204
+ bind("setData.timepicker", function (event, key, value) {
205
+ inst.settings[key] = value;
206
+ }).
207
+ bind("getData.timepicker", function (event, key) {
208
+ return this._get(inst, key);
209
+ });
210
+ $.data(target, PROP_NAME, inst);
211
+ },
212
+
213
+ /* Handle keystrokes. */
214
+ _doKeyDown: function (event) {
215
+ var inst = $.timepicker._getInst(event.target);
216
+ var handled = true;
217
+ inst._keyEvent = true;
218
+ if ($.timepicker._timepickerShowing) {
219
+ switch (event.keyCode) {
220
+ case 9: $.timepicker._hideTimepicker();
221
+ handled = false;
222
+ break; // hide on tab out
223
+ case 13:
224
+ $.timepicker._updateSelectedValue(inst);
225
+ $.timepicker._hideTimepicker();
226
+
227
+ return false; // don't submit the form
228
+ break; // select the value on enter
229
+ case 27: $.timepicker._hideTimepicker();
230
+ break; // hide on escape
231
+ default: handled = false;
232
+ }
233
+ }
234
+ else if (event.keyCode == 36 && event.ctrlKey) { // display the time picker on ctrl+home
235
+ $.timepicker._showTimepicker(this);
236
+ }
237
+ else {
238
+ handled = false;
239
+ }
240
+ if (handled) {
241
+ event.preventDefault();
242
+ event.stopPropagation();
243
+ }
244
+ },
245
+
246
+ /* Update selected time on keyUp */
247
+ /* Added verion 0.0.5 */
248
+ _doKeyUp: function (event) {
249
+ var inst = $.timepicker._getInst(event.target);
250
+ $.timepicker._setTimeFromField(inst);
251
+ $.timepicker._updateTimepicker(inst);
252
+ },
253
+
254
+ /* Make attachments based on settings. */
255
+ _attachments: function (input, inst) {
256
+ var appendText = this._get(inst, 'appendText');
257
+ var isRTL = this._get(inst, 'isRTL');
258
+ if (inst.append) { inst.append.remove(); }
259
+ if (appendText) {
260
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
261
+ input[isRTL ? 'before' : 'after'](inst.append);
262
+ }
263
+ input.unbind('focus.timepicker', this._showTimepicker);
264
+ if (inst.trigger) { inst.trigger.remove(); }
265
+
266
+ var showOn = this._get(inst, 'showOn');
267
+ if (showOn == 'focus' || showOn == 'both') { // pop-up time picker when in the marked field
268
+ input.bind("focus.timepicker", this._showTimepicker);
269
+ }
270
+ if (showOn == 'button' || showOn == 'both') { // pop-up time picker when 'button' element is clicked
271
+ var button = this._get(inst, 'button');
272
+ $(button).bind("click.timepicker", function () {
273
+ if ($.timepicker._timepickerShowing && $.timepicker._lastInput == input[0]) { $.timepicker._hideTimepicker(); }
274
+ else { $.timepicker._showTimepicker(input[0]); }
275
+ return false;
276
+ });
277
+
278
+ }
279
+ },
280
+
281
+
282
+ /* Attach an inline time picker to a div. */
283
+ _inlineTimepicker: function(target, inst) {
284
+ var divSpan = $(target);
285
+ if (divSpan.hasClass(this.markerClassName))
286
+ return;
287
+ divSpan.addClass(this.markerClassName).append(inst.tpDiv).
288
+ bind("setData.timepicker", function(event, key, value){
289
+ inst.settings[key] = value;
290
+ }).bind("getData.timepicker", function(event, key){
291
+ return this._get(inst, key);
292
+ });
293
+ $.data(target, PROP_NAME, inst);
294
+
295
+ this._setTimeFromField(inst);
296
+ this._updateTimepicker(inst);
297
+ inst.tpDiv.show();
298
+ },
299
+
300
+ /* Pop-up the time picker for a given input field.
301
+ @param input element - the input field attached to the time picker or
302
+ event - if triggered by focus */
303
+ _showTimepicker: function (input) {
304
+ input = input.target || input;
305
+ if (input.nodeName.toLowerCase() != 'input') { input = $('input', input.parentNode)[0]; } // find from button/image trigger
306
+ if ($.timepicker._isDisabledTimepicker(input) || $.timepicker._lastInput == input) { return; } // already here
307
+
308
+ // fix v 0.0.8 - close current timepicker before showing another one
309
+ $.timepicker._hideTimepicker();
310
+
311
+ var inst = $.timepicker._getInst(input);
312
+ if ($.timepicker._curInst && $.timepicker._curInst != inst) {
313
+ $.timepicker._curInst.tpDiv.stop(true, true);
314
+ }
315
+ var beforeShow = $.timepicker._get(inst, 'beforeShow');
316
+ extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
317
+ inst.lastVal = null;
318
+ $.timepicker._lastInput = input;
319
+
320
+ $.timepicker._setTimeFromField(inst);
321
+
322
+ // calculate default position
323
+ if ($.timepicker._inDialog) { input.value = ''; } // hide cursor
324
+ if (!$.timepicker._pos) { // position below input
325
+ $.timepicker._pos = $.timepicker._findPos(input);
326
+ $.timepicker._pos[1] += input.offsetHeight; // add the height
327
+ }
328
+ var isFixed = false;
329
+ $(input).parents().each(function () {
330
+ isFixed |= $(this).css('position') == 'fixed';
331
+ return !isFixed;
332
+ });
333
+ if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
334
+ $.timepicker._pos[0] -= document.documentElement.scrollLeft;
335
+ $.timepicker._pos[1] -= document.documentElement.scrollTop;
336
+ }
337
+
338
+ var offset = { left: $.timepicker._pos[0], top: $.timepicker._pos[1] };
339
+
340
+ $.timepicker._pos = null;
341
+ // determine sizing offscreen
342
+ inst.tpDiv.css({ position: 'absolute', display: 'block', top: '-1000px' });
343
+ $.timepicker._updateTimepicker(inst);
344
+
345
+
346
+ // position with the ui position utility, if loaded
347
+ if ( ( ! inst.inline ) && ( typeof $.ui.position == 'object' ) ) {
348
+ inst.tpDiv.position({
349
+ of: inst.input,
350
+ my: $.timepicker._get( inst, 'myPosition' ),
351
+ at: $.timepicker._get( inst, 'atPosition' ),
352
+ // offset: $( "#offset" ).val(),
353
+ // using: using,
354
+ collision: 'flip'
355
+ });
356
+ var offset = inst.tpDiv.offset();
357
+ $.timepicker._pos = [offset.top, offset.left];
358
+ }
359
+
360
+
361
+ // reset clicked state
362
+ inst._hoursClicked = false;
363
+ inst._minutesClicked = false;
364
+
365
+ // fix width for dynamic number of time pickers
366
+ // and adjust position before showing
367
+ offset = $.timepicker._checkOffset(inst, offset, isFixed);
368
+ inst.tpDiv.css({ position: ($.timepicker._inDialog && $.blockUI ?
369
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
370
+ left: offset.left + 'px', top: offset.top + 'px'
371
+ });
372
+ if ( ! inst.inline ) {
373
+ var showAnim = $.timepicker._get(inst, 'showAnim');
374
+ var duration = $.timepicker._get(inst, 'duration');
375
+ var zIndex = $.timepicker._get(inst, 'zIndex');
376
+ var postProcess = function () {
377
+ $.timepicker._timepickerShowing = true;
378
+ var borders = $.timepicker._getBorders(inst.tpDiv);
379
+ inst.tpDiv.find('iframe.ui-timepicker-cover'). // IE6- only
380
+ css({ left: -borders[0], top: -borders[1],
381
+ width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
382
+ });
383
+ };
384
+
385
+ // if not zIndex specified in options, use target zIndex + 1
386
+ if ( ! zIndex) {
387
+ zIndex = $(input).attr('zIndex') + 1;
388
+ }
389
+ inst.tpDiv.attr('zIndex', zIndex);
390
+ inst.tpDiv.css('zIndex', zIndex);
391
+
392
+ if ($.effects && $.effects[showAnim]) {
393
+ inst.tpDiv.show(showAnim, $.timepicker._get(inst, 'showOptions'), duration, postProcess);
394
+ }
395
+ else {
396
+ inst.tpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
397
+ }
398
+ if (!showAnim || !duration) { postProcess(); }
399
+ if (inst.input.is(':visible') && !inst.input.is(':disabled')) { inst.input.focus(); }
400
+ $.timepicker._curInst = inst;
401
+ }
402
+ },
403
+
404
+ /* Generate the time picker content. */
405
+ _updateTimepicker: function (inst) {
406
+ inst.tpDiv.empty().append(this._generateHTML(inst));
407
+ this._rebindDialogEvents(inst);
408
+
409
+ },
410
+
411
+ _rebindDialogEvents: function (inst) {
412
+ var borders = $.timepicker._getBorders(inst.tpDiv),
413
+ self = this;
414
+ inst.tpDiv
415
+ .find('iframe.ui-timepicker-cover') // IE6- only
416
+ .css({ left: -borders[0], top: -borders[1],
417
+ width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
418
+ })
419
+ .end()
420
+ // after the picker html is appended bind the click & double click events (faster in IE this way
421
+ // then letting the browser interpret the inline events)
422
+ // the binding for the minute cells also exists in _updateMinuteDisplay
423
+ .find('.ui-timepicker-minute-cell')
424
+ .bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectMinutes, this))
425
+ .bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectMinutes, this))
426
+ .end()
427
+ .find('.ui-timepicker-hour-cell')
428
+ .bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectHours, this))
429
+ .bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectHours, this))
430
+ .end()
431
+ .find('.ui-timepicker td a')
432
+ .bind('mouseout', function () {
433
+ $(this).removeClass('ui-state-hover');
434
+ if (this.className.indexOf('ui-timepicker-prev') != -1) $(this).removeClass('ui-timepicker-prev-hover');
435
+ if (this.className.indexOf('ui-timepicker-next') != -1) $(this).removeClass('ui-timepicker-next-hover');
436
+ })
437
+ .bind('mouseover', function () {
438
+ if ( ! self._isDisabledTimepicker(inst.inline ? inst.tpDiv.parent()[0] : inst.input[0])) {
439
+ $(this).parents('.ui-timepicker-calendar').find('a').removeClass('ui-state-hover');
440
+ $(this).addClass('ui-state-hover');
441
+ if (this.className.indexOf('ui-timepicker-prev') != -1) $(this).addClass('ui-timepicker-prev-hover');
442
+ if (this.className.indexOf('ui-timepicker-next') != -1) $(this).addClass('ui-timepicker-next-hover');
443
+ }
444
+ })
445
+ .end()
446
+ .find('.' + this._dayOverClass + ' a')
447
+ .trigger('mouseover')
448
+ .end();
449
+ },
450
+
451
+ /* Generate the HTML for the current state of the date picker. */
452
+ _generateHTML: function (inst) {
453
+
454
+ var h, m, row, col, html, hoursHtml, minutesHtml = '',
455
+ showPeriod = (this._get(inst, 'showPeriod') == true),
456
+ showPeriodLabels = (this._get(inst, 'showPeriodLabels') == true),
457
+ showLeadingZero = (this._get(inst, 'showLeadingZero') == true),
458
+ showHours = (this._get(inst, 'showHours') == true),
459
+ showMinutes = (this._get(inst, 'showMinutes') == true),
460
+ amPmText = this._get(inst, 'amPmText'),
461
+ rows = this._get(inst, 'rows'),
462
+ amRows = 0,
463
+ pmRows = 0,
464
+ amItems = 0,
465
+ pmItems = 0,
466
+ amFirstRow = 0,
467
+ pmFirstRow = 0,
468
+ hours = Array(),
469
+ hours_options = this._get(inst, 'hours'),
470
+ hoursPerRow = null,
471
+ hourCounter = 0,
472
+ hourLabel = this._get(inst, 'hourText');
473
+
474
+ // prepare all hours and minutes, makes it easier to distribute by rows
475
+ for (h = hours_options.starts; h <= hours_options.ends; h++) {
476
+ hours.push (h);
477
+ }
478
+ hoursPerRow = Math.ceil(hours.length / rows); // always round up
479
+
480
+ if (showPeriodLabels) {
481
+ for (hourCounter = 0; hourCounter < hours.length; hourCounter++) {
482
+ if (hours[hourCounter] < 12) {
483
+ amItems++;
484
+ }
485
+ else {
486
+ pmItems++;
487
+ }
488
+ }
489
+ hourCounter = 0;
490
+
491
+ amRows = Math.floor(amItems / hours.length * rows);
492
+ pmRows = Math.floor(pmItems / hours.length * rows);
493
+
494
+ // assign the extra row to the period that is more densly populated
495
+ if (rows != amRows + pmRows) {
496
+ // Make sure: AM Has Items and either PM Does Not, AM has no rows yet, or AM is more dense
497
+ if (amItems && (!pmItems || !amRows || (pmRows && amItems / amRows >= pmItems / pmRows))) {
498
+ amRows++;
499
+ } else {
500
+ pmRows++;
501
+ }
502
+ }
503
+ amFirstRow = Math.min(amRows, 1);
504
+ pmFirstRow = amRows + 1;
505
+ hoursPerRow = Math.ceil(Math.max(amItems / amRows, pmItems / pmRows));
506
+ }
507
+
508
+
509
+ html = '<table class="ui-timepicker-table ui-widget-content ui-corner-all"><tr>';
510
+
511
+ if (showHours) {
512
+
513
+ html += '<td class="ui-timepicker-hours">' +
514
+ '<div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
515
+ hourLabel +
516
+ '</div>' +
517
+ '<table class="ui-timepicker">';
518
+
519
+ for (row = 1; row <= rows; row++) {
520
+ html += '<tr>';
521
+ // AM
522
+ if (row == amFirstRow && showPeriodLabels) {
523
+ html += '<th rowspan="' + amRows.toString() + '" class="periods" scope="row">' + amPmText[0] + '</th>';
524
+ }
525
+ // PM
526
+ if (row == pmFirstRow && showPeriodLabels) {
527
+ html += '<th rowspan="' + pmRows.toString() + '" class="periods" scope="row">' + amPmText[1] + '</th>';
528
+ }
529
+ for (col = 1; col <= hoursPerRow; col++) {
530
+ if (showPeriodLabels && row < pmFirstRow && hours[hourCounter] >= 12) {
531
+ html += this._generateHTMLHourCell(inst, undefined, showPeriod, showLeadingZero);
532
+ } else {
533
+ html += this._generateHTMLHourCell(inst, hours[hourCounter], showPeriod, showLeadingZero);
534
+ hourCounter++;
535
+ }
536
+ }
537
+ html += '</tr>';
538
+ }
539
+ html += '</tr></table>' + // Close the hours cells table
540
+ '</td>'; // Close the Hour td
541
+ }
542
+
543
+ if (showMinutes) {
544
+ html += '<td class="ui-timepicker-minutes">';
545
+ html += this._generateHTMLMinutes(inst);
546
+ html += '</td>';
547
+ }
548
+
549
+ html += '</tr></table>';
550
+
551
+ /* IE6 IFRAME FIX (taken from datepicker 1.5.3, fixed in 0.1.2 */
552
+ html += ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
553
+ '<iframe src="javascript:false;" class="ui-timepicker-cover" frameborder="0"></iframe>' : '');
554
+
555
+ return html;
556
+ },
557
+
558
+ /* Special function that update the minutes selection in currently visible timepicker
559
+ * called on hour selection when onMinuteShow is defined */
560
+ _updateMinuteDisplay: function (inst) {
561
+ var newHtml = this._generateHTMLMinutes(inst);
562
+ inst.tpDiv.find('td.ui-timepicker-minutes').html(newHtml);
563
+ this._rebindDialogEvents(inst);
564
+ // after the picker html is appended bind the click & double click events (faster in IE this way
565
+ // then letting the browser interpret the inline events)
566
+ // yes I know, duplicate code, sorry
567
+ /* .find('.ui-timepicker-minute-cell')
568
+ .bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectMinutes, this))
569
+ .bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectMinutes, this));
570
+ */
571
+
572
+ },
573
+
574
+ /*
575
+ * Generate the minutes table
576
+ * This is separated from the _generateHTML function because is can be called separately (when hours changes)
577
+ */
578
+ _generateHTMLMinutes: function (inst) {
579
+
580
+ var m, row, html = '',
581
+ rows = this._get(inst, 'rows'),
582
+ minutes = Array(),
583
+ minutes_options = this._get(inst, 'minutes'),
584
+ minutesPerRow = null,
585
+ minuteCounter = 0,
586
+ showMinutesLeadingZero = (this._get(inst, 'showMinutesLeadingZero') == true),
587
+ onMinuteShow = this._get(inst, 'onMinuteShow'),
588
+ minuteLabel = this._get(inst, 'minuteText');
589
+
590
+ if ( ! minutes_options.starts) {
591
+ minutes_options.starts = 0;
592
+ }
593
+ if ( ! minutes_options.ends) {
594
+ minutes_options.ends = 59;
595
+ }
596
+ for (m = minutes_options.starts; m <= minutes_options.ends; m += minutes_options.interval) {
597
+ minutes.push(m);
598
+ }
599
+ minutesPerRow = Math.round(minutes.length / rows + 0.49); // always round up
600
+
601
+ /*
602
+ * The minutes table
603
+ */
604
+ // if currently selected minute is not enabled, we have a problem and need to select a new minute.
605
+ if (onMinuteShow &&
606
+ (onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours , inst.minutes]) == false) ) {
607
+ // loop minutes and select first available
608
+ for (minuteCounter = 0; minuteCounter < minutes.length; minuteCounter += 1) {
609
+ m = minutes[minuteCounter];
610
+ if (onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours, m])) {
611
+ inst.minutes = m;
612
+ break;
613
+ }
614
+ }
615
+ }
616
+
617
+
618
+
619
+ html += '<div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
620
+ minuteLabel +
621
+ '</div>' +
622
+ '<table class="ui-timepicker">';
623
+
624
+ minuteCounter = 0;
625
+ for (row = 1; row <= rows; row++) {
626
+ html += '<tr>';
627
+ while (minuteCounter < row * minutesPerRow) {
628
+ var m = minutes[minuteCounter];
629
+ var displayText = '';
630
+ if (m !== undefined ) {
631
+ displayText = (m < 10) && showMinutesLeadingZero ? "0" + m.toString() : m.toString();
632
+ }
633
+ html += this._generateHTMLMinuteCell(inst, m, displayText);
634
+ minuteCounter++;
635
+ }
636
+ html += '</tr>';
637
+ }
638
+
639
+ html += '</table>';
640
+
641
+ return html;
642
+ },
643
+
644
+ /* Generate the content of a "Hour" cell */
645
+ _generateHTMLHourCell: function (inst, hour, showPeriod, showLeadingZero) {
646
+
647
+ var displayHour = hour;
648
+ if ((hour > 12) && showPeriod) {
649
+ displayHour = hour - 12;
650
+ }
651
+ if ((displayHour == 0) && showPeriod) {
652
+ displayHour = 12;
653
+ }
654
+ if ((displayHour < 10) && showLeadingZero) {
655
+ displayHour = '0' + displayHour;
656
+ }
657
+
658
+ var html = "";
659
+ var enabled = true;
660
+ var onHourShow = this._get(inst, 'onHourShow'); //custom callback
661
+
662
+ if (hour == undefined) {
663
+ html = '<td><span class="ui-state-default ui-state-disabled">&nbsp;</span></td>';
664
+ return html;
665
+ }
666
+
667
+ if (onHourShow) {
668
+ enabled = onHourShow.apply((inst.input ? inst.input[0] : null), [hour]);
669
+ }
670
+
671
+ if (enabled) {
672
+ html = '<td class="ui-timepicker-hour-cell" data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-hour="' + hour.toString() + '">' +
673
+ '<a class="ui-state-default ' +
674
+ (hour == inst.hours ? 'ui-state-active' : '') +
675
+ '">' +
676
+ displayHour.toString() +
677
+ '</a></td>';
678
+ }
679
+ else {
680
+ html =
681
+ '<td>' +
682
+ '<span class="ui-state-default ui-state-disabled ' +
683
+ (hour == inst.hours ? ' ui-state-active ' : ' ') +
684
+ '">' +
685
+ displayHour.toString() +
686
+ '</span>' +
687
+ '</td>';
688
+ }
689
+ return html;
690
+ },
691
+
692
+ /* Generate the content of a "Hour" cell */
693
+ _generateHTMLMinuteCell: function (inst, minute, displayText) {
694
+ var html = "";
695
+ var enabled = true;
696
+ var onMinuteShow = this._get(inst, 'onMinuteShow'); //custom callback
697
+ if (onMinuteShow) {
698
+ //NEW: 2011-02-03 we should give the hour as a parameter as well!
699
+ enabled = onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours,minute]); //trigger callback
700
+ }
701
+
702
+ if (minute == undefined) {
703
+ html = '<td><span class="ui-state-default ui-state-disabled">&nbsp;</span></td>';
704
+ return html;
705
+ }
706
+
707
+ if (enabled) {
708
+ html = '<td class="ui-timepicker-minute-cell" data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-minute="' + minute.toString() + '" >' +
709
+ '<a class="ui-state-default ' +
710
+ (minute == inst.minutes ? 'ui-state-active' : '') +
711
+ '" >' +
712
+ displayText +
713
+ '</a></td>';
714
+ }
715
+ else {
716
+
717
+ html = '<td>' +
718
+ '<span class="ui-state-default ui-state-disabled" >' +
719
+ displayText +
720
+ '</span>' +
721
+ '</td>';
722
+ }
723
+ return html;
724
+ },
725
+
726
+
727
+ /* Enable the date picker to a jQuery selection.
728
+ @param target element - the target input field or division or span */
729
+ _enableTimepicker: function(target) {
730
+ var $target = $(target),
731
+ target_id = $target.attr('id'),
732
+ inst = $.data(target, PROP_NAME);
733
+
734
+ if (!$target.hasClass(this.markerClassName)) {
735
+ return;
736
+ }
737
+ var nodeName = target.nodeName.toLowerCase();
738
+ if (nodeName == 'input') {
739
+ target.disabled = false;
740
+ inst.trigger.filter('button').
741
+ each(function() { this.disabled = false; }).end();
742
+ }
743
+ else if (nodeName == 'div' || nodeName == 'span') {
744
+ var inline = $target.children('.' + this._inlineClass);
745
+ inline.children().removeClass('ui-state-disabled');
746
+ }
747
+ this._disabledInputs = $.map(this._disabledInputs,
748
+ function(value) { return (value == target_id ? null : value); }); // delete entry
749
+ },
750
+
751
+ /* Disable the time picker to a jQuery selection.
752
+ @param target element - the target input field or division or span */
753
+ _disableTimepicker: function(target) {
754
+ var $target = $(target);
755
+ var inst = $.data(target, PROP_NAME);
756
+ if (!$target.hasClass(this.markerClassName)) {
757
+ return;
758
+ }
759
+ var nodeName = target.nodeName.toLowerCase();
760
+ if (nodeName == 'input') {
761
+ target.disabled = true;
762
+
763
+ inst.trigger.filter('button').
764
+ each(function() { this.disabled = true; }).end();
765
+
766
+ }
767
+ else if (nodeName == 'div' || nodeName == 'span') {
768
+ var inline = $target.children('.' + this._inlineClass);
769
+ inline.children().addClass('ui-state-disabled');
770
+ }
771
+ this._disabledInputs = $.map(this._disabledInputs,
772
+ function(value) { return (value == target ? null : value); }); // delete entry
773
+ this._disabledInputs[this._disabledInputs.length] = $target.attr('id');
774
+ },
775
+
776
+ /* Is the first field in a jQuery collection disabled as a timepicker?
777
+ @param target_id element - the target input field or division or span
778
+ @return boolean - true if disabled, false if enabled */
779
+ _isDisabledTimepicker: function (target_id) {
780
+ if ( ! target_id) { return false; }
781
+ for (var i = 0; i < this._disabledInputs.length; i++) {
782
+ if (this._disabledInputs[i] == target_id) { return true; }
783
+ }
784
+ return false;
785
+ },
786
+
787
+ /* Check positioning to remain on screen. */
788
+ _checkOffset: function (inst, offset, isFixed) {
789
+ var tpWidth = inst.tpDiv.outerWidth();
790
+ var tpHeight = inst.tpDiv.outerHeight();
791
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
792
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
793
+ var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
794
+ var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
795
+
796
+ offset.left -= (this._get(inst, 'isRTL') ? (tpWidth - inputWidth) : 0);
797
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
798
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
799
+
800
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
801
+ offset.left -= Math.min(offset.left, (offset.left + tpWidth > viewWidth && viewWidth > tpWidth) ?
802
+ Math.abs(offset.left + tpWidth - viewWidth) : 0);
803
+ offset.top -= Math.min(offset.top, (offset.top + tpHeight > viewHeight && viewHeight > tpHeight) ?
804
+ Math.abs(tpHeight + inputHeight) : 0);
805
+
806
+ return offset;
807
+ },
808
+
809
+ /* Find an object's position on the screen. */
810
+ _findPos: function (obj) {
811
+ var inst = this._getInst(obj);
812
+ var isRTL = this._get(inst, 'isRTL');
813
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
814
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
815
+ }
816
+ var position = $(obj).offset();
817
+ return [position.left, position.top];
818
+ },
819
+
820
+ /* Retrieve the size of left and top borders for an element.
821
+ @param elem (jQuery object) the element of interest
822
+ @return (number[2]) the left and top borders */
823
+ _getBorders: function (elem) {
824
+ var convert = function (value) {
825
+ return { thin: 1, medium: 2, thick: 3}[value] || value;
826
+ };
827
+ return [parseFloat(convert(elem.css('border-left-width'))),
828
+ parseFloat(convert(elem.css('border-top-width')))];
829
+ },
830
+
831
+
832
+ /* Close time picker if clicked elsewhere. */
833
+ _checkExternalClick: function (event) {
834
+ if (!$.timepicker._curInst) { return; }
835
+ var $target = $(event.target);
836
+ if ($target[0].id != $.timepicker._mainDivId &&
837
+ $target.parents('#' + $.timepicker._mainDivId).length == 0 &&
838
+ !$target.hasClass($.timepicker.markerClassName) &&
839
+ !$target.hasClass($.timepicker._triggerClass) &&
840
+ $.timepicker._timepickerShowing && !($.timepicker._inDialog && $.blockUI))
841
+ $.timepicker._hideTimepicker();
842
+ },
843
+
844
+ /* Hide the time picker from view.
845
+ @param input element - the input field attached to the time picker */
846
+ _hideTimepicker: function (input) {
847
+ var inst = this._curInst;
848
+ if (!inst || (input && inst != $.data(input, PROP_NAME))) { return; }
849
+ if (this._timepickerShowing) {
850
+ var showAnim = this._get(inst, 'showAnim');
851
+ var duration = this._get(inst, 'duration');
852
+ var postProcess = function () {
853
+ $.timepicker._tidyDialog(inst);
854
+ this._curInst = null;
855
+ };
856
+ if ($.effects && $.effects[showAnim]) {
857
+ inst.tpDiv.hide(showAnim, $.timepicker._get(inst, 'showOptions'), duration, postProcess);
858
+ }
859
+ else {
860
+ inst.tpDiv[(showAnim == 'slideDown' ? 'slideUp' :
861
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
862
+ }
863
+ if (!showAnim) { postProcess(); }
864
+ var onClose = this._get(inst, 'onClose');
865
+ if (onClose) {
866
+ onClose.apply(
867
+ (inst.input ? inst.input[0] : null),
868
+ [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
869
+ }
870
+ this._timepickerShowing = false;
871
+ this._lastInput = null;
872
+ if (this._inDialog) {
873
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
874
+ if ($.blockUI) {
875
+ $.unblockUI();
876
+ $('body').append(this.tpDiv);
877
+ }
878
+ }
879
+ this._inDialog = false;
880
+ }
881
+ },
882
+
883
+ /* Tidy up after a dialog display. */
884
+ _tidyDialog: function (inst) {
885
+ inst.tpDiv.removeClass(this._dialogClass).unbind('.ui-timepicker');
886
+ },
887
+
888
+ /* Retrieve the instance data for the target control.
889
+ @param target element - the target input field or division or span
890
+ @return object - the associated instance data
891
+ @throws error if a jQuery problem getting data */
892
+ _getInst: function (target) {
893
+ try {
894
+ return $.data(target, PROP_NAME);
895
+ }
896
+ catch (err) {
897
+ throw 'Missing instance data for this timepicker';
898
+ }
899
+ },
900
+
901
+ /* Get a setting value, defaulting if necessary. */
902
+ _get: function (inst, name) {
903
+ return inst.settings[name] !== undefined ?
904
+ inst.settings[name] : this._defaults[name];
905
+ },
906
+
907
+ /* Parse existing time and initialise time picker. */
908
+ _setTimeFromField: function (inst) {
909
+ if (inst.input.val() == inst.lastVal) { return; }
910
+ var defaultTime = this._get(inst, 'defaultTime');
911
+
912
+ var timeToParse = defaultTime == 'now' ? this._getCurrentTimeRounded(inst) : defaultTime;
913
+ if ((inst.inline == false) && (inst.input.val() != '')) { timeToParse = inst.input.val() }
914
+
915
+ var timeVal = inst.lastVal = timeToParse;
916
+
917
+
918
+
919
+ if (timeToParse == '') {
920
+ inst.hours = -1;
921
+ inst.minutes = -1;
922
+ } else {
923
+ var time = this.parseTime(inst, timeVal);
924
+ inst.hours = time.hours;
925
+ inst.minutes = time.minutes;
926
+ }
927
+
928
+ $.timepicker._updateTimepicker(inst);
929
+ },
930
+ /* Set the dates for a jQuery selection.
931
+ @param target element - the target input field or division or span
932
+ @param date Date - the new date */
933
+ _setTimeTimepicker: function(target, time) {
934
+ var inst = this._getInst(target);
935
+ if (inst) {
936
+ this._setTime(inst, time);
937
+ this._updateTimepicker(inst);
938
+ this._updateAlternate(inst, time);
939
+ }
940
+ },
941
+
942
+ /* Set the time directly. */
943
+ _setTime: function(inst, time, noChange) {
944
+ var origHours = inst.hours;
945
+ var origMinutes = inst.minutes;
946
+ var time = this.parseTime(inst, time);
947
+ inst.hours = time.hours;
948
+ inst.minutes = time.minutes;
949
+
950
+ if ((origHours != inst.hours || origMinutes != inst.minuts) && !noChange) {
951
+ inst.input.trigger('change');
952
+ }
953
+ this._updateTimepicker(inst);
954
+ this._updateSelectedValue(inst);
955
+ },
956
+
957
+ /* Return the current time, ready to be parsed, rounded to the closest 5 minute */
958
+ _getCurrentTimeRounded: function (inst) {
959
+ var currentTime = new Date();
960
+ var timeSeparator = this._get(inst, 'timeSeparator');
961
+ // setting selected time , least priority first
962
+ var currentMinutes = currentTime.getMinutes()
963
+ // round to closest 5
964
+ currentMinutes = Math.round( currentMinutes / 5 ) * 5;
965
+
966
+ return currentTime.getHours().toString() + timeSeparator + currentMinutes.toString();
967
+ },
968
+
969
+ /*
970
+ * Pase a time string into hours and minutes
971
+ */
972
+ parseTime: function (inst, timeVal) {
973
+ var retVal = new Object();
974
+ retVal.hours = -1;
975
+ retVal.minutes = -1;
976
+
977
+ var timeSeparator = this._get(inst, 'timeSeparator'),
978
+ amPmText = this._get(inst, 'amPmText'),
979
+ showHours = this._get(inst, 'showHours'),
980
+ showMinutes = this._get(inst, 'showMinutes'),
981
+ showPeriod = (this._get(inst, 'showPeriod') == true),
982
+ p = timeVal.indexOf(timeSeparator);
983
+
984
+ // check if time separator found
985
+ if (p != -1) {
986
+ retVal.hours = parseInt(timeVal.substr(0, p), 10);
987
+ retVal.minutes = parseInt(timeVal.substr(p + 1), 10);
988
+ }
989
+ // check for hours only
990
+ else if ( (showHours) && ( ! showMinutes) ) {
991
+ retVal.hours = parseInt(timeVal, 10);
992
+ }
993
+ // check for minutes only
994
+ else if ( ( ! showHours) && (showMinutes) ) {
995
+ retVal.minutes = parseInt(timeVal, 10);
996
+ }
997
+
998
+ if (showHours) {
999
+ var timeValUpper = timeVal.toUpperCase();
1000
+ if ((retVal.hours < 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[1].toUpperCase()) != -1)) {
1001
+ retVal.hours += 12;
1002
+ }
1003
+ // fix for 12 AM
1004
+ if ((retVal.hours == 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[0].toUpperCase()) != -1)) {
1005
+ retVal.hours = 0;
1006
+ }
1007
+ }
1008
+
1009
+ return retVal;
1010
+ },
1011
+
1012
+
1013
+
1014
+ selectHours: function (event) {
1015
+ var $td = $(event.currentTarget),
1016
+ id = $td.attr("data-timepicker-instance-id"),
1017
+ newHours = $td.attr("data-hour"),
1018
+ fromDoubleClick = event.data.fromDoubleClick,
1019
+ $target = $(id),
1020
+ inst = this._getInst($target[0]),
1021
+ showMinutes = (this._get(inst, 'showMinutes') == true);
1022
+
1023
+ // don't select if disabled
1024
+ if ( $.timepicker._isDisabledTimepicker($target.attr('id')) ) { return false }
1025
+
1026
+ $td.parents('.ui-timepicker-hours:first').find('a').removeClass('ui-state-active');
1027
+ $td.children('a').addClass('ui-state-active');
1028
+ inst.hours = newHours;
1029
+
1030
+ // added for onMinuteShow callback
1031
+ var onMinuteShow = this._get(inst, 'onMinuteShow');
1032
+ if (onMinuteShow) {
1033
+ // this will trigger a callback on selected hour to make sure selected minute is allowed.
1034
+ this._updateMinuteDisplay(inst);
1035
+ }
1036
+
1037
+ this._updateSelectedValue(inst);
1038
+
1039
+ inst._hoursClicked = true;
1040
+ if ((inst._minutesClicked) || (fromDoubleClick) || (showMinutes == false)) {
1041
+ $.timepicker._hideTimepicker();
1042
+ }
1043
+ // return false because if used inline, prevent the url to change to a hashtag
1044
+ return false;
1045
+ },
1046
+
1047
+ selectMinutes: function (event) {
1048
+ var $td = $(event.currentTarget),
1049
+ id = $td.attr("data-timepicker-instance-id"),
1050
+ newMinutes = $td.attr("data-minute"),
1051
+ fromDoubleClick = event.data.fromDoubleClick,
1052
+ $target = $(id),
1053
+ inst = this._getInst($target[0]),
1054
+ showHours = (this._get(inst, 'showHours') == true);
1055
+
1056
+ // don't select if disabled
1057
+ if ( $.timepicker._isDisabledTimepicker($target.attr('id')) ) { return false }
1058
+
1059
+ $td.parents('.ui-timepicker-minutes:first').find('a').removeClass('ui-state-active');
1060
+ $td.children('a').addClass('ui-state-active');
1061
+
1062
+ inst.minutes = newMinutes;
1063
+ this._updateSelectedValue(inst);
1064
+
1065
+ inst._minutesClicked = true;
1066
+ if ((inst._hoursClicked) || (fromDoubleClick) || (showHours == false)) {
1067
+ $.timepicker._hideTimepicker();
1068
+ // return false because if used inline, prevent the url to change to a hashtag
1069
+ return false;
1070
+ }
1071
+
1072
+ // return false because if used inline, prevent the url to change to a hashtag
1073
+ return false;
1074
+ },
1075
+
1076
+ _updateSelectedValue: function (inst) {
1077
+ var newTime = this._getParsedTime(inst);
1078
+ if (inst.input) {
1079
+ inst.input.val(newTime);
1080
+ inst.input.trigger('change');
1081
+ }
1082
+ var onSelect = this._get(inst, 'onSelect');
1083
+ if (onSelect) { onSelect.apply((inst.input ? inst.input[0] : null), [newTime, inst]); } // trigger custom callback
1084
+ this._updateAlternate(inst, newTime);
1085
+ return newTime;
1086
+ },
1087
+
1088
+ /* this function process selected time and return it parsed according to instance options */
1089
+ _getParsedTime: function(inst) {
1090
+
1091
+ if ((inst.hours < 0) || (inst.hours > 23)) { inst.hours = 12; }
1092
+ if ((inst.minutes < 0) || (inst.minutes > 59)) { inst.minutes = 0; }
1093
+
1094
+ var period = "",
1095
+ showPeriod = (this._get(inst, 'showPeriod') == true),
1096
+ showLeadingZero = (this._get(inst, 'showLeadingZero') == true),
1097
+ showHours = (this._get(inst, 'showHours') == true),
1098
+ showMinutes = (this._get(inst, 'showMinutes') == true),
1099
+ amPmText = this._get(inst, 'amPmText'),
1100
+ selectedHours = inst.hours ? inst.hours : 0,
1101
+ selectedMinutes = inst.minutes ? inst.minutes : 0,
1102
+ displayHours = selectedHours ? selectedHours : 0,
1103
+ parsedTime = '';
1104
+
1105
+ if (showPeriod) {
1106
+ if (inst.hours == 0) {
1107
+ displayHours = 12;
1108
+ }
1109
+ if (inst.hours < 12) {
1110
+ period = amPmText[0];
1111
+ }
1112
+ else {
1113
+ period = amPmText[1];
1114
+ if (displayHours > 12) {
1115
+ displayHours -= 12;
1116
+ }
1117
+ }
1118
+ }
1119
+
1120
+ var h = displayHours.toString();
1121
+ if (showLeadingZero && (displayHours < 10)) { h = '0' + h; }
1122
+
1123
+ var m = selectedMinutes.toString();
1124
+ if (selectedMinutes < 10) { m = '0' + m; }
1125
+
1126
+ if (showHours) {
1127
+ parsedTime += h;
1128
+ }
1129
+ if (showHours && showMinutes) {
1130
+ parsedTime += this._get(inst, 'timeSeparator');
1131
+ }
1132
+ if (showMinutes) {
1133
+ parsedTime += m;
1134
+ }
1135
+ if (showHours) {
1136
+ if (period.length > 0) { parsedTime += this._get(inst, 'periodSeparator') + period; }
1137
+ }
1138
+
1139
+ return parsedTime;
1140
+ },
1141
+
1142
+ /* Update any alternate field to synchronise with the main field. */
1143
+ _updateAlternate: function(inst, newTime) {
1144
+ var altField = this._get(inst, 'altField');
1145
+ if (altField) { // update alternate field too
1146
+ $(altField).each(function(i,e) {
1147
+ $(e).val(newTime);
1148
+ });
1149
+ }
1150
+ },
1151
+
1152
+ /* This might look unused but it's called by the $.fn.timepicker function with param getTime */
1153
+ /* added v 0.2.3 - gitHub issue #5 - Thanks edanuff */
1154
+ _getTimeTimepicker : function(input) {
1155
+ var inst = this._getInst(input);
1156
+ return this._getParsedTime(inst);
1157
+ },
1158
+ _getHourTimepicker: function(input) {
1159
+ var inst = this._getInst(input);
1160
+ if ( inst == undefined) { return -1; }
1161
+ return inst.hours;
1162
+ },
1163
+ _getMinuteTimepicker: function(input) {
1164
+ var inst= this._getInst(input);
1165
+ if ( inst == undefined) { return -1; }
1166
+ return inst.minutes;
1167
+ }
1168
+
1169
+ });
1170
+
1171
+
1172
+
1173
+ /* Invoke the timepicker functionality.
1174
+ @param options string - a command, optionally followed by additional parameters or
1175
+ Object - settings for attaching new timepicker functionality
1176
+ @return jQuery object */
1177
+ $.fn.timepicker = function (options) {
1178
+
1179
+ /* Initialise the date picker. */
1180
+ if (!$.timepicker.initialized) {
1181
+ $(document).mousedown($.timepicker._checkExternalClick).
1182
+ find('body').append($.timepicker.tpDiv);
1183
+ $.timepicker.initialized = true;
1184
+ }
1185
+
1186
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
1187
+ if (typeof options == 'string' && (options == 'getTime' || options == 'getHour' || options == 'getMinute' ))
1188
+ return $.timepicker['_' + options + 'Timepicker'].
1189
+ apply($.timepicker, [this[0]].concat(otherArgs));
1190
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
1191
+ return $.timepicker['_' + options + 'Timepicker'].
1192
+ apply($.timepicker, [this[0]].concat(otherArgs));
1193
+ return this.each(function () {
1194
+ typeof options == 'string' ?
1195
+ $.timepicker['_' + options + 'Timepicker'].
1196
+ apply($.timepicker, [this].concat(otherArgs)) :
1197
+ $.timepicker._attachTimepicker(this, options);
1198
+ });
1199
+ };
1200
+
1201
+ /* jQuery extend now ignores nulls! */
1202
+ function extendRemove(target, props) {
1203
+ $.extend(target, props);
1204
+ for (var name in props)
1205
+ if (props[name] == null || props[name] == undefined)
1206
+ target[name] = props[name];
1207
+ return target;
1208
+ };
1209
+
1210
+ $.timepicker = new Timepicker(); // singleton instance
1211
+ $.timepicker.initialized = false;
1212
+ $.timepicker.uuid = new Date().getTime();
1213
+ $.timepicker.version = "0.2.5";
1214
+
1215
+ // Workaround for #4055
1216
+ // Add another global to avoid noConflict issues with inline event handlers
1217
+ window['TP_jQuery_' + tpuuid] = $;
1218
+
1219
+ })(jQuery);