community_engine 2.3.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (580) hide show
  1. checksums.yaml +13 -5
  2. data/.travis.yml +5 -4
  3. data/CHANGELOG +43 -5
  4. data/Gemfile +1 -16
  5. data/README.markdown +22 -19
  6. data/UPGRADING.markdown +10 -0
  7. data/about.yml +1 -1
  8. data/app/assets/javascripts/community_engine.js +187 -18
  9. data/app/assets/javascripts/cropper.js +86 -565
  10. data/app/assets/javascripts/forum.js +26 -71
  11. data/app/assets/javascripts/jquery.migrate.js +521 -0
  12. data/app/assets/stylesheets/_colors.css.scss +100 -0
  13. data/app/assets/stylesheets/_font.css.scss +17 -0
  14. data/app/assets/stylesheets/_forms.css.scss +20 -0
  15. data/app/assets/stylesheets/_forum.css.scss +0 -0
  16. data/app/assets/stylesheets/_grid.css.scss +7 -0
  17. data/app/assets/stylesheets/_layers.css.scss +7 -0
  18. data/app/assets/stylesheets/_layout.css.scss +28 -0
  19. data/app/assets/stylesheets/community_engine.css.scss +18 -0
  20. data/app/assets/stylesheets/cropper.css +6 -182
  21. data/app/controllers/activities_controller.rb +10 -10
  22. data/app/controllers/admin_controller.rb +23 -23
  23. data/app/controllers/ads_controller.rb +16 -5
  24. data/app/controllers/albums_controller.rb +11 -5
  25. data/app/controllers/base_controller.rb +5 -8
  26. data/app/controllers/categories_controller.rb +31 -31
  27. data/app/controllers/clippings_controller.rb +18 -12
  28. data/app/controllers/comments_controller.rb +17 -8
  29. data/app/controllers/events_controller.rb +25 -21
  30. data/app/controllers/favorites_controller.rb +12 -12
  31. data/app/controllers/forums_controller.rb +20 -9
  32. data/app/controllers/friendships_controller.rb +41 -48
  33. data/app/controllers/homepage_features_controller.rb +11 -5
  34. data/app/controllers/invitations_controller.rb +15 -9
  35. data/app/controllers/messages_controller.rb +25 -19
  36. data/app/controllers/metro_areas_controller.rb +9 -3
  37. data/app/controllers/moderators_controller.rb +1 -1
  38. data/app/controllers/monitorships_controller.rb +2 -2
  39. data/app/controllers/pages_controller.rb +16 -4
  40. data/app/controllers/password_resets_controller.rb +0 -1
  41. data/app/controllers/photos_controller.rb +32 -30
  42. data/app/controllers/posts_controller.rb +33 -17
  43. data/app/controllers/rsvps_controller.rb +8 -4
  44. data/app/controllers/sb_posts_controller.rb +22 -18
  45. data/app/controllers/sessions_controller.rb +2 -1
  46. data/app/controllers/sitemap_controller.rb +8 -8
  47. data/app/controllers/statistics_controller.rb +9 -8
  48. data/app/controllers/tags_controller.rb +26 -24
  49. data/app/controllers/topics_controller.rb +10 -6
  50. data/app/controllers/users_controller.rb +63 -34
  51. data/app/helpers/base_helper.rb +119 -29
  52. data/app/helpers/friendships_helper.rb +3 -3
  53. data/app/helpers/posts_helper.rb +5 -7
  54. data/app/models/acts_as_taggable_on/tag.rb +12 -13
  55. data/app/models/ad.rb +2 -5
  56. data/app/models/album.rb +0 -2
  57. data/app/models/category.rb +6 -7
  58. data/app/models/clipping.rb +2 -5
  59. data/app/models/clipping_image.rb +5 -5
  60. data/app/models/comment.rb +4 -5
  61. data/app/models/country.rb +2 -4
  62. data/app/models/event.rb +1 -2
  63. data/app/models/favorite.rb +5 -10
  64. data/app/models/forum.rb +0 -2
  65. data/app/models/friendship.rb +3 -5
  66. data/app/models/friendship_status.rb +0 -2
  67. data/app/models/homepage_feature.rb +4 -6
  68. data/app/models/invitation.rb +6 -8
  69. data/app/models/message.rb +25 -26
  70. data/app/models/message_thread.rb +1 -1
  71. data/app/models/metro_area.rb +0 -2
  72. data/app/models/page.rb +0 -2
  73. data/app/models/photo.rb +8 -8
  74. data/app/models/poll.rb +7 -9
  75. data/app/models/post.rb +11 -15
  76. data/app/models/role.rb +1 -2
  77. data/app/models/rsvp.rb +0 -3
  78. data/app/models/sb_post.rb +14 -9
  79. data/app/models/state.rb +0 -2
  80. data/app/models/topic.rb +5 -6
  81. data/app/models/user.rb +50 -63
  82. data/app/models/vote.rb +1 -1
  83. data/app/views/activities/_activity.html.haml +9 -9
  84. data/app/views/activities/destroy.js.erb +1 -0
  85. data/app/views/activities/index.html.haml +13 -13
  86. data/app/views/activities/network.html.haml +10 -13
  87. data/app/views/admin/comments.html.haml +48 -70
  88. data/app/views/admin/events.html.haml +20 -27
  89. data/app/views/admin/messages.html.haml +2 -3
  90. data/app/views/admin/update.js.erb +1 -0
  91. data/app/views/admin/users.html.haml +51 -66
  92. data/app/views/ads/_form.html.haml +21 -0
  93. data/app/views/ads/edit.html.haml +6 -46
  94. data/app/views/ads/index.html.haml +25 -39
  95. data/app/views/ads/new.html.haml +4 -43
  96. data/app/views/ads/show.html.haml +18 -35
  97. data/app/views/albums/_form.html.haml +17 -12
  98. data/app/views/albums/edit.html.haml +12 -14
  99. data/app/views/albums/new.html.haml +8 -13
  100. data/app/views/albums/show.html.haml +25 -32
  101. data/app/views/base/_homepage_banner_message.html.haml +5 -19
  102. data/app/views/base/advertise.html.haml +5 -8
  103. data/app/views/base/site_index.html.haml +25 -27
  104. data/app/views/categories/_form.html.haml +8 -0
  105. data/app/views/categories/_menu_item.html.haml +13 -0
  106. data/app/views/categories/_tips.html.haml +2 -2
  107. data/app/views/categories/edit.html.haml +3 -33
  108. data/app/views/categories/index.html.haml +18 -28
  109. data/app/views/categories/new.html.haml +3 -8
  110. data/app/views/categories/show.html.haml +33 -36
  111. data/app/views/clippings/_clipping.html.haml +10 -17
  112. data/app/views/clippings/_favorite.html.haml +14 -0
  113. data/app/views/clippings/_form.html.haml +15 -0
  114. data/app/views/clippings/_images.html.haml +1 -1
  115. data/app/views/clippings/_menu_item.html.haml +6 -0
  116. data/app/views/clippings/edit.html.haml +12 -23
  117. data/app/views/clippings/index.html.haml +29 -30
  118. data/app/views/clippings/load_images_from_uri.js.erb +1 -0
  119. data/app/views/clippings/new.html.haml +9 -26
  120. data/app/views/clippings/new_clipping.html.haml +30 -77
  121. data/app/views/clippings/show.html.haml +48 -53
  122. data/app/views/clippings/site_index.html.haml +19 -32
  123. data/app/views/comments/_comment.html.haml +40 -40
  124. data/app/views/comments/_comment_form.html.haml +22 -46
  125. data/app/views/comments/_edit_form.html.haml +13 -28
  126. data/app/views/comments/create.js.erb +25 -0
  127. data/app/views/comments/destroy.js.erb +3 -0
  128. data/app/views/comments/edit.js.erb +11 -0
  129. data/app/views/comments/index.html.haml +12 -22
  130. data/app/views/comments/update.js.erb +14 -0
  131. data/app/views/events/_event.html.haml +26 -24
  132. data/app/views/events/_form.html.haml +18 -0
  133. data/app/views/events/_menu_item.html.haml +6 -0
  134. data/app/views/events/_subscribe.html.haml +1 -1
  135. data/app/views/events/edit.html.haml +7 -32
  136. data/app/views/events/index.html.haml +11 -19
  137. data/app/views/events/new.html.haml +2 -31
  138. data/app/views/events/show.html.haml +54 -24
  139. data/app/views/favorites/create.js.erb +10 -0
  140. data/app/views/favorites/destroy.js.erb +6 -0
  141. data/app/views/favorites/index.html.haml +6 -8
  142. data/app/views/forums/_form.html.haml +10 -20
  143. data/app/views/forums/_menu_item.html.haml +6 -0
  144. data/app/views/forums/edit.html.haml +8 -10
  145. data/app/views/forums/index.html.haml +56 -64
  146. data/app/views/forums/new.html.haml +5 -8
  147. data/app/views/forums/show.html.haml +65 -72
  148. data/app/views/friendships/_friendship.html.haml +14 -16
  149. data/app/views/friendships/accepted.html.haml +7 -11
  150. data/app/views/friendships/create.js.haml +1 -0
  151. data/app/views/friendships/denied.html.haml +4 -8
  152. data/app/views/friendships/pending.html.haml +4 -6
  153. data/app/views/friendships/show.html.haml +10 -11
  154. data/app/views/homepage_features/_form.html.haml +6 -0
  155. data/app/views/homepage_features/edit.html.haml +5 -30
  156. data/app/views/homepage_features/index.html.haml +22 -28
  157. data/app/views/homepage_features/new.html.haml +2 -30
  158. data/app/views/homepage_features/show.html.haml +27 -29
  159. data/app/views/invitations/index.html.haml +8 -0
  160. data/app/views/invitations/new.html.haml +21 -30
  161. data/app/views/kaminari/bootstrap/_first_page.html.erb +13 -0
  162. data/app/views/kaminari/bootstrap/_gap.html.erb +8 -0
  163. data/app/views/kaminari/bootstrap/_last_page.html.erb +13 -0
  164. data/app/views/kaminari/bootstrap/_next_page.html.erb +13 -0
  165. data/app/views/kaminari/bootstrap/_page.html.erb +12 -0
  166. data/app/views/kaminari/bootstrap/_paginator.html.erb +25 -0
  167. data/app/views/kaminari/bootstrap/_prev_page.html.erb +13 -0
  168. data/app/views/layouts/application.html.haml +26 -37
  169. data/app/views/messages/_form.html.haml +6 -12
  170. data/app/views/messages/_inbox.html.haml +34 -39
  171. data/app/views/messages/_menu_item.html.haml +11 -0
  172. data/app/views/messages/_sent.html.haml +22 -33
  173. data/app/views/messages/_sidebar_nav.html.haml +12 -9
  174. data/app/views/messages/index.html.haml +2 -2
  175. data/app/views/messages/new.html.haml +2 -9
  176. data/app/views/messages/show.html.haml +28 -36
  177. data/app/views/metro_areas/_form.html.haml +6 -0
  178. data/app/views/metro_areas/edit.html.haml +6 -14
  179. data/app/views/metro_areas/index.html.haml +19 -26
  180. data/app/views/metro_areas/new.html.haml +4 -14
  181. data/app/views/metro_areas/show.html.haml +13 -21
  182. data/app/views/moderators/_toggle.html.haml +6 -0
  183. data/app/views/moderators/create.js.erb +5 -0
  184. data/app/views/moderators/destroy.js.erb +1 -0
  185. data/app/views/monitorships/create.js.erb +1 -0
  186. data/app/views/monitorships/destroy.js.erb +1 -0
  187. data/app/views/pages/_form.html.haml +16 -23
  188. data/app/views/pages/edit.html.haml +2 -14
  189. data/app/views/pages/index.html.haml +32 -32
  190. data/app/views/pages/new.html.haml +5 -12
  191. data/app/views/pages/show.html.haml +4 -8
  192. data/app/views/password_resets/edit.html.haml +6 -14
  193. data/app/views/password_resets/new.html.haml +7 -11
  194. data/app/views/photo_manager/index.html.haml +45 -43
  195. data/app/views/photos/_form.html.haml +24 -0
  196. data/app/views/photos/_manage_photos.html.haml +14 -6
  197. data/app/views/photos/_show_image_list.html.haml +2 -2
  198. data/app/views/photos/create.js.erb +1 -0
  199. data/app/views/photos/edit.html.haml +10 -38
  200. data/app/views/photos/index.html.haml +20 -20
  201. data/app/views/photos/manage_photos.js.erb +5 -0
  202. data/app/views/photos/new.html.haml +11 -49
  203. data/app/views/photos/recent.html.haml +6 -6
  204. data/app/views/photos/show.html.haml +48 -52
  205. data/app/views/polls/_edit.html.haml +6 -10
  206. data/app/views/polls/_excerpt.html.haml +3 -4
  207. data/app/views/polls/_new.html.haml +10 -9
  208. data/app/views/polls/_poll_ui.html.haml +30 -34
  209. data/app/views/posts/_author_profile.html.haml +12 -11
  210. data/app/views/posts/_favorited_post.html.haml +8 -10
  211. data/app/views/posts/_form.html.haml +40 -0
  212. data/app/views/posts/_menu_item.html.haml +6 -0
  213. data/app/views/posts/_post.html.haml +27 -24
  214. data/app/views/posts/_send_to_friend.html.haml +26 -0
  215. data/app/views/posts/edit.html.haml +11 -48
  216. data/app/views/posts/featured.html.haml +7 -12
  217. data/app/views/posts/index.html.haml +14 -18
  218. data/app/views/posts/manage.html.haml +44 -59
  219. data/app/views/posts/new.html.haml +9 -64
  220. data/app/views/posts/popular.html.haml +25 -30
  221. data/app/views/posts/preview.html.haml +27 -26
  222. data/app/views/posts/recent.html.haml +20 -27
  223. data/app/views/posts/send_to_friend.js.erb +3 -0
  224. data/app/views/posts/show.html.haml +67 -76
  225. data/app/views/rsvps/_form.html.haml +3 -0
  226. data/app/views/rsvps/edit.html.haml +3 -9
  227. data/app/views/rsvps/new.html.haml +3 -9
  228. data/app/views/sb_posts/_dummy_forum_post.html.haml +13 -0
  229. data/app/views/sb_posts/_edit.html.haml +6 -0
  230. data/app/views/sb_posts/_edit_script.js.erb +14 -0
  231. data/app/views/sb_posts/_reply_form.html.haml +14 -35
  232. data/app/views/sb_posts/_reply_script.js.erb +13 -0
  233. data/app/views/sb_posts/_sb_post.html.haml +31 -33
  234. data/app/views/sb_posts/create.js.erb +30 -0
  235. data/app/views/sb_posts/destroy.js.erb +2 -0
  236. data/app/views/sb_posts/edit.html.erb +4 -4
  237. data/app/views/sb_posts/edit.js.erb +14 -0
  238. data/app/views/sb_posts/index.html.haml +3 -16
  239. data/app/views/sb_posts/monitored.html.erb +3 -9
  240. data/app/views/sb_posts/update.js.erb +11 -0
  241. data/app/views/sessions/_menu_item.html.haml +28 -0
  242. data/app/views/sessions/new.html.haml +19 -24
  243. data/app/views/shared/_add_friend_link.html.haml +9 -0
  244. data/app/views/shared/_admin_nav.html.haml +6 -8
  245. data/app/views/shared/_contact.html.haml +1 -1
  246. data/app/views/shared/_end_javascript.html.haml +4 -4
  247. data/app/views/shared/_explore.html.haml +7 -6
  248. data/app/views/shared/_footer_content.html.haml +12 -10
  249. data/app/views/shared/_footer_links.html.haml +18 -0
  250. data/app/views/shared/_friend_link.html.haml +25 -0
  251. data/app/views/shared/_header.html.haml +22 -42
  252. data/app/views/shared/_jumbotron.html.haml +3 -0
  253. data/app/views/shared/_load_tinymce.js.erb +15 -0
  254. data/app/views/shared/_location_chooser.html.haml +26 -17
  255. data/app/views/shared/_login_sidebar.html.haml +6 -5
  256. data/app/views/shared/_messages.html.haml +6 -8
  257. data/app/views/shared/_scripts_and_styles.html.haml +1 -2
  258. data/app/views/shared/_sidebar.html.haml +1 -0
  259. data/app/views/shared/_tag_auto_complete.html.haml +19 -0
  260. data/app/views/shared/_widget.html.haml +3 -0
  261. data/app/views/sitemap/index.html.haml +15 -20
  262. data/app/views/statistics/index.html.haml +32 -40
  263. data/app/views/tags/edit.html.haml +12 -19
  264. data/app/views/tags/index.html.haml +16 -25
  265. data/app/views/tags/manage.html.haml +24 -33
  266. data/app/views/tags/show.html.haml +52 -58
  267. data/app/views/topics/_form.html.haml +23 -25
  268. data/app/views/topics/_recent_topics_sidebar.haml +1 -1
  269. data/app/views/topics/edit.html.haml +7 -9
  270. data/app/views/topics/new.html.haml +6 -21
  271. data/app/views/topics/show.html.haml +48 -106
  272. data/app/views/user_notifier/follow_up_comment_notice.text.erb +1 -1
  273. data/app/views/user_notifier/message_notification.text.erb +1 -1
  274. data/app/views/user_notifier/new_forum_post_notice.text.erb +1 -1
  275. data/app/views/users/_dashboard_nav.html.haml +36 -39
  276. data/app/views/users/_menu_item.html.haml +6 -0
  277. data/app/views/users/_omniauth_connect.html.haml +4 -4
  278. data/app/views/users/_profile_completeness.html.haml +3 -3
  279. data/app/views/users/_profile_user_info_sidebar.html.haml +40 -43
  280. data/app/views/users/_search_options.html.haml +9 -7
  281. data/app/views/users/_sidebar_user.html.haml +1 -1
  282. data/app/views/users/_user.html.haml +27 -28
  283. data/app/views/users/crop_profile_photo.html.haml +30 -37
  284. data/app/views/users/dashboard.html.haml +37 -41
  285. data/app/views/users/edit.html.haml +53 -71
  286. data/app/views/users/edit_account.html.haml +44 -64
  287. data/app/views/users/forgot_username.html.haml +6 -12
  288. data/app/views/users/index.html.haml +4 -14
  289. data/app/views/users/invite.html.haml +14 -25
  290. data/app/views/users/new.html.haml +27 -48
  291. data/app/views/users/resend_activation.html.haml +7 -12
  292. data/app/views/users/show.html.haml +88 -90
  293. data/app/views/users/signup_completed.html.haml +7 -7
  294. data/app/views/users/statistics.html.haml +17 -18
  295. data/app/views/users/update.js.erb +1 -0
  296. data/app/views/users/upload_profile_photo.html.haml +10 -15
  297. data/app/views/users/welcome_about.html.haml +54 -61
  298. data/app/views/users/welcome_invite.html.haml +16 -25
  299. data/app/views/users/welcome_photo.html.haml +18 -27
  300. data/app/views/votes/create.js.erb +5 -0
  301. data/community_engine.gemspec +49 -41
  302. data/config/application_config.rb +13 -16
  303. data/config/initializers/mce_options.rb +9 -32
  304. data/config/initializers/recaptcha_constants.rb +2 -2
  305. data/config/locales/de-DE.yml +1 -17
  306. data/config/locales/en.yml +18 -32
  307. data/config/locales/es-AR.yml +2 -14
  308. data/config/locales/es-ES.yml +0 -6
  309. data/config/locales/es-MX.yml +1 -9
  310. data/config/locales/fr-FR.yml +3 -17
  311. data/config/locales/ja-JP.yml +2 -18
  312. data/config/locales/ru-RU.yml +3 -21
  313. data/config/locales/sr-CP.yml +0 -4
  314. data/config/locales/sv-SE.yml +3 -20
  315. data/config/routes.rb +37 -42
  316. data/db/migrate/016_add_metro_areas.rb +2 -2
  317. data/db/migrate/039_create_activities_table.rb +2 -2
  318. data/db/migrate/056_create_roles.rb +8 -6
  319. data/db/migrate/069_create_pages.rb +3 -3
  320. data/db/migrate/081_upgrade_to_friendly_id_5x.rb +25 -0
  321. data/db/migrate/082_upgrade_to_acts_as_commentable_4x.rb +29 -0
  322. data/lib/activity_tracker.rb +3 -0
  323. data/{vendor/plugins/activity_tracker/lib → lib/activity_tracker}/activity.rb +6 -6
  324. data/{vendor/plugins/activity_tracker/lib → lib/activity_tracker}/activity_tracker.rb +0 -0
  325. data/{vendor/plugins/acts_as_publishable/init.rb → lib/acts_as_publishable.rb} +1 -1
  326. data/{vendor/plugins/acts_as_publishable/lib → lib/acts_as_publishable}/acts_as_publishable.rb +3 -3
  327. data/lib/community_engine.rb +31 -9
  328. data/lib/community_engine/engine.rb +17 -1
  329. data/lib/community_engine/engines_extensions.rb +1 -3
  330. data/lib/community_engine/version.rb +3 -3
  331. data/{config/initializers → lib/paperclip_processors}/cropper.rb +3 -3
  332. data/lib/resource_feeder.rb +3 -0
  333. data/{vendor/plugins/resource_feeder/lib → lib}/resource_feeder/atom.rb +0 -0
  334. data/{vendor/plugins/resource_feeder/lib → lib}/resource_feeder/rss.rb +0 -0
  335. data/{vendor/plugins/white_list/init.rb → lib/white_list.rb} +1 -1
  336. data/{vendor/plugins/white_list/lib → lib/white_list}/white_list_helper.rb +0 -0
  337. data/test/fixtures/messages.yml +2 -2
  338. data/test/functional/admin_controller_test.rb +11 -11
  339. data/test/functional/ads_controller_test.rb +11 -11
  340. data/test/functional/albums_controller_test.rb +4 -4
  341. data/test/functional/categories_controller_test.rb +4 -4
  342. data/test/functional/clippings_controller_test.rb +4 -4
  343. data/test/functional/comments_controller_test.rb +20 -16
  344. data/test/functional/events_controller_test.rb +6 -6
  345. data/test/functional/forums_controller_test.rb +8 -8
  346. data/test/functional/friendships_controller_test.rb +13 -18
  347. data/test/functional/homepage_features_controller_test.rb +5 -5
  348. data/test/functional/messages_controller_test.rb +6 -2
  349. data/test/functional/metro_areas_controller_test.rb +7 -7
  350. data/test/functional/moderators_controller_test.rb +1 -1
  351. data/test/functional/pages_controller_test.rb +2 -2
  352. data/test/functional/password_reset_controller_test.rb +2 -2
  353. data/test/functional/photos_controller_test.rb +16 -15
  354. data/test/functional/posts_controller_test.rb +4 -4
  355. data/test/functional/rsvps_controller_test.rb +6 -6
  356. data/test/functional/sb_posts_controller_test.rb +53 -50
  357. data/test/functional/sessions_controller_test.rb +4 -1
  358. data/test/functional/tags_controller_test.rb +1 -1
  359. data/test/functional/topics_controller_test.rb +10 -10
  360. data/test/functional/users_controller_test.rb +32 -19
  361. data/test/functional/votes_controller_test.rb +1 -1
  362. data/test/test_helper.rb +3 -1
  363. data/test/testapp/config/application.rb +1 -9
  364. data/test/testapp/config/environments/development.rb +1 -2
  365. data/test/testapp/config/environments/production.rb +2 -0
  366. data/test/testapp/config/environments/test.rb +1 -2
  367. data/test/testapp/config/initializers/omniauth.rb +3 -3
  368. data/test/testapp/config/initializers/secret_token.rb +1 -0
  369. data/test/testapp/db/schema.rb +143 -152
  370. data/test/unit/category_test.rb +2 -2
  371. data/test/unit/comment_test.rb +64 -53
  372. data/test/unit/event_test.rb +4 -4
  373. data/test/unit/forum_test.rb +1 -1
  374. data/test/unit/message_test.rb +7 -1
  375. data/test/unit/page_test.rb +2 -2
  376. data/test/unit/post_test.rb +47 -47
  377. data/test/unit/sb_post_test.rb +24 -20
  378. data/test/unit/topic_test.rb +7 -6
  379. data/test/unit/user_test.rb +75 -52
  380. data/vendor/assets/javascripts/.gitkeep +0 -0
  381. data/vendor/assets/javascripts/jcrop/jquery.Jcrop.js +1699 -0
  382. data/vendor/assets/javascripts/jcrop/jquery.color.js +661 -0
  383. data/vendor/assets/javascripts/tag-it/tag-it.js +597 -0
  384. data/vendor/assets/stylesheets/.gitkeep +0 -0
  385. data/vendor/assets/stylesheets/jcrop/Jcrop.gif +0 -0
  386. data/vendor/assets/stylesheets/jcrop/jquery.Jcrop.min.css +28 -0
  387. data/vendor/assets/stylesheets/tag-it/tag-it.css +69 -0
  388. data/vendor/assets/stylesheets/tag-it/tagit.ui-zendesk.css +107 -0
  389. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/acts_as_publishable/README +0 -0
  390. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/acts_as_publishable/Rakefile +0 -0
  391. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/acts_as_publishable/generators/publishing/publishing_generator.rb +0 -0
  392. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/acts_as_publishable/generators/publishing/templates/migration.rb +0 -0
  393. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/acts_as_publishable/install.rb +0 -0
  394. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/acts_as_publishable/test/acts_as_publishable_test.rb +0 -0
  395. data/vendor/{plugins/activity_tracker → converted2.3plugins_to_lib_leftovers/acts_as_publishable}/uninstall.rb +0 -0
  396. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/resource_feeder/README +0 -0
  397. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/resource_feeder/Rakefile +0 -0
  398. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/resource_feeder/test/atom_feed_test.rb +0 -0
  399. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/resource_feeder/test/rss_feed_test.rb +0 -0
  400. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/resource_feeder/test/test_helper.rb +0 -0
  401. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/white_list/README +0 -0
  402. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/white_list/Rakefile +0 -0
  403. data/vendor/{plugins → converted2.3plugins_to_lib_leftovers}/white_list/test/white_list_test.rb +0 -0
  404. metadata +348 -302
  405. data/app/assets/images/bg_h6btn.gif +0 -0
  406. data/app/assets/images/bg_navbar.gif +0 -0
  407. data/app/assets/images/clearbits/bg_rounded.gif +0 -0
  408. data/app/assets/images/clearbits/comment.gif +0 -0
  409. data/app/assets/images/clearbits/lock.gif +0 -0
  410. data/app/assets/images/clearbits/smile.gif +0 -0
  411. data/app/assets/images/close.gif +0 -0
  412. data/app/assets/images/cropper/marqueeHoriz.gif +0 -0
  413. data/app/assets/images/cropper/marqueeVert.gif +0 -0
  414. data/app/assets/images/feed.png +0 -0
  415. data/app/assets/images/icons/31.png +0 -0
  416. data/app/assets/images/icons/52.png +0 -0
  417. data/app/assets/images/icons/accept.png +0 -0
  418. data/app/assets/images/icons/activity_default.png +0 -0
  419. data/app/assets/images/icons/add.png +0 -0
  420. data/app/assets/images/icons/book.png +0 -0
  421. data/app/assets/images/icons/bullet_arrow_down.png +0 -0
  422. data/app/assets/images/icons/bullet_arrow_down_50.png +0 -0
  423. data/app/assets/images/icons/clipping.png +0 -0
  424. data/app/assets/images/icons/comment.png +0 -0
  425. data/app/assets/images/icons/comments.png +0 -0
  426. data/app/assets/images/icons/date.png +0 -0
  427. data/app/assets/images/icons/delete.png +0 -0
  428. data/app/assets/images/icons/email.png +0 -0
  429. data/app/assets/images/icons/email_edit.png +0 -0
  430. data/app/assets/images/icons/email_go.png +0 -0
  431. data/app/assets/images/icons/email_open.png +0 -0
  432. data/app/assets/images/icons/group_go.png +0 -0
  433. data/app/assets/images/icons/heart.png +0 -0
  434. data/app/assets/images/icons/heart_add.png +0 -0
  435. data/app/assets/images/icons/heart_off.png +0 -0
  436. data/app/assets/images/icons/page_white.png +0 -0
  437. data/app/assets/images/icons/page_white_magnify.png +0 -0
  438. data/app/assets/images/icons/picture.png +0 -0
  439. data/app/assets/images/icons/poll.png +0 -0
  440. data/app/assets/images/icons/post.png +0 -0
  441. data/app/assets/images/icons/printer.png +0 -0
  442. data/app/assets/images/icons/rss.png +0 -0
  443. data/app/assets/images/icons/slides.png +0 -0
  444. data/app/assets/images/icons/tag_blue.png +0 -0
  445. data/app/assets/images/icons/user.png +0 -0
  446. data/app/assets/images/icons/user_add.png +0 -0
  447. data/app/assets/images/icons/user_edit.png +0 -0
  448. data/app/assets/images/icons/user_go.png +0 -0
  449. data/app/assets/images/icons/vote.png +0 -0
  450. data/app/assets/images/icons/world.png +0 -0
  451. data/app/assets/images/icons/wrench.png +0 -0
  452. data/app/assets/images/logo.gif +0 -0
  453. data/app/assets/images/reply_background.png +0 -0
  454. data/app/assets/images/search.gif +0 -0
  455. data/app/assets/images/thumb.gif +0 -0
  456. data/app/assets/javascripts/builder.js +0 -136
  457. data/app/assets/javascripts/calendarview.js +0 -839
  458. data/app/assets/javascripts/lightbox.js +0 -151
  459. data/app/assets/javascripts/prototip-min.js +0 -27
  460. data/app/assets/javascripts/rails.js +0 -202
  461. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/css/advimage.css +0 -84
  462. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/editor_plugin.js +0 -52
  463. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/editor_plugin_src.js +0 -45
  464. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/image.htm +0 -180
  465. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/img/sample.gif +0 -0
  466. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/js/functions.js +0 -508
  467. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/langs/en.js +0 -3
  468. data/app/assets/javascripts/tinymce/plugins/curblyadvimage/langs/en_dlg.js +0 -43
  469. data/app/assets/javascripts/tinymce/plugins/tinyautosave/editor_plugin.js +0 -8
  470. data/app/assets/javascripts/tinymce/plugins/tinyautosave/editor_plugin_src.js +0 -1001
  471. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress.gif +0 -0
  472. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress10.gif +0 -0
  473. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress11.gif +0 -0
  474. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress12.gif +0 -0
  475. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress2.gif +0 -0
  476. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress3.gif +0 -0
  477. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress4.gif +0 -0
  478. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress5.gif +0 -0
  479. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress6.gif +0 -0
  480. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress7.gif +0 -0
  481. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress8.gif +0 -0
  482. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/progress9.gif +0 -0
  483. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/restore.gif +0 -0
  484. data/app/assets/javascripts/tinymce/plugins/tinyautosave/images/restore.png +0 -0
  485. data/app/assets/javascripts/tinymce/plugins/tinyautosave/langs/da.js +0 -5
  486. data/app/assets/javascripts/tinymce/plugins/tinyautosave/langs/en.js +0 -5
  487. data/app/assets/stylesheets/community_engine.css +0 -6
  488. data/app/assets/stylesheets/forum.css +0 -605
  489. data/app/assets/stylesheets/prototip.css +0 -73
  490. data/app/assets/stylesheets/reset-fonts-grids.css +0 -8
  491. data/app/assets/stylesheets/screen.css +0 -977
  492. data/app/helpers/monitorships_helper.rb +0 -2
  493. data/app/views/activities/_icon.html.haml +0 -14
  494. data/app/views/activities/destroy.js.rjs +0 -1
  495. data/app/views/clippings/_meta.html.haml +0 -26
  496. data/app/views/clippings/load_images_from_uri.js.rjs +0 -1
  497. data/app/views/comments/create.js.rjs +0 -20
  498. data/app/views/comments/edit.js.rjs +0 -7
  499. data/app/views/comments/update.js.rjs +0 -9
  500. data/app/views/favorites/create.js.rjs +0 -17
  501. data/app/views/favorites/destroy.js.rjs +0 -14
  502. data/app/views/favorites/show.html.haml +0 -13
  503. data/app/views/friendships/_friendships.html.erb +0 -14
  504. data/app/views/friendships/index.html.erb +0 -3
  505. data/app/views/friendships/index.xml.builder +0 -29
  506. data/app/views/invitations/index.html.erb +0 -16
  507. data/app/views/moderators/_toggle.html.erb +0 -14
  508. data/app/views/moderators/create.js.rjs +0 -5
  509. data/app/views/moderators/destroy.js.rjs +0 -1
  510. data/app/views/monitorships/create.js.rjs +0 -4
  511. data/app/views/monitorships/destroy.js.rjs +0 -4
  512. data/app/views/photos/manage_photos.js.rjs +0 -5
  513. data/app/views/polls/_polls_sidebar.html.haml +0 -8
  514. data/app/views/posts/_send_to_friend.html.erb +0 -29
  515. data/app/views/sb_posts/_dummy_forum_post.html.erb +0 -13
  516. data/app/views/sb_posts/_edit.html.erb +0 -31
  517. data/app/views/sb_posts/create.js.rjs +0 -16
  518. data/app/views/sb_posts/edit.js.rjs +0 -6
  519. data/app/views/sb_posts/update.js.rjs +0 -5
  520. data/app/views/shared/_user_menu.html.haml +0 -21
  521. data/app/views/votes/create.js.rjs +0 -6
  522. data/db/migrate/090_add_comment_role.rb +0 -15
  523. data/vendor/plugins/activity_tracker/README +0 -4
  524. data/vendor/plugins/activity_tracker/Rakefile +0 -22
  525. data/vendor/plugins/activity_tracker/generators/activity_migration/USAGE +0 -13
  526. data/vendor/plugins/activity_tracker/generators/activity_migration/activity_migration_generator.rb +0 -11
  527. data/vendor/plugins/activity_tracker/generators/activity_migration/templates/migration.rb +0 -17
  528. data/vendor/plugins/activity_tracker/init.rb +0 -1
  529. data/vendor/plugins/activity_tracker/install.rb +0 -1
  530. data/vendor/plugins/activity_tracker/tasks/activity_tracker_tasks.rake +0 -4
  531. data/vendor/plugins/activity_tracker/test/abstract_unit.rb +0 -47
  532. data/vendor/plugins/activity_tracker/test/activity_tracker_test.rb +0 -48
  533. data/vendor/plugins/activity_tracker/test/database.yml +0 -18
  534. data/vendor/plugins/activity_tracker/test/debug.log +0 -3329
  535. data/vendor/plugins/activity_tracker/test/fixtures/test_post.rb +0 -5
  536. data/vendor/plugins/activity_tracker/test/fixtures/test_posts.yml +0 -3
  537. data/vendor/plugins/activity_tracker/test/fixtures/test_user.rb +0 -4
  538. data/vendor/plugins/activity_tracker/test/fixtures/test_users.yml +0 -6
  539. data/vendor/plugins/activity_tracker/test/schema.rb +0 -21
  540. data/vendor/plugins/acts_as_list/README +0 -23
  541. data/vendor/plugins/acts_as_list/init.rb +0 -3
  542. data/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb +0 -256
  543. data/vendor/plugins/acts_as_list/test/list_test.rb +0 -332
  544. data/vendor/plugins/acts_as_publishable/uninstall.rb +0 -1
  545. data/vendor/plugins/auto_complete/README +0 -23
  546. data/vendor/plugins/auto_complete/Rakefile +0 -22
  547. data/vendor/plugins/auto_complete/init.rb +0 -2
  548. data/vendor/plugins/auto_complete/lib/auto_complete.rb +0 -47
  549. data/vendor/plugins/auto_complete/lib/auto_complete_macros_helper.rb +0 -143
  550. data/vendor/plugins/auto_complete/test/auto_complete_test.rb +0 -67
  551. data/vendor/plugins/enumerations_mixin/.gitignore +0 -1
  552. data/vendor/plugins/enumerations_mixin/Gemfile +0 -1
  553. data/vendor/plugins/enumerations_mixin/LICENSE +0 -20
  554. data/vendor/plugins/enumerations_mixin/README.md +0 -120
  555. data/vendor/plugins/enumerations_mixin/README_ENUMERATIONS +0 -163
  556. data/vendor/plugins/enumerations_mixin/Rakefile +0 -14
  557. data/vendor/plugins/enumerations_mixin/VERSION +0 -1
  558. data/vendor/plugins/enumerations_mixin/enumerations_mixin.gemspec +0 -44
  559. data/vendor/plugins/enumerations_mixin/examples/virtual_enumerations_sample.rb +0 -76
  560. data/vendor/plugins/enumerations_mixin/init.rb +0 -21
  561. data/vendor/plugins/enumerations_mixin/lib/active_record/acts/enumerated.rb +0 -180
  562. data/vendor/plugins/enumerations_mixin/lib/active_record/aggregations/has_enumerated.rb +0 -60
  563. data/vendor/plugins/enumerations_mixin/lib/active_record/virtual_enumerations.rb +0 -68
  564. data/vendor/plugins/enumerations_mixin/lib/enumerations_mixin.rb +0 -12
  565. data/vendor/plugins/enumerations_mixin/virtual_enumerations_sample.rb +0 -76
  566. data/vendor/plugins/prototype_legacy_helper/README.markdown +0 -13
  567. data/vendor/plugins/prototype_legacy_helper/init.rb +0 -1
  568. data/vendor/plugins/prototype_legacy_helper/lib/prototype_legacy_helper.rb +0 -432
  569. data/vendor/plugins/prototype_legacy_helper/test/test_prototype_helper.rb +0 -297
  570. data/vendor/plugins/resource_feeder/init.rb +0 -2
  571. data/vendor/plugins/resource_feeder/lib/resource_feeder.rb +0 -2
  572. data/vendor/plugins/respond_to_parent/MIT-LICENSE +0 -20
  573. data/vendor/plugins/respond_to_parent/README +0 -47
  574. data/vendor/plugins/respond_to_parent/Rakefile +0 -22
  575. data/vendor/plugins/respond_to_parent/init.rb +0 -1
  576. data/vendor/plugins/respond_to_parent/install.rb +0 -1
  577. data/vendor/plugins/respond_to_parent/lib/responds_to_parent.rb +0 -70
  578. data/vendor/plugins/respond_to_parent/test/responds_to_parent_test.rb +0 -10
  579. data/vendor/plugins/respond_to_parent/test/test_helper.rb +0 -6
  580. data/vendor/plugins/respond_to_parent/uninstall.rb +0 -1
