d?(b=a,l=i,h=0):1<=d&&2>d?(b=i,l=a,h=0):2<=d&&3>d?(b=0,l=a,h=i):3<=d&&4>d?(b=0,l=i,h=a):4<=d&&5>d?(b=i,l=0,h=a):5<=d&&6>d&&(b=a,l=0,h=i);e=e.value-a;return["Color",Math.round(255*(b+e)),Math.round(255*(l+e)),Math.round(255*(h+e)),1]}return{rgba:function(e){return function(a){return function(d){return function(i){return["Color",e,a,d,i]}}}},rgb:function(e){return function(a){return function(d){return["Color",e,
-a,d,1]}}},hsva:function(j){return function(a){return function(d){return function(i){var b=e({hue:j,saturation:a,value:d});b[4]=i;return b}}}},hsv:function(j){return function(a){return function(d){return e({hue:j,saturation:a,value:d})}}},red:["Color",255,0,0,1],green:["Color",0,255,0,1],blue:["Color",0,0,255,1],yellow:["Color",255,255,0,1],cyan:["Color",0,255,255,1],magenta:["Color",255,0,255,1],black:["Color",0,0,0,1],white:["Color",255,255,255,1],gray:["Color",128,128,128,1],grey:["Color",128,128,
-128,1],complement:function(j){var a;a=j[1]/255;var d=j[2]/255,j=j[3]/255,i=Math.max(a,d,j),b=Math.min(a,d,j),b=i-b,l=0;0===b?l=0:i===a?l=(d-j)/b%6:i===d?l=(j-a)/b+2:i===j&&(l=(a-d)/b+4);a={value:i,hue:60*l,saturation:0===i?0:b/i};a.hue=(a.hue+180)%360;return e(a)},extract:function(e){return 1===e[4]?"rgb("+e[1]+","+e[2]+","+e[3]+")":"rgba("+e[1]+","+e[2]+","+e[3]+","+e[4]+")"}}}();
-var Collage=function(){function e(a,b){var c=b.length-1;if(!(0>=c))for(a.moveTo(b[c][1],b[c][2]);c--;)a.lineTo(b[c][1],b[c][2])}function j(a,b,c,g){0===a.length&&(a=[8,4]);var d=g.length-1;if(!(0>=d)){var m=g[d][1],h=g[d][2],e=0,i=0,j=0,l=0,p=0,s=0,v=a.length,z=!0,w=a[0];for(b.moveTo(m,h);d--;){e=g[d][1];i=g[d][2];j=e-m;l=i-h;for(p=Math.sqrt(j*j+l*l);w<=p;)m+=j*w/p,h+=l*w/p,b[z?"lineTo":"moveTo"](m,h),j=e-m,l=i-h,p=Math.sqrt(j*j+l*l),z=!z,s=(s+1)%v,w=a[s];0b.length){var d=b[3][1],e=b[3][2],h=0,i=b[2];switch(b[4][0]){case "FShape":for(var j=b[4][3][1],q=j.length;--q;)var t=j[q],h=Math.max(h,t[1]*t[1]+t[2]*t[2]);h*=i*i;break;case "FImage":j=i*b[4][1]/2;i=i*b[4][2]/2;h=j*j+i*i;break;case "FElement":j=i*b[4][1][3]/2,i=i*b[4][1][4]/2,h=j*j+i*i}b.push(function(a,b){var c=a-d,f=b-e;return c*c+f*f'+b+""+a+">"}},a=function(a,b){return function(g){return""+g+""}},d=function(b){b=Elm.JavaScript.castStringToJSString(b);return a("font-family",b)},i=j("h1"),b=a("font-style","italic"),j=j("b"),l=a("text-decoration","underline"),h=a("text-decoration","overline"),k=a("text-decoration","line-through");return{fromString:e,toText:e,header:i,
-height:function(b){return a("font-size",b+"em")},italic:b,bold:j,underline:l,overline:h,strikeThrough:k,monospace:d("monospace"),typeface:d,color:function(b){return a("color",Elm.Color.extract(b))},link:function(a){return function(b){return""+b+""}}}}();
-var Render=function(){function e(a){a=document.createElement(a);a.style.padding="0";a.style.margin="0";return a}function j(a){return a}function a(a){a.style.styleFloat="left";a.style.cssFloat="left";return a}function d(a){a.style.position="absolute";return a}function i(a,b,g){for(var d=e("div"),h=g.length;h--;){var i=a(b(g[h]));d.appendChild(i)}return d}function b(a){switch(a[0]){case "Absolute":return a[1]+"px";case "Relative":return 100*a[1]+"%"}}function l(a,c){c.style.position="absolute";c.style.margin=
-"auto";switch(a[0]){case "Position":"Far"!==a[1][0]&&(c.style.left=0);"Near"!==a[1][0]&&(c.style.right=0);"Far"!==a[2][0]&&(c.style.top=0);"Near"!==a[2][0]&&(c.style.bottom=0);break;case "PositionAt":c.style.top=b(a[2]);c.style.left=b(a[1]);var g="translate("+~~(-c.style.width.slice(0,-2)/2)+"px,"+~~(-c.style.height.slice(0,-2)/2)+"px)";c.style.transform=g;c.style.msTransform=g;c.style.MozTransform=g;c.style.webkitTransform=g;c.style.OTransform=g;break;default:g=a[0].slice(-2),c.style["T"===g[0]?
-"top":"bottom"]=b(a[2]),c.style["L"===g[1]?"left":"right"]=b(a[1])}}function h(b){var c={};switch(b[2][0]){case "EText":var c=b[2][1],g=b[2][2],r=e("div");r.innerHTML=g;r.style.textAlign=c;c=r;break;case "EImage":c=b[2][1];g=e("img");g.src=c;g.name=c;g.style.display="block";c=g;break;case "EVideo":r=b[2][1];c=e("video");c.controls="controls";g=e("source");g.src=r;r=r.split(".");g.type="video/"+r[r.length-1];c.appendChild(g);c.style.display="block";break;case "EFittedImage":var m=b[3],n=b[4],c=b[2][1],
-g=e("div");g.style.width=m+"px";g.style.height=n+"px";g.style.position="relative";g.style.overflow="hidden";var k=e("img");k.onload=function(){k.style.position="absolute";k.style.margin="auto";var a=m,b=n;m/n>this.width/this.height?b=Math.round(this.height*m/this.width):a=Math.round(this.width*n/this.height);k.style.width=a+"px";k.style.height=b+"px";k.style.left=(m-a)/2+"px";k.style.top=(n-b)/2+"px"};k.src=c;k.name=c;g.appendChild(k);c=g;break;case "EFlow":a:{c=b[2][2];switch(b[2][1][0]){case "DDown":c=
-c.slice(0).reverse();case "DUp":c=i(j,h,c);break a;case "DRight":c=c.slice(0).reverse();case "DLeft":c=i(a,h,c);break a;case "DOut":c=c.slice(0).reverse();case "DIn":c=i(d,h,c);break a}c=void 0}break;case "ECollage":c=Collage.collage(b[2][1],b[2][2],b[2][3]);break;case "EEmpty":c=e("div");break;case "EContainer":g=b[2][1];c=h(b[2][2]);l(g,c);g=e("div");g.style.position="relative";g.style.overflow="hidden";g.appendChild(c);c=g;break;case "EHtml":c=b[2][1];"button"!==c.type&&(g=Value.getExcess(c),b[3]-=
-g[0],b[4]-=g[1]);break;case "EExternalHtml":c=e("div"),c.appendChild(b[2][1])}c.id=b[1];c.style.width=~~b[3]+"px";c.style.height=~~b[4]+"px";1!==b[5]&&(c.style.opacity=b[5]);"Just"===b[6][0]&&(c.style.backgroundColor=Elm.Color.extract(b[6][1]));return"Just"===b[7][0]?(g=e("a"),g.href=b[7][1],g.appendChild(c),g):c}function k(b,c,g){"A"===b.tagName&&(b=b.firstChild);if(c[1]!==g[1]){if(c[2][0]!==g[2][0])return b.parentNode.replaceChild(h(g),b);var e=g[2],i=c[2];switch(e[0]){case "EText":e[1]!==i[1]&&
-(b.style.textAlign=e[1]);e[2]!==i[2]&&(b.innerHTML=e[2]);break;case "EImage":e[1]!==i[1]&&(b.src=e[1]);break;case "EVideo":case "EFittedImage":if(!Value.eq(e,i)||g[3]!==c[3]||g[4]!==c[4])return b.parentNode.replaceChild(h(g),b);break;case "ECollage":if(e[1]!==i[1]||e[2]!==i[2]||e[3].length!==i[3].length)return b.parentNode.replaceChild(h(g),b);Collage.updateCollage(b,i[3],e[3]);break;case "EFlow":if(e[1]!==i[1])return b.parentNode.replaceChild(h(g),b);var n=e[2],u=b.childNodes;if(n.length!==u.length)return b.parentNode.replaceChild(h(g),
-b);var i=i[2],x=function(a){return a};switch(e[1][0]){case "DDown":case "DUp":x=j;break;case "DRight":case "DLeft":x=a;break;case "DOut":case "DIn":x=d}for(e=u.length;e--;)k(u[e],i[e],n[e]),x(u[e]);break;case "EContainer":k(b.childNodes[0],i[2],e[2]);l(e[1],b.childNodes[0]);break;case "EHtml":g[1]!==c[1]&&(n=h(g),b.parentNode.replaceChild(n,b),b=n);"button"!==n.type&&(e=Value.getExcess(b),g[3]-=e[0],g[4]-=e[1]);break;case "EExternalHtml":g[1]!==c[1]&&b.parentNode.replaceChild(h(g),b)}g[3]!==c[3]&&
-(b.style.width=~~g[3]+"px");g[4]!==c[4]&&(b.style.height=~~g[4]+"px");g[5]!==c[5]&&(b.style.opacity=g[5]);2===g[6].length&&(e=Elm.Color.extract(g[6][1]),e!==b.style.backgroundColor&&(b.style.backgroundColor=e));if(2===g[7].length&&(1===c[7].length||g[7][1]!==c[7][1]))b.parentNode.href=g[7][1];g[1]=c[1]}}return{render:h,update:k,addTo:function(a,b){a.appendChild(b)},newElement:e,flowWith:i,goIn:d}}();
-Elm.Signal=function(){function e(a){this.id=Guid.guid();this.value=a;this.kids=[];this.defaultNumberOfKids=0;this.recv=function(a,b,c){if(b=b===this.id)this.value=c;k(this,a,b);return b};Dispatcher.inputs.push(this)}function j(a,b){this.id=Guid.guid();this.value=null;this.kids=[];this.count=0;this.changed=!1;b.reverse();this.recalc=function(){for(var d=a,f=b.length;f--;)d=d(b[f].value);this.value=d};this.recalc();this.recv=function(a,c){this.count+=1;c&&(this.changed=!0);this.count==b.length&&(this.changed&&
-this.recalc(),k(this,a,this.changed),this.changed=!1,this.count=0)};for(var d=b.length;d--;)b[d].kids.push(this)}function a(a,b,d,f){this.id=Guid.guid();this.value=d?b(f.value):b;this.kids=[];this.recv=function(b,d){d&&(this.value=a(f.value)(this.value));k(this,b,d)};f.kids.push(this)}function d(a,b,d){this.id=Guid.guid();this.value=a(d.value)?b:d.value;this.kids=[];this.recv=function(b,g){var f=g&&!a(d.value);f&&(this.value=d.value);k(this,b,f)};d.kids.push(this)}function i(a){this.id=Guid.guid();
-this.value=a.value;this.kids=[];this.recv=function(b,d){var f=d&&!Value.eq(this.value,a.value);f&&(this.value=a.value);k(this,b,f)};a.kids.push(this)}function b(a,b){this.id=Guid.guid();var d=(new window.Date).getTime();this.value=a?Value.Tuple(d,b.value):d;this.kids=[];this.recv=function(d,f){f&&(this.value=a?Value.Tuple(d,b.value):d);k(this,d,f)};b.kids.push(this)}function l(a,b){this.id=Guid.guid();this.value=b.value;this.kids=[];this.count=0;this.changed=!1;this.recv=function(d,f,e){e===a.id&&
-(this.changed=f);this.count+=1;2==this.count&&(this.changed&&(this.value=b.value),k(this,d,this.changed),this.count=0,this.changed=!1)};a.kids.push(this);b.kids.push(this)}function h(a,b){this.id=Guid.guid();this.value=a.value;this.kids=[];this.next=null;this.count=0;this.changed=!1;this.recv=function(d,f,e){this.count+=1;f&&(this.changed=!0,e==b.id&&null===this.next&&(this.next=b.value),e==a.id&&(this.next=a.value));2==this.count&&(this.changed&&(this.value=this.next,this.next=null),k(this,d,this.changed),
-this.changed=!1,this.count=0)};a.kids.push(this);b.kids.push(this)}var k=function(a,b,d){for(var f=a.kids,e=f.length;e--;)f[e].recv(b,d,a.id)},f=function(a){return function(b){return function(f){f=new j(function(a){return function(b){return[a,b]}},[a,f]);f=new d(function(a){return a[0]},[!0,b],f);return new j(function(a){return a[1]},[f])}}};return{constant:function(a){return new e(a)},lift:function(a){return function(b){return new j(a,[b])}},lift2:function(a){return function(b){return function(d){return new j(a,
-[b,d])}}},lift3:function(a){return function(b){return function(d){return function(f){return new j(a,[b,d,f])}}}},lift4:function(a){return function(b){return function(d){return function(f){return function(e){return new j(a,[b,d,f,e])}}}}},lift5:function(a){return function(b){return function(d){return function(f){return function(e){return function(h){return new j(a,[b,d,f,e,h])}}}}}},lift6:function(a){return function(b){return function(d){return function(f){return function(e){return function(h){return function(i){return new j(a,
-[b,d,f,e,h,i])}}}}}}},lift7:function(a){return function(b){return function(d){return function(f){return function(e){return function(h){return function(i){return function(k){return new j(a,[b,d,f,e,h,i,k])}}}}}}}},lift8:function(a){return function(b){return function(d){return function(f){return function(e){return function(h){return function(i){return function(k){return function(l){return new j(a,[b,d,f,e,h,i,k,l])}}}}}}}}},foldp:function(b){return function(d){return function(f){return new a(b,d,!1,
-f)}}},foldp_:function(b){return function(d){return function(f){return new a(b,d,!0,f)}}},foldp1:function(b){return function(d){return new a(b,function(a){return a},!0,d)}},delay:function(a){return function(b){var d=new e(b.value),f=!0,b=new l(d,new j(function(a){return function(){return a}},[d,new j(function(b){f||setTimeout(function(){Dispatcher.notify(d.id,b)},a)},[b])])),f=!1;return b}},merge:function(a){return function(b){return new h(a,b)}},merges:function(a){return Elm.List.foldl1(function(a){return function(b){return new h(a,
-b)}})(a)},average:function(a){return function(b){for(var d=Array(a),f=a;f--;)d[f]=0;var f=0,e=!1,h=0;return new j(function(b){h+=b-d[f];d[f]=b;b=h/Math.max(1,e?a:f);++f==a&&(e=!0,f=0);return b},[b])}},count:function(b){return new a(function(){return function(a){return a+1}},0,!1,b)},countIf:function(b){return function(d){return new a(function(a){return function(d){return b(a)?d+1:d}},0,!1,d)}},keepIf:function(a){return function(b){return function(f){return new d(function(b){return!a(b)},b,f)}}},dropIf:function(a){return function(b){return function(f){return new d(a,
-b,f)}}},keepWhen:function(a){return f(new j(function(a){return!a},[a]))},dropWhen:f,dropRepeats:function(a){return new i(a)},sampleOn:function(a){return function(b){return new l(a,b)}},timestamp:function(a){return new b(!0,a)},timeOf:function(a){return new b(!1,a)}}}();
-var Dispatcher=function(){function e(a){if(!a.hasOwnProperty("defaultNumberOfKids"))return!0;var b=a.kids.length;if(0==b)return!1;if(b>a.defaultNumberOfKids)return!0;for(var d=!1;b--;)d=d||e(a.kids[b]);return d}var j=null,a=[],d=null;return{initialize:function(){j=Elm.main();j.hasOwnProperty("recv")||(j=Elm.Signal.constant(j));d=j.value;for(var i=[],b=a.length;b--;)e(a[b])&&i.push(a[b]);a=i;document.getElementById("content").appendChild(Render.render(d));i=document.getElementById("widthChecker").offsetWidth;
-i!==window.innerWidth&&Dispatcher.notify(Elm.Window.dimensions.id,Value.Tuple(i,window.innerHeight));j=Elm.Signal.lift(function(a){var b=document.getElementById("content");Render.update(b.firstChild,d,a);return d=a})(j)},notify:function(d,b){for(var e=(new window.Date).getTime(),h=!1,j=a.length;j--;)h=a[j].recv(e,d,b)||h;return h},inputs:a}}();
-Elm.HTTP=function(){function e(a){return function(d){return function(f){return function(c){return{"0":"Request",length:1,verb:b.castStringToJSString(a),url:b.castStringToJSString(d),data:null===f?null:b.castStringToJSString(f),headers:c}}}}}function j(a){return e("GET")(a)(null)(["Nil"])}function a(a,e){return function(f){if(""!==f.url){var c={value:["Waiting"]};a.push(c);var g=null;window.ActiveXObject&&(g=new ActiveXObject("Microsoft.XMLHTTP"));window.XMLHttpRequest&&(g=new XMLHttpRequest);g.onreadystatechange=
-function(){4===g.readyState&&(c.value=200===g.status?["Success",l(g.responseText)]:["Failure",g.status,l(g.statusText)],setTimeout(function(){d(a,e)},0))};g.open(f.verb,f.url,!0);Elm.List.map(function(a){g.setRequestHeader(b.castStringToJSString(a[1]),b.castStringToJSString(a[2]))})(f.headers);g.send(f.data)}}}function d(a,b){0=b))continue;return["Nothing"]}return["Just",parseFloat(a)]},sqrt:Math.sqrt,abs:Math.abs,pi:Math.PI,e:Math.E,sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,atan2:function(a){return function(d){return Math.atan2(a,d)}},mod:j,min:function(a){return function(d){return Math.min(a,
-d)}},max:function(a){return function(d){return Math.max(a,d)}},flip:function(a){return function(d){return function(e){return a(e)(d)}}},clamp:function(a){return function(d){return function(e){return Math.min(d,Math.max(a,e))}}},curry:function(a){return function(d){return function(e){return a(["Tuple2",d,e])}}},uncurry:function(a){return function(d){if("Tuple2"!==d[0])throw"Function was uncurry'd but was not given a pair.";return a(d[1])(d[2])}},logBase:function(a){return function(d){return Math.log(d)/
-Math.log(a)}},Just:Elm.Maybe.Just,Nothing:Elm.Maybe.Nothing,maybe:Elm.Maybe.maybe,map:Elm.List.map,zip:Elm.List.zip,zipWith:Elm.List.zipWith,filter:Elm.List.filter,head:Elm.List.head,tail:Elm.List.tail,last:Elm.List.last,length:Elm.List.length,reverse:Elm.List.reverse,foldr:Elm.List.foldr,foldr1:Elm.List.foldr1,foldl:Elm.List.foldl,foldl1:Elm.List.foldl1,and:Elm.List.and,or:Elm.List.or,all:Elm.List.all,any:Elm.List.any,sum:Elm.List.sum,product:Elm.List.product,concat:Elm.List.concat,concatMap:Elm.List.concatMap,
-maximum:Elm.List.maximum,minimum:Elm.List.minimum,scanl:Elm.List.scanl,scanl1:Elm.List.scanl1,take:Elm.List.take,drop:Elm.List.drop,zip:Elm.List.zip,unzip:Elm.List.unzip,lift:Elm.Signal.lift,lift2:Elm.Signal.lift2,lift3:Elm.Signal.lift3,lift4:Elm.Signal.lift4,lift5:Elm.Signal.lift5,lift6:Elm.Signal.lift6,lift7:Elm.Signal.lift7,lift8:Elm.Signal.lift8,foldp:Elm.Signal.foldp,foldp1:Elm.Signal.foldp1,foldp_:Elm.Signal.foldp_,constant:Elm.Signal.constant,merge:Elm.Signal.merge,count:Elm.Signal.count,countIf:Elm.Signal.countIf,
-average:Elm.Signal.average,keepIf:Elm.Signal.keepIf,dropIf:Elm.Signal.dropIf,keepWhen:Elm.Signal.keepWhen,dropWhen:Elm.Signal.dropWhen,dropRepeats:Elm.Signal.dropRepeats,sampleOn:Elm.Signal.sampleOn,timestamp:Elm.Signal.timestamp,timeOf:Elm.Signal.timeOf}}();(function(){var e=function(e){for(var a in e)Elm.Prelude[a]=e[a]};e(Elm.Color);e(Elm.Text);e(Elm.Graphics);e(Elm.Time);show=Value.show})();
-Elm.Dict=function(){function e(a){return function(b){return function(c){return function(d){return function(e){return["RBNode",a,b,c,d,e]}}}}}function j(a){a:{switch(a[0]){case "RBEmpty":throw"(min RBEmpty) is not defined";case "RBNode":switch(a[4][0]){case "RBEmpty":a=["Tuple2",a[2],a[3]];break a}a=j(a[4]);break a}throw"Non-exhaustive pattern match in case";}return a}function a(b){return function(c){var d;a:{switch(c[0]){case "RBEmpty":d=v;break a;case "RBNode":d=function(){switch(p(b)(c[2])[0]){case "EQ":return z(c[3]);
-case "GT":return a(b)(c[5]);case "LT":return a(b)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";}return d}}function d(a){return function(b){return function(c){var e;a:{switch(c[0]){case "RBEmpty":e=a;break a;case "RBNode":e=function(){switch(p(b)(c[2])[0]){case "EQ":return c[3];case "GT":return d(a)(b)(c[5]);case "LT":return d(a)(b)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";
-}return e}}}function i(b){return function(c){return E(a(b)(c))}}function b(a){a:{switch(a[0]){case "RBNode":switch(a[5][0]){case "RBNode":a=e(a[1])(a[5][2])(a[5][3])(e(A)(a[2])(a[3])(a[4])(a[5][4]))(a[5][5]);break a}}throw"rotateLeft of a node without enough children";}return a}function l(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":a=e(a[1])(a[4][2])(a[4][3])(a[4][4])(e(A)(a[2])(a[3])(a[4][5])(a[5]));break a}}throw"rotateRight of a node without enough children";}return a}function h(a){a:{switch(a[0]){case "Black":a=
-A;break a;case "Red":a=D;break a}throw"Non-exhaustive pattern match in case";}return a}function k(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[5][0]){case "RBNode":a=e(h(a[1]))(a[2])(a[3])(e(h(a[4][1]))(a[4][2])(a[4][3])(a[4][4])(a[4][5]))(e(h(a[5][1]))(a[5][2])(a[5][3])(a[5][4])(a[5][5]));break a}}}throw"color_flip called on a RBEmpty or RBNode with a RBEmpty child";}return a}function f(a){a:switch(a[0]){case "RBNode":switch(a[5][0]){case "RBNode":switch(a[5][1][0]){case "Red":a=
-b(a);break a}}}a:switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":switch(a[4][4][0]){case "RBNode":switch(a[4][4][1][0]){case "Red":a=l(a);break a}}}}}a:switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":switch(a[5][0]){case "RBNode":switch(a[5][1][0]){case "Red":a=k(a);break a}}}}}return a}function c(a){a:switch(a[0]){case "RBNode":switch(a[1][0]){case "Red":a=e(D)(a[2])(a[3])(a[4])(a[5]);break a}}return a}function g(a){return function(b){return function(d){var g=
-function(c){var d;a:{switch(c[0]){case "RBEmpty":d=e(A)(a)(b)(y)(y);break a;case "RBNode":d=function(){switch(p(a)(c[2])[0]){case "EQ":return e(c[1])(c[2])(b)(c[4])(c[5]);case "GT":return e(c[1])(c[2])(c[3])(c[4])(g(c[5]));case "LT":return e(c[1])(c[2])(c[3])(g(c[4]))(c[5])}throw"Non-exhaustive pattern match in case";}();d=f(d);break a}throw"Non-exhaustive pattern match in case";}return d};return c(g(d))}}}function r(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":a=
-!0;break a}}}a=!1}return a}function m(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][4][0]){case "RBNode":switch(a[4][4][1][0]){case "Red":a=!0;break a}}}}a=!1}return a}function n(a){if(w(r(a))&&w(m(a))){a=k(a);a:switch(a[0]){case "RBNode":b:switch(a[5][0]){case "RBNode":switch(a[5][4][0]){case "RBNode":switch(a[5][4][1][0]){case "Red":a=k(b(e(a[1])(a[2])(a[3])(a[4])(l(a[5]))));break b}}}break a}}return a}function u(a){return function(b){var d=function(b){a:{switch(b[0]){case "RBEmpty":b=
-y;break a;case "RBNode":if("LT"===p(a)(b[2])[0])b:{b=n(b);switch(b[0]){case "RBEmpty":throw"delLT on RBEmpty";case "RBNode":b=f(e(b[1])(b[2])(b[3])(d(b[4]))(b[5]));break b}break}else{var g=r(b)?l(b):b,h;b:{switch(g[0]){case "RBNode":switch(g[5][0]){case "RBEmpty":h=C(a,g[2]);break b}}h=!1}if(h)b=g[4];else{g=w;b:{switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":h=!0;break b}}}h=!1}if(g=g(h)){g=w;b:{switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][4][0]){case "RBNode":switch(b[5][4][1][0]){case "Red":h=
-!0;break b}}}}h=!1}g=g(h)}g&&(b=k(b),b=m(b)?k(l(b)):b);b:{switch(b[0]){case "RBNode":g=C(a,b[2]);break b}g=!1}if(g)b:{switch(b[0]){case "RBEmpty":throw"delEQ called on a RBEmpty";case "RBNode":h=j(b[5]);c:{switch(h[0]){case "Tuple2":g=h[1];break c}break}c:{switch(h[0]){case "Tuple2":h=h[2];break c}break}var g=e(b[1])(g)(h)(b[4]),i=function(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBEmpty":a=y;break a}}b:{a=n(a);switch(a[0]){case "RBEmpty":a=y;break b;case "RBNode":a=f(e(a[1])(a[2])(a[3])(i(a[4]))(a[5]));
-break b}throw"Non-exhaustive pattern match in case";}}return a},b=c(i(b[5])),b=f(g(b));break b}break}else b:{switch(b[0]){case "RBEmpty":throw"delGT called on a RBEmpty";case "RBNode":b=f(e(b[1])(b[2])(b[3])(b[4])(d(b[5])));break b}break}}}break a}throw"Non-exhaustive pattern match in case";}return b};return i(a)(b)?c(d(b)):b}}function x(a){return function(b){a:{switch(b[0]){case "RBEmpty":b=y;break a;case "RBNode":b=e(b[1])(b[2])(a(b[3]))(x(a)(b[4]))(x(a)(b[5]));break a}throw"Non-exhaustive pattern match in case";
-}return b}}function q(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=q(a)(a(c[2])(c[3])(q(a)(b)(c[4])))(c[5]);break a}throw"Non-exhaustive pattern match in case";}return c}}}function t(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=t(a)(a(c[2])(c[3])(t(a)(b)(c[5])))(c[4]);break a}throw"Non-exhaustive pattern match in case";}return c}}}var p=Elm.Prelude.compare,s=Elm.Prelude.uncurry,v=Elm.Prelude.Nothing,
-z=Elm.Prelude.Just,w=Elm.Prelude.not,C=Elm.Prelude.eq,E=Elm.Maybe.isJust,A=["Red"],D=["Black"],y=["RBEmpty"],B=y;return{$op:{},empty:B,lookup:a,findWithDefault:d,member:i,insert:g,singleton:function(a){return function(b){return g(a)(b)(y)}},remove:u,map:x,foldl:q,foldr:t,union:function(a){return function(b){return q(g)(b)(a)}},intersect:function(a){return function(b){return q(function(a){return function(c){return function(d){return i(a)(b)?g(a)(c)(d):d}}})(B)(a)}},diff:function(a){return function(b){return q(function(a){return function(){return function(b){return u(a)(b)}}})(a)(b)}},
-keys:function(a){return t(function(a){return function(){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},values:function(a){return t(function(){return function(a){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},toList:function(a){return t(function(a){return function(b){return function(c){return["Cons",["Tuple2",a,b],c]}}})(["Nil"])(a)},fromList:function(a){return Elm.List.foldl(s(g))(B)(a)}}}();
-Elm.Set=function(){var e=Elm.Dict.empty,j=Elm.Dict.remove,a=Elm.Dict.member,d=Elm.Dict.union,i=Elm.Dict.intersect,b=Elm.Dict.diff,l=Elm.Dict.keys,h=Elm.List.foldl(function(a){return function(b){return Elm.Dict.insert(a)(["Tuple0"])(b)}})(e);return{empty:e,singleton:function(a){return Elm.Dict.singleton(a)(["Tuple0"])},insert:function(a){return Elm.Dict.insert(a)(["Tuple0"])},remove:j,member:a,union:d,intersect:i,diff:b,toList:l,fromList:h,foldl:function(a){return Elm.Dict.foldl(function(b){return function(){return function(c){return a(b)(c)}}})},
-foldr:function(a){return Elm.Dict.foldr(function(b){return function(){return function(c){return a(b)(c)}}})},map:function(a){return function(b){b=l(b);return h(Elm.List.map(a)(b))}}}}();
-(function(){try{var e={};for(this.i in Elm)eval("var "+this.i+"=Elm[this.i];");if(Elm.Automaton)throw"Module name collision, 'Automaton' is already defined.";Elm.Automaton=function(){function a(a){return["Automaton",a]}function d(b){return a(function(a){var c=unzip(map(function(b){a:{switch(b[0]){case "Automaton":b=b[1](a);break a}throw"Non-exhaustive pattern match in case";}return b})(b)),e;a:{switch(c[0]){case "Tuple2":e=c[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(c[0]){case "Tuple2":c=
-c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",e,d(c)]})}function i(b){return a(function(a){return["Tuple2",b(a),i(b)]})}function b(c){return function(d){return a(function(a){a=d(a)(c);return["Tuple2",a,b(a)(d)]})}}function j(b){return function(c){return a(function(a){var d=c(a)(b);a:{switch(d[0]){case "Tuple2":a=d[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(d[0]){case "Tuple2":d=d[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",
-a,j(d)(c)]})}}function h(a){return function(b){a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":b=["Tuple2",a[1]-b[1],a[2]-b[2]];break b}break}break a}throw"Non-exhaustive pattern match in case";}return b}}function k(a){return function(b){var c;a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":var d=function(a){return["Tuple2",b[2],["Tuple2",a,b[2]]]};c=function(){switch(b[1][0]){case "DragFrom":var c;a[1]?c=["Tuple2",uncurry(move)(h(a[2])(b[1][1]))(b[2]),["Tuple2",["DragFrom",
-b[1][1]],b[2]]]:(c=uncurry(move)(h(a[2])(b[1][1]))(b[2]),c=["Tuple2",c,["Tuple2",g,c]]);return c;case "Ignore":return d(a[1]?r:g);case "Listen":return d(not(a[1])?g:isWithin(a[2])(b[2])?["DragFrom",a[2]]:r)}throw"Non-exhaustive pattern match in case";}();break b}break}break a}throw"Non-exhaustive pattern match in case";}return c}}try{if(!(Elm.Prelude instanceof Object))throw"module not found";}catch(f){throw"Module 'Prelude' is missing. Compile with --make flag or load missing module in a separate JavaScript file.";
-}var c={};for(this.i in Elm.Prelude)c[this.i]||eval("var "+this.i+" = Elm.Prelude[this.i];");var g=["Listen"],r=["Ignore"];e[">>>"]=function(b){return function(c){var d;a:{switch(b[0]){case "Automaton":d=b[1];break a}throw"Non-exhaustive pattern match in case";}var f;a:{switch(c[0]){case "Automaton":f=c[1];break a}throw"Non-exhaustive pattern match in case";}return a(function(a){var a=d(a),b;a:{switch(a[0]){case "Tuple2":b=a[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(a[0]){case "Tuple2":a=
-a[2];break a}throw"Non-exhaustive pattern match in case";}var c=f(b);a:{switch(c[0]){case "Tuple2":b=c[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(c[0]){case "Tuple2":c=c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",b,e[">>>"](a)(c)]})}};e["<<<"]=function(a){return function(b){return e[">>>"](b)(a)}};e["^>>"]=function(a){return function(b){return e[">>>"](i(a))(b)}};e[">>^"]=function(a){return function(b){return e[">>>"](a)(i(b))}};e["^<<"]=function(a){return function(b){return e[">>>"](b)(i(a))}};
-e["<<^"]=function(a){return function(b){return e[">>>"](i(b))(a)}};c=b(0)(function(){return function(a){return 1+a}});return{$op:{">>>":e[">>>"],"<<<":e["<<<"],"^>>":e["^>>"],">>^":e[">>^"],"^<<":e["^<<"],"<<^":e["<<^"]},run:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=lift(fst)(foldp_(function(a){return function(b){a:{switch(b[0]){case "Tuple2":switch(b[2][0]){case "Automaton":b=b[2][1](a);break a}}throw"Non-exhaustive pattern match in case";}return b}})(a[1])(b));break a}throw"Non-exhaustive pattern match in case";
-}return b}},step:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return b}},combine:d,pure:i,init:b,init_:j,count:c,draggable:function(a){return j(["Tuple2",g,a])(k)}}}();Elm.main=function(){return Elm.Automaton.main}}catch(j){Elm.main=function(){document.body.innerHTML=Elm.Text.monospace('
Your browser may not be supported. Are you using a modern browser?
Runtime Error in Automaton module:
'+
-j+"");throw j;}}})();
\ No newline at end of file
diff --git a/elm/elm-runtime-0.7.1.1.js b/elm/elm-runtime-0.7.1.1.js
deleted file mode 100644
index 8608836..0000000
--- a/elm/elm-runtime-0.7.1.1.js
+++ /dev/null
@@ -1,142 +0,0 @@
-Elm={};var Guid=function(){var d=0;return{guid:function(){return d+=1}}}();
-Elm.JavaScript=function(){function d(b){for(var a=["Nil"],c=b.length;c--;)a=["Cons",b[c],a];return a}function f(b){for(var a=[];"Cons"===b[0];)a.push(b[1]),b=b[2];return a}function b(b){return b.slice(1)}function c(b){return["Tuple"+b.length].concat(b)}return{castJSBoolToBool:function(b){return b},castBoolToJSBool:function(b){return b},castJSNumberToFloat:function(b){return b},castFloatToJSNumber:function(b){return b},castJSNumberToInt:function(b){return~~b},castIntToJSNumber:function(b){return b},
-Experimental:{castJSElementToElement:function(b){return function(a){return function(c){return["Element",Guid.guid(),["EExternalHtml",c],b,a,1,["Nothing"],["Nothing"]]}}},castElementToJSElement:function(b){return Render.render(b)}},castJSArrayToList:d,castListToJSArray:f,castJSStringToString:d,castStringToJSString:function(b){return"string"===typeof b?b:f(b).join("")},castTupleToJSTuple2:b,castTupleToJSTuple3:b,castTupleToJSTuple4:b,castTupleToJSTuple5:b,castJSTupleToTuple2:c,castJSTupleToTuple3:c,
-castJSTupleToTuple4:c,castJSTupleToTuple5:c}}();var JSjson=window.JSON;
-Elm.JSON=function(){function d(a,b){return function(j){return function(l){var g=c.castStringToJSString(j);return l[1].hasOwnProperty(g)&&(l=l[1][g],l[0]===a)?l[1]:b}}}function f(a){return function(b){function j(a){switch(a[0]){case "JsonNull":return null;case "JsonString":return c.castStringToJSString(a[1]);case "JsonObject":var g={};a=a[1][1];for(var e in a)g[e]=j(a[e]);return g;case "JsonArray":g=c.castListToJSArray(a[1]);for(e=g.length;e--;)g[e]=j(g[e]);return g;default:return a[1]}}return JSjson.stringify(j(["JsonObject",
-b]),null,c.castStringToJSString(a))}}function b(a){function b(a){switch(typeof a){case "string":return["JsonString",c.castJSStringToString(a)];case "number":return["JsonNumber",c.castJSNumberToFloat(a)];case "boolean":return["JsonBool",c.castJSBoolToBool(a)];case "object":if(null===a)return["JsonNull"];for(var g in a)a[g]=b(a[g]);return a instanceof Array?["JsonArray",c.castJSArrayToList(a)]:["JsonObject",["JSON",a]]}}a=JSjson.parse(a);for(var j in a)a[j]=b(a[j]);return["JSON",a]}var c=Elm.JavaScript,
-h=["JSON",{}];return{empty:h,singleton:function(a){return function(b){var j={};j[c.castStringToJSString(a)]=b;return["JSON",j]}},insert:function(a){return function(b){return function(j){j=j[1];var l={},g;for(g in j)l[g]=j[g];l[c.castStringToJSString(a)]=b;return["JSON",l]}}},lookup:function(a){return function(b){var j=c.castStringToJSString(a);return b[1].hasOwnProperty(j)?["Just",b[1][j]]:["Nothing"]}},findString:d("JsonString",["Nil"]),findObject:d("JsonObject",h),findArray:d("JsonArray",["Nil"]),
-findWithDefault:function(a){return function(b){return function(j){var l=c.castStringToJSString(b);return j[1].hasOwnProperty(l)?j[1][l]:a}}},remove:function(a){return function(b){b=b[1];var j={},l;for(l in b)j[l]=b[l];delete j[c.castStringToJSString(a)];return["JSON",j]}},toPrettyJSString:f,toJSString:f(""),fromJSString:b,toPrettyString:function(a){return function(b){return c.castJSStringToString(f(a)(b))}},toString:function(a){return c.castJSStringToString(f("")(a))},fromString:function(a){return b(c.castStringToJSString(a))},
-toList:function(a){a=a[1];var b=[],j;for(j in a)b.push(Value.Tuple(c.castJSStringToString(j),a[j]));return c.castJSArrayToList(b)},fromList:function(a){a=c.castListToJSArray(a);for(var b={},j=a.length;j--;)b[c.castStringToJSString(a[j][1])]=a[j][2];return["JSON",b]},JsonString:function(a){return["JsonString",a]},JsonNumber:function(a){return["JsonNumber",a]},JsonBool:function(a){return["JsonBool",a]},JsonNull:["JsonNull"],JsonArray:function(a){return["JsonArray",a]},JsonObject:function(a){return["JsonObject",
-a]}}}();
-var Value=function(){function d(a){if(0==a.length)return a;a=a.replace(/"/g,""").replace(/'/g,"'").replace(//g,">").replace(/\n/g,"
");a=a.split("
");for(var b=a.length;b--;){var c=a,l=b,g;g=a[b];if(0!=g.length){g=g.split("");" "==g[0]&&(g[0]=" ");for(var e=g.length;--e;)" "==g[e][0]&&" "==g[e-1]&&(g[e-1]+=g[e],g[e]="");for(e=g.length;e--;)if(1")}var f=function(a,b){if("object"===typeof a){if(a.hasOwnProperty("_")){for(var c in a)if(a[c]!=b[c])return!1;for(c in b)if(a[c]!=b[c])return!1;return!0}if(a===b)return!0;if(a.length!==b.length)return!1;for(c=a.length;c--;)if(!f(a[c],b[c]))return!1;return!0}return a===b},b=function(a){if("function"===typeof a)return"";if("boolean"===typeof a)return a?"True":"False";if("number"!==typeof a){if("string"===typeof a&&
-2>a.length)return"'"+a+"'";if("object"===typeof a&&a.hasOwnProperty("_")){var c=[],j;for(j in a)if("_"!=j)for(var l=a[j].length;l--;)c.push(j+" = "+b(a[j][l]));return 0===c.length?"{}":"{ "+c.join(", ")+" }"}if(a[0]){if("Tuple"===a[0].substring(0,5)){c=Array(a.length-1);for(l=a.length;--l;)c[l-1]=b(a[l]);return"("+c.join(",")+")"}if("Cons"===a[0]){j="string"===typeof a[1]?'"':"]";var l="string"===typeof a[1]?"":",",g="string"===typeof a[1]?function(a){return a}:b,c=("string"===typeof a[1]?'"':"[")+
-g(a[1]);for(a=a[2];;)if("Cons"===a[0])c+=l+g(a[1]),a=a[2];else return c+j}else{if("Nil"===a[0])return"[]";if("JSON"===a[0])return"(JSON.fromList "+b(Elm.JSON.toList(a))+")";if("RBNode"===a[0]||"RBEmpty"===a[0])return a=Elm.Dict.foldr(function(a){return function(g){return function(b){return["Cons",["Tuple2",a,g],b]}}})(["Nil"])(a),c="Dict","Cons"===a[0]&&"Tuple0"===a[1][2][0]&&(c="Set",a=Elm.List.map(function(a){return a[1]})(a)),"("+c+".fromList "+b(a)+")";c="";for(l=a.length;--l;)c=" "+b(a[l])+c;
-c=a[0]+c;return 1=a)return["Nil"];if("Nil"===b[0])return b;"Cons"!==b[0]&&g("take");var e=["Cons",b[1],["Nil"]],c=e;b=b[2];for(--a;"Cons"===b[0]&&0c?(a=b,m=d,j=0):1<=c&&2>c?(a=d,m=b,j=0):2<=c&&3>c?(a=0,m=b,j=d):3<=c&&4>c?(a=0,m=d,j=b):4<=c&&5>c?(a=d,m=0,j=b):5<=c&&6>c&&(a=b,m=0,j=d);f=f.value-b;return["Color",Math.round(255*(a+f)),Math.round(255*(m+f)),Math.round(255*(j+f)),1]}return{rgba:function(f){return function(b){return function(c){return function(d){return["Color",f,b,c,d]}}}},rgb:function(f){return function(b){return function(c){return["Color",f,
-b,c,1]}}},hsva:function(f){return function(b){return function(c){return function(h){var a=d({hue:f,saturation:b,value:c});a[4]=h;return a}}}},hsv:function(f){return function(b){return function(c){return d({hue:f,saturation:b,value:c})}}},red:["Color",255,0,0,1],green:["Color",0,255,0,1],blue:["Color",0,0,255,1],yellow:["Color",255,255,0,1],cyan:["Color",0,255,255,1],magenta:["Color",255,0,255,1],black:["Color",0,0,0,1],white:["Color",255,255,255,1],gray:["Color",128,128,128,1],grey:["Color",128,128,
-128,1],complement:function(f){var b;b=f[1]/255;var c=f[2]/255;f=f[3]/255;var h=Math.max(b,c,f),a=Math.min(b,c,f),a=h-a,m=0;0===a?m=0:h===b?m=(c-f)/a%6:h===c?m=(f-b)/a+2:h===f&&(m=(b-c)/a+4);b={value:h,hue:60*m,saturation:0===h?0:a/h};b.hue=(b.hue+180)%360;return d(b)},extract:function(f){return 1===f[4]?"rgb("+f[1]+","+f[2]+","+f[3]+")":"rgba("+f[1]+","+f[2]+","+f[3]+","+f[4]+")"}}}();
-var Collage=function(){function d(b,a){var e=a.length-1;if(!(0>=e))for(b.moveTo(a[e][1],a[e][2]);e--;)b.lineTo(a[e][1],a[e][2])}function f(b,a,e,c){0===b.length&&(b=[8,4]);var f=c.length-1;if(!(0>=f)){var n=c[f][1],p=c[f][2],d=0,j=0,h=0,m=0,q=0,u=0,w=b.length,z=!0,y=b[0];for(a.moveTo(n,p);f--;){d=c[f][1];j=c[f][2];h=d-n;m=j-p;for(q=Math.sqrt(h*h+m*m);y<=q;)n+=h*y/q,p+=m*y/q,a[z?"lineTo":"moveTo"](n,p),h=d-n,m=j-p,q=Math.sqrt(h*h+m*m),z=!z,u=(u+1)%w,y=b[u];0a.length){var f=a[3][1],d=a[3][2],j=0,h=a[2];switch(a[4][0]){case "FShape":for(var v=a[4][3][1],t=v.length;--t;)var r=v[t],j=Math.max(j,r[1]*r[1]+r[2]*r[2]);j*=h*h;break;case "FImage":v=h*a[4][1]/2;h=h*a[4][2]/2;j=v*v+h*h;break;case "FElement":v=h*a[4][1][3]/2,h=h*a[4][1][4]/2,j=v*v+h*h}a.push(function(b,a){var e=b-f,c=a-d;return e*
-e+c*c'+b+""+a+">"}},b=function(a,b){return function(c){return""+c+""}},c=function(a){a=Elm.JavaScript.castStringToJSString(a);return b("font-family",a)},h=f("h1"),a=b("font-style","italic"),f=f("b"),m=b("text-decoration","underline"),j=b("text-decoration","overline"),l=b("text-decoration","line-through");return{fromString:d,toText:d,header:h,
-height:function(a){return b("font-size",a+"em")},italic:a,bold:f,underline:m,overline:j,strikeThrough:l,monospace:c("monospace"),typeface:c,color:function(a){return b("color",Elm.Color.extract(a))},link:function(a){return function(b){return""+b+""}}}}();
-var Render=function(){function d(a){a=document.createElement(a);a.style.padding="0";a.style.margin="0";return a}function f(a){return a}function b(a){a.style.styleFloat="left";a.style.cssFloat="left";return a}function c(a){a.style.position="absolute";return a}function h(a,b,c){for(var f=d("div"),j=c.length;j--;){var h=a(b(c[j]));f.appendChild(h)}return f}function a(a){switch(a[0]){case "Absolute":return a[1]+"px";case "Relative":return 100*a[1]+"%"}}function m(b,e){e.style.position="absolute";e.style.margin=
-"auto";switch(b[0]){case "Position":"Far"!==b[1][0]&&(e.style.left=0);"Near"!==b[1][0]&&(e.style.right=0);"Far"!==b[2][0]&&(e.style.top=0);"Near"!==b[2][0]&&(e.style.bottom=0);break;case "PositionAt":e.style.top=a(b[2]);e.style.left=a(b[1]);var c="translate("+~~(-e.style.width.slice(0,-2)/2)+"px,"+~~(-e.style.height.slice(0,-2)/2)+"px)";e.style.transform=c;e.style.msTransform=c;e.style.MozTransform=c;e.style.webkitTransform=c;e.style.OTransform=c;break;default:c=b[0].slice(-2),e.style["T"===c[0]?
-"top":"bottom"]=a(b[2]),e.style["L"===c[1]?"left":"right"]=a(b[1])}}function j(a){var e={};switch(a[2][0]){case "EText":var e=a[2][1],k=a[2][2],l=d("div");l.innerHTML=k;l.style.textAlign=e;e=l;break;case "EImage":e=a[2][1];k=d("img");k.src=e;k.name=e;k.style.display="block";e=k;break;case "EVideo":l=a[2][1];e=d("video");e.controls="controls";k=d("source");k.src=l;l=l.split(".");k.type="video/"+l[l.length-1];e.appendChild(k);e.style.display="block";break;case "EFittedImage":var n=a[3],p=a[4],e=a[2][1],
-k=d("div");k.style.width=n+"px";k.style.height=p+"px";k.style.position="relative";k.style.overflow="hidden";var s=d("img");s.onload=function(){s.style.position="absolute";s.style.margin="auto";var a=n,b=p;n/p>this.width/this.height?b=Math.round(this.height*n/this.width):a=Math.round(this.width*p/this.height);s.style.width=a+"px";s.style.height=b+"px";s.style.left=(n-a)/2+"px";s.style.top=(p-b)/2+"px"};s.src=e;s.name=e;k.appendChild(s);e=k;break;case "EFlow":a:{e=a[2][2];switch(a[2][1][0]){case "DDown":e=
-e.slice(0).reverse();case "DUp":e=h(f,j,e);break a;case "DRight":e=e.slice(0).reverse();case "DLeft":e=h(b,j,e);break a;case "DOut":e=e.slice(0).reverse();case "DIn":e=h(c,j,e);break a}e=void 0}break;case "ECollage":e=Collage.collage(a[2][1],a[2][2],a[2][3]);break;case "EEmpty":e=d("div");break;case "EContainer":k=a[2][1];e=j(a[2][2]);m(k,e);k=d("div");k.style.position="relative";k.style.overflow="hidden";k.appendChild(e);e=k;break;case "EHtml":e=a[2][1];"button"!==e.type&&(k=Value.getExcess(e),a[3]-=
-k[0],a[4]-=k[1]);break;case "EExternalHtml":e=d("div"),e.appendChild(a[2][1])}e.id=a[1];e.style.width=~~a[3]+"px";e.style.height=~~a[4]+"px";1!==a[5]&&(e.style.opacity=a[5]);"Just"===a[6][0]&&(e.style.backgroundColor=Elm.Color.extract(a[6][1]));return"Just"===a[7][0]?(k=d("a"),k.href=a[7][1],k.appendChild(e),k):e}function l(a,e,k){"A"===a.tagName&&(a=a.firstChild);if(e[1]!==k[1]){if(e[2][0]!==k[2][0])return a.parentNode.replaceChild(j(k),a);var d=k[2],n=e[2];switch(d[0]){case "EText":d[1]!==n[1]&&
-(a.style.textAlign=d[1]);d[2]!==n[2]&&(a.innerHTML=d[2]);break;case "EImage":d[1]!==n[1]&&(a.src=d[1]);break;case "EVideo":case "EFittedImage":if(!Value.eq(d,n)||k[3]!==e[3]||k[4]!==e[4])return a.parentNode.replaceChild(j(k),a);break;case "ECollage":if(d[1]!==n[1]||d[2]!==n[2]||d[3].length!==n[3].length)return a.parentNode.replaceChild(j(k),a);Collage.updateCollage(a,n[3],d[3]);break;case "EFlow":if(d[1]!==n[1])return a.parentNode.replaceChild(j(k),a);var h=d[2],s=a.childNodes;if(h.length!==s.length)return a.parentNode.replaceChild(j(k),
-a);var n=n[2],v=function(a){return a};switch(d[1][0]){case "DDown":case "DUp":v=f;break;case "DRight":case "DLeft":v=b;break;case "DOut":case "DIn":v=c}for(d=s.length;d--;)l(s[d],n[d],h[d]),v(s[d]);break;case "EContainer":l(a.childNodes[0],n[2],d[2]);m(d[1],a.childNodes[0]);break;case "EHtml":k[1]!==e[1]&&(h=j(k),a.parentNode.replaceChild(h,a),a=h);"button"!==h.type&&(d=Value.getExcess(a),k[3]-=d[0],k[4]-=d[1]);break;case "EExternalHtml":k[1]!==e[1]&&a.parentNode.replaceChild(j(k),a)}k[3]!==e[3]&&
-(a.style.width=~~k[3]+"px");k[4]!==e[4]&&(a.style.height=~~k[4]+"px");k[5]!==e[5]&&(a.style.opacity=k[5]);2===k[6].length&&(d=Elm.Color.extract(k[6][1]),d!==a.style.backgroundColor&&(a.style.backgroundColor=d));if(2===k[7].length&&(1===e[7].length||k[7][1]!==e[7][1]))a.parentNode.href=k[7][1];k[1]=e[1]}}return{render:j,update:l,addTo:function(a,b){a.appendChild(b)},newElement:d,flowWith:h,goIn:c}}();
-Elm.Signal=function(){function d(a){this.id=Guid.guid();this.value=a;this.kids=[];this.defaultNumberOfKids=0;this.recv=function(a,b,e){if(b=b===this.id)this.value=e;l(this,a,b);return b};Dispatcher.inputs.push(this)}function f(a,b){this.id=Guid.guid();this.value=null;this.kids=[];this.count=0;this.changed=!1;b.reverse();this.recalc=function(){for(var c=a,d=b.length;d--;)c=c(b[d].value);this.value=c};this.recalc();this.recv=function(a,e){this.count+=1;e&&(this.changed=!0);this.count==b.length&&(this.changed&&
-this.recalc(),l(this,a,this.changed),this.changed=!1,this.count=0)};for(var c=b.length;c--;)b[c].kids.push(this)}function b(a,b,c,d){this.id=Guid.guid();this.value=c?b(d.value):b;this.kids=[];this.recv=function(b,c){c&&(this.value=a(d.value)(this.value));l(this,b,c)};d.kids.push(this)}function c(a,b,c){this.id=Guid.guid();this.value=a(c.value)?b:c.value;this.kids=[];this.recv=function(b,d){var f=d&&!a(c.value);f&&(this.value=c.value);l(this,b,f)};c.kids.push(this)}function h(a){this.id=Guid.guid();
-this.value=a.value;this.kids=[];this.recv=function(b,c){var d=c&&!Value.eq(this.value,a.value);d&&(this.value=a.value);l(this,b,d)};a.kids.push(this)}function a(a,b){this.id=Guid.guid();var c=(new window.Date).getTime();this.value=a?Value.Tuple(c,b.value):c;this.kids=[];this.recv=function(c,d){d&&(this.value=a?Value.Tuple(c,b.value):c);l(this,c,d)};b.kids.push(this)}function m(a,b){this.id=Guid.guid();this.value=b.value;this.kids=[];this.count=0;this.changed=!1;this.recv=function(c,d,f){f===a.id&&
-(this.changed=d);this.count+=1;2==this.count&&(this.changed&&(this.value=b.value),l(this,c,this.changed),this.count=0,this.changed=!1)};a.kids.push(this);b.kids.push(this)}function j(a,b){this.id=Guid.guid();this.value=a.value;this.kids=[];this.next=null;this.count=0;this.changed=!1;this.recv=function(c,d,f){this.count+=1;d&&(this.changed=!0,f==b.id&&null===this.next&&(this.next=b.value),f==a.id&&(this.next=a.value));2==this.count&&(this.changed&&(this.value=this.next,this.next=null),l(this,c,this.changed),
-this.changed=!1,this.count=0)};a.kids.push(this);b.kids.push(this)}var l=function(a,b,c){for(var d=a.kids,f=d.length;f--;)d[f].recv(b,c,a.id)},g=function(a){return function(b){return function(d){d=new f(function(a){return function(b){return[a,b]}},[a,d]);d=new c(function(a){return a[0]},[!0,b],d);return new f(function(a){return a[1]},[d])}}};return{constant:function(a){return new d(a)},lift:function(a){return function(b){return new f(a,[b])}},lift2:function(a){return function(b){return function(c){return new f(a,
-[b,c])}}},lift3:function(a){return function(b){return function(c){return function(d){return new f(a,[b,c,d])}}}},lift4:function(a){return function(b){return function(c){return function(d){return function(j){return new f(a,[b,c,d,j])}}}}},lift5:function(a){return function(b){return function(c){return function(d){return function(j){return function(g){return new f(a,[b,c,d,j,g])}}}}}},lift6:function(a){return function(b){return function(c){return function(d){return function(j){return function(g){return function(h){return new f(a,
-[b,c,d,j,g,h])}}}}}}},lift7:function(a){return function(b){return function(c){return function(d){return function(j){return function(g){return function(h){return function(l){return new f(a,[b,c,d,j,g,h,l])}}}}}}}},lift8:function(a){return function(b){return function(c){return function(d){return function(j){return function(g){return function(h){return function(l){return function(m){return new f(a,[b,c,d,j,g,h,l,m])}}}}}}}}},foldp:function(a){return function(c){return function(d){return new b(a,c,!1,
-d)}}},foldp$:function(a){return function(c){return function(d){return new b(a,c,!0,d)}}},foldp1:function(a){return function(c){return new b(a,function(a){return a},!0,c)}},delay:function(a){return function(b){var c=new d(b.value),j=!0;b=new m(c,new f(function(a){return function(){return a}},[c,new f(function(b){j||setTimeout(function(){Dispatcher.notify(c.id,b)},a)},[b])]));j=!1;return b}},merge:function(a){return function(b){return new j(a,b)}},merges:function(a){return Elm.List.foldl1(function(a){return function(b){return new j(a,
-b)}})(a)},mergeEither:function(a){return function(b){function c(a){return function(b){return[a,b]}}return new j(new f(c("Left"),[a]),new f(c("Right"),[b]))}},average:function(a){return function(b){for(var c=Array(a),d=a;d--;)c[d]=0;var d=0,j=!1,g=0;return new f(function(b){g+=b-c[d];c[d]=b;b=g/Math.max(1,j?a:d);++d==a&&(j=!0,d=0);return b},[b])}},count:function(a){return new b(function(){return function(a){return a+1}},0,!1,a)},countIf:function(a){return function(c){return new b(function(b){return function(c){return a(b)?
-c+1:c}},0,!1,c)}},keepIf:function(a){return function(b){return function(d){return new c(function(b){return!a(b)},b,d)}}},dropIf:function(a){return function(b){return function(d){return new c(a,b,d)}}},keepWhen:function(a){return g(new f(function(a){return!a},[a]))},dropWhen:g,dropRepeats:function(a){return new h(a)},sampleOn:function(a){return function(b){return new m(a,b)}},timestamp:function(b){return new a(!0,b)},timeOf:function(b){return new a(!1,b)}}}();
-var Dispatcher=function(){function d(b){if(!b.hasOwnProperty("defaultNumberOfKids"))return!0;var a=b.kids.length;if(0==a)return!1;if(a>b.defaultNumberOfKids)return!0;for(var c=!1;a--;)c=c||d(b.kids[a]);return c}var f=null,b=[],c=null;return{initialize:function(){f=Elm.main();f.hasOwnProperty("recv")||(f=Elm.Signal.constant(f));c=f.value;for(var h=[],a=b.length;a--;)d(b[a])&&h.push(b[a]);b=h;document.getElementById("content").appendChild(Render.render(c));h=document.getElementById("widthChecker").offsetWidth;
-h!==window.innerWidth&&Dispatcher.notify(Elm.Window.dimensions.id,Value.Tuple(h,window.innerHeight));f=Elm.Signal.lift(function(a){var b=document.getElementById("content");Render.update(b.firstChild,c,a);return c=a})(f)},notify:function(c,a){for(var d=(new window.Date).getTime(),f=!1,l=b.length;l--;)f=b[l].recv(d,c,a)||f;return f},inputs:b}}();
-Elm.HTTP=function(){function d(b){return function(c){return function(d){return function(e){return{"0":"Request",length:1,verb:a.castStringToJSString(b),url:a.castStringToJSString(c),data:null===d?null:a.castStringToJSString(d),headers:e}}}}}function f(a){return d("GET")(a)(null)(["Nil"])}function b(b,d){return function(f){if(""!==f.url){var e={value:["Waiting"]};b.push(e);var h=null;window.ActiveXObject&&(h=new ActiveXObject("Microsoft.XMLHTTP"));window.XMLHttpRequest&&(h=new XMLHttpRequest);h.onreadystatechange=
-function(){4===h.readyState&&(e.value=200===h.status?["Success",m(h.responseText)]:["Failure",h.status,m(h.statusText)],setTimeout(function(){c(b,d)},0))};h.open(f.verb,f.url,!0);Elm.List.map(function(b){h.setRequestHeader(a.castStringToJSString(b[1]),a.castStringToJSString(b[2]))})(f.headers);h.send(f.data)}}}function c(a,b){0=a))continue;return["Nothing"]}return["Just",parseFloat(b)]},sqrt:Math.sqrt,abs:Math.abs,pi:Math.PI,e:Math.E,sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,atan2:function(b){return function(c){return Math.atan2(b,
-c)}},mod:f,min:function(b){return function(c){return Math.min(b,c)}},max:function(b){return function(c){return Math.max(b,c)}},flip:function(b){return function(c){return function(d){return b(d)(c)}}},clamp:function(b){return function(c){return function(d){return Math.min(c,Math.max(b,d))}}},curry:function(b){return function(c){return function(d){return b(["Tuple2",c,d])}}},uncurry:function(b){return function(c){if("Tuple2"!==c[0])throw"Function was uncurry'd but was not given a pair.";return b(c[1])(c[2])}},
-logBase:function(b){return function(c){return Math.log(c)/Math.log(b)}},Just:Elm.Maybe.Just,Nothing:Elm.Maybe.Nothing,maybe:Elm.Maybe.maybe,map:Elm.List.map,zip:Elm.List.zip,zipWith:Elm.List.zipWith,filter:Elm.List.filter,head:Elm.List.head,tail:Elm.List.tail,last:Elm.List.last,length:Elm.List.length,reverse:Elm.List.reverse,foldr:Elm.List.foldr,foldr1:Elm.List.foldr1,foldl:Elm.List.foldl,foldl1:Elm.List.foldl1,and:Elm.List.and,or:Elm.List.or,all:Elm.List.all,any:Elm.List.any,sum:Elm.List.sum,product:Elm.List.product,
-concat:Elm.List.concat,concatMap:Elm.List.concatMap,maximum:Elm.List.maximum,minimum:Elm.List.minimum,scanl:Elm.List.scanl,scanl1:Elm.List.scanl1,take:Elm.List.take,drop:Elm.List.drop,zip:Elm.List.zip,unzip:Elm.List.unzip,lift:Elm.Signal.lift,lift2:Elm.Signal.lift2,lift3:Elm.Signal.lift3,lift4:Elm.Signal.lift4,lift5:Elm.Signal.lift5,lift6:Elm.Signal.lift6,lift7:Elm.Signal.lift7,lift8:Elm.Signal.lift8,foldp:Elm.Signal.foldp,foldp1:Elm.Signal.foldp1,foldp$:Elm.Signal.foldp$,constant:Elm.Signal.constant,
-merge:Elm.Signal.merge,merges:Elm.Signal.merges,mergeEither:Elm.Signal.mergeEither,count:Elm.Signal.count,countIf:Elm.Signal.countIf,average:Elm.Signal.average,keepIf:Elm.Signal.keepIf,dropIf:Elm.Signal.dropIf,keepWhen:Elm.Signal.keepWhen,dropWhen:Elm.Signal.dropWhen,dropRepeats:Elm.Signal.dropRepeats,sampleOn:Elm.Signal.sampleOn,timestamp:Elm.Signal.timestamp,timeOf:Elm.Signal.timeOf}}();
-(function(){var d=function(d){for(var b in d)Elm.Prelude[b]=d[b]};d(Elm.Color);d(Elm.Text);d(Elm.Graphics);d(Elm.Time);show=Value.show})();
-Elm.Touch=function(){function d(b){b=j.remove(b.identifier);Date.now()-b.ta)){var b=this.values[a];this.keys.splice(a,1);this.values.splice(a,1);return b}}};
-f("touchstart",function(a){j.insert(a.identifier,{x:a.pageX,y:a.pageY,t:Date.now()})});f("touchmove",function(){});f("touchend",d);f("touchcancel",d);f("touchleave",d);var l=b(function(a){return Elm.JavaScript.castJSArrayToList(a)}),g=b(function(){return m});g.defaultNumberOfKids=1;g=Elm.Signal.keepIf(function(){var b=a;a=!1;return b})({_:[!0],x:[0],y:[0]})(g);g.defaultNumberOfKids=0;return{touches:l,taps:g}}();
-Elm.Dict=function(){function d(a){return function(b){return function(c){return function(d){return function(e){return["RBNode",a,b,c,d,e]}}}}}function f(a){a:{switch(a[0]){case "RBEmpty":throw"(min RBEmpty) is not defined";case "RBNode":switch(a[4][0]){case "RBEmpty":a=["Tuple2",a[2],a[3]];break a}a=f(a[4]);break a}throw"Non-exhaustive pattern match in case";}return a}function b(a){return function(c){var d;a:{switch(c[0]){case "RBEmpty":d=w;break a;case "RBNode":d=function(){switch(q(a)(c[2])[0]){case "EQ":return z(c[3]);
-case "GT":return b(a)(c[5]);case "LT":return b(a)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";}return d}}function c(a){return function(b){return function(d){var e;a:{switch(d[0]){case "RBEmpty":e=a;break a;case "RBNode":e=function(){switch(q(b)(d[2])[0]){case "EQ":return d[3];case "GT":return c(a)(b)(d[5]);case "LT":return c(a)(b)(d[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";
-}return e}}}function h(a){return function(c){return F(b(a)(c))}}function a(a){a:{switch(a[0]){case "RBNode":switch(a[5][0]){case "RBNode":a=d(a[1])(a[5][2])(a[5][3])(d(B)(a[2])(a[3])(a[4])(a[5][4]))(a[5][5]);break a}}throw"rotateLeft of a node without enough children";}return a}function m(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":a=d(a[1])(a[4][2])(a[4][3])(a[4][4])(d(B)(a[2])(a[3])(a[4][5])(a[5]));break a}}throw"rotateRight of a node without enough children";}return a}function j(a){a:{switch(a[0]){case "Black":a=
-B;break a;case "Red":a=E;break a}throw"Non-exhaustive pattern match in case";}return a}function l(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[5][0]){case "RBNode":a=d(j(a[1]))(a[2])(a[3])(d(j(a[4][1]))(a[4][2])(a[4][3])(a[4][4])(a[4][5]))(d(j(a[5][1]))(a[5][2])(a[5][3])(a[5][4])(a[5][5]));break a}}}throw"color_flip called on a RBEmpty or RBNode with a RBEmpty child";}return a}function g(b){a:switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":b=
-a(b);break a}}}a:switch(b[0]){case "RBNode":switch(b[4][0]){case "RBNode":switch(b[4][1][0]){case "Red":switch(b[4][4][0]){case "RBNode":switch(b[4][4][1][0]){case "Red":b=m(b);break a}}}}}a:switch(b[0]){case "RBNode":switch(b[4][0]){case "RBNode":switch(b[4][1][0]){case "Red":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":b=l(b);break a}}}}}return b}function e(a){a:switch(a[0]){case "RBNode":switch(a[1][0]){case "Red":a=d(E)(a[2])(a[3])(a[4])(a[5]);break a}}return a}function k(a){return function(b){return function(c){var f=
-function(c){var e;a:{switch(c[0]){case "RBEmpty":e=d(B)(a)(b)(A)(A);break a;case "RBNode":e=function(){switch(q(a)(c[2])[0]){case "EQ":return d(c[1])(c[2])(b)(c[4])(c[5]);case "GT":return d(c[1])(c[2])(c[3])(c[4])(f(c[5]));case "LT":return d(c[1])(c[2])(c[3])(f(c[4]))(c[5])}throw"Non-exhaustive pattern match in case";}();e=g(e);break a}throw"Non-exhaustive pattern match in case";}return e};return e(f(c))}}}function x(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":a=
-!0;break a}}}a=!1}return a}function n(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][4][0]){case "RBNode":switch(a[4][4][1][0]){case "Red":a=!0;break a}}}}a=!1}return a}function p(b){if(y(x(b))&&y(n(b))){b=l(b);a:switch(b[0]){case "RBNode":b:switch(b[5][0]){case "RBNode":switch(b[5][4][0]){case "RBNode":switch(b[5][4][1][0]){case "Red":b=l(a(d(b[1])(b[2])(b[3])(b[4])(m(b[5]))));break b}}}break a}}return b}function s(a){return function(b){var c=function(b){a:{switch(b[0]){case "RBEmpty":b=
-A;break a;case "RBNode":if("LT"===q(a)(b[2])[0])b:{b=p(b);switch(b[0]){case "RBEmpty":throw"delLT on RBEmpty";case "RBNode":b=g(d(b[1])(b[2])(b[3])(c(b[4]))(b[5]));break b}break}else{var h=x(b)?m(b):b,j;b:{switch(h[0]){case "RBNode":switch(h[5][0]){case "RBEmpty":j=D(a,h[2]);break b}}j=!1}if(j)b=h[4];else{h=y;b:{switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":j=!0;break b}}}j=!1}if(h=h(j)){h=y;b:{switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][4][0]){case "RBNode":switch(b[5][4][1][0]){case "Red":j=
-!0;break b}}}}j=!1}h=h(j)}h&&(b=l(b),b=n(b)?l(m(b)):b);b:{switch(b[0]){case "RBNode":h=D(a,b[2]);break b}h=!1}if(h)b:{switch(b[0]){case "RBEmpty":throw"delEQ called on a RBEmpty";case "RBNode":j=f(b[5]);c:{switch(j[0]){case "Tuple2":h=j[1];break c}break}c:{switch(j[0]){case "Tuple2":j=j[2];break c}break}var h=d(b[1])(h)(j)(b[4]),k=function(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBEmpty":a=A;break a}}b:{a=p(a);switch(a[0]){case "RBEmpty":a=A;break b;case "RBNode":a=g(d(a[1])(a[2])(a[3])(k(a[4]))(a[5]));
-break b}throw"Non-exhaustive pattern match in case";}}return a};b=e(k(b[5]));b=g(h(b));break b}break}else b:{switch(b[0]){case "RBEmpty":throw"delGT called on a RBEmpty";case "RBNode":b=g(d(b[1])(b[2])(b[3])(b[4])(c(b[5])));break b}break}}}break a}throw"Non-exhaustive pattern match in case";}return b};return h(a)(b)?e(c(b)):b}}function v(a){return function(b){a:{switch(b[0]){case "RBEmpty":b=A;break a;case "RBNode":b=d(b[1])(b[2])(a(b[3]))(v(a)(b[4]))(v(a)(b[5]));break a}throw"Non-exhaustive pattern match in case";
-}return b}}function t(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=t(a)(a(c[2])(c[3])(t(a)(b)(c[4])))(c[5]);break a}throw"Non-exhaustive pattern match in case";}return c}}}function r(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=r(a)(a(c[2])(c[3])(r(a)(b)(c[5])))(c[4]);break a}throw"Non-exhaustive pattern match in case";}return c}}}var q=Elm.Prelude.compare,u=Elm.Prelude.uncurry,w=Elm.Prelude.Nothing,
-z=Elm.Prelude.Just,y=Elm.Prelude.not,D=Elm.Prelude.eq,F=Elm.Maybe.isJust,B=["Red"],E=["Black"],A=["RBEmpty"],C=A;return{$op:{},empty:C,lookup:b,findWithDefault:c,member:h,insert:k,singleton:function(a){return function(b){return k(a)(b)(A)}},remove:s,map:v,foldl:t,foldr:r,union:function(a){return function(b){return t(k)(b)(a)}},intersect:function(a){return function(b){return t(function(a){return function(c){return function(d){return h(a)(b)?k(a)(c)(d):d}}})(C)(a)}},diff:function(a){return function(b){return t(function(a){return function(){return function(b){return s(a)(b)}}})(a)(b)}},
-keys:function(a){return r(function(a){return function(){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},values:function(a){return r(function(){return function(a){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},toList:function(a){return r(function(a){return function(b){return function(c){return["Cons",["Tuple2",a,b],c]}}})(["Nil"])(a)},fromList:function(a){return Elm.List.foldl(u(k))(C)(a)}}}();
-Elm.Set=function(){var d=Elm.Dict.empty,f=Elm.Dict.remove,b=Elm.Dict.member,c=Elm.Dict.union,h=Elm.Dict.intersect,a=Elm.Dict.diff,m=Elm.Dict.keys,j=Elm.List.foldl(function(a){return function(b){return Elm.Dict.insert(a)(["Tuple0"])(b)}})(d);return{empty:d,singleton:function(a){return Elm.Dict.singleton(a)(["Tuple0"])},insert:function(a){return Elm.Dict.insert(a)(["Tuple0"])},remove:f,member:b,union:c,intersect:h,diff:a,toList:m,fromList:j,foldl:function(a){return Elm.Dict.foldl(function(b){return function(){return function(c){return a(b)(c)}}})},
-foldr:function(a){return Elm.Dict.foldr(function(b){return function(){return function(c){return a(b)(c)}}})},map:function(a){return function(b){b=m(b);return j(Elm.List.map(a)(b))}}}}();
-(function(){try{var d={};for(this.i in Elm)eval("var "+this.i+"=Elm[this.i];");if(Elm.Automaton)throw"Module name collision, 'Automaton' is already defined.";Elm.Automaton=function(){function b(a){return["Automaton",a]}function c(a){return b(function(b){var d=unzip(map(function(a){a:{switch(a[0]){case "Automaton":a=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return a})(a)),e;a:{switch(d[0]){case "Tuple2":e=d[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(d[0]){case "Tuple2":d=
-d[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",e,c(d)]})}function f(a){return b(function(b){return["Tuple2",a(b),f(a)]})}function a(c){return function(d){return b(function(b){b=d(b)(c);return["Tuple2",b,a(b)(d)]})}}function m(a){return function(c){return b(function(b){var d=c(b)(a);a:{switch(d[0]){case "Tuple2":b=d[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(d[0]){case "Tuple2":d=d[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",
-b,m(d)(c)]})}}function j(a){return function(b){a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":b=["Tuple2",a[1]-b[1],a[2]-b[2]];break b}break}break a}throw"Non-exhaustive pattern match in case";}return b}}function l(a){return function(b){var c;a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":var d=function(a){return["Tuple2",b[2],["Tuple2",a,b[2]]]};c=function(){switch(b[1][0]){case "DragFrom":var c;a[1]?c=["Tuple2",uncurry(move)(j(a[2])(b[1][1]))(b[2]),["Tuple2",["DragFrom",
-b[1][1]],b[2]]]:(c=uncurry(move)(j(a[2])(b[1][1]))(b[2]),c=["Tuple2",c,["Tuple2",k,c]]);return c;case "Ignore":return d(a[1]?x:k);case "Listen":return d(not(a[1])?k:isWithin(a[2])(b[2])?["DragFrom",a[2]]:x)}throw"Non-exhaustive pattern match in case";}();break b}break}break a}throw"Non-exhaustive pattern match in case";}return c}}try{if(!(Elm.Prelude instanceof Object))throw"module not found";}catch(g){throw"Module 'Prelude' is missing. Compile with --make flag or load missing module in a separate JavaScript file.";
-}var e={};for(this.i in Elm.Prelude)e[this.i]||eval("var "+this.i+" = Elm.Prelude[this.i];");var k=["Listen"],x=["Ignore"];d[">>>"]=function(a){return function(c){var e;a:{switch(a[0]){case "Automaton":e=a[1];break a}throw"Non-exhaustive pattern match in case";}var f;a:{switch(c[0]){case "Automaton":f=c[1];break a}throw"Non-exhaustive pattern match in case";}return b(function(a){a=e(a);var b;a:{switch(a[0]){case "Tuple2":b=a[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(a[0]){case "Tuple2":a=
-a[2];break a}throw"Non-exhaustive pattern match in case";}var c=f(b);a:{switch(c[0]){case "Tuple2":b=c[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(c[0]){case "Tuple2":c=c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",b,d[">>>"](a)(c)]})}};d["<<<"]=function(a){return function(b){return d[">>>"](b)(a)}};d["^>>"]=function(a){return function(b){return d[">>>"](f(a))(b)}};d[">>^"]=function(a){return function(b){return d[">>>"](a)(f(b))}};d["^<<"]=function(a){return function(b){return d[">>>"](b)(f(a))}};
-d["<<^"]=function(a){return function(b){return d[">>>"](f(b))(a)}};e=a(0)(function(){return function(a){return 1+a}});return{$op:{">>>":d[">>>"],"<<<":d["<<<"],"^>>":d["^>>"],">>^":d[">>^"],"^<<":d["^<<"],"<<^":d["<<^"]},run:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=lift(fst)(foldp$(function(a){return function(b){a:{switch(b[0]){case "Tuple2":switch(b[2][0]){case "Automaton":b=b[2][1](a);break a}}throw"Non-exhaustive pattern match in case";}return b}})(a[1])(b));break a}throw"Non-exhaustive pattern match in case";
-}return b}},step:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return b}},combine:c,pure:f,init:a,init$:m,count:e,draggable:function(a){return m(["Tuple2",k,a])(l)}}}();Elm.main=function(){return Elm.Automaton.main}}catch(f){Elm.main=function(){document.body.innerHTML=Elm.Text.monospace('
Your browser may not be supported. Are you using a modern browser?
Runtime Error in Automaton module:
'+
-f+"");throw f;}}})();
\ No newline at end of file
diff --git a/elm/elm-runtime-0.7.2.js b/elm/elm-runtime-0.7.2.js
deleted file mode 100644
index 65ce33f..0000000
--- a/elm/elm-runtime-0.7.2.js
+++ /dev/null
@@ -1,4522 +0,0 @@
-
-Elm = {};
-
-var Guid = function() {
- var counter = 0;
- var guid = function() { counter += 1; return counter; };
- return {guid : guid};
-}();
-Elm.JavaScript = function() {
- function castJSBoolToBool(b) { return b; }
- function castBoolToJSBool(b) { return b; }
-
- function castJSNumberToFloat(n) { return n; }
- function castFloatToJSNumber(n) { return n; }
-
- function castJSNumberToInt(n) { return ~~n; }
- function castIntToJSNumber(n) { return n; }
-
- function castJSElementToElement(w) {
- return function(h) {
- return function(node) {
- return ["Element",Guid.guid(),
- ["EExternalHtml",node],
- w,h,1,["Nothing"],["Nothing"]];
- }
- }
- }
- function castElementToJSElement(elem) { return Render.render(elem); }
-
- function castJSArrayToList(arr) {
- var list = ["Nil"];
- for (var i = arr.length; i--; ) {
- list = [ "Cons", arr[i], list ];
- }
- return list;
- }
- function castListToJSArray(list) {
- var a = [];
- while (list[0] === "Cons") {
- a.push(list[1]);
- list = list[2];
- }
- return a;
- }
-
- var castJSStringToString = castJSArrayToList;
- function castStringToJSString(str) {
- if (typeof str === "string") return str;
- return castListToJSArray(str).join('');
- }
-
- function fromTuple(t) { return t.slice(1); }
- function toTuple(a) { return ["Tuple" + a.length].concat(a); }
-
- return {castJSBoolToBool:castJSBoolToBool,
- castBoolToJSBool:castBoolToJSBool,
- castJSNumberToFloat:castJSNumberToFloat,
- castFloatToJSNumber:castFloatToJSNumber,
- castJSNumberToInt:castJSNumberToInt,
- castIntToJSNumber:castIntToJSNumber,
- Experimental : {castJSElementToElement:castJSElementToElement,
- castElementToJSElement:castElementToJSElement},
- castJSArrayToList:castJSArrayToList,
- castListToJSArray:castListToJSArray,
- castJSStringToString:castJSStringToString,
- castStringToJSString:castStringToJSString,
- castTupleToJSTuple2:fromTuple,
- castTupleToJSTuple3:fromTuple,
- castTupleToJSTuple4:fromTuple,
- castTupleToJSTuple5:fromTuple,
- castJSTupleToTuple2:toTuple,
- castJSTupleToTuple3:toTuple,
- castJSTupleToTuple4:toTuple,
- castJSTupleToTuple5:toTuple
- };
-}();
-
-var JSjson = window.JSON;
-Elm.JSON = function() {
- var JS = Elm.JavaScript;
- var empty = ['JSON',{}];
- function singleton(k) { return function(v) {
- var obj = {};
- obj[JS.castStringToJSString(k)] = v;
- return ['JSON', obj ];
- };
- }
- function insert(k) { return function(v) { return function(inObj) {
- var obj = inObj[1];
- var outObj = {};
- for (var i in obj) {
- outObj[i] = obj[i];
- }
- outObj[JS.castStringToJSString(k)] = v;
- return ['JSON', outObj ];
- };
- };
- }
-
- function lookup(key) { return function(obj) {
- var k = JS.castStringToJSString(key);
- return (k in obj[1]) ? ["Just", obj[1][k]] : ["Nothing"] ;
- };
- }
- function find(tipe,base) { return function (key) { return function(obj) {
- var k = JS.castStringToJSString(key);
- if (k in obj[1]) {
- var v = obj[1][k];
- if (v[0] === tipe) { return v[1]; }
- }
- return base;
- };
- }
- }
- function lookupWithDefault(base) { return function(key) { return function(obj) {
- var k = JS.castStringToJSString(key);
- return (k in obj[1]) ? obj[1][k] : base ;
- };
- };
- }
-
- function remove(k) { return function(inObj) {
- var obj = inObj[1];
- var outObj = {};
- for (var i in obj) {
- outObj[i] = obj[i];
- }
- delete outObj[JS.castStringToJSString(k)];
- return ['JSON', outObj];
- };
- }
-
- function JsonString(v) { return [ "JsonString", v ]; }
- function JsonNumber(v) { return [ "JsonNumber", v ]; }
- function JsonBool(v) { return [ "JsonBool", v ]; }
- var JsonNull = [ "JsonNull" ];
- function JsonArray(v) { return [ "JsonArray", v ]; }
- function JsonObject(v) { return [ "JsonObject", v ]; }
-
- function toList(json) {
- var obj = json[1];
- var arr = [];
- for (var i in obj) {
- arr.push(Value.Tuple(JS.castJSStringToString(i), obj[i]));
- }
- return JS.castJSArrayToList(arr);
- }
- function fromList(list) {
- var arr = JS.castListToJSArray(list);
- var obj = {};
- for (var i = arr.length; i--; ) {
- obj[JS.castStringToJSString(arr[i][1])] = arr[i][2];
- }
- return [ "JSON", obj ];
- }
-
- function toPrettyJSString(sep) { return function (obj) {
- function fromValue(v) {
- switch (v[0]) {
- case 'JsonNull' : return null;
- case 'JsonString' : return JS.castStringToJSString(v[1]);
- case 'JsonObject' :
- var o = {};
- var from = v[1][1];
- for (var i in from) {
- o[i] = fromValue(from[i]);
- }
- return o;
- case 'JsonArray' :
- var a = JS.castListToJSArray(v[1]);
- for (var i = a.length; i--; ) {
- a[i] = fromValue(a[i]);
- }
- return a;
- default :
- return v[1];
- }
- }
- return JSjson.stringify(fromValue([ 'JsonObject', obj ]), null, JS.castStringToJSString(sep));
- };
- }
- function fromJSString(str) {
- var obj;
- try {
- obj = JSjson.parse(str);
- } catch (e) {
- return Elm.Maybe.Nothing;
- }
- function toValue(v) {
- switch (typeof v) {
- case 'string' : return [ "JsonString", JS.castJSStringToString(v) ];
- case 'number' : return [ "JsonNumber", JS.castJSNumberToFloat(v) ];
- case 'boolean' : return [ "JsonBool", JS.castJSBoolToBool(v) ];
- case 'object' :
- if (v === null) return [ "JsonNull" ];
- for (var i in v) {
- v[i] = toValue(v[i]);
- }
- if (v instanceof Array) return [ "JsonArray", JS.castJSArrayToList(v) ];
- return [ "JsonObject", [ "JSON", v ] ];
- }
- }
- for (var i in obj) {
- obj[i] = toValue(obj[i]);
- }
- return Elm.Maybe.Just( ['JSON',obj] );
- }
- return {empty : empty,
- singleton : singleton,
- insert : insert,
- lookup : lookup,
- findNumber : find("JsonNumber",0),
- findString : find("JsonString",["Nil"]),
- findObject : find("JsonObject", empty ),
- findArray : find("JsonArray" ,["Nil"]),
- findWithDefault : lookupWithDefault,
- remove : remove,
- toPrettyJSString : toPrettyJSString,
- toJSString : toPrettyJSString(''),
- fromJSString : fromJSString,
- toPrettyString : function(sep) { return function(v) {
- return JS.castJSStringToString(toPrettyJSString(sep)(v)); }; },
- toString : function(v) { return JS.castJSStringToString(toPrettyJSString('')(v)); },
- fromString : function(v) { return fromJSString(JS.castStringToJSString(v)); },
- toList : toList,
- fromList : fromList,
- JsonString : JsonString,
- JsonNumber : JsonNumber,
- JsonBool : JsonBool,
- JsonNull : JsonNull,
- JsonArray : JsonArray,
- JsonObject : JsonObject
- };
-}();
-
-var Value = function(){
-
- var eq = function(x,y) {
- if (typeof x === "object") {
- if (x !== null && '_' in x) {
- for (var i in x) { if (x[i] != y[i]) return false; }
- for (var i in y) { if (!(i in x)) return false; }
- return true;
- }
- if (x === y) return true;
- if (x.length !== y.length) return false;
- for (var i = x.length; i--; ) {
- if (!eq(x[i],y[i])) return false;
- }
- return true;
- }
- return x === y;
- };
-
- var Tuple = function() {
- var len = arguments.length;
- var arr = new Array(len+1);
- arr[0] = "Tuple" + arguments.length;
- for (var i = len; i--; ) {
- arr[i+1] = arguments[i];
- }
- return arr;
- };
-
- var listToArray = function(list) {
- var arr = [];
- while (list[0] === "Cons") {
- arr.push(list[1]);
- list = list[2];
- }
- return arr;
- };
-
- function makeSpaces(s) {
- if (s.length == 0) { return s; }
- var arr = s.split('');
- if (arr[0] == ' ') { arr[0] = " " }
- for (var i = arr.length; --i; ) {
- if (arr[i][0] == ' ' && arr[i-1] == ' ') {
- arr[i-1] = arr[i-1] + arr[i];
- arr[i] = '';
- }
- }
- for (var i = arr.length; i--; ) {
- if (arr[i].length > 1 && arr[i][0] == ' ') {
- var spaces = arr[i].split('');
- for (var j = spaces.length - 2; j >= 0; j -= 2) {
- spaces[j] = ' ';
- }
- arr[i] = spaces.join('');
- }
- }
- arr = arr.join('');
- if (arr[arr.length-1] === " ") {
- return arr.slice(0,-1) + ' ';
- }
- return arr;
- }
-
- function properEscape(str) {
- if (str.length == 0) return str;
- str = str //.replace(/&/g, "&")
- .replace(/"/g, /*"*/ """)
- .replace(/'/g, /*'*/ "'")
- .replace(//g, ">")
- .replace(/\n/g, "
");
- var arr = str.split('
');
- for (var i = arr.length; i--; ) {
- arr[i] = makeSpaces(arr[i]);
- }
- return arr.join('
');
- }
-
- var toText = function(elmList) {
- if (typeof elmList === "string") return properEscape(elmList);
- var a = [];
- while (elmList[0] === "Cons") {
- a.push(elmList[1]);
- elmList = elmList[2];
- }
- return properEscape(a.join(''));
- };
-
- function getTextSize(w,h,txt) {
- var t = document.createElement('div');
- t.innerHTML = txt;
- t.style.textAlign = 'left';
- if (w > 0) { t.style.width = w + "px"; }
-
- t.style.visibility = "hidden";
- t.style.styleFloat = "left";
- t.style.cssFloat = "left";
-
- document.body.appendChild(t);
- var cStyle = window.getComputedStyle(t,null);
- var realW = cStyle.getPropertyValue("width").slice(0,-2) - 0;
- var realH = cStyle.getPropertyValue("height").slice(0,-2) - 0;
- document.body.removeChild(t);
- //delete t;
- return [Math.ceil(realW),Math.ceil(Math.max(h,realH))];
- }
-
- function getSize(e) {
- var t = e.cloneNode(true);
-
- t.style.visibility = "hidden";
- t.style.styleFloat = "left";
- t.style.cssFloat = "left";
-
- document.body.appendChild(t);
- var w = t.offsetWidth;
- var h = t.offsetHeight;
- document.body.removeChild(t);
- //delete t;
- return [w,h];
- }
-
- function getExcess(e) {
- var t = e.cloneNode(true);
-
- t.style.visibility = "hidden";
- t.style.styleFloat = "left";
- t.style.cssFloat = "left";
-
- document.body.appendChild(t);
- var ow = t.offsetWidth;
- var oh = t.offsetHeight;
- var cStyle = window.getComputedStyle(t,null);
- var w = cStyle.getPropertyValue("width").slice(0,-2) - 0;
- var h = cStyle.getPropertyValue("height").slice(0,-2) - 0;
- document.body.removeChild(t);
- //delete t;
- return [ow-w,oh-h];
- }
-
-
- function groupForms(forms) {
- forms = Elm.JavaScript.castListToJSArray(forms);
- var groups = [];
- var arr = [];
- for (var i = forms.length; i--; ) {
- var f = forms[i];
- switch(f[4][0]) {
- case "FElement":
- if (arr.length > 0) {
- groups.push(arr);
- arr = [];
- }
- groups.push(f);
- break;
- default:
- arr.push(f);
- }
- }
- if (arr.length > 0) groups.push(arr);
- return groups;
- }
-
- var toString = function(v) {
- if (typeof v === "function") {
- return "";
- } else if (typeof v === "boolean") {
- return v ? "True" : "False";
- } else if (typeof v === "number") {
- return v+"";
- } else if (typeof v === "string" && v.length < 2) {
- return "'"+v+"'";
- } else if (typeof v === "object" && ('_' in v)) {
- var output = [];
- for (var k in v._) {
- console.log(k,v._[k]);
- for (var i = v._[k].length; i--; ) {
- output.push(k + " = " + toString(v._[k][i]));
- }
- }
- for (var k in v) {
- if (k === '_') continue;
- output.push(k + " = " + toString(v[k]));
- }
- if (output.length === 0) return "{}";
- return "{ " + output.join(", ") + " }";
- } else if (v[0]) {
- if (v[0].substring(0,5) === "Tuple") {
- var output = new Array(v.length-1);
- for (var i = v.length; --i; ) { output[i-1] = toString(v[i]); }
- return "(" + output.join(",") + ")";
- } else if (v[0] === "Cons") {
- var start = (typeof v[1] === "string") ? '"' : "[";
- var end = (typeof v[1] === "string") ? '"' : "]";
- var div = (typeof v[1] === "string") ? "" : ",";
- var f = (typeof v[1] === "string") ? function(x){return x} : toString;
- var output = start + f(v[1]);
- v = v[2];
- while (true) {
- if (v[0] === "Cons") {
- output += div + f(v[1]);
- v = v[2];
- } else {
- return output + end;
- }
- }
- } else if (v[0] === "Nil") {
- return "[]";
- } else if (v[0] === "JSON") {
- return "(JSON.fromList " + toString(Elm.JSON.toList(v)) + ")";
- } else if (v[0] === "RBNode" || v[0] === "RBEmpty") {
- function cons(k){ return function(v) { return function(acc) { return ["Cons",["Tuple2",k,v],acc]; }; }; }
- var list = Elm.Dict.foldr(cons)(["Nil"])(v);
- var name = "Dict";
- if (list[0] === "Cons" && list[1][2][0] === "Tuple0") {
- name = "Set";
- list = Elm.List.map(function(x) { return x[1]; })(list);
- }
- return "(" + name + ".fromList " + toString(list) + ")";
- } else {
- var output = "";
- for (var i = v.length; --i; ) { output = ' ' + toString(v[i]) + output; }
- output = v[0] + output;
- return (v.length > 1) ? "(" + output + ")" : output;
- }
- }
- return v+"";
- };
- var show = function(v) { return str(toString(v)); };
- var append = function(xs,ys) {
- if (typeof xs === "string" && typeof ys === "string") {
- return xs.concat(ys);
- }
- if (xs[0] === "Nil") {
- return ys;
- }
- var root = ["Cons", xs[1], ["Nil"]];
- var curr = root;
- xs = xs[2];
- while (xs[0]==="Cons") {
- curr[2] = ["Cons", xs[1], ["Nil"]];
- xs = xs[2];
- curr = curr[2];
- }
- curr[2] = ys;
- return root;
- };
-
- var str = function(s) {
- var out = ["Nil"];
- for (var i = s.length; i--; ) {
- out = ["Cons", s[i], out];
- }
- return out;
- };
-
- function wrap(elem) {
- var p = Value.getSize(elem);
- return ["Element", Guid.guid(), ["EHtml",elem],
- p[0], p[1], 1, ["Nothing"], ["Nothing"]];
- }
- var addListener = function() {
- if(document.addEventListener) {
- return function(element, event, handler) {
- element.addEventListener(event, handler, false);
- };
- } else {
- return function(element, event, handler) {
- element.attachEvent('on' + event, handler);
- };
- }
- }();
-
- return {eq:eq,
- str:str,
- show:show,
- Tuple:Tuple,
- append:append,
- listToArray:listToArray,
- toText : toText,
- properEscape : properEscape,
- getTextSize : getTextSize,
- getSize : getSize,
- getExcess : getExcess,
- groupForms : groupForms,
- wrap : wrap,
- addListener : addListener
- };
-}();Elm.List = function() {
-
- var throwError = function(f) {
- throw new Error("Function '" + f + "' expecting a list!");
- }
-
- function length(xs) {
- var out = 0;
- while (xs[0] === "Cons") {
- out += 1;
- xs = xs[2];
- }
- return out;
- };
- var reverse = foldl(function(x_72) {
- return function(y_73) {
- return["Cons", x_72, y_73]
- }
- })(["Nil"]);
- var concat = foldr(function(x_74) {
- return function(y_75) {
- return Value.append(x_74, y_75)
- }
- })(["Nil"]);
- var and = foldl(function(x_77) {
- return function(y_78) {
- return x_77 && y_78
- }
- })(true);
- var or = foldl(function(x_79) {
- return function(y_80) {
- return x_79 || y_80
- }
- })(false);
- var sum = foldl(function(x_89) {
- return function(y_90) {
- return x_89 + y_90
- }
- })(0);
- var product = foldl(function(x_91) {
- return function(y_92) {
- return x_91 * y_92
- }
- })(1);
- var maximum = foldl1(function(x) { return function(y) { return Math.max(x,y) } });
- var minimum = foldl1(function(x) { return function(y) { return Math.min(x,y) } });
- function head(v) {
- if (v[0] !== "Cons") {
- throw new Error("Error: 'head' only accepts lists of length greater than one.");
- }
- return v[1];
- }
- function tail(v) {
- if (v[0] !== "Cons") {
- throw new Error("Error: 'tail' only accepts lists of length greater than one.");
- }
- return v[2];
- }
- function last(v) {
- if (v[0] !== "Cons") {
- throw new Error("Error: 'last' only accepts lists of length greater than one.");
- }
- var out = v[1];
- while (v[0] === "Cons") {
- out = v[1];
- v = v[2];
- }
- return out;
- }
- function map(f) {
- return function(xs) {
- if (xs[0] === "Nil") { return xs; }
- if (xs[0] !== "Cons") { throwError('map'); }
- var root = ["Cons", f(xs[1]), ["Nil"]];
- var curr = root;
- xs = xs[2];
- while (xs[0]==="Cons") {
- curr[2] = ["Cons", f(xs[1]), ["Nil"]];
- xs = xs[2];
- curr = curr[2];
- }
- return root;
- }
- }
- function foldl(f) {
- return function(b) {
- return function(xs) {
- var acc = b;
- if (xs[0] === "Nil") { return acc; }
- if (xs[0] !== "Cons") { throwError('foldl'); }
- while (xs[0] === "Cons") {
- acc = f(xs[1])(acc);
- xs = xs[2];
- }
- return acc;
- }
- }
- }
- function foldr(f) {
- return function(b) {
- return function(xs) {
- var acc = b;
- if (xs[0] === "Nil") { return acc; }
- if (xs[0] !== "Cons") { throwError('foldr'); }
- var arr = [];
- while (xs[0] === "Cons") {
- arr.push(xs[1]);
- xs = xs[2];
- }
- for (var i = arr.length; i--; ) {
- acc = f(arr[i])(acc);
- }
- return acc;
- }
- }
- }
- function foldl1(f_49) {
- return function(_temp_50) {
- return function(v) {
- if("Cons" !== v[0]) {
- return undefined
- }else {
- var x_51 = v[1];
- var xs_52 = v[2];
- return foldl(f_49)(x_51)(xs_52)
- }
- }(_temp_50)
- }
- }
- function foldr1(f) {
- return function(xs) {
- if (xs[0] === "Nil") { throw new Error("'foldr1' requires an non-empty list.") }
- if (xs[0] !== "Cons") { throwError('foldr1'); }
- var arr = [];
- while (xs[0] === "Cons") {
- arr.push(xs[1]);
- xs = xs[2];
- }
- var acc = arr.pop();
- for (var i = arr.length; i--; ) {
- acc = f(arr[i])(acc);
- }
- return acc;
- }
- }
- function scanl(f) {
- return function(b) {
- return function(xs) {
- if (xs[0] === "Nil") { return ["Cons",b,["Nil"]]; }
- if (xs[0] !== "Cons") { throwError('scanl'); }
- var arr = [b];
- while (xs[0] === "Cons") {
- b = f(xs[1])(b);
- arr.push(b);
- xs = xs[2];
- }
- var out = ["Nil"];
- for (var i = arr.length; i--; ) {
- out = ["Cons", arr[i], out];
- }
- return out;
- }
- }
- }
- function scanl1(f) {
- return function(xs) {
- if (xs[0] !== "Cons") {
- throw new Error("Error: 'scanl1' requires a list of at least length 1.");
- }
- return scanl(f)(xs[1])(xs[2]);
- }
- }
- function filter(pred) {
- return function(xs) {
- if (xs[0] === "Nil") { return xs; }
- if (xs[0] !== "Cons") { throwError('filter'); }
- var arr = [];
- while (xs[0] === "Cons") {
- if (pred(xs[1])) { arr.push(xs[1]); }
- xs = xs[2];
- }
- var out = ["Nil"];
- for (var i = arr.length; i--; ) {
- out = ["Cons", arr[i], out];
- }
- return out;
- }
- }
- function concatMap(f_76) {
- return function(x) {
- return concat(map(f_76)(x))
- }
- }
- function all(pred) {
- return foldl(function(x) { return function(acc) {
- return acc && pred(x);
- };})(true);
- }
- function any(pred) {
- return foldl(function(x) { return function(acc) {
- return acc || pred(x);
- };})(false);
- }
- function partition(pred_93) {
- return function(lst_94) {
- return function() {
- var v = lst_94;
- var c = [function(v) {
- if("Nil" !== v[0]) {
- return undefined
- }else {
- return["Tuple2", ["Nil"], ["Nil"]]
- }
- }, function(v) {
- if("Cons" !== v[0]) {
- return undefined
- }else {
- var x_95 = v[1];
- var xs_96 = v[2];
- return function(v) {
- if("Tuple2" !== v[0]) {
- return undefined
- }else {
- var as_97 = v[1];
- var bs_98 = v[2];
- return pred_93(x_95) ? ["Tuple2", ["Cons", x_95, as_97], bs_98] : ["Tuple2", as_97, ["Cons", x_95, bs_98]]
- }
- }(partition(pred_93)(xs_96))
- }
- }];
- for(var i = c.length;i--;) {
- var r = c[i](v);
- if(r !== undefined) {
- return r
- }
- }
- }()
- }
- }
- function zipWith(f) {
- return function(listA) {
- return function(listB) {
- if (listA[0] === "Nil" || listB[0] === "Nil") { return ["Nil"]; }
- if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError('zipWith'); }
- var arr = [];
- while (listA[0] === "Cons" && listB[0] === "Cons") {
- arr.push(f(listA[1])(listB[1]));
- listA = listA[2];
- listB = listB[2];
- }
- var out = ["Nil"];
- for (var i = arr.length; i--; ) {
- out = ["Cons", arr[i], out];
- }
- return out;
- }
- }
- }
- function zip(listA) {
- return function(listB) {
- if (listA[0] === "Nil" || listB[0] === "Nil") { return ["Nil"]; }
- if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError('zip'); }
- var arr = [];
- while (listA[0] === "Cons" && listB[0] === "Cons") {
- arr.push(["Tuple2", listA[1], listB[1]]);
- listA = listA[2];
- listB = listB[2];
- }
- var out = ["Nil"];
- for (var i = arr.length; i--; ) {
- out = ["Cons", arr[i], out];
- }
- return out;
- }
- }
- function unzip(pairs_112) {
- return function() {
- var v = pairs_112;
- var c = [function(v) {
- if("Nil" !== v[0]) {
- return undefined
- }else {
- return["Tuple2", ["Nil"], ["Nil"]]
- }
- }, function(v) {
- if("Cons" !== v[0]) {
- return undefined
- }else {
- var p_113 = v[1];
- var ps_114 = v[2];
- return function(v) {
- if("Tuple2" !== v[0]) {
- return undefined
- }else {
- if("Tuple2" !== v[1][0]) {
- return undefined
- }else {
- var x_115 = v[1][1];
- var y_116 = v[1][2];
- if("Tuple2" !== v[2][0]) {
- return undefined
- }else {
- var xs_117 = v[2][1];
- var ys_118 = v[2][2];
- return["Tuple2", ["Cons", x_115, xs_117], ["Cons", y_116, ys_118]]
- }
- }
- }
- }(["Tuple2", p_113, unzip(ps_114)])
- }
- }];
- for(var i = c.length;i--;) {
- var r = c[i](v);
- if(r !== undefined) {
- return r
- }
- }
- }()
- }
- function intersperse(sep_119) {
- return function(xs_120) {
- return function() {
- var v = xs_120;
- var c = [function(v) {
- if("Nil" !== v[0]) {
- return undefined
- }else {
- return["Nil"]
- }
- }, function(v) {
- if("Cons" !== v[0]) {
- return undefined
- }else {
- var a_124 = v[1];
- if("Nil" !== v[2][0]) {
- return undefined
- }else {
- return["Cons", a_124, ["Nil"]]
- }
- }
- }, function(v) {
- if("Cons" !== v[0]) {
- return undefined
- }else {
- var a_121 = v[1];
- if("Cons" !== v[2][0]) {
- return undefined
- }else {
- var b_122 = v[2][1];
- var cs_123 = v[2][2];
- return["Cons", a_121, ["Cons", sep_119, intersperse(sep_119)(["Cons", b_122, cs_123])]]
- }
- }
- }];
- for(var i = c.length;i--;) {
- var r = c[i](v);
- if(r !== undefined) {
- return r
- }
- }
- }()
- }
- }
- function intercalate(sep_125) {
- return function(xs_126) {
- return function() {
- var v = xs_126;
- var c = [function(v) {
- if("Nil" !== v[0]) {
- return undefined
- }else {
- return["Nil"]
- }
- }, function(v) {
- if("Cons" !== v[0]) {
- return undefined
- }else {
- var a_130 = v[1];
- if("Nil" !== v[2][0]) {
- return undefined
- }else {
- return a_130
- }
- }
- }, function(v) {
- if("Cons" !== v[0]) {
- return undefined
- }else {
- var a_127 = v[1];
- if("Cons" !== v[2][0]) {
- return undefined
- }else {
- var b_128 = v[2][1];
- var cs_129 = v[2][2];
- return Value.append(a_127, Value.append(sep_125, intercalate(sep_125)(["Cons", b_128, cs_129])))
- }
- }
- }];
- for(var i = c.length;i--;) {
- var r = c[i](v);
- if(r !== undefined) {
- return r
- }
- }
- }()
- }
- }
- function sort(xs) {
- if (xs[0] === "Nil") { return xs; }
- if (xs[0] !== "Cons") { throwError('sort'); }
- var arr = [];
- while (xs[0] === "Cons") {
- arr.push(xs[1]);
- xs = xs[2];
- }
- arr.sort(function(a,b) { return a - b});
- var out = ["Nil"];
- for (var i = arr.length; i--; ) {
- out = [ "Cons", arr[i], out ];
- }
- return out;
- }
- function take(n) { return function(xs) {
- if (n <= 0) { return ["Nil"]; }
- if (xs[0] === "Nil") { return xs; }
- if (xs[0] !== "Cons") { throwError('take'); }
- var out = [ "Cons", xs[1], ["Nil"] ];
- var temp = out;
- xs = xs[2];
- --n;
- while (xs[0] === "Cons" && n > 0) {
- temp[2] = [ "Cons", xs[1], ["Nil"] ];
- temp = temp[2];
- xs = xs[2];
- --n;
- }
- return out;
- };
- }
- function drop(n) { return function(xs) {
- if (xs[0] === "Nil") { return xs; }
- if (xs[0] !== "Cons") { throwError('drop'); }
- while (xs[0] === "Cons" && n > 0) {
- xs = xs[2];
- --n;
- }
- return xs;
- };
- }
- return {head:head,
- tail:tail,
- last:last,
- map:map,
- foldl:foldl,
- foldr:foldr,
- foldl1:foldl1,
- foldr1:foldr1,
- scanl:scanl,
- scanl1:scanl1,
- filter:filter,
- length:length,
- reverse:reverse,
- concat:concat,
- concatMap:concatMap,
- and:and,
- or:or,
- all:all,
- any:any,
- sum:sum,
- product:product,
- maximum:maximum,
- minimum:minimum,
- partition:partition,
- zipWith:zipWith,
- zip:zip,
- unzip:unzip,
- intersperse:intersperse,
- intercalate:intercalate,
- sort:sort,
- take:take,
- drop:drop};
-}();/*! Maybe
-!*/
-
-/*[Definition]*/
-
-/** data Maybe a = Just a | Nothing
- The Maybe datatype. Useful when a computation may or may not
- result in a value (e.g. logarithm is defined only for positive numbers).
-**/
-
-/*[Basic Utilities]*/
-
-/** maybe : b -> (a -> b) -> Maybe a -> b
- Apply a function to the contents of a `Maybe`.
- Return default when given `Nothing`.
-**/
-/** isJust : Maybe a -> Bool
- Check if constructed with `Just`.
-**/
-/** isNothing : Maybe a -> Bool
- Check if constructed with `Nothing`.
-**/
-
-/*[Maybe with Lists]*/
-
-/** cons : Maybe a -> [a] -> [a]
- If `Just`, adds the value to the front of the list.
- If `Nothing`, list is unchanged.
-**/
-/** justs : [Maybe a] -> [a]
- Filters out Nothings and extracts the remaining values.
-**/
-
-Elm.Maybe = function() {
- function consMaybe(x) { return function(xs) {
- if (x[0] === "Just") return ["Cons", x[1], xs];
- return xs;
- };
- }
- function mapCons(f) { return function(y) { return function(xs) {
- var x = f(y);
- if (x[0] === "Just") return ["Cons", x[1], xs];
- return xs;
- };
- };
- }
- function maybe(b) { return function(f) { return function(m) {
- if (m[0] === "Just") return f(m[1]);
- return b;
- };
- };
- }
-
- return {Just : function(x) { return ["Just",x]; },
- Nothing : ["Nothing"],
- justs : Elm.List.foldr(consMaybe)(["Nil"]),
- isJust : function(m) { return m[0] === "Just"; },
- isNothing : function(m) { return m[0] === "Nothing"; },
- cons : consMaybe,
- maybe : maybe
- };
-}();
-/*! Either
-!*/
-
-
-Elm.Either = function() {
- /*[Definition]*/
-
- /** data Either a b = Left a | Right b
- Represents any data that can take two different types.
-
- This can also be used for error handling (`Either String a`) where
- error messages are stored on the left, and the correct values
- ("right" values) are stored on the right.
- **/
- function Left(a1) { return ['Left',a1]; }
- function Right(a1){ return ['Right',a1]; }
-
- /*[Basics]*/
-
- /** either : (a -> c) -> (b -> c) -> Either a b -> c
- Apply the first function to a `Left` and the second function to a `Right`.
- This allows the extraction of a value from an `Either`.
- **/
- function either(f){ return function(g){ return function(e){
- switch(e[0]){
- case 'Left': return f(e[1]);
- case 'Right': return g(e[1]);
- }
- };};}
-
- /** isLeft : Either a b -> Bool
- True if the value is a `Left`.
- **/
- function isLeft(e) { return e[0] == 'Left'; }
-
- /** isRight : Either a b -> Bool
- True if the value is a `Right`.
- **/
- function isRight(e) { return e[0] == 'Right'; }
-
- /*[With Lists]*/
-
- function get(es) { return Elm.List.map(function(x){return x[1];})(es); }
-
- /** lefts : [Either a b] -> [a]
- Keep only the values held in `Left` values.
- **/
- function lefts(es) { return get(Elm.List.filter(isLeft)(es)); }
-
- /** rights : [Either a b] -> [a]
- Keep only the values held in `Right` values.
- **/
- function rights(es) { return get(Elm.List.filter(isRight)(es)); }
-
- /** partition : [Either a b] -> ([a],[b])
- Split into two lists, lefts on the left and rights on the right.
- So we have the equivalence:
-
- partition es == (lefts es, rights es)
- **/
- function partition(es) {
- var lrs = Elm.List.partition(isLeft)(es);
- lrs[1] = get(lrs[1]);
- lrs[2] = get(lrs[2]);
- return lrs;
- }
- return {Left:Left,
- Right:Right,
- either:either,
- isLeft:isLeft,
- isRight:isRight,
- lefts:lefts,
- rights:rights,
- partition:partition};
-}();
-/*! Char !*/
-
-/*[Classification]*/
-
-/** isUpper : Char -> Bool
- Selects upper case letters.
-**/
-/** isLower : Char -> Bool
- Selects lower case letters.
-**/
-/** isDigit : Char -> Bool
- Selects ASCII digits (0..9).
-**/
-/** isOctDigit : Char -> Bool
- Selects ASCII octal digits (0..7).
-**/
-/** isHexDigit : Char -> Bool
- Selects ASCII hexadecimal digits (0..9a..fA..F).
-**/
-
-/*[Conversion]*/
-
-/** toUpper : Char -> Char
- Convert to upper case.
-**/
-/** toLower : Char -> Char
- Convert to lower case.
-**/
-/** toLocaleUpper : Char -> Char
- Convert to upper case, according to any locale-specific case mappings.
-**/
-/** toLocaleLower : Char -> Char
- Convert to lower case, according to any locale-specific case mappings.
-**/
-/** toCode : Char -> Int
- Convert to unicode.
-**/
-/** fromCode : Int -> Char
- Convert from unicode.
-**/
-
-Elm.Char = function() {
- function isBetween(lo,hi) { return function(chr) {
- var c = chr.charCodeAt(0);
- return lo <= c && c <= hi;
- };
- }
- var isDigit = isBetween('0'.charCodeAt(0),'9'.charCodeAt(0));
- var chk1 = isBetween('a'.charCodeAt(0),'f'.charCodeAt(0));
- var chk2 = isBetween('A'.charCodeAt(0),'F'.charCodeAt(0));
-
- return {fromCode : function(c) { return String.fromCharCode(c); },
- toCode : function(c) { return c.charCodeAt(0); },
- toUpper : function(c) { return c.toUpperCase(); },
- toLower : function(c) { return c.toLowerCase(); },
- toLocaleUpper : function(c) { return c.toLocaleUpperCase(); },
- toLocaleLower : function(c) { return c.toLocaleLowerCase(); },
- isLower : isBetween('a'.charCodeAt(0),'z'.charCodeAt(0)),
- isUpper : isBetween('A'.charCodeAt(0),'Z'.charCodeAt(0)),
- isDigit : isDigit,
- isOctDigit : isBetween('0'.charCodeAt(0),'7'.charCodeAt(0)),
- isHexDigit : function(c) { return isDigit(c) || chk1(c) || chk2(c); }
- };
-}();
-Elm.Color = function() {
-
-function Color_0(a1) {
- return function(a2) {
- return function(a3) {
- return function(a4) {
- return["Color", a1, a2, a3, a4]
- }
- }
- }
-}
-var rgba_1 = Color_0;
-var red_3 = ["Color",255,0,0,1];
-var green_4 = ["Color",0,255,0,1];
-var blue_5 = ["Color",0,0,255,1];
-var yellow_6 = ["Color",255,255,0,1];
-var cyan_7 = ["Color",0,255,255,1];
-var magenta_8 = ["Color",255,0,255,1];
-var black_9 = ["Color",0,0,0,1];
-var white_10 = ["Color",255,255,255,1];
-var gray_11 = ["Color",128,128,128,1];
-var grey_12 = ["Color",128,128,128,1];
-function rgb_2(r_13) {
- return function(g_14) {
- return function(b_15) {
- return ["Color",r_13,g_14,b_15,1]
- }
- }
-}
-function extract(c) {
- if (c[4] === 1) { return 'rgb(' + c[1] + ',' + c[2] + ',' + c[3] + ')'; }
- return 'rgba(' + c[1] + ',' + c[2] + ',' + c[3] + ',' + c[4] + ')';
-}
-function complement(rgb) {
- var hsv = toHSV(rgb);
- hsv.hue = (hsv.hue + 180) % 360;
- return toRGB(hsv);
-}
-
-function hsva(h) { return function(s) { return function(v) { return function(a) {
- var clr = toRGB({hue:h, saturation:s, value:v});
- clr[4] = a;
- return clr;
- }; }; };
-}
-
-function hsv(h) { return function(s) { return function(v) {
- return toRGB({hue:h, saturation:s, value:v}); }; }; }
-
-function toHSV(rgb) {
- var hsv = {};
- var r = rgb[1] / 255.0, g = rgb[2] / 255.0, b = rgb[3] / 255.0;
- var M = Math.max(r,g,b);
- var m = Math.min(r,g,b);
- var c = M - m;
-
- var h = 0;
- if (c === 0) { h = 0; }
- else if (M === r) { h = ((g - b) / c) % 6; }
- else if (M === g) { h = ((b - r) / c) + 2; }
- else if (M === b) { h = ((r - g) / c) + 4; }
- h *= 60;
-
- return { value : M, hue : h, saturation : (M === 0 ? 0 : c / M) };
-}
-
-function between(lo,hi,x) { return lo <= x && x < hi; }
-function norm(n) { return Math.round(n*255); }
-
-function toRGB(hsv) {
- var c = hsv.value * hsv.saturation;
- var hue = hsv.hue / 60;
- var x = c * (1 - Math.abs((hue % 2) - 1));
- var r = 0, g = 0, b = 0;
- if (between(0,1,hue)) { r = c; g = x; b = 0; }
- else if (between(1,2,hue)) { r = x; g = c; b = 0; }
- else if (between(2,3,hue)) { r = 0; g = c; b = x; }
- else if (between(3,4,hue)) { r = 0; g = x; b = c; }
- else if (between(4,5,hue)) { r = x; g = 0; b = c; }
- else if (between(5,6,hue)) { r = c; g = 0; b = x; }
-
- var m = hsv.value - c;
- return ["Color", norm(r+m), norm(g+m), norm(b+m), 1 ];
-}
- return{rgba:rgba_1, rgb:rgb_2, hsva:hsva, hsv:hsv, red:red_3, green:green_4, blue:blue_5, yellow:yellow_6, cyan:cyan_7, magenta:magenta_8, black:black_9, white:white_10, gray:gray_11, grey:grey_12,complement:complement,extract:extract}
-}();
-var Collage = function() {
-
-var JS = Elm.JavaScript;
-
-function tracePoints(ctx,points) {
- var i = points.length - 1;
- if (i <= 0) return;
- ctx.moveTo(points[i][1], points[i][2]);
- while (i--) { ctx.lineTo(points[i][1], points[i][2]); }
-}
-
-function solid(ctx,color,points) {
- tracePoints(ctx,points);
- ctx.strokeStyle = Elm.Color.extract(color);
- ctx.stroke();
-};
-
-function filled(ctx,color,points) {
- tracePoints(ctx,points);
- ctx.fillStyle = Elm.Color.extract(color);
- ctx.fill();
-}
-
-function textured(redo,ctx,src,points) {
- var img = new Image();
- img.src = JS.castStringToJSString(src);
- img.onload = redo;
-
- tracePoints(ctx,points);
- ctx.fillStyle = ctx.createPattern(img,'repeat');
- ctx.fill();
-}
-
-function customLine(pattern,ctx,color,points) {
- if (pattern.length === 0) { pattern = [8,4]; }
- customLineHelp(ctx, pattern, points);
- ctx.strokeStyle = Elm.Color.extract(color);
- ctx.stroke();
-};
-
-var customLineHelp = function(ctx, pattern, points) {
- var i = points.length - 1;
- if (i <= 0) return;
- var x0 = points[i][1], y0 = points[i][2];
- var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
- var pindex = 0, plen = pattern.length;
- var draw = true, segmentLength = pattern[0];
- ctx.moveTo(x0,y0);
- while (i--) {
- x1 = points[i][1]; y1 = points[i][2];
- dx = x1 - x0; dy = y1 - y0;
- remaining = Math.sqrt(dx * dx + dy * dy);
- while (segmentLength <= remaining) {
- x0 += dx * segmentLength / remaining;
- y0 += dy * segmentLength / remaining;
- ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
- // update starting position
- dx = x1 - x0; dy = y1 - y0;
- remaining = Math.sqrt(dx * dx + dy * dy);
- // update pattern
- draw = !draw;
- pindex = (pindex + 1) % plen;
- segmentLength = pattern[pindex];
- }
- if (remaining > 0) {
- ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
- segmentLength -= remaining;
- }
- x0 = x1; y0 = y1;
- }
-};
-
-function drawLine(ctx,form) {
- var points = form[3][1];
- switch(form[1][0]) {
- case "Solid" : return solid(ctx,form[2],points);
- case "Dotted": return customLine([3,3],ctx,form[2],points);
- case "Dashed": return customLine([8,4],ctx,form[2],points);
- case "Custom": return customLine(form[1][1],ctx,form[2],points);
- }
-};
-
-function drawShape(redo,ctx,shapeStyle,color,points) {
- switch(shapeStyle[0]) {
- case "Filled": return filled(ctx,color,points);
- case "Outlined": return solid(ctx,color,points);
- case "Textured": return textured(redo,ctx,shapeStyle[1],points);
- case "CustomOutline":
- return customLine(shapeStyle[1],ctx,color,points);
- }
-};
-
-function drawImage(redo,ctx,w,h,src) {
- var img = new Image();
- img.onload = redo;
- img.src = JS.castStringToJSString(src);
- ctx.drawImage(img,-w/2,-h/2,w,h);
-}
-
-function renderForm(redo,ctx,theta,scale,x,y,form) {
- ctx.save();
- if (x !== 0 || y !== 0) ctx.translate(x,y);
- if (theta !== ~~theta) ctx.rotate(2*Math.PI*theta);
- if (scale !== 1) ctx.scale(scale,scale);
- ctx.beginPath();
- switch(form[0]) {
- case "FLine": drawLine(ctx,form); break;
- case "FShape": drawShape(redo,ctx,form[1],form[2],form[3][1]); break;
- case "FImage": drawImage(redo,ctx,form[1],form[2],form[3]); break;
- }
- ctx.restore();
-};
-
-function renderForms(redo,ctx,w,h,forms) {
- ctx.clearRect(0,0,w,h);
- for (var i = forms.length; i--; ) {
- var f = forms[i];
- renderForm(redo,ctx,f[1],f[2],f[3][1],f[3][2],f[4]);
- }
-}
-
-function collageForms(w,h,forms) {
- var canvas = Render.newElement('canvas');
- w = ~~w;
- h = ~~h;
- canvas.style.width = w + 'px';
- canvas.style.height = h + 'px';
- canvas.style.display = "block";
- canvas.width = w;
- canvas.height = h;
- if (canvas.getContext) {
- var ctx = canvas.getContext('2d');
- function redo() { renderForms(this,ctx,w,h,forms); }
- renderForms(redo,ctx,w,h,forms);
- return canvas;
- }
- canvas.innerHTML = "Your browser does not support the canvas element.";
- return canvas;
-};
-
-function applyTransforms(theta,scale,x,y,w,h,e) {
- var t = "translate(" + (x - w / 2) + "px,"+ (y - h / 2) + "px)";
- var r = theta === (~~theta) ? "" : "rotate(" + theta*360 + "deg)";
- var s = scale === 1 ? "" : "scale(" + scale + "," + scale + ")";
- var transforms = t + " " + s + " " + r;
- e.style.transform = transforms;
- e.style.msTransform = transforms;
- e.style.MozTransform = transforms;
- e.style.webkitTransform = transforms;
- e.style.OTransform = transforms;
-}
-
-function collageElement(w,h,theta,scale,x,y,elem) {
- var e = Render.render(elem);
- applyTransforms(theta,scale,x,y,elem[3],elem[4],e);
- var div = Render.newElement('div');
- Render.addTo(div,e);
- div.style.width = (~~w) + "px";
- div.style.height = (~~h) + "px";
- div.style.overflow = "hidden";
- return div;
-}
-
-function collage(w,h,formss) {
- if (formss.length === 0) { return collageForms(w,h,[]); }
- var elems = new Array(formss.length);
- for (var i = formss.length; i--; ) {
- var f = formss[i];
- if (typeof f[0] === "string") {
- elems[i] = collageElement(w,h,f[1],f[2],f[3][1],f[3][2],f[4][1]);
- } else {
- elems[i] = collageForms(w,h,f);
- }
- }
- if (formss.length === 1) { return elems[0]; }
- return Render.flowWith(Render.goIn,function(x){return x},elems);
-}
-
-function updateFormSet(node,currSet,nextSet) {
- if (Value.eq(nextSet,currSet)) return;
- var w = node.style.width.slice(0,-2) - 0;
- var h = node.style.height.slice(0,-2) - 0;
- if (typeof nextSet[0] === "object") {
- if (typeof currSet[0] === "object") {
- if (node.getContext) {
- var ctx = node.getContext('2d');
- function redo() { renderForms(this,ctx,w,h,nextSet); }
- return renderForms(redo,ctx,w,h,nextSet);
- }
- }
- var newNode = collageForms(w,h,nextSet);
- newNode.style.position = 'absolute';
- return node.parentNode.replaceChild(newNode,node);
- }
- node.style.width = (~~w) + "px";
- node.style.height = (~~h) + "px";
- var f = nextSet;
- var next = nextSet[4][1];
- Render.update(node.firstChild, currSet[4][1], next);
- applyTransforms(f[1],f[2],f[3][1],f[3][2],next[3],next[4],node.firstChild);
-}
-
-// assumes that the form sets are the same length.
-function updateCollage(node,currs,nexts) {
- if (nexts.length === 1) {
- return updateFormSet(node,currs[0],nexts[0]);
- }
- var kids = node.childNodes;
- var len = kids.length;
- for (var i = len; i--; ) {
- updateFormSet(kids[len-i-1], currs[i], nexts[i]);
- }
-}
-
-function style(clr,n,list) {
- return ["Tuple2",
- '' + n + '',
- list];
-}
-
-function insideForm(point) { return function(form) {
- if (!inBoundsOf(point[1],point[2],form)) return false;
- var hw, hh;
- switch (form[4][0]) {
- case "FShape": return insideShape(point,form[1],form[2],form[3],form[4][3][1]);
- case "FLine": return false;
- case "FImage":
- hw = form[4][1] / 2;
- hh = form[4][2] / 2;
- break;
- case "FElement":
- hw = form[4][1][3] / 2;
- hh = form[4][1][4] / 2;
- break;
- }
- return insideShape(point,form[1],form[2],form[3],
- [ [null, hw, hh],
- [null,-hw, hh],
- [null,-hw,-hh],
- [null, hw,-hh],
- [null, hw, hh] ]);
- };
-}
-
-function inBoundsOf(px,py,form) {
- if (form.length < 6) {
- var fx = form[3][1], fy = form[3][2];
- var radiusSquared = 0;
- var scale = form[2];
- switch (form[4][0]) {
- case "FShape":
- var points = form[4][3][1];
- for (var i = points.length; --i; ) {
- var p = points[i];
- radiusSquared = Math.max(radiusSquared, p[1]*p[1] + p[2]*p[2]);
- }
- radiusSquared *= scale * scale;
- break;
- case "FLine":
- break;
- case "FImage":
- var x = scale * form[4][1] / 2;
- var y = scale * form[4][2] / 2;
- radiusSquared = x*x + y*y;
- break;
- case "FElement":
- var x = scale * form[4][1][3] / 2;
- var y = scale * form[4][1][4] / 2;
- radiusSquared = x*x + y*y;
- break;
- }
- form.push(function(px,py) {
- var dx = px - fx;
- var dy = py - fy;
- return dx*dx + dy*dy < radiusSquared + 1;
- });
- }
- return form[5](px,py);
-}
-
-function insideShape(point,theta,scale,pos,points) {
- var counter = 0;
- var list = ["Nil"];
- var p1,p2;
-
- var x = (point[1] - pos[1]) / scale;
- var y = (point[2] - pos[2]) / scale;
- if (theta !== 0) {
- var t = -2 * Math.PI * theta;
- var nx = x * Math.cos(t) - y * Math.sin(t);
- y = x * Math.sin(t) + y * Math.cos(t);
- x = nx;
- }
-
- if (points.length === 0) { return false; }
- p1 = points[0];
- for (var i = points.length - 1; i--; ) {
- p2 = points[i];
- var p1x = p1[1], p1y = p1[2], p2x = p2[1], p2y = p2[2];
-
- if (p1y < p2y) {var ymin=p1y, ymax=p2y;} else {var ymin=p2y, ymax=p1y;}
- if (p1x < p2x) {var xmin=p1x, xmax=p2x;} else {var xmin=p2x, xmax=p1x;}
-
- if (ymin < y && y <= ymax && x <= xmax) {
- if (x <= xmin || x <= ((y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x)) {
- ++counter;
- }
- }
- p1 = p2;
- }
- return (counter % 2) === 1;
-}
-
-return {collage:collage, updateCollage:updateCollage, insideForm:insideForm};
-
-}();Elm.Graphics = function() {
- for (this['i'] in Elm.List) {
- eval('var ' + this['i'] + ' = Elm.List[this.i];');
- }
- var JS = Elm.JavaScript;
- var DLeft_0 = ["DLeft"];
- var DRight_1 = ["DRight"];
- var DUp_2 = ["DUp"];
- var DDown_3 = ["DDown"];
- var DIn_4 = ["DIn"];
- var DOut_5 = ["DOut"];
- function Absolute_12(a1) {
- return["Absolute", a1]
- }
- function Relative_13(a1) {
- return["Relative", a1]
- }
- var Near_14 = ["Near"];
- var Mid_15 = ["Mid"];
- var Far_16 = ["Far"];
- function Position_17(a1) {
- return function(a2) {
- return["Position", a1, a2]
- }
- }
- function PositionTL_18(a1) {
- return function(a2) {
- return["PositionTL", a1, a2]
- }
- }
- function PositionTR_19(a1) {
- return function(a2) {
- return["PositionTR", a1, a2]
- }
- }
- function PositionBL_20(a1) {
- return function(a2) {
- return["PositionBL", a1, a2]
- }
- }
- function PositionBR_21(a1) {
- return function(a2) {
- return["PositionBR", a1, a2]
- }
- }
- function Element_37(id,e,w,h,o,c,l) {
- return["Element", id, e, w, h, o, c, l ]
- }
- function EText_39(a1) {
- return function(a2) {
- return["EText", a1, a2]
- }
- }
- function EImage_40(a1) {
- return["EImage", JS.castStringToJSString(a1)]
- }
- function EVideo_41(a1) {
- return["EVideo", JS.castStringToJSString(a1)]
- }
- function EFittedImage_42(a1) {
- return["EFittedImage", JS.castStringToJSString(a1)]
- }
- function EFlow_43(a1) {
- return function(a2) {
- return["EFlow", a1, JS.castListToJSArray(a2)]
- }
- }
- function ECollage_44(a1) {
- return function(a2) {
- return function(a3) {
- return["ECollage", a1, a2, Value.groupForms(a3)]
- }
- }
- }
- var EEmpty_45 = ["EEmpty"];
- function EContainer_46(a1) {
- return function(a2) {
- return["EContainer", a1, a2]
- }
- }
- var Solid_68 = ["Solid"];
- var Dotted_69 = ["Dotted"];
- var Dashed_70 = ["Dashed"];
- function Custom_71(a1) {
- return["Custom", JS.castListToJSArray(a1)]
- }
- var Filled_72 = ["Filled"];
- var Outlined_73 = ["Outlined"];
- function CustomOutline_74(a1) {
- return["CustomOutline", JS.castListToJSArray(a1)]
- }
- function Line_75(a1) {
- return["Line", JS.castListToJSArray(a1)]
- }
- function Shape_78(a1) {
- return function(a2) {
- var points = JS.castListToJSArray(a1);
- if (points.length > 0) { points.push(points[0]); }
- return["Shape", points, a2];
- }
- }
- function Form_84(a1) {
- return function(a2) {
- return function(a3) {
- return function(a4) {
- return["Form", a1, a2, a3, a4]
- }
- }
- }
- }
- function FLine_85(a1) {
- return function(a2) {
- return function(a3) {
- return["FLine", a1, a2, a3]
- }
- }
- }
- function FShape_86(a1) {
- return function(a2) {
- return function(a3) {
- return["FShape", a1, a2, a3]
- }
- }
- }
- function FImage_87(a1) {
- return function(a2) {
- return function(a3) {
- return["FImage", a1, a2, JS.castStringToJSString(a3)]
- }
- }
- }
- function FElement_88(a1) {
- return["FElement", a1]
- }
- var left_6 = DLeft_0;
- var right_7 = DRight_1;
- var down_8 = DDown_3;
- var up_9 = DUp_2;
- var inward_10 = DIn_4;
- var outward_11 = DOut_5;
- var topLeft_22 = Position_17(Near_14)(Near_14);
- var topRight_23 = Position_17(Far_16)(Near_14);
- var bottomLeft_24 = Position_17(Near_14)(Far_16);
- var bottomRight_25 = Position_17(Far_16)(Far_16);
- var midLeft_26 = Position_17(Near_14)(Mid_15);
- var midRight_27 = Position_17(Far_16)(Mid_15);
- var midTop_28 = Position_17(Mid_15)(Near_14);
- var midBottom_29 = Position_17(Mid_15)(Far_16);
- var middle_30 = Position_17(Mid_15)(Mid_15);
- function middleAt(a1) {
- return function(a2) {
- return["PositionAt", a1, a2]
- }
- }
- var topLeftAt_31 = PositionTL_18;
- var topRightAt_32 = PositionTR_19;
- var bottomLeftAt_33 = PositionBL_20;
- var bottomRightAt_34 = PositionBR_21;
- var absolute_35 = Absolute_12;
- var relative_36 = Relative_13;
- function newElement_38(e,w,h,o,c,l) { return Element_37(Guid.guid(),e,w,h,o,c,l); }
- function basicNewElement(e,w,h) { return Element_37(Guid.guid(),e,w,h,1,["Nothing"],["Nothing"]); }
- var line_76 = Line_75;
- var polygon_79 = Shape_78;
- function sprite_96(src) {
- return function(w) {
- return function(h) {
- return function(pos) {
- return Form_84(0)(1)(pos)(FImage_87(w)(h)(src))
- }
- }
- }
- }
- function toForm_97(pos) {
- return function(e) {
- return Form_84(0)(1)(pos)(FElement_88(e))
- }
- }
- function width_47(w__101) {
- return function(e) {
- var be = e[2];
- switch(be[0]) {
- case "EImage":
- case "EVideo":
- return newElement_38(e[2],w__101,e[4] * w__101 / e[3], e[5], e[6], e[7]);
- case "EText":
- var p = Value.getTextSize(w__101,e[4],be[2]);
- return newElement_38(e[2], w__101, p[1], e[5], e[6], e[7]);
- }
- return newElement_38(e[2], w__101, e[4], e[5], e[6], e[7]);
- }
- }
- function height_48(h__108) {
- return function(e) {
- var be = e[2];
- switch(be[0]) {
- case "EImage":
- case "EVideo":
- return newElement_38(e[2], e[3] * h__108 / e[4], h__108, e[5], e[6], e[7]);
- }
- return newElement_38(e[2], e[3], h__108, e[5], e[6], e[7]);
- }
- }
- function size_49(w) {
- return function(h) {
- return function(e) {
- return newElement_38(e[2], w, h, e[5], e[6], e[7]);
- }
- }
- }
- function opacity_50(o) {
- return function(e) {
- return newElement_38(e[2], e[3], e[4], o, e[6], e[7]);
- }
- }
- function color_51(c) {
- return function(e) {
- return newElement_38(e[2], e[3], e[4], e[5], ["Just",c], e[7]);
- }
- }
- function link(lnk) {
- return function(e) {
- return newElement_38(e[2], e[3], e[4], e[5], e[6], ["Just", JS.castStringToJSString(lnk)]);
- }
- }
- function widthOf_52(e) { return ~~e[3]; }
- function heightOf_53(e) { return ~~e[4]; }
- function sizeOf_54(e) { return["Tuple2", ~~e[3], ~~e[4]] }
- function text_56(txt) {
- var p = Value.getTextSize(0,0,txt);
- return basicNewElement(EText_39("left")(txt), p[0], p[1])
- }
- function plainText(str) {
- var txt = Value.toText(str);
- var p = Value.getTextSize(0,0,txt);
- return basicNewElement(EText_39("left")(txt),p[0],p[1])
- }
- function asText(v) {
- var txt = Elm.Text.monospace(Value.toText(Value.show(v)));
- var p = Value.getTextSize(0,0,txt);
- return basicNewElement(EText_39("left")(txt),p[0],p[1])
- }
- function centeredText(txt) {
- var p = Value.getTextSize(0,0,txt);
- return basicNewElement(EText_39("center")(txt),p[0],p[1])
- }
- function justifiedText(txt) {
- var p = Value.getTextSize(0,0,txt);
- return basicNewElement(EText_39("justify")(txt),p[0],p[1])
- }
- function rightedText(txt) {
- var p = Value.getTextSize(0,0,txt);
- return basicNewElement(EText_39("right")(txt),p[0],p[1])
- }
- function image_57(w) {
- return function(h) {
- return function(src) {
- return basicNewElement(EImage_40(src),w,h)
- }
- }
- }
- function images(srcs) {
- var pics = Elm.Signal.constant(spacer_66(0)(0));
- var update = Elm.Signal.lift(function(src) {
- src = JS.castStringToJSString(src);
- var img = new Image();
- img.onload = function() {
- Dispatcher.notify(pics.id,
- image_57(this.width)(this.height)(src));
- };
- img.src = src;
- })(srcs);
- function f(x) { return function(y) { return x; } }
- var combine = Elm.Signal.lift2(f)(pics)(update);
- return combine;
- }
- function video_58(w) {
- return function(h) {
- return function(src) {
- return basicNewElement(EVideo_41(src),w,h)
- }
- }
- }
- function fittedImage_59(w_147) {
- return function(h_148) {
- return function(s_149) {
- return basicNewElement(EFittedImage_42(s_149),w_147,h_148)
- }
- }
- }
- function flow_60(dir_150) {
- return function(es_151) {
- return function() {
- var w_152 = function() {
- var ws_154 = map(widthOf_52)(es_151);
- return function(case1) {
- var case0 = case1;
- switch(case0[0]) {
- case "DLeft":
- return sum(ws_154);
- case "DRight":
- return sum(ws_154)
- }
- return maximum(ws_154)
- }(dir_150)
- }();
- var h_153 = function() {
- var hs_155 = map(heightOf_53)(es_151);
- return function(case3) {
- var case2 = case3;
- switch(case2[0]) {
- case "DDown":
- return sum(hs_155);
- case "DUp":
- return sum(hs_155)
- }
- return maximum(hs_155)
- }(dir_150)
- }();
- return basicNewElement(EFlow_43(dir_150)(es_151), w_152, h_153)
- }()
- }
- }
- function above_61(e1_156) {
- return function(e2_157) {
- return basicNewElement(EFlow_43(DDown_3)(["Cons", e1_156, ["Cons", e2_157, ["Nil"]]]), Math.max(widthOf_52(e1_156),widthOf_52(e2_157)), heightOf_53(e1_156) + heightOf_53(e2_157));
- }
- }
- function below_62(e1_158) {
- return function(e2_159) {
- return basicNewElement(EFlow_43(DDown_3)(["Cons", e2_159, ["Cons", e1_158, ["Nil"]]]), Math.max(widthOf_52(e1_158),widthOf_52(e2_159)), heightOf_53(e1_158) + heightOf_53(e2_159));
- }
- }
- function beside_63(e1_160) {
- return function(e2_161) {
- return basicNewElement(EFlow_43(DRight_1)(["Cons", e1_160, ["Cons", e2_161, ["Nil"]]]), widthOf_52(e1_160) + widthOf_52(e2_161), Math.max(heightOf_53(e1_160),heightOf_53(e2_161)));
- }
- }
- function layers_64(es_162) {
- return basicNewElement(EFlow_43(DOut_5)(es_162), maximum(map(widthOf_52)(es_162)), maximum(map(heightOf_53)(es_162)))
- }
- function collage_65(w_163) {
- return function(h_164) {
- return function(forms_165) {
- return basicNewElement(ECollage_44(w_163)(h_164)(forms_165),w_163,h_164)
- }
- }
- }
- function spacer_66(w_166) {
- return function(h_167) {
- return basicNewElement(EEmpty_45,w_166,h_167)
- }
- }
- function container_67(w_169) {
- return function(h_170) {
- return function(pos_168) {
- return function(e_171) {
- return basicNewElement(EContainer_46(pos_168)(e_171),w_169,h_170)
- }
- }
- }
- }
- function segment_77(p1_172) {
- return function(p2_173) {
- return Line_75(["Cons", p1_172, ["Cons", p2_173, ["Nil"]]])
- }
- }
- function rect_80(w_174) {
- return function(h_175) {
- return function(pos_176) {
- return Shape_78(["Cons", ["Tuple2", 0 - w_174 / 2, 0 - h_175 / 2],
- ["Cons", ["Tuple2", 0 - w_174 / 2, h_175 / 2],
- ["Cons", ["Tuple2", w_174 / 2, h_175 / 2],
- ["Cons", ["Tuple2", w_174 / 2, 0 - h_175 / 2], ["Nil"]]]]])(pos_176)
- }
- }
- }
- function oval_81(w_177) {
- return function(h_178) {
- return function(pos_179) {
- return function() {
- var n_180 = 50;
- return function() {
- function f_181(i_182) {
- return["Tuple2", w_177 / 2 * Math.cos(2 * (Math.PI / n_180) * i_182), h_178 / 2 * Math.sin(2 * (Math.PI / n_180) * i_182)];
- }
- return Shape_78(map(f_181)(function() {
- var lo = 0;
- var hi = n_180 - 1;
- var lst = ["Nil"];
- if(lo <= hi) {
- do {
- lst = ["Cons", hi, lst]
- }while(hi-- > lo)
- }
- return lst
- }()))(pos_179)
- }()
- }()
- }
- }
- }
- function circle_82(r_183) {
- return oval_81(2 * r_183)(2 * r_183)
- }
- function ngon_83(n_184) {
- return function(r_185) {
- return function(pos_186) {
- return function() {
- var m_187 = n_184;
- return function() {
- function f_188(i_189) {
- return["Tuple2", r_185 * Math.cos(2 * (Math.PI / m_187) * i_189), r_185 * Math.sin(2 * (Math.PI / m_187) * i_189)];
- }
- return Shape_78(map(f_188)(function() {
- var lo = 0;
- var hi = n_184 - 1;
- var lst = ["Nil"];
- if(lo <= hi) {
- do {
- lst = ["Cons", hi, lst]
- }while(hi-- > lo)
- }
- return lst
- }()))(pos_186)
- }()
- }()
- }
- }
- }
- function solid_89(clr_190) {
- return function(ln_191) {
- return Form_84(0)(1)(["Tuple2", 0, 0])(FLine_85(Solid_68)(clr_190)(ln_191))
- }
- }
- function dotted_90(clr_192) {
- return function(ln_193) {
- return Form_84(0)(1)(["Tuple2", 0, 0])(FLine_85(Dotted_69)(clr_192)(ln_193))
- }
- }
- function dashed_91(clr_194) {
- return function(ln_195) {
- return Form_84(0)(1)(["Tuple2", 0, 0])(FLine_85(Dashed_70)(clr_194)(ln_195))
- }
- }
- function customLine_92(pattern_196) {
- return function(clr_197) {
- return function(ln_198) {
- return Form_84(0)(1)(["Tuple2", 0, 0])(FLine_85(Custom_71(pattern_196))(clr_197)(ln_198))
- }
- }
- }
- function filled_93(clr) {
- return function(shape) {
- return Form_84(0)(1)(shape[2])(FShape_86(Filled_72)(clr)(shape));
- }
- }
- function outlined_94(clr) {
- return function(shape) {
- return Form_84(0)(1)(shape[2])(FShape_86(Outlined_73)(clr)(shape));
- }
- }
- function customOutline_95(pattern) {
- return function(clr) {
- return function(shape) {
- return Form_84(0)(1)(shape[2])(FShape_86(CustomOutline_74(pattern))(clr)(shape));
- }
- }
- }
- function textured(src) {
- return function(shape) {
- return Form_84(0)(1)(shape[2])(FShape_86(["Textured",src])(null)(shape));
- }
- }
- function rotate_98(t_212) {
- return function(Form$thetascaleposform_213) {
- return function(case5) {
- var case0 = case5;
- switch(case0[0]) {
- case "Form":
- var case1 = case0[1], case2 = case0[2], case3 = case0[3], case4 = case0[4];
- return Form_84(t_212 + case1)(case2)(case3)(case4)
- }
- throw new Error("Non-exhaustive pattern match in case");
- }(Form$thetascaleposform_213)
- }
- }
- function scale_99(s) {
- return function(form) {
- return Form_84(form[1])(s * form[2])(form[3])(form[4])
- }
- }
- function move_100(x_224) {
- return function(y_225) {
- return function(Form$thetascaleTuple2$pxpyform_226) {
- return function(case7) {
- var case0 = case7;
- switch(case0[0]) {
- case "Form":
- var case1 = case0[1], case2 = case0[2], case3 = case0[3], case4 = case0[4];
- switch(case3[0]) {
- case "Tuple2":
- var case5 = case3[1], case6 = case3[2];
- return Form_84(case1)(case2)(["Tuple2", x_224 + case5, y_225 + case6])(case4)
- }
- break
- }
- throw new Error("Non-exhaustive pattern match in case");
- }(Form$thetascaleTuple2$pxpyform_226)
- }
- }
- }
- return{left:left_6, right:right_7, down:down_8, up:up_9, inward:inward_10, outward:outward_11, topLeft:topLeft_22, topRight:topRight_23, bottomLeft:bottomLeft_24, bottomRight:bottomRight_25, midLeft:midLeft_26, midRight:midRight_27, midTop:midTop_28, midBottom:midBottom_29, middle:middle_30, middleAt:middleAt, topLeftAt:topLeftAt_31, topRightAt:topRightAt_32, bottomLeftAt:bottomLeftAt_33, bottomRightAt:bottomRightAt_34, absolute:absolute_35, relative:relative_36, width:width_47, height:height_48, size:size_49, opacity:opacity_50,
- color:color_51, link:link, widthOf:widthOf_52, heightOf:heightOf_53, sizeOf:sizeOf_54, text:text_56, asText:asText, plainText:plainText, centeredText:centeredText, justifiedText:justifiedText, rightedText:rightedText, image:image_57, images:images, video:video_58, fittedImage:fittedImage_59, flow:flow_60, above:above_61, below:below_62, beside:beside_63, layers:layers_64, collage:collage_65, spacer:spacer_66, container:container_67, line:line_76, segment:segment_77, polygon:polygon_79, rect:rect_80, oval:oval_81, circle:circle_82, ngon:ngon_83, solid:solid_89, dotted:dotted_90, dashed:dashed_91, customLine:customLine_92, filled:filled_93,
- outlined:outlined_94, customOutline:customOutline_95, textured:textured, sprite:sprite_96, toForm:toForm_97, rotate:rotate_98, scale:scale_99, move:move_100,
- isWithin: Collage.insideForm}
-}();
-Elm.Text = function() {
- function fromString(s) { return Value.toText(s); }
-
- var addTag = function(tag) { return function(text) {
- return '<' + tag + ' style="padding:0;margin:0">' + text + '' + tag + '>';
- };
- };
- var addStyle = function(style, value) { return function(text) {
- return "" + text + "";
- };
- };
-
- var typeface = function(name) {
- name = Elm.JavaScript.castStringToJSString(name);
- return addStyle('font-family', name);
- };
- var size = function(px) {
- return addStyle('font-size', px + 'px');
- };
- var header = addTag('h1');
- var height = function(h) { return addStyle('font-size', h+'em'); }
- var italic = addStyle('font-style', 'italic');
- var bold = addTag('b');
- var color = function(c) {
- return addStyle('color', Elm.Color.extract(c));
- };
- var underline = addStyle('text-decoration', 'underline');
- var overline = addStyle('text-decoration', 'overline');
- var strikeThrough = addStyle('text-decoration', 'line-through');
- var link = function(href) { return function(text) {
- return "" + text + "";
- };
- };
-
- return {fromString : fromString,
- toText: fromString,
- header : header,
- height : height,
- italic : italic,
- bold : bold,
- underline : underline,
- overline : overline,
- strikeThrough : strikeThrough,
- monospace : typeface('monospace'),
- typeface : typeface,
- color : color,
- link : link };
-}();
-
-var Render = function(){
-
-function newElement(elementType) {
- var e = document.createElement(elementType);
- e.style.padding = "0";
- e.style.margin = "0";
- return e;
-};
-
-function addTo(container, elem) {
- container.appendChild(elem);
-};
-
-function makeText(pos,txt) {
- var e = newElement('div');
- e.innerHTML = txt;
- e.style.textAlign = pos;
- return e;
-};
-
-function image(src) {
- var img = newElement('img');
- img.src = src;
- img.name = src;
- img.style.display = "block";
- return img;
-}
-
-function fittedImage(w,h,src) {
- var e = newElement('div');
- e.style.width = w + 'px';
- e.style.height = h + 'px';
- e.style.position = "relative";
- e.style.overflow = "hidden";
-
- var img = newElement('img');
- img.onload = function() {
- img.style.position = 'absolute';
- img.style.margin = 'auto';
-
- var sw = w, sh = h;
- if (w / h > this.width / this.height) {
- sh = Math.round(this.height * w / this.width);
- } else {
- sw = Math.round(this.width * h / this.height);
- }
- img.style.width = sw + 'px';
- img.style.height = sh + 'px';
- img.style.left = ((w - sw) / 2) + 'px';
- img.style.top = ((h - sh) / 2) + 'px';
- };
- img.src = src;
- img.name = src;
- addTo(e,img);
- return e;
-};
-
-var video = function(src) {
- var e = newElement('video');
- e.controls = "controls";
- var source = newElement('source');
- source.src = src;
- var segs = src.split('.');
- source.type = "video/" + segs[segs.length-1];
- addTo(e, source);
- e.style.display = "block";
- return e;
-};
-
-function divify(e) {
- var div = newElement('div');
- addTo(div, e);
- return div;
-};
-function goDown(e) {
- return e //.tagName === "DIV" ? e : divify(e);
-};
-function goRight(e) {
- e.style.styleFloat = "left";
- e.style.cssFloat = "left";
- return e;
-};
-function goIn(e) {
- e.style.position = 'absolute';
- return e;
-};
-function flowWith(f, prep, elist) {
- var container = newElement('div');
- for (var i = elist.length; i--; ) {
- addTo(container, f(prep(elist[i])));
- }
- return container;
-};
-
-function flow(dir,elist) {
- switch(dir) {
- case "DDown": elist = elist.slice(0).reverse();
- case "DUp": return flowWith(goDown,render,elist);
- case "DRight": elist = elist.slice(0).reverse();
- case "DLeft": return flowWith(goRight,render,elist);
- case "DOut": elist = elist.slice(0).reverse();
- case "DIn": return flowWith(goIn,render,elist);
- };
-};
-
-function toPos(pos) {
- switch(pos[0]) {
- case "Absolute": return pos[1] + "px";
- case "Relative": return (pos[1] * 100) + "%";
- }
-}
-
-function setPos(pos,e) {
- e.style.position = 'absolute';
- e.style.margin = 'auto';
- switch(pos[0]) {
- case "Position":
- if (pos[1][0] !== "Far") e.style.left = 0;
- if (pos[1][0] !== "Near") e.style.right = 0;
- if (pos[2][0] !== "Far") e.style.top = 0;
- if (pos[2][0] !== "Near") e.style.bottom = 0;
- break;
- case "PositionAt":
- e.style.top = toPos(pos[2]);
- e.style.left = toPos(pos[1]);
- var shift = "translate(" + ~~(-e.style.width.slice(0,-2) / 2) + "px," + ~~(-e.style.height.slice(0,-2) / 2) + "px)";
- e.style.transform = shift;
- e.style.msTransform = shift;
- e.style.MozTransform = shift;
- e.style.webkitTransform = shift;
- e.style.OTransform = shift;
- break;
- default:
- var p = pos[0].slice(-2);
- e.style[p[0] === "T" ? 'top' : 'bottom'] = toPos(pos[2]);
- e.style[p[1] === "L" ? 'left' : 'right'] = toPos(pos[1]);
- }
-}
-
-function container(pos,elem) {
- var e = render(elem);
- setPos(pos,e);
- var div = newElement('div');
- div.style.position = "relative";
- div.style.overflow = "hidden";
- addTo(div,e);
- return div;
-};
-
-function render(elem) {
- var e = {};
- switch(elem[2][0]) {
- case "EText": e = makeText(elem[2][1],elem[2][2]); break;
- case "EImage": e = image(elem[2][1]); break;
- case "EVideo": e = video(elem[2][1]); break;
- case "EFittedImage": e = fittedImage(elem[3],elem[4],elem[2][1]); break;
- case "EFlow": e = flow(elem[2][1][0],elem[2][2]); break;
- case "ECollage": e = Collage.collage(elem[2][1],elem[2][2],elem[2][3]); break;
- case "EEmpty": e = newElement('div'); break;
- case "EContainer": e = container(elem[2][1],elem[2][2]); break;
- case "EHtml":
- e = elem[2][1];
- if (e.type !== 'button') {
- var p = Value.getExcess(e);
- elem[3] -= p[0];
- elem[4] -= p[1];
- }
- break;
- case "EExternalHtml":
- e = newElement('div');
- addTo(e, elem[2][1]);
- break;
- }
- e.id = elem[1];
- e.style.width = (~~elem[3]) + 'px';
- e.style.height = (~~elem[4]) + 'px';
- if (elem[5] !== 1) { e.style.opacity = elem[5]; }
- if (elem[6][0] === "Just") {
- e.style.backgroundColor = Elm.Color.extract(elem[6][1]);
- }
- if (elem[7][0] === "Just") {
- var a = newElement('a');
- a.href = elem[7][1];
- addTo(a,e);
- return a;
- }
- return e;
-};
-
-function update(node,curr,next) {
- if (node.tagName === 'A') { node = node.firstChild; }
- if (curr[1] === next[1]) return;
- if (curr[2][0] !== next[2][0]) {
- return node.parentNode.replaceChild(render(next),node);
- }
- var nextE = next[2], currE = curr[2];
- switch(nextE[0]) {
- case "EText":
- if (nextE[1] !== currE[1]) node.style.textAlign = nextE[1];
- if (nextE[2] !== currE[2]) node.innerHTML = nextE[2];
- break;
- case "EImage":
- if (nextE[1] !== currE[1]) node.src = nextE[1];
- break;
- case "EVideo":
- case "EFittedImage":
- if (!Value.eq(nextE,currE) || next[3]!==curr[3] || next[4]!==curr[4]) {
- return node.parentNode.replaceChild(render(next),node);
- }
- break;
- case "ECollage":
- if (nextE[1] !== currE[1] || nextE[2] !== currE[2] || nextE[3].length !== currE[3].length) {
- return node.parentNode.replaceChild(render(next),node);
- }
- Collage.updateCollage(node,currE[3],nextE[3]);
- break;
- case "EFlow":
- if (nextE[1] !== currE[1]) {
- return node.parentNode.replaceChild(render(next),node);
- }
- var nexts = nextE[2];
- var kids = node.childNodes;
- if (nexts.length !== kids.length) {
- return node.parentNode.replaceChild(render(next),node);
- }
- var currs = currE[2];
- var goDir = function(x) { return x; };
- switch(nextE[1][0]) {
- case "DDown": case "DUp": goDir = goDown; break;
- case "DRight": case "DLeft": goDir = goRight; break;
- case "DOut": case "DIn": goDir = goIn; break;
- }
- for (var i = kids.length; i-- ;) {
- update(kids[i],currs[i],nexts[i]);
- goDir(kids[i]);
- }
- break;
- case "EContainer":
- update(node.childNodes[0],currE[2],nextE[2]);
- setPos(nextE[1],node.childNodes[0]);
- break;
- case "EEmpty":
- break;
- case "EHtml":
- if (next[1] !== curr[1]) {
- var e = render(next);
- node.parentNode.replaceChild(e,node);
- node = e;
- }
- if (e.type !== 'button') {
- var p = Value.getExcess(node);
- next[3] -= p[0];
- next[4] -= p[1];
- }
- break;
- case "EExternalHtml":
- if (next[1] !== curr[1])
- node.parentNode.replaceChild(render(next),node);
- break;
- }
- if (next[3] !== curr[3]) node.style.width = (~~next[3]) + 'px';
- if (next[4] !== curr[4]) node.style.height = (~~next[4]) + 'px';
- if (next[5] !== curr[5]) node.style.opacity = next[5];
- if (next[6].length === 2) {
- var clr = Elm.Color.extract(next[6][1]);
- if (clr !== node.style.backgroundColor) node.style.backgroundColor = clr;
- }
- if (next[7].length === 2) {
- if (curr[7].length === 1 || next[7][1] !== curr[7][1]) node.parentNode.href = next[7][1];
- }
- next[1] = curr[1];
-}
-
-return {render:render,update:update,addTo:addTo,newElement:newElement,flowWith:flowWith,goIn:goIn};
-
-}();
-Elm.Signal = function() {
- var send = function(node, timestep, changed) {
- var kids = node.kids;
- for (var i = kids.length; i--; ) {
- kids[i].recv(timestep, changed, node.id);
- }
- };
- function input(base) {
- this.id = Guid.guid();
- this.value = base;
- this.kids = [];
- this.defaultNumberOfKids = 0;
- this.recv = function(timestep, eid, v) {
- var changed = eid === this.id;
- if (changed) { this.value = v; }
- send(this, timestep, changed);
- return changed;
- };
- Dispatcher.inputs.push(this);
- };
- function lift(func,args) {
- this.id = Guid.guid();
- this.value = null;
- this.kids = [];
- this.count = 0;
- this.changed = false;
-
- args.reverse();
- this.recalc = function() {
- var f = func;
- for (var i = args.length; i--; ) {
- f = f(args[i].value);
- }
- this.value = f;
- };
- this.recalc();
-
- this.recv = function(timestep, changed, parentID) {
- this.count += 1;
- if (changed) { this.changed = true; }
- if (this.count == args.length) {
- if (this.changed) { this.recalc() }
- send(this, timestep, this.changed);
- this.changed = false;
- this.count = 0;
- }
- };
- for (var i = args.length; i--; ) {
- args[i].kids.push(this);
- }
- };
- function fold(func,base,baseIsFunc,input) {
- this.id = Guid.guid();
- this.value = baseIsFunc ? base(input.value) : base;
- this.kids = [];
- this.recv = function(timestep, changed, parentID) {
- if (changed) { this.value = func(input.value)(this.value); }
- send(this, timestep, changed);
- };
- input.kids.push(this);
- };
-
- function dropIf(pred,base,input) {
- this.id = Guid.guid();
- this.value = pred(input.value) ? base : input.value;
- this.kids = [];
- this.recv = function(timestep, changed, parentID) {
- var chng = changed && !pred(input.value);
- if (chng) { this.value = input.value; }
- send(this, timestep, chng);
- };
- input.kids.push(this);
- };
-
- function dropRepeats(input) {
- this.id = Guid.guid();
- this.value = input.value;
- this.kids = [];
- this.recv = function(timestep, changed, parentID) {
- var chng = changed && !Value.eq(this.value,input.value);
- if (chng) { this.value = input.value; }
- send(this, timestep, chng);
- };
- 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]); }; };
- };
-
- function timeIndex(pair,s) {
- this.id = Guid.guid();
- var t = (new window.Date).getTime();
- this.value = pair ? Value.Tuple(t,s.value) : t;
- this.kids = [];
- this.recv = function(timestep, changed, parentID) {
- if (changed) this.value = pair ? Value.Tuple(timestep, s.value) : timestep;
- send(this, timestep, changed);
- };
- s.kids.push(this);
- }
-
- function sampleOn(s1,s2) {
- this.id = Guid.guid();
- this.value = s2.value;
- this.kids = [];
- this.count = 0;
- this.changed = false;
-
- this.recv = function(timestep, changed, parentID) {
- if (parentID === s1.id) this.changed = changed;
- this.count += 1;
- if (this.count == 2) {
- if (this.changed) { this.value = s2.value; }
- send(this, timestep, this.changed);
- this.count = 0;
- this.changed = false;
- }
- };
- s1.kids.push(this);
- s2.kids.push(this);
- };
-
- function delay(t) { return function(s) {
- var delayed = new input(s.value);
- var firstEvent = true;
- function update(v) {
- if (firstEvent) return;
- setTimeout(function() { Dispatcher.notify(delayed.id,v); },t);
- }
- function first(a) { return function(b) { return a; }; }
- var out = new sampleOn(delayed,new lift(first, [delayed, new lift(update,[s])]));
- firstEvent = false;
- return out;
- };
- }
-
- function merge(s1,s2) {
- this.id = Guid.guid();
- this.value = s1.value;
- this.kids = [];
- this.next = null;
- this.count = 0;
- this.changed = false;
-
- this.recv = function(timestep, changed, parentID) {
- this.count += 1;
- if (changed) {
- this.changed = true;
- if (parentID == s2.id && this.next === null) { this.next = s2.value; }
- if (parentID == s1.id) { this.next = s1.value; }
- }
-
- if (this.count == 2) {
- if (this.changed) {
- this.value = this.next;
- this.next = null;
- }
- send(this, timestep, this.changed);
- this.changed = false;
- this.count = 0;
- }
- };
- s1.kids.push(this);
- s2.kids.push(this);
- };
-
- function merges(ss) {
- function mrg(x) { return function(y) { return new merge(x,y); }; }
- return Elm.List.foldl1(mrg)(ss);
- }
-
- function mergeEither(s1) { return function(s2) {
- function f(s) { return function(x) { return [s,x]; }; }
- return new merge(new lift(f('Left'),[s1]), new lift(f('Right'),[s2]));
- };
- }
-
- function average(sampleSize) { return function(s) {
- var sample = new Array(sampleSize);
- var i = sampleSize;
- while (i--) sample[i] = 0;
- i = 0;
- var full = false;
- var total = 0;
- function f(n) {
- total += n - sample[i];
- sample[i] = n;
- var avg = total / Math.max(1, full ? sampleSize : i);
- if (++i == sampleSize) { full = true; i = 0; }
- return avg;
- }
- return new lift(f, [s]);
- };
- }
-
- return {
- constant : function(v) { return new input(v); },
- lift : function(f){return function(e){return new lift(f,[e]);};},
- lift2 : function(f) {
- return function(e1) { return function(e2) {
- return new lift(f, [e1,e2]); };};},
- lift3 : function(f) {
- return function(e1) { return function(e2) {
- return function(e3){return new lift(f,[e1,e2,e3]);};};};},
- lift4 : function(f) {
- return function(e1) { return function(e2) {
- return function(e3) { return function(e4) {
- return new lift(f, [e1,e2,e3,e4]);};};};};},
- lift5 : function(f) {
- return function(e1) { return function(e2) {
- return function(e3) { return function(e4) {
- return function(e5) {
- return new lift(f, [e1,e2,e3,e4,e5]);};};};};};},
- lift6 : function(f) { return function(e1) { return function(e2) {
- return function(e3) { return function(e4) {
- return function(e5) { return function(e6) {
- return new lift(f, [e1,e2,e3,e4,e5,e6]); };};};};};};},
- lift7 : function(f) { return function(e1) { return function(e2) {
- return function(e3) { return function(e4) {
- return function(e5) { return function(e6) {
- return function(e7) {
- return new lift(f, [e1,e2,e3,e4,e5,e6,e7]);};};};};};};};},
- lift8 : function(f) { return function(e1) { return function(e2) {
- return function(e3) { return function(e4) {
- return function(e5) { return function(e6) {
- return function(e7) { return function(e8) {
- return new lift(f, [e1,e2,e3,e4,e5,e6,e7,e8]);};};};};};};};};},
- foldp : function(f) { return function(b) { return function(e) {
- return new fold(f,b,false,e); }; }; },
- foldp$ : function(f) { return function(b) { return function(e) {
- return new fold(f,b,true,e); }; }; },
- foldp1 : function(f) { return function(e) {
- return new fold(f,function(x){return x;},true,e); }; },
- delay : delay,
- merge : function(s1) { return function(s2) { return new merge(s1,s2)}; },
- merges : merges,
- mergeEither : mergeEither,
- average : average,
- count : function(sig) {
- var incr = function(_){return function(c){return c+1;};};
- return new fold(incr,0,false,sig) },
- countIf : function(pred) { return function(sig) {
- var incr = function(x){return function(c){return pred(x) ? c+1 : c;};};
- return new fold(incr,0,false,sig) }; },
- 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,
- dropRepeats : function(s) { return new dropRepeats(s);},
- sampleOn : function(s1){return function(s2){return new sampleOn(s1,s2);};},
- timestamp : function(s) { return new timeIndex(true, s); },
- timeOf : function(s) { return new timeIndex(false, s); }
- };
-}();
-var Dispatcher = function() {
- var program = null;
- var inputs = [];
- var currentElement = null;
-
- var initialize = function() {
- program = Elm.main();
- if (!('recv' in program)) {
- program = Elm.Signal.constant(program);
- }
-
- currentElement = program.value;
- filterDeadInputs();
-
- var content = document.getElementById('content');
- content.appendChild(Render.render(currentElement));
- var w = document.getElementById('widthChecker').offsetWidth;
- if (w !== window.innerWidth) {
- Dispatcher.notify(Elm.Window.dimensions.id, Value.Tuple(w, window.innerHeight));
- }
- program = Elm.Signal.lift(function(value) {
- var content = document.getElementById('content');
- Render.update(content.firstChild,currentElement,value);
- currentElement = value;
- return value;
- })(program);
- };
- var notify = function(id, v) {
- var timestep = (new window.Date).getTime();
- var hasListener = false;
- for (var i = inputs.length; i--; ) {
- hasListener = inputs[i].recv(timestep, id, v) || hasListener;
- }
- return hasListener;
- };
-
- function isAlive(input) {
- if (!('defaultNumberOfKids' in input)) return true;
- var len = input.kids.length;
- if (len == 0) return false;
- if (len > input.defaultNumberOfKids) return true;
- var alive = false;
- for (var i = len; i--; ) {
- alive = alive || isAlive(input.kids[i]);
- }
- return alive;
- }
- function filterDeadInputs() {
- var temp = [];
- for (var i = inputs.length; i--; ) {
- if (isAlive(inputs[i])) temp.push(inputs[i]);
- }
- inputs = temp;
- }
-
- return {initialize:initialize, notify:notify, inputs:inputs};
-}();
-/*! HTTP
-A library for asynchronous HTTP requests (AJAX). See the
-[WebSocket](http://elm-lang.org/docs/WebSocket.elm) library if
-you have very strict latency requirements.
-!*/
-
-Elm.HTTP = function() {
- var JS = Elm.JavaScript;
- var toElmString = Elm.JavaScript.castJSStringToString;
-
- /*[Creating Requests]*/
-
- /** get : String -> Request String
- Create a GET request to the given url.
- **/
- function get(url) { return request("GET")(url)(null)(["Nil"]); }
-
- /** post : String -> String -> Request String
- Create a POST request to the given url, carrying the given data.
- **/
- function post(url) { return function(data) {
- return request("POST")(url)(data)(["Nil"]); }; }
-
- /** request : String -> String -> String -> [(String,String)] -> Request String
- Create a customized request. Arguments are request type (get, post, put,
- delete, etc.), target url, data, and a list of additional headers.
- **/
- function request(verb) { return function(url) { return function(data) {
- return function(headers) {
- return {0 : "Request",
- length : 1,
- verb : JS.castStringToJSString(verb),
- url : JS.castStringToJSString(url),
- data : data === null ? null : JS.castStringToJSString(data),
- headers : headers }; }; }; };
- }
-
- function registerReq(queue,responses) { return function(req) {
- if (req.url !== "") { sendReq(queue,responses,req); }
- };
- }
-
- function updateQueue(queue,responses) {
- if (queue.length > 0) {
- Dispatcher.notify(responses.id, queue[0].value);
- if (queue[0].value[0] !== "Waiting") {
- queue.shift();
- setTimeout(function() { updateQueue(queue,responses); }, 0);
- }
- }
- }
-
- function sendReq(queue,responses,req) {
- var response = { value: ["Waiting"] };
- queue.push(response);
-
- var request = null;
- if (window.ActiveXObject) { request = new ActiveXObject("Microsoft.XMLHTTP"); }
- if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
- request.onreadystatechange = function(e) {
- if (request.readyState === 4) {
- response.value = (request.status === 200
- ? ["Success", toElmString(request.responseText)]
- : ["Failure", request.status,
- toElmString(request.statusText)]);
- setTimeout(function() { updateQueue(queue,responses); }, 0);
- }
- };
- request.open(req.verb, req.url, true);
- Elm.List.map(function(pair) {
- request.setRequestHeader(
- JS.castStringToJSString(pair[1]),
- JS.castStringToJSString(pair[2]));
- })(req.headers);
- request.send(req.data);
- return null;
- }
-
- /*[Responses]*/
-
- /** data Response a = Waiting | Success a | Failure Int String
- The datatype for responses. Success contains only the returned message.
- Failures contain both an error code and an error message.
- **/
-
- /*[Sending Requests]*/
-
- /** send : Signal (Request a) -> Signal (Response String)
- Performs an HTTP request with the given requests. Produces a signal
- that carries the responses.
- **/
- function send(requests) {
- var responses = Elm.Signal.constant(["Waiting"]);
- var sender = Elm.Signal.lift(registerReq([],responses))(requests);
- function f(x) { return function(y) { return x; } }
- return Elm.Signal.lift2(f)(responses)(sender);
- }
-
- /** sendGet : Signal String -> Signal (Response String)
- Performs an HTTP GET request with the given urls. Produces a signal
- that carries the responses.
- **/
-
- return {get : get,
- post : post,
- request : request,
- send : send,
- sendGet : function(urls){return send(Elm.Signal.lift(get)(urls));}
- };
-}();
-/*! WebSocket
-A library for low latency HTTP communication. See the HTTP library for standard
-requests like GET, POST, etc.
-!*/
-
-Elm.WebSocket = function() {
- var JS = Elm.JavaScript;
-
- /** open : String -> Signal String -> Signal String
- Create a web-socket. The first argument is the URL of the desired
- web-socket server. The input signal holds the outgoing messages,
- and the resulting signal contains the incoming ones.
- **/
- function open(url) { return function(outgoing) {
- var incoming = Elm.Signal.constant(["Nil"]);
- var ws = new window.WebSocket(JS.castStringToJSString(url));
-
- var pending = [];
- var ready = false;
-
- ws.onopen = function(e) {
- var len = pending.length;
- for (var i = 0; i < len; ++i) { ws.send(pending[i]); }
- ready = true;
- };
- ws.onmessage = function(event) {
- Dispatcher.notify(incoming.id, JS.castJSStringToString(event.data));
- };
-
- function send(msg) {
- var s = JS.castStringToJSString(msg);
- ready ? ws.send(s) : pending.push(s);
- }
-
- function take1(x) { return function(y) { return x; } }
- return Elm.Signal.lift2(take1)(incoming)(Elm.Signal.lift(send)(outgoing));
- };
- }
-
- return {open:open};
-}();
-
-Elm.Input = function() {
- var JS = Elm.JavaScript;
- var toElmString = Elm.JavaScript.castJSStringToString;
- var newTextInput = function(elem, ghostText) {
- elem.placeholder = JS.castStringToJSString(ghostText);
- var str = Elm.Signal.constant(["Nil"]);
- Value.addListener(elem, 'keyup', function(e) {
- Dispatcher.notify(str.id, toElmString(elem.value));
- elem.focus();
- });
- elem.style.padding = "1px";
- return Value.Tuple(Value.wrap(elem), str);
- };
- var newElement = function(name) {
- var e = document.createElement(name);
- e.style.padding = "0";
- e.style.margin = "0";
- return e;
- };
- var textArea = function(cols) { return function(rows) {
- var textarea = newElement('textarea');
- textarea.rows = rows;
- textarea.cols = cols;
- return newTextInput(textarea, "");
- };
- };
- var textField = function(ghostText) {
- var field = newElement('input');
- field.type = 'text';
- return newTextInput(field, ghostText);
- };
- var password = function(ghostText) {
- var field = newElement('input');
- field.type = 'password';
- return newTextInput(field, ghostText);
- };
- var checkbox = function(checked) {
- var box = newElement('input');
- box.type = 'checkbox';
- box.checked = checked;
- var status = Elm.Signal.constant(checked);
- Value.addListener(box, 'change', function(e) {
- Dispatcher.notify(status.id, box.checked);
- });
- return Value.Tuple(Value.wrap(box), status);
- };
- var dropDown = function(options) {
- var slct = newElement('select');
- var opts = [];
- while (options[0] === "Cons") {
- var opt = newElement('option');
- var str = Value.toText(options[1][1]);
- opt.value = str;
- opt.innerHTML = str;
- slct.appendChild(opt);
- opts.push(options[1][2]);
- options = options[2];
- }
- var status = Elm.Signal.constant(opts[0]);
- Value.addListener(slct, 'change', function(e) {
- Dispatcher.notify(status.id, opts[slct.selectedIndex]);
- });
- return Value.Tuple(Value.wrap(slct), status);
- };
- var stringDropDown = function(opts) {
- return dropDown(Elm.List.map (function(x) {return Value.Tuple(x,x);}) (opts));
- };
- var button = function(name) {
- var b = newElement('input');
- b.type = "button";
- b.value = JS.castStringToJSString(name);
- var press = Elm.Signal.constant(false);
- Value.addListener(b, 'click', function(e) {
- Dispatcher.notify(press.id, true);
- Dispatcher.notify(press.id, false);
- });
- return Value.Tuple(Value.wrap(b),press);
- };
- return {textArea:textArea, textField:textField,
- password:password, checkbox:checkbox,
- dropDown:dropDown, stringDropDown:stringDropDown,
- button:button};
-}();
-
-Elm.Keyboard = { Raw : function() {
- var keysDown = Elm.Signal.constant(["Nil"]);
- var charPressed = Elm.Signal.constant(["Nothing"]);
-
- function remove(x,xs) {
- if (xs[0] === "Nil") return xs;
- if (xs[1] === x) return xs[2];
- return ["Cons", xs[1], remove(x,xs[2])];
- }
- function has(x,xs) {
- while (xs[0] !== "Nil") {
- if (xs[1] === x) return true;
- xs = xs[2];
- }
- return false;
- }
- Value.addListener(document, 'keydown', function(e) {
- if (has(e.keyCode, keysDown.value)) return;
- var hasListener = Dispatcher.notify(keysDown.id, ["Cons", e.keyCode, keysDown.value]);
- if (!hasListener)
- this.removeEventListener('keydown',arguments.callee,false);
- });
- Value.addListener(document, 'keyup', function(e) {
- var codes = remove(e.keyCode, keysDown.value);
- var hasListener = Dispatcher.notify(keysDown.id, codes);
- if (!hasListener)
- this.removeEventListener('keyup',arguments.callee,false);
- });
- Value.addListener(window, 'blur', function(e) {
- var hasListener = Dispatcher.notify(keysDown.id, ["Nil"]);
- if (!hasListener)
- this.removeEventListener('blur',arguments.callee,false);
- });
- Value.addListener(document, 'keypress', function(e) {
- var hasListener = Dispatcher.notify(charPressed.id, ["Just",e.charCode || e.keyCode]);
- Dispatcher.notify(charPressed.id, ["Nothing"]);
- if (!hasListener)
- this.removeEventListener('keypress',arguments.callee,false);
- });
- return {keysDown:keysDown,
- charPressed:charPressed};
- }()
-};
-
-/*! Keyboard
-These are nicely curated inputs from the keyboard. See the
-[Keyboard.Raw library](/docs/Signal/KeyboardRaw.elm) for a
-lower-level interface that will let you define more complicated behavior.
-!*/
-
-(function() {
- function keySignal(f) {
- var signal = Elm.Signal.lift(f)(Elm.Keyboard.Raw.keysDown);
- Elm.Keyboard.Raw.keysDown.defaultNumberOfKids += 1;
- signal.defaultNumberOfKids = 0;
- return signal;
- }
-
- function dir(left,right,up,down) {
- function f(ks) {
- var x = 0, y = 0;
- while (ks[0] == "Cons") {
- switch (ks[1]) {
- case left : --x; break;
- case right: ++x; break;
- case up : ++y; break;
- case down : --y; break;
- }
- ks = ks[2];
- }
- return { _:[true], x:[x], y:[y] };
- }
- return keySignal(f);
- }
-
- function is(key) {
- function f(ks) {
- while (ks[0] == "Cons") {
- if (key == ks[1]) return true;
- ks = ks[2];
- }
- return false;
- }
- return keySignal(f);
- }
-
- /*[Directions]*/
-
- /** arrows : Signal { x:Int, y:Int }
- A signal of records indicating which arrow keys are pressed.
-
- `{ x = 0, y = 0 }` when pressing no arrows.
- `{ x =-1, y = 0 }` when pressing the left arrow.
- `{ x = 1, y = 1 }` when pressing the up and right arrows.
- `{ x = 0, y =-1 }` when pressing the down, left, and right arrows.
- **/
- Elm.Keyboard.arrows = dir(37,39,38,40);
-
- /** wasd : Signal { x:Int, y:Int }
- Just like the arrows signal, but this uses keys w, a, s, and d,
- which are common controls for many computer games.
- **/
- Elm.Keyboard.wasd = dir(65,68,87,83);
-
- /*[Modifiers]*/
-
- /** shift : Signal Bool
- Whether the shift key is pressed.
- **/
- Elm.Keyboard.shift = is(16);
-
- /** ctrl : Signal Bool
- Whether the control key is pressed.
- **/
- Elm.Keyboard.ctrl = is(17);
-
- /** space : Signal Bool
- Whether the space key is pressed.
- **/
- Elm.Keyboard.space = is(32);
-
-}());
-/*! Mouse
- !*/
-
-Elm.Mouse = function() {
- /*[Position]*/
-
- /** position : Signal (Int,Int)
- The current mouse position.
- **/
- var position = Elm.Signal.constant(Value.Tuple(0,0));
- position.defaultNumberOfKids = 2;
-
- /** x : Signal Int
- The current x-coordinate of the mouse.
- **/
- var x = Elm.Signal.lift(function(p){return p[1];})(position);
- x.defaultNumberOfKids = 0;
-
- /** y : Signal Int
- The current y-coordinate of the mouse.
- **/
- var y = Elm.Signal.lift(function(p){return p[2];})(position);
- y.defaultNumberOfKids = 0;
-
- /*[Button Status]*/
-
- /** isDown : Signal Bool
- The current state of the left mouse-button.
- True when the button is down, and false otherwise.
- **/
- var isDown = Elm.Signal.constant(false);
-
- /** isClicked : Signal Bool
- True immediately after the left mouse-button has been clicked,
- and false otherwise.
- **/
- var isClicked = Elm.Signal.constant(false);
-
- /** clicks : Signal ()
- Always equal to unit. Event triggers on every mouse click.
- **/
- var clicks = Elm.Signal.constant(Value.Tuple());
-
- function getXY(e) {
- var posx = 0;
- var posy = 0;
- if (!e) e = window.event;
- if (e.pageX || e.pageY) {
- posx = e.pageX;
- posy = e.pageY;
- } else if (e.clientX || e.clientY) {
- posx = e.clientX + document.body.scrollLeft +
- document.documentElement.scrollLeft;
- posy = e.clientY + document.body.scrollTop +
- document.documentElement.scrollTop;
- }
- return Value.Tuple(posx, posy);
- }
-
- Value.addListener(document, 'click', function(e) {
- var hasListener1 = Dispatcher.notify(isClicked.id, true);
- var hasListener2 = Dispatcher.notify(clicks.id, Value.Tuple());
- Dispatcher.notify(isClicked.id, false);
- if (!hasListener1 && !hasListener2)
- this.removeEventListener('click',arguments.callee,false);
- });
- Value.addListener(document, 'mousedown', function(e) {
- var hasListener = Dispatcher.notify(isDown.id, true);
- if (!hasListener)
- this.removeEventListener('mousedown',arguments.callee,false);
- });
- Value.addListener(document, 'mouseup', function(e) {
- var hasListener = Dispatcher.notify(isDown.id, false);
- if (!hasListener)
- this.removeEventListener('mouseup',arguments.callee,false);
- });
- Value.addListener(document, 'mousemove', function(e) {
- var hasListener = Dispatcher.notify(position.id, getXY(e));
- if (!hasListener)
- this.removeEventListener('mousemove',arguments.callee,false);
- });
-
- /** isClickedOn : Element -> (Element, Signal Bool)
- Determine whether an element has been clicked. The resulting pair
- is a signal of booleans that is true when its paired element has
- been clicked. The signal is True immediately after the left
- mouse-button has been clicked, and false otherwise.
- **/
- var clickedOn = function(elem) {
- var node = Render.render(elem);
- var click = Elm.Signal.constant(false);
- Value.addListener(node, 'click', function(e) {
- Dispatcher.notify(click.id, true);
- Dispatcher.notify(click.id, false);
- });
- return Value.Tuple(Value.wrap(node), click);
- };
- return {position: position,
- x:x,
- y:y,
- isClicked: isClicked,
- isDown: isDown,
- clicks: clicks,
- isClickedOn: clickedOn
- };
- }();/*! Random
- !*/
-
-Elm.Random = function() {
- /*[In a Range]*/
-
- /** inRange : Int -> Int -> Signal Int
- Given a range from low to high, this produces a random number
- between 'low' and 'high' inclusive. The value in the signal does
- not change after the page has loaded.
- **/
- var inRange = function(min) { return function(max) {
- return Elm.Signal.constant(Math.floor(Math.random() * (max-min+1)) + min);
- };
- };
-
- /** randomize : Int -> Int -> Signal a -> Signal Int
- Given a range from low to high and a signal of values, this produces
- a new signal that changes whenever the input signal changes. The new
- values are random number between 'low' and 'high' inclusive.
- **/
- var randomize = function(min) { return function(max) { return function(signal) {
- function f(x) { return Math.floor(Math.random() * (max-min+1)) + min; }
- return Elm.Signal.lift(f)(signal);
- };
- };
- };
- return { inRange:inRange, randomize:randomize };
-}();/*! Time
-Library for working with time. Type `Time` represents some number of
-milliseconds.
-!*/
-
-Elm.Time = function() {
-
- /*[Times]*/
-
- /** hour, minute, second, ms : Time
- Units of time, making it easier to specify things like a
- half-second `(second / 2)`.
- **/
-
- function timeNow() { return (new window.Date).getTime(); }
-
- /*[Tickers]*/
-
- /** fps : Number -> Signal Time
- Takes desired number of frames per second (fps). The resulting signal
- gives a sequence of time deltas as quickly as possible until it reaches
- the desired FPS. A time delta is the time between the last frame and the
- current frame.
- **/
-
- /** fpsWhen : Number -> Signal Bool -> Signal Time
- Same as the fps function, but you can turn it on and off. Allows you
- to do brief animations based on user input without major ineffeciencies.
- The first time delta after a pause is always zero, no matter how long
- the pause was. This way summing the deltas will actually give the amount
- of time that the output signal has been running.
- **/
- function fpsWhen(desiredFPS) { return function (isOn) {
- var msPerFrame = 1000 / desiredFPS;
- var prev = timeNow(), curr = prev, diff = 0, wasOn = true;
- var ticker = Elm.Signal.constant(diff);
- function tick(zero) { return function() {
- curr = timeNow();
- diff = zero ? 0 : curr - prev;
- prev = curr;
- Dispatcher.notify(ticker.id, diff);
- };
- }
- var timeoutID = 0;
- function f(isOn) { return function(t) {
- if (isOn) {
- timeoutID = setTimeout(tick(!wasOn && isOn), msPerFrame);
- } else if (wasOn) {
- clearTimeout(timeoutID);
- }
- wasOn = isOn;
- return t;
- };
- }
- return Elm.Signal.lift2(f)(isOn)(ticker);
- };
- }
-
- /** every : Time -> Signal Time
- Takes a time interval t. The resulting signal is the current time,
- updated every t.
- **/
- function everyWhen(isOn) { return function(t) {
- var clock = Elm.Signal.constant(timeNow());
- function tellTime() { Dispatcher.notify(clock.id, timeNow()); }
- setInterval(tellTime, t);
- return clock;
- };
- }
-
- function since(t) { return function(s) {
- function cmp(a) { return function(b) { return !Value.eq(a,b); }; }
- var dcount = Elm.Signal.count(Elm.Signal.delay(t)(s));
- return Elm.Signal.lift2(cmp)(Elm.Signal.count(s))(dcount);
- };
- }
- function after(t) {
- t *= 1000;
- var thread = Elm.Signal.constant(false);
- setTimeout(function() { Dispatcher.notify(thread.id, true); }, t);
- return thread;
- }
- function before(t) {
- t *= 1000;
- var thread = Elm.Signal.constant(true);
- setTimeout(function() { Dispatcher.notify(thread.id, false); }, t);
- return thread;
- }
- function read(s) {
- var t = window.Date.parse(s);
- return isNaN(t) ? ["Nothing"] : ["Just",t];
- }
- return {fpsWhen : fpsWhen,
- fps : function(t) { return fpsWhen(t)(Elm.Signal.constant(true)); },
- every : everyWhen(Elm.Signal.constant(true)),
- delay : Elm.Signal.delay,
- since : since,
- after : after,
- before : before,
- hour : 3600000,
- minute : 60000,
- second : 1000,
- ms : 1,
- inHours : function(t) { return t / 3600000; },
- inMinutes : function(t) { return t / 60000; },
- inSeconds : function(t) { return t / 1000; },
- inMss : function(t) { return t; },
- toDate : function(t) { return new window.Date(t); },
- read : read
- };
-
-}();/*! Window !*/
-
-Elm.Window = function() {
-
- /*[Dimensions]*/
-
- /** dimensions : Signal (Int,Int)
- The current dimensions of the window (i.e. the area viewable to the
- user, not including scroll bars).
- **/
- var dimensions = Elm.Signal.constant(Value.Tuple(window.innerWidth,
- window.innerHeight));
- dimensions.defaultNumberOfKids = 2;
-
- /** width : Signal Int
- The current width of the window.
- **/
- var width = Elm.Signal.lift(function(p){return p[1];})(dimensions);
- width.defaultNumberOfKids = 0;
-
- /** height : Signal Int
- The current height of the window.
- **/
- var height = Elm.Signal.lift(function(p){return p[2];})(dimensions);
- height.defaultNumberOfKids = 0;
-
- Value.addListener(window, 'resize', function(e) {
- var w = document.getElementById('widthChecker').offsetWidth;
- var hasListener = Dispatcher.notify(dimensions.id,
- Value.Tuple(w, window.innerHeight));
- if (!hasListener)
- this.removeEventListener('resize',arguments.callee,false);
- });
- return {dimensions:dimensions,width:width,height:height};
-}();
-
-Elm.Date = function() {
-
- function dateNow() { return new window.Date; }
- function readDate(str) {
- var d = new window.Date(Elm.JavaScript.castStringToJSString(str));
- if (isNaN(d.getTime())) return ["Nothing"];
- return ["Just",d];
- }
-
- var dayTable = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
- var monthTable = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-
- return {
- read : readDate,
- year : function(d) { return d.getFullYear(); },
- month : function(d) { return [monthTable[d.getMonth()]]; },
- day : function(d) { return d.getDate(); },
- hour : function(d) { return d.getHours(); },
- minute : function(d) { return d.getMinutes(); },
- second : function(d) { return d.getSeconds(); },
- dayOfWeek : function(d) { return [dayTable[d.getDay()]]; },
- toTime : function(d) { return d.getTime(); },
- Mon : ["Mon"], Tue : ["Tue"], Wed : ["Wed"],
- Thu : ["Thu"], Fri : ["Fri"], Sat : ["Sat"], Sun : ["Sun"],
- Jan : ["Jan"], Feb : ["Feb"], Mar : ["Mar"], Apr : ["Apr"],
- May : ["May"], Jun : ["Jun"], Jul : ["Jul"], Aug : ["Aug"],
- Sep : ["Sep"], Oct : ["Oct"], Nov : ["Nov"], Dec : ["Dec"]
- };
-
-}();
-function elmRecordCopy(r) {
- var o = {};
- for (var i in r) { o[i] = r[i]; }
- return o;
-}
-
-function elmRecordRemove(x,r) {
- var o = elmRecordCopy(r);
- if (x in o._) {
- o[x] = o._[x][0];
- o._[x] = o._[x].slice(1);
- if (o._[x].length === 0) { delete o._[x]; }
- } else {
- delete o[x];
- }
- return o;
-}
-
-function elmRecordReplace(kvs,r) {
- var o = elmRecordCopy(r);
- for (var i = kvs.length; i--; ) {
- kvsi = kvs[i];
- o[kvsi[0]] = kvsi[1];
- }
- return o;
-}
-
-function elmRecordInsert(x,v,r) {
- var o = elmRecordCopy(r);
- if (x in o) o._[x] = [o[x]].concat(x in o._ ? o._[x].slice(0) : []);
- o[x] = v;
- return o;
-}
-
-Value.addListener(document, 'elm_log', function(e) { console.log(e.value); });
-Value.addListener(document, 'elm_title', function(e) {document.title = e.value;});
-Value.addListener(document, 'elm_redirect', function(e) {
- if (e.value.length > 0) { window.location = e.value; }
- });
-Value.addListener(document, 'elm_viewport', function(e) {
- var node = document.getElementById('elm_viewport');
- if (!node) {
- node = document.createElement('meta');
- node.id = 'elm_viewport';
- node.name = 'viewport';
- document.head.appendChild(node);
- }
- node.content = e.value;
- Dispatcher.notify(Elm.Window.dimensions.id,
- Value.Tuple(window.innerWidth, window.innerHeight));
- });
-
-Elm.Prelude = function() {
- var mod = function(x) { return function(y) {
- var r = x % y;
- var m = x==0 ? 0 : (y>0 ? (x>=0 ? r : r+y) : -mod(-x)(-y));
- return m == y ? 0 : m;
- }; };
-
- var min = function(x) { return function(y) { return Math.min(x,y); }; };
- var max = function(x) { return function(y) { return Math.max(x,y); }; };
-
- var flip=function(f){return function(x){return function(y){return f(y)(x);};};};
- var clamp = function(lo) { return function(hi) {
- return function(x) { return Math.min(hi, Math.max(lo, x)); };
- };
- };
- var curry = function(f) { return function(x) { return function(y) {
- return f(["Tuple2",x,y]); }; };
- };
- var uncurry = function(f) { return function(p) {
- if (p[0] !== "Tuple2") {
- throw new Error("Function was uncurry'd but was not given a pair.");
- }
- return f(p[1])(p[2]); };
- };
-
- var logBase=function(b){return function(x){return Math.log(x)/Math.log(b);};};
-
- function readInt(str) {
- var s = Elm.JavaScript.castStringToJSString(str);
- var len = s.length;
- if (len === 0) { return ["Nothing"]; }
- var start = 0;
- if (s[0] == '-') {
- if (len === 1) { return ["Nothing"]; }
- start = 1;
- }
- for (var i = start; i < len; ++i) {
- if (!Elm.Char.isDigit(s[i])) { return ["Nothing"]; }
- }
- return ["Just", parseInt(s)];
- }
-
- function readFloat(str) {
- var s = Elm.JavaScript.castStringToJSString(str);
- var len = s.length;
- if (len === 0) { return ["Nothing"]; }
- var start = 0;
- if (s[0] == '-') {
- if (len === 1) { return ["Nothing"]; }
- start = 1;
- }
- var dotCount = 0;
- for (var i = start; i < len; ++i) {
- if (Elm.Char.isDigit(s[i])) { continue; }
- if (s[i] === '.') {
- dotCount += 1;
- if (dotCount <= 1) { continue; }
- }
- return ["Nothing"];
- }
- return ["Just", parseFloat(s)];
- }
-
- function compare(x) { return function (y) {
- if (x instanceof Array && y instanceof Array) {
- var len = x.length;
- if (len == y.length) {
- for (var i = 1; i < len; ++i) {
- var cmp = compare(x[i])(y[i]);
- if (cmp[0] === 'EQ') continue;
- return cmp;
- }
- return ['EQ'];
- }
- return [ y.length == 1 ? 'GT' : 'LT' ];
- }
- return [ x === y ? 'EQ' : (x < y ? 'LT' : 'GT') ];
- };
- }
- return {eq : Value.eq,
- id : function(x) { return x; },
- not : function(b) { return !b; },
- xor : function(x) { return function(y) { return x != y; }; },
- fst : function(p) { return p[1]; },
- snd : function(p) { return p[2]; },
- rem : function(x) { return function(y) { return x % y; }; },
- div : function(x) { return function(y) { return ~~(x / y); }; },
- otherwise : true,
- compare : compare,
- toFloat : function(x) { return x; },
- round : function(n) { return Math.round(n); },
- floor : function(n) { return Math.floor(n); },
- ceiling : function(n) { return Math.ceil(n); },
- truncate : function(n) { return ~~n; },
- readInt : readInt,
- readFloat : readFloat,
- sqrt : Math.sqrt,
- abs : Math.abs,
- pi : Math.PI,
- e : Math.E,
- sin : Math.sin,
- cos : Math.cos,
- tan : Math.tan,
- asin : Math.asin,
- acos : Math.acos,
- atan : Math.atan,
- atan2 : function(y) { return function(x) { return Math.atan2(y,x); }; },
- mod : mod,
- min : min,
- max : max,
- flip : flip,
- clamp : clamp,
- curry : curry,
- uncurry : uncurry,
- logBase : logBase,
- Just : Elm.Maybe.Just,
- Nothing : Elm.Maybe.Nothing,
- maybe : Elm.Maybe.maybe,
- map : Elm.List.map,
- zip : Elm.List.zip,
- zipWith : Elm.List.zipWith,
- filter : Elm.List.filter,
- head : Elm.List.head,
- tail : Elm.List.tail,
- last : Elm.List.last,
- length : Elm.List.length,
- reverse : Elm.List.reverse,
- foldr : Elm.List.foldr,
- foldr1 : Elm.List.foldr1,
- foldl : Elm.List.foldl,
- foldl1 : Elm.List.foldl1,
- and : Elm.List.and,
- or : Elm.List.or,
- all : Elm.List.all,
- any : Elm.List.any,
- sum : Elm.List.sum,
- product : Elm.List.product,
- concat : Elm.List.concat,
- concatMap : Elm.List.concatMap,
- maximum : Elm.List.maximum,
- minimum : Elm.List.minimum,
- scanl : Elm.List.scanl,
- scanl1 : Elm.List.scanl1,
- take : Elm.List.take,
- drop : Elm.List.drop,
- zip : Elm.List.zip,
- unzip : Elm.List.unzip,
- lift : Elm.Signal.lift,
- lift2 : Elm.Signal.lift2,
- lift3 : Elm.Signal.lift3,
- lift4 : Elm.Signal.lift4,
- lift5 : Elm.Signal.lift5,
- lift6 : Elm.Signal.lift6,
- lift7 : Elm.Signal.lift7,
- lift8 : Elm.Signal.lift8,
- foldp : Elm.Signal.foldp,
- foldp1 : Elm.Signal.foldp1,
- foldp$ : Elm.Signal.foldp$,
- constant : Elm.Signal.constant,
- merge : Elm.Signal.merge,
- merges : Elm.Signal.merges,
- mergeEither : Elm.Signal.mergeEither,
- count : Elm.Signal.count,
- countIf : Elm.Signal.countIf,
- average : Elm.Signal.average,
- keepIf : Elm.Signal.keepIf,
- dropIf : Elm.Signal.dropIf,
- keepWhen : Elm.Signal.keepWhen,
- dropWhen : Elm.Signal.dropWhen,
- dropRepeats : Elm.Signal.dropRepeats,
- sampleOn : Elm.Signal.sampleOn,
- timestamp : Elm.Signal.timestamp,
- timeOf : Elm.Signal.timeOf
- };
-
-}();
-
-(function() {
- var include = function(library) {
- for (var i in library) {
- Elm.Prelude[i] = library[i];
- }
- };
- include (Elm.Color);
- include (Elm.Text);
- include (Elm.Graphics);
- include (Elm.Time);
-
- show = Value.show;
-
-}());
-/*! Touch
-This is an early version of the touch library. It will likely grow to
-include gestures that would be useful for both games and web-pages.
-!*/
-
-Elm.Touch = function() {
-
- function Dict() {
- this.keys = [];
- this.values = [];
-
- this.insert = function(key,value) {
- this.keys.push(key);
- this.values.push(value);
- };
- this.lookup = function(key) {
- var i = this.keys.indexOf(key)
- return i >= 0 ? this.values[i] : {x:0,y:0,t:0};
- };
- this.remove = function(key) {
- var i = this.keys.indexOf(key);
- if (i < 0) return;
- var t = this.values[i];
- this.keys.splice(i,1);
- this.values.splice(i,1);
- return t;
- };
- }
-
- var root = Elm.Signal.constant([]),
- tapTime = 500,
- hasTap = false,
- tap = {_:[true],x:[0],y:[0]},
- dict = new Dict();
-
- function touch(t) {
- var r = dict.lookup(t.identifier);
- return {_ : [true], id: [t.identifier],
- x: [t.pageX], y: [t.pageY],
- x0: [r.x], y0: [r.y],
- t0: [r.t] };
- }
-
- function start(e) {
- dict.insert(e.identifier,{x:e.pageX,y:e.pageY,t:Date.now()});
- }
- function end(e) {
- var t = dict.remove(e.identifier);
- if (Date.now() - t.t < tapTime) {
- hasTap = true;
- tap = {_:[true], x:[t.x], y:[t.y]};
- }
- }
-
- function listen(name, f) {
- function update(e) {
- for (var i = e.changedTouches.length; i--; ) { f(e.changedTouches[i]); }
- var ts = new Array(e.touches.length);
- for (var i = e.touches.length; i--; ) { ts[i] = touch(e.touches[i]); }
- var hasListener = Dispatcher.notify(root.id, ts);
- if (!hasListener) return document.removeEventListener(name, update);
- e.preventDefault();
- }
- Value.addListener(document, name, update);
- }
-
- listen("touchstart", start);
- listen("touchmove", function(_){});
- listen("touchend", end);
- listen("touchcancel", end);
- listen("touchleave", end);
-
- function dependency(f) {
- var sig = Elm.Signal.lift(f)(root);
- root.defaultNumberOfKids += 1;
- sig.defaultNumberOfKids = 0;
- return sig;
- }
-
- /*[Touches]*/
-
- /** touches : Signal [{ x:Int, y:Int, id:Int, x0:Int, y0:Int, t0:Time }]
- A list of touches. Each ongoing touch is represented by a set of
- coordinates and an identifier id that allows you to distinguish
- between different touches. Each touch also contains the coordinates and
- time of the initial contact (x0, y0, and t0) which helps compute more
- complicated gestures.
- **/
- var touches = dependency(function(ts) {
- return Elm.JavaScript.castJSArrayToList(ts);
- });
-
- /*[Gestures]*/
-
- /** taps : Signal { x:Int, y:Int }
- The last position that was tapped. Default value is `{x=0,y=0}`.
- Updates whenever the user taps the screen.
- **/
- var taps = function() {
- var sig = dependency(function(_) { return tap; });
- sig.defaultNumberOfKids = 1;
- function pred(_) { var b = hasTap; hasTap = false; return b; }
- var sig2 = Elm.Signal.keepIf(pred)({_:[true],x:[0],y:[0]})(sig);
- sig2.defaultNumberOfKids = 0;
- return sig2;
- }();
-
- return { touches: touches, taps: taps };
-}();
-Elm.Dict=function(){
- var compare = Elm.Prelude.compare;
- var uncurry = Elm.Prelude.uncurry;
- var Nothing = Elm.Prelude.Nothing;
- var Just = Elm.Prelude.Just;
- var not = Elm.Prelude.not;
- var eq = Elm.Prelude.eq;
- var isJust=Elm.Maybe.isJust;
- var Red_0=['Red'];
- var Black_1=['Black'];
- function RBNode_2(a1){
- return function(a2){
- return function(a3){
- return function(a4){
- return function(a5){
- return ['RBNode',a1,a2,a3,a4,a5];};};};};}
- var RBEmpty_3=['RBEmpty'];
- function min_6(t_42){
- return function(){
- switch(t_42[0]){
- case 'RBEmpty':
- throw '(min RBEmpty) is not defined';
- case 'RBNode':
- switch(t_42[4][0]){
- case 'RBEmpty':
- return ['Tuple2',t_42[2],t_42[3]];
- }
- return min_6(t_42[4]);
- }
- throw new Error("Non-exhaustive pattern match in case");}();}
- function lookup_7(k_46){
- return function(t_47){
- return function(){
- switch(t_47[0]){
- case 'RBEmpty':
- return Nothing;
- case 'RBNode':
- return function(){
- var case12=compare(k_46)(t_47[2]);
- switch(case12[0]){
- case 'EQ':
- return Just(t_47[3]);
- case 'GT':
- return lookup_7(k_46)(t_47[5]);
- case 'LT':
- return lookup_7(k_46)(t_47[4]);
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- }
- throw new Error("Non-exhaustive pattern match in case");}();};}
- function findWithDefault_8(base_52){
- return function(k_53){
- return function(t_54){
- return function(){
- switch(t_54[0]){
- case 'RBEmpty':
- return base_52;
- case 'RBNode':
- return function(){
- var case19=compare(k_53)(t_54[2]);
- switch(case19[0]){
- case 'EQ':
- return t_54[3];
- case 'GT':
- return findWithDefault_8(base_52)(k_53)(t_54[5]);
- case 'LT':
- return findWithDefault_8(base_52)(k_53)(t_54[4]);
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- }
- throw new Error("Non-exhaustive pattern match in case");}();};};}
- function member_9(k_59){
- return function(t_60){
- return isJust(lookup_7(k_59)(t_60));};}
- function rotateLeft_10(t_61){
- return function(){
- switch(t_61[0]){
- case 'RBNode':
- switch(t_61[5][0]){
- case 'RBNode':
- return RBNode_2(t_61[1])(t_61[5][2])(t_61[5][3])(RBNode_2(Red_0)(t_61[2])(t_61[3])(t_61[4])(t_61[5][4]))(t_61[5][5]);
- }break;
- }
- throw 'rotateLeft of a node without enough children';}();}
- function rotateRight_11(t_71){
- return function(){
- switch(t_71[0]){
- case 'RBNode':
- switch(t_71[4][0]){
- case 'RBNode':
- return RBNode_2(t_71[1])(t_71[4][2])(t_71[4][3])(t_71[4][4])(RBNode_2(Red_0)(t_71[2])(t_71[3])(t_71[4][5])(t_71[5]));
- }break;
- }
- throw 'rotateRight of a node without enough children';}();}
- function rotateLeftIfNeeded_12(t_81){
- return function(){
- switch(t_81[0]){
- case 'RBNode':
- switch(t_81[5][0]){
- case 'RBNode':
- switch(t_81[5][1][0]){
- case 'Red':
- return rotateLeft_10(t_81);
- }break;
- }break;
- }
- return t_81;}();}
- function rotateRightIfNeeded_13(t_82){
- return function(){
- switch(t_82[0]){
- case 'RBNode':
- switch(t_82[4][0]){
- case 'RBNode':
- switch(t_82[4][1][0]){
- case 'Red':
- switch(t_82[4][4][0]){
- case 'RBNode':
- switch(t_82[4][4][1][0]){
- case 'Red':
- return rotateRight_11(t_82);
- }break;
- }break;
- }break;
- }break;
- }
- return t_82;}();}
- function otherColor_14(c_83){
- return function(){
- switch(c_83[0]){
- case 'Black':
- return Red_0;
- case 'Red':
- return Black_1;
- }
- throw new Error("Non-exhaustive pattern match in case");}();}
- function color_flip_15(t_84){
- return function(){
- switch(t_84[0]){
- case 'RBNode':
- switch(t_84[4][0]){
- case 'RBNode':
- switch(t_84[5][0]){
- case 'RBNode':
- return RBNode_2(otherColor_14(t_84[1]))(t_84[2])(t_84[3])(RBNode_2(otherColor_14(t_84[4][1]))(t_84[4][2])(t_84[4][3])(t_84[4][4])(t_84[4][5]))(RBNode_2(otherColor_14(t_84[5][1]))(t_84[5][2])(t_84[5][3])(t_84[5][4])(t_84[5][5]));
- }break;
- }break;
- }
- throw 'color_flip called on a RBEmpty or RBNode with a RBEmpty child';}();}
- function color_flipIfNeeded_16(t_98){
- return function(){
- switch(t_98[0]){
- case 'RBNode':
- switch(t_98[4][0]){
- case 'RBNode':
- switch(t_98[4][1][0]){
- case 'Red':
- switch(t_98[5][0]){
- case 'RBNode':
- switch(t_98[5][1][0]){
- case 'Red':
- return color_flip_15(t_98);
- }break;
- }break;
- }break;
- }break;
- }
- return t_98;}();}
- function fixUp_17(t_99){
- return color_flipIfNeeded_16(rotateRightIfNeeded_13(rotateLeftIfNeeded_12(t_99)));}
- function ensureBlackRoot_18(t_100){
- return function(){
- switch(t_100[0]){
- case 'RBNode':
- switch(t_100[1][0]){
- case 'Red':
- return RBNode_2(Black_1)(t_100[2])(t_100[3])(t_100[4])(t_100[5]);
- }break;
- }
- return t_100;}();}
- function insert_19(k_105){
- return function(v_106){
- return function(t_107){
- return function(){
- function ins_108(t_109){
- return function(){
- switch(t_109[0]){
- case 'RBEmpty':
- return RBNode_2(Red_0)(k_105)(v_106)(RBEmpty_3)(RBEmpty_3);
- case 'RBNode':
- return function(){
- var h_115=function(){
- var case114=compare(k_105)(t_109[2]);
- switch(case114[0]){
- case 'EQ':
- return RBNode_2(t_109[1])(t_109[2])(v_106)(t_109[4])(t_109[5]);
- case 'GT':
- return RBNode_2(t_109[1])(t_109[2])(t_109[3])(t_109[4])(ins_108(t_109[5]));
- case 'LT':
- return RBNode_2(t_109[1])(t_109[2])(t_109[3])(ins_108(t_109[4]))(t_109[5]);
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- return fixUp_17(h_115);}();
- }
- throw new Error("Non-exhaustive pattern match in case");}();}
- return ensureBlackRoot_18(ins_108(t_107));}();};};}
- function singleton_20(k_116){
- return function(v_117){
- return insert_19(k_116)(v_117)(RBEmpty_3);};}
- function isRed_21(t_118){
- return function(){
- switch(t_118[0]){
- case 'RBNode':
- switch(t_118[1][0]){
- case 'Red':
- return true;
- }break;
- }
- return false;}();}
- function isRedLeft_22(t_119){
- return function(){
- switch(t_119[0]){
- case 'RBNode':
- switch(t_119[4][0]){
- case 'RBNode':
- switch(t_119[4][1][0]){
- case 'Red':
- return true;
- }break;
- }break;
- }
- return false;}();}
- function isRedLeftLeft_23(t_120){
- return function(){
- switch(t_120[0]){
- case 'RBNode':
- switch(t_120[4][0]){
- case 'RBNode':
- switch(t_120[4][4][0]){
- case 'RBNode':
- switch(t_120[4][4][1][0]){
- case 'Red':
- return true;
- }break;
- }break;
- }break;
- }
- return false;}();}
- function isRedRight_24(t_121){
- return function(){
- switch(t_121[0]){
- case 'RBNode':
- switch(t_121[5][0]){
- case 'RBNode':
- switch(t_121[5][1][0]){
- case 'Red':
- return true;
- }break;
- }break;
- }
- return false;}();}
- function isRedRightLeft_25(t_122){
- return function(){
- switch(t_122[0]){
- case 'RBNode':
- switch(t_122[5][0]){
- case 'RBNode':
- switch(t_122[5][4][0]){
- case 'RBNode':
- switch(t_122[5][4][1][0]){
- case 'Red':
- return true;
- }break;
- }break;
- }break;
- }
- return false;}();}
- function moveRedLeft_26(t_123){
- return function(){
- var t__124=color_flip_15(t_123);
- return function(){
- switch(t__124[0]){
- case 'RBNode':
- return function(){
- switch(t__124[5][0]){
- case 'RBNode':
- switch(t__124[5][4][0]){
- case 'RBNode':
- switch(t__124[5][4][1][0]){
- case 'Red':
- return color_flip_15(rotateLeft_10(RBNode_2(t__124[1])(t__124[2])(t__124[3])(t__124[4])(rotateRight_11(t__124[5]))));
- }break;
- }break;
- }
- return t__124;}();
- }
- return t__124;}();}();}
- function moveRedRight_27(t_130){
- return function(){
- var t__131=color_flip_15(t_130);
- return (isRedLeftLeft_23(t__131)?color_flip_15(rotateRight_11(t__131)):t__131);}();}
- function moveRedLeftIfNeeded_28(t_132){
- return ((not(isRedLeft_22(t_132))&¬(isRedLeftLeft_23(t_132)))?moveRedLeft_26(t_132):t_132);}
- function moveRedRightIfNeeded_29(t_133){
- return ((not(isRedRight_24(t_133))&¬(isRedRightLeft_25(t_133)))?moveRedRight_27(t_133):t_133);}
- function deleteMin_30(t_134){
- return function(){
- function del_135(t_136){
- return function(){
- switch(t_136[0]){
- case 'RBNode':
- switch(t_136[4][0]){
- case 'RBEmpty':
- return RBEmpty_3;
- }break;
- }
- return function(){
- var case198=moveRedLeftIfNeeded_28(t_136);
- switch(case198[0]){
- case 'RBEmpty':
- return RBEmpty_3;
- case 'RBNode':
- return fixUp_17(RBNode_2(case198[1])(case198[2])(case198[3])(del_135(case198[4]))(case198[5]));
- }
- throw new Error("Non-exhaustive pattern match in case");}();}();}
- return ensureBlackRoot_18(del_135(t_134));}();}
- function remove_31(k_142){
- return function(t_143){
- return function(){
- function eq_and_noRightNode_144(t_150){
- return function(){
- switch(t_150[0]){
- case 'RBNode':
- switch(t_150[5][0]){
- case 'RBEmpty':
- return eq(k_142,t_150[2]);
- }break;
- }
- return false;}();}
- function eq_145(t_152){
- return function(){
- switch(t_152[0]){
- case 'RBNode':
- return eq(k_142,t_152[2]);
- }
- return false;}();}
- function delLT_146(t_154){
- return function(){
- var case216=moveRedLeftIfNeeded_28(t_154);
- switch(case216[0]){
- case 'RBEmpty':
- throw 'delLT on RBEmpty';
- case 'RBNode':
- return fixUp_17(RBNode_2(case216[1])(case216[2])(case216[3])(del_149(case216[4]))(case216[5]));
- }
- throw new Error("Non-exhaustive pattern match in case");}();}
- function delEQ_147(t_160){
- return function(){
- switch(t_160[0]){
- case 'RBEmpty':
- throw 'delEQ called on a RBEmpty';
- case 'RBNode':
- return function(){
- var Tuple2$k_v__164=min_6(t_160[5]);
- var k__165=function(){
- switch(Tuple2$k_v__164[0]){
- case 'Tuple2':
- return Tuple2$k_v__164[1];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- var v__166=function(){
- switch(Tuple2$k_v__164[0]){
- case 'Tuple2':
- return Tuple2$k_v__164[2];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- return fixUp_17(RBNode_2(t_160[1])(k__165)(v__166)(t_160[4])(deleteMin_30(t_160[5])));}();
- }
- throw new Error("Non-exhaustive pattern match in case");}();}
- function delGT_148(t_171){
- return function(){
- switch(t_171[0]){
- case 'RBEmpty':
- throw 'delGT called on a RBEmpty';
- case 'RBNode':
- return fixUp_17(RBNode_2(t_171[1])(t_171[2])(t_171[3])(t_171[4])(del_149(t_171[5])));
- }
- throw new Error("Non-exhaustive pattern match in case");}();}
- function del_149(t_177){
- return function(){
- switch(t_177[0]){
- case 'RBEmpty':
- return RBEmpty_3;
- case 'RBNode':
- return ((compare(k_142)(t_177[2])[0] === 'LT')?delLT_146(t_177):function(){
- var u_179=(isRedLeft_22(t_177)?rotateRight_11(t_177):t_177);
- return (eq_and_noRightNode_144(u_179)?u_179[4]:function(){
- var t__180=moveRedRightIfNeeded_29(t_177);
- return (eq_145(t__180)?delEQ_147(t__180):delGT_148(t__180));}());}());
- }
- throw new Error("Non-exhaustive pattern match in case");}();}
- return (member_9(k_142)(t_143)?ensureBlackRoot_18(del_149(t_143)):t_143);}();};}
- function map_32(f_181){
- return function(t_182){
- return function(){
- switch(t_182[0]){
- case 'RBEmpty':
- return RBEmpty_3;
- case 'RBNode':
- return RBNode_2(t_182[1])(t_182[2])(f_181(t_182[3]))(map_32(f_181)(t_182[4]))(map_32(f_181)(t_182[5]));
- }
- throw new Error("Non-exhaustive pattern match in case");}();};}
- function foldl_33(f_188){
- return function(acc_189){
- return function(t_190){
- return function(){
- switch(t_190[0]){
- case 'RBEmpty':
- return acc_189;
- case 'RBNode':
- return foldl_33(f_188)(f_188(t_190[2])(t_190[3])(foldl_33(f_188)(acc_189)(t_190[4])))(t_190[5]);
- }
- throw new Error("Non-exhaustive pattern match in case");}();};};}
- function foldr_34(f_195){
- return function(acc_196){
- return function(t_197){
- return function(){
- switch(t_197[0]){
- case 'RBEmpty':
- return acc_196;
- case 'RBNode':
- return foldr_34(f_195)(f_195(t_197[2])(t_197[3])(foldr_34(f_195)(acc_196)(t_197[5])))(t_197[4]);
- }
- throw new Error("Non-exhaustive pattern match in case");}();};};}
- function union_35(t1_202){
- return function(t2_203){
- return foldl_33(insert_19)(t2_203)(t1_202);};}
- function intersect_36(t1_204){
- return function(t2_205){
- return foldl_33(function(k_206){
- return function(v_207){
- return function(t_208){
- return (member_9(k_206)(t2_205)?insert_19(k_206)(v_207)(t_208):t_208);};};})(empty_4)(t1_204);};}
- function diff_37(t1_209){
- return function(t2_210){
- return foldl_33(function(k_211){
- return function(v_212){
- return function(t_213){
- return remove_31(k_211)(t_213);};};})(t1_209)(t2_210);};}
- function keys_38(t_214){
- return foldr_34(function(k_215){
- return function(v_216){
- return function(acc_217){
- return ['Cons',k_215,acc_217];};};})(['Nil'])(t_214);}
- function values_39(t_218){
- return foldr_34(function(k_219){
- return function(v_220){
- return function(acc_221){
- return ['Cons',v_220,acc_221];};};})(['Nil'])(t_218);}
- function toList_40(t_222){
- return foldr_34(function(k_223){
- return function(v_224){
- return function(acc_225){
- return ['Cons',['Tuple2',k_223,v_224],acc_225];};};})(['Nil'])(t_222);}
- function fromList_41(assocs_226){
- return Elm.List.foldl(uncurry(insert_19))(empty_4)(assocs_226);}
- var empty_4=RBEmpty_3;
- return {$op : {},
- empty:empty_4,
- lookup:lookup_7,
- findWithDefault:findWithDefault_8,
- member:member_9,
- insert:insert_19,
- singleton:singleton_20,
- remove:remove_31,
- map:map_32,
- foldl:foldl_33,
- foldr:foldr_34,
- union:union_35,
- intersect:intersect_36,
- diff:diff_37,
- keys:keys_38,
- values:values_39,
- toList:toList_40,
- fromList:fromList_41};}();
-
-Elm.Set=function(){
- var empty_0=Elm.Dict.empty;
- var remove_3=Elm.Dict.remove;
- var member_4=Elm.Dict.member;
- var union_5=Elm.Dict.union;
- var intersect_6=Elm.Dict.intersect;
- var diff_7=Elm.Dict.diff;
- var toList_8=Elm.Dict.keys;
- var fromList_9=Elm.List.foldl(function(k_15){
- return function(t_16){
- return Elm.Dict.insert(k_15)(["Tuple0"])(t_16);};})(empty_0);
- function singleton_1(k_13){
- return Elm.Dict.singleton(k_13)(["Tuple0"]);};
- function insert_2(k_14){
- return Elm.Dict.insert(k_14)(["Tuple0"]);};
- function foldl_10(f_17){
- return Elm.Dict.foldl(function(k_18){
- return function(v_19){
- return function(b_20){
- return f_17(k_18)(b_20);};};});};
- function foldr_11(f_21){
- return Elm.Dict.foldr(function(k_22){
- return function(v_23){
- return function(b_24){
- return f_21(k_22)(b_24);};};});};
- function map_12(f_25){
- return function(t_26){
- return function(x){
- return fromList_9(Elm.List.map(f_25)(x));}(toList_8(t_26));};};
- return {empty:empty_0,singleton:singleton_1,insert:insert_2,remove:remove_3,member:member_4,union:union_5,intersect:intersect_6,diff:diff_7,toList:toList_8,fromList:fromList_9,foldl:foldl_10,foldr:foldr_11,map:map_12};}();
-
-(function() {
-try{
-
-var $op={};
-for(this['i'] in Elm){eval('var '+this['i']+'=Elm[this.i];');}
-if (Elm.Automaton) throw new Error("Module name collision, 'Automaton' is already defined.");
-Elm.Automaton=function(){
- try{
- if (!(Elm.Prelude instanceof Object)) throw 'module not found';
- } catch(e) {
- throw ("Module 'Prelude' is missing. Compile with --make flag or load missing module in a separate JavaScript file.");
- }
- var hiddenVars={};
- for (this['i'] in Elm.Prelude) {
- if (hiddenVars[this['i']]) continue;
- eval('var ' + this['i'] + ' = Elm.Prelude[this.i];');}
- function Automaton_0(a1){
- return ["Automaton",a1];}
- var Listen_8=["Listen"];
- var Ignore_9=["Ignore"];
- function DragFrom_10(a1){
- return ["DragFrom",a1];}
- $op['>>>'] = function(a1_24){
- return function(a2_25){
- return function(){
- var Automaton$m1_26=a1_24;
- var m1_27=function(){
- switch(Automaton$m1_26[0]){
- case "Automaton":
- return Automaton$m1_26[1];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- var Automaton$m2_28=a2_25;
- var m2_29=function(){
- switch(Automaton$m2_28[0]){
- case "Automaton":
- return Automaton$m2_28[1];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- return Automaton_0(function(a_32){
- return function(){
- var Tuple2$bm1__33=m1_27(a_32);
- var b_34=function(){
- switch(Tuple2$bm1__33[0]){
- case "Tuple2":
- return Tuple2$bm1__33[1];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- var m1__35=function(){
- switch(Tuple2$bm1__33[0]){
- case "Tuple2":
- return Tuple2$bm1__33[2];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- return function(){
- var Tuple2$cm2__40=m2_29(b_34);
- var c_41=function(){
- switch(Tuple2$cm2__40[0]){
- case "Tuple2":
- return Tuple2$cm2__40[1];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- var m2__42=function(){
- switch(Tuple2$cm2__40[0]){
- case "Tuple2":
- return Tuple2$cm2__40[2];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- return ["Tuple2",c_41,$op['>>>'](m1__35)(m2__42)];}();}();});}();};};
- $op['<<<'] = function(a2_47){
- return function(a1_48){
- return $op['>>>'](a1_48)(a2_47);};};
- $op['^>>'] = function(f_49){
- return function(a_50){
- return $op['>>>'](pure_4(f_49))(a_50);};};
- $op['>>^'] = function(a_51){
- return function(f_52){
- return $op['>>>'](a_51)(pure_4(f_52));};};
- $op['^<<'] = function(f_53){
- return function(a_54){
- return $op['>>>'](a_54)(pure_4(f_53));};};
- $op['<<^'] = function(a_55){
- return function(f_56){
- return $op['>>>'](pure_4(f_56))(a_55);};};
- var count_7=init_5(0)(function(__84){
- return function(c_85){
- return (1+c_85);};});
- function run_1(Automaton$m0_14){
- return function(input_15){
- return function(){
- switch(Automaton$m0_14[0]){
- case "Automaton":
- return lift(fst)(foldp$(function(a_17){
- return function(Tuple2$bAutomaton$m_18){
- return function(){
- switch(Tuple2$bAutomaton$m_18[0]){
- case "Tuple2":
- switch(Tuple2$bAutomaton$m_18[2][0]){
- case "Automaton":
- return Tuple2$bAutomaton$m_18[2][1](a_17);
- }break;
- }
- throw new Error("Non-exhaustive pattern match in case");}();};})(Automaton$m0_14[1])(input_15));
- }
- throw new Error("Non-exhaustive pattern match in case");}();};}
- function step_2(Automaton$m_21){
- return function(a_22){
- return function(){
- switch(Automaton$m_21[0]){
- case "Automaton":
- return Automaton$m_21[1](a_22);
- }
- throw new Error("Non-exhaustive pattern match in case");}();};}
- function combine_3(autos_57){
- return Automaton_0(function(a_58){
- return function(){
- var Tuple2$bsautos__59=unzip(map(function(Automaton$m_62){
- return function(){
- switch(Automaton$m_62[0]){
- case "Automaton":
- return Automaton$m_62[1](a_58);
- }
- throw new Error("Non-exhaustive pattern match in case");}();})(autos_57));
- var bs_60=function(){
- switch(Tuple2$bsautos__59[0]){
- case "Tuple2":
- return Tuple2$bsautos__59[1];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- var autos__61=function(){
- switch(Tuple2$bsautos__59[0]){
- case "Tuple2":
- return Tuple2$bsautos__59[2];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- return ["Tuple2",bs_60,combine_3(autos__61)];}();});}
- function pure_4(f_68){
- return Automaton_0(function(x_69){
- return ["Tuple2",f_68(x_69),pure_4(f_68)];});}
- function init_5(s_70){
- return function(step_71){
- return Automaton_0(function(a_72){
- return function(){
- var s__73=step_71(a_72)(s_70);
- return ["Tuple2",s__73,init_5(s__73)(step_71)];}();});};}
- function init__6(s_74){
- return function(step_75){
- return Automaton_0(function(a_76){
- return function(){
- var Tuple2$bs__77=step_75(a_76)(s_74);
- var b_78=function(){
- switch(Tuple2$bs__77[0]){
- case "Tuple2":
- return Tuple2$bs__77[1];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- var s__79=function(){
- switch(Tuple2$bs__77[0]){
- case "Tuple2":
- return Tuple2$bs__77[2];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- return ["Tuple2",b_78,init__6(s__79)(step_75)];}();});};}
- function vecSub_11(Tuple2$x1y1_86){
- return function(Tuple2$x2y2_87){
- return function(){
- switch(Tuple2$x1y1_86[0]){
- case "Tuple2":
- return function(){
- switch(Tuple2$x2y2_87[0]){
- case "Tuple2":
- return ["Tuple2",(Tuple2$x1y1_86[1]-Tuple2$x2y2_87[1]),(Tuple2$x1y1_86[2]-Tuple2$x2y2_87[2])];
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- }
- throw new Error("Non-exhaustive pattern match in case");}();};}
- function stepDrag_12(Tuple2$presspos_92){
- return function(Tuple2$dsform_93){
- return function(){
- switch(Tuple2$presspos_92[0]){
- case "Tuple2":
- return function(){
- switch(Tuple2$dsform_93[0]){
- case "Tuple2":
- return function(){
- function wrap_98(ds__99){
- return ["Tuple2",Tuple2$dsform_93[2],["Tuple2",ds__99,Tuple2$dsform_93[2]]];}
- return function(){
- switch(Tuple2$dsform_93[1][0]){
- case "DragFrom":
- return (Tuple2$presspos_92[1]?["Tuple2",uncurry(move)(vecSub_11(Tuple2$presspos_92[2])(Tuple2$dsform_93[1][1]))(Tuple2$dsform_93[2]),["Tuple2",DragFrom_10(Tuple2$dsform_93[1][1]),Tuple2$dsform_93[2]]]:function(){
- var form__101=uncurry(move)(vecSub_11(Tuple2$presspos_92[2])(Tuple2$dsform_93[1][1]))(Tuple2$dsform_93[2]);
- return ["Tuple2",form__101,["Tuple2",Listen_8,form__101]];}());
- case "Ignore":
- return wrap_98((Tuple2$presspos_92[1]?Ignore_9:Listen_8));
- case "Listen":
- return wrap_98((not(Tuple2$presspos_92[1])?Listen_8:(isWithin(Tuple2$presspos_92[2])(Tuple2$dsform_93[2])?DragFrom_10(Tuple2$presspos_92[2]):Ignore_9)));
- }
- throw new Error("Non-exhaustive pattern match in case");}();}();
- }
- throw new Error("Non-exhaustive pattern match in case");}();
- }
- throw new Error("Non-exhaustive pattern match in case");}();};}
- function draggable_13(form_102){
- return init__6(["Tuple2",Listen_8,form_102])(stepDrag_12);}
- return {$op : {'>>>' : $op['>>>'], '<<<' : $op['<<<'], '^>>' : $op['^>>'], '>>^' : $op['>>^'], '^<<' : $op['^<<'], '<<^' : $op['<<^']},
- run:run_1,
- step:step_2,
- combine:combine_3,
- pure:pure_4,
- init:init_5,
- init$:init__6,
- count:count_7,
- draggable:draggable_13};}();
-Elm.main=function(){
- return Elm.Automaton.main;};
-} catch (e) {
-Elm.main=function() {
-var msg = ('
Your browser may not be supported. Are you using a modern browser?
' + '
Runtime Error in Automaton module:
' + e + '');
-document.body.innerHTML = Elm.Text.monospace(msg);throw e;};}}());
\ No newline at end of file
diff --git a/elm/elm-runtime-0.7.js b/elm/elm-runtime-0.7.js
deleted file mode 100644
index 539c9fc..0000000
--- a/elm/elm-runtime-0.7.js
+++ /dev/null
@@ -1,135 +0,0 @@
-Elm={};var Guid=function(){var e=0;return{guid:function(){return e+=1}}}();
-Elm.JavaScript=function(){function e(b){for(var a=["Nil"],m=b.length;m--;)a=["Cons",b[m],a];return a}function k(b){for(var a=[];"Cons"===b[0];)a.push(b[1]),b=b[2];return a}function b(b){return b.slice(1)}function d(b){return["Tuple"+b.length].concat(b)}return{castJSBoolToBool:function(b){return b},castBoolToJSBool:function(b){return b},castJSNumberToFloat:function(b){return b},castFloatToJSNumber:function(b){return b},castJSNumberToInt:function(b){return~~b},castIntToJSNumber:function(b){return b},
-Experimental:{castJSElementToElement:function(b){return function(a){return function(m){return["Element",Guid.guid(),["EExternalHtml",m],b,a,1,["Nothing"],["Nothing"]]}}},castElementToJSElement:function(b){return Render.render(b)}},castJSArrayToList:e,castListToJSArray:k,castJSStringToString:e,castStringToJSString:function(b){return"string"===typeof b?b:k(b).join("")},castTupleToJSTuple2:b,castTupleToJSTuple3:b,castTupleToJSTuple4:b,castTupleToJSTuple5:b,castJSTupleToTuple2:d,castJSTupleToTuple3:d,
-castJSTupleToTuple4:d,castJSTupleToTuple5:d}}();var JSjson=window.JSON;
-Elm.JSON=function(){function e(a,b){return function(g){return function(l){var h=d.castStringToJSString(g);return l[1].hasOwnProperty(h)&&(l=l[1][h],l[0]===a)?l[1]:b}}}function k(a){return function(b){function g(a){switch(a[0]){case "JsonNull":return null;case "JsonString":return d.castStringToJSString(a[1]);case "JsonObject":var h={};a=a[1][1];for(var c in a)h[c]=g(a[c]);return h;case "JsonArray":h=d.castListToJSArray(a[1]);for(c=h.length;c--;)h[c]=g(h[c]);return h;default:return a[1]}}return JSjson.stringify(g(["JsonObject",
-b]),null,d.castStringToJSString(a))}}function b(a){function b(a){switch(typeof a){case "string":return["JsonString",d.castJSStringToString(a)];case "number":return["JsonNumber",d.castJSNumberToFloat(a)];case "boolean":return["JsonBool",d.castJSBoolToBool(a)];case "object":if(null===a)return["JsonNull"];for(var h in a)a[h]=b(a[h]);return a instanceof Array?["JsonArray",d.castJSArrayToList(a)]:["JsonObject",["JSON",a]]}}a=JSjson.parse(a);for(var g in a)a[g]=b(a[g]);return["JSON",a]}var d=Elm.JavaScript,
-j=["JSON",{}];return{empty:j,singleton:function(a){return function(b){var g={};g[d.castStringToJSString(a)]=b;return["JSON",g]}},insert:function(a){return function(b){return function(g){g=g[1];var l={},h;for(h in g)l[h]=g[h];l[d.castStringToJSString(a)]=b;return["JSON",l]}}},lookup:function(a){return function(b){var g=d.castStringToJSString(a);return b[1].hasOwnProperty(g)?["Just",b[1][g]]:["Nothing"]}},findString:e("JsonString",["Nil"]),findObject:e("JsonObject",j),findArray:e("JsonArray",["Nil"]),
-findWithDefault:function(a){return function(b){return function(g){var l=d.castStringToJSString(b);return g[1].hasOwnProperty(l)?g[1][l]:a}}},remove:function(a){return function(b){b=b[1];var g={},l;for(l in b)g[l]=b[l];delete g[d.castStringToJSString(a)];return["JSON",g]}},toPrettyJSString:k,toJSString:k(""),fromJSString:b,toPrettyString:function(a){return function(b){return d.castJSStringToString(k(a)(b))}},toString:function(a){return d.castJSStringToString(k("")(a))},fromString:function(a){return b(d.castStringToJSString(a))},
-toList:function(a){a=a[1];var b=[],g;for(g in a)b.push(Value.Tuple(d.castJSStringToString(g),a[g]));return d.castJSArrayToList(b)},fromList:function(a){a=d.castListToJSArray(a);for(var b={},g=a.length;g--;)b[d.castStringToJSString(a[g][1])]=a[g][2];return["JSON",b]},JsonString:function(a){return["JsonString",a]},JsonNumber:function(a){return["JsonNumber",a]},JsonBool:function(a){return["JsonBool",a]},JsonNull:["JsonNull"],JsonArray:function(a){return["JsonArray",a]},JsonObject:function(a){return["JsonObject",
-a]}}}();
-var Value=function(){function e(a){if(0==a.length)return a;a=a.replace(/"/g,""").replace(/'/g,"'").replace(//g,">").replace(/\n/g,"
");a=a.split("
");for(var b=a.length;b--;){var g=a,d=b,h;h=a[b];if(0!=h.length){h=h.split("");" "==h[0]&&(h[0]=" ");for(var c=h.length;--c;)" "==h[c][0]&&" "==h[c-1]&&(h[c-1]+=h[c],h[c]="");for(c=h.length;c--;)if(1")}var k=function(a,b){if("object"===typeof a){if(a.hasOwnProperty("_")){for(var g in a)if(a[g]!=b[g])return!1;for(g in b)if(a[g]!=b[g])return!1;return!0}if(a===b)return!0;if(a.length!==b.length)return!1;for(g=a.length;g--;)if(!k(a[g],b[g]))return!1;return!0}return a===b},b=function(a){if("function"===typeof a)return"";if("boolean"===typeof a)return a?"True":"False";if("number"!==typeof a){if("string"===typeof a&&
-2>a.length)return"'"+a+"'";if("object"===typeof a&&a.hasOwnProperty("_")){var d=[],g;for(g in a)if("_"!=g)for(var l=a[g].length;l--;)d.push(g+" = "+b(a[g][l]));return 0===d.length?"{}":"{ "+d.join(", ")+" }"}if(a[0]){if("Tuple"===a[0].substring(0,5)){d=Array(a.length-1);for(l=a.length;--l;)d[l-1]=b(a[l]);return"("+d.join(",")+")"}if("Cons"===a[0]){g="string"===typeof a[1]?'"':"]";var l="string"===typeof a[1]?"":",",h="string"===typeof a[1]?function(a){return a}:b,d=("string"===typeof a[1]?'"':"[")+
-h(a[1]);for(a=a[2];;)if("Cons"===a[0])d+=l+h(a[1]),a=a[2];else return d+g}else{if("Nil"===a[0])return"[]";if("JSON"===a[0])return"(JSON.fromList "+b(Elm.JSON.toList(a))+")";if("RBNode"===a[0]||"RBEmpty"===a[0])return a=Elm.Dict.foldr(function(a){return function(b){return function(h){return["Cons",["Tuple2",a,b],h]}}})(["Nil"])(a),d="Dict","Cons"===a[0]&&"Tuple0"===a[1][2][0]&&(d="Set",a=Elm.List.map(function(a){return a[1]})(a)),"("+d+".fromList "+b(a)+")";d=[];for(l=a.length;--l;)d.push(b(a[l]));
-d=a[0]+" "+d.join(" ");return 1=b)return["Nil"];if("Nil"===a[0])return a;"Cons"!==a[0]&&h("take");var c=["Cons",a[1],["Nil"]],f=c;a=a[2];for(--b;"Cons"===a[0]&&0d?(a=b,m=j,g=0):1<=d&&2>d?(a=j,m=b,g=0):2<=d&&3>d?(a=0,m=b,g=j):3<=d&&4>d?(a=0,m=j,g=b):4<=d&&5>d?(a=j,m=0,g=b):5<=d&&6>d&&(a=b,m=0,g=j);e=e.value-b;return["Color",Math.round(255*(a+e)),Math.round(255*(m+e)),Math.round(255*(g+e)),1]}return{rgba:function(e){return function(b){return function(d){return function(j){return["Color",e,b,d,j]}}}},rgb:function(e){return function(b){return function(d){return["Color",e,
-b,d,1]}}},hsva:function(k){return function(b){return function(d){return function(j){var a=e({hue:k,saturation:b,value:d});a[4]=j;return a}}}},hsv:function(k){return function(b){return function(d){return e({hue:k,saturation:b,value:d})}}},red:["Color",255,0,0,1],green:["Color",0,255,0,1],blue:["Color",0,0,255,1],yellow:["Color",255,255,0,1],cyan:["Color",0,255,255,1],magenta:["Color",255,0,255,1],black:["Color",0,0,0,1],white:["Color",255,255,255,1],gray:["Color",128,128,128,1],grey:["Color",128,128,
-128,1],complement:function(k){var b;b=k[1]/255;var d=k[2]/255;k=k[3]/255;var j=Math.max(b,d,k),a=Math.min(b,d,k),a=j-a,m=0;0===a?m=0:j===b?m=(d-k)/a%6:j===d?m=(k-b)/a+2:j===k&&(m=(b-d)/a+4);b={value:j,hue:60*m,saturation:0===j?0:a/j};b.hue=(b.hue+180)%360;return e(b)},extract:function(e){return 1===e[4]?"rgb("+e[1]+","+e[2]+","+e[3]+")":"rgba("+e[1]+","+e[2]+","+e[3]+","+e[4]+")"}}}();
-var Collage=function(){function e(b,a){var c=a.length-1;if(!(0>=c))for(b.moveTo(a[c][1],a[c][2]);c--;)b.lineTo(a[c][1],a[c][2])}function k(b,a,c,f){0===b.length&&(b=[8,4]);var d=f.length-1;if(!(0>=d)){var n=f[d][1],g=f[d][2],e=0,j=0,k=0,m=0,q=0,t=0,w=b.length,A=!0,x=b[0];for(a.moveTo(n,g);d--;){e=f[d][1];j=f[d][2];k=e-n;m=j-g;for(q=Math.sqrt(k*k+m*m);x<=q;)n+=k*x/q,g+=m*x/q,a[A?"lineTo":"moveTo"](n,g),k=e-n,m=j-g,q=Math.sqrt(k*k+m*m),A=!A,t=(t+1)%w,x=b[t];0a.length){var d=a[3][1],g=a[3][2],e=0,j=a[2];switch(a[4][0]){case "FShape":for(var k=a[4][3][1],s=k.length;--s;)var u=k[s],e=Math.max(e,u[1]*u[1]+u[2]*u[2]);e*=j*j;break;case "FImage":k=j*a[4][1]/2;j=j*a[4][2]/2;e=k*k+j*j;break;case "FElement":k=j*a[4][1][3]/2,j=j*a[4][1][4]/2,e=k*k+j*j}a.push(function(a,b){var c=a-d,h=b-g;return c*c+h*h'+b+""+a+">"}},b=function(a,b){return function(f){return""+f+""}},d=function(a){a=Elm.JavaScript.castStringToJSString(a);return b("font-family",a)},j=k("h1"),a=b("font-style","italic"),k=k("b"),m=b("text-decoration","underline"),g=b("text-decoration","overline"),l=b("text-decoration","line-through");return{fromString:e,toText:e,header:j,
-height:function(a){return b("font-size",a+"em")},italic:a,bold:k,underline:m,overline:g,strikeThrough:l,monospace:d("monospace"),typeface:d,color:function(a){return b("color",Elm.Color.extract(a))},link:function(a){return function(b){return""+b+""}}}}();
-var Render=function(){function e(a){a=document.createElement(a);a.style.padding="0";a.style.margin="0";return a}function k(a){return a}function b(a){a.style.styleFloat="left";a.style.cssFloat="left";return a}function d(a){a.style.position="absolute";return a}function j(a,b,f){for(var d=e("div"),g=f.length;g--;){var j=a(b(f[g]));d.appendChild(j)}return d}function a(a){switch(a[0]){case "Absolute":return a[1]+"px";case "Relative":return 100*a[1]+"%"}}function m(b,c){c.style.position="absolute";c.style.margin=
-"auto";switch(b[0]){case "Position":"Far"!==b[1][0]&&(c.style.left=0);"Near"!==b[1][0]&&(c.style.right=0);"Far"!==b[2][0]&&(c.style.top=0);"Near"!==b[2][0]&&(c.style.bottom=0);break;case "PositionAt":c.style.top=a(b[2]);c.style.left=a(b[1]);var f="translate("+~~(-c.style.width.slice(0,-2)/2)+"px,"+~~(-c.style.height.slice(0,-2)/2)+"px)";c.style.transform=f;c.style.msTransform=f;c.style.MozTransform=f;c.style.webkitTransform=f;c.style.OTransform=f;break;default:f=b[0].slice(-2),c.style["T"===f[0]?
-"top":"bottom"]=a(b[2]),c.style["L"===f[1]?"left":"right"]=a(b[1])}}function g(a){var c={};switch(a[2][0]){case "EText":var c=a[2][1],f=a[2][2],l=e("div");l.innerHTML=f;l.style.textAlign=c;c=l;break;case "EImage":c=a[2][1];f=e("img");f.src=c;f.name=c;f.style.display="block";c=f;break;case "EVideo":l=a[2][1];c=e("video");c.controls="controls";f=e("source");f.src=l;l=l.split(".");f.type="video/"+l[l.length-1];c.appendChild(f);c.style.display="block";break;case "EFittedImage":var n=a[3],p=a[4],c=a[2][1],
-f=e("div");f.style.width=n+"px";f.style.height=p+"px";f.style.position="relative";f.style.overflow="hidden";var r=e("img");r.onload=function(){r.style.position="absolute";r.style.margin="auto";var a=n,b=p;n/p>this.width/this.height?b=Math.round(this.height*n/this.width):a=Math.round(this.width*p/this.height);r.style.width=a+"px";r.style.height=b+"px";r.style.left=(n-a)/2+"px";r.style.top=(p-b)/2+"px"};r.src=c;r.name=c;f.appendChild(r);c=f;break;case "EFlow":a:{c=a[2][2];switch(a[2][1][0]){case "DDown":c=
-c.slice(0).reverse();case "DUp":c=j(k,g,c);break a;case "DRight":c=c.slice(0).reverse();case "DLeft":c=j(b,g,c);break a;case "DOut":c=c.slice(0).reverse();case "DIn":c=j(d,g,c);break a}c=void 0}break;case "ECollage":c=Collage.collage(a[2][1],a[2][2],a[2][3]);break;case "EEmpty":c=e("div");break;case "EContainer":f=a[2][1];c=g(a[2][2]);m(f,c);f=e("div");f.style.position="relative";f.style.overflow="hidden";f.appendChild(c);c=f;break;case "EHtml":c=a[2][1];"button"!==c.type&&(f=Value.getExcess(c),a[3]-=
-f[0],a[4]-=f[1]);break;case "EExternalHtml":c=e("div"),c.appendChild(a[2][1])}c.id=a[1];c.style.width=~~a[3]+"px";c.style.height=~~a[4]+"px";1!==a[5]&&(c.style.opacity=a[5]);"Just"===a[6][0]&&(c.style.backgroundColor=Elm.Color.extract(a[6][1]));return"Just"===a[7][0]?(f=e("a"),f.href=a[7][1],f.appendChild(c),f):c}function l(a,c,f){"A"===a.tagName&&(a=a.firstChild);if(c[1]!==f[1]){if(c[2][0]!==f[2][0])return a.parentNode.replaceChild(g(f),a);var e=f[2],j=c[2];switch(e[0]){case "EText":e[1]!==j[1]&&
-(a.style.textAlign=e[1]);e[2]!==j[2]&&(a.innerHTML=e[2]);break;case "EImage":e[1]!==j[1]&&(a.src=e[1]);break;case "EVideo":case "EFittedImage":if(!Value.eq(e,j)||f[3]!==c[3]||f[4]!==c[4])return a.parentNode.replaceChild(g(f),a);break;case "ECollage":if(e[1]!==j[1]||e[2]!==j[2]||e[3].length!==j[3].length)return a.parentNode.replaceChild(g(f),a);Collage.updateCollage(a,j[3],e[3]);break;case "EFlow":if(e[1]!==j[1])return a.parentNode.replaceChild(g(f),a);var p=e[2],r=a.childNodes;if(p.length!==r.length)return a.parentNode.replaceChild(g(f),
-a);var j=j[2],y=function(a){return a};switch(e[1][0]){case "DDown":case "DUp":y=k;break;case "DRight":case "DLeft":y=b;break;case "DOut":case "DIn":y=d}for(e=r.length;e--;)l(r[e],j[e],p[e]),y(r[e]);break;case "EContainer":l(a.childNodes[0],j[2],e[2]);m(e[1],a.childNodes[0]);break;case "EHtml":f[1]!==c[1]&&(p=g(f),a.parentNode.replaceChild(p,a),a=p);"button"!==p.type&&(e=Value.getExcess(a),f[3]-=e[0],f[4]-=e[1]);break;case "EExternalHtml":f[1]!==c[1]&&a.parentNode.replaceChild(g(f),a)}f[3]!==c[3]&&
-(a.style.width=~~f[3]+"px");f[4]!==c[4]&&(a.style.height=~~f[4]+"px");f[5]!==c[5]&&(a.style.opacity=f[5]);2===f[6].length&&(e=Elm.Color.extract(f[6][1]),e!==a.style.backgroundColor&&(a.style.backgroundColor=e));if(2===f[7].length&&(1===c[7].length||f[7][1]!==c[7][1]))a.parentNode.href=f[7][1];f[1]=c[1]}}return{render:g,update:l,addTo:function(a,b){a.appendChild(b)},newElement:e,flowWith:j,goIn:d}}();
-Elm.Signal=function(){function e(a){this.id=Guid.guid();this.value=a;this.kids=[];this.defaultNumberOfKids=0;this.recv=function(a,b,c){if(b=b===this.id)this.value=c;l(this,a,b);return b};Dispatcher.inputs.push(this)}function k(a,b){this.id=Guid.guid();this.value=null;this.kids=[];this.count=0;this.changed=!1;b.reverse();this.recalc=function(){for(var d=a,e=b.length;e--;)d=d(b[e].value);this.value=d};this.recalc();this.recv=function(a,c){this.count+=1;c&&(this.changed=!0);this.count==b.length&&(this.changed&&
-this.recalc(),l(this,a,this.changed),this.changed=!1,this.count=0)};for(var d=b.length;d--;)b[d].kids.push(this)}function b(a,b,d,e){this.id=Guid.guid();this.value=d?b(e.value):b;this.kids=[];this.recv=function(b,d){d&&(this.value=a(e.value)(this.value));l(this,b,d)};e.kids.push(this)}function d(a,b,d){this.id=Guid.guid();this.value=a(d.value)?b:d.value;this.kids=[];this.recv=function(b,f){var e=f&&!a(d.value);e&&(this.value=d.value);l(this,b,e)};d.kids.push(this)}function j(a){this.id=Guid.guid();
-this.value=a.value;this.kids=[];this.recv=function(b,d){var e=d&&!Value.eq(this.value,a.value);e&&(this.value=a.value);l(this,b,e)};a.kids.push(this)}function a(a,b){this.id=Guid.guid();var d=(new window.Date).getTime();this.value=a?Value.Tuple(d,b.value):d;this.kids=[];this.recv=function(d,e){e&&(this.value=a?Value.Tuple(d,b.value):d);l(this,d,e)};b.kids.push(this)}function m(a,b){this.id=Guid.guid();this.value=b.value;this.kids=[];this.count=0;this.changed=!1;this.recv=function(d,e,g){g===a.id&&
-(this.changed=e);this.count+=1;2==this.count&&(this.changed&&(this.value=b.value),l(this,d,this.changed),this.count=0,this.changed=!1)};a.kids.push(this);b.kids.push(this)}function g(a,b){this.id=Guid.guid();this.value=a.value;this.kids=[];this.next=null;this.count=0;this.changed=!1;this.recv=function(d,e,g){this.count+=1;e&&(this.changed=!0,g==b.id&&null===this.next&&(this.next=b.value),g==a.id&&(this.next=a.value));2==this.count&&(this.changed&&(this.value=this.next,this.next=null),l(this,d,this.changed),
-this.changed=!1,this.count=0)};a.kids.push(this);b.kids.push(this)}var l=function(a,b,d){for(var e=a.kids,g=e.length;g--;)e[g].recv(b,d,a.id)},h=function(a){return function(b){return function(e){e=new k(function(a){return function(b){return[a,b]}},[a,e]);e=new d(function(a){return a[0]},[!0,b],e);return new k(function(a){return a[1]},[e])}}};return{constant:function(a){return new e(a)},lift:function(a){return function(b){return new k(a,[b])}},lift2:function(a){return function(b){return function(d){return new k(a,
-[b,d])}}},lift3:function(a){return function(b){return function(d){return function(e){return new k(a,[b,d,e])}}}},lift4:function(a){return function(b){return function(d){return function(e){return function(g){return new k(a,[b,d,e,g])}}}}},lift5:function(a){return function(b){return function(d){return function(e){return function(g){return function(h){return new k(a,[b,d,e,g,h])}}}}}},lift6:function(a){return function(b){return function(d){return function(e){return function(g){return function(h){return function(j){return new k(a,
-[b,d,e,g,h,j])}}}}}}},lift7:function(a){return function(b){return function(d){return function(e){return function(g){return function(h){return function(j){return function(l){return new k(a,[b,d,e,g,h,j,l])}}}}}}}},lift8:function(a){return function(b){return function(d){return function(e){return function(g){return function(h){return function(j){return function(l){return function(m){return new k(a,[b,d,e,g,h,j,l,m])}}}}}}}}},foldp:function(a){return function(d){return function(e){return new b(a,d,!1,
-e)}}},foldp_:function(a){return function(d){return function(e){return new b(a,d,!0,e)}}},foldp1:function(a){return function(d){return new b(a,function(a){return a},!0,d)}},delay:function(a){return function(b){var d=new e(b.value),g=!0;b=new m(d,new k(function(a){return function(){return a}},[d,new k(function(b){g||setTimeout(function(){Dispatcher.notify(d.id,b)},a)},[b])]));g=!1;return b}},merge:function(a){return function(b){return new g(a,b)}},merges:function(a){return Elm.List.foldl1(function(a){return function(b){return new g(a,
-b)}})(a)},average:function(a){return function(b){for(var d=Array(a),e=a;e--;)d[e]=0;var e=0,g=!1,h=0;return new k(function(b){h+=b-d[e];d[e]=b;b=h/Math.max(1,g?a:e);++e==a&&(g=!0,e=0);return b},[b])}},count:function(a){return new b(function(){return function(a){return a+1}},0,!1,a)},countIf:function(a){return function(d){return new b(function(b){return function(d){return a(b)?d+1:d}},0,!1,d)}},keepIf:function(a){return function(b){return function(e){return new d(function(b){return!a(b)},b,e)}}},dropIf:function(a){return function(b){return function(e){return new d(a,
-b,e)}}},keepWhen:function(a){return h(new k(function(a){return!a},[a]))},dropWhen:h,dropRepeats:function(a){return new j(a)},sampleOn:function(a){return function(b){return new m(a,b)}},timestamp:function(b){return new a(!0,b)},timeOf:function(b){return new a(!1,b)}}}();
-var Dispatcher=function(){function e(b){if(!b.hasOwnProperty("defaultNumberOfKids"))return!0;var a=b.kids.length;if(0==a)return!1;if(a>b.defaultNumberOfKids)return!0;for(var d=!1;a--;)d=d||e(b.kids[a]);return d}var k=null,b=[],d=null;return{initialize:function(){k=Elm.main();k.hasOwnProperty("recv")||(k=Elm.Signal.constant(k));d=k.value;for(var j=[],a=b.length;a--;)e(b[a])&&j.push(b[a]);b=j;document.getElementById("content").appendChild(Render.render(d));j=document.getElementById("widthChecker").offsetWidth;
-j!==window.innerWidth&&Dispatcher.notify(Elm.Window.dimensions.id,Value.Tuple(j,window.innerHeight));k=Elm.Signal.lift(function(a){var b=document.getElementById("content");Render.update(b.firstChild,d,a);return d=a})(k)},notify:function(d,a){for(var e=(new window.Date).getTime(),g=!1,k=b.length;k--;)g=b[k].recv(e,d,a)||g;return g},inputs:b}}();
-Elm.HTTP=function(){function e(b){return function(d){return function(e){return function(c){return{"0":"Request",length:1,verb:a.castStringToJSString(b),url:a.castStringToJSString(d),data:null===e?null:a.castStringToJSString(e),headers:c}}}}}function k(a){return e("GET")(a)(null)(["Nil"])}function b(b,e){return function(h){if(""!==h.url){var c={value:["Waiting"]};b.push(c);var f=null;window.ActiveXObject&&(f=new ActiveXObject("Microsoft.XMLHTTP"));window.XMLHttpRequest&&(f=new XMLHttpRequest);f.onreadystatechange=
-function(){4===f.readyState&&(c.value=200===f.status?["Success",m(f.responseText)]:["Failure",f.status,m(f.statusText)],setTimeout(function(){d(b,e)},0))};f.open(h.verb,h.url,!0);Elm.List.map(function(b){f.setRequestHeader(a.castStringToJSString(b[1]),a.castStringToJSString(b[2]))})(h.headers);f.send(h.data)}}}function d(a,b){0=a))continue;return["Nothing"]}return["Just",parseFloat(b)]},sqrt:Math.sqrt,abs:Math.abs,pi:Math.PI,e:Math.E,sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,atan2:function(b){return function(d){return Math.atan2(b,d)}},mod:k,min:function(b){return function(d){return Math.min(b,
-d)}},max:function(b){return function(d){return Math.max(b,d)}},flip:function(b){return function(d){return function(e){return b(e)(d)}}},clamp:function(b){return function(d){return function(e){return Math.min(d,Math.max(b,e))}}},curry:function(b){return function(d){return function(e){return b(["Tuple2",d,e])}}},uncurry:function(b){return function(d){if("Tuple2"!==d[0])throw"Function was uncurry'd but was not given a pair.";return b(d[1])(d[2])}},logBase:function(b){return function(d){return Math.log(d)/
-Math.log(b)}},Just:Elm.Maybe.Just,Nothing:Elm.Maybe.Nothing,maybe:Elm.Maybe.maybe,map:Elm.List.map,zip:Elm.List.zip,zipWith:Elm.List.zipWith,filter:Elm.List.filter,head:Elm.List.head,tail:Elm.List.tail,last:Elm.List.last,length:Elm.List.length,reverse:Elm.List.reverse,foldr:Elm.List.foldr,foldr1:Elm.List.foldr1,foldl:Elm.List.foldl,foldl1:Elm.List.foldl1,and:Elm.List.and,or:Elm.List.or,all:Elm.List.all,any:Elm.List.any,sum:Elm.List.sum,product:Elm.List.product,concat:Elm.List.concat,concatMap:Elm.List.concatMap,
-maximum:Elm.List.maximum,minimum:Elm.List.minimum,scanl:Elm.List.scanl,scanl1:Elm.List.scanl1,take:Elm.List.take,drop:Elm.List.drop,zip:Elm.List.zip,unzip:Elm.List.unzip,lift:Elm.Signal.lift,lift2:Elm.Signal.lift2,lift3:Elm.Signal.lift3,lift4:Elm.Signal.lift4,lift5:Elm.Signal.lift5,lift6:Elm.Signal.lift6,lift7:Elm.Signal.lift7,lift8:Elm.Signal.lift8,foldp:Elm.Signal.foldp,foldp1:Elm.Signal.foldp1,foldp_:Elm.Signal.foldp_,constant:Elm.Signal.constant,merge:Elm.Signal.merge,count:Elm.Signal.count,countIf:Elm.Signal.countIf,
-average:Elm.Signal.average,keepIf:Elm.Signal.keepIf,dropIf:Elm.Signal.dropIf,keepWhen:Elm.Signal.keepWhen,dropWhen:Elm.Signal.dropWhen,dropRepeats:Elm.Signal.dropRepeats,sampleOn:Elm.Signal.sampleOn,timestamp:Elm.Signal.timestamp,timeOf:Elm.Signal.timeOf}}();(function(){var e=function(e){for(var b in e)Elm.Prelude[b]=e[b]};e(Elm.Color);e(Elm.Text);e(Elm.Graphics);e(Elm.Time);show=Value.show})();
-Elm.Dict=function(){function e(a){return function(b){return function(c){return function(e){return function(d){return["RBNode",a,b,c,e,d]}}}}}function k(a){a:{switch(a[0]){case "RBEmpty":throw"(min RBEmpty) is not defined";case "RBNode":switch(a[4][0]){case "RBEmpty":a=["Tuple2",a[2],a[3]];break a}a=k(a[4]);break a}throw"Non-exhaustive pattern match in case";}return a}function b(a){return function(c){var e;a:{switch(c[0]){case "RBEmpty":e=w;break a;case "RBNode":e=function(){switch(q(a)(c[2])[0]){case "EQ":return A(c[3]);
-case "GT":return b(a)(c[5]);case "LT":return b(a)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";}return e}}function d(a){return function(b){return function(c){var e;a:{switch(c[0]){case "RBEmpty":e=a;break a;case "RBNode":e=function(){switch(q(b)(c[2])[0]){case "EQ":return c[3];case "GT":return d(a)(b)(c[5]);case "LT":return d(a)(b)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";
-}return e}}}function j(a){return function(c){return F(b(a)(c))}}function a(a){a:{switch(a[0]){case "RBNode":switch(a[5][0]){case "RBNode":a=e(a[1])(a[5][2])(a[5][3])(e(B)(a[2])(a[3])(a[4])(a[5][4]))(a[5][5]);break a}}throw"rotateLeft of a node without enough children";}return a}function m(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":a=e(a[1])(a[4][2])(a[4][3])(a[4][4])(e(B)(a[2])(a[3])(a[4][5])(a[5]));break a}}throw"rotateRight of a node without enough children";}return a}function g(a){a:{switch(a[0]){case "Black":a=
-B;break a;case "Red":a=E;break a}throw"Non-exhaustive pattern match in case";}return a}function l(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[5][0]){case "RBNode":a=e(g(a[1]))(a[2])(a[3])(e(g(a[4][1]))(a[4][2])(a[4][3])(a[4][4])(a[4][5]))(e(g(a[5][1]))(a[5][2])(a[5][3])(a[5][4])(a[5][5]));break a}}}throw"color_flip called on a RBEmpty or RBNode with a RBEmpty child";}return a}function h(b){a:switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":b=
-a(b);break a}}}a:switch(b[0]){case "RBNode":switch(b[4][0]){case "RBNode":switch(b[4][1][0]){case "Red":switch(b[4][4][0]){case "RBNode":switch(b[4][4][1][0]){case "Red":b=m(b);break a}}}}}a:switch(b[0]){case "RBNode":switch(b[4][0]){case "RBNode":switch(b[4][1][0]){case "Red":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":b=l(b);break a}}}}}return b}function c(a){a:switch(a[0]){case "RBNode":switch(a[1][0]){case "Red":a=e(E)(a[2])(a[3])(a[4])(a[5]);break a}}return a}function f(a){return function(b){return function(d){var f=
-function(c){var d;a:{switch(c[0]){case "RBEmpty":d=e(B)(a)(b)(z)(z);break a;case "RBNode":d=function(){switch(q(a)(c[2])[0]){case "EQ":return e(c[1])(c[2])(b)(c[4])(c[5]);case "GT":return e(c[1])(c[2])(c[3])(c[4])(f(c[5]));case "LT":return e(c[1])(c[2])(c[3])(f(c[4]))(c[5])}throw"Non-exhaustive pattern match in case";}();d=h(d);break a}throw"Non-exhaustive pattern match in case";}return d};return c(f(d))}}}function v(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":a=
-!0;break a}}}a=!1}return a}function n(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][4][0]){case "RBNode":switch(a[4][4][1][0]){case "Red":a=!0;break a}}}}a=!1}return a}function p(b){if(x(v(b))&&x(n(b))){b=l(b);a:switch(b[0]){case "RBNode":b:switch(b[5][0]){case "RBNode":switch(b[5][4][0]){case "RBNode":switch(b[5][4][1][0]){case "Red":b=l(a(e(b[1])(b[2])(b[3])(b[4])(m(b[5]))));break b}}}break a}}return b}function r(a){return function(b){var d=function(b){a:{switch(b[0]){case "RBEmpty":b=
-z;break a;case "RBNode":if("LT"===q(a)(b[2])[0])b:{b=p(b);switch(b[0]){case "RBEmpty":throw"delLT on RBEmpty";case "RBNode":b=h(e(b[1])(b[2])(b[3])(d(b[4]))(b[5]));break b}break}else{var f=v(b)?m(b):b,g;b:{switch(f[0]){case "RBNode":switch(f[5][0]){case "RBEmpty":g=D(a,f[2]);break b}}g=!1}if(g)b=f[4];else{f=x;b:{switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":g=!0;break b}}}g=!1}if(f=f(g)){f=x;b:{switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][4][0]){case "RBNode":switch(b[5][4][1][0]){case "Red":g=
-!0;break b}}}}g=!1}f=f(g)}f&&(b=l(b),b=n(b)?l(m(b)):b);b:{switch(b[0]){case "RBNode":f=D(a,b[2]);break b}f=!1}if(f)b:{switch(b[0]){case "RBEmpty":throw"delEQ called on a RBEmpty";case "RBNode":g=k(b[5]);c:{switch(g[0]){case "Tuple2":f=g[1];break c}break}c:{switch(g[0]){case "Tuple2":g=g[2];break c}break}var f=e(b[1])(f)(g)(b[4]),j=function(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBEmpty":a=z;break a}}b:{a=p(a);switch(a[0]){case "RBEmpty":a=z;break b;case "RBNode":a=h(e(a[1])(a[2])(a[3])(j(a[4]))(a[5]));
-break b}throw"Non-exhaustive pattern match in case";}}return a};b=c(j(b[5]));b=h(f(b));break b}break}else b:{switch(b[0]){case "RBEmpty":throw"delGT called on a RBEmpty";case "RBNode":b=h(e(b[1])(b[2])(b[3])(b[4])(d(b[5])));break b}break}}}break a}throw"Non-exhaustive pattern match in case";}return b};return j(a)(b)?c(d(b)):b}}function y(a){return function(b){a:{switch(b[0]){case "RBEmpty":b=z;break a;case "RBNode":b=e(b[1])(b[2])(a(b[3]))(y(a)(b[4]))(y(a)(b[5]));break a}throw"Non-exhaustive pattern match in case";
-}return b}}function s(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=s(a)(a(c[2])(c[3])(s(a)(b)(c[4])))(c[5]);break a}throw"Non-exhaustive pattern match in case";}return c}}}function u(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=u(a)(a(c[2])(c[3])(u(a)(b)(c[5])))(c[4]);break a}throw"Non-exhaustive pattern match in case";}return c}}}var q=Elm.Prelude.compare,t=Elm.Prelude.uncurry,w=Elm.Prelude.Nothing,
-A=Elm.Prelude.Just,x=Elm.Prelude.not,D=Elm.Prelude.eq,F=Elm.Maybe.isJust,B=["Red"],E=["Black"],z=["RBEmpty"],C=z;return{$op:{},empty:C,lookup:b,findWithDefault:d,member:j,insert:f,singleton:function(a){return function(b){return f(a)(b)(z)}},remove:r,map:y,foldl:s,foldr:u,union:function(a){return function(b){return s(f)(b)(a)}},intersect:function(a){return function(b){return s(function(a){return function(c){return function(d){return j(a)(b)?f(a)(c)(d):d}}})(C)(a)}},diff:function(a){return function(b){return s(function(a){return function(){return function(b){return r(a)(b)}}})(a)(b)}},
-keys:function(a){return u(function(a){return function(){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},values:function(a){return u(function(){return function(a){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},toList:function(a){return u(function(a){return function(b){return function(c){return["Cons",["Tuple2",a,b],c]}}})(["Nil"])(a)},fromList:function(a){return Elm.List.foldl(t(f))(C)(a)}}}();
-Elm.Set=function(){var e=Elm.Dict.empty,k=Elm.Dict.remove,b=Elm.Dict.member,d=Elm.Dict.union,j=Elm.Dict.intersect,a=Elm.Dict.diff,m=Elm.Dict.keys,g=Elm.List.foldl(function(a){return function(b){return Elm.Dict.insert(a)(["Tuple0"])(b)}})(e);return{empty:e,singleton:function(a){return Elm.Dict.singleton(a)(["Tuple0"])},insert:function(a){return Elm.Dict.insert(a)(["Tuple0"])},remove:k,member:b,union:d,intersect:j,diff:a,toList:m,fromList:g,foldl:function(a){return Elm.Dict.foldl(function(b){return function(){return function(c){return a(b)(c)}}})},
-foldr:function(a){return Elm.Dict.foldr(function(b){return function(){return function(c){return a(b)(c)}}})},map:function(a){return function(b){b=m(b);return g(Elm.List.map(a)(b))}}}}();
-(function(){try{var e={};for(this.i in Elm)eval("var "+this.i+"=Elm[this.i];");if(Elm.Automaton)throw"Module name collision, 'Automaton' is already defined.";Elm.Automaton=function(){function b(a){return["Automaton",a]}function d(a){return b(function(b){var c=unzip(map(function(a){a:{switch(a[0]){case "Automaton":a=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return a})(a)),e;a:{switch(c[0]){case "Tuple2":e=c[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(c[0]){case "Tuple2":c=
-c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",e,d(c)]})}function j(a){return b(function(b){return["Tuple2",a(b),j(a)]})}function a(c){return function(d){return b(function(b){b=d(b)(c);return["Tuple2",b,a(b)(d)]})}}function k(a){return function(c){return b(function(b){var d=c(b)(a);a:{switch(d[0]){case "Tuple2":b=d[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(d[0]){case "Tuple2":d=d[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",
-b,k(d)(c)]})}}function g(a){return function(b){a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":b=["Tuple2",a[1]-b[1],a[2]-b[2]];break b}break}break a}throw"Non-exhaustive pattern match in case";}return b}}function l(a){return function(b){var c;a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":var d=function(a){return["Tuple2",b[2],["Tuple2",a,b[2]]]};c=function(){switch(b[1][0]){case "DragFrom":var c;a[1]?c=["Tuple2",uncurry(move)(g(a[2])(b[1][1]))(b[2]),["Tuple2",["DragFrom",
-b[1][1]],b[2]]]:(c=uncurry(move)(g(a[2])(b[1][1]))(b[2]),c=["Tuple2",c,["Tuple2",f,c]]);return c;case "Ignore":return d(a[1]?v:f);case "Listen":return d(not(a[1])?f:isWithin(a[2])(b[2])?["DragFrom",a[2]]:v)}throw"Non-exhaustive pattern match in case";}();break b}break}break a}throw"Non-exhaustive pattern match in case";}return c}}try{if(!(Elm.Prelude instanceof Object))throw"module not found";}catch(h){throw"Module 'Prelude' is missing. Compile with --make flag or load missing module in a separate JavaScript file.";
-}var c={};for(this.i in Elm.Prelude)c[this.i]||eval("var "+this.i+" = Elm.Prelude[this.i];");var f=["Listen"],v=["Ignore"];e[">>>"]=function(a){return function(c){var d;a:{switch(a[0]){case "Automaton":d=a[1];break a}throw"Non-exhaustive pattern match in case";}var f;a:{switch(c[0]){case "Automaton":f=c[1];break a}throw"Non-exhaustive pattern match in case";}return b(function(a){a=d(a);var b;a:{switch(a[0]){case "Tuple2":b=a[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(a[0]){case "Tuple2":a=
-a[2];break a}throw"Non-exhaustive pattern match in case";}var c=f(b);a:{switch(c[0]){case "Tuple2":b=c[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(c[0]){case "Tuple2":c=c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",b,e[">>>"](a)(c)]})}};e["<<<"]=function(a){return function(b){return e[">>>"](b)(a)}};e["^>>"]=function(a){return function(b){return e[">>>"](j(a))(b)}};e[">>^"]=function(a){return function(b){return e[">>>"](a)(j(b))}};e["^<<"]=function(a){return function(b){return e[">>>"](b)(j(a))}};
-e["<<^"]=function(a){return function(b){return e[">>>"](j(b))(a)}};c=a(0)(function(){return function(a){return 1+a}});return{$op:{">>>":e[">>>"],"<<<":e["<<<"],"^>>":e["^>>"],">>^":e[">>^"],"^<<":e["^<<"],"<<^":e["<<^"]},run:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=lift(fst)(foldp_(function(a){return function(b){a:{switch(b[0]){case "Tuple2":switch(b[2][0]){case "Automaton":b=b[2][1](a);break a}}throw"Non-exhaustive pattern match in case";}return b}})(a[1])(b));break a}throw"Non-exhaustive pattern match in case";
-}return b}},step:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return b}},combine:d,pure:j,init:a,init_:k,count:c,draggable:function(a){return k(["Tuple2",f,a])(l)}}}();Elm.main=function(){return Elm.Automaton.main}}catch(k){Elm.main=function(){document.body.innerHTML=Elm.Text.monospace('
Your browser may not be supported. Are you using a modern browser?
Runtime Error in Automaton module:
'+
-k+"");throw k;}}})();
\ No newline at end of file
diff --git a/elm/src/Gen/CompileToJS.hs b/elm/src/Gen/CompileToJS.hs
deleted file mode 100644
index 366e4c2..0000000
--- a/elm/src/Gen/CompileToJS.hs
+++ /dev/null
@@ -1,323 +0,0 @@
-module CompileToJS (showErr, jsModule) where
-
-import Ast
-import Context
-import Control.Arrow (first,second)
-import Control.Monad (liftM,(<=<),join,ap)
-import Data.Char (isAlpha,isDigit)
-import Data.List (intercalate,sortBy,inits,foldl')
-import qualified Data.Map as Map
-import Data.Either (partitionEithers)
-import qualified Text.Pandoc as Pan
-
-import Initialize
-import Rename (derename)
-import Cases
-import Guid
-import Parse.Library (isOp)
-import Rename (deprime)
-
-showErr :: String -> String
-showErr err = mainEquals $ "Elm.Graphics.text(Elm.Text.monospace(" ++ msg ++ "))"
- where msg = show . concatMap (++"
") . lines $ err
-
-indent = concatMap f
- where f '\n' = "\n "
- f c = [c]
-
-parens s = "(" ++ s ++ ")"
-braces s = "{" ++ s ++ "}"
-jsList ss = "["++ intercalate "," ss ++"]"
-jsFunc args body = "function(" ++ args ++ "){" ++ indent body ++ "}"
-assign x e = "\nvar " ++ x ++ "=" ++ e ++ ";"
-ret e = "\nreturn "++ e ++";"
-iff a b c = a ++ "?" ++ b ++ ":" ++ c
-quoted s = "'" ++ concatMap f s ++ "'"
- where f '\n' = "\\n"
- f '\'' = "\\'"
- f '\t' = "\\t"
- f '\"' = "\\\""
- f '\\' = "\\\\"
- f c = [c]
-
-mainEquals s = globalAssign "Elm.main" (jsFunc "" (ret s))
-globalAssign m s = "\n" ++ m ++ "=" ++ s ++ ";"
-
-tryBlock escapees names e =
- concat [ "\ntry{\n" ++ e ++ "\n} catch (e) {"
- , "\nElm.main=function() {"
- , "\nvar msg = ('
Your browser may not be supported. " ++
- "Are you using a modern browser?
' +" ++
- " '
Runtime Error in " ++
- intercalate "." names ++ " module:
' + e + '" ++ msg ++ "');"
- , "\ndocument.body.innerHTML = Elm.Text.monospace(msg);"
- , "throw e;"
- , "};}"
- ]
- where msg | escapees /= [] = concat [ "
The problem may stem from an improper usage of:
"
- , intercalate ", " $ map (concatMap escape) escapees ]
- | otherwise = ""
- escape '\'' = "\\'"
- escape '"' = "\\\""
- escape c = [c]
-
-
-jsModule (escapees, Module names exports imports stmts) =
- tryBlock escapees (tail modNames) $ concat
- [ concatMap (\n -> globalAssign n $ n ++ " || {}") .
- map (intercalate ".") . drop 2 . inits $
- take (length modNames - 1) modNames
- , "\nif (" ++ modName ++ ") throw new Error(\"Module name collision, '" ++
- intercalate "." (tail modNames) ++ "' is already defined.\"); "
- , globalAssign modName $ jsFunc "" (defs ++ includes ++ body ++ export) ++ "()"
- , mainEquals $ modName ++ ".main" ]
- where modNames = if null names then ["Elm", "Main"]
- else "Elm" : names
- modName = intercalate "." modNames
- includes = concatMap jsImport $ map (first ("Elm."++)) imports
- body = stmtsToJS stmts
- export = getExports exports stmts
- exps = if null exports then ["main"] else exports
- defs = concat [ assign "$op" "{}"
- , "\nfor(Elm['i'] in Elm){eval('var '+Elm['i']+'=Elm[Elm.i];');}" ]
-
-getExports names stmts = ret . braces $ intercalate ",\n" (op : map fnPair fns)
- where exNames n = either derename id n `elem` names
- exports | null names = concatMap get stmts
- | otherwise = filter exNames (concatMap get stmts)
-
- (fns,ops) = partitionEithers exports
-
- opPair op = "'" ++ op ++ "' : $op['" ++ op ++ "']"
- fnPair fn = let fn' = derename fn in fn' ++ ":" ++ fn
-
- op = ("$op : "++) . braces . intercalate ", " $ map opPair ops
-
- get' (FnDef x _ _) = Left x
- get' (OpDef op _ _ _) = Right op
- get s = case s of Definition d -> [ get' d ]
- Datatype _ _ tcs -> map (Left . fst) tcs
- ImportEvent _ _ x _ -> [ Left x ]
- ExportEvent _ _ _ -> []
- TypeAlias _ _ _ -> []
- TypeAnnotation _ _ -> []
-
-
-jsImport (modul, how) =
- concat [ "\ntry{\n if (!(" ++ modul ++ " instanceof Object)) throw new Error('module not found');\n} catch(e) {\n throw new Error(\"Module '"
- , drop 1 (dropWhile (/='.') modul)
- , "' is missing. Compile with --make flag or load missing "
- , "module in a separate JavaScript file.\");\n}" ] ++
- jsImport' (modul, how)
-
-jsImport' (modul, As name) = assign name modul
-jsImport' (modul, Importing vs) = concatMap def vs
- where def [] = []
- def (o:p) | isOp o = let v = "$op['" ++ o:p ++ "']" in
- "\n" ++ v ++ " = " ++ modul ++ "." ++ v ++ ";"
- | otherwise = let v = deprime (o:p) in
- assign v $ modul ++ "." ++ v
-
-jsImport' (modul, Hiding vs) =
- concat [ assign "hiddenVars" . ("{"++) . (++"}") . intercalate "," $
- map (\v -> v ++ ":true") (map deprime vs)
- , "\nfor (Elm['i'] in " ++ modul ++ ") "
- , braces . indent . concat $
- [ "\nif (hiddenVars[Elm['i']]) continue;"
- , "\neval('var ' + Elm['i'] + ' = "
- , modul, "[Elm.i];');" ]
- ]
-
-stmtsToJS :: [Statement] -> String
-stmtsToJS stmts = run (concat `liftM` mapM toJS (sortBy cmpStmt stmts))
- where cmpStmt s1 s2 = compare (valueOf s1) (valueOf s2)
- valueOf s = case s of
- Datatype _ _ _ -> 1
- ImportEvent _ _ _ _ -> 2
- Definition (FnDef f [] _) ->
- if derename f == "main" then 5 else 4
- Definition _ -> 3
- ExportEvent _ _ _ -> 6
- TypeAlias _ _ _ -> 0
- TypeAnnotation _ _ -> 0
-
-class ToJS a where
- toJS :: a -> GuidCounter String
-
-instance ToJS Def where
- toJS (FnDef x [] e) = assign x `liftM` toJS' e
- toJS (FnDef f (a:as) e) =
- do body <- toJS' (foldr (\x e -> noContext (Lambda x e)) e as)
- return $ concat ["\nfunction ",f,parens a, braces . indent $ ret body]
- toJS (OpDef op a1 a2 e) =
- do body <- toJS' (foldr (\x e -> noContext (Lambda x e)) e [a1,a2])
- return $ concat [ "\n$op['", op, "'] = ", body, ";" ]
-
-instance ToJS Statement where
- toJS (Definition d) = toJS d
- toJS (Datatype _ _ tcs) = concat `liftM` mapM (toJS . toDef) tcs
- where toDef (name,args) = Definition . FnDef name vars . noContext $
- Data (derename name) (map (noContext . Var) vars)
- where vars = map (('a':) . show) [1..length args]
- toJS (ImportEvent js base elm _) =
- do v <- toJS' base
- return $ concat [ "\nvar " ++ elm ++ "=Elm.Signal.constant(" ++ v ++ ");"
- , "\nValue.addListener(document, '" ++ js
- , "', function(e) { Dispatcher.notify(" ++ elm
- , ".id, e.value); });" ]
- toJS (ExportEvent js elm _) =
- return $ concat [ "\nlift(function(v) { "
- , "var e = document.createEvent('Event');"
- , "e.initEvent('", js, "', true, true);"
- , "e.value = v;"
- , "document.dispatchEvent(e); return v; })(", elm, ");" ]
- toJS (TypeAnnotation _ _) = return ""
- toJS (TypeAlias _ _ _) = return ""
-
-toJS' :: CExpr -> GuidCounter String
-toJS' (C txt span expr) =
- case expr of
- MultiIf ps -> multiIfToJS span ps
- Case e cases -> caseToJS span e cases
- _ -> toJS expr
-
-remove x e = "elmRecordRemove('" ++ x ++ "', " ++ e ++ ")"
-addField x v e = "elmRecordInsert('" ++ x ++ "', " ++ v ++ ", " ++ e ++ ")"
-setField fs e = "elmRecordReplace(" ++ jsList (map f fs) ++ ", " ++ e ++ ")"
- where f (x,v) = "['" ++ x ++ "'," ++ v ++ "]"
-access x e = parens e ++ "." ++ x
-makeRecord kvs = record `liftM` collect kvs
- where
- combine r (k,v) = Map.insertWith (++) k v r
- collect = liftM (foldl' combine Map.empty) . mapM prep
- prep (k, as, e@(C t s _)) =
- do v <- toJS' (foldr (\x e -> C t s $ Lambda x e) e as)
- return (k,[v])
- fields fs =
- braces ("\n "++intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
- hidden = fields . map (second jsList) .
- filter (not . null . snd) . Map.toList . Map.map tail
- record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
-
-
-instance ToJS Expr where
- toJS expr =
- case expr of
- IntNum n -> return $ show n
- FloatNum n -> return $ show n
- Var x -> return $ x
- Chr c -> return $ quoted [c]
- Str s -> return $ "Value.str" ++ parens (quoted s)
- Boolean b -> return $ if b then "true" else "false"
- Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
- Access e x -> access x `liftM` toJS' e
- Remove e x -> remove x `liftM` toJS' e
- Insert e x v -> addField x `liftM` toJS' v `ap` toJS' e
- Modify e fs -> do fs' <- (mapM (\(x,v) -> (,) x `liftM` toJS' v) fs)
- setField fs' `liftM` toJS' e
- Record fs -> makeRecord fs
- Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
-
- If eb et ef ->
- parens `liftM` (iff `liftM` toJS' eb `ap` toJS' et `ap` toJS' ef)
-
- Lambda v e -> liftM (jsFunc v . ret) (toJS' e)
-
- App (C _ _ (Var "toText")) (C _ _ (Str s)) ->
- return $ "toText" ++ parens (quoted s)
-
- App (C _ _ (Var "link")) (C _ _ (Str s)) ->
- return $ "link(" ++ quoted s ++ ")"
-
- App (C _ _ (Var "plainText")) (C _ _ (Str s)) ->
- return $ "plainText(" ++ quoted s ++ ")"
-
- App e1 e2 -> (++) `liftM` (toJS' e1) `ap` (parens `liftM` toJS' e2)
- Let defs e -> jsLet defs e
- Data name es -> (\ss -> jsList $ quoted name : ss) `liftM` mapM toJS' es
-
- Markdown doc -> return $ "text('" ++ pad ++ md ++ pad ++ "')"
- where pad = "
"
- md = formatMarkdown $ Pan.writeHtmlString Pan.def doc
-
-formatMarkdown = concatMap f
- where f '\'' = "\\'"
- f '\n' = "\\n"
- f '"' = "\""
- f c = [c]
-
-multiIfToJS span ps = format `liftM` mapM f ps
- where format cs = foldr (\c e -> parens $ c ++ " : " ++ e) err cs
- err = concat [ "(function(){throw new Error(\"Non-exhaustive "
- , "multi-way-if expression (", show span, ")\");}())" ]
- f (b,e) = do b' <- toJS' b
- e' <- toJS' e
- return (b' ++ " ? " ++ e')
-
-jsLet defs e' = do
- body <- (++) `liftM` jsDefs defs `ap` (ret `liftM` toJS' e')
- return $ jsFunc "" body ++ "()"
-
-jsDefs defs = concat `liftM` mapM toJS (sortBy f defs)
- where f a b = compare (valueOf a) (valueOf b)
- valueOf (FnDef _ args _) = min 1 (length args)
- valueOf (OpDef _ _ _ _) = 1
-
-caseToJS span e ps = do
- match <- caseToMatch ps
- e' <- toJS' e
- (match',stmt) <- case (match,e) of
- (Match name _ _, C _ _ (Var x)) -> return (matchSubst [(name,x)] match, "")
- (Match name _ _, _) -> return (match, assign name e')
- _ -> liftM (\n -> (match, e')) guid
- matches <- matchToJS span match'
- return $ concat [ "function(){", stmt, matches, "}()" ]
-
-matchToJS span (Match name clauses def) = do
- cases <- concat `liftM` mapM (clauseToJS span name) clauses
- finally <- matchToJS span def
- return $ concat [ "\nswitch(", name, "[0]){", indent cases, "\n}", finally ]
-matchToJS span Fail = return ("\nthrow new Error(\"Non-exhaustive pattern match " ++
- "in case expression (" ++ show span ++ ")\");")
-matchToJS span Break = return "break;"
-matchToJS span (Other e) = ret `liftM` toJS' e
-matchToJS span (Seq ms) = concat `liftM` mapM (matchToJS span) ms
-
-clauseToJS span var (Clause name vars e) = do
- let vars' = map (\n -> var ++ "[" ++ show n ++ "]") [ 1 .. length vars ]
- s <- matchToJS span $ matchSubst (zip vars vars') e
- return $ concat [ "\ncase ", quoted name, ":", s ]
-
-jsNil = "[\"Nil\"]"
-jsCons e1 e2 = jsList [ quoted "Cons", e1, e2 ]
-jsRange e1 e2 = (++"()") . jsFunc "" $
- assign "lo" e1 ++ assign "hi" e2 ++ assign "lst" jsNil ++
- "if(lo<=hi){do{lst=" ++ (jsCons "hi" "lst") ++ "}while(hi-->lo)}" ++
- ret "lst"
-
-binop (o:p) e1 e2
- | isAlpha o || '_' == o = (o:p) ++ parens e1 ++ parens e2
- | otherwise =
- let ops = ["+","-","*","/","&&","||"] in
- case o:p of
- "::" -> jsCons e1 e2
- "++" -> append e1 e2
- "$" -> e1 ++ parens e2
- "." -> jsFunc "x" . ret $ e1 ++ parens (e2 ++ parens "x")
- "^" -> "Math.pow(" ++ e1 ++ "," ++ e2 ++ ")"
- "==" -> "eq(" ++ e1 ++ "," ++ e2 ++ ")"
- "/=" -> "not(eq(" ++ e1 ++ "," ++ e2 ++ "))"
- "<" -> "(compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0] === 'LT')"
- ">" -> "(compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0] === 'GT')"
- "<=" -> "function() { var ord = compare(" ++ e1 ++ ")(" ++
- e2 ++ ")[0]; return ord==='LT' || ord==='EQ'; }()"
- ">=" -> "function() { var ord = compare(" ++ e1 ++ ")(" ++
- e2 ++ ")[0]; return ord==='GT' || ord==='EQ'; }()"
- "<~" -> "lift" ++ parens e1 ++ parens e2
- "~" -> "lift2(function(f){return function(x){return f(x);};})" ++
- parens e1 ++ parens e2
- _ | elem (o:p) ops -> parens (e1 ++ (o:p) ++ e2)
- | otherwise -> concat [ "$op['", o:p, "']"
- , parens e1, parens e2 ]
-
-append e1 e2 = "Value.append" ++ parens (e1 ++ "," ++ e2)
diff --git a/elm/src/Gen/GenerateHtml.hs b/elm/src/Gen/GenerateHtml.hs
deleted file mode 100644
index b18645d..0000000
--- a/elm/src/Gen/GenerateHtml.hs
+++ /dev/null
@@ -1,89 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module GenerateHtml (generateHtml,
- body, css, widgetBody,
- modulesToHtml, linkedHtml,
- JSStyle (..)
- ) where
-
-import Data.List (intercalate)
-import Text.Blaze (preEscapedToMarkup)
-import Text.Blaze.Html (Html)
-import qualified Text.Blaze.Html5 as H
-import Text.Blaze.Html5 ((!))
-import qualified Text.Blaze.Html5.Attributes as A
-
-import Text.Jasmine (minify)
-import qualified Data.ByteString.Lazy.Char8 as BS
-
-import Ast
-import Initialize
-import CompileToJS
-import ExtractNoscript
-
-css = H.style ! A.type_ "text/css" $ preEscapedToMarkup
- ("html,head,body { padding:0; margin:0; }\
- \body { font-family: helvetica, arial, sans-serif; }" :: String)
-
-data JSStyle = Minified | Readable
-
-makeScript :: JSStyle -> Either String String -> H.Html
-makeScript _ (Left s) =
- H.script ! A.type_ "text/javascript" ! A.src (H.toValue s) $ ""
-makeScript jsStyle (Right s) =
- H.script ! A.type_ "text/javascript" $ preEscapedToMarkup content
- where content = case jsStyle of
- Minified -> BS.unpack . minify . BS.pack $ s
- Readable -> s
-
--- |This function compiles Elm code into simple HTML.
---
--- Usage example:
---
--- > generateHtml "/elm-min.js" "Some title" [elmFile|elm-source/somePage.elm|]
-generateHtml :: String -- ^ Location of elm-min.js as expected by the browser
- -> String -- ^ The page title
- -> String -- ^ The elm source code.
- -> Html
-generateHtml libLoc title source =
- case buildFromSource source of
- Left err -> createHtml Readable libLoc title (Right $ showErr err) (H.noscript "")
- Right (escs, modul) -> modulesToHtml Readable title libLoc [] True [(escs,modul)]
-
-
-modulesToHtml jsStyle title libLoc jss nscrpt pairs =
- createHtml jsStyle libLoc title' js noscript
- where modules = map snd pairs
- js = Right $ jss ++ concatMap jsModule pairs
- noscript = if nscrpt then extractNoscript $ last modules else ""
- title' = if null title then altTitle else title
- altTitle = (\(Module names _ _ _) -> intercalate "." names) $
- last modules
-
-
-linkedHtml rtLoc jsLoc modules =
- createHtml Readable rtLoc title (Left jsLoc) (H.noscript "")
- where title = (\(Module names _ _ _) -> intercalate "." names) $
- snd (last modules)
-
-
-createHtml jsStyle libLoc title js noscript =
- H.docTypeHtml $ do
- H.head $ do
- H.meta ! A.charset "UTF-8"
- H.title . H.toHtml $ title
- css
- H.body $ do
- makeScript Readable (Left libLoc)
- makeScript jsStyle js
- body noscript
-
-body noscript = do
- H.div ! A.id "widthChecker" ! A.style "width:100%; height:1px; position:absolute; top:-1px;" $ ""
- H.div ! A.id "content" $ ""
- H.script ! A.type_ "text/javascript" $ "Dispatcher.initialize()"
- H.noscript $ preEscapedToMarkup noscript
-
-widgetBody noscript = do
- H.div ! A.id "widthChecker" ! A.style "width:100%; height:1px; position:absolute; top:-1px;" $ ""
- H.div ! A.id "content" $ ""
- H.noscript $ preEscapedToMarkup noscript
diff --git a/elm/src/Initialize.hs b/elm/src/Initialize.hs
deleted file mode 100644
index 253de6a..0000000
--- a/elm/src/Initialize.hs
+++ /dev/null
@@ -1,95 +0,0 @@
-module Initialize (build,buildFromSource) where
-
-import Control.Applicative ((<$>))
-import Control.Monad.Error
-import Data.List (lookup)
-
-import Ast
-import Data.Either (lefts,rights)
-import Data.List (intercalate,partition)
-import Parse.Parser (parseProgram)
-import Rename
-import Types.Types ((-:))
-import Types.Hints (hints)
-import Types.Unify
-import Types.Alias
-import Optimize
-
-checkMistakes :: Module -> Either String Module
-checkMistakes modul@(Module name ex im stmts) =
- case mistakes stmts of
- m:ms -> Left (unlines (m:ms))
- [] -> return modul
-
-checkTypes :: Module -> Either String ([String], Module)
-checkTypes (Module name ex im stmts) =
- let stmts' = dealias stmts
- modul = Module name ex im stmts'
- in do (escapees, subs) <- unify hints modul
- let im' | any ((=="Prelude") . fst) im = im
- | otherwise = ("Prelude", Hiding []) : im
- modul' = optimize . renameModule $ Module name ex im' stmts'
- subs `seq` return (escapees, modul')
-
-check :: Module -> Either String ([String], Module)
-check = checkMistakes >=> checkTypes
-
-buildFromSource :: String -> Either String ([String],Module)
-buildFromSource = parseProgram >=> check
-
-build :: Bool -> FilePath -> IO (Either String ([String],[Module]))
-build make root = do
- proj <- parse make root
- return $ do
- ms <- proj
- (escapeess, modules) <- unzip `liftM` mapM check ms
- sortedModules <- (if make then sort else return) modules
- return (concat escapeess, sortedModules)
-
-parse :: Bool -> FilePath -> IO (Either String [Module])
-parse make root = parseProject [] make root
-
-parseProject :: [FilePath] -> Bool -> FilePath -> IO (Either String [Module])
-parseProject seen make root = do
- txt <- readFile root
- case parseProgram txt of
- Left err -> return (Left err)
- Right modul@(Module names exs ims stmts) ->
- let allDeps = map toFilePath (getDeps modul)
- newDeps = if make then filter (`notElem` seen) allDeps else []
- name = intercalate "." names
- in do ps <- mapM (parseProject (name : seen ++ newDeps) make) newDeps
- return $ case unlines (lefts ps) of
- c:cs -> Left (c:cs)
- _ -> Right (modul : concat (rights ps))
-
-toFilePath :: String -> FilePath
-toFilePath modul = map (\c -> if c == '.' then '/' else c) modul ++ ".elm"
-
-getDeps :: Module -> [String]
-getDeps (Module _ _ is _) = filter (`notElem` builtInModules) (map fst is)
- where
- builtInModules =
- ["List","Char","Either","Maybe","Dict","Set","Automaton","Date",
- "Signal","Mouse","Keyboard.Raw","Keyboard","Touch",
- "WebSocket","Window","Time","HTTP","Input","Random",
- "Graphics","Text","Color","JavaScript",
- "JavaScript.Experimental","Prelude","JSON"]
-
-
-sort :: [Module] -> Either String [Module]
-sort = go []
- where
- msg = "A cyclical or missing module dependency or was detected in: "
- getName (Module names _ _ _) = intercalate "." names
-
- has name modul = name == getName modul
- within ms name = any (has name) ms
-
- go :: [Module] -> [Module] -> Either String [Module]
- go sorted [] = Right sorted
- go sorted unsorted =
- case partition (all (within sorted) . getDeps) unsorted of
- ([],m:ms) -> Left (msg ++ intercalate ", " (map getName (m:ms)))
- (srtd,unsrtd) -> go (sorted ++ srtd) unsrtd
-
\ No newline at end of file
diff --git a/elm/src/Language/Elm.hs b/elm/src/Language/Elm.hs
deleted file mode 100644
index a57076e..0000000
--- a/elm/src/Language/Elm.hs
+++ /dev/null
@@ -1,82 +0,0 @@
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
-{- | This module exports the functions necessary for compiling Elm code into the
- respective HTML, JS and CSS code.
-
- The type class @'ElmSource'@ requires an instance for all types that the Elm compiler
- understands. The provided instances for String, Text and QuasiQuoted Elm source code
- should be sufficient.
-
- The documentation for the Elm language is available at ,
- and many interactive examples are available at
-
- Example implementations using Yesod and Happstack are available at
--}
-module Language.Elm (
- ElmSource (..),
- runtimeLocation
- ) where
-
-import Data.Version (showVersion)
-import CompileToJS
-import ExtractNoscript
-import GenerateHtml
-import Initialize
-import Text.Blaze.Html (Html)
-import Language.Elm.Quasi
-import Paths_Elm
-
-import qualified Data.Text as TS
-import qualified Data.Text.Lazy as TL
-
--- |The absolute path to Elm's runtime system.
-runtimeLocation :: IO FilePath
-runtimeLocation =
- getDataFileName ("elm-runtime-" ++ showVersion version ++ ".js")
-
-class ElmSource a where
- -- |This function compiles Elm code to three separate parts: HTML, CSS,
- -- and JavaScript. The HTML is only the contents of the body, so the three
- -- parts must be combined in a basic HTML skeleton.
- toParts :: a -> (Html, Html, String)
-
- -- |This function compiles Elm code into a full HTML page.
- toHtml :: String -- ^ Location of elm-min.js as expected by the browser
- -> String -- ^ The page title
- -> a -- ^ The elm source code
- -> Html
-
-instance ElmSource String where
- toParts = toPartsHelper
- toHtml = generateHtml
-
-instance ElmSource Elm where
- toParts = toPartsHelper . TL.unpack . renderElm
- toHtml elmL title = generateHtml elmL title . TL.unpack . renderElm
-
---Â |Strict text
-instance ElmSource TS.Text where
- toParts = toPartsHelper . TS.unpack
- toHtml elmL title = generateHtml elmL title . TS.unpack
-
--- |Lazy text
-instance ElmSource TL.Text where
- toParts = toPartsHelper . TL.unpack
- toHtml elmL title = generateHtml elmL title . TL.unpack
-
--- |Â (urlRenderFn, urlRenderFn -> Elm)
-instance ElmSource (t, t -> Elm) where
- toParts (f, s) = toPartsHelper $ TL.unpack $ renderElm $ s f
- toHtml elmL title (f, s) = generateHtml elmL title $ TL.unpack $ renderElm $ s f
-
--- |Â to be used without URL interpolation
-instance ElmSource (t -> Elm) where
- toParts s = toPartsHelper $ TL.unpack $ renderElm $ s undefined
- toHtml l t s = generateHtml l t $ TL.unpack $ renderElm $ s undefined
-
-
--- build helper to avoid boilerplate repetition
-toPartsHelper :: String -> (Html, Html, String)
-toPartsHelper source = (html, css, js)
- where modul = buildFromSource source
- js = either showErr jsModule modul
- html = widgetBody $ either id (extractNoscript . snd) modul
diff --git a/elm/src/Types/Hints.hs b/elm/src/Types/Hints.hs
deleted file mode 100644
index 1f8d5d4..0000000
--- a/elm/src/Types/Hints.hs
+++ /dev/null
@@ -1,446 +0,0 @@
-module Types.Hints (hints) where
-
-import Context
-import Control.Arrow (first)
-import Control.Monad (liftM,mapM)
-import Types.Types
-import Types.Substitutions (rescheme)
-
-ctx str = C (Just str) NoSpan
-prefix pre xs = map (first (\x -> pre ++ "." ++ x)) xs
-hasType t = map (-: t)
-
-
--------- Text and Elements --------
-
-textToText = [ "header", "italic", "bold", "underline"
- , "overline", "strikeThrough", "monospace" ]
-
-textAttrs = [ "toText" -: string ==> text
- , "Text.typeface" -: string ==> text ==> text
- , "Text.link" -:: string ==> text ==> text
- , numScheme (\t -> t ==> text ==> text) "Text.height"
- ] ++ prefix "Text" (hasType (text ==> text) textToText)
-
-elements =
- let iee = int ==> element ==> element in
- [ "plainText" -: string ==> element
- , "link" -:: string ==> element ==> element
- , "flow" -: direction ==> listOf element ==> element
- , "layers" -: listOf element ==> element
- , "text" -: text ==> element
- , "image" -: int ==> int ==> string ==> element
- , "video" -: int ==> int ==> string ==> element
- , "opacity" -: float ==> element ==> element
- , "width" -: iee
- , "height" -: iee
- , "size" -: int ==> iee
- , "widthOf" -: element ==> int
- , "heightOf"-: element ==> int
- , "sizeOf" -: element ==> pairOf int
- , "color" -: color ==> element ==> element
- , "container" -: int ==> int ==> position ==> element ==> element
- , "spacer" -: int ==> int ==> element
- , "rightedText" -: text ==> element
- , "centeredText" -: text ==> element
- , "justifiedText" -: text ==> element
- , "asText" -:: a ==> element
- , "collage" -: int ==> int ==> listOf form ==> element
- , "fittedImage" -: int ==> int ==> string ==> element
- ]
-
-directions = hasType direction ["up","down","left","right","inward","outward"]
-positions =
- hasType position ["topLeft","midLeft","bottomLeft","midTop","middle"
- ,"midBottom","topRight","midRight","bottomRight"] ++
- hasType (location ==> location ==> position)
- ["topLeftAt","bottomLeftAt","middleAt","topRightAt","bottomRightAt"] ++
- [ "absolute" -: int ==> location, "relative" -: float ==> location ]
-
-lineTypes = [ numScheme (\n -> listOf (pairOf n) ==> line) "line"
- , numScheme (\n -> pairOf n ==> pairOf n ==> line) "segment"
- , "customLine" -: listOf int ==> color ==> line ==> form
- ] ++ hasType (color ==> line ==> form) ["solid","dashed","dotted"]
-
-shapes = [ twoNums (\n m -> listOf (pairOf n) ==> pairOf m ==> shape) "polygon"
- , "filled" -: color ==> shape ==> form
- , "outlined" -: color ==> shape ==> form
- , "textured" -: string ==> shape ==> form
- , "customOutline" -: listOf int ==> color ==> shape ==> form
- ] ++ map (twoNums (\n m -> n ==> n ==> pairOf m ==> shape)) [ "ngon"
- , "rect"
- , "oval" ]
-
-collages = [ numScheme (\n -> pairOf n ==> element ==> form) "toForm"
- , numScheme (\n -> string ==> n ==> n ==> pairOf n ==> form) "sprite"
- , numScheme (\n -> n ==> n ==> form ==> form) "move"
- , numScheme (\n -> n ==> form ==> form) "rotate"
- , numScheme (\n -> n ==> form ==> form) "scale"
- , numScheme (\n -> pairOf n ==> form ==> bool) "isWithin"
- ]
-
-graphicsElement = prefix "Graphics"
- (concat [elements,directions,positions,lineTypes,shapes,collages])
-graphicsColor = prefix "Color" clrs
- where clrs = [ numScheme (\n -> n ==> n ==> n ==> color) "rgb"
- , numScheme (\n -> n ==> n ==> n ==> n ==> color) "rgba"
- , "complement" -: color ==> color
- ] ++ hasType color ["red","green","blue","black","white"
- ,"yellow","cyan","magenta","grey","gray"]
-
-
--------- Foreign --------
-
-casts =
- [ "castJSBoolToBool" -: jsBool ==> bool
- , "castBoolToJSBool" -: bool ==> jsBool
- , "castJSNumberToInt" -: jsNumber ==> int
- , "castIntToJSNumber" -: int ==> jsNumber
- , "castJSElementToElement" -: int ==> int ==> jsElement ==> element
- , "castElementToJSElement" -: element ==> jsElement
- , "castJSStringToString" -: jsString ==> string
- , "castStringToJSString" -: string ==> jsString
- , "castJSNumberToFloat" -: jsNumber ==> float
- , "castFloatToJSNumber" -: float ==> jsNumber
- ]
-
-castToTuple n = (,) name $ Forall [1..n] [] (jsTuple vs ==> tupleOf vs)
- where vs = map VarT [1..n]
- name = "castJSTupleToTuple" ++ show n
-castToJSTuple n = (,) name $ Forall [1..n] [] (tupleOf vs ==> jsTuple vs)
- where vs = map VarT [1..n]
- name = "castTupleToJSTuple" ++ show n
-
-polyCasts =
- map castToTuple [2..5] ++ map castToJSTuple [2..5] ++
- [ "castJSArrayToList" -:: jsArray a ==> listOf a
- , "castListToJSArray" -:: listOf a ==> jsArray a
- ]
-
-javascript = prefix "JavaScript" (concat [casts,polyCasts])
-
-json = prefix "JSON"
- [ "JsonString" -: string ==> jsonValue
- , "JsonBool" -: bool ==> jsonValue
- , "JsonNull" -: jsonValue
- , "JsonArray" -: listOf jsonValue ==> jsonValue
- , "JsonObject" -: jsonObject ==> jsonValue
- , numScheme (\n -> n ==> jsonValue) "JsonNumber"
- , "toString" -: jsonObject ==> string
- , "fromString" -: string ==> maybeOf jsonObject
- , "lookup" -: string ==> jsonObject ==> maybeOf jsonValue
- , "findObject" -: string ==> jsonObject ==> jsonObject
- , "findArray" -: string ==> jsonObject ==> listOf jsonValue
- , "findString" -: string ==> jsonObject ==> string
- , "findNumber" -: float ==> jsonObject ==> float
- , "findWithDefault" -:: jsonValue ==> string ==> jsonObject ==> jsonValue
- , "toPrettyString" -: string ==> jsonObject ==> string
- , "toPrettyJSString" -: string ==> jsonObject ==> jsString
- , "toList" -: jsonObject ==> listOf (tupleOf [string,jsonValue])
- , "fromList" -: listOf (tupleOf [string,jsonValue]) ==> jsonObject
- , "toJSString" -: jsonObject ==> jsString
- , "fromJSString" -: jsString ==> jsonObject
- ]
-
-
--------- Signals --------
-
-lyft n = sig (n+1) ("lift" ++ show n)
-sig n name = (,) name $ Forall [1..n] [] (fn ts ==> fn (map signalOf ts))
- where fn = foldr1 (==>)
- ts = map VarT [1..n]
-
-signals = prefix "Signal"
- [ sig 1 "constant"
- , sig 2 "lift"
- ] ++ map lyft [2..8] ++ [
- "<~" -:: (a ==> b) ==> signalOf a ==> signalOf b
- , "~" -:: signalOf (a ==> b) ==> signalOf a ==> signalOf b
- , "foldp" -:: (a ==> b ==> b) ==> b ==> signalOf a ==> signalOf b
- , "foldp1" -:: (a ==> a ==> a) ==> signalOf a ==> signalOf a
- , "foldp'" -:: (a ==> b ==> b) ==> (a ==> b) ==> signalOf a ==> signalOf b
- , "count" -:: signalOf a ==> signalOf int
- , "countIf" -:: (a ==> bool) ==> signalOf a ==> signalOf int
- , "keepIf" -:: (a ==> bool) ==> a ==> signalOf a ==> signalOf a
- , "dropIf" -:: (a ==> bool) ==> a ==> signalOf a ==> signalOf a
- , "keepWhen" -:: signalOf bool ==> a ==> signalOf a ==> signalOf a
- , "dropWhen" -:: signalOf bool ==> a ==> signalOf a ==> signalOf a
- , "dropRepeats" -:: signalOf a ==> signalOf a
- , "sampleOn" -:: signalOf a ==> signalOf b ==> signalOf b
- , "timestamp" -:: signalOf a ==> signalOf (tupleOf [time,a])
- , "timeOf" -:: signalOf a ==> signalOf time
- , "merge" -:: signalOf a ==> signalOf a ==> signalOf a
- , "merges" -:: listOf (signalOf a) ==> signalOf a
- , "mergeEither" -:: signalOf a ==> signalOf b ==> signalOf (eitherOf a b)
- , numScheme (\n -> int ==> signalOf n ==> signalOf float) "average"
- ]
-
-http = prefix "HTTP"
- [ "send" -:: signalOf (request a) ==> signalOf (response string)
- , "sendGet" -:: signalOf string ==> signalOf (response string)
- , "get" -: string ==> request string
- , "post" -: string ==> string ==> request string
- , "request" -: string ==> string ==> string ==> listOf (pairOf string) ==> request string
- , "Waiting" -:: response a
- , "Failure" -:: int ==> string ==> response a
- , "Success" -:: a ==> response a ]
- where request t = ADT "Request" [t]
- response t = ADT "Response" [t]
-
-concreteSignals =
- [ "Random.inRange" -: int ==> int ==> signalOf int
- , "Random.randomize" -:: int ==> int ==> signalOf a ==> signalOf int
- , "Window.dimensions" -: signalOf point
- , "Window.width" -: signalOf int
- , "Window.height" -: signalOf int
- , "Mouse.position" -: signalOf point
- , "Mouse.x" -: signalOf int
- , "Mouse.y" -: signalOf int
- , "Mouse.isDown" -: signalOf bool
- , "Mouse.isClicked" -: signalOf bool
- , "Mouse.clicks" -: signalOf (tupleOf [])
- , "Input.textField" -: string ==> tupleOf [element, signalOf string]
- , "Input.password" -: string ==> tupleOf [element, signalOf string]
- , "Input.textArea" -: int ==> int ==> tupleOf [element, signalOf string]
- , "Input.checkBox" -: bool ==> tupleOf [element, signalOf bool]
- , "Input.button" -: string ==> tupleOf [element, signalOf bool]
- , "Input.stringDropDown" -: listOf string ==> tupleOf [element, signalOf string]
- , "Input.dropDown" -:: listOf (tupleOf [string,a]) ==> tupleOf [element, signalOf a]
- ]
-
-keyboards = prefix "Keyboard"
- [ "Raw.keysDown" -: signalOf (listOf int)
- , "Raw.charPressed" -: signalOf (maybeOf int)
- , "arrows" -: signalOf (recordOf [("x",int),("y",int)])
- , "wasd" -: signalOf (recordOf [("x",int),("y",int)])
- , "ctrl" -: signalOf bool
- , "space" -: signalOf bool
- , "shift" -: signalOf bool
- ]
-
-touches = prefix "Touch"
- [ "touches" -: signalOf (listOf (recordOf [("x" ,int) ,("y" ,int)
- ,("x0",int) ,("y0",int)
- ,("t0",time),("id",int)]))
- , "taps" -: signalOf (recordOf [("x",int),("y",int)])
- ]
-
-times = prefix "Time"
- [ numScheme (\n -> n ==> signalOf time) "fps"
- , numScheme (\n -> n ==> signalOf bool ==> signalOf time) "fpsWhen"
- , "every" -: time ==> signalOf time
- , "delay" -:: time ==> signalOf a ==> signalOf a
- , "since" -:: time ==> signalOf a ==> signalOf bool
- , "hour" -: time
- , "minute" -: time
- , "second" -: time
- , "ms" -: time
- , "inHours" -: time ==> float
- , "inMinutes" -: time ==> float
- , "inSeconds" -: time ==> float
- , "inMss" -: time ==> float
- , "toDate" -: time ==> date
- , "read" -: string ==> maybeOf time
- ]
-
-dates =
- let days = map (-: day) ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
- months = map (-: month) [ "Jan", "Feb", "Mar", "Apr", "May", "Jun"
- , "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
- in prefix "Date"
- ([ "read" -: string ==> maybeOf date
- , "year" -: date ==> int
- , "month" -: date ==> month
- , "day" -: date ==> int
- , "hour" -: date ==> int
- , "minute" -: date ==> int
- , "second" -: date ==> int
- , "dayOfWeek" -: date ==> day
- , "toTime" -: date ==> time
- ] ++ days ++ months)
-
--------- Math and Binops --------
-
-binop t = t ==> t ==> t
-scheme1 super t name =
- (name, Forall [0] [ ctx name $ VarT 0 :<: super
- ] (t (VarT 0)))
-scheme2 s1 s2 t name =
- (name, Forall [0,1] [ ctx name $ VarT 0 :<: s1
- , ctx name $ VarT 1 :<: s2
- ] (t (VarT 0) (VarT 1)))
-numScheme t name = scheme1 number t name
-twoNums f name = scheme2 number number f name
-
-math =
- map (numScheme (\t -> t ==> binop t)) ["clamp"] ++
- map (numScheme (\t -> binop t)) ["+","-","*","max","min"] ++
- [ numScheme (\t -> t ==> t) "abs" ] ++
- hasType (binop float) [ "/", "logBase" ] ++
- hasType (binop int) ["rem","div","mod"] ++
- hasType (float ==> float) ["sin","cos","tan","asin","acos","atan","sqrt"] ++
- hasType float ["pi","e"] ++
- hasType (int ==> float) ["toFloat","castIntToFloat"] ++
- hasType (float ==> int) ["round","floor","ceiling","truncate"] ++
- [ "show" -:: a ==> string
- , "readInt" -: string ==> maybeOf int
- , "readFloat" -: string ==> maybeOf float ]
-
-bools =
- [ "not" -: bool ==> bool ] ++
- hasType (binop bool) ["&&","||","xor"] ++
- map (scheme1 comparable (\t -> t ==> t ==> bool)) ["<",">","<=",">="] ++
- [ ( "compare"
- , Forall [0,1] [ ctx "compare" $ VarT 0 :<: comparable ] (VarT 0 ==> VarT 0 ==> VarT 1) )
- ]
-
-chars = prefix "Char" (classify ++ convert1 ++ convert2)
- where classify = hasType (char ==> bool)
- ["isDigit","isOctDigit","isHexDigit","isUpper","isLower"]
- convert1 = hasType (char ==> char)
- ["toUpper","toLower","toLocaleUpper","toLocaleLower"]
- convert2 = [ "toCode" -: char ==> int, "fromCode" -: int ==> char ]
-
-
--------- Polymorphic Functions --------
-
-[a,b,c] = map VarT [1,2,3]
-
-infix 8 -::
-name -:: tipe = (name, Forall [1,2,3] [] tipe)
-
-funcs =
- [ "id" -:: a ==> a
- , "==" -:: a ==> a ==> bool
- , "/=" -:: a ==> a ==> bool
- , "flip" -:: (a ==> b ==> c) ==> (b ==> a ==> c)
- , "." -:: (b ==> c) ==> (a ==> b) ==> (a ==> c)
- , "$" -:: (a ==> b) ==> a ==> b
- , ":" -:: a ==> listOf a ==> listOf a
- , (,) "++" . Forall [0,1] [ ctx "++" $ VarT 0 :<: appendable (VarT 1) ] $ VarT 0 ==> VarT 0 ==> VarT 0
- , "Cons" -:: a ==> listOf a ==> listOf a
- , "Nil" -:: listOf a
- , "Just" -:: a ==> maybeOf a
- , "Nothing" -:: maybeOf a
- , "Left" -:: a ==> eitherOf a b
- , "Right" -:: b ==> eitherOf a b
- , "curry" -:: (tupleOf [a,b] ==> c) ==> a ==> b ==> c
- , "uncurry" -:: (a ==> b ==> c) ==> tupleOf [a,b] ==> c
- ] ++ map tuple [0..8]
-
-tuple n = ("Tuple" ++ show n, Forall [1..n] [] $ foldr (==>) (tupleOf vs) vs)
- where vs = map VarT [1..n]
-
-lists = prefix "List"
- [ "and" -:: listOf bool ==> bool
- , "or" -:: listOf bool ==> bool
- , numScheme (\n -> listOf n ==> listOf n) "sort"
- , "head" -:: listOf a ==> a
- , "tail" -:: listOf a ==> listOf a
- , "length" -:: listOf a ==> int
- , "filter" -:: (a ==> bool) ==> listOf a ==> listOf a
- , "foldr1" -:: (a ==> a ==> a) ==> listOf a ==> a
- , "foldl1" -:: (a ==> a ==> a) ==> listOf a ==> a
- , "scanl1" -:: (a ==> a ==> a) ==> listOf a ==> a
- , "all" -:: (a ==> bool) ==> listOf a ==> bool
- , "any" -:: (a ==> bool) ==> listOf a ==> bool
- , "reverse" -:: listOf a ==> listOf a
- , "take" -:: int ==> listOf a ==> listOf a
- , "drop" -:: int ==> listOf a ==> listOf a
- , "partition" -:: (a ==> bool) ==> listOf a ==> tupleOf [listOf a,listOf a]
- , "intersperse" -:: a ==> listOf a ==> listOf a
- , "zip" -:: listOf a ==>listOf b ==>listOf(tupleOf [a,b])
- , "map" -:: (a ==> b) ==> listOf a ==> listOf b
- , "foldr" -:: (a ==> b ==> b) ==> b ==> listOf a ==> b
- , "foldl" -:: (a ==> b ==> b) ==> b ==> listOf a ==> b
- , "scanl" -:: (a ==> b ==> b) ==> b ==> listOf a ==> listOf b
- , (,) "concat" . Forall [0,1] [ ctx "concat" $ VarT 0 :<: appendable (VarT 1) ] $
- listOf (VarT 0) ==> VarT 0
- , (,) "concatMap" . Forall [0,1,2] [ ctx "concatMap" $ VarT 0 :<: appendable (VarT 1) ] $
- (VarT 2 ==> VarT 0) ==> listOf (VarT 2) ==> VarT 0
- , (,) "intercalate" . Forall [0,1] [ ctx "intercalate" $ VarT 0 :<: appendable (VarT 1) ] $
- VarT 0 ==> listOf (VarT 0) ==> VarT 0
- , "zipWith" -:: (a ==> b ==> c) ==> listOf a ==> listOf b ==> listOf c
- ] ++ map (numScheme (\n -> listOf n ==> n)) [ "sum", "product"
- , "maximum", "minimum" ]
-
-maybeFuncs = prefix "Maybe"
- [ "maybe" -:: b ==> (a ==> b) ==> maybeOf a ==> b
- , "isJust" -:: maybeOf a ==> bool
- , "isNothing" -:: maybeOf a ==> bool
- , "cons" -:: maybeOf a ==> listOf a ==> listOf a
- , "justs" -:: listOf (maybeOf a) ==> listOf a
- ]
-
-eithers = prefix "Either"
- [ "isLeft" -:: eitherOf a b ==> bool
- , "isRight" -:: eitherOf a b ==> bool
- , "either" -:: (a ==> c) ==> (b ==> c) ==> eitherOf a b ==> c
- , "lefts" -:: listOf (eitherOf a b) ==> listOf a
- , "rights" -:: listOf (eitherOf a b) ==> listOf b
- , "partition" -:: listOf (eitherOf a b) ==> tupleOf [listOf a,listOf b]
- ]
-
-dictionary =
- let dict k v = ADT "Dict" [k,v] in
- prefix "Dict"
- [ "empty" -:: dict a b
- , "singleton" -:: a ==> b ==> dict a b
- , "insert" -:: a ==> b ==> dict a b ==> dict a b
- , "remove" -:: a ==> dict a b ==> dict a b
- , "member" -:: a ==> dict a b ==> bool
- , "lookup" -:: a ==> dict a b ==> maybeOf b
- , "findWithDefault" -:: b ==> a ==> dict a b ==> b
- , "intersect" -:: dict a b ==> dict a c ==> dict a b
- , "union" -:: dict a b ==> dict a b ==> dict a b
- , "diff" -:: dict a b ==> dict a c ==> dict a b
- , "map" -:: (b ==> c) ==> dict a b ==> dict a c
- , "foldl" -:: (a ==> b ==> c ==> c) ==> c ==> dict a b ==> c
- , "foldr" -:: (a ==> b ==> c ==> c) ==> c ==> dict a b ==> c
- , "keys" -:: dict a b ==> listOf a
- , "values" -:: dict a b ==> listOf b
- , "toList" -:: dict a b ==> listOf (tupleOf [a,b])
- , "fromList" -:: listOf (tupleOf [a,b]) ==> dict a b
- ]
-
-sets =
- let set v = ADT "Set" [v] in
- prefix "Set"
- [ "empty" -:: set a
- , "singleton" -:: a ==> set a
- , "insert" -:: a ==> set a ==> set a
- , "remove" -:: a ==> set a ==> set a
- , "member" -:: a ==> set a ==> bool
- , "intersect" -:: set a ==> set a ==> set a
- , "union" -:: set a ==> set a ==> set a
- , "diff" -:: set a ==> set a ==> set a
- , "map" -:: (a ==> b) ==> set a ==> set b
- , "foldl" -:: (a ==> b ==> b) ==> b ==> set a ==> b
- , "foldr" -:: (a ==> b ==> b) ==> b ==> set a ==> b
- , "toList" -:: set a ==> listOf a
- , "fromList" -:: listOf a ==> set a
- ]
-
-automaton =
- let auto a b = ADT "Automaton" [a,b] in
- prefix "Automaton"
- [ "pure" -:: (a ==> b) ==> auto a b
- , "init" -:: b ==> (a ==> b ==> b) ==> auto a b
- , "init'" -:: c ==> (a ==> c ==> tupleOf [b,c]) ==> auto a b
- , ">>>" -:: auto a b ==> auto b c ==> auto a c
- , "<<<" -:: auto b c ==> auto a b ==> auto a c
- , "combine" -:: listOf (auto a b) ==> auto a (listOf b)
- , "run" -:: auto a b ==> signalOf a ==> signalOf b
- , "step" -:: auto a b ==> a ==> tupleOf [b,auto a b]
- , "count" -:: auto a int
- , "draggable" -:: form ==> auto (tupleOf [bool,point]) form
- ]
-
--------- Everything --------
-
-hints = mapM (\(n,s) -> (,) n `liftM` rescheme s) (concat hs)
- where hs = [ funcs, lists, signals, math, bools, textAttrs
- , graphicsElement, graphicsColor, eithers, keyboards, touches
- , concreteSignals, javascript, json, maybeFuncs
- , http, dictionary, sets, automaton, times, dates
- ]
diff --git a/elm/src/Types/Types.hs b/elm/src/Types/Types.hs
deleted file mode 100644
index 2de3239..0000000
--- a/elm/src/Types/Types.hs
+++ /dev/null
@@ -1,119 +0,0 @@
-
-module Types.Types where
-
-import Context
-import Data.Char (isDigit)
-import Data.List (intercalate,isPrefixOf)
-import qualified Data.Set as Set
-import qualified Data.Map as Map
-
-type X = Int
-
-data Type = LambdaT Type Type
- | VarT X
- | ADT String [Type]
- | EmptyRecord
- | RecordT (Map.Map String [Type]) Type
- | Super (Set.Set Type)
- deriving (Eq, Ord)
-
-data Scheme = Forall [X] [Context Constraint] Type deriving (Eq, Ord)
-
-data Constraint = Type :=: Type
- | Type :<: Type
- | X :<<: Scheme
- deriving (Eq, Ord, Show)
-
-recordT :: [(String,Type)] -> Map.Map String [Type]
-recordT fields =
- foldl (\r (x,t) -> Map.insertWith (++) x [t] r) Map.empty fields
-
-recordOf :: [(String,Type)] -> Type
-recordOf fields = RecordT (recordT fields) EmptyRecord
-
-tipe t = ADT t []
-
-int = tipe "Int"
-float = tipe "Float"
-number = Super (Set.fromList [ int, float ])
-
-char = tipe "Char"
-bool = tipe "Bool"
-
-string = listOf char -- tipe "String"
-text = tipe "Text"
-
-time = float --tipe "Time"
-date = tipe "Date"
-month = tipe "Month"
-day = tipe "Day"
-
-element = tipe "Element"
-direction = tipe "Direction"
-form = tipe "Form"
-line = tipe "Line"
-shape = tipe "Shape"
-color = tipe "Color"
-position = tipe "Position"
-location = tipe "Location"
-
-listOf t = ADT "List" [t]
-signalOf t = ADT "Signal" [t]
-tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
-maybeOf t = ADT "Maybe" [t]
-eitherOf a b = ADT "Either" [a,b]
-pairOf t = tupleOf [t,t]
-point = pairOf int
-appendable t = Super (Set.fromList [ string, text, listOf t ])
-comparable = Super (Set.fromList [ int, float, char, string, time, date ])
-
-jsBool = tipe "JSBool"
-jsNumber = tipe "JSNumber"
-jsString = tipe "JSString"
-jsElement = tipe "JSElement"
-jsArray t = ADT "JSArray" [t]
-jsTuple ts = ADT ("JSTuple" ++ show (length ts)) ts
-jsonValue = tipe "JsonValue"
-jsonObject = tipe "JsonObject"
-
-infixr ==>
-t1 ==> t2 = LambdaT t1 t2
-
-infix 8 -:
-name -: tipe = (,) name $ Forall [] [] tipe
-
-parens = ("("++) . (++")")
-
-instance Show Type where
- show t =
- case t of
- { LambdaT t1@(LambdaT _ _) t2 -> parens (show t1) ++ " -> " ++ show t2
- ; LambdaT t1 t2 -> show t1 ++ " -> " ++ show t2
- ; VarT x -> 't' : show x
- ; ADT "List" [ADT "Char" []] -> "String"
- ; ADT "List" [tipe] -> "[" ++ show tipe ++ "]"
- ; ADT name cs ->
- if isTupleString name
- then parens . intercalate "," $ map show cs
- else case cs of
- [] -> name
- _ -> parens $ name ++ " " ++ unwords (map show cs)
- ; Super ts -> "{" ++ (intercalate "," . map show $ Set.toList ts) ++ "}"
- ; EmptyRecord -> "{}"
- ; RecordT fs t ->
- start ++ intercalate ", " (concatMap fields $ Map.toList fs) ++ " }"
- where field n s = n ++ " :: " ++ show s
- fields (n,ss) = map (field n) ss
- start = case t of
- EmptyRecord -> "{ "
- _ -> "{ " ++ show t ++ " | "
- }
-
-instance Show Scheme where
- show (Forall [] [] t) = show t
- show (Forall xs cs t) =
- concat [ "Forall ", show xs
- , concatMap (("\n "++) . show) cs
- , "\n ", parens (show t) ]
-
-isTupleString str = "Tuple" `isPrefixOf` str && all isDigit (drop 5 str)
\ No newline at end of file
diff --git a/elm/src/Types/Unify.hs b/elm/src/Types/Unify.hs
deleted file mode 100644
index 4180558..0000000
--- a/elm/src/Types/Unify.hs
+++ /dev/null
@@ -1,19 +0,0 @@
-
-module Types.Unify (unify) where
-
-import Control.Monad (liftM)
-import qualified Data.Map as Map
-
-import Guid
-import Types.Constrain
-import Types.Solver
-
-unify hints modul = run $ do
- constraints <- constrain hints modul
- case constraints of
- Left msg -> return (Left msg)
- Right (escapees, cs) ->
- do subs <- solver cs Map.empty
- return $ do ss <- subs
- return (escapees, ss)
-
diff --git a/libraries/Automaton.elm b/libraries/Automaton.elm
new file mode 100644
index 0000000..ad95bc9
--- /dev/null
+++ b/libraries/Automaton.elm
@@ -0,0 +1,96 @@
+-- This library is a way to package up dynamic behavior. It makes it easier to
+-- dynamically create dynamic components. See the [original release
+-- notes](/blog/announce/version-0.5.0.elm) on this library to get a feel for how
+-- it can be used.
+module Automaton where
+
+data Automaton a b = Step (a -> (Automaton a b, b))
+
+-- Run an automaton on a given signal. The automaton steps forward
+-- whenever the input signal updates.
+run : Automaton a b -> b -> Signal a -> Signal b
+run (Step f) base inputs =
+ let step a (Step f, _) = f a
+ in lift snd $ foldp step base inputs
+
+-- Step an automaton forward once with a given input.
+step : a -> Automaton a b -> (Automaton a b, b)
+step a (Step f) = f a
+
+-- Compose two automatons, chaining them together.
+(>>>) : Automaton a b -> Automaton b c -> Automaton a c
+f >>> g =
+ Step (\a -> let (f', b) = step a f
+ (g', c) = step b g
+ in (f' >>> g', c))
+
+-- Compose two automatons, chaining them together.
+(<<<) : Automaton b c -> Automaton a b -> Automaton a c
+g <<< f = f >>> g
+
+-- Combine a list of automatons into a single automaton that produces a list.
+combine : [Automaton a b] -> Automaton a [b]
+combine autos =
+ Step (\a -> let (autos', bs) = unzip $ map (step a) autos
+ in (combine autos', bs))
+
+-- Create an automaton with no memory. It just applies the given function to
+-- every input.
+pure : (a -> b) -> Automaton a b
+pure f = Step (\x -> (pure f, f x))
+
+-- Create an automaton with state. Requires an initial state and a step
+-- function to step the state forward. For example, an automaton that counted
+-- how many steps it has taken would look like this:
+--
+-- count = Automaton a Int
+-- count = state 0 (\\_ c -> c+1)
+--
+-- It is a stateful automaton. The initial state is zero, and the step function
+-- increments the state on every step.
+state : b -> (a -> b -> b) -> Automaton a b
+state s f = Step (\x -> let s' = f x s
+ in (state s' f, s'))
+
+-- Create an automaton with hidden state. Requires an initial state and a
+-- step function to step the state forward and produce an output.
+hiddenState : s -> (a -> s -> (s,b)) -> Automaton a b
+hiddenState s f = Step (\x -> let (s',out) = f x s
+ in (hiddenState s' f, out))
+
+-- Count the number of steps taken.
+count : Automaton a Int
+count = state 0 (\_ c -> c + 1)
+
+type Queue t = ([t],[t])
+empty = ([],[])
+enqueue x (en,de) = (x::en, de)
+dequeue q = case q of
+ ([],[]) -> Nothing
+ (en,[]) -> enqueue ([], reverse en)
+ (en,hd::tl) -> Just (hd, (en,tl))
+
+-- Computes the running average of the last `n` inputs.
+average : Int -> Automaton Float Float
+average k =
+ let step n (ns,len,sum) =
+ if len == k then stepFull n (ns,len,sum)
+ else ((enqueue n ns, len+1, sum+n), (sum+n) / (len+1))
+ stepFull n (ns,len,sum) =
+ case dequeue ns of
+ Nothing -> ((ns,len,sum), 0)
+ Just (m,ns') -> let sum' = sum + n - m
+ in ((enqueue n ns', len, sum'), sum' / len)
+ in hiddenState (empty,0,0) step
+
+
+{-- TODO(evancz): See the following papers for ideas on how to make this
+library faster and better:
+
+- Functional Reactive Programming, Continued
+- Causal commutative arrows and their optimization
+
+Speeding things up is a really low priority. Language features and
+libraries with nice APIs and are way more important!
+--}
+
diff --git a/libraries/Char.elm b/libraries/Char.elm
new file mode 100644
index 0000000..70c81b6
--- /dev/null
+++ b/libraries/Char.elm
@@ -0,0 +1,38 @@
+
+module Char where
+
+import Native.Char as N
+
+-- True for upper case letters.
+isUpper : Char -> Bool
+
+-- True for lower case letters.
+isLower : Char -> Bool
+
+-- True for ASCII digits (`0..9`).
+isDigit : Char -> Bool
+
+-- True for ASCII octal digits (`0..7`).
+isOctDigit : Char -> Bool
+
+-- True for ASCII hexadecimal digits (`0..9a..fA..F`).
+isHexDigit : Char -> Bool
+
+-- Convert to upper case.
+toUpper : Char -> Char
+
+-- Convert to lower case.
+toLower : Char -> Char
+
+-- Convert to upper case, according to any locale-specific case mappings.
+toLocaleUpper : Char -> Char
+
+-- Convert to lower case, according to any locale-specific case mappings.
+toLocaleLower : Char -> Char
+
+-- Convert to unicode.
+toCode : Char -> KeyCode
+
+-- Convert from unicode.
+fromCode : KeyCode -> Char
+
diff --git a/libraries/Color.elm b/libraries/Color.elm
new file mode 100644
index 0000000..2761da3
--- /dev/null
+++ b/libraries/Color.elm
@@ -0,0 +1,87 @@
+
+module Color where
+
+data Color = Color Int Int Int Float
+
+-- Create RGB colors with an alpha component for transparency.
+-- The alpha component is specified with numbers between 0 and 1.
+rgba : Int -> Int -> Int -> Float -> Color
+rgba = Color
+
+-- Create RGB colors from numbers between 0 and 255 inclusive.
+rgb : Int -> Int -> Int -> Color
+rgb r g b = Color r g b 1
+
+red : Color
+red = Color 255 0 0 1
+lime : Color
+lime = Color 0 255 0 1
+blue : Color
+blue = Color 0 0 255 1
+
+yellow : Color
+yellow = Color 255 255 0 1
+cyan : Color
+cyan = Color 0 255 255 1
+magenta : Color
+magenta = Color 255 0 255 1
+
+black : Color
+black = Color 0 0 0 1
+white : Color
+white = Color 255 255 255 1
+
+gray : Color
+gray = Color 128 128 128 1
+grey : Color
+grey = Color 128 128 128 1
+
+maroon : Color
+maroon = Color 128 0 0 1
+navy : Color
+navy = Color 0 0 128 1
+green : Color
+green = Color 0 128 0 1
+
+teal : Color
+teal = Color 0 128 128 1
+purple : Color
+purple = Color 128 0 128 1
+
+violet : Color
+violet = Color 238 130 238 1
+forestGreen : Color
+forestGreen = Color 34 139 34 1
+
+-- Produce a “complementary color”.
+-- The two colors will accent each other.
+complement : Color -> Color
+
+-- Create [HSV colors](http://en.wikipedia.org/wiki/HSL_and_HSV)
+-- with an alpha component for transparency.
+hsva : Float -> Float -> Float -> Float -> Color
+
+-- Create [HSV colors](http://en.wikipedia.org/wiki/HSL_and_HSV).
+-- This is very convenient for creating colors that cycle and shift.
+--
+-- hsv (degrees 240) 1 1 == blue
+hsv : Float -> Float -> Float -> Color
+
+data Gradient
+ = Linear (Float,Float) (Float,Float) [(Float,Color)]
+ | Radial (Float,Float) Float (Float,Float) Float [(Float,Color)]
+
+-- Create a linear gradient. Takes a start and end point and then a series
+-- of “color stops” that indicate how to interpolate between
+-- the start and end points. See [this example](/edit/examples/Elements/LinearGradient.elm) for
+-- a more visual explanation.
+linear : (Number a, Number a) -> (Number a, Number a) -> [(Float,Color)] -> Gradient
+linear = Linear
+
+-- Create a radial gradient. First takes a start point and inner radius.
+-- Then takes an end point and outer radius. It then takes a series
+-- of “color stops” that indicate how to interpolate between
+-- the inner and outer circles. See [this example](/edit/examples/Elements/RadialGradient.elm) for
+-- a more visual explanation.
+radial : (Number a,Number a) -> Number a -> (Number a,Number a) -> Number a -> [(Float,Color)] -> Gradient
+radial = Radial
diff --git a/libraries/Date.elm b/libraries/Date.elm
new file mode 100644
index 0000000..a7c43ef
--- /dev/null
+++ b/libraries/Date.elm
@@ -0,0 +1,50 @@
+
+-- Library for working with dates. It is still a work in progress, so email
+-- the mailing list if you are having issues with internationalization or
+-- locale formatting or something.
+module Date where
+
+-- Represents the days of the week.
+data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun
+
+-- Represents the month of the year.
+data Month = Jan | Feb | Mar | Apr
+ | May | Jun | Jul | Aug
+ | Sep | Oct | Nov | Dec
+
+-- Attempt to read a date from a string.
+read : String -> Maybe Date
+
+-- Convert a date into a time since midnight (UTC) of 1 January 1990 (i.e.
+-- [UNIX time](http://en.wikipedia.org/wiki/Unix_time)). Given the date 23 June
+-- 1990 at 11:45AM this returns the corresponding time.
+toTime : Date -> Time
+
+-- Extract the year of a given date. Given the date 23 June 1990 at 11:45AM
+-- this returns the integer `1990`.
+year : Date -> Int
+
+-- Extract the month of a given date. Given the date 23 June 1990 at 11:45AM
+-- this returns the Month `Jun` as defined below.
+month : Date -> Month
+
+
+-- Extract the day of a given date. Given the date 23 June 1990 at 11:45AM
+-- this returns the integer `23`.
+day : Date -> Int
+
+-- Extract the day of the week for a given date. Given the date 23 June
+-- 1990 at 11:45AM this returns the Day `Thu` as defined below.
+dayOfWeek : Date -> Day
+
+-- Extract the hour of a given date. Given the date 23 June 1990 at 11:45AM
+-- this returns the integer `11`.
+hour : Date -> Int
+
+-- Extract the minute of a given date. Given the date 23 June 1990 at 11:45AM
+-- this returns the integer `45`.
+minute : Date -> Int
+
+-- Extract the second of a given date. Given the date 23 June 1990 at 11:45AM
+-- this returns the integer `0`.
+second : Date -> Int
diff --git a/core/Dict.elm b/libraries/Dict.elm
similarity index 59%
rename from core/Dict.elm
rename to libraries/Dict.elm
index c45de71..33a9ea4 100644
--- a/core/Dict.elm
+++ b/libraries/Dict.elm
@@ -8,40 +8,41 @@ module Dict (empty,singleton,insert
,toList,fromList
) where
-import Maybe (isJust)
+import Maybe as Maybe
+import Native.Error as Error
+import List as List
+import Native.Utils (compare)
data NColor = Red | Black
-data RBTree k v = RBNode NColor k v (RBTree k v) (RBTree k v) | RBEmpty
+data Dict k v = RBNode NColor k v (Dict k v) (Dict k v) | RBEmpty
-empty : RBTree k v
+-- Create an empty dictionary.
+empty : Dict (Comparable k) v
empty = RBEmpty
-raise err = throw (JavaScript.castStringToJSString err)
-
{-- Helpers for checking invariants
-- Check that the tree has an equal number of black nodes on each path
-equal_pathLen t =
+equal_pathLen t =
let path_numBlacks t =
case t of
- { RBEmpty -> 1
- ; RBNode col _ _ l r ->
+ RBEmpty -> 1
+ RBNode col _ _ l r ->
let { bl = path_numBlacks l ; br = path_numBlacks r } in
if bl /= br || bl == 0-1 || br == 0-1
then 0-1
else bl + (if col == Red then 0 else 1)
- }
in 0-1 /= path_numBlacks t
-rootBlack t =
+rootBlack t =
case t of
- { RBEmpty -> True
- ; RBNode Black _ _ _ _ -> True
- ; _ -> False }
+ RBEmpty -> True
+ RBNode Black _ _ _ _ -> True
+ _ -> False
-redBlack_children t =
- case t of
+redBlack_children t =
+ case t of
{ RBNode Red _ _ (RBNode Red _ _ _ _) _ -> False
; RBNode Red _ _ _ (RBNode Red _ _ _ _) -> False
; RBEmpty -> True
@@ -56,7 +57,7 @@ findExtreme f t =
{ Nothing -> Just k
; Just k' -> Just k' }
}
-
+
findminRbt t = findExtreme fst t
findmaxRbt t = findExtreme snd t
@@ -82,7 +83,7 @@ ordered t =
}
-- Check that there aren't any right red nodes in the tree *)
-leftLeaning t =
+leftLeaning t =
case t of
{ RBEmpty -> True
; RBNode _ _ _ (RBNode Black _ _ _ _) (RBNode Red _ _ _ _) -> False
@@ -91,40 +92,43 @@ leftLeaning t =
}
invariants_hold t =
- ordered t && rootBlack t && redBlack_children t &&
+ ordered t && rootBlack t && redBlack_children t &&
equal_pathLen t && leftLeaning t
--** End invariant helpers *****
--}
-min : RBTree k v -> (k,v)
+min : Dict k v -> (k,v)
min t =
- case t of
+ case t of
RBNode _ k v RBEmpty _ -> (k,v)
RBNode _ _ _ l _ -> min l
- RBEmpty -> raise "(min RBEmpty) is not defined"
+ RBEmpty -> Error.raise "(min Empty) is not defined"
{--
max t =
- case t of
+ case t of
{ RBNode _ k v _ RBEmpty -> (k,v)
; RBNode _ _ _ _ r -> max r
- ; RBEmpty -> raise "(max RBEmpty) is not defined"
+ ; RBEmpty -> Error.raise "(max Empty) is not defined"
}
--}
-lookup : k -> RBTree k v -> Maybe v
+-- Lookup the value associated with a key.
+lookup : Comparable k -> Dict (Comparable k) v -> Maybe v
lookup k t =
case t of
- RBEmpty -> Nothing
+ RBEmpty -> Maybe.Nothing
RBNode _ k' v l r ->
case compare k k' of
LT -> lookup k l
- EQ -> Just v
+ EQ -> Maybe.Just v
GT -> lookup k r
-findWithDefault : v -> k -> RBTree k v -> v
+-- Find the value associated with a key. If the key is not found,
+-- return the default value.
+findWithDefault : v -> Comparable k -> Dict (Comparable k) v -> v
findWithDefault base k t =
case t of
RBEmpty -> base
@@ -135,9 +139,10 @@ findWithDefault base k t =
GT -> findWithDefault base k r
{--
+-- Find the value associated with a key. If the key is not found, there will be a runtime error.
find k t =
case t of
- { RBEmpty -> raise "Key was not found in dictionary!"
+ { RBEmpty -> Error.raise "Key was not found in dictionary!"
; RBNode _ k' v l r ->
case compare k k' of
{ LT -> find k l
@@ -146,64 +151,66 @@ find k t =
}
--}
+-- Determine if a key is in a dictionary.
+member : Comparable k -> Dict (Comparable k) v -> Bool
-- Does t contain k?
-member : k -> RBTree k v -> Bool
-member k t = isJust $ lookup k t
+member k t = Maybe.isJust $ lookup k t
-rotateLeft : RBTree k v -> RBTree k v
+rotateLeft : Dict k v -> Dict k v
rotateLeft t =
case t of
RBNode cy ky vy a (RBNode cz kz vz b c) -> RBNode cy kz vz (RBNode Red ky vy a b) c
- _ -> raise "rotateLeft of a node without enough children"
+ _ -> Error.raise "rotateLeft of a node without enough children"
--- rotateRight -- the reverse, and
+-- rotateRight -- the reverse, and
-- makes Y have Z's color, and makes Z Red.
-rotateRight : RBTree k v -> RBTree k v
+rotateRight : Dict k v -> Dict k v
rotateRight t =
case t of
RBNode cz kz vz (RBNode cy ky vy a b) c -> RBNode cz ky vy a (RBNode Red kz vz b c)
- _ -> raise "rotateRight of a node without enough children"
+ _ -> Error.raise "rotateRight of a node without enough children"
-rotateLeftIfNeeded : RBTree k v -> RBTree k v
+rotateLeftIfNeeded : Dict k v -> Dict k v
rotateLeftIfNeeded t =
- case t of
+ case t of
RBNode _ _ _ _ (RBNode Red _ _ _ _) -> rotateLeft t
_ -> t
-rotateRightIfNeeded : RBTree k v -> RBTree k v
+rotateRightIfNeeded : Dict k v -> Dict k v
rotateRightIfNeeded t =
- case t of
+ case t of
RBNode _ _ _ (RBNode Red _ _ (RBNode Red _ _ _ _) _) _ -> rotateRight t
_ -> t
otherColor c = case c of { Red -> Black ; Black -> Red }
-color_flip : RBTree k v -> RBTree k v
+color_flip : Dict k v -> Dict k v
color_flip t =
case t of
- RBNode c1 bk bv (RBNode c2 ak av la ra) (RBNode c3 ck cv lc rc) ->
+ RBNode c1 bk bv (RBNode c2 ak av la ra) (RBNode c3 ck cv lc rc) ->
RBNode (otherColor c1) bk bv
(RBNode (otherColor c2) ak av la ra)
(RBNode (otherColor c3) ck cv lc rc)
- _ -> raise "color_flip called on a RBEmpty or RBNode with a RBEmpty child"
+ _ -> Error.raise "color_flip called on a Empty or Node with a Empty child"
-color_flipIfNeeded : RBTree k v -> RBTree k v
-color_flipIfNeeded t =
+color_flipIfNeeded : Dict k v -> Dict k v
+color_flipIfNeeded t =
case t of
RBNode _ _ _ (RBNode Red _ _ _ _) (RBNode Red _ _ _ _) -> color_flip t
_ -> t
fixUp t = color_flipIfNeeded (rotateRightIfNeeded (rotateLeftIfNeeded t))
-ensureBlackRoot : RBTree k v -> RBTree k v
-ensureBlackRoot t =
+ensureBlackRoot : Dict k v -> Dict k v
+ensureBlackRoot t =
case t of
RBNode Red k v l r -> RBNode Black k v l r
_ -> t
-
--- Invariant: t is a valid left-leaning rb tree *)
-insert : k -> v -> RBTree k v -> RBTree k v
-insert k v t =
+
+-- Insert a key-value pair into a dictionary. Replaces value when there is
+-- a collision.
+insert : Comparable k -> v -> Dict (Comparable k) v -> Dict (Comparable k) v
+insert k v t = -- Invariant: t is a valid left-leaning rb tree
let ins t =
case t of
RBEmpty -> RBNode Red k v RBEmpty RBEmpty
@@ -216,48 +223,49 @@ insert k v t =
in ensureBlackRoot (ins t)
{--
if not (invariants_hold t) then
- raise "invariants broken before insert"
+ Error.raise "invariants broken before insert"
else (let new_t = ensureBlackRoot (ins t) in
if not (invariants_hold new_t) then
- raise "invariants broken after insert"
+ Error.raise "invariants broken after insert"
else new_t)
--}
-singleton : k -> v -> RBTree k v
+-- Create a dictionary with one key-value pair.
+singleton : Comparable k -> v -> Dict (Comparable k) v
singleton k v = insert k v RBEmpty
-isRed : RBTree k v -> Bool
+isRed : Dict k v -> Bool
isRed t =
case t of
RBNode Red _ _ _ _ -> True
_ -> False
-isRedLeft : RBTree k v -> Bool
+isRedLeft : Dict k v -> Bool
isRedLeft t =
case t of
RBNode _ _ _ (RBNode Red _ _ _ _) _ -> True
_ -> False
-isRedLeftLeft : RBTree k v -> Bool
+isRedLeftLeft : Dict k v -> Bool
isRedLeftLeft t =
case t of
RBNode _ _ _ (RBNode _ _ _ (RBNode Red _ _ _ _) _) _ -> True
_ -> False
-isRedRight : RBTree k v -> Bool
+isRedRight : Dict k v -> Bool
isRedRight t =
case t of
RBNode _ _ _ _ (RBNode Red _ _ _ _) -> True
_ -> False
-isRedRightLeft : RBTree k v -> Bool
+isRedRightLeft : Dict k v -> Bool
isRedRightLeft t =
case t of
RBNode _ _ _ _ (RBNode _ _ _ (RBNode Red _ _ _ _) _) -> True
_ -> False
-moveRedLeft : RBTree k v -> RBTree k v
-moveRedLeft t =
+moveRedLeft : Dict k v -> Dict k v
+moveRedLeft t =
let t' = color_flip t in
case t' of
RBNode c k v l r ->
@@ -267,23 +275,23 @@ moveRedLeft t =
_ -> t'
_ -> t'
-moveRedRight : RBTree k v -> RBTree k v
+moveRedRight : Dict k v -> Dict k v
moveRedRight t =
let t' = color_flip t in
if isRedLeftLeft t' then color_flip (rotateRight t') else t'
-moveRedLeftIfNeeded : RBTree k v -> RBTree k v
+moveRedLeftIfNeeded : Dict k v -> Dict k v
moveRedLeftIfNeeded t =
- if not (isRedLeft t) && not (isRedLeftLeft t) then moveRedLeft t else t
+ if isRedLeft t || isRedLeftLeft t then t else moveRedLeft t
-moveRedRightIfNeeded : RBTree k v -> RBTree k v
+moveRedRightIfNeeded : Dict k v -> Dict k v
moveRedRightIfNeeded t =
- if not (isRedRight t) && not (isRedRightLeft t) then moveRedRight t else t
+ if isRedRight t || isRedRightLeft t then t else moveRedRight t
-deleteMin : RBTree k v -> RBTree k v
-deleteMin t =
+deleteMin : Dict k v -> Dict k v
+deleteMin t =
let del t =
- case t of
+ case t of
RBNode _ _ _ RBEmpty _ -> RBEmpty
_ -> case moveRedLeftIfNeeded t of
RBNode c k v l r -> fixUp (RBNode c k v (del l) r)
@@ -303,22 +311,24 @@ deleteMax t =
in ensureBlackRoot (del t)
--}
-remove : k -> RBTree k v -> RBTree k v
-remove k t =
+-- Remove a key-value pair from a dictionary. If the key is not found,
+-- no changes are made.
+remove : Comparable k -> Dict (Comparable k) v -> Dict (Comparable k) v
+remove k t =
let eq_and_noRightNode t =
case t of { RBNode _ k' _ _ RBEmpty -> k == k' ; _ -> False }
eq t = case t of { RBNode _ k' _ _ _ -> k == k' ; _ -> False }
- delLT t = case moveRedLeftIfNeeded t of
+ delLT t = case moveRedLeftIfNeeded t of
RBNode c k' v l r -> fixUp (RBNode c k' v (del l) r)
- RBEmpty -> raise "delLT on RBEmpty"
+ RBEmpty -> Error.raise "delLT on Empty"
delEQ t = case t of -- Replace with successor
RBNode c _ _ l r -> let (k',v') = min r in
fixUp (RBNode c k' v' l (deleteMin r))
- RBEmpty -> raise "delEQ called on a RBEmpty"
+ RBEmpty -> Error.raise "delEQ called on a Empty"
delGT t = case t of
RBNode c k' v l r -> fixUp (RBNode c k' v l (del r))
- RBEmpty -> raise "delGT called on a RBEmpty"
- del t = case t of
+ RBEmpty -> Error.raise "delGT called on a Empty"
+ del t = case t of
RBEmpty -> RBEmpty
RBNode _ k' _ _ _ ->
if k < k' then delLT t else
@@ -329,47 +339,64 @@ remove k t =
in if member k t then ensureBlackRoot (del t) else t
{--
if not (invariants_hold t) then
- raise "invariants broken before remove"
+ Error.raise "invariants broken before remove"
else (let t' = ensureBlackRoot (del t) in
if invariants_hold t' then t' else
- raise "invariants broken after remove")
+ Error.raise "invariants broken after remove")
--}
-map : (a -> b) -> RBTree k a -> RBTree k b
+-- Apply a function to all values in a dictionary.
+map : (a -> b) -> Dict (Comparable k) a -> Dict (Comparable k) b
map f t =
case t of
RBEmpty -> RBEmpty
RBNode c k v l r -> RBNode c k (f v) (map f l) (map f r)
-foldl : (k -> v -> b -> b) -> b -> RBTree k v -> b
+-- Fold over the key-value pairs in a dictionary, in order from lowest
+-- key to highest key.
+foldl : (Comparable k -> v -> b -> b) -> b -> Dict (Comparable k) v -> b
foldl f acc t =
case t of
RBEmpty -> acc
RBNode _ k v l r -> foldl f (f k v (foldl f acc l)) r
-foldr : (k -> v -> b -> b) -> b -> RBTree k v -> b
+-- Fold over the key-value pairs in a dictionary, in order from highest
+-- key to lowest key.
+foldr : (Comparable k -> v -> b -> b) -> b -> Dict (Comparable k) v -> b
foldr f acc t =
case t of
RBEmpty -> acc
RBNode _ k v l r -> foldr f (f k v (foldr f acc r)) l
-union : RBTree k v -> RBTree k v -> RBTree k v
+-- Combine two dictionaries. If there is a collision, preference is given
+-- to the first dictionary.
+union : Dict (Comparable k) v -> Dict (Comparable k) v -> Dict (Comparable k) v
union t1 t2 = foldl insert t2 t1
-intersect : RBTree k v -> RBTree k v -> RBTree k v
-intersect t1 t2 = foldl (\k v t -> if k `member` t2 then insert k v t else t) empty t1
+-- Keep a key-value pair when its key appears in the second dictionary.
+-- Preference is given to values in the first dictionary.
+intersect : Dict (Comparable k) v -> Dict (Comparable k) v -> Dict (Comparable k) v
+intersect t1 t2 =
+ let combine k v t = if k `member` t2 then insert k v t else t
+ in foldl combine empty t1
-diff : RBTree k v -> RBTree k v -> RBTree k v
+-- Keep a key-value pair when its key does not appear in the second dictionary.
+-- Preference is given to the first dictionary.
+diff : Dict (Comparable k) v -> Dict (Comparable k) v -> Dict (Comparable k) v
diff t1 t2 = foldl (\k v t -> remove k t) t1 t2
-keys : RBTree k v -> [k]
+-- Get all of the keys in a dictionary.
+keys : Dict (Comparable k) v -> [Comparable k]
keys t = foldr (\k v acc -> k :: acc) [] t
-values : RBTree k v -> [v]
+-- Get all of the values in a dictionary.
+values : Dict (Comparable k) v -> [v]
values t = foldr (\k v acc -> v :: acc) [] t
-toList : RBTree k v -> [(k,v)]
+-- Convert a dictionary into an association list of key-value pairs.
+toList : Dict (Comparable k) v -> [(Comparable k,v)]
toList t = foldr (\k v acc -> (k,v) :: acc) [] t
-fromList : [(k,v)] -> RBTree k v
-fromList assocs = Elm.List.foldl (uncurry insert) empty assocs
+-- Convert an association list into a dictionary.
+fromList : [(Comparable k,v)] -> Dict (Comparable k) v
+fromList assocs = List.foldl (\(k,v) d -> insert k v d) empty assocs
diff --git a/libraries/Either.elm b/libraries/Either.elm
new file mode 100644
index 0000000..eb9b98d
--- /dev/null
+++ b/libraries/Either.elm
@@ -0,0 +1,51 @@
+
+module Either where
+
+import List
+
+-- Represents any data that can take two different types.
+--
+-- This can also be used for error handling `(Either String a)` where error
+-- messages are stored on the left, and the correct values (“right” values) are stored on the right.
+data Either a b = Left a | Right b
+
+-- Apply the first function to a `Left` and the second function to a `Right`.
+-- This allows the extraction of a value from an `Either`.
+either : (a -> c) -> (b -> c) -> Either a b -> c
+either f g e = case e of { Left x -> f x ; Right y -> g y }
+
+-- True if the value is a `Left`.
+isLeft : Either a b -> Bool
+isLeft e = case e of { Left _ -> True ; _ -> False }
+
+-- True if the value is a `Right`.
+isRight : Either a b -> Bool
+isRight e = case e of { Right _ -> True ; _ -> False }
+
+-- Keep only the values held in `Left` values.
+lefts : [Either a b] -> [a]
+lefts es = List.foldr consLeft [] es
+
+-- Keep only the values held in `Right` values.
+rights : [Either a b] -> [b]
+rights es = List.foldr consRight [] es
+
+-- Split into two lists, lefts on the left and rights on the right. So we
+-- have the equivalence: `(partition es == (lefts es, rights es))`
+partition : [Either a b] -> ([a],[b])
+partition es = List.foldr consEither ([],[]) es
+
+consLeft e vs =
+ case e of
+ Left v -> v::vs
+ Right _ -> vs
+
+consRight e vs =
+ case e of
+ Left _ -> vs
+ Right v -> v::vs
+
+consEither e (ls,rs) =
+ case e of
+ Left l -> (l::ls,rs)
+ Right r -> (ls,r::rs)
diff --git a/libraries/Graphics/Collage.elm b/libraries/Graphics/Collage.elm
new file mode 100644
index 0000000..ae7b6ca
--- /dev/null
+++ b/libraries/Graphics/Collage.elm
@@ -0,0 +1,205 @@
+
+module Graphics.Collage where
+
+import List
+import Native.Utils (toFloat)
+import Either
+import Native.Matrix2D as Matrix
+import Native.Graphics.Collage as N
+import Graphics.Element
+import Color
+
+type Form = {
+ theta : Float,
+ scale : Float,
+ x : Float,
+ y : Float,
+ form : BasicForm
+ }
+
+data FillStyle
+ = Solid Color
+ | Texture String
+ | Gradient Gradient
+
+-- The shape of the ends of a line.
+data LineCap = Flat | Round | Padded
+
+-- The shape of the “joints” of a line, where each line segment
+-- meets. `Sharp` takes an argument to limit the length of the joint. This
+-- defaults to 10.
+data LineJoin = Smooth | Sharp Float | Clipped
+
+-- All of the attributes of a line style. This lets you build up a line style
+-- however you want. You can also update existing line styles with record updates.
+type LineStyle = {
+ color : Color,
+ width : Float,
+ cap : LineCap,
+ join : LineJoin,
+ dashing : [Int],
+ dashOffset : Int
+ }
+
+-- The default line style, which is solid black with flat caps and sharp joints.
+-- You can use record updates to build the line style you
+-- want. For example, to make a thicker line, you could say:
+--
+-- { defaultLine | width <- 10 }
+defaultLine : LineStyle
+defaultLine = {
+ color = Color.black,
+ width = 1,
+ cap = Flat,
+ join = Sharp 10,
+ dashing = [],
+ dashOffset = 0
+ }
+
+-- Create a solid line style with a given color.
+solid : Color -> LineStyle
+solid clr = { defaultLine | color <- clr }
+
+-- Create a dashed line style with a given color. Dashing equals `[8,4]`.
+dashed : Color -> LineStyle
+dashed clr = { defaultLine | color <- clr, dashing <- [8,4] }
+
+-- Create a dotted line style with a given color. Dashing equals `[3,3]`.
+dotted : Color -> LineStyle
+dotted clr = { defaultLine | color <- clr, dashing <- [3,3] }
+
+data BasicForm
+ = FPath LineStyle Path
+ | FShape (Either LineStyle FillStyle) Shape
+ | FImage Int Int (Int,Int) String
+ | FElement Element
+ | FGroup Matrix2D [Form]
+
+form f = { theta = 0, scale = 1, x = 0, y = 0, form = f }
+
+fill style shape = form (FShape (Either.Right style) shape)
+
+-- Create a filled in shape.
+filled : Color -> Shape -> Form
+filled color shape = fill (Solid color) shape
+
+-- Create a textured shape. The texture is described by some url and is
+-- tiled to fill the entire shape.
+textured : String -> Shape -> Form
+textured src shape = fill (Texture src) shape
+
+-- Fill a shape with a [gradient](/docs/Color.elm#linear).
+gradient : Gradient -> Shape -> Form
+gradient grad shape = fill (Gradient grad) shape
+
+-- Outline a shape with a given line style.
+outlined : LineStyle -> Shape -> Form
+outlined style shape = form (FShape (Either.Left style) shape)
+
+-- Trace a path with a given line style.
+traced : LineStyle -> Path -> Form
+traced style path = form (FPath style path)
+
+-- Create a sprite from a sprite sheet. It cuts out a rectangle
+-- at a given position.
+sprite : Int -> Int -> (Int,Int) -> String -> Form
+sprite w h pos src = form (FImage w h pos src)
+
+-- Turn any `Element` into a `Form`. This lets you use text, gifs, and video
+-- in your collage. This means you can move, rotate, and scale
+-- an `Element` however you want.
+toForm : Element -> Form
+toForm e = form (FElement e)
+
+-- Flatten many forms into a single `Form`. This lets you move and rotate them
+-- as a single unit, making it possible to build small, modular components.
+group : [Form] -> Form
+group fs = form (FGroup Matrix.identity fs)
+
+-- Flatten many forms into a single `Form` and then apply a matrix
+-- transformation.
+groupTransform : Matrix2D -> [Form] -> Form
+groupTransform matrix fs = form (FGroup matrix fs)
+
+-- Rotate a form by a given angle. Rotate takes standard Elm angles (radians)
+-- and turns things counterclockwise. So to turn `form` 30° to the left
+-- you would say, `(rotate (degrees 30) form)`.
+rotate : Float -> Form -> Form
+rotate t f = { f | theta <- f.theta + t }
+
+-- Scale a form by a given factor. Scaling by 2 doubles the size.
+scale : Float -> Form -> Form
+scale s f = { f | scale <- f.scale * s }
+
+-- Move a form by the given amount. This is a relative translation so
+-- `(move (10,10) form)` would move `form` ten pixels up and ten pixels to the
+-- right.
+move : (Float,Float) -> Form -> Form
+move (x,y) f = { f | x <- f.x + x, y <- f.y + y }
+
+-- Move a shape in the x direction. This is relative so `(moveX 10 form)` moves
+-- `form` 10 pixels to the right.
+moveX : Float -> Form -> Form
+moveX x f = { f | x <- f.x + x }
+
+-- Move a shape in the y direction. This is relative so `(moveY 10 form)` moves
+-- `form` upwards by 10 pixels.
+moveY : Float -> Form -> Form
+moveY y f = { f | y <- f.y + y }
+
+-- A collage is a collection of 2D forms. There are no strict positioning
+-- relationships between forms, so you are free to do all kinds of 2D graphics.
+collage : Int -> Int -> [Form] -> Element
+
+
+type Path = [(Float,Float)]
+
+-- Create a path that follows a sequence of points.
+path : [(Number a,Number a)] -> Path
+path ps = ps
+
+-- Create a path along a given line segment.
+segment : (Number a,Number a) -> (Number a,Number a) -> Path
+segment p1 p2 = [p1,p2]
+
+type Shape = [(Float,Float)]
+
+-- Create an arbitrary polygon by specifying its corners in order.
+-- `polygon` will automatically close all shapes, so the given list
+-- of points does not need to start and end with the same position.
+polygon : [(Number a,Number a)] -> Shape
+polygon points = points
+
+-- A rectangle with a given width and height.
+rect : Number a -> Number a -> Shape
+rect w h = [ (0-w/2,0-h/2), (0-w/2,h/2), (w/2,h/2), (w/2,0-h/2) ]
+
+-- A square with a given edge length.
+square : Number a -> Shape
+square n = rect w h
+
+-- An oval with a given width and height.
+oval : Number a -> Number a -> Shape
+oval w h =
+ let n = 50
+ t = 2 * Math.PI / n
+ hw = w/2
+ hh = h/2
+ f i = (hw * Math.cos (t*i), hh * Math.sin (t*i))
+ in List.map f [0..n-1]
+
+-- A circle with a given radius.
+circle : Number a -> Shape
+circle r = oval (2*r) (2*r)
+
+-- A regular polygon with N sides. The first argument specifies the number
+-- of sides and the second is the radius. So to create a pentagon with radius
+-- 30 you would say:
+--
+-- ngon 5 30
+ngon : Int -> Number a -> Shape
+ngon n r =
+ let m = toFloat n
+ t = 2 * Math.PI / m
+ f i = ( r * Math.cos (t*i), r * Math.sin (t*i) )
+ in List.map f [0..n-1]
diff --git a/libraries/Graphics/Element.elm b/libraries/Graphics/Element.elm
new file mode 100644
index 0000000..facd121
--- /dev/null
+++ b/libraries/Graphics/Element.elm
@@ -0,0 +1,255 @@
+
+module Graphics.Element (widthOf, heightOf, sizeOf,
+ width, height, opacity, color, tag, link,
+ image, fittedImage, croppedImage,
+ flow, up, down, left, right, inward, outward,
+ above, below, beside, layers,
+ container, absolute, relative,
+ middle, topLeft, topRight, bottomLeft, bottomRight,
+ midLeft, midRight, midTop, midBottom, middleAt,
+ topLeftAt, topRightAt, bottomLeftAt, bottomRightAt,
+ midLeftAt, midRightAt, midTopAt, midBottomAt,
+ spacer, newElement
+ ) where
+
+import Native.Utils (guid, max, htmlHeight)
+import JavaScript as JS
+import List as List
+import Color
+import Maybe (Just, Nothing)
+
+type Properties = {
+ id : Int,
+ width : Int,
+ height : Int,
+ opacity : Float,
+ color : Maybe Color,
+ href : JSString,
+ tag : JSString
+ }
+
+type Element = { props : Properties, element : ElementPrim }
+
+-- Get the width of an Element
+widthOf : Element -> Int
+widthOf e = e.props.width
+
+-- Get the height of an Element
+heightOf : Element -> Int
+heightOf e = e.props.height
+
+-- Get the width and height of an Element
+sizeOf : Element -> (Int,Int)
+sizeOf e = (e.props.width, e.props.height)
+
+-- Create an `Element` with a given width.
+width : Int -> Element -> Element
+width nw e = let p = e.props
+ props = case e.element of
+ Image _ w h _ -> {p| height <- h/w*nw }
+ RawHtml html -> {p| height <- let (w,h) = htmlHeight nw html in h}
+ _ -> p
+ in { element=e.element, props={props| width <- nw} }
+
+-- Create an `Element` with a given height.
+height : Int -> Element -> Element
+height nh e = let p = e.props
+ props = case e.element of
+ Image _ w h _ -> {p| width <- w/h*nh }
+ _ -> p
+ in { element=e.element, props={p| height <- nh} }
+
+-- Create an `Element` with a given opacity. Opacity is a number between 0 and 1
+-- where 0 means totally clear.
+opacity : Float -> Element -> Element
+opacity o e = let p = e.props in { element=e.element, props={p| opacity <- o} }
+
+-- Create an `Element` with a given background color.
+color : Color -> Element -> Element
+color c e = let p = e.props in
+ { element=e.element, props={p| color <- Just c} }
+
+-- Create an `Element` with a tag. This lets you link directly to it.
+-- The element `(tag "all-about-badgers" thirdParagraph)` can be reached
+-- with a link lik this: `/facts-about-animals.elm#all-about-badgers`
+tag : String -> Element -> Element
+tag name e = let p = e.props in
+ { element=e.element, props={p| tag <- JS.fromString name} }
+
+-- Create an `Element` that is a hyper-link.
+link : String -> Element -> Element
+link href e = let p = e.props in
+ { element=e.element, props={p| href <- JS.fromString href} }
+
+emptyStr = JS.fromString ""
+newElement w h e =
+ { props = Properties (guid ()) w h 1 Nothing emptyStr emptyStr, element = e }
+
+data ElementPrim
+ = Image ImageStyle Int Int JSString
+ | Container Position Element
+ | Flow Direction [Element]
+ | Spacer
+ | RawHtml JSString
+ | Custom -- for custom Elements implemented in JS, see collage for example
+
+data ImageStyle = Plain | Fitted | Cropped (Int,Int)
+
+-- Create an image given a width, height, and image source.
+image : Int -> Int -> String -> Element
+image w h src = newElement w h (Image Plain w h (JS.fromString src))
+
+-- Create a fitted image given a width, height, and image source.
+-- This will crop the picture to best fill the given dimensions.
+fittedImage : Int -> Int -> String -> Element
+fittedImage w h src = newElement w h (Image Fitted w h (JS.fromString src))
+
+-- Create a cropped image. Take a rectangle out of the picture starting
+-- at the given top left coordinate. If you have a 140-by-140 image,
+-- the following will cut a 100-by-100 square out of the middle of it.
+--
+-- croppedImage 100 100 (20,20) "yogi.jpg"
+croppedImage : Int -> Int -> (Int,Int) -> String -> Element
+croppedImage w h pos src =
+ newElement w h (Image (Cropped pos) w h (JS.fromString src))
+
+data Three = P | Z | N
+data Pos = Absolute Int | Relative Float
+type Position = { horizontal : Three, vertical : Three, x : Pos, y : Pos }
+
+-- Put an element in a container. This lets you position the element really
+-- easily, and there are tons of ways to set the `Position`.
+-- To center `element` exactly in a 300-by-300 square you would say:
+--
+-- container 300 300 middle element
+--
+-- By setting the color of the container, you can create borders.
+container : Int -> Int -> Position -> Element -> Element
+container w h pos e = newElement w h (Container pos e)
+
+-- Create an empty box. This is useful for getting your spacing right and
+-- for making borders.
+spacer : Int -> Int -> Element
+spacer w h = newElement w h Spacer
+
+data Direction = DUp | DDown | DLeft | DRight | DIn | DOut
+
+-- Have a list of elements flow in a particular direction.
+-- The `Direction` starts from the first element in the list.
+--
+-- flow right [a,b,c]
+--
+-- +---+---+---+
+-- | a | b | c |
+-- +---+---+---+
+flow : Direction -> [Element] -> Element
+flow dir es =
+ let ws = List.map widthOf es
+ hs = List.map heightOf es
+ newFlow w h = newElement w h (Flow dir es)
+ in
+ if es == [] then spacer 0 0 else
+ case dir of
+ DUp -> newFlow (List.maximum ws) (List.sum hs)
+ DDown -> newFlow (List.maximum ws) (List.sum hs)
+ DLeft -> newFlow (List.sum ws) (List.maximum hs)
+ DRight -> newFlow (List.sum ws) (List.maximum hs)
+ DIn -> newFlow (List.maximum ws) (List.maximum hs)
+ DOut -> newFlow (List.maximum ws) (List.maximum hs)
+
+-- Stack elements vertically. To put `a` above `b` you would say:
+--
+-- a `above` b
+above : Element -> Element -> Element
+above hi lo =
+ newElement (max (widthOf hi) (widthOf lo))
+ (heightOf hi + heightOf lo)
+ (Flow DDown [hi,lo])
+
+-- Stack elements vertically. To put `a` below `b` you would say:
+--
+-- a `below` b
+below : Element -> Element -> Element
+below lo hi =
+ newElement (max (widthOf hi) (widthOf lo))
+ (heightOf hi + heightOf lo)
+ (Flow DDown [hi,lo])
+
+-- Put elements beside each other horizontally.
+beside : Element -> Element -> Element
+beside lft rht =
+ newElement (widthOf lft + widthOf rht)
+ (max (heightOf lft) (heightOf rht))
+ (Flow right [lft,rht])
+
+-- Layer elements on top of each other, starting from the bottom.
+-- `(layers == flow outward)`
+layers : [Element] -> Element
+layers es =
+ let ws = List.map widthOf es
+ hs = List.map heightOf es
+ in newElement (List.maximum ws) (List.maximum hs) (Flow DOut es)
+
+
+-- Repetitive things --
+
+absolute : Int -> Pos
+absolute = Absolute
+relative : Float -> Pos
+relative = Relative
+
+middle : Position
+middle = { horizontal=Z, vertical=Z, x=Relative 0.5, y=Relative 0.5 }
+topLeft : Position
+topLeft = { horizontal=N, vertical=P, x=Absolute 0, y=Absolute 0 }
+topRight : Position
+topRight = { topLeft | horizontal <- P }
+bottomLeft : Position
+bottomLeft = { topLeft | vertical <- N }
+bottomRight : Position
+bottomRight = { bottomLeft | horizontal <- P }
+midLeft : Position
+midLeft = { middle | horizontal <- N, x <- Absolute 0 }
+midRight : Position
+midRight = { midLeft | horizontal <- P }
+midTop : Position
+midTop = { middle | vertical <- P, y <- Absolute 0 }
+midBottom : Position
+midBottom = { midTop | vertical <- N }
+
+middleAt : Pos -> Pos -> Position
+middleAt x y = { horizontal = Z, vertical = Z, x = x, y = y }
+topLeftAt : Pos -> Pos -> Position
+topLeftAt x y = { horizontal = N, vertical = P, x = x, y = y }
+topRightAt : Pos -> Pos -> Position
+topRightAt x y = { horizontal = P, vertical = P, x = x, y = y }
+bottomLeftAt : Pos -> Pos -> Position
+bottomLeftAt x y = { horizontal = N, vertical = N, x = x, y = y }
+bottomRightAt : Pos -> Pos -> Position
+bottomRightAt x y = { horizontal = P, vertical = N, x = x, y = y }
+midLeftAt : Pos -> Pos -> Position
+midLeftAt x y = { horizontal = N, vertical = Z, x = x, y = y }
+midRightAt : Pos -> Pos -> Position
+midRightAt x y = { horizontal = P, vertical = Z, x = x, y = y }
+midTopAt : Pos -> Pos -> Position
+midTopAt x y = { horizontal = Z, vertical = P, x = x, y = y }
+midBottomAt : Pos -> Pos -> Position
+midBottomAt x y = { horizontal = Z, vertical = N, x = x, y = y }
+
+up : Direction
+up = DUp
+
+down : Direction
+down = DDown
+
+left : Direction
+left = DLeft
+
+right : Direction
+right = DRight
+
+inward : Direction
+inward = DIn
+
+outward : Direction
+outward = DOut
\ No newline at end of file
diff --git a/libraries/Graphics/Input.elm b/libraries/Graphics/Input.elm
new file mode 100644
index 0000000..2f53b02
--- /dev/null
+++ b/libraries/Graphics/Input.elm
@@ -0,0 +1,119 @@
+
+module Graphics.Input where
+
+import Signal (lift)
+import Native.Graphics.Input as N
+
+id x = x
+
+-- Create a group of buttons.
+--
+-- * The first argument is the default value of the `events` signal.
+-- * The `events` signal represents all of the activity in this group
+-- of buttons.
+-- * The `button` function creates a button
+-- with the given name, like “Submit” or “Cancel”.
+-- The `a` value is sent to `events` whenever the button is pressed.
+buttons : a -> { events : Signal a,
+ button : a -> String -> Element }
+
+-- Create a button with a given label. The result is an `Element` and
+-- a signal of units. This signal triggers whenever the button is pressed.
+button : String -> (Element, Signal ())
+button txt =
+ let pool = N.buttons ()
+ in (pool.button () txt, pool.events)
+
+-- Create a group of custom buttons.
+--
+-- * The first argument is the default value of the `events` signal.
+-- * The `events` signal represents all of the activity in this group
+-- of custom buttons.
+-- * The `customButton` function creates a button with three different visual
+-- states, one for up, hovering, and down. The resulting button has dimensions
+-- large enough to fit all three possible `Elements`.
+-- The `a` value is sent to `events` whenever the button is pressed.
+customButtons : a -> { events : Signal a,
+ customButton : a -> Element -> Element -> Element -> Element }
+
+-- Create a button with custom states for up, hovering, and down
+-- (given in that order). The result is an `Element` and
+-- a signal of units. This signal triggers whenever the button is pressed.
+customButton : Element -> Element -> Element -> (Element, Signal ())
+customButton up hover down =
+ let pool = N.customButtons ()
+ in (pool.button () up hover down, pool.events)
+
+-- Create a group of checkboxes.
+--
+-- * The first argument is the default value of the `events` signal.
+-- * The `events` signal represents all of the activity in this group
+-- of checkboxes.
+-- * The `checkbox` function creates a
+-- checkbox with a given state. The `(Bool -> a)` function is used
+-- when the checkbox is modified. It takes the new state and turns
+-- it into a value that can be sent to `events`. For example, this
+-- lets you add an ID to distinguish between checkboxes.
+checkboxes : a -> { events : Signal a,
+ checkbox : (Bool -> a) -> Bool -> Element }
+
+-- Create a checkbox with a given start state. Unlike `button`, this result
+-- is a *signal* of elements. That is because a checkbox has state that
+-- updates based on user input.
+-- The boolean signal represents the current state of the checkbox.
+checkbox : Bool -> (Signal Element, Signal Bool)
+checkbox b =
+ let cbs = N.checkboxes b
+ in (lift (cbs.box id) cbs.events, cbs.events)
+
+-- Represents the current state of a text field. The `string` represents the
+-- characters filling the text field. The `selectionStart` and `selectionEnd`
+-- values represent what the user has selected with their mouse or keyboard.
+-- For example:
+--
+-- { string="She sells sea shells", selectionStart=3, selectionEnd=0 }
+--
+-- This means the user highlighted the substring `"She"` backwards.
+type FieldState = { string:String, selectionStart:Int, selectionEnd:Int }
+
+-- Create a group of text input fields.
+--
+-- * The first argument is the default value of the `events` signal.
+-- * The `events` signal represents all of the activity in this group
+-- of text fields.
+-- * The `field` function creates a
+-- field with the given ghost text and initial field state.
+-- When the field is modified, the `(FieldState -> a)` function
+-- takes the new state and turns
+-- it into a value that can be sent to `events`. For example, this
+-- lets you add an ID to distinguish between input fields.
+fields : a -> { events : Signal a,
+ field : (FieldState -> a) -> String -> FieldState -> Element }
+
+-- The empty field state:
+--
+-- { string="", selectionStart=0, selectionEnd=0 }
+emptyFieldState : FieldState
+emptyFieldState = { string="", selectionStart=0, selectionEnd=0 }
+
+-- Create a field with the given default text. The output is an element that
+-- updates to match the user input and a signal of strings representing the
+-- content of the field.
+field : String -> (Signal Element, Signal String)
+field placeHolder =
+ let tfs = N.fields emptyFieldState
+ in (lift (tfs.field id placeHolder) tfs.events, lift .string tfs.events)
+
+-- Same as `field` but the UI element blocks out each characters.
+password : String -> (Signal Element, Signal String)
+password placeHolder =
+ let tfs = N.passwords emptyFieldState
+ in (lift (tfs.field id placeHolder) tfs.events, lift .string tfs.events)
+
+-- Same as `field` but it adds an annotation that this field is for email
+-- addresses. This is helpful for auto-complete and for mobile users who may
+-- get a custom keyboard with an `@` and `.com` button.
+email : String -> (Signal Element, Signal String)
+email placeHolder =
+ let tfs = N.emails emptyFieldState
+ in (lift (tfs.field id placeHolder) tfs.events, lift .string tfs.events)
diff --git a/libraries/Http.elm b/libraries/Http.elm
new file mode 100644
index 0000000..57094af
--- /dev/null
+++ b/libraries/Http.elm
@@ -0,0 +1,43 @@
+-- A library for asynchronous HTTP requests (AJAX). See the
+-- [WebSocket](http://elm-lang.org/docs/WebSocket.elm) library if
+-- you have very strict latency requirements.
+
+module Http where
+
+import Native.Http (send)
+import Signal (lift)
+
+-- The datatype for responses. Success contains only the returned message.
+-- Failures contain both an error code and an error message.
+data Response a = Success a | Waiting | Failure Int String
+
+type Request a = {
+ verb : String,
+ url : String,
+ body : a,
+ headers : [(String,String)]
+ }
+
+-- Create a customized request. Arguments are request type (get, post, put,
+-- delete, etc.), target url, data, and a list of additional headers.
+request : String -> String -> String -> [(String,String)] -> Request String
+request = Request
+
+-- Create a GET request to the given url.
+get : String -> Request String
+get url = Request "GET" url "" []
+
+-- Create a POST request to the given url, carrying the given data.
+post : String -> String -> Request String
+post url body = Request "POST" url body []
+
+
+-- Performs an HTTP request with the given requests. Produces a signal
+-- that carries the responses.
+send : Signal (Request a) -> Signal (Response String)
+
+-- Performs an HTTP GET request with the given urls. Produces a signal
+-- that carries the responses.
+sendGet : Signal String -> Signal (Response String)
+sendGet reqs = send (lift get reqs)
+
diff --git a/libraries/JavaScript.elm b/libraries/JavaScript.elm
new file mode 100644
index 0000000..5e712a9
--- /dev/null
+++ b/libraries/JavaScript.elm
@@ -0,0 +1,26 @@
+
+module JavaScript where
+
+
+-- Requires that the input array be uniform (all members have the same type)
+toList : JSArray a -> [a]
+toInt : JSNumber -> Int
+toFloat : JSNumber -> Float
+toBool : JSBool -> Bool
+toString : JSString -> String
+
+
+-- Produces a uniform JavaScript array with all members of the same type.
+fromList : [a] -> JSArray a
+fromInt : Int -> JSNumber
+fromFloat : Float -> JSNumber
+fromBool : Bool -> JSBool
+fromString : String -> JSString
+
+
+-- Turn an `Element` into a plain old DOM node.
+fromElement : Element -> JSDomNode
+
+-- Turn a DOM node into an `Element`. You can resize the node
+-- using the normal `width` and `height` functions.
+toElement : Int -> Int -> JSDomNode -> Element
diff --git a/libraries/JavaScript/Experimental.elm b/libraries/JavaScript/Experimental.elm
new file mode 100644
index 0000000..250988c
--- /dev/null
+++ b/libraries/JavaScript/Experimental.elm
@@ -0,0 +1,31 @@
+
+module JavaScript.Experimental where
+
+import JavaScript as JS
+
+-- Turn arbitrary JavaScript objects into Elm records.
+-- Arrays are converted into lists, nested objects are allowed.
+-- No `null` values or non-homogeneous arrays.
+--
+-- -- OK objects
+-- { student:"Steve", scores:[83,94,99,72] }
+-- { errorLevel:10, critical:true }
+--
+-- -- BAD objects
+-- { answer:null }
+-- { info:[true,42,'what'] }
+toRecord : JSObject -> a
+toRecord = JS.toRecord
+
+-- Turn arbitrary Elm records into JavaScript objects.
+-- Lists become arrays, nested records are allowed. No ADTs.
+--
+-- -- OK records
+-- { student="Steve", scores=[83,94,99,72] }
+-- { errorLevel=10, critical=True }
+--
+-- -- BAD records
+-- { answer = Nothing }
+-- { result = Left "An error occurred" }
+fromRecord : a -> JSObject
+fromRecord = JS.fromRecord
\ No newline at end of file
diff --git a/libraries/Json.elm b/libraries/Json.elm
new file mode 100644
index 0000000..5ed3259
--- /dev/null
+++ b/libraries/Json.elm
@@ -0,0 +1,112 @@
+
+-- TOOD: Evan please review texts
+
+module Json where
+
+import Dict as Dict
+import JavaScript as JS
+import Native.Json as Native
+
+-- This datatype can represent all valid values that can be held in a JSON
+-- object. In Elm, a proper JSON object is represented as a (Dict String JsonValue)
+-- which is a mapping from strings to Json Values.
+data JsonValue
+ = String String
+ | Number Float
+ | Boolean Bool
+ | Null
+ | Array [JsonValue]
+ | Object (Dict String JsonValue)
+
+
+-- String Converters
+
+-- Convert a `JsonValue` into a prettified string.
+-- The first argument is a separator token (e.g. \" \", \"\\n\", etc.) that will
+-- be used for indentation in the prettified string version of the JSON.
+toString : String -> JsonValue -> String
+toString sep v = JS.toString (Native.toJSString sep v)
+
+-- Convert a proper JSON object into a JavaScript string.
+-- Note that the type JSString seen here is not the same as the type constructor
+-- JsonString used elsewhere in this module.
+toJSString : String -> JsonValue -> JSString
+
+-- Parse a string representation of a proper JSON object into
+-- its Elm representation.
+fromString : String -> Maybe JsonValue
+fromString s = Native.fromJSString (JS.fromString s)
+
+-- Parse a JavaScript string representation of a proper JSON object into
+-- its Elm representation.
+fromJSString : JSString -> Maybe JsonValue
+
+-- Convert a JS object into a `JsonValue`.
+fromJSObject : JSObject -> JsonValue
+
+-- Convert a `JsonValue` into a `JSObject`. Paired with the
+-- [`JavaScript.Experimental` library](/docs/JavaScript/Experimental.elm),
+-- This lets you convert strings into Elm records:
+--
+-- import JavaScript.Experimental as JS
+--
+-- stringToRecord str =
+-- case fromString str of
+-- Just jsonValue -> Just (JS.toRecord (toJSObject jsonValue))
+-- Nothing -> Nothing
+toJSObject : JsonValue -> JSObject
+
+ {-- Extract Elm values from Json values
+
+ string : JsonValue -> String
+ string v = case v of { String s -> s ; _ -> "" }
+
+ number : JsonValue -> Float
+ number v = case v of { Number n -> n ; _ -> 0 }
+
+ boolean : JsonValue -> Bool
+ boolean v = case v of { Boolean b -> b ; _ -> False }
+
+ array : JsonValue -> [JsonValue]
+ array v = case v of { Array a -> a ; _ -> [] }
+
+ object : JsonValue -> Dict String JsonValue
+ object v = case v of { Object o -> o ; _ -> Dict.empty }
+
+
+ -- Extract Elm values from dictionaries of Json values
+
+ -- Find a value in a Json Object using the passed get function. If the key is
+ -- not found, this returns the given default/base value.
+ find get base =
+ let f key dict =
+ case Dict.lookup key dict of
+ Nothing -> base
+ Just v -> get v
+ in f
+
+ -- Find a string value in an Elm Json object. If the key is not found or the
+ -- value found is not a string, this returns the empty string.
+ findString : String -> Object -> String
+ findString = find string ""
+
+ -- Find a number value in an Elm Json object. If the key is not found or the
+ -- value found is not a number, this returns 0
+ findNumber : String -> Object -> Float
+ findNumber = find number 0
+
+ -- Find a boolean value in an Elm Json object. If the key is not found or the
+ -- value found is not a boolean, this returns the False.
+ findBoolean : String -> Object -> Bool
+ findBoolean = find boolean False
+
+ -- Find an array value in an Elm Json object. If the key is not found or the
+ -- value found is not an array, this returns an empty list.
+ findArray : String -> Object -> [JsonValue]
+ findArray = find array []
+
+ -- Find an object value in an Elm Json object. If the key is not found or the
+ -- value found is not an object, this returns an empty object.
+ findObject : String -> Object -> Object
+ findObject = find object Dict.empty
+ --}
\ No newline at end of file
diff --git a/libraries/Keyboard.elm b/libraries/Keyboard.elm
new file mode 100644
index 0000000..07ac22b
--- /dev/null
+++ b/libraries/Keyboard.elm
@@ -0,0 +1,52 @@
+module Keyboard where
+
+import Native.Keyboard as N
+
+-- Type alias to make it clearer what integers are supposed to represent
+-- in this library. Use [`Char.toCode`](docs/Char.elm#toCode) and
+-- [`Char.fromCode`](/docs/Char.elm#fromCode) to convert key codes to characters.
+type KeyCode = Int
+
+-- A signal of records indicating which arrow keys are pressed.
+--
+-- `{ x = 0, y = 0 }` when pressing no arrows.
+-- `{ x =-1, y = 0 }` when pressing the left arrow.
+-- `{ x = 1, y = 1 }` when pressing the up and right arrows.
+-- `{ x = 0, y =-1 }` when pressing the down, left, and right arrows.
+arrows : Signal { x:Int, y:Int }
+arrows = N.directions 38 40 37 39
+
+-- Just like the arrows signal, but this uses keys w, a, s, and d,
+-- which are common controls for many computer games.
+wasd : Signal { x:Int, y:Int }
+wasd = N.directions 87 83 65 68
+
+-- Custom key directions so that you can support different locales.
+-- The plan is to have a locale independent version of this function
+-- that uses the physical location of keys, but I don't know how to do it.
+directions : KeyCode -> KeyCode -> KeyCode -> KeyCode -> Signal { x:Int, y:Int }
+
+-- Whether an arbitrary key is pressed.
+isDown : KeyCode -> Signal Bool
+
+-- Whether the shift key is pressed.
+shift : Signal Bool
+shift = N.isDown 16
+
+-- Whether the control key is pressed.
+ctrl : Signal Bool
+ctrl = N.isDown 17
+
+-- Whether the space key is pressed.
+space : Signal Bool
+space = N.isDown 32
+
+-- Whether the enter key is pressed.
+enter : Signal Bool
+enter = N.isDown 13
+
+-- List of keys that are currently down.
+keysDown : Signal [KeyCode]
+
+-- The latest key that has been pressed.
+lastPressed : Signal KeyCode
diff --git a/libraries/List.elm b/libraries/List.elm
new file mode 100644
index 0000000..341910f
--- /dev/null
+++ b/libraries/List.elm
@@ -0,0 +1,155 @@
+
+module List where
+
+import Native.Utils (min, max)
+import Native.List as L
+
+-- Add an element to the front of a list `(1 :: [2,3] == [1,2,3])`
+(::) : a -> [a] -> [a]
+
+-- Puts two appendable things together:
+--
+-- [1,1] ++ [2,3] == [1,1,2,3]
+-- "abc" ++ "123" == "abc123"
+(++) : Appendable a -> Appendable a -> Appendable a
+
+-- Extract the first element of a list. List must be non-empty.
+-- `(head [1,2,3] == 1)`
+head : [a] -> a
+
+-- Extract the elements after the head of the list. List must be non-empty.
+-- `(tail [1,2,3] == [2,3])`
+tail : [a] -> [a]
+
+-- Extract the last element of a list. List must be non-empty.
+-- `(last [1,2,3] == 3)`
+last : [a] -> a
+
+-- Apply a function to every element of a list: `(map sqrt [1,4,9] == [1,2,3])`
+map : (a -> b) -> [a] -> [b]
+
+-- Reduce a list from the left: `(foldl (::) [] "gateman" == "nametag")`
+foldl : (a -> b -> b) -> b -> [a] -> b
+
+-- Reduce a list from the right: `(foldr (+) 0 [1,2,3] == 6)`
+foldr : (a -> b -> b) -> b -> [a] -> b
+
+-- Reduce a list from the left without a base case. List must be non-empty.
+foldl1 : (a -> a -> a) -> [a] -> a
+
+-- Reduce a list from the right without a base case. List must be non-empty.
+foldr1 : (a -> a -> a) -> [a] -> a
+
+-- Reduce a list from the left, building up all of the intermediate results into a list.
+--
+-- scanl (+) 0 [1,2,3,4] == [0,1,3,6,10]
+scanl : (a -> b -> b) -> b -> [a] -> [b]
+
+-- Same as scanl but it doesn't require a base case. List must be non-empty.
+--
+-- scanl1 (+) [1,2,3,4] == [1,3,6,10]
+scanl1 : (a -> a -> a) -> [a] -> [a]
+
+-- Filter out elements which do not satisfy the predicate: `(filter isLower "AaBbCc" == "abc")`
+filter : (a -> Bool) -> [a] -> [a]
+
+-- Determine the length of a list: `(length "innumerable" == 11)`
+length : [a] -> Int
+
+-- Reverse a list. `(reverse [1..4] == [4,3,2,1])`
+reverse : [a] -> [a]
+
+-- Check to see if all elements satisfy the predicate.
+all : (a -> Bool) -> [a] -> Bool
+
+-- Check to see if any elements satisfy the predicate.
+any : (a -> Bool) -> [a] -> Bool
+
+-- Check to see if all elements are True.
+and : [Bool] -> Bool
+
+-- Check to see if any elements are True.
+or : [Bool] -> Bool
+
+-- Concatenate a list of appendable things:
+--
+-- concat ["tree","house"] == "treehouse"
+concat : [Appendable a] -> Appendable a
+
+-- Map a given function onto a list and flatten the resulting lists.
+--
+-- concatMap f xs == concat (map f xs)
+concatMap : (a -> Appendable b) -> [a] -> Appendable b
+concatMap f = L.concat . L.map f
+
+-- Get the sum of the list elements. `(sum [1..4] == 10)`
+sum : [Number a] -> Number a
+sum = L.foldl (+) 0
+
+-- Get the product of the list elements. `(product [1..4] == 24)`
+product : [Number a] -> Number a
+product = L.foldl (*) 1
+
+-- Find the highest number in a non-empty list.
+maximum : [Number a] -> Number a
+maximum = L.foldl1 max
+
+-- Find the lowest number in a non-empty list.
+minimum : [Number a] -> Number a
+minimum = L.foldl1 min
+
+-- Split a list based on the predicate.
+partition : (a -> Bool) -> [a] -> ([a],[a])
+partition pred lst =
+ case lst of
+ [] -> ([],[])
+ x::xs -> let (bs,cs) = partition pred xs in
+ if pred x then (x::bs,cs) else (bs,x::cs)
+
+-- Combine two lists, combining them into tuples pairwise.
+-- If one list is longer, the extra elements are dropped.
+--
+-- zip [1,2,3] [6,7] == [(1,6),(2,7)]
+-- zip == zipWith (,)
+zip : [a] -> [b] -> [(a,b)]
+
+-- Combine two lists, combining them with the given function.
+-- If one list is longer, the extra elements are dropped.
+--
+-- zipWith (+) [1,2,3] [1,2,3,4] == [2,4,6]
+zipWith : (a -> b -> c) -> [a] -> [b] -> [c]
+
+-- Decompose a list of tuples.
+unzip : [(a,b)] -> ([a],[b])
+unzip pairs =
+ case pairs of
+ [] -> ([],[])
+ (x,y)::ps -> let (xs,ys) = (unzip ps) in (x::xs,y::ys)
+
+-- Split a list with a given seperator.
+--
+-- split "," "hello,there,friend" == ["hello", "there", "friend"]
+split : [a] -> [a] -> [[a]]
+
+-- Places the given value between all of the lists in the second argument
+-- and concatenates the result.
+--
+-- join "a" ["H","w","ii","n"] == "Hawaiian"
+join : Appendable a -> [Appendable a] -> Appendable a
+
+-- Places the given value between all members of the given list.
+--
+-- intersperse ' ' "INCEPTION" == "I N C E P T I O N"
+intersperse : a -> [a] -> [a]
+intersperse sep xs =
+ case xs of
+ a::b::cs -> a :: sep :: intersperse sep (b::cs)
+ [a] -> [a]
+ [] -> []
+
+-- Take the first n members of a list: `(take 2 [1,2,3,4] == [1,2])`
+take : Int -> [a] -> [a]
+
+-- Drop the first n members of a list: `(drop 2 [1,2,3,4] == [3,4])`
+drop : Int -> [a] -> [a]
+
diff --git a/libraries/Matrix2D.elm b/libraries/Matrix2D.elm
new file mode 100644
index 0000000..849e8d0
--- /dev/null
+++ b/libraries/Matrix2D.elm
@@ -0,0 +1,36 @@
+
+module Matrix2D where
+
+import Native.Matrix2D as M
+
+-- Create an identity matrix.
+--
+-- / 1 0 \\
+-- \\ 0 1 /
+identity : Matrix2D
+
+-- Creates an arbitrary matrix. This lets you create scales, shears, reflections,
+-- translations, or any other 2D transform.
+--
+-- matrix a b c d dx dy
+--
+-- / a b \\
+-- \\ c d /
+--
+-- And `dx` and `dy` are the translation values.
+matrix : Float -> Float -> Float -> Float -> Float -> Float -> Matrix2D
+
+-- Creates a [rotation matrix](http://en.wikipedia.org/wiki/Rotation_matrix).
+-- Given an angle t, it creates a counterclockwise rotation matrix:
+--
+-- / cos t -sin t \\
+-- \\ sin t cos t /
+rotation : Float -> Matrix2D
+
+-- Multiplies two matrices together:
+--
+-- multiply a b
+--
+-- / a11 a12 \\ . / b11 b12 \\
+-- \\ a21 a22 / \\ b21 b22 /
+multiply : Matrix2D -> Matrix2D -> Matrix2D
diff --git a/libraries/Maybe.elm b/libraries/Maybe.elm
new file mode 100644
index 0000000..918f419
--- /dev/null
+++ b/libraries/Maybe.elm
@@ -0,0 +1,33 @@
+
+module Maybe where
+
+import List as List
+
+-- The Maybe datatype. Useful when a computation may or may not
+-- result in a value (e.g. logarithm is defined only for positive numbers).
+data Maybe a = Just a | Nothing
+
+-- Apply a function to the contents of a `Maybe`.
+-- Return default when given `Nothing`.
+maybe : b -> (a -> b) -> Maybe a -> b
+maybe b f m = case m of
+ Just v -> f v
+ Nothing -> b
+
+-- Check if constructed with `Just`.
+isJust : Maybe a -> Bool
+isJust = maybe False (\_ -> True)
+
+-- Check if constructed with `Nothing`.
+isNothing : Maybe a -> Bool
+isNothing = not . isJust
+
+
+-- If `Just`, adds the value to the front of the list.
+-- If `Nothing`, list is unchanged.
+cons : Maybe a -> [a] -> [a]
+cons mx xs = maybe xs (\x -> x :: xs) mx
+
+-- Filters out Nothings and extracts the remaining values.
+justs : [Maybe a] -> [a]
+justs = List.foldr cons []
diff --git a/libraries/Mouse.elm b/libraries/Mouse.elm
new file mode 100644
index 0000000..ccfd7cc
--- /dev/null
+++ b/libraries/Mouse.elm
@@ -0,0 +1,24 @@
+
+module Mouse where
+
+import Native.Mouse as M
+
+-- The current mouse position.
+position : Signal (Int,Int)
+
+-- The current x-coordinate of the mouse.
+x : Signal Int
+
+-- The current y-coordinate of the mouse.
+y : Signal Int
+
+-- The current state of the left mouse-button.
+-- True when the button is down, and false otherwise.
+isDown : Signal Bool
+
+-- True immediately after the left mouse-button has been clicked,
+-- and false otherwise.
+isClicked : Signal Bool
+
+-- Always equal to unit. Event triggers on every mouse click.
+clicks : Signal ()
diff --git a/libraries/Native/Char.js b/libraries/Native/Char.js
new file mode 100644
index 0000000..191a834
--- /dev/null
+++ b/libraries/Native/Char.js
@@ -0,0 +1,31 @@
+
+Elm.Native.Char = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Char) return elm.Native.Char;
+
+ function isBetween(lo,hi) { return function(chr) {
+ var c = chr.charCodeAt(0);
+ return lo <= c && c <= hi;
+ };
+ }
+ var isDigit = isBetween('0'.charCodeAt(0),'9'.charCodeAt(0));
+ var chk1 = isBetween('a'.charCodeAt(0),'f'.charCodeAt(0));
+ var chk2 = isBetween('A'.charCodeAt(0),'F'.charCodeAt(0));
+
+ return elm.Native.Char = {
+ fromCode : function(c) { return String.fromCharCode(c); },
+ toCode : function(c) { return c.charCodeAt(0); },
+ toUpper : function(c) { return c.toUpperCase(); },
+ toLower : function(c) { return c.toLowerCase(); },
+ toLocaleUpper : function(c) { return c.toLocaleUpperCase(); },
+ toLocaleLower : function(c) { return c.toLocaleLowerCase(); },
+ isLower : isBetween('a'.charCodeAt(0),'z'.charCodeAt(0)),
+ isUpper : isBetween('A'.charCodeAt(0),'Z'.charCodeAt(0)),
+ isDigit : isDigit,
+ isOctDigit : isBetween('0'.charCodeAt(0),'7'.charCodeAt(0)),
+ isHexDigit : function(c) { return isDigit(c) || chk1(c) || chk2(c); }
+ };
+
+};
diff --git a/libraries/Native/Color.js b/libraries/Native/Color.js
new file mode 100644
index 0000000..ff79f6c
--- /dev/null
+++ b/libraries/Native/Color.js
@@ -0,0 +1,71 @@
+
+
+Elm.Native.Color = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Color) return elm.Native.Color;
+
+ var Utils = Elm.Native.Utils(elm);
+
+ function complement(rgb) {
+ var hsv = toHSV(rgb);
+ hsv.hue = (hsv.hue + 180) % 360;
+ return toRGB(hsv);
+ }
+
+ function hsva(h,s,v,a) {
+ var degree = A2(Utils.mod, h * 180 / Math.PI, 360);
+ var clr = toRGB({hue:degree, saturation:s, value:v});
+ clr._3 = a;
+ return clr;
+ }
+
+ function hsv(h,s,v) {
+ var degree = A2(Utils.mod, h * 180 / Math.PI, 360);
+ return toRGB({hue:degree, saturation:s, value:v});
+ }
+
+ function toHSV(rgb) {
+ var hsv = {};
+ var r = rgb._0 / 255.0, g = rgb._1 / 255.0, b = rgb._2 / 255.0;
+ var M = Math.max(r,g,b);
+ var m = Math.min(r,g,b);
+ var c = M - m;
+
+ var h = 0;
+ if (c === 0) { h = 0; }
+ else if (M === r) { h = ((g - b) / c) % 6; }
+ else if (M === g) { h = ((b - r) / c) + 2; }
+ else if (M === b) { h = ((r - g) / c) + 4; }
+ h *= 60;
+
+ return { value : M, hue : h, saturation : (M === 0 ? 0 : c / M) };
+ }
+
+ function between(lo,hi,x) { return lo <= x && x < hi; }
+ function norm(n) { return Math.round(n*255); }
+
+ function toRGB(hsv) {
+ var c = hsv.value * hsv.saturation;
+ var hue = hsv.hue / 60;
+ var x = c * (1 - Math.abs((hue % 2) - 1));
+ var r = 0, g = 0, b = 0;
+ if (between(0,1,hue)) { r = c; g = x; b = 0; }
+ else if (between(1,2,hue)) { r = x; g = c; b = 0; }
+ else if (between(2,3,hue)) { r = 0; g = c; b = x; }
+ else if (between(3,4,hue)) { r = 0; g = x; b = c; }
+ else if (between(4,5,hue)) { r = x; g = 0; b = c; }
+ else if (between(5,6,hue)) { r = c; g = 0; b = x; }
+
+ var m = hsv.value - c;
+ return { ctor:"Color", _0:norm(r+m), _1:norm(g+m), _2:norm(b+m), _3:1 };
+ }
+
+ return elm.Native.Color = {
+ hsva:F4(hsva),
+ hsv:F3(hsv),
+ complement:complement
+ };
+
+};
\ No newline at end of file
diff --git a/libraries/Native/Date.js b/libraries/Native/Date.js
new file mode 100644
index 0000000..f2dbe55
--- /dev/null
+++ b/libraries/Native/Date.js
@@ -0,0 +1,34 @@
+
+Elm.Native.Date = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Date) return elm.Native.Date;
+
+ var JS = Elm.JavaScript(elm);
+ var Maybe = Elm.Maybe(elm);
+
+ function dateNow() { return new window.Date; }
+ function readDate(str) {
+ var d = new window.Date(JS.fromString(str));
+ if (isNaN(d.getTime())) return Maybe.Nothing;
+ return Maybe.Just(d);
+ }
+
+ var dayTable = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
+ var monthTable = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+
+ return elm.Native.Date = {
+ read : readDate,
+ year : function(d) { return d.getFullYear(); },
+ month : function(d) { return { ctor:monthTable[d.getMonth()] }; },
+ day : function(d) { return d.getDate(); },
+ hour : function(d) { return d.getHours(); },
+ minute : function(d) { return d.getMinutes(); },
+ second : function(d) { return d.getSeconds(); },
+ toTime : function(d) { return d.getTime(); },
+ dayOfWeek : function(d) { return { ctor:dayTable[d.getDay()] }; }
+ };
+
+};
diff --git a/libraries/Native/Error.js b/libraries/Native/Error.js
new file mode 100644
index 0000000..a3aa28a
--- /dev/null
+++ b/libraries/Native/Error.js
@@ -0,0 +1,22 @@
+
+Elm.Native.Error = function(elm) {
+ 'use strict';
+ elm.Native = elm.Native || {};
+ if (elm.Native.Error) return elm.Native.Error;
+
+ var fromString = Elm.Native.JavaScript(elm).fromString;
+
+ function Case(span) {
+ var msg = 'Non-exhaustive pattern match in case expression'
+ throw new Error(msg + " (" + span + ")")
+ }
+
+ function If(span) {
+ var msg = 'Non-exhaustive pattern match in multi-way-if expression'
+ throw new Error(msg + " (" + span + ")")
+ }
+
+ function raise(str) { throw new Error(fromString(str)); }
+
+ return elm.Native.Error = { Case: Case, If: If, raise: raise };
+};
\ No newline at end of file
diff --git a/libraries/Native/Function.js b/libraries/Native/Function.js
new file mode 100644
index 0000000..47fe5e5
--- /dev/null
+++ b/libraries/Native/Function.js
@@ -0,0 +1,101 @@
+
+function F2(fun) {
+ function wrapper(a) { return function(b) { return fun(a,b) } }
+ wrapper.arity = 2;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function F3(fun) {
+ function wrapper(a) {
+ return function(b) { return function(c) { return fun(a,b,c) }}
+ }
+ wrapper.arity = 3;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function F4(fun) {
+ function wrapper(a) { return function(b) { return function(c) {
+ return function(d) { return fun(a,b,c,d) }}}
+ }
+ wrapper.arity = 4;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function F5(fun) {
+ function wrapper(a) { return function(b) { return function(c) {
+ return function(d) { return function(e) { return fun(a,b,c,d,e) }}}}
+ }
+ wrapper.arity = 5;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function F6(fun) {
+ function wrapper(a) { return function(b) { return function(c) {
+ return function(d) { return function(e) { return function(f) {
+ return fun(a,b,c,d,e,f) }}}}}
+ }
+ wrapper.arity = 6;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function F7(fun) {
+ function wrapper(a) { return function(b) { return function(c) {
+ return function(d) { return function(e) { return function(f) {
+ return function(g) { return fun(a,b,c,d,e,f,g) }}}}}}
+ }
+ wrapper.arity = 7;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function F8(fun) {
+ function wrapper(a) { return function(b) { return function(c) {
+ return function(d) { return function(e) { return function(f) {
+ return function(g) { return function(h) {return fun(a,b,c,d,e,f,g,h)}}}}}}}
+ }
+ wrapper.arity = 8;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function F9(fun) {
+ function wrapper(a) { return function(b) { return function(c) {
+ return function(d) { return function(e) { return function(f) {
+ return function(g) { return function(h) { return function(i) {
+ return fun(a,b,c,d,e,f,g,h,i) }}}}}}}}
+ }
+ wrapper.arity = 9;
+ wrapper.func = fun;
+ return wrapper;
+}
+
+function A2(fun,a,b) {
+ return fun.arity === 2 ? fun.func(a,b) : fun(a)(b);
+}
+function A3(fun,a,b,c) {
+ return fun.arity === 3 ? fun.func(a,b,c) : fun(a)(b)(c);
+}
+function A4(fun,a,b,c,d) {
+ return fun.arity === 4 ? fun.func(a,b,c,d) : fun(a)(b)(c)(d);
+}
+function A5(fun,a,b,c,d,e) {
+ return fun.arity === 5 ? fun.func(a,b,c,d,e) : fun(a)(b)(c)(d)(e);
+}
+function A6(fun,a,b,c,d,e,f) {
+ return fun.arity === 6 ? fun.func(a,b,c,d,e,f) : fun(a)(b)(c)(d)(e)(f);
+}
+function A7(fun,a,b,c,d,e,f,g) {
+ return fun.arity === 7 ? fun.func(a,b,c,d,e,f,g) : fun(a)(b)(c)(d)(e)(f)(g);
+}
+function A8(fun,a,b,c,d,e,f,g,h) {
+ return fun.arity === 8 ? fun.func(a,b,c,d,e,f,g,h) : fun(a)(b)(c)(d)(e)(f)(g)(h);
+}
+function A9(fun,a,b,c,d,e,f,g,h,i) {
+ return fun.arity === 9 ? fun.func(a,b,c,d,e,f,g,h,i)
+ : fun(a)(b)(c)(d)(e)(f)(g)(h)(i);
+}
diff --git a/libraries/Native/Graphics/Collage.js b/libraries/Native/Graphics/Collage.js
new file mode 100644
index 0000000..097fe97
--- /dev/null
+++ b/libraries/Native/Graphics/Collage.js
@@ -0,0 +1,23 @@
+
+Elm.Native.Graphics.Collage = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ elm.Native.Graphics = elm.Native.Graphics || {};
+ if (elm.Native.Graphics.Collage) return elm.Native.Graphics.Collage;
+
+ var newElement = Elm.Graphics.Element(elm).newElement;
+ var C = ElmRuntime.use(ElmRuntime.Render.Collage);
+
+ function collage(w,h,forms) {
+ return A3(newElement, w, h, {
+ ctor: 'Custom',
+ type: 'Collage',
+ render: C.render,
+ update: C.update,
+ model: {w:w, h:h, forms:forms}
+ });
+ }
+ return elm.Native.Graphics.Collage = { collage:F3(collage) };
+
+};
\ No newline at end of file
diff --git a/libraries/Native/Graphics/Input.js b/libraries/Native/Graphics/Input.js
new file mode 100644
index 0000000..4323024
--- /dev/null
+++ b/libraries/Native/Graphics/Input.js
@@ -0,0 +1,234 @@
+
+Elm.Native.Graphics.Input = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ elm.Native.Graphics = elm.Native.Graphics || {};
+ if (elm.Native.Graphics.Input) return elm.Native.Graphics.Input;
+
+ var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+ var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
+ var newNode = Utils.newElement, fromString = Utils.fromString,
+ toString = Utils.toString;
+
+ var Signal = Elm.Signal(elm);
+ var newElement = Elm.Graphics.Element(elm).newElement;
+
+ function buttons(defaultValue) {
+ var events = Signal.constant(defaultValue);
+
+ function render(model) {
+ var b = newNode('button');
+ b.style.display = 'block';
+ b.elmEvent = model.event;
+ function click() { elm.notify(events.id, b.elmEvent); }
+ b.addEventListener('click', click);
+ b.innerHTML = model.text;
+ return b;
+ }
+
+ function update(node, oldModel, newModel) {
+ node.elmEvent = newModel.event;
+ var txt = newModel.text;
+ if (oldModel.text !== txt) node.innerHTML = txt;
+ }
+
+ function button(evnt, txt) {
+ return A3(newElement, 100, 40, {
+ ctor: 'Custom',
+ type: 'Button',
+ render: render,
+ update: update,
+ model: { event:evnt, text:fromString(txt) }
+ });
+ }
+
+ return { _:{}, button:F2(button), events:events };
+ }
+
+ function customButtons(defaultValue) {
+ var events = Signal.constant(defaultValue);
+
+ function render(model) {
+ var btn = newNode('div');
+ btn.elmEvent = model.event;
+
+ btn.elmUp = Render.render(model.up);
+ btn.elmHover = Render.render(model.hover);
+ btn.elmDown = Render.render(model.down);
+
+ function replace(node) {
+ if (node !== btn.firstChild) btn.replaceChild(node, btn.firstChild);
+ }
+ var overCount = 0;
+ function over(e) {
+ if (overCount++ > 0) return;
+ replace(btn.elmHover);
+ }
+ function out(e) {
+ if (btn.contains(e.toElement || e.relatedTarget)) return;
+ overCount = 0;
+ replace(btn.elmUp);
+ }
+ function up() {
+ replace(btn.elmHover);
+ elm.notify(events.id, btn.elmEvent);
+ }
+ function down() { replace(btn.elmDown); }
+ btn.addEventListener('mouseover', over);
+ btn.addEventListener('mouseout' , out);
+ btn.addEventListener('mousedown', down);
+ btn.addEventListener('mouseup' , up);
+
+ btn.appendChild(btn.elmUp);
+ return btn;
+ }
+
+ function update(node, oldModel, newModel) {
+ node.elmEvent = newModel.event;
+ Render.update(node.elmUp, oldModel.up, newModel.up)
+ Render.update(node.elmHover, oldModel.hover, newModel.hover)
+ Render.update(node.elmDown, oldModel.down, newModel.down)
+ }
+
+ function button(evnt, up, hover, down) {
+ return A3(newElement,
+ Math.max(up.props.width, hover.props.width, down.props.width),
+ Math.max(up.props.height, hover.props.height, down.props.height),
+ { ctor: 'Custom',
+ type: 'CustomButton',
+ render: render,
+ update: update,
+ model: { event:evnt, up:up, hover:hover, down:down }
+ });
+ }
+
+ return { _:{}, button:F4(button), events:events };
+ }
+
+
+ function checkboxes(defaultValue) {
+ var events = Signal.constant(defaultValue);
+
+ function render(model) {
+ var b = newNode('input');
+ b.type = 'checkbox';
+ b.checked = model.checked;
+ b.style.display = 'block';
+ b.elmHandler = model.handler;
+ function change() { elm.notify(events.id, b.elmHandler(b.checked)); }
+ b.addEventListener('change', change);
+ return b;
+ }
+
+ function update(node, oldModel, newModel) {
+ node.elmHandler = newModel.handler;
+ node.checked = newModel.checked;
+ return true;
+ }
+
+ function box(handler, checked) {
+ return A3(newElement, 13, 13, {
+ ctor: 'Custom',
+ type: 'CheckBox',
+ render: render,
+ update: update,
+ model: { checked:checked, handler:handler }
+ });
+ }
+
+ return { _:{}, box:F2(box), events:events };
+ }
+
+ function mkTextPool(type) { return function fields(defaultValue) {
+ var events = Signal.constant(defaultValue);
+
+ var state = null;
+
+ function render(model) {
+ var field = newNode('input');
+ field.elmHandler = model.handler;
+
+ field.id = 'test';
+ field.type = type;
+ field.placeholder = fromString(model.placeHolder);
+ field.value = fromString(model.state.string);
+ field.setSelectionRange(model.state.selectionStart, model.state.selectionEnd);
+ field.style.border = 'none';
+ state = model.state;
+
+ function update() {
+ var start = field.selectionStart,
+ end = field.selectionEnd;
+ if (field.selectionDirection === 'backward') {
+ start = end;
+ end = field.selectionStart;
+ }
+ state = { _:{},
+ string:toString(field.value),
+ selectionStart:start,
+ selectionEnd:end };
+ elm.notify(events.id, field.elmHandler(state));
+ }
+ function mousedown() {
+ update();
+ elm.node.addEventListener('mouseup', mouseup);
+ }
+ function mouseup() {
+ update();
+ elm.node.removeEventListener('mouseup', mouseup)
+ }
+ field.addEventListener('keyup', update);
+ field.addEventListener('mousedown', mousedown);
+
+ return field;
+ }
+
+ function update(node, oldModel, newModel) {
+ node.elmHandler = newModel.handler;
+ if (state === newModel.state) return;
+ var newStr = fromString(newModel.state.string);
+ if (node.value !== newStr) node.value = newStr;
+
+ var start = newModel.state.selectionStart;
+ var end = newModel.state.selectionEnd;
+ var direction = 'forward';
+ if (end < start) {
+ start = end;
+ end = newModel.state.selectionStart;
+ direction = 'backward';
+ }
+
+ if (node.selectionStart !== start
+ || node.selectionEnd !== end
+ || node.selectionDirection !== direction) {
+ node.setSelectionRange(start, end, direction);
+ }
+ }
+
+ function field(handler, placeHolder, state) {
+ return A3(newElement, 200, 30,
+ { ctor: 'Custom',
+ type: type + 'Input',
+ render: render,
+ update: update,
+ model: { handler:handler,
+ placeHolder:placeHolder,
+ state:state }
+ });
+ }
+
+ return { _:{}, field:F3(field), events:events };
+ }
+ }
+
+ return elm.Native.Graphics.Input = {
+ buttons:buttons,
+ customButtons:customButtons,
+ checkboxes:checkboxes,
+ fields:mkTextPool('text'),
+ emails:mkTextPool('email'),
+ passwords:mkTextPool('password')
+ };
+
+};
diff --git a/libraries/Native/JavaScript.js b/libraries/Native/JavaScript.js
new file mode 100644
index 0000000..22993a0
--- /dev/null
+++ b/libraries/Native/JavaScript.js
@@ -0,0 +1,102 @@
+
+Elm.Native.JavaScript = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.JavaScript) return elm.Native.JavaScript;
+
+ var List = Elm.Native.List(elm);
+ var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+
+ function fromJS(v) {
+ var type = typeof v;
+ if (type === 'number' ) return v;
+ if (type === 'boolean') return v;
+ if (type === 'string' ) return List.fromArray(v);
+ if (v instanceof Array) {
+ var arr = [];
+ var len = v.length;
+ for (var i = 0; i < len; ++i) {
+ var x = fromJS(v[i]);
+ if (x !== null) arr.push(x);
+ }
+ return List.fromArray(arr);
+ }
+ if (type === 'object') {
+ var rec = { _:{} };
+ for (var f in v) {
+ var x = fromJS(v[f]);
+ if (x !== null) rec[f] = x;
+ }
+ return rec;
+ }
+ return null;
+ }
+
+ function toJS(v) {
+ var type = typeof v;
+ if (type === 'number' || type === 'boolean') return v;
+ if (type === 'object' && '_' in v) {
+ var obj = {};
+ for (var k in v) {
+ var x = v[k];
+ if (x !== null) obj[k] = x;
+ }
+ return obj;
+ }
+ if (type === 'object' && (v.ctor === 'Cons' || v.ctor === 'Nil')) {
+ var array = List.toArray(v);
+ for (var i = array.length; i--; ) {
+ array[i] = toJS(array[i]);
+ }
+ if (typeof array[0] === 'string') array.join('');
+ return array;
+ }
+ return null;
+ }
+
+ function fromRecord(r) {
+ if (typeof r === 'object' && '_' in r) {
+ return toJS(r);
+ }
+ throw new Error("'fromRecord' must be called on a record.");
+ }
+
+ function id(n) { return n; }
+
+ function toElement(w,h,domNode) {
+ return A3( newElement, w, h, {
+ ctor: 'Custom',
+ type: 'DomNode',
+ render: function(node) { return node; },
+ update: function(node,oldNode,newNode) {
+ if (node === newNode) return;
+ node.parentNode.replaceChild(newNode, node);
+ },
+ model: domNode
+ });
+ }
+
+ function fromElement(element) {
+ return Render.render(element);
+ }
+
+ return elm.Native.JavaScript = {
+ toFloat : id,
+ toBool : id,
+ toInt : function(n) { return n|0; },
+ toString : List.fromArray,
+ toList : List.fromArray,
+ fromString : function(s) { return List.toArray(s).join(''); },
+ fromList : List.toArray,
+ fromInt : id,
+ fromFloat : id,
+ fromBool : id,
+
+ toElement : toElement,
+ fromElement : fromElement,
+ toRecord : fromJS,
+ fromRecord : fromRecord
+ };
+
+};
\ No newline at end of file
diff --git a/libraries/Native/Json.js b/libraries/Native/Json.js
new file mode 100644
index 0000000..93305d2
--- /dev/null
+++ b/libraries/Native/Json.js
@@ -0,0 +1,69 @@
+
+Elm.Native.Json = function(elm) {
+ 'use strict';
+
+ var Maybe = Elm.Maybe(elm);
+ var Dict = Elm.Dict(elm);
+ var List = Elm.List(elm);
+ var JS = Elm.JavaScript(elm);
+ var Utils = Elm.Native.Utils(elm);
+
+ function fromValue(v) {
+ switch (v.ctor) {
+ case 'Null' : return null;
+ case 'String' : return JS.fromString(v._0);
+ case 'Object' :
+ var obj = {};
+ var array = JS.fromList(Dict.toList(v._0));
+ for (var i = arr.length; i--; ) {
+ obj[JS.fromString(array[i]._0)] = fromValue(array[i]._1);
+ }
+ return obj;
+ case 'Array' :
+ var array = JS.fromList(v._0);
+ for (var i = array.length; i--; ) {
+ array[i] = fromValue(array[i]);
+ }
+ return array;
+ default :
+ return v._0;
+ }
+ }
+
+ function toPrettyJSString(sep, obj) {
+ return JSON.stringify(fromValue(obj), null, JS.fromString(sep));
+ }
+
+ function toValue(v) {
+ switch (typeof v) {
+ case 'string' : return { ctor:"String", _0: JS.toString(v) };
+ case 'number' : return { ctor:"Number", _0: JS.toFloat(v) };
+ case 'boolean': return { ctor:"Bool" , _0: JS.toBool(v) };
+ case 'object' :
+ if (v === null) return { ctor:"Null" };
+ if (v instanceof Array) {
+ for (var i = v.length; i--; ) { v[i] = toValue(v[i]); }
+ return { ctor:"Array", _0: JS.toList(v) };
+ }
+ var array = [];
+ for (var k in v) array.push(Utils.Tuple2(JS.toString(k), toValue(v[k])));
+ return { ctor:"Object", _0: Dict.fromList(JS.toList(array)) };
+ }
+ }
+
+ function fromJSString(str) {
+ try {
+ return Maybe.Just(toValue(JSON.parse(str)));
+ } catch (e) {
+ return Maybe.Nothing;
+ }
+ }
+
+ return elm.Native.Json = {
+ toJSString : F2(toPrettyJSString),
+ fromJSString : fromJSString,
+ toJSObject : fromValue,
+ fromJSObject : toValue
+ };
+
+};
diff --git a/libraries/Native/List.js b/libraries/Native/List.js
new file mode 100644
index 0000000..7950aab
--- /dev/null
+++ b/libraries/Native/List.js
@@ -0,0 +1,347 @@
+Elm.Native.List = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.List) return elm.Native.List;
+ if ('values' in Elm.Native.List)
+ return elm.Native.List = Elm.Native.List.values;
+
+ var Utils = Elm.Native.Utils(elm);
+
+ // TODO: Improve Nil handling
+ // We can change places like: if (xs.ctor === 'Nil') ... to if (xs === Nil) ...
+ // but only if we're confident Nil can only be defined once.
+ // Currently (27Mar2013) each module can have different instantiations, so multiple Nil objects can exist
+ // (and if they're used interchangeably then direct object comparison fails where ctor doesn't).
+ // So, this can only be fixed when modules initialisation is also fixed.
+ // The performance overhead of the .ctor calls is 5-10% according to jsperf (depending on fn + list size)
+ // (on firefox 19)
+
+ var Nil = { ctor:'Nil' };
+
+ // using freeze for every cons would be nice but is a huge (9x on firefox 19)
+ // performance penalty
+ function Cons(hd,tl) { return { ctor:"Cons", _0:hd, _1:tl }; }
+
+ function throwError(f) {
+ throw new Error("Function '" + f + "' expects a non-empty list!");
+ }
+
+ function toArray(xs) {
+ var out = [];
+ while (xs.ctor !== 'Nil') {
+ out.push(xs._0);
+ xs = xs._1;
+ }
+ return out;
+ }
+
+ function fromArray(arr) {
+ var out = Nil;
+ for (var i = arr.length; i--; ) {
+ out = Cons(arr[i], out);
+ }
+ return out;
+ }
+
+ function range(lo,hi) {
+ var lst = Nil;
+ if (lo <= hi) {
+ do { lst = Cons(hi,lst) } while (hi-->lo);
+ }
+ return lst
+ }
+
+ function append(xs,ys) {
+ if (typeof xs === "string") { return xs.concat(ys); }
+ if (xs.ctor === 'Nil') { return ys; }
+ var root = Cons(xs._0, Nil);
+ var curr = root;
+ xs = xs._1;
+ while (xs.ctor !== 'Nil') {
+ curr._1 = Cons(xs._0, Nil);
+ xs = xs._1;
+ curr = curr._1;
+ }
+ curr._1 = ys;
+ return root;
+ }
+
+ function head(v) { return v.ctor === 'Nil' ? throwError('head') : v._0; }
+ function tail(v) { return v.ctor === 'Nil' ? throwError('tail') : v._1; }
+
+ function last(xs) {
+ if (xs.ctor === 'Nil') { throwError('last'); }
+ var out = xs._0;
+ while (xs.ctor !== 'Nil') {
+ out = xs._0;
+ xs = xs._1;
+ }
+ return out;
+ }
+
+ function map(f, xs) {
+ var arr = [];
+ while (xs.ctor !== 'Nil') {
+ arr.push(f(xs._0));
+ xs = xs._1;
+ }
+ return fromArray(arr);
+ }
+
+ // f defined similarly for both foldl and foldr (NB: different from Haskell)
+ // ie, foldl :: (a -> b -> b) -> b -> [a] -> b
+ function foldl(f, b, xs) {
+ var acc = b;
+ while (xs.ctor !== 'Nil') {
+ acc = A2(f, xs._0, acc);
+ xs = xs._1;
+ }
+ return acc;
+ }
+
+ function foldr(f, b, xs) {
+ var arr = toArray(xs);
+ var acc = b;
+ for (var i = arr.length; i--; ) {
+ acc = A2(f, arr[i], acc);
+ }
+ return acc;
+ }
+
+ function foldl1(f, xs) {
+ return xs.ctor === 'Nil' ? throwError('foldl1') : foldl(f, xs._0, xs._1);
+ }
+
+ function foldr1(f, xs) {
+ if (xs.ctor === 'Nil') { throwError('foldr1'); }
+ var arr = toArray(xs);
+ var acc = arr.pop();
+ for (var i = arr.length; i--; ) {
+ acc = A2(f, arr[i], acc);
+ }
+ return acc;
+ }
+
+ function scanl(f, b, xs) {
+ var arr = toArray(xs);
+ arr.unshift(b);
+ var len = arr.length;
+ for (var i = 1; i < len; ++i) {
+ arr[i] = A2(f, arr[i], arr[i-1]);
+ }
+ return fromArray(arr);
+ }
+
+ function scanl1(f, xs) {
+ return xs.ctor === 'Nil' ? throwError('scanl1') : scanl(f, xs._0, xs._1);
+ }
+
+ function filter(pred, xs) {
+ var arr = [];
+ while (xs.ctor !== 'Nil') {
+ if (pred(xs._0)) { arr.push(xs._0); }
+ xs = xs._1;
+ }
+ return fromArray(arr);
+ }
+
+ function length(xs) {
+ var out = 0;
+ while (xs.ctor !== 'Nil') {
+ out += 1;
+ xs = xs._1;
+ }
+ return out;
+ }
+
+ function member(x, xs) {
+ while (xs.ctor !== 'Nil') {
+ if (Utils.eq(x,xs._0)) return true;
+ xs = xs._1;
+ }
+ return false;
+ }
+
+ function reverse(xs) { return fromArray(toArray(xs).reverse()); }
+
+ function concat(xss) {
+ if (xss.ctor === 'Nil') return xss;
+ var arr = toArray(xss);
+ var xs = arr[arr.length-1];
+ for (var i = arr.length-1; i--; ) {
+ xs = append(arr[i], xs);
+ }
+ return xs;
+ }
+
+ function all(pred, xs) {
+ while (xs.ctor !== 'Nil') {
+ if (!pred(xs._0)) return false;
+ xs = xs._1;
+ }
+ return true;
+ }
+
+ function any(pred, xs) {
+ while (xs.ctor !== 'Nil') {
+ if (pred(xs._0)) return true;
+ xs = xs._1;
+ }
+ return false;
+ }
+
+ function zipWith(f, xs, ys) {
+ var arr = [];
+ while (xs.ctor !== 'Nil' && ys.ctor !== 'Nil') {
+ arr.push(A2(f, xs._0, ys._0));
+ xs = xs._1;
+ ys = ys._1;
+ }
+ return fromArray(arr);
+ }
+
+ function zip(xs, ys) {
+ var arr = [];
+ while (xs.ctor !== 'Nil' && ys.ctor !== 'Nil') {
+ arr.push(Utils.Tuple2(xs._0, ys._0));
+ xs = xs._1;
+ ys = ys._1;
+ }
+ return fromArray(arr);
+ }
+
+ function sort(xs) {
+ function cmp(a,b) {
+ var ord = Utils.compare(a,b).ctor;
+ return ord=== 'EQ' ? 0 : ord === 'LT' ? -1 : 1;
+ }
+ return fromArray(toArray(xs).sort(cmp));
+ }
+
+ function take(n, xs) {
+ var arr = [];
+ while (xs.ctor !== 'Nil' && n > 0) {
+ arr.push(xs._0);
+ xs = xs._1;
+ --n;
+ }
+ return fromArray(arr);
+ }
+
+ function drop(n, xs) {
+ while (xs.ctor !== 'Nil' && n > 0) {
+ xs = xs._1;
+ --n;
+ }
+ return xs;
+ }
+
+ function join(sep, xss) {
+ if (typeof sep === 'string') return toArray(xss).join(sep);
+ if (xss.ctor === 'Nil') return Nil;
+ var s = toArray(sep);
+ var out = toArray(xss._0);
+ xss = xss._1;
+ while (xss.ctor !== 'Nil') {
+ out = out.concat(s, toArray(xss._0));
+ xss = xss._1;
+ }
+ return fromArray(out);
+ }
+
+ function split(seperator, list) {
+ var array = toArray(list);
+ var alen = array.length;
+ if (alen === 0) {
+ // splitting an empty list is a list of lists: [[]]
+ return Cons(Nil,Nil);
+ }
+
+ var sep = toArray(seperator);
+ var seplen = sep.length;
+ if (seplen === 0) {
+ // splitting with an empty sep is a list of all elements
+ // Same as (map (\x -> [x]) list)
+ var out = Nil;
+ for (var i = alen; i--; ) {
+ out = Cons(Cons(array[i],Nil), out);
+ }
+ return out;
+ }
+
+ var matches = [-seplen];
+ var sepStart = sep[0];
+ var len = alen - seplen + 1;
+ for (var i = 0; i < len; ++i) {
+ if (Utils.eq(array[i], sepStart)) {
+ var match = true;
+ for (var j = seplen; --j; ) {
+ if (!Utils.eq(array[i+j], sep[j])) { match = false; break; }
+ }
+ if (match) {
+ matches.push(i);
+ i += seplen - 1;
+ }
+ }
+ }
+
+ // shortcut in case of no matches
+ if (matches.length === 0) {
+ return Cons(list,Nil);
+ }
+
+ var out = Nil;
+ var index = alen - 1;
+ for (var i = matches.length; i--; ) {
+ var temp = Nil;
+ var stop = matches[i] + seplen - 1;
+ for ( ; index > stop; --index ) {
+ temp = Cons(array[index], temp);
+ }
+ out = Cons(temp,out);
+ index -= seplen;
+ }
+ return out;
+ }
+
+ Elm.Native.List.values = {
+ Nil:Nil,
+ Cons:Cons,
+ toArray:toArray,
+ fromArray:fromArray,
+ range:range,
+ append:append,
+
+ head:head,
+ tail:tail,
+ last:last,
+
+ map:F2(map),
+ foldl:F3(foldl),
+ foldr:F3(foldr),
+
+ foldl1:F2(foldl1),
+ foldr1:F2(foldr1),
+ scanl:F3(scanl),
+ scanl1:F2(scanl1),
+ filter:F2(filter),
+ length:length,
+ member:F2(member),
+ reverse:reverse,
+ concat:concat,
+
+ all:F2(all),
+ any:F2(any),
+ zipWith:F3(zipWith),
+ zip:F2(zip),
+ sort:sort,
+ take:F2(take),
+ drop:F2(drop),
+
+ join:F2(join),
+ split:F2(split)
+ };
+ return elm.Native.List = Elm.Native.List.values;
+
+};
\ No newline at end of file
diff --git a/libraries/Native/Matrix2D.js b/libraries/Native/Matrix2D.js
new file mode 100644
index 0000000..b7e8439
--- /dev/null
+++ b/libraries/Native/Matrix2D.js
@@ -0,0 +1,88 @@
+
+Elm.Native.Matrix2D = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Matrix2D) return elm.Native.Matrix2D;
+
+ if (typeof Float32Array === 'undefined'){ Float32Array = Array; }
+ var A = Float32Array;
+
+ // layout of matrix in an array is
+ //
+ // | m11 m12 dx |
+ // | m21 m22 dy |
+ // | 0 0 1 |
+ //
+ // new A([ m11, m12, dx, m21, m22, dy ])
+
+ var identity = new A([1,0,0,0,1,0]);
+ function matrix(m11, m12, m21, m22, dx, dy) {
+ return new A([m11, m12, dx, m21, m22, dy]);
+ }
+ function rotation(t) {
+ var c = Math.cos(t);
+ var s = Math.sin(t);
+ return new A([c, -s, 0, s, c, 0]);
+ }
+
+ function rotate(t,m) {
+ var c = Math.cos(t);
+ var s = Math.sin(t);
+ var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
+ return new A([m11*c + m12*s, -m11*s + m12*c, m[2],
+ m21*c + m22*s, -m21*s + m22*c, m[5]]);
+ }
+ /*
+ function move(xy,m) {
+ var x = xy._0;
+ var y = xy._1;
+ var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
+ return new A([m11, m12, m11*x + m12*y + m[2],
+ m21, m22, m21*x + m22*y + m[5]]);
+ }
+ function scale(s,m) { return new A([m[0]*s, m[1]*s, m[2], m[3]*s, m[4]*s, m[5]]); }
+ function scaleX(x,m) { return new A([m[0]*x, m[1], m[2], m[3]*x, m[4], m[5]]); }
+ function scaleY(y,m) { return new A([m[0], m[1]*y, m[2], m[3], m[4]*y, m[5]]); }
+ function reflectX(m) { return new A([-m[0], m[1], m[2], -m[3], m[4], m[5]]); }
+ function reflectY(m) { return new A([m[0], -m[1], m[2], m[3], -m[4], m[5]]); }
+
+ function transform(m11, m21, m12, m22, mdx, mdy, n) {
+ var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
+ return new A([m11*n11 + m12*n21,
+ m11*n12 + m12*n22,
+ m11*ndx + m12*ndy + mdx,
+ m21*n11 + m22*n21,
+ m21*n12 + m22*n22,
+ m21*ndx + m22*ndy + mdy]);
+ }
+ */
+ function multiply(m, n) {
+ var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4], mdx = m[2], mdy = m[5];
+ var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
+ return new A([m11*n11 + m12*n21,
+ m11*n12 + m12*n22,
+ m11*ndx + m12*ndy + mdx,
+ m21*n11 + m22*n21,
+ m21*n12 + m22*n22,
+ m21*ndx + m22*ndy + mdy]);
+ }
+
+ return elm.Native.Matrix2D = {
+ identity:identity,
+ matrix:F6(matrix),
+ rotation:rotation,
+ multiply:F2(multiply)
+ /*
+ transform:F7(transform),
+ rotate:F2(rotate),
+ move:F2(move),
+ scale:F2(scale),
+ scaleX:F2(scaleX),
+ scaleY:F2(scaleY),
+ reflectX:reflectX,
+ reflectY:reflectY
+ */
+ };
+
+};
diff --git a/libraries/Native/Prelude.js b/libraries/Native/Prelude.js
new file mode 100644
index 0000000..2c4b700
--- /dev/null
+++ b/libraries/Native/Prelude.js
@@ -0,0 +1,123 @@
+
+Elm.Native.Prelude = function(elm) {
+ 'use strict';
+ if (elm.Native.Prelude) return elm.Native.Prelude;
+
+ var JS = Elm.JavaScript(elm);
+ var Maybe = Elm.Maybe(elm);
+ var Utils = Elm.Native.Utils(elm);
+ var Char = Elm.Char(elm);
+
+ function div(a,b) { return (a/b)|0; }
+ function rem(a,b) { return a % b; }
+ var mod = Utils.mod;
+ function abs(x) { return x < 0 ? -x : x; }
+ function logBase(base,n) { return Math.log(n) / Math.log(base); }
+ function min(a,b) { return a < b ? a : b; }
+ function max(a,b) { return a > b ? a : b; }
+ function clamp(lo,hi,n) { return n < lo ? lo : n > hi ? hi : n; }
+ function xor(a,b) { return a !== b; }
+ function not(b) { return !b; }
+
+ function truncate(n) { return n|0; }
+
+ function id(n) { return n; }
+ function flip(f,a,b) { return A2(f,b,a); }
+ function curry(f,a,b) { return f(Utils.Tuple2(a,b)); }
+ function uncurry(f,v) { return A2(f,v._0,v._1); }
+ function fst(t) { return t._0; }
+ function snd(t) { return t._1; }
+
+ function readInt(str) {
+ var s = JS.fromString(str);
+ var len = s.length;
+ if (len === 0) { return Maybe.Nothing; }
+ var start = 0;
+ if (s[0] == '-') {
+ if (len === 1) { return Maybe.Nothing; }
+ start = 1;
+ }
+ for (var i = start; i < len; ++i) {
+ if (!Char.isDigit(s[i])) { return Maybe.Nothing; }
+ }
+ return Maybe.Just(parseInt(s, 10));
+ }
+
+ function readFloat(str) {
+ var s = JS.fromString(str);
+ var len = s.length;
+ if (len === 0) { return Maybe.Nothing; }
+ var start = 0;
+ if (s[0] == '-') {
+ if (len === 1) { return Maybe.Nothing; }
+ start = 1;
+ }
+ var dotCount = 0;
+ for (var i = start; i < len; ++i) {
+ if (Char.isDigit(s[i])) { continue; }
+ if (s[i] === '.') {
+ dotCount += 1;
+ if (dotCount <= 1) { continue; }
+ }
+ return Maybe.Nothing;
+ }
+ return Maybe.Just(parseFloat(s));
+ }
+
+ var prelude = {
+ div:F2(div),
+ rem:F2(rem),
+ mod:mod,
+
+ pi:Math.PI,
+ e:Math.e,
+ cos:Math.cos,
+ sin:Math.sin,
+ tan:Math.tan,
+ acos:Math.acos,
+ asin:Math.asin,
+ atan:Math.atan,
+ atan2:F2(Math.atan2),
+
+ sqrt:Math.sqrt,
+ abs:abs,
+ logBase:F2(logBase),
+ min:F2(min),
+ max:F2(max),
+ clamp:F3(clamp),
+ compare:Utils.compare,
+
+ xor:F2(xor),
+ not:not,
+ otherwise:true,
+
+ truncate:truncate,
+ ceiling:Math.ceil,
+ floor:Math.floor,
+ round:Math.round,
+ toFloat:id,
+
+ readInt:readInt,
+ readFloat:readFloat,
+
+ id:id,
+ flip:F3(flip),
+ curry:F3(curry),
+ uncurry:F2(uncurry),
+ fst:fst,
+ snd:snd
+ };
+
+ function add(Module) {
+ var M = Module(elm);
+ for (var k in M) { prelude[k] = M[k]; }
+ }
+ add(Elm.Native.Show);
+ add(Elm.Signal);
+ add(Elm.List);
+ add(Elm.Maybe);
+ add(Elm.Time);
+ add(Elm.Graphics.Element);
+
+ return elm.Native.Prelude = prelude;
+};
diff --git a/libraries/Native/Show.js b/libraries/Native/Show.js
new file mode 100644
index 0000000..6917742
--- /dev/null
+++ b/libraries/Native/Show.js
@@ -0,0 +1,99 @@
+
+Elm.Native.Show = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Show) return elm.Native.Show;
+
+ var NList = Elm.Native.List(elm);
+ var List = Elm.List(elm);
+ var Maybe = Elm.Maybe(elm);
+ var JS = Elm.JavaScript(elm);
+ var Dict = Elm.Dict(elm);
+ var Json = Elm.Json(elm);
+ var Tuple2 = Elm.Native.Utils(elm).Tuple2;
+
+ var toString = function(v) {
+ if (typeof v === "function") {
+ var name = v.func ? v.func.name : v.name;
+ return '';
+ } else if (typeof v === "boolean") {
+ return v ? "True" : "False";
+ } else if (typeof v === "number") {
+ return v+"";
+ } else if (typeof v === "string" && v.length < 2) {
+ return "'" + showChar(v) + "'";
+ } else if (typeof v === "object" && '_' in v) {
+ var output = [];
+ for (var k in v._) {
+ for (var i = v._[k].length; i--; ) {
+ output.push(k + " = " + toString(v._[k][i]));
+ }
+ }
+ for (var k in v) {
+ if (k === '_') continue;
+ output.push(k + " = " + toString(v[k]));
+ }
+ if (output.length === 0) return "{}";
+ return "{ " + output.join(", ") + " }";
+ } else if (typeof v === "object" && 'ctor' in v) {
+ if (v.ctor.substring(0,5) === "Tuple") {
+ var output = [];
+ for (var k in v) {
+ if (k === 'ctor') continue;
+ output.push(toString(v[k]));
+ }
+ return "(" + output.join(",") + ")";
+ } else if (v.ctor === "Cons") {
+ var isStr = typeof v._0 === "string",
+ start = isStr ? '"' : "[",
+ end = isStr ? '"' : "]",
+ sep = isStr ? "" : ",",
+ f = !isStr ? toString : showChar;
+ var output = start + f(v._0);
+ v = v._1;
+ while (v.ctor === "Cons") {
+ output += sep + f(v._0);
+ v = v._1;
+ }
+ return output + end;
+ } else if (v.ctor === "Nil") {
+ return "[]";
+ } else if (v.ctor === "RBNode" || v.ctor === "RBEmpty") {
+ var cons = F3(function(k,v,acc){return NList.Cons(Tuple2(k,v),acc)});
+ var list = A3(Dict.foldr, cons, NList.Nil, v);
+ var name = "Dict";
+ if (list.ctor === "Cons" && list._0._1.ctor === "Tuple0") {
+ name = "Set";
+ list = A2(List.map, function(x){return x._0}, list);
+ }
+ return name + ".fromList " + toString(list);
+ } else {
+ var output = "";
+ for (var i in v) {
+ if (i === 'ctor') continue;
+ var str = toString(v[i]);
+ var parenless = str[0] === '{' || str.indexOf(' ') < 0;
+ output += ' ' + (parenless ? str : '(' + str + ')');
+ }
+ return v.ctor + output;
+ }
+ }
+ return v+"";
+ };
+ function show(v) { return NList.fromArray(toString(v)); }
+
+ function showChar (c) {
+ return c === '\n' ? '\\n' :
+ c === '\t' ? '\\t' :
+ c === '\b' ? '\\b' :
+ c === '\r' ? '\\r' :
+ c === '\v' ? '\\v' :
+ c === '\0' ? '\\0' :
+ c === '\'' ? "\\'" :
+ c === '\"' ? '\\"' :
+ c === '\\' ? '\\\\' : c;
+ }
+
+ return elm.Native.Show = { show:show };
+};
diff --git a/libraries/Native/Signal/Http.js b/libraries/Native/Signal/Http.js
new file mode 100644
index 0000000..b0dea8b
--- /dev/null
+++ b/libraries/Native/Signal/Http.js
@@ -0,0 +1,61 @@
+
+Elm.Native.Http = function(elm) {
+ 'use strict';
+ elm.Native = elm.Native || {};
+ if (elm.Native.Http) return elm.Native.Http;
+
+
+ var JS = Elm.JavaScript(elm);
+ var List = Elm.List(elm);
+ var Signal = Elm.Signal(elm);
+
+
+ function registerReq(queue,responses) { return function(req) {
+ if (req.url !== "") { sendReq(queue,responses,req); }
+ };
+ }
+
+ function updateQueue(queue,responses) {
+ if (queue.length > 0) {
+ elm.notify(responses.id, queue[0].value);
+ if (queue[0].value.ctor !== 'Waiting') {
+ queue.shift();
+ setTimeout(function() { updateQueue(queue,responses); }, 0);
+ }
+ }
+ }
+
+ function setHeader(pair) {
+ request.setRequestHeader( JS.fomString(pair._0), JS.fromString(pair._1) );
+ }
+
+ function sendReq(queue,responses,req) {
+ var response = { value: { ctor:'Waiting' } };
+ queue.push(response);
+
+ var request = null;
+ if (window.ActiveXObject) { request = new ActiveXObject("Microsoft.XMLHTTP"); }
+ if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
+ request.onreadystatechange = function(e) {
+ if (request.readyState === 4) {
+ response.value = (request.status === 200 ?
+ { ctor:'Success', _0:JS.toString(request.responseText) } :
+ { ctor:'Failure', _0:request.status, _1:JS.toString(request.statusText) });
+ setTimeout(function() { updateQueue(queue,responses); }, 0);
+ }
+ };
+ request.open(JS.fromString(req.verb), JS.fromString(req.url), true);
+ List.map(setHeader)(req.headers);
+ request.send(JS.fromString(req.body));
+ }
+
+ function send(requests) {
+ var responses = Signal.constant(elm.Http.Waiting);
+ var sender = A2( Signal.lift, registerReq([],responses), requests );
+ function f(x) { return function(y) { return x; } }
+ return A3( Signal.lift2, f, responses, sender );
+ }
+
+ return elm.Native.Http = {send:send};
+
+};
diff --git a/libraries/Native/Signal/Keyboard.js b/libraries/Native/Signal/Keyboard.js
new file mode 100644
index 0000000..6ddd934
--- /dev/null
+++ b/libraries/Native/Signal/Keyboard.js
@@ -0,0 +1,72 @@
+
+Elm.Native.Keyboard = function(elm) {
+ 'use strict';
+ elm.Native = elm.Native || {};
+ if (elm.Native.Keyboard) return elm.Native.Keyboard;
+
+ var Signal = Elm.Signal(elm);
+ var NList = Elm.Native.List(elm);
+
+ var keysDown = Signal.constant(NList.Nil);
+ var lastKey = Signal.constant('\0');
+
+ function down(e) {
+ if (NList.member(e.keyCode)(keysDown.value)) return;
+ var list = NList.Cons(e.keyCode, keysDown.value);
+ var hasListener = elm.notify(keysDown.id, list);
+ if (!hasListener) document.removeEventListener('keydown', down);
+ }
+ function up(e) {
+ function notEq(kc) { return kc !== e.keyCode; }
+ var codes = NList.filter(notEq)(keysDown.value);
+ var hasListener = elm.notify(keysDown.id, codes);
+ if (!hasListener) document.removeEventListener('keyup', up);
+ }
+ function blur(e) {
+ var hasListener = elm.notify(keysDown.id, NList.Nil);
+ if (!hasListener) document.removeEventListener('blur', blur);
+ }
+ function press(e) {
+ var hasListener = elm.notify(lastKey.id, e.charCode || e.keyCode);
+ if (!hasListener) document.removeEventListener('keypress', press);
+ }
+
+ document.addEventListener('keydown' , down );
+ document.addEventListener('keyup' , up );
+ document.addEventListener('blur' , blur );
+ document.addEventListener('keypress', press);
+
+ function keySignal(f) {
+ var signal = A2( Signal.lift, f, keysDown );
+ keysDown.defaultNumberOfKids += 1;
+ signal.defaultNumberOfKids = 0;
+ return signal;
+ }
+
+ function dir(up, down, left, right) {
+ function f(ks) {
+ var x = 0, y = 0;
+ while (ks.ctor == "Cons") {
+ switch (ks._0) {
+ case left : --x; break;
+ case right: ++x; break;
+ case up : ++y; break;
+ case down : --y; break;
+ }
+ ks = ks._1;
+ }
+ return { _:{}, x:x, y:y };
+ }
+ return keySignal(f);
+ }
+
+ function is(key) { return keySignal(NList.member(key)); }
+
+ return elm.Native.Keyboard = {
+ isDown:is,
+ directions:F4(dir),
+ keysDown:keysDown,
+ lastPressed:lastKey
+ };
+
+};
diff --git a/libraries/Native/Signal/Mouse.js b/libraries/Native/Signal/Mouse.js
new file mode 100644
index 0000000..a928b0f
--- /dev/null
+++ b/libraries/Native/Signal/Mouse.js
@@ -0,0 +1,79 @@
+
+Elm.Native.Mouse = function(elm) {
+ 'use strict';
+ elm.Native = elm.Native || {};
+ if (elm.Native.Mouse) return elm.Native.Mouse;
+
+ var Signal = Elm.Signal(elm);
+ var Utils = Elm.Native.Utils(elm);
+
+ var position = Signal.constant(Utils.Tuple2(0,0));
+ position.defaultNumberOfKids = 2;
+
+ // do not move x and y into Elm. By setting their default number
+ // of kids, it is possible to detatch the mouse listeners if
+ // they are not needed.
+ var x = A2( Signal.lift, function(p){return p._0}, position);
+ x.defaultNumberOfKids = 0;
+ var y = A2( Signal.lift, function(p){return p._1}, position);
+ y.defaultNumberOfKids = 0;
+
+ var isDown = Signal.constant(false);
+ var isClicked = Signal.constant(false);
+ var clicks = Signal.constant(Utils.Tuple0);
+
+ function getXY(e) {
+ var posx = 0;
+ var posy = 0;
+ if (!e) e = window.event;
+ if (e.pageX || e.pageY) {
+ posx = e.pageX;
+ posy = e.pageY;
+ } else if (e.clientX || e.clientY) {
+ posx = e.clientX + document.body.scrollLeft +
+ document.documentElement.scrollLeft;
+ posy = e.clientY + document.body.scrollTop +
+ document.documentElement.scrollTop;
+ }
+ return Utils.Tuple2(posx-elm.node.offsetX, posy-elm.node.offsetY);
+ }
+
+ var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
+
+ function click(e) {
+ var hasListener1 = elm.notify(isClicked.id, true);
+ var hasListener2 = elm.notify(clicks.id, Utils.Tuple0);
+ elm.notify(isClicked.id, false);
+ if (!hasListener1 && !hasListener2)
+ node.removeEventListener('click', click);
+ }
+
+ function down(e) {
+ var hasListener = elm.notify(isDown.id, true);
+ if (!hasListener) node.removeEventListener('mousedown', down);
+ }
+
+ function up(e) {
+ var hasListener = elm.notify(isDown.id, false);
+ if (!hasListener) node.removeEventListener('mouseup', up);
+ }
+
+ function move(e) {
+ var hasListener = elm.notify(position.id, getXY(e));
+ if (!hasListener) node.removeEventListener('mousemove', move);
+ }
+
+ node.addEventListener('click' , click);
+ node.addEventListener('mousedown', down);
+ node.addEventListener('mouseup' , up);
+ node.addEventListener('mousemove', move);
+
+ return elm.Native.Mouse = {
+ position: position,
+ x:x,
+ y:y,
+ isClicked: isClicked,
+ isDown: isDown,
+ clicks: clicks
+ };
+};
\ No newline at end of file
diff --git a/libraries/Native/Signal/Random.js b/libraries/Native/Signal/Random.js
new file mode 100644
index 0000000..119ba11
--- /dev/null
+++ b/libraries/Native/Signal/Random.js
@@ -0,0 +1,21 @@
+
+Elm.Native.Random = function(elm) {
+ 'use strict';
+ elm.Native = elm.Native || {};
+ if (elm.Native.Random) return elm.Native.Random;
+
+ var Signal = Elm.Signal(elm);
+
+ function range(min, max, signal) {
+ function f(x) { return Math.floor(Math.random() * (max-min+1)) + min; }
+ return A2( Signal.lift, f, signal );
+ }
+
+ function flt(signal) {
+ function f(x) { return Math.random(); }
+ return A2( Signal.lift, f, signal );
+ }
+
+ return elm.Native.Random = { range: F3(range), float: flt };
+
+};
diff --git a/libraries/Native/Signal/Signal.js b/libraries/Native/Signal/Signal.js
new file mode 100644
index 0000000..f5c10c3
--- /dev/null
+++ b/libraries/Native/Signal/Signal.js
@@ -0,0 +1,225 @@
+
+Elm.Native.Signal = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Signal) return elm.Native.Signal;
+
+ var Utils = Elm.Native.Utils(elm);
+ var foldl1 = Elm.List(elm).foldl1;
+
+ function send(node, timestep, changed) {
+ var kids = node.kids;
+ for (var i = kids.length; i--; ) {
+ kids[i].recv(timestep, changed, node.id);
+ }
+ }
+
+ function Input(base) {
+ this.id = Utils.guid();
+ this.value = base;
+ this.kids = [];
+ this.defaultNumberOfKids = 0;
+ this.recv = function(timestep, eid, v) {
+ var changed = eid === this.id;
+ if (changed) { this.value = v; }
+ send(this, timestep, changed);
+ return changed;
+ };
+ elm.inputs.push(this);
+ }
+
+ function LiftN(update, args) {
+ this.id = Utils.guid();
+ this.value = update();
+ this.kids = [];
+
+ var n = args.length;
+ var count = 0;
+ var isChanged = false;
+
+ this.recv = function(timestep, changed, parentID) {
+ ++count;
+ if (changed) { isChanged = true; }
+ if (count == n) {
+ if (isChanged) { this.value = update(); }
+ send(this, timestep, isChanged);
+ isChanged = false;
+ count = 0;
+ }
+ };
+ for (var i = n; i--; ) { args[i].kids.push(this); }
+ }
+
+ function lift(func, a) {
+ function update() { return func(a.value); }
+ return new LiftN(update, [a]);
+ }
+ function lift2(func, a, b) {
+ function update() { return A2( func, a.value, b.value ); }
+ return new LiftN(update, [a,b]);
+ }
+ function lift3(func, a, b, c) {
+ function update() { return A3( func, a.value, b.value, c.value ); }
+ return new LiftN(update, [a,b,c]);
+ }
+ function lift4(func, a, b, c, d) {
+ function update() { return A4( func, a.value, b.value, c.value, d.value ); }
+ return new LiftN(update, [a,b,c,d]);
+ }
+ function lift5(func, a, b, c, d, e) {
+ function update() { return A5( func, a.value, b.value, c.value, d.value, e.value ); }
+ return new LiftN(update, [a,b,c,d,e]);
+ }
+ function lift6(func, a, b, c, d, e, f) {
+ function update() { return A6( func, a.value, b.value, c.value, d.value, e.value, f.value ); }
+ return new LiftN(update, [a,b,c,d,e,f]);
+ }
+ function lift7(func, a, b, c, d, e, f, g) {
+ function update() { return A7( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value ); }
+ return new LiftN(update, [a,b,c,d,e,f,g]);
+ }
+ function lift8(func, a, b, c, d, e, f, g, h) {
+ function update() { return A8( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value ); }
+ return new LiftN(update, [a,b,c,d,e,f,g,h]);
+ }
+
+ function foldp(func,state,input) {
+ var first = true;
+ function update() {
+ first ? first = false : state = A2(func, input.value, state);
+ return state;
+ }
+ return new LiftN(update, [input]);
+ }
+
+ function DropIf(pred,base,input) {
+ this.id = Utils.guid();
+ this.value = pred(input.value) ? base : input.value;
+ this.kids = [];
+ this.recv = function(timestep, changed, parentID) {
+ var chng = changed && !pred(input.value);
+ if (chng) { this.value = input.value; }
+ send(this, timestep, chng);
+ };
+ input.kids.push(this);
+ }
+
+ function DropRepeats(input) {
+ this.id = Utils.guid();
+ this.value = input.value;
+ this.kids = [];
+ this.recv = function(timestep, changed, parentID) {
+ var chng = changed && !Utils.eq(this.value,input.value);
+ if (chng) { this.value = input.value; }
+ send(this, timestep, chng);
+ };
+ input.kids.push(this);
+ }
+
+ function dropWhen(s1,b,s2) {
+ var pairs = lift2( F2(function(x,y){return {x:x,y:y};}), s1, s2 );
+ var dropped = new DropIf(function(p){return p.x;},{x:true,y:b},pairs);
+ return lift(function(p){return p.y;}, dropped);
+ }
+
+ function timestamp(a) {
+ function update() { return Utils.Tuple2(Date.now(), a.value); }
+ return new LiftN(update, [a]);
+ }
+
+ function SampleOn(s1,s2) {
+ this.id = Utils.guid();
+ this.value = s2.value;
+ this.kids = [];
+
+ var count = 0;
+ var isChanged = false;
+
+ this.recv = function(timestep, changed, parentID) {
+ if (parentID === s1.id) isChanged = changed;
+ ++count;
+ if (count == 2) {
+ if (isChanged) { this.value = s2.value; }
+ send(this, timestep, isChanged);
+ count = 0;
+ isChanged = false;
+ }
+ };
+ s1.kids.push(this);
+ s2.kids.push(this);
+ }
+
+ function sampleOn(s1,s2) { return new SampleOn(s1,s2); }
+
+ function delay(t,s) {
+ var delayed = new Input(s.value);
+ var firstEvent = true;
+ function update(v) {
+ if (firstEvent) { firstEvent = false; return; }
+ setTimeout(function() { elm.notify(delayed.id, v); }, t);
+ }
+ function first(a,b) { return a; }
+ return new SampleOn(delayed, lift2(F2(first), delayed, lift(update,s)));
+ }
+
+ function Merge(s1,s2) {
+ this.id = Utils.guid();
+ this.value = s1.value;
+ this.kids = [];
+
+ var next = null;
+ var count = 0;
+ var isChanged = false;
+
+ this.recv = function(timestep, changed, parentID) {
+ ++count;
+ if (changed) {
+ isChanged = true;
+ if (parentID == s2.id && next === null) { next = s2.value; }
+ if (parentID == s1.id) { next = s1.value; }
+ }
+
+ if (count == 2) {
+ if (isChanged) { this.value = next; next = null; }
+ send(this, timestep, isChanged);
+ isChanged = false;
+ count = 0;
+ }
+ };
+ s1.kids.push(this);
+ s2.kids.push(this);
+ }
+
+ function merge(s1,s2) { return new Merge(s1,s2); }
+ function merges(ss) { return A2(foldl1, F2(merge), ss); }
+
+ return elm.Native.Signal = {
+ constant : function(v) { return new Input(v); },
+ lift : F2(lift ),
+ lift2 : F3(lift2),
+ lift3 : F4(lift3),
+ lift4 : F5(lift4),
+ lift5 : F6(lift5),
+ lift6 : F7(lift6),
+ lift7 : F8(lift7),
+ lift8 : F9(lift8),
+ foldp : F3(foldp),
+ delay : F2(delay),
+ merge : F2(merge),
+ merges : merges,
+ count : function(s) { return foldp(F2(function(_,c) { return c+1; }), 0, s); },
+ countIf : F2(function(pred,s) {
+ return foldp(F2(function(x,c){
+ return pred(x) ? c+1 : c; }), 0, s)}),
+ keepIf : F3(function(pred,base,sig) {
+ return new DropIf(function(x) {return !pred(x);},base,sig); }),
+ dropIf : F3(function(pred,base,sig) { return new DropIf(pred,base,sig); }),
+ keepWhen : F3(function(s1,b,s2) {
+ return dropWhen(lift(function(b){return !b;},s1), b, s2); }),
+ dropWhen : F3(dropWhen),
+ dropRepeats : function(s) { return new DropRepeats(s);},
+ sampleOn : F2(sampleOn),
+ timestamp : timestamp
+ };
+};
diff --git a/libraries/Native/Signal/Time.js b/libraries/Native/Signal/Time.js
new file mode 100644
index 0000000..e5ec52d
--- /dev/null
+++ b/libraries/Native/Signal/Time.js
@@ -0,0 +1,60 @@
+
+Elm.Native.Time = function(elm) {
+ 'use strict';
+
+ var Signal = Elm.Signal(elm);
+ var Maybe = Elm.Maybe(elm);
+ var Utils = Elm.Native.Utils(elm);
+
+ function fpsWhen(desiredFPS, isOn) {
+ var msPerFrame = 1000 / desiredFPS;
+ var prev = Date.now(), curr = prev, diff = 0, wasOn = true;
+ var ticker = Signal.constant(diff);
+ function tick(zero) { return function() {
+ curr = Date.now();
+ diff = zero ? 0 : curr - prev;
+ prev = curr;
+ elm.notify(ticker.id, diff);
+ };
+ }
+ var timeoutID = 0;
+ function f(isOn, t) {
+ if (isOn) {
+ timeoutID = setTimeout(tick(!wasOn && isOn), msPerFrame);
+ } else if (wasOn) {
+ clearTimeout(timeoutID);
+ }
+ wasOn = isOn;
+ return t;
+ }
+ return A3( Signal.lift2, F2(f), isOn, ticker );
+ }
+
+ function everyWhen(t, isOn) {
+ var clock = Signal.constant(Date.now());
+ function tellTime() { elm.notify(clock.id, Date.now()); }
+ setInterval(tellTime, t);
+ return clock;
+ }
+
+ function since(t, s) {
+ function cmp(a,b) { return !Utils.eq(a,b); }
+ var dcount = Signal.count(A2(Signal.delay, t, s));
+ return A3( Signal.lift2, F2(cmp), Signal.count(s), dcount );
+ }
+ function read(s) {
+ var t = Date.parse(s);
+ return isNaN(t) ? Maybe.Nothing : Maybe.Just(t);
+ }
+ return elm.Native.Time = {
+ fpsWhen : F2(fpsWhen),
+ fps : function(t) { return fpsWhen(t, Signal.constant(true)); },
+ every : function(t) { return everyWhen(t, Signal.constant(true)) },
+ delay : Signal.delay,
+ timestamp : Signal.timestamp,
+ since : F2(since),
+ toDate : function(t) { return new window.Date(t); },
+ read : read
+ };
+
+};
diff --git a/libraries/Native/Signal/Touch.js b/libraries/Native/Signal/Touch.js
new file mode 100644
index 0000000..89f761b
--- /dev/null
+++ b/libraries/Native/Signal/Touch.js
@@ -0,0 +1,150 @@
+
+Elm.Native.Touch = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Touch) return elm.Native.Touch;
+
+ var Signal = Elm.Signal(elm);
+ var JS = Elm.JavaScript(elm);
+ var _ = Elm.Native.Utils(elm);
+
+ function Dict() {
+ this.keys = [];
+ this.values = [];
+
+ this.insert = function(key,value) {
+ this.keys.push(key);
+ this.values.push(value);
+ };
+ this.lookup = function(key) {
+ var i = this.keys.indexOf(key)
+ return i >= 0 ? this.values[i] : {x:0,y:0,t:0};
+ };
+ this.remove = function(key) {
+ var i = this.keys.indexOf(key);
+ if (i < 0) return;
+ var t = this.values[i];
+ this.keys.splice(i,1);
+ this.values.splice(i,1);
+ return t;
+ };
+ this.clear = function() {
+ this.keys = [];
+ this.values = [];
+ };
+ }
+
+ var root = Signal.constant([]),
+ tapTime = 500,
+ hasTap = false,
+ tap = {_:{},x:0,y:0},
+ dict = new Dict();
+
+ function touch(t) {
+ var r = dict.lookup(t.identifier);
+ return {_ : {},
+ id: t.identifier,
+ x : t.pageX - elm.node.offsetX,
+ y : t.pageY - elm.node.offsetY,
+ x0: r.x,
+ y0: r.y,
+ t0: r.t
+ };
+ }
+
+ var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
+
+ function start(e) {
+ dict.insert(e.identifier,
+ {x: e.pageX - elm.node.offsetX,
+ y: e.pageY - elm.node.offsetY,
+ t: Date.now()});
+ }
+ function end(e) {
+ var t = dict.remove(e.identifier);
+ if (Date.now() - t.t < tapTime) {
+ hasTap = true;
+ tap = {_:{}, x:t.x, y:t.y};
+ }
+ }
+
+ function listen(name, f) {
+ function update(e) {
+ for (var i = e.changedTouches.length; i--; ) { f(e.changedTouches[i]); }
+ var ts = new Array(e.touches.length);
+ for (var i = e.touches.length; i--; ) { ts[i] = touch(e.touches[i]); }
+ var hasListener = elm.notify(root.id, ts);
+ if (!hasListener) return node.removeEventListener(name, update);
+ e.preventDefault();
+ }
+ node.addEventListener(name, update);
+ }
+
+ listen("touchstart", start);
+ listen("touchmove", function(_){});
+ listen("touchend", end);
+ listen("touchcancel", end);
+ listen("touchleave", end);
+
+ var mouseID = -1;
+ function move(e) {
+ for (var i = root.value.length; i--; ) {
+ if (root.value[i].id === mouseID) {
+ root.value[i].x = e.pageX - elm.node.offsetX;
+ root.value[i].y = e.pageY - elm.node.offsetY;
+ elm.notify(root.id, root.value);
+ break;
+ }
+ }
+ }
+ node.addEventListener("mousedown", function(e) {
+ node.addEventListener("mousemove", move);
+ e.identifier = mouseID;
+ start(e);
+ root.value.push(touch(e));
+ elm.notify(root.id, root.value);
+ });
+ node.addEventListener("mouseup", function(e) {
+ node.removeEventListener("mousemove", move);
+ e.identifier = mouseID;
+ end(e);
+ for (var i = root.value.length; i--; ) {
+ if (root.value[i].id === mouseID) {
+ root.value.splice(i, 1);
+ --mouseID;
+ break;
+ }
+ }
+ elm.notify(root.id, root.value);
+ });
+ node.addEventListener("blur", function() {
+ node.removeEventListener("mousemove", move);
+ if (root.values.length > 0) {
+ elm.notify(root.id, []);
+ --mouseID;
+ }
+ dict.clear();
+ });
+
+ function dependency(f) {
+ var sig = A2( Signal.lift, f, root );
+ root.defaultNumberOfKids += 1;
+ sig.defaultNumberOfKids = 0;
+ return sig;
+ }
+
+ var touches = dependency(JS.toList);
+
+ var taps = function() {
+ var sig = dependency(function(_) { return tap; });
+ sig.defaultNumberOfKids = 1;
+ function pred(_) { var b = hasTap; hasTap = false; return b; }
+ var sig2 = A3( Signal.keepIf, pred, {_:{},x:0,y:0}, sig);
+ sig2.defaultNumberOfKids = 0;
+ return sig2;
+ }();
+
+ return elm.Native.Touch = { touches: touches, taps: taps };
+
+};
\ No newline at end of file
diff --git a/libraries/Native/Signal/WebSocket.js b/libraries/Native/Signal/WebSocket.js
new file mode 100644
index 0000000..3709fc9
--- /dev/null
+++ b/libraries/Native/Signal/WebSocket.js
@@ -0,0 +1,38 @@
+
+Elm.Native.WebSocket = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.WebSocket) return elm.Native.WebSocket;
+
+ var Signal = Elm.Signal(elm);
+ var JS = Elm.JavaScript(elm);
+ var List = Elm.Native.List(elm);
+
+ function open(url, outgoing) {
+ var incoming = Signal.constant(List.Nil);
+ var ws = new WebSocket(JS.fromString(url));
+
+ var pending = [];
+ var ready = false;
+
+ ws.onopen = function(e) {
+ var len = pending.length;
+ for (var i = 0; i < len; ++i) { ws.send(pending[i]); }
+ ready = true;
+ };
+ ws.onmessage = function(event) {
+ elm.notify(incoming.id, JS.toString(event.data));
+ };
+
+ function send(msg) {
+ var s = JS.fromString(msg);
+ ready ? ws.send(s) : pending.push(s);
+ }
+
+ function take1(x,y) { return x }
+ return A3(Signal.lift2, F2(take1), incoming, A2(Signal.lift, send, outgoing));
+ }
+
+ return elm.Native.WebSocket = { connect: F2(open) };
+};
diff --git a/libraries/Native/Signal/Window.js b/libraries/Native/Signal/Window.js
new file mode 100644
index 0000000..560f266
--- /dev/null
+++ b/libraries/Native/Signal/Window.js
@@ -0,0 +1,46 @@
+
+Elm.Native.Window = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Window) return elm.Native.Window;
+
+ var Signal = Elm.Signal(elm);
+ var Tuple2 = Elm.Native.Utils(elm).Tuple2;
+
+ function getWidth() { return elm.node.clientWidth; }
+ function getHeight() {
+ if (elm.display === ElmRuntime.Display.FULLSCREEN) {
+ return window.innerHeight;
+ }
+ return elm.node.clientHeight;
+ }
+
+ var dimensions = Signal.constant(Tuple2(getWidth(), getHeight()));
+ dimensions.defaultNumberOfKids = 2;
+
+ // Do not move width and height into Elm. By setting the default number of kids,
+ // the resize listener can be detached.
+ var width = A2(Signal.lift, function(p){return p._0;}, dimensions);
+ width.defaultNumberOfKids = 0;
+
+ var height = A2(Signal.lift, function(p){return p._1;}, dimensions);
+ height.defaultNumberOfKids = 0;
+
+ function resizeIfNeeded() {
+ var w = getWidth();
+ var h = getHeight();
+ if (dimensions.value._0 === w && dimensions.value._1 === h) return;
+ var hasListener = elm.notify(dimensions.id, Tuple2(w,h));
+ if (!hasListener) window.removeEventListener('resize', resizeIfNeeded);
+ }
+ window.addEventListener('resize', resizeIfNeeded);
+
+ return elm.Native.Window = {
+ dimensions:dimensions,
+ width:width,
+ height:height,
+ resizeIfNeeded:resizeIfNeeded
+ };
+
+};
diff --git a/libraries/Native/Text.js b/libraries/Native/Text.js
new file mode 100644
index 0000000..db7ad96
--- /dev/null
+++ b/libraries/Native/Text.js
@@ -0,0 +1,136 @@
+
+Elm.Native.Text = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Text) return elm.Native.Text;
+
+ var JS = Elm.JavaScript(elm);
+ var htmlHeight = Elm.Native.Utils(elm).htmlHeight;
+ var Color = Elm.Native.Color(elm);
+ var Element = Elm.Graphics.Element(elm);
+ var show = Elm.Native.Show(elm).show;
+
+ function makeSpaces(s) {
+ if (s.length == 0) { return s; }
+ var arr = s.split('');
+ if (arr[0] == ' ') { arr[0] = " " }
+ for (var i = arr.length; --i; ) {
+ if (arr[i][0] == ' ' && arr[i-1] == ' ') {
+ arr[i-1] = arr[i-1] + arr[i];
+ arr[i] = '';
+ }
+ }
+ for (var i = arr.length; i--; ) {
+ if (arr[i].length > 1 && arr[i][0] == ' ') {
+ var spaces = arr[i].split('');
+ for (var j = spaces.length - 2; j >= 0; j -= 2) {
+ spaces[j] = ' ';
+ }
+ arr[i] = spaces.join('');
+ }
+ }
+ arr = arr.join('');
+ if (arr[arr.length-1] === " ") {
+ return arr.slice(0,-1) + ' ';
+ }
+ return arr;
+ }
+
+ function properEscape(str) {
+ if (str.length == 0) return str;
+ str = str //.replace(/&/g, "&")
+ .replace(/"/g, /*"*/ '"')
+ .replace(/'/g, /*'*/ "'")
+ .replace(//g, ">")
+ .replace(/\n/g, "
");
+ var arr = str.split('
');
+ for (var i = arr.length; i--; ) {
+ arr[i] = makeSpaces(arr[i]);
+ }
+ return arr.join('
');
+ }
+
+ function toText(str) { return properEscape(JS.fromString(str)); }
+
+ function addTag(tag) { return function(text) {
+ return '<' + tag + ' style="padding:0;margin:0">' + text + '' + tag + '>';
+ }
+ }
+
+ function addStyle(style, value, text) {
+ return "" + text + "";
+ }
+
+ function typeface(name, text) {
+ return addStyle('font-family', JS.fromString(name), text);
+ }
+ function monospace(text) {
+ return addStyle('font-family', 'monospace', text);
+ }
+ function size(px, text) { return addStyle('font-size', px + 'px', text) }
+ var header = addTag('h1');
+ function height(h, text) { return addStyle('font-size', h+'em', text) }
+ function italic(text) { return addStyle('font-style', 'italic', text) }
+ var bold = addTag('b');
+
+ function extract(c) {
+ if (c._3 === 1) { return 'rgb(' + c._0 + ',' + c._1 + ',' + c._2 + ')'; }
+ return 'rgba(' + c._0 + ',' + c._1 + ',' + c._2 + ',' + c._3 + ')';
+ }
+ function color(c, text) {
+ return addStyle('color', extract(c), text);
+ }
+ function underline(text) { return addStyle('text-decoration', 'underline', text) }
+ function overline(text) { return addStyle('text-decoration', 'overline', text) }
+ function strikeThrough(text) {
+ return addStyle('text-decoration', 'line-through', text);
+ }
+ function link(href, text) {
+ return "" + text + "";
+ }
+
+ function position(pos) { return function(text) {
+ var e = {ctor:'RawHtml',
+ _0: '' + text + '
'
+ };
+ var p = A2(htmlHeight, 0, text);
+ return A3(Element.newElement, p._0, p._1, e);
+ }
+ }
+
+ function asText(v) {
+ return position('left')(monospace(toText(show(v))));
+ }
+
+ function plainText(v) {
+ return position('left')(toText(v));
+ }
+
+ return elm.Native.Text = {
+ toText: toText,
+
+ header : header,
+ height : F2(height),
+ italic : italic,
+ bold : bold,
+ underline : underline,
+ overline : overline,
+ strikeThrough : strikeThrough,
+ monospace : monospace,
+ typeface : F2(typeface),
+ color : F2(color),
+ link : F2(link),
+
+ justified : position('justify'),
+ centered : position('center'),
+ righted : position('right'),
+ text : position('left'),
+ plainText : plainText,
+
+ asText : asText
+ };
+
+};
\ No newline at end of file
diff --git a/libraries/Native/Utils.js b/libraries/Native/Utils.js
new file mode 100644
index 0000000..0056c52
--- /dev/null
+++ b/libraries/Native/Utils.js
@@ -0,0 +1,157 @@
+
+Elm.Native.Utils = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Utils) return elm.Native.Utils;
+
+ function eq(x,y) {
+ if (x === y) return true;
+ if (typeof x === "object") {
+ var c = 0;
+ for (var i in x) { ++c; if (!eq(x[i],y[i])) return false; }
+ return c === Object.keys(y).length;
+ }
+ if (typeof x === 'function') {
+ throw new Error('Equality error: general function equality is ' +
+ 'undecidable, and therefore, unsupported');
+ }
+ return x === y;
+ }
+
+ var EQ = 0, LT = 1, GT = 2, ord = ['EQ','LT','GT'];
+ function compare(x,y) { return { ctor: ord[cmp(x,y)] } }
+ function cmp(x,y) {
+ var ord;
+ if (typeof x !== 'object') return x === y ? EQ : x < y ? LT : GT;
+
+ if (x.ctor === "Cons" || x.ctor === "Nil") {
+ while (true) {
+ if (x.ctor === "Nil" && y.ctor === "Nil") return EQ;
+ if (x.ctor !== y.ctor) return x.ctor === 'Nil' ? LT : GT;
+ ord = cmp(x._0, y._0);
+ if (ord !== EQ) return ord;
+ x = x._1;
+ y = y._1;
+ }
+ }
+
+ if (x.ctor.slice(0,5) === 'Tuple') {
+ var n = x.ctor.slice(5) - 0;
+ var err = 'cannot compare tuples with more than 6 elements.';
+ if (n === 0) return EQ;
+ if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
+ if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
+ if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
+ if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
+ if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
+ if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
+ if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
+ return EQ;
+ }
+ throw new Error('Comparison error: comparison is only defined on ints, ' +
+ 'floats, times, chars, strings, lists of comparable values, ' +
+ 'and tuples of comparable values.')
+ }
+
+
+ var Tuple0 = { ctor: "Tuple0" };
+ function Tuple2(x,y) { return { ctor:"Tuple2", _0:x, _1:y } }
+
+ var count = 0;
+ function guid(_) { return count++ }
+
+ function copy(r) {
+ var o = {};
+ for (var i in r) { o[i] = r[i]; }
+ return o;
+ }
+
+ function remove(x,r) {
+ var o = copy(r);
+ if (x in o._) {
+ o[x] = o._[x][0];
+ o._[x] = o._[x].slice(1);
+ if (o._[x].length === 0) { delete o._[x]; }
+ } else {
+ delete o[x];
+ }
+ return o;
+ }
+
+ function replace(kvs,r) {
+ var o = copy(r);
+ for (var i = kvs.length; i--; ) {
+ var kvsi = kvs[i];
+ o[kvsi[0]] = kvsi[1];
+ }
+ return o;
+ }
+
+ function insert(x,v,r) {
+ var o = copy(r);
+ if (x in o) o._[x] = [o[x]].concat(x in o._ ? o._[x].slice(0) : []);
+ o[x] = v;
+ return o;
+ }
+
+ function max(a,b) { return a > b ? a : b }
+ function min(a,b) { return a < b ? a : b }
+
+ function mod(a,b) {
+ var r = a % b;
+ var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r+b) : -mod(-a,-b));
+
+ return m === b ? 0 : m;
+ }
+
+ function htmlHeight(width, html) {
+ var t = document.createElement('div');
+ t.innerHTML = html;
+ if (width > 0) { t.style.width = width + "px"; }
+ t.style.visibility = "hidden";
+ t.style.styleFloat = "left";
+ t.style.cssFloat = "left";
+
+ elm.node.appendChild(t);
+ var w = t.clientWidth;
+ var h = t.clientHeight;
+ elm.node.removeChild(t);
+ return Tuple2(w,h);
+ }
+
+ function adjustOffset() {
+ var node = elm.node;
+ var offsetX = 0, offsetY = 0;
+ if (node.offsetParent) {
+ do {
+ offsetX += node.offsetLeft;
+ offsetY += node.offsetTop;
+ } while (node = node.offsetParent);
+ }
+ elm.node.offsetX = offsetX;
+ elm.node.offsetY = offsetY;
+ }
+
+ if (elm.display === ElmRuntime.Display.COMPONENT) {
+ elm.node.addEventListener('mouseover', adjustOffset);
+ }
+
+ return elm.Native.Utils = {
+ eq:eq,
+ cmp:compare,
+ compare:F2(compare),
+ Tuple0:Tuple0,
+ Tuple2:Tuple2,
+ copy: copy,
+ remove: remove,
+ replace: replace,
+ insert: insert,
+ guid: guid,
+ max : F2(max),
+ min : F2(min),
+ mod : F2(mod),
+ htmlHeight: F2(htmlHeight),
+ toFloat: function(x){return x}
+ };
+};
diff --git a/libraries/Prelude.elm b/libraries/Prelude.elm
new file mode 100644
index 0000000..5eee1c4
--- /dev/null
+++ b/libraries/Prelude.elm
@@ -0,0 +1,202 @@
+
+module Prelude where
+
+import Native.Prelude as N
+
+-- Convert radians to standard Elm angles (radians).
+radians : Float -> Float
+radians t = t
+
+-- Convert degrees to standard Elm angles (radians).
+degrees : Float -> Float
+degrees d = d * Math.PI / 180
+
+-- Convert turns to standard Elm angles (radians).
+-- One turn is equal to 360°.
+turns : Float -> Float
+turns r = 2 * Math.PI * r
+
+-- Start with polar coordinates (r,θ)
+-- and get out cartesian coordinates (x,y).
+fromPolar : (Float,Float) -> (Float,Float)
+fromPolar (r,t) = (r * N.cos t, r * N.sin t)
+
+-- Start with cartesian coordinates (x,y)
+-- and get out polar coordinates (r,θ).
+toPolar : (Float,Float) -> (Float,Float)
+toPolar (x,y) = (N.sqrt (x^2 + y^2), N.atan2 y x)
+
+(+) : Number a -> Number a -> Number a
+(-) : Number a -> Number a -> Number a
+(*) : Number a -> Number a -> Number a
+
+-- Floating point division.
+(/) : Float -> Float -> Float
+
+-- Integer division, remainder is discarded.
+div : Int -> Int -> Int
+
+-- Finds the remainder after dividing one number by another: ``4 `rem` 3 == 1``
+rem : Int -> Int -> Int
+
+-- Perform modular arithmetic: ``7 `mod` 2 == 1``
+mod : Int -> Int -> Int
+
+-- Exponentiation: `3^2 == 9`
+(^) : Number a -> Number a -> Number a
+
+cos : Float -> Float
+sin : Float -> Float
+tan : Float -> Float
+acos : Float -> Float
+asin : Float -> Float
+
+-- You probably do not want to use this. Because it takes `(y/x)` as the argument
+-- there is no way to know where the negative signs come from so the resulting
+-- angle is always between π/2 and -π/2 (in quadrants I and IV).
+atan : Float -> Float
+
+-- This helps you find the angle of a cartesian coordinate.
+-- You will almost certainly want to use this instead of `atan`.
+-- So `atan2 y x` computes *atan(y/x)* but also keeps track of which
+-- quadrant the angle should really be in. The result will be between
+-- π and -π, giving you the full range of angles.
+atan2 : Float -> Float -> Float
+
+-- Take the square root of a number.
+sqrt : Number a -> Number a
+
+-- Take the absolute value of a number.
+abs : Number a -> Number a
+
+-- Calculate the logarithm of a number with a given base: `logBase 10 100 == 2`
+logBase : Number a -> Number a -> Number a
+
+-- Given two numbers, returns the smaller one.
+min : Number a -> Number a -> Number a
+
+-- Given two numbers, returns the larger one.
+max : Number a -> Number a -> Number a
+
+-- Clamps a number within a given range. With the expression `clamp 100 200 x`
+-- the results are as follows:
+--
+-- * `100 if x < 100`
+-- * ` x if 100 <= x < 200`
+-- * `200 if 200 <= x`
+clamp : Number a -> Number a -> Number a -> Number a
+
+-- An approximation of pi.
+pi : Float
+
+-- An approximation of e.
+e : Float
+
+-- Compare any two values for structural equality. Functions cannot be compared.
+(==) : a -> a -> Bool
+(/=) : a -> a -> Bool
+
+(<) : Comparable a -> Comparable a -> Bool
+(>) : Comparable a -> Comparable a -> Bool
+(<=) : Comparable a -> Comparable a -> Bool
+(>=) : Comparable a -> Comparable a -> Bool
+
+-- Compare any two comparable values. Comparable values include `String`, `Char`,
+-- `Int`, `Float`, `Time`, or a list or tuple containing comparable values.
+-- These are also the only values that work as `Dict` keys or `Set` members.
+compare : Comparable a -> Comparable a -> Order
+
+-- Represents the relative ordering of two things.
+-- The relations are less than, equal to, and greater than.
+data Order = LT | EQ | GT
+
+-- The and operator. True if both inputs are True.
+(&&) : Bool -> Bool -> Bool
+
+-- The or operator. True if one or both inputs are True.
+(||) : Bool -> Bool -> Bool
+
+-- The exclusive-or operator. True if exactly one input is True.
+xor : Bool -> Bool -> Bool
+
+-- Negate a boolean value: `(not True == False)` and `(not False == True)`
+not : Bool -> Bool
+
+-- Equal to true. Useful as the last case of a multi-way-if.
+otherwise : Bool
+otherwise = True
+
+
+-- Conversions
+
+-- Round a number to the nearest integer.
+round : Float -> Int
+
+-- Truncate a decimal number, rounding towards zero.
+truncate : Float -> Int
+
+-- Floor function, rounding down.
+floor : Float -> Int
+
+-- Ceiling function, rounding up.
+ceiling : Float -> Int
+
+-- Convert an integer into a float.
+toFloat : Int -> Float
+
+-- Convert almost any value to its string representation.
+show : a -> String
+
+-- Read an integer from a string
+readInt : String -> Maybe Int
+
+-- Read a float from a string.
+readFloat : String -> Maybe Float
+
+-- Function Helpers
+
+-- Function composition: `(f . g == (\\x -> f (g x)))`
+(.) : (b -> c) -> (a -> b) -> (a -> c)
+
+-- Forward function application `x |> f == f x`. This function is useful
+-- for avoiding parenthesis and writing code in a more natural way.
+-- Consider the following code to create a pentagon:
+--
+-- scale 2 (move (10,10) (filled blue (ngon 5 30)))
+--
+-- This can also be written as:
+--
+-- ngon 5 30 |> filled blue
+-- |> move (10,10)
+-- |> scale 2
+(|>) : a -> (a -> b) -> b
+
+-- Function application `f <| x == f x`. This function is useful for avoiding
+-- parenthesis. Consider the following code to create a text element:
+--
+-- text (monospace (toText "code"))
+--
+-- This can also be written as:
+--
+-- text . monospace <| toText "code"
+(<|) : (a -> b) -> a -> b
+
+-- Given a value, returns exactly the same value.
+id : a -> a
+
+-- Given a 2-tuple, returns the first value.
+fst : (a,b) -> a
+
+-- Given a 2-tuple, returns the second value.
+snd : (a,b) -> b
+
+-- Flips the order of the first two arguments to a function.
+flip : (a -> b -> c) -> (b -> a -> c)
+
+-- Change how arguments are passed to a function. This splits paired arguments
+-- into two separate arguments.
+curry : ((a,b) -> c) -> a -> b -> c
+
+-- Change how arguments are passed to a function. This combines two arguments
+-- into a sigle pair.
+uncurry : (a -> b -> c) -> (a,b) -> c
diff --git a/libraries/Random.elm b/libraries/Random.elm
new file mode 100644
index 0000000..e32e115
--- /dev/null
+++ b/libraries/Random.elm
@@ -0,0 +1,13 @@
+
+module Random where
+
+import Native.Random as R
+
+-- Given a range from low to high and a signal of values, this produces
+-- a new signal that changes whenever the input signal changes. The new
+-- values are random number between 'low' and 'high' inclusive.
+range : Int -> Int -> Signal a -> Signal Int
+
+-- Produces a new signal that changes whenever the input signal changes.
+-- The new values are random numbers in [0..1).
+float : Signal a -> Signal Float
diff --git a/libraries/Set.elm b/libraries/Set.elm
new file mode 100644
index 0000000..356cbde
--- /dev/null
+++ b/libraries/Set.elm
@@ -0,0 +1,65 @@
+
+module Set (empty,singleton,insert,remove
+ ,member
+ ,foldl,foldr,map
+ ,union,intersect,diff
+ ,toList,fromList
+ ) where
+
+import Dict as Dict
+import List as List
+
+type Set t = Dict t ()
+
+-- Create an empty set.
+empty : Set (Comparable k)
+empty = Dict.empty
+
+-- Create a set with one value.
+singleton : Comparable k -> Set (Comparable k)
+singleton k = Dict.singleton k ()
+
+-- Insert a value into a set.
+insert : Comparable k -> Set (Comparable k) -> Set (Comparable k)
+insert k = Dict.insert k ()
+
+-- Remove a value from a set. If the value is not found, no changes are made.
+remove : Comparable k -> Set (Comparable k) -> Set (Comparable k)
+remove = Dict.remove
+
+-- Determine if a value is in a set.
+member : Comparable k -> Set (Comparable k) -> Bool
+member = Dict.member
+
+-- Get the union of two sets. Keep all values.
+union : Set (Comparable k) -> Set (Comparable k) -> Set (Comparable k)
+union = Dict.union
+
+-- Get the intersection of two sets. Keeps values that appear in both sets.
+intersect : Set (Comparable k) -> Set (Comparable k) -> Set (Comparable k)
+intersect = Dict.intersect
+
+-- Get the difference between the first set and the second. Keeps values
+-- that do not appear in the second set.
+diff : Set (Comparable k) -> Set (Comparable k) -> Set (Comparable k)
+diff = Dict.diff
+
+-- Convert a set into a list.
+toList : Set (Comparable k) -> [Comparable k]
+toList = Dict.keys
+
+-- Convert a list into a set, removing any duplicates.
+fromList : [Comparable k] -> Set (Comparable k)
+fromList xs = List.foldl insert empty xs
+
+-- Fold over the values in a set, in order from lowest to highest.
+foldl : (Comparable a -> b -> b) -> b -> Set (Comparable a) -> b
+foldl f b s = Dict.foldl (\k _ b -> f k b) b s
+
+-- Fold over the values in a set, in order from highest to lowest.
+foldr : (Comparable a -> b -> b) -> b -> Set (Comparable a) -> b
+foldr f b s = Dict.foldr (\k _ b -> f k b) b s
+
+-- Map a function onto a set, creating a new set with no duplicates.
+map : (Comparable a -> Comparable b) -> Set (Comparable a) -> Set (Comparable b)
+map f s = fromList (List.map f (toList s))
diff --git a/libraries/Signal.elm b/libraries/Signal.elm
new file mode 100644
index 0000000..3f8ef3f
--- /dev/null
+++ b/libraries/Signal.elm
@@ -0,0 +1,109 @@
+
+-- The library for general signal manipulation. Some useful functions for
+-- working with time (e.g. setting FPS) and combining signals and time (e.g.
+-- delaying updates, getting timestamps) can be found in the
+-- [`Time`](/docs/Signal/Time.elm) library.
+--
+-- Note: There are lift functions up to `lift8`.
+module Signal where
+
+import Native.Signal as S
+import List as L
+
+-- Create a constant signal that never changes.
+constant : a -> Signal a
+
+-- Transform a signal with a given function.
+lift : (a -> b) -> Signal a -> Signal b
+
+-- Combine two signals with a given function.
+lift2 : (a -> b -> c) -> Signal a -> Signal b -> Signal c
+
+-- Combine three signals with a given function.
+lift3 : (a -> b -> c -> d) -> Signal a -> Signal b -> Signal c -> Signal d
+lift4 : (a -> b -> c -> d -> e) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e
+lift5 : (a -> b -> c -> d -> e -> f) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f
+lift6 : (a -> b -> c -> d -> e -> f -> g)
+ -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g
+lift7 : (a -> b -> c -> d -> e -> f -> g -> h)
+ -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g -> Signal h
+lift8 : (a -> b -> c -> d -> e -> f -> g -> h -> i)
+ -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g -> Signal h -> Signal i
+
+-- Create a past-dependent signal. Each value given on the input signal will
+-- be accumulated, producing a new output value.
+--
+-- For instance, `(foldp (\\t acc -> acc + 1) 0 (Time.every second))` increments every second.
+foldp : (a -> b -> b) -> b -> Signal a -> Signal b
+
+-- Merge two signals into one, biased towards the first signal if both signals
+-- update at the same time.
+merge : Signal a -> Signal a -> Signal a
+
+-- Merge many signals into one, biased towards the left-most signal if multiple
+-- signals update simultaneously.
+merges : [Signal a] -> Signal a
+
+-- Combine a list of signals into a signal of lists.
+combine : [Signal a] -> Signal [a]
+combine = L.foldr (S.lift2 (::)) (S.constant [])
+
+ -- Merge two signals into one, but distinguishing the values by marking the first
+ -- signal as `Left` and the second signal as `Right`. This allows you to easily
+ -- fold over non-homogeneous inputs.
+ -- mergeEither : Signal a -> Signal b -> Signal (Either a b)
+
+-- Count the number of events that have occured.
+count : Signal a -> Signal Int
+
+-- Count the number of events that have occured that satisfy a given predicate.
+countIf : (a -> Bool) -> Signal a -> Signal Int
+
+-- Keep only events that satisfy the given predicate. Elm does not allow
+-- undefined signals, so a base case must be provided in case the predicate is
+-- never satisfied.
+keepIf : (a -> Bool) -> a -> Signal a -> Signal a
+
+-- Drop events that satisfy the given predicate. Elm does not allow undefined
+-- signals, so a base case must be provided in case the predicate is never
+-- satisfied.
+dropIf : (a -> Bool) -> a -> Signal a -> Signal a
+
+-- Keep events only when the first signal is true. When the first signal becomes
+-- true, the most recent value of the second signal will be propagated. Until
+-- the first signal becomes false again, all events will be propagated. Elm does
+-- not allow undefined signals, so a base case must be provided in case the first
+-- signal is never true.
+keepWhen : Signal Bool -> a -> Signal a -> Signal a
+
+-- Drop events when the first signal is true. When the first signal becomes false,
+-- the most recent value of the second signal will be propagated. Until the first
+-- signal becomes true again, all events will be propagated. Elm does not allow
+-- undefined signals, so a base case must be provided in case the first signal is
+-- always true.
+dropWhen : Signal Bool -> a -> Signal a -> Signal a
+
+-- Drop sequential repeated values. For example, if a signal produces the
+-- sequence `[1,1,2,2,1]`, it becomes `[1,2,1]` by dropping the values that
+-- are the same as the previous value.
+dropRepeats : Signal a -> Signal a
+
+-- Sample from the second input every time an event occurs on the first input.
+-- For example, `(sampleOn clicks (every second))` will give the approximate
+-- time of the latest click.
+sampleOn : Signal a -> Signal b -> Signal b
+
+-- An alias for `lift`. A prettier way to apply a
+-- function to the current value of a signal.
+--
+-- lift f signal == f <~ signal
+(<~) : (a -> b) -> Signal a -> Signal b
+
+-- Signal application. This takes two signals, holding a function and
+-- a value. It applies the current function to the current value.
+--
+-- So the following expressions are equivalent:
+--
+-- scene <~ Window.dimensions ~ Mouse.position
+-- lift2 scene Window.dimensions Mouse.position
+(~) : Signal (a -> b) -> Signal a -> Signal b
diff --git a/libraries/Text.elm b/libraries/Text.elm
new file mode 100644
index 0000000..923a66d
--- /dev/null
+++ b/libraries/Text.elm
@@ -0,0 +1,65 @@
+
+module Text where
+
+import Native.Text as T
+
+
+-- Convert a string into text which can be styled and displayed.
+toText : String -> Text
+
+-- Set the typeface of some text. The first argument should be a comma separated listing of the desired typefaces
+-- "helvetica, arial, sans-serif"
+-- Works the same as the CSS font-family property.
+typeface : String -> Text -> Text
+
+-- Switch to a monospace typeface. Good for code snippets.
+monospace : Text -> Text
+
+-- Make text big and noticable.
+header : Text -> Text
+
+-- Create a link.
+link : String -> Text -> Text
+
+-- Set the height of text in \"ems\". 1em is the normal height of text. 2ems is twice that height.
+height : Float -> Text -> Text
+
+-- Set the color of a string.
+color : Color -> Text -> Text
+
+-- Make a string bold.
+bold : Text -> Text
+
+-- Italicize a string.
+italic : Text -> Text
+
+-- Draw a line above a string.
+overline : Text -> Text
+
+-- Underline a string.
+underline : Text -> Text
+
+-- Draw a line through a string.
+strikeThrough : Text -> Text
+
+-- Display justified, styled text.
+justified : Text -> Element
+
+-- Display centered, styled text.
+centered : Text -> Element
+
+-- Display right justified, styled text.
+righted : Text -> Element
+
+-- Display styled text.
+text : Text -> Element
+
+-- Display a plain string.
+plainText : String -> Element
+
+-- Convert anything to it's textual representation and make it displayable in browser
+--
+-- asText == text . monospace . show
+--
+-- Excellent for debugging.
+asText : a -> Element
diff --git a/libraries/Time.elm b/libraries/Time.elm
new file mode 100644
index 0000000..234f82c
--- /dev/null
+++ b/libraries/Time.elm
@@ -0,0 +1,69 @@
+-- Library for working with time. Type `Time` represents some number of milliseconds.
+module Time where
+
+import Native.Time as T
+
+-- Type alias to make it clearer when you are working with time values.
+-- Using the `Time` constants instead of raw numbers is very highly recommended.
+type Time = Float
+
+-- Units of time, making it easier to specify things like a
+-- half-second `(500 * milliseconds)` without remembering Elm’s
+-- underlying units of time.
+millisecond : Time
+millisecond = 1
+
+second : Time
+second = 1000 * millisecond
+
+minute : Time
+minute = 60 * second
+
+hour : Time
+hour = 60 * minute
+
+inMilliseconds : Time -> Float
+inMilliseconds t = t
+
+inSeconds : Time -> Float
+inSeconds t = t / second
+
+inMinutes : Time -> Float
+inMinutes t = t / minute
+
+inHours : Time -> Float
+inHours t = t / hour
+
+-- Takes desired number of frames per second (fps). The resulting signal
+-- gives a sequence of time deltas as quickly as possible until it reaches
+-- the desired FPS. A time delta is the time between the last frame and the
+-- current frame.
+fps : Number a -> Signal Time
+
+-- Same as the fps function, but you can turn it on and off. Allows you
+-- to do brief animations based on user input without major inefficiencies.
+-- The first time delta after a pause is always zero, no matter how long
+-- the pause was. This way summing the deltas will actually give the amount
+-- of time that the output signal has been running.
+fpsWhen : Number a -> Signal Bool -> Signal Time
+
+-- Takes a time interval t. The resulting signal is the current time,
+-- updated every t.
+every : Time -> Signal Time
+
+-- Takes a time `t` and any signal. The resulting boolean signal
+-- is true for time `t` after every event on the input signal.
+-- So ``(second `since` Mouse.clicks)`` would result in a signal
+-- that is true for one second after each mouse click and false
+-- otherwise.
+since : Time -> Signal a -> Signal Bool
+
+-- Add a timestamp to any signal. Timestamps increase monotonically. Each
+-- timestamp is related to a specfic event, so `Mouse.x` and `Mouse.y` will
+-- always have the same timestamp because they both rely on the same
+-- underlying event.
+timestamp : Signal a -> Signal (Time, a)
+
+-- Delay a signal by a certain amount of time. So `(delay second Mouse.clicks)`
+-- will update one second later than any mouse click.
+delay : Time -> Signal a -> Signal a
diff --git a/libraries/Touch.elm b/libraries/Touch.elm
new file mode 100644
index 0000000..d2b0ee9
--- /dev/null
+++ b/libraries/Touch.elm
@@ -0,0 +1,20 @@
+-- This is an early version of the touch library. It will likely grow to
+-- include gestures that would be useful for both games and web-pages.
+module Touch where
+
+import Native.Touch as T
+
+-- Every `Touch` has `xy` coordinates. It also has an identifier `id` to
+-- distinguish one touch from another.
+--
+-- A touch also keeps info about the intial point and time of contact:
+-- `x0`, `y0`, and `t0`. This helps compute more complicated gestures
+-- like taps, drags, and swipes which need to know about timing or direction.
+type Touch = { x:Int, y:Int, id:Int, x0:Int, y0:Int, t0:Time }
+
+-- A list of ongoing touches.
+touches : Signal [Touch]
+
+-- The last position that was tapped. Default value is `{x=0,y=0}`.
+-- Updates whenever the user taps the screen.
+taps : Signal { x:Int, y:Int }
diff --git a/libraries/WebSocket.elm b/libraries/WebSocket.elm
new file mode 100644
index 0000000..9263c56
--- /dev/null
+++ b/libraries/WebSocket.elm
@@ -0,0 +1,13 @@
+-- A library for low latency HTTP communication. See the HTTP library for
+-- standard requests like GET, POST, etc.
+module WebSocket where
+
+import Native.WebSocket as WS
+
+-- Create a web-socket. The first argument is the URL of the desired
+-- web-socket server. The input signal holds the outgoing messages,
+-- and the resulting signal contains the incoming ones.
+connect : String -> Signal String -> Signal String
+
+-- data Action = Open String | Close String | Send String String
+-- connections : Signal Action -> Signal String
\ No newline at end of file
diff --git a/libraries/Window.elm b/libraries/Window.elm
new file mode 100644
index 0000000..efdaeaa
--- /dev/null
+++ b/libraries/Window.elm
@@ -0,0 +1,14 @@
+
+module Window where
+
+import Native.Window as W
+
+-- The current dimensions of the window (i.e. the area viewable to the
+-- user, not including scroll bars).
+dimensions : Signal (Int,Int)
+
+-- The current width of the window.
+width : Signal Int
+
+-- The current height of the window.
+height : Signal Int
diff --git a/runtime/Init.js b/runtime/Init.js
new file mode 100644
index 0000000..a003f98
--- /dev/null
+++ b/runtime/Init.js
@@ -0,0 +1,117 @@
+
+(function() {
+'use strict';
+
+Elm.fullscreen = function(module) {
+ var style = document.createElement('style');
+ style.type = 'text/css';
+ style.innerHTML = "html,head,body { padding:0; margin:0; }" +
+ "body { font-family: calibri, helvetica, arial, sans-serif; }";
+ document.head.appendChild(style);
+ var container = document.createElement('div');
+ document.body.appendChild(container);
+ return init(ElmRuntime.Display.FULLSCREEN, container, module);
+};
+
+Elm.byId = function(id, module) {
+ var container = document.getElementById(id);
+ var tag = container.tagName;
+ if (tag !== 'DIV') {
+ throw new Error('Elm.byId must be given a div, not a ' + tag + '.');
+ }
+ while (container.hasChildNodes()) {
+ container.removeChild(container.lastChild);
+ }
+ return init(ElmRuntime.Display.COMPONENT, container, module);
+};
+
+Elm.worker = function(module) {
+ return init(ElmRuntime.Display.NONE, {}, module);
+};
+
+function init(display, container, module) {
+ // defining state needed for an instance of the Elm RTS
+ var signalGraph = null;
+ var inputs = [];
+ var visualModel = null;
+
+ function notify(id, v) {
+ var timestep = Date.now();
+ var hasListener = false;
+ for (var i = inputs.length; i--; ) {
+ // must maintain the order of this stmt to avoid having the ||
+ // short-circuiting the necessary work of recv
+ hasListener = inputs[i].recv(timestep, id, v) || hasListener;
+ }
+ return hasListener;
+ }
+
+ container.offsetX = 0;
+ container.offsetY = 0;
+
+ // create the actual RTS. Any impure modules will attach themselves to this
+ // object. This permits many Elm programs to be embedded per document.
+ var elm = { notify:notify,
+ node:container,
+ display:display,
+ id:ElmRuntime.guid(),
+ inputs:inputs
+ };
+
+ // Set up methods to communicate with Elm program from JS.
+ function send(name, value) {
+ if (typeof value === 'undefined') return function(v) { return send(name,v); };
+ var e = document.createEvent('Event');
+ e.initEvent(name + '_' + elm.id, true, true);
+ e.value = value;
+ document.dispatchEvent(e);
+ }
+ function recv(name, handler) {
+ document.addEventListener(name + '_' + elm.id, handler);
+ }
+
+ recv('log', function(e) {console.log(e.value)});
+ recv('title', function(e) {document.title = e.value});
+ recv('redirect', function(e) {
+ if (e.value.length > 0) { window.location = e.value; }
+ });
+
+ // If graphics are not enabled, escape early, skip over setting up DOM stuff.
+ if (display === ElmRuntime.Display.NONE) {
+ module(elm);
+ return { send : send, recv : recv };
+ }
+
+ var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+
+ // evaluate the given module and extract its 'main' value.
+ signalGraph = module(elm).main;
+
+ // make sure the signal graph is actually a signal, extract the visual model,
+ // and filter out any unused inputs.
+ var Signal = Elm.Signal(elm);
+ if (!('recv' in signalGraph)) signalGraph = Signal.constant(signalGraph);
+ visualModel = signalGraph.value;
+ inputs = ElmRuntime.filterDeadInputs(inputs);
+
+ // Add the visualModel to the DOM
+ container.appendChild(Render.render(visualModel));
+ if (elm.Native.Window) elm.Native.Window.resizeIfNeeded();
+
+ // set up updates so that the DOM is adjusted as necessary.
+ var update = Render.update;
+ function domUpdate(value) {
+ ElmRuntime.draw(function(_) {
+ update(container.firstChild, visualModel, value);
+ visualModel = value;
+ if (elm.Native.Window) elm.Native.Window.resizeIfNeeded();
+ });
+ return value;
+ }
+
+ signalGraph = A2(Signal.lift, domUpdate, signalGraph);
+
+ return { send : send, recv : recv, node : container };
+};
+
+}());
\ No newline at end of file
diff --git a/runtime/Render/Collage.js b/runtime/Render/Collage.js
new file mode 100644
index 0000000..fc4b22d
--- /dev/null
+++ b/runtime/Render/Collage.js
@@ -0,0 +1,340 @@
+
+ElmRuntime.Render.Collage = function() {
+'use strict';
+
+var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+var Matrix = Elm.Matrix2D({});
+var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
+var newElement = Utils.newElement,
+ extract = Utils.extract, fromList = Utils.fromList,
+ fromString = Utils.fromString, addTransform = Utils.addTransform;
+
+function trace(ctx, path) {
+ var points = fromList(path);
+ var i = points.length - 1;
+ if (i <= 0) return;
+ ctx.moveTo(points[i]._0, points[i]._1);
+ while (i--) { ctx.lineTo(points[i]._0, points[i]._1); }
+ if (path.closed) {
+ i = points.length - 1;
+ ctx.lineTo(points[i]._0, points[i]._1);
+ }
+}
+
+function line(ctx,style,path) {
+ style.dashing.ctor === 'Nil' ? trace(ctx, path) : customLineHelp(ctx, style, path);
+ ctx.stroke();
+}
+
+function customLineHelp(ctx, style, path) {
+ var points = fromList(path);
+ if (path.closed) points.push(points[0]);
+ var pattern = fromList(style.dashing);
+ var i = points.length - 1;
+ if (i <= 0) return;
+ var x0 = points[i]._0, y0 = points[i]._1;
+ var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
+ var pindex = 0, plen = pattern.length;
+ var draw = true, segmentLength = pattern[0];
+ ctx.moveTo(x0,y0);
+ while (i--) {
+ x1 = points[i]._0; y1 = points[i]._1;
+ dx = x1 - x0; dy = y1 - y0;
+ remaining = Math.sqrt(dx * dx + dy * dy);
+ while (segmentLength <= remaining) {
+ x0 += dx * segmentLength / remaining;
+ y0 += dy * segmentLength / remaining;
+ ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
+ // update starting position
+ dx = x1 - x0; dy = y1 - y0;
+ remaining = Math.sqrt(dx * dx + dy * dy);
+ // update pattern
+ draw = !draw;
+ pindex = (pindex + 1) % plen;
+ segmentLength = pattern[pindex];
+ }
+ if (remaining > 0) {
+ ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
+ segmentLength -= remaining;
+ }
+ x0 = x1; y0 = y1;
+ }
+}
+
+function drawLine(ctx, style, path) {
+ ctx.lineWidth = style.width;
+ var cap = style.cap.ctor;
+ ctx.lineCap = cap === 'Flat' ? 'butt' :
+ cap === 'Round' ? 'round' : 'square';
+ var join = style.join.ctor;
+ ctx.lineJoin = join === 'Smooth' ? 'round' :
+ join === 'Sharp' ? 'miter' : 'bevel';
+ ctx.miterLimit = style.join._0 || 10;
+ ctx.strokeStyle = extract(style.color);
+ return line(ctx, style, path);
+}
+
+function texture(redo, ctx, src) {
+ var img = new Image();
+ img.src = fromString(src);
+ img.onload = redo;
+ return ctx.createPattern(img, 'repeat');
+}
+
+function gradient(ctx, grad) {
+ var g;
+ var stops = [];
+ if (grad.ctor === 'Linear') {
+ var p0 = grad._0, p1 = grad._1;
+ g = ctx.createLinearGradient(p0._0, -p0._1, p1._0, -p1._1);
+ stops = fromList(grad._2);
+ } else {
+ var p0 = grad._0, p2 = grad._2;
+ g = ctx.createRadialGradient(p0._0, -p0._1, grad._1, p2._0, -p2._1, grad._3);
+ stops = fromList(grad._4);
+ }
+ var len = stops.length;
+ for (var i = 0; i < len; ++i) {
+ var stop = stops[i];
+ g.addColorStop(stop._0, extract(stop._1));
+ }
+ return g;
+}
+
+function drawShape(redo, ctx, style, path) {
+ trace(ctx, path);
+ var sty = style.ctor;
+ ctx.fillStyle =
+ sty === 'Solid' ? extract(style._0) :
+ sty === 'Texture' ? texture(redo, ctx, style._0) : gradient(ctx, style._0);
+ ctx.fill();
+}
+
+function drawImage(redo, ctx, form) {
+ var img = new Image();
+ img.onload = redo;
+ img.src = fromString(form._3);
+ var w = form._0,
+ h = form._1,
+ pos = form._2,
+ srcX = pos._0,
+ srcY = pos._1,
+ srcW = w,
+ srcH = h,
+ destX = -w/2,
+ destY = -h/2,
+ destW = w,
+ destH = h;
+
+ ctx.drawImage(img, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
+}
+
+function renderForm(redo, ctx, form) {
+ ctx.save();
+ var x = form.x, y = form.y, theta = form.theta, scale = form.scale;
+ if (x !== 0 || y !== 0) ctx.translate(x, y);
+ if (theta !== 0) ctx.rotate(theta);
+ ctx.scale(scale,-scale);
+ ctx.beginPath();
+ var f = form.form;
+ switch(f.ctor) {
+ case 'FPath' : drawLine(ctx, f._0, f._1); break;
+ case 'FImage': drawImage(redo, ctx, f); break;
+ case 'FShape':
+ if (f._0.ctor === 'Left') {
+ f._1.closed = true;
+ drawLine(ctx, f._0._0, f._1);
+ } else {
+ drawShape(redo, ctx, f._0._0, f._1);
+ }
+ break;
+ }
+ ctx.restore();
+}
+
+function formToMatrix(form) {
+ var scale = form.scale;
+ var matrix = A6( Matrix.matrix, scale, 0, 0, scale, scale * form.x, scale * form.y );
+
+ var theta = form.theta
+ if (theta !== 0)
+ matrix = A2( Matrix.multiply, matrix, Matrix.rotation(theta) );
+
+ return matrix;
+}
+
+function makeTransform(w, h, form, matrices) {
+ var props = form.form._0.props;
+ var m = A6( Matrix.matrix, 1, 0, 0, 1,
+ (w - props.width)/2,
+ (h - props.height)/2 );
+ var len = matrices.length;
+ for (var i = 0; i < len; ++i) { m = A2( Matrix.multiply, m, matrices[i] ); }
+ m = A2( Matrix.multiply, m, formToMatrix(form) );
+
+ return 'matrix(' + m[0] + ',' + m[3] + ',' +
+ (-m[1]) + ',' + (-m[4]) + ',' +
+ m[2] + ',' + m[5] + ')';
+}
+
+function stepperHelp(list) {
+ var arr = fromList(list);
+ var i = 0;
+ function peekNext() {
+ return i < arr.length ? arr[i].form.ctor : '';
+ }
+ // assumes that there is a next element
+ function next() {
+ var out = arr[i];
+ ++i;
+ return out;
+ }
+ return { peekNext:peekNext, next:next };
+}
+
+function stepper(forms) {
+ var ps = [stepperHelp(forms)];
+ var matrices = [];
+ function peekNext() {
+ var len = ps.length;
+ var formType = '';
+ for (var i = 0; i < len; ++i ) {
+ if (formType = ps[i].peekNext()) return formType;
+ }
+ return '';
+ }
+ // assumes that there is a next element
+ function next(ctx) {
+ while (!ps[0].peekNext()) { ps.shift(); matrices.pop(); ctx.restore(); }
+ var out = ps[0].next();
+ var f = out.form;
+ if (f.ctor === 'FGroup') {
+ ps.unshift(stepperHelp(f._1));
+ var m = A2( Matrix.multiply, f._0, formToMatrix(out));
+ ctx.save();
+ ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
+ matrices.push(m);
+ }
+ return out;
+ }
+ function transforms() { return matrices; }
+ return { peekNext:peekNext, next:next, transforms:transforms };
+}
+
+function makeCanvas(w,h) {
+ var canvas = newElement('canvas');
+ canvas.style.width = w + 'px';
+ canvas.style.height = h + 'px';
+ canvas.style.display = "block";
+ canvas.style.position = "absolute";
+ canvas.width = w;
+ canvas.height = h;
+ return canvas;
+}
+
+function render(model) {
+ var div = newElement('div');
+ update(div, model, model);
+ return div;
+}
+
+function updateTracker(w,h,div) {
+ var kids = div.childNodes;
+ var i = 0;
+ function transform(transforms, ctx) {
+ ctx.translate(w/2, h/2);
+ var len = transforms.length;
+ for (var i = 0; i < len; ++i) {
+ var m = transforms[i];
+ ctx.save();
+ ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
+ }
+ return ctx;
+ }
+ function getContext(transforms) {
+ while (i < kids.length) {
+ var node = kids[i++];
+ if (node.getContext) {
+ node.width = w;
+ node.height = h;
+ node.style.width = w + 'px';
+ node.style.height = h + 'px';
+ return transform(transforms, node.getContext('2d'));
+ }
+ div.removeChild(node);
+ }
+ var canvas = makeCanvas(w,h);
+ div.appendChild(canvas);
+ // we have added a new node, so we must step our position
+ ++i;
+ return transform(transforms, canvas.getContext('2d'));
+ }
+ function element(matrices, form) {
+ var container = kids[i];
+ if (!container || container.getContext) {
+ container = newElement('div');
+ container.style.overflow = 'hidden';
+ container.style.position = 'absolute';
+ addTransform(container.style, 'scaleY(-1)');
+ if (!container) {
+ div.appendChild(container);
+ } else {
+ div.insertBefore(container, kids[i]);
+ }
+ }
+ // we have added a new node, so we must step our position
+ ++i;
+
+ container.style.width = w + 'px';
+ container.style.height = h + 'px';
+
+ var elem = form.form._0;
+ var node = container.firstChild;
+ if (node) {
+ Render.update(node, node.oldElement, elem);
+ node = container.firstChild;
+ } else {
+ node = Render.render(elem);
+ container.appendChild(node);
+ }
+ node.oldElement = elem;
+ addTransform(node.style, makeTransform(w, h, form, matrices));
+ }
+ return { getContext:getContext, element:element };
+}
+
+
+function update(div, _, model) {
+ var w = model.w;
+ var h = model.h;
+ div.style.width = w + 'px';
+ div.style.height = h + 'px';
+ if (model.forms.ctor === 'Nil') {
+ while (div.hasChildNodes()) {
+ div.removeChild(div.lastChild);
+ }
+ }
+ var stpr = stepper(model.forms);
+ var tracker = updateTracker(w,h,div);
+ var ctx = null;
+ var formType = '';
+
+ while (formType = stpr.peekNext()) {
+ if (ctx === null && formType !== 'FElement') {
+ ctx = tracker.getContext(stpr.transforms());
+ ctx.scale(1,-1);
+ }
+ var form = stpr.next(ctx);
+ if (formType === 'FElement') {
+ tracker.element(stpr.transforms(), form);
+ ctx = null;
+ } else if (formType !== 'FGroup') {
+ renderForm(function() { update(div, model, model); }, ctx, form);
+ }
+ }
+ return div;
+}
+
+return { render:render, update:update };
+
+};
diff --git a/runtime/Render/Element.js b/runtime/Render/Element.js
new file mode 100644
index 0000000..30d57d2
--- /dev/null
+++ b/runtime/Render/Element.js
@@ -0,0 +1,269 @@
+
+ElmRuntime.Render.Element = function() {
+'use strict';
+
+var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
+var newElement = Utils.newElement, extract = Utils.extract,
+ addTransform = Utils.addTransform, removeTransform = Utils.removeTransform,
+ fromList = Utils.fromList, eq = Utils.eq;
+
+function setProps(props, e) {
+ e.style.width = (props.width |0) + 'px';
+ e.style.height = (props.height|0) + 'px';
+ if (props.opacity !== 1) { e.style.opacity = props.opacity; }
+ if (props.color.ctor === 'Just') {
+ e.style.backgroundColor = extract(props.color._0);
+ }
+ if (props.tag !== '') { e.id = props.tag; }
+ if (props.href !== '') {
+ var a = newElement('a');
+ a.href = props.href;
+ a.appendChild(e);
+ return a;
+ }
+ return e;
+}
+
+function image(props, img) {
+ switch (img._0.ctor) {
+ case 'Plain': return plainImage(img._3);
+ case 'Fitted': return fittedImage(props.width, props.height, img._3);
+ case 'Cropped': return croppedImage(img,props.width,props.height,img._3);
+ }
+}
+
+function plainImage(src) {
+ var img = newElement('img');
+ img.src = src;
+ img.name = src;
+ img.style.display = "block";
+ return img;
+}
+
+function fittedImage(w, h, src) {
+ var e = newElement('div');
+ e.style.position = "relative";
+ e.style.overflow = "hidden";
+
+ var img = newElement('img');
+ img.onload = function() {
+ img.style.position = 'absolute';
+ img.style.margin = 'auto';
+
+ var sw = w, sh = h;
+ if (w / h > this.width / this.height) {
+ sh = Math.round(this.height * w / this.width);
+ } else {
+ sw = Math.round(this.width * h / this.height);
+ }
+ img.style.width = sw + 'px';
+ img.style.height = sh + 'px';
+ img.style.left = ((w - sw) / 2) + 'px';
+ img.style.top = ((h - sh) / 2) + 'px';
+ };
+ img.src = src;
+ img.name = src;
+ e.appendChild(img);
+ return e;
+}
+
+function croppedImage(elem, w, h, src) {
+ var pos = elem._0._0;
+ var e = newElement('div');
+ e.style.position = "relative";
+ e.style.overflow = "hidden";
+
+ var img = newElement('img');
+ img.onload = function() {
+ img.style.position = 'absolute';
+ img.style.margin = 'auto';
+ var sw = w / elem._1, sh = h / elem._2;
+ img.style.width = ((this.width * sw)|0) + 'px';
+ img.style.height = ((this.height * sh)|0) + 'px';
+ img.style.left = ((- pos._0 * sw)|0) + 'px';
+ img.style.top = ((- pos._1 * sh)|0) + 'px';
+ };
+ img.src = src;
+ img.name = src;
+ e.appendChild(img);
+ return e;
+}
+
+function goIn(e) { e.style.position = 'absolute'; return e; }
+function goDown(e) { return e }
+function goRight(e) { e.style.styleFloat = e.style.cssFloat = "left"; return e; }
+function flowWith(f, array) {
+ var container = newElement('div');
+ for (var i = array.length; i--; ) {
+ container.appendChild(f(render(array[i])));
+ }
+ return container;
+}
+
+function flow(dir,elist) {
+ var array = fromList(elist);
+ switch(dir.ctor) {
+ case "DDown": array.reverse();
+ case "DUp": return flowWith(goDown,array);
+ case "DRight": array.reverse();
+ case "DLeft": return flowWith(goRight,array);
+ case "DOut": array.reverse();
+ case "DIn": return flowWith(goIn,array);
+ }
+}
+
+function toPos(pos) {
+ switch(pos.ctor) {
+ case "Absolute": return pos._0 + "px";
+ case "Relative": return (pos._0 * 100) + "%";
+ }
+}
+
+function setPos(pos,w,h,e) {
+ e.style.position = 'absolute';
+ e.style.margin = 'auto';
+ var transform = '';
+ switch(pos.horizontal.ctor) {
+ case 'P': e.style.right = toPos(pos.x); break;
+ case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) ';
+ case 'N': e.style.left = toPos(pos.x); break;
+ }
+ switch(pos.vertical.ctor) {
+ case 'N': e.style.bottom = toPos(pos.y); break;
+ case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)';
+ case 'P': e.style.top = toPos(pos.y); break;
+ }
+ if (transform !== '') addTransform(e.style, transform);
+ return e;
+}
+
+function container(pos,elem) {
+ var e = render(elem);
+ setPos(pos, elem.props.width, elem.props.height, e);
+ var div = newElement('div');
+ div.style.position = 'relative';
+ div.style.overflow = 'hidden';
+ div.appendChild(e);
+ return div;
+}
+
+function rawHtml(html) {
+ var e = newElement('div');
+ e.innerHTML = html;
+ return e;
+}
+
+function render(elem) { return setProps(elem.props, makeElement(elem)); }
+function makeElement(e) {
+ var elem = e.element;
+ switch(elem.ctor) {
+ case 'Image': return image(e.props, elem);
+ case 'Flow': return flow(elem._0, elem._1);
+ case 'Container': return container(elem._0, elem._1);
+ case 'Spacer': return newElement('div');
+ case 'RawHtml': return rawHtml(elem._0);
+ case 'Custom': return elem.render(elem.model);
+ }
+}
+
+function update(node, curr, next) {
+ if (node.tagName === 'A') { node = node.firstChild; }
+ if (curr.props.id === next.props.id) return updateProps(node, curr, next);
+ if (curr.element.ctor !== next.element.ctor) {
+ node.parentNode.replaceChild(render(next),node);
+ return true;
+ }
+ var nextE = next.element, currE = curr.element;
+ switch(nextE.ctor) {
+ case "Spacer": break;
+ case "RawHtml":
+ if (nextE._0 !== currE._0) node.innerHTML = nextE._0;
+ break;
+ case "Image":
+ if (nextE._0.ctor === 'Plain') {
+ if (nextE._3 !== currE._3) node.src = nextE._3;
+ } else if (!eq(nextE,currE) ||
+ next.props.width !== curr.props.width ||
+ next.props.height !== curr.props.height) {
+ node.parentNode.replaceChild(render(next),node);
+ return true;
+ }
+ break;
+ case "Flow":
+ var arr = fromList(nextE._1);
+ for (var i = arr.length; i--; ) { arr[i] = arr[i].element.ctor; }
+ if (nextE._0.ctor !== currE._0.ctor) {
+ node.parentNode.replaceChild(render(next),node);
+ return true;
+ }
+ var nexts = fromList(nextE._1);
+ var kids = node.childNodes;
+ if (nexts.length !== kids.length) {
+ node.parentNode.replaceChild(render(next),node);
+ return true;
+ }
+ var currs = fromList(currE._1);
+ var goDir = function(x) { return x; };
+ switch(nextE._0.ctor) {
+ case "DDown": case "DUp": goDir = goDown; break;
+ case "DRight": case "DLeft": goDir = goRight; break;
+ case "DOut": case "DIn": goDir = goIn; break;
+ }
+ for (var i = kids.length; i-- ;) {
+ update(kids[i],currs[i],nexts[i]);
+ goDir(kids[i]);
+ }
+ break;
+ case "Container":
+ var inner = node.firstChild;
+ if (!update(inner, currE._1, nextE._1)) {
+ if (nextE._0.horizontal.ctor !== currE._0.horizontal.ctor) {
+ inner.style.left = inner.style.right = 'none';
+ removeTransform(inner.style);
+ }
+ if (nextE._0.vertical.ctor !== currE._0.vertical.ctor) {
+ inner.style.top = inner.style.bottom = 'none';
+ removeTransform(inner.style);
+ }
+ }
+ setPos(nextE._0, nextE._1.props.width, nextE._1.props.height, inner);
+ break;
+ case "Custom":
+ if (currE.type === nextE.type) {
+ var done = nextE.update(node, currE.model, nextE.model);
+ if (done) return;
+ } else {
+ return node.parentNode.replaceChild(render(next), node);
+ }
+ }
+ updateProps(node, curr, next);
+}
+
+function updateProps(node, curr, next) {
+ var props = next.props, currP = curr.props, e = node;
+ if (props.width !== currP.width) e.style.width = (props.width |0) + 'px';
+ if (props.height !== currP.height) e.style.height = (props.height|0) + 'px';
+ if (props.opacity !== 1 && props.opacity !== currP.opacity) {
+ e.style.opacity = props.opacity;
+ }
+ var nextColor = (props.color.ctor === 'Just' ?
+ extract(props.color._0) : 'transparent');
+ if (e.style.backgroundColor !== nextColor) {
+ e.style.backgroundColor = nextColor;
+ }
+ if (props.tag !== currP.tag) { e.id = props.tag; }
+ if (props.href !== currP.href) {
+ if (currP.href === '') {
+ var a = newElement('a');
+ a.href = props.href;
+ a.appendChild(e);
+ e.parentNode.replaceChild(a,e);
+ } else {
+ node.parentNode.href = props.href;
+ }
+ }
+}
+
+return { render:render, update:update };
+
+};
\ No newline at end of file
diff --git a/runtime/Render/Utils.js b/runtime/Render/Utils.js
new file mode 100644
index 0000000..aa4a6cf
--- /dev/null
+++ b/runtime/Render/Utils.js
@@ -0,0 +1,49 @@
+
+ElmRuntime.Render.Utils = function() {
+'use strict';
+
+function newElement(elementType) {
+ var e = document.createElement(elementType);
+ e.style.padding = "0";
+ e.style.margin = "0";
+ return e;
+}
+
+function addTo(container, elem) {
+ container.appendChild(elem);
+}
+
+function extract(c) {
+ if (c._3 === 1) { return 'rgb(' + c._0 + ',' + c._1 + ',' + c._2 + ')'; }
+ return 'rgba(' + c._0 + ',' + c._1 + ',' + c._2 + ',' + c._3 + ')';
+}
+
+function addTransform(style, trans) {
+ style.transform = trans;
+ style.msTransform = trans;
+ style.MozTransform = trans;
+ style.webkitTransform = trans;
+ style.OTransform = trans;
+}
+
+function removeTransform(style) {
+ style.transform = 'none';
+ style.msTransform = 'none';
+ style.MozTransform = 'none';
+ style.webkitTransform = 'none';
+ style.OTransform = 'none';
+}
+
+var List = Elm.Native.List({});
+
+return {addTo:addTo,
+ newElement:newElement,
+ extract : extract,
+ fromList: List.toArray,
+ fromString: function(s) { return List.toArray(s).join(''); },
+ toString: List.fromArray,
+ eq: Elm.Native.Utils({}).eq,
+ addTransform: addTransform,
+ removeTransform: removeTransform
+ };
+};
diff --git a/runtime/Utils.js b/runtime/Utils.js
new file mode 100644
index 0000000..fa44af2
--- /dev/null
+++ b/runtime/Utils.js
@@ -0,0 +1,53 @@
+
+(function() {
+'use strict';
+
+ElmRuntime.Display = { FULLSCREEN: 0, COMPONENT: 1, NONE: 2 };
+
+ElmRuntime.counter = 0;
+ElmRuntime.guid = function() { return ElmRuntime.counter++; }
+
+ElmRuntime.use = function(M) {
+ if (typeof M === 'function') M = M();
+ return M;
+};
+
+function isAlive(input) {
+ if (!('defaultNumberOfKids' in input)) return true;
+ var len = input.kids.length;
+ if (len === 0) return false;
+ if (len > input.defaultNumberOfKids) return true;
+ var alive = false;
+ for (var i = len; i--; ) {
+ alive = alive || isAlive(input.kids[i]);
+ }
+ return alive;
+}
+
+ElmRuntime.filterDeadInputs = function(inputs) {
+ var temp = [];
+ for (var i = inputs.length; i--; ) {
+ if (isAlive(inputs[i])) temp.push(inputs[i]);
+ }
+ return temp;
+};
+
+// define the draw function
+var vendors = ['ms', 'moz', 'webkit', 'o'];
+for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
+ window.requestAnimationFrame = window[vendors[i]+'RequestAnimationFrame'];
+ window.cancelAnimationFrame = window[vendors[i]+'CancelAnimationFrame'] ||
+ window[vendors[i]+'CancelRequestAnimationFrame'];
+}
+
+if (window.requestAnimationFrame && window.cancelAnimationFrame) {
+ var previous = 0;
+ ElmRuntime.draw = function(callback) {
+ window.cancelAnimationFrame(previous);
+ previous = window.requestAnimationFrame(callback);
+ };
+} else {
+ ElmRuntime.draw = function(callback) { callback(); };
+}
+
+}());
diff --git a/elm/LICENSE b/server/LICENSE
similarity index 100%
rename from elm/LICENSE
rename to server/LICENSE
diff --git a/elm-server/Server.hs b/server/Server.hs
similarity index 93%
rename from elm-server/Server.hs
rename to server/Server.hs
index 776b151..72fcf7c 100644
--- a/elm-server/Server.hs
+++ b/server/Server.hs
@@ -16,7 +16,8 @@ runtime = "/elm-" ++ showVersion version ++ ".js"
serve :: String -> IO ()
serve libLoc = do
- putStrLn ("Elm Server " ++ showVersion version ++ ": running at ")
+ putStrLn ("Elm Server " ++ showVersion version ++
+ ": running at ")
putStrLn "Just refresh a page to recompile it!"
simpleHTTP nullConf $ do
_ <- compressedResponseFilter
@@ -43,7 +44,7 @@ main = getArgs >>= parse
parse :: [String] -> IO ()
parse ("--help":_) = putStrLn usage
parse ("--version":_) = putStrLn ("The Elm Server " ++ showVersion version)
-parse [] = serve =<< Elm.runtimeLocation
+parse [] = serve =<< Elm.runtime
parse [arg]
| "--runtime-location=" `isPrefixOf` arg =
serve . tail $ dropWhile (/='=') arg
diff --git a/elm-server/Setup.hs b/server/Setup.hs
similarity index 100%
rename from elm-server/Setup.hs
rename to server/Setup.hs
diff --git a/elm-server/elm-server.cabal b/server/elm-server.cabal
similarity index 94%
rename from elm-server/elm-server.cabal
rename to server/elm-server.cabal
index a4f85e2..68c4568 100644
--- a/elm-server/elm-server.cabal
+++ b/server/elm-server.cabal
@@ -1,5 +1,5 @@
Name: elm-server
-Version: 0.7
+Version: 0.8
Synopsis: The Elm language server.
Description: This package provides a standalone, Happstack-based Elm server.
@@ -35,4 +35,4 @@ Executable elm-server
happstack-server == 7.1.1 || == 7.1.7 || == 7.0.2,
deepseq,
filepath,
- Elm >= 0.7
+ Elm >= 0.8