~bac/juju-gui/trunkcopy

« back to all changes in this revision

Viewing changes to lib/yui/build/event-move/event-move-debug.js

  • Committer: kapil.foss at gmail
  • Date: 2012-07-13 18:45:59 UTC
  • Revision ID: kapil.foss@gmail.com-20120713184559-2xl7be17egsrz0c9
reshape

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
YUI 3.5.1 (build 22)
3
 
Copyright 2012 Yahoo! Inc. All rights reserved.
4
 
Licensed under the BSD License.
5
 
http://yuilibrary.com/license/
6
 
*/
7
 
YUI.add('event-move', function(Y) {
8
 
 
9
 
/**
10
 
 * Adds lower level support for "gesturemovestart", "gesturemove" and "gesturemoveend" events, which can be used to create drag/drop
11
 
 * interactions which work across touch and mouse input devices. They correspond to "touchstart", "touchmove" and "touchend" on a touch input
12
 
 * device, and "mousedown", "mousemove", "mouseup" on a mouse based input device.
13
 
 *
14
 
 * @module event-gestures
15
 
 * @submodule event-move
16
 
 */
17
 
 
18
 
var EVENT = ((Y.config.win && ("ontouchstart" in Y.config.win)) && !(Y.UA.chrome && Y.UA.chrome < 6)) ? {
19
 
        start: "touchstart",
20
 
        move: "touchmove",
21
 
        end: "touchend"
22
 
    } : {
23
 
        start: "mousedown",
24
 
        move: "mousemove",
25
 
        end: "mouseup"
26
 
    },
27
 
 
28
 
    START = "start",
29
 
    MOVE = "move",
30
 
    END = "end",
31
 
 
32
 
    GESTURE_MOVE = "gesture" + MOVE,
33
 
    GESTURE_MOVE_END = GESTURE_MOVE + END,
34
 
    GESTURE_MOVE_START = GESTURE_MOVE + START,
35
 
 
36
 
    _MOVE_START_HANDLE = "_msh",
37
 
    _MOVE_HANDLE = "_mh",
38
 
    _MOVE_END_HANDLE = "_meh",
39
 
 
40
 
    _DEL_MOVE_START_HANDLE = "_dmsh",
41
 
    _DEL_MOVE_HANDLE = "_dmh",
42
 
    _DEL_MOVE_END_HANDLE = "_dmeh",
43
 
 
44
 
    _MOVE_START = "_ms",
45
 
    _MOVE = "_m",
46
 
 
47
 
    MIN_TIME = "minTime",
48
 
    MIN_DISTANCE = "minDistance",
49
 
    PREVENT_DEFAULT = "preventDefault",
50
 
    BUTTON = "button",
51
 
    OWNER_DOCUMENT = "ownerDocument",
52
 
 
53
 
    CURRENT_TARGET = "currentTarget",
54
 
    TARGET = "target",
55
 
 
56
 
    NODE_TYPE = "nodeType",
57
 
 
58
 
    _defArgsProcessor = function(se, args, delegate) {
59
 
        var iConfig = (delegate) ? 4 : 3, 
60
 
            config = (args.length > iConfig) ? Y.merge(args.splice(iConfig,1)[0]) : {};
61
 
 
62
 
        if (!(PREVENT_DEFAULT in config)) {
63
 
            config[PREVENT_DEFAULT] = se.PREVENT_DEFAULT;
64
 
        }
65
 
 
66
 
        return config;
67
 
    },
68
 
 
69
 
    _getRoot = function(node, subscriber) {
70
 
        return subscriber._extra.root || (node.get(NODE_TYPE) === 9) ? node : node.get(OWNER_DOCUMENT);
71
 
    },
72
 
 
73
 
    _normTouchFacade = function(touchFacade, touch, params) {
74
 
        touchFacade.pageX = touch.pageX;
75
 
        touchFacade.pageY = touch.pageY;
76
 
        touchFacade.screenX = touch.screenX;
77
 
        touchFacade.screenY = touch.screenY;
78
 
        touchFacade.clientX = touch.clientX;
79
 
        touchFacade.clientY = touch.clientY;
80
 
        touchFacade[TARGET] = touchFacade[TARGET] || touch[TARGET];
81
 
        touchFacade[CURRENT_TARGET] = touchFacade[CURRENT_TARGET] || touch[CURRENT_TARGET];
82
 
 
83
 
        touchFacade[BUTTON] = (params && params[BUTTON]) || 1; // default to left (left as per vendors, not W3C which is 0)
84
 
    },
85
 
 
86
 
    _prevent = function(e, preventDefault) {
87
 
        if (preventDefault) {
88
 
            // preventDefault is a boolean or a function
89
 
            if (!preventDefault.call || preventDefault(e)) {
90
 
                e.preventDefault();
91
 
            }
92
 
        }
93
 
    },
94
 
 
95
 
    define = Y.Event.define;
96
 
 
97
 
/**
98
 
 * Sets up a "gesturemovestart" event, that is fired on touch devices in response to a single finger "touchstart",
99
 
 * and on mouse based devices in response to a "mousedown". The subscriber can specify the minimum time
100
 
 * and distance thresholds which should be crossed before the "gesturemovestart" is fired and for the mouse,
101
 
 * which button should initiate a "gesturemovestart". This event can also be listened for using node.delegate().
102
 
 * 
103
 
 * <p>It is recommended that you use Y.bind to set up context and additional arguments for your event handler,
104
 
 * however if you want to pass the context and arguments as additional signature arguments to on/delegate, 
105
 
 * you need to provide a null value for the configuration object, e.g: <code>node.on("gesturemovestart", fn, null, context, arg1, arg2, arg3)</code></p>
106
 
 *
107
 
 * @event gesturemovestart
108
 
 * @for YUI
109
 
 * @param type {string} "gesturemovestart"
110
 
 * @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event (mousedown or touchstart.touches[0]) which contains position co-ordinates.
111
 
 * @param cfg {Object} Optional. An object which specifies:
112
 
 *
113
 
 * <dl>
114
 
 * <dt>minDistance (defaults to 0)</dt>
115
 
 * <dd>The minimum distance threshold which should be crossed before the gesturemovestart is fired</dd>
116
 
 * <dt>minTime (defaults to 0)</dt>
117
 
 * <dd>The minimum time threshold for which the finger/mouse should be help down before the gesturemovestart is fired</dd>
118
 
 * <dt>button (no default)</dt>
119
 
 * <dd>In the case of a mouse input device, if the event should only be fired for a specific mouse button.</dd>
120
 
 * <dt>preventDefault (defaults to false)</dt>
121
 
 * <dd>Can be set to true/false to prevent default behavior as soon as the touchstart or mousedown is received (that is before minTime or minDistance thresholds are crossed, and so before the gesturemovestart listener is notified) so that things like text selection and context popups (on touch devices) can be 
122
 
 * prevented. This property can also be set to a function, which returns true or false, based on the event facade passed to it (for example, DragDrop can determine if the target is a valid handle or not before preventing default).</dd>
123
 
 * </dl>
124
 
 *
125
 
 * @return {EventHandle} the detach handle
126
 
 */
127
 
 
128
 
define(GESTURE_MOVE_START, {
129
 
 
130
 
    on: function (node, subscriber, ce) {
131
 
 
132
 
        subscriber[_MOVE_START_HANDLE] = node.on(EVENT[START], 
133
 
            this._onStart,
134
 
            this,
135
 
            node,
136
 
            subscriber,
137
 
            ce);
138
 
    },
139
 
 
140
 
    delegate : function(node, subscriber, ce, filter) {
141
 
 
142
 
        var se = this;
143
 
 
144
 
        subscriber[_DEL_MOVE_START_HANDLE] = node.delegate(EVENT[START],
145
 
            function(e) {
146
 
                se._onStart(e, node, subscriber, ce, true);
147
 
            },
148
 
            filter);
149
 
    },
150
 
 
151
 
    detachDelegate : function(node, subscriber, ce, filter) {
152
 
        var handle = subscriber[_DEL_MOVE_START_HANDLE];
153
 
 
154
 
        if (handle) {
155
 
            handle.detach();
156
 
            subscriber[_DEL_MOVE_START_HANDLE] = null;
157
 
        }
158
 
    },
159
 
 
160
 
    detach: function (node, subscriber, ce) {
161
 
        var startHandle = subscriber[_MOVE_START_HANDLE];
162
 
 
163
 
        if (startHandle) {
164
 
            startHandle.detach();
165
 
            subscriber[_MOVE_START_HANDLE] = null;
166
 
        }
167
 
    },
168
 
 
169
 
    processArgs : function(args, delegate) {
170
 
        var params = _defArgsProcessor(this, args, delegate);
171
 
 
172
 
        if (!(MIN_TIME in params)) {
173
 
            params[MIN_TIME] = this.MIN_TIME;
174
 
        }
175
 
 
176
 
        if (!(MIN_DISTANCE in params)) {
177
 
            params[MIN_DISTANCE] = this.MIN_DISTANCE;
178
 
        }
179
 
 
180
 
        return params;
181
 
    },
182
 
 
183
 
    _onStart : function(e, node, subscriber, ce, delegate) {
184
 
 
185
 
        if (delegate) {
186
 
            node = e[CURRENT_TARGET];
187
 
        }
188
 
 
189
 
        var params = subscriber._extra,
190
 
            fireStart = true,
191
 
            minTime = params[MIN_TIME],
192
 
            minDistance = params[MIN_DISTANCE],
193
 
            button = params.button,
194
 
            preventDefault = params[PREVENT_DEFAULT],
195
 
            root = _getRoot(node, subscriber),
196
 
            startXY;
197
 
 
198
 
        if (e.touches) {
199
 
            if (e.touches.length === 1) {
200
 
                _normTouchFacade(e, e.touches[0], params);
201
 
            } else {
202
 
                fireStart = false;
203
 
            }
204
 
        } else {
205
 
            fireStart = (button === undefined) || (button === e.button);
206
 
        }
207
 
 
208
 
        Y.log("gesturemovestart: params = button:" + button + ", minTime = " + minTime + ", minDistance = " + minDistance, "event-gestures");
209
 
 
210
 
        if (fireStart) {
211
 
 
212
 
            _prevent(e, preventDefault);
213
 
 
214
 
            if (minTime === 0 || minDistance === 0) {
215
 
                Y.log("gesturemovestart: No minTime or minDistance. Firing immediately", "event-gestures");
216
 
                this._start(e, node, ce, params);
217
 
 
218
 
            } else {
219
 
 
220
 
                startXY = [e.pageX, e.pageY];
221
 
 
222
 
                if (minTime > 0) {
223
 
 
224
 
                    Y.log("gesturemovestart: minTime specified. Setup timer.", "event-gestures");
225
 
                    Y.log("gesturemovestart: initialTime for minTime = " + new Date().getTime(), "event-gestures");
226
 
 
227
 
                    params._ht = Y.later(minTime, this, this._start, [e, node, ce, params]);
228
 
 
229
 
                    params._hme = root.on(EVENT[END], Y.bind(function() {
230
 
                        this._cancel(params);
231
 
                    }, this));
232
 
                }
233
 
 
234
 
                if (minDistance > 0) {
235
 
 
236
 
                    Y.log("gesturemovestart: minDistance specified. Setup native mouse/touchmove listener to measure distance.", "event-gestures");
237
 
                    Y.log("gesturemovestart: initialXY for minDistance = " + startXY, "event-gestures");
238
 
 
239
 
                    params._hm = root.on(EVENT[MOVE], Y.bind(function(em) {
240
 
                        if (Math.abs(em.pageX - startXY[0]) > minDistance || Math.abs(em.pageY - startXY[1]) > minDistance) {
241
 
                            Y.log("gesturemovestart: minDistance hit.", "event-gestures");
242
 
                            this._start(e, node, ce, params);
243
 
                        }
244
 
                    }, this));
245
 
                }                        
246
 
            }
247
 
        }
248
 
    },
249
 
 
250
 
    _cancel : function(params) {
251
 
        if (params._ht) {
252
 
            params._ht.cancel();
253
 
            params._ht = null;
254
 
        }
255
 
        if (params._hme) {
256
 
            params._hme.detach();
257
 
            params._hme = null;
258
 
        }
259
 
        if (params._hm) {
260
 
            params._hm.detach();
261
 
            params._hm = null;
262
 
        }
263
 
    },
264
 
 
265
 
    _start : function(e, node, ce, params) {
266
 
 
267
 
        if (params) {
268
 
            this._cancel(params);
269
 
        }
270
 
 
271
 
        e.type = GESTURE_MOVE_START;
272
 
 
273
 
        Y.log("gesturemovestart: Firing start: " + new Date().getTime(), "event-gestures");
274
 
 
275
 
        node.setData(_MOVE_START, e);
276
 
        ce.fire(e);
277
 
    },
278
 
 
279
 
    MIN_TIME : 0,
280
 
    MIN_DISTANCE : 0,
281
 
    PREVENT_DEFAULT : false
282
 
});
283
 
 
284
 
/**
285
 
 * Sets up a "gesturemove" event, that is fired on touch devices in response to a single finger "touchmove",
286
 
 * and on mouse based devices in response to a "mousemove".
287
 
 * 
288
 
 * <p>By default this event is only fired when the same node
289
 
 * has received a "gesturemovestart" event. The subscriber can set standAlone to true, in the configuration properties,
290
 
 * if they want to listen for this event without an initial "gesturemovestart".</p>
291
 
 * 
292
 
 * <p>By default this event sets up it's internal "touchmove" and "mousemove" DOM listeners on the document element. The subscriber
293
 
 * can set the root configuration property, to specify which node to attach DOM listeners to, if different from the document.</p> 
294
 
 *
295
 
 * <p>This event can also be listened for using node.delegate().</p>
296
 
 *
297
 
 * <p>It is recommended that you use Y.bind to set up context and additional arguments for your event handler,
298
 
 * however if you want to pass the context and arguments as additional signature arguments to on/delegate, 
299
 
 * you need to provide a null value for the configuration object, e.g: <code>node.on("gesturemove", fn, null, context, arg1, arg2, arg3)</code></p>
300
 
 *
301
 
 * @event gesturemove
302
 
 * @for YUI
303
 
 * @param type {string} "gesturemove"
304
 
 * @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event (mousemove or touchmove.touches[0]) which contains position co-ordinates.
305
 
 * @param cfg {Object} Optional. An object which specifies:
306
 
 * <dl>
307
 
 * <dt>standAlone (defaults to false)</dt>
308
 
 * <dd>true, if the subscriber should be notified even if a "gesturemovestart" has not occured on the same node.</dd>
309
 
 * <dt>root (defaults to document)</dt>
310
 
 * <dd>The node to which the internal DOM listeners should be attached.</dd>
311
 
 * <dt>preventDefault (defaults to false)</dt>
312
 
 * <dd>Can be set to true/false to prevent default behavior as soon as the touchmove or mousemove is received. As with gesturemovestart, can also be set to function which returns true/false based on the event facade passed to it.</dd>
313
 
 * </dl>
314
 
 *
315
 
 * @return {EventHandle} the detach handle
316
 
 */
317
 
define(GESTURE_MOVE, {
318
 
 
319
 
    on : function (node, subscriber, ce) {
320
 
 
321
 
        var root = _getRoot(node, subscriber),
322
 
 
323
 
            moveHandle = root.on(EVENT[MOVE], 
324
 
                this._onMove,
325
 
                this,
326
 
                node,
327
 
                subscriber,
328
 
                ce);
329
 
 
330
 
        subscriber[_MOVE_HANDLE] = moveHandle;
331
 
    },
332
 
 
333
 
    delegate : function(node, subscriber, ce, filter) {
334
 
 
335
 
        var se = this;
336
 
 
337
 
        subscriber[_DEL_MOVE_HANDLE] = node.delegate(EVENT[MOVE],
338
 
            function(e) {
339
 
                se._onMove(e, node, subscriber, ce, true);
340
 
            },
341
 
            filter);
342
 
    },
343
 
 
344
 
    detach : function (node, subscriber, ce) {
345
 
        var moveHandle = subscriber[_MOVE_HANDLE];
346
 
 
347
 
        if (moveHandle) {
348
 
            moveHandle.detach();
349
 
            subscriber[_MOVE_HANDLE] = null;
350
 
        }
351
 
    },
352
 
    
353
 
    detachDelegate : function(node, subscriber, ce, filter) {
354
 
        var handle = subscriber[_DEL_MOVE_HANDLE];
355
 
 
356
 
        if (handle) {
357
 
            handle.detach();
358
 
            subscriber[_DEL_MOVE_HANDLE] = null;
359
 
        }
360
 
 
361
 
    },
362
 
 
363
 
    processArgs : function(args, delegate) {
364
 
        return _defArgsProcessor(this, args, delegate);
365
 
    },
366
 
 
367
 
    _onMove : function(e, node, subscriber, ce, delegate) {
368
 
 
369
 
        if (delegate) {
370
 
            node = e[CURRENT_TARGET];
371
 
        }
372
 
 
373
 
        var fireMove = subscriber._extra.standAlone || node.getData(_MOVE_START),
374
 
            preventDefault = subscriber._extra.preventDefault;
375
 
 
376
 
        Y.log("onMove initial fireMove check:" + fireMove,"event-gestures");
377
 
 
378
 
        if (fireMove) {
379
 
 
380
 
            if (e.touches) {
381
 
                if (e.touches.length === 1) {
382
 
                    _normTouchFacade(e, e.touches[0]);                    
383
 
                } else {
384
 
                    fireMove = false;
385
 
                }
386
 
            }
387
 
 
388
 
            if (fireMove) {
389
 
 
390
 
                _prevent(e, preventDefault);
391
 
 
392
 
                Y.log("onMove second fireMove check:" + fireMove,"event-gestures");
393
 
 
394
 
                e.type = GESTURE_MOVE;
395
 
                ce.fire(e);
396
 
            }
397
 
        }
398
 
    },
399
 
    
400
 
    PREVENT_DEFAULT : false
401
 
});
402
 
 
403
 
/**
404
 
 * Sets up a "gesturemoveend" event, that is fired on touch devices in response to a single finger "touchend",
405
 
 * and on mouse based devices in response to a "mouseup".
406
 
 * 
407
 
 * <p>By default this event is only fired when the same node
408
 
 * has received a "gesturemove" or "gesturemovestart" event. The subscriber can set standAlone to true, in the configuration properties,
409
 
 * if they want to listen for this event without a preceding "gesturemovestart" or "gesturemove".</p>
410
 
 *
411
 
 * <p>By default this event sets up it's internal "touchend" and "mouseup" DOM listeners on the document element. The subscriber
412
 
 * can set the root configuration property, to specify which node to attach DOM listeners to, if different from the document.</p> 
413
 
 *
414
 
 * <p>This event can also be listened for using node.delegate().</p>
415
 
 *
416
 
 * <p>It is recommended that you use Y.bind to set up context and additional arguments for your event handler,
417
 
 * however if you want to pass the context and arguments as additional signature arguments to on/delegate, 
418
 
 * you need to provide a null value for the configuration object, e.g: <code>node.on("gesturemoveend", fn, null, context, arg1, arg2, arg3)</code></p>
419
 
 *
420
 
 *
421
 
 * @event gesturemoveend
422
 
 * @for YUI
423
 
 * @param type {string} "gesturemoveend"
424
 
 * @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event (mouseup or touchend.changedTouches[0]).
425
 
 * @param cfg {Object} Optional. An object which specifies:
426
 
 * <dl>
427
 
 * <dt>standAlone (defaults to false)</dt>
428
 
 * <dd>true, if the subscriber should be notified even if a "gesturemovestart" or "gesturemove" has not occured on the same node.</dd>
429
 
 * <dt>root (defaults to document)</dt>
430
 
 * <dd>The node to which the internal DOM listeners should be attached.</dd>
431
 
 * <dt>preventDefault (defaults to false)</dt>
432
 
 * <dd>Can be set to true/false to prevent default behavior as soon as the touchend or mouseup is received. As with gesturemovestart, can also be set to function which returns true/false based on the event facade passed to it.</dd>
433
 
 * </dl>
434
 
 *
435
 
 * @return {EventHandle} the detach handle
436
 
 */
437
 
define(GESTURE_MOVE_END, {
438
 
 
439
 
    on : function (node, subscriber, ce) {
440
 
 
441
 
        var root = _getRoot(node, subscriber),
442
 
 
443
 
            endHandle = root.on(EVENT[END], 
444
 
                this._onEnd, 
445
 
                this,
446
 
                node,
447
 
                subscriber, 
448
 
                ce);
449
 
 
450
 
        subscriber[_MOVE_END_HANDLE] = endHandle;
451
 
    },
452
 
 
453
 
    delegate : function(node, subscriber, ce, filter) {
454
 
 
455
 
        var se = this;
456
 
 
457
 
        subscriber[_DEL_MOVE_END_HANDLE] = node.delegate(EVENT[END],
458
 
            function(e) {
459
 
                se._onEnd(e, node, subscriber, ce, true);
460
 
            },
461
 
            filter);
462
 
    },
463
 
 
464
 
    detachDelegate : function(node, subscriber, ce, filter) {
465
 
        var handle = subscriber[_DEL_MOVE_END_HANDLE];
466
 
 
467
 
        if (handle) {
468
 
            handle.detach();
469
 
            subscriber[_DEL_MOVE_END_HANDLE] = null;
470
 
        }
471
 
 
472
 
    },
473
 
 
474
 
    detach : function (node, subscriber, ce) {
475
 
        var endHandle = subscriber[_MOVE_END_HANDLE];
476
 
    
477
 
        if (endHandle) {
478
 
            endHandle.detach();
479
 
            subscriber[_MOVE_END_HANDLE] = null;
480
 
        }
481
 
    },
482
 
 
483
 
    processArgs : function(args, delegate) {
484
 
        return _defArgsProcessor(this, args, delegate);
485
 
    },
486
 
 
487
 
    _onEnd : function(e, node, subscriber, ce, delegate) {
488
 
 
489
 
        if (delegate) {
490
 
            node = e[CURRENT_TARGET];
491
 
        }
492
 
 
493
 
        var fireMoveEnd = subscriber._extra.standAlone || node.getData(_MOVE) || node.getData(_MOVE_START),
494
 
            preventDefault = subscriber._extra.preventDefault;
495
 
 
496
 
        if (fireMoveEnd) {
497
 
 
498
 
            if (e.changedTouches) {
499
 
                if (e.changedTouches.length === 1) {
500
 
                    _normTouchFacade(e, e.changedTouches[0]);                    
501
 
                } else {
502
 
                    fireMoveEnd = false;
503
 
                }
504
 
            }
505
 
 
506
 
            if (fireMoveEnd) {
507
 
 
508
 
                _prevent(e, preventDefault);
509
 
 
510
 
                e.type = GESTURE_MOVE_END;
511
 
                ce.fire(e);
512
 
 
513
 
                node.clearData(_MOVE_START);
514
 
                node.clearData(_MOVE);
515
 
            }
516
 
        }
517
 
    },
518
 
 
519
 
    PREVENT_DEFAULT : false
520
 
});
521
 
 
522
 
 
523
 
}, '3.5.1' ,{requires:['node-base','event-touch','event-synthetic']});