]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/scrollview/scrollview-base.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / scrollview / scrollview-base.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('scrollview-base', function(Y) {
9
10 /**
11  * The scrollview-base module provides a basic ScrollView Widget, without scrollbar indicators
12  *
13  * @module scrollview-base
14  */
15
16 var getClassName = Y.ClassNameManager.getClassName,
17     SCROLLVIEW = 'scrollview',
18     CLASS_NAMES = {
19         vertical: getClassName(SCROLLVIEW, 'vert'),
20         horizontal: getClassName(SCROLLVIEW, 'horiz')
21     },
22     EV_SCROLL_END = 'scrollEnd',
23     EV_SCROLL_FLICK = 'flick',
24
25     FLICK = EV_SCROLL_FLICK,
26
27     UI = 'ui',
28     
29     LEFT = "left",
30     TOP = "top",
31     
32     PX = "px",
33
34     SCROLL_Y = "scrollY",
35     SCROLL_X = "scrollX",
36     BOUNCE = "bounce",
37     
38     DIM_X = "x",
39     DIM_Y = "y",
40
41     BOUNDING_BOX = "boundingBox",
42     CONTENT_BOX = "contentBox",
43     
44     EMPTY = "",
45     ZERO = "0s",
46     
47     IE = Y.UA.ie,
48
49     NATIVE_TRANSITIONS = Y.Transition.useNative,
50     
51     _constrain = function (val, min, max) { 
52         return Math.min(Math.max(val, min), max);
53     };
54
55 Y.Node.DOM_EVENTS.DOMSubtreeModified = true;
56
57 /**
58  * ScrollView provides a scrollable widget, supporting flick gestures, across both touch and mouse based devices. 
59  *
60  * @class ScrollView
61  * @namespace 
62  * @param config {Object} Object literal with initial attribute values
63  * @extends Widget
64  * @constructor
65  */
66 function ScrollView() {
67     ScrollView.superclass.constructor.apply(this, arguments);
68 }
69
70 Y.ScrollView = Y.extend(ScrollView, Y.Widget, {
71     
72     // Y.ScrollView prototype
73     
74     /**
75      * Designated initializer
76      *
77      * @method initializer
78      */
79     initializer: function() {
80         /**
81          * Notification event fired at the end of a scroll transition
82          * 
83          * @event scrollEnd
84          * @param e {EventFacade} The default event facade.
85          */
86
87         /**
88          * Notification event fired at the end of a flick gesture (the flick animation may still be in progress)
89          * 
90          * @event flick
91          * @param e {EventFacade} The default event facade.
92          */
93         var sv = this;
94         
95         // Cache - they're write once, and not going to change
96         sv._cb = sv.get(CONTENT_BOX);
97         sv._bb = sv.get(BOUNDING_BOX);
98     },
99
100     /** 
101      * Override the contentBox sizing method, since the contentBox height
102      * should not be that of the boundingBox.
103      *
104      * @method _uiSizeCB
105      * @protected
106      */
107     _uiSizeCB: function() {},
108
109     /**
110      * Content box transition callback
111      *
112      * @method _onTransEnd
113      * @param {Event.Facade} e The event facade
114      * @private
115      */
116     _onTransEnd: function(e) {
117         this.fire(EV_SCROLL_END);
118     },
119
120     /**
121      * bindUI implementation
122      *
123      * Hooks up events for the widget
124      * @method bindUI
125      */
126     bindUI: function() {
127
128         var sv = this, // kweight
129             cb = sv._cb,
130             bb = sv._bb,
131             scrollChangeHandler = sv._afterScrollChange,
132             dimChangeHandler = sv._afterDimChange, 
133             flick = sv.get(FLICK); 
134
135         bb.on('gesturemovestart', Y.bind(sv._onGestureMoveStart, sv));
136
137         // IE SELECT HACK. See if we can do this non-natively and in the gesture for a future release.
138         if (IE) {
139             sv._fixIESelect(bb, cb);
140         }
141
142         // TODO: Fires way to often when using non-native transitions, due to property change
143         if (NATIVE_TRANSITIONS) {
144             cb.on('DOMSubtreeModified', Y.bind(sv._uiDimensionsChange, sv));
145         }
146
147         if (flick) {
148             cb.on("flick", Y.bind(sv._flick, sv), flick);
149         }
150
151         this.after({
152             'scrollYChange' : scrollChangeHandler,
153             'scrollXChange' : scrollChangeHandler,
154             'heightChange'  : dimChangeHandler,
155             'widthChange'   : dimChangeHandler
156         });
157     },
158
159     /**
160      * syncUI implementation
161      *
162      * Update the scroll position, based on the current value of scrollY
163      * @method bindUI
164      */
165     syncUI: function() {
166         this._uiDimensionsChange();
167         this.scrollTo(this.get(SCROLL_X), this.get(SCROLL_Y));
168     },
169
170     /**
171      * Scroll the element to a given y coordinate
172      *
173      * @method scrollTo
174      * @param x {Number} The x-position to scroll to
175      * @param y {Number} The y-position to scroll to
176      * @param duration {Number} Duration, in ms, of the scroll animation (default is 0)
177      * @param easing {String} An easing equation if duration is set
178      */
179     scrollTo: function(x, y, duration, easing) {
180         var cb = this._cb,
181             xSet = (x !== null),
182             ySet = (y !== null),
183             xMove = (xSet) ? x * -1 : 0,
184             yMove = (ySet) ? y * -1 : 0,
185             transition,
186             TRANS = ScrollView._TRANSITION,
187             callback = this._transEndCB;
188
189         duration = duration || 0;
190         easing = easing || ScrollView.EASING;
191
192         if (xSet) {
193             this.set(SCROLL_X, x, { src: UI });
194         }
195
196         if (ySet) {
197             this.set(SCROLL_Y, y, { src: UI });
198         }
199
200         if (NATIVE_TRANSITIONS) {
201             // ANDROID WORKAROUND - try and stop existing transition, before kicking off new one.
202             cb.setStyle(TRANS.DURATION, ZERO).setStyle(TRANS.PROPERTY, EMPTY);
203         }
204
205         if (duration !== 0) {
206
207             transition = {
208                 easing : easing,
209                 duration : duration/1000
210             };
211
212             if (NATIVE_TRANSITIONS) {
213                 transition.transform = 'translate3D('+ xMove +'px,'+ yMove +'px, 0px)';
214             } else {
215                 if (xSet) { transition.left = xMove + PX; }
216                 if (ySet) { transition.top = yMove + PX; }
217             }
218
219
220             if (!callback) {
221                 callback = this._transEndCB = Y.bind(this._onTransEnd, this);
222             }
223
224             cb.transition(transition, callback);
225
226         } else {
227             if (NATIVE_TRANSITIONS) {
228                 cb.setStyle('transform', 'translate3D('+ xMove +'px,'+ yMove +'px, 0px)');
229             } else {
230                 if (xSet) { cb.setStyle(LEFT, xMove + PX); }
231                 if (ySet) { cb.setStyle(TOP, yMove + PX); }
232             }
233         }
234     },
235
236     /**
237      * <p>Used to control whether or not ScrollView's internal
238      * gesturemovestart, gesturemove and gesturemoveend
239      * event listeners should preventDefault. The value is an
240      * object, with "start", "move" and "end" properties used to 
241      * specify which events should preventDefault and which shouldn't:</p>
242      *
243      * <pre>
244      * {
245      *    start : false,
246      *    move : true,
247      *    end : false
248      * }
249      * </pre>
250      *
251      * <p>The default values are set up in order to prevent panning,
252      * on touch devices, while allowing click listeners on elements inside 
253      * the ScrollView to be notified as expected.</p> 
254      *
255      * @property _prevent
256      * @type Object
257      * @protected
258      */
259     _prevent : {
260         start : false,
261         move : true,
262         end : false
263     },
264
265     /**
266      * gesturemovestart event handler
267      *
268      * @method _onGestureMoveStart
269      * @param e {Event.Facade} The gesturemovestart event facade
270      * @private
271      */
272     _onGestureMoveStart: function(e) {
273
274         var sv = this,
275             bb = sv._bb;
276
277         if (sv._prevent.start) {
278             e.preventDefault();
279         }
280
281         sv._killTimer();
282
283         sv._hm = bb.on('gesturemove', Y.bind(sv._onGestureMove, sv));
284         sv._hme = bb.on('gesturemoveend', Y.bind(sv._onGestureMoveEnd, sv));
285
286         sv._startY = e.clientY + sv.get(SCROLL_Y);
287         sv._startX = e.clientX + sv.get(SCROLL_X);
288         sv._startClientY = sv._endClientY = e.clientY;
289         sv._startClientX = sv._endClientX = e.clientX;
290
291         /**
292          * Internal state, defines whether or not the scrollview is currently being dragged
293          * 
294          * @property _isDragging
295          * @type boolean
296          * @protected
297          */
298         sv._isDragging = false;
299         
300         /**
301          * Internal state, defines whether or not the scrollview is currently animating a flick
302          * 
303          * @property _flicking
304          * @type boolean
305          * @protected
306          */
307         sv._flicking = false;
308         
309         /**
310          * Internal state, defines whether or not the scrollview needs to snap to a boundary edge
311          * 
312          * @property _snapToEdge
313          * @type boolean
314          * @protected
315          */
316         sv._snapToEdge = false;
317     },    
318     
319     /**
320      * gesturemove event handler
321      *
322      * @method _onGestureMove
323      * @param e {Event.Facade} The gesturemove event facade
324      * @private
325      */
326     _onGestureMove: function(e) {
327
328         var sv = this;
329
330         if (sv._prevent.move) {
331             e.preventDefault();
332         }
333
334         sv._isDragging = true;
335         sv._endClientY = e.clientY;
336         sv._endClientX = e.clientX;
337
338         if (sv._scrollsVertical) {
339             sv.set(SCROLL_Y, -(e.clientY - sv._startY));
340         }
341
342         if(sv._scrollsHorizontal) {
343             sv.set(SCROLL_X, -(e.clientX - sv._startX));
344         }
345     },
346
347     /**
348      * gestureend event handler
349      *
350      * @method _onGestureMoveEnd
351      * @param e {Event.Facade} The gesturemoveend event facade
352      * @private
353      */
354     _onGestureMoveEnd: function(e) {
355
356         if (this._prevent.end) {
357             e.preventDefault();
358         }
359
360         var sv = this, // kweight
361             minY = sv._minScrollY,
362             maxY = sv._maxScrollY,
363             minX = sv._minScrollX,
364             maxX = sv._maxScrollX,
365             vert = sv._scrollsVertical,
366             horiz = sv._scrollsHorizontal,
367             startPoint =  vert ? sv._startClientY : sv._startClientX,
368             endPoint = vert ? sv._endClientY : sv._endClientX,
369             distance = startPoint - endPoint,
370             absDistance = Math.abs(distance),
371             bb = sv._bb,
372             x, y, xOrig, yOrig;
373
374         sv._hm.detach();
375         sv._hme.detach();
376
377         /**
378          * Internal state, defines whether or not the scrollview has been scrolled half it's width/height
379          * 
380          * @property _scrolledHalfway
381          * @type boolean
382          * @protected
383          */
384         sv._scrolledHalfway = sv._snapToEdge = sv._isDragging = false;
385
386         /**
387          * Contains the distance (postive or negative) in pixels by which the scrollview was last scrolled. This is useful when
388          * setting up click listeners on the scrollview content, which on mouse based devices are always fired, even after a
389          * drag/flick. 
390          * 
391          * <p>Touch based devices don't currently fire a click event, if the finger has been moved (beyond a threshold) so this check isn't required,
392          * if working in a purely touch based environment</p>
393          * 
394          * @property lastScrolledAmt
395          * @type Number
396          * @public
397          */
398         sv.lastScrolledAmt = distance;
399
400         // Check for halfway
401         if((horiz && absDistance > bb.get('offsetWidth')/2) || (vert && absDistance > bb.get('offsetHeight')/2)) {
402             sv._scrolledHalfway = true;
403
404             /**
405              * Internal state, defines whether or not the scrollview has been scrolled in the forward (distance > 0), or backward (distance < 0) direction
406              * 
407              * @property _scrolledForward
408              * @type boolean
409              * @protected
410              */
411             sv._scrolledForward = distance > 0;
412         }
413
414         // Check for min/max
415         if (vert) {
416             yOrig = sv.get(SCROLL_Y);
417             y = _constrain(yOrig, minY, maxY);
418         }
419
420         if (horiz) {
421             xOrig = sv.get(SCROLL_X);
422             x = _constrain(xOrig, minX, maxX);
423         }
424
425         if (x !== xOrig || y !== yOrig) {
426             this._snapToEdge = true;
427             if (vert) {
428                 sv.set(SCROLL_Y, y);
429             }
430             if (horiz) {
431                 sv.set(SCROLL_X, x);
432             }
433         }
434
435
436         if(sv._snapToEdge) {
437             return;
438         }
439
440         sv.fire(EV_SCROLL_END, {
441             onGestureMoveEnd: true
442         });
443
444         return;
445     },
446
447     /**
448      * After listener for changes to the scrollX or scrollY attribute
449      *
450      * @method _afterScrollChange
451      * @param e {Event.Facade} The event facade
452      * @protected
453      */
454     _afterScrollChange : function(e) {
455         var duration = e.duration,
456             easing = e.easing,
457             val = e.newVal;
458
459         if(e.src !== UI) {
460             if (e.attrName == SCROLL_X) {
461                 this._uiScrollTo(val, null, duration, easing);
462             } else {
463                 this._uiScrollTo(null, val, duration, easing);
464             }
465         }
466     },
467
468     /**
469      * Used to move the ScrollView content
470      *
471      * @method _uiScrollTo
472      * @param x {Number}
473      * @param y {Number}
474      * @param duration {Number}
475      * @param easing {String}
476      * @protected
477      * 
478      */
479     _uiScrollTo : function(x, y, duration, easing) {
480
481         // TODO: This doesn't seem right. This is not UI logic. 
482         duration = duration || this._snapToEdge ? 400 : 0;
483         easing = easing || this._snapToEdge ? ScrollView.SNAP_EASING : null;
484
485         this.scrollTo(x, y, duration, easing);
486     },
487
488     /**
489      * After listener for the height or width attribute
490      *
491      * @method _afterDimChange
492      * @param e {Event.Facade} The event facade
493      * @protected
494      */
495     _afterDimChange: function() {
496         this._uiDimensionsChange();
497     },
498     
499     /**
500      * This method gets invoked whenever the height or width attributes change,
501      * allowing us to determine which scrolling axes need to be enabled.
502      *
503      * @method _uiDimensionsChange
504      * @protected
505      */
506     _uiDimensionsChange: function() {
507
508         var sv = this,
509             bb = sv._bb,
510
511             CLASS_NAMES = ScrollView.CLASS_NAMES,
512
513             height = sv.get('height'),
514             width = sv.get('width'),
515
516             // Use bb instead of cb. cb doesn't gives us the right results
517             // in FF (due to overflow:hidden)
518             scrollHeight = bb.get('scrollHeight'),
519             scrollWidth = bb.get('scrollWidth');
520
521         if (height && scrollHeight > height) {          
522             sv._scrollsVertical = true;
523             sv._maxScrollY = scrollHeight - height;
524             sv._minScrollY = 0;
525             sv._scrollHeight = scrollHeight;
526             bb.addClass(CLASS_NAMES.vertical);
527         }
528
529         if (width && scrollWidth > width) {
530             sv._scrollsHorizontal = true;
531             sv._maxScrollX = scrollWidth - width;
532             sv._minScrollX = 0;
533             sv._scrollWidth = scrollWidth;
534             bb.addClass(CLASS_NAMES.horizontal);
535         }
536
537         /**
538          * Internal state, defines whether or not the scrollview can scroll vertically 
539          * 
540          * @property _scrollsVertical
541          * @type boolean
542          * @protected
543          */
544         
545         /**
546          * Internal state, defines the maximum amount that the scrollview can be scrolled along the Y axis 
547          * 
548          * @property _maxScrollY
549          * @type number
550          * @protected
551          */
552
553         /**
554          * Internal state, defines the minimum amount that the scrollview can be scrolled along the Y axis 
555          * 
556          * @property _minScrollY
557          * @type number
558          * @protected
559          */
560
561         /**
562          * Internal state, cached scrollHeight, for performance 
563          * 
564          * @property _scrollHeight
565          * @type number
566          * @protected
567          */
568
569         /**
570          * Internal state, defines whether or not the scrollview can scroll horizontally 
571          * 
572          * @property _scrollsHorizontal
573          * @type boolean
574          * @protected
575          */
576         
577         /**
578          * Internal state, defines the maximum amount that the scrollview can be scrolled along the X axis 
579          * 
580          * @property _maxScrollX
581          * @type number
582          * @protected
583          */
584
585         /**
586          * Internal state, defines the minimum amount that the scrollview can be scrolled along the X axis 
587          * 
588          * @property _minScrollX
589          * @type number
590          * @protected
591          */
592
593         /**
594          * Internal state, cached scrollWidth, for performance 
595          * 
596          * @property _scrollWidth
597          * @type number
598          * @protected
599          */
600     },
601
602     /**
603      * Execute a flick at the end of a scroll action
604      *
605      * @method _flick
606      * @param distance {Number} The distance (in px) the user scrolled before the flick
607      * @param time {Number} The number of ms the scroll event lasted before the flick
608      * @protected
609      */
610     _flick: function(e) {
611         var flick = e.flick,
612             sv = this;
613
614         /**
615          * Internal state, currently calculated velocity from the flick 
616          * 
617          * @property _currentVelocity
618          * @type number
619          * @protected
620          */
621         sv._currentVelocity = flick.velocity;
622         sv._flicking = true;
623
624         sv._cDecel = sv.get('deceleration');
625         sv._cBounce = sv.get('bounce');
626
627         sv._pastYEdge = false;
628         sv._pastXEdge = false;
629
630         sv._flickFrame();
631
632         sv.fire(EV_SCROLL_FLICK);
633     },
634
635     /**
636      * Execute a single frame in the flick animation
637      *
638      * @method _flickFrame
639      * @protected
640      */
641     _flickFrame: function() {
642         var sv = this,
643             newY,
644             maxY,
645             minY,
646             newX,
647             maxX,
648             minX,
649             scrollsVertical  = sv._scrollsVertical,
650             scrollsHorizontal = sv._scrollsHorizontal,
651             deceleration = sv._cDecel,
652             bounce = sv._cBounce,
653             vel = sv._currentVelocity,
654             step = ScrollView.FRAME_STEP;
655
656         if (scrollsVertical) {
657             maxY = sv._maxScrollY;
658             minY = sv._minScrollY;
659             newY = sv.get(SCROLL_Y) - (vel * step);
660         }
661
662         if (scrollsHorizontal) {
663             maxX = sv._maxScrollX;
664             minX = sv._minScrollX;
665             newX = sv.get(SCROLL_X) - (vel * step);
666         }
667         
668         vel = sv._currentVelocity = (vel * deceleration);
669
670         if(Math.abs(vel).toFixed(4) <= 0.015) {
671             sv._flicking = false;
672             sv._killTimer(!(sv._pastYEdge || sv._pastXEdge));
673
674             if(scrollsVertical) {
675                 if(newY < minY) {
676                     sv._snapToEdge = true;
677                     sv.set(SCROLL_Y, minY);
678                 } else if(newY > maxY) {
679                     sv._snapToEdge = true;
680                     sv.set(SCROLL_Y, maxY);
681                 }
682             }
683
684             if(scrollsHorizontal) {
685                 if(newX < minX) {
686                     sv._snapToEdge = true;
687                     sv.set(SCROLL_X, minX);
688                 } else if(newX > maxX) {
689                     sv._snapToEdge = true;
690                     sv.set(SCROLL_X, maxX);
691                 }
692             }
693
694             return;
695         }
696
697         if (scrollsVertical) {
698             if (newY < minY || newY > maxY) {
699                 sv._pastYEdge = true;
700                 sv._currentVelocity *= bounce;
701             }
702
703             sv.set(SCROLL_Y, newY);
704         }
705
706         if (scrollsHorizontal) {
707             if (newX < minX || newX > maxX) {
708                 sv._pastXEdge = true;
709                 sv._currentVelocity *= bounce;
710             }
711
712             sv.set(SCROLL_X, newX);
713         }
714
715         if (!sv._flickTimer) {
716             sv._flickTimer = Y.later(step, sv, '_flickFrame', null, true);
717         }
718     },
719
720     /**
721      * Stop the animation timer
722      *
723      * @method _killTimer
724      * @param fireEvent {Boolean} If true, fire the scrollEnd event
725      * @protected
726      */
727     _killTimer: function(fireEvent) {
728         var sv = this;
729         if(sv._flickTimer) {
730             sv._flickTimer.cancel();
731             sv._flickTimer = null;
732         }
733
734         if(fireEvent) {
735             sv.fire(EV_SCROLL_END);
736         }
737     },
738
739     /**
740      * The scrollX, scrollY setter implementation
741      * 
742      * @method _setScroll
743      * @private
744      * @param {Number} val
745      * @param {String} dim
746      * 
747      * @return {Number} The constrained value, if it exceeds min/max range
748      */
749     _setScroll : function(val, dim) {
750         var bouncing = this._cachedBounce || this.get(BOUNCE),
751             range = ScrollView.BOUNCE_RANGE,
752
753             maxScroll = (dim == DIM_X) ? this._maxScrollX : this._maxScrollY,
754
755             min = bouncing ? -range : 0,
756             max = bouncing ? maxScroll + range : maxScroll;
757
758         if(!bouncing || !this._isDragging) {
759             if(val < min) {
760                 val = min;
761             } else if(val > max) {
762                 val = max;
763             }            
764         }
765
766         return val;
767     },
768
769     /**
770      * Setter for the scrollX attribute
771      *
772      * @method _setScrollX
773      * @param val {Number} The new scrollX value
774      * @return {Number} The normalized value
775      * @protected
776      */    
777     _setScrollX: function(val) {
778         return this._setScroll(val, DIM_X);
779     },
780
781     /**
782      * Setter for the scrollY ATTR
783      *
784      * @method _setScrollY
785      * @param val {Number} The new scrollY value
786      * @return {Number} The normalized value 
787      * @protected
788      */
789     _setScrollY: function(val) {
790         return this._setScroll(val, DIM_Y);
791     }
792     
793 }, {
794    
795    // Y.ScrollView static properties
796
797    /**
798     * The identity of the widget.
799     *
800     * @property ScrollView.NAME
801     * @type String
802     * @default 'scrollview'
803     * @readOnly
804     * @protected
805     * @static
806     */
807    NAME: 'scrollview',
808
809    /**
810     * Static property used to define the default attribute configuration of
811     * the Widget.
812     *
813     * @property ScrollView.ATTRS
814     * @type {Object}
815     * @protected
816     * @static
817     */
818     ATTRS: {
819
820         /**
821          * The scroll position in the y-axis
822          *
823          * @attribute scrollY
824          * @type Number
825          * @default 0
826          */
827         scrollY: {
828             value: 0,
829             setter: '_setScrollY'
830         },
831
832         /**
833          * The scroll position in the x-axis
834          *
835          * @attribute scrollX
836          * @type Number
837          * @default 0
838          */
839         scrollX: {
840             value: 0,
841             setter: '_setScrollX'
842         },
843
844         /**
845          * Drag coefficent for inertial scrolling. The closer to 1 this
846          * value is, the less friction during scrolling.
847          *
848          * @attribute deceleration
849          * @default 0.93
850          */
851         deceleration: {
852             value: 0.93
853         },
854
855         /**
856          * Drag coefficient for intertial scrolling at the upper
857          * and lower boundaries of the scrollview. Set to 0 to 
858          * disable "rubber-banding".
859          *
860          * @attribute bounce
861          * @type Number
862          * @default 0.1
863          */
864         bounce: {
865             value: 0.1
866         },
867
868         /**
869          * The minimum distance and/or velocity which define a flick
870          *
871          * @attribute flick
872          * @type Object
873          * @default Object with properties minDistance = 10, minVelocity = 0.3.
874          */
875         flick: {
876             value: {
877                 minDistance: 10,
878                 minVelocity: 0.3
879             }
880         }
881     },
882
883     /**
884      * List of class names used in the scrollview's DOM
885      *
886      * @property ScrollView.CLASS_NAMES
887      * @type Object
888      * @static
889      */
890     CLASS_NAMES: CLASS_NAMES,
891
892     /**
893      * Flag used to source property changes initiated from the DOM
894      *
895      * @property ScrollView.UI_SRC
896      * @type String
897      * @static
898      * @default "ui"
899      */
900     UI_SRC: UI,
901
902     /**
903      * The default bounce distance in pixels
904      *
905      * @property ScrollView.BOUNCE_RANGE
906      * @type Number
907      * @static
908      * @default 150
909      */
910     BOUNCE_RANGE : 150,
911
912     /**
913      * The interval used when animating the flick
914      *
915      * @property ScrollView.FRAME_STEP
916      * @type Number
917      * @static
918      * @default 30
919      */
920     FRAME_STEP : 30,
921
922     /**
923      * The default easing used when animating the flick
924      *
925      * @property ScrollView.EASING
926      * @type String
927      * @static
928      * @default 'cubic-bezier(0, 0.1, 0, 1.0)'
929      */
930     EASING : 'cubic-bezier(0, 0.1, 0, 1.0)',
931
932     /**
933      * The default easing to use when animatiing the bounce snap back.
934      *
935      * @property ScrollView.SNAP_EASING
936      * @type String
937      * @static
938      * @default 'ease-out'
939      */
940     SNAP_EASING : 'ease-out',
941
942     /**
943      * Style property name to use to set transition property. Currently, Webkit specific (WebkitTransitionProperty)
944      *
945      * @property ScrollView._TRANSITION.PROPERTY
946      * @private
947      */
948     _TRANSITION : {
949         DURATION : "WebkitTransitionDuration",
950         PROPERTY : "WebkitTransitionProperty"
951     }
952 });
953
954
955 }, '3.3.0' ,{skinnable:true, requires:['widget', 'event-gestures', 'transition']});