droom 0.0.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (459) hide show
  1. data/README.md +2 -2
  2. data/app/assets/images/droom/Untitled-1.png +0 -0
  3. data/app/assets/images/droom/acceptance.png +0 -0
  4. data/app/assets/images/droom/add.png +0 -0
  5. data/app/assets/images/droom/asterisk.png +0 -0
  6. data/app/assets/images/droom/asterisk_up.png +0 -0
  7. data/app/assets/images/droom/checkboxes.png +0 -0
  8. data/app/assets/images/droom/clear.png +0 -0
  9. data/app/assets/images/droom/cog.png +0 -0
  10. data/app/assets/images/droom/copy.png +0 -0
  11. data/app/assets/images/droom/copy_to_dropbox.png +0 -0
  12. data/app/assets/images/droom/crosses.png +0 -0
  13. data/app/assets/images/droom/dark_scrap_icons.png +0 -0
  14. data/app/assets/images/droom/defilter.png +0 -0
  15. data/app/assets/images/droom/delete.png +0 -0
  16. data/app/assets/images/droom/dropbox.png +0 -0
  17. data/app/assets/images/droom/dropbox_button.png +0 -0
  18. data/app/assets/images/droom/dropbox_button_small.png +0 -0
  19. data/app/assets/images/droom/edit.png +0 -0
  20. data/app/assets/images/droom/expand.png +0 -0
  21. data/app/assets/images/droom/expander.png +0 -0
  22. data/app/assets/images/droom/folder.png +0 -0
  23. data/app/assets/images/droom/image_box.png +0 -0
  24. data/app/assets/images/droom/in_dropbox.png +0 -0
  25. data/app/assets/images/droom/integration_buttons.png +0 -0
  26. data/app/assets/images/droom/leftright.png +0 -0
  27. data/app/assets/images/droom/manage.png +0 -0
  28. data/app/assets/images/droom/medium_object_icons.png +0 -0
  29. data/app/assets/images/droom/object_icons.png +0 -0
  30. data/app/assets/images/droom/playable.png +0 -0
  31. data/app/assets/images/droom/revoke.png +0 -0
  32. data/app/assets/images/droom/scrap_icons.png +0 -0
  33. data/app/assets/images/droom/search.png +0 -0
  34. data/app/assets/images/droom/small_asterisk.png +0 -0
  35. data/app/assets/images/droom/small_cog.png +0 -0
  36. data/app/assets/images/droom/small_download.png +0 -0
  37. data/app/assets/images/droom/small_image_box.png +0 -0
  38. data/app/assets/images/droom/smalladd.png +0 -0
  39. data/app/assets/images/droom/smallarrows.png +0 -0
  40. data/app/assets/images/droom/smallcopy.png +0 -0
  41. data/app/assets/images/droom/smalldelete.png +0 -0
  42. data/app/assets/images/droom/smalldownload.png +0 -0
  43. data/app/assets/images/droom/smalledit.png +0 -0
  44. data/app/assets/images/droom/smallmanage.png +0 -0
  45. data/app/assets/images/droom/star.png +0 -0
  46. data/app/assets/images/droom/symbols.png +0 -0
  47. data/app/assets/images/droom/tinyarrows.png +0 -0
  48. data/app/assets/images/droom/to_dropbox.png +0 -0
  49. data/app/assets/images/droom/twisty.png +0 -0
  50. data/app/assets/images/droom/youtube_icon.png +0 -0
  51. data/app/assets/javascripts/droom.js.coffee +62 -65
  52. data/app/assets/javascripts/droom/actions.js.coffee +492 -0
  53. data/app/assets/javascripts/droom/ajax.js.coffee +84 -0
  54. data/app/assets/javascripts/droom/{lib/extensions.js.coffee → extensions.js.coffee} +22 -15
  55. data/app/assets/javascripts/droom/lib/ZeroClipboard.js +334 -0
  56. data/app/assets/javascripts/droom/lib/ZeroClipboard.swf +0 -0
  57. data/app/assets/javascripts/droom/lib/ZeroClipboard10.swf +0 -0
  58. data/app/assets/javascripts/droom/map.js.coffee +124 -86
  59. data/app/assets/javascripts/droom/popups.js.coffee +252 -0
  60. data/app/assets/javascripts/droom/stream.js.coffee +92 -0
  61. data/app/assets/javascripts/droom/utilities.js.coffee +120 -0
  62. data/app/assets/javascripts/droom/widgets.js.coffee +1209 -0
  63. data/app/assets/stylesheets/_definitions.css.sass +189 -0
  64. data/app/assets/stylesheets/droom.css.sass +1429 -376
  65. data/app/assets/stylesheets/lib/_kalendae.css.sass +2 -5
  66. data/app/assets/stylesheets/lib/_popups.css.sass +86 -0
  67. data/app/assets/stylesheets/lib/_toolbar.css.sass +17 -11
  68. data/app/controllers/droom/agenda_categories_controller.rb +24 -0
  69. data/app/controllers/droom/calendars_controller.rb +29 -0
  70. data/app/controllers/droom/confirmations_controller.rb +38 -0
  71. data/app/controllers/droom/dashboard_controller.rb +2 -0
  72. data/app/controllers/droom/documents_controller.rb +42 -51
  73. data/app/controllers/droom/dropbox_tokens_controller.rb +61 -0
  74. data/app/controllers/droom/engine_controller.rb +8 -23
  75. data/app/controllers/droom/events_controller.rb +39 -27
  76. data/app/controllers/droom/folders_controller.rb +106 -0
  77. data/app/controllers/droom/group_invitations_controller.rb +15 -7
  78. data/app/controllers/droom/groups_controller.rb +4 -4
  79. data/app/controllers/droom/invitations_controller.rb +37 -9
  80. data/app/controllers/droom/memberships_controller.rb +5 -3
  81. data/app/controllers/droom/organisations_controller.rb +53 -0
  82. data/app/controllers/droom/people_controller.rb +46 -27
  83. data/app/controllers/droom/preferences_controller.rb +34 -0
  84. data/app/controllers/droom/scraps_controller.rb +77 -0
  85. data/app/controllers/droom/search_controller.rb +66 -0
  86. data/app/controllers/droom/suggestions_controller.rb +22 -35
  87. data/app/controllers/droom/users_controller.rb +69 -0
  88. data/app/controllers/droom/venues_controller.rb +1 -2
  89. data/app/controllers/droom/youtube_controller.rb +22 -0
  90. data/app/helpers/droom/droom_helper.rb +93 -5
  91. data/app/models/droom/agenda_category.rb +8 -1
  92. data/app/models/droom/calendar.rb +19 -0
  93. data/app/models/droom/category.rb +4 -6
  94. data/app/models/droom/document.rb +103 -64
  95. data/app/models/droom/document_attachment.rb +13 -47
  96. data/app/models/droom/dropbox_document.rb +41 -0
  97. data/app/models/droom/dropbox_token.rb +29 -0
  98. data/app/models/droom/event.rb +125 -90
  99. data/app/models/droom/folder.rb +134 -0
  100. data/app/models/droom/group.rb +68 -27
  101. data/app/models/droom/group_invitation.rb +12 -3
  102. data/app/models/droom/invitation.rb +50 -8
  103. data/app/models/droom/mailing_list_membership.rb +128 -0
  104. data/app/models/droom/membership.rb +71 -9
  105. data/app/models/droom/organisation.rb +22 -0
  106. data/app/models/droom/page.rb +3 -3
  107. data/app/models/droom/person.rb +180 -166
  108. data/app/models/droom/personal_folder.rb +31 -0
  109. data/app/models/droom/preference.rb +35 -0
  110. data/app/models/droom/recurrence_rule.rb +1 -1
  111. data/app/models/droom/scrap.rb +110 -0
  112. data/app/models/droom/tag.rb +120 -0
  113. data/app/models/droom/tagging.rb +13 -0
  114. data/app/models/droom/user.rb +211 -0
  115. data/app/models/droom/user_action_observer.rb +12 -0
  116. data/app/models/droom/venue.rb +56 -39
  117. data/app/views/cropper/uploads/_crop.html.haml +46 -0
  118. data/app/views/devise/mailer/confirmation_instructions.en.html.haml +24 -0
  119. data/app/views/devise/mailer/reset_password_instructions.en.html.haml +21 -0
  120. data/app/views/devise/passwords/edit.html.haml +31 -0
  121. data/app/views/devise/passwords/new.html.haml +21 -0
  122. data/app/views/devise/sessions/new.html.haml +33 -0
  123. data/app/views/droom/agenda_categories/_form.html.haml +22 -0
  124. data/app/views/droom/agenda_categories/new.html.haml +6 -0
  125. data/app/views/droom/calendars/_action_menu.html.haml +6 -0
  126. data/app/views/droom/calendars/index.html.haml +12 -0
  127. data/app/views/droom/calendars/show.rss.builder +0 -0
  128. data/app/views/droom/confirmations/show.html.haml +40 -0
  129. data/app/views/droom/dashboard/_calendar.html.haml +1 -0
  130. data/app/views/droom/dashboard/_folders.html.haml +5 -0
  131. data/app/views/droom/dashboard/_future_events.html.haml +18 -0
  132. data/app/views/droom/dashboard/_invitations.html.haml +1 -0
  133. data/app/views/droom/dashboard/_past_events.haml +14 -0
  134. data/app/views/droom/dashboard/_quicksearch.html.haml +6 -0
  135. data/app/views/droom/dashboard/_stream.html.haml +9 -0
  136. data/app/views/droom/dashboard/index.html.haml +5 -3
  137. data/app/views/droom/documents/_action_menu.html.haml +7 -0
  138. data/app/views/droom/documents/_documents.html.haml +5 -0
  139. data/app/views/droom/documents/_documents_list.html.haml +6 -6
  140. data/app/views/droom/documents/_documents_table.html.haml +29 -10
  141. data/app/views/droom/documents/_form.html.haml +3 -7
  142. data/app/views/droom/documents/_listing.html.haml +5 -6
  143. data/app/views/droom/documents/_pagination.html.haml +8 -0
  144. data/app/views/droom/documents/_search_result.html.haml +14 -0
  145. data/app/views/droom/documents/_suggested.html.haml +0 -5
  146. data/app/views/droom/documents/_table_document.html.haml +2 -8
  147. data/app/views/droom/documents/edit.html.haml +7 -1
  148. data/app/views/droom/documents/index.html.haml +10 -27
  149. data/app/views/droom/documents/new.html.haml +10 -1
  150. data/app/views/droom/dropbox_tokens/new.html.haml +6 -0
  151. data/app/views/droom/events/_action_menu.html.haml +15 -0
  152. data/app/views/droom/events/_event.html.haml +67 -57
  153. data/app/views/droom/events/_form.html.haml +15 -4
  154. data/app/views/droom/events/_invitations.html.haml +4 -19
  155. data/app/views/droom/events/_search_result.html.haml +19 -0
  156. data/app/views/droom/events/_views.html.haml +2 -2
  157. data/app/views/droom/events/edit.html.haml +7 -1
  158. data/app/views/droom/events/index.html.haml +27 -10
  159. data/app/views/droom/events/index.rss.builder +1 -1
  160. data/app/views/droom/events/new.html.haml +6 -1
  161. data/app/views/droom/events/show.html.haml +5 -1
  162. data/app/views/droom/folders/_action_menu.html.haml +14 -0
  163. data/app/views/droom/folders/_attachments.html.haml +3 -0
  164. data/app/views/droom/folders/_contents.html.haml +6 -0
  165. data/app/views/droom/folders/_folder.html.haml +20 -0
  166. data/app/views/droom/folders/_folders.html.haml +2 -0
  167. data/app/views/droom/folders/_form.html.haml +18 -0
  168. data/app/views/droom/folders/edit.html.haml +6 -0
  169. data/app/views/droom/folders/index.html.haml +32 -0
  170. data/app/views/droom/folders/new.html.haml +6 -0
  171. data/app/views/droom/folders/show.html.haml +1 -0
  172. data/app/views/droom/group_invitations/_form.html.haml +15 -4
  173. data/app/views/droom/group_invitations/new.html.haml +6 -1
  174. data/app/views/droom/groups/_action_menu.haml +11 -0
  175. data/app/views/droom/groups/_form.html.haml +10 -11
  176. data/app/views/droom/groups/_group.html.haml +9 -10
  177. data/app/views/droom/groups/_groups.html.haml +2 -3
  178. data/app/views/droom/groups/_search_result.html.haml +16 -0
  179. data/app/views/droom/groups/_suggested.html.haml +7 -0
  180. data/app/views/droom/groups/edit.html.haml +7 -1
  181. data/app/views/droom/groups/index.html.haml +6 -3
  182. data/app/views/droom/groups/new.html.haml +7 -0
  183. data/app/views/droom/groups/show.html.haml +1 -1
  184. data/app/views/droom/invitations/_created.html.haml +1 -1
  185. data/app/views/droom/invitations/_form.html.haml +9 -5
  186. data/app/views/droom/invitations/_invitation.html.haml +9 -0
  187. data/app/views/droom/invitations/_invitations.html.haml +8 -0
  188. data/app/views/droom/invitations/new.html.haml +6 -1
  189. data/app/views/droom/memberships/_member.html.haml +1 -1
  190. data/app/views/droom/memberships/_membership_toggle.html.haml +10 -0
  191. data/app/views/droom/memberships/new.html.haml +10 -0
  192. data/app/views/droom/organisations/_action_menu.html.haml +7 -0
  193. data/app/views/droom/organisations/_form.html.haml +25 -0
  194. data/app/views/droom/organisations/_organisation.html.haml +23 -0
  195. data/app/views/droom/organisations/_organisations.html.haml +2 -0
  196. data/app/views/droom/organisations/_suggested.html.haml +7 -0
  197. data/app/views/droom/organisations/edit.html.haml +6 -0
  198. data/app/views/droom/organisations/index.html.haml +20 -0
  199. data/app/views/droom/organisations/new.html.haml +6 -0
  200. data/app/views/droom/organisations/show.html.haml +1 -0
  201. data/app/views/droom/pages/_full_page.html.haml +1 -1
  202. data/app/views/droom/pages/index.html.haml +1 -1
  203. data/app/views/droom/panels/_account.html.haml +16 -0
  204. data/app/views/droom/panels/_admin.html.haml +23 -0
  205. data/app/views/droom/panels/_devices.html.haml +19 -0
  206. data/app/views/droom/panels/_dropbox.html.haml +17 -0
  207. data/app/views/droom/panels/_email.html.haml +16 -0
  208. data/app/views/droom/panels/_keywords.html.haml +3 -0
  209. data/app/views/droom/panels/_networks.html.haml +3 -0
  210. data/app/views/droom/panels/_readers.html.haml +18 -0
  211. data/app/views/droom/panels/_rss.html.haml +10 -0
  212. data/app/views/droom/panels/_search.html.haml +16 -0
  213. data/app/views/droom/panels/_vcal.html.haml +3 -0
  214. data/app/views/droom/people/_action_menu.html.haml +22 -0
  215. data/app/views/droom/people/_form.html.haml +69 -39
  216. data/app/views/droom/people/_listing.html.haml +19 -0
  217. data/app/views/droom/people/_memberships.html.haml +24 -0
  218. data/app/views/droom/people/_people.html.haml +5 -29
  219. data/app/views/droom/people/_person.html.haml +30 -32
  220. data/app/views/droom/people/_search_result.html.haml +14 -0
  221. data/app/views/droom/people/_suggested.html.haml +10 -5
  222. data/app/views/droom/people/edit.html.haml +9 -1
  223. data/app/views/droom/people/index.html.haml +6 -9
  224. data/app/views/droom/people/new.html.haml +6 -1
  225. data/app/views/droom/people/show.html.haml +1 -1
  226. data/app/views/droom/preferences/_checkbox.html.haml +7 -0
  227. data/app/views/droom/preferences/_radio_set.html.haml +9 -0
  228. data/app/views/droom/scraps/_action_menu.html.haml +9 -0
  229. data/app/views/droom/scraps/_caption.html.haml +9 -0
  230. data/app/views/droom/scraps/_credit.html.haml +10 -0
  231. data/app/views/droom/scraps/_form.html.haml +77 -0
  232. data/app/views/droom/scraps/_heading.html.haml +16 -0
  233. data/app/views/droom/scraps/_scrap.html.haml +17 -0
  234. data/app/views/droom/scraps/_search_result.html.haml +5 -0
  235. data/app/views/droom/scraps/_stream.html.haml +4 -0
  236. data/app/views/droom/scraps/_suggested.html.haml +5 -0
  237. data/app/views/droom/scraps/_thumb.html.haml +5 -0
  238. data/app/views/droom/scraps/edit.html.haml +2 -0
  239. data/app/views/droom/scraps/full/_document.html.haml +6 -0
  240. data/app/views/droom/scraps/full/_event.html.haml +20 -0
  241. data/app/views/droom/scraps/full/_image.html.haml +4 -0
  242. data/app/views/droom/scraps/full/_link.html.haml +5 -0
  243. data/app/views/droom/scraps/full/_quote.html.haml +8 -0
  244. data/app/views/droom/scraps/full/_text.html.haml +4 -0
  245. data/app/views/droom/scraps/full/_video.html.haml +4 -0
  246. data/app/views/droom/scraps/index.atom.builder +26 -0
  247. data/app/views/droom/scraps/index.html.haml +15 -0
  248. data/app/views/droom/scraps/new.html.haml +2 -0
  249. data/app/views/droom/scraps/show.html.haml +4 -0
  250. data/app/views/droom/scraps/thumbs/_document.html.haml +9 -0
  251. data/app/views/droom/scraps/thumbs/_event.html.haml +17 -0
  252. data/app/views/droom/scraps/thumbs/_image.html.haml +6 -0
  253. data/app/views/droom/scraps/thumbs/_link.html.haml +10 -0
  254. data/app/views/droom/scraps/thumbs/_quote.html.haml +8 -0
  255. data/app/views/droom/scraps/thumbs/_text.html.haml +8 -0
  256. data/app/views/droom/scraps/thumbs/_video.html.haml +6 -0
  257. data/app/views/droom/shared/_controls.html.haml +5 -3
  258. data/app/views/droom/shared/_excerpt.html.haml +2 -0
  259. data/app/views/droom/shared/_navigation.html.haml +4 -4
  260. data/app/views/droom/shared/_panels.html.haml +4 -0
  261. data/app/views/droom/shared/_quicklinks.html.haml +5 -0
  262. data/app/views/droom/shared/_search_form.html.haml +2 -1
  263. data/app/views/droom/shared/_search_results.html.haml +9 -0
  264. data/app/views/droom/shared/_suggestions.html.haml +13 -9
  265. data/app/views/droom/shared/_title_excerpt.haml +2 -0
  266. data/app/views/droom/shared/search.html.haml +18 -0
  267. data/app/views/droom/users/_confirmation.html.haml +2 -0
  268. data/app/views/droom/users/_dropbox_status.html.haml +2 -0
  269. data/app/views/droom/users/_form.html.haml +34 -0
  270. data/app/views/droom/users/_user.html.haml +2 -0
  271. data/app/views/droom/users/_user_or_person.html.haml +63 -0
  272. data/app/views/droom/users/_users_table.html.haml +17 -0
  273. data/app/views/droom/users/edit.html.haml +10 -0
  274. data/app/views/droom/users/index.html.haml +42 -0
  275. data/app/views/droom/users/unwelcome.en.html.haml +17 -0
  276. data/app/views/droom/venues/_search_result.html.haml +17 -0
  277. data/app/views/droom/youtube/show.html.haml +12 -0
  278. data/app/views/kaminari/_paginator.html.haml +16 -0
  279. data/app/views/layouts/droom/application.html.haml +17 -17
  280. data/app/views/layouts/droom/email.html.haml +59 -0
  281. data/config/cucumber.yml +8 -0
  282. data/config/initializers/devise.rb +240 -0
  283. data/config/locales/devise.en.yml +58 -0
  284. data/config/locales/en.yml +203 -32
  285. data/config/routes.rb +55 -16
  286. data/config/sunspot.yml +17 -0
  287. data/db/migrate/20121120115447_tags.rb +18 -0
  288. data/db/migrate/20130116155331_dropbox_tokens.rb +9 -0
  289. data/db/migrate/20130118103540_folders.rb +47 -0
  290. data/db/migrate/20130124113715_preferences.rb +10 -0
  291. data/db/migrate/20130125132427_users_in_droom.rb +58 -0
  292. data/db/migrate/20130129142307_mobile_phones.rb +7 -0
  293. data/db/migrate/20130130120124_folder_ancestry_to_parents.rb +7 -0
  294. data/db/migrate/20130131161430_mailing_lists.rb +37 -0
  295. data/db/migrate/20130207091903_preference_uuids.rb +5 -0
  296. data/db/migrate/20130207123614_stream.rb +13 -0
  297. data/db/migrate/20130208035113_access_token_secret.rb +5 -0
  298. data/db/migrate/20130214145014_person_image.rb +9 -0
  299. data/db/migrate/20130217152644_devise_confirmable.rb +13 -0
  300. data/db/migrate/20130225095328_create_droom_calendars.rb +20 -0
  301. data/db/migrate/20130226092944_give_scraps_document.rb +5 -0
  302. data/db/migrate/20130228083509_privateness.rb +9 -0
  303. data/db/migrate/20130228134143_store_metadata.rb +5 -0
  304. data/db/migrate/20130305150648_folders_nicely.rb +6 -0
  305. data/db/migrate/20130305151936_niceties.rb +7 -0
  306. data/db/migrate/20130308103807_create_droom_dropbox_documents.rb +11 -0
  307. data/db/migrate/20130308154552_dropbox_documents_changed.rb +5 -0
  308. data/db/migrate/20130326135738_user_titles.rb +5 -0
  309. data/lib/droom.rb +189 -22
  310. data/lib/droom/engine.rb +6 -1
  311. data/lib/droom/folders.rb +106 -0
  312. data/lib/droom/lazy_hash.rb +73 -0
  313. data/lib/droom/{helpers.rb → model_helpers.rb} +1 -1
  314. data/lib/droom/monkeys.rb +21 -2
  315. data/lib/droom/routing.rb +13 -0
  316. data/lib/droom/searchability.rb +25 -0
  317. data/lib/droom/taggability.rb +60 -0
  318. data/lib/droom/title_case.rb +101 -0
  319. data/lib/droom/user_config.rb +67 -0
  320. data/lib/droom/validators.rb +6 -0
  321. data/lib/droom/version.rb +1 -1
  322. data/lib/generators/droom/install/templates/droom_initializer.rb +0 -1
  323. data/lib/tasks/cucumber.rake +65 -0
  324. data/spec/datasets/calendar_events_dataset.rb +44 -0
  325. data/spec/datasets/calendar_pages_dataset.rb +8 -0
  326. data/spec/datasets/calendar_sites_dataset.rb +6 -0
  327. data/spec/datasets/calendars_dataset.rb +34 -0
  328. data/spec/datasets/documents_dataset.rb +28 -0
  329. data/spec/datasets/recurrence_dataset.rb +7 -0
  330. data/spec/dummy/README.rdoc +261 -0
  331. data/spec/dummy/Rakefile +7 -0
  332. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  333. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  334. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  335. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  336. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  337. data/spec/dummy/config.ru +4 -0
  338. data/spec/dummy/config/application.rb +65 -0
  339. data/spec/dummy/config/boot.rb +10 -0
  340. data/spec/dummy/config/database.yml +21 -0
  341. data/spec/dummy/config/environment.rb +5 -0
  342. data/spec/dummy/config/environments/development.rb +38 -0
  343. data/spec/dummy/config/environments/production.rb +67 -0
  344. data/spec/dummy/config/environments/test.rb +38 -0
  345. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  346. data/spec/dummy/config/initializers/inflections.rb +15 -0
  347. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  348. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  349. data/spec/dummy/config/initializers/session_store.rb +8 -0
  350. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  351. data/spec/dummy/config/locales/en.yml +7 -0
  352. data/spec/dummy/config/routes.rb +3 -0
  353. data/spec/dummy/config/sunspot.yml +17 -0
  354. data/spec/dummy/db/migrate/20120911070124_create_droom_data.droom.rb +135 -0
  355. data/spec/dummy/db/migrate/20120921094604_agenda_sections.droom.rb +14 -0
  356. data/spec/dummy/db/migrate/20120921094605_add_postal_address_to_people.droom.rb +11 -0
  357. data/spec/dummy/db/migrate/20121102064845_give_groups_descriptions.droom.rb +6 -0
  358. data/spec/dummy/db/migrate/20121102064846_more_names.droom.rb +6 -0
  359. data/spec/dummy/db/migrate/20121102064847_event_agenda_sections.droom.rb +14 -0
  360. data/spec/dummy/db/migrate/20121102064848_create_group_invitations.droom.rb +11 -0
  361. data/spec/dummy/db/migrate/20121102064849_give_people_positions.droom.rb +6 -0
  362. data/spec/dummy/db/migrate/20121102064850_help_pages.droom.rb +14 -0
  363. data/spec/dummy/db/migrate/20121102064851_category_slugs.droom.rb +6 -0
  364. data/spec/dummy/db/migrate/20121102064852_document_links.droom.rb +15 -0
  365. data/spec/dummy/db/migrate/20121102064853_people_visibility.droom.rb +8 -0
  366. data/spec/dummy/db/migrate/20121102094820_shy_people.droom.rb +6 -0
  367. data/spec/dummy/db/migrate/20121102095927_visibility_defaults.droom.rb +10 -0
  368. data/spec/dummy/db/migrate/20130121122352_tags.droom.rb +19 -0
  369. data/spec/dummy/db/migrate/20130121122353_dropbox.droom.rb +10 -0
  370. data/spec/dummy/db/migrate/20130121122354_folders.droom.rb +48 -0
  371. data/spec/dummy/db/migrate/20130128142902_memberships_expire.droom.rb +6 -0
  372. data/spec/dummy/db/migrate/20130128142903_give_documents_extracted_text.droom.rb +6 -0
  373. data/spec/dummy/db/migrate/20130128142904_preferences.droom.rb +11 -0
  374. data/spec/dummy/db/migrate/20130128142905_users_in_droom.droom.rb +59 -0
  375. data/spec/dummy/db/migrate/20130130120631_folder_ancestry_to_parents.droom.rb +8 -0
  376. data/spec/dummy/db/migrate/20130201103737_mobile_phones.droom.rb +8 -0
  377. data/spec/dummy/db/migrate/20130201103738_mailing_lists.droom.rb +38 -0
  378. data/spec/dummy/db/schema.rb +327 -0
  379. data/spec/dummy/log/sunspot-solr-test.log.1 +222 -0
  380. data/spec/dummy/public/404.html +26 -0
  381. data/spec/dummy/public/422.html +26 -0
  382. data/spec/dummy/public/500.html +25 -0
  383. data/spec/dummy/public/favicon.ico +0 -0
  384. data/spec/dummy/public/system/droom/documents/files/000/000/001/original/frog.png +0 -0
  385. data/spec/dummy/public/system/droom/documents/files/000/000/001/original/rat.png +0 -0
  386. data/spec/dummy/script/rails +6 -0
  387. data/spec/dummy/solr/conf/admin-extra.html +31 -0
  388. data/spec/dummy/solr/conf/elevate.xml +36 -0
  389. data/spec/dummy/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  390. data/spec/dummy/solr/conf/protwords.txt +21 -0
  391. data/spec/dummy/solr/conf/schema.xml +238 -0
  392. data/spec/dummy/solr/conf/scripts.conf +24 -0
  393. data/spec/dummy/solr/conf/solrconfig.xml +934 -0
  394. data/spec/dummy/solr/conf/spellings.txt +2 -0
  395. data/spec/dummy/solr/conf/stopwords.txt +58 -0
  396. data/spec/dummy/solr/conf/synonyms.txt +31 -0
  397. data/spec/dummy/solr/data/development/index/segments.gen +0 -0
  398. data/spec/dummy/solr/data/development/index/segments_1 +0 -0
  399. data/spec/dummy/solr/data/development/spellchecker/segments.gen +0 -0
  400. data/spec/dummy/solr/data/development/spellchecker/segments_1 +0 -0
  401. data/spec/dummy/solr/data/test/index/segments.gen +0 -0
  402. data/spec/dummy/solr/data/test/index/segments_3nu +0 -0
  403. data/spec/dummy/solr/data/test/spellchecker/segments.gen +0 -0
  404. data/spec/dummy/solr/data/test/spellchecker/segments_1 +0 -0
  405. data/spec/dummy/webdav/1/group/rat.png +0 -0
  406. data/spec/dummy/webdav/1/unattached/rat.png +0 -0
  407. data/spec/dummy/webdav/group/rat.png +0 -0
  408. data/spec/dummy/webdav/unattached/rat.png +0 -0
  409. data/spec/dummy/webdav/unattached/rat_v1.png +0 -0
  410. data/spec/factories/agenda_categories.rb +5 -0
  411. data/spec/factories/categories.rb +5 -0
  412. data/spec/factories/documents.rb +16 -0
  413. data/spec/factories/events.rb +41 -0
  414. data/spec/factories/folders.rb +5 -0
  415. data/spec/factories/groups.rb +6 -0
  416. data/spec/factories/memberships.rb +5 -0
  417. data/spec/factories/people.rb +16 -0
  418. data/spec/factories/recurrence_rules.rb +25 -0
  419. data/spec/factories/user.rb +6 -0
  420. data/spec/fixtures/dummy.ics +59 -0
  421. data/spec/fixtures/images/frog.png +0 -0
  422. data/spec/fixtures/images/rat.png +0 -0
  423. data/spec/fixtures/ny.ics +36 -0
  424. data/spec/lib/droom/folders_spec.rb +46 -0
  425. data/spec/lib/droom/lazy_hash_spec.rb +33 -0
  426. data/spec/models/droom/agenda_category_spec.rb +15 -0
  427. data/spec/models/droom/document_spec.rb +76 -0
  428. data/spec/models/droom/event_spec.rb +154 -0
  429. data/spec/models/droom/folder_spec.rb +5 -0
  430. data/spec/models/droom/ical_spec.rb +62 -0
  431. data/spec/models/droom/mailing_list_membership_spec.rb +81 -0
  432. data/spec/models/droom/membership_spec.rb +22 -0
  433. data/spec/models/droom/person_spec.rb +72 -0
  434. data/spec/models/droom/recurrence_rule_spec.rb +81 -0
  435. data/spec/models/droom/user_spec.rb +27 -0
  436. data/spec/models/droom/visibility_spec.rb +6 -0
  437. data/spec/spec_helper.rb +119 -0
  438. data/spec/support/matchers/content_type_matcher.rb +17 -0
  439. metadata +591 -36
  440. data/app/assets/javascripts/droom/calendar.js.coffee +0 -121
  441. data/app/assets/javascripts/droom/drag_sort.js.coffee +0 -22
  442. data/app/assets/javascripts/droom/forms.js.coffee +0 -746
  443. data/app/assets/javascripts/droom/sort.js.coffee +0 -126
  444. data/app/assets/javascripts/droom/suggester.js.coffee +0 -230
  445. data/app/controllers/droom/document_attachments_controller.rb +0 -19
  446. data/app/models/droom/document_link.rb +0 -31
  447. data/app/models/droom/personal_document.rb +0 -98
  448. data/app/views/droom/dashboard/_marginalia.html.haml +0 -3
  449. data/app/views/droom/dashboard/_my_future_events.html.haml +0 -9
  450. data/app/views/droom/dashboard/_my_group_documents.html.haml +0 -6
  451. data/app/views/droom/dashboard/_my_past_events.haml +0 -6
  452. data/app/views/droom/documents/_event_document_form.html.haml +0 -15
  453. data/app/views/droom/errors/bang.html.haml +0 -12
  454. data/app/views/droom/errors/not_allowed.html.haml +0 -12
  455. data/app/views/droom/errors/not_found.html.haml +0 -12
  456. data/app/views/droom/events/_attachment.html.haml +0 -1
  457. data/app/views/droom/events/_attachment_list.html.haml +0 -4
  458. data/app/views/droom/invitations/_attending_people.html.haml +0 -8
  459. data/config/initializers/dav.rb +0 -2
