diff --git a/js/examples/button/index.expanded.js b/js/examples/button/index.expanded.js index 3dfe4ee..efc7055 100644 --- a/js/examples/button/index.expanded.js +++ b/js/examples/button/index.expanded.js @@ -10,7 +10,7 @@ $(document).ready(function() { Syndicate.Actor.spawnActor(new Object(), function() { this.counter = 0; Syndicate.Actor.createFacet() -.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(DOM('#button-label','',Syndicate.seal(this.counter)), 0); })) +.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(); diff --git a/js/examples/button/index.js b/js/examples/button/index.js index f9ad9bd..c329a07 100644 --- a/js/examples/button/index.js +++ b/js/examples/button/index.js @@ -9,7 +9,7 @@ $(document).ready(function() { actor { this.counter = 0; react { - assert DOM('#button-label', '', Syndicate.seal(this.counter)); + assert DOM('#button-label', '', '' + this.counter); on message jQueryEvent('#counter', 'click', _) { this.counter++; } diff --git a/js/examples/chat/index.html b/js/examples/chat/index.html index 611a991..0920ab6 100644 --- a/js/examples/chat/index.html +++ b/js/examples/chat/index.html @@ -5,6 +5,7 @@ + @@ -33,7 +34,14 @@

Active Users

- +
diff --git a/js/examples/chat/index.js b/js/examples/chat/index.js index 617a269..c254dd7 100644 --- a/js/examples/chat/index.js +++ b/js/examples/chat/index.js @@ -35,10 +35,8 @@ function spawnChatApp() { assert toBroker(url, present(this.nym, this.status)); during fromBroker(url, present($who, $status)) { - assert DOM('#nymlist', 'present-nym', Syndicate.seal( - ["li", - ["span", [["class", "nym"]], who], - ["span", [["class", "nym_status"]], status]])); + assert DOM('#nymlist', 'present-nym', + Mustache.render($('#nym_template').html(), { who: who, status: status })); } on message jQueryEvent('#send_chat', 'click', _) { diff --git a/js/examples/chat/style.css b/js/examples/chat/style.css index a0fe84b..17dcfdd 100644 --- a/js/examples/chat/style.css +++ b/js/examples/chat/style.css @@ -1,3 +1,7 @@ +template { + display: none; +} + h1 { background: lightgrey; } diff --git a/js/examples/dom/index.js b/js/examples/dom/index.js index 0af4a3e..ed7dc84 100644 --- a/js/examples/dom/index.js +++ b/js/examples/dom/index.js @@ -4,7 +4,6 @@ $(document).ready(function () { var sub = Syndicate.sub; var assert = Syndicate.assert; var retract = Syndicate.retract; - var seal = Syndicate.seal; var __ = Syndicate.__; var _$ = Syndicate._$; @@ -18,8 +17,7 @@ $(document).ready(function () { Dataspace.spawn({ boot: function () { return assert(DOM("#clicker-holder", "clicker", - seal(["button", ["span", [["style", "font-style: italic"]], - "Click me!"]]))) + '')) .andThen(sub(jQueryEvent("button.clicker", "click", __))); }, handleEvent: function (e) { @@ -38,9 +36,8 @@ $(document).ready(function () { updateState: function () { Dataspace.stateChange(retract(DOM.pattern) .andThen(assert(DOM("#counter-holder", "counter", - seal(["div", - ["p", "The current count is: ", - this.counter]]))))); + '

The current count is: '+this.counter+ + '

')))); }, handleEvent: function (e) { if (e.type === "message" && e.message === "bump_count") { diff --git a/js/examples/iot/index.html b/js/examples/iot/index.html index 3a862a8..d03b18b 100644 --- a/js/examples/iot/index.html +++ b/js/examples/iot/index.html @@ -5,6 +5,7 @@ + @@ -19,13 +20,22 @@

TV

-  
    +   +

    Stove switch

    -
    +
    + +
    @@ -37,7 +47,11 @@

    Power draw meter

    -
    +
    + +
    diff --git a/js/examples/iot/index.js b/js/examples/iot/index.js index 3293a56..8ff23b3 100644 --- a/js/examples/iot/index.js +++ b/js/examples/iot/index.js @@ -15,7 +15,7 @@ function spawnTV() { actor { react { during tvAlert($text) { - assert DOM('#tv', 'alert', Syndicate.seal(["li", text])); + assert DOM('#tv', 'alert', Mustache.render($('#alert_template').html(), { text: text })); } } } @@ -68,9 +68,9 @@ function spawnStoveSwitch() { assert switchState(this.powerOn); assert DOM('#stove-switch', 'switch-state', - Syndicate.seal(["img", [["src", - "img/stove-coil-element-" + - (this.powerOn ? "hot" : "cold") + ".jpg"]]])); + 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; } @@ -92,9 +92,7 @@ function spawnPowerDrawMonitor() { assert powerDraw(this.watts); assert DOM('#power-draw-meter', 'power-draw', - Syndicate.seal(["p", "Power draw: ", - ["span", [["class", "power-meter-display"]], - this.watts + " W"]])); + Mustache.render($('#power_draw_template').html(), { watts: this.watts })); on asserted switchState($on) { this.watts = on ? 1500 : 0; diff --git a/js/examples/iot/style.css b/js/examples/iot/style.css index 2fd6050..0f34cb3 100644 --- a/js/examples/iot/style.css +++ b/js/examples/iot/style.css @@ -1,3 +1,7 @@ +template { + display: none; +} + #tv-container { background: url('img/tvscreen.gif'); background-size: 100%; diff --git a/js/examples/svg/index.js b/js/examples/svg/index.js index 485db4d..279d06b 100644 --- a/js/examples/svg/index.js +++ b/js/examples/svg/index.js @@ -19,15 +19,11 @@ $(document).ready(function () { this.handX = 50 + 40 * Math.cos(this.angle); this.handY = 50 + 40 * Math.sin(this.angle); } - assert DOM('#clock', 'clock', Syndicate.seal( - ["svg", [["xmlns", "http://www.w3.org/2000/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]]]])) + assert DOM('#clock', 'clock', + ''+ + ''+ + ''+ + '') when (typeof this.angle === 'number'); } } diff --git a/js/src/dom-driver.js b/js/src/dom-driver.js index ddffcbf..57c540c 100644 --- a/js/src/dom-driver.js +++ b/js/src/dom-driver.js @@ -3,7 +3,6 @@ var Patch = require("./patch.js"); var DemandMatcher = require('./demand-matcher.js').DemandMatcher; var Struct = require('./struct.js'); var Ack = require('./ack.js').Ack; -var Seal = require('./seal.js').Seal; var Dataspace_ = require("./dataspace.js"); var Dataspace = Dataspace_.Dataspace; @@ -89,57 +88,28 @@ DOMFragment.prototype.handleEvent = function (e) { /////////////////////////////////////////////////////////////////////////// -function isAttributes(x) { - return Array.isArray(x) && ((x.length === 0) || Array.isArray(x[0])); -} - -DOMFragment.prototype.interpretSpec = function (spec, xmlns) { - // 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 = isAttributes(spec[1]); - var attrs = hasAttrs ? spec[1] : []; - var kidIndex = hasAttrs ? 2 : 1; - - var xmlnsAttr = attrs.find(function (e) { return e[0] === 'xmlns' }); - if (xmlnsAttr) { - xmlns = xmlnsAttr[1]; - } - - // TODO: Wow! Such XSS! Many hacks! So vulnerability! Amaze! - var n = xmlns - ? document.createElementNS(xmlns, tagName) - : document.createElement(tagName); - for (var i = 0; i < attrs.length; i++) { - if (attrs[i][0] !== 'xmlns') n.setAttribute(attrs[i][0], attrs[i][1]); - } - for (var i = kidIndex; i < spec.length; i++) { - n.appendChild(this.interpretSpec(spec[i], xmlns)); - } - return n; - } else { - throw new Error("Ill-formed DOM specification"); - } -}; - DOMFragment.prototype.buildNodes = function () { var self = this; var nodes = []; $(self.selector).each(function (index, domNode) { - if (!(self.fragmentSpec instanceof Syndicate.Seal)) { - throw new Error("DOM fragmentSpec not contained in a Syndicate.Seal: " + JSON.stringify(self.fragmentSpec)); + if (typeof self.fragmentSpec !== 'string') { + throw new Error("DOM fragmentSpec not a string: " + JSON.stringify(self.fragmentSpec)); } - var n = self.interpretSpec(self.fragmentSpec.sealContents, ''); - if ('classList' in n) { - n.classList.add(self.fragmentClass); + var newNodes = $('
    ' + self.fragmentSpec + '
    ')[0].childNodes; + // This next loop looks SUPER SUSPICIOUS. What is happening is + // that each time we call domNode.appendChild(n), where n is an + // element of the NodeList newNodes, the DOM is **removing** n + // from the NodeList in order to place it in its new parent. So, + // each call to appendChild shrinks the NodeList by one node until + // it is finally empty, and its length property yields zero. + while (newNodes.length) { + var n = newNodes[0]; + if ('classList' in n) { + n.classList.add(self.fragmentClass); + } + domNode.appendChild(n); + nodes.push(n); } - domNode.appendChild(n); - nodes.push(n); }); return nodes; };