Update (new UI library)

This commit is contained in:
Tony Garnock-Jones 2016-05-11 21:03:50 -04:00
parent 4d06454e52
commit 689f4c6905
23 changed files with 1371 additions and 823 deletions

682
dist/syndicate.js vendored

File diff suppressed because one or more lines are too long

16
dist/syndicate.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,19 +1,14 @@
"use strict";
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
new Syndicate.Ground(function () {
Syndicate.UI.spawnUIDriver();
$(document).ready(function() {
new Syndicate.Ground(function () {
Syndicate.DOM.spawnDOMDriver();
Syndicate.JQuery.spawnJQueryDriver();
Syndicate.Actor.spawnActor(new Object(), function() {
this.counter = 0;
Syndicate.Actor.createFacet()
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(DOM('#button-label','',''+this.counter), 0); }))
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(jQueryEvent('#counter','click',_), 0); }), (function() { var _ = Syndicate.__; return { assertion: jQueryEvent('#counter','click',_), metalevel: 0 }; }), (function() {
this.counter++;
})).completeBuild();
});
}).startStepping();
});
Syndicate.Actor.spawnActor(new Object(), function() {
var counter = 0;
var ui = new Syndicate.UI.Anchor();
Syndicate.Actor.createFacet()
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(ui.html('#button-label',''+counter), 0); }))
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.globalEvent('#counter','click',_), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.globalEvent('#counter','click',_), metalevel: 0 }; }), (function() {
counter++;
})).completeBuild();
});
}).startStepping();

View File

@ -3,7 +3,6 @@
<head>
<title>Syndicate: Button Example</title>
<meta charset="utf-8">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicatecompiler.js"></script>
<script src="../../dist/syndicate.js"></script>
<script type="text/syndicate-js" src="index.js"></script>

View File

@ -1,19 +1,14 @@
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
ground dataspace {
Syndicate.UI.spawnUIDriver();
$(document).ready(function() {
ground dataspace {
Syndicate.DOM.spawnDOMDriver();
Syndicate.JQuery.spawnJQueryDriver();
actor {
this.counter = 0;
react {
assert DOM('#button-label', '', '' + this.counter);
on message jQueryEvent('#counter', 'click', _) {
this.counter++;
}
actor {
var counter = 0;
var ui = new Syndicate.UI.Anchor();
react {
assert ui.html('#button-label', '' + counter);
on message Syndicate.UI.globalEvent('#counter', 'click', _) {
counter++;
}
}
}
});
}

View File

@ -1,9 +1,6 @@
assertion type present(name, status);
assertion type says(who, message);
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
var brokerConnected = Syndicate.Broker.brokerConnected;
var brokerConnection = Syndicate.Broker.brokerConnection;
var toBroker = Syndicate.Broker.toBroker;
@ -19,14 +16,15 @@ function spawnChatApp() {
if (!($("#nym").val())) { $("#nym").val("nym" + Math.floor(Math.random() * 65536)); }
actor {
var ui = new Syndicate.UI.Anchor();
react {
on asserted jQueryInput('#nym', $v) { this.nym = v; }
on asserted jQueryInput('#status', $v) { this.status = v; }
on asserted inputValue('#nym', $v) { this.nym = v; }
on asserted inputValue('#status', $v) { this.status = v; }
on asserted brokerConnected($url) { outputState('connected to ' + url); }
on retracted brokerConnected($url) { outputState('disconnected from ' + url); }
during jQueryInput('#wsurl', $url) {
during inputValue('#wsurl', $url) {
assert brokerConnection(url);
on message Syndicate.WakeDetector.wakeEvent() {
@ -35,11 +33,12 @@ function spawnChatApp() {
assert toBroker(url, present(this.nym, this.status));
during fromBroker(url, present($who, $status)) {
assert DOM('#nymlist', 'present-nym',
Mustache.render($('#nym_template').html(), { who: who, status: status }));
assert ui.context(who)
.html('#nymlist',
Mustache.render($('#nym_template').html(), { who: who, status: status }));
}
on message jQueryEvent('#send_chat', 'click', _) {
on message Syndicate.UI.globalEvent('#send_chat', 'click', _) {
var inp = $("#chat_input");
var utterance = inp.val();
inp.val("");
@ -79,21 +78,21 @@ function outputUtterance(who, what) {
///////////////////////////////////////////////////////////////////////////
// Input control value monitoring
assertion type jQueryInput(selector, value);
assertion type inputValue(selector, value);
function spawnInputChangeMonitor() {
actor {
react {
on asserted Syndicate.observe(jQueryInput($selector, _)) {
on asserted Syndicate.observe(inputValue($selector, _)) {
actor {
this.value = $(selector).val();
react {
assert jQueryInput(selector, this.value);
on message jQueryEvent(selector, 'change', $e) {
assert inputValue(selector, this.value);
on message Syndicate.UI.globalEvent(selector, 'change', $e) {
this.value = e.target.value;
}
} until {
case retracted Syndicate.observe(jQueryInput(selector, _));
case retracted Syndicate.observe(inputValue(selector, _));
}
}
}
@ -106,8 +105,7 @@ function spawnInputChangeMonitor() {
$(document).ready(function () {
ground dataspace G {
Syndicate.JQuery.spawnJQueryDriver();
Syndicate.DOM.spawnDOMDriver();
Syndicate.UI.spawnUIDriver();
Syndicate.WakeDetector.spawnWakeDetector();
Syndicate.Broker.spawnBrokerClientDriver();
spawnInputChangeMonitor();

View File

@ -3,7 +3,6 @@
<head>
<title>Syndicate: DOM Example</title>
<meta charset="utf-8">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicate.js"></script>
<script src="index.js"></script>
</head>

View File

@ -1,5 +1,5 @@
var G;
$(document).ready(function () {
document.addEventListener('DOMContentLoaded', function () {
var Dataspace = Syndicate.Dataspace;
var sub = Syndicate.sub;
var assert = Syndicate.assert;
@ -10,18 +10,17 @@ $(document).ready(function () {
G = new Syndicate.Ground(function () {
console.log('starting ground boot');
Syndicate.DOM.spawnDOMDriver();
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
Syndicate.UI.spawnUIDriver();
Dataspace.spawn({
boot: function () {
return assert(DOM("#clicker-holder", "clicker",
'<button><span style="font-style: italic">Click me!</span></button>'))
.andThen(sub(jQueryEvent("button.clicker", "click", __)));
var ui = new Syndicate.UI.Anchor();
return assert(ui.html("#clicker-holder",
'<button><span style="font-style: italic">Click me!</span></button>'))
.andThen(sub(Syndicate.UI.globalEvent("button", "click", __)));
},
handleEvent: function (e) {
if (e.type === "message" && jQueryEvent.isClassOf(e.message)) {
if (e.type === "message" && Syndicate.UI.globalEvent.isClassOf(e.message)) {
Dataspace.send("bump_count");
}
}
@ -29,15 +28,17 @@ $(document).ready(function () {
Dataspace.spawn({
counter: 0,
ui: new Syndicate.UI.Anchor(),
boot: function () {
this.updateState();
return sub("bump_count");
},
updateState: function () {
Dataspace.stateChange(retract(DOM.pattern)
.andThen(assert(DOM("#counter-holder", "counter",
'<div><p>The current count is: '+this.counter+
'</p></div>'))));
Dataspace.stateChange(retract(this.ui.htmlPattern)
.andThen(assert(this.ui.html(
"#counter-holder",
'<div><p>The current count is: '+this.counter+
'</p></div>'))));
},
handleEvent: function (e) {
if (e.type === "message" && e.message === "bump_count") {
@ -49,7 +50,7 @@ $(document).ready(function () {
});
G.dataspace.setOnStateChange(function (mux, patch) {
$("#spy-holder").text(Syndicate.prettyTrie(mux.routingTable));
document.getElementById('spy-holder').innerText = Syndicate.prettyTrie(mux.routingTable);
});
G.startStepping();

View File

@ -13,36 +13,25 @@ This is a simple clickable button; each time the button is clicked,
the number on the face of the button is incremented.
The actor maintaining the counter also maintains the button's label
and listens to click events. It uses the Syndicate/js DOM driver to
publish the button's label text based on its internal state, and the
Syndicate/js jQuery driver to subscribe to button click events.
and listens to click events. It uses the Syndicate/js UI driver to
publish the button's label text based on its internal state and to
subscribe to button click events.
- [DEMO](button/)
- [Source code](button/index.js) using the Syndicate/js DSL
## DOM example
This example demonstrates two actors, each using the Syndicate/js DOM
driver to display user interface, and the jQuery driver to receive
events from it. The first actor presents a button to the user, which
when clicked sends a message to the other actor. The second actor
receives messages from the first, updates its internal state, and
reflects its new internal state in its visible UI.
This example demonstrates two actors, each using the Syndicate/js UI
driver to display user interface and receive events from it. The first
actor presents a button to the user, which when clicked sends a
message to the other actor. The second actor receives messages from
the first, updates its internal state, and reflects its new internal
state in its visible UI.
- [DEMO](dom/)
- [Source code](dom/index.js) in plain JavaScript
## jQuery Example
This example is similar to the button example, but uses plain
JavaScript instead of the Syndicate/js DSL, calling out to Syndicate
as a library. It uses the Syndicate/js jQuery driver to receive click
events from the button, but does not use the Syndicate/js DOM driver;
instead, it updates the DOM directly.
- [DEMO](jquery/)
- [Source code](jquery/index.js) in plain JavaScript
## Text Entry Widget
This is a simple text entry GUI control, following a design of

View File

@ -5,17 +5,15 @@ assertion type tvAlert(text);
assertion type switchAction(on);
assertion type componentPresent(name);
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
///////////////////////////////////////////////////////////////////////////
// TV
function spawnTV() {
actor {
var ui = new Syndicate.UI.Anchor();
react {
during tvAlert($text) {
assert DOM('#tv', 'alert', Mustache.render($('#alert_template').html(), { text: text }));
assert ui.context(text).html('#tv', Mustache.render($('#alert_template').html(), { text: text }));
}
}
}
@ -28,7 +26,7 @@ function spawnRemoteControl() {
actor {
react {
assert componentPresent('remote control');
on message jQueryEvent('#remote-control', 'click', _) {
on message Syndicate.UI.globalEvent('#remote-control', 'click', _) {
:: remoteClick();
}
}
@ -63,23 +61,24 @@ function spawnRemoteListener() {
function spawnStoveSwitch() {
actor {
this.powerOn = false;
this.ui = new Syndicate.UI.Anchor();
react {
assert componentPresent('stove switch');
assert switchState(this.powerOn);
assert DOM('#stove-switch', 'switch-state',
Mustache.render($('#stove_element_template').html(),
{ imgurl: ("img/stove-coil-element-" +
(this.powerOn ? "hot" : "cold") + ".jpg") }));
assert this.ui.html('#stove-switch',
Mustache.render($('#stove_element_template').html(),
{ imgurl: ("img/stove-coil-element-" +
(this.powerOn ? "hot" : "cold") + ".jpg") }));
on message jQueryEvent('#stove-switch-on', 'click', _) { this.powerOn = true; }
on message jQueryEvent('#stove-switch-off', 'click', _) { this.powerOn = false; }
on message Syndicate.UI.globalEvent('#stove-switch-on', 'click', _) { this.powerOn = true; }
on message Syndicate.UI.globalEvent('#stove-switch-off', 'click', _) { this.powerOn = false; }
on message switchAction($newState) {
this.powerOn = newState;
}
} until {
case message jQueryEvent('#kill-stove-switch', 'click', _);
case message Syndicate.UI.globalEvent('#kill-stove-switch', 'click', _);
}
}
}
@ -87,18 +86,19 @@ function spawnStoveSwitch() {
function spawnPowerDrawMonitor() {
actor {
this.watts = 0;
this.ui = new Syndicate.UI.Anchor();
react {
assert componentPresent('power draw monitor');
assert powerDraw(this.watts);
assert DOM('#power-draw-meter', 'power-draw',
Mustache.render($('#power_draw_template').html(), { watts: this.watts }));
assert this.ui.html('#power-draw-meter',
Mustache.render($('#power_draw_template').html(), { watts: this.watts }));
on asserted switchState($on) {
this.watts = on ? 1500 : 0;
}
} until {
case message jQueryEvent('#kill-power-draw-monitor', 'click', _);
case message Syndicate.UI.globalEvent('#kill-power-draw-monitor', 'click', _);
}
}
}
@ -207,7 +207,7 @@ function spawnChaosMonkey() {
jKillButtons.prop('disabled', true);
}
}
on message jQueryEvent(spawnButtonSelector, 'click', _) {
on message Syndicate.UI.globalEvent(spawnButtonSelector, 'click', _) {
spawnFunction();
}
}
@ -219,8 +219,7 @@ function spawnChaosMonkey() {
$(document).ready(function () {
ground dataspace G {
Syndicate.JQuery.spawnJQueryDriver();
Syndicate.DOM.spawnDOMDriver();
Syndicate.UI.spawnUIDriver();
Syndicate.Timer.spawnTimerDriver();
spawnTV();

View File

@ -1,16 +0,0 @@
<!doctype html>
<html>
<head>
<title>Syndicate: jQuery Example</title>
<meta charset="utf-8">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicate.js"></script>
<script src="index.js"></script>
</head>
<body>
<h1>jQuery example</h1>
<button id="clicker">Click me</button>
<div id="result">0</div>
<pre id="spy-holder"></pre>
</body>
</html>

View File

@ -1,34 +0,0 @@
"use strict";
var G;
$(document).ready(function () {
var Dataspace = Syndicate.Dataspace;
var sub = Syndicate.sub;
var __ = Syndicate.__;
var _$ = Syndicate._$;
G = new Syndicate.Ground(function () {
console.log('starting ground boot');
Syndicate.JQuery.spawnJQueryDriver();
Dataspace.spawn({
boot: function () {
return sub(Syndicate.JQuery.jQueryEvent('#clicker', 'click', __));
},
handleEvent: function (e) {
if (e.type === 'message'
&& Syndicate.JQuery.jQueryEvent.isClassOf(e.message)
&& e.message[0] === '#clicker')
{
var r = $('#result');
r.html(Number(r.html()) + 1);
}
}
});
});
G.dataspace.setOnStateChange(function (mux, patch) {
$("#spy-holder").text(Syndicate.prettyTrie(mux.routingTable));
});
G.startStepping();
});

View File

@ -3,7 +3,6 @@
<head>
<title>Syndicate: Smoketest with DSL</title>
<meta charset="utf-8">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicatecompiler.js"></script>
<script src="../../dist/syndicate.js"></script>
<script type="text/syndicate-js" src="index.js"></script>

View File

@ -3,7 +3,6 @@
<head>
<title>Syndicate: Smoketest</title>
<meta charset="utf-8">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicate.js"></script>
<script src="index.js"></script>
</head>

View File

@ -3,33 +3,33 @@
var beep = Syndicate.Struct.makeConstructor('beep', ['counter']);
var G;
$(document).ready(function () {
var Dataspace = Syndicate.Dataspace;
var sub = Syndicate.sub;
var __ = Syndicate.__;
var _$ = Syndicate._$;
document.addEventListener('DOMContentLoaded', function () {
var Dataspace = Syndicate.Dataspace;
var sub = Syndicate.sub;
var __ = Syndicate.__;
var _$ = Syndicate._$;
G = new Syndicate.Ground(function () {
console.log('starting ground boot');
G = new Syndicate.Ground(function () {
console.log('starting ground boot');
Dataspace.spawn({
counter: 0,
boot: function () {},
handleEvent: function (e) {},
step: function () {
Dataspace.send(beep(this.counter++));
return this.counter <= 10;
}
});
Dataspace.spawn({
boot: function () { return sub(beep.pattern); },
handleEvent: function (e) {
if (e.type === 'message') {
console.log("beep!", e.message[0]);
}
}
});
Dataspace.spawn({
counter: 0,
boot: function () {},
handleEvent: function (e) {},
step: function () {
Dataspace.send(beep(this.counter++));
return this.counter <= 10;
}
});
G.startStepping();
Dataspace.spawn({
boot: function () { return sub(beep.pattern); },
handleEvent: function (e) {
if (e.type === 'message') {
console.log("beep!", e.message[0]);
}
}
});
});
G.startStepping();
});

View File

@ -4,7 +4,6 @@
<title>Syndicate: SVG</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicatecompiler.js"></script>
<script src="../../dist/syndicate.js"></script>
<script type="text/syndicate-js" src="index.js"></script>

View File

@ -1,25 +1,22 @@
var DOM = Syndicate.DOM.DOM;
ground dataspace G {
Syndicate.UI.spawnUIDriver();
Syndicate.Timer.spawnTimerDriver();
$(document).ready(function () {
ground dataspace G {
Syndicate.DOM.spawnDOMDriver();
Syndicate.Timer.spawnTimerDriver();
actor {
var ui = new Syndicate.UI.Anchor();
react {
assert ui.html('#clock',
'<svg width="300px" viewBox="0 0 100 100">'+
'<circle fill="#0B79CE" r=45 cx=50 cy=50 />'+
'<line stroke="#023963" x1=50 y1=50 x2='+this.handX+' y2='+this.handY+' />'+
'</svg>')
when (typeof this.angle === 'number');
actor {
react {
assert DOM('#clock', 'clock',
'<svg width="300px" viewBox="0 0 100 100">'+
'<circle fill="#0B79CE" r=45 cx=50 cy=50/>'+
'<line stroke="#023963" x1=50 y1=50 x2='+this.handX+' y2='+this.handY+' />'+
'</svg>')
when (typeof this.angle === 'number');
on message Syndicate.Timer.periodicTick(1000) {
this.angle = ((((Date.now() / 1000) % 60) / 60) - 0.25) * 2 * Math.PI;
this.handX = 50 + 40 * Math.cos(this.angle);
this.handY = 50 + 40 * Math.sin(this.angle);
}
on message Syndicate.Timer.periodicTick(1000) {
this.angle = ((((Date.now() / 1000) % 60) / 60) - 0.25) * 2 * Math.PI;
this.handX = 50 + 40 * Math.cos(this.angle);
this.handY = 50 + 40 * Math.sin(this.angle);
}
}
}
});
}

View File

@ -4,7 +4,6 @@
<title>Syndicate: Textfield Example (DSL variation)</title>
<meta charset="utf-8">
<link href="style.css" rel="stylesheet">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicatecompiler.js"></script>
<script src="../../dist/syndicate.js"></script>
<script type="text/syndicate-js" src="index.js"></script>

View File

@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////
// GUI
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
var globalEvent = Syndicate.UI.globalEvent;
assertion type fieldCommand(detail);
assertion type fieldContents(text, pos);
assertion type highlight(state);
@ -36,7 +36,7 @@ function spawnGui() {
var highlight = this.highlightState;
var hLeft = highlight ? highlight[0] : 0;
var hRight = highlight ? highlight[1] : 0;
$("#fieldContents")[0].innerHTML = highlight
document.getElementById("fieldContents").innerHTML = highlight
? piece(text, pos, 0, hLeft, "normal") +
piece(text, pos, hLeft, hRight, "highlight") +
piece(text, pos, hRight, text.length + 1, "normal")
@ -44,18 +44,22 @@ function spawnGui() {
};
react {
on message jQueryEvent("#inputRow", "+keypress", $event) {
var keycode = event.keyCode;
on message globalEvent("#inputRow", "+keydown", $event) {
switch (event.keyCode) {
case 37 /* left */: :: fieldCommand("cursorLeft"); break;
case 39 /* right */: :: fieldCommand("cursorRight"); break;
case 9 /* tab */: /* ignore */ break;
case 8 /* backspace */:
event.preventDefault(); // that this works here is a minor miracle
:: fieldCommand("backspace");
break;
default: break;
}
}
on message globalEvent("#inputRow", "+keypress", $event) {
var character = String.fromCharCode(event.charCode);
if (keycode === 37 /* left */) {
:: fieldCommand("cursorLeft");
} else if (keycode === 39 /* right */) {
:: fieldCommand("cursorRight");
} else if (keycode === 9 /* tab */) {
// ignore
} else if (keycode === 8 /* backspace */) {
:: fieldCommand("backspace");
} else if (character) {
if (event.charCode && character) {
:: fieldCommand(["insert", character]);
}
}
@ -126,7 +130,7 @@ function spawnSearch() {
this.highlight = false;
this.search = function () {
var searchtext = $("#searchBox")[0].value;
var searchtext = document.getElementById("searchBox").value;
if (searchtext) {
var pos = this.fieldValue.indexOf(searchtext);
this.highlight = (pos !== -1) && [pos, pos + searchtext.length];
@ -138,7 +142,7 @@ function spawnSearch() {
react {
assert highlight(this.highlight);
on message jQueryEvent("#searchBox", "input", $event) {
on message globalEvent("#searchBox", "input", $event) {
this.search();
}
@ -153,17 +157,14 @@ function spawnSearch() {
///////////////////////////////////////////////////////////////////////////
// Main
$(document).ready(function () {
ground dataspace G {
Syndicate.JQuery.spawnJQueryDriver();
Syndicate.DOM.spawnDOMDriver();
ground dataspace G {
Syndicate.UI.spawnUIDriver();
spawnGui();
spawnModel();
spawnSearch();
}
spawnGui();
spawnModel();
spawnSearch();
}
G.dataspace.setOnStateChange(function (mux, patch) {
$("#spy-holder").text(Syndicate.prettyTrie(mux.routingTable));
});
G.dataspace.setOnStateChange(function (mux, patch) {
document.getElementById("spy-holder").innerText = Syndicate.prettyTrie(mux.routingTable);
});

View File

@ -4,7 +4,6 @@
<title>Syndicate: Textfield Example</title>
<meta charset="utf-8">
<link href="style.css" rel="stylesheet">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicate.js"></script>
<script src="index.js"></script>
</head>

View File

@ -7,7 +7,7 @@ var Patch = Syndicate.Patch;
var __ = Syndicate.__;
var _$ = Syndicate._$;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
var globalEvent = Syndicate.UI.globalEvent;
var fieldContents = Syndicate.Struct.makeConstructor('fieldContents', ['text', 'pos']);
var highlight = Syndicate.Struct.makeConstructor('highlight', ['state']);
var fieldCommand = Syndicate.Struct.makeConstructor('fieldCommand', ['detail']);
@ -36,7 +36,8 @@ function spawnGui() {
highlight: { state: false },
boot: function () {
return Patch.sub(jQueryEvent("#inputRow", "+keypress", __))
return Patch.sub(globalEvent("#inputRow", "keypress", __))
.andThen(Patch.sub(globalEvent("#inputRow", "+keydown", __)))
.andThen(Patch.sub(fieldContents.pattern))
.andThen(Patch.sub(highlight.pattern));
},
@ -46,31 +47,40 @@ function spawnGui() {
handleEvent: function (e) {
var self = this;
switch (e.type) {
case "message":
var event = e.message[2];
var keycode = event.keyCode;
var character = String.fromCharCode(event.charCode);
if (keycode === 37 /* left */) {
Dataspace.send(fieldCommand("cursorLeft"));
} else if (keycode === 39 /* right */) {
Dataspace.send(fieldCommand("cursorRight"));
} else if (keycode === 9 /* tab */) {
// ignore
} else if (keycode === 8 /* backspace */) {
Dataspace.send(fieldCommand("backspace"));
} else if (character) {
Dataspace.send(fieldCommand(["insert", character]));
}
break;
case "stateChange":
Trie.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
self.field = c;
});
Trie.projectObjects(e.patch.added, this.highlightProjection).forEach(function (c) {
self.highlight = c;
});
this.updateDisplay();
break;
case "message":
var event = e.message[2];
switch (event.type) {
case "keydown":
switch (event.keyCode) {
case 37 /* left */: Dataspace.send(fieldCommand("cursorLeft")); break;
case 39 /* right */: Dataspace.send(fieldCommand("cursorRight")); break;
case 9 /* tab */: /* ignore */ break;
case 8 /* backspace */:
event.preventDefault(); // that this works here is a minor miracle
Dataspace.send(fieldCommand("backspace"));
break;
default: break;
}
break;
case "keypress":
var character = String.fromCharCode(event.charCode);
if (event.charCode && character) {
Dataspace.send(fieldCommand(["insert", character]));
}
break;
default:
break;
}
break;
case "stateChange":
Trie.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
self.field = c;
});
Trie.projectObjects(e.patch.added, this.highlightProjection).forEach(function (c) {
self.highlight = c;
});
this.updateDisplay();
break;
}
},
@ -80,7 +90,7 @@ function spawnGui() {
var highlight = this.highlight ? this.highlight.state : false;
var hLeft = highlight ? highlight[0] : 0;
var hRight = highlight ? highlight[1] : 0;
$("#fieldContents")[0].innerHTML = highlight
document.getElementById("fieldContents").innerHTML = highlight
? piece(text, pos, 0, hLeft, "normal") +
piece(text, pos, hLeft, hRight, "highlight") +
piece(text, pos, hRight, text.length + 1, "normal")
@ -149,14 +159,14 @@ function spawnSearch() {
boot: function () {
this.publishState();
return Patch.sub(jQueryEvent("#searchBox", "input", __))
return Patch.sub(globalEvent("#searchBox", "input", __))
.andThen(Patch.sub(fieldContents.pattern));
},
fieldContentsProjection: fieldContents(_$("text"), _$("pos")),
handleEvent: function (e) {
var self = this;
if (jQueryEvent.isClassOf(e.message)) {
if (globalEvent.isClassOf(e.message)) {
this.search();
}
if (e.type === "stateChange") {
@ -174,7 +184,7 @@ function spawnSearch() {
},
search: function () {
var searchtext = $("#searchBox")[0].value;
var searchtext = document.getElementById("searchBox").value;
var oldHighlight = this.highlight;
if (searchtext) {
var pos = this.fieldValue.indexOf(searchtext);
@ -193,10 +203,9 @@ function spawnSearch() {
// Main
var G;
$(document).ready(function () {
document.addEventListener('DOMContentLoaded', function () {
G = new Syndicate.Ground(function () {
Syndicate.JQuery.spawnJQueryDriver();
Syndicate.DOM.spawnDOMDriver();
Syndicate.UI.spawnUIDriver();
spawnGui();
spawnModel();
@ -204,7 +213,7 @@ $(document).ready(function () {
});
G.dataspace.setOnStateChange(function (mux, patch) {
$("#spy-holder").text(Syndicate.prettyTrie(mux.routingTable));
document.getElementById("spy-holder").innerText = Syndicate.prettyTrie(mux.routingTable);
});
G.startStepping();