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 +3 -3
- data/doc/Bridge/Bridge.html +80 -14
- data/doc/Bridge.html +1 -1
- data/doc/created.rid +2 -2
- data/doc/js/search_index.js +1 -1
- data/doc/table_of_contents.html +2 -0
- data/examples/chat/chatclient.rb +21 -0
- data/examples/chat/chatserver.rb +24 -0
- data/examples/simple/channels.rb +47 -0
- data/examples/simple/services.rb +41 -0
- data/lib/bridge.rb +40 -9
- data/lib/connection.rb +1 -3
- data/lib/version.rb +1 -1
- metadata +94 -58
- data/examples/chat/chat_client.rb +0 -21
- data/examples/chat/chat_server.rb +0 -24
- data/examples/chat/public/css/style.css +0 -4
- data/examples/chat/public/js/all.js +0 -5
- data/examples/chat/public/js/bridge.min.js +0 -2
- data/examples/chat/public/js/index.js +0 -14
- data/examples/chat/views/index.erb +0 -5
- data/examples/chat/views/layout.erb +0 -23
- data/examples/pong/pong.rb +0 -29
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#Flotype Bridge for Javascript
|
2
|
-
Flotype Bridge
|
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://
|
20
|
-
* Getting Started: http://www.flotype.com/
|
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.
|
data/doc/Bridge/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
|
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
|
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">></span> <span class="ruby-string">'http://redirector.flotype.com'</span>,
|
200
203
|
<span class="ruby-value">:reconnect</span> =<span class="ruby-operator">></span> <span class="ruby-keyword">true</span>,
|
201
204
|
<span class="ruby-value">:log</span> =<span class="ruby-operator">></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-
|
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
|
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> &<span class="ruby-identifier">callback</span>
|
260
267
|
<span class="ruby-keyword">self</span>.<span class="ruby-identifier">ready</span> &<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
|
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>, &<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">></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">"channel:#{name}"</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
|
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>, &<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
|
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>, &<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">></span> <span class="ruby-identifier">name</span>, <span class="ruby-value">:handler</span> =<span class="ruby-operator">></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">></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
|
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>, &<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">></span> <span class="ruby-identifier">name</span>, <span class="ruby-value">:handler</span> =<span class="ruby-operator">></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">></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>, &<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"><<</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
|
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>, &<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">"Invalid service name: #{name}"</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
|
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> &<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-
|
665
|
+
<span class="ruby-identifier">on</span> <span class="ruby-string">'ready'</span>, &<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
data/doc/created.rid
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
Sat, 07 Apr 2012 02:37:02 -0700
|
2
|
+
lib\bridge.rb Sat, 07 Apr 2012 02:36:34 -0700
|
data/doc/js/search_index.js
CHANGED
@@ -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"]]}}
|
data/doc/table_of_contents.html
CHANGED
@@ -55,6 +55,8 @@
|
|
55
55
|
|
56
56
|
<li class="method"><a href="Bridge/Bridge.html#method-i-leave_channel">#leave_channel — Bridge::Bridge</a>
|
57
57
|
|
58
|
+
<li class="method"><a href="Bridge/Bridge.html#method-i-on">#on — Bridge::Bridge</a>
|
59
|
+
|
58
60
|
<li class="method"><a href="Bridge/Bridge.html#method-i-publish_service">#publish_service — Bridge::Bridge</a>
|
59
61
|
|
60
62
|
<li class="method"><a href="Bridge/Bridge.html#method-i-ready">#ready — 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, :
|
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
|
67
|
-
@
|
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
|
-
|
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
|
-
@
|
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
data/lib/version.rb
CHANGED
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
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
19
|
+
|
20
|
+
date: 2012-04-20 00:00:00 Z
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
15
23
|
name: eventmachine
|
16
|
-
|
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
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
26
39
|
name: json
|
27
|
-
|
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
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
37
55
|
name: yard
|
38
|
-
|
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
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
69
|
+
version_requirements: *id003
|
70
|
+
- !ruby/object:Gem::Dependency
|
48
71
|
name: rake-compiler
|
49
|
-
|
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
|
-
|
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
|
-
|
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/
|
106
|
-
- examples/chat/
|
107
|
-
- examples/
|
108
|
-
- examples/
|
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
|
-
|
154
|
-
|
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.
|
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,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,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>
|
data/examples/pong/pong.rb
DELETED
@@ -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
|
-
}
|