data/README.md CHANGED
@@ -4,7 +4,7 @@ This is a minimal system for secure document and event distribution. It provides
4
4
 
5
5
  ## Status
6
6
 
7
- Brand new. In progress. Avoid!
7
+ Brand new. In progress. Little bit volatile, perhaps.
8
8
 
9
9
  ## Installation
10
10
 
@@ -16,7 +16,7 @@ To migrate:
16
16
 
17
17
  rake droom:install:migrations
18
18
  rake db:migrate
19
-
19
+
20
20
 
21
21
  ## Copyright
22
22
 
@@ -1,88 +1,85 @@
1
1
  #= require droom/lib/modernizr
2
- #= require droom/lib/extensions
3
2
  #= require jquery
4
3
  #= require jquery_ujs
4
+ #= require droom/lib/ZeroClipboard
5
5
  #= require droom/lib/jquery.animate-colors
6
6
  #= require droom/lib/jquery.sortable
7
7
  #= require droom/lib/jquery.cookie
8
8
  #= require droom/lib/kalendae
9
9
  #= require droom/lib/wysihtml5
10
10
  #= require droom/lib/parser_rules/advanced
11
- #= require droom/forms
12
- #= require droom/suggester
13
- #= require droom/calendar
14
- #= require droom/sort
11
+ #= require cropper
12
+ #= require droom/extensions
13
+ #= require droom/utilities
14
+ #= require droom/ajax
15
+ #= require droom/popups
16
+ #= require droom/actions
17
+ #= require droom/widgets
18
+ #= require droom/stream
15
19
  #= require droom/map
