serum-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (340) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +42 -0
  6. data/LICENSE +22 -0
  7. data/README.md +40 -0
  8. data/bin/serum-rails +13 -0
  9. data/lib/serum/rails/app.rb +50 -0
  10. data/lib/serum/rails/code_scanner.rb +49 -0
  11. data/lib/serum/rails/metrics.rb +118 -0
  12. data/lib/serum/rails/type_selection.rb +31 -0
  13. data/lib/serum/rails/version.rb +7 -0
  14. data/lib/serum-rails.rb +5 -0
  15. data/serum-rails.gemspec +23 -0
  16. data/spec/serum/rails/metrics_spec.rb +87 -0
  17. data/spec/spec_helper.rb +80 -0
  18. data/spec/test_app/Capfile +4 -0
  19. data/spec/test_app/Gemfile +54 -0
  20. data/spec/test_app/Gemfile.lock +163 -0
  21. data/spec/test_app/Rakefile +11 -0
  22. data/spec/test_app/app/controllers/admin/categories_controller.rb +17 -0
  23. data/spec/test_app/app/controllers/admin/users_controller.rb +30 -0
  24. data/spec/test_app/app/controllers/application_controller/i18n_trait.rb +24 -0
  25. data/spec/test_app/app/controllers/application_controller/navigation_trait.rb +19 -0
  26. data/spec/test_app/app/controllers/application_controller/security_trait/disabled_clearance_accounts_trait.rb +41 -0
  27. data/spec/test_app/app/controllers/application_controller/security_trait.rb +65 -0
  28. data/spec/test_app/app/controllers/application_controller.rb +13 -0
  29. data/spec/test_app/app/controllers/conferences_controller.rb +67 -0
  30. data/spec/test_app/app/controllers/friendship_requests_controller.rb +31 -0
  31. data/spec/test_app/app/controllers/invitations_controller.rb +39 -0
  32. data/spec/test_app/app/controllers/members_controller.rb +21 -0
  33. data/spec/test_app/app/controllers/passwords_controller.rb +33 -0
  34. data/spec/test_app/app/controllers/sessions_controller.rb +17 -0
  35. data/spec/test_app/app/controllers/shared/boring_controller_trait/deletable_trait.rb +23 -0
  36. data/spec/test_app/app/controllers/shared/boring_controller_trait/flash_trait.rb +23 -0
  37. data/spec/test_app/app/controllers/shared/boring_controller_trait/helpers_trait.rb +35 -0
  38. data/spec/test_app/app/controllers/shared/boring_controller_trait/index_trait.rb +39 -0
  39. data/spec/test_app/app/controllers/shared/boring_controller_trait/log_changes_trait.rb +18 -0
  40. data/spec/test_app/app/controllers/shared/boring_controller_trait.rb +16 -0
  41. data/spec/test_app/app/controllers/users_controller.rb +49 -0
  42. data/spec/test_app/app/controllers/ws/api_controller/formatters_trait.rb +91 -0
  43. data/spec/test_app/app/controllers/ws/api_controller/parsers_trait.rb +59 -0
  44. data/spec/test_app/app/controllers/ws/api_controller.rb +70 -0
  45. data/spec/test_app/app/controllers/ws/attendees_controller.rb +43 -0
  46. data/spec/test_app/app/controllers/ws/categories_controller.rb +30 -0
  47. data/spec/test_app/app/controllers/ws/conferences_controller.rb +62 -0
  48. data/spec/test_app/app/controllers/ws/contacts_controller.rb +41 -0
  49. data/spec/test_app/app/controllers/ws/factory_controller.rb +45 -0
  50. data/spec/test_app/app/controllers/ws/members_controller.rb +34 -0
  51. data/spec/test_app/app/controllers/ws/series_controller.rb +19 -0
  52. data/spec/test_app/app/controllers/ws/tests_controller.rb +23 -0
  53. data/spec/test_app/app/helpers/application_helper.rb +180 -0
  54. data/spec/test_app/app/helpers/mail_helper.rb +9 -0
  55. data/spec/test_app/app/helpers/tags_helper.rb +16 -0
  56. data/spec/test_app/app/helpers/user_helper.rb +23 -0
  57. data/spec/test_app/app/models/attendance.rb +11 -0
  58. data/spec/test_app/app/models/category/ancestry_trait.rb +23 -0
  59. data/spec/test_app/app/models/category.rb +25 -0
  60. data/spec/test_app/app/models/conference/attendance_trait.rb +23 -0
  61. data/spec/test_app/app/models/conference/categories_trait.rb +26 -0
  62. data/spec/test_app/app/models/conference/icalendar_trait.rb +36 -0
  63. data/spec/test_app/app/models/conference/search_trait.rb +44 -0
  64. data/spec/test_app/app/models/conference.rb +24 -0
  65. data/spec/test_app/app/models/conference_category.rb +6 -0
  66. data/spec/test_app/app/models/conference_search.rb +51 -0
  67. data/spec/test_app/app/models/error.rb +25 -0
  68. data/spec/test_app/app/models/friendship.rb +14 -0
  69. data/spec/test_app/app/models/friendship_request.rb +19 -0
  70. data/spec/test_app/app/models/invitation.rb +38 -0
  71. data/spec/test_app/app/models/member_search.rb +18 -0
  72. data/spec/test_app/app/models/navigation.rb +38 -0
  73. data/spec/test_app/app/models/patterns.rb +14 -0
  74. data/spec/test_app/app/models/permissions.rb +106 -0
  75. data/spec/test_app/app/models/shared/afterlife_trait.rb +18 -0
  76. data/spec/test_app/app/models/shared/choice_trait.rb +37 -0
  77. data/spec/test_app/app/models/shared/deletable_trait.rb +8 -0
  78. data/spec/test_app/app/models/shared/flag_trait.rb +30 -0
  79. data/spec/test_app/app/models/shared/indestructible_trait.rb +19 -0
  80. data/spec/test_app/app/models/shared/list_field_trait.rb +70 -0
  81. data/spec/test_app/app/models/shared/person_name_trait.rb +25 -0
  82. data/spec/test_app/app/models/shared/searchable_trait.rb +71 -0
  83. data/spec/test_app/app/models/shared/sortable_trait.rb +24 -0
  84. data/spec/test_app/app/models/user/authentication_trait.rb +33 -0
  85. data/spec/test_app/app/models/user/authorization_trait.rb +17 -0
  86. data/spec/test_app/app/models/user/friends_trait.rb +42 -0
  87. data/spec/test_app/app/models/user/search_trait.rb +43 -0
  88. data/spec/test_app/app/models/user.rb +61 -0
  89. data/spec/test_app/app/models/util.rb +19 -0
  90. data/spec/test_app/app/views/admin/categories/_form.html.haml +18 -0
  91. data/spec/test_app/app/views/admin/categories/_list.html.haml +17 -0
  92. data/spec/test_app/app/views/admin/categories/edit.html.haml +6 -0
  93. data/spec/test_app/app/views/admin/categories/index.html.haml +6 -0
  94. data/spec/test_app/app/views/admin/categories/new.html.haml +6 -0
  95. data/spec/test_app/app/views/admin/categories/show.html.haml +27 -0
  96. data/spec/test_app/app/views/admin/users/_form.html.haml +49 -0
  97. data/spec/test_app/app/views/admin/users/_head.html.haml +5 -0
  98. data/spec/test_app/app/views/admin/users/_list.html.haml +20 -0
  99. data/spec/test_app/app/views/admin/users/_search.html.haml +9 -0
  100. data/spec/test_app/app/views/admin/users/deleted.html.haml +5 -0
  101. data/spec/test_app/app/views/admin/users/edit.html.haml +5 -0
  102. data/spec/test_app/app/views/admin/users/index.html.haml +7 -0
  103. data/spec/test_app/app/views/admin/users/new.html.haml +6 -0
  104. data/spec/test_app/app/views/clearance_mailer/change_password.erb +9 -0
  105. data/spec/test_app/app/views/conferences/_categories_list.html.haml +8 -0
  106. data/spec/test_app/app/views/conferences/_form.html.haml +32 -0
  107. data/spec/test_app/app/views/conferences/_head.html.haml +4 -0
  108. data/spec/test_app/app/views/conferences/_list.html.haml +22 -0
  109. data/spec/test_app/app/views/conferences/_search.html.haml +24 -0
  110. data/spec/test_app/app/views/conferences/edit.html.haml +8 -0
  111. data/spec/test_app/app/views/conferences/index.html.haml +22 -0
  112. data/spec/test_app/app/views/conferences/new.html.haml +9 -0
  113. data/spec/test_app/app/views/conferences/search.html.haml +7 -0
  114. data/spec/test_app/app/views/conferences/show.html.haml +78 -0
  115. data/spec/test_app/app/views/invitations/index.html.haml +26 -0
  116. data/spec/test_app/app/views/invitations/new.html.haml +22 -0
  117. data/spec/test_app/app/views/layouts/_flashes.html.haml +13 -0
  118. data/spec/test_app/app/views/layouts/_javascript_requirement.html.haml +8 -0
  119. data/spec/test_app/app/views/layouts/_javascripts.html.haml +4 -0
  120. data/spec/test_app/app/views/layouts/_notifications.html.haml +11 -0
  121. data/spec/test_app/app/views/layouts/_session_navigation.html.haml +12 -0
  122. data/spec/test_app/app/views/layouts/_stylesheets.html.haml +6 -0
  123. data/spec/test_app/app/views/layouts/screen.html.haml +30 -0
  124. data/spec/test_app/app/views/members/index.html.haml +40 -0
  125. data/spec/test_app/app/views/passwords/edit.html.haml +21 -0
  126. data/spec/test_app/app/views/passwords/new.html.haml +14 -0
  127. data/spec/test_app/app/views/sessions/new.html.haml +19 -0
  128. data/spec/test_app/app/views/users/_form.html.haml +45 -0
  129. data/spec/test_app/app/views/users/_head.html.haml +3 -0
  130. data/spec/test_app/app/views/users/edit.html.haml +5 -0
  131. data/spec/test_app/app/views/users/new.html.haml +6 -0
  132. data/spec/test_app/app/views/users/show.html.haml +49 -0
  133. data/spec/test_app/assets/data.json +981 -0
  134. data/spec/test_app/config/boot.rb +125 -0
  135. data/spec/test_app/config/cucumber.yml +8 -0
  136. data/spec/test_app/config/database.sample.yml +24 -0
  137. data/spec/test_app/config/deploy/production.rb +9 -0
  138. data/spec/test_app/config/deploy.rb +100 -0
  139. data/spec/test_app/config/environment.rb +27 -0
  140. data/spec/test_app/config/environments/cucumber.rb +28 -0
  141. data/spec/test_app/config/environments/development.rb +22 -0
  142. data/spec/test_app/config/environments/production.rb +35 -0
  143. data/spec/test_app/config/environments/test.rb +30 -0
  144. data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
  145. data/spec/test_app/config/initializers/clearance.rb +5 -0
  146. data/spec/test_app/config/initializers/collect_hash.rb +23 -0
  147. data/spec/test_app/config/initializers/collection_path_with_params.rb +18 -0
  148. data/spec/test_app/config/initializers/cookie_verification_secret.rb +10 -0
  149. data/spec/test_app/config/initializers/form_builder.rb +166 -0
  150. data/spec/test_app/config/initializers/inflections.rb +10 -0
  151. data/spec/test_app/config/initializers/invert_ordered_hash.rb +12 -0
  152. data/spec/test_app/config/initializers/localize_textfield_input_for_numbers.rb +30 -0
  153. data/spec/test_app/config/initializers/mime_types.rb +7 -0
  154. data/spec/test_app/config/initializers/new_rails_defaults.rb +21 -0
  155. data/spec/test_app/config/initializers/preload_associations.rb +7 -0
  156. data/spec/test_app/config/initializers/query_diet.rb +6 -0
  157. data/spec/test_app/config/initializers/saner_field_with_errors.rb +5 -0
  158. data/spec/test_app/config/initializers/session_store.rb +18 -0
  159. data/spec/test_app/config/locales/en.yml +231 -0
  160. data/spec/test_app/config/preinitializer.rb +22 -0
  161. data/spec/test_app/config/routes.rb +47 -0
  162. data/spec/test_app/db/migrate/20110114164517_initial_tables.rb +52 -0
  163. data/spec/test_app/db/migrate/20110118090858_add_profile_fields_to_user.rb +15 -0
  164. data/spec/test_app/db/migrate/20110118092741_create_conference.rb +20 -0
  165. data/spec/test_app/db/migrate/20110118093503_create_category.rb +17 -0
  166. data/spec/test_app/db/migrate/20110118104438_create_conference_category.rb +16 -0
  167. data/spec/test_app/db/migrate/20110118105959_create_attendance.rb +17 -0
  168. data/spec/test_app/db/migrate/20110118122324_create_friendship_requests.rb +15 -0
  169. data/spec/test_app/db/migrate/20110118162436_create_invitation.rb +16 -0
  170. data/spec/test_app/db/migrate/20110118170347_create_friendships.rb +15 -0
  171. data/spec/test_app/db/migrate/20110118193528_add_timestamps_to_conference.rb +12 -0
  172. data/spec/test_app/db/migrate/20110119075012_set_unique_index_on_username_for_user.rb +11 -0
  173. data/spec/test_app/db/migrate/20110119093458_remove_first_and_last_name_from_user.rb +12 -0
  174. data/spec/test_app/db/migrate/20110119110857_add_missing_indexes.rb +23 -0
  175. data/spec/test_app/db/migrate/20110119115751_add_uniqueness_of_name_to_category.rb +9 -0
  176. data/spec/test_app/db/seeds.rb +5 -0
  177. data/spec/test_app/lib/scripts/create_many_users_sql.rb +14 -0
  178. data/spec/test_app/lib/tasks/cucumber.rake +53 -0
  179. data/spec/test_app/lib/tasks/pending_migrations.rake +24 -0
  180. data/spec/test_app/lib/tasks/rcov.rake +42 -0
  181. data/spec/test_app/lib/tasks/rspec.rake +144 -0
  182. data/spec/test_app/public/404.html +30 -0
  183. data/spec/test_app/public/422.html +30 -0
  184. data/spec/test_app/public/500.html +30 -0
  185. data/spec/test_app/public/favicon.ico +0 -0
  186. data/spec/test_app/public/images/ajax-loader.gif +0 -0
  187. data/spec/test_app/public/images/icons/balloon-quotation.png +0 -0
  188. data/spec/test_app/public/images/icons/balloon-sound.png +0 -0
  189. data/spec/test_app/public/images/icons/balloon.png +0 -0
  190. data/spec/test_app/public/images/icons/bell.png +0 -0
  191. data/spec/test_app/public/images/icons/bin.png +0 -0
  192. data/spec/test_app/public/images/icons/bookmark.png +0 -0
  193. data/spec/test_app/public/images/icons/cake.png +0 -0
  194. data/spec/test_app/public/images/icons/calendar-blue.png +0 -0
  195. data/spec/test_app/public/images/icons/calendar-month.png +0 -0
  196. data/spec/test_app/public/images/icons/calendar-month_light.png +0 -0
  197. data/spec/test_app/public/images/icons/calendar-select.png +0 -0
  198. data/spec/test_app/public/images/icons/card-address.png +0 -0
  199. data/spec/test_app/public/images/icons/cards-address.png +0 -0
  200. data/spec/test_app/public/images/icons/cross-script.png +0 -0
  201. data/spec/test_app/public/images/icons/cross-small.png +0 -0
  202. data/spec/test_app/public/images/icons/cross.png +0 -0
  203. data/spec/test_app/public/images/icons/crown-silver.png +0 -0
  204. data/spec/test_app/public/images/icons/crown.png +0 -0
  205. data/spec/test_app/public/images/icons/dashboard.png +0 -0
  206. data/spec/test_app/public/images/icons/document-list.png +0 -0
  207. data/spec/test_app/public/images/icons/document-node.png +0 -0
  208. data/spec/test_app/public/images/icons/document-number.png +0 -0
  209. data/spec/test_app/public/images/icons/document-stamp.png +0 -0
  210. data/spec/test_app/public/images/icons/document-task.png +0 -0
  211. data/spec/test_app/public/images/icons/document-text.png +0 -0
  212. data/spec/test_app/public/images/icons/fire.png +0 -0
  213. data/spec/test_app/public/images/icons/folder-medium.png +0 -0
  214. data/spec/test_app/public/images/icons/folder.png +0 -0
  215. data/spec/test_app/public/images/icons/gear.png +0 -0
  216. data/spec/test_app/public/images/icons/globe-green.png +0 -0
  217. data/spec/test_app/public/images/icons/globe-green_light.png +0 -0
  218. data/spec/test_app/public/images/icons/globe-medium-green.png +0 -0
  219. data/spec/test_app/public/images/icons/heart-break.png +0 -0
  220. data/spec/test_app/public/images/icons/heart.png +0 -0
  221. data/spec/test_app/public/images/icons/images-flickr.png +0 -0
  222. data/spec/test_app/public/images/icons/information-balloon.png +0 -0
  223. data/spec/test_app/public/images/icons/key.png +0 -0
  224. data/spec/test_app/public/images/icons/light-bulb.png +0 -0
  225. data/spec/test_app/public/images/icons/lock--exclamation.png +0 -0
  226. data/spec/test_app/public/images/icons/lock.png +0 -0
  227. data/spec/test_app/public/images/icons/magnifier-medium.png +0 -0
  228. data/spec/test_app/public/images/icons/magnifier.png +0 -0
  229. data/spec/test_app/public/images/icons/mail.png +0 -0
  230. data/spec/test_app/public/images/icons/paper-clip-small.png +0 -0
  231. data/spec/test_app/public/images/icons/paper-clip.png +0 -0
  232. data/spec/test_app/public/images/icons/pencil.png +0 -0
  233. data/spec/test_app/public/images/icons/plus-circle.png +0 -0
  234. data/spec/test_app/public/images/icons/plus-small.png +0 -0
  235. data/spec/test_app/public/images/icons/plus.png +0 -0
  236. data/spec/test_app/public/images/icons/printer.png +0 -0
  237. data/spec/test_app/public/images/icons/question-balloon.png +0 -0
  238. data/spec/test_app/public/images/icons/question-white.png +0 -0
  239. data/spec/test_app/public/images/icons/question.png +0 -0
  240. data/spec/test_app/public/images/icons/quill.png +0 -0
  241. data/spec/test_app/public/images/icons/robot.png +0 -0
  242. data/spec/test_app/public/images/icons/ruby_16.png +0 -0
  243. data/spec/test_app/public/images/icons/ruby_2_16.png +0 -0
  244. data/spec/test_app/public/images/icons/ruby_32.png +0 -0
  245. data/spec/test_app/public/images/icons/show.png +0 -0
  246. data/spec/test_app/public/images/icons/star.png +0 -0
  247. data/spec/test_app/public/images/icons/sticky-note-text.png +0 -0
  248. data/spec/test_app/public/images/icons/telephone-fax.png +0 -0
  249. data/spec/test_app/public/images/icons/telephone-fax_light.png +0 -0
  250. data/spec/test_app/public/images/icons/telephone.png +0 -0
  251. data/spec/test_app/public/images/icons/telephone_light.png +0 -0
  252. data/spec/test_app/public/images/icons/thumb-up.png +0 -0
  253. data/spec/test_app/public/images/icons/thumb.png +0 -0
  254. data/spec/test_app/public/images/icons/tick.png +0 -0
  255. data/spec/test_app/public/images/icons/trophy-silver.png +0 -0
  256. data/spec/test_app/public/images/icons/trophy.png +0 -0
  257. data/spec/test_app/public/images/icons/user-gray.png +0 -0
  258. data/spec/test_app/public/images/icons/user-gray_gray.png +0 -0
  259. data/spec/test_app/public/images/icons/user-medium.png +0 -0
  260. data/spec/test_app/public/images/icons/user-red.png +0 -0
  261. data/spec/test_app/public/images/icons/users.png +0 -0
  262. data/spec/test_app/public/images/icons/users_gray.png +0 -0
  263. data/spec/test_app/public/images/icons/xfn.png +0 -0
  264. data/spec/test_app/public/images/legend_bg.png +0 -0
  265. data/spec/test_app/public/images/poshytip/tip-deepgray.png +0 -0
  266. data/spec/test_app/public/images/poshytip/tip-deepgray_arrows.png +0 -0
  267. data/spec/test_app/public/images/stripes_bottom_dark.png +0 -0
  268. data/spec/test_app/public/images/stripes_top_dark.png +0 -0
  269. data/spec/test_app/public/images/ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  270. data/spec/test_app/public/images/ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  271. data/spec/test_app/public/images/ui/ui-bg_flat_10_000000_40x100.png +0 -0
  272. data/spec/test_app/public/images/ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  273. data/spec/test_app/public/images/ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  274. data/spec/test_app/public/images/ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  275. data/spec/test_app/public/images/ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  276. data/spec/test_app/public/images/ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  277. data/spec/test_app/public/images/ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  278. data/spec/test_app/public/images/ui/ui-icons_222222_256x240.png +0 -0
  279. data/spec/test_app/public/images/ui/ui-icons_228ef1_256x240.png +0 -0
  280. data/spec/test_app/public/images/ui/ui-icons_ef8c08_256x240.png +0 -0
  281. data/spec/test_app/public/images/ui/ui-icons_ffd27a_256x240.png +0 -0
  282. data/spec/test_app/public/images/ui/ui-icons_ffffff_256x240.png +0 -0
  283. data/spec/test_app/public/javascripts/application.js +175 -0
  284. data/spec/test_app/public/javascripts/lib/jquery-1.4.2.min.js +154 -0
  285. data/spec/test_app/public/javascripts/lib/jquery-ui-1.8.5.custom.min.js +249 -0
  286. data/spec/test_app/public/javascripts/lib/jquery-ui-1.8.5.custom.min.txt +9 -0
  287. data/spec/test_app/public/javascripts/lib/jquery-ui-timepicker-addon.js +682 -0
  288. data/spec/test_app/public/javascripts/lib/jquery-ui-timepicker-addon.min.js +22 -0
  289. data/spec/test_app/public/javascripts/lib/jquery.elastic.js +6 -0
  290. data/spec/test_app/public/javascripts/lib/jquery.elastic.performance.js +128 -0
  291. data/spec/test_app/public/javascripts/lib/jquery.elastic.source.js +117 -0
  292. data/spec/test_app/public/javascripts/lib/jquery.poshytip.js +414 -0
  293. data/spec/test_app/public/javascripts/lib/jquery.poshytip.min.js +7 -0
  294. data/spec/test_app/public/javascripts/lib/jquery.ui.datepicker-de.js +23 -0
  295. data/spec/test_app/public/javascripts/lib/jrails.js +1 -0
  296. data/spec/test_app/public/javascripts/lib/multiple-autocomplete.js +39 -0
  297. data/spec/test_app/public/javascripts/lib/underscore-min.js +17 -0
  298. data/spec/test_app/public/javascripts/lib/underscore.js +704 -0
  299. data/spec/test_app/public/robots.txt +5 -0
  300. data/spec/test_app/public/stylesheets/lib/PIE.htc +77 -0
  301. data/spec/test_app/public/stylesheets/lib/PIE_uncompressed.htc +3064 -0
  302. data/spec/test_app/public/stylesheets/lib/jquery-ui-timepicker-addon.css +11 -0
  303. data/spec/test_app/public/stylesheets/lib/poshytip/tip-darkgray/tip-darkgray.css +62 -0
  304. data/spec/test_app/public/stylesheets/lib/poshytip/tip-darkgray/tip-darkgray.png +0 -0
  305. data/spec/test_app/public/stylesheets/lib/poshytip/tip-darkgray/tip-darkgray_arrows.png +0 -0
  306. data/spec/test_app/public/stylesheets/lib/poshytip/tip-deepgray/tip-deepgray.css +64 -0
  307. data/spec/test_app/public/stylesheets/lib/poshytip/tip-green/tip-green.css +57 -0
  308. data/spec/test_app/public/stylesheets/lib/poshytip/tip-green/tip-green_arrows.gif +0 -0
  309. data/spec/test_app/public/stylesheets/lib/poshytip/tip-skyblue/tip-skyblue.css +58 -0
  310. data/spec/test_app/public/stylesheets/lib/poshytip/tip-skyblue/tip-skyblue.png +0 -0
  311. data/spec/test_app/public/stylesheets/lib/poshytip/tip-skyblue/tip-skyblue_arrows.png +0 -0
  312. data/spec/test_app/public/stylesheets/lib/poshytip/tip-twitter/tip-twitter.css +59 -0
  313. data/spec/test_app/public/stylesheets/lib/poshytip/tip-twitter/tip-twitter_arrows.gif +0 -0
  314. data/spec/test_app/public/stylesheets/lib/poshytip/tip-violet/tip-violet.css +60 -0
  315. data/spec/test_app/public/stylesheets/lib/poshytip/tip-violet/tip-violet.png +0 -0
  316. data/spec/test_app/public/stylesheets/lib/poshytip/tip-violet/tip-violet_arrows.png +0 -0
  317. data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellow/tip-yellow.css +60 -0
  318. data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellow/tip-yellow.png +0 -0
  319. data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellow/tip-yellow_arrows.png +0 -0
  320. data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellowsimple/tip-yellowsimple.css +60 -0
  321. data/spec/test_app/public/stylesheets/lib/poshytip/tip-yellowsimple/tip-yellowsimple_arrows.gif +0 -0
  322. data/spec/test_app/public/stylesheets/lib/ui-lightness/jquery-ui-1.8.5.custom.css +459 -0
  323. data/spec/test_app/public/stylesheets/sass/_mixins.sass +79 -0
  324. data/spec/test_app/public/stylesheets/sass/_reset.sass +40 -0
  325. data/spec/test_app/public/stylesheets/sass/print.sass +22 -0
  326. data/spec/test_app/public/stylesheets/sass/screen.sass +866 -0
  327. data/spec/test_app/script/about +4 -0
  328. data/spec/test_app/script/autospec +6 -0
  329. data/spec/test_app/script/console +3 -0
  330. data/spec/test_app/script/cucumber +10 -0
  331. data/spec/test_app/script/dbconsole +3 -0
  332. data/spec/test_app/script/destroy +3 -0
  333. data/spec/test_app/script/generate +3 -0
  334. data/spec/test_app/script/performance/benchmarker +3 -0
  335. data/spec/test_app/script/performance/profiler +3 -0
  336. data/spec/test_app/script/plugin +3 -0
  337. data/spec/test_app/script/runner +3 -0
  338. data/spec/test_app/script/server +3 -0
  339. data/spec/test_app/script/spec +10 -0
  340. metadata +748 -0
