demand-matcher.js, jquery-driver.js
This commit is contained in:
parent
8c55ada827
commit
9d7dd37a37
|
@ -0,0 +1,15 @@
|
||||||
|
<!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>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,28 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var G;
|
||||||
|
$(document).ready(function () {
|
||||||
|
var Network = Syndicate.Network;
|
||||||
|
var sub = Syndicate.sub;
|
||||||
|
var __ = Syndicate.__;
|
||||||
|
var _$ = Syndicate._$;
|
||||||
|
|
||||||
|
G = new Syndicate.Ground(function () {
|
||||||
|
console.log('starting ground boot');
|
||||||
|
|
||||||
|
Syndicate.JQuery.spawnJQueryDriver();
|
||||||
|
|
||||||
|
Network.spawn({
|
||||||
|
boot: function () {
|
||||||
|
return sub(['jQuery', '#clicker', 'click', __]);
|
||||||
|
},
|
||||||
|
handleEvent: function (e) {
|
||||||
|
if (e.type === 'message' && e.message[0] === 'jQuery' && e.message[1] === '#clicker') {
|
||||||
|
var r = $('#result');
|
||||||
|
r.html(Number(r.html()) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
G.startStepping();
|
||||||
|
});
|
|
@ -0,0 +1,80 @@
|
||||||
|
var Immutable = require('immutable');
|
||||||
|
var Syndicate = require('./syndicate.js');
|
||||||
|
var Route = require('./route.js');
|
||||||
|
var Patch = require('./patch.js');
|
||||||
|
var Util = require('./util.js');
|
||||||
|
|
||||||
|
function DemandMatcher(demandSpec, supplySpec, options) {
|
||||||
|
options = Util.extend({
|
||||||
|
metaLevel: 0,
|
||||||
|
onDemandIncrease: function (captures) {
|
||||||
|
console.error("Syndicate: Unhandled increase in demand", captures);
|
||||||
|
},
|
||||||
|
onSupplyDecrease: function (captures) {
|
||||||
|
console.error("Syndicate: Unhandled decrease in supply", captures);
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
this.metaLevel = options.metaLevel;
|
||||||
|
this.onDemandIncrease = options.onDemandIncrease;
|
||||||
|
this.onSupplyDecrease = options.onSupplyDecrease;
|
||||||
|
this.demandSpec = demandSpec;
|
||||||
|
this.supplySpec = supplySpec;
|
||||||
|
this.demandPattern = Route.projectionToPattern(demandSpec);
|
||||||
|
this.supplyPattern = Route.projectionToPattern(supplySpec);
|
||||||
|
this.demandProjection = Route.compileProjection(demandSpec);
|
||||||
|
this.supplyProjection = Route.compileProjection(supplySpec);
|
||||||
|
this.currentDemand = Immutable.Set();
|
||||||
|
this.currentSupply = Immutable.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
DemandMatcher.prototype.boot = function () {
|
||||||
|
return Patch.sub(this.demandPattern, this.metaLevel)
|
||||||
|
.andThen(Patch.sub(this.supplyPattern, this.metaLevel));
|
||||||
|
};
|
||||||
|
|
||||||
|
DemandMatcher.prototype.handleEvent = function (e) {
|
||||||
|
if (e.type === "stateChange") {
|
||||||
|
this.handlePatch(e.patch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DemandMatcher.prototype.handlePatch = function (p) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var addedDemand = Route.trieKeys(Route.project(p.added, self.demandProjection));
|
||||||
|
var removedDemand = Route.trieKeys(Route.project(p.removed, self.demandProjection));
|
||||||
|
var addedSupply = Route.trieKeys(Route.project(p.added, self.supplyProjection));
|
||||||
|
var removedSupply = Route.trieKeys(Route.project(p.removed, self.supplyProjection));
|
||||||
|
|
||||||
|
if (addedDemand === null) {
|
||||||
|
throw new Error("Syndicate: wildcard demand detected:\n" +
|
||||||
|
self.demandSpec + "\n" +
|
||||||
|
p.pretty());
|
||||||
|
}
|
||||||
|
if (addedSupply === null) {
|
||||||
|
throw new Error("Syndicate: wildcard supply detected:\n" +
|
||||||
|
self.supplySpec + "\n" +
|
||||||
|
p.pretty());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.currentSupply = self.currentSupply.union(addedSupply);
|
||||||
|
self.currentDemand = self.currentDemand.subtract(removedDemand);
|
||||||
|
|
||||||
|
removedSupply.forEach(function (captures) {
|
||||||
|
if (self.currentDemand.has(captures)) {
|
||||||
|
self.onSupplyDecrease(Route.captureToObject(captures, self.supplyProjection));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addedDemand.forEach(function (captures) {
|
||||||
|
if (!self.currentSupply.has(captures)) {
|
||||||
|
self.onDemandIncrease(Route.captureToObject(captures, self.demandProjection));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.currentSupply = self.currentSupply.subtract(removedSupply);
|
||||||
|
self.currentDemand = self.currentDemand.union(addedDemand);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
module.exports.DemandMatcher = DemandMatcher;
|
|
@ -0,0 +1,90 @@
|
||||||
|
// JQuery event driver
|
||||||
|
var Syndicate = require("./syndicate.js");
|
||||||
|
var Patch = require("./patch.js");
|
||||||
|
var DemandMatcher = require('./demand-matcher.js').DemandMatcher;
|
||||||
|
var Network = Syndicate.Network;
|
||||||
|
var __ = Syndicate.__;
|
||||||
|
var _$ = Syndicate._$;
|
||||||
|
|
||||||
|
function spawnJQueryDriver(baseSelector, metaLevel, wrapFunction) {
|
||||||
|
metaLevel = metaLevel || 0;
|
||||||
|
wrapFunction = wrapFunction || defaultWrapFunction;
|
||||||
|
Network.spawn(
|
||||||
|
new DemandMatcher(Patch.observe(wrapFunction(_$('selector'), _$('eventName'), __)),
|
||||||
|
Patch.advertise(wrapFunction(_$('selector'), _$('eventName'), __)),
|
||||||
|
{
|
||||||
|
metaLevel: metaLevel,
|
||||||
|
onDemandIncrease: function (c) {
|
||||||
|
Network.spawn(new JQueryEventRouter(baseSelector,
|
||||||
|
c.selector,
|
||||||
|
c.eventName,
|
||||||
|
metaLevel,
|
||||||
|
wrapFunction));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultWrapFunction(selector, eventName, eventValue) {
|
||||||
|
return ["jQuery", selector, eventName, eventValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
function JQueryEventRouter(baseSelector, selector, eventName, metaLevel, wrapFunction) {
|
||||||
|
var self = this;
|
||||||
|
this.baseSelector = baseSelector || null;
|
||||||
|
this.selector = selector;
|
||||||
|
this.eventName = eventName;
|
||||||
|
this.metaLevel = metaLevel || 0;
|
||||||
|
this.wrapFunction = wrapFunction || defaultWrapFunction;
|
||||||
|
this.preventDefault = (this.eventName.charAt(0) !== "+");
|
||||||
|
this.handler =
|
||||||
|
Network.wrap(function (e) {
|
||||||
|
Network.send(self.wrapFunction(self.selector, self.eventName, e), self.metaLevel);
|
||||||
|
if (self.preventDefault) e.preventDefault();
|
||||||
|
return !self.preventDefault;
|
||||||
|
});
|
||||||
|
this.computeNodes().on(this.preventDefault ? this.eventName : this.eventName.substring(1),
|
||||||
|
this.handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
JQueryEventRouter.prototype.boot = function () {
|
||||||
|
return Patch.pub(this.wrapFunction(this.selector, this.eventName, __), this.metaLevel)
|
||||||
|
.andThen(Patch.sub(Patch.observe(this.wrapFunction(this.selector, this.eventName, __)),
|
||||||
|
this.metaLevel));
|
||||||
|
};
|
||||||
|
|
||||||
|
JQueryEventRouter.prototype.handleEvent = function (e) {
|
||||||
|
if (e.type === "stateChange" && e.patch.hasRemoved()) {
|
||||||
|
this.computeNodes().off(this.eventName, this.handler);
|
||||||
|
Network.exit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JQueryEventRouter.prototype.computeNodes = function () {
|
||||||
|
if (this.baseSelector) {
|
||||||
|
return $(this.baseSelector).children(this.selector).addBack(this.selector);
|
||||||
|
} else {
|
||||||
|
return $(this.selector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function simplifyDOMEvent(e) {
|
||||||
|
var keys = [];
|
||||||
|
for (var k in e) {
|
||||||
|
var v = e[k];
|
||||||
|
if (typeof v === 'object') continue;
|
||||||
|
if (typeof v === 'function') continue;
|
||||||
|
keys.push(k);
|
||||||
|
}
|
||||||
|
keys.sort();
|
||||||
|
var simplified = [];
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
simplified.push([keys[i], e[keys[i]]]);
|
||||||
|
}
|
||||||
|
return simplified;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
module.exports.spawnJQueryDriver = spawnJQueryDriver;
|
||||||
|
module.exports.simplifyDOMEvent = simplifyDOMEvent;
|
||||||
|
module.exports.defaultWrapFunction = defaultWrapFunction;
|
|
@ -17,8 +17,10 @@ copyKeys(['__', '_$', '$Capture', '$Special',
|
||||||
module.exports,
|
module.exports,
|
||||||
module.exports.Route);
|
module.exports.Route);
|
||||||
|
|
||||||
|
module.exports.DemandMatcher = require('./demand-matcher.js').DemandMatcher;
|
||||||
|
|
||||||
// module.exports.DOM = require("./dom-driver.js");
|
// module.exports.DOM = require("./dom-driver.js");
|
||||||
// module.exports.JQuery = require("./jquery-driver.js");
|
module.exports.JQuery = require("./jquery-driver.js");
|
||||||
// module.exports.RoutingTableWidget = require("./routing-table-widget.js");
|
// module.exports.RoutingTableWidget = require("./routing-table-widget.js");
|
||||||
// module.exports.WebSocket = require("./websocket-driver.js");
|
// module.exports.WebSocket = require("./websocket-driver.js");
|
||||||
module.exports.Reflect = require("./reflect.js");
|
module.exports.Reflect = require("./reflect.js");
|
||||||
|
|
Loading…
Reference in New Issue