websocket-rails-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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +11 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +13 -0
- data/Rakefile +36 -0
- data/app/assets/javascripts/websocket_rails/abstract_connection.js.coffee +45 -0
- data/app/assets/javascripts/websocket_rails/channel.js.coffee +66 -0
- data/app/assets/javascripts/websocket_rails/connection.js.coffee +62 -0
- data/app/assets/javascripts/websocket_rails/event.js.coffee +43 -0
- data/app/assets/javascripts/websocket_rails/http_connection.js.coffee +56 -0
- data/app/assets/javascripts/websocket_rails/main.js +6 -0
- data/app/assets/javascripts/websocket_rails/websocket_connection.js.coffee +29 -0
- data/app/assets/javascripts/websocket_rails/websocket_rails.js.coffee +148 -0
- data/lib/websocket-rails-js.rb +1 -0
- data/lib/websocket_rails/js/engine.rb +8 -0
- data/lib/websocket_rails/js/version.rb +5 -0
- data/spec/javascripts/helpers/.gitkeep +0 -0
- data/spec/javascripts/helpers/helpers.coffee +7 -0
- data/spec/javascripts/support/jasmine.yml +139 -0
- data/spec/javascripts/support/jasmine_helper.rb +15 -0
- data/spec/javascripts/support/jquery.min.js +4 -0
- data/spec/javascripts/support/sinon-1.7.1.js +4343 -0
- data/spec/javascripts/websocket_rails/channel_spec.js.coffee +99 -0
- data/spec/javascripts/websocket_rails/connection_spec.js.coffee +136 -0
- data/spec/javascripts/websocket_rails/event_spec.js.coffee +70 -0
- data/spec/javascripts/websocket_rails/helpers.js.coffee +7 -0
- data/spec/javascripts/websocket_rails/websocket_rails_spec.js.coffee +233 -0
- data/src/websocket_rails/abstract_connection.js +71 -0
- data/src/websocket_rails/channel.js +133 -0
- data/src/websocket_rails/connection.js +91 -0
- data/src/websocket_rails/event.js +66 -0
- data/src/websocket_rails/http_connection.js +97 -0
- data/src/websocket_rails/websocket_connection.js +59 -0
- data/src/websocket_rails/websocket_rails.js +218 -0
- data/websocket-rails-js.gemspec +25 -0
- data/websocket_rails.0.0.1.min.js +1 -0
- metadata +135 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
Abstract Interface for the WebSocketRails client.
|
4
|
+
*/
|
5
|
+
|
6
|
+
(function() {
|
7
|
+
WebSocketRails.AbstractConnection = (function() {
|
8
|
+
function AbstractConnection(url, dispatcher) {
|
9
|
+
this.dispatcher = dispatcher;
|
10
|
+
this.message_queue = [];
|
11
|
+
}
|
12
|
+
|
13
|
+
AbstractConnection.prototype.close = function() {};
|
14
|
+
|
15
|
+
AbstractConnection.prototype.trigger = function(event) {
|
16
|
+
if (this.dispatcher.state !== 'connected') {
|
17
|
+
return this.message_queue.push(event);
|
18
|
+
} else {
|
19
|
+
return this.send_event(event);
|
20
|
+
}
|
21
|
+
};
|
22
|
+
|
23
|
+
AbstractConnection.prototype.send_event = function(event) {
|
24
|
+
if (this.connection_id != null) {
|
25
|
+
return event.connection_id = this.connection_id;
|
26
|
+
}
|
27
|
+
};
|
28
|
+
|
29
|
+
AbstractConnection.prototype.on_close = function(event) {
|
30
|
+
var close_event;
|
31
|
+
if (this.dispatcher && this.dispatcher._conn === this) {
|
32
|
+
close_event = new WebSocketRails.Event(['connection_closed', event]);
|
33
|
+
this.dispatcher.state = 'disconnected';
|
34
|
+
return this.dispatcher.dispatch(close_event);
|
35
|
+
}
|
36
|
+
};
|
37
|
+
|
38
|
+
AbstractConnection.prototype.on_error = function(event) {
|
39
|
+
var error_event;
|
40
|
+
if (this.dispatcher && this.dispatcher._conn === this) {
|
41
|
+
error_event = new WebSocketRails.Event(['connection_error', event]);
|
42
|
+
this.dispatcher.state = 'disconnected';
|
43
|
+
return this.dispatcher.dispatch(error_event);
|
44
|
+
}
|
45
|
+
};
|
46
|
+
|
47
|
+
AbstractConnection.prototype.on_message = function(event_data) {
|
48
|
+
if (this.dispatcher && this.dispatcher._conn === this) {
|
49
|
+
return this.dispatcher.new_message(event_data);
|
50
|
+
}
|
51
|
+
};
|
52
|
+
|
53
|
+
AbstractConnection.prototype.setConnectionId = function(connection_id) {
|
54
|
+
this.connection_id = connection_id;
|
55
|
+
};
|
56
|
+
|
57
|
+
AbstractConnection.prototype.flush_queue = function() {
|
58
|
+
var event, _i, _len, _ref;
|
59
|
+
_ref = this.message_queue;
|
60
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
61
|
+
event = _ref[_i];
|
62
|
+
this.trigger(event);
|
63
|
+
}
|
64
|
+
return this.message_queue = [];
|
65
|
+
};
|
66
|
+
|
67
|
+
return AbstractConnection;
|
68
|
+
|
69
|
+
})();
|
70
|
+
|
71
|
+
}).call(this);
|
@@ -0,0 +1,133 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
The channel object is returned when you subscribe to a channel.
|
4
|
+
|
5
|
+
For instance:
|
6
|
+
var dispatcher = new WebSocketRails('localhost:3000/websocket');
|
7
|
+
var awesome_channel = dispatcher.subscribe('awesome_channel');
|
8
|
+
awesome_channel.bind('event', function(data) { console.log('channel event!'); });
|
9
|
+
awesome_channel.trigger('awesome_event', awesome_object);
|
10
|
+
*/
|
11
|
+
|
12
|
+
(function() {
|
13
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
14
|
+
|
15
|
+
WebSocketRails.Channel = (function() {
|
16
|
+
function Channel(name, _dispatcher, is_private, on_success, on_failure) {
|
17
|
+
var event, event_name, _ref;
|
18
|
+
this.name = name;
|
19
|
+
this._dispatcher = _dispatcher;
|
20
|
+
this.is_private = is_private;
|
21
|
+
this.on_success = on_success;
|
22
|
+
this.on_failure = on_failure;
|
23
|
+
this._failure_launcher = __bind(this._failure_launcher, this);
|
24
|
+
this._success_launcher = __bind(this._success_launcher, this);
|
25
|
+
if (this.is_private) {
|
26
|
+
event_name = 'websocket_rails.subscribe_private';
|
27
|
+
} else {
|
28
|
+
event_name = 'websocket_rails.subscribe';
|
29
|
+
}
|
30
|
+
this.connection_id = (_ref = this._dispatcher._conn) != null ? _ref.connection_id : void 0;
|
31
|
+
event = new WebSocketRails.Event([
|
32
|
+
event_name, {
|
33
|
+
channel: this.name
|
34
|
+
}, {
|
35
|
+
connection_id: this.connection_id
|
36
|
+
}
|
37
|
+
], this._success_launcher, this._failure_launcher);
|
38
|
+
this._dispatcher.trigger_event(event);
|
39
|
+
this._callbacks = {};
|
40
|
+
this._token = void 0;
|
41
|
+
this._queue = [];
|
42
|
+
}
|
43
|
+
|
44
|
+
Channel.prototype.is_public = function() {
|
45
|
+
return !this.is_private;
|
46
|
+
};
|
47
|
+
|
48
|
+
Channel.prototype.destroy = function() {
|
49
|
+
var event, event_name, _ref;
|
50
|
+
if (this.connection_id === ((_ref = this._dispatcher._conn) != null ? _ref.connection_id : void 0)) {
|
51
|
+
event_name = 'websocket_rails.unsubscribe';
|
52
|
+
event = new WebSocketRails.Event([
|
53
|
+
event_name, {
|
54
|
+
channel: this.name
|
55
|
+
}, {
|
56
|
+
connection_id: this.connection_id,
|
57
|
+
token: this._token
|
58
|
+
}
|
59
|
+
]);
|
60
|
+
this._dispatcher.trigger_event(event);
|
61
|
+
}
|
62
|
+
return this._callbacks = {};
|
63
|
+
};
|
64
|
+
|
65
|
+
Channel.prototype.bind = function(event_name, callback) {
|
66
|
+
var _base;
|
67
|
+
if ((_base = this._callbacks)[event_name] == null) {
|
68
|
+
_base[event_name] = [];
|
69
|
+
}
|
70
|
+
return this._callbacks[event_name].push(callback);
|
71
|
+
};
|
72
|
+
|
73
|
+
Channel.prototype.unbind = function(event_name) {
|
74
|
+
return delete this._callbacks[event_name];
|
75
|
+
};
|
76
|
+
|
77
|
+
Channel.prototype.trigger = function(event_name, message) {
|
78
|
+
var event;
|
79
|
+
event = new WebSocketRails.Event([
|
80
|
+
event_name, message, {
|
81
|
+
connection_id: this.connection_id,
|
82
|
+
channel: this.name,
|
83
|
+
token: this._token
|
84
|
+
}
|
85
|
+
]);
|
86
|
+
if (!this._token) {
|
87
|
+
return this._queue.push(event);
|
88
|
+
} else {
|
89
|
+
return this._dispatcher.trigger_event(event);
|
90
|
+
}
|
91
|
+
};
|
92
|
+
|
93
|
+
Channel.prototype.dispatch = function(event_name, message) {
|
94
|
+
var callback, event, _i, _j, _len, _len1, _ref, _ref1, _results;
|
95
|
+
if (event_name === 'websocket_rails.channel_token') {
|
96
|
+
this._token = message['token'];
|
97
|
+
_ref = this._queue;
|
98
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
99
|
+
event = _ref[_i];
|
100
|
+
this._dispatcher.trigger_event(event);
|
101
|
+
}
|
102
|
+
return this._queue = [];
|
103
|
+
} else {
|
104
|
+
if (this._callbacks[event_name] == null) {
|
105
|
+
return;
|
106
|
+
}
|
107
|
+
_ref1 = this._callbacks[event_name];
|
108
|
+
_results = [];
|
109
|
+
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
110
|
+
callback = _ref1[_j];
|
111
|
+
_results.push(callback(message));
|
112
|
+
}
|
113
|
+
return _results;
|
114
|
+
}
|
115
|
+
};
|
116
|
+
|
117
|
+
Channel.prototype._success_launcher = function(data) {
|
118
|
+
if (this.on_success != null) {
|
119
|
+
return this.on_success(data);
|
120
|
+
}
|
121
|
+
};
|
122
|
+
|
123
|
+
Channel.prototype._failure_launcher = function(data) {
|
124
|
+
if (this.on_failure != null) {
|
125
|
+
return this.on_failure(data);
|
126
|
+
}
|
127
|
+
};
|
128
|
+
|
129
|
+
return Channel;
|
130
|
+
|
131
|
+
})();
|
132
|
+
|
133
|
+
}).call(this);
|
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
WebSocket Interface for the WebSocketRails client.
|
4
|
+
*/
|
5
|
+
|
6
|
+
(function() {
|
7
|
+
WebSocketRails.Connection = (function() {
|
8
|
+
function Connection(url, dispatcher) {
|
9
|
+
this.url = url;
|
10
|
+
this.dispatcher = dispatcher;
|
11
|
+
this.message_queue = [];
|
12
|
+
this.state = 'connecting';
|
13
|
+
this.connection_id;
|
14
|
+
if (!(this.url.match(/^wss?:\/\//) || this.url.match(/^ws?:\/\//))) {
|
15
|
+
if (window.location.protocol === 'https:') {
|
16
|
+
this.url = "wss://" + this.url;
|
17
|
+
} else {
|
18
|
+
this.url = "ws://" + this.url;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
this._conn = new WebSocket(this.url);
|
22
|
+
this._conn.onmessage = (function(_this) {
|
23
|
+
return function(event) {
|
24
|
+
var event_data;
|
25
|
+
event_data = JSON.parse(event.data);
|
26
|
+
return _this.on_message(event_data);
|
27
|
+
};
|
28
|
+
})(this);
|
29
|
+
this._conn.onclose = (function(_this) {
|
30
|
+
return function(event) {
|
31
|
+
return _this.on_close(event);
|
32
|
+
};
|
33
|
+
})(this);
|
34
|
+
this._conn.onerror = (function(_this) {
|
35
|
+
return function(event) {
|
36
|
+
return _this.on_error(event);
|
37
|
+
};
|
38
|
+
})(this);
|
39
|
+
}
|
40
|
+
|
41
|
+
Connection.prototype.on_message = function(event) {
|
42
|
+
return this.dispatcher.new_message(event);
|
43
|
+
};
|
44
|
+
|
45
|
+
Connection.prototype.on_close = function(event) {
|
46
|
+
var data;
|
47
|
+
this.dispatcher.state = 'disconnected';
|
48
|
+
data = (event != null ? event.data : void 0) ? event.data : event;
|
49
|
+
return this.dispatcher.dispatch(new WebSocketRails.Event(['connection_closed', data]));
|
50
|
+
};
|
51
|
+
|
52
|
+
Connection.prototype.on_error = function(event) {
|
53
|
+
this.dispatcher.state = 'disconnected';
|
54
|
+
return this.dispatcher.dispatch(new WebSocketRails.Event(['connection_error', event.data]));
|
55
|
+
};
|
56
|
+
|
57
|
+
Connection.prototype.trigger = function(event) {
|
58
|
+
if (this.dispatcher.state !== 'connected') {
|
59
|
+
return this.message_queue.push(event);
|
60
|
+
} else {
|
61
|
+
return this.send_event(event);
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
65
|
+
Connection.prototype.close = function() {
|
66
|
+
return this._conn.close();
|
67
|
+
};
|
68
|
+
|
69
|
+
Connection.prototype.setConnectionId = function(connection_id) {
|
70
|
+
return this.connection_id = connection_id;
|
71
|
+
};
|
72
|
+
|
73
|
+
Connection.prototype.send_event = function(event) {
|
74
|
+
return this._conn.send(event.serialize());
|
75
|
+
};
|
76
|
+
|
77
|
+
Connection.prototype.flush_queue = function() {
|
78
|
+
var event, _i, _len, _ref;
|
79
|
+
_ref = this.message_queue;
|
80
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
81
|
+
event = _ref[_i];
|
82
|
+
this.trigger(event);
|
83
|
+
}
|
84
|
+
return this.message_queue = [];
|
85
|
+
};
|
86
|
+
|
87
|
+
return Connection;
|
88
|
+
|
89
|
+
})();
|
90
|
+
|
91
|
+
}).call(this);
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
The Event object stores all the relevant event information.
|
4
|
+
*/
|
5
|
+
|
6
|
+
(function() {
|
7
|
+
WebSocketRails.Event = (function() {
|
8
|
+
function Event(message, success_callback, failure_callback) {
|
9
|
+
var options;
|
10
|
+
this.success_callback = success_callback;
|
11
|
+
this.failure_callback = failure_callback;
|
12
|
+
this.name = message[0];
|
13
|
+
this.data = message[1];
|
14
|
+
options = message[2];
|
15
|
+
if (options != null) {
|
16
|
+
this.id = options['id'] != null ? options['id'] : ((1 + Math.random()) * 0x10000) | 0;
|
17
|
+
this.channel = options.channel;
|
18
|
+
this.token = options.token;
|
19
|
+
this.connection_id = options.connection_id;
|
20
|
+
if (options.success != null) {
|
21
|
+
this.result = true;
|
22
|
+
this.success = options.success;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
Event.prototype.is_channel = function() {
|
28
|
+
return this.channel != null;
|
29
|
+
};
|
30
|
+
|
31
|
+
Event.prototype.is_result = function() {
|
32
|
+
return typeof this.result !== 'undefined';
|
33
|
+
};
|
34
|
+
|
35
|
+
Event.prototype.is_ping = function() {
|
36
|
+
return this.name === 'websocket_rails.ping';
|
37
|
+
};
|
38
|
+
|
39
|
+
Event.prototype.serialize = function() {
|
40
|
+
return JSON.stringify([this.name, this.data, this.meta_data()]);
|
41
|
+
};
|
42
|
+
|
43
|
+
Event.prototype.meta_data = function() {
|
44
|
+
return {
|
45
|
+
id: this.id,
|
46
|
+
connection_id: this.connection_id,
|
47
|
+
channel: this.channel,
|
48
|
+
token: this.token
|
49
|
+
};
|
50
|
+
};
|
51
|
+
|
52
|
+
Event.prototype.run_callbacks = function(success, result) {
|
53
|
+
this.success = success;
|
54
|
+
this.result = result;
|
55
|
+
if (this.success === true) {
|
56
|
+
return typeof this.success_callback === "function" ? this.success_callback(this.result) : void 0;
|
57
|
+
} else {
|
58
|
+
return typeof this.failure_callback === "function" ? this.failure_callback(this.result) : void 0;
|
59
|
+
}
|
60
|
+
};
|
61
|
+
|
62
|
+
return Event;
|
63
|
+
|
64
|
+
})();
|
65
|
+
|
66
|
+
}).call(this);
|
@@ -0,0 +1,97 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
HTTP Interface for the WebSocketRails client.
|
4
|
+
*/
|
5
|
+
|
6
|
+
(function() {
|
7
|
+
var __hasProp = {}.hasOwnProperty,
|
8
|
+
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
9
|
+
|
10
|
+
WebSocketRails.HttpConnection = (function(_super) {
|
11
|
+
__extends(HttpConnection, _super);
|
12
|
+
|
13
|
+
HttpConnection.prototype.connection_type = 'http';
|
14
|
+
|
15
|
+
HttpConnection.prototype._httpFactories = function() {
|
16
|
+
return [
|
17
|
+
function() {
|
18
|
+
return new XMLHttpRequest();
|
19
|
+
}, function() {
|
20
|
+
return new ActiveXObject("Msxml2.XMLHTTP");
|
21
|
+
}, function() {
|
22
|
+
return new ActiveXObject("Msxml3.XMLHTTP");
|
23
|
+
}, function() {
|
24
|
+
return new ActiveXObject("Microsoft.XMLHTTP");
|
25
|
+
}
|
26
|
+
];
|
27
|
+
};
|
28
|
+
|
29
|
+
function HttpConnection(url, dispatcher) {
|
30
|
+
this.dispatcher = dispatcher;
|
31
|
+
HttpConnection.__super__.constructor.apply(this, arguments);
|
32
|
+
this._url = "http://" + url;
|
33
|
+
this._conn = this._createXMLHttpObject();
|
34
|
+
this.last_pos = 0;
|
35
|
+
this._conn.onreadystatechange = (function(_this) {
|
36
|
+
return function() {
|
37
|
+
return _this._parse_stream();
|
38
|
+
};
|
39
|
+
})(this);
|
40
|
+
this._conn.addEventListener("load", this.on_close, false);
|
41
|
+
this._conn.open("GET", this._url, true);
|
42
|
+
this._conn.send();
|
43
|
+
}
|
44
|
+
|
45
|
+
HttpConnection.prototype.close = function() {
|
46
|
+
return this._conn.abort();
|
47
|
+
};
|
48
|
+
|
49
|
+
HttpConnection.prototype.send_event = function(event) {
|
50
|
+
HttpConnection.__super__.send_event.apply(this, arguments);
|
51
|
+
return this._post_data(event.serialize());
|
52
|
+
};
|
53
|
+
|
54
|
+
HttpConnection.prototype._post_data = function(payload) {
|
55
|
+
return $.ajax(this._url, {
|
56
|
+
type: 'POST',
|
57
|
+
data: {
|
58
|
+
client_id: this.connection_id,
|
59
|
+
data: payload
|
60
|
+
},
|
61
|
+
success: function() {}
|
62
|
+
});
|
63
|
+
};
|
64
|
+
|
65
|
+
HttpConnection.prototype._createXMLHttpObject = function() {
|
66
|
+
var e, factories, factory, xmlhttp, _i, _len;
|
67
|
+
xmlhttp = false;
|
68
|
+
factories = this._httpFactories();
|
69
|
+
for (_i = 0, _len = factories.length; _i < _len; _i++) {
|
70
|
+
factory = factories[_i];
|
71
|
+
try {
|
72
|
+
xmlhttp = factory();
|
73
|
+
} catch (_error) {
|
74
|
+
e = _error;
|
75
|
+
continue;
|
76
|
+
}
|
77
|
+
break;
|
78
|
+
}
|
79
|
+
return xmlhttp;
|
80
|
+
};
|
81
|
+
|
82
|
+
HttpConnection.prototype._parse_stream = function() {
|
83
|
+
var data, event_data;
|
84
|
+
if (this._conn.readyState === 3) {
|
85
|
+
data = this._conn.responseText.substring(this.last_pos);
|
86
|
+
this.last_pos = this._conn.responseText.length;
|
87
|
+
data = data.replace(/\]\]\[\[/g, "],[");
|
88
|
+
event_data = JSON.parse(data);
|
89
|
+
return this.on_message(event_data);
|
90
|
+
}
|
91
|
+
};
|
92
|
+
|
93
|
+
return HttpConnection;
|
94
|
+
|
95
|
+
})(WebSocketRails.AbstractConnection);
|
96
|
+
|
97
|
+
}).call(this);
|