@@ -0,0 +1,682 @@
1
+ /*
2
+ * jQuery timepicker addon
3
+ * By: Trent Richardson [http://trentrichardson.com]
4
+ * Version 0.7
5
+ * Last Modified: 10/7/2010
6
+ *
7
+ * Copyright 2010 Trent Richardson
8
+ * Dual licensed under the MIT and GPL licenses.
9
+ * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
10
+ * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
11
+ *
12
+ * HERES THE CSS:
13
+ * .ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; }
14
+ * .ui-timepicker-div dl{ text-align: left; }
15
+ * .ui-timepicker-div dl dt{ height: 25px; }
16
+ * .ui-timepicker-div dl dd{ margin: -25px 0 10px 65px; }
17
+ * .ui-timepicker-div .ui_tpicker_hour div { padding-right: 2px; }
18
+ * .ui-timepicker-div .ui_tpicker_minute div { padding-right: 6px; }
19
+ * .ui-timepicker-div .ui_tpicker_second div { padding-right: 6px; }
20
+ * .ui-timepicker-div td { font-size: 90%; }
21
+ */
22
+
23
+ (function($) {
24
+ function Timepicker(singleton) {
25
+ if(typeof(singleton) === 'boolean' && singleton == true) {
26
+ this.regional = []; // Available regional settings, indexed by language code
27
+ this.regional[''] = { // Default regional settings
28
+ currentText: 'Now',
29
+ ampm: false,
30
+ timeFormat: 'hh:mm tt',
31
+ timeOnlyTitle: 'Choose Time',
32
+ timeText: 'Time',
33
+ hourText: 'Hour',
34
+ minuteText: 'Minute',
35
+ secondText: 'Second'
36
+ };
37
+ this.defaults = { // Global defaults for all the datetime picker instances
38
+ showButtonPanel: true,
39
+ timeOnly: false,
40
+ showHour: true,
41
+ showMinute: true,
42
+ showSecond: false,
43
+ showTime: true,
44
+ stepHour: 0.05,
45
+ stepMinute: 0.05,
46
+ stepSecond: 0.05,
47
+ hour: 0,
48
+ minute: 0,
49
+ second: 0,
50
+ hourMin: 0,
51
+ minuteMin: 0,
52
+ secondMin: 0,
53
+ hourMax: 23,
54
+ minuteMax: 59,
55
+ secondMax: 59,
56
+ hourGrid: 0,
57
+ minuteGrid: 0,
58
+ secondGrid: 0,
59
+ alwaysSetTime: true
60
+ };
61
+ $.extend(this.defaults, this.regional['']);
62
+ } else {
63
+ this.defaults = $.extend({}, $.timepicker.defaults);
64
+ }
65
+
66
+ };
67
+
68
+ Timepicker.prototype = {
69
+ $input: null,
70
+ $altInput: null,
71
+ $timeObj: null,
72
+ inst: null,
73
+ hour_slider: null,
74
+ minute_slider: null,
75
+ second_slider: null,
76
+ hour: 0,
77
+ minute: 0,
78
+ second: 0,
79
+ ampm: '',
80
+ formattedDate: '',
81
+ formattedTime: '',
82
+ formattedDateTime: '',
83
+
84
+ //########################################################################
85
+ // add our sliders to the calendar
86
+ //########################################################################
87
+ addTimePicker: function(dp_inst) {
88
+ var tp_inst = this;
89
+ var currDT;
90
+ if ((this.$altInput) && this.$altInput != null)
91
+ {
92
+ currDT = this.$input.val() + ' ' + this.$altInput.val();
93
+ }
94
+ else
95
+ {
96
+ currDT = this.$input.val();
97
+ }
98
+ var regstr = this.defaults.timeFormat.toString()
99
+ .replace(/h{1,2}/ig, '(\\d?\\d)')
100
+ .replace(/m{1,2}/ig, '(\\d?\\d)')
101
+ .replace(/s{1,2}/ig, '(\\d?\\d)')
102
+ .replace(/t{1,2}/ig, '(am|pm|a|p)?')
103
+ .replace(/\s/g, '\\s?') + '$';
104
+
105
+ if (!this.defaults.timeOnly) {
106
+ //the time should come after x number of characters and a space. x = at least the length of text specified by the date format
107
+ var dp_dateFormat = $.datepicker._get(dp_inst, 'dateFormat');
108
+ regstr = '.{' + dp_dateFormat.length + ',}\\s+' + regstr;
109
+ }
110
+
111
+ var order = this.getFormatPositions();
112
+ var treg = currDT.match(new RegExp(regstr, 'i'));
113
+
114
+ if (treg) {
115
+ if (order.t !== -1) {
116
+ this.ampm = ((treg[order.t] === undefined || treg[order.t].length === 0) ? '' : (treg[order.t].charAt(0).toUpperCase() == 'A') ? 'AM' : 'PM').toUpperCase();
117
+ }
118
+
119
+ if (order.h !== -1) {
120
+ if (this.ampm == 'AM' && treg[order.h] == '12') {
121
+ // 12am = 0 hour
122
+ this.hour = 0;
123
+ } else if (this.ampm == 'PM' && treg[order.h] != '12') {
124
+ // 12pm = 12 hour, any other pm = hour + 12
125
+ this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0);
126
+ } else {
127
+ this.hour = treg[order.h];
128
+ }
129
+ }
130
+
131
+ if (order.m !== -1) {
132
+ this.minute = treg[order.m];
133
+ }
134
+
135
+ if (order.s !== -1) {
136
+ this.second = treg[order.s];
137
+ }
138
+ }
139
+
140
+ tp_inst.timeDefined = (treg) ? true : false;
141
+
142
+ if (typeof(dp_inst.stay_open) !== 'boolean' || dp_inst.stay_open === false) {
143
+ // wait for datepicker to create itself.. 60% of the time it works every time..
144
+ setTimeout(function() {
145
+ tp_inst.injectTimePicker(dp_inst, tp_inst);
146
+ }, 10);
147
+ } else {
148
+ tp_inst.injectTimePicker(dp_inst, tp_inst);
149
+ }
150
+
151
+ },
152
+
153
+ //########################################################################
154
+ // figure out position of time elements.. cause js cant do named captures
155
+ //########################################################################
156
+ getFormatPositions: function() {
157
+ var finds = this.defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|t{1,2})/g);
158
+ var orders = { h: -1, m: -1, s: -1, t: -1 };
159
+
160
+ if (finds) {
161
+ for (var i = 0; i < finds.length; i++) {
162
+ if (orders[finds[i].toString().charAt(0)] == -1) {
163
+ orders[finds[i].toString().charAt(0)] = i + 1;
164
+ }
165
+ }
166
+ }
167
+
168
+ return orders;
169
+ },
170
+
171
+ //########################################################################
172
+ // generate and inject html for timepicker into ui datepicker
173
+ //########################################################################
174
+ injectTimePicker: function(dp_inst, tp_inst) {
175
+ var $dp = dp_inst.dpDiv;
176
+ var opts = tp_inst.defaults;
177
+
178
+ // Added by Peter Medeiros:
179
+ // - Figure out what the hour/minute/second max should be based on the step values.
180
+ // - Example: if stepMinute is 15, then minMax is 45.
181
+ var hourMax = opts.hourMax - (opts.hourMax % opts.stepHour);
182
+ var minMax = opts.minuteMax - (opts.minuteMax % opts.stepMinute);
183
+ var secMax = opts.secondMax - (opts.secondMax % opts.stepSecond);
184
+
185
+ // Prevent displaying twice
186
+ if ($dp.find("div#ui-timepicker-div-"+ dp_inst.id).length === 0) {
187
+ var noDisplay = ' style="display:none;"';
188
+ var html =
189
+ '<div class="ui-timepicker-div" id="ui-timepicker-div-' + dp_inst.id + '"><dl>' +
190
+ '<dt class="ui_tpicker_time_label" id="ui_tpicker_time_label_' + dp_inst.id + '"' + ((opts.showTime) ? '' : noDisplay) + '>' + opts.timeText + '</dt>' +
191
+ '<dd class="ui_tpicker_time" id="ui_tpicker_time_' + dp_inst.id + '"' + ((opts.showTime) ? '' : noDisplay) + '></dd>' +
192
+ '<dt class="ui_tpicker_hour_label" id="ui_tpicker_hour_label_' + dp_inst.id + '"' + ((opts.showHour) ? '' : noDisplay) + '>' + opts.hourText + '</dt>';
193
+
194
+ if (opts.hourGrid > 0)
195
+ {
196
+ html += '<dd class="ui_tpicker_hour ui_tpicker_hour_' + opts.hourGrid + '">' +
197
+ '<div id="ui_tpicker_hour_' + dp_inst.id + '"' + ((opts.showHour) ? '' : noDisplay) + '></div>' +
198
+ '<div><table><tr>';
199
+
200
+ for (var h = 0; h < hourMax; h += opts.hourGrid)
201
+ {
202
+ var tmph = h;
203
+ if(opts.ampm && h > 12)
204
+ tmph = h-12;
205
+ else tmph = h;
206
+
207
+ if(tmph < 10)
208
+ tmph = '0' + tmph;
209
+ if(opts.ampm)
210
+ {
211
+ if(h == 0)
212
+ tmph = 12 +'a';
213
+ else if(h < 12)
214
+ tmph += 'a';
215
+ else tmph += 'p';
216
+ }
217
+ html += '<td>' + tmph + '</td>';
218
+ }
219
+
220
+ html += '</tr></table></div>' +
221
+ '</dd>';
222
+ }
223
+ else
224
+ {
225
+ html += '<dd class="ui_tpicker_hour" id="ui_tpicker_hour_' + dp_inst.id + '"' + ((opts.showHour) ? '' : noDisplay) + '></dd>';
226
+ }
227
+
228
+ html += '<dt class="ui_tpicker_minute_label" id="ui_tpicker_minute_label_' + dp_inst.id + '"' + ((opts.showMinute) ? '' : noDisplay) + '>' + opts.minuteText + '</dt>';
229
+
230
+ if (opts.minuteGrid > 0)
231
+ {
232
+ html += '<dd class="ui_tpicker_minute ui_tpicker_minute_' + opts.minuteGrid + '">' +
233
+ '<div id="ui_tpicker_minute_' + dp_inst.id + '"' + ((opts.showMinute) ? '' : noDisplay) + '></div>' +
234
+ '<div><table><tr>';
235
+
236
+ for (var m = 0; m < minMax; m += opts.minuteGrid)
237
+ {
238
+ html += '<td>' + ((m < 10) ? '0' : '') + m + '</td>';
239
+ }
240
+
241
+ html += '</tr></table></div>' +
242
+ '</dd>';
243
+ }
244
+ else
245
+ {
246
+ html += '<dd class="ui_tpicker_minute" id="ui_tpicker_minute_' + dp_inst.id + '"' + ((opts.showMinute) ? '' : noDisplay) + '></dd>'
247
+ }
248
+
249
+ html += '<dt class="ui_tpicker_second_label" id="ui_tpicker_second_label_' + dp_inst.id + '"' + ((opts.showSecond) ? '' : noDisplay) + '>' + opts.secondText + '</dt>';
250
+
251
+ if (opts.secondGrid > 0)
252
+ {
253
+ html += '<dd class="ui_tpicker_second ui_tpicker_second_' + opts.secondGrid + '">' +
254
+ '<div id="ui_tpicker_second_' + dp_inst.id + '"' + ((opts.showSecond) ? '' : noDisplay) + '></div>' +
255
+ '<table><table><tr>';
256
+
257
+ for (var s = 0; s < secMax; s += opts.secondGrid)
258
+ {
259
+ html += '<td>' + ((s < 10) ? '0' : '') + s + '</td>';
260
+ }
261
+
262
+ html += '</tr></table></table>' +
263
+ '</dd>';
264
+ }
265
+ else
266
+ {
267
+ html += '<dd class="ui_tpicker_second" id="ui_tpicker_second_' + dp_inst.id + '"' + ((opts.showSecond) ? '' : noDisplay) + '></dd>';
268
+ }
269
+
270
+ html += '</dl></div>';
271
+ $tp = $(html);
272
+
273
+ // if we only want time picker...
274
+ if (opts.timeOnly === true) {
275
+ $tp.prepend(
276
+ '<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' +
277
+ '<div class="ui-datepicker-title">'+ opts.timeOnlyTitle +'</div>' +
278
+ '</div>');
279
+ $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
280
+ }
281
+
282
+ tp_inst.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_inst.id).slider({
283
+ orientation: "horizontal",
284
+ value: tp_inst.hour,
285
+ min: opts.hourMin,
286
+ max: hourMax,
287
+ step: opts.stepHour,
288
+ slide: function(event, ui) {
289
+ tp_inst.hour_slider.slider( "option", "value", ui.value );
290
+ tp_inst.onTimeChange(dp_inst, tp_inst);
291
+ }
292
+ });
293
+
294
+ // Updated by Peter Medeiros:
295
+ // - Pass in Event and UI instance into slide function
296
+ tp_inst.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_inst.id).slider({
297
+ orientation: "horizontal",
298
+ value: tp_inst.minute,
299
+ min: opts.minuteMin,
300
+ max: minMax,
301
+ step: opts.stepMinute,
302
+ slide: function(event, ui) {
303
+ // update the global minute slider instance value with the current slider value
304
+ tp_inst.minute_slider.slider( "option", "value", ui.value );
305
+ tp_inst.onTimeChange(dp_inst, tp_inst);
306
+ }
307
+ });
308
+
309
+ tp_inst.second_slider = $tp.find('#ui_tpicker_second_'+ dp_inst.id).slider({
310
+ orientation: "horizontal",
311
+ value: tp_inst.second,
312
+ min: opts.secondMin,
313
+ max: secMax,
314
+ step: opts.stepSecond,
315
+ slide: function(event, ui) {
316
+ tp_inst.second_slider.slider( "option", "value", ui.value );
317
+ tp_inst.onTimeChange(dp_inst, tp_inst);
318
+ }
319
+ });
320
+
321
+ // Add grid functionality
322
+ $tp.find(".ui_tpicker_hour td").each(
323
+ function(index)
324
+ {
325
+ $(this).click(
326
+ function()
327
+ {
328
+ var h = $(this).html();
329
+ if(opts.ampm)
330
+ {
331
+ var ap = h.substring(2).toLowerCase();
332
+ var aph = new Number(h.substring(0,2));
333
+
334
+ if(ap == 'a'){
335
+ if(aph == 12)
336
+ h = 0;
337
+ else h = aph;
338
+ }else{
339
+ if(aph == 12)
340
+ h = 12;
341
+ else h = aph + 12;
342
+ }
343
+ }
344
+ tp_inst.hour_slider.slider("option", "value", h);
345
+ tp_inst.onTimeChange(dp_inst, tp_inst);
346
+ }
347
+ );
348
+
349
+ $(this).css({ 'cursor': "pointer", 'width': '1%', 'text-align': 'left' });
350
+ }
351
+ );
352
+ $tp.find(".ui_tpicker_minute td").each(
353
+ function(index)
354
+ {
355
+ $(this).click(
356
+ function()
357
+ {
358
+ tp_inst.minute_slider.slider("option", "value", $(this).html());
359
+ tp_inst.onTimeChange(dp_inst, tp_inst);
360
+ }
361
+ );
362
+
363
+ $(this).css({ 'cursor': "pointer", 'width': '1%', 'text-align': 'left' });
364
+ }
365
+ );
366
+ $tp.find(".ui_tpicker_second td").each(
367
+ function(index)
368
+ {
369
+ $(this).click(
370
+ function()
371
+ {
372
+ tp_inst.second_slider.slider("option", "value", $(this).html());
373
+ tp_inst.onTimeChange(dp_inst, tp_inst);
374
+ }
375
+ );
376
+ $(this).css({ 'cursor': "pointer", 'width': '1%', 'text-align': 'left' });
377
+ }
378
+ );
379
+
380
+ $dp.find('.ui-datepicker-calendar').after($tp);
381
+
382
+ tp_inst.$timeObj = $('#ui_tpicker_time_'+ dp_inst.id);
383
+
384
+ if (dp_inst !== null) {
385
+ var timeDefined = tp_inst.timeDefined;
386
+ tp_inst.onTimeChange(dp_inst, tp_inst);
387
+ tp_inst.timeDefined = timeDefined;
388
+ }
389
+ }
390
+ },
391
+
392
+ //########################################################################
393
+ // when a slider moves..
394
+ // on time change is also called when the time is updated in the text field
395
+ //########################################################################
396
+ onTimeChange: function(dp_inst, tp_inst) {
397
+ var hour = tp_inst.hour_slider.slider('value');
398
+ var minute = tp_inst.minute_slider.slider('value');
399
+ var second = tp_inst.second_slider.slider('value');
400
+ var ampm = (hour < 11.5) ? 'AM' : 'PM';
401
+ hour = (hour >= 11.5 && hour < 12) ? 12 : hour;
402
+ var hasChanged = false;
403
+
404
+ // If the update was done in the input field, this field should not be updated.
405
+ // If the update was done using the sliders, update the input field.
406
+ if (tp_inst.hour != hour || tp_inst.minute != minute || tp_inst.second != second || (tp_inst.ampm.length > 0 && tp_inst.ampm != ampm)) {
407
+ hasChanged = true;
408
+ }
409
+
410
+ tp_inst.hour = parseFloat(hour).toFixed(0);
411
+ tp_inst.minute = parseFloat(minute).toFixed(0);
412
+ tp_inst.second = parseFloat(second).toFixed(0);
413
+ tp_inst.ampm = ampm;
414
+
415
+ tp_inst.formatTime(tp_inst);
416
+ tp_inst.$timeObj.text(tp_inst.formattedTime);
417
+
418
+ if (hasChanged) {
419
+ tp_inst.updateDateTime(dp_inst, tp_inst);
420
+ tp_inst.timeDefined = true;
421
+ }
422
+ },
423
+
424
+ //########################################################################
425
+ // format the time all pretty...
426
+ //########################################################################
427
+ formatTime: function(tp_inst) {
428
+ var tmptime = tp_inst.defaults.timeFormat.toString();
429
+ var hour12 = ((tp_inst.ampm == 'AM') ? (tp_inst.hour) : (tp_inst.hour % 12));
430
+ hour12 = (Number(hour12) === 0) ? 12 : hour12;
431
+
432
+ if (tp_inst.defaults.ampm === true) {
433
+ tmptime = tmptime.toString()
434
+ .replace(/hh/g, ((hour12 < 10) ? '0' : '') + hour12)
435
+ .replace(/h/g, hour12)
436
+ .replace(/mm/g, ((tp_inst.minute < 10) ? '0' : '') + tp_inst.minute)
437
+ .replace(/m/g, tp_inst.minute)
438
+ .replace(/ss/g, ((tp_inst.second < 10) ? '0' : '') + tp_inst.second)
439
+ .replace(/s/g, tp_inst.second)
440
+ .replace(/TT/g, tp_inst.ampm.toUpperCase())
441
+ .replace(/tt/g, tp_inst.ampm.toLowerCase())
442
+ .replace(/T/g, tp_inst.ampm.charAt(0).toUpperCase())
443
+ .replace(/t/g, tp_inst.ampm.charAt(0).toLowerCase());
444
+
445
+ } else {
446
+ tmptime = tmptime.toString()
447
+ .replace(/hh/g, ((tp_inst.hour < 10) ? '0' : '') + tp_inst.hour)
448
+ .replace(/h/g, tp_inst.hour)
449
+ .replace(/mm/g, ((tp_inst.minute < 10) ? '0' : '') + tp_inst.minute)
450
+ .replace(/m/g, tp_inst.minute)
451
+ .replace(/ss/g, ((tp_inst.second < 10) ? '0' : '') + tp_inst.second)
452
+ .replace(/s/g, tp_inst.second);
453
+ tmptime = $.trim(tmptime.replace(/t/gi, ''));
454
+ }
455
+
456
+ tp_inst.formattedTime = tmptime;
457
+ return tp_inst.formattedTime;
458
+ },
459
+
460
+ //########################################################################
461
+ // update our input with the new date time..
462
+ //########################################################################
463
+ updateDateTime: function(dp_inst, tp_inst) {
464
+ var dt = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
465
+ var dateFmt = $.datepicker._get(dp_inst, 'dateFormat');
466
+ var formatCfg = $.datepicker._getFormatConfig(dp_inst);
467
+ this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
468
+ var formattedDateTime = this.formattedDate;
469
+ var timeAvailable = dt !== null && tp_inst.timeDefined;
470
+
471
+ if(this.defaults.timeOnly === true){
472
+ formattedDateTime = this.formattedTime;
473
+ }
474
+ else if (this.defaults.timeOnly !== true && (this.defaults.alwaysSetTime || timeAvailable)) {
475
+ if ((this.$altInput) && this.$altInput != null)
476
+ {
477
+ this.$altInput.val(this.formattedTime);
478
+ }
479
+ else{
480
+ formattedDateTime += ' ' + this.formattedTime;
481
+ }
482
+ }
483
+
484
+ this.formattedDateTime = formattedDateTime;
485
+ this.$input.val(formattedDateTime);
486
+ this.$input.trigger("change");
487
+ },
488
+
489
+ setDefaults: function(settings) {
490
+ extendRemove(this.defaults, settings || {});
491
+ return this;
492
+ }
493
+ };
494
+
495
+ //########################################################################
496
+ // extend timepicker to datepicker
497
+ //########################################################################
498
+ jQuery.fn.datetimepicker = function(o) {
499
+ var opts = (o === undefined ? {} : o);
500
+ var input = $(this);
501
+ var tp = new Timepicker();
502
+ var inlineSettings = {};
503
+
504
+ for (var attrName in tp.defaults) {
505
+ var attrValue = input.attr('time:' + attrName);
506
+ if (attrValue) {
507
+ try {
508
+ inlineSettings[attrName] = eval(attrValue);
509
+ } catch (err) {
510
+ inlineSettings[attrName] = attrValue;
511
+ }
512
+ }
513
+ }
514
+ tp.defaults = $.extend(tp.defaults, inlineSettings);
515
+
516
+ var beforeShowFunc = function(input, inst) {
517
+ tp.hour = tp.defaults.hour;
518
+ tp.minute = tp.defaults.minute;
519
+ tp.second = tp.defaults.second;
520
+ tp.ampm = '';
521
+ tp.$input = $(input);
522
+ if(opts.altField != undefined && opts.altField != '')
523
+ tp.$altInput = $($.datepicker._get(inst, 'altField'));
524
+ tp.inst = inst;
525
+ tp.addTimePicker(inst);
526
+ if ($.isFunction(opts.beforeShow)) {
527
+ opts.beforeShow(input, inst);
528
+ }
529
+ };
530
+
531
+ var onChangeMonthYearFunc = function(year, month, inst) {
532
+ // Update the time as well : this prevents the time from disappearing from the input field.
533
+ tp.updateDateTime(inst, tp);
534
+ if ($.isFunction(opts.onChangeMonthYear)) {
535
+ opts.onChangeMonthYear(year, month, inst);
536
+ }
537
+ };
538
+
539
+ var onCloseFunc = function(dateText, inst) {
540
+ if(tp.timeDefined === true && input.val() != '') {
541
+ tp.updateDateTime(inst, tp);
542
+ }
543
+ if ($.isFunction(opts.onClose)) {
544
+ opts.onClose(dateText, inst);
545
+ }
546
+ };
547
+
548
+ tp.defaults = $.extend({}, tp.defaults, opts, {
549
+ beforeShow: beforeShowFunc,
550
+ onChangeMonthYear: onChangeMonthYearFunc,
551
+ onClose: onCloseFunc,
552
+ timepicker: tp // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
553
+ });
554
+
555
+ $(this).datepicker(tp.defaults);
556
+
557
+ };
558
+
559
+ //########################################################################
560
+ // shorthand just to use timepicker..
561
+ //########################################################################
562
+ jQuery.fn.timepicker = function(opts) {
563
+ opts = $.extend(opts, { timeOnly: true });
564
+ $(this).datetimepicker(opts);
565
+ };
566
+
567
+ //########################################################################
568
+ // the bad hack :/ override datepicker so it doesnt close on select
569
+ // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
570
+ //########################################################################
571
+ $.datepicker._base_selectDate = $.datepicker._selectDate;
572
+ $.datepicker._selectDate = function (id, dateStr) {
573
+ var target = $(id);
574
+ var inst = this._getInst(target[0]);
575
+ var tp_inst = $.datepicker._get(inst, 'timepicker');
576
+
577
+ if(tp_inst){
578
+ inst.inline = true;
579
+ inst.stay_open = true;
580
+ $.datepicker._base_selectDate(id, dateStr);
581
+ inst.stay_open = false;
582
+ inst.inline = false;
583
+ this._notifyChange(inst);
584
+ this._updateDatepicker(inst);
585
+ }
586
+ else{
587
+ $.datepicker._base_selectDate(id, dateStr);
588
+ }
589
+ };
590
+
591
+ //#############################################################################################
592
+ // second bad hack :/ override datepicker so it triggers an event when changing the input field
593
+ // and does not redraw the datepicker on every selectDate event
594
+ //#############################################################################################
595
+ $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
596
+ $.datepicker._updateDatepicker = function(inst) {
597
+ if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
598
+ this._base_updateDatepicker(inst);
599
+ // Reload the time control when changing something in the input text field.
600
+ this._beforeShow(inst.input, inst);
601
+ }
602
+ };
603
+
604
+ $.datepicker._beforeShow = function(input, inst) {
605
+ var beforeShow = this._get(inst, 'beforeShow');
606
+ if (beforeShow) {
607
+ inst.stay_open = true;
608
+ beforeShow.apply((inst.input ? inst.input[0] : null), [inst.input, inst]);
609
+ inst.stay_open = false;
610
+ }
611
+ };
612
+
613
+ //#######################################################################################
614
+ // third bad hack :/ override datepicker so it allows spaces and colan in the input field
615
+ //#######################################################################################
616
+ $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
617
+ $.datepicker._doKeyPress = function(event) {
618
+ var inst = $.datepicker._getInst(event.target);
619
+ var tp_inst = $.datepicker._get(inst, 'timepicker');
620
+
621
+ if(tp_inst){
622
+ if ($.datepicker._get(inst, 'constrainInput')) {
623
+ var dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
624
+ var chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
625
+ var chrl = chr.toLowerCase();
626
+ // keyCode == 58 => ":"
627
+ // keyCode == 32 => " "
628
+ return event.ctrlKey || (chr < ' ' || !dateChars || dateChars.indexOf(chr) > -1 || event.keyCode == 58 || event.keyCode == 32 || chr == ':' || chr == ' ' || chrl == 'a' || chrl == 'p' || chrl == 'm');
629
+ }
630
+ }
631
+ else{
632
+ return $.datepicker._base_doKeyPress(event);
633
+ }
634
+
635
+ };
636
+
637
+ //#######################################################################################
638
+ // override "Today" button to also grab the time.
639
+ //#######################################################################################
640
+ $.datepicker._base_gotoToday = $.datepicker._gotoToday;
641
+ $.datepicker._gotoToday = function(id) {
642
+ $.datepicker._base_gotoToday(id);
643
+
644
+ var target = $(id);
645
+ var dp_inst = this._getInst(target[0]);
646
+ var tp_inst = $.datepicker._get(dp_inst, 'timepicker');
647
+
648
+ if(tp_inst){
649
+ var date = new Date();
650
+ var hour = date.getHours();
651
+ var minute = date.getMinutes();
652
+ var second = date.getSeconds();
653
+
654
+ //check if within min/max times..
655
+ if( (hour < tp_inst.defaults.hourMin || hour > tp_inst.defaults.hourMax) || (minute < tp_inst.defaults.minuteMin || minute > tp_inst.defaults.minuteMax) || (second < tp_inst.defaults.secondMin || second > tp_inst.defaults.secondMax) ){
656
+ hour = tp_inst.defaults.hourMin;
657
+ minute = tp_inst.defaults.minuteMin;
658
+ second = tp_inst.defaults.secondMin;
659
+ }
660
+
661
+ tp_inst.hour_slider.slider('value', hour );
662
+ tp_inst.minute_slider.slider('value', minute );
663
+ tp_inst.second_slider.slider('value', second );
664
+
665
+ tp_inst.onTimeChange(dp_inst, tp_inst);
666
+ }
667
+ };
668
+
669
+ //#######################################################################################
670
+ // jQuery extend now ignores nulls!
671
+ //#######################################################################################
672
+ function extendRemove(target, props) {
673
+ $.extend(target, props);
674
+ for (var name in props)
675
+ if (props[name] == null || props[name] == undefined)
676
+ target[name] = props[name];
677
+ return target;
678
+ };
679
+
680
+ $.timepicker = new Timepicker(true); // singleton instance
681
+ })(jQuery);
682
+