flotype-bridge 0.2.0.beta.1 → 0.2.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
}
|