js-marketplace-2014/dom-driver.js

89 lines
2.6 KiB
JavaScript

// 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;
// Wow! Such XSS! Many hacks! So vulnerability! Amaze!
var n = document.createElement(tagName);
for (var attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
n.setAttribute(attr, attrs[attr]);
}
}
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;
};