2013-10-31 13:03:50 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2013-10-31 12:10:53 +00:00
|
|
|
// Wire protocol representation of events and actions
|
|
|
|
|
|
|
|
function encodeEvent(e) {
|
|
|
|
switch (e.type) {
|
|
|
|
case "routes":
|
|
|
|
var rs = [];
|
|
|
|
for (var i = 0; i < e.routes.length; i++) {
|
|
|
|
rs.push(e.routes[i].toJSON());
|
|
|
|
}
|
|
|
|
return ["routes", rs];
|
|
|
|
case "message":
|
|
|
|
return ["message", e.message, e.metaLevel, e.isFeedback];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function decodeAction(j) {
|
|
|
|
switch (j[0]) {
|
|
|
|
case "routes":
|
|
|
|
var rs = [];
|
|
|
|
for (var i = 0; i < j[1].length; i++) {
|
|
|
|
rs.push(Route.fromJSON(j[1][i]));
|
|
|
|
}
|
|
|
|
return updateRoutes(rs);
|
|
|
|
case "message":
|
|
|
|
return sendMessage(j[1], j[2], j[3]);
|
|
|
|
default:
|
|
|
|
throw { message: "Invalid JSON-encoded action: " + JSON.stringify(j) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Generic Spy
|
|
|
|
|
2013-10-17 15:38:47 +00:00
|
|
|
function Spy() {
|
|
|
|
}
|
|
|
|
|
|
|
|
Spy.prototype.boot = function () {
|
2013-10-31 12:10:53 +00:00
|
|
|
World.updateRoutes([sub(__, 0, Infinity), pub(__, 0, Infinity)]);
|
2013-10-17 15:38:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Spy.prototype.handleEvent = function (e) {
|
2013-10-31 12:10:53 +00:00
|
|
|
switch (e.type) {
|
|
|
|
case "routes": console.log("SPY", "routes", e.routes); break;
|
|
|
|
case "message": console.log("SPY", "message", e.message, e.metaLevel, e.isFeedback); break;
|
|
|
|
default: console.log("SPY", "unknown", e); break;
|
|
|
|
}
|
2013-10-17 15:38:47 +00:00
|
|
|
};
|
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// JQuery event driver
|
|
|
|
|
|
|
|
function spawnJQueryDriver() {
|
|
|
|
var d = new DemandMatcher(["jQuery", __, __, __]);
|
|
|
|
d.onDemandIncrease = function (r) {
|
|
|
|
var selector = r.pattern[1];
|
|
|
|
var eventName = r.pattern[2];
|
|
|
|
World.spawn(new JQueryEventRouter(selector, eventName),
|
|
|
|
[pub(["jQuery", selector, eventName, __]),
|
|
|
|
pub(["jQuery", selector, eventName, __], 0, 1)]);
|
|
|
|
};
|
|
|
|
World.spawn(d);
|
|
|
|
}
|
|
|
|
|
2013-10-22 18:14:51 +00:00
|
|
|
function JQueryEventRouter(selector, eventName) {
|
|
|
|
var self = this;
|
|
|
|
this.selector = selector;
|
|
|
|
this.eventName = eventName;
|
|
|
|
this.handler =
|
2013-10-31 12:10:53 +00:00
|
|
|
World.wrap(function (e) {
|
|
|
|
World.send(["jQuery", self.selector, self.eventName, e]);
|
|
|
|
e.preventDefault();
|
|
|
|
return false;
|
|
|
|
});
|
2013-10-22 18:14:51 +00:00
|
|
|
$(this.selector).on(this.eventName, this.handler);
|
2013-10-17 15:38:47 +00:00
|
|
|
}
|
|
|
|
|
2013-10-22 18:14:51 +00:00
|
|
|
JQueryEventRouter.prototype.handleEvent = function (e) {
|
|
|
|
if (e.type === "routes" && e.routes.length === 0) {
|
|
|
|
$(this.selector).off(this.eventName, this.handler);
|
|
|
|
World.exit();
|
2013-10-17 15:38:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-01 11:57:50 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Wake detector - notices when something (such as
|
|
|
|
// suspension/sleeping!) has caused periodic activities to be
|
|
|
|
// interrupted, and warns others about it
|
|
|
|
// Inspired by http://blog.alexmaccaw.com/javascript-wake-event
|
|
|
|
|
|
|
|
function WakeDetector(period) {
|
|
|
|
this.message = "wake";
|
|
|
|
this.period = period || 10000;
|
|
|
|
this.mostRecentTrigger = +(new Date());
|
|
|
|
this.timerId = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
WakeDetector.prototype.boot = function () {
|
|
|
|
var self = this;
|
|
|
|
World.updateRoutes([pub(this.message)]);
|
|
|
|
this.timerId = setInterval(World.wrap(function () { self.trigger(); }), this.period);
|
|
|
|
};
|
|
|
|
|
|
|
|
WakeDetector.prototype.handleEvent = function (e) {};
|
|
|
|
|
|
|
|
WakeDetector.prototype.trigger = function () {
|
|
|
|
var now = +(new Date());
|
|
|
|
if (now - this.mostRecentTrigger > this.period * 1.5) {
|
|
|
|
World.send(this.message);
|
|
|
|
}
|
|
|
|
this.mostRecentTrigger = now;
|
|
|
|
};
|
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// WebSocket client driver
|
|
|
|
|
|
|
|
var DEFAULT_RECONNECT_DELAY = 100;
|
|
|
|
var MAX_RECONNECT_DELAY = 30000;
|
|
|
|
|
|
|
|
function WebSocketConnection(label, wsurl, shouldReconnect) {
|
|
|
|
this.label = label;
|
|
|
|
this.wsurl = wsurl;
|
|
|
|
this.shouldReconnect = shouldReconnect ? true : false;
|
|
|
|
this.reconnectDelay = DEFAULT_RECONNECT_DELAY;
|
|
|
|
this.localRoutes = [];
|
|
|
|
this.peerRoutes = [];
|
|
|
|
this.prevPeerRoutesMessage = null;
|
|
|
|
this.sock = null;
|
|
|
|
this.deduplicator = new Deduplicator();
|
2013-10-22 18:14:51 +00:00
|
|
|
}
|
|
|
|
|
2013-10-31 17:38:38 +00:00
|
|
|
WebSocketConnection.prototype.statusRoute = function (status) {
|
|
|
|
return pub([this.label + "_state", status]);
|
|
|
|
};
|
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
WebSocketConnection.prototype.relayRoutes = function () {
|
|
|
|
// fresh copy each time, suitable for in-place extension/mutation
|
2013-10-31 17:38:38 +00:00
|
|
|
return [this.statusRoute(this.isConnected() ? "connected" : "disconnected"),
|
|
|
|
pub([this.label, __, __], 0, 1000),
|
|
|
|
sub([this.label, __, __], 0, 1000)];
|
2013-10-31 12:10:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
WebSocketConnection.prototype.aggregateRoutes = function () {
|
|
|
|
var rs = this.relayRoutes();
|
|
|
|
for (var i = 0; i < this.peerRoutes.length; i++) {
|
|
|
|
var r = this.peerRoutes[i];
|
|
|
|
rs.push(new Route(r.isSubscription,
|
|
|
|
[this.label, __, r.pattern],
|
|
|
|
r.metaLevel,
|
|
|
|
r.level));
|
|
|
|
}
|
2013-11-01 14:14:48 +00:00
|
|
|
// console.log("WebSocketConnection.aggregateRoutes", this.label, rs);
|
2013-10-31 12:10:53 +00:00
|
|
|
return rs;
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocketConnection.prototype.boot = function () {
|
|
|
|
this.reconnect();
|
|
|
|
};
|
|
|
|
|
2013-11-03 20:56:39 +00:00
|
|
|
WebSocketConnection.prototype.trapexit = function () {
|
|
|
|
this.forceclose();
|
|
|
|
};
|
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
WebSocketConnection.prototype.isConnected = function () {
|
|
|
|
return this.sock && this.sock.readyState === this.sock.OPEN;
|
2013-11-03 20:56:39 +00:00
|
|
|
};
|
2013-10-31 12:10:53 +00:00
|
|
|
|
2013-11-03 20:56:39 +00:00
|
|
|
WebSocketConnection.prototype.safeSend = function (m) {
|
|
|
|
try {
|
|
|
|
if (this.isConnected()) { this.sock.send(m); }
|
|
|
|
} catch (e) {
|
|
|
|
console.warn("Trapped exn while sending", e);
|
2013-10-31 12:10:53 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-03 20:56:39 +00:00
|
|
|
WebSocketConnection.prototype.sendLocalRoutes = function () {
|
|
|
|
this.safeSend(JSON.stringify(encodeEvent(updateRoutes(this.localRoutes))));
|
|
|
|
};
|
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
WebSocketConnection.prototype.handleEvent = function (e) {
|
2013-10-31 13:03:50 +00:00
|
|
|
// console.log("WebSocketConnection.handleEvent", e);
|
2013-10-31 12:10:53 +00:00
|
|
|
switch (e.type) {
|
|
|
|
case "routes":
|
|
|
|
this.localRoutes = [];
|
|
|
|
for (var i = 0; i < e.routes.length; i++) {
|
|
|
|
var r = e.routes[i];
|
|
|
|
if (r.pattern.length && r.pattern.length === 3
|
|
|
|
&& r.pattern[0] === this.label
|
|
|
|
&& typeof(r.pattern[1]) === "number")
|
|
|
|
{
|
|
|
|
this.localRoutes.push(new Route(r.isSubscription,
|
|
|
|
r.pattern[2],
|
|
|
|
r.pattern[1],
|
|
|
|
r.level));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.sendLocalRoutes();
|
|
|
|
break;
|
|
|
|
case "message":
|
|
|
|
var m = e.message;
|
|
|
|
if (m.length && m.length === 3
|
|
|
|
&& m[0] === this.label
|
|
|
|
&& typeof(m[1]) === "number")
|
|
|
|
{
|
2013-11-03 20:56:39 +00:00
|
|
|
var encoded = JSON.stringify(encodeEvent(sendMessage(m[2], m[1], e.isFeedback)));
|
|
|
|
if (this.deduplicator.accept(encoded)) {
|
|
|
|
this.safeSend(encoded);
|
2013-10-18 08:58:08 +00:00
|
|
|
}
|
2013-10-17 14:50:51 +00:00
|
|
|
}
|
2013-10-31 12:10:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-01 14:15:37 +00:00
|
|
|
WebSocketConnection.prototype.forceclose = function (keepReconnectDelay) {
|
|
|
|
if (!keepReconnectDelay) {
|
|
|
|
this.reconnectDelay = DEFAULT_RECONNECT_DELAY;
|
|
|
|
}
|
2013-10-31 12:10:53 +00:00
|
|
|
if (this.sock) {
|
2013-11-01 11:57:50 +00:00
|
|
|
console.log("WebSocketConnection.forceclose called");
|
2013-10-31 12:10:53 +00:00
|
|
|
this.sock.close();
|
|
|
|
this.sock = null;
|
|
|
|
}
|
2013-10-31 23:08:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
WebSocketConnection.prototype.reconnect = function () {
|
|
|
|
var self = this;
|
2013-11-01 14:15:37 +00:00
|
|
|
this.forceclose(true);
|
2013-10-31 12:10:53 +00:00
|
|
|
this.sock = new WebSocket(this.wsurl);
|
|
|
|
this.sock.onopen = World.wrap(function (e) { return self.onopen(e); });
|
|
|
|
this.sock.onmessage = World.wrap(function (e) { return self.onmessage(e); });
|
|
|
|
this.sock.onclose = World.wrap(function (e) { return self.onclose(e); });
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocketConnection.prototype.onopen = function (e) {
|
2013-11-01 14:14:48 +00:00
|
|
|
console.log("connected to " + this.sock.url);
|
2013-10-31 12:10:53 +00:00
|
|
|
this.reconnectDelay = DEFAULT_RECONNECT_DELAY;
|
|
|
|
this.sendLocalRoutes();
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocketConnection.prototype.onmessage = function (wse) {
|
2013-10-31 13:03:50 +00:00
|
|
|
// console.log("onmessage", wse);
|
2013-11-01 14:16:53 +00:00
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
var j = JSON.parse(wse.data);
|
2013-11-01 14:16:53 +00:00
|
|
|
if (j === "ping") {
|
2013-11-03 20:56:39 +00:00
|
|
|
this.safeSend(JSON.stringify("pong"));
|
2013-11-01 14:16:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
var e = decodeAction(j);
|
|
|
|
switch (e.type) {
|
|
|
|
case "routes":
|
|
|
|
if (this.prevPeerRoutesMessage !== wse.data) {
|
|
|
|
this.prevPeerRoutesMessage = wse.data;
|
2013-11-01 14:16:06 +00:00
|
|
|
this.peerRoutes = e.routes;
|
2013-10-31 12:10:53 +00:00
|
|
|
World.updateRoutes(this.aggregateRoutes());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "message":
|
|
|
|
if (this.deduplicator.accept(wse.data)) {
|
|
|
|
World.send([this.label, e.metaLevel, e.message], 0, e.isFeedback);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocketConnection.prototype.onclose = function (e) {
|
|
|
|
var self = this;
|
2013-11-01 10:28:35 +00:00
|
|
|
console.log("onclose", e);
|
2013-10-31 17:38:38 +00:00
|
|
|
|
|
|
|
// Update routes to give clients some indication of the discontinuity
|
|
|
|
World.updateRoutes(this.aggregateRoutes());
|
|
|
|
|
2013-10-31 12:10:53 +00:00
|
|
|
if (this.shouldReconnect) {
|
|
|
|
console.log("reconnecting to " + this.wsurl + " in " + this.reconnectDelay + "ms");
|
|
|
|
setTimeout(World.wrap(function () { self.reconnect(); }), this.reconnectDelay);
|
|
|
|
this.reconnectDelay = this.reconnectDelay * 1.618 + (Math.random() * 1000);
|
|
|
|
this.reconnectDelay =
|
|
|
|
this.reconnectDelay > MAX_RECONNECT_DELAY
|
|
|
|
? MAX_RECONNECT_DELAY + (Math.random() * 1000)
|
|
|
|
: this.reconnectDelay;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Main
|
|
|
|
|
2013-11-01 14:17:50 +00:00
|
|
|
function chatEvent(nym, status, utterance, stamp) {
|
|
|
|
return ["chatEvent", nym, status, utterance, stamp || +(new Date())];
|
|
|
|
}
|
|
|
|
function chatEventNym(c) { return c[1]; }
|
|
|
|
function chatEventStatus(c) { return c[2]; }
|
|
|
|
function chatEventUtterance(c) { return c[3]; }
|
|
|
|
function chatEventStamp(c) { return c[4]; }
|
|
|
|
|
2013-10-31 17:38:38 +00:00
|
|
|
function outputItem(item) {
|
|
|
|
var stamp = $("<span/>").text((new Date()).toGMTString()).addClass("timestamp");
|
|
|
|
var item = $("<div/>").append([stamp].concat(item));
|
|
|
|
var o = $("#chat_output");
|
|
|
|
o.append(item);
|
|
|
|
o[0].scrollTop = o[0].scrollHeight;
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2013-10-31 13:03:50 +00:00
|
|
|
function updateNymList(rs) {
|
2013-10-31 17:38:38 +00:00
|
|
|
var statuses = {};
|
2013-10-31 13:03:50 +00:00
|
|
|
for (var i = 0; i < rs.length; i++) {
|
|
|
|
var p = rs[i].pattern;
|
2013-11-01 14:17:50 +00:00
|
|
|
if (p[0] === "broker" && p[1] === 0 && p[2][0] === "chatEvent") {
|
|
|
|
statuses[chatEventNym(p[2])] = chatEventStatus(p[2]);
|
2013-10-31 17:38:38 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-01 14:17:50 +00:00
|
|
|
var nyms = [];
|
|
|
|
for (var nym in statuses) { nyms.push(nym); }
|
|
|
|
nyms.sort();
|
2013-10-31 17:38:38 +00:00
|
|
|
|
|
|
|
var container = $("#nymlist");
|
|
|
|
container[0].innerHTML = ""; // remove all children
|
|
|
|
for (var i = 0; i < nyms.length; i++) {
|
|
|
|
var n = $("<span/>").text(nyms[i]).addClass("nym");
|
|
|
|
var s = statuses[nyms[i]];
|
|
|
|
if (s) {
|
|
|
|
container.append($("<div/>").append([n, $("<span/>").text(s).addClass("nym_status")]));
|
|
|
|
} else {
|
|
|
|
container.append($("<div/>").append(n));
|
|
|
|
}
|
2013-10-31 13:03:50 +00:00
|
|
|
}
|
2013-10-31 17:38:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function outputState(state) {
|
|
|
|
outputItem([$("<span/>").text(state).addClass(state).addClass("state")])
|
|
|
|
.addClass("state_" + state);
|
2013-10-31 13:03:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function outputUtterance(who, what) {
|
2013-10-31 17:38:38 +00:00
|
|
|
outputItem([$("<span/>").text(who).addClass("nym"),
|
|
|
|
$("<span/>").text(what).addClass("utterance")]).addClass("utterance");
|
2013-10-31 13:03:50 +00:00
|
|
|
}
|
|
|
|
|
2013-11-01 10:28:22 +00:00
|
|
|
var G;
|
2013-10-31 12:10:53 +00:00
|
|
|
$(document).ready(function () {
|
|
|
|
$("#chat_form").submit(function (e) { e.preventDefault(); return false; });
|
2013-10-31 13:03:50 +00:00
|
|
|
$("#nym_form").submit(function (e) { e.preventDefault(); return false; });
|
2013-11-01 00:18:51 +00:00
|
|
|
if (!($("#nym").val())) { $("#nym").val("nym" + Math.floor(Math.random() * 65536)); }
|
2013-10-31 12:10:53 +00:00
|
|
|
|
2013-11-01 10:28:22 +00:00
|
|
|
G = new Ground(function () {
|
2013-10-31 12:10:53 +00:00
|
|
|
console.log('starting ground boot');
|
2013-10-31 13:03:50 +00:00
|
|
|
// World.spawn(new Spy());
|
2013-10-31 12:10:53 +00:00
|
|
|
spawnJQueryDriver();
|
2013-11-01 11:57:50 +00:00
|
|
|
World.spawn(new WakeDetector());
|
2013-10-31 23:08:28 +00:00
|
|
|
var wsconn = new WebSocketConnection("broker", $("#wsurl").val(), true);
|
|
|
|
World.spawn(wsconn);
|
2013-10-31 12:10:53 +00:00
|
|
|
World.spawn({
|
2013-10-31 17:38:38 +00:00
|
|
|
// Monitor connection, notifying connectivity changes
|
2013-11-03 20:56:50 +00:00
|
|
|
state: "crashed", // start with this to avoid spurious initial message print
|
2013-10-31 12:10:53 +00:00
|
|
|
boot: function () {
|
2013-10-31 17:38:38 +00:00
|
|
|
World.updateRoutes([sub(["broker_state", __], 0, 1)]);
|
2013-10-31 12:10:53 +00:00
|
|
|
},
|
2013-10-31 17:38:38 +00:00
|
|
|
handleEvent: function (e) {
|
|
|
|
if (e.type === "routes") {
|
2013-11-03 20:56:50 +00:00
|
|
|
var newState = (e.routes.length > 0) ? e.routes[0].pattern[1] : "crashed";
|
|
|
|
if (this.state != newState) {
|
|
|
|
outputState(newState);
|
|
|
|
this.state = newState;
|
2013-10-31 17:38:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
World.spawn({
|
|
|
|
// Actual chat functionality
|
|
|
|
peers: new PresenceDetector(),
|
|
|
|
peerMap: {},
|
|
|
|
boot: function () {
|
|
|
|
World.updateRoutes(this.subscriptions());
|
2013-10-31 12:10:53 +00:00
|
|
|
},
|
2013-10-31 17:38:38 +00:00
|
|
|
nym: function () { return $("#nym").val(); },
|
|
|
|
currentStatus: function () { return $("#status").val(); },
|
2013-10-31 12:10:53 +00:00
|
|
|
subscriptions: function () {
|
2013-11-01 11:57:50 +00:00
|
|
|
return [sub("wake"),
|
|
|
|
sub(["jQuery", "#send_chat", "click", __]),
|
2013-10-31 12:10:53 +00:00
|
|
|
sub(["jQuery", "#nym", "change", __]),
|
2013-10-31 17:38:38 +00:00
|
|
|
sub(["jQuery", "#status", "change", __]),
|
2013-10-31 23:08:28 +00:00
|
|
|
sub(["jQuery", "#wsurl", "change", __]),
|
2013-11-01 14:17:50 +00:00
|
|
|
pub(["broker", 0, chatEvent(this.nym(), this.currentStatus(), __, __)]),
|
|
|
|
sub(["broker", 0, chatEvent(__, __, __, __)], 0, 1)];
|
2013-10-31 12:10:53 +00:00
|
|
|
},
|
|
|
|
handleEvent: function (e) {
|
2013-10-31 17:38:38 +00:00
|
|
|
var self = this;
|
2013-10-31 13:03:50 +00:00
|
|
|
switch (e.type) {
|
|
|
|
case "routes":
|
|
|
|
updateNymList(e.routes);
|
|
|
|
break;
|
|
|
|
case "message":
|
2013-11-01 11:57:50 +00:00
|
|
|
if (e.message === "wake") {
|
|
|
|
wsconn.forceclose();
|
|
|
|
return;
|
|
|
|
}
|
2013-10-31 12:10:53 +00:00
|
|
|
switch (e.message[0]) {
|
|
|
|
case "jQuery":
|
|
|
|
switch (e.message[1]) {
|
|
|
|
case "#send_chat":
|
|
|
|
var inp = $("#chat_input");
|
|
|
|
var utterance = inp.val();
|
|
|
|
inp.val("");
|
2013-10-31 13:03:50 +00:00
|
|
|
if (utterance) {
|
2013-11-01 14:17:50 +00:00
|
|
|
World.send(["broker", 0, chatEvent(this.nym(),
|
|
|
|
this.currentStatus(),
|
|
|
|
utterance)]);
|
2013-10-31 13:03:50 +00:00
|
|
|
}
|
2013-10-31 12:10:53 +00:00
|
|
|
break;
|
|
|
|
case "#nym":
|
2013-10-31 17:38:38 +00:00
|
|
|
case "#status":
|
2013-10-31 12:10:53 +00:00
|
|
|
World.updateRoutes(this.subscriptions());
|
|
|
|
break;
|
2013-10-31 23:08:28 +00:00
|
|
|
case "#wsurl":
|
|
|
|
wsconn.forceclose();
|
|
|
|
wsconn.wsurl = $("#wsurl").val();
|
|
|
|
break;
|
2013-10-31 12:10:53 +00:00
|
|
|
default:
|
|
|
|
console.log("Got jquery event from as-yet-unhandled subscription",
|
|
|
|
e.message[2], e.message[3]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "broker":
|
2013-11-01 14:17:50 +00:00
|
|
|
if (e.message[2][0] === "chatEvent") {
|
|
|
|
outputUtterance(chatEventNym(e.message[2]),
|
|
|
|
chatEventUtterance(e.message[2]));
|
2013-10-31 13:03:50 +00:00
|
|
|
}
|
2013-10-31 12:10:53 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2013-10-31 13:03:50 +00:00
|
|
|
break;
|
2013-10-31 12:10:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2013-10-17 14:50:51 +00:00
|
|
|
});
|
2013-11-01 10:28:22 +00:00
|
|
|
G.startStepping();
|
2013-10-17 14:50:51 +00:00
|
|
|
});
|