on 63243ca help sign in
152 lines 4.4 kB history raw
1Elm.Native.Touch = {};
2Elm.Native.Touch.make = function(elm) {
4 elm.Native = elm.Native || {};
5 elm.Native.Touch = elm.Native.Touch || {};
6 if (elm.Native.Touch.values) return elm.Native.Touch.values;
8 var Signal = Elm.Signal.make(elm);
9 var JS = Elm.JavaScript.make(elm);
10 var Utils = Elm.Native.Utils.make(elm);
12 function Dict() {
13 this.keys = [];
14 this.values = [];
16 this.insert = function(key,value) {
17 this.keys.push(key);
18 this.values.push(value);
19 };
20 this.lookup = function(key) {
21 var i = this.keys.indexOf(key)
22 return i >= 0 ? this.values[i] : {x:0,y:0,t:0};
23 };
24 this.remove = function(key) {
25 var i = this.keys.indexOf(key);
26 if (i < 0) return;
27 var t = this.values[i];
28 this.keys.splice(i,1);
29 this.values.splice(i,1);
30 return t;
31 };
32 this.clear = function() {
33 this.keys = [];
34 this.values = [];
35 };
36 }
38 var root = Signal.constant([]),
39 tapTime = 500,
40 hasTap = false,
41 tap = {_:{},x:0,y:0},
42 dict = new Dict();
44 function touch(t) {
45 var r = dict.lookup(t.identifier);
46 var point = Utils.getXY(t);
47 return {_ : {},
48 id: t.identifier,
49 x : point._0,
50 y : point._1,
51 x0: r.x,
52 y0: r.y,
53 t0: r.t
54 };
55 }
57 var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
59 function start(e) {
60 var point = Utils.getXY(e);
61 dict.insert(e.identifier,
62 {x: point._0,
63 y: point._1,
64 t: Date.now()});
65 }
66 function end(e) {
67 var t = dict.remove(e.identifier);
68 if (Date.now() - t.t < tapTime) {
69 hasTap = true;
70 tap = {_:{}, x:t.x, y:t.y};
71 }
72 }
74 function listen(name, f) {
75 function update(e) {
76 for (var i = e.changedTouches.length; i--; ) { f(e.changedTouches[i]); }
77 var ts = new Array(e.touches.length);
78 for (var i = e.touches.length; i--; ) { ts[i] = touch(e.touches[i]); }
79 elm.notify(root.id, ts);
80 e.preventDefault();
81 }
82 elm.addListener([root.id], node, name, update);
83 }
85 listen("touchstart", start);
86 listen("touchmove", function(_){});
87 listen("touchend", end);
88 listen("touchcancel", end);
89 listen("touchleave", end);
91 var mouseID = -1;
92 function move(e) {
93 var point = Utils.getXY(e);
94 for (var i = root.value.length; i--; ) {
95 if (root.value[i].id === mouseID) {
96 root.value[i].x = point._0;
97 root.value[i].y = point._1;
98 elm.notify(root.id, root.value);
99 break;
100 }
101 }
102 }
103 elm.addListener([root.id], node, "mousedown", function down(e) {
104 node.addEventListener("mousemove", move);
105 e.identifier = mouseID;
106 start(e);
107 root.value.push(touch(e));
108 elm.notify(root.id, root.value);
109 });
110 elm.addListener([root.id], node, "mouseup", function up(e) {
111 node.removeEventListener("mousemove", move);
112 e.identifier = mouseID;
113 end(e);
114 for (var i = root.value.length; i--; ) {
115 if (root.value[i].id === mouseID) {
116 root.value.splice(i, 1);
117 --mouseID;
118 break;
119 }
120 }
121 elm.notify(root.id, root.value);
122 });
123 elm.addListener([root.id], node, "blur", function blur(e) {
124 node.removeEventListener("mousemove", move);
125 if (root.value.length > 0) {
126 elm.notify(root.id, []);
127 --mouseID;
128 }
129 dict.clear();
130 });
132 function dependency(f) {
133 var sig = A2( Signal.lift, f, root );
134 root.defaultNumberOfKids += 1;
135 sig.defaultNumberOfKids = 0;
136 return sig;
137 }
139 var touches = dependency(JS.toList);
141 var taps = function() {
142 var sig = dependency(function(_) { return tap; });
143 sig.defaultNumberOfKids = 1;
144 function pred(_) { var b = hasTap; hasTap = false; return b; }
145 var sig2 = A3( Signal.keepIf, pred, {_:{},x:0,y:0}, sig);
146 sig2.defaultNumberOfKids = 0;
147 return sig2;
148 }();
150 return elm.Native.Touch.values = { touches: touches, taps: taps };
152};