on b00a8cb help sign in
elk/libraries/Native/Utils.js
231 lines 7.4 kB history raw
1Elm.Native.Utils = {};
2Elm.Native.Utils.make = function(elm) {
4 elm.Native = elm.Native || {};
5 elm.Native.Utils = elm.Native.Utils || {};
6 if (elm.Native.Utils.values) return elm.Native.Utils.values;
8 function eq(x,y) {
9 if (x === y) return true;
10 if (typeof x === "object") {
11 var c = 0;
12 for (var i in x) { ++c; if (!eq(x[i],y[i])) return false; }
13 return c === Object.keys(y).length;
14 }
15 if (typeof x === 'function') {
16 throw new Error('Equality error: general function equality is ' +
17 'undecidable, and therefore, unsupported');
18 }
19 return x === y;
20 }
22 // code in Generate/JavaScript.hs depends on the particular
23 // integer values assigned to LT, EQ, and GT
24 var LT = -1, EQ = 0, GT = 1, ord = ['LT','EQ','GT'];
25 function compare(x,y) { return { ctor: ord[cmp(x,y)+1] } }
26 function cmp(x,y) {
27 var ord;
28 if (typeof x !== 'object' || x instanceof String){
29 return x === y ? EQ : x < y ? LT : GT;
30 }
32 if (x.ctor === "::" || x.ctor === "[]") {
33 while (true) {
34 if (x.ctor === "[]" && y.ctor === "[]") return EQ;
35 if (x.ctor !== y.ctor) return x.ctor === '[]' ? LT : GT;
36 ord = cmp(x._0, y._0);
37 if (ord !== EQ) return ord;
38 x = x._1;
39 y = y._1;
40 }
41 }
43 if (x.ctor.slice(0,6) === '_Tuple') {
44 var n = x.ctor.slice(6) - 0;
45 var err = 'cannot compare tuples with more than 6 elements.';
46 if (n === 0) return EQ;
47 if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
48 if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
49 if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
50 if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
51 if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
52 if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
53 if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
54 return EQ;
55 }
56 throw new Error('Comparison error: comparison is only defined on ints, ' +
57 'floats, times, chars, strings, lists of comparable values, ' +
58 'and tuples of comparable values.')
59 }
62 var Tuple0 = { ctor: "_Tuple0" };
63 function Tuple2(x,y) { return { ctor:"_Tuple2", _0:x, _1:y } }
65 function chr(c) {
66 var x = new String(c);
67 x.isChar = true;
68 return x;
69 }
71 function txt(str) {
72 var t = new String(str);
73 t.text = true;
74 return t;
75 }
77 function makeText(style, text) {
78 var style = style;
79 var line = '';
80 var href = '';
81 while (true) {
82 if (text.line) {
83 line += text.line;
84 text = text.text;
85 continue;
86 }
87 if (text.style) {
88 style += text.style;
89 text = text.text;
90 continue;
91 }
92 if (text.href) {
93 href = text.href;
94 text = text.text;
95 continue;
96 }
97 if (href) text = '<a href="' + href + '">' + text + '</a>';
98 if (line) style += 'text-decoration:' + line + ';';
99 if (style) text = '<span style="' + style + '">' + text + '</span>';
100 return text;
101 }
102 }
104 var count = 0;
105 function guid(_) { return count++ }
107 function copy(r) {
108 var o = {};
109 for (var i in r) { o[i] = r[i]; }
110 return o;
111 }
113 function remove(x,r) {
114 var o = copy(r);
115 if (x in o._) {
116 o[x] = o._[x][0];
117 o._[x] = o._[x].slice(1);
118 if (o._[x].length === 0) { delete o._[x]; }
119 } else {
120 delete o[x];
121 }
122 return o;
123 }
125 function replace(kvs,r) {
126 var o = copy(r);
127 for (var i = kvs.length; i--; ) {
128 var kvsi = kvs[i];
129 o[kvsi[0]] = kvsi[1];
130 }
131 return o;
132 }
134 function insert(x,v,r) {
135 var o = copy(r);
136 if (x in o) o._[x] = [o[x]].concat(x in o._ ? o._[x].slice(0) : []);
137 o[x] = v;
138 return o;
139 }
141 function max(a,b) { return a > b ? a : b }
142 function min(a,b) { return a < b ? a : b }
144 function mod(a,b) {
145 if (b === 0) {
146 throw new Error("Cannot perform mod 0. Division by zero error.");
147 }
148 var r = a % b;
149 var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r+b) : -mod(-a,-b));
151 return m === b ? 0 : m;
152 }
154 function htmlHeight(width, rawHtml) {
155 // create dummy node
156 var html = rawHtml.html;
157 var t = document.createElement('div');
158 t.innerHTML = html;
159 if (width > 0) { t.style.width = width + "px"; }
160 t.style.visibility = "hidden";
161 t.style.styleFloat = "left";
162 t.style.cssFloat = "left";
164 document.body.appendChild(t);
166 // insert interpolated values
167 var args = rawHtml.args;
168 var guid = rawHtml.guid;
169 for (var i = args.length; i--; ) {
170 var arg = args[i];
171 var span = document.getElementById('md-' + guid + '-' + i);
172 if (arg.isElement) {
173 span.style.width = arg.props.width + 'px';
174 span.style.height = arg.props.height + 'px';
175 } else {
176 span.innerHTML = arg;
177 }
178 }
180 // get dimensions
181 var style = window.getComputedStyle(t, null);
182 var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
183 var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
184 document.body.removeChild(t);
185 return Tuple2(w,h);
186 }
188 function getXY(e) {
189 var posx = 0;
190 var posy = 0;
191 if (e.pageX || e.pageY) {
192 posx = e.pageX;
193 posy = e.pageY;
194 } else if (e.clientX || e.clientY) {
195 posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
196 posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
197 }
199 if (elm.display === ElmRuntime.Display.COMPONENT) {
200 var rect = elm.node.getBoundingClientRect();
201 var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft;
202 var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop;
203 // TODO: figure out if there is a way to avoid rounding here
204 posx = posx - Math.round(relx) - elm.node.clientLeft;
205 posy = posy - Math.round(rely) - elm.node.clientTop;
206 }
207 return Tuple2(posx, posy);
208 }
210 return elm.Native.Utils.values = {
211 eq:eq,
212 cmp:cmp,
213 compare:F2(compare),
214 Tuple0:Tuple0,
215 Tuple2:Tuple2,
216 chr:chr,
217 txt:txt,
218 makeText:makeText,
219 copy: copy,
220 remove: remove,
221 replace: replace,
222 insert: insert,
223 guid: guid,
224 max : F2(max),
225 min : F2(min),
226 mod : F2(mod),
227 htmlHeight: F2(htmlHeight),
228 getXY: getXY,
229 toFloat: function(x) { return +x; }
230 };
231};