@@ -88,7 +88,7 @@ class SbPostTest < ActiveSupport::TestCase
88
88
  topic = topics(:pdi)
89
89
  user = users(:aaron)
90
90
  create_post topic, :body => 'foo'
91
- Monitorship.update_all ['active = ?', false], ['user_id = ? and topic_id = ?', user.id, topic.id]
91
+ Monitorship.where('user_id = ? and topic_id = ?', user.id, topic.id).update_all( ['active = ?', false])
92
92
  assert !user.monitoring_topic?(topic)
93
93
 
94
94
  p = create_post topic, :body => 'bar'
@@ -96,14 +96,15 @@ class SbPostTest < ActiveSupport::TestCase
96
96
  end
97
97
 
98
98
  test "should not monitor for anonymous posts" do
99
- configatron.allow_anonymous_forum_posting = true
100
-
101
- assert_difference Monitorship, :count, 0 do
102
- topic = topics(:pdi)
103
- topic.sb_posts.create!(:topic => topic, :body => "Ok!", :author_email => 'anon@example.com', :author_ip => "1.2.3.4")
99
+ configatron.temp do
100
+ configatron.allow_anonymous_forum_posting = true
101
+
102
+ assert_difference Monitorship, :count, 0 do
103
+ topic = topics(:pdi)
104
+ topic.sb_posts.create!(:topic => topic, :body => "Ok!", :author_email => 'anon@example.com', :author_ip => "1.2.3.4")
105
+ end
106
+
104
107
  end
