109 lines
2.6 KiB
JavaScript
109 lines
2.6 KiB
JavaScript
function spawnRoutingTableWidget(selector, fragmentClass) {
|
||
|
||
function sortedBy(xs, f) {
|
||
var keys = [];
|
||
var result = [];
|
||
for (var i = 0; i < xs.length; i++) {
|
||
keys.push([f(xs[i]), i]);
|
||
}
|
||
keys.sort();
|
||
for (var i = 0; i < xs.length; i++) {
|
||
result.push(xs[keys[i][1]]);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
function count_uniqBy(xs, f) {
|
||
var r = [];
|
||
if (xs.length === 0) return [];
|
||
var last = xs[0];
|
||
var lastKey = f(xs[0]);
|
||
var count = 1;
|
||
function fin() {
|
||
r.push([count, last]);
|
||
}
|
||
for (var i = 1; i < xs.length; i++) {
|
||
var fi = f(xs[i]);
|
||
if (fi === lastKey) {
|
||
count++;
|
||
} else {
|
||
fin();
|
||
last = xs[i];
|
||
lastKey = fi;
|
||
count = 1;
|
||
}
|
||
}
|
||
fin();
|
||
return r;
|
||
}
|
||
|
||
World.spawn({
|
||
boot: function () { this.updateState(); },
|
||
|
||
state: [],
|
||
nextState: [],
|
||
timer: false,
|
||
|
||
digestRoutes: function (rs) {
|
||
var s = [];
|
||
function key(r) { return JSON.stringify([r.pattern,
|
||
r.isSubscription ? r.level : -r.level,
|
||
r.isSubscription]); }
|
||
for (var i = 0; i < rs.length; i++) {
|
||
var p = rs[i].pattern;
|
||
if (p[0] !== "DOM" || p[1] !== selector || p[2] !== fragmentClass) {
|
||
s.push(rs[i]);
|
||
}
|
||
}
|
||
s = sortedBy(s, key);
|
||
s = count_uniqBy(s, key);
|
||
return s;
|
||
},
|
||
|
||
updateState: function () {
|
||
var elts = ["ul", {"class": "routing-table"}];
|
||
for (var i = 0; i < this.state.length; i++) {
|
||
var r = this.state[i];
|
||
var levelstr;
|
||
switch (r[1].level) {
|
||
case 0: levelstr = "participant"; break;
|
||
case 1: levelstr = "observer"; break;
|
||
case 2: levelstr = "metaobserver"; break;
|
||
default: levelstr = "level " + r[1].level; break;
|
||
}
|
||
var polarity = r[1].isSubscription ? "sub" : "pub";
|
||
var pat = JSON.stringify(r[1].pattern).replace(/{"__":"__"}/g, '★');
|
||
elts.push(["li",
|
||
["span", {"class": "repeatcount"}, r[0]],
|
||
["span", {"class": "times"}, " × "],
|
||
["span", {"class": polarity + " route"},
|
||
["span", {"class": "level", "data-level": r[1].level}, levelstr],
|
||
["span", {"class": "polarity"}, polarity],
|
||
["span", {"class": "pattern"}, pat]]]);
|
||
}
|
||
World.updateRoutes([sub(__, 0, Infinity),
|
||
pub(__, 0, Infinity),
|
||
pub(["DOM", selector, fragmentClass, elts])]);
|
||
},
|
||
|
||
handleEvent: function (e) {
|
||
var self = this;
|
||
if (e.type === "routes") {
|
||
self.nextState = self.digestRoutes(e.routes);
|
||
if (self.timer) {
|
||
clearTimeout(self.timer);
|
||
self.timer = false;
|
||
}
|
||
self.timer = setTimeout(World.wrap(function () {
|
||
if (JSON.stringify(self.nextState) !== JSON.stringify(self.state)) {
|
||
self.state = self.nextState;
|
||
self.updateState();
|
||
}
|
||
self.timer = false;
|
||
}), 50);
|
||
}
|
||
}
|
||
});
|
||
|
||
}
|