hyper-mesh 0.4.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 (469) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +11 -0
  5. data/.travis.yml +4 -0
  6. data/CODE_OF_CONDUCT.md +13 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +396 -0
  10. data/Rakefile +6 -0
  11. data/app/controllers/reactive_record/application_controller.rb +4 -0
  12. data/app/controllers/reactive_record/reactive_record_controller.rb +49 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +7 -0
  15. data/codeship.database.yml +18 -0
  16. data/config/routes.rb +7 -0
  17. data/docs/action_cable_quickstart.md +151 -0
  18. data/docs/authorization-policies.md +449 -0
  19. data/docs/client_side_scoping.md +103 -0
  20. data/docs/pusher_quickstart.md +0 -0
  21. data/docs/simple_poller_quickstart.md +121 -0
  22. data/docs/todo-example.md +116 -0
  23. data/docs/words-example.md +65 -0
  24. data/examples/action-cable/.gitignore +21 -0
  25. data/examples/action-cable/Gemfile +58 -0
  26. data/examples/action-cable/Gemfile.lock +247 -0
  27. data/examples/action-cable/README.md +24 -0
  28. data/examples/action-cable/Rakefile +6 -0
  29. data/examples/action-cable/app/assets/config/manifest.js +3 -0
  30. data/examples/action-cable/app/assets/javascripts/application.js +18 -0
  31. data/examples/action-cable/app/assets/stylesheets/application.css +15 -0
  32. data/examples/action-cable/app/controllers/application_controller.rb +3 -0
  33. data/examples/action-cable/app/controllers/test_controller.rb +6 -0
  34. data/examples/action-cable/app/models/models.rb +2 -0
  35. data/examples/action-cable/app/models/public/application_record.rb +3 -0
  36. data/examples/action-cable/app/models/public/word.rb +2 -0
  37. data/examples/action-cable/app/policies/application_policy.rb +6 -0
  38. data/examples/action-cable/app/views/components.rb +17 -0
  39. data/examples/action-cable/app/views/components/app.rb +18 -0
  40. data/examples/action-cable/app/views/layouts/application.html.erb +14 -0
  41. data/examples/action-cable/app/views/layouts/mailer.html.erb +13 -0
  42. data/examples/action-cable/app/views/layouts/mailer.text.erb +1 -0
  43. data/examples/action-cable/bin/bundle +3 -0
  44. data/examples/action-cable/bin/rails +9 -0
  45. data/examples/action-cable/bin/rake +9 -0
  46. data/examples/action-cable/bin/setup +34 -0
  47. data/examples/action-cable/bin/spring +15 -0
  48. data/examples/action-cable/bin/update +29 -0
  49. data/examples/action-cable/config.ru +5 -0
  50. data/examples/action-cable/config/application.rb +30 -0
  51. data/examples/action-cable/config/boot.rb +3 -0
  52. data/examples/action-cable/config/cable.yml +9 -0
  53. data/examples/action-cable/config/database.yml +25 -0
  54. data/examples/action-cable/config/environment.rb +5 -0
  55. data/examples/action-cable/config/environments/development.rb +45 -0
  56. data/examples/action-cable/config/environments/production.rb +86 -0
  57. data/examples/action-cable/config/environments/test.rb +42 -0
  58. data/examples/action-cable/config/initializers/application_controller_renderer.rb +6 -0
  59. data/examples/action-cable/config/initializers/assets.rb +11 -0
  60. data/examples/action-cable/config/initializers/backtrace_silencers.rb +7 -0
  61. data/examples/action-cable/config/initializers/cookies_serializer.rb +5 -0
  62. data/examples/action-cable/config/initializers/filter_parameter_logging.rb +4 -0
  63. data/examples/action-cable/config/initializers/inflections.rb +16 -0
  64. data/examples/action-cable/config/initializers/mime_types.rb +4 -0
  65. data/examples/action-cable/config/initializers/new_framework_defaults.rb +24 -0
  66. data/examples/action-cable/config/initializers/session_store.rb +3 -0
  67. data/examples/action-cable/config/initializers/synchromesh.rb +5 -0
  68. data/examples/action-cable/config/initializers/wrap_parameters.rb +14 -0
  69. data/examples/action-cable/config/locales/en.yml +23 -0
  70. data/examples/action-cable/config/puma.rb +47 -0
  71. data/examples/action-cable/config/routes.rb +5 -0
  72. data/examples/action-cable/config/secrets.yml +22 -0
  73. data/examples/action-cable/config/spring.rb +6 -0
  74. data/examples/action-cable/db/migrate/20160921223808_create_words.rb +9 -0
  75. data/examples/action-cable/db/schema.rb +21 -0
  76. data/examples/action-cable/log/.keep +0 -0
  77. data/examples/action-cable/public/404.html +67 -0
  78. data/examples/action-cable/public/422.html +67 -0
  79. data/examples/action-cable/public/500.html +66 -0
  80. data/examples/action-cable/public/apple-touch-icon-precomposed.png +0 -0
  81. data/examples/action-cable/public/apple-touch-icon.png +0 -0
  82. data/examples/action-cable/public/favicon.ico +0 -0
  83. data/examples/action-cable/public/robots.txt +5 -0
  84. data/examples/action-cable/rails_cache_dir2/C91/480/synchromesh_active_connections +0 -0
  85. data/examples/action-cable/tmp/.keep +0 -0
  86. data/examples/action-cable/vendor/assets/javascripts/.keep +0 -0
  87. data/examples/action-cable/vendor/assets/stylesheets/.keep +0 -0
  88. data/examples/simple-poller/.gitignore +21 -0
  89. data/examples/simple-poller/Gemfile +64 -0
  90. data/examples/simple-poller/Gemfile.lock +272 -0
  91. data/examples/simple-poller/README.md +24 -0
  92. data/examples/simple-poller/Rakefile +6 -0
  93. data/examples/simple-poller/app/assets/config/manifest.js +3 -0
  94. data/examples/simple-poller/app/assets/images/.keep +0 -0
  95. data/examples/simple-poller/app/assets/javascripts/application.js +20 -0
  96. data/examples/simple-poller/app/assets/javascripts/channels/.keep +0 -0
  97. data/examples/simple-poller/app/assets/stylesheets/application.css +15 -0
  98. data/examples/simple-poller/app/channels/application_cable/channel.rb +4 -0
  99. data/examples/simple-poller/app/channels/application_cable/connection.rb +4 -0
  100. data/examples/simple-poller/app/controllers/application_controller.rb +3 -0
  101. data/examples/simple-poller/app/controllers/concerns/.keep +0 -0
  102. data/examples/simple-poller/app/controllers/test_controller.rb +6 -0
  103. data/examples/simple-poller/app/helpers/application_helper.rb +2 -0
  104. data/examples/simple-poller/app/jobs/application_job.rb +2 -0
  105. data/examples/simple-poller/app/mailers/application_mailer.rb +4 -0
  106. data/examples/simple-poller/app/models/concerns/.keep +0 -0
  107. data/examples/simple-poller/app/models/models.rb +2 -0
  108. data/examples/simple-poller/app/models/public/.keep +0 -0
  109. data/examples/simple-poller/app/models/public/application_record.rb +3 -0
  110. data/examples/simple-poller/app/models/public/word.rb +2 -0
  111. data/examples/simple-poller/app/policies/application_policy.rb +5 -0
  112. data/examples/simple-poller/app/views/components.rb +18 -0
  113. data/examples/simple-poller/app/views/components/.keep +0 -0
  114. data/examples/simple-poller/app/views/components/app.rb +40 -0
  115. data/examples/simple-poller/app/views/layouts/application.html.erb +14 -0
  116. data/examples/simple-poller/app/views/layouts/mailer.html.erb +13 -0
  117. data/examples/simple-poller/app/views/layouts/mailer.text.erb +1 -0
  118. data/examples/simple-poller/bin/bundle +3 -0
  119. data/examples/simple-poller/bin/rails +9 -0
  120. data/examples/simple-poller/bin/rake +9 -0
  121. data/examples/simple-poller/bin/setup +34 -0
  122. data/examples/simple-poller/bin/spring +16 -0
  123. data/examples/simple-poller/bin/update +29 -0
  124. data/examples/simple-poller/config.ru +5 -0
  125. data/examples/simple-poller/config/application.rb +20 -0
  126. data/examples/simple-poller/config/boot.rb +3 -0
  127. data/examples/simple-poller/config/cable.yml +9 -0
  128. data/examples/simple-poller/config/database.yml +25 -0
  129. data/examples/simple-poller/config/environment.rb +5 -0
  130. data/examples/simple-poller/config/environments/development.rb +44 -0
  131. data/examples/simple-poller/config/environments/production.rb +86 -0
  132. data/examples/simple-poller/config/environments/test.rb +42 -0
  133. data/examples/simple-poller/config/initializers/application_controller_renderer.rb +6 -0
  134. data/examples/simple-poller/config/initializers/assets.rb +11 -0
  135. data/examples/simple-poller/config/initializers/backtrace_silencers.rb +7 -0
  136. data/examples/simple-poller/config/initializers/cookies_serializer.rb +5 -0
  137. data/examples/simple-poller/config/initializers/filter_parameter_logging.rb +4 -0
  138. data/examples/simple-poller/config/initializers/inflections.rb +16 -0
  139. data/examples/simple-poller/config/initializers/mime_types.rb +4 -0
  140. data/examples/simple-poller/config/initializers/new_framework_defaults.rb +24 -0
  141. data/examples/simple-poller/config/initializers/session_store.rb +3 -0
  142. data/examples/simple-poller/config/initializers/synchromesh.rb +15 -0
  143. data/examples/simple-poller/config/initializers/wrap_parameters.rb +14 -0
  144. data/examples/simple-poller/config/locales/en.yml +23 -0
  145. data/examples/simple-poller/config/puma.rb +47 -0
  146. data/examples/simple-poller/config/routes.rb +5 -0
  147. data/examples/simple-poller/config/secrets.yml +22 -0
  148. data/examples/simple-poller/config/spring.rb +6 -0
  149. data/examples/simple-poller/db/migrate/20161013220135_create_words.rb +9 -0
  150. data/examples/simple-poller/db/schema.rb +21 -0
  151. data/examples/simple-poller/db/seeds.rb +7 -0
  152. data/examples/simple-poller/lib/assets/.keep +0 -0
  153. data/examples/simple-poller/lib/tasks/.keep +0 -0
  154. data/examples/simple-poller/log/.keep +0 -0
  155. data/examples/simple-poller/public/404.html +67 -0
  156. data/examples/simple-poller/public/422.html +67 -0
  157. data/examples/simple-poller/public/500.html +66 -0
  158. data/examples/simple-poller/public/apple-touch-icon-precomposed.png +0 -0
  159. data/examples/simple-poller/public/apple-touch-icon.png +0 -0
  160. data/examples/simple-poller/public/favicon.ico +0 -0
  161. data/examples/simple-poller/public/robots.txt +5 -0
  162. data/examples/simple-poller/test/controllers/.keep +0 -0
  163. data/examples/simple-poller/test/fixtures/.keep +0 -0
  164. data/examples/simple-poller/test/fixtures/files/.keep +0 -0
  165. data/examples/simple-poller/test/fixtures/words.yml +7 -0
  166. data/examples/simple-poller/test/helpers/.keep +0 -0
  167. data/examples/simple-poller/test/integration/.keep +0 -0
  168. data/examples/simple-poller/test/mailers/.keep +0 -0
  169. data/examples/simple-poller/test/models/.keep +0 -0
  170. data/examples/simple-poller/test/models/word_test.rb +7 -0
  171. data/examples/simple-poller/test/test_helper.rb +10 -0
  172. data/examples/simple-poller/tmp/.keep +0 -0
  173. data/examples/simple-poller/vendor/assets/javascripts/.keep +0 -0
  174. data/examples/simple-poller/vendor/assets/stylesheets/.keep +0 -0
  175. data/examples/words/.gitignore +21 -0
  176. data/examples/words/Gemfile +58 -0
  177. data/examples/words/Gemfile.lock +247 -0
  178. data/examples/words/README.md +24 -0
  179. data/examples/words/Rakefile +6 -0
  180. data/examples/words/app/assets/config/manifest.js +3 -0
  181. data/examples/words/app/assets/javascripts/application.js +18 -0
  182. data/examples/words/app/assets/stylesheets/application.css +15 -0
  183. data/examples/words/app/controllers/application_controller.rb +3 -0
  184. data/examples/words/app/controllers/test_controller.rb +6 -0
  185. data/examples/words/app/models/models.rb +2 -0
  186. data/examples/words/app/models/public/application_record.rb +3 -0
  187. data/examples/words/app/models/public/word.rb +10 -0
  188. data/examples/words/app/policies/application_policy.rb +6 -0
  189. data/examples/words/app/views/components.rb +16 -0
  190. data/examples/words/app/views/components/app.rb +31 -0
  191. data/examples/words/app/views/layouts/application.html.erb +14 -0
  192. data/examples/words/app/views/layouts/mailer.html.erb +13 -0
  193. data/examples/words/app/views/layouts/mailer.text.erb +1 -0
  194. data/examples/words/bin/bundle +3 -0
  195. data/examples/words/bin/rails +9 -0
  196. data/examples/words/bin/rake +9 -0
  197. data/examples/words/bin/setup +34 -0
  198. data/examples/words/bin/spring +15 -0
  199. data/examples/words/bin/update +29 -0
  200. data/examples/words/config.ru +5 -0
  201. data/examples/words/config/application.rb +30 -0
  202. data/examples/words/config/boot.rb +3 -0
  203. data/examples/words/config/cable.yml +9 -0
  204. data/examples/words/config/database.yml +25 -0
  205. data/examples/words/config/environment.rb +5 -0
  206. data/examples/words/config/environments/development.rb +45 -0
  207. data/examples/words/config/environments/production.rb +86 -0
  208. data/examples/words/config/environments/test.rb +42 -0
  209. data/examples/words/config/initializers/application_controller_renderer.rb +6 -0
  210. data/examples/words/config/initializers/assets.rb +11 -0
  211. data/examples/words/config/initializers/backtrace_silencers.rb +7 -0
  212. data/examples/words/config/initializers/cookies_serializer.rb +5 -0
  213. data/examples/words/config/initializers/filter_parameter_logging.rb +4 -0
  214. data/examples/words/config/initializers/inflections.rb +16 -0
  215. data/examples/words/config/initializers/mime_types.rb +4 -0
  216. data/examples/words/config/initializers/new_framework_defaults.rb +24 -0
  217. data/examples/words/config/initializers/session_store.rb +3 -0
  218. data/examples/words/config/initializers/synchromesh.rb +5 -0
  219. data/examples/words/config/initializers/wrap_parameters.rb +14 -0
  220. data/examples/words/config/locales/en.yml +23 -0
  221. data/examples/words/config/puma.rb +47 -0
  222. data/examples/words/config/routes.rb +5 -0
  223. data/examples/words/config/secrets.yml +22 -0
  224. data/examples/words/config/spring.rb +6 -0
  225. data/examples/words/db/migrate/20160921223808_create_words.rb +9 -0
  226. data/examples/words/db/schema.rb +28 -0
  227. data/examples/words/log/.keep +0 -0
  228. data/examples/words/public/404.html +67 -0
  229. data/examples/words/public/422.html +67 -0
  230. data/examples/words/public/500.html +66 -0
  231. data/examples/words/public/apple-touch-icon-precomposed.png +0 -0
  232. data/examples/words/public/apple-touch-icon.png +0 -0
  233. data/examples/words/public/favicon.ico +0 -0
  234. data/examples/words/public/robots.txt +5 -0
  235. data/examples/words/tmp/.keep +0 -0
  236. data/examples/words/vendor/assets/javascripts/.keep +0 -0
  237. data/examples/words/vendor/assets/stylesheets/.keep +0 -0
  238. data/hyper-mesh.gemspec +82 -0
  239. data/lib/active_record_base.rb +152 -0
  240. data/lib/enumerable/pluck.rb +6 -0
  241. data/lib/hyper-mesh.rb +62 -0
  242. data/lib/hypermesh/version.rb +3 -0
  243. data/lib/opal/equality_patches.rb +15 -0
  244. data/lib/opal/parse_patch.rb +14 -0
  245. data/lib/opal/set_patches.rb +8 -0
  246. data/lib/reactive_record/active_record/aggregations.rb +69 -0
  247. data/lib/reactive_record/active_record/associations.rb +111 -0
  248. data/lib/reactive_record/active_record/base.rb +9 -0
  249. data/lib/reactive_record/active_record/class_methods.rb +177 -0
  250. data/lib/reactive_record/active_record/error.rb +26 -0
  251. data/lib/reactive_record/active_record/instance_methods.rb +129 -0
  252. data/lib/reactive_record/active_record/public_columns_hash.rb +19 -0
  253. data/lib/reactive_record/active_record/reactive_record/base.rb +520 -0
  254. data/lib/reactive_record/active_record/reactive_record/collection.rb +517 -0
  255. data/lib/reactive_record/active_record/reactive_record/column_types.rb +67 -0
  256. data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +218 -0
  257. data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +532 -0
  258. data/lib/reactive_record/active_record/reactive_record/reactive_set_relationship_helpers.rb +189 -0
  259. data/lib/reactive_record/active_record/reactive_record/scoped_collection.rb +62 -0
  260. data/lib/reactive_record/active_record/reactive_record/unscoped_collection.rb +16 -0
  261. data/lib/reactive_record/active_record/reactive_record/while_loading.rb +299 -0
  262. data/lib/reactive_record/engine.rb +13 -0
  263. data/lib/reactive_record/interval.rb +190 -0
  264. data/lib/reactive_record/permissions.rb +102 -0
  265. data/lib/reactive_record/pry.rb +13 -0
  266. data/lib/reactive_record/reactive_scope.rb +18 -0
  267. data/lib/reactive_record/scope_description.rb +108 -0
  268. data/lib/reactive_record/serializers.rb +7 -0
  269. data/lib/reactive_record/server_data_cache.rb +347 -0
  270. data/lib/reactive_record/version.rb +3 -0
  271. data/lib/sources/hyper-mesh/pusher.js +98 -0
  272. data/lib/synchromesh/action_cable.rb +39 -0
  273. data/lib/synchromesh/client_drivers.rb +357 -0
  274. data/lib/synchromesh/configuration.rb +40 -0
  275. data/lib/synchromesh/connection.rb +144 -0
  276. data/lib/synchromesh/policy.rb +504 -0
  277. data/lib/synchromesh/reactive_record/permission_patches.rb +43 -0
  278. data/lib/synchromesh/synchromesh.rb +155 -0
  279. data/lib/synchromesh/synchromesh_controller.rb +154 -0
  280. data/logo.jpg +0 -0
  281. data/path_release_steps.md +0 -0
  282. data/reactive_record_test_app/Gemfile +15 -0
  283. data/reactive_record_test_app/Gemfile.lock +209 -0
  284. data/reactive_record_test_app/README.rdoc +261 -0
  285. data/reactive_record_test_app/Rakefile +7 -0
  286. data/reactive_record_test_app/app/assets/javascripts/application.rb +5 -0
  287. data/reactive_record_test_app/app/assets/javascripts/components/another_component.rb +24 -0
  288. data/reactive_record_test_app/app/assets/javascripts/components/empty_component.rb +6 -0
  289. data/reactive_record_test_app/app/assets/javascripts/components/todo_item_component.js.rb +16 -0
  290. data/reactive_record_test_app/app/assets/javascripts/components/todos_component.js.rb +42 -0
  291. data/reactive_record_test_app/app/assets/javascripts/components/todos_main_component.rb +49 -0
  292. data/reactive_record_test_app/app/assets/javascripts/react_js_test_only.js +21618 -0
  293. data/reactive_record_test_app/app/assets/javascripts/reactive_record_config.js +2 -0
  294. data/reactive_record_test_app/app/assets/javascripts/spec/reactive_record_xspec.js.rb +42 -0
  295. data/reactive_record_test_app/app/assets/stylesheets/application.css +13 -0
  296. data/reactive_record_test_app/app/controllers/application_controller.rb +8 -0
  297. data/reactive_record_test_app/app/controllers/home_controller.rb +7 -0
  298. data/reactive_record_test_app/app/controllers/test_controller.rb +7 -0
  299. data/reactive_record_test_app/app/helpers/application_helper.rb +2 -0
  300. data/reactive_record_test_app/app/mailers/.gitkeep +0 -0
  301. data/reactive_record_test_app/app/models/.gitkeep +0 -0
  302. data/reactive_record_test_app/app/policies/application_policy.rb +5 -0
  303. data/reactive_record_test_app/app/views/components.rb +4 -0
  304. data/reactive_record_test_app/app/views/components/test.rb +18 -0
  305. data/reactive_record_test_app/app/views/home/index.html.erb +1 -0
  306. data/reactive_record_test_app/app/views/layouts/application.html.erb +17 -0
  307. data/reactive_record_test_app/app/views/models.rb +1 -0
  308. data/reactive_record_test_app/app/views/models/address.rb +13 -0
  309. data/reactive_record_test_app/app/views/models/comment.rb +19 -0
  310. data/reactive_record_test_app/app/views/models/todo_item.rb +36 -0
  311. data/reactive_record_test_app/app/views/models/user.rb +78 -0
  312. data/reactive_record_test_app/config.ru +33 -0
  313. data/reactive_record_test_app/config/application.rb +73 -0
  314. data/reactive_record_test_app/config/boot.rb +10 -0
  315. data/reactive_record_test_app/config/database.yml +25 -0
  316. data/reactive_record_test_app/config/environment.rb +5 -0
  317. data/reactive_record_test_app/config/environments/development.rb +43 -0
  318. data/reactive_record_test_app/config/environments/production.rb +70 -0
  319. data/reactive_record_test_app/config/environments/test.rb +41 -0
  320. data/reactive_record_test_app/config/initializers/backtrace_silencers.rb +7 -0
  321. data/reactive_record_test_app/config/initializers/inflections.rb +15 -0
  322. data/reactive_record_test_app/config/initializers/mime_types.rb +5 -0
  323. data/reactive_record_test_app/config/initializers/secret_token.rb +7 -0
  324. data/reactive_record_test_app/config/initializers/session_store.rb +8 -0
  325. data/reactive_record_test_app/config/initializers/wrap_parameters.rb +14 -0
  326. data/reactive_record_test_app/config/locales/en.yml +5 -0
  327. data/reactive_record_test_app/config/routes.rb +7 -0
  328. data/reactive_record_test_app/db/migrate/20150617002932_create_todo_items.rb +11 -0
  329. data/reactive_record_test_app/db/migrate/20150617134028_create_users.rb +14 -0
  330. data/reactive_record_test_app/db/migrate/20150729195556_add_address_to_user.rb +20 -0
  331. data/reactive_record_test_app/db/migrate/20150826142045_create_comments.rb +10 -0
  332. data/reactive_record_test_app/db/migrate/20150828172008_add_single_comment_to_todo_item.rb +5 -0
  333. data/reactive_record_test_app/db/migrate/20150908184118_add_address_id_to_user.rb +5 -0
  334. data/reactive_record_test_app/db/migrate/20150917220236_add_second_address_to_user.rb +10 -0
  335. data/reactive_record_test_app/db/migrate/20151009000111_add_test_data_attributes_to_user.rb +6 -0
  336. data/reactive_record_test_app/db/migrate/20160129182544_add_test_enum_to_user.rb +5 -0
  337. data/reactive_record_test_app/db/schema.rb +63 -0
  338. data/reactive_record_test_app/db/seeds.rb +60 -0
  339. data/reactive_record_test_app/public/404.html +26 -0
  340. data/reactive_record_test_app/public/422.html +26 -0
  341. data/reactive_record_test_app/public/500.html +25 -0
  342. data/reactive_record_test_app/public/favicon.ico +0 -0
  343. data/reactive_record_test_app/script/rails +6 -0
  344. data/reactive_record_test_app/spec-opal/active-record/aggregations_spec.rb +41 -0
  345. data/reactive_record_test_app/spec-opal/active-record/associations_spec.rb +75 -0
  346. data/reactive_record_test_app/spec-opal/active-record/base_spec.rb +126 -0
  347. data/reactive_record_test_app/spec-opal/active-record/dummy_value_spec.rb +27 -0
  348. data/reactive_record_test_app/spec-opal/active-record/edge_cases_spec.rb +116 -0
  349. data/reactive_record_test_app/spec-opal/active-record/enum_spec.rb +43 -0
  350. data/reactive_record_test_app/spec-opal/active-record/instance_methods_spec.rb +53 -0
  351. data/reactive_record_test_app/spec-opal/active-record/non_ar_aggregations_spec.rb +74 -0
  352. data/reactive_record_test_app/spec-opal/active-record/permissions_spec.rb +170 -0
  353. data/reactive_record_test_app/spec-opal/active-record/prerendering_spec.rb +49 -0
  354. data/reactive_record_test_app/spec-opal/active-record/reactive_record_load_spec.rb +23 -0
  355. data/reactive_record_test_app/spec-opal/active-record/rendering_spec.rb +221 -0
  356. data/reactive_record_test_app/spec-opal/active-record/save_spec.rb +125 -0
  357. data/reactive_record_test_app/spec-opal/active-record/scope_spec.rb +85 -0
  358. data/reactive_record_test_app/spec-opal/active-record/update_aggregations_spec.rb +76 -0
  359. data/reactive_record_test_app/spec-opal/active-record/update_attributes_spec.rb +186 -0
  360. data/reactive_record_test_app/spec-opal/active-record/virtual_methods_spec.rb +71 -0
  361. data/reactive_record_test_app/spec-opal/index.html.erb +11 -0
  362. data/reactive_record_test_app/spec-opal/spec_helper.js.rb +268 -0
  363. data/reactive_record_test_app/spec-opal/vendor/es5-shim.min.js +6 -0
  364. data/reactive_record_test_app/spec_dont_run/README.md +26 -0
  365. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzmany_to_many_spec_moved_to_main_suite.rb +30 -0
  366. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzrevert_record_spec_moved.rb +78 -0
  367. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzupdate_associations_spec_moved.rb +142 -0
  368. data/reactive_record_test_app/spec_dont_run/moved_to_main_spec_dir/zzzupdate_scopes_movedspec.rb +48 -0
  369. data/remote.md +115 -0
  370. data/spec/bin/firebug-2.0.13-fx.xpi +0 -0
  371. data/spec/component_helpers_xspec.rb +49 -0
  372. data/spec/factories/child_model.rb +5 -0
  373. data/spec/factories/comment.rb +5 -0
  374. data/spec/factories/test_models.rb +5 -0
  375. data/spec/factories/todo.rb +5 -0
  376. data/spec/factories/user.rb +5 -0
  377. data/spec/reactive_record/edge_cases_spec.rb +31 -0
  378. data/spec/reactive_record/factory.rb +62 -0
  379. data/spec/reactive_record/many_to_many_spec.rb +50 -0
  380. data/spec/reactive_record/play.rb +64 -0
  381. data/spec/reactive_record/pry_rescue_xspec.rb +48 -0
  382. data/spec/reactive_record/revert_spec.rb +112 -0
  383. data/spec/reactive_record/update_associations_spec.rb +189 -0
  384. data/spec/reactive_record/update_scopes_spec.rb +53 -0
  385. data/spec/spec_helper.rb +366 -0
  386. data/spec/support/component_helpers.rb +351 -0
  387. data/spec/synchromesh/column_types/column_type_spec.rb +302 -0
  388. data/spec/synchromesh/connection_spec.rb +144 -0
  389. data/spec/synchromesh/crud_access_regulation/broadcast_controls_access_spec.rb +105 -0
  390. data/spec/synchromesh/crud_access_regulation/model_policies_spec.rb +131 -0
  391. data/spec/synchromesh/examples/dictionary.rb +239 -0
  392. data/spec/synchromesh/examples/dictionary_with_client_scopes.rb +196 -0
  393. data/spec/synchromesh/examples/random_examples.rb +100 -0
  394. data/spec/synchromesh/examples/scoped_todos_spec.rb +167 -0
  395. data/spec/synchromesh/integration/authorization_spec.rb +111 -0
  396. data/spec/synchromesh/integration/default_scope_spec.rb +121 -0
  397. data/spec/synchromesh/integration/has_many_through_spec.rb +173 -0
  398. data/spec/synchromesh/integration/relationships_spec.rb +263 -0
  399. data/spec/synchromesh/integration/scope_spec.rb +553 -0
  400. data/spec/synchromesh/integration/synchromesh_spec.rb +80 -0
  401. data/spec/synchromesh/integration/test_components.rb +18 -0
  402. data/spec/synchromesh/integration/transports_spec.rb +308 -0
  403. data/spec/synchromesh/policies/auto_connect_spec.rb +60 -0
  404. data/spec/synchromesh/policies/auto_loader_spec.rb +34 -0
  405. data/spec/synchromesh/policies/policy_methods_spec.rb +85 -0
  406. data/spec/synchromesh/policies/regulate_all_broadcasts_spec.rb +315 -0
  407. data/spec/synchromesh/policies/regulate_broadcast_spec.rb +370 -0
  408. data/spec/synchromesh/policies/regulate_class_connection_spec.rb +50 -0
  409. data/spec/synchromesh/policies/regulate_instance_connection_spec.rb +66 -0
  410. data/spec/test_app/Gemfile +61 -0
  411. data/spec/test_app/Gemfile.lock +253 -0
  412. data/spec/test_app/Rakefile +6 -0
  413. data/spec/test_app/app/assets/javascripts/application.js +6 -0
  414. data/spec/test_app/app/assets/stylesheets/application.css +15 -0
  415. data/spec/test_app/app/controllers/application_controller.rb +13 -0
  416. data/spec/test_app/app/controllers/test_controller.rb +5 -0
  417. data/spec/test_app/app/models/_react_public_models.rb +2 -0
  418. data/spec/test_app/app/models/public/address.rb +13 -0
  419. data/spec/test_app/app/models/public/child_model.rb +3 -0
  420. data/spec/test_app/app/models/public/comment.rb +25 -0
  421. data/spec/test_app/app/models/public/test_model.rb +5 -0
  422. data/spec/test_app/app/models/public/todo.rb +6 -0
  423. data/spec/test_app/app/models/public/todo_item.rb +36 -0
  424. data/spec/test_app/app/models/public/user.rb +88 -0
  425. data/spec/test_app/app/policies/auto_loader_test_classa_policy.rb +3 -0
  426. data/spec/test_app/app/policies/auto_loader_test_classb_policy.rb +3 -0
  427. data/spec/test_app/app/policies/auto_loader_test_classc_policy.rb +3 -0
  428. data/spec/test_app/app/policies/auto_loader_test_classd_policy.rb +3 -0
  429. data/spec/test_app/app/views/components.rb +14 -0
  430. data/spec/test_app/app/views/components/show.rb +5 -0
  431. data/spec/test_app/app/views/layouts/application.html.erb +14 -0
  432. data/spec/test_app/bin/bundle +3 -0
  433. data/spec/test_app/bin/rails +4 -0
  434. data/spec/test_app/bin/rake +4 -0
  435. data/spec/test_app/bin/setup +29 -0
  436. data/spec/test_app/config.ru +4 -0
  437. data/spec/test_app/config/application.rb +42 -0
  438. data/spec/test_app/config/boot.rb +6 -0
  439. data/spec/test_app/config/cable.yml +10 -0
  440. data/spec/test_app/config/database.yml +47 -0
  441. data/spec/test_app/config/environment.rb +5 -0
  442. data/spec/test_app/config/environments/development.rb +41 -0
  443. data/spec/test_app/config/environments/production.rb +79 -0
  444. data/spec/test_app/config/environments/test.rb +42 -0
  445. data/spec/test_app/config/initializers/assets.rb +11 -0
  446. data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
  447. data/spec/test_app/config/initializers/cookies_serializer.rb +3 -0
  448. data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
  449. data/spec/test_app/config/initializers/inflections.rb +16 -0
  450. data/spec/test_app/config/initializers/mime_types.rb +4 -0
  451. data/spec/test_app/config/initializers/session_store.rb +3 -0
  452. data/spec/test_app/config/initializers/synchromesh.rb +11 -0
  453. data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
  454. data/spec/test_app/config/locales/en.yml +23 -0
  455. data/spec/test_app/config/routes.rb +61 -0
  456. data/spec/test_app/config/secrets.yml +22 -0
  457. data/spec/test_app/db/development.sqlite3 +0 -0
  458. data/spec/test_app/db/migrate/20160731182106_create_test_models.rb +75 -0
  459. data/spec/test_app/db/schema.rb +88 -0
  460. data/spec/test_app/db/seeds.rb +7 -0
  461. data/spec/test_app/lib/assets/.keep +0 -0
  462. data/spec/test_app/log/.keep +0 -0
  463. data/spec/test_app/public/404.html +67 -0
  464. data/spec/test_app/public/422.html +67 -0
  465. data/spec/test_app/public/500.html +66 -0
  466. data/spec/test_app/public/favicon.ico +0 -0
  467. data/spec/vendor/es5-shim.min.js +6 -0
  468. data/terminal.md +66 -0
  469. metadata +1175 -0
