~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

Viewing changes to lib/yuilib/3.13.0/node-flick/node-flick-debug.js

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
YUI 3.13.0 (build 508226d)
 
3
Copyright 2013 Yahoo! Inc. All rights reserved.
 
4
Licensed under the BSD License.
 
5
http://yuilibrary.com/license/
 
6
*/
 
7
 
 
8
YUI.add('node-flick', function (Y, NAME) {
 
9
 
 
10
/**
 
11
 * Provide a simple Flick plugin, which can be used along with the "flick" gesture event, to
 
12
 * animate the motion of the host node in response to a (mouse or touch) flick gesture.
 
13
 *
 
14
 * <p>The current implementation is designed to move the node, relative to the bounds of a parent node and is suitable
 
15
 * for scroll/carousel type implementations. Future versions will remove that constraint, to allow open ended movement within
 
16
 * the document.</p>
 
17
 *
 
18
 * @module node-flick
 
19
 */
 
20
 
 
21
    var HOST = "host",
 
22
        PARENT_NODE = "parentNode",
 
23
        BOUNDING_BOX = "boundingBox",
 
24
        OFFSET_HEIGHT = "offsetHeight",
 
25
        OFFSET_WIDTH = "offsetWidth",
 
26
        SCROLL_HEIGHT = "scrollHeight",
 
27
        SCROLL_WIDTH = "scrollWidth",
 
28
        BOUNCE = "bounce",
 
29
        MIN_DISTANCE = "minDistance",
 
30
        MIN_VELOCITY = "minVelocity",
 
31
        BOUNCE_DISTANCE = "bounceDistance",
 
32
        DECELERATION = "deceleration",
 
33
        STEP = "step",
 
34
        DURATION = "duration",
 
35
        EASING = "easing",
 
36
        FLICK = "flick",
 
37
 
 
38
        getClassName = Y.ClassNameManager.getClassName;
 
39
 
 
40
    /**
 
41
     * A plugin class which can be used to animate the motion of a node, in response to a flick gesture.
 
42
     *
 
43
     * @class Flick
 
44
     * @namespace Plugin
 
45
     * @param {Object} config The initial attribute values for the plugin
 
46
     */
 
47
    function Flick(config) {
 
48
        Flick.superclass.constructor.apply(this, arguments);
 
49
    }
 
50
 
 
51
    Flick.ATTRS = {
 
52
 
 
53
        /**
 
54
         * Drag coefficent for inertial scrolling. The closer to 1 this
 
55
         * value is, the less friction during scrolling.
 
56
         *
 
57
         * @attribute deceleration
 
58
         * @default 0.98
 
59
         */
 
60
        deceleration : {
 
61
            value: 0.98
 
62
        },
 
63
 
 
64
        /**
 
65
         * Drag coefficient for intertial scrolling at the upper
 
66
         * and lower boundaries of the scrollview. Set to 0 to
 
67
         * disable "rubber-banding".
 
68
         *
 
69
         * @attribute bounce
 
70
         * @type Number
 
71
         * @default 0.7
 
72
         */
 
73
        bounce : {
 
74
            value: 0.7
 
75
        },
 
76
 
 
77
        /**
 
78
         * The bounce distance in pixels
 
79
         *
 
80
         * @attribute bounceDistance
 
81
         * @type Number
 
82
         * @default 150
 
83
         */
 
84
        bounceDistance : {
 
85
            value: 150
 
86
        },
 
87
 
 
88
        /**
 
89
         * The minimum flick gesture velocity (px/ms) at which to trigger the flick response
 
90
         *
 
91
         * @attribute minVelocity
 
92
         * @type Number
 
93
         * @default 0
 
94
         */
 
95
        minVelocity : {
 
96
            value: 0
 
97
        },
 
98
 
 
99
        /**
 
100
         * The minimum flick gesture distance (px) for which to trigger the flick response
 
101
         *
 
102
         * @attribute minVelocity
 
103
         * @type Number
 
104
         * @default 10
 
105
         */
 
106
        minDistance : {
 
107
            value: 10
 
108
        },
 
109
 
 
110
        /**
 
111
         * The constraining box relative to which the flick animation and bounds should be calculated.
 
112
         *
 
113
         * @attribute boundingBox
 
114
         * @type Node
 
115
         * @default parentNode
 
116
         */
 
117
        boundingBox : {
 
118
            valueFn : function() {
 
119
                return this.get(HOST).get(PARENT_NODE);
 
120
            }
 
121
        },
 
122
 
 
123
        /**
 
124
         * Time between flick animation frames.
 
125
         *
 
126
         * @attribute step
 
127
         * @type Number
 
128
         * @default 10
 
129
         */
 
130
        step : {
 
131
            value:10
 
132
        },
 
133
 
 
134
        /**
 
135
         * The custom duration to apply to the flick animation. By default,
 
136
         * the animation duration is controlled by the deceleration factor.
 
137
         *
 
138
         * @attribute duration
 
139
         * @type Number
 
140
         * @default null
 
141
         */
 
142
        duration : {
 
143
            value:null
 
144
        },
 
145
 
 
146
        /**
 
147
         * The custom transition easing to use for the flick animation. If not
 
148
         * provided defaults to internally to Flick.EASING, or Flick.SNAP_EASING based
 
149
         * on whether or not we're animating the flick or bounce step.
 
150
         *
 
151
         * @attribute easing
 
152
         * @type String
 
153
         * @default null
 
154
         */
 
155
        easing : {
 
156
            value:null
 
157
        }
 
158
    };
 
159
 
 
160
    /**
 
161
     * The NAME of the Flick class. Used to prefix events generated
 
162
     * by the plugin.
 
163
     *
 
164
     * @property NAME
 
165
     * @static
 
166
     * @type String
 
167
     * @default "pluginFlick"
 
168
     */
 
169
    Flick.NAME = "pluginFlick";
 
170
 
 
171
    /**
 
172
     * The namespace for the plugin. This will be the property on the node, which will
 
173
     * reference the plugin instance, when it's plugged in.
 
174
     *
 
175
     * @property NS
 
176
     * @static
 
177
     * @type String
 
178
     * @default "flick"
 
179
     */
 
180
    Flick.NS = "flick";
 
181
 
 
182
    Y.extend(Flick, Y.Plugin.Base, {
 
183
 
 
184
        /**
 
185
         * The initializer lifecycle implementation.
 
186
         *
 
187
         * @method initializer
 
188
         * @param {Object} config The user configuration for the plugin
 
189
         */
 
190
        initializer : function(config) {
 
191
            this._node = this.get(HOST);
 
192
 
 
193
            this._renderClasses();
 
194
            this.setBounds();
 
195
 
 
196
            this._node.on(FLICK, Y.bind(this._onFlick, this), {
 
197
                minDistance : this.get(MIN_DISTANCE),
 
198
                minVelocity : this.get(MIN_VELOCITY)
 
199
            });
 
200
        },
 
201
 
 
202
        /**
 
203
         * Sets the min/max boundaries for the flick animation,
 
204
         * based on the boundingBox dimensions.
 
205
         *
 
206
         * @method setBounds
 
207
         */
 
208
        setBounds : function () {
 
209
            var box = this.get(BOUNDING_BOX),
 
210
                node = this._node,
 
211
 
 
212
                boxHeight = box.get(OFFSET_HEIGHT),
 
213
                boxWidth = box.get(OFFSET_WIDTH),
 
214
 
 
215
                contentHeight = node.get(SCROLL_HEIGHT),
 
216
                contentWidth = node.get(SCROLL_WIDTH);
 
217
 
 
218
            if (contentHeight > boxHeight) {
 
219
                this._maxY = contentHeight - boxHeight;
 
220
                this._minY = 0;
 
221
                this._scrollY = true;
 
222
            }
 
223
 
 
224
            if (contentWidth > boxWidth) {
 
225
                this._maxX = contentWidth - boxWidth;
 
226
                this._minX = 0;
 
227
                this._scrollX = true;
 
228
            }
 
229
 
 
230
            this._x = this._y = 0;
 
231
 
 
232
            node.set("top", this._y + "px");
 
233
            node.set("left", this._x + "px");
 
234
        },
 
235
 
 
236
        /**
 
237
         * Adds the CSS classes, necessary to set up overflow/position properties on the
 
238
         * node and boundingBox.
 
239
         *
 
240
         * @method _renderClasses
 
241
         * @protected
 
242
         */
 
243
        _renderClasses : function() {
 
244
            this.get(BOUNDING_BOX).addClass(Flick.CLASS_NAMES.box);
 
245
            this._node.addClass(Flick.CLASS_NAMES.content);
 
246
        },
 
247
 
 
248
        /**
 
249
         * The flick event listener. Kicks off the flick animation.
 
250
         *
 
251
         * @method _onFlick
 
252
         * @param e {EventFacade} The flick event facade, containing e.flick.distance, e.flick.velocity etc.
 
253
         * @protected
 
254
         */
 
255
        _onFlick: function(e) {
 
256
            this._v = e.flick.velocity;
 
257
            this._flick = true;
 
258
            this._flickAnim();
 
259
        },
 
260
 
 
261
        /**
 
262
         * Executes a single frame in the flick animation
 
263
         *
 
264
         * @method _flickFrame
 
265
         * @protected
 
266
         */
 
267
        _flickAnim: function() {
 
268
 
 
269
            var y = this._y,
 
270
                x = this._x,
 
271
 
 
272
                maxY = this._maxY,
 
273
                minY = this._minY,
 
274
                maxX = this._maxX,
 
275
                minX = this._minX,
 
276
                velocity = this._v,
 
277
 
 
278
                step = this.get(STEP),
 
279
                deceleration = this.get(DECELERATION),
 
280
                bounce = this.get(BOUNCE);
 
281
 
 
282
            this._v = (velocity * deceleration);
 
283
 
 
284
            this._snapToEdge = false;
 
285
 
 
286
            if (this._scrollX) {
 
287
                x = x - (velocity * step);
 
288
            }
 
289
 
 
290
            if (this._scrollY) {
 
291
                y = y - (velocity * step);
 
292
            }
 
293
 
 
294
            if (Math.abs(velocity).toFixed(4) <= Flick.VELOCITY_THRESHOLD) {
 
295
 
 
296
                this._flick = false;
 
297
 
 
298
                this._killTimer(!(this._exceededYBoundary || this._exceededXBoundary));
 
299
 
 
300
                if (this._scrollX) {
 
301
                    if (x < minX) {
 
302
                        this._snapToEdge = true;
 
303
                        this._setX(minX);
 
304
                    } else if (x > maxX) {
 
305
                        this._snapToEdge = true;
 
306
                        this._setX(maxX);
 
307
                    }
 
308
                }
 
309
 
 
310
                if (this._scrollY) {
 
311
                    if (y < minY) {
 
312
                        this._snapToEdge = true;
 
313
                        this._setY(minY);
 
314
                    } else if (y > maxY) {
 
315
                        this._snapToEdge = true;
 
316
                        this._setY(maxY);
 
317
                    }
 
318
                }
 
319
 
 
320
            } else {
 
321
 
 
322
                if (this._scrollX && (x < minX || x > maxX)) {
 
323
                    this._exceededXBoundary = true;
 
324
                    this._v *= bounce;
 
325
                }
 
326
 
 
327
                if (this._scrollY && (y < minY || y > maxY)) {
 
328
                    this._exceededYBoundary = true;
 
329
                    this._v *= bounce;
 
330
                }
 
331
 
 
332
                if (this._scrollX) {
 
333
                    this._setX(x);
 
334
                }
 
335
 
 
336
                if (this._scrollY) {
 
337
                    this._setY(y);
 
338
                }
 
339
 
 
340
                this._flickTimer = Y.later(step, this, this._flickAnim);
 
341
            }
 
342
        },
 
343
 
 
344
        /**
 
345
         * Internal utility method to set the X offset position
 
346
         *
 
347
         * @method _setX
 
348
         * @param {Number} val
 
349
         * @private
 
350
         */
 
351
        _setX : function(val) {
 
352
            this._move(val, null, this.get(DURATION), this.get(EASING));
 
353
        },
 
354
 
 
355
        /**
 
356
         * Internal utility method to set the Y offset position
 
357
         *
 
358
         * @method _setY
 
359
         * @param {Number} val
 
360
         * @private
 
361
         */
 
362
        _setY : function(val) {
 
363
            this._move(null, val, this.get(DURATION), this.get(EASING));
 
364
        },
 
365
 
 
366
        /**
 
367
         * Internal utility method to move the node to a given XY position,
 
368
         * using transitions, if specified.
 
369
         *
 
370
         * @method _move
 
371
         * @param {Number} x The X offset position
 
372
         * @param {Number} y The Y offset position
 
373
         * @param {Number} duration The duration to use for the transition animation
 
374
         * @param {String} easing The easing to use for the transition animation.
 
375
         *
 
376
         * @private
 
377
         */
 
378
        _move: function(x, y, duration, easing) {
 
379
 
 
380
            if (x !== null) {
 
381
                x = this._bounce(x);
 
382
            } else {
 
383
                x = this._x;
 
384
            }
 
385
 
 
386
            if (y !== null) {
 
387
                y = this._bounce(y);
 
388
            } else {
 
389
                y = this._y;
 
390
            }
 
391
 
 
392
            duration = duration || this._snapToEdge ? Flick.SNAP_DURATION : 0;
 
393
            easing = easing || this._snapToEdge ? Flick.SNAP_EASING : Flick.EASING;
 
394
 
 
395
            this._x = x;
 
396
            this._y = y;
 
397
 
 
398
            this._anim(x, y, duration, easing);
 
399
        },
 
400
 
 
401
        /**
 
402
         * Internal utility method to perform the transition step
 
403
         *
 
404
         * @method _anim
 
405
         * @param {Number} x The X offset position
 
406
         * @param {Number} y The Y offset position
 
407
         * @param {Number} duration The duration to use for the transition animation
 
408
         * @param {String} easing The easing to use for the transition animation.
 
409
         *
 
410
         * @private
 
411
         */
 
412
        _anim : function(x, y, duration, easing) {
 
413
            var xn = x * -1,
 
414
                yn = y * -1,
 
415
 
 
416
                transition = {
 
417
                    duration : duration / 1000,
 
418
                    easing : easing
 
419
                };
 
420
 
 
421
            Y.log("Transition: duration, easing:" + transition.duration, transition.easing, "node-flick");
 
422
 
 
423
            if (Y.Transition.useNative) {
 
424
                transition.transform = 'translate('+ (xn) + 'px,' + (yn) +'px)';
 
425
            } else {
 
426
                transition.left = xn + 'px';
 
427
                transition.top = yn + 'px';
 
428
            }
 
429
 
 
430
            this._node.transition(transition);
 
431
        },
 
432
 
 
433
        /**
 
434
         * Internal utility method to constrain the offset value
 
435
         * based on the bounce criteria.
 
436
         *
 
437
         * @method _bounce
 
438
         * @param {Number} x The offset value to constrain.
 
439
         * @param {Number} max The max offset value.
 
440
         *
 
441
         * @private
 
442
         */
 
443
        _bounce : function(val, max) {
 
444
            var bounce = this.get(BOUNCE),
 
445
                dist = this.get(BOUNCE_DISTANCE),
 
446
                min = bounce ? -dist : 0;
 
447
 
 
448
            max = bounce ? max + dist : max;
 
449
 
 
450
            if(!bounce) {
 
451
                if(val < min) {
 
452
                    val = min;
 
453
                } else if(val > max) {
 
454
                    val = max;
 
455
                }
 
456
            }
 
457
            return val;
 
458
        },
 
459
 
 
460
        /**
 
461
         * Stop the animation timer
 
462
         *
 
463
         * @method _killTimer
 
464
         * @private
 
465
         */
 
466
        _killTimer: function() {
 
467
            if(this._flickTimer) {
 
468
                this._flickTimer.cancel();
 
469
            }
 
470
        }
 
471
 
 
472
    }, {
 
473
 
 
474
        /**
 
475
         * The threshold used to determine when the decelerated velocity of the node
 
476
         * is practically 0.
 
477
         *
 
478
         * @property VELOCITY_THRESHOLD
 
479
         * @static
 
480
         * @type Number
 
481
         * @default 0.015
 
482
         */
 
483
        VELOCITY_THRESHOLD : 0.015,
 
484
 
 
485
        /**
 
486
         * The duration to use for the bounce snap-back transition
 
487
         *
 
488
         * @property SNAP_DURATION
 
489
         * @static
 
490
         * @type Number
 
491
         * @default 400
 
492
         */
 
493
         SNAP_DURATION : 400,
 
494
 
 
495
        /**
 
496
         * The default easing to use for the main flick movement transition
 
497
         *
 
498
         * @property EASING
 
499
         * @static
 
500
         * @type String
 
501
         * @default 'cubic-bezier(0, 0.1, 0, 1.0)'
 
502
         */
 
503
        EASING : 'cubic-bezier(0, 0.1, 0, 1.0)',
 
504
 
 
505
        /**
 
506
         * The default easing to use for the bounce snap-back transition
 
507
         *
 
508
         * @property SNAP_EASING
 
509
         * @static
 
510
         * @type String
 
511
         * @default 'ease-out'
 
512
         */
 
513
        SNAP_EASING : 'ease-out',
 
514
 
 
515
        /**
 
516
         * The default CSS class names used by the plugin
 
517
         *
 
518
         * @property CLASS_NAMES
 
519
         * @static
 
520
         * @type Object
 
521
         */
 
522
        CLASS_NAMES : {
 
523
            box: getClassName(Flick.NS),
 
524
            content: getClassName(Flick.NS, "content")
 
525
        }
 
526
    });
 
527
 
 
528
    Y.Plugin.Flick = Flick;
 
529
 
 
530
 
 
531
}, '3.13.0', {"requires": ["classnamemanager", "transition", "event-flick", "plugin"], "skinnable": true});