Update chat example to Actor; preserve non-Actor version; remove
currently-useless OSX app resources
This commit is contained in:
parent
55c9fa1d49
commit
76044b539e
|
@ -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>
|
|
@ -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();
|
||||||
|
});
|
|
@ -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;
|
||||||
|
}
|
|
@ -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.
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
cd "$(dirname "$0")"/../Resources
|
|
||||||
open examples/chat/index.html
|
|
|
@ -1,5 +1,6 @@
|
||||||
var Route = Minimart.Route;
|
var Route = Minimart.Route;
|
||||||
var World = Minimart.World;
|
var World = Minimart.World;
|
||||||
|
var Actor = Minimart.Actor;
|
||||||
var sub = Minimart.sub;
|
var sub = Minimart.sub;
|
||||||
var pub = Minimart.pub;
|
var pub = Minimart.pub;
|
||||||
var __ = Minimart.__;
|
var __ = Minimart.__;
|
||||||
|
@ -8,10 +9,6 @@ var _$ = Minimart._$;
|
||||||
function chatEvent(nym, status, utterance, stamp) {
|
function chatEvent(nym, status, utterance, stamp) {
|
||||||
return ["chatEvent", nym, status, utterance, stamp || +(new Date())];
|
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) {
|
function outputItem(item) {
|
||||||
var stamp = $("<span/>").text((new Date()).toGMTString()).addClass("timestamp");
|
var stamp = $("<span/>").text((new Date()).toGMTString()).addClass("timestamp");
|
||||||
|
@ -22,12 +19,10 @@ function outputItem(item) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateNymList(g) {
|
function updateNymList(allStatuses) {
|
||||||
var statuses = {};
|
var statuses = {};
|
||||||
var nymProj = ["broker", 0, ["chatEvent", _$, _$, __, __]];
|
for (var i = 0; i < allStatuses.length; i++) {
|
||||||
var matchedNyms = Route.matcherKeys(g.project(Route.compileProjection(nymProj), true, 0, 0));
|
statuses[allStatuses[i].nym] = allStatuses[i].status;
|
||||||
for (var i = 0; i < matchedNyms.length; i++) {
|
|
||||||
statuses[matchedNyms[i][0]] = matchedNyms[i][1];
|
|
||||||
}
|
}
|
||||||
var nyms = [];
|
var nyms = [];
|
||||||
for (var nym in statuses) { nyms.push(nym); }
|
for (var nym in statuses) { nyms.push(nym); }
|
||||||
|
@ -72,91 +67,71 @@ $(document).ready(function () {
|
||||||
World.spawn(new Minimart.WakeDetector());
|
World.spawn(new Minimart.WakeDetector());
|
||||||
var wsconn = new Minimart.WebSocket.WebSocketConnection("broker", $("#wsurl").val(), true);
|
var wsconn = new Minimart.WebSocket.WebSocketConnection("broker", $("#wsurl").val(), true);
|
||||||
World.spawn(wsconn);
|
World.spawn(wsconn);
|
||||||
World.spawn({
|
World.spawn(new Actor(function () {
|
||||||
// Monitor connection, notifying connectivity changes
|
// Monitor connection, notifying connectivity changes
|
||||||
state: "crashed", // start with this to avoid spurious initial message print
|
this.state = "crashed"; // start with this to avoid spurious initial message print
|
||||||
boot: function () {
|
|
||||||
World.updateRoutes([sub(["broker_state", __], 0, 1)]);
|
Actor.observeAdvertisers(
|
||||||
},
|
function () { return ["broker_state", _$("newState")]; },
|
||||||
handleEvent: function (e) {
|
{ name: "states" },
|
||||||
if (e.type === "routes") {
|
function () {
|
||||||
var states =
|
var newState = this.states.length > 0 ? this.states[0].newState : "crashed";
|
||||||
Route.matcherKeys(e.gestalt.project(Route.compileProjection([__, _$]),
|
|
||||||
true, 0, 0));
|
|
||||||
var newState = states.length > 0 ? states[0][0] : "crashed";
|
|
||||||
if (this.state != newState) {
|
if (this.state != newState) {
|
||||||
outputState(newState);
|
outputState(newState);
|
||||||
this.state = newState;
|
this.state = newState;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}));
|
||||||
});
|
World.spawn(new Actor(function () {
|
||||||
World.spawn({
|
|
||||||
// Actual chat functionality
|
// Actual chat functionality
|
||||||
boot: function () {
|
this.nym = function () { return $("#nym").val(); };
|
||||||
World.updateRoutes(this.subscriptions());
|
this.currentStatus = function () { return $("#status").val(); };
|
||||||
},
|
|
||||||
nym: function () { return $("#nym").val(); },
|
Actor.subscribe(
|
||||||
currentStatus: function () { return $("#status").val(); },
|
function () { return "wake"; },
|
||||||
subscriptions: function () {
|
function () { wsconn.forceclose(); });
|
||||||
return [sub("wake"),
|
|
||||||
sub(["jQuery", "#send_chat", "click", __]),
|
Actor.advertise(
|
||||||
sub(["jQuery", "#nym", "change", __]),
|
function () { return ["broker", 0,
|
||||||
sub(["jQuery", "#status", "change", __]),
|
chatEvent(this.nym(), this.currentStatus(), __, __)]; });
|
||||||
sub(["jQuery", "#wsurl", "change", __]),
|
Actor.observeAdvertisers(
|
||||||
pub(["broker", 0, chatEvent(this.nym(), this.currentStatus(), __, __)]),
|
function () { return ["broker", 0,
|
||||||
sub(["broker", 0, chatEvent(__, __, __, __)], 0, 1)];
|
chatEvent(_$("nym"), _$("status"), __, __)]; },
|
||||||
},
|
{ name: "allStatuses" },
|
||||||
handleEvent: function (e) {
|
function () { updateNymList(this.allStatuses); });
|
||||||
var self = this;
|
|
||||||
switch (e.type) {
|
Actor.subscribe(
|
||||||
case "routes":
|
function () { return ["jQuery", "#send_chat", "click", __]; },
|
||||||
updateNymList(e.gestalt);
|
function () {
|
||||||
break;
|
var inp = $("#chat_input");
|
||||||
case "message":
|
var utterance = inp.val();
|
||||||
if (e.message === "wake") {
|
inp.val("");
|
||||||
wsconn.forceclose();
|
if (utterance) {
|
||||||
return;
|
World.send(["broker", 0, chatEvent(this.nym(),
|
||||||
|
this.currentStatus(),
|
||||||
|
utterance)]);
|
||||||
}
|
}
|
||||||
switch (e.message[0]) {
|
});
|
||||||
case "jQuery":
|
|
||||||
switch (e.message[1]) {
|
Actor.subscribe(
|
||||||
case "#send_chat":
|
function () { return ["jQuery", "#nym", "change", __]; },
|
||||||
var inp = $("#chat_input");
|
function () { this.updateRoutes(); });
|
||||||
var utterance = inp.val();
|
|
||||||
inp.val("");
|
Actor.subscribe(
|
||||||
if (utterance) {
|
function () { return ["jQuery", "#status", "change", __]; },
|
||||||
World.send(["broker", 0, chatEvent(this.nym(),
|
function () { this.updateRoutes(); });
|
||||||
this.currentStatus(),
|
|
||||||
utterance)]);
|
Actor.subscribe(
|
||||||
}
|
function () { return ["jQuery", "#wsurl", "change", __]; },
|
||||||
break;
|
function () {
|
||||||
case "#nym":
|
wsconn.forceclose();
|
||||||
case "#status":
|
wsconn.wsurl = $("#wsurl").val();
|
||||||
World.updateRoutes(this.subscriptions());
|
});
|
||||||
break;
|
|
||||||
case "#wsurl":
|
Actor.subscribe(
|
||||||
wsconn.forceclose();
|
function () { return ["broker", 0, chatEvent(_$("who"), __, _$("what"), __)]; },
|
||||||
wsconn.wsurl = $("#wsurl").val();
|
function (who, what) { outputUtterance(who, what); });
|
||||||
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();
|
G.startStepping();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue