rocket-js 0.0.1
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 +24 -0
- data/LICENSE +20 -0
- data/README.md +1 -0
- data/Rakefile +70 -0
- data/bin/rocket-js +13 -0
- data/lib/rocket-js.rb +2 -0
- data/lib/rocket/js.rb +8 -0
- data/lib/rocket/js/builder.rb +83 -0
- data/lib/rocket/js/cli.rb +24 -0
- data/lib/rocket/js/version.rb +14 -0
- data/rocket-0.0.1.min.js +45 -0
- data/rocket-js.gemspec +84 -0
- data/spec/js/app.rb +15 -0
- data/spec/js/public/WebSocketMain.swf +0 -0
- data/spec/js/public/favicon.ico +0 -0
- data/spec/js/public/jquery-1.4.2.min.js +154 -0
- data/spec/js/public/qunit.css +119 -0
- data/spec/js/public/qunit.js +1069 -0
- data/spec/js/public/test.js +131 -0
- data/spec/js/public/testing/WebSocketMain.swf +0 -0
- data/spec/js/public/testing/WebSocketMainInsecure.zip +0 -0
- data/spec/js/public/testing/rocket-0.0.1.js +1445 -0
- data/spec/js/views/index.erb +40 -0
- data/spec/ruby/spec_helper.rb +8 -0
- data/src/rocket.channels.js +127 -0
- data/src/rocket.core.js +213 -0
- data/src/rocket.defaults.js +50 -0
- data/src/rocket.license.js +42 -0
- data/src/vendor/json/json2.js +482 -0
- metadata +175 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<link rel="stylesheet" href="/qunit.css">
|
5
|
+
<script src="/qunit.js"></script>
|
6
|
+
<script src="/jquery-1.4.2.min.js"></script>
|
7
|
+
<script src="/testing/rocket-<%= Rocket::JS.version %>.js"></script>
|
8
|
+
<script>
|
9
|
+
|
10
|
+
// The web-socket-js configuration.
|
11
|
+
WEB_SOCKET_SWF_LOCATION = 'rocket/WebSocketMain.swf';
|
12
|
+
WEB_SOCKET_DEBUG = false;
|
13
|
+
|
14
|
+
$(document).ready(function() {
|
15
|
+
// Logger...
|
16
|
+
Rocket.log = function(msg) { $("#log").append("<li>"+msg+"</li>") };
|
17
|
+
|
18
|
+
// Build new rocket
|
19
|
+
rocket = new Rocket('ws://localhost:9772', 'test_app');
|
20
|
+
// Subscribe a channel.
|
21
|
+
testChannel = rocket.subscribe('test-channel');
|
22
|
+
// Bind callback to event.
|
23
|
+
//testChannel.bind('test-event', function(data) {
|
24
|
+
// alert('hello!');
|
25
|
+
//});
|
26
|
+
});
|
27
|
+
</script>
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<ul id="log">
|
31
|
+
|
32
|
+
<ul>
|
33
|
+
<!--
|
34
|
+
<h1 id="qunit-header">Pusher Tests</h1>
|
35
|
+
<h2 id="qunit-banner"></h2>
|
36
|
+
<h2 id="qunit-userAgent"></h2>
|
37
|
+
<ol id="qunit-tests"></ol>
|
38
|
+
-->
|
39
|
+
</body>
|
40
|
+
</html>
|
@@ -0,0 +1,127 @@
|
|
1
|
+
/**
|
2
|
+
* This object helps with channels management. Examples:
|
3
|
+
*
|
4
|
+
* channels = new Rocket.Channels();
|
5
|
+
* channels.add('test');
|
6
|
+
* channels.find('test');
|
7
|
+
* channels.remove('test');
|
8
|
+
* // ...
|
9
|
+
*
|
10
|
+
* @class
|
11
|
+
* @constructor
|
12
|
+
*/
|
13
|
+
Rocket.Channels = function() {
|
14
|
+
this.all = {};
|
15
|
+
};
|
16
|
+
|
17
|
+
Rocket.Channels.prototype = {
|
18
|
+
/**
|
19
|
+
* Append new channel to the list of registered.
|
20
|
+
*
|
21
|
+
* @param {string} channelName
|
22
|
+
* @return Rocket.Channel
|
23
|
+
*/
|
24
|
+
add: function(channelName) {
|
25
|
+
existingChannel = this.find(channelName)
|
26
|
+
if (!existingChannel) {
|
27
|
+
return (this.all[channelName] = new Rocket.Channel());
|
28
|
+
} else {
|
29
|
+
return existingChannel;
|
30
|
+
}
|
31
|
+
},
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Returns channel with specified name when it exists.
|
35
|
+
*
|
36
|
+
* @param {string} channelName
|
37
|
+
* @return Rocket.Channel
|
38
|
+
*/
|
39
|
+
find: function(channelName) {
|
40
|
+
return this.all[channelName];
|
41
|
+
},
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Remove specified channel from the list.
|
45
|
+
*
|
46
|
+
* @param {string} channelName
|
47
|
+
* @return void
|
48
|
+
*/
|
49
|
+
remove: function(channelName) {
|
50
|
+
delete this.all[channelName];
|
51
|
+
}
|
52
|
+
};
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Single channel. It keeps eg. list of callbacks for all binded events,
|
56
|
+
* and helps with events dispatching.
|
57
|
+
*
|
58
|
+
* channel = new Rocket.Channel();
|
59
|
+
* channel.bind('my-event', function(data) {
|
60
|
+
* // do something with given data ...
|
61
|
+
* })
|
62
|
+
*
|
63
|
+
* @class
|
64
|
+
* @constructor
|
65
|
+
*/
|
66
|
+
Rocket.Channel = function() {
|
67
|
+
this.callbacks = {};
|
68
|
+
this.globalCallbacks = [];
|
69
|
+
};
|
70
|
+
|
71
|
+
Rocket.Channel.prototype = {
|
72
|
+
/**
|
73
|
+
* Assign callback to given event. More than one callback can be assigned
|
74
|
+
* to one event, eg:
|
75
|
+
*
|
76
|
+
* channel.bind('my-event', function(data){ alert('first one!') });
|
77
|
+
* channel.bind('my-event', function(data){ alert('second one!') });
|
78
|
+
*
|
79
|
+
* @param {string} eventName
|
80
|
+
* @param {function} callback
|
81
|
+
* @return self
|
82
|
+
*/
|
83
|
+
bind: function(eventName, callback) {
|
84
|
+
this.callbacks[eventName] = this.callbacks[eventName] || [];
|
85
|
+
this.callbacks[eventName].push(callback);
|
86
|
+
return this;
|
87
|
+
},
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Creates global callback which will be invoked on all events just after
|
91
|
+
* processing callbacks assigned to it.
|
92
|
+
*
|
93
|
+
* channel.bindAll(function(event, data){ alert(event) });
|
94
|
+
*
|
95
|
+
* @param {function} callback
|
96
|
+
* @return self
|
97
|
+
*/
|
98
|
+
bindAll: function(callback) {
|
99
|
+
this.globalCallbacks.push(callback);
|
100
|
+
return this;
|
101
|
+
},
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Dispatch given event with passing data to all registered callbacks.
|
105
|
+
* All global callbacks will be called here too.
|
106
|
+
*
|
107
|
+
* channel.dispatch('my-event', {'hello': 'world'});
|
108
|
+
*
|
109
|
+
* @param {string} eventName
|
110
|
+
* @param {Object} eventData
|
111
|
+
* @return void
|
112
|
+
*/
|
113
|
+
dispatch: function(eventName, eventData) {
|
114
|
+
var callbacks = this.callbacks[eventName]
|
115
|
+
if (callbacks) {
|
116
|
+
Rocket.log('Rocket : executing callbacks for ' + eventName)
|
117
|
+
for (var i = 0; i < callbacks.length; i++) {
|
118
|
+
callbacks[i](eventData);
|
119
|
+
}
|
120
|
+
} else if (!this.isGlobal) {
|
121
|
+
Rocket.log('Rocket : no callbacks for ' + eventName)
|
122
|
+
}
|
123
|
+
for (var i = 0; i < this.globalCallbacks.length; i++) {
|
124
|
+
this.globalCallbacks[i](eventName, eventData);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
};
|
data/src/rocket.core.js
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
/**
|
2
|
+
* Rocket base class. Examples:
|
3
|
+
*
|
4
|
+
* rocket = new Rocket('ws://host.com:8080', 'my-app'); // no trailing slash in url!
|
5
|
+
* rocket = new Rocket('wss://host.com:433', 'my-secured-app');
|
6
|
+
*
|
7
|
+
* @class
|
8
|
+
* @constructor
|
9
|
+
*/
|
10
|
+
var Rocket = function(url, appID) {
|
11
|
+
this.socketId;
|
12
|
+
this.url = url + '/app/' + appID;
|
13
|
+
this.appID = appID;
|
14
|
+
this.channels = new Rocket.Channels();
|
15
|
+
this.retryCounter = 0;
|
16
|
+
this.isConnected = false;
|
17
|
+
this.globalChannel = new Rocket.Channel();
|
18
|
+
this.globalChannel.isGlobal = true
|
19
|
+
this.connect();
|
20
|
+
|
21
|
+
var self = this;
|
22
|
+
|
23
|
+
this.globalChannel.bind('rocket:connected', function(data) {
|
24
|
+
self.isConnected = true;
|
25
|
+
self.retryCounter = 0;
|
26
|
+
self.socketId = data.socket_id;
|
27
|
+
self.subscribeAll();
|
28
|
+
});
|
29
|
+
|
30
|
+
this.globalChannel.bind('rocket:error', function(data) {
|
31
|
+
//self.log("Rocket : error : " + data.message);
|
32
|
+
});
|
33
|
+
};
|
34
|
+
|
35
|
+
Rocket.prototype = {
|
36
|
+
/**
|
37
|
+
* Establish connection with specified web socket server.
|
38
|
+
*
|
39
|
+
* @return self
|
40
|
+
*/
|
41
|
+
connect: function() {
|
42
|
+
Rocket.log('Rocket : connecting with ' + this.url);
|
43
|
+
this.allowReconnect = true
|
44
|
+
var self = this;
|
45
|
+
|
46
|
+
if (window["WebSocket"]) {
|
47
|
+
this.connection = new WebSocket(this.url);
|
48
|
+
this.connection.onmessage = function(msg) { self.onmessage(msg); };
|
49
|
+
this.connection.onclose = function() { self.onclose(); };
|
50
|
+
this.connection.onopen = function() { self.onopen(); };
|
51
|
+
} else {
|
52
|
+
Rocket.log("Rocket : can't establish connection")
|
53
|
+
this.connection = {};
|
54
|
+
this.onclose();
|
55
|
+
}
|
56
|
+
return this;
|
57
|
+
},
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Close connection with web socket server and cleanup configuration.
|
61
|
+
*
|
62
|
+
* @return self
|
63
|
+
*/
|
64
|
+
disconnect: function() {
|
65
|
+
Rocket.log('Rocket : disconnecting');
|
66
|
+
this.allowReconnect = false;
|
67
|
+
this.isConnected = false;
|
68
|
+
this.retryCount = 0;
|
69
|
+
this.connection.close();
|
70
|
+
return this;
|
71
|
+
},
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Trying reconnect to socket after specified time.
|
75
|
+
*
|
76
|
+
* @param {integer} delay
|
77
|
+
* @return self
|
78
|
+
*/
|
79
|
+
reconnect: function(delay) {
|
80
|
+
var self = this;
|
81
|
+
setTimeout(function(){ self.connect(); }, delay);
|
82
|
+
return this;
|
83
|
+
},
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Searches for given channel and return it when exists.
|
87
|
+
*
|
88
|
+
* @param {string} channelName
|
89
|
+
* @return Rocket.Channel
|
90
|
+
*/
|
91
|
+
channel: function(channelName) {
|
92
|
+
return this.channels.find(channelName)
|
93
|
+
},
|
94
|
+
|
95
|
+
/**
|
96
|
+
* Trigger given event by sending specified data.
|
97
|
+
*
|
98
|
+
* rocket.trigger('rocket:unsubscribe', { channel: 'my-channel' });
|
99
|
+
*
|
100
|
+
* @param {string} eventName
|
101
|
+
* @param {Object} data
|
102
|
+
* @return self
|
103
|
+
*/
|
104
|
+
trigger: function(eventName, data) {
|
105
|
+
if (this.isConnected) {
|
106
|
+
var payload = JSON.stringify({ event: eventName, data: data });
|
107
|
+
Rocket.log("Rocket : triggering event : " + payload);
|
108
|
+
this.connection.send(payload);
|
109
|
+
} else {
|
110
|
+
Rocket.log("Rocket : not connected : can't trigger event " + eventName);
|
111
|
+
}
|
112
|
+
return this;
|
113
|
+
},
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Subscribes specified channel and returns it.
|
117
|
+
*
|
118
|
+
* myChannel = rocket.subscribe('my-channel');
|
119
|
+
* myChannel.bind('my-event', function(data) {
|
120
|
+
* // do something with received data...
|
121
|
+
* });
|
122
|
+
*
|
123
|
+
* @param {string} channelName
|
124
|
+
* @return Rocket.Channel
|
125
|
+
*/
|
126
|
+
subscribe: function(channelName) {
|
127
|
+
var channel = this.channels.add(channelName);
|
128
|
+
this.trigger('rocket:subscribe', { channel: channelName });
|
129
|
+
return channel;
|
130
|
+
},
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Unsubscribes specified channel.
|
134
|
+
*
|
135
|
+
* myChannel = rocket.subscribe('my-channel');
|
136
|
+
* myChannel.bind('unsubscribe', function(data) {
|
137
|
+
* rocket.unsubscribe('my-channel');
|
138
|
+
* });
|
139
|
+
*
|
140
|
+
* @param {string} channelName
|
141
|
+
* @return self
|
142
|
+
*/
|
143
|
+
unsubscribe: function(channelName) {
|
144
|
+
this.channels.remove(channelName);
|
145
|
+
this.trigger('rocket:unsubscribe', { channel: channelName });
|
146
|
+
return this;
|
147
|
+
},
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Subscribe all registered channels. It's usualy used to subscribe all
|
151
|
+
* registered just after open connetion (or to re-subscribe after reconnect).
|
152
|
+
*
|
153
|
+
* @return void
|
154
|
+
*/
|
155
|
+
subscribeAll: function() {
|
156
|
+
for (var channel in this.channels.all) {
|
157
|
+
if (this.channels.all.hasOwnProperty(channel)) {
|
158
|
+
this.subscribe(channel);
|
159
|
+
}
|
160
|
+
};
|
161
|
+
},
|
162
|
+
|
163
|
+
/**
|
164
|
+
* Callback invoked when conneciton is closed.
|
165
|
+
*
|
166
|
+
* @return void
|
167
|
+
*/
|
168
|
+
onclose: function() {
|
169
|
+
Rocket.log("Rocket : socket closed");
|
170
|
+
this.globalChannel.dispatch('rocket:close', null);
|
171
|
+
var time = Rocket.reconnectDelay;
|
172
|
+
|
173
|
+
if (!(this.isConnected)) {
|
174
|
+
this.globalChannel.dispatch("rocket:disconnected", {});
|
175
|
+
|
176
|
+
if (Rocket.allowReconnect) {
|
177
|
+
Rocket.log('Pusher : reconnecting in 5 seconds...');
|
178
|
+
this.reconnect(time);
|
179
|
+
}
|
180
|
+
} else {
|
181
|
+
this.globalChannel("rocket:connection_failed", {});
|
182
|
+
|
183
|
+
if (this.retryCounter == 0){
|
184
|
+
time = 100;
|
185
|
+
}
|
186
|
+
this.retryCounter = this.retryCounter + 1
|
187
|
+
this.reconnect(time);
|
188
|
+
}
|
189
|
+
this.connected = false;
|
190
|
+
},
|
191
|
+
|
192
|
+
/**
|
193
|
+
* Callback invoked when connection is established.
|
194
|
+
*
|
195
|
+
* @return void
|
196
|
+
*/
|
197
|
+
onopen: function() {
|
198
|
+
this.globalChannel.dispatch('rocket:open', null);
|
199
|
+
},
|
200
|
+
|
201
|
+
/**
|
202
|
+
* Callback invoked when message is received.
|
203
|
+
*
|
204
|
+
* @param {string} msg
|
205
|
+
* @return void
|
206
|
+
*/
|
207
|
+
onmessage: function(msg) {
|
208
|
+
Rocket.log("Rocket : received message : " + msg.data)
|
209
|
+
var params = JSON.parse(msg.data);
|
210
|
+
var channel = params.channel ? this.channel(params.channel) : this.globalChannel;
|
211
|
+
channel.dispatch(params.event, params.data);
|
212
|
+
},
|
213
|
+
};
|
@@ -0,0 +1,50 @@
|
|
1
|
+
// The web-socket-js default configuration.
|
2
|
+
|
3
|
+
// Where your WebSocketMain.swf is located?
|
4
|
+
var WEB_SOCKET_SWF_LOCATION = 'WebSocketMain.swf';
|
5
|
+
// Run web socket in debug mode?
|
6
|
+
var WEB_SOCKET_DEBUG = false;
|
7
|
+
|
8
|
+
// Rocket defaults.
|
9
|
+
|
10
|
+
/**
|
11
|
+
* How many miliseconds system will wait until next reconnect try.
|
12
|
+
*
|
13
|
+
* @type integer
|
14
|
+
*/
|
15
|
+
Rocket.reconnectDelay = 5000;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Allow socket reconnect?
|
19
|
+
*
|
20
|
+
* @type boolean
|
21
|
+
*/
|
22
|
+
Rocket.allowReconnect = true;
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Default logger. You can replace it with your own, eg.
|
26
|
+
*
|
27
|
+
* Rocket.log = function(msg) { console.log(msg) };
|
28
|
+
*
|
29
|
+
* @param {string} msg
|
30
|
+
* @return void
|
31
|
+
*/
|
32
|
+
Rocket.log = function(msg) {
|
33
|
+
// nothing to do...
|
34
|
+
};
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Default data parser. By default received data is treated as JSON. You
|
38
|
+
* can change this behaviour by replacing this parser.
|
39
|
+
*
|
40
|
+
* @param {string} data
|
41
|
+
* @return Object or string
|
42
|
+
*/
|
43
|
+
Rocket.parser = function(data) {
|
44
|
+
try {
|
45
|
+
return JSON.parse(data);
|
46
|
+
} catch(e) {
|
47
|
+
Pusher.log("Rocket : data attribute not valid JSON - you may wish to implement your own Rocket.parser");
|
48
|
+
return data;
|
49
|
+
}
|
50
|
+
};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/**
|
2
|
+
* Rocket JavaScript Library v<%= VERSION %>
|
3
|
+
*
|
4
|
+
* Copyright 2010, Araneo Ltd. <http://www.araneo.pl>
|
5
|
+
* Released under the MIT license.
|
6
|
+
*
|
7
|
+
* Author: Chris Kowalik <chris@nu7hat.ch>
|
8
|
+
*/
|
9
|
+
|
10
|
+
/**
|
11
|
+
* This code is strongly inspired by and based on the Pusher JavaScript Library.
|
12
|
+
*
|
13
|
+
* Pusher JavaScript Library:
|
14
|
+
*
|
15
|
+
* Copyright 2010, New Bamboo <http://new-bamboo.co.uk/>
|
16
|
+
* Released under the MIT licence.
|
17
|
+
* Reference: http://pusherapp.com
|
18
|
+
*
|
19
|
+
* This library contains also code with the following licences:
|
20
|
+
*
|
21
|
+
* web_socket.js:
|
22
|
+
*
|
23
|
+
* Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
|
24
|
+
* License: New BSD License
|
25
|
+
* Reference: http://dev.w3.org/html5/websockets/
|
26
|
+
* Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
|
27
|
+
*
|
28
|
+
* swfobject.js:
|
29
|
+
*
|
30
|
+
* SWFObject v2.2 <http://code.google.com/p/swfobject/>
|
31
|
+
* is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
|
32
|
+
*
|
33
|
+
* FABridge.js:
|
34
|
+
*
|
35
|
+
* Copyright 2006 Adobe Systems Incorporated
|
36
|
+
*
|
37
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
38
|
+
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
39
|
+
* 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:
|
40
|
+
*
|
41
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
42
|
+
*/
|