1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<div class="intro">
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith This example shows how you can support a "swipeleft" gesture, built on
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith top of the synthetic "gesturemove" events, which work not only on touch
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith devices, but also on mouse based input devices.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<div class="example newwindow">
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith <a href="swipe-example-content.html" target="_blank" class="button">
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith View Example in New Window
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<h2>Modules Used</h2>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<p>For the example, the two core modules we'll use are:</p>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith <dt>The `event-move` module</dt>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith Provides the `gesturemovestart`, `gesturemove` and `gesturemoveend`
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith low-level gesture events. These events are fired whenever the user
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith performs a move gesture (mouse button/finger down, mouse/finger move,
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith mouse button/finger up) with the mouse or their finger.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith <dt>The `transitions` module</dt>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith Provides transitions support, leveraging CSS transitions under the hood
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith where supported.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<p>The YUI use statement for the example is shown below:</p>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke SmithYUI().use("node-base", "node-event-delegate", "transition", "event-move", function(Y) {
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<h2>Delegating Gesture Move Events</h2>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith The basic idea for the example is to listen for a `gesturemovestart` on a
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith list item, and when we get one, store its position, and then listen for a
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith gesturemoveend. If the gesturemoveend occurs more than X pixels to the left
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith of the start, then we've identified a "swipeleft" gesture. Future versions
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith of the library will package such logic into a higher level gesture event
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith (ala event-flick).
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith For this example, since we're dealing with a list of items, rather than
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith attach individual listeners to each <li> in the list, we use
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `delegate` on the parent <ul> element, which leads to better
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith performance and avoids having to add/remove listeners each time the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith contents of the list change. The `gesturemovestart`, `gesturemove` and
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `gesturemoveend` are synthetic events, and can all be used with `delegate`,
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith just like any DOM event.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith We set up a delegate listener on the <ul> which listens for the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `gesturemovestart` event (`gesturemovestart` abstracts
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `mousedown`/`touchstart` events under the hood). The delegate listener is
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith set up to be notified when the target of the `gesturemovestart` is an
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke SmithY.Node.one("#swipe").delegate("gesturemovestart", function(e) {
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith}, "li", { // filter for "li"
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith preventDefault:true
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith The `gesturemovestart` event supports a configuration object passed as an
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith additional subscription argument, which can be used to set minimum distance
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith and minimum time thresholds at which to fire the start event. The
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith configuration also supports the ability to prevent the default behavior
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith before the minimum time or distance thresholds kick in, which is what we do
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith above by passing `preventDefault:true`.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith The advantage of the gesture synthetic events is that the developer can use
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith the same API without having to worry about whether or not the browser
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith platform is touch based or mouse based.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<h2>Gesture Move End</h2>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith As mentioned above, the `gesturemovestart` listener is notified whenever a
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `mousedown` or `touchstart` is received on a list item. The listener has
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith <dd>The list item targeted.</dd>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith The element clicked on (it may be an element inside the targeted
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith list item, the span for example).
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith The element to which the delegate listener is attached (the ul in
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith The event facade also has the page coordinates for the `mousedown` or
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `touchstart` event. We use the list item's `setData` method, to store the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `pageX` position for the start event, so we can compare it when we get the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `gesturemoveend` event. This way it's stored on the node instance, and we
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith don't need to pass it along separately to the `gesturemoveend` event, or
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith store it globally.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `getData`, `setData` and `clearData` are useful methods to store ad-hoc
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith node centric data.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke SmithY.Node.one("#swipe").delegate("gesturemovestart", function(e) {
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith item.once("gesturemoveend", function(e) {
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith var swipeStart = item.getData("swipeStart"),
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith isSwipeLeft = (swipeStart - swipeEnd) > MIN_SWIPE;
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith if (isSwipeLeft) {
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith item.one(".myapp-delete").removeClass("myapp-hidden");
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith When we get the `gesturemovestart` event, we set up a listener for the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `gesturemoveend` event, so we can determine the end of the gesture, and
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith figure out if the user swiped left. Since we don't want to set up a new
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith listener every time we get a `gesturemovestart` we use `once` to set up the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `gesturemoveend` listener. `once` will detach the listener after it's been
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith invoked. Again, since `gesturemoveend` is a synthetic event, it works with
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `once` just like any other DOM event.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith In the `gesturemoveend` listener we check the page position of the event,
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith and if it's far enough to the left of the start position, we display the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith "Delete" button by removing the hidden class which it contains.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<h2>Transitions</h2>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith To hide and remove the item when the delete button is pressed, we use the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith `transition` method, to animate its opacity and height down to 0. Under the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith hood transition will use CSS transition support where available (WebKit)
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith and set up timer based animation where not (IE). As with the gesture event
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith support, the developer gets to use the same API without having to worry
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith about the browser environment.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smithitem = target.get("parentNode");
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith duration:0.3,
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith}, function() {
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith The second argument to transition above is a callback function, which is
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith invoked when the transition is complete. We use this support to remove the
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith item from the DOM.
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith<h2>Full Code Listing</h2>
350964af8dfc6ab5df9d3fb0f274f7d018986c5bLuke Smith{{>swipe-example-js}}