105
-
106
- configatron.allow_anonymous_forum_posting = false
107
108
  end
108
109
 
109
110
  def test_should_be_deleted_when_user_destroyed
@@ -114,21 +115,24 @@ class SbPostTest < ActiveSupport::TestCase
114
115
  end
115
116
 
116
117
  test "should not allow anonymous posting" do
117
- configatron.allow_anonymous_forum_posting = false
118
- topic = topics(:pdi)
119
- post = topic.sb_posts.create(:topic => topic, :body => "Ok!", :author_email => 'anon@example.com', :author_ip => "1.2.3.4")
120
- assert !post.valid?
121
- assert post.errors[:user_id]
118
+ configatron.temp do
119
+ configatron.allow_anonymous_forum_posting = false
120
+ topic = topics(:pdi)
121
+ post = topic.sb_posts.create(:topic => topic, :body => "Ok!", :author_email => 'anon@example.com', :author_ip => "1.2.3.4")
122
+ assert !post.valid?
123
+ assert post.errors[:user_id]
124
+ end
122
125
  end
123
126
 
124
127
  test "should allow anonymous posting if configatron specifies it's ok" do
125
- configatron.allow_anonymous_forum_posting = true
126
-
127
- topic = topics(:pdi)
128
-
129
- assert topic.sb_posts.create!(:topic => topic, :body => "Ok!", :author_email => 'anon@example.com', :author_ip => "1.2.3.4")
130
-
131
- configatron.allow_anonymous_forum_posting = false
128
+ configatron.temp do
129
+ configatron.allow_anonymous_forum_posting = true
130
+
131
+ topic = topics(:pdi)
132
+
133
+ assert topic.sb_posts.create!(:topic => topic, :body => "Ok!", :author_email => 'anon@example.com', :author_ip => "1.2.3.4")
134
+
135
+ end
132
136
  end
