flotype-bridge 0.2.0.beta.1 → 0.2.0.beta.2

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.
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  #Flotype Bridge for Javascript
2
- Flotype Bridge enables cross-language RPC for interserver and client-server communication.
2
+ Flotype Bridge is a unified messaging system that allows you to easily build cross-language services to share data and realtime updates among your servers and your clients
3
3
 
4
4
  ##Installation
5
5
  Quick install: Using [RubyGems](https://rubygems.org/), do `gem install flotype-bridge --pre`
@@ -16,8 +16,8 @@ Clone this repository using `git clone git@bitbucket.org:flotype/bridge-ruby.git
16
16
  loop.
17
17
 
18
18
  ##Documentation and Support
19
- * API Reference: http://www.flotype.com/resources/api
20
- * Getting Started: http://www.flotype.com/resources/gettingstarted
19
+ * API Reference: http://flotype.com/docs/api/ruby/
20
+ * Getting Started: http://www.flotype.com/docs/gettingstarted/ruby/
21
21
  * About Flotype and Flotype Bridge: http://www.flotype.com/
22
22
 
23
23
  The `examples` directory of this library contains sample applications for Flotype Bridge.
@@ -47,7 +47,7 @@
47
47
  <nav id="file-list-section" class="section">
48
48
  <h3 class="section-header">Defined In</h3>
49
49
  <ul>
50
- <li>.\lib\bridge.rb
50
+ <li>lib\bridge.rb
51
51
  </ul>
52
52
  </nav>
53
53
 
@@ -82,6 +82,8 @@
82
82
 
83
83
  <li><a href="#method-i-leave_channel">#leave_channel</a>
84
84
 
85
+ <li><a href="#method-i-on">#on</a>
86
+
85
87
  <li><a href="#method-i-publish_service">#publish_service</a>
86
88
 
87
89
  <li><a href="#method-i-ready">#ready</a>
@@ -192,27 +194,32 @@ server to connect to. Overrides <code>:redirector</code> when both
192
194
 
193
195
 
194
196
  <div class="method-source-code" id="new-source">
195
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 43</span>
197
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 43</span>
196
198
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">options</span> = {})
197
199
 
200
+ <span class="ruby-comment"># Set default options</span>
198
201
  <span class="ruby-ivar">@options</span> = {
199
202
  <span class="ruby-value">:redirector</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-string">'http://redirector.flotype.com'</span>,
200
203
  <span class="ruby-value">:reconnect</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-keyword">true</span>,
201
204
  <span class="ruby-value">:log</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-value">2</span>, <span class="ruby-comment"># 0 for no output</span>
202
205
  }
203
-
206
+
204
207
  <span class="ruby-ivar">@options</span> = <span class="ruby-ivar">@options</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">options</span>)
205
208
 
206
- <span class="ruby-constant">Util</span>.<span class="ruby-identifier">set_log_level</span>(<span class="ruby-ivar">@options</span>[<span class="ruby-value">:log</span>]);
209
+ <span class="ruby-constant">Util</span>.<span class="ruby-identifier">set_log_level</span>(<span class="ruby-ivar">@options</span>[<span class="ruby-value">:log</span>])
207
210
 
208
211
  <span class="ruby-ivar">@store</span> = {}
212
+ <span class="ruby-comment"># Initialize system service call</span>
209
213
  <span class="ruby-ivar">@store</span>[<span class="ruby-string">'system'</span>] = <span class="ruby-constant">SystemService</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword">self</span>)
210
214
 
215
+ <span class="ruby-comment"># Indicates whether server is connected and handshaken</span>
211
216
  <span class="ruby-ivar">@is_ready</span> = <span class="ruby-keyword">false</span>
212
217
 
218
+ <span class="ruby-comment"># Create connection object</span>
213
219
  <span class="ruby-ivar">@connection</span> = <span class="ruby-constant">Connection</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword">self</span>)
214
220
 
215
- <span class="ruby-ivar">@queue</span> = []
221
+ <span class="ruby-comment"># Store event handlers</span>
222
+ <span class="ruby-ivar">@events</span> = {}
216
223
 
217
224
  <span class="ruby-keyword">end</span></pre>
218
225
  </div><!-- new-source -->
@@ -255,7 +262,7 @@ href="Bridge.html">Bridge</a> is connected and ready.</p>
255
262
 
256
263
 
257
264
  <div class="method-source-code" id="connect-source">
258
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 224</span>
265
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 269</span>
259
266
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">connect</span> &amp;<span class="ruby-identifier">callback</span>
260
267
  <span class="ruby-keyword">self</span>.<span class="ruby-identifier">ready</span> &amp;<span class="ruby-identifier">callback</span> <span class="ruby-keyword">if</span> <span class="ruby-identifier">callback</span>
261
268
  <span class="ruby-ivar">@connection</span>.<span class="ruby-identifier">start</span>
@@ -318,8 +325,9 @@ channel name.</p>
318
325
 
319
326
 
320
327
  <div class="method-source-code" id="get_channel-source">
321
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 158</span>
328
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 203</span>
322
329
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">get_channel</span> <span class="ruby-identifier">name</span>, &amp;<span class="ruby-identifier">callback</span>
330
+ <span class="ruby-comment"># Send GETCHANNEL command in order to establih link for channel if client is not member</span>
323
331
  <span class="ruby-ivar">@connection</span>.<span class="ruby-identifier">send_command</span>(<span class="ruby-value">:GETCHANNEL</span>, {<span class="ruby-value">:name</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">name</span>})
324
332
  <span class="ruby-identifier">ref</span> = <span class="ruby-constant">Reference</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword">self</span>, [<span class="ruby-string">'channel'</span>, <span class="ruby-identifier">name</span>, <span class="ruby-node">&quot;channel:#{name}&quot;</span>])
325
333
  <span class="ruby-identifier">callback</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">ref</span>, <span class="ruby-identifier">name</span>) <span class="ruby-keyword">if</span> <span class="ruby-identifier">callback</span>
@@ -382,7 +390,7 @@ service name.</p>
382
390
 
383
391
 
384
392
  <div class="method-source-code" id="get_service-source">
385
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 134</span>
393
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 179</span>
386
394
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">get_service</span> <span class="ruby-identifier">name</span>, &amp;<span class="ruby-identifier">callback</span>
387
395
  <span class="ruby-identifier">ref</span> = <span class="ruby-constant">Reference</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword">self</span>, [<span class="ruby-string">'named'</span>, <span class="ruby-identifier">name</span>, <span class="ruby-identifier">name</span>])
388
396
  <span class="ruby-identifier">callback</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">ref</span>, <span class="ruby-identifier">name</span>) <span class="ruby-keyword">if</span> <span class="ruby-identifier">callback</span>
@@ -439,7 +447,7 @@ channel</p>
439
447
 
440
448
 
441
449
  <div class="method-source-code" id="join_channel-source">
442
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 179</span>
450
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 225</span>
443
451
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">join_channel</span> <span class="ruby-identifier">name</span>, <span class="ruby-identifier">handler</span>, &amp;<span class="ruby-identifier">callback</span>
444
452
  <span class="ruby-ivar">@connection</span>.<span class="ruby-identifier">send_command</span>(<span class="ruby-value">:JOINCHANNEL</span>, {<span class="ruby-value">:name</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">name</span>, <span class="ruby-value">:handler</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-constant">Serializer</span>.<span class="ruby-identifier">serialize</span>(<span class="ruby-keyword">self</span>, <span class="ruby-identifier">handler</span>), <span class="ruby-value">:callback</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-constant">Serializer</span>.<span class="ruby-identifier">serialize</span>(<span class="ruby-keyword">self</span>, <span class="ruby-identifier">callback</span>)})
445
453
  <span class="ruby-keyword">end</span></pre>
@@ -499,7 +507,7 @@ calls from the channel</p>
499
507
 
500
508
 
501
509
  <div class="method-source-code" id="leave_channel-source">
502
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 198</span>
510
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 244</span>
503
511
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">leave_channel</span> <span class="ruby-identifier">channel</span>, <span class="ruby-identifier">handler</span>, &amp;<span class="ruby-identifier">callback</span>
504
512
  <span class="ruby-ivar">@connection</span>.<span class="ruby-identifier">send_command</span>(<span class="ruby-value">:LEAVECHANNEL</span>, {<span class="ruby-value">:name</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">name</span>, <span class="ruby-value">:handler</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-constant">Serializer</span>.<span class="ruby-identifier">serialize</span>(<span class="ruby-keyword">self</span>, <span class="ruby-identifier">handler</span>), <span class="ruby-value">:callback</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-constant">Serializer</span>.<span class="ruby-identifier">serialize</span>(<span class="ruby-keyword">self</span>, <span class="ruby-identifier">callback</span>)})
505
513
  <span class="ruby-keyword">end</span></pre>
@@ -513,6 +521,65 @@ calls from the channel</p>
513
521
  </div><!-- leave_channel-method -->
514
522
 
515
523
 
524
+ <div id="method-i-on" class="method-detail ">
525
+
526
+
527
+ <div class="method-heading">
528
+ <span class="method-callseq">
529
+ on(name) { |*args| block }
530
+ </span>
531
+
532
+ <span class="method-click-advice">click to toggle source</span>
533
+
534
+ </div>
535
+
536
+
537
+
538
+ <div class="method-description">
539
+
540
+ <p>Adds the given block as a handler for the event specified by
541
+ <code>name</code>. Calling multiple times will result in multiple handlers
542
+ being attached to the event</p>
543
+
544
+ <h3 id="method-i-on-label-Attributes++">Attributes </h3>
545
+ <dl class="rdoc-list note-list"><dt><code>name</code>
546
+ <dd>
547
+ <p>The name of the event for the given block to listen to</p>
548
+ </dd></dl>
549
+
550
+ <h3 id="method-i-on-label-Events++">Events </h3>
551
+
552
+ <p>List of events <a href="Bridge.html">Bridge</a> emits</p>
553
+ <dl class="rdoc-list note-list"><dt><code>'ready' ()</code>
554
+ <dd>
555
+ <p><a href="Bridge.html">Bridge</a> is connected and ready. Not emitted on
556
+ reconnects</p>
557
+ </dd><dt><code>'remoteError' (error_message)</code>
558
+ <dd>
559
+ <p>A remote error has occurred in <a href="Bridge.html">Bridge</a>. The error
560
+ message is provided as a parameter</p>
561
+ </dd></dl>
562
+
563
+
564
+
565
+ <div class="method-source-code" id="on-source">
566
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 121</span>
567
+ <span class="ruby-keyword">def</span> <span class="ruby-identifier">on</span> <span class="ruby-identifier">name</span>, &amp;<span class="ruby-identifier">fn</span>
568
+ <span class="ruby-keyword">if</span> <span class="ruby-operator">!</span><span class="ruby-ivar">@events</span>.<span class="ruby-identifier">key?</span> <span class="ruby-identifier">name</span>
569
+ <span class="ruby-ivar">@events</span>[<span class="ruby-identifier">name</span>] = [];
570
+ <span class="ruby-keyword">end</span>
571
+ <span class="ruby-ivar">@events</span>[<span class="ruby-identifier">name</span>] <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">fn</span>
572
+ <span class="ruby-keyword">end</span></pre>
573
+ </div><!-- on-source -->
574
+
575
+ </div>
576
+
577
+
578
+
579
+
580
+ </div><!-- on-method -->
581
+
582
+
516
583
  <div id="method-i-publish_service" class="method-detail ">
517
584
 
518
585
 
@@ -548,7 +615,7 @@ be published with</p>
548
615
 
549
616
 
550
617
  <div class="method-source-code" id="publish_service-source">
551
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 107</span>
618
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 152</span>
552
619
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">publish_service</span> <span class="ruby-identifier">name</span>, <span class="ruby-identifier">handler</span>, &amp;<span class="ruby-identifier">callback</span>
553
620
  <span class="ruby-keyword">if</span> <span class="ruby-identifier">name</span> <span class="ruby-operator">==</span> <span class="ruby-string">'system'</span>
554
621
  <span class="ruby-constant">Util</span>.<span class="ruby-identifier">error</span>(<span class="ruby-node">&quot;Invalid service name: #{name}&quot;</span>)
@@ -590,13 +657,12 @@ href="Bridge.html">Bridge</a> is already ready.</p>
590
657
 
591
658
 
592
659
  <div class="method-source-code" id="ready-source">
593
- <pre><span class="ruby-comment"># File .\lib\bridge.rb, line 208</span>
660
+ <pre><span class="ruby-comment"># File lib\bridge.rb, line 254</span>
594
661
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">ready</span> &amp;<span class="ruby-identifier">callback</span>
595
- <span class="ruby-identifier">puts</span> <span class="ruby-string">'adding'</span>
596
662
  <span class="ruby-keyword">if</span> <span class="ruby-ivar">@is_ready</span>
597
663
  <span class="ruby-identifier">callback</span>.<span class="ruby-identifier">call</span>
598
664
  <span class="ruby-keyword">else</span>
599
- <span class="ruby-ivar">@queue</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">callback</span>
665
+ <span class="ruby-identifier">on</span> <span class="ruby-string">'ready'</span>, &amp;<span class="ruby-identifier">callback</span>
600
666
  <span class="ruby-keyword">end</span>
601
667
  <span class="ruby-keyword">end</span></pre>
602
668
  </div><!-- ready-source -->
data/doc/Bridge.html CHANGED
@@ -47,7 +47,7 @@
47
47
  <nav id="file-list-section" class="section">
48
48
  <h3 class="section-header">Defined In</h3>
49
49
  <ul>
50
- <li>.\lib\bridge.rb
50
+ <li>lib\bridge.rb
51
51
  </ul>
52
52
  </nav>
53
53
 
data/doc/created.rid CHANGED
@@ -1,2 +1,2 @@
1
- Fri, 23 Mar 2012 13:01:16 -0700
2
- .\lib\bridge.rb Fri, 23 Mar 2012 13:01:02 -0700
1
+ Sat, 07 Apr 2012 02:37:02 -0700
2
+ lib\bridge.rb Sat, 07 Apr 2012 02:36:34 -0700
@@ -1 +1 @@
1
- var search_data = {"index":{"searchIndex":["bridge","bridge","connect()","get_channel()","get_service()","join_channel()","leave_channel()","new()","publish_service()","ready()"],"longSearchIndex":["bridge","bridge::bridge","bridge::bridge#connect()","bridge::bridge#get_channel()","bridge::bridge#get_service()","bridge::bridge#join_channel()","bridge::bridge#leave_channel()","bridge::bridge::new()","bridge::bridge#publish_service()","bridge::bridge#ready()"],"info":[["Bridge","","Bridge.html","","<p>Flotype Bridge\n<p>Bridge is a cross-language and platform framework for realtime\ncommunication and RPC\n<p>The ...\n"],["Bridge::Bridge","","Bridge/Bridge.html","",""],["connect","Bridge::Bridge","Bridge/Bridge.html#method-i-connect","(&callback)","<p>Starts the connection to the Bridge server.\n<p>If a block is given, calls the given block when Bridge is ...\n"],["get_channel","Bridge::Bridge","Bridge/Bridge.html#method-i-get_channel","(name, &callback)","<p>Retrives a channel from Bridge with the given name.\n<p>Calling a method on the channel object will result ...\n"],["get_service","Bridge::Bridge","Bridge/Bridge.html#method-i-get_service","(name, &callback)","<p>Retrives a service published to Bridge with the given name.\n<p>If multiple Bridge clients have a published ...\n"],["join_channel","Bridge::Bridge","Bridge/Bridge.html#method-i-join_channel","(name, handler, &callback)","<p>Provides a remote object, ruby object or module as a receiver for methods\ncalls on a Bridge channel. ...\n"],["leave_channel","Bridge::Bridge","Bridge/Bridge.html#method-i-leave_channel","(channel, handler, &callback)","<p>Leaves a Bridge channel with the given name and handler object.\n<p>The given handler can be a remote object, ...\n"],["new","Bridge::Bridge","Bridge/Bridge.html#method-c-new","(options = {})","<p>Create an instance of the Bridge object. This object will be used for\nBridge interactions\n<p>Bridge#connect ...\n"],["publish_service","Bridge::Bridge","Bridge/Bridge.html#method-i-publish_service","(name, handler, &callback)","<p>Publishes a ruby object or module as a Bridge service with the given name.\n<p>If a block is given, calls ...\n"],["ready","Bridge::Bridge","Bridge/Bridge.html#method-i-ready","(&callback)","<p>Calls the given block when Bridge is connected and ready. Calls the given\nblock immediately if Bridge ...\n"]]}}
1
+ var search_data = {"index":{"searchIndex":["bridge","bridge","connect()","get_channel()","get_service()","join_channel()","leave_channel()","new()","on()","publish_service()","ready()"],"longSearchIndex":["bridge","bridge::bridge","bridge::bridge#connect()","bridge::bridge#get_channel()","bridge::bridge#get_service()","bridge::bridge#join_channel()","bridge::bridge#leave_channel()","bridge::bridge::new()","bridge::bridge#on()","bridge::bridge#publish_service()","bridge::bridge#ready()"],"info":[["Bridge","","Bridge.html","","<p>Flotype Bridge\n<p>Bridge is a cross-language and platform framework for realtime\ncommunication and RPC\n<p>The ...\n"],["Bridge::Bridge","","Bridge/Bridge.html","",""],["connect","Bridge::Bridge","Bridge/Bridge.html#method-i-connect","(&callback)","<p>Starts the connection to the Bridge server.\n<p>If a block is given, calls the given block when Bridge is ...\n"],["get_channel","Bridge::Bridge","Bridge/Bridge.html#method-i-get_channel","(name, &callback)","<p>Retrives a channel from Bridge with the given name.\n<p>Calling a method on the channel object will result ...\n"],["get_service","Bridge::Bridge","Bridge/Bridge.html#method-i-get_service","(name, &callback)","<p>Retrives a service published to Bridge with the given name.\n<p>If multiple Bridge clients have a published ...\n"],["join_channel","Bridge::Bridge","Bridge/Bridge.html#method-i-join_channel","(name, handler, &callback)","<p>Provides a remote object, ruby object or module as a receiver for methods\ncalls on a Bridge channel. ...\n"],["leave_channel","Bridge::Bridge","Bridge/Bridge.html#method-i-leave_channel","(channel, handler, &callback)","<p>Leaves a Bridge channel with the given name and handler object.\n<p>The given handler can be a remote object, ...\n"],["new","Bridge::Bridge","Bridge/Bridge.html#method-c-new","(options = {})","<p>Create an instance of the Bridge object. This object will be used for\nBridge interactions\n<p>Bridge#connect ...\n"],["on","Bridge::Bridge","Bridge/Bridge.html#method-i-on","(name, &fn)","<p>Adds the given block as a handler for the event specified by\n<code>name</code>. Calling multiple times will result ...\n"],["publish_service","Bridge::Bridge","Bridge/Bridge.html#method-i-publish_service","(name, handler, &callback)","<p>Publishes a ruby object or module as a Bridge service with the given name.\n<p>If a block is given, calls ...\n"],["ready","Bridge::Bridge","Bridge/Bridge.html#method-i-ready","(&callback)","<p>Calls the given block when Bridge is connected and ready. Calls the given\nblock immediately if Bridge ...\n"]]}}
@@ -55,6 +55,8 @@
55
55
 
56
56
  <li class="method"><a href="Bridge/Bridge.html#method-i-leave_channel">#leave_channel &mdash; Bridge::Bridge</a>
57
57
 
58
+ <li class="method"><a href="Bridge/Bridge.html#method-i-on">#on &mdash; Bridge::Bridge</a>
59
+
58
60
  <li class="method"><a href="Bridge/Bridge.html#method-i-publish_service">#publish_service &mdash; Bridge::Bridge</a>
59
61
 
60
62
  <li class="method"><a href="Bridge/Bridge.html#method-i-ready">#ready &mdash; Bridge::Bridge</a>
@@ -0,0 +1,21 @@
1
+ require 'bridge'
2
+
3
+ EventMachine.run do
4
+
5
+ bridge = Bridge::Bridge.new(:api_key => 'myapikey')
6
+
7
+ class ChatHandler
8
+ def message sender, msg
9
+ puts "#{sender}: #{msg}"
10
+ end
11
+ end
12
+
13
+ bridge.connect
14
+
15
+ auth = bridge.get_service('auth')
16
+ auth.join('flotype-lovers', 'secret123', ChatHandler.new) do |channel, name|
17
+ puts "Joined: #{name}"
18
+ channel.message('steve', 'Flotype Bridge is nifty')
19
+ end
20
+
21
+ end
@@ -0,0 +1,24 @@
1
+ require 'bridge'
2
+
3
+ EventMachine.run do
4
+
5
+ bridge = Bridge::Bridge.new(:api_key => 'myapikey')
6
+
7
+ class AuthHandler
8
+ def initialize bridge
9
+ @bridge = bridge
10
+ end
11
+
12
+ def join name, password, handler, &callback
13
+ if password == 'secret123'
14
+ @bridge.join_channel(name, handler, &callback)
15
+ puts 'Welcome!'
16
+ else
17
+ puts 'Sorry!'
18
+ end
19
+ end
20
+ end
21
+
22
+ bridge.connect
23
+ bridge.publish_service('auth', AuthHandler.new(bridge))
24
+ end
@@ -0,0 +1,47 @@
1
+ require 'bridge'
2
+
3
+ EventMachine.run do
4
+ bridge = Bridge::Bridge.new(:api_key => 'myapikey')
5
+ bridge.connect
6
+
7
+
8
+ #
9
+ # Joining a Bridge channel
10
+ #
11
+ # In order to join a Bridge channel, clients must provide the name
12
+ # of the channel to join and a handler object on which RPC calls
13
+ # in the channel will act on. Note that the client that is joined
14
+ # to the channel is whoever created the handler, not necessarily the
15
+ # client executing the join command. This means clients can join other
16
+ # clients to channels by having a reference to an object of theirs.
17
+ #
18
+ # Only Bridge clients using the private API key may call the join command.
19
+ # However, those clients may join other clients using the public API key on their behalf.
20
+ #
21
+ class TestHandler
22
+ def log msg
23
+ puts "Got message: #{msg}"
24
+ end
25
+ end
26
+
27
+ bridge.join_channel 'testChannel', TestHandler.new do
28
+ ready bridge
29
+ end
30
+
31
+ def ready bridge
32
+ #
33
+ # Getting and calling a Bridge channel
34
+ #
35
+ # This can be done from any Bridge client connected to the same
36
+ # Bridge server, regardless of language.
37
+ # When a function call is made to a channel object, the requested
38
+ # function will be executed on everyone in the channel
39
+ #
40
+ # Only Bridge clients using the private API key may call the join command.
41
+ #
42
+ bridge.get_channel 'testChannel' do |testChannel, name|
43
+ puts 'Sending message'
44
+ testChannel.log 'hello'
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ require 'bridge'
2
+
3
+ EventMachine.run do
4
+ bridge = Bridge::Bridge.new(:api_key => 'myapikey')
5
+ bridge.connect
6
+
7
+
8
+ #
9
+ # Publishing a Bridge service
10
+ #
11
+ # Any Javascript object can be published. A published service
12
+ # can be retrieved by any Bridge client with the same API key pair.
13
+ #
14
+ # Only Bridge clients using the prviate API key may publish services.
15
+ #
16
+ class TestService
17
+ def ping
18
+ puts 'Received ping request!'
19
+ yield 'Pong'
20
+ end
21
+ end
22
+
23
+ bridge.publish_service 'testService', TestService.new
24
+
25
+
26
+
27
+ #
28
+ # Retrieving a Bridge service
29
+ #
30
+ # This can be done from any Bridge client connected to the same
31
+ # Bridge server, regardless of language.
32
+ # If multiple clients publish a Bridge service, getService will
33
+ # retrieve from the publisher with the least load.
34
+ #
35
+ bridge.get_service 'testService' do |testService, name|
36
+ puts 'Sending ping request'
37
+ testService.ping do |msg|
38
+ puts msg
39
+ end
40
+ end
41
+ end
data/lib/bridge.rb CHANGED
@@ -17,7 +17,7 @@ module Bridge
17
17
 
18
18
  class Bridge
19
19
 
20
- attr_accessor :options, :connection, :queue, :store, :is_ready #:nodoc:
20
+ attr_accessor :options, :connection, :store, :is_ready #:nodoc:
21
21
 
22
22
  # :call-seq:
23
23
  # new(options={})
@@ -63,8 +63,8 @@ module Bridge
63
63
  # Create connection object
64
64
  @connection = Connection.new(self)
65
65
 
66
- # Store ready event handler
67
- @queue = []
66
+ # Store event handlers
67
+ @events = {}
68
68
 
69
69
  end
70
70
 
@@ -103,6 +103,36 @@ module Bridge
103
103
  Reference.new(self, ['client', @connection.client_id, name], ops)
104
104
  end
105
105
 
106
+ # :call-seq:
107
+ # on(name) { |*args| block }
108
+ #
109
+ # Adds the given block as a handler for the event specified by <tt>name</tt>. Calling multiple times will result in multiple handlers being attached to the event
110
+ #
111
+ # === Attributes
112
+ #
113
+ # +name+:: The name of the event for the given block to listen to
114
+ #
115
+ # === Events
116
+ #
117
+ # List of events Bridge emits
118
+ #
119
+ # <tt>'ready' ()</tt>:: Bridge is connected and ready. Not emitted on reconnects
120
+ # <tt>'remoteError' (error_message)</tt>:: A remote error has occurred in Bridge. The error message is provided as a parameter
121
+ def on name, &fn
122
+ if !@events.key? name
123
+ @events[name] = [];
124
+ end
125
+ @events[name] << fn
126
+ end
127
+
128
+ def emit name, args=[] #:nodoc:
129
+ if @events.key? name
130
+ @events[name].each do |fn|
131
+ fn.call *args
132
+ end
133
+ end
134
+ end
135
+
106
136
  def send args, destination #:nodoc:
107
137
  @connection.send_command(:SEND, { :args => Serializer.serialize(self, args), :destination => destination })
108
138
  end
@@ -225,7 +255,7 @@ module Bridge
225
255
  if @is_ready
226
256
  callback.call
227
257
  else
228
- @queue << callback
258
+ on 'ready', &callback
229
259
  end
230
260
  end
231
261
 
@@ -246,21 +276,21 @@ module Bridge
246
276
  # Erlang gateway.
247
277
  class SystemService #:nodoc:
248
278
  def initialize bridge
249
- @store = bridge.store
279
+ @bridge = bridge
250
280
  end
251
281
 
252
282
  def hookChannelHandler name, handler, callback = nil
253
283
  # Retrieve requested handler
254
- obj = @store[handler.address[2]]
284
+ obj = @bridge.store[handler.address[2]]
255
285
  # Store under channel name
256
- @store["channel:#{name}"] = obj
286
+ @bridge.store["channel:#{name}"] = obj
257
287
  # Send callback with reference to channel and handler operations
258
288
  callback.call(Reference.new(self, ['channel', name, "channel:#{name}"], Util.find_ops(obj)), name) if callback
259
289
  end
260
290
 
261
291
  def getService name, callback
262
- if @store.key? name
263
- callback.call(@store[name], name)
292
+ if @bridge.store.key? name
293
+ callback.call(@bridge.store[name], name)
264
294
  else
265
295
  callback.call(nil, name)
266
296
  end
@@ -268,6 +298,7 @@ module Bridge
268
298
 
269
299
  def remoteError msg
270
300
  Util.warn msg
301
+ @bridge.emit 'remote_error', [msg]
271
302
  end
272
303
  end
273
304
 
data/lib/connection.rb CHANGED
@@ -81,10 +81,8 @@ module Bridge
81
81
  Util.info('Handshake complete')
82
82
  # Trigger ready callback
83
83
  if not @bridge.is_ready
84
- @bridge.queue.each do |fun|
85
- fun.call
86
- end
87
84
  @bridge.is_ready = true
85
+ @bridge.emit 'ready'
88
86
  end
89
87
  end
90
88
  end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Bridge
2
- VERSION = "0.2.0.beta.1"
2
+ VERSION = "0.2.0.beta.2"
3
3
  end
metadata CHANGED
@@ -1,68 +1,98 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: flotype-bridge
3
- version: !ruby/object:Gem::Version
4
- version: 0.2.0.beta.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 62196359
5
5
  prerelease: 6
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ - beta
11
+ - 2
12
+ version: 0.2.0.beta.2
6
13
  platform: ruby
7
- authors:
14
+ authors:
8
15
  - Flotype
9
16
  autorequire:
10
17
  bindir: bin
11
18
  cert_chain: []
12
- date: 2012-04-06 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
19
+
20
+ date: 2012-04-20 00:00:00 Z
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
15
23
  name: eventmachine
16
- requirement: &70366802877940 !ruby/object:Gem::Requirement
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
17
26
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 47
31
+ segments:
32
+ - 0
33
+ - 12
34
+ - 0
21
35
  version: 0.12.0
22
36
  type: :runtime
23
- prerelease: false
24
- version_requirements: *70366802877940
25
- - !ruby/object:Gem::Dependency
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
26
39
  name: json
27
- requirement: &70366802877100 !ruby/object:Gem::Requirement
40
+ prerelease: false
41
+ requirement: &id002 !ruby/object:Gem::Requirement
28
42
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 3
47
+ segments:
48
+ - 1
49
+ - 5
50
+ - 0
32
51
  version: 1.5.0
33
52
  type: :runtime
34
- prerelease: false
35
- version_requirements: *70366802877100
36
- - !ruby/object:Gem::Dependency
53
+ version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
37
55
  name: yard
38
- requirement: &70366802876120 !ruby/object:Gem::Requirement
56
+ prerelease: false
57
+ requirement: &id003 !ruby/object:Gem::Requirement
39
58
  none: false
40
- requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 7
63
+ segments:
64
+ - 0
65
+ - 7
66
+ - 2
43
67
  version: 0.7.2
44
68
  type: :development
45
- prerelease: false
46
- version_requirements: *70366802876120
47
- - !ruby/object:Gem::Dependency
69
+ version_requirements: *id003
70
+ - !ruby/object:Gem::Dependency
48
71
  name: rake-compiler
49
- requirement: &70366802875420 !ruby/object:Gem::Requirement
72
+ prerelease: false
73
+ requirement: &id004 !ruby/object:Gem::Requirement
50
74
  none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 17
79
+ segments:
80
+ - 0
81
+ - 7
82
+ - 9
54
83
  version: 0.7.9
55
84
  type: :development
56
- prerelease: false
57
- version_requirements: *70366802875420
85
+ version_requirements: *id004
58
86
  description: Ruby client for Flotype Bridge.
59
- email:
87
+ email:
60
88
  - team@flotype.com
61
89
  executables: []
90
+
62
91
  extensions: []
63
- extra_rdoc_files:
92
+
93
+ extra_rdoc_files:
64
94
  - README.md
65
- files:
95
+ files:
66
96
  - LICENSE
67
97
  - README.md
68
98
  - Rakefile
@@ -102,15 +132,10 @@ files:
102
132
  - doc/js/searcher.js
103
133
  - doc/rdoc.css
104
134
  - doc/table_of_contents.html
105
- - examples/chat/chat_client.rb
106
- - examples/chat/chat_server.rb
107
- - examples/chat/public/css/style.css
108
- - examples/chat/public/js/all.js
109
- - examples/chat/public/js/bridge.min.js
110
- - examples/chat/public/js/index.js
111
- - examples/chat/views/index.erb
112
- - examples/chat/views/layout.erb
113
- - examples/pong/pong.rb
135
+ - examples/chat/chatclient.rb
136
+ - examples/chat/chatserver.rb
137
+ - examples/simple/channels.rb
138
+ - examples/simple/services.rb
114
139
  - flotype-bridge.gemspec
115
140
  - lib/bridge.rb
116
141
  - lib/connection.rb
@@ -135,32 +160,43 @@ files:
135
160
  - test/unit/test_util.rb
136
161
  homepage: http://flotype.com
137
162
  licenses: []
163
+
138
164
  post_install_message:
139
- rdoc_options:
165
+ rdoc_options:
140
166
  - --title
141
167
  - Bridge
142
168
  - --main
143
169
  - README.md
144
170
  - -x
145
171
  - lib/bb/version
146
- require_paths:
172
+ require_paths:
147
173
  - lib
148
- required_ruby_version: !ruby/object:Gem::Requirement
174
+ required_ruby_version: !ruby/object:Gem::Requirement
149
175
  none: false
150
- requirements:
151
- - - ! '>='
152
- - !ruby/object:Gem::Version
153
- version: '0'
154
- required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ hash: 3
180
+ segments:
181
+ - 0
182
+ version: "0"
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
184
  none: false
156
- requirements:
157
- - - ! '>'
158
- - !ruby/object:Gem::Version
185
+ requirements:
186
+ - - ">"
187
+ - !ruby/object:Gem::Version
188
+ hash: 25
189
+ segments:
190
+ - 1
191
+ - 3
192
+ - 1
159
193
  version: 1.3.1
160
194
  requirements: []
195
+
161
196
  rubyforge_project:
162
- rubygems_version: 1.8.10
197
+ rubygems_version: 1.8.7
163
198
  signing_key:
164
199
  specification_version: 3
165
200
  summary: Ruby/Bridge library
166
201
  test_files: []
202
+
@@ -1,21 +0,0 @@
1
- require 'bridge'
2
-
3
- EventMachine.run do
4
-
5
- bridge = Bridge::Bridge.new(:api_key => 'abcdefgh', :log => 5)
6
-
7
- class ChatHandler
8
- def message sender, msg
9
- print sender, ":", msg
10
- end
11
- end
12
-
13
- bridge.connect
14
-
15
- auth = bridge.get_service('auth')
16
- auth.join('flotype-lovers', 'secret123', ChatHandler.new) do |channel, name|
17
- print "Joined: ", name
18
- end
19
-
20
- end
21
-
@@ -1,24 +0,0 @@
1
- require 'bridge'
2
-
3
- EventMachine.run do
4
-
5
- bridge = Bridge::Bridge.new(:api_key => 'abcdefgh')
6
-
7
- class AuthHandler
8
- def initialize bridge
9
- @bridge = bridge
10
- end
11
-
12
- def join name, password, handler, &callback
13
- if password == 'secret123'
14
- @bridge.join_channel(name, handler, &callback)
15
- puts 'Welcome!'
16
- else
17
- puts 'Sorry!'
18
- end
19
- end
20
- end
21
-
22
- bridge.connect
23
- bridge.publish_service('auth', AuthHandler.new(bridge))
24
- end
@@ -1,4 +0,0 @@
1
- html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{font-size:100%;}
2
- a {outline: none;} /* Gets rid of Firefox's dotted borders */
3
- a img {border: none;} /* Gets rid of IE's blue borders */
4
-
@@ -1,5 +0,0 @@
1
- var bridge;
2
- $(function(){
3
- bridge = new Bridge({ apiKey: "abcdefgh" }).connect();
4
- });
5
-
@@ -1,2 +0,0 @@
1
- /*! bridge.min.js build:0.0.1, production. Copyright(c) 2011 Flotype <team@flotype.com> MIT Licensed */
2
- function Reference(a,b,c){var d=this;for(var e in c){var f=c[e];f&&(this[f]=function(a,b){return function(){var c=[].slice.apply(arguments);a._call(b,c)}}(this,f))}this._operations=c||[],this._bridge=a,this._address=b}function Connection(a){var b=this;this.bridge=a,this.options=a._options,this.sockBuffer=new SockBuffer,this.sock=this.sockBuffer,this.interval=400}function SockBuffer(){this.buffer=[]}function Bridge(a){var b=this,c={redirector:"http://redirector.flotype.com",reconnect:!0,log:2,tcp:!1},d={hookChannelHandler:function(a,c,d){var e=b._store[c._address[2]];b._store["channel:"+a]=e;if(d){var f=new Reference(b,["channel",a,"channel:"+a],util.findOps(e));d(f,a)}},getService:function(a,c){util.hasProp(b._store,a)?c(b._store[a],a):c(null,a)},remoteError:function(a){util.warn(a),b.emit("remoteError",[a])}};this._options=util.extend(c,a),util.setLogLevel(this._options.log),this._store={system:d},this._ready=!1,this._connection=new Connection(this),this._events={}}var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";return e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g,e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]=="string"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));return e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g,e}}function quote(a){return escapable.lastIndex=0,escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),typeof reviver=="function"?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(),SockJS=function(){var a=document,b=window,c=function(){};c.prototype.addEventListener=function(a,b){this._listeners||(this._listeners={}),a in this._listeners||(this._listeners[a]=[]);var c=this._listeners[a];e.arrIndexOf(c,b)===-1&&c.push(b);return},c.prototype.removeEventListener=function(a,b){if(!(this._listeners&&a in this._listeners))return;var c=this._listeners[a],d=e.arrIndexOf(c,b);if(d!==-1){c.length>1?this._listeners[a]=c.slice(0,d).concat(c.slice(d+1)):delete this._listeners[a];return}return},c.prototype.dispatchEvent=function(a){var b=a.type,c=Array.prototype.slice.call(arguments,0);this["on"+b]&&this["on"+b].apply(this,c);if(this._listeners&&b in this._listeners)for(var d=0;d<this._listeners[b].length;d++)this._listeners[b][d].apply(this,c)};var d=function(a,b){this.type=a;if(typeof b!="undefined")for(var c in b){if(!b.hasOwnProperty(c))continue;this[c]=b[c]}};d.prototype.toString=function(){var a=[];for(var b in this){if(!this.hasOwnProperty(b))continue;var c=this[b];typeof c=="function"&&(c="[function]"),a.push(b+"="+c)}return"SimpleEvent("+a.join(", ")+")"};var e={},f="abcdefghijklmnopqrstuvwxyz0123456789_";e.random_string=function(a,b){b=b||f.length;var c,d=[];for(c=0;c<a;c++)d.push(f.substr(Math.floor(Math.random()*b),1));return d.join("")},e.random_number=function(a){return Math.floor(Math.random()*a)},e.random_number_string=function(a){var b=(""+(a-1)).length,c=Array(b+1).join("0");return(c+e.random_number(a)).slice(-b)},e.getOrigin=function(a){a+="/";var b=a.split("/").slice(0,3);return b.join("/")},e.objectExtend=function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a};var g="_jp";e.polluteGlobalNamespace=function(){g in b||(b[g]={})},e.closeFrame=function(a,b){return"c"+JSON.stringify([a,b])},e.userSetCode=function(a){return a===1e3||a>=3e3&&a<=4999},e.log=function(){b.console&&console.log&&console.log.apply&&console.log.apply(console,arguments)},e.bind=function(a,b){return a.bind?a.bind(b):function(){return a.apply(b,arguments)}},e.amendUrl=function(b){var c=a.location;if(!b)throw new Error("Wrong url for SockJS");return b.indexOf("//")===0&&(b=c.protocol+b),b.indexOf("/")===0&&(b=c.protocol+"//"+c.host+b),b=b.replace(/[/]+$/,""),b},e.arrIndexOf=function(a,b){for(var c=0;c<a.length;c++)if(a[c]===b)return c;return-1},e.delay=function(a,b){return typeof a=="function"&&(b=a,a=0),setTimeout(b,a)};var h=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,i={"\0":"\\u0000","":"\\u0001","":"\\u0002","":"\\u0003","":"\\u0004","":"\\u0005","":"\\u0006","":"\\u0007","\b":"\\b","\t":"\\t","\n":"\\n"," ":"\\u000b","\f":"\\f","\r":"\\r","":"\\u000e","":"\\u000f","":"\\u0010","":"\\u0011","":"\\u0012","":"\\u0013","":"\\u0014","":"\\u0015","":"\\u0016","":"\\u0017","":"\\u0018","":"\\u0019","":"\\u001a","":"\\u001b","":"\\u001c","":"\\u001d","":"\\u001e","":"\\u001f",'"':'\\"',"\\":"\\\\","":"\\u007f","\u0080":"\\u0080","\u0081":"\\u0081","\u0082":"\\u0082","\u0083":"\\u0083","\u0084":"\\u0084","\u0085":"\\u0085","\u0086":"\\u0086","\u0087":"\\u0087","\u0088":"\\u0088","\u0089":"\\u0089","\u008a":"\\u008a","\u008b":"\\u008b","\u008c":"\\u008c","\u008d":"\\u008d","\u008e":"\\u008e","\u008f":"\\u008f","\u0090":"\\u0090","\u0091":"\\u0091","\u0092":"\\u0092","\u0093":"\\u0093","\u0094":"\\u0094","\u0095":"\\u0095","\u0096":"\\u0096","\u0097":"\\u0097","\u0098":"\\u0098","\u0099":"\\u0099","\u009a":"\\u009a","\u009b":"\\u009b","\u009c":"\\u009c","\u009d":"\\u009d","\u009e":"\\u009e","\u009f":"\\u009f","\u00ad":"\\u00ad","\u0600":"\\u0600","\u0601":"\\u0601","\u0602":"\\u0602","\u0603":"\\u0603","\u0604":"\\u0604","\u070f":"\\u070f","\u17b4":"\\u17b4","\u17b5":"\\u17b5","\u200c":"\\u200c","\u200d":"\\u200d","\u200e":"\\u200e","\u200f":"\\u200f","\u2028":"\\u2028","\u2029":"\\u2029","\u202a":"\\u202a","\u202b":"\\u202b","\u202c":"\\u202c","\u202d":"\\u202d","\u202e":"\\u202e","\u202f":"\\u202f","\u2060":"\\u2060","\u2061":"\\u2061","\u2062":"\\u2062","\u2063":"\\u2063","\u2064":"\\u2064","\u2065":"\\u2065","\u2066":"\\u2066","\u2067":"\\u2067","\u2068":"\\u2068","\u2069":"\\u2069","\u206a":"\\u206a","\u206b":"\\u206b","\u206c":"\\u206c","\u206d":"\\u206d","\u206e":"\\u206e","\u206f":"\\u206f","\ufeff":"\\ufeff","\ufff0":"\\ufff0","\ufff1":"\\ufff1","\ufff2":"\\ufff2","\ufff3":"\\ufff3","\ufff4":"\\ufff4","\ufff5":"\\ufff5","\ufff6":"\\ufff6","\ufff7":"\\ufff7","\ufff8":"\\ufff8","\ufff9":"\\ufff9","\ufffa":"\\ufffa","\ufffb":"\\ufffb","\ufffc":"\\ufffc","\ufffd":"\\ufffd","\ufffe":"\\ufffe","\uffff":"\\uffff"},j=/[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g,k,l=JSON&&JSON.stringify||function(a){return h.lastIndex=0,h.test(a)&&(a=a.replace(h,function(a){return i[a]})),'"'+a+'"'},m=function(a){var b,c={},d=[];for(b=0;b<65536;b++)d.push(String.fromCharCode(b));return a.lastIndex=0,d.join("").replace(a,function(a){return c[a]="\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4),""}),a.lastIndex=0,c};e.quote=function(a){var b=l(a);return j.lastIndex=0,j.test(b)?(k||(k=m(j)),b.replace(j,function(a){return k[a]})):b};var n="_sockjs_global";e.createHook=function(){var a="a"+e.random_string(8);if(!(n in b)){var c={};b[n]=function(a){return a in c||(c[a]={id:a,del:function(){delete c[a]}}),c[a]}}return b[n](a)},e.attachMessage=function(a){e.attachEvent("message",a)},e.attachEvent=function(c,d){typeof b.addEventListener!="undefined"?b.addEventListener(c,d,!1):(a.attachEvent("on"+c,d),b.attachEvent("on"+c,d))},e.detachMessage=function(a){e.detachEvent("message",a)},e.detachEvent=function(c,d){typeof b.addEventListener!="undefined"?b.removeEventListener(c,d,!1):(a.detachEvent("on"+c,d),b.detachEvent("on"+c,d))};var o={"User-Agent":"",Accept:"","Accept-Language":"","Content-Type":"text/plain;charset=UTF-8"};navigator&&(navigator.userAgent.indexOf("Chrome")!=-1||navigator.userAgent.indexOf("Safari")!=-1)&&delete o["User-Agent"],e.createXDR=function(a,b,c,d){var f={status:null,responseText:"",readyState:1},g=new XDomainRequest;b+=(b.indexOf("?")===-1?"?":"&")+"t="+e.random_string(8);var h=function(){if(g){i=g.onerror=g.ontimeout=g.onprogress=g.onload=null;try{g.abort()}catch(a){}g=d=null}},i=g.ontimeout=g.onerror=function(){f.status=500,f.readyState=4,d(f),h()};g.onload=function(){f.status=200,f.readyState=4,f.responseText=g.responseText,d(f),h()},g.onprogress=function(){f.status=200,f.readyState=3,f.responseText=g.responseText,d(f)};try{g.open(a,b),g.send(c)}catch(j){e.delay(i)}return function(a){d&&(d(f,null,a),h())}},e.createXHR=function(a,c,d,f){var g;if(b.ActiveXObject){c+=(c.indexOf("?")===-1?"?":"&")+"t="+ +(new Date);try{g=new ActiveXObject("Microsoft.XMLHTTP")}catch(h){}}g||(g=new XMLHttpRequest),g.open(a,c,!0);for(var i in o)try{g.setRequestHeader(i,o[i])}catch(h){delete o[i]}"withCredentials"in g&&(g.withCredentials="true");var j=function(){if(g){try{g.onreadystatechange=null}catch(a){g.onreadystatechange=function(){}}try{g.abort()}catch(b){}e.detachEvent("unload",j)}f=g=null};return g.onreadystatechange=function(a){g&&f&&(f(g,a),g&&g.readyState===4&&j())},g.send(d),e.attachEvent("unload",j),function(a){f&&(f(g,null,a),j())}},e.createIframe=function(b,c){var d=a.createElement("iframe"),f,g=function(){clearTimeout(f);try{d.onload=null}catch(a){}d.onerror=null},h=function(){d&&(g(),d.src="about:blank",setTimeout(function(){d&&d.parentNode.removeChild(d),d=null},0),e.detachEvent("unload",h))},i=function(a){d&&(h(),c(a))};return d.src=b,d.style.display="none",d.style.position="absolute",d.onerror=function(){i("onerror")},d.onload=function(){clearTimeout(f),f=setTimeout(function(){i("onload timeout")},2e3)},a.body.appendChild(d),f=setTimeout(function(){i("timeout")},5e3),e.attachEvent("unload",h),{iframe:d,cleanup:h,loaded:g}},e.createHtmlfile=function(a,c){var d=new ActiveXObject("htmlfile"),f,h,i=function(){clearTimeout(f)},j=function(){if(d){i(),e.detachEvent("unload",j);try{h.src="about:blank"}catch(a){}h.parentNode.removeChild(h),h=d=null,CollectGarbage()}},k=function(a){d&&(j(),c(a))};d.open(),d.write('<html><script>document.domain="'+document.domain+'";'+"</script></html>"),d.close(),d.parentWindow[g]=b[g];var l=d.createElement("div");return d.body.appendChild(l),h=d.createElement("iframe"),l.appendChild(h),h.src=a,f=setTimeout(function(){k("timeout")},5e3),e.attachEvent("unload",j),{iframe:h,cleanup:j,loaded:i}};var p=function(){var b=this,c=function(a){b.state=p[a];var c={state:b.state,name:a};b.dispatchEvent(new d("change",c)),b.dispatchEvent(new d(a,c))};c("init"),a.body?c("load"):e.attachEvent("load",function(){c("load")}),e.attachEvent("beforeunload",function(){c("beforeunload")}),e.attachEvent("unload",function(){c("unload")})};p.prototype=new c,p.init=0,p.load=1,p.beforeunload=2,p.unload=3;var q=new p,r=function(a,b,c){var d=this;d._options={devel:!1,debug:!1,chunking:undefined},c&&e.objectExtend(d._options,c),d._base_url=e.amendUrl(a),d._server=d._options.server||e.random_number_string(1e3),d._connid=e.random_string(8),d._trans_url=d._base_url+"/"+d._server+"/"+d._connid,d._protocols=["websocket","xhr-streaming","iframe-eventsource","iframe-htmlfile","xhr-polling","iframe-xhr-polling","jsonp-polling"];switch(typeof b){case"undefined":break;case"string":d._protocols=[b];break;default:d._protocols=b}d.protocol=null,d.readyState=r.CONNECTING,d._didClose()};r.prototype=new c,r.version="0.1.2",r.CONNECTING=0,r.OPEN=1,r.CLOSING=2,r.CLOSED=3,r.prototype._debug=function(){this._options.debug&&e.log.apply(e,arguments)},r.prototype._dispatchOpen=function(){var a=this;a.readyState===r.CONNECTING?(a._transport_tref&&(clearTimeout(a._transport_tref),a._transport_tref=null),a.readyState=r.OPEN,a.dispatchEvent(new d("open"))):a._didClose(1006,"Server lost session")},r.prototype._dispatchMessage=function(a){var b=this;if(b.readyState!==r.OPEN)return;b.dispatchEvent(new d("message",{data:a}))},r.prototype._dispatchHeartbeat=function(a){var b=this;if(b.readyState!==r.OPEN)return;b.dispatchEvent(new d("heartbeat",{}))},r.prototype._didClose=function(a,b){var c=this;if(c.readyState!==r.CONNECTING&&c.readyState!==r.OPEN&&c.readyState!==r.CLOSING)throw new Error("INVALID_STATE_ERR");c._transport&&c._transport.doCleanup(),c._transport=null,c._transport_tref&&(clearTimeout(c._transport_tref),c._transport_tref=null);var f=new d("close",{code:a,reason:b,wasClean:e.userSetCode(a)});if(!e.userSetCode(a)&&c.readyState===r.CONNECTING){if(c._try_next_protocol(f)){c._transport_tref=setTimeout(function(){c.readyState===r.CONNECTING&&c._didClose(2007,"Transport timeouted")},5001);return}f=new d("close",{code:2e3,reason:"All transports failed",wasClean:!1,last_event:f})}c.readyState=r.CLOSED,e.delay(function(){c.dispatchEvent(f)})},r.prototype._didMessage=function(a){var b=this,c=a.slice(0,1);switch(c){case"o":b._dispatchOpen();break;case"a":var d=JSON.parse(a.slice(1)||"[]");for(var e=0;e<d.length;e++)b._dispatchMessage(d[e]);break;case"m":var d=JSON.parse(a.slice(1)||"null");b._dispatchMessage(d);break;case"c":var d=JSON.parse(a.slice(1)||"[]");b._didClose(d[0],d[1]);break;case"h":b._dispatchHeartbeat()}},r.prototype._try_next_protocol=function(b){var c=this;c.protocol&&(c._debug("Closed transport:",c.protocol,""+b),c.protocol=null);for(;;){var d=c.protocol=c._protocols.shift();if(!d)return!1;if(r[d]&&r[d].need_chunking===!0&&c._options.chunking===undefined)return c._protocols.unshift(d),c.protocol="chunking-test",c._options.chunking=!1,K(c._base_url,function(a){c._options.chunking=a,c._try_next_protocol()},c._options),!0;if(r[d]&&r[d].need_body===!0&&!a.body)return c._protocols.unshift(d),c.protocol="waiting-for-load",e.attachEvent("load",function(){c._try_next_protocol()}),!0;if(!(!r[d]||r[d].need_chunking===!0&&c._options.chunking!==!0||!r[d].enabled(c._options)))return c._debug("Opening transport:",d),c._transport=new r[d](c,c._trans_url,c._base_url),!0;c._debug("Skipping transport:",d)}},r.prototype.close=function(a,b){var c=this;if(a&&!e.userSetCode(a))throw new Error("INVALID_ACCESS_ERR");return c.readyState!==r.CONNECTING&&c.readyState!==r.OPEN?!1:(c.readyState=r.CLOSING,c._didClose(a||1e3,b||"Normal closure"),!0)},r.prototype.send=function(a){var b=this;if(b.readyState===r.CONNECTING)throw new Error("INVALID_STATE_ERR");return b.readyState===r.OPEN&&b._transport.doSend(e.quote(""+a)),!0};var s=r.websocket=function(a,b){var c=this,d=b+"/websocket";d.slice(0,5)==="https"?d="wss"+d.slice(5):d="ws"+d.slice(4),c.ri=a,c.url=d;var f=window.WebSocket||window.MozWebSocket;if(q.state>=p.beforeunload){e.log("Can't open a WebSocket connection after onbeforeunload!");return}c.ws=new f(c.url),c.ws.onmessage=function(a){c.ri._didMessage(a.data)},c.ws.onclose=function(){c.ri._didMessage(e.closeFrame(1006,"WebSocket connection broken"))}};s.prototype.doSend=function(a){this.ws.send(a)},s.prototype.doCleanup=function(){var a=this,b=a.ws;b&&(b.onmessage=b.onclose=null,b.close(),a.ri=a.ws=null)},s.enabled=function(){return!!window.WebSocket||!!window.MozWebSocket};var t=function(){};t.prototype.send_constructor=function(a){var b=this;b.send_buffer=[],b.sender=a},t.prototype.doSend=function(a){var b=this;b.send_buffer.push(a),b.send_stop||b.send_schedule()},t.prototype.send_schedule_wait=function(){var a=this,b;a.send_stop=function(){a.send_stop=null,clearTimeout(b)},b=e.delay(25,function(){a.send_stop=null,a.send_schedule()})},t.prototype.send_schedule=function(){var a=this;if(a.send_buffer.length>0){var b="["+a.send_buffer.join(",")+"]";a.send_stop=a.sender(a.trans_url,b,function(){a.send_stop=null,a.send_schedule_wait()}),a.send_buffer=[]}},t.prototype.send_destructor=function(){var a=this;a._send_stop&&a._send_stop(),a._send_stop=null};var u=function(b,c,d){var f=this;if(!("_send_form"in f)){var g=f._send_form=a.createElement("form"),h=f._send_area=a.createElement("textarea");h.name="d",g.style.display="none",g.style.position="absolute",g.method="POST",g.enctype="application/x-www-form-urlencoded",g.acceptCharset="UTF-8",g.appendChild(h),a.body.appendChild(g)}var g=f._send_form,h=f._send_area,i="a"+e.random_string(8);g.target=i,g.action=b+"/jsonp_send?i="+i;var j;try{j=a.createElement('<iframe name="'+i+'">')}catch(k){j=a.createElement("iframe"),j.name=i}j.id=i,g.appendChild(j),j.style.display="none",h.value=c,g.submit();var l=function(a){if(!j.onerror)return;j.onreadystatechange=j.onerror=j.onload=null,e.delay(500,function(){j.parentNode.removeChild(j),j=null}),h.value=null,d()};return j.onerror=j.onload=l,j.onreadystatechange=function(a){j.readyState=="complete"&&l()},l},v=function(a,b,c){var d=function(a,b,d){(a.readyState===4||d)&&c(a.status,d)};return e.createXHR("POST",a+"/xhr_send",b,d)},w=function(a,b,c){var d=function(a,b,d){(a.readyState===4||d)&&c(a.status,d)},f=window.XDomainRequest?e.createXDR:e.createXHR;return f("POST",a+"/xhr_send",b,d)},x=function(b,c){var d,f=a.createElement("script"),g,h=function(a){g&&(g.parentNode.removeChild(g),g=null),f&&(clearTimeout(d),f.parentNode.removeChild(f),f.onreadystatechange=f.onerror=f.onload=f.onclick=null,f=null,c(a),c=null)},i=!1,j=null;f.id="a"+e.random_string(8),f.src=b,f.type="text/javascript",f.charset="UTF-8",f.onerror=function(a){j||(j=setTimeout(function(){i||h(e.closeFrame(1006,"JSONP script loaded abnormally (onerror)"))},1e3))},f.onload=function(a){h(e.closeFrame(1006,"JSONP script loaded abnormally (onload)"))},f.onreadystatechange=function(a){if(/loaded|closed/.test(f.readyState)){if(f&&f.htmlFor&&f.onclick){i=!0;try{f.onclick()}catch(b){}}f&&h(e.closeFrame(1006,"JSONP script loaded abnormally (onreadystatechange)"))}};if(typeof f.async=="undefined"&&a.attachEvent)if(!/opera/i.test(navigator.userAgent)){try{f.htmlFor=f.id,f.event="onclick"}catch(k){}f.async=!0}else g=a.createElement("script"),g.text="try{var a = document.getElementById('"+f.id+"'); if (a)a.onerror();}catch(x){};",f.async=g.async=!1;typeof f.async!="undefined"&&(f.async=!0),d=setTimeout(function(){h(e.closeFrame(1006,"JSONP script loaded abnormally (timeout)"))},35e3);var l=a.getElementsByTagName("head")[0];return l.insertBefore(f,l.firstChild),g&&l.insertBefore(g,l.firstChild),h},y=r["jsonp-polling"]=function(a,b){e.polluteGlobalNamespace();var c=this;c.ri=a,c.trans_url=b,c.send_constructor(u),c._schedule_recv()};y.prototype=new t,y.prototype._schedule_recv=function(){var a=this,b=function(b){a._recv_stop=null,b&&(a._is_closing||a.ri._didMessage(b)),a._is_closing||a._schedule_recv()};a._recv_stop=z(a.trans_url+"/jsonp",x,b)},y.enabled=function(){return!0},y.need_body=!0,y.prototype.doCleanup=function(){var a=this;a._is_closing=!0,a._recv_stop&&a._recv_stop(),a.ri=a._recv_stop=null,a.send_destructor()};var z=function(a,c,d){var f="a"+e.random_string(6),h=a+"?c="+escape(g+"."+f),i=function(a){delete b[g][f],d(a)},j=c(h,i);b[g][f]=j;var k=function(){b[g][f]&&b[g][f](e.closeFrame(1e3,"JSONP user aborted read"))};return k},A=r["xhr-streaming"]=function(a,b){var c=this;c.ri=a,c.trans_url=b,c.send_constructor(w),c.poll=new R(a,W,b+"/xhr_streaming",{cors:!0})};A.prototype=new t,A.prototype.doCleanup=function(){var a=this;a.poll&&(a.poll.abort(),a.poll=null)},A.enabled=function(a){return a.cookie!==!0&&window.XDomainRequest?!0:window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest?!0:!1},A.need_chunking=!0;var B=r["xhr-polling"]=function(a,b){var c=this;c.ri=a,c.trans_url=b,c.send_constructor(w),c.poll=new R(a,W,b+"/xhr",{cors:!0})};B.prototype=new t,B.prototype.doCleanup=function(){var a=this;a.poll&&(a.poll.abort(),a.poll=null)},B.enabled=A.enabled;var C=function(){};C.prototype.i_constructor=function(a,b,c){var d=this;d.ri=a,d.origin=e.getOrigin(c),d.base_url=c,d.trans_url=b;var f=c+"/iframe.html";d.ri._options.devel&&(f+="?t="+ +(new Date)),d.window_id=e.random_string(8),f+="#"+d.window_id,d.iframeObj=e.createIframe(f,function(a){d.ri._didClose(1006,"Unable to load an iframe ("+a+")")}),d.onmessage_cb=e.bind(d.onmessage,d),e.attachMessage(d.onmessage_cb)},C.prototype.doCleanup=function(){var a=this;if(a.iframeObj){e.detachMessage(a.onmessage_cb);try{a.iframeObj.iframe.contentWindow&&a.postMessage("c")}catch(b){}a.iframeObj.cleanup(),a.iframeObj=null,a.onmessage_cb=a.iframeObj=null}},C.prototype.onmessage=function(a){var b=this;if(a.origin!==b.origin)return;var c=a.data.slice(0,8),d=a.data.slice(8,9),e=a.data.slice(9);if(c!==b.window_id)return;switch(d){case"s":b.iframeObj.loaded(),b.postMessage("s",JSON.stringify([r.version,b.protocol,b.trans_url,b.base_url]));break;case"t":b.ri._didMessage(e)}},C.prototype.postMessage=function(a,b){var c=this;c.iframeObj.iframe.contentWindow.postMessage(c.window_id+a+(b||""),c.origin)},C.prototype.doSend=function(a){this.postMessage("m",a)},C.enabled=function(){var a=navigator&&navigator.userAgent&&navigator.userAgent.indexOf("Konqueror")!==-1;return(typeof b.postMessage=="function"||typeof b.postMessage=="object")&&!a};var D,E=function(a,c){parent!==b?parent.postMessage(D+a+(c||""),"*"):e.log("Can't postMessage, no parent window.",a,c)},F=function(){};F.prototype._didClose=function(a,b){E("t",e.closeFrame(a,b))},F.prototype._didMessage=function(a){E("t",a)},F.prototype._doSend=function(a){this._transport.doSend(a)},F.prototype._doCleanup=function(){this._transport.doCleanup()},r.bootstrap_iframe=function(){var b;D=a.location.hash.slice(1);var c=function(a){if(a.source!==parent)return;var c=a.data.slice(0,8),d=a.data.slice(8,9),f=a.data.slice(9);if(c!==D)return;switch(d){case"s":var g=JSON.parse(f),h=g[0],i=g[1],j=g[2],k=g[3];h!==r.version&&e.log('Incompatibile SockJS! Main site uses: "'+h+'", the iframe:'+' "'+r.version+'".'),b=new F,b._transport=new F[i](b,j,k);break;case"m":b._doSend(f);break;case"c":b._doCleanup(),b=null}};e.attachMessage(c),E("s")};var G=function(a,b,c){var d=new W(a+"/chunking_test",{cors:c}),f=0;d.onmessage=function(a){var b=a.responsetext.split("h\n").length;a.readystate===3&&b>0&&b<6&&(f=b,d.abort())},d.onclose=function(a){d=d.onmessage=d.onclose=null,e.log("Chunking test: "+(f?"passed":"failed")+" ("+f+" chunk received)"),b(!!f)}},H=F["w-iframe-chunking-test"]=function(a,b,c){G(c,function(b){a._didMessage("m"+b),a._didClose()},!1)};H.prototype.doCleanup=function(){};var I=r.chunkingTest=function(c,d,f){c=e.amendUrl(c);if(b.XDomainRequest||b.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest){G(c,d,!0);return}a.body?J(c,d,f):e.attachEvent("load",function(){J(c,d,f)})},J=function(a,b,c){if(C.enabled()){var d=new C;d.protocol="w-iframe-chunking-test";var e=function(a){d&&(b(a==="mtrue"),d.doCleanup(),d=null)},f={_options:c||{},_didClose:e,_didMessage:e};d.i_constructor(f,"",a);return}setTimeout(function(){b(!1)},0);return},K=function(){var a,b=0;return function(c,d){var e=(new Date).getTime();e-b>1e4?I(c,function(c){a=c,b=(new Date).getTime(),d(a)}):setTimeout(function(){d(a)},0)}}(),L=r["iframe-eventsource"]=function(){var a=this;a.protocol="w-iframe-eventsource",a.i_constructor.apply(a,arguments)};L.prototype=new C,L.enabled=function(){return"EventSource"in window&&C.enabled()},L.need_chunking=!0,L.need_body=!0;var M=F["w-iframe-eventsource"]=function(a,b){var c=this;c.ri=a,c.trans_url=b,c.send_constructor(v),c.poll=new R(a,S,b+"/eventsource")};M.prototype=new t,M.prototype.doCleanup=function(){var a=this;a.poll&&(a.poll.abort(),a.poll=null)};var N=r["iframe-xhr-polling"]=function(){var a=this;a.protocol="w-iframe-xhr-polling",a.i_constructor.apply(a,arguments)};N.prototype=new C,N.enabled=function(){return window.XMLHttpRequest&&C.enabled()},N.need_body=!0;var O=F["w-iframe-xhr-polling"]=function(a,b){var c=this;c.trans_url=b,c.send_constructor(v),c.poll=new R(a,W,b+"/xhr",{cors:!1})};O.prototype=new t,O.prototype.doCleanup=function(){var a=this;a.poll&&(a.poll.abort(),a.poll=null)};var P=r["iframe-htmlfile"]=function(){var a=this;a.protocol="w-iframe-htmlfile",a.i_constructor.apply(a,arguments)};P.prototype=new C,P.enabled=function(a){var b=U();return a.cookie!==!1&&C.enabled()},P.need_chunking=!0,P.need_body=!0;var Q=F["w-iframe-htmlfile"]=function(a,b){var c=this;c.trans_url=b,c.send_constructor(v),c.poll=new R(a,V,b+"/htmlfile")};Q.prototype=new t,Q.prototype.doCleanup=function(){var a=this;a.poll&&(a.poll.abort(),a.poll=null)};var R=function(a,b,c,d){var e=this;e.ri=a,e.Receiver=b,e.recv_url=c,e.opts=d,e._scheduleRecv()};R.prototype._scheduleRecv=function(){var a=this,b=a.poll=new a.Receiver(a.recv_url,a.opts),c=0;b.onmessage=function(b){c+=1,a.ri._didMessage(b.data)},b.onclose=function(c){a.poll=b=b.onmessage=b.onclose=null,a.poll_is_closing||(c.reason==="permanent"?a.ri._didClose(1006,"Polling error ("+c.reason+")"):a._scheduleRecv())}},R.prototype.abort=function(){var a=this;a.poll_is_closing=!0,a.poll&&a.poll.abort()};var S=function(a){var b=this,c=new EventSource(a);c.onmessage=function(a){b.dispatchEvent(new d("message",{data:unescape(a.data)}))},b.es_close=c.onerror=function(a,f){var g=f?"user":c.readyState!==2?"network":"permanent";b.es_close=c.onmessage=c.onerror=null,c.close(),c=null,e.delay(200,function(){b.dispatchEvent(new d("close",{reason:g}))})}};S.prototype=new c,S.prototype.abort=function(){var a=this;a.es_close&&a.es_close({},!0)};var T,U=function(){if(T===undefined)if("ActiveXObject"in window)try{T=!!(new ActiveXObject("htmlfile"))}catch(a){}else T=!1;return T},V=function(a){var c=this;e.polluteGlobalNamespace(),c.id="a"+e.random_string(6,26),a+=(a.indexOf("?")===-1?"?":"&")+"c="+escape(g+"."+c.id);var f=U()?e.createHtmlfile:e.createIframe,h;b[g][c.id]={start:function(){h.loaded()},message:function(a){c.dispatchEvent(new d("message",{data:a}))},stop:function(){c.iframe_close({},"network")}},c.iframe_close=function(a,e){h.cleanup(),c.iframe_close=h=null,delete b[g][c.id],c.dispatchEvent(new d("close",{reason:e}))},h=f(a,function(a){c.iframe_close({},"permanent")})};V.prototype=new c,V.prototype.abort=function(){var a=this;a.iframe_close&&a.iframe_close({},"user")};var W=function(a,c){var f=this,g=0,h=function(a,b,c){if(a.readyState===3||a.readyState===4){try{var e=a.responseText,h=a.status}catch(i){}if(e&&h===200){var j=[];for(;;){var k=e.slice(g),l=k.indexOf("\n");if(l===-1)break;g+=l+1;var m=k.slice(0,l);f.dispatchEvent(new d("message",{data:m,readystate:a.readyState,responsetext:e}))}}}if(a.readyState===4||c){var n=c?"user":a.status===200?"network":"permanent";f.xhr_close=null,f.dispatchEvent(new d("close",{reason:n}))}},i=c.cors&&b.XDomainRequest?e.createXDR:e.createXHR;f.xhr_close=i("POST",a,null,h)};return W.prototype=new c,W.prototype.abort=function(){var a=this;a.xhr_close&&a.xhr_close(!0)},r.getUtils=function(){return e},r.getIframeTransport=function(){return C},r}(),"_sockjs_onload"in window&&setTimeout(_sockjs_onload,1);var log;window.console&&console.log?log=function(){console.log.apply(console,arguments)}:log=function(){};var util={hasProp:function(a,b){return Object.prototype.hasOwnProperty.call(Object(a),b)},extend:function(a,b){function d(){this.constructor=a}if(a===undefined||b===undefined)return a;for(var c in b)util.hasProp(b,c)&&(a[c]=b[c]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a},generateGuid:function(){var a="",b="abcdefghijklmnopqrstuvwxyz0123456789";for(var c=0;c<12;c++)a+=b.charAt(Math.floor(Math.random()*b.length));return a},typeOf:function(a){var b=typeof a;return b==="object"&&(a?typeof a.length=="number"&&!a.propertyIsEnumerable("length")&&typeof a.splice=="function"&&(b="array"):b="null"),b},findOps:function(a){var b=[];for(var c in a)typeof a[c]=="function"&&util.isValid(c)&&b.push(c);return b},isValid:function(a){return a.charAt(0)!=="_"},inherit:function(a,b){var c=function(){};c.prototype=b.prototype,a.prototype=new c},stringify:JSON.stringify,parse:JSON.parse,log:log,info:function(){util.log.apply(this,arguments)},warn:function(){util.log.apply(this,arguments)},error:function(){util.log.apply(this,arguments)},setLogLevel:function(a){a<3&&(util.info=function(){}),a<2&&(util.warn=function(){}),a<1&&(util.error=function(){})},refCallback:function(a){var b=function(){var b=[].slice.apply(arguments);a._call("callback",b)};return b._reference=a,b._toDict=function(){return a._toDict()},b.callback=b,b}},Serializer={serialize:function(a,b){var c=util.typeOf(b),d;switch(c){case"object":if(b===null)d=null;else if("_toDict"in b)d=b._toDict();else{var e=util.findOps(b);if(e.length>0)d=a._storeObject(b,e)._toDict();else{d={};for(var f in b){var g=b[f];d[f]=Serializer.serialize(a,g)}}}break;case"array":d=[];for(var h=0,i=b.length;h<i;h++){var g=b[h];d.push(Serializer.serialize(a,g))}break;case"function":util.hasProp("_reference")?d=b._toDict():d=a._storeObject({callback:b},["callback"])._toDict();break;default:d=b}return d},unserialize:function(a,b){var c;for(var d in b){var e=b[d];if(typeof e=="object")if(util.hasProp(e,"ref")){var f=new Reference(a,e.ref,e.operations);e.operations&&e.operations.length===1&&e.operations[0]==="callback"?b[d]=util.refCallback(f):b[d]=f}else Serializer.unserialize(a,e)}}};Reference.prototype._toDict=function(a){var b={},c=this._address;return a&&(c=c.slice(),c.push(a)),b.ref=c,c.length<4&&(b.operations=this._operations),b},Reference.prototype._call=function(a,b){util.info("Calling",this._address+"."+a);var c=this._toDict(a);this._bridge._send(b,c)},Connection.prototype.redirector=function(){var a=this;if(this.options.tcp){var b=url.parse(this.options.redirector);http.get({host:b.hostname,port:b.port,path:"/redirect/"+this.options.apiKey},function(b){var c="";b.on("data",function(a){c+=a}),b.on("end",function(){try{var b=JSON.parse(c);a.options.host=b.data.bridge_host,a.options.port=b.data.bridge_port,!a.options.host||!a.options.port?util.error("Could not find host and port in JSON"):a.establishConnection()}catch(d){util.error("Unable to parse redirector response "+c)}})}).on("error",function(a){util.error("Unable to contact redirector")})}else{window.bridgeHost=function(b,c,d){a.options.host=c,a.options.port=parseInt(d,10),!a.options.host||!a.options.port?util.error("Could not find host and port in JSON"):a.establishConnection(),delete window.bridgeHost};var c=document.createElement("script");c.setAttribute("src",this.options.redirector+"/redirect/"+this.options.apiKey+"/jsonp"),document.getElementsByTagName("head")[0].appendChild(c)}},Connection.prototype.reconnect=function(){util.info("Attempting reconnect");var a=this;this.interval<32768&&setTimeout(function(){a.establishConnection()},this.interval*=2)},Connection.prototype.establishConnection=function(){var a=this,b;this.options.tcp?(util.info("Starting TCP connection",this.options.host,this.options.port),b=(new TCP(this.options)).sock):(util.info("Starting SockJS connection"),b=new SockJS("http://"+this.options.host+":"+this.options.port+"/bridge",this.options.protocols,this.options.sockjs)),b.bridge=this.bridge,b.onmessage=function(c){util.info("clientId and secret received",c.data);var d=c.data.toString().split("|");d.length!==2?a.processMessage(c):(a.clientId=d[0],a.secret=d[1],a.interval=400,a.sock.processQueue(b,a.clientId),a.sock=b,a.sock.onmessage=a.processMessage,util.info("Handshake complete"),a.bridge._ready||(a.bridge._ready=!0,a.bridge.emit("ready")))},b.onopen=function(){util.info("Beginning handshake");var c=util.stringify({command:"CONNECT",data:{session:[a.clientId||null,a.secret||null],api_key:a.options.apiKey}});b.send(c)},b.onclose=function(){util.warn("Connection closed"),a.sock=a.sockBuffer,a.options.reconnect&&a.reconnect()}},Connection.prototype.processMessage=function(a){try{util.info("Received",a.data),a=util.parse(a.data),Serializer.unserialize(this.bridge,a);var b=a.destination;if(!b){util.warn("No destination in message",a);return}this.bridge._execute(a.destination._address,a.args)}catch(c){util.error("Message parsing failed: ",c.message,c.stack)}},Connection.prototype.sendCommand=function(a,b){var c=util.stringify({command:a,data:b});util.info("Sending",c),this.sock.send(c)},Connection.prototype.start=function(){!this.options.host||!this.options.port?this.redirector():this.establishConnection()},SockBuffer.prototype.send=function(a){this.buffer.push(a)},SockBuffer.prototype.processQueue=function(a,b){for(var c=0,d=this.buffer.length;c<d;c++)a.send(this.buffer[c].replace('"client",null','"client","'+b+'"'));this.buffer=[]},Bridge.prototype._execute=function(a,b){var c=this._store[a[2]],d=c[a[3]];d?d.apply(c,b):util.warn("Could not find object to handle",a)},Bridge.prototype._storeObject=function(a,b){var c=util.generateGuid();return this._store[c]=a,new Reference(this,["client",this._connection.clientId,c],b)},Bridge.prototype.on=function(a,b){return util.hasProp(this._events,a)||(this._events[a]=[]),this._events[a].push(b),this},Bridge.prototype.emit=function(a,b){if(util.hasProp(this._events,a)){var c=this._events[a].slice(0);for(var d=0,e=c.length;d<e;d++)c[d].apply(this,b===undefined?[]:b)}return this},Bridge.prototype.removeEvent=function(a,b){if(util.hasProp(this._events,a))for(var c=0,d=this._events[a].length;c<d;c++)this._events[a][c]===b&&this._events[a].splice(c,1);return this},Bridge.prototype._send=function(a,b){this._connection.sendCommand("SEND",{args:Serializer.serialize(this,a),destination:b})},Bridge.prototype.publishService=function(a,b,c){a==="system"?util.error("Invalid service name: "+a):(this._store[a]=b,this._connection.sendCommand("JOINWORKERPOOL",{name:a,callback:Serializer.serialize(this,c)}))},Bridge.prototype.getService=function(a,b){this._connection.sendCommand("GETOPS",{name:a,callback:Serializer.serialize(this,b)})},Bridge.prototype.getChannel=function(a,b){var c=this;this._connection.sendCommand("GETCHANNEL",{name:a,callback:Serializer.serialize(this,function(a,d){d=d.split(":")[1];if(a===null){b(null,d);return}b(new Reference(c,["channel",d,"channel:"+d],a._operations),d)})})},Bridge.prototype.joinChannel=function(a,b,c){this._connection.sendCommand("JOINCHANNEL",{name:a,handler:Serializer.serialize(this,b),callback:Serializer.serialize(this,c)})},Bridge.prototype.leaveChannel=function(a,b,c){this._connection.sendCommand("LEAVECHANNEL",{name:a,handler:Serializer.serialize(this,b),callback:Serializer.serialize(this,c)})},Bridge.prototype.ready=function(a){this._ready?a():this.on("ready",a)},Bridge.prototype.connect=function(a){return a&&this.ready(a),this._connection.start(),this}
@@ -1,14 +0,0 @@
1
- $(function(){
2
-
3
- bridge.getService('chatserver', function(chat){
4
- chat.join('lobby', {msg: function(name, msg){
5
- $('#messages').append(name + ': ' + msg + '<br>');
6
- }}, function(lobby) {
7
- $('#y').click(function(){
8
- lobby.msg('someone', $('#x').val());
9
- $('#x').val('');
10
- });
11
- });
12
- });
13
-
14
- });
@@ -1,5 +0,0 @@
1
- <div id="messages"></div>
2
-
3
-
4
- <input type="text" id="x">
5
- <input type="button" id="y" value="submit">
@@ -1,23 +0,0 @@
1
- <!DOCTYPE HTML>
2
- <html lang="en">
3
- <head>
4
- <title></title>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
- <meta http-equiv="Content-Language" content="en-us">
7
- <meta name="description" content="">
8
- <meta name="keywords" content="">
9
-
10
-
11
- <link href="/css/style.css" rel="stylesheet" type="text/css">
12
-
13
- <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
14
- <script type="text/javascript" src="/js/bridge.min.js"></script>
15
- <script type="text/javascript" src="/js/all.js"></script>
16
- <script type="text/javascript" src="/js/<%= title %>.js"></script>
17
-
18
- </head>
19
-
20
- <body>
21
- <%= yield %>
22
- </body>
23
- </html>
@@ -1,29 +0,0 @@
1
- require 'eventmachine'
2
- require 'bridge'
3
-
4
-
5
- module EchoModule
6
- def self.echo name, msg
7
- puts(name + ": " + msg)
8
- end
9
- def self.pong msg, count, fun
10
- if msg == "ping"
11
- puts :pong
12
- fun.call(count + 1)
13
- end
14
- end
15
- end
16
-
17
- EventMachine::run {
18
- Bridge::initialize({ :reconnect => false,
19
- :host => '127.0.0.1',
20
- :port => 8090})
21
- Bridge::ready lambda {
22
- puts 'Connected.'
23
- }
24
- puts 'enqueued ready func'
25
- Bridge::publish_service("pong", EchoModule)
26
- puts 'published pong service'
27
- Bridge::join_channel("duuuude", EchoModule, lambda {puts "Duuude."})
28
- puts 'joined channel'
29
- }