rocket-js 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,8 @@
1
+ require 'rubygems'
2
+ require 'mocha'
3
+ require 'rspec'
4
+ require 'rocket-js'
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :mocha
8
+ end
@@ -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
+ };
@@ -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
+ */