@@ -1,367 +1,143 @@
2−var Signal = function() {
3+Elm.Signal = function() {
3− function wrap(elem) {
4+ var send = function(node, timestep, changed) {
4− var p = Value.getSize(elem);
5+ var kids = node.kids;
5− return ["Element", Guid.guid(), ["EHtml",elem], p[0], p[1], 1, Nothing, Nothing];
6+ for (var i = kids.length; i--; ) {
7+ kids[i].recv(timestep, changed, node.id);
7− function toElmString(str) {
10+ var input = function(base) {
8− var out = ["Nil"];
11+ this.id = Guid.guid();
9− for (var i = str.length; i--; ) {
12+ this.value = base;
10− out = ["Cons", str[i], out];
13+ this.kids = [];
11− }
14+ this.defaultNumberOfKids = 0;
12− return out;
15+ this.recv = function(timestep, eid, v) {
13− }
16+ var changed = eid === this.id;
14− var addListener = function() {
17+ if (changed) { this.value = v; }
15− if(document.addEventListener) {
18+ send(this, timestep, changed);
16− return function(element, event, handler) {
19+ return changed;
17− element.addEventListener(event, handler, false);
21− return function(element, event, handler) {
22− element.attachEvent('on' + event, handler);
24− }
21+ Dispatcher.inputs.push(this);
27− var Mouse = function() {
23+ var lift = function(func,args) {
28− var position = Elm.Input(Value.Tuple(0,0));
24+ this.id = Guid.guid();
29− position.defaultNumberOfKids = 2;
25+ this.value = null;
31− var x = Elm.Lift(function(p){return p[1];},[position]);
27+ this.count = 0;
32− x.defaultNumberOfKids = 0;
28+ this.changed = false;
33− var y = Elm.Lift(function(p){return p[2];},[position]);
29+
34− y.defaultNumberOfKids = 0;
30+ args.reverse();
35−
31+ this.recalc = function() {
36− var isDown = Elm.Input(false);
32+ var f = func;
37− var isClicked = Elm.Input(false);
33+ for (var i = args.length; i--; ) {
38− var clicks = Elm.Input(Value.Tuple());
34+ f = f(args[i].value);
40− function getXY(e) {
40+ this.recv = function(timestep, changed, parentID) {
41− var posx = 0;
41+ this.count += 1;
42− var posy = 0;
42+ if (changed) { this.changed = true; }
43− if (!e) var e = window.event;
43+ if (this.count == args.length) {
44− if (e.pageX || e.pageY) {
44+ if (this.changed) { this.recalc() }
45− posx = e.pageX;
45+ send(this, timestep, this.changed);
46− posy = e.pageY;
46+ this.changed = false;
47− } else if (e.clientX || e.clientY) {
47+ this.count = 0;
48− posx = e.clientX + document.body.scrollLeft +
49− document.documentElement.scrollLeft;
50− posy = e.clientY + document.body.scrollTop +
51− document.documentElement.scrollTop;
53− return Value.Tuple(posx, posy);
49+ };
50+ for (var i = args.length; i--; ) {
51+ args[i].kids.push(this);
56− addListener(document, 'click', function(e) {
54+ var fold = function(func,base,baseIsFunc,input) {
57− var hasListener1 = Dispatcher.notify(isClicked.id, true);
55+ this.id = Guid.guid();
58− var hasListener2 = Dispatcher.notify(clicks.id, Value.Tuple());
56+ this.value = baseIsFunc ? base(input.value) : base;
59− Dispatcher.notify(isClicked.id, false);
57+ this.kids = [];
60− if (!hasListener1 && !hasListener2)
58+ this.recv = function(timestep, changed, parentID) {
61− this.removeEventListener('click',arguments.callee,false);
59+ if (changed) { this.value = func(input.value)(this.value); }
62− });
60+ send(this, timestep, changed);
63− addListener(document, 'mousedown', function(e) {
64− var hasListener = Dispatcher.notify(isDown.id, true);
66− this.removeEventListener('mousedown',arguments.callee,false);
68− addListener(document, 'mouseup', function(e) {
69− var hasListener = Dispatcher.notify(isDown.id, false);
71− this.removeEventListener('mouseup',arguments.callee,false);
73− addListener(document, 'mousemove', function(e) {
74− var hasListener = Dispatcher.notify(position.id, getXY(e));
76− this.removeEventListener('mousemove',arguments.callee,false);
78− var clickedOn = function(elem) {
79− var node = Render.render(elem);
80− var click = Elm.Input(false);
81− addListener(node, 'click', function(e) {
82− Dispatcher.notify(click.id, true);
83− Dispatcher.notify(click.id, false);
85− return Value.Tuple(wrap(node), click);
87− return {position: position,
62+ input.kids.push(this);
90− isClicked: isClicked,
93− isClickedOn: clickedOn
97− var Time = function() {
65+ var dropIf = function(pred,base,input) {
98− var every = function(t) {
66+ this.id = Guid.guid();
99− t *= 1000;
67+ this.value = pred(input.value) ? base : input.value;
100− var clock = Elm.Input(0);
68+ this.kids = [];
101− var time = 0;
69+ this.recv = function(timestep, changed, parentID) {
102− setInterval(function() {
70+ var chng = changed && !pred(input.value);
103− time += t;
71+ if (chng) { this.value = input.value; }
104− Dispatcher.notify(clock.id, time/1000);
72+ send(this, timestep, chng);
106− return clock;
74+ input.kids.push(this);
108− var after = function(t) {
76+ var dropRepeats = function(input) {
109− t *= 1000;
77+ this.id = Guid.guid();
110− var thread = Elm.Input(false);
78+ this.value = input.value;
111− setTimeout(function() { Dispatcher.notify(thread.id, true); }, t);
79+ this.kids = [];
112− return thread;
80+ this.recv = function(timestep, changed, parentID) {
113− };
81+ var chng = changed && !eq(this.value,input.value);
114− var before = function(t) {
82+ if (chng) { this.value = input.value; }
115− t *= 1000;
83+ send(this, timestep, chng);
116− var thread = Elm.Input(true);
117− setTimeout(function() { Dispatcher.notify(thread.id, false); }, t);
120− return {every:every,after:after,before:before};
85+ input.kids.push(this);
123− var Window = function() {
88+ var dropWhen = function(s1) { return function(b) { return function(s2) {
124− var dimensions = Elm.Input(Value.Tuple(window.innerWidth,window.innerHeight));
89+ var pairs = new lift(function(x){return function(y){return [x,y];};},[s1,s2]);
125− dimensions.defaultNumberOfKids = 2;
90+ var dropped = new dropIf(function(p){return p[0];},[true,b],pairs);
126−
91+ return new lift(function(p){return p[1];},[dropped]); }; };
127− var width = Elm.Lift(function(p){return p[1];},[dimensions]);
128− width.defaultNumberOfKids = 0;
129− var height = Elm.Lift(function(p){return p[2];},[dimensions]);
130− height.defaultNumberOfKids = 0;
132− addListener(window, 'resize', function(e) {
133− var w = document.getElementById('widthChecker').offsetWidth;
134− var hasListener = Dispatcher.notify(dimensions.id, Value.Tuple(w, window.innerHeight));
136− this.removeEventListener('resize',arguments.callee,false);
138− return {dimensions:dimensions,width:width,height:height};
141− var Keyboard = { Raw : function() {
142− var keysDown = Elm.Input(["Nil"]);
143− var charPressed = Elm.Input(["Nothing"]);
144− function remove(x,xs) {
145− if (xs[0] === "Nil") return xs;
146− if (xs[1] === x) return xs[2];
147− return ["Cons", xs[1], remove(x,xs[2])];
149− function has(x,xs) {
150− while (xs[0] !== "Nil") {
151− if (xs[1] === x) return true;
156− addListener(document, 'keydown', function(e) {
157− if (has(e.keyCode, keysDown.value)) return;
158− var hasListener = Dispatcher.notify(keysDown.id, ["Cons", e.keyCode, keysDown.value]);
160− this.removeEventListener('keydown',arguments.callee,false);
162− addListener(document, 'keyup', function(e) {
163− var codes = remove(e.keyCode, keysDown.value);
164− var hasListener = Dispatcher.notify(keysDown.id, codes);
166− this.removeEventListener('keyup',arguments.callee,false);
168− addListener(window, 'blur', function(e) {
169− var hasListener = Dispatcher.notify(keysDown.id, ["Nil"]);
171− this.removeEventListener('blur',arguments.callee,false);
173− addListener(document, 'keypress', function(e) {
174− var hasListener = Dispatcher.notify(charPressed.id, ["Just",e.charCode || e.keyCode]);
175− Dispatcher.notify(charPressed.id, ["Nothing"]);
177− this.removeEventListener('keypress',arguments.callee,false);
179− return {keysDown:keysDown,
180− charPressed:charPressed};
184− var HTTP = function() {
94+ var sampleOn = function(s1,s2) {
185−
95+ this.id = Guid.guid();
186− function request(verb) { return function(url) { return function(data) {
96+ this.value = s2.value;
187− return function(headers) {
97+ this.kids = [];
188− return {0 : "Request",
98+ this.count = 0;
189− length : 1,
99+ this.changed = false;
190− verb : Foreign.JavaScript.castStringToJSString(verb),
100+
191− url : Foreign.JavaScript.castStringToJSString(url),
101+ this.recv = function(timestep, changed, parentID) {
192− data : data === null ? null : Foreign.JavaScript.castStringToJSString(data),
102+ if (parentID === s1.id) this.changed = changed;
193− headers : headers }; }; }; };
103+ this.count += 1;
194− }
104+ if (this.count == 2) {
195− function get(url) { return request("GET")(url)(null)(["Nil"]); }
105+ if (this.changed) { this.value = s2.value; }
196− function post(url) { return function(data) {
106+ send(this, timestep, this.changed);
197− return request("POST")(url)(data)(["Nil"]); }; }
107+ this.count = 0;
198−
108+ this.changed = false;
199− function sendReq(responses) { return function(req) {
200− Dispatcher.notify(responses.id,["Waiting"]);
202− if (window.XMLHttpRequest) {
203− request = new XMLHttpRequest();
204− } else if (window.ActiveXObject) {
205− request = new ActiveXObject("Microsoft.XMLHTTP");
207− request.onreadystatechange = function(e) {
208− if (request.readyState === 4) {
211− request.status === 200
212− ? ["Success", toElmString(request.responseText)]
213− : ["Failure", request.status, toElmString(request.statusText)]);
216− request.open(req.verb, req.url, true);
217− List.map(function(pair) {
218− request.setRequestHeader(
219− Foreign.JavaScript.castStringToJSString(pair[1]),
220− Foreign.JavaScript.castStringToJSString(pair[2]));
222− request.send(req.data);
225− }
111+ s1.kids.push(this);
226−
112+ s2.kids.push(this);
227− function send(requests) {
228− var responses = Elm.Input(["Waiting"]);
229− var sender = Elm.Lift(sendReq(responses), [requests]);
230− var combine = Elm.Lift(function(x){return function(y){return x;}},
231− [responses,sender]);
239− sendGet : function(urls){return send(Elm.Lift(get,[urls]));}
242− var Random = function() {
243− var inRange = function(min) { return function(max) {
244− return Elm.Input(Math.floor(Math.random() * (max-min+1)) + min);
247− var randomize = function(min) { return function(max) { return function(signal) {
248− return Elm.Lift(function(x) { return Math.floor(Math.random() * (max-min+1)) + min;},[signal]);
252− return { inRange:inRange, randomize:randomize };
254− var Input = function() {
114+
255− var newTextInput = function(elem, ghostText) {
115+ return {
256− elem.placeholder = Foreign.JavaScript.castStringToJSString(ghostText);
257− var str = Elm.Input(["Nil"]);
258− addListener(elem, 'keyup', function(e) {
259− Dispatcher.notify(str.id, toElmString(elem.value));
262− elem.style.padding = "1px";
263− return Value.Tuple(wrap(elem), str);
265− var newElement = function(name) {
266− var e = document.createElement(name);
267− e.style.padding = "0";
268− e.style.margin = "0";
271− var textArea = function(cols) { return function(rows) {
272− var textarea = newElement('textarea');
273− textarea.rows = rows;
274− textarea.cols = cols;
275− return newTextInput(textarea, "");
278− var textField = function(ghostText) {
279− var field = newElement('input');
280− field.type = 'text';
281− return newTextInput(field, ghostText);
283− var password = function(ghostText) {
284− var field = newElement('input');
285− field.type = 'password';
286− return newTextInput(field, ghostText);
288− var checkbox = function(checked) {
289− var box = newElement('input');
290− box.type = 'checkbox';
291− box.checked = checked;
292− var status = Elm.Input(checked);
293− addListener(box, 'change', function(e) {
294− Dispatcher.notify(status.id, box.checked);
296− return Value.Tuple(wrap(box), status);
298− var dropDown = function(options) {
299− var slct = newElement('select');
301− while (options[0] === "Cons") {
302− var opt = newElement('option');
303− var str = Text.toText(options[1][1]);
305− opt.innerHTML = str;
306− slct.appendChild(opt);
307− opts.push(options[1][2]);
308− options = options[2];
310− var status = Elm.Input(opts[0]);
311− addListener(slct, 'change', function(e) {
312− Dispatcher.notify(status.id, opts[slct.selectedIndex]);
314− return Value.Tuple(wrap(slct), status);
316− var stringDropDown = function(opts) {
317− return dropDown(List.map (function(x) {return Value.Tuple(x,x);}) (opts));
319− var button = function(name) {
320− var b = newElement('input');
322− b.value = Foreign.JavaScript.castStringToJSString(name);
323− var press = Elm.Input(false);
324− addListener(b, 'click', function(e) {
325− Dispatcher.notify(press.id, true);
326− Dispatcher.notify(press.id, false);
328− return Value.Tuple(wrap(b),press);
330− return {textArea:textArea, textField:textField,
331− password:password, checkbox:checkbox,
332− dropDown:dropDown, stringDropDown:stringDropDown,
336− return {addListener:addListener,
344− constant : function(v) { return Elm.Input(v); },
116+ constant : function(v) { return new input(v); },
345− lift : function(f){return function(e){return Elm.Lift(f,[e]);};},
117+ lift : function(f){return function(e){return new lift(f,[e]);};},
346− lift2 : function(f) { return function(e1) { return function(e2) {
118+ lift2 : function(f) { return function(e1) { return function(e2) {
347− return Elm.Lift(f, [e1,e2]); }; }; },
119+ return new lift(f, [e1,e2]); }; }; },
348− lift3 : function(f) { return function(e1) { return function(e2) {
120+ lift3 : function(f) { return function(e1) { return function(e2) {
349− return function(e3){return Elm.Lift(f,[e1,e2,e3]);};};};},
121+ return function(e3){return new lift(f,[e1,e2,e3]);};};};},
350− lift4 : function(f) { return function(e1) { return function(e2) {
122+ lift4 : function(f) { return function(e1) { return function(e2) {
351 return function(e3) { return function(e4) {
123 return function(e3) { return function(e4) {
352− return Elm.Lift(f, [e1,e2,e3,e4]); }; }; }; }; },
124+ return new lift(f, [e1,e2,e3,e4]); }; }; }; }; },
353− foldp : function(f) { return function(b) { return function(e) {
125+ foldp : function(f) { return function(b) { return function(e) {
354− return Elm.Fold(f,b,e); }; }; },
126+ return new fold(f,b,false,e); }; }; },
355− foldp_ : function(f) { return function(b) { return function(e) {
127+ foldp_ : function(f) { return function(b) { return function(e) {
356− return Elm.Fold1(f,b,e); }; }; },
128+ return new fold(f,b,true,e); }; }; },
357− foldp1 : function(f) { return function(e) {
129+ foldp1 : function(f) { return function(e) {
358− return Elm.Fold1(f,function(x){return x;},e); }; },
130+ return new fold(f,function(x){return x;},true,e); }; },
131+ count : function(sig) {
359− count : function(sig){return Elm.Fold(function(_){return function(c){return c+1;};},0,sig)},
132+ var incr = function(_){return function(c){return c+1;};};
360− keepIf : Elm.keepIf,
133+ return new fold(incr,0,false,sig) },
361− dropIf : Elm.dropIf,
134+ keepIf : function(pred) { return function(base) { return function(sig) {
362− keepWhen : Elm.keepWhen,
135+ return new dropIf(function(x) { return !pred(x)},base,sig); }; }; },
136+ dropIf : function(pred) { return function(base) { return function(sig) {
137+ return new dropIf(pred,base,sig); }; }; },
138+ keepWhen : function(s) { return dropWhen(new lift(function(b){return !b;},[s])); },
363− dropWhen : Elm.dropWhen,
139+ dropWhen : dropWhen,
364− dropRepeats : Elm.dropRepeats,
140+ dropRepeats : function(s) { return new dropRepeats(s);},
365− sampleOn : Elm.sampleOn
141+ sampleOn : function(s1){return function(s2){return new sampleOn(s1,s2);};}