scrollview-base-debug.js revision e669f4800bb30c0f9b6ac93af6c8390e5f3c672b
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * The scrollview-base module provides a basic ScrollView Widget, without scrollbar indicators
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @module scrollview-base
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassvar getClassName = Y.ClassNameManager.getClassName,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * ScrollView provides a scrollable widget, supporting flick gestures, across both touch and mouse based devices.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @class ScrollView
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param config {Object} Object literal with initial attribute values
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @extends Widget
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @constructor
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass ScrollView.superclass.constructor.apply(this, arguments);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Y.ScrollView prototype
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Designated initializer
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method initializer
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass initializer: function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Notification event fired at the end of a scroll transition
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @event scrollEnd
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param e {EventFacade} The default event facade.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Notification event fired at the end of a flick gesture (the flick animation may still be in progress)
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @event flick
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param e {EventFacade} The default event facade.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var sv = this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Cache - they're write once, and not going to change
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Override the contentBox sizing method, since the contentBox height
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * should not be that of the boundingBox.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _uiSizeCB
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _uiSizeCB: function() {},
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Content box transition callback
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _onTransEnd
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param {Event.Facade} e The event facade
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _onTransEnd: function(e) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * bindUI implementation
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Hooks up events for the widget
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method bindUI
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass bindUI: function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var sv = this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Note: You can find _bindMousewheel() inside syncUI(), becuase it depends on UI details
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // IE SELECT HACK. See if we can do this non-natively and in the gesture for a future release.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _bindAttrs
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _bindAttrs : function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var sv = this,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Helps avoid potential CSS race where in the styles from
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // scrollview-list-skin.css are applied after syncUI() fires.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Without a _uiDimensionChange() call, the scrollview only
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // scrolls partially due to the fact that styles added in the CSS
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // altered the height/width of the bounding box.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // TODO: Remove?
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass //this._uiDimensionsChange();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Bind (or unbind) gesture move listeners required for drag support
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _bindDrag
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param drag {boolean} If true, the method binds listener to enable drag (gesturemovestart). If false, the method unbinds gesturemove listeners for drag support.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass bb.on('drag|gesturemovestart', Y.bind(this._onGestureMoveStart, this));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Bind (or unbind) flick listeners.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _bindFlick
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param flick {Object|boolean} If truthy, the method binds listeners for flick support. If false, the method unbinds flick listeners.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass cb.on("flick|flick", Y.bind(this._flick, this), flick);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Bind (or unbind) mousewheel listeners.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _bindMousewheel
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param mousewheel {Object|boolean} If truthy, the method binds listeners for mousewheel support. If false, the method unbinds mousewheel listeners.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Only enable for vertical scrollviews
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass cb.on("mousewheel", Y.bind(this._mousewheel, this), mousewheel);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * syncUI implementation.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Update the scroll position, based on the current value of scrollX/scrollY.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method syncUI
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass syncUI: function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.scrollTo(this.get(SCROLL_X), this.get(SCROLL_Y));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Scroll the element to a given xy coordinate
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method scrollTo
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param x {Number} The x-position to scroll to
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param y {Number} The y-position to scroll to
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param duration {Number} Duration, in ms, of the scroll animation (default is 0)
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param easing {String} An easing equation if duration is set
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // TODO: Figure out a better way to detect mousewheel events
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if ( y < this._minScrollY) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass else if ( y > this._maxScrollY) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass xSet = (x !== null),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass ySet = (y !== null),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // ANDROID WORKAROUND - try and stop existing transition, before kicking off new one.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass cb.setStyle(TRANS.DURATION, ZERO).setStyle(TRANS.PROPERTY, EMPTY);
if (NATIVE_TRANSITIONS) {
if (!callback) {
if (NATIVE_TRANSITIONS) {
_transform : function(x, y) {
return (this._forceHWTransforms) ? 'translate('+ x +'px,'+ y +'px) translateZ(0px)' : 'translate('+ x +'px,'+ y +'px)';
if (NATIVE_TRANSITIONS) {
* Flag driving whether or not we should try and force H/W acceleration when transforming. Currently enabled by default for Webkit.
_prevent : {
start : false,
move : true,
end : false
_onGestureMoveStart: function(e) {
var sv = this,
e.preventDefault();
_onGestureMove: function(e) {
var sv = this;
e.preventDefault();
_onGestureMoveEnd: function(e) {
e.preventDefault();
* Contains the distance (postive or negative) in pixels by which the scrollview was last scrolled. This is useful when
* setting up click listeners on the scrollview content, which on mouse based devices are always fired, even after a
* <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,
if((horiz && absDistance > bb.get('offsetWidth')/2) || (vert && absDistance > bb.get('offsetHeight')/2)) {
* Internal state, defines whether or not the scrollview has been scrolled in the forward (distance > 0), or backward (distance < 0) direction
if (vert) {
if (horiz) {
this._snapToEdge = true;
if (vert) {
if (horiz) {
onGestureMoveEnd: true
_afterScrollChange : function(e) {
_afterFlickChange : function(e) {
_afterDisabledChange : function(e) {
_afterDragChange : function(e) {
_afterDimChange: function() {
this._uiDimensionsChange();
* @returns {Array} The offsetWidth, offsetHeight, scrollWidth and scrollHeight as an array: [offsetWidth, offsetHeight, scrollWidth, scrollHeight]
_getScrollDims: function() {
var dims,
if (NATIVE_TRANSITIONS) {
this._forceHWTransforms = false; // the z translation was causing issues with picking up accurate scrollWidths in Chrome/Mac.
dims = [bb.get("offsetWidth"), bb.get("offsetHeight"), bb.get('scrollWidth'), bb.get('scrollHeight')];
return dims;
_uiDimensionsChange: function() {
var sv = this,
_flick: function(e) {
sv = this;
_mousewheel: function(e) {
if (this.scrollbars) {
e.preventDefault();
_flickFrame: function() {
var sv = this,
newY,
maxY,
minY,
newX,
maxX,
minX,
if (scrollsVertical) {
if (scrollsHorizontal) {
if(scrollsVertical) {
if(scrollsHorizontal) {
if (scrollsVertical) {
if (scrollsHorizontal) {
var sv = this;
if(fireEvent) {
if (this._cDisabled) {
return val;
ATTRS: {
scrollY: {
scrollX: {
deceleration: {
bounce: {
flick: {
value: {
* Enable/Disable dragging the ScrollView content (note: flick support is enabled/disabled separately)
drag: {
value: true
_TRANSITION : {