2014-02-28 14:48:10 +00:00
|
|
|
// DOM fragment display driver
|
2014-07-24 00:21:51 +00:00
|
|
|
var Minimart = require("./minimart.js");
|
|
|
|
var World = Minimart.World;
|
|
|
|
var sub = Minimart.sub;
|
|
|
|
var pub = Minimart.pub;
|
|
|
|
var __ = Minimart.__;
|
|
|
|
var _$ = Minimart._$;
|
2014-02-28 14:48:10 +00:00
|
|
|
|
2014-07-24 23:21:54 +00:00
|
|
|
function spawnDOMDriver(domWrapFunction, jQueryWrapFunction) {
|
|
|
|
domWrapFunction = domWrapFunction || defaultWrapFunction;
|
|
|
|
var d = new Minimart.DemandMatcher(domWrapFunction(_$, _$, _$));
|
2014-05-26 18:36:57 +00:00
|
|
|
d.onDemandIncrease = function (captures) {
|
|
|
|
var selector = captures[0];
|
|
|
|
var fragmentClass = captures[1];
|
|
|
|
var fragmentSpec = captures[2];
|
2014-07-24 23:21:54 +00:00
|
|
|
World.spawn(new DOMFragment(selector,
|
|
|
|
fragmentClass,
|
|
|
|
fragmentSpec,
|
|
|
|
domWrapFunction,
|
|
|
|
jQueryWrapFunction),
|
|
|
|
[sub(domWrapFunction(selector, fragmentClass, fragmentSpec)),
|
|
|
|
sub(domWrapFunction(selector, fragmentClass, fragmentSpec), 0, 1)]);
|
2014-02-28 14:48:10 +00:00
|
|
|
};
|
|
|
|
World.spawn(d);
|
|
|
|
}
|
|
|
|
|
2014-07-24 23:21:54 +00:00
|
|
|
function defaultWrapFunction(selector, fragmentClass, fragmentSpec) {
|
|
|
|
return ["DOM", selector, fragmentClass, fragmentSpec];
|
|
|
|
}
|
|
|
|
|
|
|
|
function DOMFragment(selector, fragmentClass, fragmentSpec, domWrapFunction, jQueryWrapFunction) {
|
2014-02-28 14:48:10 +00:00
|
|
|
this.selector = selector;
|
|
|
|
this.fragmentClass = fragmentClass;
|
|
|
|
this.fragmentSpec = fragmentSpec;
|
2014-07-24 23:21:54 +00:00
|
|
|
this.domWrapFunction = domWrapFunction;
|
|
|
|
this.jQueryWrapFunction = jQueryWrapFunction;
|
2014-02-28 14:48:10 +00:00
|
|
|
this.nodes = this.buildNodes();
|
|
|
|
}
|
|
|
|
|
|
|
|
DOMFragment.prototype.boot = function () {
|
|
|
|
var self = this;
|
2014-07-24 23:21:54 +00:00
|
|
|
var monitoring =
|
|
|
|
sub(this.domWrapFunction(self.selector, self.fragmentClass, self.fragmentSpec), 1, 2);
|
2014-02-28 14:48:10 +00:00
|
|
|
World.spawn(new World(function () {
|
2014-07-24 23:21:54 +00:00
|
|
|
Minimart.JQuery.spawnJQueryDriver(self.selector+" > ."+self.fragmentClass,
|
|
|
|
1,
|
|
|
|
self.jQueryWrapFunction);
|
2014-02-28 14:48:10 +00:00
|
|
|
World.spawn({
|
|
|
|
handleEvent: function (e) {
|
|
|
|
if (e.type === "routes") {
|
2014-05-26 18:36:57 +00:00
|
|
|
var level = e.gestalt.getLevel(1, 0); // find participant peers
|
|
|
|
if (!e.gestalt.isEmpty() && level.isEmpty()) {
|
2014-02-28 14:48:10 +00:00
|
|
|
World.shutdownWorld();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-10 15:44:01 +00:00
|
|
|
}, [monitoring]);
|
2014-02-28 14:48:10 +00:00
|
|
|
}));
|
|
|
|
};
|
|
|
|
|
|
|
|
DOMFragment.prototype.handleEvent = function (e) {
|
2014-05-26 18:36:57 +00:00
|
|
|
if (e.type === "routes" && e.gestalt.isEmpty()) {
|
2014-02-28 14:48:10 +00:00
|
|
|
for (var i = 0; i < this.nodes.length; i++) {
|
|
|
|
var n = this.nodes[i];
|
|
|
|
n.parentNode.removeChild(n);
|
|
|
|
}
|
|
|
|
World.exit();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-07-24 23:21:07 +00:00
|
|
|
function isAttributes(x) {
|
2014-07-25 03:02:00 +00:00
|
|
|
return Array.isArray(x) && ((x.length === 0) || Array.isArray(x[0]));
|
2014-07-24 23:21:07 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 14:48:10 +00:00
|
|
|
DOMFragment.prototype.interpretSpec = function (spec) {
|
|
|
|
// Fragment specs are roughly JSON-equivalents of SXML.
|
2014-08-25 20:00:18 +00:00
|
|
|
// spec ::== ["tag", [["attr", "value"], ...], spec, spec, ...]
|
2014-02-28 14:48:10 +00:00
|
|
|
// | ["tag", spec, spec, ...]
|
|
|
|
// | "cdata"
|
|
|
|
if (typeof(spec) === "string" || typeof(spec) === "number") {
|
|
|
|
return document.createTextNode(spec);
|
|
|
|
} else if ($.isArray(spec)) {
|
|
|
|
var tagName = spec[0];
|
2014-07-24 23:21:07 +00:00
|
|
|
var hasAttrs = isAttributes(spec[1]);
|
2014-02-28 14:48:10 +00:00
|
|
|
var attrs = hasAttrs ? spec[1] : {};
|
|
|
|
var kidIndex = hasAttrs ? 2 : 1;
|
|
|
|
|
2014-03-07 14:35:41 +00:00
|
|
|
// Wow! Such XSS! Many hacks! So vulnerability! Amaze!
|
2014-02-28 14:48:10 +00:00
|
|
|
var n = document.createElement(tagName);
|
2014-07-24 23:21:07 +00:00
|
|
|
for (var i = 0; i < attrs.length; i++) {
|
|
|
|
n.setAttribute(attrs[i][0], attrs[i][1]);
|
2014-03-07 14:35:41 +00:00
|
|
|
}
|
2014-02-28 14:48:10 +00:00
|
|
|
for (var i = kidIndex; i < spec.length; i++) {
|
|
|
|
n.appendChild(this.interpretSpec(spec[i]));
|
|
|
|
}
|
|
|
|
return n;
|
2014-08-25 20:00:33 +00:00
|
|
|
} else {
|
|
|
|
throw new Error("Ill-formed DOM specification");
|
2014-02-28 14:48:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
DOMFragment.prototype.buildNodes = function () {
|
|
|
|
var self = this;
|
|
|
|
var nodes = [];
|
|
|
|
$(self.selector).each(function (index, domNode) {
|
|
|
|
var n = self.interpretSpec(self.fragmentSpec);
|
2014-03-10 18:50:18 +00:00
|
|
|
n.classList.add(self.fragmentClass);
|
2014-02-28 14:48:10 +00:00
|
|
|
domNode.appendChild(n);
|
|
|
|
nodes.push(n);
|
|
|
|
});
|
|
|
|
return nodes;
|
|
|
|
};
|
2014-07-24 00:21:51 +00:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
module.exports.spawnDOMDriver = spawnDOMDriver;
|
2014-07-24 23:21:54 +00:00
|
|
|
module.exports.defaultWrapFunction = defaultWrapFunction;
|