droom 0.4.3 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/images/droom/admin_menu.png +0 -0
  3. data/app/assets/images/droom/applications_menu.png +0 -0
  4. data/app/assets/images/droom/arrows_small.png +0 -0
  5. data/app/assets/images/droom/config_menu.png +0 -0
  6. data/app/assets/images/droom/dropdown.png +0 -0
  7. data/app/assets/images/droom/menu/asterisk.png +0 -0
  8. data/app/assets/images/droom/{smalladd.png → menu/smalladd.png} +0 -0
  9. data/app/assets/images/droom/{small_asterisk.png → menu/smallasterisk.png} +0 -0
  10. data/app/assets/images/droom/{smalldelete.png → menu/smalldelete.png} +0 -0
  11. data/app/assets/images/droom/{smalldownload.png → menu/smalldownload.png} +0 -0
  12. data/app/assets/images/droom/{smalledit.png → menu/smalledit.png} +0 -0
  13. data/app/assets/images/droom/message.png +0 -0
  14. data/app/assets/images/droom/missing/scrap.jpg +0 -0
  15. data/app/assets/images/droom/missing/scrap.png +0 -0
  16. data/app/assets/images/droom/missing/thumb.png +0 -0
  17. data/app/assets/images/droom/missing/user.png +0 -0
  18. data/app/assets/images/droom/object_icons.png +0 -0
  19. data/app/assets/images/droom/panel/add.png +0 -0
  20. data/app/assets/images/droom/panel/edit.png +0 -0
  21. data/app/assets/images/droom/panel/manage.png +0 -0
  22. data/app/assets/images/droom/pointer_upwards.png +0 -0
  23. data/app/assets/images/droom/search_menu.png +0 -0
  24. data/app/assets/images/droom/setter.png +0 -0
  25. data/app/assets/images/droom/small_icons.png +0 -0
  26. data/app/assets/images/droom/stream/closer.png +0 -0
  27. data/app/assets/images/droom/stream/next.png +0 -0
  28. data/app/assets/images/droom/stream/prev.png +0 -0
  29. data/app/assets/images/droom/stream/previous.png +0 -0
  30. data/app/assets/images/droom/subscribe.png +0 -0
  31. data/app/assets/javascripts/droom.js.coffee +23 -13
  32. data/app/assets/javascripts/droom/actions.js.coffee +104 -10
  33. data/app/assets/javascripts/droom/ajax.js.coffee +36 -24
  34. data/app/assets/javascripts/droom/extensions.js.coffee +13 -0
  35. data/app/assets/javascripts/droom/lib/jquery.datepicker.js +1026 -0
  36. data/app/assets/javascripts/droom/lib/jquery.deserialize.js +142 -0
  37. data/app/assets/javascripts/droom/lib/jquery_ujs.js +416 -0
  38. data/app/assets/javascripts/droom/lib/swipe.js +568 -0
  39. data/app/assets/javascripts/droom/lib/underscore.js +1276 -0
  40. data/app/assets/javascripts/droom/popups.js.coffee +98 -37
  41. data/app/assets/javascripts/droom/stream.js.coffee +119 -77
  42. data/app/assets/javascripts/droom/utilities.js.coffee +25 -3
  43. data/app/assets/javascripts/droom/widgets.js.coffee +318 -253
  44. data/app/assets/stylesheets/droom.css.sass +482 -955
  45. data/app/assets/stylesheets/droom/_mixins.css.sass +12 -42
  46. data/app/assets/stylesheets/droom/_popups.css.sass +28 -11
  47. data/app/assets/stylesheets/droom/_stream.css.sass +375 -0
  48. data/app/assets/stylesheets/droom/_toolbar.css.sass +0 -6
  49. data/app/assets/stylesheets/droom/_variables.css.sass +4 -2
  50. data/app/controllers/droom/agenda_categories_controller.rb +6 -14
  51. data/app/controllers/droom/api/api_controller.rb +56 -0
  52. data/app/controllers/droom/api/events_controller.rb +74 -0
  53. data/app/controllers/droom/api/users_controller.rb +92 -0
  54. data/app/controllers/droom/api/venues_controller.rb +71 -0
  55. data/app/controllers/droom/calendars_controller.rb +4 -10
  56. data/app/controllers/droom/{user_confirmations_controller.rb → confirmations_controller.rb} +8 -7
  57. data/app/controllers/droom/dashboard_controller.rb +2 -19
  58. data/app/controllers/droom/documents_controller.rb +12 -60
  59. data/app/controllers/droom/dropbox_tokens_controller.rb +3 -4
  60. data/app/controllers/droom/engine_controller.rb +39 -11
  61. data/app/controllers/droom/events_controller.rb +62 -84
  62. data/app/controllers/droom/folders_controller.rb +30 -40
  63. data/app/controllers/droom/group_invitations_controller.rb +6 -23
  64. data/app/controllers/droom/group_permissions_controller.rb +26 -0
  65. data/app/controllers/droom/groups_controller.rb +10 -14
  66. data/app/controllers/droom/invitations_controller.rb +7 -25
  67. data/app/controllers/droom/memberships_controller.rb +13 -18
  68. data/app/controllers/droom/organisations_controller.rb +6 -25
  69. data/app/controllers/droom/permissions_controller.rb +50 -0
  70. data/app/controllers/droom/preferences_controller.rb +9 -10
  71. data/app/controllers/droom/scraps_controller.rb +23 -26
  72. data/app/controllers/droom/services_controller.rb +50 -0
  73. data/app/controllers/droom/suggestions_controller.rb +6 -4
  74. data/app/controllers/droom/users/confirmations_controller.rb +24 -0
  75. data/app/controllers/droom/users/passwords_controller.rb +39 -0
  76. data/app/controllers/droom/users/sessions_controller.rb +7 -0
  77. data/app/controllers/droom/users_controller.rb +60 -38
  78. data/app/controllers/droom/venues_controller.rb +8 -15
  79. data/app/controllers/droom/youtube_controller.rb +1 -1
  80. data/app/helpers/droom/droom_helper.rb +22 -17
  81. data/app/models/droom/ability.rb +81 -0
  82. data/app/models/droom/agenda_category.rb +0 -1
  83. data/app/models/droom/calendar.rb +12 -7
  84. data/app/models/droom/category.rb +4 -10
  85. data/app/models/droom/concerns/slugged.rb +21 -0
  86. data/app/models/droom/document.rb +15 -17
  87. data/app/models/droom/dropbox_document.rb +3 -6
  88. data/app/models/droom/dropbox_token.rb +2 -3
  89. data/app/models/droom/event.rb +117 -163
  90. data/app/models/droom/event_type.rb +25 -0
  91. data/app/models/droom/folder.rb +36 -48
  92. data/app/models/droom/group.rb +35 -27
  93. data/app/models/droom/group_invitation.rb +7 -10
  94. data/app/models/droom/group_permission.rb +29 -0
  95. data/app/models/droom/invitation.rb +14 -23
  96. data/app/models/droom/mailing_list_membership.rb +0 -1
  97. data/app/models/droom/membership.rb +32 -31
  98. data/app/models/droom/organisation.rb +6 -3
  99. data/app/models/droom/permission.rb +19 -0
  100. data/app/models/droom/personal_folder.rb +9 -21
  101. data/app/models/droom/preference.rb +1 -2
  102. data/app/models/droom/scrap.rb +31 -26
  103. data/app/models/droom/service.rb +31 -0
  104. data/app/models/droom/tag.rb +10 -9
  105. data/app/models/droom/tagging.rb +1 -1
  106. data/app/models/droom/user.rb +453 -130
  107. data/app/models/droom/user_permission.rb +8 -0
  108. data/app/models/droom/venue.rb +21 -32
  109. data/app/serializers/droom/user_serializer.rb +45 -0
  110. data/app/serializers/droom/venue_serializer.rb +5 -0
  111. data/app/views/droom/dashboard/_documents.html.haml +1 -1
  112. data/app/views/droom/dashboard/_folders.html.haml +1 -1
  113. data/app/views/droom/dashboard/_future_events.html.haml +10 -8
  114. data/app/views/droom/dashboard/_groups.html.haml +1 -1
  115. data/app/views/droom/dashboard/_past_events.haml +19 -12
  116. data/app/views/droom/dashboard/_stream.html.haml +2 -2
  117. data/app/views/droom/{users/_extra_columns.html.haml → dashboard/_welcome.html.haml} +0 -0
  118. data/app/views/droom/dashboard/index.html.haml +3 -0
  119. data/app/views/droom/documents/_document.html.haml +0 -2
  120. data/app/views/droom/documents/_documents.html.haml +1 -1
  121. data/app/views/droom/documents/_documents_list.html.haml +1 -1
  122. data/app/views/droom/documents/_documents_table.html.haml +1 -1
  123. data/app/views/droom/documents/_form.html.haml +8 -5
  124. data/app/views/droom/documents/_listing.html.haml +4 -2
  125. data/app/views/droom/documents/index.html.haml +13 -7
  126. data/app/views/droom/documents/new.html.haml +1 -4
  127. data/app/views/droom/events/_action_menu.html.haml +2 -2
  128. data/app/views/droom/events/_attachments.html.haml +8 -0
  129. data/app/views/droom/events/_calendar.html.haml +4 -8
  130. data/app/views/droom/events/_event.html.haml +44 -63
  131. data/app/views/droom/events/_event_line.html.haml +1 -1
  132. data/app/views/droom/events/_events.html.haml +18 -2
  133. data/app/views/droom/events/_form.html.haml +26 -19
  134. data/app/views/droom/events/_invitations.html.haml +7 -3
  135. data/app/views/droom/events/_scrap_events.html.haml +8 -0
  136. data/app/views/droom/events/_suggested.html.haml +4 -1
  137. data/app/views/droom/events/calendar.html.haml +8 -0
  138. data/app/views/droom/events/index.html.haml +24 -26
  139. data/app/views/droom/events/show.html.haml +6 -6
  140. data/app/views/droom/folders/_contents.html.haml +34 -4
  141. data/app/views/droom/folders/_folder.html.haml +7 -2
  142. data/app/views/droom/folders/_form.html.haml +11 -8
  143. data/app/views/droom/folders/index.html.haml +19 -22
  144. data/app/views/droom/group_invitations/_attending_groups.html.haml +1 -1
  145. data/app/views/droom/group_permissions/_toggle.html.haml +18 -0
  146. data/app/views/droom/groups/_action_menu.haml +0 -2
  147. data/app/views/droom/groups/_created.html.haml +0 -1
  148. data/app/views/droom/groups/_form.html.haml +3 -0
  149. data/app/views/droom/groups/_group.html.haml +10 -8
  150. data/app/views/droom/groups/_groups.html.haml +1 -1
  151. data/app/views/droom/groups/_search_result.html.haml +1 -1
  152. data/app/views/droom/groups/_suggested.html.haml +1 -1
  153. data/app/views/droom/groups/index.html.haml +15 -16
  154. data/app/views/droom/invitations/_form.html.haml +1 -1
  155. data/app/views/droom/invitations/_invitation.html.haml +1 -1
  156. data/app/views/droom/invitations/_invitations.html.haml +4 -4
  157. data/app/views/droom/memberships/_button.html.haml +5 -5
  158. data/app/views/droom/memberships/_form.html.haml +26 -7
  159. data/app/views/droom/memberships/_member.html.haml +1 -1
  160. data/app/views/droom/memberships/{_membership_toggle.html.haml → _toggle.html.haml} +4 -4
  161. data/app/views/droom/memberships/index.html.haml +9 -0
  162. data/app/views/droom/organisations/_action_menu.html.haml +1 -1
  163. data/app/views/droom/organisations/_organisation.html.haml +2 -2
  164. data/app/views/droom/organisations/_suggested.html.haml +1 -1
  165. data/app/views/droom/organisations/index.html.haml +11 -11
  166. data/app/views/droom/panels/_admin.html.haml +2 -2
  167. data/app/views/droom/panels/_configuration.html.haml +28 -0
  168. data/app/views/droom/panels/_devices.html.haml +2 -4
  169. data/app/views/droom/panels/_search.html.haml +9 -0
  170. data/app/views/droom/permissions/_action_menu.html.haml +10 -0
  171. data/app/views/droom/permissions/_created.html.haml +3 -0
  172. data/app/views/droom/permissions/_form.html.haml +17 -0
  173. data/app/views/droom/permissions/edit.html.haml +7 -0
  174. data/app/views/droom/permissions/new.html.haml +8 -0
  175. data/app/views/droom/permissions/show.html.haml +4 -0
  176. data/app/views/droom/preferences/_checkbox.html.haml +4 -2
  177. data/app/views/droom/scraps/_caption.html.haml +0 -2
  178. data/app/views/droom/scraps/_credit.html.haml +1 -1
  179. data/app/views/droom/scraps/_form.html.haml +68 -69
  180. data/app/views/droom/scraps/_preload.html.haml +4 -0
  181. data/app/views/droom/scraps/_stream.html.haml +11 -3
  182. data/app/views/droom/scraps/_thumb.html.haml +33 -1
  183. data/app/views/droom/scraps/edit.html.haml +6 -1
  184. data/app/views/droom/scraps/full/_document.html.haml +4 -3
  185. data/app/views/droom/scraps/full/_event.html.haml +17 -16
  186. data/app/views/droom/scraps/full/_image.html.haml +1 -2
  187. data/app/views/droom/scraps/full/_link.html.haml +4 -3
  188. data/app/views/droom/scraps/full/_quote.html.haml +4 -7
  189. data/app/views/droom/scraps/full/_text.html.haml +3 -2
  190. data/app/views/droom/scraps/full/_video.html.haml +2 -2
  191. data/app/views/droom/scraps/new.html.haml +6 -1
  192. data/app/views/droom/scraps/show.html.haml +4 -3
  193. data/app/views/droom/services/_action_menu.html.haml +12 -0
  194. data/app/views/droom/services/_created.html.haml +3 -0
  195. data/app/views/droom/services/_form.html.haml +18 -0
  196. data/app/views/droom/services/_services.html.haml +44 -0
  197. data/app/views/droom/services/edit.html.haml +7 -0
  198. data/app/views/droom/services/index.html.haml +5 -0
  199. data/app/views/droom/{people → services}/new.html.haml +4 -3
  200. data/app/views/droom/services/show.html.haml +4 -0
  201. data/app/views/droom/shared/_controls.html.haml +2 -2
  202. data/app/views/droom/shared/_navigation.html.haml +2 -2
  203. data/app/views/droom/shared/_toolbar.html.haml +1 -1
  204. data/app/views/droom/suggestions/index.html.haml +1 -0
  205. data/app/views/droom/users/_action_menu.html.haml +21 -0
  206. data/app/views/droom/users/_suggested.html.haml +14 -0
  207. data/app/views/droom/users/_user.html.haml +2 -2
  208. data/app/views/droom/users/_users.html.haml +7 -0
  209. data/app/views/droom/users/_users_table.html.haml +21 -22
  210. data/app/views/droom/users/admin.html.haml +10 -0
  211. data/app/views/droom/users/confirmations/_after_confirmation.html.haml +2 -0
  212. data/app/views/droom/users/confirmations/_password_required.html.haml +30 -0
  213. data/app/views/droom/users/confirmations/failure.en.html.haml +22 -0
  214. data/app/views/droom/users/confirmations/show.html.haml +13 -0
  215. data/app/views/droom/users/edit.html.haml +2 -10
  216. data/app/views/droom/users/edit/_details.html.haml +13 -0
  217. data/app/views/droom/users/edit/_memberships.html.haml +13 -0
  218. data/app/views/droom/users/edit/_password_fields.html.haml +16 -0
  219. data/app/views/droom/users/edit/_preferences.html.haml +37 -0
  220. data/app/views/droom/users/edit/_profile.html.haml +26 -0
  221. data/app/views/droom/users/edit/_user_fields.html.haml +66 -0
  222. data/app/views/droom/users/index.html.haml +6 -32
  223. data/app/views/droom/users/new.html.haml +3 -0
  224. data/app/views/droom/users/passwords/completed.html.haml +13 -0
  225. data/app/views/{devise → droom/users}/passwords/edit.html.haml +10 -4
  226. data/app/views/{devise → droom/users}/passwords/new.html.haml +4 -3
  227. data/app/views/droom/users/passwords/show.html.haml +6 -0
  228. data/app/views/droom/users/show.html.haml +2 -0
  229. data/app/views/droom/users/show/_listed.html.haml +46 -0
  230. data/app/views/droom/users/show/_profile.html.haml +33 -0
  231. data/app/views/droom/users/show/_tabled.html.haml +28 -0
  232. data/config/initializers/chronic.rb +2 -0
  233. data/config/initializers/devise.rb +35 -2
  234. data/config/initializers/paperclip.rb +11 -6
  235. data/config/locales/devise.en.yml +1 -1
  236. data/config/locales/en.yml +198 -103
  237. data/config/routes.rb +37 -45
  238. data/db/migrate/20130207123614_stream.rb +5 -1
  239. data/db/migrate/20130225095328_create_droom_calendars.rb +0 -1
  240. data/db/migrate/20130627065459_permissions.rb +34 -0
  241. data/db/migrate/20130627071938_users_take_over.rb +38 -0
  242. data/db/migrate/20130627073759_user_properties.rb +34 -0
  243. data/db/migrate/20130627080021_no_more_people.rb +11 -0
  244. data/db/migrate/20130701122935_directory_groups.rb +8 -0
  245. data/db/migrate/20130701123152_remove_old_access_control.rb +16 -0
  246. data/db/migrate/20130729102857_more_scrap_data.rb +12 -0
  247. data/db/migrate/20130904080340_international_names.rb +17 -0
  248. data/db/migrate/20130904080341_honours.rb +5 -0
  249. data/db/migrate/20131124082222_simple_addresses.rb +25 -0
  250. data/db/migrate/20131201093351_event_time_zone.rb +5 -0
  251. data/db/migrate/20131217060311_session_revocable.rb +5 -0
  252. data/db/migrate/20131219180311_event_types.rb +15 -0
  253. data/lib/devise/strategies/cookie_authenticatable.rb +46 -0
  254. data/lib/droom.rb +48 -33
  255. data/lib/droom/auth_cookie.rb +82 -0
  256. data/lib/droom/cropper.rb +24 -0
  257. data/lib/droom/engine.rb +20 -2
  258. data/lib/droom/folders.rb +6 -6
  259. data/lib/droom/lazy_hash.rb +11 -1
  260. data/lib/droom/monkeys.rb +6 -6
  261. data/lib/droom/taggability.rb +1 -1
  262. data/lib/droom/validators.rb +1 -1
  263. data/lib/droom/version.rb +1 -1
  264. data/lib/generators/droom/install/templates/droom_initializer.rb +10 -2
  265. data/lib/paperclip/geometry_transformation.rb +80 -0
  266. data/lib/paperclip/validators/attachment_height_validator.rb +89 -0
  267. data/lib/paperclip/validators/attachment_width_validator.rb +89 -0
  268. data/lib/paperclip_processors/offset_thumbnail.rb +85 -0
  269. data/spec/dummy/config/application.rb +0 -7
  270. data/spec/dummy/config/environments/development.rb +1 -10
  271. data/spec/dummy/config/environments/production.rb +1 -0
  272. data/spec/dummy/config/environments/test.rb +2 -7
  273. data/spec/dummy/db/migrate/20130130120631_folder_ancestry_to_parents.droom.rb +1 -1
  274. data/spec/dummy/db/migrate/20130724124758_dropbox_tokens.droom.rb +10 -0
  275. data/spec/dummy/db/migrate/20130724124759_preference_uuids.droom.rb +6 -0
  276. data/spec/dummy/db/migrate/20130724124760_stream.droom.rb +14 -0
  277. data/spec/dummy/db/migrate/20130724124761_access_token_secret.droom.rb +6 -0
  278. data/spec/dummy/db/migrate/20130724124762_person_image.droom.rb +10 -0
  279. data/spec/dummy/db/migrate/20130724124763_devise_confirmable.droom.rb +14 -0
  280. data/spec/dummy/db/migrate/20130724124764_create_droom_calendars.droom.rb +20 -0
  281. data/spec/dummy/db/migrate/20130724124765_give_scraps_document.droom.rb +6 -0
  282. data/spec/dummy/db/migrate/20130724124766_privateness.droom.rb +10 -0
  283. data/spec/dummy/db/migrate/20130724124767_store_metadata.droom.rb +6 -0
  284. data/spec/dummy/db/migrate/20130724124768_folders_nicely.droom.rb +7 -0
  285. data/spec/dummy/db/migrate/20130724124769_niceties.droom.rb +8 -0
  286. data/spec/dummy/db/migrate/20130724124770_create_droom_dropbox_documents.droom.rb +12 -0
  287. data/spec/dummy/db/migrate/20130724124771_dropbox_documents_changed.droom.rb +6 -0
  288. data/spec/dummy/db/migrate/20130724124772_user_titles.droom.rb +6 -0
  289. data/spec/dummy/db/migrate/20130724124773_permissions.droom.rb +35 -0
  290. data/spec/dummy/db/migrate/20130724124774_users_take_over.droom.rb +39 -0
  291. data/spec/dummy/db/migrate/20130724124775_user_properties.droom.rb +35 -0
  292. data/spec/dummy/db/migrate/20130724124776_no_more_people.droom.rb +12 -0
  293. data/spec/dummy/db/migrate/20130724124777_directory_groups.droom.rb +9 -0
  294. data/spec/dummy/db/migrate/20130724124778_remove_old_access_control.droom.rb +17 -0
  295. data/spec/dummy/db/schema.rb +217 -140
  296. data/spec/factories/documents.rb +0 -5
  297. data/spec/factories/events.rb +0 -9
  298. data/spec/factories/user.rb +4 -2
  299. data/spec/lib/droom/folders_spec.rb +8 -8
  300. data/spec/models/droom/document_spec.rb +6 -43
  301. data/spec/models/droom/event_spec.rb +0 -34
  302. data/spec/models/droom/mailing_list_membership_spec.rb +4 -4
  303. data/spec/models/droom/membership_spec.rb +2 -2
  304. data/spec/spec_helper.rb +1 -10
  305. metadata +322 -282
  306. data/app/assets/images/droom/Untitled-1.png +0 -0
  307. data/app/assets/images/droom/asterisk.png +0 -0
  308. data/app/assets/images/droom/smallmanage.png +0 -0
  309. data/app/assets/javascripts/droom/lib/kalendae.js +0 -1692
  310. data/app/assets/stylesheets/lib/_kalendae.css.sass +0 -139
  311. data/app/controllers/droom/pages_controller.rb +0 -61
  312. data/app/controllers/droom/people_controller.rb +0 -111
  313. data/app/models/droom/document_attachment.rb +0 -37
  314. data/app/models/droom/page.rb +0 -26
  315. data/app/models/droom/person.rb +0 -309
  316. data/app/models/droom/recurrence_rule.rb +0 -82
  317. data/app/models/droom/user_action_observer.rb +0 -12
  318. data/app/views/devise/confirmations/failure.en.html.haml +0 -20
  319. data/app/views/devise/confirmations/show.html.haml +0 -19
  320. data/app/views/droom/confirmations/show.html.haml +0 -40
  321. data/app/views/droom/documents/_document_line.html.haml +0 -2
  322. data/app/views/droom/events/_created.html.haml +0 -2
  323. data/app/views/droom/folders/_attachments.html.haml +0 -3
  324. data/app/views/droom/pages/_contents.html.haml +0 -10
  325. data/app/views/droom/pages/_form.html.haml +0 -36
  326. data/app/views/droom/pages/_full_page.html.haml +0 -17
  327. data/app/views/droom/pages/_page.html.haml +0 -5
  328. data/app/views/droom/pages/_pages.html.haml +0 -2
  329. data/app/views/droom/pages/admin.html.haml +0 -24
  330. data/app/views/droom/pages/edit.html.haml +0 -1
  331. data/app/views/droom/pages/index.html.haml +0 -10
  332. data/app/views/droom/pages/new.html.haml +0 -4
  333. data/app/views/droom/pages/show.html.haml +0 -5
  334. data/app/views/droom/panels/_account.html.haml +0 -16
  335. data/app/views/droom/panels/_readers.html.haml +0 -18
  336. data/app/views/droom/panels/_suggestions.html.haml +0 -15
  337. data/app/views/droom/people/_action_menu.html.haml +0 -22
  338. data/app/views/droom/people/_created.html.haml +0 -6
  339. data/app/views/droom/people/_form.html.haml +0 -66
  340. data/app/views/droom/people/_listing.html.haml +0 -19
  341. data/app/views/droom/people/_memberships.html.haml +0 -24
  342. data/app/views/droom/people/_people.html.haml +0 -5
  343. data/app/views/droom/people/_person.html.haml +0 -32
  344. data/app/views/droom/people/_search_result.html.haml +0 -14
  345. data/app/views/droom/people/_suggested.html.haml +0 -14
  346. data/app/views/droom/people/edit.html.haml +0 -9
  347. data/app/views/droom/people/index.html.haml +0 -8
  348. data/app/views/droom/people/show.html.haml +0 -31
  349. data/app/views/droom/scraps/_heading.html.haml +0 -16
  350. data/app/views/droom/scraps/thumbs/_document.html.haml +0 -9
  351. data/app/views/droom/scraps/thumbs/_event.html.haml +0 -17
  352. data/app/views/droom/scraps/thumbs/_image.html.haml +0 -6
  353. data/app/views/droom/scraps/thumbs/_link.html.haml +0 -10
  354. data/app/views/droom/scraps/thumbs/_quote.html.haml +0 -8
  355. data/app/views/droom/scraps/thumbs/_text.html.haml +0 -8
  356. data/app/views/droom/scraps/thumbs/_video.html.haml +0 -6
  357. data/app/views/droom/users/_extra_columns_header.html.haml +0 -0
  358. data/app/views/droom/users/_extra_columns_note.html.haml +0 -0
  359. data/app/views/droom/users/_form.html.haml +0 -14
  360. data/app/views/droom/users/_password_fields.html.haml +0 -15
  361. data/app/views/droom/users/_user_or_person.html.haml +0 -72
  362. data/app/views/kaminari/_paginator.html.haml +0 -16
  363. data/lib/droom/dav_resource.rb +0 -36
  364. data/lib/droom/model_helpers.rb +0 -25
  365. data/lib/droom/routing.rb +0 -13
  366. data/spec/datasets/calendar_events_dataset.rb +0 -44
  367. data/spec/datasets/calendar_pages_dataset.rb +0 -8
  368. data/spec/datasets/calendar_sites_dataset.rb +0 -6
  369. data/spec/datasets/calendars_dataset.rb +0 -34
  370. data/spec/datasets/documents_dataset.rb +0 -28
  371. data/spec/datasets/recurrence_dataset.rb +0 -7
  372. data/spec/dummy/config/sunspot.yml +0 -17
  373. data/spec/dummy/log/dav.log +0 -1
  374. data/spec/dummy/log/development.log +0 -2
  375. data/spec/dummy/log/test.log +0 -1
  376. data/spec/dummy/solr/conf/admin-extra.html +0 -31
  377. data/spec/dummy/solr/conf/elevate.xml +0 -36
  378. data/spec/dummy/solr/conf/mapping-ISOLatin1Accent.txt +0 -246
  379. data/spec/dummy/solr/conf/protwords.txt +0 -21
  380. data/spec/dummy/solr/conf/schema.xml +0 -238
  381. data/spec/dummy/solr/conf/scripts.conf +0 -24
  382. data/spec/dummy/solr/conf/solrconfig.xml +0 -934
  383. data/spec/dummy/solr/conf/spellings.txt +0 -2
  384. data/spec/dummy/solr/conf/stopwords.txt +0 -58
  385. data/spec/dummy/solr/conf/synonyms.txt +0 -31
  386. data/spec/dummy/solr/data/development/index/segments.gen +0 -0
  387. data/spec/dummy/solr/data/development/index/segments_1 +0 -0
  388. data/spec/dummy/solr/data/development/spellchecker/segments.gen +0 -0
  389. data/spec/dummy/solr/data/development/spellchecker/segments_1 +0 -0
  390. data/spec/dummy/solr/data/test/index/segments.gen +0 -0
  391. data/spec/dummy/solr/data/test/index/segments_3nu +0 -0
  392. data/spec/dummy/solr/data/test/spellchecker/segments.gen +0 -0
  393. data/spec/dummy/solr/data/test/spellchecker/segments_1 +0 -0
  394. data/spec/factories/recurrence_rules.rb +0 -25
  395. data/spec/models/droom/person_spec.rb +0 -72
  396. data/spec/models/droom/recurrence_rule_spec.rb +0 -81