133
137
 
134
138
  test "should tranform body before saving" do
@@ -72,7 +72,7 @@ class TopicTest < ActiveSupport::TestCase
72
72
  end
73
73
 
74
74
  def test_doesnt_change_replied_at_on_save
75
- t=Topic.find(:first)
75
+ t=Topic.first
76
76
  old=t.replied_at
77
77
  assert t.save
78
78
  assert_equal old, t.replied_at
@@ -86,11 +86,12 @@ class TopicTest < ActiveSupport::TestCase
86
86
  end
87
87
 
88
88
  test "should notify for new anonymous post" do
89
- configatron.allow_anonymous_forum_posting = true
90
- assert_difference ActionMailer::Base.deliveries, :length, 2 do
91
- post = topics(:pdi).sb_posts.create!(:body => "Anonymous post", :author_email => 'foo@bar.com', :author_ip => '1.2.3.4')
92
- end
93
- configatron.allow_anonymous_forum_posting = false
89
+ configatron.temp do
90
+ configatron.allow_anonymous_forum_posting = true
91
+ assert_difference ActionMailer::Base.deliveries, :length, 2 do
92
+ post = topics(:pdi).sb_posts.create!(:body => "Anonymous post", :author_email => 'foo@bar.com', :author_ip => '1.2.3.4')
93
+ end
94
+ end
94
95
  end
95
96
 
96
97
  def test_topic_creator_should_monitor_automatically
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class UserTest < ActiveSupport::TestCase
4
- fixtures :all
4
+ fixtures :all
5
5
 
6
6
  test "should_create_user" do
7
7
  assert_difference User, :count do
@@ -9,20 +9,43 @@ class UserTest < ActiveSupport::TestCase
9
9
  assert !user.new_record?, "#{user.errors.full_messages.to_sentence}"
10
10
  end
11
11
  end
12
-
13
-
12
+
13
+ test "should prevent short login" do
14
+ assert_no_difference User, :count do
15
+ user = create_user(:login => 'quen')
16
+ assert !user.valid?
17
+ assert user.errors[:login]
18
+ end
19
+ end
20
+
21
+ test "should prevent short password" do
22
+ assert_no_difference User, :count do
23
+ user = create_user(:password => 'pas')
24
+ assert !user.valid?
25
+ assert user.errors[:password]
26
+ end
27
+ end
28
+
29
+ test "should prevent short email" do
30
+ assert_no_difference User, :count do
31
+ user = create_user(:email => 'a@')
32
+ assert !user.valid?
33
+ assert user.errors[:email]
34
+ end
35
+ end
36
+
14
37
  test "should prevent malicious chars inserted in email via newlines" do
15
38
  user = User.new(:email => "valid@email.com%0A<script>alert('hello')</script>")
16
39
  assert !user.valid?
17
40
  assert user.errors[:email]
18
41
  end
19
-
42
+
20
43
  test "should prevent malicious chars inserted in login via newlines" do
21
44
  user = User.new(:login => "validlogin%0A<script>alert('hello')</script>")
22
45
  assert !user.valid?
23
46
  assert user.errors[:email]
24
47
  end
25
-
48
+
26
49
  test "should_trim_whitespace" do
27
50
  user = users(:quentin)
28
51
  user.login = 'quentin '
@@ -41,7 +64,7 @@ class UserTest < ActiveSupport::TestCase
41
64
  assert !user.valid?
42
65
  assert user.errors[:login]
43
66
  end
44
-
67
+
45
68
  test "should_accept_normal_chars_in_login" do
46
69
  u = create_user(:login => "foo_and_bar")
47
70
  assert u.errors[:login].empty?
@@ -55,13 +78,13 @@ class UserTest < ActiveSupport::TestCase
55
78
  assert u.errors[:login]
56
79
  end
57
80
  end
58
-
81
+
59
82
  test "should_find_user_with_numerals_in_login" do
60
83
  u = create_user(:login => "2foo-and-bar")
61
84
  assert u.errors[:login].empty?
62
85
  assert_equal u, User.find("2foo-and-bar")
63
86
  end
64
-
87
+
65
88
  test "should_require_password" do
66
89
  assert_no_difference User, :count do
67
90
  u = create_user(:password => nil)
@@ -82,13 +105,13 @@ class UserTest < ActiveSupport::TestCase
82
105
  assert u.errors[:email]
83
106
  end
84
107
  end
85
-
108
+
86
109
  test "should_require_valid_birthday" do
87
110
  assert_no_difference User, :count do
88
111
  u = create_user(:birthday => 1.year.ago)
89
112
  assert u.errors[:birthday].any?
90
113
  end
91
- end
114
+ end
92
115
 
93
116
  test "should_handle_email_upcase" do
94
117
  assert_difference User, :count, 1 do
@@ -101,7 +124,7 @@ class UserTest < ActiveSupport::TestCase
101
124
  users(:quentin).update_attributes(:password => 'new password', :password_confirmation => 'new password')
102
125
  assert_equal users(:quentin), UserSession.create(:login => 'quentin', :password => 'new password').record
103
126
  end
104
-
127
+
105
128
  test "should deliver password reset instructions" do
106
129
  assert_difference ActionMailer::Base.deliveries, :length, 1 do
107
130
  users(:quentin).deliver_password_reset_instructions!
@@ -117,12 +140,12 @@ class UserTest < ActiveSupport::TestCase
117
140
  test "should_show_location" do
118
141
  assert_equal users(:quentin).location, metro_areas(:twincities).name
119
142
  end
120
-
143
+
121
144
  test "should_call_avatar_photo" do
122
145
  assert_equal users(:quentin).avatar_photo_url, configatron.photo.missing_medium
123
146
  assert_equal users(:quentin).avatar_photo_url(:thumb), configatron.photo.missing_thumb
124
147
  end
125
-
148
+
126
149
  test "should_find_featured" do
127
150
  featured = User.find_featured
128
151
  assert_equal featured.size, 1
@@ -132,15 +155,15 @@ class UserTest < ActiveSupport::TestCase
132
155
  assert_difference Activity, :count, 3 do
133
156
  users(:quentin).track_activity(:logged_in)
134
157
  users(:quentin).track_activity(:logged_in)
135
- users(:quentin).track_activity(:logged_in)
158
+ users(:quentin).track_activity(:logged_in)
136
159
  end
137
160
 
138
161
  assert !User.find_by_activity({:require_avatar => false}).empty?
139
-
162
+
140
163
  users(:quentin).update_attribute(:avatar_id, 1) #just pretend
141
- assert !User.find_by_activity.empty?
164
+ assert !User.find_by_activity.empty?
142
165
  end
143
-
166
+
144
167
  test "should_not_include_inactive_users_in_find_by_activity" do
145
168
  inactive_user = create_user
146
169
  assert !inactive_user.active?
@@ -148,14 +171,14 @@ class UserTest < ActiveSupport::TestCase
148
171
  assert_nothing_raised do
149
172
  User.find_by_activity({:limit => 5, :require_avatar => false})
150
173
  end
151
- end
152
-
153
-
174
+ end
175
+
176
+
154
177
  test "should_update_activities_counter_on_user" do
155
178
  #make sure the initial count is right
156
179
  Activity.destroy_all
157
180
  users(:quentin).update_attribute( :activities_count, Activity.by(users(:quentin)) )
158
-
181
+
159
182
  assert_difference users(:quentin), :activities_count, 1 do
160
183
  users(:quentin).track_activity(:logged_in)
161
184
  users(:quentin).reload
@@ -165,31 +188,31 @@ class UserTest < ActiveSupport::TestCase
165
188
 
166
189
  test "should_have_reached_daily_friend_request_limit" do
167
190
  Friendship.daily_request_limit = 1
168
-
191
+
169
192
  assert !users(:quentin).has_reached_daily_friend_request_limit?
170
193
  f = Friendship.create!(:user => users(:quentin), :friend => users(:kevin), :initiator => true, :friendship_status => FriendshipStatus[:pending])
171
194
  assert users(:quentin).has_reached_daily_friend_request_limit?
172
195
  end
173
-
196
+
174
197
  test "get_network_activity" do
175
198
  users(:aaron).track_activity(:logged_in) #create an activity
176
-
199
+
177
200
  u = users(:quentin)
178
201
  f = friendships(:aaron_receive_quentin_pending)
179
202
  f.update_attributes(:friendship_status => FriendshipStatus[:accepted]) && f.reverse.update_attributes(:friendship_status => FriendshipStatus[:accepted])
180
- assert !u.network_activity.empty?
203
+ assert !u.network_activity.empty?
181
204
  end
182
-
205
+
183
206
  test "should_get_comments_activity" do
184
207
  user = users(:quentin)
185
-
208
+
186
209
  2.times do
187
210
  comment = user.comments.create!(:comment => "foo", :user => users(:aaron), :recipient => user)
188
211
  end
189
-
212
+
190
213
  assert_equal 2, user.comments_activity.size
191
214
  end
192
-
215
+
193
216
  test "should_deactivate" do
194
217
  assert users(:quentin).active?
195
218
  users(:quentin).deactivate
@@ -200,22 +223,22 @@ class UserTest < ActiveSupport::TestCase
200
223
  #make quentin inactive
201
224
  users(:quentin).deactivate
202
225
  assert !users(:quentin).reload.active?
203
-
204
- assert_difference ActionMailer::Base.deliveries, :length, 1 do
226
+
227
+ assert_difference ActionMailer::Base.deliveries, :length, 1 do
205
228
  users(:quentin).activate
206
229
  assert users(:quentin).reload.active?
207
230
  end
208
231
  end
209
232
 
210
233
  test "should_return_full_location" do
211
- assert_equal "Minneapolis / St. Paul", users(:quentin).full_location
234
+ assert_equal "Minneapolis / St. Paul", users(:quentin).full_location
212
235
  end
213
-
236
+
214
237
  test "should_prohibit_reserved_logins " do
215
238
  user = create_user(:login => configatron.reserved_logins.first)
216
239
  assert !user.valid?
217
240
  end
218
-
241
+
219
242
  test "should find user tagged with a tag" do
220
243
  user = users(:quentin)
221
244
  user.tag_list = 'foo'
@@ -223,51 +246,51 @@ class UserTest < ActiveSupport::TestCase
223
246
 
224
247
  assert User.tagged_with('foo').include?(user)
225
248
  end
226
-
227
-
249
+
250
+
228
251
  test "should prepare params for search" do
229
252
  params = User.prepare_params_for_search(:metro_area_id => 1, :state_id => 1)
230
253
  assert_equal(params, {:metro_area_id=>1, :state_id=>1, "metro_area_id"=>1, "state_id"=>1, "country_id"=>nil})
231
254
  end
232
-
255
+
233
256
  test "should build scope for search params" do
234
257
  params = {'country_id' => 1, 'state_id' => 1, 'metro_area_id' => 1, 'login' => 'foo', 'vendor' => false, 'description' => 'baz'}
235
258
  scope = User.build_conditions_for_search(params)
236
259
 
237
260
  #This sucks; I want to make sure that the correct scopes are set up on the relation, but I don't know a better way.
238
- assert_equal("SELECT \"users\".* FROM \"users\" WHERE \"users\".\"metro_area_id\" = 1 AND (users.activated_at IS NOT NULL) AND (`users`.login LIKE '%foo%') AND (`users`.description LIKE '%baz%')", scope.to_sql)
261
+ assert_equal("SELECT \"users\".* FROM \"users\" WHERE (users.activated_at IS NOT NULL) AND \"users\".\"metro_area_id\" = 1 AND (\"users\".\"login\" LIKE '%foo%') AND (\"users\".\"description\" LIKE '%baz%')", scope.to_sql)
239
262
  end
240
263
 
241
264
  test "should create user from authorization" do
242
265
  hash = {'provider' => 'twitter',
243
266
  'uid' => '12345',
244
267
  'nickname' => 'omniauthuser',
245
- 'email' => 'email@example.com' }
246
-
268
+ 'email' => 'email@example.com' }
269
+
247
270
  Authorization.create!(hash) do |auth|
248
271
  assert_difference User, :count, 1 do
249
272
  user = User.find_or_create_from_authorization(auth)
250
- auth.user = user
251
- end
273
+ auth.user = user
274
+ end
252
275
  end
253
-
276
+
254
277
  end
255
-
278
+
256
279
  test "should not require password or email for omniauthed user" do
257
280
  user = User.new
258
281
  user.authorizing_from_omniauth = true
259
282
  user.valid?
260
283
  assert(user.errors[:email].empty?, "Should not have errors on email")