16
- #= require droom/drag_sort
17
20
  #= require_self
18
21
 
19
22
  jQuery ($) ->
20
- $.fn.flash = ->
21
- @each ->
22
- container = $(this)
23
- container.fadeIn "fast"
24
- $("<a href=\"#\" class=\"closer\">close</a>").prependTo(container)
25
- container.bind "click", (e) ->
26
- e.preventDefault()
27
- container.fadeOut "fast"
28
-
29
- $.fn.signal = (color, duration) ->
30
- color ?= "#f7f283"
31
- duration ?= 1000
32
- @each ->
33
- $(@).css('backgroundColor', color).animate({'backgroundColor': '#ffffff'}, duration)
34
-
35
- $.fn.signal_confirmation = ->
36
- @signal('#c7ebb4')
37
-
38
- $.fn.signal_error = ->
39
- @signal('#e55a51')
40
-
41
- $.fn.signal_cancellation = ->
42
- @signal('#a2a3a3')
23
+ $.activate_with () ->
24
+ # console.log "activate", @
43
25
 
44
- $.fn.back_button = ->
45
- @click (e) ->
46
- e.preventDefault() if e
47
- history.back()
48
- true
49
-
50
- $.fn.find_including_self = (selector) ->
51
- selection = @.find(selector)
52
- selection.push @ if @is(selector)
53
- selection
54
-
55
- $.fn.activate = () ->
56
- @find_including_self('a.toggle_active').replace_with_remote_toggle()
57
26
  @find_including_self('#flashes p:parent').flash()
