Update chat example to Actor; preserve non-Actor version; remove

currently-useless OSX app resources
This commit is contained in:
Tony Garnock-Jones 2014-07-25 16:53:17 -07:00
parent 55c9fa1d49
commit 76044b539e
7 changed files with 364 additions and 118 deletions

View File

@ -0,0 +1,67 @@
<!doctype html>
<html>
<head>
<title>JS Marketplace: Chat Example</title>
<meta charset="utf-8">
<link href="../../third-party/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="../../third-party/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
<script src="../../third-party/jquery-2.0.3.min.js"></script>
<script src="../../dist/minimart.js"></script>
<script src="index.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<form class="form-horizontal" name="nym_form">
<fieldset>
<div class="control-group">
<label class="control-label" for="wsurl">Server:</label>
<div class="controls">
<input type="text" id="wsurl" name="wsurl" value="ws://localhost:8000/">
</div>
<label class="control-label" for="nym">Nym:</label>
<div class="controls">
<input type="text" id="nym" name="nym" value="">
</div>
<label class="control-label" for="status">Status:</label>
<div class="controls">
<input type="text" id="status" name="status" value="">
</div>
</div>
</fieldset>
</form>
</div>
</div>
<div class="row-fluid">
<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 class="row-fluid">
<div class="span12">
<form class="form-horizontal" name="chat_form">
<fieldset>
<div class="control-group">
<div class="controls">
<input type="text" id="chat_input" name="chat_input" value="" autocomplete="off">
<button id="send_chat">Send</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
<div class="row-fluid">
<div class="span12" id="spy-holder">
</div>
</div>
</div>
</body>
</html>

162
examples/chat-raw/index.js Normal file
View File

@ -0,0 +1,162 @@
var Route = Minimart.Route;
var World = Minimart.World;
var sub = Minimart.sub;
var pub = Minimart.pub;
var __ = Minimart.__;
var _$ = Minimart._$;
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]; }
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(g) {
var statuses = {};
var nymProj = ["broker", 0, ["chatEvent", _$, _$, __, __]];
var matchedNyms = Route.matcherKeys(g.project(Route.compileProjection(nymProj), true, 0, 0));
for (var i = 0; i < matchedNyms.length; i++) {
statuses[matchedNyms[i][0]] = matchedNyms[i][1];
}
var nyms = [];
for (var nym in statuses) { nyms.push(nym); }
nyms.sort();
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) {
outputItem([$("<span/>").text(who).addClass("nym"),
$("<span/>").text(what).addClass("utterance")]).addClass("utterance");
}
var G;
$(document).ready(function () {
$("#chat_form").submit(function (e) { e.preventDefault(); return false; });
$("#nym_form").submit(function (e) { e.preventDefault(); return false; });
if (!($("#nym").val())) { $("#nym").val("nym" + Math.floor(Math.random() * 65536)); }
G = new Minimart.Ground(function () {
console.log('starting ground boot');
// World.spawn(new Spy());
Minimart.JQuery.spawnJQueryDriver();
Minimart.DOM.spawnDOMDriver();
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy");
World.spawn(new Minimart.WakeDetector());
var wsconn = new Minimart.WebSocket.WebSocketConnection("broker", $("#wsurl").val(), true);
World.spawn(wsconn);
World.spawn({
// Monitor connection, notifying connectivity changes
state: "crashed", // start with this to avoid spurious initial message print
boot: function () {
World.updateRoutes([sub(["broker_state", __], 0, 1)]);
},
handleEvent: function (e) {
if (e.type === "routes") {
var states =
Route.matcherKeys(e.gestalt.project(Route.compileProjection([__, _$]),
true, 0, 0));
var newState = states.length > 0 ? states[0][0] : "crashed";
if (this.state != newState) {
outputState(newState);
this.state = newState;
}
}
}
});
World.spawn({
// Actual chat functionality
boot: function () {
World.updateRoutes(this.subscriptions());
},
nym: function () { return $("#nym").val(); },
currentStatus: function () { return $("#status").val(); },
subscriptions: function () {
return [sub("wake"),
sub(["jQuery", "#send_chat", "click", __]),
sub(["jQuery", "#nym", "change", __]),
sub(["jQuery", "#status", "change", __]),
sub(["jQuery", "#wsurl", "change", __]),
pub(["broker", 0, chatEvent(this.nym(), this.currentStatus(), __, __)]),
sub(["broker", 0, chatEvent(__, __, __, __)], 0, 1)];
},
handleEvent: function (e) {
var self = this;
switch (e.type) {
case "routes":
updateNymList(e.gestalt);
break;
case "message":
if (e.message === "wake") {
wsconn.forceclose();
return;
}
switch (e.message[0]) {
case "jQuery":
switch (e.message[1]) {
case "#send_chat":
var inp = $("#chat_input");
var utterance = inp.val();
inp.val("");
if (utterance) {
World.send(["broker", 0, chatEvent(this.nym(),
this.currentStatus(),
utterance)]);
}
break;
case "#nym":
case "#status":
World.updateRoutes(this.subscriptions());
break;
case "#wsurl":
wsconn.forceclose();
wsconn.wsurl = $("#wsurl").val();
break;
default:
console.log("Got jquery event from as-yet-unhandled subscription",
e.message[2], e.message[3]);
}
break;
case "broker":
if (e.message[2][0] === "chatEvent") {
outputUtterance(chatEventNym(e.message[2]),
chatEventUtterance(e.message[2]));
}
break;
default:
break;
}
break;
}
}
});
});
G.startStepping();
});

