vkhater-social_stream-base 0.11.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (629) hide show
  1. data/.gitignore +16 -0
  2. data/.rspec +1 -0
  3. data/.yardopts +2 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +68 -0
  7. data/Rakefile +35 -0
  8. data/app/assets/images/HTML5.png +0 -0
  9. data/app/assets/images/HTML5_Semantics.png +0 -0
  10. data/app/assets/images/HTML5_Styling.png +0 -0
  11. data/app/assets/images/Jcrop.gif +0 -0
  12. data/app/assets/images/arrow-end.png +0 -0
  13. data/app/assets/images/arrow-start.png +0 -0
  14. data/app/assets/images/arrow.png +0 -0
  15. data/app/assets/images/big-logo.png +0 -0
  16. data/app/assets/images/btn/1-facebook.png +0 -0
  17. data/app/assets/images/btn/_notes/btn_certificates.png.mno +4 -0
  18. data/app/assets/images/btn/activity.png +0 -0
  19. data/app/assets/images/btn/arrowBlue.png +0 -0
  20. data/app/assets/images/btn/arrow_session_change.png +0 -0
  21. data/app/assets/images/btn/arrows-ffffff.png +0 -0
  22. data/app/assets/images/btn/bold.png +0 -0
  23. data/app/assets/images/btn/btn_account.png +0 -0
  24. data/app/assets/images/btn/btn_activities.png +0 -0
  25. data/app/assets/images/btn/btn_bookmark.png +0 -0
  26. data/app/assets/images/btn/btn_browse.png +0 -0
  27. data/app/assets/images/btn/btn_check.png +0 -0
  28. data/app/assets/images/btn/btn_close.png +0 -0
  29. data/app/assets/images/btn/btn_comment.png +0 -0
  30. data/app/assets/images/btn/btn_comment_add.png +0 -0
  31. data/app/assets/images/btn/btn_config.png +0 -0
  32. data/app/assets/images/btn/btn_date.png +0 -0
  33. data/app/assets/images/btn/btn_delete.png +0 -0
  34. data/app/assets/images/btn/btn_down.png +0 -0
  35. data/app/assets/images/btn/btn_edit.png +0 -0
  36. data/app/assets/images/btn/btn_exit.png +0 -0
  37. data/app/assets/images/btn/btn_find.png +0 -0
  38. data/app/assets/images/btn/btn_follow.png +0 -0
  39. data/app/assets/images/btn/btn_foward.png +0 -0
  40. data/app/assets/images/btn/btn_friend.png +0 -0
  41. data/app/assets/images/btn/btn_gallery.png +0 -0
  42. data/app/assets/images/btn/btn_group.png +0 -0
  43. data/app/assets/images/btn/btn_help.png +0 -0
  44. data/app/assets/images/btn/btn_home.png +0 -0
  45. data/app/assets/images/btn/btn_inbox.png +0 -0
  46. data/app/assets/images/btn/btn_info.png +0 -0
  47. data/app/assets/images/btn/btn_invitation.png +0 -0
  48. data/app/assets/images/btn/btn_like.png +0 -0
  49. data/app/assets/images/btn/btn_next.png +0 -0
  50. data/app/assets/images/btn/btn_notification.png +0 -0
  51. data/app/assets/images/btn/btn_notification_delete.png +0 -0
  52. data/app/assets/images/btn/btn_notification_read.png +0 -0
  53. data/app/assets/images/btn/btn_notifications.png +0 -0
  54. data/app/assets/images/btn/btn_page_link.png +0 -0
  55. data/app/assets/images/btn/btn_partner.png +0 -0
  56. data/app/assets/images/btn/btn_photo.png +0 -0
  57. data/app/assets/images/btn/btn_play.png +0 -0
  58. data/app/assets/images/btn/btn_printer.png +0 -0
  59. data/app/assets/images/btn/btn_profile.png +0 -0
  60. data/app/assets/images/btn/btn_rank.png +0 -0
  61. data/app/assets/images/btn/btn_read.png +0 -0
  62. data/app/assets/images/btn/btn_security.png +0 -0
  63. data/app/assets/images/btn/btn_send.png +0 -0
  64. data/app/assets/images/btn/btn_spam.png +0 -0
  65. data/app/assets/images/btn/btn_star.png +0 -0
  66. data/app/assets/images/btn/btn_tag.png +0 -0
  67. data/app/assets/images/btn/btn_write.png +0 -0
  68. data/app/assets/images/btn/close.png +0 -0
  69. data/app/assets/images/btn/date.png +0 -0
  70. data/app/assets/images/btn/delete.png +0 -0
  71. data/app/assets/images/btn/download.png +0 -0
  72. data/app/assets/images/btn/edit.png +0 -0
  73. data/app/assets/images/btn/error.png +0 -0
  74. data/app/assets/images/btn/facebook.png +0 -0
  75. data/app/assets/images/btn/flag.png +0 -0
  76. data/app/assets/images/btn/group_left.png +0 -0
  77. data/app/assets/images/btn/group_right.png +0 -0
  78. data/app/assets/images/btn/header_notifications.png +0 -0
  79. data/app/assets/images/btn/index_71.png +0 -0
  80. data/app/assets/images/btn/info.png +0 -0
  81. data/app/assets/images/btn/italic.png +0 -0
  82. data/app/assets/images/btn/like.png +0 -0
  83. data/app/assets/images/btn/linkedin.png +0 -0
  84. data/app/assets/images/btn/message_conversation.png +0 -0
  85. data/app/assets/images/btn/message_inbox.png +0 -0
  86. data/app/assets/images/btn/message_new.png +0 -0
  87. data/app/assets/images/btn/message_sentbox.png +0 -0
  88. data/app/assets/images/btn/message_trash.png +0 -0
  89. data/app/assets/images/btn/new.png +0 -0
  90. data/app/assets/images/btn/next_conference.png +0 -0
  91. data/app/assets/images/btn/next_space.png +0 -0
  92. data/app/assets/images/btn/nolike.png +0 -0
  93. data/app/assets/images/btn/notifications.png +0 -0
  94. data/app/assets/images/btn/pixel.png +0 -0
  95. data/app/assets/images/btn/point_blue.png +0 -0
  96. data/app/assets/images/btn/point_gray.png +0 -0
  97. data/app/assets/images/btn/post.png +0 -0
  98. data/app/assets/images/btn/search.png +0 -0
  99. data/app/assets/images/btn/search_icon.png +0 -0
  100. data/app/assets/images/btn/shadow.png +0 -0
  101. data/app/assets/images/btn/share.png +0 -0
  102. data/app/assets/images/btn/subtime.png +0 -0
  103. data/app/assets/images/btn/success.png +0 -0
  104. data/app/assets/images/btn/tag_cloud.png +0 -0
  105. data/app/assets/images/btn/twitter-follow-icon.png +0 -0
  106. data/app/assets/images/btn/twitter.png +0 -0
  107. data/app/assets/images/btn/uno.png +0 -0
  108. data/app/assets/images/btn/viewer.png +0 -0
  109. data/app/assets/images/btn/warning.png +0 -0
  110. data/app/assets/images/cancel.png +0 -0
  111. data/app/assets/images/cleditor/buttons.gif +0 -0
  112. data/app/assets/images/cleditor/toolbar.gif +0 -0
  113. data/app/assets/images/frontpage/collaborate.png +0 -0
  114. data/app/assets/images/frontpage/comments.png +0 -0
  115. data/app/assets/images/frontpage/green_sq.png +0 -0
  116. data/app/assets/images/frontpage/meet.png +0 -0
  117. data/app/assets/images/frontpage/people.png +0 -0
  118. data/app/assets/images/frontpage/purple_sq.png +0 -0
  119. data/app/assets/images/frontpage/right_comments.gif +0 -0
  120. data/app/assets/images/frontpage/right_conference.png +0 -0
  121. data/app/assets/images/frontpage/right_organizers.gif +0 -0
  122. data/app/assets/images/frontpage/right_people.gif +0 -0
  123. data/app/assets/images/frontpage/right_social.gif +0 -0
  124. data/app/assets/images/frontpage/right_tags.gif +0 -0
  125. data/app/assets/images/frontpage/right_webcam.gif +0 -0
  126. data/app/assets/images/frontpage/share.png +0 -0
  127. data/app/assets/images/frontpage/tags.png +0 -0
  128. data/app/assets/images/frontpage/yellow_sq.png +0 -0
  129. data/app/assets/images/header-logo.png +0 -0
  130. data/app/assets/images/html5-badge-h-css3-semantics.png +0 -0
  131. data/app/assets/images/icon_checkbox.png +0 -0
  132. data/app/assets/images/icons/favicon.ico +0 -0
  133. data/app/assets/images/left.png +0 -0
  134. data/app/assets/images/lightbox-blank.gif +0 -0
  135. data/app/assets/images/lightbox-btn-close.gif +0 -0
  136. data/app/assets/images/lightbox-btn-next.gif +0 -0
  137. data/app/assets/images/lightbox-btn-prev.gif +0 -0
  138. data/app/assets/images/lightbox-ico-loading.gif +0 -0
  139. data/app/assets/images/loader.gif +0 -0
  140. data/app/assets/images/loading.gif +0 -0
  141. data/app/assets/images/logo.png +0 -0
  142. data/app/assets/images/logos/actor/group.png +0 -0
  143. data/app/assets/images/logos/actor/remote_subject.png +0 -0
  144. data/app/assets/images/logos/actor/remote_user.png +0 -0
  145. data/app/assets/images/logos/actor/user.png +0 -0
  146. data/app/assets/images/logos/contact/group.png +0 -0
  147. data/app/assets/images/logos/contact/user.png +0 -0
  148. data/app/assets/images/logos/original/group.png +0 -0
  149. data/app/assets/images/logos/original/user.png +0 -0
  150. data/app/assets/images/logos/profile/group.png +0 -0
  151. data/app/assets/images/logos/profile/user.png +0 -0
  152. data/app/assets/images/logos/representation/group.png +0 -0
  153. data/app/assets/images/logos/representation/user.png +0 -0
  154. data/app/assets/images/mini-loading.gif +0 -0
  155. data/app/assets/images/right.png +0 -0
  156. data/app/assets/images/tipsy.gif +0 -0
  157. data/app/assets/javascripts/activities.js.erb +250 -0
  158. data/app/assets/javascripts/activities_security_chosen-modified.jquery.js +767 -0
  159. data/app/assets/javascripts/cheesecake.js +6 -0
  160. data/app/assets/javascripts/contacts.js +4 -0
  161. data/app/assets/javascripts/conversations.js +3 -0
  162. data/app/assets/javascripts/groups.js +5 -0
  163. data/app/assets/javascripts/invitations.js +8 -0
  164. data/app/assets/javascripts/jquery.ad-gallery.js +850 -0
  165. data/app/assets/javascripts/jquery.ad-gallery.pack.js +10 -0
  166. data/app/assets/javascripts/layouts.js +21 -0
  167. data/app/assets/javascripts/messages.js +4 -0
  168. data/app/assets/javascripts/posts.js +1 -0
  169. data/app/assets/javascripts/preloader.js +6 -0
  170. data/app/assets/javascripts/profiles.js +9 -0
  171. data/app/assets/javascripts/relation_customs.js +32 -0
  172. data/app/assets/javascripts/search.js.erb +3 -0
  173. data/app/assets/javascripts/settings.js +14 -0
  174. data/app/assets/javascripts/social_stream-base.js +11 -0
  175. data/app/assets/javascripts/ties.js +67 -0
  176. data/app/assets/javascripts/toolbar.js +1 -0
  177. data/app/assets/javascripts/users.js +2 -0
  178. data/app/assets/stylesheets/0_devise_sign.css +28 -0
  179. data/app/assets/stylesheets/_colors.scss +25 -0
  180. data/app/assets/stylesheets/activities.css.scss +88 -0
  181. data/app/assets/stylesheets/base.css.scss +257 -0
  182. data/app/assets/stylesheets/cheesecake.css.scss +55 -0
  183. data/app/assets/stylesheets/contacts.css.scss +100 -0
  184. data/app/assets/stylesheets/conversations.css +4 -0
  185. data/app/assets/stylesheets/footer.css.scss +22 -0
  186. data/app/assets/stylesheets/frontpage.css.scss +70 -0
  187. data/app/assets/stylesheets/groups.css +4 -0
  188. data/app/assets/stylesheets/header.css.scss +203 -0
  189. data/app/assets/stylesheets/home.css.scss +53 -0
  190. data/app/assets/stylesheets/images/add-policy.png +0 -0
  191. data/app/assets/stylesheets/images/fcbkcomplete/close.gif +0 -0
  192. data/app/assets/stylesheets/images/loading.gif +0 -0
  193. data/app/assets/stylesheets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  194. data/app/assets/stylesheets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  195. data/app/assets/stylesheets/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  196. data/app/assets/stylesheets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  197. data/app/assets/stylesheets/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  198. data/app/assets/stylesheets/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  199. data/app/assets/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  200. data/app/assets/stylesheets/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  201. data/app/assets/stylesheets/images/ui-icons_222222_256x240.png +0 -0
  202. data/app/assets/stylesheets/images/ui-icons_2e83ff_256x240.png +0 -0
  203. data/app/assets/stylesheets/images/ui-icons_454545_256x240.png +0 -0
  204. data/app/assets/stylesheets/images/ui-icons_888888_256x240.png +0 -0
  205. data/app/assets/stylesheets/images/ui-icons_cd0a0a_256x240.png +0 -0
  206. data/app/assets/stylesheets/invitations.css +3 -0
  207. data/app/assets/stylesheets/location.css.scss +38 -0
  208. data/app/assets/stylesheets/menu.css.scss +19 -0
  209. data/app/assets/stylesheets/messages.css.scss +141 -0
  210. data/app/assets/stylesheets/opa75.png +0 -0
  211. data/app/assets/stylesheets/profiles.css +4 -0
  212. data/app/assets/stylesheets/relation_customs.css.scss +233 -0
  213. data/app/assets/stylesheets/search.css.scss +165 -0
  214. data/app/assets/stylesheets/settings.css +9 -0
  215. data/app/assets/stylesheets/social_stream-base.css +5 -0
  216. data/app/assets/stylesheets/ties.css.scss +12 -0
  217. data/app/assets/stylesheets/toolbar.css +10 -0
  218. data/app/assets/stylesheets/users.css +4 -0
  219. data/app/controllers/activities_controller.rb +19 -0
  220. data/app/controllers/api_controller.rb +38 -0
  221. data/app/controllers/authentications_controller.rb +17 -0
  222. data/app/controllers/cheesecake_controller.rb +9 -0
  223. data/app/controllers/comments_controller.rb +8 -0
  224. data/app/controllers/contacts_controller.rb +95 -0
  225. data/app/controllers/conversations_controller.rb +102 -0
  226. data/app/controllers/frontpage_controller.rb +23 -0
  227. data/app/controllers/groups_controller.rb +58 -0
  228. data/app/controllers/home_controller.rb +3 -0
  229. data/app/controllers/invitations_controller.rb +36 -0
  230. data/app/controllers/likes_controller.rb +41 -0
  231. data/app/controllers/messages_controller.rb +87 -0
  232. data/app/controllers/notifications_controller.rb +73 -0
  233. data/app/controllers/omniauth_callbacks_controller.rb +17 -0
  234. data/app/controllers/permissions_controller.rb +15 -0
  235. data/app/controllers/posts_controller.rb +3 -0
  236. data/app/controllers/profiles_controller.rb +9 -0
  237. data/app/controllers/relation/customs_controller.rb +6 -0
  238. data/app/controllers/search_controller.rb +79 -0
  239. data/app/controllers/settings_controller.rb +43 -0
  240. data/app/controllers/subjects_controller.rb +7 -0
  241. data/app/controllers/tags_controller.rb +15 -0
  242. data/app/controllers/ties_controller.rb +11 -0
  243. data/app/controllers/users_controller.rb +31 -0
  244. data/app/helpers/activities_helper.rb +37 -0
  245. data/app/helpers/contacts_helper.rb +24 -0
  246. data/app/helpers/groups_helper.rb +3 -0
  247. data/app/helpers/location_helper.rb +46 -0
  248. data/app/helpers/permissions_helper.rb +16 -0
  249. data/app/helpers/profiles_helper.rb +37 -0
  250. data/app/helpers/search_helper.rb +38 -0
  251. data/app/helpers/settings_helper.rb +9 -0
  252. data/app/helpers/sidebar_helper.rb +10 -0
  253. data/app/helpers/subjects_helper.rb +15 -0
  254. data/app/helpers/toolbar_helper.rb +109 -0
  255. data/app/helpers/users_helper.rb +4 -0
  256. data/app/mailers/invitation_mailer.rb +11 -0
  257. data/app/models/ability.rb +2 -0
  258. data/app/models/activity.rb +390 -0
  259. data/app/models/activity_object.rb +64 -0
  260. data/app/models/activity_object_activity.rb +14 -0
  261. data/app/models/activity_verb.rb +22 -0
  262. data/app/models/actor.rb +553 -0
  263. data/app/models/audience.rb +9 -0
  264. data/app/models/authentication.rb +3 -0
  265. data/app/models/comment.rb +10 -0
  266. data/app/models/contact.rb +209 -0
  267. data/app/models/group.rb +51 -0
  268. data/app/models/like.rb +49 -0
  269. data/app/models/permission.rb +52 -0
  270. data/app/models/post.rb +12 -0
  271. data/app/models/profile.rb +58 -0
  272. data/app/models/relation.rb +169 -0
  273. data/app/models/relation/custom.rb +112 -0
  274. data/app/models/relation/public.rb +11 -0
  275. data/app/models/relation/reject.rb +3 -0
  276. data/app/models/relation/single.rb +22 -0
  277. data/app/models/relation_permission.rb +4 -0
  278. data/app/models/tie.rb +147 -0
  279. data/app/models/user.rb +148 -0
  280. data/app/views/activities/_activity.html.erb +5 -0
  281. data/app/views/activities/_child.html.erb +18 -0
  282. data/app/views/activities/_comments.html.erb +3 -0
  283. data/app/views/activities/_filter.html.erb +83 -0
  284. data/app/views/activities/_index.html.erb +14 -0
  285. data/app/views/activities/_new.html.erb +56 -0
  286. data/app/views/activities/_options.html.erb +27 -0
  287. data/app/views/activities/_root.html.erb +37 -0
  288. data/app/views/activities/_wall.html.erb +5 -0
  289. data/app/views/activities/index.html.erb +0 -0
  290. data/app/views/activities/index.js.erb +3 -0
  291. data/app/views/activity_objects/_activity_object.html.erb +7 -0
  292. data/app/views/actors/_actor.html.erb +0 -0
  293. data/app/views/actors/_actor_cheesecake.html.erb +4 -0
  294. data/app/views/api/activity_atom_feed.atom.builder +40 -0
  295. data/app/views/avatars/index.html.erb +15 -0
  296. data/app/views/avatars/update.js.erb +15 -0
  297. data/app/views/cheesecake/_index.html.erb +38 -0
  298. data/app/views/cheesecake/index.html.erb +10 -0
  299. data/app/views/comments/_comment.html.erb +1 -0
  300. data/app/views/comments/_new.html.erb +47 -0
  301. data/app/views/comments/create.js.erb +10 -0
  302. data/app/views/comments/destroy.js.erb +1 -0
  303. data/app/views/contacts/_contact.html.erb +20 -0
  304. data/app/views/contacts/_form.html.erb +38 -0
  305. data/app/views/contacts/_index.html.erb +40 -0
  306. data/app/views/contacts/_link.html.erb +9 -0
  307. data/app/views/contacts/_pendings.html.erb +18 -0
  308. data/app/views/contacts/_suggestions.html.erb +15 -0
  309. data/app/views/contacts/_suggestions_and_pendings.html.erb +6 -0
  310. data/app/views/contacts/destroy.js.erb +6 -0
  311. data/app/views/contacts/edit.html.erb +6 -0
  312. data/app/views/contacts/index.html.erb +37 -0
  313. data/app/views/contacts/index.js.erb +3 -0
  314. data/app/views/contacts/new.html.erb +5 -0
  315. data/app/views/contacts/suggestion.html.erb +1 -0
  316. data/app/views/contacts/suggestion.js.erb +1 -0
  317. data/app/views/conversations/_conversation.html.erb +38 -0
  318. data/app/views/conversations/_conversation_full.html.erb +71 -0
  319. data/app/views/conversations/_conversations.html.erb +5 -0
  320. data/app/views/conversations/_index.html.erb +11 -0
  321. data/app/views/conversations/_show.html.erb +13 -0
  322. data/app/views/conversations/edit.html.erb +10 -0
  323. data/app/views/conversations/index.html.erb +15 -0
  324. data/app/views/conversations/index.js.erb +6 -0
  325. data/app/views/conversations/show.html.erb +33 -0
  326. data/app/views/conversations/show.js.erb +26 -0
  327. data/app/views/devise/passwords/edit.html.erb +21 -0
  328. data/app/views/devise/passwords/new.html.erb +27 -0
  329. data/app/views/devise/registrations/_delete_account.html.erb +20 -0
  330. data/app/views/devise/registrations/_edit_user.html.erb +113 -0
  331. data/app/views/devise/registrations/edit.html.erb +20 -0
  332. data/app/views/devise/registrations/new.html.erb +44 -0
  333. data/app/views/devise/sessions/new.html.erb +35 -0
  334. data/app/views/devise/shared/_links.erb +25 -0
  335. data/app/views/frontpage/_caracteristics.html.erb +23 -0
  336. data/app/views/frontpage/_social_networks.html.erb +3 -0
  337. data/app/views/frontpage/_sponsor.html.erb +12 -0
  338. data/app/views/frontpage/host_meta.xml.builder +11 -0
  339. data/app/views/frontpage/index.html.erb +69 -0
  340. data/app/views/groups/_group.html.erb +4 -0
  341. data/app/views/groups/_group_focus_search.html.erb +2 -0
  342. data/app/views/groups/_group_global_search.html.erb +2 -0
  343. data/app/views/groups/_group_with_details.html.erb +2 -0
  344. data/app/views/groups/_index.html.erb +19 -0
  345. data/app/views/groups/_new.html.erb +81 -0
  346. data/app/views/groups/_show.html.erb +33 -0
  347. data/app/views/groups/_tag_cloud.html.erb +25 -0
  348. data/app/views/groups/index.html.erb +57 -0
  349. data/app/views/groups/index.js.erb +1 -0
  350. data/app/views/groups/new.html.erb +9 -0
  351. data/app/views/groups/show.html.erb +1 -0
  352. data/app/views/groups/show.js.erb +2 -0
  353. data/app/views/home/_groups.html.erb +24 -0
  354. data/app/views/home/index.html.erb +19 -0
  355. data/app/views/home/index.js.erb +5 -0
  356. data/app/views/invitation_mailer/send_invitation.html.erb +79 -0
  357. data/app/views/invitation_mailer/send_invitation.text.erb +21 -0
  358. data/app/views/invitations/_new.html.erb +28 -0
  359. data/app/views/invitations/new.html.erb +9 -0
  360. data/app/views/invitations/new.js.erb +4 -0
  361. data/app/views/layouts/_account.html.erb +18 -0
  362. data/app/views/layouts/_flash.html.erb +5 -0
  363. data/app/views/layouts/_footer.html.erb +16 -0
  364. data/app/views/layouts/_header.erb +5 -0
  365. data/app/views/layouts/_header_dropdown_menu.html.erb +19 -0
  366. data/app/views/layouts/_header_dropdown_menu_sessions.html.erb +14 -0
  367. data/app/views/layouts/_header_signed_in.erb +45 -0
  368. data/app/views/layouts/_header_signed_out.erb +34 -0
  369. data/app/views/layouts/_representation.html.erb +28 -0
  370. data/app/views/layouts/_search.html.erb +62 -0
  371. data/app/views/layouts/_settings.html.erb +18 -0
  372. data/app/views/layouts/application.html.erb +60 -0
  373. data/app/views/layouts/frontpage.html.erb +43 -0
  374. data/app/views/likes/create.js.erb +2 -0
  375. data/app/views/likes/destroy.js.erb +1 -0
  376. data/app/views/location/_location.html.erb +3 -0
  377. data/app/views/location/_location_body.html.erb +18 -0
  378. data/app/views/message_mailer/new_message_email.html.erb +35 -0
  379. data/app/views/message_mailer/new_message_email.text.erb +8 -0
  380. data/app/views/message_mailer/reply_message_email.html.erb +35 -0
  381. data/app/views/message_mailer/reply_message_email.text.erb +8 -0
  382. data/app/views/messages/_form.html.erb +39 -0
  383. data/app/views/messages/_message.html.erb +31 -0
  384. data/app/views/messages/_new.html.erb +10 -0
  385. data/app/views/messages/new.html.erb +37 -0
  386. data/app/views/messages/new.js.erb +28 -0
  387. data/app/views/notification_mailer/new_notification_email.html.erb +35 -0
  388. data/app/views/notification_mailer/new_notification_email.text.erb +9 -0
  389. data/app/views/notifications/_index.html.erb +21 -0
  390. data/app/views/notifications/_notification.html.erb +41 -0
  391. data/app/views/notifications/activities/_follow.html.erb +10 -0
  392. data/app/views/notifications/activities/_follow.text.erb +8 -0
  393. data/app/views/notifications/activities/_like.html.erb +30 -0
  394. data/app/views/notifications/activities/_like.text.erb +23 -0
  395. data/app/views/notifications/activities/_make-friend.html.erb +10 -0
  396. data/app/views/notifications/activities/_make-friend.text.erb +7 -0
  397. data/app/views/notifications/activities/_post.html.erb +22 -0
  398. data/app/views/notifications/activities/_post.text.erb +17 -0
  399. data/app/views/notifications/activities/_update.html.erb +18 -0
  400. data/app/views/notifications/activities/_update.text.erb +15 -0
  401. data/app/views/notifications/index.html.erb +13 -0
  402. data/app/views/notifications/index.js.erb +6 -0
  403. data/app/views/objects/_destroy.js.erb +2 -0
  404. data/app/views/objects/_new_activity.html.erb +8 -0
  405. data/app/views/objects/_show.html.erb +3 -0
  406. data/app/views/permissions/_index.html.erb +35 -0
  407. data/app/views/permissions/index.js.erb +15 -0
  408. data/app/views/posts/_new_activity.html.erb +1 -0
  409. data/app/views/posts/_new_activity_fields.erb +7 -0
  410. data/app/views/posts/_post.html.erb +3 -0
  411. data/app/views/posts/_post_focus_search.html.erb +37 -0
  412. data/app/views/posts/_post_global_search.html.erb +18 -0
  413. data/app/views/posts/_post_with_details.html.erb +3 -0
  414. data/app/views/posts/create.js.erb +7 -0
  415. data/app/views/posts/destroy.js.erb +1 -0
  416. data/app/views/posts/show.html.erb +10 -0
  417. data/app/views/profiles/_contact.html.erb +81 -0
  418. data/app/views/profiles/_experience.html.erb +22 -0
  419. data/app/views/profiles/_personal.html.erb +74 -0
  420. data/app/views/profiles/_profile.html.erb +40 -0
  421. data/app/views/profiles/_tags.html.erb +22 -0
  422. data/app/views/profiles/edit.html.erb +205 -0
  423. data/app/views/profiles/show.html.erb +22 -0
  424. data/app/views/profiles/update.js.erb +20 -0
  425. data/app/views/relation/customs/_form.html.erb +29 -0
  426. data/app/views/relation/customs/_list.html.erb +63 -0
  427. data/app/views/relation/customs/_update_rules.js.erb +5 -0
  428. data/app/views/relation/customs/create.js.erb +21 -0
  429. data/app/views/relation/customs/index.html.erb +43 -0
  430. data/app/views/relation/customs/update.js.erb +11 -0
  431. data/app/views/search/_extended_search.html.erb +19 -0
  432. data/app/views/search/_form.html.erb +54 -0
  433. data/app/views/search/_header_search.html.erb +16 -0
  434. data/app/views/search/_index.html.erb +12 -0
  435. data/app/views/search/index.html.erb +9 -0
  436. data/app/views/search/index.js.erb +22 -0
  437. data/app/views/settings/_api_key.html.erb +26 -0
  438. data/app/views/settings/_destroy.html.erb +17 -0
  439. data/app/views/settings/_index.html.erb +8 -0
  440. data/app/views/settings/_notifications.html.erb +34 -0
  441. data/app/views/settings/index.html.erb +16 -0
  442. data/app/views/settings/index.js.erb +7 -0
  443. data/app/views/subjects/_contacts.html.erb +18 -0
  444. data/app/views/subjects/_show.js.erb +5 -0
  445. data/app/views/subjects/_subject.html.erb +8 -0
  446. data/app/views/subjects/_subject_with_details.html.erb +17 -0
  447. data/app/views/ties/index.html.erb +8 -0
  448. data/app/views/toolbar/_home.html.erb +15 -0
  449. data/app/views/toolbar/_logo.html.erb +23 -0
  450. data/app/views/toolbar/_messages.html.erb +11 -0
  451. data/app/views/toolbar/_profile.html.erb +24 -0
  452. data/app/views/toolbar/_subject.html.erb +10 -0
  453. data/app/views/users/_groups.html.erb +22 -0
  454. data/app/views/users/_index.html.erb +19 -0
  455. data/app/views/users/_show.html.erb +34 -0
  456. data/app/views/users/_user.html.erb +2 -0
  457. data/app/views/users/_user_focus_search.html.erb +2 -0
  458. data/app/views/users/_user_global_search.html.erb +2 -0
  459. data/app/views/users/_user_with_details.html.erb +2 -0
  460. data/app/views/users/index.html.erb +41 -0
  461. data/app/views/users/index.js.erb +1 -0
  462. data/app/views/users/info.html.erb +0 -0
  463. data/app/views/users/show.html.erb +1 -0
  464. data/app/views/users/show.js.erb +2 -0
  465. data/app/views/users/show.xml.builder +15 -0
  466. data/config/locales/en.yml +472 -0
  467. data/config/locales/es.yml +470 -0
  468. data/config/routes.rb +102 -0
  469. data/db/migrate/20110610112023_create_social_stream.rb +319 -0
  470. data/db/migrate/20110705103202_empty_ties_count.rb +17 -0
  471. data/db/migrate/20110712090343_remove_spheres.rb +30 -0
  472. data/db/migrate/20110712142140_remove_permission_function.rb +26 -0
  473. data/db/migrate/20110912074426_add_reject_relation.rb +29 -0
  474. data/db/migrate/20111124100618_object_actors.rb +52 -0
  475. data/db/migrate/20111221103509_add_language_field.rb +13 -0
  476. data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
  477. data/lib/acts_as_taggable_on/social_stream.rb +58 -0
  478. data/lib/generators/social_stream/base/install_generator.rb +66 -0
  479. data/lib/generators/social_stream/base/templates/initializer.rb +32 -0
  480. data/lib/generators/social_stream/base/templates/navigation.rb +4 -0
  481. data/lib/generators/social_stream/base/templates/relations.yml +39 -0
  482. data/lib/generators/social_stream/base/templates/sphinx.yml +9 -0
  483. data/lib/paperclip/social_stream.rb +6 -0
  484. data/lib/social_stream-base.rb +104 -0
  485. data/lib/social_stream/ability.rb +7 -0
  486. data/lib/social_stream/ability/base.rb +101 -0
  487. data/lib/social_stream/base/dependencies.rb +47 -0
  488. data/lib/social_stream/base/engine.rb +69 -0
  489. data/lib/social_stream/base/version.rb +5 -0
  490. data/lib/social_stream/controllers/cancan_devise_integration.rb +33 -0
  491. data/lib/social_stream/controllers/helpers.rb +135 -0
  492. data/lib/social_stream/controllers/objects.rb +39 -0
  493. data/lib/social_stream/d3.rb +53 -0
  494. data/lib/social_stream/migrations/base.rb +58 -0
  495. data/lib/social_stream/migrations/components.rb +19 -0
  496. data/lib/social_stream/models/object.rb +133 -0
  497. data/lib/social_stream/models/subject.rb +118 -0
  498. data/lib/social_stream/models/supertype.rb +37 -0
  499. data/lib/social_stream/populate.rb +26 -0
  500. data/lib/social_stream/test_helpers.rb +11 -0
  501. data/lib/social_stream/test_helpers/controllers.rb +122 -0
  502. data/lib/social_stream/toolbar_config/base.rb +94 -0
  503. data/lib/social_stream/views/list.rb +17 -0
  504. data/lib/social_stream/views/settings/base.rb +43 -0
  505. data/lib/social_stream/views/sidebar/base.rb +27 -0
  506. data/lib/tasks/db/populate.rake +241 -0
  507. data/lib/tasks/workers.rake +163 -0
  508. data/social_stream-base.gemspec +83 -0
  509. data/spec/controllers/comments_controller_spec.rb +66 -0
  510. data/spec/controllers/contacts_controller_spec.rb +111 -0
  511. data/spec/controllers/frontpage_controller_spec.rb +16 -0
  512. data/spec/controllers/groups_controller_spec.rb +178 -0
  513. data/spec/controllers/home_controller_spec.rb +56 -0
  514. data/spec/controllers/invitations_controller_spec.rb +34 -0
  515. data/spec/controllers/likes_controller_spec.rb +48 -0
  516. data/spec/controllers/notifications_controller_spec.rb +46 -0
  517. data/spec/controllers/permissions_controller_spec.rb +45 -0
  518. data/spec/controllers/posts_controller_spec.rb +233 -0
  519. data/spec/controllers/profiles_controller_spec.rb +102 -0
  520. data/spec/controllers/relation_customs_controller_spec.rb +139 -0
  521. data/spec/controllers/representations_spec.rb +74 -0
  522. data/spec/controllers/settings_controller_spec.rb +41 -0
  523. data/spec/controllers/subjects_controller.rb +14 -0
  524. data/spec/controllers/users_controller_spec.rb +98 -0
  525. data/spec/dummy/.gitignore +5 -0
  526. data/spec/dummy/Rakefile +7 -0
  527. data/spec/dummy/app/assets/javascripts/application.js +8 -0
  528. data/spec/dummy/app/assets/stylesheets/application.css +8 -0
  529. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  530. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  531. data/spec/dummy/config.ru +4 -0
  532. data/spec/dummy/config/application.rb +44 -0
  533. data/spec/dummy/config/boot.rb +10 -0
  534. data/spec/dummy/config/database.yml +40 -0
  535. data/spec/dummy/config/environment.rb +5 -0
  536. data/spec/dummy/config/environments/development.rb +30 -0
  537. data/spec/dummy/config/environments/production.rb +54 -0
  538. data/spec/dummy/config/environments/test.rb +40 -0
  539. data/spec/dummy/config/environments/test_pg.rb +35 -0
  540. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  541. data/spec/dummy/config/initializers/devise.rb +220 -0
  542. data/spec/dummy/config/initializers/inflections.rb +10 -0
  543. data/spec/dummy/config/initializers/mailboxer.rb +8 -0
  544. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  545. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  546. data/spec/dummy/config/initializers/session_store.rb +8 -0
  547. data/spec/dummy/config/initializers/social_stream.rb +32 -0
  548. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  549. data/spec/dummy/config/locales/en.yml +5 -0
  550. data/spec/dummy/config/navigation.rb +4 -0
  551. data/spec/dummy/config/relations.yml +39 -0
  552. data/spec/dummy/config/routes.rb +60 -0
  553. data/spec/dummy/db/schema.rb +5 -0
  554. data/spec/dummy/db/seeds.rb +8 -0
  555. data/spec/dummy/public/404.html +26 -0
  556. data/spec/dummy/public/422.html +26 -0
  557. data/spec/dummy/public/500.html +26 -0
  558. data/spec/dummy/public/favicon.ico +0 -0
  559. data/spec/dummy/script/rails +6 -0
  560. data/spec/factories/activity.rb +52 -0
  561. data/spec/factories/comment.rb +6 -0
  562. data/spec/factories/contact.rb +16 -0
  563. data/spec/factories/group.rb +5 -0
  564. data/spec/factories/post.rb +11 -0
  565. data/spec/factories/relation_custom.rb +4 -0
  566. data/spec/factories/tie.rb +43 -0
  567. data/spec/factories/user.rb +6 -0
  568. data/spec/integration/navigation_spec.rb +33 -0
  569. data/spec/models/activity_authorization_spec.rb +350 -0
  570. data/spec/models/activity_spec.rb +131 -0
  571. data/spec/models/actor_spec.rb +80 -0
  572. data/spec/models/contact_spec.rb +53 -0
  573. data/spec/models/group_spec.rb +28 -0
  574. data/spec/models/like_spec.rb +68 -0
  575. data/spec/models/post_spec.rb +63 -0
  576. data/spec/models/profile_spec.rb +39 -0
  577. data/spec/models/relation_spec.rb +78 -0
  578. data/spec/models/tie_spec.rb +169 -0
  579. data/spec/models/user_spec.rb +109 -0
  580. data/spec/social_stream_spec.rb +7 -0
  581. data/spec/spec_helper.rb +26 -0
  582. data/spec/support/cancan.rb +1 -0
  583. data/spec/support/db.rb +7 -0
  584. data/spec/support/devise.rb +4 -0
  585. data/spec/support/mock.rb +4 -0
  586. data/vendor/assets/javascripts/ajax.paginate.js +46 -0
  587. data/vendor/assets/javascripts/d3.geom.js +825 -0
  588. data/vendor/assets/javascripts/d3.js +4013 -0
  589. data/vendor/assets/javascripts/d3.layout.js +1865 -0
  590. data/vendor/assets/javascripts/hoverIntent.js +84 -0
  591. data/vendor/assets/javascripts/jqcloud-0.1.3.js +87 -0
  592. data/vendor/assets/javascripts/jquery.ae.image.resize.js +69 -0
  593. data/vendor/assets/javascripts/jquery.ba-url.js +1091 -0
  594. data/vendor/assets/javascripts/jquery.cleditor.min.js +31 -0
  595. data/vendor/assets/javascripts/jquery.fcbkcomplete.js +553 -0
  596. data/vendor/assets/javascripts/jquery.lightbox-with-resize-plugin.js +533 -0
  597. data/vendor/assets/javascripts/jquery.livequery.js +250 -0
  598. data/vendor/assets/javascripts/jquery.screw.js +186 -0
  599. data/vendor/assets/javascripts/jquery.scrollTo.min.js +11 -0
  600. data/vendor/assets/javascripts/jquery.tipsy.js +263 -0
  601. data/vendor/assets/javascripts/jquery.validate.js +1166 -0
  602. data/vendor/assets/javascripts/jquery.validate.old.js +1132 -0
  603. data/vendor/assets/javascripts/jquery.watermarkinput.js +81 -0
  604. data/vendor/assets/javascripts/menu.js +25 -0
  605. data/vendor/assets/javascripts/superfish.js +121 -0
  606. data/vendor/assets/stylesheets/carousel.css +23 -0
  607. data/vendor/assets/stylesheets/chosen-sprite.png +0 -0
  608. data/vendor/assets/stylesheets/chosen.css +317 -0
  609. data/vendor/assets/stylesheets/fcbkComplete.css +44 -0
  610. data/vendor/assets/stylesheets/jqcloud.css +15 -0
  611. data/vendor/assets/stylesheets/jquery-ui.css +620 -0
  612. data/vendor/assets/stylesheets/jquery.cleditor.css +24 -0
  613. data/vendor/assets/stylesheets/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  614. data/vendor/assets/stylesheets/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  615. data/vendor/assets/stylesheets/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  616. data/vendor/assets/stylesheets/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  617. data/vendor/assets/stylesheets/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  618. data/vendor/assets/stylesheets/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  619. data/vendor/assets/stylesheets/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  620. data/vendor/assets/stylesheets/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  621. data/vendor/assets/stylesheets/smoothness/images/ui-icons_222222_256x240.png +0 -0
  622. data/vendor/assets/stylesheets/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  623. data/vendor/assets/stylesheets/smoothness/images/ui-icons_454545_256x240.png +0 -0
  624. data/vendor/assets/stylesheets/smoothness/images/ui-icons_888888_256x240.png +0 -0
  625. data/vendor/assets/stylesheets/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  626. data/vendor/assets/stylesheets/smoothness/jquery-ui-1.7.3.custom.css +405 -0
  627. data/vendor/assets/stylesheets/smoothness/jquery-ui-1.8.4.custom.css +572 -0
  628. data/vendor/assets/stylesheets/tipsy.css +25 -0
  629. metadata +997 -0