261
- assert(user.errors[:birthday].empty?, "Should not have errors on birthday")
284
+ assert(user.errors[:birthday].empty?, "Should not have errors on birthday")
262
285
  end
263
-
286
+
264
287
  protected
265
- def create_user(options = {})
266
- User.create({
267
- :login => 'quire',
268
- :email => 'quire@example.com',
269
- :password => 'quire123',
270
- :password_confirmation => 'quire123',
288
+ def create_user(options = {})
289
+ User.create({
290
+ :login => 'quire',
291
+ :email => 'quire@example.com',
292
+ :password => 'quire123',
293
+ :password_confirmation => 'quire123',
271
294
  :birthday => configatron.min_age.years.ago }.merge(options))
272
295
  end
273
296
  end
File without changes
@@ -0,0 +1,1699 @@
1
+ /**
2
+ * jquery.Jcrop.js v0.9.10
3
+ * jQuery Image Cropping Plugin - released under MIT License
4
+ * Author: Kelly Hallman <khallman@gmail.com>
5
+ * http://github.com/tapmodo/Jcrop
6
+ * Copyright (c) 2008-2012 Tapmodo Interactive LLC {{{
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person
9
+ * obtaining a copy of this software and associated documentation
10
+ * files (the "Software"), to deal in the Software without
11
+ * restriction, including without limitation the rights to use,
12
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ * copies of the Software, and to permit persons to whom the
14
+ * Software is furnished to do so, subject to the following
15
+ * conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be
18
+ * included in all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27
+ * OTHER DEALINGS IN THE SOFTWARE.
28
+ *
29
+ * }}}
30
+ */
31
+
32
+ (function ($) {
33
+
34
+ $.Jcrop = function (obj, opt) {
35
+ var options = $.extend({}, $.Jcrop.defaults),
36
+ docOffset, lastcurs, ie6mode = false;
37
+
38
+ // Internal Methods {{{
39
+ function px(n) {
40
+ return Math.round(n) + 'px';
41
+ }
42
+ function cssClass(cl) {
43
+ return options.baseClass + '-' + cl;
44
+ }
45
+ function supportsColorFade() {
46
+ return $.fx.step.hasOwnProperty('backgroundColor');
47
+ }
48
+ function getPos(obj) //{{{
49
+ {
50
+ var pos = $(obj).offset();
51
+ return [pos.left, pos.top];
52
+ }
53
+ //}}}
54
+ function mouseAbs(e) //{{{
55
+ {
56
+ return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])];
57
+ }
58
+ //}}}
59
+ function setOptions(opt) //{{{
60
+ {
61
+ if (typeof(opt) !== 'object') opt = {};
62
+ options = $.extend(options, opt);
63
+
64
+ $.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) {
65
+ if (typeof(options[e]) !== 'function') options[e] = function () {};
66
+ });
67
+ }
68
+ //}}}
69
+ function startDragMode(mode, pos) //{{{
70
+ {
71
+ docOffset = getPos($img);
72
+ Tracker.setCursor(mode === 'move' ? mode : mode + '-resize');
73
+
74
+ if (mode === 'move') {
75
+ return Tracker.activateHandlers(createMover(pos), doneSelect);
76
+ }
77
+
78
+ var fc = Coords.getFixed();
79
+ var opp = oppLockCorner(mode);
80
+ var opc = Coords.getCorner(oppLockCorner(opp));
81
+
82
+ Coords.setPressed(Coords.getCorner(opp));
83
+ Coords.setCurrent(opc);
84
+
85
+ Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect);
86
+ }
87
+ //}}}
88
+ function dragmodeHandler(mode, f) //{{{
89
+ {
90
+ return function (pos) {
91
+ if (!options.aspectRatio) {
92
+ switch (mode) {
93
+ case 'e':
94
+ pos[1] = f.y2;
95
+ break;
96
+ case 'w':
97
+ pos[1] = f.y2;
98
+ break;
99
+ case 'n':
100
+ pos[0] = f.x2;
101
+ break;
102
+ case 's':
103
+ pos[0] = f.x2;
104
+ break;
105
+ }
106
+ } else {
107
+ switch (mode) {
108
+ case 'e':
109
+ pos[1] = f.y + 1;
110
+ break;
111
+ case 'w':
112
+ pos[1] = f.y + 1;
113
+ break;
114
+ case 'n':
115
+ pos[0] = f.x + 1;
116
+ break;
117
+ case 's':
118
+ pos[0] = f.x + 1;
119
+ break;
120
+ }
121
+ }
122
+ Coords.setCurrent(pos);
123
+ Selection.update();
124
+ };
125
+ }
126
+ //}}}
127
+ function createMover(pos) //{{{
128
+ {
129
+ var lloc = pos;
130
+ KeyManager.watchKeys();
131
+
132
+ return function (pos) {
133
+ Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]);
134
+ lloc = pos;
135
+
136
+ Selection.update();
137
+ };
138
+ }
139
+ //}}}
140
+ function oppLockCorner(ord) //{{{
141
+ {
142
+ switch (ord) {
143
+ case 'n':
144
+ return 'sw';
145
+ case 's':
146
+ return 'nw';
147
+ case 'e':
148
+ return 'nw';
149
+ case 'w':
150
+ return 'ne';
151
+ case 'ne':
152
+ return 'sw';
153
+ case 'nw':
154
+ return 'se';
155
+ case 'se':
156
+ return 'nw';
157
+ case 'sw':
158
+ return 'ne';
159
+ }
160
+ }
161
+ //}}}
162
+ function createDragger(ord) //{{{
163
+ {
164
+ return function (e) {
165
+ if (options.disabled) {
166
+ return false;
167
+ }
168
+ if ((ord === 'move') && !options.allowMove) {
169
+ return false;
170
+ }
171
+
172
+ // Fix position of crop area when dragged the very first time.
173
+ // Necessary when crop image is in a hidden element when page is loaded.
174
+ docOffset = getPos($img);
175
+
176
+ btndown = true;
177
+ startDragMode(ord, mouseAbs(e));
178
+ e.stopPropagation();
179
+ e.preventDefault();
180
+ return false;
181
+ };
182
+ }
183
+ //}}}
184
+ function presize($obj, w, h) //{{{
185
+ {
186
+ var nw = $obj.width(),
187
+ nh = $obj.height();
188
+ if ((nw > w) && w > 0) {
189
+ nw = w;
190
+ nh = (w / $obj.width()) * $obj.height();
191
+ }
192
+ if ((nh > h) && h > 0) {
193
+ nh = h;
194
+ nw = (h / $obj.height()) * $obj.width();
195
+ }
196
+ xscale = $obj.width() / nw;
197
+ yscale = $obj.height() / nh;
198
+ $obj.width(nw).height(nh);
199
+ }
200
+ //}}}
201
+ function unscale(c) //{{{
202
+ {
203
+ return {
204
+ x: c.x * xscale,
205
+ y: c.y * yscale,
206
+ x2: c.x2 * xscale,
207
+ y2: c.y2 * yscale,
208
+ w: c.w * xscale,
209
+ h: c.h * yscale
210
+ };
211
+ }
212
+ //}}}
213
+ function doneSelect(pos) //{{{
214
+ {
215
+ var c = Coords.getFixed();
216
+ if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) {
217
+ Selection.enableHandles();
218
+ Selection.done();
219
+ } else {
220
+ Selection.release();
221
+ }
222
+ Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');
223
+ }
224
+ //}}}
225
+ function newSelection(e) //{{{
226
+ {
227
+ if (options.disabled) {
228
+ return false;
229
+ }
230
+ if (!options.allowSelect) {
231
+ return false;
232
+ }
233
+ btndown = true;
234
+ docOffset = getPos($img);
235
+ Selection.disableHandles();
236
+ Tracker.setCursor('crosshair');
237
+ var pos = mouseAbs(e);
238
+ Coords.setPressed(pos);
239
+ Selection.update();
240
+ Tracker.activateHandlers(selectDrag, doneSelect);
241
+ KeyManager.watchKeys();
242
+
243
+ e.stopPropagation();
244
+ e.preventDefault();
245
+ return false;
246
+ }
247
+ //}}}
248
+ function selectDrag(pos) //{{{
249
+ {
250
+ Coords.setCurrent(pos);
251
+ Selection.update();
252
+ }
253
+ //}}}
254
+ function newTracker() //{{{
255
+ {
256
+ var trk = $('<div></div>').addClass(cssClass('tracker'));
257
+ if ($.browser.msie) {
258
+ trk.css({
259
+ opacity: 0,
260
+ backgroundColor: 'white'
261
+ });
262
+ }
263
+ return trk;
264
+ }
265
+ //}}}
266
+
267
+ // }}}
268
+ // Initialization {{{
269
+ // Sanitize some options {{{
270
+ if ($.browser.msie && ($.browser.version.split('.')[0] === '6')) {
271
+ ie6mode = true;
272
+ }
273
+ if (typeof(obj) !== 'object') {
274
+ obj = $(obj)[0];
275
+ }
276
+ if (typeof(opt) !== 'object') {
277
+ opt = {};
278
+ }
279
+ // }}}
280
+ setOptions(opt);
281
+ // Initialize some jQuery objects {{{
282
+ // The values are SET on the image(s) for the interface
283
+ // If the original image has any of these set, they will be reset
284
+ // However, if you destroy() the Jcrop instance the original image's
285
+ // character in the DOM will be as you left it.
286
+ var img_css = {
287
+ border: 'none',
288
+ visibility: 'visible',
289
+ margin: 0,
290
+ padding: 0,
291
+ position: 'absolute',
292
+ top: 0,
293
+ left: 0
294
+ };
295
+
296
+ var $origimg = $(obj),
297
+ img_mode = true;
298
+
299
+ if (obj.tagName == 'IMG') {
300
+ // Fix size of crop image.
301
+ // Necessary when crop image is within a hidden element when page is loaded.
302
+ if ($origimg[0].width != 0 && $origimg[0].height != 0) {
303
+ // Obtain dimensions from contained img element.
304
+ $origimg.width($origimg[0].width);
305
+ $origimg.height($origimg[0].height);
306
+ } else {
307
+ // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0).
308
+ var tempImage = new Image();
309
+ tempImage.src = $origimg[0].src;
310
+ $origimg.width(tempImage.width);
311
+ $origimg.height(tempImage.height);
312
+ }
313
+
314
+ var $img = $origimg.clone().removeAttr('id').css(img_css).show();
315
+
316
+ $img.width($origimg.width());
317
+ $img.height($origimg.height());
318
+ $origimg.after($img).hide();
319
+
320
+ } else {
321
+ $img = $origimg.css(img_css).show();
322
+ img_mode = false;
323
+ if (options.shade === null) { options.shade = true; }
324
+ }
325
+
326
+ presize($img, options.boxWidth, options.boxHeight);
327
+
328
+ var boundx = $img.width(),
329
+ boundy = $img.height(),
330
+
331
+
332
+ $div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({
333
+ position: 'relative',
334
+ backgroundColor: options.bgColor
335
+ }).insertAfter($origimg).append($img);
336
+
337
+ if (options.addClass) {
338
+ $div.addClass(options.addClass);
339
+ }
340
+
341
+ var $img2 = $('<div />'),
342
+
343
+ $img_holder = $('<div />')
344
+ .width('100%').height('100%').css({
345
+ zIndex: 310,
346
+ position: 'absolute',
347
+ overflow: 'hidden'
348
+ }),
349
+
350
+ $hdl_holder = $('<div />')
351
+ .width('100%').height('100%').css('zIndex', 320),
352
+
353
+ $sel = $('<div />')
354
+ .css({
355
+ position: 'absolute',
356
+ zIndex: 600
357
+ }).dblclick(function(){
358
+ var c = Coords.getFixed();
359
+ options.onDblClick.call(api,c);
360
+ }).insertBefore($img).append($img_holder, $hdl_holder);
361
+
362
+ if (img_mode) {
363
+
364
+ $img2 = $('<img />')
365
+ .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy),
366
+
367
+ $img_holder.append($img2);
368
+
369
+ }
370
+
371
+ if (ie6mode) {
372
+ $sel.css({
373
+ overflowY: 'hidden'
374
+ });
375
+ }
376
+
377
+ var bound = options.boundary;
378
+ var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({
379
+ position: 'absolute',
380
+ top: px(-bound),
381
+ left: px(-bound),
382
+ zIndex: 290
383
+ }).mousedown(newSelection);
384
+
385
+ /* }}} */
386
+ // Set more variables {{{
387
+ var bgcolor = options.bgColor,
388
+ bgopacity = options.bgOpacity,
389
+ xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true,
390
+ btndown, animating, shift_down;
391
+
392
+ docOffset = getPos($img);
393
+ // }}}
394
+ // }}}
395
+ // Internal Modules {{{
396
+ // Touch Module {{{
397
+ var Touch = (function () {
398
+ // Touch support detection function adapted (under MIT License)
399
+ // from code by Jeffrey Sambells - http://github.com/iamamused/
400
+ function hasTouchSupport() {
401
+ var support = {},
402
+ events = ['touchstart', 'touchmove', 'touchend'],
403
+ el = document.createElement('div'), i;
404
+
405
+ try {
406
+ for(i=0; i<events.length; i++) {
407
+ var eventName = events[i];
408
+ eventName = 'on' + eventName;
409
+ var isSupported = (eventName in el);
410
+ if (!isSupported) {
411
+ el.setAttribute(eventName, 'return;');
412
+ isSupported = typeof el[eventName] == 'function';
413
+ }
414
+ support[events[i]] = isSupported;
415
+ }
416
+ return support.touchstart && support.touchend && support.touchmove;
417
+ }
418
+ catch(err) {
419
+ return false;
420
+ }
421
+ }
422
+
423
+ function detectSupport() {
424
+ if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport;
425
+ else return hasTouchSupport();
426
+ }
427
+ return {
428
+ createDragger: function (ord) {
429
+ return function (e) {
430
+ e.pageX = e.originalEvent.changedTouches[0].pageX;
431
+ e.pageY = e.originalEvent.changedTouches[0].pageY;
432
+ if (options.disabled) {
433
+ return false;
434
+ }
435
+ if ((ord === 'move') && !options.allowMove) {
436
+ return false;
437
+ }
438
+ btndown = true;
439
+ startDragMode(ord, mouseAbs(e));
440
+ e.stopPropagation();
441
+ e.preventDefault();
442
+ return false;
443
+ };
444
+ },
445
+ newSelection: function (e) {
446
+ e.pageX = e.originalEvent.changedTouches[0].pageX;
447
+ e.pageY = e.originalEvent.changedTouches[0].pageY;
448
+ return newSelection(e);
449
+ },
450
+ isSupported: hasTouchSupport,
451
+ support: detectSupport()
452
+ };
453
+ }());
454
+ // }}}
455
+ // Coords Module {{{
456
+ var Coords = (function () {
457
+ var x1 = 0,
458
+ y1 = 0,
459
+ x2 = 0,
460
+ y2 = 0,
461
+ ox, oy;
462
+
463
+ function setPressed(pos) //{{{
464
+ {
465
+ pos = rebound(pos);
466
+ x2 = x1 = pos[0];
467
+ y2 = y1 = pos[1];
468
+ }
469
+ //}}}
470
+ function setCurrent(pos) //{{{
471
+ {
472
+ pos = rebound(pos);
473
+ ox = pos[0] - x2;
474
+ oy = pos[1] - y2;
475
+ x2 = pos[0];
476
+ y2 = pos[1];
477
+ }
478
+ //}}}
479
+ function getOffset() //{{{
480
+ {
481
+ return [ox, oy];
482
+ }
483
+ //}}}
484
+ function moveOffset(offset) //{{{
485
+ {
486
+ var ox = offset[0],
487
+ oy = offset[1];
488
+
489
+ if (0 > x1 + ox) {
490
+ ox -= ox + x1;
491
+ }
492
+ if (0 > y1 + oy) {
493
+ oy -= oy + y1;
494
+ }
495
+
496
+ if (boundy < y2 + oy) {
497
+ oy += boundy - (y2 + oy);
498
+ }
499
+ if (boundx < x2 + ox) {
500
+ ox += boundx - (x2 + ox);
501
+ }
502
+
503
+ x1 += ox;
504
+ x2 += ox;
505
+ y1 += oy;
506
+ y2 += oy;
507
+ }
508
+ //}}}
509
+ function getCorner(ord) //{{{
510
+ {
511
+ var c = getFixed();
512
+ switch (ord) {
513
+ case 'ne':
514
+ return [c.x2, c.y];
515
+ case 'nw':
516
+ return [c.x, c.y];
517
+ case 'se':
518
+ return [c.x2, c.y2];
519
+ case 'sw':
520
+ return [c.x, c.y2];
521
+ }
522
+ }
523
+ //}}}
524
+ function getFixed() //{{{
525
+ {
526
+ if (!options.aspectRatio) {
527
+ return getRect();
528
+ }
529
+ // This function could use some optimization I think...
530
+ var aspect = options.aspectRatio,
531
+ min_x = options.minSize[0] / xscale,
532
+
533
+
534
+ //min_y = options.minSize[1]/yscale,
535
+ max_x = options.maxSize[0] / xscale,
536
+ max_y = options.maxSize[1] / yscale,
537
+ rw = x2 - x1,
538
+ rh = y2 - y1,
539
+ rwa = Math.abs(rw),
540
+ rha = Math.abs(rh),
541
+ real_ratio = rwa / rha,
542
+ xx, yy, w, h;
543
+
544
+ if (max_x === 0) {
545
+ max_x = boundx * 10;
546
+ }
547
+ if (max_y === 0) {
548
+ max_y = boundy * 10;
549
+ }
550
+ if (real_ratio < aspect) {
551
+ yy = y2;
552
+ w = rha * aspect;
553
+ xx = rw < 0 ? x1 - w : w + x1;
554
+
555
+ if (xx < 0) {
556
+ xx = 0;
557
+ h = Math.abs((xx - x1) / aspect);
558
+ yy = rh < 0 ? y1 - h : h + y1;
559
+ } else if (xx > boundx) {
560
+ xx = boundx;
561
+ h = Math.abs((xx - x1) / aspect);
562
+ yy = rh < 0 ? y1 - h : h + y1;
563
+ }
564
+ } else {
565
+ xx = x2;
566
+ h = rwa / aspect;
567
+ yy = rh < 0 ? y1 - h : y1 + h;
568
+ if (yy < 0) {
569
+ yy = 0;
570
+ w = Math.abs((yy - y1) * aspect);
571
+ xx = rw < 0 ? x1 - w : w + x1;
572
+ } else if (yy > boundy) {
573
+ yy = boundy;
574
+ w = Math.abs(yy - y1) * aspect;
575
+ xx = rw < 0 ? x1 - w : w + x1;
576
+ }
577
+ }
578
+
579
+ // Magic %-)
580
+ if (xx > x1) { // right side
581
+ if (xx - x1 < min_x) {
582
+ xx = x1 + min_x;
583
+ } else if (xx - x1 > max_x) {
584
+ xx = x1 + max_x;
585
+ }
586
+ if (yy > y1) {
587
+ yy = y1 + (xx - x1) / aspect;
588
+ } else {
589
+ yy = y1 - (xx - x1) / aspect;
590
+ }
591
+ } else if (xx < x1) { // left side
592
+ if (x1 - xx < min_x) {
593
+ xx = x1 - min_x;
594
+ } else if (x1 - xx > max_x) {
595
+ xx = x1 - max_x;
596
+ }
597
+ if (yy > y1) {
598
+ yy = y1 + (x1 - xx) / aspect;
599
+ } else {
600
+ yy = y1 - (x1 - xx) / aspect;
601
+ }
602
+ }
603
+
604
+ if (xx < 0) {
605
+ x1 -= xx;
606
+ xx = 0;
607
+ } else if (xx > boundx) {
608
+ x1 -= xx - boundx;
609
+ xx = boundx;
610
+ }
611
+
612
+ if (yy < 0) {
613
+ y1 -= yy;
614
+ yy = 0;
615
+ } else if (yy > boundy) {
616
+ y1 -= yy - boundy;
617
+ yy = boundy;
618
+ }
619
+
620
+ return makeObj(flipCoords(x1, y1, xx, yy));
621
+ }
622
+ //}}}
623
+ function rebound(p) //{{{
624
+ {
625
+ if (p[0] < 0) {
626
+ p[0] = 0;
627
+ }
628
+ if (p[1] < 0) {
629
+ p[1] = 0;
630
+ }
631
+
632
+ if (p[0] > boundx) {
633
+ p[0] = boundx;
634
+ }
635
+ if (p[1] > boundy) {
636
+ p[1] = boundy;
637
+ }
638
+
639
+ return [p[0], p[1]];
640
+ }
641
+ //}}}
642
+ function flipCoords(x1, y1, x2, y2) //{{{
643
+ {
644
+ var xa = x1,
645
+ xb = x2,
646
+ ya = y1,
647
+ yb = y2;
648
+ if (x2 < x1) {
649
+ xa = x2;
650
+ xb = x1;
651
+ }
652
+ if (y2 < y1) {
653
+ ya = y2;
654
+ yb = y1;
655
+ }
656
+ return [xa, ya, xb, yb];
657
+ }
658
+ //}}}
659
+ function getRect() //{{{
660
+ {
661
+ var xsize = x2 - x1,
662
+ ysize = y2 - y1,
663
+ delta;
664
+
665
+ if (xlimit && (Math.abs(xsize) > xlimit)) {
666
+ x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit);
667
+ }
668
+ if (ylimit && (Math.abs(ysize) > ylimit)) {
669
+ y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit);
670
+ }
671
+
672
+ if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) {
673
+ y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale);
674
+ }
675
+ if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) {
676
+ x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale);
677
+ }
678
+
679
+ if (x1 < 0) {
680
+ x2 -= x1;
681
+ x1 -= x1;
682
+ }
683
+ if (y1 < 0) {
684
+ y2 -= y1;
685
+ y1 -= y1;
686
+ }
687
+ if (x2 < 0) {
688
+ x1 -= x2;
689
+ x2 -= x2;
690
+ }
691
+ if (y2 < 0) {
692
+ y1 -= y2;
693
+ y2 -= y2;
694
+ }
695
+ if (x2 > boundx) {
696
+ delta = x2 - boundx;
697
+ x1 -= delta;
698
+ x2 -= delta;
699
+ }
700
+ if (y2 > boundy) {
701
+ delta = y2 - boundy;
702
+ y1 -= delta;
703
+ y2 -= delta;
704
+ }
705
+ if (x1 > boundx) {
706
+ delta = x1 - boundy;
707
+ y2 -= delta;
708
+ y1 -= delta;
709
+ }
710
+ if (y1 > boundy) {
711
+ delta = y1 - boundy;
712
+ y2 -= delta;
713
+ y1 -= delta;
714
+ }
715
+
716
+ return makeObj(flipCoords(x1, y1, x2, y2));
717
+ }
718
+ //}}}
719
+ function makeObj(a) //{{{
720
+ {
721
+ return {
722
+ x: a[0],
723
+ y: a[1],
724
+ x2: a[2],
725
+ y2: a[3],
726
+ w: a[2] - a[0],
727
+ h: a[3] - a[1]
728
+ };
729
+ }
730
+ //}}}
731
+
732
+ return {
733
+ flipCoords: flipCoords,
734
+ setPressed: setPressed,
735
+ setCurrent: setCurrent,
736
+ getOffset: getOffset,
737
+ moveOffset: moveOffset,
738
+ getCorner: getCorner,
739
+ getFixed: getFixed
740
+ };
741
+ }());
742
+
743
+ //}}}
744
+ // Shade Module {{{
745
+ var Shade = (function() {
746
+ var enabled = false,
747
+ holder = $('<div />').css({
748
+ position: 'absolute',
749
+ zIndex: 240,
750
+ opacity: 0
751
+ }),
752
+ shades = {
753
+ top: createShade(),
754
+ left: createShade().height(boundy),
755
+ right: createShade().height(boundy),
756
+ bottom: createShade()
757
+ };
758
+
759
+ function resizeShades(w,h) {
760
+ shades.left.css({ height: px(h) });
761
+ shades.right.css({ height: px(h) });
762
+ }
763
+ function updateAuto()
764
+ {
765
+ return updateShade(Coords.getFixed());
766
+ }
767
+ function updateShade(c)
768
+ {
769
+ shades.top.css({
770
+ left: px(c.x),
771
+ width: px(c.w),
772
+ height: px(c.y)
773
+ });
774
+ shades.bottom.css({
775
+ top: px(c.y2),
776
+ left: px(c.x),
777
+ width: px(c.w),
778
+ height: px(boundy-c.y2)
779
+ });
780
+ shades.right.css({
781
+ left: px(c.x2),
782
+ width: px(boundx-c.x2)
783
+ });
784
+ shades.left.css({
785
+ width: px(c.x)
786
+ });
787
+ }
788
+ function createShade() {
789
+ return $('<div />').css({
790
+ position: 'absolute',
791
+ backgroundColor: options.shadeColor||options.bgColor
792
+ }).appendTo(holder);
793
+ }
794
+ function enableShade() {
795
+ if (!enabled) {
796
+ enabled = true;
797
+ holder.insertBefore($img);
798
+ updateAuto();
799
+ Selection.setBgOpacity(1,0,1);
800
+ $img2.hide();
801
+
802
+ setBgColor(options.shadeColor||options.bgColor,1);
803
+ if (Selection.isAwake())
804
+ {
805
+ setOpacity(options.bgOpacity,1);
806
+ }
807
+ else setOpacity(1,1);
808
+ }
809
+ }
810
+ function setBgColor(color,now) {
811
+ colorChangeMacro(getShades(),color,now);
812
+ }
813
+ function disableShade() {
814
+ if (enabled) {
815
+ holder.remove();
816
+ $img2.show();
817
+ enabled = false;
818
+ if (Selection.isAwake()) {
819
+ Selection.setBgOpacity(options.bgOpacity,1,1);
820
+ } else {
821
+ Selection.setBgOpacity(1,1,1);
822
+ Selection.disableHandles();
823
+ }
824
+ colorChangeMacro($div,0,1);
825
+ }
826
+ }
827
+ function setOpacity(opacity,now) {
828
+ if (enabled) {
829
+ if (options.bgFade && !now) {
830
+ holder.animate({
831
+ opacity: 1-opacity
832
+ },{
833
+ queue: false,
834
+ duration: options.fadeTime
835
+ });
836
+ }
837
+ else holder.css({opacity:1-opacity});
838
+ }
839
+ }
840
+ function refreshAll() {
841
+ options.shade ? enableShade() : disableShade();
842
+ if (Selection.isAwake()) setOpacity(options.bgOpacity);
843
+ }
844
+ function getShades() {
845
+ return holder.children();
846
+ }
847
+
848
+ return {
849
+ update: updateAuto,
850
+ updateRaw: updateShade,
851
+ getShades: getShades,
852
+ setBgColor: setBgColor,
853
+ enable: enableShade,
854
+ disable: disableShade,
855
+ resize: resizeShades,
856
+ refresh: refreshAll,
857
+ opacity: setOpacity
858
+ };
859
+ }());
860
+ // }}}
861
+ // Selection Module {{{
862
+ var Selection = (function () {
863
+ var awake,
864
+ hdep = 370,
865
+ borders = {},
866
+ handle = {},
867
+ dragbar = {},
868
+ seehandles = false;
869
+
870
+ // Private Methods
871
+ function insertBorder(type) //{{{
872
+ {
873
+ var jq = $('<div />').css({
874
+ position: 'absolute',
875
+ opacity: options.borderOpacity
876
+ }).addClass(cssClass(type));
877
+ $img_holder.append(jq);
878
+ return jq;
879
+ }
880
+ //}}}
881
+ function dragDiv(ord, zi) //{{{
882
+ {
883
+ var jq = $('<div />').mousedown(createDragger(ord)).css({
884
+ cursor: ord + '-resize',
885
+ position: 'absolute',
886
+ zIndex: zi
887
+ }).addClass('ord-'+ord);
888
+
889
+ if (Touch.support) {
890
+ jq.bind('touchstart.jcrop', Touch.createDragger(ord));
891
+ }
892
+
893
+ $hdl_holder.append(jq);
894
+ return jq;
895
+ }
896
+ //}}}
897
+ function insertHandle(ord) //{{{
898
+ {
899
+ var hs = options.handleSize;
900
+ return dragDiv(ord, hdep++).css({
901
+ opacity: options.handleOpacity
902
+ }).width(hs).height(hs).addClass(cssClass('handle'));
903
+ }
904
+ //}}}
905
+ function insertDragbar(ord) //{{{
906
+ {
907
+ return dragDiv(ord, hdep++).addClass('jcrop-dragbar');
908
+ }
909
+ //}}}
910
+ function createDragbars(li) //{{{
911
+ {
912
+ var i;
913
+ for (i = 0; i < li.length; i++) {
914
+ dragbar[li[i]] = insertDragbar(li[i]);
915
+ }
916
+ }
917
+ //}}}
918
+ function createBorders(li) //{{{
919
+ {
920
+ var cl,i;
921
+ for (i = 0; i < li.length; i++) {
922
+ switch(li[i]){
923
+ case'n': cl='hline'; break;
924
+ case's': cl='hline bottom'; break;
925
+ case'e': cl='vline right'; break;
926
+ case'w': cl='vline'; break;
927
+ }
928
+ borders[li[i]] = insertBorder(cl);
929
+ }
930
+ }
931
+ //}}}
932
+ function createHandles(li) //{{{
933
+ {
934
+ var i;
935
+ for (i = 0; i < li.length; i++) {
936
+ handle[li[i]] = insertHandle(li[i]);
937
+ }
938
+ }
939
+ //}}}
940
+ function moveto(x, y) //{{{
941
+ {
942
+ if (!options.shade) {
943
+ $img2.css({
944
+ top: px(-y),
945
+ left: px(-x)
946
+ });
947
+ }
948
+ $sel.css({
949
+ top: px(y),
950
+ left: px(x)
951
+ });
952
+ }
953
+ //}}}
954
+ function resize(w, h) //{{{
955
+ {
956
+ $sel.width(Math.round(w)).height(Math.round(h));
957
+ }
958
+ //}}}
959
+ function refresh() //{{{
960
+ {
961
+ var c = Coords.getFixed();
962
+
963
+ Coords.setPressed([c.x, c.y]);
964
+ Coords.setCurrent([c.x2, c.y2]);
965
+
966
+ updateVisible();
967
+ }
968
+ //}}}
969
+
970
+ // Internal Methods
971
+ function updateVisible(select) //{{{
972
+ {
973
+ if (awake) {
974
+ return update(select);
975
+ }
976
+ }
977
+ //}}}
978
+ function update(select) //{{{
979
+ {
980
+ var c = Coords.getFixed();
981
+
982
+ resize(c.w, c.h);
983
+ moveto(c.x, c.y);
984
+ if (options.shade) Shade.updateRaw(c);
985
+
986
+ awake || show();
987
+
988
+ if (select) {
989
+ options.onSelect.call(api, unscale(c));
990
+ } else {
991
+ options.onChange.call(api, unscale(c));
992
+ }
993
+ }
994
+ //}}}
995
+ function setBgOpacity(opacity,force,now) //{{{
996
+ {
997
+ if (!awake && !force) return;
998
+ if (options.bgFade && !now) {
999
+ $img.animate({
1000
+ opacity: opacity
1001
+ },{
1002
+ queue: false,
1003
+ duration: options.fadeTime
1004
+ });
1005
+ } else {
1006
+ $img.css('opacity', opacity);
1007
+ }
1008
+ }
1009
+ //}}}
1010
+ function show() //{{{
1011
+ {
1012
+ $sel.show();
1013
+
1014
+ if (options.shade) Shade.opacity(bgopacity);
1015
+ else setBgOpacity(bgopacity,true);
1016
+
1017
+ awake = true;
1018
+ }
1019
+ //}}}
1020
+ function release() //{{{
1021
+ {
1022
+ disableHandles();
1023
+ $sel.hide();
1024
+
1025
+ if (options.shade) Shade.opacity(1);
1026
+ else setBgOpacity(1);
1027
+
1028
+ awake = false;
1029
+ options.onRelease.call(api);
1030
+ }
1031
+ //}}}
1032
+ function showHandles() //{{{
1033
+ {
1034
+ if (seehandles) {
1035
+ $hdl_holder.show();
1036
+ }
1037
+ }
1038
+ //}}}
1039
+ function enableHandles() //{{{
1040
+ {
1041
+ seehandles = true;
1042
+ if (options.allowResize) {
1043
+ $hdl_holder.show();
1044
+ return true;
1045
+ }
1046
+ }
1047
+ //}}}
1048
+ function disableHandles() //{{{
1049
+ {
1050
+ seehandles = false;
1051
+ $hdl_holder.hide();
1052
+ }
1053
+ //}}}
1054
+ function animMode(v) //{{{
1055
+ {
1056
+ if (v) {
1057
+ animating = true;
1058
+ disableHandles();
1059
+ } else {
1060
+ animating = false;
1061
+ enableHandles();
1062
+ }
1063
+ }
1064
+ //}}}
1065
+ function done() //{{{
1066
+ {
1067
+ animMode(false);
1068
+ refresh();
1069
+ }
1070
+ //}}}
1071
+ // Insert draggable elements {{{
1072
+ // Insert border divs for outline
1073
+
1074
+ if (options.dragEdges && $.isArray(options.createDragbars))
1075
+ createDragbars(options.createDragbars);
1076
+
1077
+ if ($.isArray(options.createHandles))
1078
+ createHandles(options.createHandles);
1079
+
1080
+ if (options.drawBorders && $.isArray(options.createBorders))
1081
+ createBorders(options.createBorders);
1082
+
1083
+ //}}}
1084
+
1085
+ // This is a hack for iOS5 to support drag/move touch functionality
1086
+ $(document).bind('touchstart.jcrop-ios',function(e) {
1087
+ if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation();
1088
+ });
1089
+
1090
+ var $track = newTracker().mousedown(createDragger('move')).css({
1091
+ cursor: 'move',
1092
+ position: 'absolute',
1093
+ zIndex: 360
1094
+ });
1095
+
1096
+ if (Touch.support) {
1097
+ $track.bind('touchstart.jcrop', Touch.createDragger('move'));
1098
+ }
1099
+
1100
+ $img_holder.append($track);
1101
+ disableHandles();
1102
+
1103
+ return {
1104
+ updateVisible: updateVisible,
1105
+ update: update,
1106
+ release: release,
1107
+ refresh: refresh,
1108
+ isAwake: function () {
1109
+ return awake;
1110
+ },
1111
+ setCursor: function (cursor) {
1112
+ $track.css('cursor', cursor);
1113
+ },
1114
+ enableHandles: enableHandles,
1115
+ enableOnly: function () {
1116
+ seehandles = true;
1117
+ },
1118
+ showHandles: showHandles,
1119
+ disableHandles: disableHandles,
1120
+ animMode: animMode,
1121
+ setBgOpacity: setBgOpacity,
1122
+ done: done
1123
+ };
1124
+ }());
1125
+
1126
+ //}}}
1127
+ // Tracker Module {{{
1128
+ var Tracker = (function () {
1129
+ var onMove = function () {},
1130
+ onDone = function () {},
1131
+ trackDoc = options.trackDocument;
1132
+
1133
+ function toFront() //{{{
1134
+ {
1135
+ $trk.css({
1136
+ zIndex: 450
1137
+ });
1138
+ if (Touch.support) {
1139
+ $(document)
1140
+ .bind('touchmove.jcrop', trackTouchMove)
1141
+ .bind('touchend.jcrop', trackTouchEnd);
1142
+ }
1143
+ if (trackDoc) {
1144
+ $(document)
1145
+ .bind('mousemove.jcrop',trackMove)
1146
+ .bind('mouseup.jcrop',trackUp);
1147
+ }
1148
+ }
1149
+ //}}}
1150
+ function toBack() //{{{
1151
+ {
1152
+ $trk.css({
1153
+ zIndex: 290
1154
+ });
1155
+ $(document).unbind('.jcrop');
1156
+ }
1157
+ //}}}
1158
+ function trackMove(e) //{{{
1159
+ {
1160
+ onMove(mouseAbs(e));
1161
+ return false;
1162
+ }
1163
+ //}}}
1164
+ function trackUp(e) //{{{
1165
+ {
1166
+ e.preventDefault();
1167
+ e.stopPropagation();
1168
+
1169
+ if (btndown) {
1170
+ btndown = false;
1171
+
1172
+ onDone(mouseAbs(e));
1173
+
1174
+ if (Selection.isAwake()) {
1175
+ options.onSelect.call(api, unscale(Coords.getFixed()));
1176
+ }
1177
+
1178
+ toBack();
1179
+ onMove = function () {};
1180
+ onDone = function () {};
1181
+ }
1182
+
1183
+ return false;
1184
+ }
1185
+ //}}}
1186
+ function activateHandlers(move, done) //{{{
1187
+ {
1188
+ btndown = true;
1189
+ onMove = move;
1190
+ onDone = done;
1191
+ toFront();
1192
+ return false;
1193
+ }
1194
+ //}}}
1195
+ function trackTouchMove(e) //{{{
1196
+ {
1197
+ e.pageX = e.originalEvent.changedTouches[0].pageX;
1198
+ e.pageY = e.originalEvent.changedTouches[0].pageY;
1199
+ return trackMove(e);
1200
+ }
1201
+ //}}}
1202
+ function trackTouchEnd(e) //{{{
1203
+ {
1204
+ e.pageX = e.originalEvent.changedTouches[0].pageX;
1205
+ e.pageY = e.originalEvent.changedTouches[0].pageY;
1206
+ return trackUp(e);
1207
+ }
1208
+ //}}}
1209
+ function setCursor(t) //{{{
1210
+ {
1211
+ $trk.css('cursor', t);
1212
+ }
1213
+ //}}}
1214
+
1215
+ if (!trackDoc) {
1216
+ $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);
1217
+ }
1218
+
1219
+ $img.before($trk);
1220
+ return {
1221
+ activateHandlers: activateHandlers,
1222
+ setCursor: setCursor
1223
+ };
1224
+ }());
1225
+ //}}}
1226
+ // KeyManager Module {{{
1227
+ var KeyManager = (function () {
1228
+ var $keymgr = $('<input type="radio" />').css({
1229
+ position: 'fixed',
1230
+ left: '-120px',
1231
+ width: '12px'
1232
+ }).addClass('jcrop-keymgr'),
1233
+
1234
+ $keywrap = $('<div />').css({
1235
+ position: 'absolute',
1236
+ overflow: 'hidden'
1237
+ }).append($keymgr);
1238
+
1239
+ function watchKeys() //{{{
1240
+ {
1241
+ if (options.keySupport) {
1242
+ $keymgr.show();
1243
+ $keymgr.focus();
1244
+ }
1245
+ }
1246
+ //}}}
1247
+ function onBlur(e) //{{{
1248
+ {
1249
+ $keymgr.hide();
1250
+ }
1251
+ //}}}
1252
+ function doNudge(e, x, y) //{{{
1253
+ {
1254
+ if (options.allowMove) {
1255
+ Coords.moveOffset([x, y]);
1256
+ Selection.updateVisible(true);
1257
+ }
1258
+ e.preventDefault();
1259
+ e.stopPropagation();
1260
+ }
1261
+ //}}}
1262
+ function parseKey(e) //{{{
1263
+ {
1264
+ if (e.ctrlKey || e.metaKey) {
1265
+ return true;
1266
+ }
1267
+ shift_down = e.shiftKey ? true : false;
1268
+ var nudge = shift_down ? 10 : 1;
1269
+
1270
+ switch (e.keyCode) {
1271
+ case 37:
1272
+ doNudge(e, -nudge, 0);
1273
+ break;
1274
+ case 39:
1275
+ doNudge(e, nudge, 0);
1276
+ break;
1277
+ case 38:
1278
+ doNudge(e, 0, -nudge);
1279
+ break;
1280
+ case 40:
1281
+ doNudge(e, 0, nudge);
1282
+ break;
1283
+ case 27:
1284
+ if (options.allowSelect) Selection.release();
1285
+ break;
1286
+ case 9:
1287
+ return true;
1288
+ }
1289
+
1290
+ return false;
1291
+ }
1292
+ //}}}
1293
+
1294
+ if (options.keySupport) {
1295
+ $keymgr.keydown(parseKey).blur(onBlur);
1296
+ if (ie6mode || !options.fixedSupport) {
1297
+ $keymgr.css({
1298
+ position: 'absolute',
1299
+ left: '-20px'
1300
+ });
1301
+ $keywrap.append($keymgr).insertBefore($img);
1302
+ } else {
1303
+ $keymgr.insertBefore($img);
1304
+ }
1305
+ }
1306
+
1307
+
1308
+ return {
1309
+ watchKeys: watchKeys
1310
+ };
1311
+ }());
1312
+ //}}}
1313
+ // }}}
1314
+ // API methods {{{
1315
+ function setClass(cname) //{{{
1316
+ {
1317
+ $div.removeClass().addClass(cssClass('holder')).addClass(cname);
1318
+ }
1319
+ //}}}
1320
+ function animateTo(a, callback) //{{{
1321
+ {
1322
+ var x1 = a[0] / xscale,
1323
+ y1 = a[1] / yscale,
1324
+ x2 = a[2] / xscale,
1325
+ y2 = a[3] / yscale;
1326
+
1327
+ if (animating) {
1328
+ return;
1329
+ }
1330
+
1331
+ var animto = Coords.flipCoords(x1, y1, x2, y2),
1332
+ c = Coords.getFixed(),
1333
+ initcr = [c.x, c.y, c.x2, c.y2],
1334
+ animat = initcr,
1335
+ interv = options.animationDelay,
1336
+ ix1 = animto[0] - initcr[0],
1337
+ iy1 = animto[1] - initcr[1],
1338
+ ix2 = animto[2] - initcr[2],
1339
+ iy2 = animto[3] - initcr[3],
1340
+ pcent = 0,
1341
+ velocity = options.swingSpeed;
1342
+
1343
+ x1 = animat[0];
1344
+ y1 = animat[1];
1345
+ x2 = animat[2];
1346
+ y2 = animat[3];
1347
+
1348
+ Selection.animMode(true);
1349
+ var anim_timer;
1350
+
1351
+ function queueAnimator() {
1352
+ window.setTimeout(animator, interv);
1353
+ }
1354
+ var animator = (function () {
1355
+ return function () {
1356
+ pcent += (100 - pcent) / velocity;
1357
+
1358
+ animat[0] = Math.round(x1 + ((pcent / 100) * ix1));
1359
+ animat[1] = Math.round(y1 + ((pcent / 100) * iy1));
1360
+ animat[2] = Math.round(x2 + ((pcent / 100) * ix2));
1361
+ animat[3] = Math.round(y2 + ((pcent / 100) * iy2));
1362
+
1363
+ if (pcent >= 99.8) {
1364
+ pcent = 100;
1365
+ }
1366
+ if (pcent < 100) {
1367
+ setSelectRaw(animat);
1368
+ queueAnimator();
1369
+ } else {
1370
+ Selection.done();
1371
+ Selection.animMode(false);
1372
+ if (typeof(callback) === 'function') {
1373
+ callback.call(api);
1374
+ }
1375
+ }
1376
+ };
1377
+ }());
1378
+ queueAnimator();
1379
+ }
1380
+ //}}}
1381
+ function setSelect(rect) //{{{
1382
+ {
1383
+ setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]);
1384
+ options.onSelect.call(api, unscale(Coords.getFixed()));
1385
+ Selection.enableHandles();
1386
+ }
1387
+ //}}}
1388
+ function setSelectRaw(l) //{{{
1389
+ {
1390
+ Coords.setPressed([l[0], l[1]]);
1391
+ Coords.setCurrent([l[2], l[3]]);
1392
+ Selection.update();
1393
+ }
1394
+ //}}}
1395
+ function tellSelect() //{{{
1396
+ {
1397
+ return unscale(Coords.getFixed());
1398
+ }
1399
+ //}}}
1400
+ function tellScaled() //{{{
1401
+ {
1402
+ return Coords.getFixed();
1403
+ }
1404
+ //}}}
1405
+ function setOptionsNew(opt) //{{{
1406
+ {
1407
+ setOptions(opt);
1408
+ interfaceUpdate();
1409
+ }
1410
+ //}}}
1411
+ function disableCrop() //{{{
1412
+ {
1413
+ options.disabled = true;
1414
+ Selection.disableHandles();
1415
+ Selection.setCursor('default');
1416
+ Tracker.setCursor('default');
1417
+ }
1418
+ //}}}
1419
+ function enableCrop() //{{{
1420
+ {
1421
+ options.disabled = false;
1422
+ interfaceUpdate();
1423
+ }
1424
+ //}}}
1425
+ function cancelCrop() //{{{
1426
+ {
1427
+ Selection.done();
1428
+ Tracker.activateHandlers(null, null);
1429
+ }
1430
+ //}}}
1431
+ function destroy() //{{{
1432
+ {
1433
+ $div.remove();
1434
+ $origimg.show();
1435
+ $(obj).removeData('Jcrop');
1436
+ }
1437
+ //}}}
1438
+ function setImage(src, callback) //{{{
1439
+ {
1440
+ Selection.release();
1441
+ disableCrop();
1442
+ var img = new Image();
1443
+ img.onload = function () {
1444
+ var iw = img.width;
1445
+ var ih = img.height;
1446
+ var bw = options.boxWidth;
1447
+ var bh = options.boxHeight;
1448
+ $img.width(iw).height(ih);
1449
+ $img.attr('src', src);
1450
+ $img2.attr('src', src);
1451
+ presize($img, bw, bh);
1452
+ boundx = $img.width();
1453
+ boundy = $img.height();
1454
+ $img2.width(boundx).height(boundy);
1455
+ $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2));
1456
+ $div.width(boundx).height(boundy);
1457
+ Shade.resize(boundx,boundy);
1458
+ enableCrop();
1459
+
1460
+ if (typeof(callback) === 'function') {
1461
+ callback.call(api);
1462
+ }
1463
+ };
1464
+ img.src = src;
1465
+ }
1466
+ //}}}
1467
+ function colorChangeMacro($obj,color,now) {
1468
+ var mycolor = color || options.bgColor;
1469
+ if (options.bgFade && supportsColorFade() && options.fadeTime && !now) {
1470
+ $obj.animate({
1471
+ backgroundColor: mycolor
1472
+ }, {
1473
+ queue: false,
1474
+ duration: options.fadeTime
1475
+ });
1476
+ } else {
1477
+ $obj.css('backgroundColor', mycolor);
1478
+ }
1479
+ }
1480
+ function interfaceUpdate(alt) //{{{
1481
+ // This method tweaks the interface based on options object.
1482
+ // Called when options are changed and at end of initialization.
1483
+ {
1484
+ if (options.allowResize) {
1485
+ if (alt) {
1486
+ Selection.enableOnly();
1487
+ } else {
1488
+ Selection.enableHandles();
1489
+ }
1490
+ } else {
1491
+ Selection.disableHandles();
1492
+ }
1493
+
1494
+ Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');
1495
+ Selection.setCursor(options.allowMove ? 'move' : 'default');
1496
+
1497
+ if (options.hasOwnProperty('trueSize')) {
1498
+ xscale = options.trueSize[0] / boundx;
1499
+ yscale = options.trueSize[1] / boundy;
1500
+ }
1501
+
1502
+ if (options.hasOwnProperty('setSelect')) {
1503
+ setSelect(options.setSelect);
1504
+ Selection.done();
1505
+ delete(options.setSelect);
1506
+ }
1507
+
1508
+ Shade.refresh();
1509
+
1510
+ if (options.bgColor != bgcolor) {
1511
+ colorChangeMacro(
1512
+ options.shade? Shade.getShades(): $div,
1513
+ options.shade?
1514
+ (options.shadeColor || options.bgColor):
1515
+ options.bgColor
1516
+ );
1517
+ bgcolor = options.bgColor;
1518
+ }
1519
+
1520
+ if (bgopacity != options.bgOpacity) {
1521
+ bgopacity = options.bgOpacity;
1522
+ if (options.shade) Shade.refresh();
1523
+ else Selection.setBgOpacity(bgopacity);
1524
+ }
1525
+
1526
+ xlimit = options.maxSize[0] || 0;
1527
+ ylimit = options.maxSize[1] || 0;
1528
+ xmin = options.minSize[0] || 0;
1529
+ ymin = options.minSize[1] || 0;
1530
+
1531
+ if (options.hasOwnProperty('outerImage')) {
1532
+ $img.attr('src', options.outerImage);
1533
+ delete(options.outerImage);
1534
+ }
1535
+
1536
+ Selection.refresh();
1537
+ }
1538
+ //}}}
1539
+ //}}}
1540
+
1541
+ if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection);
1542
+
1543
+ $hdl_holder.hide();
1544
+ interfaceUpdate(true);
1545
+
1546
+ var api = {
1547
+ setImage: setImage,
1548
+ animateTo: animateTo,
1549
+ setSelect: setSelect,
1550
+ setOptions: setOptionsNew,
1551
+ tellSelect: tellSelect,
1552
+ tellScaled: tellScaled,
1553
+ setClass: setClass,
1554
+
1555
+ disable: disableCrop,
1556
+ enable: enableCrop,
1557
+ cancel: cancelCrop,
1558
+ release: Selection.release,
1559
+ destroy: destroy,
1560
+
1561
+ focus: KeyManager.watchKeys,
1562
+
1563
+ getBounds: function () {
1564
+ return [boundx * xscale, boundy * yscale];
1565
+ },
1566
+ getWidgetSize: function () {
1567
+ return [boundx, boundy];
1568
+ },
1569
+ getScaleFactor: function () {
1570
+ return [xscale, yscale];
1571
+ },
1572
+ getOptions: function() {
1573
+ // careful: internal values are returned
1574
+ return options;
1575
+ },
1576
+
1577
+ ui: {
1578
+ holder: $div,
1579
+ selection: $sel
1580
+ }
1581
+ };
1582
+
1583
+ if ($.browser.msie)
1584
+ $div.bind('selectstart', function () { return false; });
1585
+
1586
+ $origimg.data('Jcrop', api);
1587
+ return api;
1588
+ };
1589
+ $.fn.Jcrop = function (options, callback) //{{{
1590
+ {
1591
+ var api;
1592
+ // Iterate over each object, attach Jcrop
1593
+ this.each(function () {
1594
+ // If we've already attached to this object
1595
+ if ($(this).data('Jcrop')) {
1596
+ // The API can be requested this way (undocumented)
1597
+ if (options === 'api') return $(this).data('Jcrop');
1598
+ // Otherwise, we just reset the options...
1599
+ else $(this).data('Jcrop').setOptions(options);
1600
+ }
1601
+ // If we haven't been attached, preload and attach
1602
+ else {
1603
+ if (this.tagName == 'IMG')
1604
+ $.Jcrop.Loader(this,function(){
1605
+ $(this).css({display:'block',visibility:'hidden'});
1606
+ api = $.Jcrop(this, options);
1607
+ if ($.isFunction(callback)) callback.call(api);
1608
+ });
1609
+ else {
1610
+ $(this).css({display:'block',visibility:'hidden'});
1611
+ api = $.Jcrop(this, options);
1612
+ if ($.isFunction(callback)) callback.call(api);
1613
+ }
1614
+ }
1615
+ });
1616
+
1617
+ // Return "this" so the object is chainable (jQuery-style)
1618
+ return this;
1619
+ };
1620
+ //}}}
1621
+ // $.Jcrop.Loader - basic image loader {{{
1622
+
1623
+ $.Jcrop.Loader = function(imgobj,success,error){
1624
+ var $img = $(imgobj), img = $img[0];
1625
+
1626
+ function completeCheck(){
1627
+ if (img.complete) {
1628
+ $img.unbind('.jcloader');
1629
+ if ($.isFunction(success)) success.call(img);
1630
+ }
1631
+ else window.setTimeout(completeCheck,50);
1632
+ }
1633
+
1634
+ $img
1635
+ .bind('load.jcloader',completeCheck)
1636
+ .bind('error.jcloader',function(e){
1637
+ $img.unbind('.jcloader');
1638
+ if ($.isFunction(error)) error.call(img);
1639
+ });
1640
+
1641
+ if (img.complete && $.isFunction(success)){
1642
+ $img.unbind('.jcloader');
1643
+ success.call(img);
1644
+ }
1645
+ };
1646
+
1647
+ //}}}
1648
+ // Global Defaults {{{
1649
+ $.Jcrop.defaults = {
1650
+
1651
+ // Basic Settings
1652
+ allowSelect: true,
1653
+ allowMove: true,
1654
+ allowResize: true,
1655
+
1656
+ trackDocument: true,
1657
+
1658
+ // Styling Options
1659
+ baseClass: 'jcrop',
1660
+ addClass: null,
1661
+ bgColor: 'black',
1662
+ bgOpacity: 0.6,
1663
+ bgFade: false,
1664
+ borderOpacity: 0.4,
1665
+ handleOpacity: 0.5,
1666
+ handleSize: 7,
1667
+
1668
+ aspectRatio: 0,
1669
+ keySupport: true,
1670
+ createHandles: ['n','s','e','w','nw','ne','se','sw'],
1671
+ createDragbars: ['n','s','e','w'],
1672
+ createBorders: ['n','s','e','w'],
1673
+ drawBorders: true,
1674
+ dragEdges: true,
1675
+ fixedSupport: true,
1676
+ touchSupport: null,
1677
+
1678
+ shade: null,
1679
+
1680
+ boxWidth: 0,
1681
+ boxHeight: 0,
1682
+ boundary: 2,
1683
+ fadeTime: 400,
1684
+ animationDelay: 20,
1685
+ swingSpeed: 3,
1686
+
1687
+ minSelect: [0, 0],
1688
+ maxSize: [0, 0],
1689
+ minSize: [0, 0],
1690
+
1691
+ // Callbacks / Event Handlers
1692
+ onChange: function () {},
1693
+ onSelect: function () {},
1694
+ onDblClick: function () {},
1695
+ onRelease: function () {}
1696
+ };
1697
+
1698
+ // }}}
1699
+ }(jQuery));