on 727d708 help sign in
elk/libraries/Native/Utils.js
158 lines 4.4 kB history raw
2Elm.Native.Utils = function(elm) {
3 'use strict';
5 elm.Native = elm.Native || {};
6 if (elm.Native.Utils) return elm.Native.Utils;
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 var EQ = 0, LT = -1, GT = 1, ord = ['EQ','LT','GT'];
23 function compare(x,y) { return { ctor: ord[cmp(x,y)] } }
24 function cmp(x,y) {
25 var ord;
26 if (typeof x !== 'object') return x === y ? EQ : x < y ? LT : GT;
28 if (x.ctor === "::" || x.ctor === "[]") {
29 while (true) {
30 if (x.ctor === "[]" && y.ctor === "[]") return EQ;
31 if (x.ctor !== y.ctor) return x.ctor === '[]' ? LT : GT;
32 ord = cmp(x._0, y._0);
33 if (ord !== EQ) return ord;
34 x = x._1;
35 y = y._1;
36 }
37 }
39 if (x.ctor.slice(0,6) === '_Tuple') {
40 var n = x.ctor.slice(6) - 0;
41 var err = 'cannot compare tuples with more than 6 elements.';
42 if (n === 0) return EQ;
43 if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
44 if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
45 if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
46 if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
47 if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
48 if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
49 if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
50 return EQ;
51 }
52 throw new Error('Comparison error: comparison is only defined on ints, ' +
53 'floats, times, chars, strings, lists of comparable values, ' +
54 'and tuples of comparable values.')
55 }
58 var Tuple0 = { ctor: "_Tuple0" };
59 function Tuple2(x,y) { return { ctor:"_Tuple2", _0:x, _1:y } }
61 var count = 0;
62 function guid(_) { return count++ }
64 function copy(r) {
65 var o = {};
66 for (var i in r) { o[i] = r[i]; }
67 return o;
68 }
70 function remove(x,r) {
71 var o = copy(r);
72 if (x in o._) {
73 o[x] = o._[x][0];
74 o._[x] = o._[x].slice(1);
75 if (o._[x].length === 0) { delete o._[x]; }
76 } else {
77 delete o[x];
78 }
79 return o;
80 }
82 function replace(kvs,r) {
83 var o = copy(r);
84 for (var i = kvs.length; i--; ) {
85 var kvsi = kvs[i];
86 o[kvsi[0]] = kvsi[1];
87 }
88 return o;
89 }
91 function insert(x,v,r) {
92 var o = copy(r);
93 if (x in o) o._[x] = [o[x]].concat(x in o._ ? o._[x].slice(0) : []);
94 o[x] = v;
95 return o;
96 }
98 function max(a,b) { return a > b ? a : b }
99 function min(a,b) { return a < b ? a : b }
101 function mod(a,b) {
102 var r = a % b;
103 var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r+b) : -mod(-a,-b));
105 return m === b ? 0 : m;
106 }
108 function htmlHeight(width, html) {
109 var t = document.createElement('div');
110 t.innerHTML = html;
111 if (width > 0) { t.style.width = width + "px"; }
112 t.style.visibility = "hidden";
113 t.style.styleFloat = "left";
114 t.style.cssFloat = "left";
116 elm.node.appendChild(t);
117 var style = window.getComputedStyle(t, null);
118 var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
119 var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
120 elm.node.removeChild(t);
121 return Tuple2(w,h);
122 }
124 function adjustOffset() {
125 var node = elm.node;
126 var offsetX = 0, offsetY = 0;
127 if (node.offsetParent) {
128 do {
129 offsetX += node.offsetLeft;
130 offsetY += node.offsetTop;
131 } while (node = node.offsetParent);
132 }
133 elm.node.offsetX = offsetX;
134 elm.node.offsetY = offsetY;
135 }
137 if (elm.display === ElmRuntime.Display.COMPONENT) {
138 elm.addListener(elm.inputs, elm.node, 'mouseover', adjustOffset);
139 }
141 return elm.Native.Utils = {
142 eq:eq,
143 cmp:cmp,
144 compare:F2(compare),
145 Tuple0:Tuple0,
146 Tuple2:Tuple2,
147 copy: copy,
148 remove: remove,
149 replace: replace,
150 insert: insert,
151 guid: guid,
152 max : F2(max),
153 min : F2(min),
154 mod : F2(mod),
155 htmlHeight: F2(htmlHeight),
156 toFloat: function(x){return x}
157 };
158};