@@ -0,0 +1,1865 @@
1
+ (function(){d3.layout = {};
2
+ // Implements hierarchical edge bundling using Holten's algorithm. For each
3
+ // input link, a path is computed that travels through the tree, up the parent
4
+ // hierarchy to the least common ancestor, and then back down to the destination
5
+ // node. Each path is simply an array of nodes.
6
+ d3.layout.bundle = function() {
7
+ return function(links) {
8
+ var paths = [],
9
+ i = -1,
10
+ n = links.length;
11
+ while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
12
+ return paths;
13
+ };
14
+ };
15
+
16
+ function d3_layout_bundlePath(link) {
17
+ var start = link.source,
18
+ end = link.target,
19
+ lca = d3_layout_bundleLeastCommonAncestor(start, end),
20
+ points = [start];
21
+ while (start !== lca) {
22
+ start = start.parent;
23
+ points.push(start);
24
+ }
25
+ var k = points.length;
26
+ while (end !== lca) {
27
+ points.splice(k, 0, end);
28
+ end = end.parent;
29
+ }
30
+ return points;
31
+ }
32
+
33
+ function d3_layout_bundleAncestors(node) {
34
+ var ancestors = [],
35
+ parent = node.parent;
36
+ while (parent != null) {
37
+ ancestors.push(node);
38
+ node = parent;
39
+ parent = parent.parent;
40
+ }
41
+ ancestors.push(node);
42
+ return ancestors;
43
+ }
44
+
45
+ function d3_layout_bundleLeastCommonAncestor(a, b) {
46
+ if (a === b) return a;
47
+ var aNodes = d3_layout_bundleAncestors(a),
48
+ bNodes = d3_layout_bundleAncestors(b),
49
+ aNode = aNodes.pop(),
50
+ bNode = bNodes.pop(),
51
+ sharedNode = null;
52
+ while (aNode === bNode) {
53
+ sharedNode = aNode;
54
+ aNode = aNodes.pop();
55
+ bNode = bNodes.pop();
56
+ }
57
+ return sharedNode;
58
+ }
59
+ d3.layout.chord = function() {
60
+ var chord = {},
61
+ chords,
62
+ groups,
63
+ matrix,
64
+ n,
65
+ padding = 0,
66
+ sortGroups,
67
+ sortSubgroups,
68
+ sortChords;
69
+
70
+ function relayout() {
71
+ var subgroups = {},
72
+ groupSums = [],
73
+ groupIndex = d3.range(n),
74
+ subgroupIndex = [],
75
+ k,
76
+ x,
77
+ x0,
78
+ i,
79
+ j;
80
+
81
+ chords = [];
82
+ groups = [];
83
+
84
+ // Compute the sum.
85
+ k = 0, i = -1; while (++i < n) {
86
+ x = 0, j = -1; while (++j < n) {
87
+ x += matrix[i][j];
88
+ }
89
+ groupSums.push(x);
90
+ subgroupIndex.push(d3.range(n));
91
+ k += x;
92
+ }
93
+
94
+ // Sort groups…
95
+ if (sortGroups) {
96
+ groupIndex.sort(function(a, b) {
97
+ return sortGroups(groupSums[a], groupSums[b]);
98
+ });
99
+ }
100
+
101
+ // Sort subgroups…
102
+ if (sortSubgroups) {
103
+ subgroupIndex.forEach(function(d, i) {
104
+ d.sort(function(a, b) {
105
+ return sortSubgroups(matrix[i][a], matrix[i][b]);
106
+ });
107
+ });
108
+ }
109
+
110
+ // Convert the sum to scaling factor for [0, 2pi].
111
+ // TODO Allow start and end angle to be specified.
112
+ // TODO Allow padding to be specified as percentage?
113
+ k = (2 * Math.PI - padding * n) / k;
114
+
115
+ // Compute the start and end angle for each group and subgroup.
116
+ x = 0, i = -1; while (++i < n) {
117
+ x0 = x, j = -1; while (++j < n) {
118
+ var di = groupIndex[i],
119
+ dj = subgroupIndex[i][j],
120
+ v = matrix[di][dj];
121
+ subgroups[di + "-" + dj] = {
122
+ index: di,
123
+ subindex: dj,
124
+ startAngle: x,
125
+ endAngle: x += v * k,
126
+ value: v
127
+ };
128
+ }
129
+ groups.push({
130
+ index: di,
131
+ startAngle: x0,
132
+ endAngle: x,
133
+ value: (x - x0) / k
134
+ });
135
+ x += padding;
136
+ }
137
+
138
+ // Generate chords for each (non-empty) subgroup-subgroup link.
139
+ i = -1; while (++i < n) {
140
+ j = i - 1; while (++j < n) {
141
+ var source = subgroups[i + "-" + j],
142
+ target = subgroups[j + "-" + i];
143
+ if (source.value || target.value) {
144
+ chords.push(source.value < target.value
145
+ ? {source: target, target: source}
146
+ : {source: source, target: target});
147
+ }
148
+ }
149
+ }
150
+
151
+ if (sortChords) resort();
152
+ }
153
+
154
+ function resort() {
155
+ chords.sort(function(a, b) {
156
+ return sortChords(a.target.value, b.target.value);
157
+ });
158
+ }
159
+
160
+ chord.matrix = function(x) {
161
+ if (!arguments.length) return matrix;
162
+ n = (matrix = x) && matrix.length;
163
+ chords = groups = null;
164
+ return chord;
165
+ };
166
+
167
+ chord.padding = function(x) {
168
+ if (!arguments.length) return padding;
169
+ padding = x;
170
+ chords = groups = null;
171
+ return chord;
172
+ };
173
+
174
+ chord.sortGroups = function(x) {
175
+ if (!arguments.length) return sortGroups;
176
+ sortGroups = x;
177
+ chords = groups = null;
178
+ return chord;
179
+ };
180
+
181
+ chord.sortSubgroups = function(x) {
182
+ if (!arguments.length) return sortSubgroups;
183
+ sortSubgroups = x;
184
+ chords = null;
185
+ return chord;
186
+ };
187
+
188
+ chord.sortChords = function(x) {
189
+ if (!arguments.length) return sortChords;
190
+ sortChords = x;
191
+ if (chords) resort();
192
+ return chord;
193
+ };
194
+
195
+ chord.chords = function() {
196
+ if (!chords) relayout();
197
+ return chords;
198
+ };
199
+
200
+ chord.groups = function() {
201
+ if (!groups) relayout();
202
+ return groups;
203
+ };
204
+
205
+ return chord;
206
+ };
207
+ // A rudimentary force layout using Gauss-Seidel.
208
+ d3.layout.force = function() {
209
+ var force = {},
210
+ event = d3.dispatch("tick"),
211
+ size = [1, 1],
212
+ drag,
213
+ alpha,
214
+ friction = .9,
215
+ linkDistance = d3_layout_forceLinkDistance,
216
+ linkStrength = d3_layout_forceLinkStrength,
217
+ charge = -30,
218
+ gravity = .1,
219
+ theta = .8,
220
+ interval,
221
+ nodes = [],
222
+ links = [],
223
+ distances,
224
+ strengths;
225
+
226
+ function repulse(node, kc) {
227
+ return function(quad, x1, y1, x2, y2) {
228
+ if (quad.point !== node) {
229
+ var dx = quad.cx - node.x,
230
+ dy = quad.cy - node.y,
231
+ dn = 1 / Math.sqrt(dx * dx + dy * dy);
232
+
233
+ /* Barnes-Hut criterion. */
234
+ if ((x2 - x1) * dn < theta) {
235
+ var k = kc * quad.count * dn * dn;
236
+ node.px -= dx * k;
237
+ node.py -= dy * k;
238
+ return true;
239
+ }
240
+
241
+ if (quad.point && isFinite(dn)) {
242
+ var k = kc * dn * dn;
243
+ node.px -= dx * k;
244
+ node.py -= dy * k;
245
+ }
246
+ }
247
+ };
248
+ }
249
+
250
+ function tick() {
251
+ var n = nodes.length,
252
+ m = links.length,
253
+ q,
254
+ i, // current index
255
+ o, // current object
256
+ s, // current source
257
+ t, // current target
258
+ l, // current distance
259
+ k, // current force
260
+ x, // x-distance
261
+ y; // y-distance
262
+
263
+ // gauss-seidel relaxation for links
264
+ for (i = 0; i < m; ++i) {
265
+ o = links[i];
266
+ s = o.source;
267
+ t = o.target;
268
+ x = t.x - s.x;
269
+ y = t.y - s.y;
270
+ if (l = (x * x + y * y)) {
271
+ l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
272
+ x *= l;
273
+ y *= l;
274
+ t.x -= x * (k = s.weight / (t.weight + s.weight));
275
+ t.y -= y * k;
276
+ s.x += x * (k = 1 - k);
277
+ s.y += y * k;
278
+ }
279
+ }
280
+
281
+ // apply gravity forces
282
+ if (k = alpha * gravity) {
283
+ x = size[0] / 2;
284
+ y = size[1] / 2;
285
+ i = -1; if (k) while (++i < n) {
286
+ o = nodes[i];
287
+ o.x += (x - o.x) * k;
288
+ o.y += (y - o.y) * k;
289
+ }
290
+ }
291
+
292
+ // compute quadtree center of mass and apply charge forces
293
+ if (k = alpha * charge) {
294
+ d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes));
295
+ i = -1; while (++i < n) {
296
+ if (!(o = nodes[i]).fixed) {
297
+ q.visit(repulse(o, k));
298
+ }
299
+ }
300
+ }
301
+
302
+ // position verlet integration
303
+ i = -1; while (++i < n) {
304
+ o = nodes[i];
305
+ if (o.fixed) {
306
+ o.x = o.px;
307
+ o.y = o.py;
308
+ } else {
309
+ o.x -= (o.px - (o.px = o.x)) * friction;
310
+ o.y -= (o.py - (o.py = o.y)) * friction;
311
+ }
312
+ }
313
+
314
+ event.tick.dispatch({type: "tick", alpha: alpha});
315
+
316
+ // simulated annealing, basically
317
+ return (alpha *= .99) < .005;
318
+ }
319
+
320
+ force.on = function(type, listener) {
321
+ event[type].add(listener);
322
+ return force;
323
+ };
324
+
325
+ force.nodes = function(x) {
326
+ if (!arguments.length) return nodes;
327
+ nodes = x;
328
+ return force;
329
+ };
330
+
331
+ force.links = function(x) {
332
+ if (!arguments.length) return links;
333
+ links = x;
334
+ return force;
335
+ };
336
+
337
+ force.size = function(x) {
338
+ if (!arguments.length) return size;
339
+ size = x;
340
+ return force;
341
+ };
342
+
343
+ force.linkDistance = function(x) {
344
+ if (!arguments.length) return linkDistance;
345
+ linkDistance = d3.functor(x);
346
+ return force;
347
+ };
348
+
349
+ // For backwards-compatibility.
350
+ force.distance = force.linkDistance;
351
+
352
+ force.linkStrength = function(x) {
353
+ if (!arguments.length) return linkStrength;
354
+ linkStrength = d3.functor(x);
355
+ return force;
356
+ };
357
+
358
+ force.friction = function(x) {
359
+ if (!arguments.length) return friction;
360
+ friction = x;
361
+ return force;
362
+ };
363
+
364
+ force.charge = function(x) {
365
+ if (!arguments.length) return charge;
366
+ charge = x;
367
+ return force;
368
+ };
369
+
370
+ force.gravity = function(x) {
371
+ if (!arguments.length) return gravity;
372
+ gravity = x;
373
+ return force;
374
+ };
375
+
376
+ force.theta = function(x) {
377
+ if (!arguments.length) return theta;
378
+ theta = x;
379
+ return force;
380
+ };
381
+
382
+ force.start = function() {
383
+ var i,
384
+ j,
385
+ n = nodes.length,
386
+ m = links.length,
387
+ w = size[0],
388
+ h = size[1],
389
+ neighbors,
390
+ o;
391
+
392
+ for (i = 0; i < n; ++i) {
393
+ (o = nodes[i]).index = i;
394
+ o.weight = 0;
395
+ }
396
+
397
+ distances = [];
398
+ strengths = [];
399
+ for (i = 0; i < m; ++i) {
400
+ o = links[i];
401
+ if (typeof o.source == "number") o.source = nodes[o.source];
402
+ if (typeof o.target == "number") o.target = nodes[o.target];
403
+ distances[i] = linkDistance.call(this, o, i);
404
+ strengths[i] = linkStrength.call(this, o, i);
405
+ ++o.source.weight;
406
+ ++o.target.weight;
407
+ }
408
+
409
+ for (i = 0; i < n; ++i) {
410
+ o = nodes[i];
411
+ if (isNaN(o.x)) o.x = position("x", w);
412
+ if (isNaN(o.y)) o.y = position("y", h);
413
+ if (isNaN(o.px)) o.px = o.x;
414
+ if (isNaN(o.py)) o.py = o.y;
415
+ }
416
+
417
+ // initialize node position based on first neighbor
418
+ function position(dimension, size) {
419
+ var neighbors = neighbor(i),
420
+ j = -1,
421
+ m = neighbors.length,
422
+ x;
423
+ while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;
424
+ return Math.random() * size;
425
+ }
426
+
427
+ // initialize neighbors lazily
428
+ function neighbor() {
429
+ if (!neighbors) {
430
+ neighbors = [];
431
+ for (j = 0; j < n; ++j) {
432
+ neighbors[j] = [];
433
+ }
434
+ for (j = 0; j < m; ++j) {
435
+ var o = links[j];
436
+ neighbors[o.source.index].push(o.target);
437
+ neighbors[o.target.index].push(o.source);
438
+ }
439
+ }
440
+ return neighbors[i];
441
+ }
442
+
443
+ return force.resume();
444
+ };
445
+
446
+ force.resume = function() {
447
+ alpha = .1;
448
+ d3.timer(tick);
449
+ return force;
450
+ };
451
+
452
+ force.stop = function() {
453
+ alpha = 0;
454
+ return force;
455
+ };
456
+
457
+ // use `node.call(force.drag)` to make nodes draggable
458
+ force.drag = function() {
459
+ if (!drag) drag = d3.behavior.drag()
460
+ .on("dragstart", dragstart)
461
+ .on("drag", d3_layout_forceDrag)
462
+ .on("dragend", d3_layout_forceDragEnd);
463
+
464
+ this.on("mouseover.force", d3_layout_forceDragOver)
465
+ .on("mouseout.force", d3_layout_forceDragOut)
466
+ .call(drag);
467
+ };
468
+
469
+ function dragstart(d) {
470
+ d3_layout_forceDragOver(d3_layout_forceDragNode = d);
471
+ d3_layout_forceDragForce = force;
472
+ }
473
+
474
+ return force;
475
+ };
476
+
477
+ var d3_layout_forceDragForce,
478
+ d3_layout_forceDragNode;
479
+
480
+ function d3_layout_forceDragOver(d) {
481
+ d.fixed |= 2;
482
+ }
483
+
484
+ function d3_layout_forceDragOut(d) {
485
+ if (d !== d3_layout_forceDragNode) d.fixed &= 1;
486
+ }
487
+
488
+ function d3_layout_forceDragEnd() {
489
+ d3_layout_forceDrag();
490
+ d3_layout_forceDragNode.fixed &= 1;
491
+ d3_layout_forceDragForce = d3_layout_forceDragNode = null;
492
+ }
493
+
494
+ function d3_layout_forceDrag() {
495
+ d3_layout_forceDragNode.px += d3.event.dx;
496
+ d3_layout_forceDragNode.py += d3.event.dy;
497
+ d3_layout_forceDragForce.resume(); // restart annealing
498
+ }
499
+
500
+ function d3_layout_forceAccumulate(quad) {
501
+ var cx = 0,
502
+ cy = 0;
503
+ quad.count = 0;
504
+ if (!quad.leaf) {
505
+ var nodes = quad.nodes,
506
+ n = nodes.length,
507
+ i = -1,
508
+ c;
509
+ while (++i < n) {
510
+ c = nodes[i];
511
+ if (c == null) continue;
512
+ d3_layout_forceAccumulate(c);
513
+ quad.count += c.count;
514
+ cx += c.count * c.cx;
515
+ cy += c.count * c.cy;
516
+ }
517
+ }
518
+ if (quad.point) {
519
+ // jitter internal nodes that are coincident
520
+ if (!quad.leaf) {
521
+ quad.point.x += Math.random() - .5;
522
+ quad.point.y += Math.random() - .5;
523
+ }
524
+ quad.count++;
525
+ cx += quad.point.x;
526
+ cy += quad.point.y;
527
+ }
528
+ quad.cx = cx / quad.count;
529
+ quad.cy = cy / quad.count;
530
+ }
531
+
532
+ function d3_layout_forceLinkDistance(link) {
533
+ return 20;
534
+ }
535
+
536
+ function d3_layout_forceLinkStrength(link) {
537
+ return 1;
538
+ }
539
+ d3.layout.partition = function() {
540
+ var hierarchy = d3.layout.hierarchy(),
541
+ size = [1, 1]; // width, height
542
+
543
+ function position(node, x, dx, dy) {
544
+ var children = node.children;
545
+ node.x = x;
546
+ node.y = node.depth * dy;
547
+ node.dx = dx;
548
+ node.dy = dy;
549
+ if (children) {
550
+ var i = -1,
551
+ n = children.length,
552
+ c,
553
+ d;
554
+ dx = node.value ? dx / node.value : 0;
555
+ while (++i < n) {
556
+ position(c = children[i], x, d = c.value * dx, dy);
557
+ x += d;
558
+ }
559
+ }
560
+ }
561
+
562
+ function depth(node) {
563
+ var children = node.children,
564
+ d = 0;
565
+ if (children) {
566
+ var i = -1,
567
+ n = children.length;
568
+ while (++i < n) d = Math.max(d, depth(children[i]));
569
+ }
570
+ return 1 + d;
571
+ }
572
+
573
+ function partition(d, i) {
574
+ var nodes = hierarchy.call(this, d, i);
575
+ position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
576
+ return nodes;
577
+ }
578
+
579
+ partition.size = function(x) {
580
+ if (!arguments.length) return size;
581
+ size = x;
582
+ return partition;
583
+ };
584
+
585
+ return d3_layout_hierarchyRebind(partition, hierarchy);
586
+ };
587
+ d3.layout.pie = function() {
588
+ var value = Number,
589
+ sort = null,
590
+ startAngle = 0,
591
+ endAngle = 2 * Math.PI;
592
+
593
+ function pie(data, i) {
594
+
595
+ // Compute the start angle.
596
+ var a = +(typeof startAngle === "function"
597
+ ? startAngle.apply(this, arguments)
598
+ : startAngle);
599
+
600
+ // Compute the angular range (end - start).
601
+ var k = (typeof endAngle === "function"
602
+ ? endAngle.apply(this, arguments)
603
+ : endAngle) - startAngle;
604
+
605
+ // Optionally sort the data.
606
+ var index = d3.range(data.length);
607
+ if (sort != null) index.sort(function(i, j) {
608
+ return sort(data[i], data[j]);
609
+ });
610
+
611
+ // Compute the numeric values for each data element.
612
+ var values = data.map(value);
613
+
614
+ // Convert k into a scale factor from value to angle, using the sum.
615
+ k /= values.reduce(function(p, d) { return p + d; }, 0);
616
+
617
+ // Compute the arcs!
618
+ var arcs = index.map(function(i) {
619
+ return {
620
+ data: data[i],
621
+ value: d = values[i],
622
+ startAngle: a,
623
+ endAngle: a += d * k
624
+ };
625
+ });
626
+
627
+ // Return the arcs in the original data's order.
628
+ return data.map(function(d, i) {
629
+ return arcs[index[i]];
630
+ });
631
+ }
632
+
633
+ /**
634
+ * Specifies the value function *x*, which returns a nonnegative numeric value
635
+ * for each datum. The default value function is `Number`. The value function
636
+ * is passed two arguments: the current datum and the current index.
637
+ */
638
+ pie.value = function(x) {
639
+ if (!arguments.length) return value;
640
+ value = x;
641
+ return pie;
642
+ };
643
+
644
+ /**
645
+ * Specifies a sort comparison operator *x*. The comparator is passed two data
646
+ * elements from the data array, a and b; it returns a negative value if a is
647
+ * less than b, a positive value if a is greater than b, and zero if a equals
648
+ * b.
649
+ */
650
+ pie.sort = function(x) {
651
+ if (!arguments.length) return sort;
652
+ sort = x;
653
+ return pie;
654
+ };
655
+
656
+ /**
657
+ * Specifies the overall start angle of the pie chart. Defaults to 0. The
658
+ * start angle can be specified either as a constant or as a function; in the
659
+ * case of a function, it is evaluated once per array (as opposed to per
660
+ * element).
661
+ */
662
+ pie.startAngle = function(x) {
663
+ if (!arguments.length) return startAngle;
664
+ startAngle = x;
665
+ return pie;
666
+ };
667
+
668
+ /**
669
+ * Specifies the overall end angle of the pie chart. Defaults to 2π. The
670
+ * end angle can be specified either as a constant or as a function; in the
671
+ * case of a function, it is evaluated once per array (as opposed to per
672
+ * element).
673
+ */
674
+ pie.endAngle = function(x) {
675
+ if (!arguments.length) return endAngle;
676
+ endAngle = x;
677
+ return pie;
678
+ };
679
+
680
+ return pie;
681
+ };
682
+ // data is two-dimensional array of x,y; we populate y0
683
+ d3.layout.stack = function() {
684
+ var values = Object,
685
+ order = d3_layout_stackOrders["default"],
686
+ offset = d3_layout_stackOffsets["zero"],
687
+ out = d3_layout_stackOut,
688
+ x = d3_layout_stackX,
689
+ y = d3_layout_stackY;
690
+
691
+ function stack(data, index) {
692
+
693
+ // Convert series to canonical two-dimensional representation.
694
+ var series = data.map(function(d, i) {
695
+ return values.call(stack, d, i);
696
+ });
697
+
698
+ // Convert each series to canonical [[x,y]] representation.
699
+ var points = series.map(function(d, i) {
700
+ return d.map(function(v, i) {
701
+ return [x.call(stack, v, i), y.call(stack, v, i)];
702
+ });
703
+ });
704
+
705
+ // Compute the order of series, and permute them.
706
+ var orders = order.call(stack, points, index);
707
+ series = d3.permute(series, orders);
708
+ points = d3.permute(points, orders);
709
+
710
+ // Compute the baseline…
711
+ var offsets = offset.call(stack, points, index);
712
+
713
+ // And propagate it to other series.
714
+ var n = series.length,
715
+ m = series[0].length,
716
+ i,
717
+ j,
718
+ o;
719
+ for (j = 0; j < m; ++j) {
720
+ out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
721
+ for (i = 1; i < n; ++i) {
722
+ out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
723
+ }
724
+ }
725
+
726
+ return data;
727
+ }
728
+
729
+ stack.values = function(x) {
730
+ if (!arguments.length) return values;
731
+ values = x;
732
+ return stack;
733
+ };
734
+
735
+ stack.order = function(x) {
736
+ if (!arguments.length) return order;
737
+ order = typeof x === "function" ? x : d3_layout_stackOrders[x];
738
+ return stack;
739
+ };
740
+
741
+ stack.offset = function(x) {
742
+ if (!arguments.length) return offset;
743
+ offset = typeof x === "function" ? x : d3_layout_stackOffsets[x];
744
+ return stack;
745
+ };
746
+
747
+ stack.x = function(z) {
748
+ if (!arguments.length) return x;
749
+ x = z;
750
+ return stack;
751
+ };
752
+
753
+ stack.y = function(z) {
754
+ if (!arguments.length) return y;
755
+ y = z;
756
+ return stack;
757
+ };
758
+
759
+ stack.out = function(z) {
760
+ if (!arguments.length) return out;
761
+ out = z;
762
+ return stack;
763
+ };
764
+
765
+ return stack;
766
+ }
767
+
768
+ function d3_layout_stackX(d) {
769
+ return d.x;
770
+ }
771
+
772
+ function d3_layout_stackY(d) {
773
+ return d.y;
774
+ }
775
+
776
+ function d3_layout_stackOut(d, y0, y) {
777
+ d.y0 = y0;
778
+ d.y = y;
779
+ }
780
+
781
+ var d3_layout_stackOrders = {
782
+
783
+ "inside-out": function(data) {
784
+ var n = data.length,
785
+ i,
786
+ j,
787
+ max = data.map(d3_layout_stackMaxIndex),
788
+ sums = data.map(d3_layout_stackReduceSum),
789
+ index = d3.range(n).sort(function(a, b) { return max[a] - max[b]; }),
790
+ top = 0,
791
+ bottom = 0,
792
+ tops = [],
793
+ bottoms = [];
794
+ for (i = 0; i < n; ++i) {
795
+ j = index[i];
796
+ if (top < bottom) {
797
+ top += sums[j];
798
+ tops.push(j);
799
+ } else {
800
+ bottom += sums[j];
801
+ bottoms.push(j);
802
+ }
803
+ }
804
+ return bottoms.reverse().concat(tops);
805
+ },
806
+
807
+ "reverse": function(data) {
808
+ return d3.range(data.length).reverse();
809
+ },
810
+
811
+ "default": function(data) {
812
+ return d3.range(data.length);
813
+ }
814
+
815
+ };
816
+
817
+ var d3_layout_stackOffsets = {
818
+
819
+ "silhouette": function(data) {
820
+ var n = data.length,
821
+ m = data[0].length,
822
+ sums = [],
823
+ max = 0,
824
+ i,
825
+ j,
826
+ o,
827
+ y0 = [];
828
+ for (j = 0; j < m; ++j) {
829
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
830
+ if (o > max) max = o;
831
+ sums.push(o);
832
+ }
833
+ for (j = 0; j < m; ++j) {
834
+ y0[j] = (max - sums[j]) / 2;
835
+ }
836
+ return y0;
837
+ },
838
+
839
+ "wiggle": function(data) {
840
+ var n = data.length,
841
+ x = data[0],
842
+ m = x.length,
843
+ max = 0,
844
+ i,
845
+ j,
846
+ k,
847
+ s1,
848
+ s2,
849
+ s3,
850
+ dx,
851
+ o,
852
+ o0,
853
+ y0 = [];
854
+ y0[0] = o = o0 = 0;
855
+ for (j = 1; j < m; ++j) {
856
+ for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
857
+ for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
858
+ for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
859
+ s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
860
+ }
861
+ s2 += s3 * data[i][j][1];
862
+ }
863
+ y0[j] = o -= s1 ? s2 / s1 * dx : 0;
864
+ if (o < o0) o0 = o;
865
+ }
866
+ for (j = 0; j < m; ++j) y0[j] -= o0;
867
+ return y0;
868
+ },
869
+
870
+ "expand": function(data) {
871
+ var n = data.length,
872
+ m = data[0].length,
873
+ k = 1 / n,
874
+ i,
875
+ j,
876
+ o,
877
+ y0 = [];
878
+ for (j = 0; j < m; ++j) {
879
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
880
+ if (o) for (i = 0; i < n; i++) data[i][j][1] /= o;
881
+ else for (i = 0; i < n; i++) data[i][j][1] = k;
882
+ }
883
+ for (j = 0; j < m; ++j) y0[j] = 0;
884
+ return y0;
885
+ },
886
+
887
+ "zero": function(data) {
888
+ var j = -1,
889
+ m = data[0].length,
890
+ y0 = [];
891
+ while (++j < m) y0[j] = 0;
892
+ return y0;
893
+ }
894
+
895
+ };
896
+
897
+ function d3_layout_stackMaxIndex(array) {
898
+ var i = 1,
899
+ j = 0,
900
+ v = array[0][1],
901
+ k,
902
+ n = array.length;
903
+ for (; i < n; ++i) {
904
+ if ((k = array[i][1]) > v) {
905
+ j = i;
906
+ v = k;
907
+ }
908
+ }
909
+ return j;
910
+ }
911
+
912
+ function d3_layout_stackReduceSum(d) {
913
+ return d.reduce(d3_layout_stackSum, 0);
914
+ }
915
+
916
+ function d3_layout_stackSum(p, d) {
917
+ return p + d[1];
918
+ }
919
+ d3.layout.histogram = function() {
920
+ var frequency = true,
921
+ valuer = Number,
922
+ ranger = d3_layout_histogramRange,
923
+ binner = d3_layout_histogramBinSturges;
924
+
925
+ function histogram(data, i) {
926
+ var bins = [],
927
+ values = data.map(valuer, this),
928
+ range = ranger.call(this, values, i),
929
+ thresholds = binner.call(this, range, values, i),
930
+ bin,
931
+ i = -1,
932
+ n = values.length,
933
+ m = thresholds.length - 1,
934
+ k = frequency ? 1 : 1 / n,
935
+ x;
936
+
937
+ // Initialize the bins.
938
+ while (++i < m) {
939
+ bin = bins[i] = [];
940
+ bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
941
+ bin.y = 0;
942
+ }
943
+
944
+ // Fill the bins, ignoring values outside the range.
945
+ i = -1; while(++i < n) {
946
+ x = values[i];
947
+ if ((x >= range[0]) && (x <= range[1])) {
948
+ bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
949
+ bin.y += k;
950
+ bin.push(data[i]);
951
+ }
952
+ }
953
+
954
+ return bins;
955
+ }
956
+
957
+ // Specifies how to extract a value from the associated data. The default
958
+ // value function is `Number`, which is equivalent to the identity function.
959
+ histogram.value = function(x) {
960
+ if (!arguments.length) return valuer;
961
+ valuer = x;
962
+ return histogram;
963
+ };
964
+
965
+ // Specifies the range of the histogram. Values outside the specified range
966
+ // will be ignored. The argument `x` may be specified either as a two-element
967
+ // array representing the minimum and maximum value of the range, or as a
968
+ // function that returns the range given the array of values and the current
969
+ // index `i`. The default range is the extent (minimum and maximum) of the
970
+ // values.
971
+ histogram.range = function(x) {
972
+ if (!arguments.length) return ranger;
973
+ ranger = d3.functor(x);
974
+ return histogram;
975
+ };
976
+
977
+ // Specifies how to bin values in the histogram. The argument `x` may be
978
+ // specified as a number, in which case the range of values will be split
979
+ // uniformly into the given number of bins. Or, `x` may be an array of
980
+ // threshold values, defining the bins; the specified array must contain the
981
+ // rightmost (upper) value, thus specifying n + 1 values for n bins. Or, `x`
982
+ // may be a function which is evaluated, being passed the range, the array of
983
+ // values, and the current index `i`, returning an array of thresholds. The
984
+ // default bin function will divide the values into uniform bins using
985
+ // Sturges' formula.
986
+ histogram.bins = function(x) {
987
+ if (!arguments.length) return binner;
988
+ binner = typeof x === "number"
989
+ ? function(range) { return d3_layout_histogramBinFixed(range, x); }
990
+ : d3.functor(x);
991
+ return histogram;
992
+ };
993
+
994
+ // Specifies whether the histogram's `y` value is a count (frequency) or a
995
+ // probability (density). The default value is true.
996
+ histogram.frequency = function(x) {
997
+ if (!arguments.length) return frequency;
998
+ frequency = !!x;
999
+ return histogram;
1000
+ };
1001
+
1002
+ return histogram;
1003
+ };
1004
+
1005
+ function d3_layout_histogramBinSturges(range, values) {
1006
+ return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
1007
+ }
1008
+
1009
+ function d3_layout_histogramBinFixed(range, n) {
1010
+ var x = -1,
1011
+ b = +range[0],
1012
+ m = (range[1] - b) / n,
1013
+ f = [];
1014
+ while (++x <= n) f[x] = m * x + b;
1015
+ return f;
1016
+ }
1017
+
1018
+ function d3_layout_histogramRange(values) {
1019
+ return [d3.min(values), d3.max(values)];
1020
+ }
1021
+ d3.layout.hierarchy = function() {
1022
+ var sort = d3_layout_hierarchySort,
1023
+ children = d3_layout_hierarchyChildren,
1024
+ value = d3_layout_hierarchyValue;
1025
+
1026
+ // Recursively compute the node depth and value.
1027
+ // Also converts the data representation into a standard hierarchy structure.
1028
+ function recurse(data, depth, nodes) {
1029
+ var childs = children.call(hierarchy, data, depth),
1030
+ node = d3_layout_hierarchyInline ? data : {data: data};
1031
+ node.depth = depth;
1032
+ nodes.push(node);
1033
+ if (childs) {
1034
+ var i = -1,
1035
+ n = childs.length,
1036
+ c = node.children = [],
1037
+ v = 0,
1038
+ j = depth + 1;
1039
+ while (++i < n) {
1040
+ d = recurse(childs[i], j, nodes);
1041
+ d.parent = node;
1042
+ c.push(d);
1043
+ v += d.value;
1044
+ }
1045
+ if (sort) c.sort(sort);
1046
+ if (value) node.value = v;
1047
+ } else if (value) {
1048
+ node.value = +value.call(hierarchy, data, depth) || 0;
1049
+ }
1050
+ return node;
1051
+ }
1052
+
1053
+ // Recursively re-evaluates the node value.
1054
+ function revalue(node, depth) {
1055
+ var children = node.children,
1056
+ v = 0;
1057
+ if (children) {
1058
+ var i = -1,
1059
+ n = children.length,
1060
+ j = depth + 1;
1061
+ while (++i < n) v += revalue(children[i], j);
1062
+ } else if (value) {
1063
+ v = +value.call(hierarchy, d3_layout_hierarchyInline ? node : node.data, depth) || 0;
1064
+ }
1065
+ if (value) node.value = v;
1066
+ return v;
1067
+ }
1068
+
1069
+ function hierarchy(d) {
1070
+ var nodes = [];
1071
+ recurse(d, 0, nodes);
1072
+ return nodes;
1073
+ }
1074
+
1075
+ hierarchy.sort = function(x) {
1076
+ if (!arguments.length) return sort;
1077
+ sort = x;
1078
+ return hierarchy;
1079
+ };
1080
+
1081
+ hierarchy.children = function(x) {
1082
+ if (!arguments.length) return children;
1083
+ children = x;
1084
+ return hierarchy;
1085
+ };
1086
+
1087
+ hierarchy.value = function(x) {
1088
+ if (!arguments.length) return value;
1089
+ value = x;
1090
+ return hierarchy;
1091
+ };
1092
+
1093
+ // Re-evaluates the `value` property for the specified hierarchy.
1094
+ hierarchy.revalue = function(root) {
1095
+ revalue(root, 0);
1096
+ return root;
1097
+ };
1098
+
1099
+ return hierarchy;
1100
+ };
1101
+
1102
+ // A method assignment helper for hierarchy subclasses.
1103
+ function d3_layout_hierarchyRebind(object, hierarchy) {
1104
+ object.sort = d3.rebind(object, hierarchy.sort);
1105
+ object.children = d3.rebind(object, hierarchy.children);
1106
+ object.links = d3_layout_hierarchyLinks;
1107
+ object.value = d3.rebind(object, hierarchy.value);
1108
+
1109
+ // If the new API is used, enabling inlining.
1110
+ object.nodes = function(d) {
1111
+ d3_layout_hierarchyInline = true;
1112
+ return (object.nodes = object)(d);
1113
+ };
1114
+
1115
+ return object;
1116
+ }
1117
+
1118
+ function d3_layout_hierarchyChildren(d) {
1119
+ return d.children;
1120
+ }
1121
+
1122
+ function d3_layout_hierarchyValue(d) {
1123
+ return d.value;
1124
+ }
1125
+
1126
+ function d3_layout_hierarchySort(a, b) {
1127
+ return b.value - a.value;
1128
+ }
1129
+
1130
+ // Returns an array source+target objects for the specified nodes.
1131
+ function d3_layout_hierarchyLinks(nodes) {
1132
+ return d3.merge(nodes.map(function(parent) {
1133
+ return (parent.children || []).map(function(child) {
1134
+ return {source: parent, target: child};
1135
+ });
1136
+ }));
1137
+ }
1138
+
1139
+ // For backwards-compatibility, don't enable inlining by default.
1140
+ var d3_layout_hierarchyInline = false;
1141
+ d3.layout.pack = function() {
1142
+ var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort),
1143
+ size = [1, 1];
1144
+
1145
+ function pack(d, i) {
1146
+ var nodes = hierarchy.call(this, d, i),
1147
+ root = nodes[0];
1148
+
1149
+ // Recursively compute the layout.
1150
+ root.x = 0;
1151
+ root.y = 0;
1152
+ d3_layout_packTree(root);
1153
+
1154
+ // Scale the layout to fit the requested size.
1155
+ var w = size[0],
1156
+ h = size[1],
1157
+ k = 1 / Math.max(2 * root.r / w, 2 * root.r / h);
1158
+ d3_layout_packTransform(root, w / 2, h / 2, k);
1159
+
1160
+ return nodes;
1161
+ }
1162
+
1163
+ pack.size = function(x) {
1164
+ if (!arguments.length) return size;
1165
+ size = x;
1166
+ return pack;
1167
+ };
1168
+
1169
+ return d3_layout_hierarchyRebind(pack, hierarchy);
1170
+ };
1171
+
1172
+ function d3_layout_packSort(a, b) {
1173
+ return a.value - b.value;
1174
+ }
1175
+
1176
+ function d3_layout_packInsert(a, b) {
1177
+ var c = a._pack_next;
1178
+ a._pack_next = b;
1179
+ b._pack_prev = a;
1180
+ b._pack_next = c;
1181
+ c._pack_prev = b;
1182
+ }
1183
+
1184
+ function d3_layout_packSplice(a, b) {
1185
+ a._pack_next = b;
1186
+ b._pack_prev = a;
1187
+ }
1188
+
1189
+ function d3_layout_packIntersects(a, b) {
1190
+ var dx = b.x - a.x,
1191
+ dy = b.y - a.y,
1192
+ dr = a.r + b.r;
1193
+ return (dr * dr - dx * dx - dy * dy) > .001; // within epsilon
1194
+ }
1195
+
1196
+ function d3_layout_packCircle(nodes) {
1197
+ var xMin = Infinity,
1198
+ xMax = -Infinity,
1199
+ yMin = Infinity,
1200
+ yMax = -Infinity,
1201
+ n = nodes.length,
1202
+ a, b, c, j, k;
1203
+
1204
+ function bound(node) {
1205
+ xMin = Math.min(node.x - node.r, xMin);
1206
+ xMax = Math.max(node.x + node.r, xMax);
1207
+ yMin = Math.min(node.y - node.r, yMin);
1208
+ yMax = Math.max(node.y + node.r, yMax);
1209
+ }
1210
+
1211
+ // Create node links.
1212
+ nodes.forEach(d3_layout_packLink);
1213
+
1214
+ // Create first node.
1215
+ a = nodes[0];
1216
+ a.x = -a.r;
1217
+ a.y = 0;
1218
+ bound(a);
1219
+
1220
+ // Create second node.
1221
+ if (n > 1) {
1222
+ b = nodes[1];
1223
+ b.x = b.r;
1224
+ b.y = 0;
1225
+ bound(b);
1226
+
1227
+ // Create third node and build chain.
1228
+ if (n > 2) {
1229
+ c = nodes[2];
1230
+ d3_layout_packPlace(a, b, c);
1231
+ bound(c);
1232
+ d3_layout_packInsert(a, c);
1233
+ a._pack_prev = c;
1234
+ d3_layout_packInsert(c, b);
1235
+ b = a._pack_next;
1236
+
1237
+ // Now iterate through the rest.
1238
+ for (var i = 3; i < n; i++) {
1239
+ d3_layout_packPlace(a, b, c = nodes[i]);
1240
+
1241
+ // Search for the closest intersection.
1242
+ var isect = 0, s1 = 1, s2 = 1;
1243
+ for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
1244
+ if (d3_layout_packIntersects(j, c)) {
1245
+ isect = 1;
1246
+ break;
1247
+ }
1248
+ }
1249
+ if (isect == 1) {
1250
+ for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
1251
+ if (d3_layout_packIntersects(k, c)) {
1252
+ if (s2 < s1) {
1253
+ isect = -1;
1254
+ j = k;
1255
+ }
1256
+ break;
1257
+ }
1258
+ }
1259
+ }
1260
+
1261
+ // Update node chain.
1262
+ if (isect == 0) {
1263
+ d3_layout_packInsert(a, c);
1264
+ b = c;
1265
+ bound(c);
1266
+ } else if (isect > 0) {
1267
+ d3_layout_packSplice(a, j);
1268
+ b = j;
1269
+ i--;
1270
+ } else { // isect < 0
1271
+ d3_layout_packSplice(j, b);
1272
+ a = j;
1273
+ i--;
1274
+ }
1275
+ }
1276
+ }
1277
+ }
1278
+
1279
+ // Re-center the circles and return the encompassing radius.
1280
+ var cx = (xMin + xMax) / 2,
1281
+ cy = (yMin + yMax) / 2,
1282
+ cr = 0;
1283
+ for (var i = 0; i < n; i++) {
1284
+ var node = nodes[i];
1285
+ node.x -= cx;
1286
+ node.y -= cy;
1287
+ cr = Math.max(cr, node.r + Math.sqrt(node.x * node.x + node.y * node.y));
1288
+ }
1289
+
1290
+ // Remove node links.
1291
+ nodes.forEach(d3_layout_packUnlink);
1292
+
1293
+ return cr;
1294
+ }
1295
+
1296
+ function d3_layout_packLink(node) {
1297
+ node._pack_next = node._pack_prev = node;
1298
+ }
1299
+
1300
+ function d3_layout_packUnlink(node) {
1301
+ delete node._pack_next;
1302
+ delete node._pack_prev;
1303
+ }
1304
+
1305
+ function d3_layout_packTree(node) {
1306
+ var children = node.children;
1307
+ if (children) {
1308
+ children.forEach(d3_layout_packTree);
1309
+ node.r = d3_layout_packCircle(children);
1310
+ } else {
1311
+ node.r = Math.sqrt(node.value);
1312
+ }
1313
+ }
1314
+
1315
+ function d3_layout_packTransform(node, x, y, k) {
1316
+ var children = node.children;
1317
+ node.x = (x += k * node.x);
1318
+ node.y = (y += k * node.y);
1319
+ node.r *= k;
1320
+ if (children) {
1321
+ var i = -1, n = children.length;
1322
+ while (++i < n) d3_layout_packTransform(children[i], x, y, k);
1323
+ }
1324
+ }
1325
+
1326
+ function d3_layout_packPlace(a, b, c) {
1327
+ var da = b.r + c.r,
1328
+ db = a.r + c.r,
1329
+ dx = b.x - a.x,
1330
+ dy = b.y - a.y,
1331
+ dc = Math.sqrt(dx * dx + dy * dy),
1332
+ cos = (db * db + dc * dc - da * da) / (2 * db * dc),
1333
+ theta = Math.acos(cos),
1334
+ x = cos * db,
1335
+ h = Math.sin(theta) * db;
1336
+ dx /= dc;
1337
+ dy /= dc;
1338
+ c.x = a.x + x * dx + h * dy;
1339
+ c.y = a.y + x * dy - h * dx;
1340
+ }
1341
+ // Implements a hierarchical layout using the cluster (or dendogram) algorithm.
1342
+ d3.layout.cluster = function() {
1343
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null),
1344
+ separation = d3_layout_treeSeparation,
1345
+ size = [1, 1]; // width, height
1346
+
1347
+ function cluster(d, i) {
1348
+ var nodes = hierarchy.call(this, d, i),
1349
+ root = nodes[0],
1350
+ previousNode,
1351
+ x = 0,
1352
+ kx,
1353
+ ky;
1354
+
1355
+ // First walk, computing the initial x & y values.
1356
+ d3_layout_treeVisitAfter(root, function(node) {
1357
+ if (node.children) {
1358
+ node.x = d3_layout_clusterX(node.children);
1359
+ node.y = d3_layout_clusterY(node.children);
1360
+ } else {
1361
+ node.x = previousNode ? x += separation(node, previousNode) : 0;
1362
+ node.y = 0;
1363
+ previousNode = node;
1364
+ }
1365
+ });
1366
+
1367
+ // Compute the left-most, right-most, and depth-most nodes for extents.
1368
+ var left = d3_layout_clusterLeft(root),
1369
+ right = d3_layout_clusterRight(root),
1370
+ x0 = left.x - separation(left, right) / 2,
1371
+ x1 = right.x + separation(right, left) / 2;
1372
+
1373
+ // Second walk, normalizing x & y to the desired size.
1374
+ d3_layout_treeVisitAfter(root, function(node) {
1375
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
1376
+ node.y = (1 - node.y / root.y) * size[1];
1377
+ });
1378
+
1379
+ return nodes;
1380
+ }
1381
+
1382
+ cluster.separation = function(x) {
1383
+ if (!arguments.length) return separation;
1384
+ separation = x;
1385
+ return cluster;
1386
+ };
1387
+
1388
+ cluster.size = function(x) {
1389
+ if (!arguments.length) return size;
1390
+ size = x;
1391
+ return cluster;
1392
+ };
1393
+
1394
+ return d3_layout_hierarchyRebind(cluster, hierarchy);
1395
+ };
1396
+
1397
+ function d3_layout_clusterY(children) {
1398
+ return 1 + d3.max(children, function(child) {
1399
+ return child.y;
1400
+ });
1401
+ }
1402
+
1403
+ function d3_layout_clusterX(children) {
1404
+ return children.reduce(function(x, child) {
1405
+ return x + child.x;
1406
+ }, 0) / children.length;
1407
+ }
1408
+
1409
+ function d3_layout_clusterLeft(node) {
1410
+ var children = node.children;
1411
+ return children ? d3_layout_clusterLeft(children[0]) : node;
1412
+ }
1413
+
1414
+ function d3_layout_clusterRight(node) {
1415
+ var children = node.children;
1416
+ return children ? d3_layout_clusterRight(children[children.length - 1]) : node;
1417
+ }
1418
+ // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
1419
+ d3.layout.tree = function() {
1420
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null),
1421
+ separation = d3_layout_treeSeparation,
1422
+ size = [1, 1]; // width, height
1423
+
1424
+ function tree(d, i) {
1425
+ var nodes = hierarchy.call(this, d, i),
1426
+ root = nodes[0];
1427
+
1428
+ function firstWalk(node, previousSibling) {
1429
+ var children = node.children,
1430
+ layout = node._tree;
1431
+ if (children && (n = children.length)) {
1432
+ var n,
1433
+ firstChild = children[0],
1434
+ previousChild,
1435
+ ancestor = firstChild,
1436
+ child,
1437
+ i = -1;
1438
+ while (++i < n) {
1439
+ child = children[i];
1440
+ firstWalk(child, previousChild);
1441
+ ancestor = apportion(child, previousChild, ancestor);
1442
+ previousChild = child;
1443
+ }
1444
+ d3_layout_treeShift(node);
1445
+ var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
1446
+ if (previousSibling) {
1447
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
1448
+ layout.mod = layout.prelim - midpoint;
1449
+ } else {
1450
+ layout.prelim = midpoint;
1451
+ }
1452
+ } else {
1453
+ if (previousSibling) {
1454
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
1455
+ }
1456
+ }
1457
+ }
1458
+
1459
+ function secondWalk(node, x) {
1460
+ node.x = node._tree.prelim + x;
1461
+ var children = node.children;
1462
+ if (children) {
1463
+ var i = -1,
1464
+ n = children.length;
1465
+ x += node._tree.mod;
1466
+ while (++i < n) {
1467
+ secondWalk(children[i], x);
1468
+ }
1469
+ }
1470
+ }
1471
+
1472
+ function apportion(node, previousSibling, ancestor) {
1473
+ if (previousSibling) {
1474
+ var vip = node,
1475
+ vop = node,
1476
+ vim = previousSibling,
1477
+ vom = node.parent.children[0],
1478
+ sip = vip._tree.mod,
1479
+ sop = vop._tree.mod,
1480
+ sim = vim._tree.mod,
1481
+ som = vom._tree.mod,
1482
+ shift;
1483
+ while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
1484
+ vom = d3_layout_treeLeft(vom);
1485
+ vop = d3_layout_treeRight(vop);
1486
+ vop._tree.ancestor = node;
1487
+ shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
1488
+ if (shift > 0) {
1489
+ d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
1490
+ sip += shift;
1491
+ sop += shift;
1492
+ }
1493
+ sim += vim._tree.mod;
1494
+ sip += vip._tree.mod;
1495
+ som += vom._tree.mod;
1496
+ sop += vop._tree.mod;
1497
+ }
1498
+ if (vim && !d3_layout_treeRight(vop)) {
1499
+ vop._tree.thread = vim;
1500
+ vop._tree.mod += sim - sop;
1501
+ }
1502
+ if (vip && !d3_layout_treeLeft(vom)) {
1503
+ vom._tree.thread = vip;
1504
+ vom._tree.mod += sip - som;
1505
+ ancestor = node;
1506
+ }
1507
+ }
1508
+ return ancestor;
1509
+ }
1510
+
1511
+ // Initialize temporary layout variables.
1512
+ d3_layout_treeVisitAfter(root, function(node, previousSibling) {
1513
+ node._tree = {
1514
+ ancestor: node,
1515
+ prelim: 0,
1516
+ mod: 0,
1517
+ change: 0,
1518
+ shift: 0,
1519
+ number: previousSibling ? previousSibling._tree.number + 1 : 0
1520
+ };
1521
+ });
1522
+
1523
+ // Compute the layout using Buchheim et al.'s algorithm.
1524
+ firstWalk(root);
1525
+ secondWalk(root, -root._tree.prelim);
1526
+
1527
+ // Compute the left-most, right-most, and depth-most nodes for extents.
1528
+ var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost),
1529
+ right = d3_layout_treeSearch(root, d3_layout_treeRightmost),
1530
+ deep = d3_layout_treeSearch(root, d3_layout_treeDeepest),
1531
+ x0 = left.x - separation(left, right) / 2,
1532
+ x1 = right.x + separation(right, left) / 2,
1533
+ y1 = deep.depth || 1;
1534
+
1535
+ // Clear temporary layout variables; transform x and y.
1536
+ d3_layout_treeVisitAfter(root, function(node) {
1537
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
1538
+ node.y = node.depth / y1 * size[1];
1539
+ delete node._tree;
1540
+ });
1541
+
1542
+ return nodes;
1543
+ }
1544
+
1545
+ tree.separation = function(x) {
1546
+ if (!arguments.length) return separation;
1547
+ separation = x;
1548
+ return tree;
1549
+ };
1550
+
1551
+ tree.size = function(x) {
1552
+ if (!arguments.length) return size;
1553
+ size = x;
1554
+ return tree;
1555
+ };
1556
+
1557
+ return d3_layout_hierarchyRebind(tree, hierarchy);
1558
+ };
1559
+
1560
+ function d3_layout_treeSeparation(a, b) {
1561
+ return a.parent == b.parent ? 1 : 2;
1562
+ }
1563
+
1564
+ // function d3_layout_treeSeparationRadial(a, b) {
1565
+ // return (a.parent == b.parent ? 1 : 2) / a.depth;
1566
+ // }
1567
+
1568
+ function d3_layout_treeLeft(node) {
1569
+ return node.children ? node.children[0] : node._tree.thread;
1570
+ }
1571
+
1572
+ function d3_layout_treeRight(node) {
1573
+ return node.children ? node.children[node.children.length - 1] : node._tree.thread;
1574
+ }
1575
+
1576
+ function d3_layout_treeSearch(node, compare) {
1577
+ var children = node.children;
1578
+ if (children) {
1579
+ var child,
1580
+ n = children.length,
1581
+ i = -1;
1582
+ while (++i < n) {
1583
+ if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
1584
+ node = child;
1585
+ }
1586
+ }
1587
+ }
1588
+ return node;
1589
+ }
1590
+
1591
+ function d3_layout_treeRightmost(a, b) {
1592
+ return a.x - b.x;
1593
+ }
1594
+
1595
+ function d3_layout_treeLeftmost(a, b) {
1596
+ return b.x - a.x;
1597
+ }
1598
+
1599
+ function d3_layout_treeDeepest(a, b) {
1600
+ return a.depth - b.depth;
1601
+ }
1602
+
1603
+ function d3_layout_treeVisitAfter(node, callback) {
1604
+ function visit(node, previousSibling) {
1605
+ var children = node.children;
1606
+ if (children) {
1607
+ var child,
1608
+ previousChild = null,
1609
+ i = -1,
1610
+ n = children.length;
1611
+ while (++i < n) {
1612
+ child = children[i];
1613
+ visit(child, previousChild);
1614
+ previousChild = child;
1615
+ }
1616
+ }
1617
+ callback(node, previousSibling);
1618
+ }
1619
+ visit(node, null);
1620
+ }
1621
+
1622
+ function d3_layout_treeShift(node) {
1623
+ var shift = 0,
1624
+ change = 0,
1625
+ children = node.children,
1626
+ i = children.length,
1627
+ child;
1628
+ while (--i >= 0) {
1629
+ child = children[i]._tree;
1630
+ child.prelim += shift;
1631
+ child.mod += shift;
1632
+ shift += child.shift + (change += child.change);
1633
+ }
1634
+ }
1635
+
1636
+ function d3_layout_treeMove(ancestor, node, shift) {
1637
+ ancestor = ancestor._tree;
1638
+ node = node._tree;
1639
+ var change = shift / (node.number - ancestor.number);
1640
+ ancestor.change += change;
1641
+ node.change -= change;
1642
+ node.shift += shift;
1643
+ node.prelim += shift;
1644
+ node.mod += shift;
1645
+ }
1646
+
1647
+ function d3_layout_treeAncestor(vim, node, ancestor) {
1648
+ return vim._tree.ancestor.parent == node.parent
1649
+ ? vim._tree.ancestor
1650
+ : ancestor;
1651
+ }
1652
+ // Squarified Treemaps by Mark Bruls, Kees Huizing, and Jarke J. van Wijk
1653
+ // Modified to support a target aspect ratio by Jeff Heer
1654
+ d3.layout.treemap = function() {
1655
+ var hierarchy = d3.layout.hierarchy(),
1656
+ round = Math.round,
1657
+ size = [1, 1], // width, height
1658
+ padding = null,
1659
+ pad = d3_layout_treemapPadNull,
1660
+ sticky = false,
1661
+ stickies,
1662
+ ratio = 0.5 * (1 + Math.sqrt(5)); // golden ratio
1663
+
1664
+ // Compute the area for each child based on value & scale.
1665
+ function scale(children, k) {
1666
+ var i = -1,
1667
+ n = children.length,
1668
+ child,
1669
+ area;
1670
+ while (++i < n) {
1671
+ area = (child = children[i]).value * (k < 0 ? 0 : k);
1672
+ child.area = isNaN(area) || area <= 0 ? 0 : area;
1673
+ }
1674
+ }
1675
+
1676
+ // Recursively arranges the specified node's children into squarified rows.
1677
+ function squarify(node) {
1678
+ if (!node.children) return;
1679
+ var rect = pad(node),
1680
+ row = [],
1681
+ children = node.children.slice(), // copy-on-write
1682
+ child,
1683
+ best = Infinity, // the best row score so far
1684
+ score, // the current row score
1685
+ u = Math.min(rect.dx, rect.dy), // initial orientation
1686
+ n;
1687
+ scale(children, rect.dx * rect.dy / node.value);
1688
+ row.area = 0;
1689
+ while ((n = children.length) > 0) {
1690
+ row.push(child = children[n - 1]);
1691
+ row.area += child.area;
1692
+ if ((score = worst(row, u)) <= best) { // continue with this orientation
1693
+ children.pop();
1694
+ best = score;
1695
+ } else { // abort, and try a different orientation
1696
+ row.area -= row.pop().area;
1697
+ position(row, u, rect, false);
1698
+ u = Math.min(rect.dx, rect.dy);
1699
+ row.length = row.area = 0;
1700
+ best = Infinity;
1701
+ }
1702
+ }
1703
+ if (row.length) {
1704
+ position(row, u, rect, true);
1705
+ row.length = row.area = 0;
1706
+ }
1707
+ node.children.forEach(squarify);
1708
+ }
1709
+
1710
+ // Recursively resizes the specified node's children into existing rows.
1711
+ // Preserves the existing layout!
1712
+ function stickify(node) {
1713
+ if (!node.children) return;
1714
+ var rect = pad(node),
1715
+ children = node.children.slice(), // copy-on-write
1716
+ child,
1717
+ row = [];
1718
+ scale(children, rect.dx * rect.dy / node.value);
1719
+ row.area = 0;
1720
+ while (child = children.pop()) {
1721
+ row.push(child);
1722
+ row.area += child.area;
1723
+ if (child.z != null) {
1724
+ position(row, child.z ? rect.dx : rect.dy, rect, !children.length);
1725
+ row.length = row.area = 0;
1726
+ }
1727
+ }
1728
+ node.children.forEach(stickify);
1729
+ }
1730
+
1731
+ // Computes the score for the specified row, as the worst aspect ratio.
1732
+ function worst(row, u) {
1733
+ var s = row.area,
1734
+ r,
1735
+ rmax = 0,
1736
+ rmin = Infinity,
1737
+ i = -1,
1738
+ n = row.length;
1739
+ while (++i < n) {
1740
+ if (!(r = row[i].area)) continue;
1741
+ if (r < rmin) rmin = r;
1742
+ if (r > rmax) rmax = r;
1743
+ }
1744
+ s *= s;
1745
+ u *= u;
1746
+ return s
1747
+ ? Math.max((u * rmax * ratio) / s, s / (u * rmin * ratio))
1748
+ : Infinity;
1749
+ }
1750
+
1751
+ // Positions the specified row of nodes. Modifies `rect`.
1752
+ function position(row, u, rect, flush) {
1753
+ var i = -1,
1754
+ n = row.length,
1755
+ x = rect.x,
1756
+ y = rect.y,
1757
+ v = u ? round(row.area / u) : 0,
1758
+ o;
1759
+ if (u == rect.dx) { // horizontal subdivision
1760
+ if (flush || v > rect.dy) v = v ? rect.dy : 0; // over+underflow
1761
+ while (++i < n) {
1762
+ o = row[i];
1763
+ o.x = x;
1764
+ o.y = y;
1765
+ o.dy = v;
1766
+ x += o.dx = v ? round(o.area / v) : 0;
1767
+ }
1768
+ o.z = true;
1769
+ o.dx += rect.x + rect.dx - x; // rounding error
1770
+ rect.y += v;
1771
+ rect.dy -= v;
1772
+ } else { // vertical subdivision
1773
+ if (flush || v > rect.dx) v = v ? rect.dx : 0; // over+underflow
1774
+ while (++i < n) {
1775
+ o = row[i];
1776
+ o.x = x;
1777
+ o.y = y;
1778
+ o.dx = v;
1779
+ y += o.dy = v ? round(o.area / v) : 0;
1780
+ }
1781
+ o.z = false;
1782
+ o.dy += rect.y + rect.dy - y; // rounding error
1783
+ rect.x += v;
1784
+ rect.dx -= v;
1785
+ }
1786
+ }
1787
+
1788
+ function treemap(d) {
1789
+ var nodes = stickies || hierarchy(d),
1790
+ root = nodes[0];
1791
+ root.x = 0;
1792
+ root.y = 0;
1793
+ root.dx = size[0];
1794
+ root.dy = size[1];
1795
+ if (stickies) hierarchy.revalue(root);
1796
+ scale([root], root.dx * root.dy / root.value);
1797
+ (stickies ? stickify : squarify)(root);
1798
+ if (sticky) stickies = nodes;
1799
+ return nodes;
1800
+ }
1801
+
1802
+ treemap.size = function(x) {
1803
+ if (!arguments.length) return size;
1804
+ size = x;
1805
+ return treemap;
1806
+ };
1807
+
1808
+ treemap.padding = function(x) {
1809
+ if (!arguments.length) return padding;
1810
+
1811
+ function padFunction(node) {
1812
+ var p = x.call(treemap, node, node.depth);
1813
+ return p == null
1814
+ ? d3_layout_treemapPadNull(node)
1815
+ : d3_layout_treemapPad(node, typeof p === "number" ? [p, p, p, p] : p);
1816
+ }
1817
+
1818
+ function padConstant(node) {
1819
+ return d3_layout_treemapPad(node, x);
1820
+ }
1821
+
1822
+ var type;
1823
+ pad = (padding = x) == null ? d3_layout_treemapPadNull
1824
+ : (type = typeof x) === "function" ? padFunction
1825
+ : type === "number" ? (x = [x, x, x, x], padConstant)
1826
+ : padConstant;
1827
+ return treemap;
1828
+ };
1829
+
1830
+ treemap.round = function(x) {
1831
+ if (!arguments.length) return round != Number;
1832
+ round = x ? Math.round : Number;
1833
+ return treemap;
1834
+ };
1835
+
1836
+ treemap.sticky = function(x) {
1837
+ if (!arguments.length) return sticky;
1838
+ sticky = x;
1839
+ stickies = null;
1840
+ return treemap;
1841
+ };
1842
+
1843
+ treemap.ratio = function(x) {
1844
+ if (!arguments.length) return ratio;
1845
+ ratio = x;
1846
+ return treemap;
1847
+ };
1848
+
1849
+ return d3_layout_hierarchyRebind(treemap, hierarchy);
1850
+ };
1851
+
1852
+ function d3_layout_treemapPadNull(node) {
1853
+ return {x: node.x, y: node.y, dx: node.dx, dy: node.dy};
1854
+ }
1855
+
1856
+ function d3_layout_treemapPad(node, padding) {
1857
+ var x = node.x + padding[3],
1858
+ y = node.y + padding[0],
1859
+ dx = node.dx - padding[1] - padding[3],
1860
+ dy = node.dy - padding[0] - padding[2];
1861
+ if (dx < 0) { x += dx / 2; dx = 0; }
1862
+ if (dy < 0) { y += dy / 2; dy = 0; }
1863
+ return {x: x, y: y, dx: dx, dy: dy};
1864
+ }
1865
+ })();