sproutcore 1.11.0.rc3 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +6 -14
- data/CHANGELOG +5 -0
- data/VERSION.yml +1 -1
- data/lib/frameworks/sproutcore/Buildfile +3 -2
- data/lib/frameworks/sproutcore/CHANGELOG.md +59 -10
- data/lib/frameworks/sproutcore/apps/showcase/resources/main_page.js +1 -0
- data/lib/frameworks/sproutcore/apps/showcase/resources/stylesheet.css +9 -4
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/manipulation.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +0 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +10 -45
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/selection_set.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/touch.js +76 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/{touch.js → touch_test.js} +64 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/append_remove.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/design_mode_test.js +61 -24
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/createChildViews.js +1 -2
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/destroy.js +0 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/{layoutStyle.js → layout_style_test.js} +4 -4
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout_test.js +602 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/viewDidResize.js +0 -23
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +18 -17
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +5 -5
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/design_mode.js +64 -24
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +904 -871
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +1 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +40 -24
- data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +5 -5
- data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +14 -14
- data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +36 -33
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/autonomous_dataSourceCallbacks.js +6 -6
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitChangesFromNestedStore.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataSourceCallbacks.js +7 -7
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/destroyRecord.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/recordDidChange.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/retrieveRecord.js +4 -4
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +11 -11
- data/lib/frameworks/sproutcore/frameworks/designer/coders/object.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +30 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +12 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +5 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroller_view.js +0 -36
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll_view.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/gestures/pinch_gesture.js +286 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/gestures/swipe_gesture.js +449 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/gestures/tap_gesture.js +259 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/gesturable.js +218 -30
- data/lib/frameworks/sproutcore/frameworks/foundation/system/gesture.js +259 -158
- data/lib/frameworks/sproutcore/frameworks/foundation/system/string.js +58 -50
- data/lib/frameworks/sproutcore/frameworks/foundation/system/utils/string_measurement.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/gestures/pinch_gesture_test.js +321 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/gestures/swipe_gesture_test.js +154 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/gestures/tap_gesture_test.js +55 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/gesturable_test.js +233 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/staticLayout.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/system/gesture_test.js +254 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/views/container.js +1 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/legacy/object_keys_polyfill.js +51 -0
- data/lib/frameworks/sproutcore/frameworks/{core_foundation/system/req_anim_frame.js → legacy/request_animation_frame_polyfill.js} +10 -3
- data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +19 -25
- data/lib/frameworks/sproutcore/frameworks/media/views/controls.js +7 -7
- data/lib/frameworks/sproutcore/frameworks/media/views/mini_controls.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/media/views/simple_controls.js +9 -9
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/insertAt.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/removeAt.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/ext/array.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/array.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/freezable.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +66 -5
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/tree.js +44 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/private/observer_queue.js +4 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +0 -25
- data/lib/frameworks/sproutcore/frameworks/runtime/system/enumerator.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/system/error.js +67 -15
- data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +6 -11
- data/lib/frameworks/sproutcore/frameworks/runtime/system/set.js +6 -6
- data/lib/frameworks/sproutcore/frameworks/runtime/system/string.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/{observable.js → observable_test.js} +110 -16
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/error.js +21 -0
- data/lib/frameworks/sproutcore/frameworks/statechart/system/statechart.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/template_view/ext/handlebars.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/testing/system/plan.js +1 -1
- data/lib/sproutcore/render_engines/haml.rb +1 -1
- metadata +610 -604
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +0 -210
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +0 -275
- data/lib/frameworks/sproutcore/frameworks/foundation/gestures/pinch.js +0 -119
- data/lib/frameworks/sproutcore/frameworks/foundation/gestures/swipe.js +0 -234
- data/lib/frameworks/sproutcore/frameworks/foundation/gestures/tap.js +0 -157
@@ -0,0 +1,259 @@
|
|
1
|
+
// ==========================================================================
|
2
|
+
// Project: SproutCore - JavaScript Application Framework
|
3
|
+
// Copyright: ©2010 Strobe Inc. All rights reserved.
|
4
|
+
// Author: Peter Wagenet
|
5
|
+
// License: Licensed under MIT license (see license.js)
|
6
|
+
// ==========================================================================
|
7
|
+
|
8
|
+
sc_require("system/gesture");
|
9
|
+
|
10
|
+
/**
|
11
|
+
## What is a "tap"?
|
12
|
+
|
13
|
+
A tap is a touch that starts and ends in a short amount of time without moving along either axis.
|
14
|
+
A tap may consist of more than one touch, provided that the touches start and end together. The time
|
15
|
+
allowed for touches to start and end together is defined by `touchUnityDelay`.
|
16
|
+
Again, to be considered a tap, there should be very little movement of any touches on either axis
|
17
|
+
while still touching. The amount of movement allowed is defined by `tapWiggle`.
|
18
|
+
|
19
|
+
@class
|
20
|
+
@extends SC.Gesture
|
21
|
+
*/
|
22
|
+
SC.TapGesture = SC.Gesture.extend(
|
23
|
+
/** @scope SC.TapGesture.prototype */{
|
24
|
+
|
25
|
+
/** @private The time that the first touch started at. */
|
26
|
+
_sc_firstTouchAddedAt: null,
|
27
|
+
|
28
|
+
/** @private The time that the first touch ended at. */
|
29
|
+
_sc_firstTouchEndedAt: null,
|
30
|
+
|
31
|
+
/** @private A flag used to track when the touch was long enough to register tapStart (and tapEnd). */
|
32
|
+
_sc_isTapping: false,
|
33
|
+
|
34
|
+
/** @private The number of touches in the current tap. */
|
35
|
+
_sc_numberOfTouches: 0,
|
36
|
+
|
37
|
+
/** @private A timer started after the first touch starts. */
|
38
|
+
_sc_tapStartTimer: null,
|
39
|
+
|
40
|
+
/**
|
41
|
+
@type String
|
42
|
+
@default "tap"
|
43
|
+
@readOnly
|
44
|
+
*/
|
45
|
+
name: "tap",
|
46
|
+
|
47
|
+
/**
|
48
|
+
The amount of time in milliseconds between when the first touch starts and the last touch ends
|
49
|
+
that should be considered a short enough time to constitute a tap.
|
50
|
+
|
51
|
+
@type Number
|
52
|
+
@default 250
|
53
|
+
*/
|
54
|
+
tapLengthDelay: 250,
|
55
|
+
|
56
|
+
/**
|
57
|
+
The amount of time in milliseconds after the first touch starts at which, *if the tap hasn't
|
58
|
+
ended in that time*, the `tapStart` event should trigger.
|
59
|
+
|
60
|
+
Because taps may be very short or because movement of the touch may invalidate a tap gesture
|
61
|
+
entirely, you generally won't want to update the state of the view immediately when a touch
|
62
|
+
starts.
|
63
|
+
|
64
|
+
@type Number
|
65
|
+
@default 150
|
66
|
+
*/
|
67
|
+
tapStartDelay: 150,
|
68
|
+
|
69
|
+
/**
|
70
|
+
The number of pixels that a touch may move before it will no longer be considered a tap. If any
|
71
|
+
of the touches move more than this amount, the gesture will give up.
|
72
|
+
|
73
|
+
@type Number
|
74
|
+
@default 10
|
75
|
+
*/
|
76
|
+
tapWiggle: 10,
|
77
|
+
|
78
|
+
/**
|
79
|
+
The number of milliseconds that touches must start and end together in in order to be considered a
|
80
|
+
tap. If the touches start too far apart in time or end too far apart in time based on this
|
81
|
+
value, the gesture will give up.
|
82
|
+
|
83
|
+
@type Number
|
84
|
+
@default 75
|
85
|
+
*/
|
86
|
+
touchUnityDelay: 75,
|
87
|
+
|
88
|
+
/** @private Calculates the distance a touch has moved. */
|
89
|
+
_sc_calculateDragDistance: function (touch) {
|
90
|
+
return Math.sqrt(Math.pow(touch.pageX - touch.startX, 2) + Math.pow(touch.pageY - touch.startY, 2));
|
91
|
+
},
|
92
|
+
|
93
|
+
/** @private Cleans up the touch session. */
|
94
|
+
_sc_cleanUpTouchSession: function (wasCancelled) {
|
95
|
+
if (this._sc_isTapping) {
|
96
|
+
// Trigger the gesture, 'tapCancelled'.
|
97
|
+
if (wasCancelled) {
|
98
|
+
this.cancel();
|
99
|
+
|
100
|
+
// Trigger the gesture, 'tapEnd'.
|
101
|
+
} else {
|
102
|
+
this.end();
|
103
|
+
}
|
104
|
+
|
105
|
+
this._sc_isTapping = false;
|
106
|
+
}
|
107
|
+
|
108
|
+
// Clean up.
|
109
|
+
this._sc_tapStartTimer.invalidate();
|
110
|
+
this._sc_numberOfTouches = 0;
|
111
|
+
this._sc_tapStartTimer = this._sc_firstTouchAddedAt = this._sc_firstTouchEndedAt = null;
|
112
|
+
},
|
113
|
+
|
114
|
+
/** @private Triggers the tapStart event. Should *not* be reachable unless the tap is still valid. */
|
115
|
+
_sc_triggerTapStart: function () {
|
116
|
+
// Trigger the gesture, 'tapStart'.
|
117
|
+
this.start();
|
118
|
+
|
119
|
+
this._sc_isTapping = true;
|
120
|
+
},
|
121
|
+
|
122
|
+
/**
|
123
|
+
The tap gesture only remains interested in a touch session as long as none of the touches have
|
124
|
+
started too long after the first touch (value of `touchUnityDelay`). Once any touch has started
|
125
|
+
too late, the tap gesture gives up for the entire touch session and won't attempt to re-engage
|
126
|
+
(i.e. even if an extra touch "taps" cleanly in the same touch session, it won't trigger any
|
127
|
+
further tap callbacks).
|
128
|
+
|
129
|
+
@param {SC.Touch} touch The touch to be added to the session.
|
130
|
+
@param {Array} touchesInSession The touches already in the session.
|
131
|
+
@returns {Boolean} True as long as the new touch doesn't start too late after the first touch.
|
132
|
+
@see SC.Gesture#touchAddedToSession
|
133
|
+
*/
|
134
|
+
touchAddedToSession: function (touch, touchesInSession) {
|
135
|
+
var stillInterestedInSession,
|
136
|
+
delay;
|
137
|
+
|
138
|
+
// If the new touch came in too late after the first touch was added.
|
139
|
+
delay = Date.now() - this._sc_firstTouchAddedAt;
|
140
|
+
stillInterestedInSession = delay < this.get('touchUnityDelay');
|
141
|
+
|
142
|
+
return stillInterestedInSession;
|
143
|
+
},
|
144
|
+
|
145
|
+
/**
|
146
|
+
If a touch cancels, the tap doesn't care and remains interested.
|
147
|
+
|
148
|
+
@param {SC.Touch} touch The touch to be removed from the session.
|
149
|
+
@param {Array} touchesInSession The touches in the session.
|
150
|
+
@returns {Boolean} True
|
151
|
+
@see SC.Gesture#touchCancelledInSession
|
152
|
+
*/
|
153
|
+
touchCancelledInSession: function (touch, touchesInSession) {
|
154
|
+
return true;
|
155
|
+
},
|
156
|
+
|
157
|
+
/**
|
158
|
+
The tap gesture only remains interested in a touch session as long as none of the touches have
|
159
|
+
ended too long after the first touch ends (value of `touchUnityDelay`). Once any touch has ended
|
160
|
+
too late, the tap gesture gives up for the entire touch session and won't attempt to re-engage
|
161
|
+
(i.e. even if an extra touch "taps" cleanly in the same touch session, it won't trigger any
|
162
|
+
further tap callbacks).
|
163
|
+
|
164
|
+
@param {SC.Touch} touch The touch to be removed from the session.
|
165
|
+
@param {Array} touchesInSession The touches in the session.
|
166
|
+
@returns {Boolean} True if it is the first touch to end or a subsequent touch that ends not too long after the first touch ended.
|
167
|
+
@see SC.Gesture#touchEndedInSession
|
168
|
+
*/
|
169
|
+
touchEndedInSession: function (touch, touchesInSession) {
|
170
|
+
var stillInterestedInSession;
|
171
|
+
|
172
|
+
// Increment the number of touches in the tap.
|
173
|
+
this._sc_numberOfTouches += 1;
|
174
|
+
|
175
|
+
// If it's the first touch to end, remain interested unless tapLengthDelay has passed.
|
176
|
+
if (this._sc_firstTouchEndedAt === null) {
|
177
|
+
this._sc_firstTouchEndedAt = Date.now();
|
178
|
+
stillInterestedInSession = this._sc_firstTouchEndedAt - this._sc_firstTouchAddedAt < this.get('tapLengthDelay');
|
179
|
+
|
180
|
+
// If the touch ended too late after the first touch ended, give up entirely.
|
181
|
+
} else {
|
182
|
+
stillInterestedInSession = Date.now() - this._sc_firstTouchEndedAt < this.get('touchUnityDelay');
|
183
|
+
}
|
184
|
+
|
185
|
+
return stillInterestedInSession;
|
186
|
+
},
|
187
|
+
|
188
|
+
/**
|
189
|
+
The tap gesture only remains interested in a touch session as long as none of the touches have
|
190
|
+
moved too far (value of `tapWiggle`). Once any touch has moved too far, the tap gesture gives
|
191
|
+
up for the entire touch session and won't attempt to re-engage (i.e. even if an extra touch
|
192
|
+
"taps" cleanly in the same touch session, it won't trigger any further tap callbacks).
|
193
|
+
|
194
|
+
@param {Array} touchesInSession All touches in the session.
|
195
|
+
@returns {Boolean} True as long as none of the touches have moved too far to be a clean tap.
|
196
|
+
@see SC.Gesture#touchesMovedInSession
|
197
|
+
*/
|
198
|
+
touchesMovedInSession: function (touchesInSession) {
|
199
|
+
var stillInterestedInSession = true;
|
200
|
+
|
201
|
+
for (var i = 0, len = touchesInSession.length; i < len; i++) {
|
202
|
+
var touch = touchesInSession[i],
|
203
|
+
movedTooFar = this._sc_calculateDragDistance(touch) > this.get('tapWiggle');
|
204
|
+
|
205
|
+
// If any touch has gone too far, we don't want to consider any further tap actions for this
|
206
|
+
// session. No need to continue.
|
207
|
+
if (movedTooFar) {
|
208
|
+
stillInterestedInSession = false;
|
209
|
+
break;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
return stillInterestedInSession;
|
214
|
+
},
|
215
|
+
|
216
|
+
/**
|
217
|
+
Cleans up all touch session variables.
|
218
|
+
|
219
|
+
@returns {void}
|
220
|
+
@see SC.Gesture#touchSessionCancelled
|
221
|
+
*/
|
222
|
+
touchSessionCancelled: function () {
|
223
|
+
// Clean up (will fire tapCancelled if _sc_isTapping is true).
|
224
|
+
this._sc_cleanUpTouchSession(true);
|
225
|
+
},
|
226
|
+
|
227
|
+
/**
|
228
|
+
Cleans up all touch session variables and triggers the gesture.
|
229
|
+
|
230
|
+
@returns {void}
|
231
|
+
@see SC.Gesture#touchSessionEnded
|
232
|
+
*/
|
233
|
+
touchSessionEnded: function () {
|
234
|
+
// Trigger the gesture, 'tap'.
|
235
|
+
this.trigger(this._sc_numberOfTouches);
|
236
|
+
|
237
|
+
// Clean up (will fire tapEnd if _sc_isTapping is true).
|
238
|
+
this._sc_cleanUpTouchSession(false);
|
239
|
+
},
|
240
|
+
|
241
|
+
/**
|
242
|
+
Registers when the first touch started.
|
243
|
+
|
244
|
+
@param {SC.Touch} touch The touch that started the session.
|
245
|
+
@returns {void}
|
246
|
+
@see SC.Gesture#touchSessionStarted
|
247
|
+
*/
|
248
|
+
touchSessionStarted: function (touch) {
|
249
|
+
// Initialize.
|
250
|
+
this._sc_firstTouchAddedAt = Date.now();
|
251
|
+
|
252
|
+
this._sc_tapStartTimer = SC.Timer.schedule({
|
253
|
+
target: this,
|
254
|
+
action: this._sc_triggerTapStart,
|
255
|
+
interval: this.get('tapStartDelay')
|
256
|
+
});
|
257
|
+
}
|
258
|
+
|
259
|
+
});
|
@@ -8,8 +8,7 @@
|
|
8
8
|
/**
|
9
9
|
@namespace
|
10
10
|
|
11
|
-
You can mix in SC.Gesturable to your views to add some support for recognizing
|
12
|
-
gestures.
|
11
|
+
You can mix in SC.Gesturable to your views to add some support for recognizing gestures.
|
13
12
|
|
14
13
|
SproutCore views have built-in touch events. However, sometimes you may want
|
15
14
|
to recognize gestures like tap, pinch, swipe, etc. This becomes tedious if you
|
@@ -76,9 +75,33 @@
|
|
76
75
|
})
|
77
76
|
|
78
77
|
@extends SC.ObjectMixinProtocol
|
78
|
+
@extends SC.ResponderProtocol
|
79
79
|
*/
|
80
80
|
SC.Gesturable = {
|
81
81
|
|
82
|
+
/** @private An array of all gestures currently interested in the touch session.
|
83
|
+
|
84
|
+
@type Array
|
85
|
+
@default null
|
86
|
+
*/
|
87
|
+
_sc_interestedGestures: null,
|
88
|
+
|
89
|
+
/** @private An array of the touches that are currently active in a touch session.
|
90
|
+
|
91
|
+
@type Array
|
92
|
+
@default null
|
93
|
+
*/
|
94
|
+
_sc_touchesInSession: null,
|
95
|
+
|
96
|
+
/**
|
97
|
+
Gestures need to understand multiple touches.
|
98
|
+
|
99
|
+
@type Boolean
|
100
|
+
@default true
|
101
|
+
@see SC.View#acceptsMultitouch
|
102
|
+
*/
|
103
|
+
acceptsMultitouch: true,
|
104
|
+
|
82
105
|
/**
|
83
106
|
@type Array
|
84
107
|
@default ['gestures']
|
@@ -114,6 +137,59 @@ SC.Gesturable = {
|
|
114
137
|
*/
|
115
138
|
gestures: null,
|
116
139
|
|
140
|
+
/** @private Shared method for finishing a touch.
|
141
|
+
|
142
|
+
@param {SC.Touch} touch The touch that ended or cancelled.
|
143
|
+
@param {Boolean} wasCancelled Whether the touch was cancelled or not (i.e. ended normally).
|
144
|
+
*/
|
145
|
+
_sc_gestureTouchFinish: function (touch, wasCancelled) {
|
146
|
+
var touchesInSession = this._sc_touchesInSession,
|
147
|
+
touchIndexInSession = touchesInSession.indexOf(touch);
|
148
|
+
|
149
|
+
// Decrement our list of touches that are being acted upon.
|
150
|
+
touchesInSession.replace(touchIndexInSession, 1);
|
151
|
+
|
152
|
+
var gestures = this._sc_interestedGestures,
|
153
|
+
idx,
|
154
|
+
gesture;
|
155
|
+
|
156
|
+
// Loop through the gestures in reverse, as the list may be mutated.
|
157
|
+
for (idx = gestures.length - 1; idx >= 0; idx--) {
|
158
|
+
var isInterested;
|
159
|
+
|
160
|
+
gesture = gestures[idx];
|
161
|
+
|
162
|
+
if (wasCancelled) {
|
163
|
+
isInterested = gesture.touchCancelledInSession(touch, touchesInSession);
|
164
|
+
} else {
|
165
|
+
isInterested = gesture.touchEndedInSession(touch, touchesInSession);
|
166
|
+
}
|
167
|
+
|
168
|
+
// If the gesture is no longer interested in *any* touches for this session, remove it.
|
169
|
+
if (!isInterested) {
|
170
|
+
// Tell the gesture that the touch session has ended for it.
|
171
|
+
gesture.touchSessionCancelled();
|
172
|
+
|
173
|
+
gestures.replace(idx, 1);
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
// Once there are no more touches in the session, reset the interested gestures.
|
178
|
+
if (touchesInSession.length === 0) {
|
179
|
+
// Notify all remaining interested gestures that the touch session has finished cleanly.
|
180
|
+
var len;
|
181
|
+
|
182
|
+
for (idx = 0, len = gestures.length; idx < len; idx++) {
|
183
|
+
gesture = gestures[idx];
|
184
|
+
|
185
|
+
gesture.touchSessionEnded();
|
186
|
+
}
|
187
|
+
|
188
|
+
// Clear out the current cache of interested gestures for the session.
|
189
|
+
this._sc_interestedGestures.length = 0;
|
190
|
+
}
|
191
|
+
},
|
192
|
+
|
117
193
|
/**
|
118
194
|
When SC.Gesturable initializes, any gestures named on the view are instantiated.
|
119
195
|
|
@@ -178,9 +254,13 @@ SC.Gesturable = {
|
|
178
254
|
at any time. This allows you to avoid passing control until _after_ you
|
179
255
|
have determined your own touchStart, touchesDragged, and touchEnd methods
|
180
256
|
are not going to handle it.
|
257
|
+
|
258
|
+
@param {SC.Touch} touch The touch that started.
|
259
|
+
@returns {Boolean} Whether the touch should be claimed by the view or not.
|
260
|
+
@see SC.ResponderProtocol#touchStart
|
181
261
|
*/
|
182
262
|
touchStart: function(touch) {
|
183
|
-
this.gestureTouchStart(touch);
|
263
|
+
return this.gestureTouchStart(touch);
|
184
264
|
},
|
185
265
|
|
186
266
|
/**
|
@@ -189,6 +269,8 @@ SC.Gesturable = {
|
|
189
269
|
If you override touchesDragged, you will need to call gestureTouchesDragged
|
190
270
|
(at least for any touches you called gestureTouchStart for in touchStart) to
|
191
271
|
allow the gesture system to update.
|
272
|
+
|
273
|
+
@see SC.ResponderProtocol#touchesDragged
|
192
274
|
*/
|
193
275
|
touchesDragged: function(evt, touches) {
|
194
276
|
this.gestureTouchesDragged(evt, touches);
|
@@ -198,58 +280,164 @@ SC.Gesturable = {
|
|
198
280
|
Tells the gesture recognizing code about a touch ending.
|
199
281
|
|
200
282
|
If you override touchEnd, you will need to call gestureTouchEnd
|
201
|
-
for any touches you called touchStart
|
283
|
+
for any touches you called gestureTouchStart for in touchStart (if overridden).
|
284
|
+
|
285
|
+
@param {SC.Touch} touch The touch that ended.
|
286
|
+
@see SC.ResponderProtocol#touchEnd
|
202
287
|
*/
|
203
288
|
touchEnd: function(touch) {
|
204
289
|
this.gestureTouchEnd(touch);
|
205
290
|
},
|
206
291
|
|
207
292
|
/**
|
208
|
-
Tells the gesture recognizing
|
293
|
+
Tells the gesture recognizing code about a touch cancelling.
|
209
294
|
|
210
|
-
|
211
|
-
|
295
|
+
If you override touchCancelled, you will need to call gestureTouchCancelled
|
296
|
+
for any touches you called gestureTouchStart for in touchStart (if overridden).
|
212
297
|
|
213
|
-
|
214
|
-
|
298
|
+
@param {SC.Touch} touch The touch that cancelled.
|
299
|
+
@see SC.ResponderProtocol#touchCancelled
|
215
300
|
*/
|
216
|
-
|
217
|
-
touch
|
301
|
+
touchCancelled: function (touch) {
|
302
|
+
this.gestureTouchCancelled(touch);
|
303
|
+
},
|
218
304
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
305
|
+
/**
|
306
|
+
Called by a gesture that has lost interest in the entire touch session, likely due to too much
|
307
|
+
time having passed since `gestureTouchStart` or `gestureTouchesDragged` having been called.
|
308
|
+
|
309
|
+
Simply removes the gesture from the list of interested gestures and calls
|
310
|
+
`touchSessionCancelled` on the gesture.
|
311
|
+
*/
|
312
|
+
gestureLostInterest: function (gesture) {
|
313
|
+
var gestures = this._sc_interestedGestures,
|
314
|
+
gestureIndex = gestures.indexOf(gesture);
|
315
|
+
|
316
|
+
// Remove the gesture.
|
317
|
+
if (gestureIndex >= 0) {
|
318
|
+
gesture.touchSessionCancelled();
|
319
|
+
|
320
|
+
gestures.replace(gestureIndex, 1);
|
223
321
|
}
|
224
322
|
},
|
225
323
|
|
226
324
|
/**
|
227
|
-
Tells the gesture
|
325
|
+
Tells the gesture recognizing system about a new touch. This notifies all gestures of a new
|
326
|
+
touch session starting (if there were no previous touches) or notifies all interested gestures
|
327
|
+
that a touch has been added.
|
228
328
|
|
229
|
-
|
230
|
-
|
231
|
-
|
329
|
+
As touches are added beyond the first touch, gestures may "lose interest" in the touch session.
|
330
|
+
For example, a gesture may explicitly want only a single touch and if a second touch appears,
|
331
|
+
the gesture may not want any further updates on this touch session (even if the second touch
|
332
|
+
ends again).
|
333
|
+
|
334
|
+
@param {SC.Touch} touch The touch that started.
|
335
|
+
@returns {Boolean} Whether any gesture is interested in the touch or not.
|
232
336
|
*/
|
233
|
-
|
234
|
-
var
|
235
|
-
|
236
|
-
|
237
|
-
|
337
|
+
gestureTouchStart: function (touch) {
|
338
|
+
var interestedGestures = this._sc_interestedGestures,
|
339
|
+
touchesInSession = this._sc_touchesInSession,
|
340
|
+
claimedTouch = false,
|
341
|
+
idx;
|
342
|
+
|
343
|
+
// Instantiate once.
|
344
|
+
if (touchesInSession === null) {
|
345
|
+
touchesInSession = this._sc_touchesInSession = [];
|
346
|
+
interestedGestures = this._sc_interestedGestures = [];
|
347
|
+
}
|
348
|
+
|
349
|
+
// When there are no touches in the session, check all gestures.
|
350
|
+
if (touchesInSession.length === 0) {
|
351
|
+
var gestures = this.get("gestures"),
|
352
|
+
len;
|
353
|
+
|
354
|
+
for (idx = 0, len = gestures.length; idx < len; idx++) {
|
355
|
+
var gesture = gestures[idx];
|
356
|
+
|
357
|
+
gesture.touchSessionStarted(touch);
|
358
|
+
interestedGestures.push(gesture);
|
359
|
+
}
|
360
|
+
|
361
|
+
// Keep this touch.
|
362
|
+
claimedTouch = true;
|
363
|
+
|
364
|
+
// Only check gestures that are interested.
|
365
|
+
} else {
|
366
|
+
// Loop through the gestures in reverse, as the list may be mutated.
|
367
|
+
for (idx = interestedGestures.length - 1; idx >= 0; idx--) {
|
368
|
+
var interestedGesture = interestedGestures[idx],
|
369
|
+
isInterested;
|
370
|
+
|
371
|
+
// Keep only the gestures still interested in the touch.
|
372
|
+
isInterested = interestedGesture.touchAddedToSession(touch, touchesInSession);
|
373
|
+
|
374
|
+
if (isInterested) {
|
375
|
+
// Keep this touch.
|
376
|
+
claimedTouch = true;
|
377
|
+
} else {
|
378
|
+
// Tell the gesture that the touch session has ended for it.
|
379
|
+
interestedGesture.touchSessionCancelled();
|
380
|
+
|
381
|
+
interestedGestures.replace(idx, 1);
|
382
|
+
}
|
383
|
+
}
|
384
|
+
}
|
385
|
+
|
386
|
+
// If any gesture is interested in the new touch. Add it to the list of touches in the session.
|
387
|
+
if (claimedTouch) {
|
388
|
+
touchesInSession.push(touch);
|
238
389
|
}
|
390
|
+
|
391
|
+
return claimedTouch;
|
239
392
|
},
|
240
393
|
|
241
394
|
/**
|
242
|
-
Tells the gesture recognition system that
|
395
|
+
Tells the gesture recognition system that touches have moved.
|
396
|
+
|
397
|
+
@param {SC.Event} evt The touch event.
|
398
|
+
@param {Array} touches The touches previously claimed by this view.
|
399
|
+
@returns {void}
|
400
|
+
*/
|
401
|
+
gestureTouchesDragged: function (evt, touches) {
|
402
|
+
var gestures = this._sc_interestedGestures,
|
403
|
+
touchesInSession = this._sc_touchesInSession;
|
404
|
+
|
405
|
+
// Loop through the gestures in reverse, as the list may be mutated.
|
406
|
+
for (var i = gestures.length - 1; i >= 0; i--) {
|
407
|
+
var gesture = gestures[i],
|
408
|
+
isInterested = gesture.touchesMovedInSession(touchesInSession);
|
409
|
+
|
410
|
+
// If the gesture is no longer interested in *any* touches for this session, remove it.
|
411
|
+
if (!isInterested) {
|
412
|
+
// Tell the gesture that the touch session has ended for it.
|
413
|
+
gesture.touchSessionCancelled();
|
414
|
+
|
415
|
+
gestures.replace(i, 1);
|
416
|
+
|
417
|
+
// TODO: When there are no more interested gestures? Do what with the touches? Anything?
|
418
|
+
}
|
419
|
+
}
|
420
|
+
},
|
421
|
+
|
422
|
+
/**
|
423
|
+
Tells the gesture recognition system that an unassigned touch has ended.
|
243
424
|
|
244
425
|
This informs all of the gestures that the touch ended. The touch is
|
245
426
|
an unassigned touch as, if it were assigned to a gesture, it would have
|
246
427
|
been sent directly to the gesture, bypassing this view.
|
247
428
|
*/
|
248
429
|
gestureTouchEnd: function(touch) {
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
430
|
+
this._sc_gestureTouchFinish(touch, false);
|
431
|
+
},
|
432
|
+
|
433
|
+
/**
|
434
|
+
Tells the gesture recognition system that an unassigned touch has cancelled.
|
435
|
+
|
436
|
+
This informs all of the gestures that the touch cancelled. The touch is
|
437
|
+
an unassigned touch as, if it were assigned to a gesture, it would have
|
438
|
+
been sent directly to the gesture, bypassing this view.
|
439
|
+
*/
|
440
|
+
gestureTouchCancelled: function(touch) {
|
441
|
+
this._sc_gestureTouchFinish(touch, true);
|
254
442
|
}
|
255
443
|
};
|