on d178521 help sign in
elk/core-js/runtime/Signal.js
367 lines 12 kB history raw
2var Signal = function() {
3 function wrap(elem) {
4 var p = Value.getSize(elem);
5 return ["Element", Guid.guid(), ["EHtml",elem], p[0], p[1], 1, Nothing, Nothing];
6 }
7 function toElmString(str) {
8 var out = ["Nil"];
9 for (var i = str.length; i--; ) {
10 out = ["Cons", str[i], out];
11 }
12 return out;
13 }
14 var addListener = function() {
15 if(document.addEventListener) {
16 return function(element, event, handler) {
17 element.addEventListener(event, handler, false);
18 };
19 }
20 else {
21 return function(element, event, handler) {
22 element.attachEvent('on' + event, handler);
23 };
24 }
25 }();
27 var Mouse = function() {
28 var position = Elm.Input(Value.Tuple(0,0));
29 position.defaultNumberOfKids = 2;
31 var x = Elm.Lift(function(p){return p[1];},[position]);
32 x.defaultNumberOfKids = 0;
33 var y = Elm.Lift(function(p){return p[2];},[position]);
34 y.defaultNumberOfKids = 0;
36 var isDown = Elm.Input(false);
37 var isClicked = Elm.Input(false);
38 var clicks = Elm.Input(Value.Tuple());
40 function getXY(e) {
41 var posx = 0;
42 var posy = 0;
43 if (!e) var e = window.event;
44 if (e.pageX || e.pageY) {
45 posx = e.pageX;
46 posy = e.pageY;
47 } else if (e.clientX || e.clientY) {
48 posx = e.clientX + document.body.scrollLeft +
49 document.documentElement.scrollLeft;
50 posy = e.clientY + document.body.scrollTop +
51 document.documentElement.scrollTop;
52 }
53 return Value.Tuple(posx, posy);
54 }
56 addListener(document, 'click', function(e) {
57 var hasListener1 = Dispatcher.notify(isClicked.id, true);
58 var hasListener2 = Dispatcher.notify(clicks.id, Value.Tuple());
59 Dispatcher.notify(isClicked.id, false);
60 if (!hasListener1 && !hasListener2)
61 this.removeEventListener('click',arguments.callee,false);
62 });
63 addListener(document, 'mousedown', function(e) {
64 var hasListener = Dispatcher.notify(isDown.id, true);
65 if (!hasListener)
66 this.removeEventListener('mousedown',arguments.callee,false);
67 });
68 addListener(document, 'mouseup', function(e) {
69 var hasListener = Dispatcher.notify(isDown.id, false);
70 if (!hasListener)
71 this.removeEventListener('mouseup',arguments.callee,false);
72 });
73 addListener(document, 'mousemove', function(e) {
74 var hasListener = Dispatcher.notify(position.id, getXY(e));
75 if (!hasListener)
76 this.removeEventListener('mousemove',arguments.callee,false);
77 });
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);
84 });
85 return Value.Tuple(wrap(node), click);
86 };
87 return {position: position,
88 x:x,
89 y:y,
90 isClicked: isClicked,
91 isDown: isDown,
92 clicks: clicks,
93 isClickedOn: clickedOn
94 };
95 }();
97 var Time = function() {
98 var every = function(t) {
99 t *= 1000;
100 var clock = Elm.Input(0);
101 var time = 0;
102 setInterval(function() {
103 time += t;
104 Dispatcher.notify(clock.id, time/1000);
105 }, t);
106 return clock;
107 };
108 var after = function(t) {
109 t *= 1000;
110 var thread = Elm.Input(false);
111 setTimeout(function() { Dispatcher.notify(thread.id, true); }, t);
112 return thread;
113 };
114 var before = function(t) {
115 t *= 1000;
116 var thread = Elm.Input(true);
117 setTimeout(function() { Dispatcher.notify(thread.id, false); }, t);
118 return thread;
119 };
120 return {every:every,after:after,before:before};
121 }();
123 var Window = function() {
124 var dimensions = Elm.Input(Value.Tuple(window.innerWidth,window.innerHeight));
125 dimensions.defaultNumberOfKids = 2;
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));
135 if (!hasListener)
136 this.removeEventListener('resize',arguments.callee,false);
137 });
138 return {dimensions:dimensions,width:width,height:height};
139 }();
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])];
148 }
149 function has(x,xs) {
150 while (xs[0] !== "Nil") {
151 if (xs[1] === x) return true;
152 xs = xs[2];
153 }
154 return false;
155 }
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]);
159 if (!hasListener)
160 this.removeEventListener('keydown',arguments.callee,false);
161 });
162 addListener(document, 'keyup', function(e) {
163 var codes = remove(e.keyCode, keysDown.value);
164 var hasListener = Dispatcher.notify(keysDown.id, codes);
165 if (!hasListener)
166 this.removeEventListener('keyup',arguments.callee,false);
167 });
168 addListener(window, 'blur', function(e) {
169 var hasListener = Dispatcher.notify(keysDown.id, ["Nil"]);
170 if (!hasListener)
171 this.removeEventListener('blur',arguments.callee,false);
172 });
173 addListener(document, 'keypress', function(e) {
174 var hasListener = Dispatcher.notify(charPressed.id, ["Just",e.charCode || e.keyCode]);
175 Dispatcher.notify(charPressed.id, ["Nothing"]);
176 if (!hasListener)
177 this.removeEventListener('keypress',arguments.callee,false);
178 });
179 return {keysDown:keysDown,
180 charPressed:charPressed};
181 }()
182 };
184 var HTTP = function() {
186 function request(verb) { return function(url) { return function(data) {
187 return function(headers) {
188 return {0 : "Request",
189 length : 1,
190 verb : Foreign.JavaScript.castStringToJSString(verb),
191 url : Foreign.JavaScript.castStringToJSString(url),
192 data : data === null ? null : Foreign.JavaScript.castStringToJSString(data),
193 headers : headers }; }; }; };
194 }
195 function get(url) { return request("GET")(url)(null)(["Nil"]); }
196 function post(url) { return function(data) {
197 return request("POST")(url)(data)(["Nil"]); }; }
199 function sendReq(responses) { return function(req) {
200 Dispatcher.notify(responses.id,["Waiting"]);
201 var request = null;
202 if (window.XMLHttpRequest) {
203 request = new XMLHttpRequest();
204 } else if (window.ActiveXObject) {
205 request = new ActiveXObject("Microsoft.XMLHTTP");
206 }
207 request.onreadystatechange = function(e) {
208 if (request.readyState === 4) {
209 Dispatcher.notify(
210 responses.id,
211 request.status === 200
212 ? ["Success", toElmString(request.responseText)]
213 : ["Failure", request.status, toElmString(request.statusText)]);
214 }
215 };
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]));
221 })(req.headers);
222 request.send(req.data);
223 return null;
224 };
225 }
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]);
232 return combine;
233 }
235 return {get : get,
236 post : post,
237 request : request,
238 send : send,
239 sendGet : function(urls){return send(Elm.Lift(get,[urls]));}
240 };
241 }();
242 var Random = function() {
243 var inRange = function(min) { return function(max) {
244 return Elm.Input(Math.floor(Math.random() * (max-min+1)) + min);
245 };
246 };
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]);
249 };
250 };
251 };
252 return { inRange:inRange, randomize:randomize };
253 }();
254 var Input = function() {
255 var newTextInput = function(elem, ghostText) {
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));
260 elem.focus();
261 });
262 elem.style.padding = "1px";
263 return Value.Tuple(wrap(elem), str);
264 };
265 var newElement = function(name) {
266 var e = document.createElement(name);
267 e.style.padding = "0";
268 e.style.margin = "0";
269 return e;
270 };
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, "");
276 };
277 };
278 var textField = function(ghostText) {
279 var field = newElement('input');
280 field.type = 'text';
281 return newTextInput(field, ghostText);
282 };
283 var password = function(ghostText) {
284 var field = newElement('input');
285 field.type = 'password';
286 return newTextInput(field, ghostText);
287 };
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);
295 });
296 return Value.Tuple(wrap(box), status);
297 };
298 var dropDown = function(options) {
299 var slct = newElement('select');
300 var opts = [];
301 while (options[0] === "Cons") {
302 var opt = newElement('option');
303 var str = Text.toText(options[1][1]);
304 opt.value = str;
305 opt.innerHTML = str;
306 slct.appendChild(opt);
307 opts.push(options[1][2]);
308 options = options[2];
309 }
310 var status = Elm.Input(opts[0]);
311 addListener(slct, 'change', function(e) {
312 Dispatcher.notify(status.id, opts[slct.selectedIndex]);
313 });
314 return Value.Tuple(wrap(slct), status);
315 };
316 var stringDropDown = function(opts) {
317 return dropDown(List.map (function(x) {return Value.Tuple(x,x);}) (opts));
318 };
319 var button = function(name) {
320 var b = newElement('input');
321 b.type = "button";
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);
327 });
328 return Value.Tuple(wrap(b),press);
329 };
330 return {textArea:textArea, textField:textField,
331 password:password, checkbox:checkbox,
332 dropDown:dropDown, stringDropDown:stringDropDown,
333 button:button};
334 }();
336 return {addListener:addListener,
337 Mouse:Mouse,
338 Keyboard:Keyboard,
339 Time:Time,
340 Window:Window,
341 HTTP:HTTP,
342 Random:Random,
343 Input:Input,
344 constant : function(v) { return Elm.Input(v); },
345 lift : function(f){return function(e){return Elm.Lift(f,[e]);};},
346 lift2 : function(f) { return function(e1) { return function(e2) {
347 return Elm.Lift(f, [e1,e2]); }; }; },
348 lift3 : function(f) { return function(e1) { return function(e2) {
349 return function(e3){return Elm.Lift(f,[e1,e2,e3]);};};};},
350 lift4 : function(f) { return function(e1) { return function(e2) {
351 return function(e3) { return function(e4) {
352 return Elm.Lift(f, [e1,e2,e3,e4]); }; }; }; }; },
353 foldp : function(f) { return function(b) { return function(e) {
354 return Elm.Fold(f,b,e); }; }; },
355 foldp_ : function(f) { return function(b) { return function(e) {
356 return Elm.Fold1(f,b,e); }; }; },
357 foldp1 : function(f) { return function(e) {
358 return Elm.Fold1(f,function(x){return x;},e); }; },
359 count : function(sig){return Elm.Fold(function(_){return function(c){return c+1;};},0,sig)},
360 keepIf : Elm.keepIf,
361 dropIf : Elm.dropIf,
362 keepWhen : Elm.keepWhen,
363 dropWhen : Elm.dropWhen,
364 dropRepeats : Elm.dropRepeats,
365 sampleOn : Elm.sampleOn
366 };
367}();