View File

@ -0,0 +1,73 @@
span.timestamp {
color: #d0d0d0;
}
span.timestamp:after {
content: " ";
}
.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;
}
span.state.disconnected, span.departed {
color: #c00000;
}
span.state.crashed {
color: white;
background: red;
}
span.state.crashed:after {
content: "; please reload the page";
}
div.state_disconnected {
background-color: #ffeeee;
}
div.state_connected {
background-color: #eeffee;
}
#chat_output {
height: 15em;
overflow-y: scroll;
}
#chat_input {
width: 80%;
}
.nym {
color: #00c000;
}
.nym_status:before {
content: " (";
}
.nym_status:after {
content: ")";
}
.nym_status {
font-size: smaller;
}

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>boot.sh</string>
<key>CFBundleIconFile</key>
<string>app.icns</string>
<key>CFBundleIdentifier</key>
<string>com.leastfixedpoint.js-marketplace.chat-demo</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>chat-demo</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>chat-demo 0.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.0.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.6</string>
</dict>
</plist>

Binary file not shown.

View File

@ -1,3 +0,0 @@
#!/bin/bash
cd "$(dirname "$0")"/../Resources
open examples/chat/index.html

View File

@ -1,5 +1,6 @@
var Route = Minimart.Route;
var World = Minimart.World;
var Actor = Minimart.Actor;
var sub = Minimart.sub;
var pub = Minimart.pub;
var __ = Minimart.__;
@ -8,10 +9,6 @@ var _$ = Minimart._$;
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]; }
function outputItem(item) {
var stamp = $("<span/>").text((new Date()).toGMTString()).addClass("timestamp");
@ -22,12 +19,10 @@ function outputItem(item) {
return item;
}
function updateNymList(g) {
function updateNymList(allStatuses) {
var statuses = {};
var nymProj = ["broker", 0, ["chatEvent", _$, _$, __, __]];
var matchedNyms = Route.matcherKeys(g.project(Route.compileProjection(nymProj), true, 0, 0));
for (var i = 0; i < matchedNyms.length; i++) {
statuses[matchedNyms[i][0]] = matchedNyms[i][1];
for (var i = 0; i < allStatuses.length; i++) {
statuses[allStatuses[i].nym] = allStatuses[i].status;
}
var nyms = [];
for (var nym in statuses) { nyms.push(nym); }
@ -72,91 +67,71 @@ $(document).ready(function () {
World.spawn(new Minimart.WakeDetector());
var wsconn = new Minimart.WebSocket.WebSocketConnection("broker", $("#wsurl").val(), true);
World.spawn(wsconn);
World.spawn({
World.spawn(new Actor(function () {
// Monitor connection, notifying connectivity changes
state: "crashed", // start with this to avoid spurious initial message print
boot: function () {
World.updateRoutes([sub(["broker_state", __], 0, 1)]);
},
handleEvent: function (e) {
if (e.type === "routes") {
var states =
Route.matcherKeys(e.gestalt.project(Route.compileProjection([__, _$]),
true, 0, 0));
var newState = states.length > 0 ? states[0][0] : "crashed";
this.state = "crashed"; // start with this to avoid spurious initial message print
Actor.observeAdvertisers(
function () { return ["broker_state", _$("newState")]; },
{ name: "states" },
function () {
var newState = this.states.length > 0 ? this.states[0].newState : "crashed";
if (this.state != newState) {
outputState(newState);
this.state = newState;
}
}
}
});
World.spawn({
});
}));
World.spawn(new Actor(function () {
// Actual chat functionality
boot: function () {
World.updateRoutes(this.subscriptions());
},
nym: function () { return $("#nym").val(); },
currentStatus: function () { return $("#status").val(); },
subscriptions: function () {
return [sub("wake"),
sub(["jQuery", "#send_chat", "click", __]),
sub(["jQuery", "#nym", "change", __]),
sub(["jQuery", "#status", "change", __]),
sub(["jQuery", "#wsurl", "change", __]),
pub(["broker", 0, chatEvent(this.nym(), this.currentStatus(), __, __)]),
sub(["broker", 0, chatEvent(__, __, __, __)], 0, 1)];
},
handleEvent: function (e) {
var self = this;
switch (e.type) {
case "routes":
updateNymList(e.gestalt);
break;
case "message":
if (e.message === "wake") {
wsconn.forceclose();
return;
this.nym = function () { return $("#nym").val(); };
this.currentStatus = function () { return $("#status").val(); };
Actor.subscribe(
function () { return "wake"; },
function () { wsconn.forceclose(); });
Actor.advertise(
function () { return ["broker", 0,
chatEvent(this.nym(), this.currentStatus(), __, __)]; });
Actor.observeAdvertisers(
function () { return ["broker", 0,
chatEvent(_$("nym"), _$("status"), __, __)]; },
{ name: "allStatuses" },
function () { updateNymList(this.allStatuses); });
Actor.subscribe(
function () { return ["jQuery", "#send_chat", "click", __]; },
function () {
var inp = $("#chat_input");
var utterance = inp.val();
inp.val("");
if (utterance) {
World.send(["broker", 0, chatEvent(this.nym(),
this.currentStatus(),
utterance)]);
}
switch (e.message[0]) {
case "jQuery":
switch (e.message[1]) {
case "#send_chat":
var inp = $("#chat_input");
var utterance = inp.val();
inp.val("");
if (utterance) {
World.send(["broker", 0, chatEvent(this.nym(),
this.currentStatus(),
utterance)]);
}
break;
case "#nym":
case "#status":
World.updateRoutes(this.subscriptions());
break;
case "#wsurl":
wsconn.forceclose();
wsconn.wsurl = $("#wsurl").val();
break;
default:
console.log("Got jquery event from as-yet-unhandled subscription",
e.message[2], e.message[3]);
}
break;
case "broker":
if (e.message[2][0] === "chatEvent") {
outputUtterance(chatEventNym(e.message[2]),
chatEventUtterance(e.message[2]));
}
break;
default:
break;
}
break;
}
}
});
});
Actor.subscribe(
function () { return ["jQuery", "#nym", "change", __]; },
function () { this.updateRoutes(); });
Actor.subscribe(
function () { return ["jQuery", "#status", "change", __]; },
function () { this.updateRoutes(); });
Actor.subscribe(
function () { return ["jQuery", "#wsurl", "change", __]; },
function () {
wsconn.forceclose();
wsconn.wsurl = $("#wsurl").val();
});
Actor.subscribe(
function () { return ["broker", 0, chatEvent(_$("who"), __, _$("what"), __)]; },
function (who, what) { outputUtterance(who, what); });
}));
});
G.startStepping();
});