Nymlist; status; connection state
This commit is contained in:
parent
2203795902
commit
671c5dbda6
22
index.html
22
index.html
|
@ -15,11 +15,11 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row-fluid">
|
<!-- <div class="row-fluid"> -->
|
||||||
<div class="span12">
|
<!-- <div class="span12"> -->
|
||||||
<h1>JS Marketplace</h1>
|
<!-- <h1>JS Marketplace</h1> -->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div class="span12">
|
<div class="span12">
|
||||||
<form class="form-horizontal" name="nym_form">
|
<form class="form-horizontal" name="nym_form">
|
||||||
|
@ -29,13 +29,23 @@
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="nym" name="nym" value="pseud">
|
<input type="text" id="nym" name="nym" value="pseud">
|
||||||
</div>
|
</div>
|
||||||
|
<label class="control-label" for="status">Status:</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="status" name="status" value="">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div id="chat_output" class="span12">
|
<div class="span9">
|
||||||
|
<h2>Messages</h2>
|
||||||
|
<div id="chat_output"></div>
|
||||||
|
</div>
|
||||||
|
<div class="span3">
|
||||||
|
<h2>Active Users</h2>
|
||||||
|
<div id="nymlist"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
|
|
94
index.js
94
index.js
|
@ -100,9 +100,15 @@ function WebSocketConnection(label, wsurl, shouldReconnect) {
|
||||||
this.deduplicator = new Deduplicator();
|
this.deduplicator = new Deduplicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebSocketConnection.prototype.statusRoute = function (status) {
|
||||||
|
return pub([this.label + "_state", status]);
|
||||||
|
};
|
||||||
|
|
||||||
WebSocketConnection.prototype.relayRoutes = function () {
|
WebSocketConnection.prototype.relayRoutes = function () {
|
||||||
// fresh copy each time, suitable for in-place extension/mutation
|
// fresh copy each time, suitable for in-place extension/mutation
|
||||||
return [pub([this.label, __, __], 0, 1000), sub([this.label, __, __], 0, 1000)];
|
return [this.statusRoute(this.isConnected() ? "connected" : "disconnected"),
|
||||||
|
pub([this.label, __, __], 0, 1000),
|
||||||
|
sub([this.label, __, __], 0, 1000)];
|
||||||
};
|
};
|
||||||
|
|
||||||
WebSocketConnection.prototype.aggregateRoutes = function () {
|
WebSocketConnection.prototype.aggregateRoutes = function () {
|
||||||
|
@ -119,7 +125,6 @@ WebSocketConnection.prototype.aggregateRoutes = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
WebSocketConnection.prototype.boot = function () {
|
WebSocketConnection.prototype.boot = function () {
|
||||||
World.updateRoutes(this.aggregateRoutes());
|
|
||||||
this.reconnect();
|
this.reconnect();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -224,6 +229,10 @@ WebSocketConnection.prototype.onmessage = function (wse) {
|
||||||
WebSocketConnection.prototype.onclose = function (e) {
|
WebSocketConnection.prototype.onclose = function (e) {
|
||||||
var self = this;
|
var self = this;
|
||||||
// console.log("onclose", e);
|
// console.log("onclose", e);
|
||||||
|
|
||||||
|
// Update routes to give clients some indication of the discontinuity
|
||||||
|
World.updateRoutes(this.aggregateRoutes());
|
||||||
|
|
||||||
if (this.shouldReconnect) {
|
if (this.shouldReconnect) {
|
||||||
console.log("reconnecting to " + this.wsurl + " in " + this.reconnectDelay + "ms");
|
console.log("reconnecting to " + this.wsurl + " in " + this.reconnectDelay + "ms");
|
||||||
setTimeout(World.wrap(function () { self.reconnect(); }), this.reconnectDelay);
|
setTimeout(World.wrap(function () { self.reconnect(); }), this.reconnectDelay);
|
||||||
|
@ -238,34 +247,55 @@ WebSocketConnection.prototype.onclose = function (e) {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Main
|
// Main
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
function updateNymList(rs) {
|
function updateNymList(rs) {
|
||||||
var nyms = [];
|
var nyms = [];
|
||||||
|
var statuses = {};
|
||||||
for (var i = 0; i < rs.length; i++) {
|
for (var i = 0; i < rs.length; i++) {
|
||||||
var p = rs[i].pattern;
|
var p = rs[i].pattern;
|
||||||
if (p[0] === "broker"
|
if (p[0] === "broker" && p[1] === 0 && p[2][1] === "says") {
|
||||||
&& p[1] === 0
|
|
||||||
&& p[2][1] === "says")
|
|
||||||
{
|
|
||||||
nyms.push(p[2][0]);
|
nyms.push(p[2][0]);
|
||||||
}
|
}
|
||||||
|
if (p[0] === "broker" && p[1] === 0 && p[2][1] === "status") {
|
||||||
|
statuses[p[2][0]] = p[2][2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log(nyms);
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function outputState(state) {
|
||||||
|
outputItem([$("<span/>").text(state).addClass(state).addClass("state")])
|
||||||
|
.addClass("state_" + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function outputUtterance(who, what) {
|
function outputUtterance(who, what) {
|
||||||
var stamp = $("<span/>").text((new Date()).toGMTString()).addClass("timestamp");
|
outputItem([$("<span/>").text(who).addClass("nym"),
|
||||||
var nymLabel = $("<span/>").text(who).addClass("nym");
|
$("<span/>").text(what).addClass("utterance")]).addClass("utterance");
|
||||||
var utterance = $("<span/>").text(what).addClass("utterance");
|
|
||||||
var o = $("#chat_output");
|
|
||||||
o.append($("<div/>")
|
|
||||||
.append([stamp, nymLabel, utterance])
|
|
||||||
.addClass("utterance"));
|
|
||||||
o[0].scrollTop = o[0].scrollHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#chat_form").submit(function (e) { e.preventDefault(); return false; });
|
$("#chat_form").submit(function (e) { e.preventDefault(); return false; });
|
||||||
$("#nym_form").submit(function (e) { e.preventDefault(); return false; });
|
$("#nym_form").submit(function (e) { e.preventDefault(); return false; });
|
||||||
|
$("#nym").val("nym" + Math.floor(Math.random() * 65536));
|
||||||
|
|
||||||
var g = new Ground(function () {
|
var g = new Ground(function () {
|
||||||
console.log('starting ground boot');
|
console.log('starting ground boot');
|
||||||
|
@ -273,20 +303,43 @@ $(document).ready(function () {
|
||||||
spawnJQueryDriver();
|
spawnJQueryDriver();
|
||||||
World.spawn(new WebSocketConnection("broker", "ws://localhost:8000/", true));
|
World.spawn(new WebSocketConnection("broker", "ws://localhost:8000/", true));
|
||||||
World.spawn({
|
World.spawn({
|
||||||
// step: function () { console.log('dummy step'); },
|
// Monitor connection, notifying connectivity changes
|
||||||
|
state: null,
|
||||||
|
boot: function () {
|
||||||
|
World.updateRoutes([sub(["broker_state", __], 0, 1)]);
|
||||||
|
},
|
||||||
|
handleEvent: function (e) {
|
||||||
|
if (e.type === "routes") {
|
||||||
|
if (e.routes.length > 0) {
|
||||||
|
var newState = e.routes[0].pattern[1];
|
||||||
|
if (this.state != newState) {
|
||||||
|
outputState(newState);
|
||||||
|
this.state = newState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
World.spawn({
|
||||||
|
// Actual chat functionality
|
||||||
|
peers: new PresenceDetector(),
|
||||||
|
peerMap: {},
|
||||||
boot: function () {
|
boot: function () {
|
||||||
World.updateRoutes(this.subscriptions());
|
World.updateRoutes(this.subscriptions());
|
||||||
},
|
},
|
||||||
nym: function () {
|
nym: function () { return $("#nym").val(); },
|
||||||
return $("#nym").val();
|
currentStatus: function () { return $("#status").val(); },
|
||||||
},
|
|
||||||
subscriptions: function () {
|
subscriptions: function () {
|
||||||
return [sub(["jQuery", "#send_chat", "click", __]),
|
return [sub(["jQuery", "#send_chat", "click", __]),
|
||||||
sub(["jQuery", "#nym", "change", __]),
|
sub(["jQuery", "#nym", "change", __]),
|
||||||
|
sub(["jQuery", "#status", "change", __]),
|
||||||
pub(["broker", 0, [this.nym(), "says", __]]),
|
pub(["broker", 0, [this.nym(), "says", __]]),
|
||||||
sub(["broker", 0, [__, "says", __]], 0, 1)];
|
pub(["broker", 0, [this.nym(), "status", this.currentStatus()]]),
|
||||||
|
sub(["broker", 0, [__, "says", __]], 0, 1),
|
||||||
|
sub(["broker", 0, [__, "status", __]], 0, 1)];
|
||||||
},
|
},
|
||||||
handleEvent: function (e) {
|
handleEvent: function (e) {
|
||||||
|
var self = this;
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case "routes":
|
case "routes":
|
||||||
updateNymList(e.routes);
|
updateNymList(e.routes);
|
||||||
|
@ -304,6 +357,7 @@ $(document).ready(function () {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "#nym":
|
case "#nym":
|
||||||
|
case "#status":
|
||||||
World.updateRoutes(this.subscriptions());
|
World.updateRoutes(this.subscriptions());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
50
style.css
50
style.css
|
@ -1,17 +1,41 @@
|
||||||
div.utterance span.timestamp {
|
span.timestamp {
|
||||||
color: #d0d0d0;
|
color: #d0d0d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.utterance span.timestamp:after {
|
span.timestamp:after {
|
||||||
content: " ";
|
content: " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
div.utterance span.nym {
|
.utterance span.nym:after {
|
||||||
|
content: ": ";
|
||||||
|
}
|
||||||
|
|
||||||
|
span.arrived:after {
|
||||||
|
content: " arrived";
|
||||||
|
}
|
||||||
|
|
||||||
|
span.departed:after {
|
||||||
|
content: " departed";
|
||||||
|
}
|
||||||
|
|
||||||
|
div.notification {
|
||||||
|
background-color: #eeeeff;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.state.connected, span.arrived {
|
||||||
color: #00c000;
|
color: #00c000;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.utterance span.nym:after {
|
span.state.disconnected, span.departed {
|
||||||
content: ": ";
|
color: #c00000;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.state_disconnected {
|
||||||
|
background-color: #ffeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.state_connected {
|
||||||
|
background-color: #eeffee;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat_output {
|
#chat_output {
|
||||||
|
@ -22,3 +46,19 @@ div.utterance span.nym:after {
|
||||||
#chat_input {
|
#chat_input {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nym {
|
||||||
|
color: #00c000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nym_status:before {
|
||||||
|
content: " (";
|
||||||
|
}
|
||||||
|
|
||||||
|
.nym_status:after {
|
||||||
|
content: ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
.nym_status {
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
Loading…
Reference in New Issue