58
- @find_including_self('.twister').twister()
27
+ @find_including_self('[data-refreshable]').refresher()
28
+ @find_including_self('.hidden').find('input, select, textarea').attr('disabled', true)
29
+ @find_including_self('.temporary').disappearAfter(1000)
30
+
31
+ # link actions
32
+
33
+ @find_including_self('[data-action="popup"]').popup()
34
+ @find_including_self('[data-action="close"]').closes()
35
+ @find_including_self('[data-action="upload"]').uploader()
36
+ @find_including_self('[data-action="recrop"]').recropper()
37
+ @find_including_self('[data-action="affect"]').affects()
38
+ @find_including_self('[data-action="reveal"]').reveals()
39
+ @find_including_self('[data-action="remove"]').removes()
40
+ @find_including_self('[data-action="copy"]').copier()
41
+ @find_including_self('[data-action="column_toggle"]').column_expander()
42
+ @find_including_self('[data-action="toggle"]').toggle()
43
+ @find_including_self('[data-action="twister"]').twister()
44
+ @find_including_self('[data-action="alternate"]').alternator()
45
+ @find_including_self('[data-action="replace"]').replace_with_remote_content()
46
+ @find_including_self('[data-action="autofetch"]').replace_with_remote_content ".holder", {force: true}
47
+ @find_including_self('[data-action="slide"]').sliding_link()
48
+ @find_including_self('[data-action="fit"]').self_sizes()
49
+ @find_including_self('form[data-action="filter"]').filter_form()
50
+ @find_including_self('[data-menu]').action_menu()
51
+
52
+ # it's not very easy to add data attributes to kaminari pagination links
53
+
54
+ @find_including_self('.pagination a').page_turner()
55
+
56
+ # and some shortcuts for compatibility
57
+
58
+ @find_including_self('a.inline, a.fetch').replace_with_remote_content()
59
+
60
+ # form widgets and input modification. These might move to [data-widget] markup.
61
+
59
62
  @find_including_self('.wysihtml').html_editable()