@@ -0,0 +1,7 @@
1
+ ActiveRecord::Base.send(:define_method, :react_serializer) do
2
+ serializable_hash.merge(ReactiveRecord::Base.get_type_hash(self))
3
+ end
4
+
5
+ ActiveRecord::Relation.send(:define_method, :react_serializer) do
6
+ all.to_a.react_serializer
7
+ end
@@ -0,0 +1,347 @@
1
+ module ReactiveRecord
2
+
3
+ # the point is to collect up a all records needed, with whatever attributes were required + primary key, and inheritance column
4
+ # or get all scope arrays, with the record ids
5
+
6
+ # the incoming vector includes the terminal method
7
+
8
+ # output is a hash tree of the form
9
+ # tree ::= {method => tree | [value]} | method's value is either a nested tree or a single value which is wrapped in array
10
+ # {:id => primary_key_id_value} | if its the id method we leave the array off because we know it must be an int
11
+ # {integer => tree} for collections, each item retrieved will be represented by its id
12
+ #
13
+ # example
14
+ # {
15
+ # "User" => {
16
+ # ["find", 12] => {
17
+ # :id => 12
18
+ # "email" => ["mitch@catprint.com"]
19
+ # "todos" => {
20
+ # "active" => {
21
+ # 123 =>
22
+ # {
23
+ # id: 123,
24
+ # title: ["get fetch_records_from_db done"]
25
+ # },
26
+ # 119 =>
27
+ # {
28
+ # id: 119
29
+ # title: ["go for a swim"]
30
+ # }
31
+ # ]
32
+ # }
33
+ # }
34
+ # }
35
+ # }
36
+ # }
37
+ # }
38
+
39
+ # To build this tree we first fill values for each individual vector, saving all the intermediate data
40
+ # when all these are built we build the above hash structure
41
+
42
+ # basic
43
+ # [Todo, [find, 123], title]
44
+ # -> [[Todo, [find, 123], title], "get fetch_records_from_db done", 123]
45
+
46
+ # [User, [find_by_email, "mitch@catprint.com"], first_name]
47
+ # -> [[User, [find_by_email, "mitch@catprint.com"], first_name], "Mitch", 12]
48
+
49
+ # misses
50
+ # [User, [find_by_email, "foobar@catprint.com"], first_name]
51
+ # nothing is found so nothing is downloaded
52
+ # prerendering may do this
53
+ # [User, [find_by_email, "foobar@catprint.com"]]
54
+ # which will return a cache object whose id is nil, and value is nil
55
+
56
+ # scoped collection
57
+ # [User, [find, 12], todos, active, *, title]
58
+ # -> [[User, [find, 12], todos, active, *, title], "get fetch_records_from_db done", 12, 123]
59
+ # -> [[User, [find, 12], todos, active, *, title], "go for a swim", 12, 119]
60
+
61
+ # collection with nested belongs_to
62
+ # [User, [find, 12], todos, *, team]
63
+ # -> [[User, [find, 12], todos, *, team, name], "developers", 12, 123, 252]
64
+ # [[User, [find, 12], todos, *, team, name], nil, 12, 119] <- no team defined for todo<119> so list ends early
65
+
66
+ # collections that are empty will deliver nothing
67
+ # [User, [find, 13], todos, *, team, name] # no todos for user 13
68
+ # evaluation will get this far: [[User, [find, 13], todos], nil, 13]
69
+ # nothing will match [User, [find, 13], todos, team, name] so nothing will be downloaded
70
+
71
+
72
+ # aggregate
73
+ # [User, [find, 12], address, zip_code]
74
+ # -> [[User, [find, 12], address, zip_code]], "14622", 12] <- note parent id is returned
75
+
76
+ # aggregate with a belongs_to
77
+ # [User, [find, 12], address, country, country_code]
78
+ # -> [[User, [find, 12], address, country, country_code], "US", 12, 342]
79
+
80
+ # collection * (for iterators etc)
81
+ # [User, [find, 12], todos, overdue, *all]
82
+ # -> [[User, [find, 12], todos, active, *all], [119, 123], 12]
83
+
84
+ # [Todo, [find, 119], owner, todos, active, *all]
85
+ # -> [[Todo, [find, 119], owner, todos, active, *all], [119, 123], 119, 12]
86
+
87
+
88
+ class ServerDataCache
89
+
90
+ def initialize(acting_user, preloaded_records)
91
+ @acting_user = acting_user
92
+ @cache = []
93
+ @requested_cache_items = []
94
+ @preloaded_records = preloaded_records
95
+ end
96
+
97
+ if RUBY_ENGINE != 'opal'
98
+
99
+ def [](*vector)
100
+ root = CacheItem.new(@cache, @acting_user, vector[0], @preloaded_records)
101
+ vector[1..-1].inject(root) { |cache_item, method| cache_item.apply_method method if cache_item }
102
+ vector[0] = vector[0].constantize
103
+ new_items = @cache.select { | cache_item | cache_item.root == root }
104
+ @requested_cache_items += new_items
105
+ new_items.last.value if new_items.last
106
+ end
107
+
108
+ def self.[](models, associations, vectors, acting_user)
109
+ result = nil
110
+ ActiveRecord::Base.transaction do
111
+ cache = new(acting_user, ReactiveRecord::Base.save_records(models, associations, acting_user, false, false))
112
+ vectors.each { |vector| cache[*vector] }
113
+ result = cache.as_json
114
+ raise ActiveRecord::Rollback
115
+ end
116
+ result
117
+ end
118
+
119
+ def clear_requests
120
+ @requested_cache_items = []
121
+ end
122
+
123
+ def as_json
124
+ @requested_cache_items.inject({}) do | hash, cache_item|
125
+ hash.deep_merge! cache_item.as_hash
126
+ end
127
+ end
128
+
129
+ def select(&block); @cache.select &block; end
130
+
131
+ def detect(&block); @cache.detect &block; end
132
+
133
+ def inject(initial, &block); @cache.inject(initial) &block; end
134
+
135
+ class CacheItem
136
+
137
+ attr_reader :vector
138
+ attr_reader :absolute_vector
139
+ attr_reader :record_chain
140
+ attr_reader :root
141
+ attr_reader :acting_user
142
+
143
+ def value
144
+ @ar_object
145
+ end
146
+
147
+ def method
148
+ vector.last
149
+ end
150
+
151
+ def self.new(db_cache, acting_user, klass, preloaded_records)
152
+ klass_constant = klass.constantize
153
+ if existing = db_cache.detect { |cached_item| cached_item.vector == [klass_constant] }
154
+ return existing
155
+ end
156
+ super
157
+ end
158
+
159
+ def initialize(db_cache, acting_user, klass, preloaded_records)
160
+ klass = klass.constantize
161
+ @db_cache = db_cache
162
+ @acting_user = acting_user
163
+ @vector = @absolute_vector = [klass]
164
+ @ar_object = klass
165
+ @record_chain = []
166
+ @parent = nil
167
+ @root = self
168
+ @preloaded_records = preloaded_records
169
+ db_cache << self
170
+ end
171
+
172
+ def apply_method_to_cache(method)
173
+ @db_cache.inject(nil) do | representative, cache_item |
174
+ if cache_item.vector == vector
175
+ if @ar_object.class < ActiveRecord::Base and @ar_object.attributes.has_key?(method)
176
+ @ar_object.check_permission_with_acting_user(acting_user, :view_permitted?, method)
177
+ end
178
+ if method == "*"
179
+ cache_item.apply_star || representative
180
+ elsif method == "*all"
181
+ cache_item.build_new_cache_item(cache_item.value.collect { |record| record.id }, method, method)
182
+ elsif method == "*count"
183
+ cache_item.build_new_cache_item(cache_item.value.count, method, method)
184
+ elsif preloaded_value = @preloaded_records[cache_item.absolute_vector + [method]]
185
+ cache_item.build_new_cache_item(preloaded_value, method, method)
186
+ elsif aggregation = cache_item.aggregation?(method)
187
+ cache_item.build_new_cache_item(aggregation.mapping.collect { |attribute, accessor| cache_item.value[attribute] }, method, method)
188
+ else
189
+ begin
190
+ cache_item.build_new_cache_item(cache_item.value.send(*method), method, method)
191
+ rescue Exception => e
192
+ if cache_item.value and cache_item.value != []
193
+ ReactiveRecord::Pry::rescued(e)
194
+ raise e, "ReactiveRecord exception caught when applying #{method} to db object #{cache_item.value}: #{e}", e.backtrace
195
+ else
196
+ representative
197
+ end
198
+ end
199
+ end
200
+ else
201
+ representative
202
+ end
203
+ end
204
+ end
205
+
206
+ def aggregation?(method)
207
+ if method.is_a?(String) && value.class.respond_to?(:reflect_on_aggregation)
208
+ aggregation = value.class.reflect_on_aggregation(method.to_sym)
209
+ if aggregation && !(aggregation.klass < ActiveRecord::Base) && value.send(method)
210
+ aggregation
211
+ end
212
+ end
213
+ end
214
+
215
+ def apply_star
216
+ if value && value.length > 0
217
+ i = -1
218
+ value.inject(nil) do | representative, ar_object |
219
+ i += 1
220
+ if preloaded_value = @preloaded_records[absolute_vector + ["*#{i}"]]
221
+ build_new_cache_item(preloaded_value, "*", "*#{i}")
222
+ else
223
+ build_new_cache_item(ar_object, "*", "*#{i}")
224
+ end
225
+ end
226
+ else
227
+ build_new_cache_item([], "*", "*")
228
+ end
229
+ end
230
+
231
+ def build_new_cache_item(new_ar_object, method, absolute_method)
232
+ new_parent = self
233
+ self.clone.instance_eval do
234
+ @vector = @vector + [method] # don't push it on since you need a new vector!
235
+ @absolute_vector = @absolute_vector + [absolute_method]
236
+ @ar_object = new_ar_object
237
+ @db_cache << self
238
+ @parent = new_parent
239
+ @root = new_parent.root
240
+ self
241
+ end
242
+ end
243
+
244
+ def apply_method(method)
245
+ if method.is_a? Array and method.first == "find_by_id"
246
+ method[0] = "find"
247
+ elsif method.is_a? String and method =~ /^\*[0-9]+$/
248
+ method = "*"
249
+ end
250
+ new_vector = vector + [method]
251
+ @db_cache.detect { |cached_item| cached_item.vector == new_vector} || apply_method_to_cache(method)
252
+ end
253
+
254
+ def jsonize(method)
255
+ # sadly standard json converts {[:foo, nil] => 123} to {"['foo', nil]": 123}
256
+ # luckily [:foo, nil] does convert correctly
257
+ # so we check the methods and force proper conversion
258
+ method.is_a?(Array) ? method.to_json : method
259
+ end
260
+
261
+ def as_hash(children = nil)
262
+ unless children
263
+ return {} if @ar_object.is_a?(Class) and (@ar_object < ActiveRecord::Base)
264
+ children = [@ar_object.is_a?(BigDecimal) ? @ar_object.to_f : @ar_object]
265
+ end
266
+ if @parent
267
+ if method == "*"
268
+ if @ar_object.is_a? Array # this happens when a scope is empty there is test case, but
269
+ @parent.as_hash({}) # does it work for all edge cases?
270
+ else
271
+ @parent.as_hash({@ar_object.id => children})
272
+ end
273
+ elsif @ar_object.class < ActiveRecord::Base and children.is_a? Hash
274
+ @parent.as_hash({jsonize(method) => children.merge({
275
+ :id => (method.is_a?(Array) && method.first == "new") ? [nil] : [@ar_object.id],
276
+ @ar_object.class.inheritance_column => [@ar_object[@ar_object.class.inheritance_column]],
277
+ })})
278
+ elsif method == "*all"
279
+ @parent.as_hash({jsonize(method) => children.first})
280
+ else
281
+ @parent.as_hash({jsonize(method) => children})
282
+ end
283
+ else
284
+ {method.name => children}
285
+ end
286
+ end
287
+
288
+ end
289
+
290
+ end
291
+
292
+ def self.load_from_json(tree, target = nil)
293
+ ignore_all = nil
294
+
295
+ # have to process *all before any other items
296
+ # we leave the "*all" key in just for debugging purposes, and then skip it below
297
+
298
+ if sorted_collection = tree["*all"]
299
+ target.replace sorted_collection.collect { |id| target.proxy_association.klass.find(id) }
300
+ end
301
+
302
+ if id_value = tree["id"] and id_value.is_a? Array
303
+ target.id = id_value.first
304
+ end
305
+ tree.each do |method, value|
306
+ method = JSON.parse(method) rescue method
307
+ new_target = nil
308
+ if method == "*all"
309
+ next # its already been processed above
310
+ elsif !target
311
+ load_from_json(value, Object.const_get(method))
312
+ elsif method == "*count"
313
+ target.set_count_state(value.first)
314
+ elsif method.is_a? Integer or method =~ /^[0-9]+$/
315
+ new_target = target.push_and_update_belongs_to(method)
316
+ #target << (new_target = target.proxy_association.klass.find(method))
317
+ elsif method.is_a? Array
318
+ if method[0] == "new"
319
+ new_target = ReactiveRecord::Base.find_by_object_id(target.base_class, method[1])
320
+ elsif !(target.class < ActiveRecord::Base)
321
+ new_target = target.send *method
322
+ # value is an array if scope returns nil, so we destroy the bogus record
323
+ new_target.destroy and new_target = nil if value.is_a? Array
324
+ else
325
+ target.backing_record.update_attribute([method], target.backing_record.convert(method, value.first))
326
+ end
327
+ elsif target.class.respond_to?(:reflect_on_aggregation) and aggregation = target.class.reflect_on_aggregation(method) and
328
+ !(aggregation.klass < ActiveRecord::Base)
329
+ target.send "#{method}=", aggregation.deserialize(value.first)
330
+ elsif value.is_a? Array
331
+ target.send "#{method}=", value.first unless method == "id" # we handle ids first so things sync nicely
332
+ elsif value.is_a? Hash and value[:id] and value[:id].first and association = target.class.reflect_on_association(method)
333
+ # not sure if its necessary to check the id above... is it possible to for the method to be an association but not have an id?
334
+ new_target = association.klass.find(value[:id].first)
335
+ target.send "#{method}=", new_target
336
+ elsif !(target.class < ActiveRecord::Base)
337
+ new_target = target.send *method
338
+ # value is an array if scope returns nil, so we destroy the bogus record
339
+ new_target.destroy and new_target = nil if value.is_a? Array
340
+ else
341
+ new_target = target.send("#{method}=", target.send(method))
342
+ end
343
+ load_from_json(value, new_target) if new_target
344
+ end
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,3 @@
1
+ module ReactiveRecord
2
+ VERSION = "0.8.4"
3
+ end
@@ -0,0 +1,98 @@
1
+ /*!
2
+ * Pusher JavaScript Library v3.0.0
3
+ * http://pusher.com/
4
+ *
5
+ * Copyright 2014, Pusher
6
+ * Released under the MIT licence.
7
+ */
8
+
9
+ (function(b,c){"function"===typeof define&&define.amd?define([],function(){return b.Pusher=c()}):"object"===typeof exports?module.exports=c():b.Pusher=c()})(this,function(){(function(){function b(a,d){(null===a||void 0===a)&&b.warn("Warning","You must pass your app key when you instantiate Pusher.");d=d||{};var c=this;this.key=a;this.config=b.Util.extend(b.getGlobalConfig(),d.cluster?b.getClusterConfig(d.cluster):{},d);this.channels=new b.Channels;this.global_emitter=new b.EventsDispatcher;this.sessionID=
10
+ Math.floor(1E9*Math.random());this.timeline=new b.Timeline(this.key,this.sessionID,{cluster:this.config.cluster,features:b.Util.getClientFeatures(),params:this.config.timelineParams||{},limit:50,level:b.Timeline.INFO,version:b.VERSION});this.config.disableStats||(this.timelineSender=new b.TimelineSender(this.timeline,{host:this.config.statsHost,path:"/timeline/v2/jsonp"}));this.connection=new b.ConnectionManager(this.key,b.Util.extend({getStrategy:function(a){a=b.Util.extend({},c.config,a);return b.StrategyBuilder.build(b.getDefaultStrategy(a),
11
+ a)},timeline:this.timeline,activityTimeout:this.config.activity_timeout,pongTimeout:this.config.pong_timeout,unavailableTimeout:this.config.unavailable_timeout},this.config,{encrypted:this.isEncrypted()}));this.connection.bind("connected",function(){c.subscribeAll();c.timelineSender&&c.timelineSender.send(c.connection.isEncrypted())});this.connection.bind("message",function(a){var d=0===a.event.indexOf("pusher_internal:");if(a.channel){var b=c.channel(a.channel);b&&b.handleEvent(a.event,a.data)}d||
12
+ c.global_emitter.emit(a.event,a.data)});this.connection.bind("disconnected",function(){c.channels.disconnect()});this.connection.bind("error",function(a){b.warn("Error",a)});b.instances.push(this);this.timeline.info({instances:b.instances.length});b.isReady&&c.connect()}var c=b.prototype;b.instances=[];b.isReady=!1;b.debug=function(){b.log&&b.log(b.Util.stringify.apply(this,arguments))};b.warn=function(){var a=b.Util.stringify.apply(this,arguments);window.console&&(window.console.warn?window.console.warn(a):
13
+ window.console.log&&window.console.log(a));b.log&&b.log(a)};b.ready=function(){b.isReady=!0;for(var a=0,d=b.instances.length;a<d;a++)b.instances[a].connect()};c.channel=function(a){return this.channels.find(a)};c.allChannels=function(){return this.channels.all()};c.connect=function(){this.connection.connect();if(this.timelineSender&&!this.timelineSenderTimer){var a=this.connection.isEncrypted(),d=this.timelineSender;this.timelineSenderTimer=new b.PeriodicTimer(6E4,function(){d.send(a)})}};c.disconnect=
14
+ function(){this.connection.disconnect();this.timelineSenderTimer&&(this.timelineSenderTimer.ensureAborted(),this.timelineSenderTimer=null)};c.bind=function(a,d){this.global_emitter.bind(a,d);return this};c.bind_all=function(a){this.global_emitter.bind_all(a);return this};c.subscribeAll=function(){for(var a in this.channels.channels)this.channels.channels.hasOwnProperty(a)&&this.subscribe(a)};c.subscribe=function(a){a=this.channels.add(a,this);"connected"===this.connection.state&&a.subscribe();return a};
15
+ c.unsubscribe=function(a){(a=this.channels.remove(a))&&"connected"===this.connection.state&&a.unsubscribe()};c.send_event=function(a,d,b){return this.connection.send_event(a,d,b)};c.isEncrypted=function(){return"https:"===b.Util.getDocument().location.protocol?!0:Boolean(this.config.encrypted)};b.HTTP={};this.Pusher=b}).call(this);(function(){function b(a){window.clearTimeout(a)}function c(a){window.clearInterval(a)}function a(a,d,b,c){var k=this;this.clear=d;this.timer=a(function(){null!==k.timer&&
16
+ (k.timer=c(k.timer))},b)}var d=a.prototype;d.isRunning=function(){return null!==this.timer};d.ensureAborted=function(){this.timer&&(this.clear(this.timer),this.timer=null)};Pusher.Timer=function(d,c){return new a(setTimeout,b,d,function(a){c();return null})};Pusher.PeriodicTimer=function(d,b){return new a(setInterval,c,d,function(a){b();return a})}}).call(this);(function(){Pusher.Util={now:function(){return Date.now?Date.now():(new Date).valueOf()},defer:function(b){return new Pusher.Timer(0,b)},
17
+ extend:function(b){for(var c=1;c<arguments.length;c++){var a=arguments[c],d;for(d in a)b[d]=a[d]&&a[d].constructor&&a[d].constructor===Object?Pusher.Util.extend(b[d]||{},a[d]):a[d]}return b},stringify:function(){for(var b=["Pusher"],c=0;c<arguments.length;c++)"string"===typeof arguments[c]?b.push(arguments[c]):void 0===window.JSON?b.push(arguments[c].toString()):b.push(JSON.stringify(arguments[c]));return b.join(" : ")},arrayIndexOf:function(b,c){var a=Array.prototype.indexOf;if(null===b)return-1;
18
+ if(a&&b.indexOf===a)return b.indexOf(c);for(var a=0,d=b.length;a<d;a++)if(b[a]===c)return a;return-1},objectApply:function(b,c){for(var a in b)Object.prototype.hasOwnProperty.call(b,a)&&c(b[a],a,b)},keys:function(b){var c=[];Pusher.Util.objectApply(b,function(a,d){c.push(d)});return c},values:function(b){var c=[];Pusher.Util.objectApply(b,function(a){c.push(a)});return c},apply:function(b,c,a){for(var d=0;d<b.length;d++)c.call(a||window,b[d],d,b)},map:function(b,c){for(var a=[],d=0;d<b.length;d++)a.push(c(b[d],
19
+ d,b,a));return a},mapObject:function(b,c){var a={};Pusher.Util.objectApply(b,function(d,b){a[b]=c(d)});return a},filter:function(b,c){c=c||function(a){return!!a};for(var a=[],d=0;d<b.length;d++)c(b[d],d,b,a)&&a.push(b[d]);return a},filterObject:function(b,c){var a={};Pusher.Util.objectApply(b,function(d,h){if(c&&c(d,h,b,a)||Boolean(d))a[h]=d});return a},flatten:function(b){var c=[];Pusher.Util.objectApply(b,function(a,d){c.push([d,a])});return c},any:function(b,c){for(var a=0;a<b.length;a++)if(c(b[a],
20
+ a,b))return!0;return!1},all:function(b,c){for(var a=0;a<b.length;a++)if(!c(b[a],a,b))return!1;return!0},method:function(b){var c=Array.prototype.slice.call(arguments,1);return function(a){return a[b].apply(a,c.concat(arguments))}},getWindow:function(){return window},getDocument:function(){return document},getLocalStorage:function(){try{return window.localStorage}catch(b){}},getClientFeatures:function(){return Pusher.Util.keys(Pusher.Util.filterObject({ws:Pusher.WSTransport},function(b){return b.isSupported({})}))},
21
+ addWindowListener:function(b,c){var a=Pusher.Util.getWindow();void 0!==a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent("on"+b,c)},removeWindowListener:function(b,c){var a=Pusher.Util.getWindow();void 0!==a.addEventListener?a.removeEventListener(b,c,!1):a.detachEvent("on"+b,c)},isXHRSupported:function(){var b=window.XMLHttpRequest;return Boolean(b)&&void 0!==(new b).withCredentials},isXDRSupported:function(b){b=b?"https:":"http:";var c=Pusher.Util.getDocument().location.protocol;return Boolean(window.XDomainRequest)&&
22
+ c===b}}}).call(this);(function(){Pusher.VERSION="3.0.0";Pusher.PROTOCOL=7;Pusher.host="ws.pusherapp.com";Pusher.ws_port=80;Pusher.wss_port=443;Pusher.sockjs_host="sockjs.pusher.com";Pusher.sockjs_http_port=80;Pusher.sockjs_https_port=443;Pusher.sockjs_path="/pusher";Pusher.stats_host="stats.pusher.com";Pusher.channel_auth_endpoint="/pusher/auth";Pusher.channel_auth_transport="ajax";Pusher.activity_timeout=12E4;Pusher.pong_timeout=3E4;Pusher.unavailable_timeout=1E4;Pusher.cdn_http="http://js.pusher.com/";
23
+ Pusher.cdn_https="https://js.pusher.com/";Pusher.dependency_suffix=".min";Pusher.getDefaultStrategy=function(b){return[[":def","ws_options",{hostUnencrypted:b.wsHost+":"+b.wsPort,hostEncrypted:b.wsHost+":"+b.wssPort}],[":def","wss_options",[":extend",":ws_options",{encrypted:!0}]],[":def","sockjs_options",{hostUnencrypted:b.httpHost+":"+b.httpPort,hostEncrypted:b.httpHost+":"+b.httpsPort,httpPath:b.httpPath}],[":def","timeouts",{loop:!0,timeout:15E3,timeoutLimit:6E4}],[":def","ws_manager",[":transport_manager",
24
+ {lives:2,minPingDelay:1E4,maxPingDelay:b.activity_timeout}]],[":def","streaming_manager",[":transport_manager",{lives:2,minPingDelay:1E4,maxPingDelay:b.activity_timeout}]],[":def_transport","ws","ws",3,":ws_options",":ws_manager"],[":def_transport","wss","ws",3,":wss_options",":ws_manager"],[":def_transport","sockjs","sockjs",1,":sockjs_options"],[":def_transport","xhr_streaming","xhr_streaming",1,":sockjs_options",":streaming_manager"],[":def_transport","xdr_streaming","xdr_streaming",1,":sockjs_options",
25
+ ":streaming_manager"],[":def_transport","xhr_polling","xhr_polling",1,":sockjs_options"],[":def_transport","xdr_polling","xdr_polling",1,":sockjs_options"],[":def","ws_loop",[":sequential",":timeouts",":ws"]],[":def","wss_loop",[":sequential",":timeouts",":wss"]],[":def","sockjs_loop",[":sequential",":timeouts",":sockjs"]],[":def","streaming_loop",[":sequential",":timeouts",[":if",[":is_supported",":xhr_streaming"],":xhr_streaming",":xdr_streaming"]]],[":def","polling_loop",[":sequential",":timeouts",
26
+ [":if",[":is_supported",":xhr_polling"],":xhr_polling",":xdr_polling"]]],[":def","http_loop",[":if",[":is_supported",":streaming_loop"],[":best_connected_ever",":streaming_loop",[":delayed",4E3,[":polling_loop"]]],[":polling_loop"]]],[":def","http_fallback_loop",[":if",[":is_supported",":http_loop"],[":http_loop"],[":sockjs_loop"]]],[":def","strategy",[":cached",18E5,[":first_connected",[":if",[":is_supported",":ws"],b.encrypted?[":best_connected_ever",":ws_loop",[":delayed",2E3,[":http_fallback_loop"]]]:
27
+ [":best_connected_ever",":ws_loop",[":delayed",2E3,[":wss_loop"]],[":delayed",5E3,[":http_fallback_loop"]]],":http_fallback_loop"]]]]]}}).call(this);(function(){Pusher.getGlobalConfig=function(){return{wsHost:Pusher.host,wsPort:Pusher.ws_port,wssPort:Pusher.wss_port,httpHost:Pusher.sockjs_host,httpPort:Pusher.sockjs_http_port,httpsPort:Pusher.sockjs_https_port,httpPath:Pusher.sockjs_path,statsHost:Pusher.stats_host,authEndpoint:Pusher.channel_auth_endpoint,authTransport:Pusher.channel_auth_transport,
28
+ activity_timeout:Pusher.activity_timeout,pong_timeout:Pusher.pong_timeout,unavailable_timeout:Pusher.unavailable_timeout}};Pusher.getClusterConfig=function(b){return{wsHost:"ws-"+b+".pusher.com",httpHost:"sockjs-"+b+".pusher.com"}}}).call(this);(function(){function b(b){var a=function(a){Error.call(this,a);this.name=b};Pusher.Util.extend(a.prototype,Error.prototype);return a}Pusher.Errors={BadEventName:b("BadEventName"),RequestTimedOut:b("RequestTimedOut"),TransportPriorityTooLow:b("TransportPriorityTooLow"),
29
+ TransportClosed:b("TransportClosed"),UnsupportedTransport:b("UnsupportedTransport"),UnsupportedStrategy:b("UnsupportedStrategy")}}).call(this);(function(){function b(a){this.callbacks=new c;this.global_callbacks=[];this.failThrough=a}function c(){this._callbacks={}}var a=b.prototype;a.bind=function(a,b,c){this.callbacks.add(a,b,c);return this};a.bind_all=function(a){this.global_callbacks.push(a);return this};a.unbind=function(a,b,c){this.callbacks.remove(a,b,c);return this};a.unbind_all=function(a,
30
+ b){this.callbacks.remove(a,b);return this};a.emit=function(a,b){var c;for(c=0;c<this.global_callbacks.length;c++)this.global_callbacks[c](a,b);var e=this.callbacks.get(a);if(e&&0<e.length)for(c=0;c<e.length;c++)e[c].fn.call(e[c].context||window,b);else this.failThrough&&this.failThrough(a,b);return this};c.prototype.get=function(a){return this._callbacks["_"+a]};c.prototype.add=function(a,b,c){a="_"+a;this._callbacks[a]=this._callbacks[a]||[];this._callbacks[a].push({fn:b,context:c})};c.prototype.remove=
31
+ function(a,b,c){!a&&!b&&!c?this._callbacks={}:(a=a?["_"+a]:Pusher.Util.keys(this._callbacks),b||c?Pusher.Util.apply(a,function(a){this._callbacks[a]=Pusher.Util.filter(this._callbacks[a]||[],function(a){return b&&b!==a.fn||c&&c!==a.context});0===this._callbacks[a].length&&delete this._callbacks[a]},this):Pusher.Util.apply(a,function(a){delete this._callbacks[a]},this))};Pusher.EventsDispatcher=b}).call(this);(function(){function b(a,d){this.lastId=0;this.prefix=a;this.name=d}var c=b.prototype;c.create=
32
+ function(a){this.lastId++;var d=this.lastId,b=this.prefix+d,c=this.name+"["+d+"]",e=!1,g=function(){e||(a.apply(null,arguments),e=!0)};this[d]=g;return{number:d,id:b,name:c,callback:g}};c.remove=function(a){delete this[a.number]};Pusher.ScriptReceiverFactory=b;Pusher.ScriptReceivers=new b("_pusher_script_","Pusher.ScriptReceivers")}).call(this);(function(){function b(a){this.src=a}var c=b.prototype;c.send=function(a){var d=this,b="Error loading "+d.src;d.script=document.createElement("script");d.script.id=
33
+ a.id;d.script.src=d.src;d.script.type="text/javascript";d.script.charset="UTF-8";d.script.addEventListener?(d.script.onerror=function(){a.callback(b)},d.script.onload=function(){a.callback(null)}):d.script.onreadystatechange=function(){("loaded"===d.script.readyState||"complete"===d.script.readyState)&&a.callback(null)};void 0===d.script.async&&document.attachEvent&&/opera/i.test(navigator.userAgent)?(d.errorScript=document.createElement("script"),d.errorScript.id=a.id+"_error",d.errorScript.text=
34
+ a.name+"('"+b+"');",d.script.async=d.errorScript.async=!1):d.script.async=!0;var c=document.getElementsByTagName("head")[0];c.insertBefore(d.script,c.firstChild);d.errorScript&&c.insertBefore(d.errorScript,d.script.nextSibling)};c.cleanup=function(){this.script&&(this.script.onload=this.script.onerror=null,this.script.onreadystatechange=null);this.script&&this.script.parentNode&&this.script.parentNode.removeChild(this.script);this.errorScript&&this.errorScript.parentNode&&this.errorScript.parentNode.removeChild(this.errorScript);
35
+ this.errorScript=this.script=null};Pusher.ScriptRequest=b}).call(this);(function(){function b(a){this.options=a;this.receivers=a.receivers||Pusher.ScriptReceivers;this.loading={}}var c=b.prototype;c.load=function(a,d,b){var c=this;if(c.loading[a]&&0<c.loading[a].length)c.loading[a].push(b);else{c.loading[a]=[b];var e=new Pusher.ScriptRequest(c.getPath(a,d)),g=c.receivers.create(function(d){c.receivers.remove(g);if(c.loading[a]){var b=c.loading[a];delete c.loading[a];for(var h=function(a){a||e.cleanup()},
36
+ m=0;m<b.length;m++)b[m](d,h)}});e.send(g)}};c.getRoot=function(a){var d=Pusher.Util.getDocument().location.protocol;return(a&&a.encrypted||"https:"===d?this.options.cdn_https:this.options.cdn_http).replace(/\/*$/,"")+"/"+this.options.version};c.getPath=function(a,d){return this.getRoot(d)+"/"+a+this.options.suffix+".js"};Pusher.DependencyLoader=b}).call(this);(function(){function b(){Pusher.ready()}function c(a){document.body?a():setTimeout(function(){c(a)},0)}function a(){c(b)}Pusher.DependenciesReceivers=
37
+ new Pusher.ScriptReceiverFactory("_pusher_dependencies","Pusher.DependenciesReceivers");Pusher.Dependencies=new Pusher.DependencyLoader({cdn_http:Pusher.cdn_http,cdn_https:Pusher.cdn_https,version:Pusher.VERSION,suffix:Pusher.dependency_suffix,receivers:Pusher.DependenciesReceivers});window.JSON?a():Pusher.Dependencies.load("json2",{},a)})();(function(){for(var b=String.fromCharCode,c=0;64>c;c++)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c);var a=function(a){var d=a.charCodeAt(0);
38
+ return 128>d?a:2048>d?b(192|d>>>6)+b(128|d&63):b(224|d>>>12&15)+b(128|d>>>6&63)+b(128|d&63)},d=function(a){var d=[0,2,1][a.length%3];a=a.charCodeAt(0)<<16|(1<a.length?a.charCodeAt(1):0)<<8|(2<a.length?a.charCodeAt(2):0);return["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(a>>>18),"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(a>>>12&63),2<=d?"=":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(a>>>6&63),1<=d?"=":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(a&
39
+ 63)].join("")},h=window.btoa||function(a){return a.replace(/[\s\S]{1,3}/g,d)};Pusher.Base64={encode:function(d){return h(d.replace(/[^\x00-\x7F]/g,a))}}}).call(this);(function(){function b(a,b){this.url=a;this.data=b}function c(a){return Pusher.Util.mapObject(a,function(a){"object"===typeof a&&(a=JSON.stringify(a));return encodeURIComponent(Pusher.Base64.encode(a.toString()))})}var a=b.prototype;a.send=function(a){if(!this.request){var b=Pusher.Util.filterObject(this.data,function(a){return void 0!==
40
+ a}),b=Pusher.Util.map(Pusher.Util.flatten(c(b)),Pusher.Util.method("join","=")).join("&");this.request=new Pusher.ScriptRequest(this.url+"/"+a.number+"?"+b);this.request.send(a)}};a.cleanup=function(){this.request&&this.request.cleanup()};Pusher.JSONPRequest=b}).call(this);(function(){function b(a,b,c){this.key=a;this.session=b;this.events=[];this.options=c||{};this.uniqueID=this.sent=0}var c=b.prototype;b.ERROR=3;b.INFO=6;b.DEBUG=7;c.log=function(a,b){a<=this.options.level&&(this.events.push(Pusher.Util.extend({},
41
+ b,{timestamp:Pusher.Util.now()})),this.options.limit&&this.events.length>this.options.limit&&this.events.shift())};c.error=function(a){this.log(b.ERROR,a)};c.info=function(a){this.log(b.INFO,a)};c.debug=function(a){this.log(b.DEBUG,a)};c.isEmpty=function(){return 0===this.events.length};c.send=function(a,b){var c=this,f=Pusher.Util.extend({session:c.session,bundle:c.sent+1,key:c.key,lib:"js",version:c.options.version,cluster:c.options.cluster,features:c.options.features,timeline:c.events},c.options.params);
42
+ c.events=[];a(f,function(a,g){a||c.sent++;b&&b(a,g)});return!0};c.generateUniqueID=function(){this.uniqueID++;return this.uniqueID};Pusher.Timeline=b}).call(this);(function(){function b(b,a){this.timeline=b;this.options=a||{}}b.prototype.send=function(b,a){var d=this;d.timeline.isEmpty()||d.timeline.send(function(a,f){var e=new Pusher.JSONPRequest("http"+(b?"s":"")+"://"+(d.host||d.options.host)+d.options.path,a),g=Pusher.ScriptReceivers.create(function(a,b){Pusher.ScriptReceivers.remove(g);e.cleanup();
43
+ b&&b.host&&(d.host=b.host);f&&f(a,b)});e.send(g)},a)};Pusher.TimelineSender=b}).call(this);(function(){function b(a){this.strategies=a}function c(a,b,c){var h=Pusher.Util.map(a,function(a,d,h,f){return a.connect(b,c(d,f))});return{abort:function(){Pusher.Util.apply(h,d)},forceMinPriority:function(a){Pusher.Util.apply(h,function(b){b.forceMinPriority(a)})}}}function a(a){return Pusher.Util.all(a,function(a){return Boolean(a.error)})}function d(a){!a.error&&!a.aborted&&(a.abort(),a.aborted=!0)}var h=
44
+ b.prototype;h.isSupported=function(){return Pusher.Util.any(this.strategies,Pusher.Util.method("isSupported"))};h.connect=function(b,d){return c(this.strategies,b,function(b,c){return function(h,f){(c[b].error=h)?a(c)&&d(!0):(Pusher.Util.apply(c,function(a){a.forceMinPriority(f.transport.priority)}),d(null,f))}})};Pusher.BestConnectedEverStrategy=b}).call(this);(function(){function b(a,b,d){this.strategy=a;this.transports=b;this.ttl=d.ttl||18E5;this.encrypted=d.encrypted;this.timeline=d.timeline}
45
+ function c(a){return"pusherTransport"+(a?"Encrypted":"Unencrypted")}function a(a){var b=Pusher.Util.getLocalStorage();if(b)try{var h=b[c(a)];if(h)return JSON.parse(h)}catch(k){d(a)}return null}function d(a){var b=Pusher.Util.getLocalStorage();if(b)try{delete b[c(a)]}catch(d){}}var h=b.prototype;h.isSupported=function(){return this.strategy.isSupported()};h.connect=function(b,h){var g=this.encrypted,k=a(g),l=[this.strategy];if(k&&k.timestamp+this.ttl>=Pusher.Util.now()){var n=this.transports[k.transport];
46
+ n&&(this.timeline.info({cached:!0,transport:k.transport,latency:k.latency}),l.push(new Pusher.SequentialStrategy([n],{timeout:2*k.latency+1E3,failFast:!0})))}var m=Pusher.Util.now(),p=l.pop().connect(b,function s(a,k){if(a)d(g),0<l.length?(m=Pusher.Util.now(),p=l.pop().connect(b,s)):h(a);else{var n=k.transport.name,t=Pusher.Util.now()-m,r=Pusher.Util.getLocalStorage();if(r)try{r[c(g)]=JSON.stringify({timestamp:Pusher.Util.now(),transport:n,latency:t})}catch(u){}h(null,k)}});return{abort:function(){p.abort()},
47
+ forceMinPriority:function(a){b=a;p&&p.forceMinPriority(a)}}};Pusher.CachedStrategy=b}).call(this);(function(){function b(a,b){this.strategy=a;this.options={delay:b.delay}}var c=b.prototype;c.isSupported=function(){return this.strategy.isSupported()};c.connect=function(a,b){var c=this.strategy,f,e=new Pusher.Timer(this.options.delay,function(){f=c.connect(a,b)});return{abort:function(){e.ensureAborted();f&&f.abort()},forceMinPriority:function(b){a=b;f&&f.forceMinPriority(b)}}};Pusher.DelayedStrategy=
48
+ b}).call(this);(function(){function b(a){this.strategy=a}var c=b.prototype;c.isSupported=function(){return this.strategy.isSupported()};c.connect=function(a,b){var c=this.strategy.connect(a,function(a,e){e&&c.abort();b(a,e)});return c};Pusher.FirstConnectedStrategy=b}).call(this);(function(){function b(a,b,c){this.test=a;this.trueBranch=b;this.falseBranch=c}var c=b.prototype;c.isSupported=function(){return(this.test()?this.trueBranch:this.falseBranch).isSupported()};c.connect=function(a,b){return(this.test()?
49
+ this.trueBranch:this.falseBranch).connect(a,b)};Pusher.IfStrategy=b}).call(this);(function(){function b(a,b){this.strategies=a;this.loop=Boolean(b.loop);this.failFast=Boolean(b.failFast);this.timeout=b.timeout;this.timeoutLimit=b.timeoutLimit}var c=b.prototype;c.isSupported=function(){return Pusher.Util.any(this.strategies,Pusher.Util.method("isSupported"))};c.connect=function(a,b){var c=this,f=this.strategies,e=0,g=this.timeout,k=null,l=function(n,m){m?b(null,m):(e+=1,c.loop&&(e%=f.length),e<f.length?
50
+ (g&&(g*=2,c.timeoutLimit&&(g=Math.min(g,c.timeoutLimit))),k=c.tryStrategy(f[e],a,{timeout:g,failFast:c.failFast},l)):b(!0))},k=this.tryStrategy(f[e],a,{timeout:g,failFast:this.failFast},l);return{abort:function(){k.abort()},forceMinPriority:function(b){a=b;k&&k.forceMinPriority(b)}}};c.tryStrategy=function(a,b,c,f){var e=null,g=null;0<c.timeout&&(e=new Pusher.Timer(c.timeout,function(){g.abort();f(!0)}));g=a.connect(b,function(a,b){if(!a||!e||!e.isRunning()||c.failFast)e&&e.ensureAborted(),f(a,b)});
51
+ return{abort:function(){e&&e.ensureAborted();g.abort()},forceMinPriority:function(a){g.forceMinPriority(a)}}};Pusher.SequentialStrategy=b}).call(this);(function(){function b(a,b,c,e){this.name=a;this.priority=b;this.transport=c;this.options=e||{}}function c(a,b){Pusher.Util.defer(function(){b(a)});return{abort:function(){},forceMinPriority:function(){}}}var a=b.prototype;a.isSupported=function(){return this.transport.isSupported({encrypted:this.options.encrypted})};a.connect=function(a,b){if(this.isSupported()){if(this.priority<
52
+ a)return c(new Pusher.Errors.TransportPriorityTooLow,b)}else return c(new Pusher.Errors.UnsupportedStrategy,b);var f=this,e=!1,g=this.transport.createConnection(this.name,this.priority,this.options.key,this.options),k=null,l=function(){g.unbind("initialized",l);g.connect()},n=function(){k=new Pusher.Handshake(g,function(a){e=!0;q();b(null,a)})},m=function(a){q();b(a)},p=function(){q();b(new Pusher.Errors.TransportClosed(g))},q=function(){g.unbind("initialized",l);g.unbind("open",n);g.unbind("error",
53
+ m);g.unbind("closed",p)};g.bind("initialized",l);g.bind("open",n);g.bind("error",m);g.bind("closed",p);g.initialize();return{abort:function(){e||(q(),k?k.close():g.close())},forceMinPriority:function(a){e||f.priority<a&&(k?k.close():g.close())}}};Pusher.TransportStrategy=b}).call(this);(function(){function b(a,b,c){return a+(b.encrypted?"s":"")+"://"+(b.encrypted?b.hostEncrypted:b.hostUnencrypted)+c}function c(a,b){return"/app/"+a+("?protocol="+Pusher.PROTOCOL+"&client=js&version="+Pusher.VERSION+
54
+ (b?"&"+b:""))}Pusher.URLSchemes={ws:{getInitial:function(a,d){return b("ws",d,c(a,"flash=false"))}},sockjs:{getInitial:function(a,c){return b("http",c,c.httpPath||"/pusher","")},getPath:function(a,b){return c(a)}},http:{getInitial:function(a,d){var h=(d.httpPath||"/pusher")+c(a);return b("http",d,h)}}}}).call(this);(function(){function b(a,b,c,f,e){Pusher.EventsDispatcher.call(this);this.hooks=a;this.name=b;this.priority=c;this.key=f;this.options=e;this.state="new";this.timeline=e.timeline;this.activityTimeout=
55
+ e.activityTimeout;this.id=this.timeline.generateUniqueID()}var c=b.prototype;Pusher.Util.extend(c,Pusher.EventsDispatcher.prototype);c.handlesActivityChecks=function(){return Boolean(this.hooks.handlesActivityChecks)};c.supportsPing=function(){return Boolean(this.hooks.supportsPing)};c.initialize=function(){var a=this;a.timeline.info(a.buildTimelineMessage({transport:a.name+(a.options.encrypted?"s":"")}));if(a.hooks.isInitialized())a.changeState("initialized");else if(a.hooks.file)a.changeState("initializing"),
56
+ Pusher.Dependencies.load(a.hooks.file,{encrypted:a.options.encrypted},function(b,c){if(a.hooks.isInitialized())a.changeState("initialized"),c(!0);else{if(b)a.onError(b);a.onClose();c(!1)}});else a.onClose()};c.connect=function(){var a=this;if(a.socket||"initialized"!==a.state)return!1;var b=a.hooks.urls.getInitial(a.key,a.options);try{a.socket=a.hooks.getSocket(b,a.options)}catch(c){return Pusher.Util.defer(function(){a.onError(c);a.changeState("closed")}),!1}a.bindListeners();Pusher.debug("Connecting",
57
+ {transport:a.name,url:b});a.changeState("connecting");return!0};c.close=function(){return this.socket?(this.socket.close(),!0):!1};c.send=function(a){var b=this;return"open"===b.state?(Pusher.Util.defer(function(){b.socket&&b.socket.send(a)}),!0):!1};c.ping=function(){"open"===this.state&&this.supportsPing()&&this.socket.ping()};c.onOpen=function(){this.hooks.beforeOpen&&this.hooks.beforeOpen(this.socket,this.hooks.urls.getPath(this.key,this.options));this.changeState("open");this.socket.onopen=void 0};
58
+ c.onError=function(a){this.emit("error",{type:"WebSocketError",error:a});this.timeline.error(this.buildTimelineMessage({error:a.toString()}))};c.onClose=function(a){a?this.changeState("closed",{code:a.code,reason:a.reason,wasClean:a.wasClean}):this.changeState("closed");this.unbindListeners();this.socket=void 0};c.onMessage=function(a){this.emit("message",a)};c.onActivity=function(){this.emit("activity")};c.bindListeners=function(){var a=this;a.socket.onopen=function(){a.onOpen()};a.socket.onerror=
59
+ function(b){a.onError(b)};a.socket.onclose=function(b){a.onClose(b)};a.socket.onmessage=function(b){a.onMessage(b)};a.supportsPing()&&(a.socket.onactivity=function(){a.onActivity()})};c.unbindListeners=function(){this.socket&&(this.socket.onopen=void 0,this.socket.onerror=void 0,this.socket.onclose=void 0,this.socket.onmessage=void 0,this.supportsPing()&&(this.socket.onactivity=void 0))};c.changeState=function(a,b){this.state=a;this.timeline.info(this.buildTimelineMessage({state:a,params:b}));this.emit(a,
60
+ b)};c.buildTimelineMessage=function(a){return Pusher.Util.extend({cid:this.id},a)};Pusher.TransportConnection=b}).call(this);(function(){function b(a){this.hooks=a}var c=b.prototype;c.isSupported=function(a){return this.hooks.isSupported(a)};c.createConnection=function(a,b,c,f){return new Pusher.TransportConnection(this.hooks,a,b,c,f)};Pusher.Transport=b}).call(this);(function(){Pusher.WSTransport=new Pusher.Transport({urls:Pusher.URLSchemes.ws,handlesActivityChecks:!1,supportsPing:!1,isInitialized:function(){return Boolean(window.WebSocket||
61
+ window.MozWebSocket)},isSupported:function(){return Boolean(window.WebSocket||window.MozWebSocket)},getSocket:function(a){return new (window.WebSocket||window.MozWebSocket)(a)}});Pusher.SockJSTransport=new Pusher.Transport({file:"sockjs",urls:Pusher.URLSchemes.sockjs,handlesActivityChecks:!0,supportsPing:!1,isSupported:function(){return!0},isInitialized:function(){return void 0!==window.SockJS},getSocket:function(a,b){return new SockJS(a,null,{js_path:Pusher.Dependencies.getPath("sockjs",{encrypted:b.encrypted}),
62
+ ignore_null_origin:b.ignoreNullOrigin})},beforeOpen:function(a,b){a.send(JSON.stringify({path:b}))}});var b={urls:Pusher.URLSchemes.http,handlesActivityChecks:!1,supportsPing:!0,isInitialized:function(){return Boolean(Pusher.HTTP.Socket)}},c=Pusher.Util.extend({getSocket:function(a){return Pusher.HTTP.getStreamingSocket(a)}},b),b=Pusher.Util.extend({getSocket:function(a){return Pusher.HTTP.getPollingSocket(a)}},b),a={file:"xhr",isSupported:Pusher.Util.isXHRSupported},d={file:"xdr",isSupported:function(a){return Pusher.Util.isXDRSupported(a.encrypted)}};
63
+ Pusher.XHRStreamingTransport=new Pusher.Transport(Pusher.Util.extend({},c,a));Pusher.XDRStreamingTransport=new Pusher.Transport(Pusher.Util.extend({},c,d));Pusher.XHRPollingTransport=new Pusher.Transport(Pusher.Util.extend({},b,a));Pusher.XDRPollingTransport=new Pusher.Transport(Pusher.Util.extend({},b,d))}).call(this);(function(){function b(a,b,c){this.manager=a;this.transport=b;this.minPingDelay=c.minPingDelay;this.maxPingDelay=c.maxPingDelay;this.pingDelay=void 0}var c=b.prototype;c.createConnection=
64
+ function(a,b,c,f){var e=this;f=Pusher.Util.extend({},f,{activityTimeout:e.pingDelay});var g=e.transport.createConnection(a,b,c,f),k=null,l=function(){g.unbind("open",l);g.bind("closed",n);k=Pusher.Util.now()},n=function(a){g.unbind("closed",n);1002===a.code||1003===a.code?e.manager.reportDeath():!a.wasClean&&k&&(a=Pusher.Util.now()-k,a<2*e.maxPingDelay&&(e.manager.reportDeath(),e.pingDelay=Math.max(a/2,e.minPingDelay)))};g.bind("open",l);return g};c.isSupported=function(a){return this.manager.isAlive()&&
65
+ this.transport.isSupported(a)};Pusher.AssistantToTheTransportManager=b}).call(this);(function(){function b(a){this.options=a||{};this.livesLeft=this.options.lives||Infinity}var c=b.prototype;c.getAssistant=function(a){return new Pusher.AssistantToTheTransportManager(this,a,{minPingDelay:this.options.minPingDelay,maxPingDelay:this.options.maxPingDelay})};c.isAlive=function(){return 0<this.livesLeft};c.reportDeath=function(){this.livesLeft-=1};Pusher.TransportManager=b}).call(this);(function(){function b(a){return function(b){return[a.apply(this,
66
+ arguments),b]}}function c(a,b){if(0===a.length)return[[],b];var h=d(a[0],b),f=c(a.slice(1),h[1]);return[[h[0]].concat(f[0]),f[1]]}function a(a,b){if("string"===typeof a[0]&&":"===a[0].charAt(0)){var h=b[a[0].slice(1)];if(1<a.length){if("function"!==typeof h)throw"Calling non-function "+a[0];var f=[Pusher.Util.extend({},b)].concat(Pusher.Util.map(a.slice(1),function(a){return d(a,Pusher.Util.extend({},b))[0]}));return h.apply(this,f)}return[h,b]}return c(a,b)}function d(b,c){if("string"===typeof b){var d;
67
+ if("string"===typeof b&&":"===b.charAt(0)){d=c[b.slice(1)];if(void 0===d)throw"Undefined symbol "+b;d=[d,c]}else d=[b,c];return d}return"object"===typeof b&&b instanceof Array&&0<b.length?a(b,c):[b,c]}var h={ws:Pusher.WSTransport,sockjs:Pusher.SockJSTransport,xhr_streaming:Pusher.XHRStreamingTransport,xdr_streaming:Pusher.XDRStreamingTransport,xhr_polling:Pusher.XHRPollingTransport,xdr_polling:Pusher.XDRPollingTransport},f={isSupported:function(){return!1},connect:function(a,b){var c=Pusher.Util.defer(function(){b(new Pusher.Errors.UnsupportedStrategy)});
68
+ return{abort:function(){c.ensureAborted()},forceMinPriority:function(){}}}},e={extend:function(a,b,c){return[Pusher.Util.extend({},b,c),a]},def:function(a,b,c){if(void 0!==a[b])throw"Redefining symbol "+b;a[b]=c;return[void 0,a]},def_transport:function(a,b,c,d,e,p){var q=h[c];if(!q)throw new Pusher.Errors.UnsupportedTransport(c);c=(!a.enabledTransports||-1!==Pusher.Util.arrayIndexOf(a.enabledTransports,b))&&(!a.disabledTransports||-1===Pusher.Util.arrayIndexOf(a.disabledTransports,b))?new Pusher.TransportStrategy(b,
69
+ d,p?p.getAssistant(q):q,Pusher.Util.extend({key:a.key,encrypted:a.encrypted,timeline:a.timeline,ignoreNullOrigin:a.ignoreNullOrigin},e)):f;d=a.def(a,b,c)[1];d.transports=a.transports||{};d.transports[b]=c;return[void 0,d]},transport_manager:b(function(a,b){return new Pusher.TransportManager(b)}),sequential:b(function(a,b){var c=Array.prototype.slice.call(arguments,2);return new Pusher.SequentialStrategy(c,b)}),cached:b(function(a,b,c){return new Pusher.CachedStrategy(c,a.transports,{ttl:b,timeline:a.timeline,
70
+ encrypted:a.encrypted})}),first_connected:b(function(a,b){return new Pusher.FirstConnectedStrategy(b)}),best_connected_ever:b(function(){var a=Array.prototype.slice.call(arguments,1);return new Pusher.BestConnectedEverStrategy(a)}),delayed:b(function(a,b,c){return new Pusher.DelayedStrategy(c,{delay:b})}),"if":b(function(a,b,c,d){return new Pusher.IfStrategy(b,c,d)}),is_supported:b(function(a,b){return function(){return b.isSupported()}})};Pusher.StrategyBuilder={build:function(a,b){var c=Pusher.Util.extend({},
71
+ e,b);return d(a,c)[1].strategy}}}).call(this);(function(){Pusher.Protocol={decodeMessage:function(b){try{var c=JSON.parse(b.data);if("string"===typeof c.data)try{c.data=JSON.parse(c.data)}catch(a){if(!(a instanceof SyntaxError))throw a;}return c}catch(d){throw{type:"MessageParseError",error:d,data:b.data};}},encodeMessage:function(b){return JSON.stringify(b)},processHandshake:function(b){b=this.decodeMessage(b);if("pusher:connection_established"===b.event){if(!b.data.activity_timeout)throw"No activity timeout specified in handshake";
72
+ return{action:"connected",id:b.data.socket_id,activityTimeout:1E3*b.data.activity_timeout}}if("pusher:error"===b.event)return{action:this.getCloseAction(b.data),error:this.getCloseError(b.data)};throw"Invalid handshake";},getCloseAction:function(b){return 4E3>b.code?1002<=b.code&&1004>=b.code?"backoff":null:4E3===b.code?"ssl_only":4100>b.code?"refused":4200>b.code?"backoff":4300>b.code?"retry":"refused"},getCloseError:function(b){return 1E3!==b.code&&1001!==b.code?{type:"PusherError",data:{code:b.code,
73
+ message:b.reason||b.message}}:null}}}).call(this);(function(){function b(a,b){Pusher.EventsDispatcher.call(this);this.id=a;this.transport=b;this.activityTimeout=b.activityTimeout;this.bindListeners()}var c=b.prototype;Pusher.Util.extend(c,Pusher.EventsDispatcher.prototype);c.handlesActivityChecks=function(){return this.transport.handlesActivityChecks()};c.send=function(a){return this.transport.send(a)};c.send_event=function(a,b,c){a={event:a,data:b};c&&(a.channel=c);Pusher.debug("Event sent",a);return this.send(Pusher.Protocol.encodeMessage(a))};
74
+ c.ping=function(){this.transport.supportsPing()?this.transport.ping():this.send_event("pusher:ping",{})};c.close=function(){this.transport.close()};c.bindListeners=function(){var a=this,b={message:function(b){var c;try{c=Pusher.Protocol.decodeMessage(b)}catch(d){a.emit("error",{type:"MessageParseError",error:d,data:b.data})}if(void 0!==c){Pusher.debug("Event recd",c);switch(c.event){case "pusher:error":a.emit("error",{type:"PusherError",data:c.data});break;case "pusher:ping":a.emit("ping");break;
75
+ case "pusher:pong":a.emit("pong")}a.emit("message",c)}},activity:function(){a.emit("activity")},error:function(b){a.emit("error",{type:"WebSocketError",error:b})},closed:function(b){c();b&&b.code&&a.handleCloseEvent(b);a.transport=null;a.emit("closed")}},c=function(){Pusher.Util.objectApply(b,function(b,c){a.transport.unbind(c,b)})};Pusher.Util.objectApply(b,function(b,c){a.transport.bind(c,b)})};c.handleCloseEvent=function(a){var b=Pusher.Protocol.getCloseAction(a);(a=Pusher.Protocol.getCloseError(a))&&
76
+ this.emit("error",a);b&&this.emit(b)};Pusher.Connection=b}).call(this);(function(){function b(a,b){this.transport=a;this.callback=b;this.bindListeners()}var c=b.prototype;c.close=function(){this.unbindListeners();this.transport.close()};c.bindListeners=function(){var a=this;a.onMessage=function(b){a.unbindListeners();try{var c=Pusher.Protocol.processHandshake(b);"connected"===c.action?a.finish("connected",{connection:new Pusher.Connection(c.id,a.transport),activityTimeout:c.activityTimeout}):(a.finish(c.action,
77
+ {error:c.error}),a.transport.close())}catch(f){a.finish("error",{error:f}),a.transport.close()}};a.onClosed=function(b){a.unbindListeners();var c=Pusher.Protocol.getCloseAction(b)||"backoff";b=Pusher.Protocol.getCloseError(b);a.finish(c,{error:b})};a.transport.bind("message",a.onMessage);a.transport.bind("closed",a.onClosed)};c.unbindListeners=function(){this.transport.unbind("message",this.onMessage);this.transport.unbind("closed",this.onClosed)};c.finish=function(a,b){this.callback(Pusher.Util.extend({transport:this.transport,
78
+ action:a},b))};Pusher.Handshake=b}).call(this);(function(){function b(a,b){Pusher.EventsDispatcher.call(this);this.key=a;this.options=b||{};this.state="initialized";this.connection=null;this.encrypted=!!b.encrypted;this.timeline=this.options.timeline;this.connectionCallbacks=this.buildConnectionCallbacks();this.errorCallbacks=this.buildErrorCallbacks();this.handshakeCallbacks=this.buildHandshakeCallbacks(this.errorCallbacks);var c=this;Pusher.Network.bind("online",function(){c.timeline.info({netinfo:"online"});
79
+ ("connecting"===c.state||"unavailable"===c.state)&&c.retryIn(0)});Pusher.Network.bind("offline",function(){c.timeline.info({netinfo:"offline"});c.connection&&c.sendActivityCheck()});this.updateStrategy()}var c=b.prototype;Pusher.Util.extend(c,Pusher.EventsDispatcher.prototype);c.connect=function(){!this.connection&&!this.runner&&(this.strategy.isSupported()?(this.updateState("connecting"),this.startConnecting(),this.setUnavailableTimer()):this.updateState("failed"))};c.send=function(a){return this.connection?
80
+ this.connection.send(a):!1};c.send_event=function(a,b,c){return this.connection?this.connection.send_event(a,b,c):!1};c.disconnect=function(){this.disconnectInternally();this.updateState("disconnected")};c.isEncrypted=function(){return this.encrypted};c.startConnecting=function(){var a=this,b=function(c,f){c?a.runner=a.strategy.connect(0,b):"error"===f.action?(a.emit("error",{type:"HandshakeError",error:f.error}),a.timeline.error({handshakeError:f.error})):(a.abortConnecting(),a.handshakeCallbacks[f.action](f))};
81
+ a.runner=a.strategy.connect(0,b)};c.abortConnecting=function(){this.runner&&(this.runner.abort(),this.runner=null)};c.disconnectInternally=function(){this.abortConnecting();this.clearRetryTimer();this.clearUnavailableTimer();this.connection&&this.abandonConnection().close()};c.updateStrategy=function(){this.strategy=this.options.getStrategy({key:this.key,timeline:this.timeline,encrypted:this.encrypted})};c.retryIn=function(a){var b=this;b.timeline.info({action:"retry",delay:a});0<a&&b.emit("connecting_in",
82
+ Math.round(a/1E3));b.retryTimer=new Pusher.Timer(a||0,function(){b.disconnectInternally();b.connect()})};c.clearRetryTimer=function(){this.retryTimer&&(this.retryTimer.ensureAborted(),this.retryTimer=null)};c.setUnavailableTimer=function(){var a=this;a.unavailableTimer=new Pusher.Timer(a.options.unavailableTimeout,function(){a.updateState("unavailable")})};c.clearUnavailableTimer=function(){this.unavailableTimer&&this.unavailableTimer.ensureAborted()};c.sendActivityCheck=function(){var a=this;a.stopActivityCheck();
83
+ a.connection.ping();a.activityTimer=new Pusher.Timer(a.options.pongTimeout,function(){a.timeline.error({pong_timed_out:a.options.pongTimeout});a.retryIn(0)})};c.resetActivityCheck=function(){var a=this;a.stopActivityCheck();a.connection.handlesActivityChecks()||(a.activityTimer=new Pusher.Timer(a.activityTimeout,function(){a.sendActivityCheck()}))};c.stopActivityCheck=function(){this.activityTimer&&this.activityTimer.ensureAborted()};c.buildConnectionCallbacks=function(){var a=this;return{message:function(b){a.resetActivityCheck();
84
+ a.emit("message",b)},ping:function(){a.send_event("pusher:pong",{})},activity:function(){a.resetActivityCheck()},error:function(b){a.emit("error",{type:"WebSocketError",error:b})},closed:function(){a.abandonConnection();a.shouldRetry()&&a.retryIn(1E3)}}};c.buildHandshakeCallbacks=function(a){var b=this;return Pusher.Util.extend({},a,{connected:function(a){b.activityTimeout=Math.min(b.options.activityTimeout,a.activityTimeout,a.connection.activityTimeout||Infinity);b.clearUnavailableTimer();b.setConnection(a.connection);
85
+ b.socket_id=b.connection.id;b.updateState("connected",{socket_id:b.socket_id})}})};c.buildErrorCallbacks=function(){function a(a){return function(c){c.error&&b.emit("error",{type:"WebSocketError",error:c.error});a(c)}}var b=this;return{ssl_only:a(function(){b.encrypted=!0;b.updateStrategy();b.retryIn(0)}),refused:a(function(){b.disconnect()}),backoff:a(function(){b.retryIn(1E3)}),retry:a(function(){b.retryIn(0)})}};c.setConnection=function(a){this.connection=a;for(var b in this.connectionCallbacks)this.connection.bind(b,
86
+ this.connectionCallbacks[b]);this.resetActivityCheck()};c.abandonConnection=function(){if(this.connection){this.stopActivityCheck();for(var a in this.connectionCallbacks)this.connection.unbind(a,this.connectionCallbacks[a]);a=this.connection;this.connection=null;return a}};c.updateState=function(a,b){var c=this.state;this.state=a;c!==a&&(Pusher.debug("State changed",c+" -> "+a),this.timeline.info({state:a,params:b}),this.emit("state_change",{previous:c,current:a}),this.emit(a,b))};c.shouldRetry=function(){return"connecting"===
87
+ this.state||"connected"===this.state};Pusher.ConnectionManager=b}).call(this);(function(){function b(){Pusher.EventsDispatcher.call(this);var b=this;void 0!==window.addEventListener&&(window.addEventListener("online",function(){b.emit("online")},!1),window.addEventListener("offline",function(){b.emit("offline")},!1))}Pusher.Util.extend(b.prototype,Pusher.EventsDispatcher.prototype);b.prototype.isOnline=function(){return void 0===window.navigator.onLine?!0:window.navigator.onLine};Pusher.NetInfo=b;
88
+ Pusher.Network=new b}).call(this);(function(){function b(){this.reset()}var c=b.prototype;c.get=function(a){return Object.prototype.hasOwnProperty.call(this.members,a)?{id:a,info:this.members[a]}:null};c.each=function(a){var b=this;Pusher.Util.objectApply(b.members,function(c,f){a(b.get(f))})};c.setMyID=function(a){this.myID=a};c.onSubscription=function(a){this.members=a.presence.hash;this.count=a.presence.count;this.me=this.get(this.myID)};c.addMember=function(a){null===this.get(a.user_id)&&this.count++;
89
+ this.members[a.user_id]=a.user_info;return this.get(a.user_id)};c.removeMember=function(a){var b=this.get(a.user_id);b&&(delete this.members[a.user_id],this.count--);return b};c.reset=function(){this.members={};this.count=0;this.me=this.myID=null};Pusher.Members=b}).call(this);(function(){function b(a,b){Pusher.EventsDispatcher.call(this,function(b,c){Pusher.debug("No callbacks on "+a+" for "+b)});this.name=a;this.pusher=b;this.subscribed=!1}var c=b.prototype;Pusher.Util.extend(c,Pusher.EventsDispatcher.prototype);
90
+ c.authorize=function(a,b){return b(!1,{})};c.trigger=function(a,b){if(0!==a.indexOf("client-"))throw new Pusher.Errors.BadEventName("Event '"+a+"' does not start with 'client-'");return this.pusher.send_event(a,b,this.name)};c.disconnect=function(){this.subscribed=!1};c.handleEvent=function(a,b){0===a.indexOf("pusher_internal:")?"pusher_internal:subscription_succeeded"===a&&(this.subscribed=!0,this.emit("pusher:subscription_succeeded",b)):this.emit(a,b)};c.subscribe=function(){var a=this;a.authorize(a.pusher.connection.socket_id,
91
+ function(b,c){b?a.handleEvent("pusher:subscription_error",c):a.pusher.send_event("pusher:subscribe",{auth:c.auth,channel_data:c.channel_data,channel:a.name})})};c.unsubscribe=function(){this.pusher.send_event("pusher:unsubscribe",{channel:this.name})};Pusher.Channel=b}).call(this);(function(){function b(a,b){Pusher.Channel.call(this,a,b)}var c=b.prototype;Pusher.Util.extend(c,Pusher.Channel.prototype);c.authorize=function(a,b){return(new Pusher.Channel.Authorizer(this,this.pusher.config)).authorize(a,
92
+ b)};Pusher.PrivateChannel=b}).call(this);(function(){function b(a,b){Pusher.PrivateChannel.call(this,a,b);this.members=new Pusher.Members}var c=b.prototype;Pusher.Util.extend(c,Pusher.PrivateChannel.prototype);c.authorize=function(a,b){var c=this;Pusher.PrivateChannel.prototype.authorize.call(c,a,function(a,e){if(!a){if(void 0===e.channel_data){Pusher.warn("Invalid auth response for channel '"+c.name+"', expected 'channel_data' field");b("Invalid auth response");return}var g=JSON.parse(e.channel_data);
93
+ c.members.setMyID(g.user_id)}b(a,e)})};c.handleEvent=function(a,b){switch(a){case "pusher_internal:subscription_succeeded":this.members.onSubscription(b);this.subscribed=!0;this.emit("pusher:subscription_succeeded",this.members);break;case "pusher_internal:member_added":var c=this.members.addMember(b);this.emit("pusher:member_added",c);break;case "pusher_internal:member_removed":(c=this.members.removeMember(b))&&this.emit("pusher:member_removed",c);break;default:Pusher.PrivateChannel.prototype.handleEvent.call(this,
94
+ a,b)}};c.disconnect=function(){this.members.reset();Pusher.PrivateChannel.prototype.disconnect.call(this)};Pusher.PresenceChannel=b}).call(this);(function(){function b(){this.channels={}}var c=b.prototype;c.add=function(a,b){if(!this.channels[a]){var c=this.channels,f;f=0===a.indexOf("private-")?new Pusher.PrivateChannel(a,b):0===a.indexOf("presence-")?new Pusher.PresenceChannel(a,b):new Pusher.Channel(a,b);c[a]=f}return this.channels[a]};c.all=function(a){return Pusher.Util.values(this.channels)};
95
+ c.find=function(a){return this.channels[a]};c.remove=function(a){var b=this.channels[a];delete this.channels[a];return b};c.disconnect=function(){Pusher.Util.objectApply(this.channels,function(a){a.disconnect()})};Pusher.Channels=b}).call(this);(function(){Pusher.Channel.Authorizer=function(b,a){this.channel=b;this.type=a.authTransport;this.options=a;this.authOptions=(a||{}).auth||{}};Pusher.Channel.Authorizer.prototype={composeQuery:function(b){b="socket_id="+encodeURIComponent(b)+"&channel_name="+
96
+ encodeURIComponent(this.channel.name);for(var a in this.authOptions.params)b+="&"+encodeURIComponent(a)+"="+encodeURIComponent(this.authOptions.params[a]);return b},authorize:function(b,a){return Pusher.authorizers[this.type].call(this,b,a)}};var b=1;Pusher.auth_callbacks={};Pusher.authorizers={ajax:function(b,a){var d;d=Pusher.XHR?new Pusher.XHR:window.XMLHttpRequest?new window.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");d.open("POST",this.options.authEndpoint,!0);d.setRequestHeader("Content-Type",
97
+ "application/x-www-form-urlencoded");for(var h in this.authOptions.headers)d.setRequestHeader(h,this.authOptions.headers[h]);d.onreadystatechange=function(){if(4===d.readyState)if(200===d.status){var b,c=!1;try{b=JSON.parse(d.responseText),c=!0}catch(g){a(!0,"JSON returned from webapp was invalid, yet status code was 200. Data was: "+d.responseText)}c&&a(!1,b)}else Pusher.warn("Couldn't get auth info from your webapp",d.status),a(!0,d.status)};d.send(this.composeQuery(b));return d},jsonp:function(c,
98
+ a){void 0!==this.authOptions.headers&&Pusher.warn("Warn","To send headers with the auth request, you must use AJAX, rather than JSONP.");var d=b.toString();b++;var h=Pusher.Util.getDocument(),f=h.createElement("script");Pusher.auth_callbacks[d]=function(b){a(!1,b)};f.src=this.options.authEndpoint+"?callback="+encodeURIComponent("Pusher.auth_callbacks['"+d+"']")+"&"+this.composeQuery(c);d=h.getElementsByTagName("head")[0]||h.documentElement;d.insertBefore(f,d.firstChild)}}}).call(this);return Pusher});