OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 /** | |
6 * Wraps a callback with translations of mouse events to touch events. Use | |
7 * this function to invoke your callback that expects touch events after | |
8 * touch events are created from the actual mouse events. | |
9 */ | |
10 EventListener mouseToTouchCallback(EventListener callback) { | |
11 return (MouseEvent e) { | |
12 var touches = <Touch>[]; | |
13 var targetTouches = <Touch>[]; | |
14 var changedTouches = <Touch>[]; | |
15 final mockTouch = new MockTouch(e); | |
16 final mockTouchList = <Touch>[mockTouch]; | |
17 if (e.type == 'mouseup') { | |
18 changedTouches = mockTouchList; | |
19 } else { | |
20 touches = mockTouchList; | |
21 targetTouches = mockTouchList; | |
22 } | |
23 callback(new MockTouchEvent(e, touches, targetTouches, changedTouches)); | |
24 // Required to prevent spurious selection changes while tracking touches | |
25 // on devices that don't support touch events. | |
26 e.preventDefault(); | |
27 }; | |
28 } | |
29 | |
30 /** Helper method to attach event listeners to a [node]. */ | |
31 void _addEventListeners(Element node, | |
32 EventListener onStart, EventListener onMove, EventListener onEnd, | |
33 EventListener onCancel, [bool capture = false]) { | |
34 | |
35 Function removeListeners; | |
36 | |
37 onEndWrapper(e) { | |
38 removeListeners(); | |
39 return onEnd(e); | |
40 } | |
41 | |
42 onLeaveWrapper(e) { | |
43 removeListeners(); | |
44 return onEnd(e); | |
45 } | |
46 | |
47 onCancelWrapper(e) { | |
48 removeListeners(); | |
49 return onCancel(e); | |
50 } | |
51 | |
52 if (Device.supportsTouch) { | |
53 removeListeners = () { | |
54 document.on.touchMove.remove(onMove, capture); | |
55 document.on.touchEnd.remove(onEndWrapper, capture); | |
56 document.on.touchLeave.remove(onLeaveWrapper, capture); | |
57 document.on.touchCancel.remove(onCancelWrapper, capture); | |
58 }; | |
59 | |
60 node.on.touchStart.add((e) { | |
61 document.on.touchMove.add(onMove, capture); | |
62 document.on.touchEnd.add(onEndWrapper, capture); | |
63 document.on.touchLeave.add(onLeaveWrapper, capture); | |
64 document.on.touchCancel.add(onCancelWrapper, capture); | |
65 return onStart(e); | |
66 }, capture); | |
67 } else { | |
68 onStart = mouseToTouchCallback(onStart); | |
69 onMove = mouseToTouchCallback(onMove); | |
70 onEnd = mouseToTouchCallback(onEnd); | |
71 // onLeave will never be called if the device does not support touches. | |
72 | |
73 removeListeners = () { | |
74 document.on.mouseMove.remove(onMove, capture); | |
75 document.on.mouseUp.remove(onEndWrapper, capture); | |
76 document.on.touchCancel.remove(onCancelWrapper, capture); | |
77 }; | |
78 | |
79 node.on.mouseDown.add((e) { | |
80 document.on.mouseMove.add(onMove, capture); | |
81 document.on.mouseUp.add(onEndWrapper, capture); | |
82 document.on.touchCancel.add(onCancelWrapper, capture); | |
83 return onStart(e); | |
84 }, capture); | |
85 } | |
86 } | |
87 | |
88 /** | |
89 * Gets whether the given touch event targets the node, or one of the node's | |
90 * children. | |
91 */ | |
92 bool _touchEventTargetsNode(event, Node node) { | |
93 Node target = event.changedTouches[0].target; | |
94 | |
95 // TODO(rnystrom): Move this into Dom. | |
96 // Walk up the parents looking for the node. | |
97 while (target != null) { | |
98 if (target == node) { | |
99 return true; | |
100 } | |
101 target = target.parent; | |
102 } | |
103 | |
104 return false; | |
105 } | |
106 | |
107 interface Touchable { | |
108 /** | |
109 * Provide the HTML element that should respond to touch events. | |
110 */ | |
111 Element getElement(); | |
112 | |
113 /** | |
114 * The object has received a touchend event. | |
115 */ | |
116 void onTouchEnd(); | |
117 | |
118 /** | |
119 * The object has received a touchstart event. | |
120 * Returns return true if you want to allow a drag sequence to begin, | |
121 * false you want to disable dragging for the duration of this touch. | |
122 */ | |
123 bool onTouchStart(TouchEvent e); | |
124 } | |
125 | |
126 interface Draggable extends Touchable { | |
127 /** | |
128 * The object's drag sequence is now complete. | |
129 */ | |
130 void onDragEnd(); | |
131 | |
132 /** | |
133 * The object has been dragged to a new position. | |
134 */ | |
135 void onDragMove(); | |
136 | |
137 /** | |
138 * The object has started dragging. | |
139 * Returns true to allow a drag sequence to begin (custom behavior), | |
140 * false to disable dragging for this touch duration (allow native scrolling). | |
141 */ | |
142 bool onDragStart(TouchEvent e); | |
143 | |
144 bool get verticalEnabled(); | |
145 bool get horizontalEnabled(); | |
146 } | |
147 | |
148 class MockTouch implements Touch { | |
149 MouseEvent wrapped; | |
150 | |
151 MockTouch(MouseEvent this.wrapped) {} | |
152 | |
153 int get clientX() => wrapped.clientX; | |
154 | |
155 int get clientY() => wrapped.clientY; | |
156 | |
157 int get identifier() => 0; | |
158 | |
159 int get pageX() => wrapped.pageX; | |
160 | |
161 int get pageY() => wrapped.pageY; | |
162 | |
163 int get screenX() => wrapped.screenX; | |
164 | |
165 int get screenY() {return wrapped.screenY; } | |
166 | |
167 EventTarget get target() => wrapped.target; | |
168 | |
169 num get webkitForce() { throw new NotImplementedException(); } | |
170 int get webkitRadiusX() { throw new NotImplementedException(); } | |
171 int get webkitRadiusY() { throw new NotImplementedException(); } | |
172 num get webkitRotationAngle() { throw new NotImplementedException(); } | |
173 } | |
174 | |
175 class MockTouchEvent implements TouchEvent { | |
176 MouseEvent wrapped; | |
177 // TODO(jacobr): these are currently Lists instead of a TouchList. | |
178 final List<Touch> touches; | |
179 final List<Touch> targetTouches; | |
180 final List<Touch> changedTouches; | |
181 MockTouchEvent(MouseEvent this.wrapped, List<Touch> this.touches, | |
182 List<Touch> this.targetTouches, | |
183 List<Touch> this.changedTouches) {} | |
184 | |
185 bool get bubbles() => wrapped.bubbles; | |
186 | |
187 bool get cancelBubble() => wrapped.cancelBubble; | |
188 | |
189 void set cancelBubble(bool value) { wrapped.cancelBubble = value; } | |
190 | |
191 bool get cancelable() => wrapped.cancelable; | |
192 | |
193 EventTarget get currentTarget() => wrapped.currentTarget; | |
194 | |
195 bool get defaultPrevented() => wrapped.defaultPrevented; | |
196 | |
197 int get eventPhase() => wrapped.eventPhase; | |
198 | |
199 void set returnValue(bool value) { wrapped.returnValue = value; } | |
200 | |
201 bool get returnValue() => wrapped.returnValue; | |
202 | |
203 EventTarget get srcElement() => wrapped.srcElement; | |
204 | |
205 EventTarget get target() => wrapped.target; | |
206 | |
207 int get timeStamp() => wrapped.timeStamp; | |
208 | |
209 String get type() => wrapped.type; | |
210 | |
211 void preventDefault() { wrapped.preventDefault(); } | |
212 | |
213 void stopImmediatePropagation() { wrapped.stopImmediatePropagation(); } | |
214 | |
215 void stopPropagation() { wrapped.stopPropagation(); } | |
216 | |
217 int get charCode() => wrapped.charCode; | |
218 | |
219 int get detail() => wrapped.detail; | |
220 | |
221 int get keyCode() => wrapped.keyCode; | |
222 | |
223 int get layerX() => wrapped.layerX; | |
224 | |
225 int get layerY() => wrapped.layerY; | |
226 | |
227 int get pageX() => wrapped.pageX; | |
228 | |
229 int get pageY() => wrapped.pageY; | |
230 | |
231 Window get view() => wrapped.view; | |
232 | |
233 int get which() => wrapped.which; | |
234 | |
235 bool get altKey() => wrapped.altKey; | |
236 | |
237 bool get ctrlKey() => wrapped.ctrlKey; | |
238 | |
239 bool get metaKey() => wrapped.metaKey; | |
240 | |
241 bool get shiftKey() => wrapped.shiftKey; | |
242 } | |
OLD | NEW |