60
63
  @find_including_self('.venuepicker').venue_picker()
61
64
  @find_including_self('.datepicker').date_picker()
62
65
  @find_including_self('.timepicker').time_picker()
63
66
  @find_including_self('.filepicker').file_picker()
64
- @find_including_self('a.delete').removes('.holder')
65
- @find_including_self('[data-action="popup"]').popup_remote_content()
66
- @find_including_self('[data-action="toggle"]').toggle()
67
- @find_including_self('[data-action="append_form"]').append_remote_form()
68
- @find_including_self('[data-action="overlay_form"]').overlay_remote_form()
69
- @find_including_self('[data-action="replace_with_form"]').replace_with_remote_form()
70
- @find_including_self('[data-refreshable]').refresher()
71
- @find_including_self('table.sortable').table_sort
72
- sort: "created"
73
- order: "DESC"
74
- @find_including_self('#map').init_map()
67
+ @find_including_self('.person_selector').person_selector()
68
+ @find_including_self('.person_picker').person_picker()
69
+ @find_including_self('.group_picker').group_picker()
70
+ @find_including_self('.drag_sort').drag_sort()
75
71
  @find_including_self('input.password').password_field()
76
72
  @find_including_self('input[type="submit"]').submitter()
77
- @find_including_self('input.person_picker').person_picker()
78
- @find_including_self('input.group_picker').group_picker()
79
- @find_including_self('.drag_sort').drag_sort()
80
- @find_including_self('.back').back_button()
73
+ @find_including_self('form.preferences').preferences_form()
74
+ @find_including_self('form.scrap').scrap_form()
75
+
76
+ # page widgets
77
+
78
+ @find_including_self('#map').init_map()
79
+ @find_including_self('#minicalendar').calendar()
80
+ @find_including_self('form.search_form').search()
81
+ @find_including_self('form.fancy').captive()
82
+ @find_including_self('li.folder').folder()
83
+ @find_including_self('form#suggestions').suggestion_form()
84
+ @find_including_self('.panel').panel()
81
85
  @
