websocket-rails-js 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|