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 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();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue