DOM driver and example

This commit is contained in:
Tony Garnock-Jones 2014-02-28 09:48:10 -05:00
parent 4141057a7c
commit f04fb92ea4
4 changed files with 153 additions and 0 deletions

82
dom-driver.js Normal file
View File

@ -0,0 +1,82 @@
// DOM fragment display driver
function spawnDOMDriver() {
var d = new DemandMatcher(["DOM", __, __, __], 0, {demandSideIsSubscription: false});
d.onDemandIncrease = function (r) {
var selector = r.pattern[1];
var fragmentClass = r.pattern[2];
var fragmentSpec = r.pattern[3];
World.spawn(new DOMFragment(selector, fragmentClass, fragmentSpec),
[sub(["DOM", selector, fragmentClass, fragmentSpec]),
sub(["DOM", selector, fragmentClass, fragmentSpec], 0, 1)]);
};
World.spawn(d);
}
function DOMFragment(selector, fragmentClass, fragmentSpec) {
this.selector = selector;
this.fragmentClass = fragmentClass;
this.fragmentSpec = fragmentSpec;
this.nodes = this.buildNodes();
}
DOMFragment.prototype.boot = function () {
var self = this;
World.spawn(new World(function () {
spawnJQueryDriver(self.selector+" > ."+self.fragmentClass, 1);
World.spawn({
maxRouteCount: 0,
handleEvent: function (e) {
if (e.type === "routes") {
this.maxRouteCount = Math.max(this.maxRouteCount, e.routes.length);
if (e.routes.length < this.maxRouteCount) {
World.shutdownWorld();
}
}
}
}, [sub(["DOM", self.selector, self.fragmentClass, self.fragmentSpec], 1, 1)]);
}));
};
DOMFragment.prototype.handleEvent = function (e) {
if (e.type === "routes" && e.routes.length === 0) {
for (var i = 0; i < this.nodes.length; i++) {
var n = this.nodes[i];
n.parentNode.removeChild(n);
}
World.exit();
}
};
DOMFragment.prototype.interpretSpec = function (spec) {
// Fragment specs are roughly JSON-equivalents of SXML.
// spec ::== ["tag", {"attr": "value", ...}, spec, spec, ...]
// | ["tag", spec, spec, ...]
// | "cdata"
if (typeof(spec) === "string" || typeof(spec) === "number") {
return document.createTextNode(spec);
} else if ($.isArray(spec)) {
var tagName = spec[0];
var hasAttrs = $.isPlainObject(spec[1]);
var attrs = hasAttrs ? spec[1] : {};
var kidIndex = hasAttrs ? 2 : 1;
var n = document.createElement(tagName);
for (var i = kidIndex; i < spec.length; i++) {
n.appendChild(this.interpretSpec(spec[i]));
}
return n;
}
};
DOMFragment.prototype.buildNodes = function () {
var self = this;
var nodes = [];
$(self.selector).each(function (index, domNode) {
var n = self.interpretSpec(self.fragmentSpec);
n.className = self.fragmentClass;
domNode.appendChild(n);
nodes.push(n);
});
return nodes;
};

32
examples/dom/index.html Normal file
View File

@ -0,0 +1,32 @@
<!doctype html>
<html>
<head>
<title>JS Marketplace: DOM 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/bootstrap/js/bootstrap.min.js"></script> -->
<script src="../../third-party/jquery-2.0.3.min.js"></script>
<script src="../../marketplace.js"></script>
<script src="../../spy.js"></script>
<script src="../../dom-driver.js"></script>
<script src="../../jquery-driver.js"></script>
<script src="../../wake-detector.js"></script>
<script src="../../websocket-driver.js"></script>
<script src="index.js"></script>
</head>
<body>
<h1>DOM example</h1>
<div class="container-fluid">
<div class="row-fluid">
<div class="span3 well" id="counter-holder">
</div>
<div class="span9 well" id="clicker-holder">
</div>
</div>
</div>
</body>
</html>

39
examples/dom/index.js Normal file
View File

@ -0,0 +1,39 @@
var G;
$(document).ready(function () {
G = new Ground(function () {
console.log('starting ground boot');
World.spawn(new Spy("GROUND", true));
spawnDOMDriver();
World.spawn({
handleEvent: function (e) {
if (e.type === "message" && e.message[0] === "jQuery") {
World.send("bump_count");
}
}
}, [pub(["DOM", "#clicker-holder", "clicker",
["button", "Click me!"]]),
pub("bump_count"),
sub(["jQuery", "button.clicker", "click", __])]);
World.spawn({
counter: 0,
boot: function () {
this.updateState();
},
updateState: function () {
World.updateRoutes([sub("bump_count"),
pub(["DOM", "#counter-holder", "counter",
["div",
["p", "The current count is: ", this.counter]]])]);
},
handleEvent: function (e) {
if (e.type === "message" && e.message === "bump_count") {
this.counter++;
this.updateState();
}
}
});
});
G.startStepping();
});

0
examples/dom/style.css Normal file
View File