/
socketstream.js
130 lines (109 loc) · 3.82 KB
/
socketstream.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'use strict';
// SocketStream Browser Client
// ---------------------------
// The code in this file is always sent to the browser, regardless which websocket transport is used
var message, server, transport = null,
EventEmitter2 = require('eventemitter2').EventEmitter2;
// Setup message emitters
server = exports.server = new EventEmitter2();
message = exports.message = new EventEmitter2();
// Provide a place to store templates
exports.tmpl = {};
exports.assignTransport = function (config) {
transport = require('socketstream-transport')(server, message, config);
transport.send = transport.connect();
return transport.send;
};
exports.registerApi = function(name, fn) {
var api;
api = exports[name];
if (api) {
return console.error('SocketStream Error: Unable to register the \'ss.' + name + '\' responder as this name has already been taken');
} else {
exports[name] = fn;
return exports[name];
}
};
exports.send = function(responderId) {
return function(msg) {
return transport.send(responderId + '|' + msg);
};
};
/* ON DEMAND LOADING
*/
var async = {
loaded: {},
loading: new EventEmitter2
};
exports.load = {
// Enables asynchronous loading of additional client-side modules
// Pass the name of a module file (complete with file extension), or name of a directory in /client/code
code: function(nameOrDir, cb) {
var errorPrefix, onError, onSuccess;
// Strip any leading slash
if (nameOrDir && nameOrDir.substr(0, 1) === '/') {
nameOrDir = nameOrDir.substr(1);
}
// Check for errors. Note this feature requires jQuery at the moment
errorPrefix = 'SocketStream Error: The ss.load.code() command ';
if (!jQuery) {
return console.error(errorPrefix + 'requires jQuery to be present');
}
if (!nameOrDir) {
return console.error(errorPrefix + 'requires a directory to load. Specify it as the first argument. '+
'E.g. The ss.load.code(\'/mail\',cb) will load code in /client/code/mail');
}
if (!cb) {
return console.error(errorPrefix + 'requires a callback. Specify it as the last argument');
}
// If we've loaded this module or package before, callback right away
if (async.loaded[nameOrDir]) {
return cb();
}
// Else, register callback and use EE to prevent multiple reqs for the same mod/package to the server before the first responds
async.loading.once(nameOrDir, cb);
// Retrieve module or directory of modules from the server if this is the first request
if (async.loading.listeners(nameOrDir).length === 1) {
onError = function() {
console.error('SocketStream Error: Could not asynchronously load ' + nameOrDir);
return console.log(arguments);
};
onSuccess = function() {
async.loaded[nameOrDir] = true;
return async.loading.emit(nameOrDir);
};
// Send request to server
return $.ajax({
url: '/assets/ondemand/' + nameOrDir,
type: 'GET',
cache: false,
dataType: 'script',
success: onSuccess,
error: onError
});
}
},
// Load Web Workers from /client/workers
worker: function(name) {
return new Worker('/assets/workers/' + name);
}
};
/* LIVE RELOAD
*/
// Reload browser if reload system event received
server.on('__ss:reload', function() {
return window.location.reload();
});
// Reload CSS if only the stylesheets have changed
server.on('__ss:updateCSS', function() {
var h, tag, _i, _len, _ref;
_ref = document.getElementsByTagName('link');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
tag = _ref[_i];
if (tag.rel.toLowerCase().indexOf('stylesheet') >= 0 && tag.href) {
h = tag.href.replace(/(&|%5C?)\d+/, '');
tag.href = h + (h.indexOf('?') >= 0 ? '&' : '?') + (new Date().valueOf());
}
}
return console.log('CSS updated');
});