~michael.nelson/ubuntu-webcatalog/1267731-import-sca-apps-error

« back to all changes in this revision

Viewing changes to src/webcatalog/static/yui/3.10.3/build/scrollview-base/scrollview-base-debug.js

  • Committer: Tarmac
  • Author(s): Stephen Stewart
  • Date: 2013-06-26 09:19:32 UTC
  • mfrom: (184.1.4 ubuntu-global-nav)
  • Revision ID: tarmac-20130626091932-8urtuli368k8p7ds
[r=beuno,jonas-drange] add ubuntu global nav to apps.ubuntu.com

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
YUI 3.10.3 (build 2fb5187)
 
3
Copyright 2013 Yahoo! Inc. All rights reserved.
 
4
Licensed under the BSD License.
 
5
http://yuilibrary.com/license/
 
6
*/
 
7
 
 
8
YUI.add('scrollview-base', function (Y, NAME) {
 
9
 
 
10
/**
 
11
 * The scrollview-base module provides a basic ScrollView Widget, without scrollbar indicators
 
12
 *
 
13
 * @module scrollview
 
14
 * @submodule scrollview-base
 
15
 */
 
16
 
 
17
 // Local vars
 
18
var getClassName = Y.ClassNameManager.getClassName,
 
19
    DOCUMENT = Y.config.doc,
 
20
    IE = Y.UA.ie,
 
21
    NATIVE_TRANSITIONS = Y.Transition.useNative,
 
22
    vendorPrefix = Y.Transition._VENDOR_PREFIX, // Todo: This is a private property, and alternative approaches should be investigated
 
23
    SCROLLVIEW = 'scrollview',
 
24
    CLASS_NAMES = {
 
25
        vertical: getClassName(SCROLLVIEW, 'vert'),
 
26
        horizontal: getClassName(SCROLLVIEW, 'horiz')
 
27
    },
 
28
    EV_SCROLL_END = 'scrollEnd',
 
29
    FLICK = 'flick',
 
30
    DRAG = 'drag',
 
31
    MOUSEWHEEL = 'mousewheel',
 
32
    UI = 'ui',
 
33
    TOP = 'top',
 
34
    LEFT = 'left',
 
35
    PX = 'px',
 
36
    AXIS = 'axis',
 
37
    SCROLL_Y = 'scrollY',
 
38
    SCROLL_X = 'scrollX',
 
39
    BOUNCE = 'bounce',
 
40
    DISABLED = 'disabled',
 
41
    DECELERATION = 'deceleration',
 
42
    DIM_X = 'x',
 
43
    DIM_Y = 'y',
 
44
    BOUNDING_BOX = 'boundingBox',
 
45
    CONTENT_BOX = 'contentBox',
 
46
    GESTURE_MOVE = 'gesturemove',
 
47
    START = 'start',
 
48
    END = 'end',
 
49
    EMPTY = '',
 
50
    ZERO = '0s',
 
51
    SNAP_DURATION = 'snapDuration',
 
52
    SNAP_EASING = 'snapEasing',
 
53
    EASING = 'easing',
 
54
    FRAME_DURATION = 'frameDuration',
 
55
    BOUNCE_RANGE = 'bounceRange',
 
56
    _constrain = function (val, min, max) {
 
57
        return Math.min(Math.max(val, min), max);
 
58
    };
 
59
 
 
60
/**
 
61
 * ScrollView provides a scrollable widget, supporting flick gestures,
 
62
 * across both touch and mouse based devices.
 
63
 *
 
64
 * @class ScrollView
 
65
 * @param config {Object} Object literal with initial attribute values
 
66
 * @extends Widget
 
67
 * @constructor
 
68
 */
 
69
function ScrollView() {
 
70
    ScrollView.superclass.constructor.apply(this, arguments);
 
71
}
 
72
 
 
73
Y.ScrollView = Y.extend(ScrollView, Y.Widget, {
 
74
 
 
75
    // *** Y.ScrollView prototype
 
76
 
 
77
    /**
 
78
     * Flag driving whether or not we should try and force H/W acceleration when transforming. Currently enabled by default for Webkit.
 
79
     * Used by the _transform method.
 
80
     *
 
81
     * @property _forceHWTransforms
 
82
     * @type boolean
 
83
     * @protected
 
84
     */
 
85
    _forceHWTransforms: Y.UA.webkit ? true : false,
 
86
 
 
87
    /**
 
88
     * <p>Used to control whether or not ScrollView's internal
 
89
     * gesturemovestart, gesturemove and gesturemoveend
 
90
     * event listeners should preventDefault. The value is an
 
91
     * object, with "start", "move" and "end" properties used to
 
92
     * specify which events should preventDefault and which shouldn't:</p>
 
93
     *
 
94
     * <pre>
 
95
     * {
 
96
     *    start: false,
 
97
     *    move: true,
 
98
     *    end: false
 
99
     * }
 
100
     * </pre>
 
101
     *
 
102
     * <p>The default values are set up in order to prevent panning,
 
103
     * on touch devices, while allowing click listeners on elements inside
 
104
     * the ScrollView to be notified as expected.</p>
 
105
     *
 
106
     * @property _prevent
 
107
     * @type Object
 
108
     * @protected
 
109
     */
 
110
    _prevent: {
 
111
        start: false,
 
112
        move: true,
 
113
        end: false
 
114
    },
 
115
 
 
116
    /**
 
117
     * Contains the distance (postive or negative) in pixels by which
 
118
     *  the scrollview was last scrolled. This is useful when setting up
 
119
     *  click listeners on the scrollview content, which on mouse based
 
120
     *  devices are always fired, even after a drag/flick.
 
121
     *
 
122
     * <p>Touch based devices don't currently fire a click event,
 
123
     *  if the finger has been moved (beyond a threshold) so this
 
124
     *  check isn't required, if working in a purely touch based environment</p>
 
125
     *
 
126
     * @property lastScrolledAmt
 
127
     * @type Number
 
128
     * @public
 
129
     * @default 0
 
130
     */
 
131
    lastScrolledAmt: 0,
 
132
 
 
133
    /**
 
134
     * Internal state, defines the minimum amount that the scrollview can be scrolled along the X axis
 
135
     *
 
136
     * @property _minScrollX
 
137
     * @type number
 
138
     * @protected
 
139
     */
 
140
    _minScrollX: null,
 
141
 
 
142
    /**
 
143
     * Internal state, defines the maximum amount that the scrollview can be scrolled along the X axis
 
144
     *
 
145
     * @property _maxScrollX
 
146
     * @type number
 
147
     * @protected
 
148
     */
 
149
    _maxScrollX: null,
 
150
 
 
151
    /**
 
152
     * Internal state, defines the minimum amount that the scrollview can be scrolled along the Y axis
 
153
     *
 
154
     * @property _minScrollY
 
155
     * @type number
 
156
     * @protected
 
157
     */
 
158
    _minScrollY: null,
 
159
 
 
160
    /**
 
161
     * Internal state, defines the maximum amount that the scrollview can be scrolled along the Y axis
 
162
     *
 
163
     * @property _maxScrollY
 
164
     * @type number
 
165
     * @protected
 
166
     */
 
167
    _maxScrollY: null,
 
168
    
 
169
    /**
 
170
     * Designated initializer
 
171
     *
 
172
     * @method initializer
 
173
     * @param {config} Configuration object for the plugin
 
174
     */
 
175
    initializer: function () {
 
176
        var sv = this;
 
177
 
 
178
        // Cache these values, since they aren't going to change.
 
179
        sv._bb = sv.get(BOUNDING_BOX);
 
180
        sv._cb = sv.get(CONTENT_BOX);
 
181
 
 
182
        // Cache some attributes
 
183
        sv._cAxis = sv.get(AXIS);
 
184
        sv._cBounce = sv.get(BOUNCE);
 
185
        sv._cBounceRange = sv.get(BOUNCE_RANGE);
 
186
        sv._cDeceleration = sv.get(DECELERATION);
 
187
        sv._cFrameDuration = sv.get(FRAME_DURATION);
 
188
    },
 
189
 
 
190
    /**
 
191
     * bindUI implementation
 
192
     *
 
193
     * Hooks up events for the widget
 
194
     * @method bindUI
 
195
     */
 
196
    bindUI: function () {
 
197
        var sv = this;
 
198
 
 
199
        // Bind interaction listers
 
200
        sv._bindFlick(sv.get(FLICK));
 
201
        sv._bindDrag(sv.get(DRAG));
 
202
        sv._bindMousewheel(true);
 
203
        
 
204
        // Bind change events
 
205
        sv._bindAttrs();
 
206
 
 
207
        // IE SELECT HACK. See if we can do this non-natively and in the gesture for a future release.
 
208
        if (IE) {
 
209
            sv._fixIESelect(sv._bb, sv._cb);
 
210
        }
 
211
 
 
212
        // Set any deprecated static properties
 
213
        if (ScrollView.SNAP_DURATION) {
 
214
            sv.set(SNAP_DURATION, ScrollView.SNAP_DURATION);
 
215
        }
 
216
 
 
217
        if (ScrollView.SNAP_EASING) {
 
218
            sv.set(SNAP_EASING, ScrollView.SNAP_EASING);
 
219
        }
 
220
 
 
221
        if (ScrollView.EASING) {
 
222
            sv.set(EASING, ScrollView.EASING);
 
223
        }
 
224
 
 
225
        if (ScrollView.FRAME_STEP) {
 
226
            sv.set(FRAME_DURATION, ScrollView.FRAME_STEP);
 
227
        }
 
228
 
 
229
        if (ScrollView.BOUNCE_RANGE) {
 
230
            sv.set(BOUNCE_RANGE, ScrollView.BOUNCE_RANGE);
 
231
        }
 
232
 
 
233
        // Recalculate dimension properties
 
234
        // TODO: This should be throttled.
 
235
        // Y.one(WINDOW).after('resize', sv._afterDimChange, sv);
 
236
    },
 
237
 
 
238
    /**
 
239
     * Bind event listeners
 
240
     *
 
241
     * @method _bindAttrs
 
242
     * @private
 
243
     */
 
244
    _bindAttrs: function () {
 
245
        var sv = this,
 
246
            scrollChangeHandler = sv._afterScrollChange,
 
247
            dimChangeHandler = sv._afterDimChange;
 
248
 
 
249
        // Bind any change event listeners
 
250
        sv.after({
 
251
            'scrollEnd': sv._afterScrollEnd,
 
252
            'disabledChange': sv._afterDisabledChange,
 
253
            'flickChange': sv._afterFlickChange,
 
254
            'dragChange': sv._afterDragChange,
 
255
            'axisChange': sv._afterAxisChange,
 
256
            'scrollYChange': scrollChangeHandler,
 
257
            'scrollXChange': scrollChangeHandler,
 
258
            'heightChange': dimChangeHandler,
 
259
            'widthChange': dimChangeHandler
 
260
        });
 
261
    },
 
262
 
 
263
    /**
 
264
     * Bind (or unbind) gesture move listeners required for drag support
 
265
     *
 
266
     * @method _bindDrag
 
267
     * @param drag {boolean} If true, the method binds listener to enable
 
268
     *  drag (gesturemovestart). If false, the method unbinds gesturemove
 
269
     *  listeners for drag support.
 
270
     * @private
 
271
     */
 
272
    _bindDrag: function (drag) {
 
273
        var sv = this,
 
274
            bb = sv._bb;
 
275
 
 
276
        // Unbind any previous 'drag' listeners
 
277
        bb.detach(DRAG + '|*');
 
278
 
 
279
        if (drag) {
 
280
            bb.on(DRAG + '|' + GESTURE_MOVE + START, Y.bind(sv._onGestureMoveStart, sv));
 
281
        }
 
282
    },
 
283
 
 
284
    /**
 
285
     * Bind (or unbind) flick listeners.
 
286
     *
 
287
     * @method _bindFlick
 
288
     * @param flick {Object|boolean} If truthy, the method binds listeners for
 
289
     *  flick support. If false, the method unbinds flick listeners.
 
290
     * @private
 
291
     */
 
292
    _bindFlick: function (flick) {
 
293
        var sv = this,
 
294
            bb = sv._bb;
 
295
 
 
296
        // Unbind any previous 'flick' listeners
 
297
        bb.detach(FLICK + '|*');
 
298
 
 
299
        if (flick) {
 
300
            bb.on(FLICK + '|' + FLICK, Y.bind(sv._flick, sv), flick);
 
301
 
 
302
            // Rebind Drag, becuase _onGestureMoveEnd always has to fire -after- _flick
 
303
            sv._bindDrag(sv.get(DRAG));
 
304
        }
 
305
    },
 
306
 
 
307
    /**
 
308
     * Bind (or unbind) mousewheel listeners.
 
309
     *
 
310
     * @method _bindMousewheel
 
311
     * @param mousewheel {Object|boolean} If truthy, the method binds listeners for
 
312
     *  mousewheel support. If false, the method unbinds mousewheel listeners.
 
313
     * @private
 
314
     */
 
315
    _bindMousewheel: function (mousewheel) {
 
316
        var sv = this,
 
317
            bb = sv._bb;
 
318
 
 
319
        // Unbind any previous 'mousewheel' listeners
 
320
        // TODO: This doesn't actually appear to work properly. Fix. #2532743
 
321
        bb.detach(MOUSEWHEEL + '|*');
 
322
 
 
323
        // Only enable for vertical scrollviews
 
324
        if (mousewheel) {
 
325
            // Bound to document, because that's where mousewheel events fire off of.
 
326
            Y.one(DOCUMENT).on(MOUSEWHEEL, Y.bind(sv._mousewheel, sv));
 
327
        }
 
328
    },
 
329
 
 
330
    /**
 
331
     * syncUI implementation.
 
332
     *
 
333
     * Update the scroll position, based on the current value of scrollX/scrollY.
 
334
     *
 
335
     * @method syncUI
 
336
     */
 
337
    syncUI: function () {
 
338
        var sv = this,
 
339
            scrollDims = sv._getScrollDims(),
 
340
            width = scrollDims.offsetWidth,
 
341
            height = scrollDims.offsetHeight,
 
342
            scrollWidth = scrollDims.scrollWidth,
 
343
            scrollHeight = scrollDims.scrollHeight;
 
344
 
 
345
        // If the axis is undefined, auto-calculate it
 
346
        if (sv._cAxis === undefined) {
 
347
            // This should only ever be run once (for now).
 
348
            // In the future SV might post-load axis changes
 
349
            sv._cAxis = {
 
350
                x: (scrollWidth > width),
 
351
                y: (scrollHeight > height)
 
352
            };
 
353
 
 
354
            sv._set(AXIS, sv._cAxis);
 
355
        }
 
356
        
 
357
        // get text direction on or inherited by scrollview node
 
358
        sv.rtl = (sv._cb.getComputedStyle('direction') === 'rtl');
 
359
 
 
360
        // Cache the disabled value
 
361
        sv._cDisabled = sv.get(DISABLED);
 
362
 
 
363
        // Run this to set initial values
 
364
        sv._uiDimensionsChange();
 
365
 
 
366
        // If we're out-of-bounds, snap back.
 
367
        if (sv._isOutOfBounds()) {
 
368
            sv._snapBack();
 
369
        }
 
370
    },
 
371
 
 
372
    /**
 
373
     * Utility method to obtain widget dimensions
 
374
     *
 
375
     * @method _getScrollDims
 
376
     * @return {Object} The offsetWidth, offsetHeight, scrollWidth and
 
377
     *  scrollHeight as an array: [offsetWidth, offsetHeight, scrollWidth,
 
378
     *  scrollHeight]
 
379
     * @private
 
380
     */
 
381
    _getScrollDims: function () {
 
382
        var sv = this,
 
383
            cb = sv._cb,
 
384
            bb = sv._bb,
 
385
            TRANS = ScrollView._TRANSITION,
 
386
            // Ideally using CSSMatrix - don't think we have it normalized yet though.
 
387
            // origX = (new WebKitCSSMatrix(cb.getComputedStyle("transform"))).e,
 
388
            // origY = (new WebKitCSSMatrix(cb.getComputedStyle("transform"))).f,
 
389
            origX = sv.get(SCROLL_X),
 
390
            origY = sv.get(SCROLL_Y),
 
391
            origHWTransform,
 
392
            dims;
 
393
 
 
394
        // TODO: Is this OK? Just in case it's called 'during' a transition.
 
395
        if (NATIVE_TRANSITIONS) {
 
396
            cb.setStyle(TRANS.DURATION, ZERO);
 
397
            cb.setStyle(TRANS.PROPERTY, EMPTY);
 
398
        }
 
399
 
 
400
        origHWTransform = sv._forceHWTransforms;
 
401
        sv._forceHWTransforms = false; // the z translation was causing issues with picking up accurate scrollWidths in Chrome/Mac.
 
402
 
 
403
        sv._moveTo(cb, 0, 0);
 
404
        dims = {
 
405
            'offsetWidth': bb.get('offsetWidth'),
 
406
            'offsetHeight': bb.get('offsetHeight'),
 
407
            'scrollWidth': bb.get('scrollWidth'),
 
408
            'scrollHeight': bb.get('scrollHeight')
 
409
        };
 
410
        sv._moveTo(cb, -(origX), -(origY));
 
411
 
 
412
        sv._forceHWTransforms = origHWTransform;
 
413
 
 
414
        return dims;
 
415
    },
 
416
 
 
417
    /**
 
418
     * This method gets invoked whenever the height or width attributes change,
 
419
     * allowing us to determine which scrolling axes need to be enabled.
 
420
     *
 
421
     * @method _uiDimensionsChange
 
422
     * @protected
 
423
     */
 
424
    _uiDimensionsChange: function () {
 
425
        var sv = this,
 
426
            bb = sv._bb,
 
427
            scrollDims = sv._getScrollDims(),
 
428
            width = scrollDims.offsetWidth,
 
429
            height = scrollDims.offsetHeight,
 
430
            scrollWidth = scrollDims.scrollWidth,
 
431
            scrollHeight = scrollDims.scrollHeight,
 
432
            rtl = sv.rtl,
 
433
            svAxis = sv._cAxis,
 
434
            minScrollX = (rtl ? Math.min(0, -(scrollWidth - width)) : 0),
 
435
            maxScrollX = (rtl ? 0 : Math.max(0, scrollWidth - width)),
 
436
            minScrollY = 0,
 
437
            maxScrollY = Math.max(0, scrollHeight - height);
 
438
            
 
439
        if (svAxis && svAxis.x) {
 
440
            bb.addClass(CLASS_NAMES.horizontal);
 
441
        }
 
442
 
 
443
        if (svAxis && svAxis.y) {
 
444
            bb.addClass(CLASS_NAMES.vertical);
 
445
        }
 
446
 
 
447
        sv._setBounds({
 
448
            minScrollX: minScrollX,
 
449
            maxScrollX: maxScrollX,
 
450
            minScrollY: minScrollY,
 
451
            maxScrollY: maxScrollY
 
452
        });
 
453
    },
 
454
 
 
455
    /**
 
456
     * Set the bounding dimensions of the ScrollView
 
457
     *
 
458
     * @method _setBounds
 
459
     * @protected
 
460
     * @param bounds {Object} [duration] ms of the scroll animation. (default is 0)
 
461
     *   @param {Number} [bounds.minScrollX] The minimum scroll X value
 
462
     *   @param {Number} [bounds.maxScrollX] The maximum scroll X value
 
463
     *   @param {Number} [bounds.minScrollY] The minimum scroll Y value
 
464
     *   @param {Number} [bounds.maxScrollY] The maximum scroll Y value
 
465
     */
 
466
    _setBounds: function (bounds) {
 
467
        var sv = this;
 
468
        
 
469
        // TODO: Do a check to log if the bounds are invalid
 
470
 
 
471
        sv._minScrollX = bounds.minScrollX;
 
472
        sv._maxScrollX = bounds.maxScrollX;
 
473
        sv._minScrollY = bounds.minScrollY;
 
474
        sv._maxScrollY = bounds.maxScrollY;
 
475
    },
 
476
 
 
477
    /**
 
478
     * Get the bounding dimensions of the ScrollView
 
479
     *
 
480
     * @method _getBounds
 
481
     * @protected
 
482
     */
 
483
    _getBounds: function () {
 
484
        var sv = this;
 
485
        
 
486
        return {
 
487
            minScrollX: sv._minScrollX,
 
488
            maxScrollX: sv._maxScrollX,
 
489
            minScrollY: sv._minScrollY,
 
490
            maxScrollY: sv._maxScrollY
 
491
        };
 
492
 
 
493
    },
 
494
 
 
495
    /**
 
496
     * Scroll the element to a given xy coordinate
 
497
     *
 
498
     * @method scrollTo
 
499
     * @param x {Number} The x-position to scroll to. (null for no movement)
 
500
     * @param y {Number} The y-position to scroll to. (null for no movement)
 
501
     * @param {Number} [duration] ms of the scroll animation. (default is 0)
 
502
     * @param {String} [easing] An easing equation if duration is set. (default is `easing` attribute)
 
503
     * @param {String} [node] The node to transform.  Setting this can be useful in
 
504
     *  dual-axis paginated instances. (default is the instance's contentBox)
 
505
     */
 
506
    scrollTo: function (x, y, duration, easing, node) {
 
507
        // Check to see if widget is disabled
 
508
        if (this._cDisabled) {
 
509
            return;
 
510
        }
 
511
 
 
512
        var sv = this,
 
513
            cb = sv._cb,
 
514
            TRANS = ScrollView._TRANSITION,
 
515
            callback = Y.bind(sv._onTransEnd, sv), // @Todo : cache this
 
516
            newX = 0,
 
517
            newY = 0,
 
518
            transition = {},
 
519
            transform;
 
520
 
 
521
        // default the optional arguments
 
522
        duration = duration || 0;
 
523
        easing = easing || sv.get(EASING); // @TODO: Cache this
 
524
        node = node || cb;
 
525
 
 
526
        if (x !== null) {
 
527
            sv.set(SCROLL_X, x, {src:UI});
 
528
            newX = -(x);
 
529
        }
 
530
 
 
531
        if (y !== null) {
 
532
            sv.set(SCROLL_Y, y, {src:UI});
 
533
            newY = -(y);
 
534
        }
 
535
 
 
536
        transform = sv._transform(newX, newY);
 
537
 
 
538
        if (NATIVE_TRANSITIONS) {
 
539
            // ANDROID WORKAROUND - try and stop existing transition, before kicking off new one.
 
540
            node.setStyle(TRANS.DURATION, ZERO).setStyle(TRANS.PROPERTY, EMPTY);
 
541
        }
 
542
 
 
543
        // Move
 
544
        if (duration === 0) {
 
545
            if (NATIVE_TRANSITIONS) {
 
546
                node.setStyle('transform', transform);
 
547
            }
 
548
            else {
 
549
                // TODO: If both set, batch them in the same update
 
550
                // Update: Nope, setStyles() just loops through each property and applies it.
 
551
                if (x !== null) {
 
552
                    node.setStyle(LEFT, newX + PX);
 
553
                }
 
554
                if (y !== null) {
 
555
                    node.setStyle(TOP, newY + PX);
 
556
                }
 
557
            }
 
558
        }
 
559
 
 
560
        // Animate
 
561
        else {
 
562
            transition.easing = easing;
 
563
            transition.duration = duration / 1000;
 
564
 
 
565
            if (NATIVE_TRANSITIONS) {
 
566
                transition.transform = transform;
 
567
            }
 
568
            else {
 
569
                transition.left = newX + PX;
 
570
                transition.top = newY + PX;
 
571
            }
 
572
 
 
573
            node.transition(transition, callback);
 
574
        }
 
575
    },
 
576
 
 
577
    /**
 
578
     * Utility method, to create the translate transform string with the
 
579
     * x, y translation amounts provided.
 
580
     *
 
581
     * @method _transform
 
582
     * @param {Number} x Number of pixels to translate along the x axis
 
583
     * @param {Number} y Number of pixels to translate along the y axis
 
584
     * @private
 
585
     */
 
586
    _transform: function (x, y) {
 
587
        // TODO: Would we be better off using a Matrix for this?
 
588
        var prop = 'translate(' + x + 'px, ' + y + 'px)';
 
589
 
 
590
        if (this._forceHWTransforms) {
 
591
            prop += ' translateZ(0)';
 
592
        }
 
593
 
 
594
        return prop;
 
595
    },
 
596
 
 
597
    /**
 
598
    * Utility method, to move the given element to the given xy position
 
599
    *
 
600
    * @method _moveTo
 
601
    * @param node {Node} The node to move
 
602
    * @param x {Number} The x-position to move to
 
603
    * @param y {Number} The y-position to move to
 
604
    * @private
 
605
    */
 
606
    _moveTo : function(node, x, y) {
 
607
        if (NATIVE_TRANSITIONS) {
 
608
            node.setStyle('transform', this._transform(x, y));
 
609
        } else {
 
610
            node.setStyle(LEFT, x + PX);
 
611
            node.setStyle(TOP, y + PX);
 
612
        }
 
613
    },
 
614
 
 
615
 
 
616
    /**
 
617
     * Content box transition callback
 
618
     *
 
619
     * @method _onTransEnd
 
620
     * @param {Event.Facade} e The event facade
 
621
     * @private
 
622
     */
 
623
    _onTransEnd: function () {
 
624
        var sv = this;
 
625
        
 
626
        // If for some reason we're OOB, snapback
 
627
        if (sv._isOutOfBounds()) {
 
628
            sv._snapBack();
 
629
        }
 
630
        else {
 
631
            /**
 
632
             * Notification event fired at the end of a scroll transition
 
633
             *
 
634
             * @event scrollEnd
 
635
             * @param e {EventFacade} The default event facade.
 
636
             */
 
637
            sv.fire(EV_SCROLL_END);
 
638
        }
 
639
    },
 
640
 
 
641
    /**
 
642
     * gesturemovestart event handler
 
643
     *
 
644
     * @method _onGestureMoveStart
 
645
     * @param e {Event.Facade} The gesturemovestart event facade
 
646
     * @private
 
647
     */
 
648
    _onGestureMoveStart: function (e) {
 
649
 
 
650
        if (this._cDisabled) {
 
651
            return false;
 
652
        }
 
653
 
 
654
        var sv = this,
 
655
            bb = sv._bb,
 
656
            currentX = sv.get(SCROLL_X),
 
657
            currentY = sv.get(SCROLL_Y),
 
658
            clientX = e.clientX,
 
659
            clientY = e.clientY;
 
660
 
 
661
        if (sv._prevent.start) {
 
662
            e.preventDefault();
 
663
        }
 
664
 
 
665
        // if a flick animation is in progress, cancel it
 
666
        if (sv._flickAnim) {
 
667
            sv._cancelFlick();
 
668
            sv._onTransEnd();
 
669
        }
 
670
 
 
671
        // Reset lastScrolledAmt
 
672
        sv.lastScrolledAmt = 0;
 
673
 
 
674
        // Stores data for this gesture cycle.  Cleaned up later
 
675
        sv._gesture = {
 
676
 
 
677
            // Will hold the axis value
 
678
            axis: null,
 
679
 
 
680
            // The current attribute values
 
681
            startX: currentX,
 
682
            startY: currentY,
 
683
 
 
684
            // The X/Y coordinates where the event began
 
685
            startClientX: clientX,
 
686
            startClientY: clientY,
 
687
 
 
688
            // The X/Y coordinates where the event will end
 
689
            endClientX: null,
 
690
            endClientY: null,
 
691
 
 
692
            // The current delta of the event
 
693
            deltaX: null,
 
694
            deltaY: null,
 
695
 
 
696
            // Will be populated for flicks
 
697
            flick: null,
 
698
 
 
699
            // Create some listeners for the rest of the gesture cycle
 
700
            onGestureMove: bb.on(DRAG + '|' + GESTURE_MOVE, Y.bind(sv._onGestureMove, sv)),
 
701
            
 
702
            // @TODO: Don't bind gestureMoveEnd if it's a Flick?
 
703
            onGestureMoveEnd: bb.on(DRAG + '|' + GESTURE_MOVE + END, Y.bind(sv._onGestureMoveEnd, sv))
 
704
        };
 
705
    },
 
706
 
 
707
    /**
 
708
     * gesturemove event handler
 
709
     *
 
710
     * @method _onGestureMove
 
711
     * @param e {Event.Facade} The gesturemove event facade
 
712
     * @private
 
713
     */
 
714
    _onGestureMove: function (e) {
 
715
        var sv = this,
 
716
            gesture = sv._gesture,
 
717
            svAxis = sv._cAxis,
 
718
            svAxisX = svAxis.x,
 
719
            svAxisY = svAxis.y,
 
720
            startX = gesture.startX,
 
721
            startY = gesture.startY,
 
722
            startClientX = gesture.startClientX,
 
723
            startClientY = gesture.startClientY,
 
724
            clientX = e.clientX,
 
725
            clientY = e.clientY;
 
726
 
 
727
        if (sv._prevent.move) {
 
728
            e.preventDefault();
 
729
        }
 
730
 
 
731
        gesture.deltaX = startClientX - clientX;
 
732
        gesture.deltaY = startClientY - clientY;
 
733
 
 
734
        // Determine if this is a vertical or horizontal movement
 
735
        // @TODO: This is crude, but it works.  Investigate more intelligent ways to detect intent
 
736
        if (gesture.axis === null) {
 
737
            gesture.axis = (Math.abs(gesture.deltaX) > Math.abs(gesture.deltaY)) ? DIM_X : DIM_Y;
 
738
        }
 
739
 
 
740
        // Move X or Y.  @TODO: Move both if dualaxis.
 
741
        if (gesture.axis === DIM_X && svAxisX) {
 
742
            sv.set(SCROLL_X, startX + gesture.deltaX);
 
743
        }
 
744
        else if (gesture.axis === DIM_Y && svAxisY) {
 
745
            sv.set(SCROLL_Y, startY + gesture.deltaY);
 
746
        }
 
747
    },
 
748
 
 
749
    /**
 
750
     * gesturemoveend event handler
 
751
     *
 
752
     * @method _onGestureMoveEnd
 
753
     * @param e {Event.Facade} The gesturemoveend event facade
 
754
     * @private
 
755
     */
 
756
    _onGestureMoveEnd: function (e) {
 
757
        var sv = this,
 
758
            gesture = sv._gesture,
 
759
            flick = gesture.flick,
 
760
            clientX = e.clientX,
 
761
            clientY = e.clientY,
 
762
            isOOB;
 
763
 
 
764
        if (sv._prevent.end) {
 
765
            e.preventDefault();
 
766
        }
 
767
 
 
768
        // Store the end X/Y coordinates
 
769
        gesture.endClientX = clientX;
 
770
        gesture.endClientY = clientY;
 
771
 
 
772
        // Cleanup the event handlers
 
773
        gesture.onGestureMove.detach();
 
774
        gesture.onGestureMoveEnd.detach();
 
775
 
 
776
        // If this wasn't a flick, wrap up the gesture cycle
 
777
        if (!flick) {
 
778
            // @TODO: Be more intelligent about this. Look at the Flick attribute to see
 
779
            // if it is safe to assume _flick did or didn't fire.
 
780
            // Then, the order _flick and _onGestureMoveEnd fire doesn't matter?
 
781
 
 
782
            // If there was movement (_onGestureMove fired)
 
783
            if (gesture.deltaX !== null && gesture.deltaY !== null) {
 
784
                
 
785
                isOOB = sv._isOutOfBounds();
 
786
                
 
787
                // If we're out-out-bounds, then snapback
 
788
                if (isOOB) {
 
789
                    sv._snapBack();
 
790
                }
 
791
 
 
792
                // Inbounds
 
793
                else {
 
794
                    // Fire scrollEnd unless this is a paginated instance and the gesture axis is the same as paginator's
 
795
                    // Not totally confident this is ideal to access a plugin's properties from a host, @TODO revisit
 
796
                    if (!sv.pages || (sv.pages && !sv.pages.get(AXIS)[gesture.axis])) {
 
797
                        sv._onTransEnd();
 
798
                    }
 
799
                }
 
800
            }
 
801
        }
 
802
    },
 
803
 
 
804
    /**
 
805
     * Execute a flick at the end of a scroll action
 
806
     *
 
807
     * @method _flick
 
808
     * @param e {Event.Facade} The Flick event facade
 
809
     * @private
 
810
     */
 
811
    _flick: function (e) {
 
812
        if (this._cDisabled) {
 
813
            return false;
 
814
        }
 
815
 
 
816
        var sv = this,
 
817
            svAxis = sv._cAxis,
 
818
            flick = e.flick,
 
819
            flickAxis = flick.axis,
 
820
            flickVelocity = flick.velocity,
 
821
            axisAttr = flickAxis === DIM_X ? SCROLL_X : SCROLL_Y,
 
822
            startPosition = sv.get(axisAttr);
 
823
 
 
824
        // Sometimes flick is enabled, but drag is disabled
 
825
        if (sv._gesture) {
 
826
            sv._gesture.flick = flick;
 
827
        }
 
828
 
 
829
        // Prevent unneccesary firing of _flickFrame if we can't scroll on the flick axis
 
830
        if (svAxis[flickAxis]) {
 
831
            sv._flickFrame(flickVelocity, flickAxis, startPosition);
 
832
        }
 
833
    },
 
834
 
 
835
    /**
 
836
     * Execute a single frame in the flick animation
 
837
     *
 
838
     * @method _flickFrame
 
839
     * @param velocity {Number} The velocity of this animated frame
 
840
     * @param flickAxis {String} The axis on which to animate
 
841
     * @param startPosition {Number} The starting X/Y point to flick from
 
842
     * @protected
 
843
     */
 
844
    _flickFrame: function (velocity, flickAxis, startPosition) {
 
845
 
 
846
        var sv = this,
 
847
            axisAttr = flickAxis === DIM_X ? SCROLL_X : SCROLL_Y,
 
848
            bounds = sv._getBounds(),
 
849
 
 
850
            // Localize cached values
 
851
            bounce = sv._cBounce,
 
852
            bounceRange = sv._cBounceRange,
 
853
            deceleration = sv._cDeceleration,
 
854
            frameDuration = sv._cFrameDuration,
 
855
 
 
856
            // Calculate
 
857
            newVelocity = velocity * deceleration,
 
858
            newPosition = startPosition - (frameDuration * newVelocity),
 
859
 
 
860
            // Some convinience conditions
 
861
            min = flickAxis === DIM_X ? bounds.minScrollX : bounds.minScrollY,
 
862
            max = flickAxis === DIM_X ? bounds.maxScrollX : bounds.maxScrollY,
 
863
            belowMin       = (newPosition < min),
 
864
            belowMax       = (newPosition < max),
 
865
            aboveMin       = (newPosition > min),
 
866
            aboveMax       = (newPosition > max),
 
867
            belowMinRange  = (newPosition < (min - bounceRange)),
 
868
            withinMinRange = (belowMin && (newPosition > (min - bounceRange))),
 
869
            withinMaxRange = (aboveMax && (newPosition < (max + bounceRange))),
 
870
            aboveMaxRange  = (newPosition > (max + bounceRange)),
 
871
            tooSlow;
 
872
 
 
873
        // If we're within the range but outside min/max, dampen the velocity
 
874
        if (withinMinRange || withinMaxRange) {
 
875
            newVelocity *= bounce;
 
876
        }
 
877
 
 
878
        // Is the velocity too slow to bother?
 
879
        tooSlow = (Math.abs(newVelocity).toFixed(4) < 0.015);
 
880
 
 
881
        // If the velocity is too slow or we're outside the range
 
882
        if (tooSlow || belowMinRange || aboveMaxRange) {
 
883
            // Cancel and delete sv._flickAnim
 
884
            if (sv._flickAnim) {
 
885
                sv._cancelFlick();
 
886
            }
 
887
 
 
888
            // If we're inside the scroll area, just end
 
889
            if (aboveMin && belowMax) {
 
890
                sv._onTransEnd();
 
891
            }
 
892
 
 
893
            // We're outside the scroll area, so we need to snap back
 
894
            else {
 
895
                sv._snapBack();
 
896
            }
 
897
        }
 
898
 
 
899
        // Otherwise, animate to the next frame
 
900
        else {
 
901
            // @TODO: maybe use requestAnimationFrame instead
 
902
            sv._flickAnim = Y.later(frameDuration, sv, '_flickFrame', [newVelocity, flickAxis, newPosition]);
 
903
            sv.set(axisAttr, newPosition);
 
904
        }
 
905
    },
 
906
 
 
907
    _cancelFlick: function () {
 
908
        var sv = this;
 
909
 
 
910
        if (sv._flickAnim) {
 
911
            // Cancel the flick (if it exists)
 
912
            sv._flickAnim.cancel();
 
913
 
 
914
            // Also delete it, otherwise _onGestureMoveStart will think we're still flicking
 
915
            delete sv._flickAnim;
 
916
        }
 
917
 
 
918
    },
 
919
 
 
920
    /**
 
921
     * Handle mousewheel events on the widget
 
922
     *
 
923
     * @method _mousewheel
 
924
     * @param e {Event.Facade} The mousewheel event facade
 
925
     * @private
 
926
     */
 
927
    _mousewheel: function (e) {
 
928
        var sv = this,
 
929
            scrollY = sv.get(SCROLL_Y),
 
930
            bounds = sv._getBounds(),
 
931
            bb = sv._bb,
 
932
            scrollOffset = 10, // 10px
 
933
            isForward = (e.wheelDelta > 0),
 
934
            scrollToY = scrollY - ((isForward ? 1 : -1) * scrollOffset);
 
935
 
 
936
        scrollToY = _constrain(scrollToY, bounds.minScrollY, bounds.maxScrollY);
 
937
 
 
938
        // Because Mousewheel events fire off 'document', every ScrollView widget will react
 
939
        // to any mousewheel anywhere on the page. This check will ensure that the mouse is currently
 
940
        // over this specific ScrollView.  Also, only allow mousewheel scrolling on Y-axis,
 
941
        // becuase otherwise the 'prevent' will block page scrolling.
 
942
        if (bb.contains(e.target) && sv._cAxis[DIM_Y]) {
 
943
 
 
944
            // Reset lastScrolledAmt
 
945
            sv.lastScrolledAmt = 0;
 
946
 
 
947
            // Jump to the new offset
 
948
            sv.set(SCROLL_Y, scrollToY);
 
949
 
 
950
            // if we have scrollbars plugin, update & set the flash timer on the scrollbar
 
951
            // @TODO: This probably shouldn't be in this module
 
952
            if (sv.scrollbars) {
 
953
                // @TODO: The scrollbars should handle this themselves
 
954
                sv.scrollbars._update();
 
955
                sv.scrollbars.flash();
 
956
                // or just this
 
957
                // sv.scrollbars._hostDimensionsChange();
 
958
            }
 
959
 
 
960
            // Fire the 'scrollEnd' event
 
961
            sv._onTransEnd();
 
962
 
 
963
            // prevent browser default behavior on mouse scroll
 
964
            e.preventDefault();
 
965
        }
 
966
    },
 
967
 
 
968
    /**
 
969
     * Checks to see the current scrollX/scrollY position beyond the min/max boundary
 
970
     *
 
971
     * @method _isOutOfBounds
 
972
     * @param x {Number} [optional] The X position to check
 
973
     * @param y {Number} [optional] The Y position to check
 
974
     * @return {boolen} Whether the current X/Y position is out of bounds (true) or not (false)
 
975
     * @private
 
976
     */
 
977
    _isOutOfBounds: function (x, y) {
 
978
        var sv = this,
 
979
            svAxis = sv._cAxis,
 
980
            svAxisX = svAxis.x,
 
981
            svAxisY = svAxis.y,
 
982
            currentX = x || sv.get(SCROLL_X),
 
983
            currentY = y || sv.get(SCROLL_Y),
 
984
            bounds = sv._getBounds(),
 
985
            minX = bounds.minScrollX,
 
986
            minY = bounds.minScrollY,
 
987
            maxX = bounds.maxScrollX,
 
988
            maxY = bounds.maxScrollY;
 
989
 
 
990
        return (svAxisX && (currentX < minX || currentX > maxX)) || (svAxisY && (currentY < minY || currentY > maxY));
 
991
    },
 
992
 
 
993
    /**
 
994
     * Bounces back
 
995
     * @TODO: Should be more generalized and support both X and Y detection
 
996
     *
 
997
     * @method _snapBack
 
998
     * @private
 
999
     */
 
1000
    _snapBack: function () {
 
1001
        var sv = this,
 
1002
            currentX = sv.get(SCROLL_X),
 
1003
            currentY = sv.get(SCROLL_Y),
 
1004
            bounds = sv._getBounds(),
 
1005
            minX = bounds.minScrollX,
 
1006
            minY = bounds.minScrollY,
 
1007
            maxX = bounds.maxScrollX,
 
1008
            maxY = bounds.maxScrollY,
 
1009
            newY = _constrain(currentY, minY, maxY),
 
1010
            newX = _constrain(currentX, minX, maxX),
 
1011
            duration = sv.get(SNAP_DURATION),
 
1012
            easing = sv.get(SNAP_EASING);
 
1013
 
 
1014
        if (newX !== currentX) {
 
1015
            sv.set(SCROLL_X, newX, {duration:duration, easing:easing});
 
1016
        }
 
1017
        else if (newY !== currentY) {
 
1018
            sv.set(SCROLL_Y, newY, {duration:duration, easing:easing});
 
1019
        }
 
1020
        else {
 
1021
            sv._onTransEnd();
 
1022
        }
 
1023
    },
 
1024
 
 
1025
    /**
 
1026
     * After listener for changes to the scrollX or scrollY attribute
 
1027
     *
 
1028
     * @method _afterScrollChange
 
1029
     * @param e {Event.Facade} The event facade
 
1030
     * @protected
 
1031
     */
 
1032
    _afterScrollChange: function (e) {
 
1033
        if (e.src === ScrollView.UI_SRC) {
 
1034
            return false;
 
1035
        }
 
1036
 
 
1037
        var sv = this,
 
1038
            duration = e.duration,
 
1039
            easing = e.easing,
 
1040
            val = e.newVal,
 
1041
            scrollToArgs = [];
 
1042
 
 
1043
        // Set the scrolled value
 
1044
        sv.lastScrolledAmt = sv.lastScrolledAmt + (e.newVal - e.prevVal);
 
1045
 
 
1046
        // Generate the array of args to pass to scrollTo()
 
1047
        if (e.attrName === SCROLL_X) {
 
1048
            scrollToArgs.push(val);
 
1049
            scrollToArgs.push(sv.get(SCROLL_Y));
 
1050
        }
 
1051
        else {
 
1052
            scrollToArgs.push(sv.get(SCROLL_X));
 
1053
            scrollToArgs.push(val);
 
1054
        }
 
1055
 
 
1056
        scrollToArgs.push(duration);
 
1057
        scrollToArgs.push(easing);
 
1058
 
 
1059
        sv.scrollTo.apply(sv, scrollToArgs);
 
1060
    },
 
1061
 
 
1062
    /**
 
1063
     * After listener for changes to the flick attribute
 
1064
     *
 
1065
     * @method _afterFlickChange
 
1066
     * @param e {Event.Facade} The event facade
 
1067
     * @protected
 
1068
     */
 
1069
    _afterFlickChange: function (e) {
 
1070
        this._bindFlick(e.newVal);
 
1071
    },
 
1072
 
 
1073
    /**
 
1074
     * After listener for changes to the disabled attribute
 
1075
     *
 
1076
     * @method _afterDisabledChange
 
1077
     * @param e {Event.Facade} The event facade
 
1078
     * @protected
 
1079
     */
 
1080
    _afterDisabledChange: function (e) {
 
1081
        // Cache for performance - we check during move
 
1082
        this._cDisabled = e.newVal;
 
1083
    },
 
1084
 
 
1085
    /**
 
1086
     * After listener for the axis attribute
 
1087
     *
 
1088
     * @method _afterAxisChange
 
1089
     * @param e {Event.Facade} The event facade
 
1090
     * @protected
 
1091
     */
 
1092
    _afterAxisChange: function (e) {
 
1093
        this._cAxis = e.newVal;
 
1094
    },
 
1095
 
 
1096
    /**
 
1097
     * After listener for changes to the drag attribute
 
1098
     *
 
1099
     * @method _afterDragChange
 
1100
     * @param e {Event.Facade} The event facade
 
1101
     * @protected
 
1102
     */
 
1103
    _afterDragChange: function (e) {
 
1104
        this._bindDrag(e.newVal);
 
1105
    },
 
1106
 
 
1107
    /**
 
1108
     * After listener for the height or width attribute
 
1109
     *
 
1110
     * @method _afterDimChange
 
1111
     * @param e {Event.Facade} The event facade
 
1112
     * @protected
 
1113
     */
 
1114
    _afterDimChange: function () {
 
1115
        this._uiDimensionsChange();
 
1116
    },
 
1117
 
 
1118
    /**
 
1119
     * After listener for scrollEnd, for cleanup
 
1120
     *
 
1121
     * @method _afterScrollEnd
 
1122
     * @param e {Event.Facade} The event facade
 
1123
     * @protected
 
1124
     */
 
1125
    _afterScrollEnd: function () {
 
1126
        var sv = this;
 
1127
 
 
1128
        if (sv._flickAnim) {
 
1129
            sv._cancelFlick();
 
1130
        }
 
1131
 
 
1132
        // Ideally this should be removed, but doing so causing some JS errors with fast swiping
 
1133
        // because _gesture is being deleted after the previous one has been overwritten
 
1134
        // delete sv._gesture; // TODO: Move to sv.prevGesture?
 
1135
    },
 
1136
 
 
1137
    /**
 
1138
     * Setter for 'axis' attribute
 
1139
     *
 
1140
     * @method _axisSetter
 
1141
     * @param val {Mixed} A string ('x', 'y', 'xy') to specify which axis/axes to allow scrolling on
 
1142
     * @param name {String} The attribute name
 
1143
     * @return {Object} An object to specify scrollability on the x & y axes
 
1144
     *
 
1145
     * @protected
 
1146
     */
 
1147
    _axisSetter: function (val) {
 
1148
 
 
1149
        // Turn a string into an axis object
 
1150
        if (Y.Lang.isString(val)) {
 
1151
            return {
 
1152
                x: val.match(/x/i) ? true : false,
 
1153
                y: val.match(/y/i) ? true : false
 
1154
            };
 
1155
        }
 
1156
    },
 
1157
    
 
1158
    /**
 
1159
    * The scrollX, scrollY setter implementation
 
1160
    *
 
1161
    * @method _setScroll
 
1162
    * @private
 
1163
    * @param {Number} val
 
1164
    * @param {String} dim
 
1165
    *
 
1166
    * @return {Number} The value
 
1167
    */
 
1168
    _setScroll : function(val) {
 
1169
 
 
1170
        // Just ensure the widget is not disabled
 
1171
        if (this._cDisabled) {
 
1172
            val = Y.Attribute.INVALID_VALUE;
 
1173
        }
 
1174
 
 
1175
        return val;
 
1176
    },
 
1177
 
 
1178
    /**
 
1179
    * Setter for the scrollX attribute
 
1180
    *
 
1181
    * @method _setScrollX
 
1182
    * @param val {Number} The new scrollX value
 
1183
    * @return {Number} The normalized value
 
1184
    * @protected
 
1185
    */
 
1186
    _setScrollX: function(val) {
 
1187
        return this._setScroll(val, DIM_X);
 
1188
    },
 
1189
 
 
1190
    /**
 
1191
    * Setter for the scrollY ATTR
 
1192
    *
 
1193
    * @method _setScrollY
 
1194
    * @param val {Number} The new scrollY value
 
1195
    * @return {Number} The normalized value
 
1196
    * @protected
 
1197
    */
 
1198
    _setScrollY: function(val) {
 
1199
        return this._setScroll(val, DIM_Y);
 
1200
    }
 
1201
 
 
1202
    // End prototype properties
 
1203
 
 
1204
}, {
 
1205
 
 
1206
    // Static properties
 
1207
 
 
1208
    /**
 
1209
     * The identity of the widget.
 
1210
     *
 
1211
     * @property NAME
 
1212
     * @type String
 
1213
     * @default 'scrollview'
 
1214
     * @readOnly
 
1215
     * @protected
 
1216
     * @static
 
1217
     */
 
1218
    NAME: 'scrollview',
 
1219
 
 
1220
    /**
 
1221
     * Static property used to define the default attribute configuration of
 
1222
     * the Widget.
 
1223
     *
 
1224
     * @property ATTRS
 
1225
     * @type {Object}
 
1226
     * @protected
 
1227
     * @static
 
1228
     */
 
1229
    ATTRS: {
 
1230
 
 
1231
        /**
 
1232
         * Specifies ability to scroll on x, y, or x and y axis/axes.
 
1233
         *
 
1234
         * @attribute axis
 
1235
         * @type String
 
1236
         */
 
1237
        axis: {
 
1238
            setter: '_axisSetter',
 
1239
            writeOnce: 'initOnly'
 
1240
        },
 
1241
 
 
1242
        /**
 
1243
         * The current scroll position in the x-axis
 
1244
         *
 
1245
         * @attribute scrollX
 
1246
         * @type Number
 
1247
         * @default 0
 
1248
         */
 
1249
        scrollX: {
 
1250
            value: 0,
 
1251
            setter: '_setScrollX'
 
1252
        },
 
1253
 
 
1254
        /**
 
1255
         * The current scroll position in the y-axis
 
1256
         *
 
1257
         * @attribute scrollY
 
1258
         * @type Number
 
1259
         * @default 0
 
1260
         */
 
1261
        scrollY: {
 
1262
            value: 0,
 
1263
            setter: '_setScrollY'
 
1264
        },
 
1265
 
 
1266
        /**
 
1267
         * Drag coefficent for inertial scrolling. The closer to 1 this
 
1268
         * value is, the less friction during scrolling.
 
1269
         *
 
1270
         * @attribute deceleration
 
1271
         * @default 0.93
 
1272
         */
 
1273
        deceleration: {
 
1274
            value: 0.93
 
1275
        },
 
1276
 
 
1277
        /**
 
1278
         * Drag coefficient for intertial scrolling at the upper
 
1279
         * and lower boundaries of the scrollview. Set to 0 to
 
1280
         * disable "rubber-banding".
 
1281
         *
 
1282
         * @attribute bounce
 
1283
         * @type Number
 
1284
         * @default 0.1
 
1285
         */
 
1286
        bounce: {
 
1287
            value: 0.1
 
1288
        },
 
1289
 
 
1290
        /**
 
1291
         * The minimum distance and/or velocity which define a flick. Can be set to false,
 
1292
         * to disable flick support (note: drag support is enabled/disabled separately)
 
1293
         *
 
1294
         * @attribute flick
 
1295
         * @type Object
 
1296
         * @default Object with properties minDistance = 10, minVelocity = 0.3.
 
1297
         */
 
1298
        flick: {
 
1299
            value: {
 
1300
                minDistance: 10,
 
1301
                minVelocity: 0.3
 
1302
            }
 
1303
        },
 
1304
 
 
1305
        /**
 
1306
         * Enable/Disable dragging the ScrollView content (note: flick support is enabled/disabled separately)
 
1307
         * @attribute drag
 
1308
         * @type boolean
 
1309
         * @default true
 
1310
         */
 
1311
        drag: {
 
1312
            value: true
 
1313
        },
 
1314
 
 
1315
        /**
 
1316
         * The default duration to use when animating the bounce snap back.
 
1317
         *
 
1318
         * @attribute snapDuration
 
1319
         * @type Number
 
1320
         * @default 400
 
1321
         */
 
1322
        snapDuration: {
 
1323
            value: 400
 
1324
        },
 
1325
 
 
1326
        /**
 
1327
         * The default easing to use when animating the bounce snap back.
 
1328
         *
 
1329
         * @attribute snapEasing
 
1330
         * @type String
 
1331
         * @default 'ease-out'
 
1332
         */
 
1333
        snapEasing: {
 
1334
            value: 'ease-out'
 
1335
        },
 
1336
 
 
1337
        /**
 
1338
         * The default easing used when animating the flick
 
1339
         *
 
1340
         * @attribute easing
 
1341
         * @type String
 
1342
         * @default 'cubic-bezier(0, 0.1, 0, 1.0)'
 
1343
         */
 
1344
        easing: {
 
1345
            value: 'cubic-bezier(0, 0.1, 0, 1.0)'
 
1346
        },
 
1347
 
 
1348
        /**
 
1349
         * The interval (ms) used when animating the flick for JS-timer animations
 
1350
         *
 
1351
         * @attribute frameDuration
 
1352
         * @type Number
 
1353
         * @default 15
 
1354
         */
 
1355
        frameDuration: {
 
1356
            value: 15
 
1357
        },
 
1358
 
 
1359
        /**
 
1360
         * The default bounce distance in pixels
 
1361
         *
 
1362
         * @attribute bounceRange
 
1363
         * @type Number
 
1364
         * @default 150
 
1365
         */
 
1366
        bounceRange: {
 
1367
            value: 150
 
1368
        }
 
1369
    },
 
1370
 
 
1371
    /**
 
1372
     * List of class names used in the scrollview's DOM
 
1373
     *
 
1374
     * @property CLASS_NAMES
 
1375
     * @type Object
 
1376
     * @static
 
1377
     */
 
1378
    CLASS_NAMES: CLASS_NAMES,
 
1379
 
 
1380
    /**
 
1381
     * Flag used to source property changes initiated from the DOM
 
1382
     *
 
1383
     * @property UI_SRC
 
1384
     * @type String
 
1385
     * @static
 
1386
     * @default 'ui'
 
1387
     */
 
1388
    UI_SRC: UI,
 
1389
 
 
1390
    /**
 
1391
     * Object map of style property names used to set transition properties.
 
1392
     * Defaults to the vendor prefix established by the Transition module.
 
1393
     * The configured property names are `_TRANSITION.DURATION` (e.g. "WebkitTransitionDuration") and
 
1394
     * `_TRANSITION.PROPERTY (e.g. "WebkitTransitionProperty").
 
1395
     *
 
1396
     * @property _TRANSITION
 
1397
     * @private
 
1398
     */
 
1399
    _TRANSITION: {
 
1400
        DURATION: (vendorPrefix ? vendorPrefix + 'TransitionDuration' : 'transitionDuration'),
 
1401
        PROPERTY: (vendorPrefix ? vendorPrefix + 'TransitionProperty' : 'transitionProperty')
 
1402
    },
 
1403
 
 
1404
    /**
 
1405
     * The default bounce distance in pixels
 
1406
     *
 
1407
     * @property BOUNCE_RANGE
 
1408
     * @type Number
 
1409
     * @static
 
1410
     * @default false
 
1411
     * @deprecated (in 3.7.0)
 
1412
     */
 
1413
    BOUNCE_RANGE: false,
 
1414
 
 
1415
    /**
 
1416
     * The interval (ms) used when animating the flick
 
1417
     *
 
1418
     * @property FRAME_STEP
 
1419
     * @type Number
 
1420
     * @static
 
1421
     * @default false
 
1422
     * @deprecated (in 3.7.0)
 
1423
     */
 
1424
    FRAME_STEP: false,
 
1425
 
 
1426
    /**
 
1427
     * The default easing used when animating the flick
 
1428
     *
 
1429
     * @property EASING
 
1430
     * @type String
 
1431
     * @static
 
1432
     * @default false
 
1433
     * @deprecated (in 3.7.0)
 
1434
     */
 
1435
    EASING: false,
 
1436
 
 
1437
    /**
 
1438
     * The default easing to use when animating the bounce snap back.
 
1439
     *
 
1440
     * @property SNAP_EASING
 
1441
     * @type String
 
1442
     * @static
 
1443
     * @default false
 
1444
     * @deprecated (in 3.7.0)
 
1445
     */
 
1446
    SNAP_EASING: false,
 
1447
 
 
1448
    /**
 
1449
     * The default duration to use when animating the bounce snap back.
 
1450
     *
 
1451
     * @property SNAP_DURATION
 
1452
     * @type Number
 
1453
     * @static
 
1454
     * @default false
 
1455
     * @deprecated (in 3.7.0)
 
1456
     */
 
1457
    SNAP_DURATION: false
 
1458
 
 
1459
    // End static properties
 
1460
 
 
1461
});
 
1462
 
 
1463
}, '3.10.3', {"requires": ["widget", "event-gestures", "event-mousewheel", "transition"], "skinnable": true});