@@ -34,6 +34,19 @@ unless Array::empty?
34
34
  Array::empty = ()->
35
35
  @length == 0
36
36
 
37
+ # Returns true if this array contains that thing.
38
+
39
+ unless Array::contains?
40
+ Array::contains = (thing)->
41
+ @indexOf(thing) != -1
42
+
43
+ # Returns the position of that thing in this array, for the few browsers that don't already know how to do that.
44
+ unless Array::indexOf?
45
+ Array::indexOf = (elt)->
46
+ for item, i in this
47
+ return i if item is elt
48
+ return -1
49
+
37
50
  # Removes one instance of the supplied thing from an array
38
51
 
39
52
  unless Array::remove?
@@ -0,0 +1,1026 @@
1
+ /**
2
+ * DatePicker 1.0.0
3
+ *
4
+ * A jQuery-based DatePicker that provides an easy way of creating both single
5
+ * and multi-viewed calendars capable of accepting single, range, and multiple
6
+ * selected dates. Easily styled with two example styles provided: an attractive
7
+ * 'dark' style, and a Google Analytics-like 'clean' style.
8
+ *
9
+ * View project page for Examples and Documentation:
10
+ * http://foxrunsoftware.github.com/DatePicker/
11
+ *
12
+ * This project is distinct from and not affiliated with the jquery.ui.datepicker.
13
+ *
14
+ * Copyright 2012, Justin Stern (www.foxrunsoftware.net)
15
+ * Dual licensed under the MIT and GPL Version 2 licenses.
16
+ *
17
+ * Based on Work by Original Author: Stefan Petre www.eyecon.ro
18
+ *
19
+ * Depends:
20
+ * jquery.js
21
+ */
22
+ (function ($) {
23
+ var cache = {}, tmpl,
24
+ DatePicker = function () {
25
+ var ids = {},
26
+ views = {
27
+ years: 'datepickerViewYears',
28
+ moths: 'datepickerViewMonths',
29
+ days: 'datepickerViewDays'
30
+ },
31
+ tpl = {
32
+ wrapper: '<div class="datepicker"><div class="datepickerBorderT" /><div class="datepickerBorderB" /><div class="datepickerBorderL" /><div class="datepickerBorderR" /><div class="datepickerBorderTL" /><div class="datepickerBorderTR" /><div class="datepickerBorderBL" /><div class="datepickerBorderBR" /><div class="datepickerContainer"><table cellspacing="0" cellpadding="0"><tbody><tr></tr></tbody></table></div></div>',
33
+ head: [
34
+ '<td class="datepickerBlock">',
35
+ '<table cellspacing="0" cellpadding="0">',
36
+ '<thead>',
37
+ '<tr>',
38
+ '<th colspan="7"><a class="datepickerGoPrev" href="#"><span><%=prev%></span></a>',
39
+ '<a class="datepickerMonth" href="#"><span></span></a>',
40
+ '<a class="datepickerGoNext" href="#"><span><%=next%></span></a></th>',
41
+ '</tr>',
42
+ '<tr class="datepickerDoW">',
43
+ '<th><span><%=day1%></span></th>',
44
+ '<th><span><%=day2%></span></th>',
45
+ '<th><span><%=day3%></span></th>',
46
+ '<th><span><%=day4%></span></th>',
47
+ '<th><span><%=day5%></span></th>',
48
+ '<th><span><%=day6%></span></th>',
49
+ '<th><span><%=day7%></span></th>',
50
+ '</tr>',
51
+ '</thead>',
52
+ '</table></td>'
53
+ ],
54
+ space : '<td class="datepickerSpace"><div></div></td>',
55
+ days: [
56
+ '<tbody class="datepickerDays">',
57
+ '<tr>',
58
+ '<td class="<%=weeks[0].days[0].classname%>"><a href="#"><span><%=weeks[0].days[0].text%></span></a></td>',
59
+ '<td class="<%=weeks[0].days[1].classname%>"><a href="#"><span><%=weeks[0].days[1].text%></span></a></td>',
60
+ '<td class="<%=weeks[0].days[2].classname%>"><a href="#"><span><%=weeks[0].days[2].text%></span></a></td>',
61
+ '<td class="<%=weeks[0].days[3].classname%>"><a href="#"><span><%=weeks[0].days[3].text%></span></a></td>',
62
+ '<td class="<%=weeks[0].days[4].classname%>"><a href="#"><span><%=weeks[0].days[4].text%></span></a></td>',
63
+ '<td class="<%=weeks[0].days[5].classname%>"><a href="#"><span><%=weeks[0].days[5].text%></span></a></td>',
64
+ '<td class="<%=weeks[0].days[6].classname%>"><a href="#"><span><%=weeks[0].days[6].text%></span></a></td>',
65
+ '</tr>',
66
+ '<tr>',
67
+ '<td class="<%=weeks[1].days[0].classname%>"><a href="#"><span><%=weeks[1].days[0].text%></span></a></td>',
68
+ '<td class="<%=weeks[1].days[1].classname%>"><a href="#"><span><%=weeks[1].days[1].text%></span></a></td>',
69
+ '<td class="<%=weeks[1].days[2].classname%>"><a href="#"><span><%=weeks[1].days[2].text%></span></a></td>',
70
+ '<td class="<%=weeks[1].days[3].classname%>"><a href="#"><span><%=weeks[1].days[3].text%></span></a></td>',
71
+ '<td class="<%=weeks[1].days[4].classname%>"><a href="#"><span><%=weeks[1].days[4].text%></span></a></td>',
72
+ '<td class="<%=weeks[1].days[5].classname%>"><a href="#"><span><%=weeks[1].days[5].text%></span></a></td>',
73
+ '<td class="<%=weeks[1].days[6].classname%>"><a href="#"><span><%=weeks[1].days[6].text%></span></a></td>',
74
+ '</tr>',
75
+ '<tr>',
76
+ '<td class="<%=weeks[2].days[0].classname%>"><a href="#"><span><%=weeks[2].days[0].text%></span></a></td>',
77
+ '<td class="<%=weeks[2].days[1].classname%>"><a href="#"><span><%=weeks[2].days[1].text%></span></a></td>',
78
+ '<td class="<%=weeks[2].days[2].classname%>"><a href="#"><span><%=weeks[2].days[2].text%></span></a></td>',
79
+ '<td class="<%=weeks[2].days[3].classname%>"><a href="#"><span><%=weeks[2].days[3].text%></span></a></td>',
80
+ '<td class="<%=weeks[2].days[4].classname%>"><a href="#"><span><%=weeks[2].days[4].text%></span></a></td>',
81
+ '<td class="<%=weeks[2].days[5].classname%>"><a href="#"><span><%=weeks[2].days[5].text%></span></a></td>',
82
+ '<td class="<%=weeks[2].days[6].classname%>"><a href="#"><span><%=weeks[2].days[6].text%></span></a></td>',
83
+ '</tr>',
84
+ '<tr>',
85
+ '<td class="<%=weeks[3].days[0].classname%>"><a href="#"><span><%=weeks[3].days[0].text%></span></a></td>',
86
+ '<td class="<%=weeks[3].days[1].classname%>"><a href="#"><span><%=weeks[3].days[1].text%></span></a></td>',
87
+ '<td class="<%=weeks[3].days[2].classname%>"><a href="#"><span><%=weeks[3].days[2].text%></span></a></td>',
88
+ '<td class="<%=weeks[3].days[3].classname%>"><a href="#"><span><%=weeks[3].days[3].text%></span></a></td>',
89
+ '<td class="<%=weeks[3].days[4].classname%>"><a href="#"><span><%=weeks[3].days[4].text%></span></a></td>',
90
+ '<td class="<%=weeks[3].days[5].classname%>"><a href="#"><span><%=weeks[3].days[5].text%></span></a></td>',
91
+ '<td class="<%=weeks[3].days[6].classname%>"><a href="#"><span><%=weeks[3].days[6].text%></span></a></td>',
92
+ '</tr>',
93
+ '<tr>',
94
+ '<td class="<%=weeks[4].days[0].classname%>"><a href="#"><span><%=weeks[4].days[0].text%></span></a></td>',
95
+ '<td class="<%=weeks[4].days[1].classname%>"><a href="#"><span><%=weeks[4].days[1].text%></span></a></td>',
96
+ '<td class="<%=weeks[4].days[2].classname%>"><a href="#"><span><%=weeks[4].days[2].text%></span></a></td>',
97
+ '<td class="<%=weeks[4].days[3].classname%>"><a href="#"><span><%=weeks[4].days[3].text%></span></a></td>',
98
+ '<td class="<%=weeks[4].days[4].classname%>"><a href="#"><span><%=weeks[4].days[4].text%></span></a></td>',
99
+ '<td class="<%=weeks[4].days[5].classname%>"><a href="#"><span><%=weeks[4].days[5].text%></span></a></td>',
100
+ '<td class="<%=weeks[4].days[6].classname%>"><a href="#"><span><%=weeks[4].days[6].text%></span></a></td>',
101
+ '</tr>',
102
+ '<tr>',
103
+ '<td class="<%=weeks[5].days[0].classname%>"><a href="#"><span><%=weeks[5].days[0].text%></span></a></td>',
104
+ '<td class="<%=weeks[5].days[1].classname%>"><a href="#"><span><%=weeks[5].days[1].text%></span></a></td>',
105
+ '<td class="<%=weeks[5].days[2].classname%>"><a href="#"><span><%=weeks[5].days[2].text%></span></a></td>',
106
+ '<td class="<%=weeks[5].days[3].classname%>"><a href="#"><span><%=weeks[5].days[3].text%></span></a></td>',
107
+ '<td class="<%=weeks[5].days[4].classname%>"><a href="#"><span><%=weeks[5].days[4].text%></span></a></td>',
108
+ '<td class="<%=weeks[5].days[5].classname%>"><a href="#"><span><%=weeks[5].days[5].text%></span></a></td>',
109
+ '<td class="<%=weeks[5].days[6].classname%>"><a href="#"><span><%=weeks[5].days[6].text%></span></a></td>',
110
+ '</tr>',
111
+ '</tbody>'
112
+ ],
113
+ months: [
114
+ '<tbody class="<%=className%>">',
115
+ '<tr>',
116
+ '<td colspan="2"><a href="#"><span><%=data[0]%></span></a></td>',
117
+ '<td colspan="2"><a href="#"><span><%=data[1]%></span></a></td>',
118
+ '<td colspan="2"><a href="#"><span><%=data[2]%></span></a></td>',
119
+ '<td colspan="1"><a href="#"><span><%=data[3]%></span></a></td>',
120
+ '</tr>',
121
+ '<tr>',
122
+ '<td colspan="2"><a href="#"><span><%=data[4]%></span></a></td>',
123
+ '<td colspan="2"><a href="#"><span><%=data[5]%></span></a></td>',
124
+ '<td colspan="2"><a href="#"><span><%=data[6]%></span></a></td>',
125
+ '<td colspan="1"><a href="#"><span><%=data[7]%></span></a></td>',
126
+ '</tr>',
127
+ '<tr>',
128
+ '<td colspan="2"><a href="#"><span><%=data[8]%></span></a></td>',
129
+ '<td colspan="2"><a href="#"><span><%=data[9]%></span></a></td>',
130
+ '<td colspan="2"><a href="#"><span><%=data[10]%></span></a></td>',
131
+ '<td colspan="1"><a href="#"><span><%=data[11]%></span></a></td>',
132
+ '</tr>',
133
+ '</tbody>'
134
+ ]
135
+ },
136
+ defaults = {
137
+ /**
138
+ * The currently selected date(s). This can be: a single date, an array
139
+ * of two dates (sets a range when 'mode' is 'range'), or an array of
140
+ * any number of dates (selects all dates when 'mode' is 'multiple'.
141
+ * The supplied dates can be any one of: Date object, milliseconds
142
+ * (as from date.getTime(), date.valueOf()), or a date string
143
+ * parseable by Date.parse().
144
+ */
145
+ date: null,
146
+ /**
147
+ * Optional date which determines the current calendar month/year. This
148
+ * can be one of: Date object, milliseconds (as from date.getTime(), date.valueOf()), or a date string
149
+ * parseable by Date.parse(). Defaults to todays date.
150
+ */
151
+ current: null,
152
+ /**
153
+ * true causes the datepicker calendar to be appended to the DatePicker
154
+ * element and rendered, false binds the DatePicker to an event on the trigger element
155
+ */
156
+ inline: false,
157
+ /**
158
+ * Date selection mode, one of 'single', 'range' or 'multiple'. Default
159
+ * 'single'. 'Single' allows the selection of a single date, 'range'
160
+ * allows the selection of range of dates, and 'multiple' allows the
161
+ * selection of any number of individual dates.
162
+ */
163
+ mode: 'single',
164
+ /**
165
+ * Number of side-by-side calendars, defaults to 1.
166
+ */
167
+ calendars: 1,
168
+ /**
169
+ * The day that starts the week, where 0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday. Defaults to Sunday
170
+ */
171
+ starts: 0,
172
+ /**
173
+ * Previous link text. Default '&#9664;' (Unicode left arrow)
174
+ */
175
+ prev: '&#9664;',
176
+ /**
177
+ * Next link text. Default '&#9664;' (Unicode left arrow)
178
+ */
179
+ next: '&#9654;',
180
+ /**
181
+ * Initial calendar view, one of 'days', 'months' or 'years'. Defaults to 'days'.
182
+ */
183
+ view: 'days',
184
+ /**
185
+ * Date picker's position relative to the trigger element (non inline
186
+ * mode only), one of 'top', 'left', 'right' or 'bottom'. Defaults to 'bottom'
187
+ */
188
+ position: 'bottom',
189
+ /**
190
+ * The trigger event used to show a non-inline calendar. Defaults to
191
+ * 'focus' which is useful when the trigger element is a text input,
192
+ * can also be 'click' for instance if the trigger element is a button
193
+ * or some text element.
194
+ */
195
+ showOn: 'focus',
196
+ /**
197
+ * Callback, invoked prior to the rendering of each date cell, which
198
+ * allows control of the styling of the cell via the returned hash.
199
+ *
200
+ * @param HTMLDivElement el the datepicker containing element, ie the
201
+ * div with class 'datepicker'
202
+ * @param Date date the date that will be rendered
203
+ * @return hash with the following optional attributes:
204
+ * selected: if true, date will be selected
205
+ * disabled: if true, date cell will be disabled
206
+ * className: css class name to add to the cell
207
+ */
208
+ onRenderCell: function() { return {} },
209
+ /*
210
+ * Callback, invoked when a date is selected, with 'this' referring to
211
+ * the HTMLElement that DatePicker was invoked upon.
212
+ *
213
+ * @param dates: Selected date(s) depending on calendar mode. When calendar mode is 'single' this
214
+ * is a single Date object. When calendar mode is 'range', this is an array containing
215
+ * a 'from' and 'to' Date objects. When calendar mode is 'multiple' this is an array
216
+ * of Date objects.
217
+ * @param HTMLElement el the DatePicker element, ie the element that DatePicker was invoked upon
218
+ */
219
+ onChange: function() { },
220
+ /*
221
+ * Callback, invoked when a date range is selected, with 'this' referring to
222
+ * the HTMLElement that DatePicker was invoked upon.
223
+ *
224
+ * @param dates: Selected date(s), ie an array containing a 'from' and 'to' Date objects.
225
+ * @param HTMLElement el the DatePicker element, ie the element that DatePicker was invoked upon
226
+ */
227
+ onRangeChange: function() { },
228
+ /**
229
+ * Invoked before a non-inline datepicker is shown, with 'this'
230
+ * referring to the HTMLElement that DatePicker was invoked upon, ie
231
+ * the trigger element
232
+ *
233
+ * @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'.
234
+ * @return true to allow the datepicker to be shown, false to keep it hidden
235
+ */
236
+
237
+ onBeforeShow: function() { return true },
238
+ /**
239
+ * Invoked after a non-inline datepicker is shown, with 'this'
240
+ * referring to the HTMLElement that DatePicker was invoked upon, ie
241
+ * the trigger element
242
+ *
243
+ * @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'
244
+ */
245
+ onAfterShow: function() { },
246
+ /**
247
+ * Invoked before a non-inline datepicker is hidden, with 'this'
248
+ * referring to the HTMLElement that DatePicker was invoked upon, ie
249
+ * the trigger element
250
+ *
251
+ * @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'
252
+ * @return true to allow the datepicker to be hidden, false to keep it visible
253
+ */
254
+ onBeforeHide: function() { return true },
255
+ /**
256
+ * Invoked after a non-inline datepicker is hidden, with 'this'
257
+ * referring to the HTMLElement that DatePicker was invoked upon, ie
258
+ * the trigger element
259
+ *
260
+ * @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'
261
+ */
262
+ onAfterHide: function() { },
263
+ /**
264
+ * Locale text for day/month names: provide a hash with keys 'daysMin', 'months' and 'monthsShort'. Default english
265
+ */
266
+ locale: {
267
+ daysMin: ["S", "M", "T", "W", "T", "F", "S"],
268
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
269
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
270
+ },
271
+ /**
272
+ * The combined height from the top/bottom borders. 'false' is the default
273
+ * and generally the correct value.
274
+ */
275
+ extraHeight: false,
276
+ /**
277
+ * The combined width from the left/right borders. 'false' is the default
278
+ * and generally the correct value.
279
+ */
280
+ extraWidth: false,
281
+ /**
282
+ * Private option, used to determine when a range is selected
283
+ */
284
+ lastSel: false
285
+ },
286
+
287
+ /**
288
+ * Internal method which renders the calendar cells
289
+ *
290
+ * @param HTMLDivElement el datepicker container element
291
+ */
292
+ fill = function(el) {
293
+ var options = $(el).data('datepicker');
294
+ var cal = $(el);
295
+ var currentCal = Math.floor(options.calendars/2), date, data, dow, month, cnt = 0, days, indic, indic2, html, tblCal;
296
+
297
+ cal.find('td>table tbody').remove();
298
+ for(var i = 0; i < options.calendars; i++) {
299
+ date = new Date(options.current);
300
+ date.addMonths(-currentCal + i);
301
+ tblCal = cal.find('table').eq(i+1);
302
+
303
+ if(i == 0) tblCal.addClass('datepickerFirstView');
304
+ if(i == options.calendars - 1) tblCal.addClass('datepickerLastView');
305
+
306
+ if(tblCal.hasClass('datepickerViewDays')) {
307
+ dow = date.getMonthName(true)+" "+date.getFullYear();
308
+ } else if(tblCal.hasClass('datepickerViewMonths')) {
309
+ dow = date.getFullYear();
310
+ } else if(tblCal.hasClass('datepickerViewYears')) {
311
+ dow = (date.getFullYear()-6) + ' - ' + (date.getFullYear()+5);
312
+ }
313
+ tblCal.find('thead tr:first th a:eq(1) span').text(dow);
314
+ dow = date.getFullYear()-6;
315
+ data = {
316
+ data: [],
317
+ className: 'datepickerYears'
318
+ }
319
+ for( var j = 0; j < 12; j++) {
320
+ data.data.push(dow + j);
321
+ }
322
+ // datepickerYears template
323
+ html = tmpl(tpl.months.join(''), data);
324
+ date.setDate(1);
325
+ data = {weeks:[], test: 10};
326
+ month = date.getMonth();
327
+ var dow = (date.getDay() - options.starts) % 7;
328
+ date.addDays(-(dow + (dow < 0 ? 7 : 0)));
329
+ cnt = 0;
330
+ while(cnt < 42) {
331
+ indic = parseInt(cnt/7,10);
332
+ indic2 = cnt%7;
333
+ if (!data.weeks[indic]) {
334
+ data.weeks[indic] = {
335
+ days: []
336
+ };
337
+ }
338
+ data.weeks[indic].days[indic2] = {
339
+ text: date.getDate(),
340
+ classname: []
341
+ };
342
+ var today = new Date();
343
+ if (today.getDate() == date.getDate() && today.getMonth() == date.getMonth() && today.getYear() == date.getYear()) {
344
+ data.weeks[indic].days[indic2].classname.push('datepickerToday');
345
+ }
346
+ if (date > today) {
347
+ // current month, date in future
348
+ data.weeks[indic].days[indic2].classname.push('datepickerFuture');
349
+ }
350
+
351
+ if (month != date.getMonth()) {
352
+ data.weeks[indic].days[indic2].classname.push('datepickerNotInMonth');
353
+ // disable clicking of the 'not in month' cells
354
+ data.weeks[indic].days[indic2].classname.push('datepickerDisabled');
355
+ }
356
+ if (date.getDay() == 0) {
357
+ data.weeks[indic].days[indic2].classname.push('datepickerSunday');
358
+ }
359
+ if (date.getDay() == 6) {
360
+ data.weeks[indic].days[indic2].classname.push('datepickerSaturday');
361
+ }
362
+ var fromUser = options.onRenderCell(el, date);
363
+ var val = date.valueOf();
364
+ if(options.date && (!$.isArray(options.date) || options.date.length > 0)) {
365
+ if (fromUser.selected || options.date == val || $.inArray(val, options.date) > -1 || (options.mode == 'range' && val >= options.date[0] && val <= options.date[1])) {
366
+ data.weeks[indic].days[indic2].classname.push('datepickerSelected');
367
+ }
368
+ }
369
+ if (fromUser.disabled) {
370
+ data.weeks[indic].days[indic2].classname.push('datepickerDisabled');
371
+ }
372
+ if (fromUser.className) {
373
+ data.weeks[indic].days[indic2].classname.push(fromUser.className);
374
+ }
375
+ data.weeks[indic].days[indic2].classname = data.weeks[indic].days[indic2].classname.join(' ');
376
+ cnt++;
377
+ date.addDays(1);
378
+ }
379
+ // Fill the datepickerDays template with data
380
+ html = tmpl(tpl.days.join(''), data) + html;
381
+
382
+ data = {
383
+ data: options.locale.monthsShort,
384
+ className: 'datepickerMonths'
385
+ };
386
+ // datepickerMonths template
387
+ html = tmpl(tpl.months.join(''), data) + html;
388
+ tblCal.append(html);
389
+ }
390
+ },
391
+
392
+ /**
393
+ * Extends the Date object with some useful helper methods
394
+ */
395
+ extendDate = function(locale) {
396
+ if (Date.prototype.tempDate) {
397
+ return;
398
+ }
399
+ Date.prototype.tempDate = null;
400
+ Date.prototype.months = locale.months;
401
+ Date.prototype.monthsShort = locale.monthsShort;
402
+ Date.prototype.getMonthName = function(fullName) {
403
+ return this[fullName ? 'months' : 'monthsShort'][this.getMonth()];
404
+ };
405
+ Date.prototype.addDays = function (n) {
406
+ this.setDate(this.getDate() + n);
407
+ this.tempDate = this.getDate();
408
+ };
409
+ Date.prototype.addMonths = function (n) {
410
+ if (this.tempDate == null) {
411
+ this.tempDate = this.getDate();
412
+ }
413
+ this.setDate(1);
414
+ this.setMonth(this.getMonth() + n);
415
+ this.setDate(Math.min(this.tempDate, this.getMaxDays()));
416
+ };
417
+ Date.prototype.addYears = function (n) {
418
+ if (this.tempDate == null) {
419
+ this.tempDate = this.getDate();
420
+ }
421
+ this.setDate(1);
422
+ this.setFullYear(this.getFullYear() + n);
423
+ this.setDate(Math.min(this.tempDate, this.getMaxDays()));
424
+ };
425
+ Date.prototype.getMaxDays = function() {
426
+ var tmpDate = new Date(Date.parse(this)),
427
+ d = 28, m;
428
+ m = tmpDate.getMonth();
429
+ d = 28;
430
+ while (tmpDate.getMonth() == m) {
431
+ d ++;
432
+ tmpDate.setDate(d);
433
+ }
434
+ return d - 1;
435
+ };
436
+ },
437
+
438
+ /**
439
+ * Internal method which lays out the calendar widget
440
+ */
441
+ layout = function(el) {
442
+ var options = $(el).data('datepicker');
443
+ var cal = $('#' + options.id);
444
+ if (options.extraHeight === false) {
445
+ var divs = $(el).find('div');
446
+ options.extraHeight = divs.get(0).offsetHeight + divs.get(1).offsetHeight; // heights from top/bottom borders
447
+ options.extraWidth = divs.get(2).offsetWidth + divs.get(3).offsetWidth; // widths from left/right borders
448
+ }
449
+ var tbl = cal.find('table:first').get(0);
450
+ var width = tbl.offsetWidth;
451
+ var height = tbl.offsetHeight;
452
+ cal.css({
453
+ width: width + options.extraWidth + 'px',
454
+ height: height + options.extraHeight + 'px'
455
+ }).find('div.datepickerContainer').css({
456
+ width: width + 'px',
457
+ height: height + 'px'
458
+ });
459
+ },
460
+
461
+ /**
462
+ * Internal method, bound to the HTML DatePicker Element, onClick.
463
+ * This is the function that controls the behavior of the calendar when
464
+ * the title, next/previous, or a date cell is clicked on.
465
+ */
466
+ click = function(ev) {
467
+ if ($(ev.target).is('span')) {
468
+ ev.target = ev.target.parentNode;
469
+ }
470
+ var el = $(ev.target);
471
+ if (el.is('a')) {
472
+ ev.target.blur();
473
+ if (el.hasClass('datepickerDisabled')) {
474
+ return false;
475
+ }
476
+ var options = $(this).data('datepicker');
477
+ var parentEl = el.parent();
478
+ var tblEl = parentEl.parent().parent().parent();
479
+ var tblIndex = $('table', this).index(tblEl.get(0)) - 1;
480
+ var tmp = new Date(options.current);
481
+ var changed = false;
482
+ var changedRange = false;
483
+ var fillIt = false;
484
+ var currentCal = Math.floor(options.calendars/2);
485
+
486
+ if (parentEl.is('th')) {
487
+ // clicking the calendar title
488
+
489
+ if (el.hasClass('datepickerMonth')) {
490
+ // clicking on the title of a Month Datepicker
491
+ tmp.addMonths(tblIndex - currentCal);
492
+
493
+ if(options.mode == 'range') {
494
+ // range, select the whole month
495
+ options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
496
+ tmp.addDays(tmp.getMaxDays()-1);
497
+ tmp.setHours(23,59,59,0);
498
+ options.date[1] = tmp.valueOf();
499
+ fillIt = true;
500
+ changed = true;
501
+ options.lastSel = false;
502
+ } else if(options.calendars == 1) {
503
+ // single/multiple mode with a single calendar: swap between daily/monthly/yearly view.
504
+ // Note: there's no reason a multi-calendar widget can't have this functionality,
505
+ // however I think it looks really unintuitive.
506
+ if(tblEl.eq(0).hasClass('datepickerViewDays')) {
507
+ tblEl.eq(0).toggleClass('datepickerViewDays datepickerViewMonths');
508
+ el.find('span').text(tmp.getFullYear());
509
+ } else if(tblEl.eq(0).hasClass('datepickerViewMonths')) {
510
+ tblEl.eq(0).toggleClass('datepickerViewMonths datepickerViewYears');
511
+ el.find('span').text((tmp.getFullYear()-6) + ' - ' + (tmp.getFullYear()+5));
512
+ } else if(tblEl.eq(0).hasClass('datepickerViewYears')) {
513
+ tblEl.eq(0).toggleClass('datepickerViewYears datepickerViewDays');
514
+ el.find('span').text(tmp.getMonthName(true)+", "+tmp.getFullYear());
515
+ }
516
+ }
517
+ } else if (parentEl.parent().parent().is('thead')) {
518
+ // clicked either next/previous arrows
519
+ if(tblEl.eq(0).hasClass('datepickerViewDays')) {
520
+ options.current.addMonths(el.hasClass('datepickerGoPrev') ? -1 : 1);
521
+ } else if(tblEl.eq(0).hasClass('datepickerViewMonths')) {
522
+ options.current.addYears(el.hasClass('datepickerGoPrev') ? -1 : 1);
523
+ } else if(tblEl.eq(0).hasClass('datepickerViewYears')) {
524
+ options.current.addYears(el.hasClass('datepickerGoPrev') ? -12 : 12);
525
+ }
526
+ fillIt = true;
527
+ }
528
+
529
+ } else if (parentEl.is('td') && !parentEl.hasClass('datepickerDisabled')) {
530
+ // clicking the calendar grid
531
+
532
+ if(tblEl.eq(0).hasClass('datepickerViewMonths')) {
533
+ // clicked a month cell
534
+ options.current.setMonth(tblEl.find('tbody.datepickerMonths td').index(parentEl));
535
+ options.current.setFullYear(parseInt(tblEl.find('thead th a.datepickerMonth span').text(), 10));
536
+ options.current.addMonths(currentCal - tblIndex);
537
+ tblEl.eq(0).toggleClass('datepickerViewMonths datepickerViewDays');
538
+ } else if(tblEl.eq(0).hasClass('datepickerViewYears')) {
539
+ // clicked a year cell
540
+ options.current.setFullYear(parseInt(el.text(), 10));
541
+ tblEl.eq(0).toggleClass('datepickerViewYears datepickerViewMonths');
542
+ } else {
543
+ // clicked a day cell
544
+ var val = parseInt(el.text(), 10);
545
+ tmp.addMonths(tblIndex - currentCal);
546
+ if (parentEl.hasClass('datepickerNotInMonth')) {
547
+ tmp.addMonths(val > 15 ? -1 : 1);
548
+ }
549
+ tmp.setDate(val);
550
+ switch (options.mode) {
551
+ case 'multiple':
552
+ val = (tmp.setHours(0,0,0,0)).valueOf();
553
+ if ($.inArray(val, options.date) > -1) {
554
+ $.each(options.date, function(nr, dat){
555
+ if (dat == val) {
556
+ options.date.splice(nr,1);
557
+ return false;
558
+ }
559
+ });
560
+ } else {
561
+ options.date.push(val);
562
+ }
563
+ break;
564
+ case 'range':
565
+ if (!options.lastSel) {
566
+ // first click: set to the start of the day
567
+ options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
568
+ }
569
+ // get the very end of the day clicked
570
+ val = (tmp.setHours(23,59,59,0)).valueOf();
571
+
572
+ if (val < options.date[0]) {
573
+ // second range click < first
574
+ options.date[1] = options.date[0] + 86399000; // starting date + 1 day
575
+ options.date[0] = val - 86399000; // minus 1 day
576
+
577
+ } else {
578
+ // initial range click, or final range click >= first
579
+ options.date[1] = val;
580
+ }
581
+ options.lastSel = !options.lastSel;
582
+ changedRange = !options.lastSel;
583
+ break;
584
+ default:
585
+ options.date = tmp.valueOf();
586
+ break;
587
+ }
588
+ changed = true;
589
+ }
590
+ fillIt = true;
591
+ }
592
+ if(fillIt) {
593
+ fill(this);
594
+ }
595
+ if(changed) {
596
+ options.onChange.apply(this, prepareDate(options));
597
+ }
598
+ if(changedRange) {
599
+ options.onRangeChange.apply(this, prepareDate(options));
600
+ }
601
+ }
602
+ return false;
603
+ },
604
+
605
+ /**
606
+ * Internal method, called from the public getDate() method, and when
607
+ * invoking the onChange callback function
608
+ *
609
+ * @param object options with the following attributes: 'mode' which can
610
+ * be one of 'single', 'range', or 'multiple'. Attribute 'date'
611
+ * which will be a single timestamp when 'mode' is 'single', or
612
+ * an array of timestamps otherwise. Attribute 'el' which is the
613
+ * HTML element that DatePicker was invoked upon.
614
+ * @return array where the first item is either a Date object, or an
615
+ * array of Date objects, depending on the DatePicker mode, and
616
+ * the second item is the HTMLElement that DatePicker was invoked
617
+ * upon.
618
+ */
619
+ prepareDate = function (options) {
620
+ var dates = null;
621
+ if (options.mode == 'single') {
622
+ if(options.date) dates = new Date(options.date);
623
+ } else {
624
+ dates = new Array();
625
+ $(options.date).each(function(i, val){
626
+ dates.push(new Date(val));
627
+ });
628
+ }
629
+ return [dates, options.el];
630
+ },
631
+
632
+ /**
633
+ * Internal method, returns an object containing the viewport dimensions
634
+ */
635
+ getViewport = function () {
636
+ var m = document.compatMode == 'CSS1Compat';
637
+ return {
638
+ l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
639
+ t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
640
+ w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
641
+ h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
642
+ };
643
+ },
644
+
645
+ /**
646
+ * Internal method, returns true if el is a child of parentEl
647
+ */
648
+ isChildOf = function(parentEl, el, container) {
649
+ if(parentEl == el) {
650
+ return true;
651
+ }
652
+ if(parentEl.contains) {
653
+ return parentEl.contains(el);
654
+ }
655
+ if( parentEl.compareDocumentPosition ) {
656
+ return !!(parentEl.compareDocumentPosition(el) & 16);
657
+ }
658
+ var prEl = el.parentNode;
659
+ while(prEl && prEl != container) {
660
+ if(prEl == parentEl)
661
+ return true;
662
+ prEl = prEl.parentNode;
663
+ }
664
+ return false;
665
+ },
666
+
667
+ /**
668
+ * Bound to the HTML DatePicker element when it's not inline, and also
669
+ * can be called directly to show the bound datepicker. A DatePicker
670
+ * calendar shown with this method will hide on a mouseclick outside
671
+ * of the calendar.
672
+ *
673
+ * Method is not applicable for inline DatePickers
674
+ */
675
+ show = function (ev) {
676
+ var cal = $('#' + $(this).data('datepickerId'));
677
+ if (!cal.is(':visible')) {
678
+ var calEl = cal.get(0);
679
+ var options = cal.data('datepicker');
680
+
681
+ var test = options.onBeforeShow.apply(this, [calEl]);
682
+ if(options.onBeforeShow.apply(this, [calEl]) == false) {
683
+ return;
684
+ }
685
+
686
+ fill(calEl);
687
+ var pos = $(this).offset();
688
+ var viewPort = getViewport();
689
+ var top = pos.top;
690
+ var left = pos.left;
691
+ cal.css({
692
+ visibility: 'hidden',
693
+ display: 'block'
694
+ });
695
+ layout(calEl);
696
+ switch (options.position){
697
+ case 'top':
698
+ top -= calEl.offsetHeight;
699
+ break;
700
+ case 'left':
701
+ left -= calEl.offsetWidth;
702
+ break;
703
+ case 'right':
704
+ left += this.offsetWidth;
705
+ break;
706
+ case 'bottom':
707
+ top += this.offsetHeight;
708
+ break;
709
+ }
710
+ if(top + calEl.offsetHeight > viewPort.t + viewPort.h) {
711
+ top = pos.top - calEl.offsetHeight;
712
+ }
713
+ if(top < viewPort.t) {
714
+ top = pos.top + this.offsetHeight + calEl.offsetHeight;
715
+ }
716
+ if(left + calEl.offsetWidth > viewPort.l + viewPort.w) {
717
+ left = pos.left - calEl.offsetWidth;
718
+ }
719
+ if(left < viewPort.l) {
720
+ left = pos.left + this.offsetWidth
721
+ }
722
+ cal.css({
723
+ visibility: 'visible',
724
+ display: 'block',
725
+ top: top + 'px',
726
+ left: left + 'px'
727
+ });
728
+ options.onAfterShow.apply(this, [cal.get(0)]);
729
+ $(document).bind('mousedown', {cal: cal, trigger: this}, hide); // global listener so clicking outside the calendar will close it
730
+ }
731
+ return false;
732
+ },
733
+
734
+ /**
735
+ * Hide a non-inline DatePicker calendar.
736
+ *
737
+ * Not applicable for inline DatePickers.
738
+ *
739
+ * @param ev Event object
740
+ */
741
+ hide = function (ev) {
742
+ if (ev.target != ev.data.trigger && !isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
743
+ if (ev.data.cal.data('datepicker').onBeforeHide.apply(this, [ev.data.cal.get(0)]) != false) {
744
+ ev.data.cal.hide();
745
+ ev.data.cal.data('datepicker').onAfterHide.apply(this, [ev.data.cal.get(0)]);
746
+ $(document).unbind('mousedown', hide); // remove the global listener
747
+ }
748
+ }
749
+ },
750
+
751
+ /**
752
+ * Internal method to normalize the selected date based on the current
753
+ * calendar mode.
754
+ */
755
+ normalizeDate = function (mode, date) {
756
+ // if range/multi mode, make sure that the current date value is at least an empty array
757
+ if(mode != 'single' && !date) date = [];
758
+
759
+ // if we have a selected date and not a null or empty array
760
+ if(date && (!$.isArray(date) || date.length > 0)) {
761
+ // Create a standardized date depending on the calendar mode
762
+ if (mode != 'single') {
763
+ if (!$.isArray(date)) {
764
+ date = [((new Date(date)).setHours(0,0,0,0)).valueOf()];
765
+ if (mode == 'range') {
766
+ // create a range of one day
767
+ date.push(((new Date(date[0])).setHours(23,59,59,0)).valueOf());
768
+ }
769
+ } else {
770
+ for (var i = 0; i < date.length; i++) {
771
+ date[i] = ((new Date(date[i])).setHours(0,0,0,0)).valueOf();
772
+ }
773
+ if (mode == 'range') {
774
+ // for range mode, create the other end of the range
775
+ if(date.length == 1) date.push(new Date(date[0]));
776
+ date[1] = ((new Date(date[1])).setHours(23,59,59,0)).valueOf();
777
+ }
778
+ }
779
+ } else {
780
+ // mode is single, convert date object into a timestamp
781
+ date = ((new Date(date)).setHours(0,0,0,0)).valueOf();
782
+ }
783
+ // at this point date is either a timestamp at hour zero
784
+ // for 'single' mode, an array of timestamps at hour zero for
785
+ // 'multiple' mode, or a two-item array with timestamps at hour
786
+ // zero and hour 23:59 for 'range' mode
787
+ }
788
+ return date;
789
+ };
790
+ return {
791
+ /**
792
+ * 'Public' functions
793
+ */
794
+
795
+ /**
796
+ * Called when element.DatePicker() is invoked
797
+ *
798
+ * Note that 'this' is the HTML element that DatePicker was invoked upon
799
+ * @see DatePicker()
800
+ */
801
+ init: function(options){
802
+ options = $.extend({}, defaults, options||{});
803
+ extendDate(options.locale);
804
+ options.calendars = Math.max(1, parseInt(options.calendars,10)||1);
805
+ options.mode = /single|multiple|range/.test(options.mode) ? options.mode : 'single';
806
+
807
+ return this.each(function(){
808
+ if (!$(this).data('datepicker')) {
809
+ options.el = this;
810
+
811
+ options.date = normalizeDate(options.mode, options.date);
812
+
813
+ if (!options.current) {
814
+ options.current = new Date();
815
+ } else {
816
+ options.current = new Date(options.current);
817
+ }
818
+ options.current.setDate(1);
819
+ options.current.setHours(0,0,0,0);
820
+
821
+ var id = 'datepicker_' + parseInt(Math.random() * 1000), cnt;
822
+ options.id = id;
823
+ $(this).data('datepickerId', options.id);
824
+ var cal = $(tpl.wrapper).attr('id', id).bind('click', click).data('datepicker', options);
825
+ if (options.className) {
826
+ cal.addClass(options.className);
827
+ }
828
+ var html = '';
829
+ for (var i = 0; i < options.calendars; i++) {
830
+ cnt = options.starts;
831
+ if (i > 0) {
832
+ html += tpl.space;
833
+ }
834
+ // calendar header template
835
+ html += tmpl(tpl.head.join(''), {
836
+ prev: options.prev,
837
+ next: options.next,
838
+ day1: options.locale.daysMin[(cnt++)%7],
839
+ day2: options.locale.daysMin[(cnt++)%7],
840
+ day3: options.locale.daysMin[(cnt++)%7],
841
+ day4: options.locale.daysMin[(cnt++)%7],
842
+ day5: options.locale.daysMin[(cnt++)%7],
843
+ day6: options.locale.daysMin[(cnt++)%7],
844
+ day7: options.locale.daysMin[(cnt++)%7]
845
+ });
846
+ }
847
+ cal
848
+ .find('tr:first').append(html)
849
+ .find('table').addClass(views[options.view]);
850
+ fill(cal.get(0));
851
+ if (options.inline) {
852
+ cal.appendTo(this).show().css('position', 'relative');
853
+ layout(cal.get(0));
854
+ } else {
855
+ cal.appendTo(document.body);
856
+ $(this).bind(options.showOn, show);
857
+ }
858
+ }
859
+ });
860
+ },
861
+
862
+ /**
863
+ * Shows the DatePicker, applicable only when the picker is not inline
864
+ *
865
+ * @return the DatePicker HTML element
866
+ * @see DatePickerShow()
867
+ */
868
+ showPicker: function() {
869
+ return this.each( function() {
870
+ if ($(this).data('datepickerId')) {
871
+ var cal = $('#' + $(this).data('datepickerId'));
872
+ var options = cal.data('datepicker');
873
+ if(!options.inline) {
874
+ show.apply(this);
875
+ }
876
+ }
877
+ });
878
+ },
879
+
880
+ /**
881
+ * Hides the DatePicker, applicable only when the picker is not inline
882
+ *
883
+ * @return the DatePicker HTML element
884
+ * @see DatePickerHide()
885
+ */
886
+ hidePicker: function() {
887
+ return this.each( function() {
888
+ if ($(this).data('datepickerId')) {
889
+ var cal = $('#' + $(this).data('datepickerId'));
890
+ var options = cal.data('datepicker');
891
+ if(!options.inline) {
892
+ $('#' + $(this).data('datepickerId')).hide();
893
+ }
894
+ }
895
+ });
896
+ },
897
+
898
+ /**
899
+ * Sets the DatePicker current date, and optionally shifts the current
900
+ * calendar to that date.
901
+ *
902
+ * @param Date|String|int|Array date The currently selected date(s).
903
+ * This can be: a single date, an array
904
+ * of two dates (sets a range when 'mode' is 'range'), or an array of
905
+ * any number of dates (selects all dates when 'mode' is 'multiple'.
906
+ * The supplied dates can be any one of: Date object, milliseconds
907
+ * (as from date.getTime(), date.valueOf()), or a date string
908
+ * parseable by Date.parse().
909
+ * @param boolean shiftTo if true, shifts the visible calendar to the
910
+ * newly set date(s)
911
+ *
912
+ * @see DatePickerSetDate()
913
+ */
914
+ setDate: function(date, shiftTo){
915
+ return this.each(function(){
916
+ if ($(this).data('datepickerId')) {
917
+ var cal = $('#' + $(this).data('datepickerId'));
918
+ var options = cal.data('datepicker');
919
+ options.date = normalizeDate(options.mode, date);
920
+
921
+ if (shiftTo) {
922
+ options.current = new Date(options.mode != 'single' ? options.date[0] : options.date);
923
+ }
924
+ fill(cal.get(0));
925
+ }
926
+ });
927
+ },
928
+
929
+ /**
930
+ * Returns the currently selected date(s) and the datepicker element.
931
+ *
932
+ * @return array where the first element is the selected date(s) When calendar mode is 'single' this
933
+ * is a single date object, or null if no date is selected. When calendar mode is 'range', this is an array containing
934
+ * a 'from' and 'to' date objects, or the empty array if no date range is selected. When calendar mode is 'multiple' this
935
+ * is an array of Date objects, or the empty array if no date is selected.
936
+ * The second element is the HTMLElement that DatePicker was invoked upon
937
+ *
938
+ * @see DatePickerGetDate()
939
+ */
940
+ getDate: function() {
941
+ if (this.size() > 0) {
942
+ return prepareDate($('#' + $(this).data('datepickerId')).data('datepicker'));
943
+ }
944
+ },
945
+
946
+ /**
947
+ * Clears the currently selected date(s)
948
+ *
949
+ * @see DatePickerClear()
950
+ */
951
+ clear: function(){
952
+ return this.each(function(){
953
+ if ($(this).data('datepickerId')) {
954
+ var cal = $('#' + $(this).data('datepickerId'));
955
+ var options = cal.data('datepicker');
956
+ if (options.mode == 'single') {
957
+ options.date = null;
958
+ } else {
959
+ options.date = [];
960
+ }
961
+ fill(cal.get(0));
962
+ }
963
+ });
964
+ },
965
+
966
+ /**
967
+ * Only applicable when the DatePicker is inline
968
+ *
969
+ * @see DatePickerLayout()
970
+ */
971
+ fixLayout: function(){
972
+ return this.each(function(){
973
+ if ($(this).data('datepickerId')) {
974
+ var cal = $('#' + $(this).data('datepickerId'));
975
+ var options = cal.data('datepicker');
976
+ if(options.inline) {
977
+ layout(cal.get(0));
978
+ }
979
+ }
980
+ });
981
+ }
982
+ };
983
+ }(); // DatePicker
984
+
985
+ // Extend jQuery with the following functions so that they can be called on HTML elements, ie: $('#widgetCalendar').DatePicker();
986
+ $.fn.extend({
987
+ DatePicker: DatePicker.init,
988
+ DatePickerHide: DatePicker.hidePicker,
989
+ DatePickerShow: DatePicker.showPicker,
990
+ DatePickerSetDate: DatePicker.setDate,
991
+ DatePickerGetDate: DatePicker.getDate,
992
+ DatePickerClear: DatePicker.clear,
993
+ DatePickerLayout: DatePicker.fixLayout
994
+ });
995
+
996
+ tmpl = function tmpl(str, data){
997
+ // Figure out if we're getting a template, or if we need to
998
+ // load the template - and be sure to cache the result.
999
+ var fn = !/\W/.test(str) ?
1000
+ cache[str] = cache[str] ||
1001
+ tmpl(document.getElementById(str).innerHTML) :
1002
+
1003
+ // Generate a reusable function that will serve as a template
1004
+ // generator (and which will be cached).
1005
+ new Function("obj",
1006
+ "var p=[],print=function(){p.push.apply(p,arguments);};" +
1007
+
1008
+ // Introduce the data as local variables using with(){}
1009
+ "with(obj){p.push('" +
1010
+
1011
+ // Convert the template into pure JavaScript
1012
+ str
1013
+ .replace(/[\r\t\n]/g, " ")
1014
+ .split("<%").join("\t")
1015
+ .replace(/((^|%>)[^\t]*)'/g, "$1\r")
1016
+ .replace(/\t=(.*?)%>/g, "',$1,'")
1017
+ .split("\t").join("');")
1018
+ .split("%>").join("p.push('")
1019
+ .split("\r").join("\\'")
1020
+ + "');}return p.join('');");
1021
+
1022
+ // Provide some basic currying to the user
1023
+ return data ? fn( data ) : fn;
1024
+ };
1025
+
1026
+ })(jQuery);