community_engine 2.3.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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));