82
-
83
- $ ->
84
- $('body').activate()
85
- $('#minicalendar').calendar()
86
- $('form#searchform').captive
87
- replacing: '.search_results'
88
- fast: true
@@ -0,0 +1,492 @@
1
+ # This is a collection of useful interface behaviours. Most of them are form- or input-based. They shouldn't ever
2
+ # be object-specific, but can be used throughout the droom interface to make forms and other controls more lively.
3
+ #
4
+ # The basic approach here is PJAX: our remote calls always return chunks of html. There are no client-side templates
5
+ # or model classes. Instead we have defined a set of actions, by which page elements can interact with the server in
6
+ # structured ways. A tag will declare that it triggers an action, and may also declare that the action will replace or
7
+ # affect other elements.
8
+ #
9
+ # Many elements are refreshable, and an action that affects them will trigger their refreshment. Editing an event is
10
+ # a simple remote form operation with several consequences for the page:
11
+ #
12
+ # link_to t(:edit_event), edit_event_url(event), :class => 'edit minimal', :data => {
13
+ # :action => "popup",
14
+ # :replaced => "#event_#{event.id}",
15
+ # :affected => ".minimonth"
16
+ # }
17
+ #
18
+ # When the `popup` action is complete - that is, the server returns a response with no form in it - the final response
19
+ # will replace the original event container and the small calendar display will be refreshed to show the possibly revised
20
+ # date of the event.
21
+ #
22
+ # It is our hope that this simple non-architecture will make it easy to support a future pub-sub update.
23
+
24
+ jQuery ($) ->
25
+
26
+ ## Affecting the page
27
+ #
28
+ # refreshable, affected rules, etc.
29
+
30
+ $.fn.refresher = () ->
31
+ @each ->
32
+ new Refresher @
33
+
34
+ class Refresher
35
+ constructor: (element) ->
36
+ @_container = $(element)
37
+ @_url = @_container.attr 'data-url'
38
+ @_container.bind "refresh", @refresh
39
+
40
+ refresh: (e) =>
41
+ e.stopPropagation()
42
+ e.preventDefault()
43
+ $.ajax @_url,
44
+ dataType: "html"
45
+ success: @replace
46
+
47
+ replace: (data, textStatus, jqXHR) =>
48
+ replacement = $(data)
49
+ @_container.fadeOut 'fast', () =>
50
+ replacement.hide().insertAfter(@_container)
51
+ @_container.remove()
52
+ @_container = replacement
53
+ @_container.activate().fadeIn('fast')
54
+
55
+
56
+ # ## Actions
57
+ #
58
+ # The 'remove' action takes out the parent element of this node designated by the usual 'affected'
59
+ # attribute. The delete link next to an event, for example:
60
+ #
61
+ # link_to t(:remove), event_url(event), :method => 'delete', :data => {
62
+ # :confirm => t(:confirm_delete_event, :name => event.name),
63
+ # :removes => ".holder",
64
+ # :affected => ".minimonth"}
65
+ #
66
+ # ...will (on success) remove the first containing '.holder' element and also refresh the mini calendar display.
67
+ #
68
+ $.fn.removes = () ->
69
+ @each ->
70
+ removed = $(@).attr('data-removed') || ".holder"
71
+ affected = $(@).attr('data-affected')
72
+
73
+ $(@).remote
74
+ on_success: (response) =>
75
+ $(@).parents(removed).first().fadeOut 'fast', () ->
76
+ $(@).remove()
77
+ $(affected).trigger "refresh"
78
+
79
+
80
+ $.fn.affects = () ->
81
+ @each ->
82
+ affected = $(@).attr('data-affected')
83
+ $(@).remote
84
+ on_success: (response) =>
85
+ $(affected).trigger "refresh"
86
+
87
+
88
+ # Close links work just by triggering a 'hide' event and hoping that something further up the tree will bind
89
+ # it to the right thing.
90
+
91
+ $.fn.closes = () ->
92
+ @click (e) ->
93
+ e.preventDefault()
94
+ $(@).trigger('close')
95
+
96
+
97
+
98
+ # *replace_with_remote_content* is a useful shortcut for links and forms that should simply be replaced with the
99
+ # result of their action.
100
+ #
101
+ $.fn.replace_with_remote_content = (selector, opts) ->
102
+ selector ?= '.holder'
103
+ options = $.extend { force: false }, opts
104
+ @each ->
105
+ container = $(@).attr('data-replaced') || selector
106
+ affected = $(@).attr('data-affected')
107
+ $(@).remote
108
+ on_success: (r) =>
109
+ replaced = $(@).self_or_ancestor(container).last()
110
+ replacement = $(r).insertAfter(replaced)
111
+ replaced?.remove()
112
+ replacement.activate()
113
+ $(affected).trigger('refresh')
114
+ $(@).click() if options['force']
115
+
116
+
117
+
118
+
119
+ # The submitter is a self-disabling submit button that can only be clicked once.
120
+ #
121
+ $.fn.submitter = ->
122
+ @each ->
123
+ button = $(@)
124
+ button.parents('form').bind "submit", (e) ->
125
+ button.addClass('waiting').text('Please wait').bind "click", (e) =>
126
+ e.preventDefault() if e
127
+
128
+
129
+ # The toggle action shows or hides the affected elements with cookie-based persistence across page
130
+ # views. A link like this:
131
+ #
132
+ # %a{:data => {:action => 'toggle', :affected => '.admin'}}
133
+ #
134
+ # will toggle on and off the display of anything with the 'admin' class.
135
+ #
136
+ $.fn.toggle = () ->
137
+ @each ->
138
+ new Toggle(@, $(@).attr('data-affected'))
139
+
140
+ #todo: make this a more versatile base class
141
+ class Toggle
142
+ constructor: (element, @_selector, @_name) ->
143
+ @_container = $(element)
144
+ @_name ?= "droom_#{@_selector}_state"
145
+ @_showing_text = @_container.text().replace('show', 'hide').replace('Show', 'Hide').replace('more', 'less').replace('More', 'Less')
146
+ @_hiding_text = @_showing_text.replace('hide', 'show').replace('Hide', 'Show').replace('less', 'more').replace('Less', 'More')
147
+ @_container.click @toggle
148
+ if cookie = $.cookie(@_name)
149
+ @_showing = cookie is "showing"
150
+ @apply()
151
+ else
152
+ @_showing = $(@_selector).is(":visible")
153
+ @store()
154
+
155
+ apply: (e) =>
156
+ e.preventDefault() if e
157
+ if @_showing then @show() else @hide()
158
+
159
+ toggle: (e) =>
160
+ e.preventDefault() if e
161
+ if @_showing then @slideUp() else @slideDown()
162
+
163
+ slideDown: =>
164
+ @_container.addClass('showing')
165
+ $(@_selector).slideDown () =>
166
+ @show()
167
+
168
+ show: =>
169
+ $(@_selector).show()
170
+ @_container.addClass('showing')
171
+ @_container.text(@_showing_text)
172
+ @_showing = true
173
+ @store()
174
+
175
+ slideUp: =>
176
+ $(@_selector).slideUp () =>
177
+ @hide()
178
+
179
+ hide: =>
180
+ $(@_selector).hide()
181
+ @_container.removeClass('showing')
182
+ @_container.text(@_hiding_text)
183
+ @_showing = false
184
+ @store()
185
+
186
+ store: () =>
187
+ value = if @_showing then "showing" else "hidden"
188
+ $.cookie @_name, value,
189
+ path: '/'
190
+
191
+
192
+ # The collapser is a self-expanding unit. Basically a toggle. #todo: amalgamate!
193
+
194
+ $.fn.collapser = (options) ->
195
+ @each ->
196
+ new Collapser(@, options)
197
+ @
198
+
199
+ class Collapser
200
+ constructor: (element, opts) ->
201
+ @container = $(element)
202
+ @options = $.extend {
203
+ toggle: ".heading a.name"
204
+ body: ".detail"
205
+ preview: ".preview"
206
+ }, opts
207
+ @id = @container.attr('id')
208
+ @switch = @container.find(@options.toggle)
209
+ @body = @container.find(@options.body)
210
+ @preview = @container.find(@options.preview)
211
+ @switch.click @toggle
212
+ @set()
213
+
214
+ set: () =>
215
+ if @container.hasClass("open") then @show() else @hide()
216
+
217
+ toggle: (e) =>
218
+ e.preventDefault() if e
219
+ if @container.hasClass("open") then @hide() else @show()
220
+
221
+ hide: () =>
222
+ @container.removeClass('open')
223
+ @preview.show().css('position', 'relative')
224
+ @body.stop().slideUp
225
+ duration: 'slow'
226
+ easing: 'glide'
227
+ complete: =>
228
+ @body.hide()
229
+
230
+ show: () =>
231
+ @container.addClass('open')
232
+ @preview.css('position', 'absolute')
233
+ @body.stop().slideDown
234
+ duration: 'normal'
235
+ easing: 'boing'
236
+ complete: =>
237
+ @preview.hide().css('position', 'relative')
238
+
239
+
240
+ # this one just shows or hides based on whether a checkbox is checked
241
+
242
+ $.fn.reveals = () ->
243
+ @each ->
244
+ new Revealer(@)
245
+
246
+ class Revealer
247
+ constructor: (element) ->
248
+ @_input = $(element)
249
+ @_affected = @_input.attr('data-affected')
250
+ @_converse = @_input.attr('data-converse')
251
+ @_input.bind "click", @set
252
+ @set()
253
+
254
+ set: () =>
255
+ if @_input.is(":checked") then @show() else @hide()
256
+
257
+ show: (e) =>
258
+ $(@_affected).stop().slideDown()
259
+ $(@_affected).find('input').attr('disabled', false)
260
+ $(@_converse).stop().slideUp()
261
+ $(@_converse).find('input').attr('disabled', true)
262
+
263
+ hide: (e) =>
264
+ $(@_affected).stop().slideUp()
265
+ $(@_affected).find('input').attr('disabled', true)
266
+ $(@_converse).stop().slideDown()
267
+ $(@_converse).find('input').attr('disabled', false)
268
+
269
+
270
+ # Yet another toggle, preserved for cdr reviewers but I hope not for long.
271
+
272
+ $.fn.twister = ->
273
+ @each ->
274
+ new Twister(@)
275
+
276
+ class Twister
277
+ @currently_open: []
278
+ constructor: (element) ->
279
+ @_twister = $(element)
280
+ @_twisted = @_twister.find('.twisted')
281
+ @_toggles = @_twister.find('a.twisty')
282
+ @_toggles.click @toggle
283
+ @_open = @_twister.hasClass("showing")
284
+ @set()
285
+
286
+ set: () =>
287
+ if @_open then @open() else @close()
288
+
289
+ toggle: (e) =>
290
+ e.preventDefault() if e
291
+ if @_open then @close() else @open()
292
+
293
+ open: () =>
294
+ @_twister.addClass("showing")
295
+ @_twisted.show()
296
+ @_open = true
297
+ Twister.currently_open.push(@_id)
298
+
299
+ close: () =>
300
+ @_twister.removeClass("showing")
301
+ @_twisted.hide()
302
+ @_open = false
303
+ Twister.currently_open.remove(@_id) # remove is defined in lib/extensions
304
+
305
+
306
+
307
+ # The *alternator* action is a more extreme toggle. It allows an element to declare its alternate:
308
+ # when a link within the element is clicked, it will be removed from the DOM and its alternate
309
+ # inserted. Usually the relation is reciprocal, so that another link in the alternate will bring
310
+ # the original element back.
311
+ #
312
+ # The main use for this is to have two alternative blocks of form inputs: one to add a new associate
313
+ # and one to choose from the existing list.
314
+ #
315
+ class Alternator
316
+ constructor: (element) ->
317
+ @_container = $(element)
318
+ @_selector = @_container.attr("data-selector")
319
+ @_alternate = @_container.siblings(@_selector)
320
+ @revert()
321
+
322
+ flip: (e) =>
323
+ e.preventDefault() if e
324
+ @_container.after(@_alternate)
325
+ @_container.remove()
326
+ @_alternate.find('a').click @revert
327
+
328
+ revert: (e) =>
329
+ e.preventDefault() if e
330
+ @_alternate.before(@_container)
331
+ @_alternate.remove()
332
+ @_container.find('a').click @flip
333
+
334
+ $.fn.alternator = ->
335
+ @each ->
336
+ new Alternator(@)
337
+
338
+
339
+
340
+
341
+
342
+
343
+ # The *copier* action uses ZeroClipboard to put on the clipboard whatever is in our data-value attribute.
344
+ #
345
+ $.fn.copier = ->
346
+ ZeroClipboard.setMoviePath( '/assets/droom/lib/ZeroClipboard.swf' );
347
+ @each ->
348
+ new Copier @
349
+
350
+ class Copier
351
+ constructor: (element) ->
352
+ @_link = $(element)
353
+ @_link.click @failed
354
+ @_link.wrap $('<div class="copyholder" />')
355
+ @_container = @_link.parents('.copyholder')
356
+ @_clip = new ZeroClipboard.Client()
357
+ @_clip.setHandCursor true
358
+ @_clip.setText(@_link.attr('data-value').replace(/^\s+/gm, ''))
359
+
360
+ [w, h] = [@_link.width() || 60, @_link.height() || 15]
361
+ @_clip_element = @_clip.getHTML(w, h+5)
362
+ $(@_clip_element).appendTo @_container
363
+
364
+ @_clip.addEventListener 'complete', @complete
365
+ @_clip.addEventListener 'onMouseOver', @hover
366
+ @_clip.addEventListener 'onMouseOut', @unHover
367
+
368
+ hover: (e) =>
369
+ @_link.addClass('hover')
370
+
371
+ unHover: (e) =>
372
+ @_link.removeClass('hover')
373
+
374
+ complete: (client, text) =>
375
+ @_link.signal_confirmation()
376
+
377
+ failed: (e) =>
378
+ e.preventDefault()
379
+
380
+
381
+ # The main search page hasn't had much love yet.
382
+ #
383
+ # If we keep the inline functionality it should probably use the standard captive form.
384
+
385
+ $.fn.search = ->
386
+ @each ->
387
+ new Search @
388
+
389
+ class Search
390
+ constructor: (element) ->
391
+ @form = $(element)
392
+ @search_box = @form.find(".search_box")
393
+ @container = $(".search_results")
394
+ @filters = @form.find "input[type='checkbox']"
395
+ @search_box.on "keyup", @submit
396
+ @filters.on "change", @submit
397
+
398
+ submit: =>
399
+ $.ajax
400
+ url: "#{@form.attr('action')}?#{@form.serialize()}"
401
+ type: "GET"
402
+ dataType: "script"
403
+ complete: (data) =>
404
+ @container.replaceWith data.responseText
405
+ @container = $(".search_results")
406
+
407
+ #todo: Dragsort also needs to use Remote.
408
+
409
+ $.fn.drag_sort = (options) ->
410
+ @each ->
411
+ first = 0
412
+ offset = 1 + first
413
+ sorter = $(@).sortable
414
+ handle: ".handle"
415
+ $.each $(@).children(), (i, child) =>
416
+ $(child).bind "dragend", (e) =>
417
+ child = $(child)
418
+ index = child.index() + offset
419
+ id = parseInt(child.attr('id').split("person_")[1], 10)
420
+ $.ajax
421
+ url: "/people/#{id}"
422
+ type: "PUT"
423
+ dataType: "JSON"
424
+ data:
425
+ person:
426
+ position: index
427
+
428
+
429
+ #todo: this has been replaced with the filterform.
430
+
431
+ $.fn.search_filter = () ->
432
+ @each ->
433
+ new Filter @
434
+ @
435
+
436
+ class Filter
437
+ constructor: (element) ->
438
+ @_container = $(element)
439
+ @_defilter = $('<a href="#" class="defilter" />').insertAfter(@_container)
440
+ @_affected = @_container.attr('data-affected')
441
+ @setDefilter()
442
+ @_container.bind "keyup", @setQuery
443
+ @_defilter.bind "click", @clearQuery
444
+ # @announce()
445
+
446
+ setDefilter: () =>
447
+ if @_container.val()
448
+ @_defilter.show()
449
+ else
450
+ @_defilter.hide()
451
+
452
+ setQuery: (e) =>
453
+ kc = e.which
454
+ # delete, backspace, alphanumerics, number pad, punctuation
455
+ if (kc is 8) or (kc is 46) or (47 < kc < 91) or (96 < kc < 112) or (kc > 145)
456
+ @setDefilter()
457
+ @filter()
458
+
459
+ clearQuery: (e) =>
460
+ e.preventDefault() if e
461
+ @_container.val("")
462
+ @setDefilter()
463
+ @filter()
464
+
465
+ filter: () =>
466
+ $(@_affected).trigger "filter", @_container.val()
467
+
468
+
469
+
470
+
471
+
472
+ # A text input that sizes to fit will adjust its font size to suit the length of its content.
473
+ # At the moment this is done just by fitting a curve, but it ought really to be based on a
474
+ # calculation of area occupied.
475
+
476
+ $.size_to_fit = (e) ->
477
+ container = $(@)
478
+ l = container.val().length
479
+ size = if l then (((560.0/(2 * l+150.0)) + 0.25)).toFixed(2) else 1
480
+ container.stop().animate
481
+ 'font-size': "#{size}em"
482
+ width: 532
483
+ height: 290
484
+ ,
485
+ queue: false
486
+ duration: 100
487
+
488
+ $.fn.self_sizes = () ->
489
+ @each ->
490
+ $(@).bind "keyup", $.size_to_fit
491
+ $(@).bind "change", $.size_to_fit
492
+ $.size_to_fit.apply(@)