2012-04-20 03:10:25 +00:00
|
|
|
|
|
|
|
var Elm = function() {
|
2012-06-29 15:21:06 +00:00
|
|
|
var send = function(node, timestep, changed) {
|
|
|
|
var kids = node.kids;
|
2012-06-08 05:54:22 +00:00
|
|
|
for (var i = kids.length; i--; ) {
|
2012-06-29 15:21:06 +00:00
|
|
|
kids[i].recv(timestep, changed, node.id);
|
2012-06-08 05:54:22 +00:00
|
|
|
}
|
|
|
|
};
|
2012-04-20 03:10:25 +00:00
|
|
|
var input = function(base) {
|
|
|
|
this.id = Guid.guid();
|
|
|
|
this.value = base;
|
2012-06-08 05:54:22 +00:00
|
|
|
this.kids = [];
|
|
|
|
this.recv = function(timestep, eid, v) {
|
2012-04-20 03:10:25 +00:00
|
|
|
var changed = eid === this.id;
|
|
|
|
if (changed) { this.value = v; }
|
2012-06-29 15:21:06 +00:00
|
|
|
send(this, timestep, changed);
|
2012-04-20 03:10:25 +00:00
|
|
|
};
|
2012-06-08 05:54:22 +00:00
|
|
|
Dispatcher.inputs.push(this);
|
2012-04-20 03:10:25 +00:00
|
|
|
};
|
|
|
|
var lift = function(func,args) {
|
|
|
|
this.id = Guid.guid();
|
|
|
|
this.value = null;
|
2012-06-08 05:54:22 +00:00
|
|
|
this.kids = [];
|
|
|
|
this.inbox = {};
|
2012-04-20 03:10:25 +00:00
|
|
|
|
|
|
|
args.reverse();
|
|
|
|
this.recalc = function() {
|
|
|
|
var f = func;
|
|
|
|
for (var i = args.length; i--; ) {
|
|
|
|
f = f(args[i].value);
|
|
|
|
}
|
|
|
|
this.value = f;
|
|
|
|
};
|
|
|
|
this.recalc();
|
|
|
|
|
2012-06-29 15:21:06 +00:00
|
|
|
this.recv = function(timestep, changed, parentID) {
|
2012-06-08 05:54:22 +00:00
|
|
|
if (!this.inbox.hasOwnProperty(timestep)) {
|
|
|
|
this.inbox[timestep] = { changed: false, count: 0 };
|
|
|
|
}
|
|
|
|
var box = this.inbox[timestep];
|
|
|
|
box.count += 1;
|
|
|
|
if (changed) { box.changed = true; }
|
|
|
|
if (box.count == args.length) {
|
|
|
|
if (box.changed) { this.recalc() }
|
2012-06-29 15:21:06 +00:00
|
|
|
send(this, timestep, box.changed);
|
2012-06-08 05:54:22 +00:00
|
|
|
delete this.inbox[timestep];
|
2012-04-20 03:10:25 +00:00
|
|
|
}
|
|
|
|
};
|
2012-06-08 05:54:22 +00:00
|
|
|
for (var i = args.length; i--; ) {
|
|
|
|
args[i].kids.push(this);
|
|
|
|
}
|
2012-04-20 03:10:25 +00:00
|
|
|
};
|
|
|
|
var fold = function(func,base,input) {
|
|
|
|
this.id = Guid.guid();
|
|
|
|
this.value = base;
|
2012-06-08 05:54:22 +00:00
|
|
|
this.kids = [];
|
2012-06-29 15:21:06 +00:00
|
|
|
this.recv = function(timestep, changed, parentID) {
|
2012-04-20 03:10:25 +00:00
|
|
|
if (changed) { this.value = func(input.value)(this.value); }
|
2012-06-29 15:21:06 +00:00
|
|
|
send(this, timestep, changed);
|
2012-04-20 03:10:25 +00:00
|
|
|
};
|
2012-06-08 05:54:22 +00:00
|
|
|
input.kids.push(this);
|
2012-04-20 03:10:25 +00:00
|
|
|
};
|
2012-06-28 08:50:16 +00:00
|
|
|
|
|
|
|
var dropIf = function(pred,base,input) {
|
|
|
|
this.id = Guid.guid();
|
|
|
|
this.value = pred(input.value) ? base : input.value;
|
|
|
|
this.kids = [];
|
2012-06-29 15:21:06 +00:00
|
|
|
this.recv = function(timestep, changed, parentID) {
|
2012-06-28 08:50:16 +00:00
|
|
|
var chng = changed && !pred(input.value);
|
|
|
|
if (chng) { this.value = input.value; }
|
2012-06-29 15:21:06 +00:00
|
|
|
send(this, timestep, chng);
|
2012-06-28 08:50:16 +00:00
|
|
|
};
|
|
|
|
input.kids.push(this);
|
|
|
|
};
|
|
|
|
var dropRepeats = function(input) {
|
|
|
|
this.id = Guid.guid();
|
|
|
|
this.value = input.value;
|
|
|
|
this.kids = [];
|
2012-06-29 15:21:06 +00:00
|
|
|
this.recv = function(timestep, changed, parentID) {
|
2012-06-28 08:50:16 +00:00
|
|
|
var chng = changed && !eq(this.value,input.value);
|
|
|
|
if (chng) { this.value = input.value; }
|
2012-06-29 15:21:06 +00:00
|
|
|
send(this, timestep, chng);
|
2012-06-28 08:50:16 +00:00
|
|
|
};
|
|
|
|
input.kids.push(this);
|
|
|
|
};
|
|
|
|
|
|
|
|
var dropWhen = function(s1) { return function(b) { return function(s2) {
|
|
|
|
var pairs = new lift(function(x){return function(y){return [x,y];};},[s1,s2]);
|
|
|
|
var dropped = new dropIf(function(p){return p[0];},[true,b],pairs);
|
|
|
|
return new lift(function(p){return p[1];},[dropped]); }; };
|
|
|
|
};
|
|
|
|
|
2012-06-29 15:21:06 +00:00
|
|
|
var sampleOn = function(s1,s2) {
|
|
|
|
this.id = Guid.guid();
|
|
|
|
this.value = s2.value;
|
|
|
|
this.kids = [];
|
|
|
|
this.inbox = {};
|
|
|
|
|
|
|
|
this.recv = function(timestep, changed, parentID) {
|
|
|
|
var chng = changed && parentID === s1.id;
|
|
|
|
if (chng) { this.value = s2.value; }
|
|
|
|
send(this, timestep, chng);
|
|
|
|
};
|
|
|
|
s1.kids.push(this);
|
|
|
|
s2.kids.push(this);
|
|
|
|
};
|
|
|
|
|
2012-04-20 03:10:25 +00:00
|
|
|
return {Input: function(x) {return new input(x);},
|
|
|
|
Lift: function(f,xs){return new lift(f,xs);},
|
2012-06-28 08:50:16 +00:00
|
|
|
Fold: function(f,b,x){return new fold(f,b,x);},
|
|
|
|
keepIf : function(pred) { return function(base) { return function(sig) {
|
|
|
|
return new dropIf(function(x) { return !pred(x)},base,sig); }; }; },
|
|
|
|
dropIf : function(pred) { return function(base) { return function(sig) {
|
|
|
|
return new dropIf(pred,base,sig); }; }; },
|
|
|
|
keepWhen : function(s) { return dropWhen(new lift(function(b){return !b;},[s])); },
|
|
|
|
dropWhen : dropWhen,
|
2012-06-29 15:21:06 +00:00
|
|
|
dropRepeats : function(s) { return new dropRepeats(s);},
|
2012-06-29 16:29:41 +00:00
|
|
|
sampleOn : function(s1) { return function(s2) { return new sampleOn(s1,s2); }; }
|
2012-04-20 03:10:25 +00:00
|
|
|
};
|
|
|
|
}();
|
|
|
|
|
|
|
|
var Dispatcher = function() {
|
|
|
|
var program = null;
|
2012-06-08 05:54:22 +00:00
|
|
|
var timestep = 0;
|
|
|
|
var inputs = [];
|
|
|
|
|
2012-04-20 03:10:25 +00:00
|
|
|
var correctSize = function(e) {
|
|
|
|
var kids = e.childNodes;
|
|
|
|
var len = kids.length;
|
|
|
|
if (e.hasOwnProperty('isElmLeaf')) {
|
2012-06-12 10:44:45 +00:00
|
|
|
if (e.hasOwnProperty('isElmText')) { Element.correctTextSize(e); }
|
2012-04-20 03:10:25 +00:00
|
|
|
var w = e.style.width === "" ?
|
|
|
|
0 : e.style.width.slice(0,-2) - 0;
|
|
|
|
var h = e.style.height === "" ?
|
|
|
|
0 : e.style.height.slice(0,-2) - 0;
|
|
|
|
return [w, h];
|
|
|
|
}
|
|
|
|
if (len === 1) {
|
|
|
|
var dim = correctSize(kids[0]);
|
2012-07-28 18:32:31 +00:00
|
|
|
if (e.style.hasOwnProperty('width') && e.style.width.length > 0) { dim[0] = e.style.width.slice(0,-2) - 0; }
|
|
|
|
if (e.style.hasOwnProperty('height') && e.style.height.length > 0) { dim[1] = e.style.height.slice(0,-2) - 0; }
|
2012-04-20 03:10:25 +00:00
|
|
|
if (dim[0] !== 0) { e.style.width = dim[0] + "px"; }
|
|
|
|
if (dim[1] !== 0) { e.style.height = dim[1] + "px"; }
|
|
|
|
return dim;
|
|
|
|
}
|
|
|
|
var wmax = 0, hmax = 0, wsum = 0, hsum = 0;
|
|
|
|
var hasWidth = true, hasHeight = true, dim = null;
|
|
|
|
while (len--) {
|
|
|
|
dim = correctSize(kids[len]);
|
|
|
|
wmax = Math.max(wmax, dim[0]);
|
|
|
|
hmax = Math.max(hmax, dim[1]);
|
|
|
|
wsum += dim[0];
|
|
|
|
hsum += dim[1];
|
|
|
|
hasWidth = hasWidth && dim[0] > 0;
|
|
|
|
hasHeight = hasHeight && dim[1] > 0;
|
|
|
|
}
|
|
|
|
var w = wmax, h = hmax, dir = e.elmFlowDirection;
|
|
|
|
if (dir === "X") { w = hasWidth ? wsum : 0; }
|
|
|
|
if (dir === "Y") { h = hasHeight ? hsum : 0; }
|
|
|
|
if (w > 0) e.style.width = w + "px";
|
|
|
|
if (h > 0) e.style.height = h + "px";
|
|
|
|
return [w,h];
|
|
|
|
};
|
|
|
|
|
|
|
|
var initialize = function() {
|
2012-06-28 08:50:16 +00:00
|
|
|
program = ElmCode.main();
|
2012-06-08 05:54:22 +00:00
|
|
|
if (!program.hasOwnProperty('recv')) {
|
2012-04-20 03:10:25 +00:00
|
|
|
program = Elm.Input(program);
|
|
|
|
}
|
|
|
|
var content = document.getElementById('content');
|
|
|
|
content.appendChild(program.value);
|
2012-06-15 08:23:42 +00:00
|
|
|
adjust();
|
2012-04-20 03:10:25 +00:00
|
|
|
var w = document.getElementById('widthChecker').offsetWidth;
|
|
|
|
if (w !== window.innerWidth) {
|
|
|
|
Dispatcher.notify(Window.dimensions.id, Value.Tuple(w, window.innerHeight));
|
|
|
|
}
|
2012-06-08 05:54:22 +00:00
|
|
|
program = Elm.Lift(function(value) {
|
|
|
|
var content = document.getElementById('content');
|
2012-06-19 06:59:46 +00:00
|
|
|
var kid = content.children[0]
|
|
|
|
content.replaceChild(value, kid);
|
|
|
|
delete kid;
|
2012-06-15 08:23:42 +00:00
|
|
|
adjust();
|
2012-06-08 05:54:22 +00:00
|
|
|
return value;
|
|
|
|
}, [program]);
|
2012-04-20 03:10:25 +00:00
|
|
|
};
|
|
|
|
var adjust = function() {
|
|
|
|
var content = document.getElementById('content');
|
2012-06-15 08:23:42 +00:00
|
|
|
correctSize(content.children[0]);
|
2012-04-20 03:10:25 +00:00
|
|
|
}
|
|
|
|
var notify = function(id, v) {
|
2012-06-08 05:54:22 +00:00
|
|
|
timestep += 1;
|
|
|
|
for (var i = inputs.length; i--; ) {
|
|
|
|
inputs[i].recv(timestep, id, v);
|
2012-04-20 03:10:25 +00:00
|
|
|
}
|
|
|
|
};
|
2012-06-08 05:54:22 +00:00
|
|
|
return {initialize:initialize, notify:notify, adjust:adjust, inputs:inputs};
|
2012-04-20 03:10:25 +00:00
|
|
|
}();
|