rcomet 0.0.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/.gitignore +22 -0
- data/History.rdoc +10 -0
- data/LICENSE +340 -0
- data/README.rdoc +98 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/bin/rcomet +3 -0
- data/examples/chart/README.rdoc +18 -0
- data/examples/chart/chart-cometd.rb +18 -0
- data/examples/chart/chart.rb +19 -0
- data/examples/chart/static/chart.rhtml +75 -0
- data/examples/chat/README.rdoc +18 -0
- data/examples/chat/chat-cometd.rb +30 -0
- data/examples/chat/chat.rb +31 -0
- data/examples/chat/static/chat.rhtml +75 -0
- data/examples/chat/static/login.rhtml +20 -0
- data/examples/chat/static/style.css +61 -0
- data/examples/soapbox/README.rdoc +30 -0
- data/examples/soapbox/client.rb +36 -0
- data/examples/soapbox/soapbox-cometd.rb +14 -0
- data/examples/soapbox/soapbox.rb +19 -0
- data/examples/soapbox/static/soapbox.rhtml +92 -0
- data/examples/soapbox/static/style.css +42 -0
- data/lib/rcomet/channel.rb +76 -0
- data/lib/rcomet/client.rb +188 -0
- data/lib/rcomet/core_ext.rb +5 -0
- data/lib/rcomet/rack_adapter.rb +289 -0
- data/lib/rcomet/server.rb +57 -0
- data/lib/rcomet/user.rb +61 -0
- data/lib/rcomet.rb +15 -0
- data/rcomet.gemspec +90 -0
- data/spec/rcomet_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- metadata +120 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
= Chat -- Simple chat room
|
|
2
|
+
|
|
3
|
+
== Requirements
|
|
4
|
+
|
|
5
|
+
* Capcode
|
|
6
|
+
sudo gem install Capcode
|
|
7
|
+
* Dojo Toolkit (http://www.dojotoolkit.org/downloads)
|
|
8
|
+
|
|
9
|
+
== Running the demo
|
|
10
|
+
|
|
11
|
+
* Download the Dojo Toolkit: Dojo + Dijit + DojoX and copy all files in static/dojo
|
|
12
|
+
* run
|
|
13
|
+
ruby chat-commet.rb
|
|
14
|
+
* run
|
|
15
|
+
ruby chat.rb
|
|
16
|
+
* Open some browsers at http://localhost:3000
|
|
17
|
+
|
|
18
|
+
If you have the exception RCometAddrInUse change the port 8990 in chat-cometd.rb and in chat.html
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
$:.unshift("../../lib")
|
|
2
|
+
require 'rcomet/server'
|
|
3
|
+
|
|
4
|
+
users = {}
|
|
5
|
+
|
|
6
|
+
RComet::Server.new( :host => '0.0.0.0', :port => 8990, :mount => '/', :server => :mongrel ) {
|
|
7
|
+
|
|
8
|
+
timeout do |user|
|
|
9
|
+
puts "*** User ID:#{user.id} (aka #{users[user.id]}) is not ready !"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
channel['/users']
|
|
13
|
+
|
|
14
|
+
channel['/login'].callback do |message|
|
|
15
|
+
puts "*** Login : #{message['data']}"
|
|
16
|
+
users.merge!({ message['clientId'] => message['data'] })
|
|
17
|
+
channel['/users'].data( users.values )
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
channel['/logout'].callback do |message|
|
|
21
|
+
users.delete(message['clientId'])
|
|
22
|
+
channel['/users'].data( users.values )
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
channel['/message'].callback do |message|
|
|
26
|
+
channel['/message'].data( message['data'] )
|
|
27
|
+
end
|
|
28
|
+
}.start
|
|
29
|
+
|
|
30
|
+
while true; end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'capcode'
|
|
3
|
+
require 'capcode/render/static'
|
|
4
|
+
require 'capcode/render/erb'
|
|
5
|
+
|
|
6
|
+
module Capcode
|
|
7
|
+
set :static, "static"
|
|
8
|
+
set :erb, "static"
|
|
9
|
+
set :verbose, true
|
|
10
|
+
|
|
11
|
+
class Index < Route '/'
|
|
12
|
+
def get
|
|
13
|
+
@ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last }
|
|
14
|
+
render :erb => :login
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Chat < Route '/chat'
|
|
19
|
+
def post
|
|
20
|
+
@username = params["username"]
|
|
21
|
+
@ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last }
|
|
22
|
+
render :erb => :chat
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get
|
|
26
|
+
redirect Index
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
Capcode.run( )
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>RComet demo: chat client</title>
|
|
5
|
+
<link rel="stylesheet" href="/static/style.css" type="text/css" media="screen">
|
|
6
|
+
<script language="JavaScript" type="text/javascript" src="/static/dojo/dojo/dojo.js" charset="utf-8" djConfig="parseOnLoad: true"></script>
|
|
7
|
+
|
|
8
|
+
<script language="JavaScript" type="text/javascript">
|
|
9
|
+
dojo.require("dojox.cometd");
|
|
10
|
+
dojo.require("dojo.fx");
|
|
11
|
+
|
|
12
|
+
var comet = dojox.cometd;
|
|
13
|
+
comet.init("http://<%= @ip %>:8990");
|
|
14
|
+
|
|
15
|
+
var message = {
|
|
16
|
+
_init : function() {
|
|
17
|
+
comet.subscribe("/message", message, "publish");
|
|
18
|
+
comet.subscribe("/users", message, "users");
|
|
19
|
+
comet.publish("/login", "<%= @username %>");
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
publish : function(msg) {
|
|
23
|
+
current = dojo.byId("stream").innerHTML
|
|
24
|
+
dojo.byId("stream").innerHTML = "<li><b>"+msg.data.username+"</b>: "+msg.data.message+"</li>"+current;
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
users : function(msg) {
|
|
28
|
+
dojo.byId("usersList").innerHTML = "";
|
|
29
|
+
dojo.map(msg.data, function(el) {
|
|
30
|
+
current = dojo.byId("usersList").innerHTML
|
|
31
|
+
dojo.byId("usersList").innerHTML = "<li>"+el+"</li>"+current;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
dojo.addOnLoad(message, "_init");
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
<div class="chat">
|
|
41
|
+
<h1>RComet Chat Demo | <%= @username %></h1>
|
|
42
|
+
|
|
43
|
+
<div class="room">
|
|
44
|
+
<ul id="stream">
|
|
45
|
+
<!-- messages -->
|
|
46
|
+
</ul>
|
|
47
|
+
<form id="message">
|
|
48
|
+
<label for="text">Message </label>
|
|
49
|
+
<input type="text" name="text" id="text" size="50">
|
|
50
|
+
<input type="submit" value="Send">
|
|
51
|
+
</form>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="users">
|
|
55
|
+
<label>Users :</label>
|
|
56
|
+
<ul id="usersList">
|
|
57
|
+
<!-- users list -->
|
|
58
|
+
</ul>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
<script language="JavaScript" type="text/javascript">
|
|
64
|
+
var postMessageForm = dojo.byId("message");
|
|
65
|
+
dojo.connect(postMessageForm, "onsubmit", function(evt) {
|
|
66
|
+
evt.preventDefault();
|
|
67
|
+
dojo.stopEvent(evt);
|
|
68
|
+
message = dojo.byId("text").value;
|
|
69
|
+
comet.publish( '/message', { "username":"<%= @username %>", "message":message } );
|
|
70
|
+
dojo.byId("text").value = "";
|
|
71
|
+
return false;
|
|
72
|
+
})
|
|
73
|
+
</script>
|
|
74
|
+
</body>
|
|
75
|
+
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>RComet demo: chat</title>
|
|
5
|
+
<link rel="stylesheet" href="/static/style.css" type="text/css" media="screen">
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<div class="container">
|
|
9
|
+
<h1>RComet chat demo</h1>
|
|
10
|
+
|
|
11
|
+
<div>
|
|
12
|
+
<form action="<%= URL( Chat ) %>" method="POST">
|
|
13
|
+
<label for="username">Username</label>
|
|
14
|
+
<input type="text" name="username" id="username">
|
|
15
|
+
<input type="submit" value="Login">
|
|
16
|
+
</form>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background: #bfbfbf;
|
|
3
|
+
margin: 0;
|
|
4
|
+
padding: 0;
|
|
5
|
+
font: 16px/1.5 Helvetica, Arial, sans-serif;
|
|
6
|
+
text-align: center;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.container {
|
|
10
|
+
text-align: left;
|
|
11
|
+
width: 400px;
|
|
12
|
+
margin: 40px auto;
|
|
13
|
+
padding: 24px;
|
|
14
|
+
border: 1px solid #3f3f3f;
|
|
15
|
+
background: #FFF;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
h1 {
|
|
19
|
+
font-size: 24px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.chat {
|
|
23
|
+
width: 800px;
|
|
24
|
+
margin: 40px auto;
|
|
25
|
+
padding: 5px;
|
|
26
|
+
border: 1px solid #3f3f3f;
|
|
27
|
+
background: #fff;
|
|
28
|
+
text-align: left;
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.room {
|
|
33
|
+
padding-left: 1%;
|
|
34
|
+
padding-bottom: 1px;
|
|
35
|
+
padding-right: 1%;
|
|
36
|
+
padding-top: 1px;
|
|
37
|
+
width: 65%;
|
|
38
|
+
border: 0px solid #000000;
|
|
39
|
+
}
|
|
40
|
+
.room ul {
|
|
41
|
+
border: 1px solid black;
|
|
42
|
+
height: 310px;
|
|
43
|
+
overflow: auto;
|
|
44
|
+
}
|
|
45
|
+
.room form#message {
|
|
46
|
+
background: #ABB;
|
|
47
|
+
padding: 3px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.users {
|
|
51
|
+
position: absolute;
|
|
52
|
+
top: 114px;
|
|
53
|
+
right: 12%;
|
|
54
|
+
padding: 1em;
|
|
55
|
+
width: 20%;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ul, li {
|
|
59
|
+
list-style: none;
|
|
60
|
+
padding-left: 5px;
|
|
61
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
= Soapbox -- a Twitter-style chat app
|
|
2
|
+
|
|
3
|
+
== Requirements
|
|
4
|
+
|
|
5
|
+
* Capcode
|
|
6
|
+
sudo gem install Capcode
|
|
7
|
+
* Dojo Toolkit (http://www.dojotoolkit.org/downloads)
|
|
8
|
+
|
|
9
|
+
== Running the demo
|
|
10
|
+
|
|
11
|
+
* Download the Dojo Toolkit: Dojo + Dijit + DojoX and copy all files in static/dojo
|
|
12
|
+
* run
|
|
13
|
+
ruby soapbox-commet.rb
|
|
14
|
+
* run
|
|
15
|
+
ruby soapbox.rb
|
|
16
|
+
* Open some browsers at http://localhost:3000
|
|
17
|
+
|
|
18
|
+
If you have the exception RCometAddrInUse change the port 8990 in soapbox-cometd.rb and in soapbox.html
|
|
19
|
+
|
|
20
|
+
== Licence
|
|
21
|
+
|
|
22
|
+
Because this example was trully inspired by the faye example "Soapbox" (http://github.com/jcoglan/faye/tree/master/examples/soapbox/), it follow the faye license :
|
|
23
|
+
|
|
24
|
+
(The MIT License)
|
|
25
|
+
|
|
26
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
27
|
+
|
|
28
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
29
|
+
|
|
30
|
+
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
$:.unshift( "../../lib" )
|
|
2
|
+
require 'rcomet/client'
|
|
3
|
+
|
|
4
|
+
x = RComet::Client.new( 'http://localhost:8990/' )
|
|
5
|
+
|
|
6
|
+
puts "-- handshake"
|
|
7
|
+
x.handshake
|
|
8
|
+
|
|
9
|
+
puts "-- login as `daemon'"
|
|
10
|
+
x.publish( '/login', "daemon" );
|
|
11
|
+
|
|
12
|
+
puts "-- subscriptions"
|
|
13
|
+
x.subscribe( "/from/greg" ) { |r|
|
|
14
|
+
puts "#{r["username"]} : #{r["message"]}"
|
|
15
|
+
}
|
|
16
|
+
x.subscribe( "/from/daemon" ) { |r|
|
|
17
|
+
puts "#{r["username"]} : #{r["message"]}"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
puts "-- connect"
|
|
21
|
+
x.connect
|
|
22
|
+
|
|
23
|
+
msg = ""
|
|
24
|
+
while msg != "quit"
|
|
25
|
+
msg = $stdin.readline.chomp
|
|
26
|
+
unless msg == "quit"
|
|
27
|
+
channel = "/from/daemon"
|
|
28
|
+
data = { "username" => "daemon", "message" => msg }
|
|
29
|
+
r = x.publish( channel, data )
|
|
30
|
+
unless r["successful"]
|
|
31
|
+
puts "=> Message not send !"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
x.disconnect
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
$:.unshift( "../../lib" )
|
|
2
|
+
require 'rcomet/server'
|
|
3
|
+
|
|
4
|
+
RComet::Server.new( :host => '0.0.0.0', :port => 8990, :mount => '/', :server => :thin ) {
|
|
5
|
+
channel['/login'].callback do |message|
|
|
6
|
+
puts "someone send "
|
|
7
|
+
p message['data']
|
|
8
|
+
puts 'on channel /login'
|
|
9
|
+
channel["/from/#{message['data']}"]
|
|
10
|
+
end
|
|
11
|
+
}.start
|
|
12
|
+
|
|
13
|
+
while true
|
|
14
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'capcode'
|
|
3
|
+
require 'capcode/render/static'
|
|
4
|
+
require 'capcode/render/erb'
|
|
5
|
+
|
|
6
|
+
module Capcode
|
|
7
|
+
set :static, "static"
|
|
8
|
+
set :erb, "static"
|
|
9
|
+
set :verbose, true
|
|
10
|
+
|
|
11
|
+
class Index < Route '/'
|
|
12
|
+
def get
|
|
13
|
+
@ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last }
|
|
14
|
+
render :erb => :soapbox
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Capcode.run( )
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>RComet demo: chat client</title>
|
|
5
|
+
<link rel="stylesheet" href="/static/style.css" type="text/css" media="screen">
|
|
6
|
+
<script language="JavaScript" type="text/javascript" src="/static/dojo/dojo/dojo.js" charset="utf-8" djConfig="parseOnLoad: true"></script>
|
|
7
|
+
|
|
8
|
+
<script language="JavaScript" type="text/javascript">
|
|
9
|
+
dojo.require("dojox.cometd");
|
|
10
|
+
dojo.require("dojo.fx");
|
|
11
|
+
|
|
12
|
+
var comet = dojox.cometd;
|
|
13
|
+
comet.init("http://<%= @ip %>:8990");
|
|
14
|
+
|
|
15
|
+
var message = {
|
|
16
|
+
publish : function(msg) {
|
|
17
|
+
current = dojo.byId("stream").innerHTML
|
|
18
|
+
dojo.byId("stream").innerHTML = "<li><b>"+msg.data.username+"</b>: "+msg.data.message+"</li>"+current;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
</head>
|
|
24
|
+
<body>
|
|
25
|
+
<div class="container">
|
|
26
|
+
|
|
27
|
+
<h1><em>Soapbox</em> | a Twitter-style chat app</h1>
|
|
28
|
+
|
|
29
|
+
<!-- <form id="enterUsername" onSubmit="return login();"> -->
|
|
30
|
+
<div id="login">
|
|
31
|
+
<form id="enterUsername">
|
|
32
|
+
<label for="username">Pick a username</label>
|
|
33
|
+
<input type="text" name="username" id="username">
|
|
34
|
+
<input type="submit" value="Go">
|
|
35
|
+
</form>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div id="app">
|
|
39
|
+
<!-- <form id="addFollowee" onSubmit="return follow();"> -->
|
|
40
|
+
<form id="addFollowee">
|
|
41
|
+
<label for="followee">Follow</label>
|
|
42
|
+
<input type="text" name="followee" id="followee">
|
|
43
|
+
<input type="submit" value="Go">
|
|
44
|
+
</form>
|
|
45
|
+
|
|
46
|
+
<form id="postMessage">
|
|
47
|
+
<label for="message">Post a message</label><br>
|
|
48
|
+
<textarea name="message" id="message" rows="3" cols="40"></textarea>
|
|
49
|
+
<!-- <input type="button" value="Go" onClick="javascript:send();"> -->
|
|
50
|
+
<input type="submit" value="Send">
|
|
51
|
+
</form>
|
|
52
|
+
|
|
53
|
+
<ul id="stream">
|
|
54
|
+
</ul>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
<script language="JavaScript" type="text/javascript">
|
|
58
|
+
var username = null;
|
|
59
|
+
dojo.connect(dojo.byId("enterUsername"), "onsubmit", function(evt) {
|
|
60
|
+
evt.preventDefault();
|
|
61
|
+
dojo.stopEvent(evt);
|
|
62
|
+
username = dojo.byId("username").value;
|
|
63
|
+
comet.publish( '/login', username );
|
|
64
|
+
|
|
65
|
+
dojo.fadeOut({node:dojo.byId("enterUsername")}).play( );
|
|
66
|
+
dojo.animateProperty({
|
|
67
|
+
node: dojo.byId("login"),
|
|
68
|
+
properties: { height: { end: 0 } }
|
|
69
|
+
}).play( );
|
|
70
|
+
return false;
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
var addFolloweeForm = dojo.byId("addFollowee");
|
|
74
|
+
dojo.connect(addFolloweeForm, "onsubmit", function(evt) {
|
|
75
|
+
evt.preventDefault();
|
|
76
|
+
dojo.stopEvent(evt);
|
|
77
|
+
followee = dojo.byId("followee").value;
|
|
78
|
+
comet.subscribe( '/from/'+followee, message, "publish" );
|
|
79
|
+
return false;
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
var postMessageForm = dojo.byId("postMessage");
|
|
83
|
+
dojo.connect(postMessageForm, "onsubmit", function(evt) {
|
|
84
|
+
evt.preventDefault();
|
|
85
|
+
dojo.stopEvent(evt);
|
|
86
|
+
message = dojo.byId("message").value;
|
|
87
|
+
comet.publish( '/from/'+username, { "username":username, "message":message } );
|
|
88
|
+
return false;
|
|
89
|
+
})
|
|
90
|
+
</script>
|
|
91
|
+
</body>
|
|
92
|
+
</html>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background: #c9eb70;
|
|
3
|
+
margin: 0;
|
|
4
|
+
padding: 0;
|
|
5
|
+
font: 16px/1.5 Helvetica, Arial, sans-serif;
|
|
6
|
+
text-align: center;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.container {
|
|
10
|
+
text-align: left;
|
|
11
|
+
width: 400px;
|
|
12
|
+
margin: 40px auto;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
h1, form, ul li {
|
|
16
|
+
background: #fff;
|
|
17
|
+
padding: 24px;
|
|
18
|
+
border: 1px solid #9dba4f;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
h1 {
|
|
22
|
+
font-size: 20px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
h1 em {
|
|
26
|
+
font-style: normal;
|
|
27
|
+
font-weight: normal;
|
|
28
|
+
color: #444;
|
|
29
|
+
text-transform: uppercase;
|
|
30
|
+
letter-spacing: -0.06em;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
label {
|
|
34
|
+
color: #444;
|
|
35
|
+
font-weight: bold;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
ul, li {
|
|
39
|
+
list-style: none;
|
|
40
|
+
margin: 0;
|
|
41
|
+
padding: 0;
|
|
42
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module RComet
|
|
2
|
+
class ChannelSet #:nodoc:
|
|
3
|
+
def initialize
|
|
4
|
+
@channels = Hash.new
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def [](channel_or_path)
|
|
8
|
+
channel = nil
|
|
9
|
+
if( channel_or_path.class == RComet::Channel )
|
|
10
|
+
return @channels[channel_or_path.path] if @channels.has_key?(channel_or_path.path)
|
|
11
|
+
channel = channel_or_path
|
|
12
|
+
else
|
|
13
|
+
return @channels[channel_or_path] if @channels.has_key?(channel_or_path)
|
|
14
|
+
channel = RComet::Channel.new( channel_or_path )
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@channels[channel.path] = channel
|
|
18
|
+
return channel
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def []=(channel_or_path, data)
|
|
22
|
+
channel = self[channel_or_path]
|
|
23
|
+
channel.data( data )
|
|
24
|
+
return channel
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Channel
|
|
29
|
+
HANDSHAKE = '/meta/handshake'
|
|
30
|
+
CONNECT = '/meta/connect'
|
|
31
|
+
SUBSCRIBE = '/meta/subscribe'
|
|
32
|
+
UNSUBSCRIBE = '/meta/unsubscribe'
|
|
33
|
+
DISCONNECT = '/meta/disconnect'
|
|
34
|
+
|
|
35
|
+
attr_reader :path, :handler
|
|
36
|
+
|
|
37
|
+
# Create a new channel
|
|
38
|
+
def initialize( path, data = nil )
|
|
39
|
+
@path = path
|
|
40
|
+
@users = Hash.new
|
|
41
|
+
@data = data
|
|
42
|
+
@handler = nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Send data to the channel or, if no parameter is given, get available data for the channel
|
|
46
|
+
def data( data = nil, &block )
|
|
47
|
+
unless data or block_given?
|
|
48
|
+
return @data
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if block_given?
|
|
52
|
+
@data = yield( data )
|
|
53
|
+
else
|
|
54
|
+
@data = data
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@users.each do |id, user|
|
|
58
|
+
message = {
|
|
59
|
+
'channel' => @path,
|
|
60
|
+
'data' => @data,
|
|
61
|
+
'clientId' => id
|
|
62
|
+
}
|
|
63
|
+
user.send( message )
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Define the channel publishion callback
|
|
68
|
+
def callback( &block )
|
|
69
|
+
@handler = block
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def add_user( user ) #:nodoc:
|
|
73
|
+
@users[user.id] = user
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|