scrollview-base-debug.js revision e669f4800bb30c0f9b6ac93af6c8390e5f3c672b
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassYUI.add('scrollview-base', function(Y) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass/**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * The scrollview-base module provides a basic ScrollView Widget, without scrollbar indicators
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @module scrollview-base
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassvar getClassName = Y.ClassNameManager.getClassName,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass SCROLLVIEW = 'scrollview',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass CLASS_NAMES = {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass vertical: getClassName(SCROLLVIEW, 'vert'),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass horizontal: getClassName(SCROLLVIEW, 'horiz')
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass EV_SCROLL_END = 'scrollEnd',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass EV_SCROLL_FLICK = 'flick',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass FLICK = EV_SCROLL_FLICK,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass DRAG = "drag",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass MOUSEWHEEL_ENABLED = true,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass UI = 'ui',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass LEFT = "left",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass TOP = "top",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass PX = "px",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass SCROLL_Y = "scrollY",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass SCROLL_X = "scrollX",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass BOUNCE = "bounce",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass DISABLED = "disabled",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass DIM_X = "x",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass DIM_Y = "y",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass BOUNDING_BOX = "boundingBox",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass CONTENT_BOX = "contentBox",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass EMPTY = "",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass ZERO = "0s",
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass IE = Y.UA.ie,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Transition = Y.Transition,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass NATIVE_TRANSITIONS = Transition.useNative,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _constrain = function (val, min, max) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return Math.min(Math.max(val, min), max);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass };
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass/**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * ScrollView provides a scrollable widget, supporting flick gestures, across both touch and mouse based devices.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @class ScrollView
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param config {Object} Object literal with initial attribute values
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @extends Widget
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @constructor
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassfunction ScrollView() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass ScrollView.superclass.constructor.apply(this, arguments);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass}
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassY.ScrollView = Y.extend(ScrollView, Y.Widget, {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Y.ScrollView prototype
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Designated initializer
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method initializer
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass initializer: function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Notification event fired at the end of a scroll transition
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @event scrollEnd
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param e {EventFacade} The default event facade.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Notification event fired at the end of a flick gesture (the flick animation may still be in progress)
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @event flick
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param e {EventFacade} The default event facade.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var sv = this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Cache - they're write once, and not going to change
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sv._cb = sv.get(CONTENT_BOX);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sv._bb = sv.get(BOUNDING_BOX);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Override the contentBox sizing method, since the contentBox height
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * should not be that of the boundingBox.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _uiSizeCB
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _uiSizeCB: function() {},
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Content box transition callback
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _onTransEnd
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @param {Event.Facade} e The event facade
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @private
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _onTransEnd: function(e) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.fire(EV_SCROLL_END);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * bindUI implementation
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Hooks up events for the widget
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method bindUI
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass bindUI: function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var sv = this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sv._bindDrag(sv.get(DRAG));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sv._bindFlick(sv.get(FLICK));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Note: You can find _bindMousewheel() inside syncUI(), becuase it depends on UI details
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sv._bindAttrs();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // IE SELECT HACK. See if we can do this non-natively and in the gesture for a future release.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (IE) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sv._fixIESelect(sv._bb, sv._cb);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method _bindAttrs
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @private
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _bindAttrs : function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var sv = this,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass scrollChangeHandler = sv._afterScrollChange,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass dimChangeHandler = sv._afterDimChange;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.after({
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass 'disabledChange': sv._afterDisabledChange,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass 'flickChange' : sv._afterFlickChange,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass 'dragChange' : sv._afterDragChange,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass 'scrollYChange' : scrollChangeHandler,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass 'scrollXChange' : scrollChangeHandler,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass 'heightChange' : dimChangeHandler,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass 'widthChange' : dimChangeHandler
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
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 if (!IE) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.after('renderedChange', function(e) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass //this._uiDimensionsChange();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Bind (or unbind) gesture move listeners required for drag support
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
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 * @private
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _bindDrag : function(drag) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var bb = this._bb;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (drag) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass bb.on('drag|gesturemovestart', Y.bind(this._onGestureMoveStart, this));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass } else {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass bb.detach('drag|*');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Bind (or unbind) flick listeners.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
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 * @private
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _bindFlick : function(flick) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var cb = this._cb;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (flick) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass cb.on("flick|flick", Y.bind(this._flick, this), flick);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass } else {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass cb.detach('flick|*');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Bind (or unbind) mousewheel listeners.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
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 * @private
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _bindMousewheel : function(mousewheel) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var cb = this._cb;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Only enable for vertical scrollviews
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (this._scrollsVertical) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (mousewheel) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass cb.on("mousewheel", Y.bind(this._mousewheel, this), mousewheel);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass } else {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass cb.detach('mousewheel|*');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * syncUI implementation.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Update the scroll position, based on the current value of scrollX/scrollY.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * @method syncUI
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass syncUI: function() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._cDisabled = this.get(DISABLED);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._uiDimensionsChange();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._bindMousewheel(MOUSEWHEEL_ENABLED);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.scrollTo(this.get(SCROLL_X), this.get(SCROLL_Y));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * Scroll the element to a given xy coordinate
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass *
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 */
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass scrollTo: function(x, y, duration, easing) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // TODO: Figure out a better way to detect mousewheel events
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (easing === undefined) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if ( y < this._minScrollY) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass y = this._minScrollY;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass else if ( y > this._maxScrollY) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass y = this._maxScrollY;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!this._cDisabled) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var cb = this._cb,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass xSet = (x !== null),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass ySet = (y !== null),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass xMove = (xSet) ? x * -1 : 0,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass yMove = (ySet) ? y * -1 : 0,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass transition,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass TRANS = ScrollView._TRANSITION,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass callback = this._transEndCB;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass duration = duration || 0;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass easing = easing || ScrollView.EASING;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (xSet) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.set(SCROLL_X, x, { src: UI });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (ySet) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.set(SCROLL_Y, y, { src: UI });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (NATIVE_TRANSITIONS) {
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);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (duration !== 0) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass transition = {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass easing : easing,
duration : duration/1000
};
if (NATIVE_TRANSITIONS) {
transition.transform = this._transform(xMove, yMove);
} else {
if (xSet) { transition.left = xMove + PX; }
if (ySet) { transition.top = yMove + PX; }
}
Y.log("Transition: duration, easing:" + [transition.duration, transition.easing], "scrollview");
if (!callback) {
callback = this._transEndCB = Y.bind(this._onTransEnd, this);
}
cb.transition(transition, callback);
} else {
if (NATIVE_TRANSITIONS) {
cb.setStyle('transform', this._transform(xMove, yMove));
} else {
if (xSet) { cb.setStyle(LEFT, xMove + PX); }
if (ySet) { cb.setStyle(TOP, yMove + PX); }
}
}
}
},
/**
* Utility method, to create the translate transform string with the
* x, y translation amounts provided.
*
* @method _transform
* @param {Number} x Number of pixels to translate along the x axis
* @param {Number} y Number of pixels to translate along the y axis
* @private
*/
_transform : function(x, y) {
// TODO: Would we be better off using a Matrix for this?
return (this._forceHWTransforms) ? 'translate('+ x +'px,'+ y +'px) translateZ(0px)' : 'translate('+ x +'px,'+ y +'px)';
},
/**
* Utility method, to move the given element to the given xy position
*
* @method _moveTo
* @param node {Node} The node to move
* @param x {Number} The x-position to move to
* @param y {Number} The y-position to move to
* @private
*/
_moveTo : function(node, x, y) {
if (NATIVE_TRANSITIONS) {
node.setStyle('transform', this._transform(x, y));
} else {
node.setStyle(LEFT, x + PX);
node.setStyle(TOP, y + PX);
}
},
/**
* Flag driving whether or not we should try and force H/W acceleration when transforming. Currently enabled by default for Webkit.
* Used by the _transform method.
*
* @property _forceHWTransforms
* @type boolean
* @protected
*/
_forceHWTransforms: Y.UA.webkit ? true : false,
/**
* <p>Used to control whether or not ScrollView's internal
* gesturemovestart, gesturemove and gesturemoveend
* event listeners should preventDefault. The value is an
* object, with "start", "move" and "end" properties used to
* specify which events should preventDefault and which shouldn't:</p>
*
* <pre>
* {
* start : false,
* move : true,
* end : false
* }
* </pre>
*
* <p>The default values are set up in order to prevent panning,
* on touch devices, while allowing click listeners on elements inside
* the ScrollView to be notified as expected.</p>
*
* @property _prevent
* @type Object
* @protected
*/
_prevent : {
start : false,
move : true,
end : false
},
/**
* gesturemovestart event handler
*
* @method _onGestureMoveStart
* @param e {Event.Facade} The gesturemovestart event facade
* @private
*/
_onGestureMoveStart: function(e) {
var sv = this,
bb = sv._bb;
if (!sv._cDisabled) {
if (sv._prevent.start) {
e.preventDefault();
}
sv._killTimer();
sv._hm = bb.on('drag|gesturemove', Y.bind(sv._onGestureMove, sv));
sv._hme = bb.on('drag|gesturemoveend', Y.bind(sv._onGestureMoveEnd, sv));
sv._startY = e.clientY + sv.get(SCROLL_Y);
sv._startX = e.clientX + sv.get(SCROLL_X);
sv._startClientY = sv._endClientY = e.clientY;
sv._startClientX = sv._endClientX = e.clientX;
/**
* Internal state, defines whether or not the scrollview is currently being dragged
*
* @property _isDragging
* @type boolean
* @protected
*/
sv._isDragging = false;
/**
* Internal state, defines whether or not the scrollview is currently animating a flick
*
* @property _flicking
* @type boolean
* @protected
*/
sv._flicking = false;
/**
* Internal state, defines whether or not the scrollview needs to snap to a boundary edge
*
* @property _snapToEdge
* @type boolean
* @protected
*/
sv._snapToEdge = false;
}
},
/**
* gesturemove event handler
*
* @method _onGestureMove
* @param e {Event.Facade} The gesturemove event facade
* @private
*/
_onGestureMove: function(e) {
var sv = this;
if (sv._prevent.move) {
e.preventDefault();
}
sv._isDragging = true;
sv._endClientY = e.clientY;
sv._endClientX = e.clientX;
if (sv._scrollsVertical) {
sv.set(SCROLL_Y, -(e.clientY - sv._startY));
}
if(sv._scrollsHorizontal) {
sv.set(SCROLL_X, -(e.clientX - sv._startX));
}
},
/**
* gestureend event handler
*
* @method _onGestureMoveEnd
* @param e {Event.Facade} The gesturemoveend event facade
* @private
*/
_onGestureMoveEnd: function(e) {
if (this._prevent.end) {
e.preventDefault();
}
var sv = this, // kweight
minY = sv._minScrollY,
maxY = sv._maxScrollY,
minX = sv._minScrollX,
maxX = sv._maxScrollX,
vert = sv._scrollsVertical,
horiz = sv._scrollsHorizontal,
startPoint = vert ? sv._startClientY : sv._startClientX,
endPoint = vert ? sv._endClientY : sv._endClientX,
distance = startPoint - endPoint,
absDistance = Math.abs(distance),
bb = sv._bb,
x, y, xOrig, yOrig;
sv._hm.detach();
sv._hme.detach();
/**
* Internal state, defines whether or not the scrollview has been scrolled half it's width/height
*
* @property _scrolledHalfway
* @type boolean
* @protected
*/
sv._scrolledHalfway = sv._snapToEdge = sv._isDragging = false;
/**
* 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
* drag/flick.
*
* <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 working in a purely touch based environment</p>
*
* @property lastScrolledAmt
* @type Number
* @public
*/
sv.lastScrolledAmt = distance;
// Check for halfway
if((horiz && absDistance > bb.get('offsetWidth')/2) || (vert && absDistance > bb.get('offsetHeight')/2)) {
sv._scrolledHalfway = true;
/**
* Internal state, defines whether or not the scrollview has been scrolled in the forward (distance > 0), or backward (distance < 0) direction
*
* @property _scrolledForward
* @type boolean
* @protected
*/
sv._scrolledForward = distance > 0;
}
// Check for min/max
if (vert) {
yOrig = sv.get(SCROLL_Y);
y = _constrain(yOrig, minY, maxY);
}
if (horiz) {
xOrig = sv.get(SCROLL_X);
x = _constrain(xOrig, minX, maxX);
}
if (x !== xOrig || y !== yOrig) {
this._snapToEdge = true;
if (vert) {
sv.set(SCROLL_Y, y);
}
if (horiz) {
sv.set(SCROLL_X, x);
}
}
Y.log("half:" + sv._scrolledHalfway + ", fwd:" + sv._scrolledForward, "scrollview");
if(sv._snapToEdge) {
return;
}
sv.fire(EV_SCROLL_END, {
onGestureMoveEnd: true
});
return;
},
/**
* After listener for changes to the scrollX or scrollY attribute
*
* @method _afterScrollChange
* @param e {Event.Facade} The event facade
* @protected
*/
_afterScrollChange : function(e) {
var duration = e.duration,
easing = e.easing,
val = e.newVal;
if(e.src !== UI) {
if (e.attrName == SCROLL_X) {
this._uiScrollTo(val, null, duration, easing);
} else {
this._uiScrollTo(null, val, duration, easing);
}
}
},
/**
* After listener for changes to the flick attribute
*
* @method _afterFlickChange
* @param e {Event.Facade} The event facade
* @protected
*/
_afterFlickChange : function(e) {
this._bindFlick(e.newVal);
},
/**
* After listener for changes to the disabled attribute
*
* @method _afterDisabledChange
* @param e {Event.Facade} The event facade
* @protected
*/
_afterDisabledChange : function(e) {
// Cache for performance - we check during move
this._cDisabled = e.newVal;
},
/**
* After listener for changes to the drag attribute
*
* @method _afterDragChange
* @param e {Event.Facade} The event facade
* @protected
*/
_afterDragChange : function(e) {
this._bindDrag(e.newVal);
},
/**
* Used to move the ScrollView content
*
* @method _uiScrollTo
* @param x {Number}
* @param y {Number}
* @param duration {Number}
* @param easing {String}
* @protected
*
*/
_uiScrollTo : function(x, y, duration, easing) {
// TODO: This doesn't seem right. This is not UI logic.
duration = duration || this._snapToEdge ? 400 : 0;
easing = easing || this._snapToEdge ? ScrollView.SNAP_EASING : null;
this.scrollTo(x, y, duration, easing);
},
/**
* After listener for the height or width attribute
*
* @method _afterDimChange
* @param e {Event.Facade} The event facade
* @protected
*/
_afterDimChange: function() {
this._uiDimensionsChange();
},
/**
* Utility method to obtain scrollWidth, scrollHeight,
* accounting for the impact of translate on scrollWidth, scrollHeight
* @method _getScrollDims
* @returns {Array} The offsetWidth, offsetHeight, scrollWidth and scrollHeight as an array: [offsetWidth, offsetHeight, scrollWidth, scrollHeight]
* @private
*/
_getScrollDims: function() {
var dims,
// Ideally using CSSMatrix - don't think we have it normalized yet though.
// origX = (new WebKitCSSMatrix(cb.getComputedStyle("transform"))).e;
// origY = (new WebKitCSSMatrix(cb.getComputedStyle("transform"))).f;
origX = this.get(SCROLL_X),
origY = this.get(SCROLL_Y),
cb = this.get(CONTENT_BOX),
bb = this.get(BOUNDING_BOX),
HWTransform,
TRANS = ScrollView._TRANSITION;
// TODO: Is this OK? Just in case it's called 'during' a transition.
if (NATIVE_TRANSITIONS) {
cb.setStyle(TRANS.DURATION, ZERO);
cb.setStyle(TRANS.PROPERTY, EMPTY);
}
HWTransform = this._forceHWTransforms;
this._forceHWTransforms = false; // the z translation was causing issues with picking up accurate scrollWidths in Chrome/Mac.
this._moveTo(cb, 0, 0);
dims = [bb.get("offsetWidth"), bb.get("offsetHeight"), bb.get('scrollWidth'), bb.get('scrollHeight')];
this._moveTo(cb, -1*origX, -1*origY);
this._forceHWTransforms = HWTransform;
return dims;
},
/**
* This method gets invoked whenever the height or width attributes change,
* allowing us to determine which scrolling axes need to be enabled.
*
* @method _uiDimensionsChange
* @protected
*/
_uiDimensionsChange: function() {
var sv = this,
bb = sv._bb,
CLASS_NAMES = ScrollView.CLASS_NAMES,
scrollDims = this._getScrollDims(),
width = scrollDims[0],
height = scrollDims[1],
scrollWidth = scrollDims[2],
scrollHeight = scrollDims[3];
if (height && scrollHeight > height) {
sv._scrollsVertical = true;
sv._maxScrollY = scrollHeight - height;
sv._minScrollY = 0;
sv._scrollHeight = scrollHeight;
sv._height = height;
bb.addClass(CLASS_NAMES.vertical);
} else {
sv._scrollsVertical = false;
delete sv._maxScrollY;
delete sv._minScrollY;
delete sv._scrollHeight;
delete sv._height;
bb.removeClass(CLASS_NAMES.vertical);
}
if (width && scrollWidth > width) {
sv._scrollsHorizontal = true;
sv._maxScrollX = scrollWidth - width;
sv._minScrollX = 0;
sv._scrollWidth = scrollWidth;
sv._width = width;
bb.addClass(CLASS_NAMES.horizontal);
} else {
sv._scrollsHorizontal = false;
delete sv._maxScrollX;
delete sv._minScrollX;
delete sv._scrollWidth;
delete sv._width;
bb.removeClass(CLASS_NAMES.horizontal);
}
/**
* Internal state, defines whether or not the scrollview can scroll vertically
*
* @property _scrollsVertical
* @type boolean
* @protected
*/
/**
* Internal state, defines the maximum amount that the scrollview can be scrolled along the Y axis
*
* @property _maxScrollY
* @type number
* @protected
*/
/**
* Internal state, defines the minimum amount that the scrollview can be scrolled along the Y axis
*
* @property _minScrollY
* @type number
* @protected
*/
/**
* Internal state, cached scrollHeight, for performance
*
* @property _scrollHeight
* @type number
* @protected
*/
/**
* Internal state, defines whether or not the scrollview can scroll horizontally
*
* @property _scrollsHorizontal
* @type boolean
* @protected
*/
/**
* Internal state, defines the maximum amount that the scrollview can be scrolled along the X axis
*
* @property _maxScrollX
* @type number
* @protected
*/
/**
* Internal state, defines the minimum amount that the scrollview can be scrolled along the X axis
*
* @property _minScrollX
* @type number
* @protected
*/
/**
* Internal state, cached scrollWidth, for performance
*
* @property _scrollWidth
* @type number
* @protected
*/
},
/**
* Execute a flick at the end of a scroll action
*
* @method _flick
* @param distance {Number} The distance (in px) the user scrolled before the flick
* @param time {Number} The number of ms the scroll event lasted before the flick
* @protected
*/
_flick: function(e) {
var flick = e.flick,
sv = this;
if (!sv._cDisabled) {
/**
* Internal state, currently calculated velocity from the flick
*
* @property _currentVelocity
* @type number
* @protected
*/
sv._currentVelocity = flick.velocity;
sv._flicking = true;
sv._cDecel = sv.get('deceleration');
sv._cBounce = sv.get('bounce');
sv._pastYEdge = false;
sv._pastXEdge = false;
sv._flickFrame();
sv.fire(EV_SCROLL_FLICK);
}
},
_mousewheel: function(e) {
var scrollY = this.get('scrollY'),
contentBox = this._cb,
scrollOffset = 10, // 10px
scrollToY = scrollY - (e.wheelDelta * scrollOffset);
this.scrollTo(0, scrollToY);
// if we have scrollbars plugin, update & set the flash timer on the scrollbar
if (this.scrollbars) {
// TODO: The scrollbars should handle this themselves
this.scrollbars._update();
this.scrollbars.flash();
// or just this
// this.scrollbars._hostDimensionsChange();
}
// prevent browser default behavior on mouse scroll
e.preventDefault();
},
/**
* Execute a single frame in the flick animation
*
* @method _flickFrame
* @protected
*/
_flickFrame: function() {
var sv = this,
newY,
maxY,
minY,
newX,
maxX,
minX,
scrollsVertical = sv._scrollsVertical,
scrollsHorizontal = sv._scrollsHorizontal,
deceleration = sv._cDecel,
bounce = sv._cBounce,
vel = sv._currentVelocity,
step = ScrollView.FRAME_STEP;
if (scrollsVertical) {
maxY = sv._maxScrollY;
minY = sv._minScrollY;
newY = sv.get(SCROLL_Y) - (vel * step);
}
if (scrollsHorizontal) {
maxX = sv._maxScrollX;
minX = sv._minScrollX;
newX = sv.get(SCROLL_X) - (vel * step);
}
vel = sv._currentVelocity = (vel * deceleration);
if(Math.abs(vel).toFixed(4) <= 0.015) {
sv._flicking = false;
sv._killTimer(!(sv._pastYEdge || sv._pastXEdge));
if(scrollsVertical) {
if(newY < minY) {
sv._snapToEdge = true;
sv.set(SCROLL_Y, minY);
} else if(newY > maxY) {
sv._snapToEdge = true;
sv.set(SCROLL_Y, maxY);
}
}
if(scrollsHorizontal) {
if(newX < minX) {
sv._snapToEdge = true;
sv.set(SCROLL_X, minX);
} else if(newX > maxX) {
sv._snapToEdge = true;
sv.set(SCROLL_X, maxX);
}
}
return;
}
if (scrollsVertical) {
if (newY < minY || newY > maxY) {
sv._pastYEdge = true;
sv._currentVelocity *= bounce;
}
sv.set(SCROLL_Y, newY);
}
if (scrollsHorizontal) {
if (newX < minX || newX > maxX) {
sv._pastXEdge = true;
sv._currentVelocity *= bounce;
}
sv.set(SCROLL_X, newX);
}
if (!sv._flickTimer) {
sv._flickTimer = Y.later(step, sv, '_flickFrame', null, true);
}
},
/**
* Stop the animation timer
*
* @method _killTimer
* @param fireEvent {Boolean} If true, fire the scrollEnd event
* @protected
*/
_killTimer: function(fireEvent) {
var sv = this;
if(sv._flickTimer) {
sv._flickTimer.cancel();
sv._flickTimer = null;
}
if(fireEvent) {
sv.fire(EV_SCROLL_END);
}
},
/**
* The scrollX, scrollY setter implementation
*
* @method _setScroll
* @private
* @param {Number} val
* @param {String} dim
*
* @return {Number} The constrained value, if it exceeds min/max range
*/
_setScroll : function(val, dim) {
if (this._cDisabled) {
val = Y.Attribute.INVALID_VALUE;
} else {
var bouncing = this._cachedBounce || this.get(BOUNCE),
range = ScrollView.BOUNCE_RANGE,
maxScroll = (dim == DIM_X) ? this._maxScrollX : this._maxScrollY,
min = bouncing ? -range : 0,
max = bouncing ? maxScroll + range : maxScroll;
if(!bouncing || !this._isDragging) {
if(val < min) {
val = min;
} else if(val > max) {
val = max;
}
}
}
return val;
},
/**
* Setter for the scrollX attribute
*
* @method _setScrollX
* @param val {Number} The new scrollX value
* @return {Number} The normalized value
* @protected
*/
_setScrollX: function(val) {
return this._setScroll(val, DIM_X);
},
/**
* Setter for the scrollY ATTR
*
* @method _setScrollY
* @param val {Number} The new scrollY value
* @return {Number} The normalized value
* @protected
*/
_setScrollY: function(val) {
return this._setScroll(val, DIM_Y);
}
}, {
// Y.ScrollView static properties
/**
* The identity of the widget.
*
* @property NAME
* @type String
* @default 'scrollview'
* @readOnly
* @protected
* @static
*/
NAME: 'scrollview',
/**
* Static property used to define the default attribute configuration of
* the Widget.
*
* @property ATTRS
* @type {Object}
* @protected
* @static
*/
ATTRS: {
/**
* The scroll position in the y-axis
*
* @attribute scrollY
* @type Number
* @default 0
*/
scrollY: {
value: 0,
setter: '_setScrollY'
},
/**
* The scroll position in the x-axis
*
* @attribute scrollX
* @type Number
* @default 0
*/
scrollX: {
value: 0,
setter: '_setScrollX'
},
/**
* Drag coefficent for inertial scrolling. The closer to 1 this
* value is, the less friction during scrolling.
*
* @attribute deceleration
* @default 0.93
*/
deceleration: {
value: 0.93
},
/**
* Drag coefficient for intertial scrolling at the upper
* and lower boundaries of the scrollview. Set to 0 to
* disable "rubber-banding".
*
* @attribute bounce
* @type Number
* @default 0.1
*/
bounce: {
value: 0.1
},
/**
* The minimum distance and/or velocity which define a flick. Can be set to false,
* to disable flick support (note: drag support is enabled/disabled separately)
*
* @attribute flick
* @type Object
* @default Object with properties minDistance = 10, minVelocity = 0.3.
*/
flick: {
value: {
minDistance: 10,
minVelocity: 0.3
}
},
/**
* Enable/Disable dragging the ScrollView content (note: flick support is enabled/disabled separately)
* @attribute drag
* @type boolean
* @default true
*/
drag: {
value: true
}
},
/**
* List of class names used in the scrollview's DOM
*
* @property CLASS_NAMES
* @type Object
* @static
*/
CLASS_NAMES: CLASS_NAMES,
/**
* Flag used to source property changes initiated from the DOM
*
* @property UI_SRC
* @type String
* @static
* @default "ui"
*/
UI_SRC: UI,
/**
* The default bounce distance in pixels
*
* @property BOUNCE_RANGE
* @type Number
* @static
* @default 150
*/
BOUNCE_RANGE : 150,
/**
* The interval used when animating the flick
*
* @property FRAME_STEP
* @type Number
* @static
* @default 30
*/
FRAME_STEP : 30,
/**
* The default easing used when animating the flick
*
* @property EASING
* @type String
* @static
* @default 'cubic-bezier(0, 0.1, 0, 1.0)'
*/
EASING : 'cubic-bezier(0, 0.1, 0, 1.0)',
/**
* The default easing to use when animating the bounce snap back.
*
* @property SNAP_EASING
* @type String
* @static
* @default 'ease-out'
*/
SNAP_EASING : 'ease-out',
/**
* Object map of style property names used to set transition properties.
* Defaults to the vendor prefix established by the Transition module.
* The configured property names are `_TRANSITION.DURATION` (e.g. "WebkitTransitionDuration") and
* `_TRANSITION.PROPERTY (e.g. "WebkitTransitionProperty").
*
* @property _TRANSITION
* @private
*/
_TRANSITION : {
DURATION : Transition._VENDOR_PREFIX + "TransitionDuration",
PROPERTY : Transition._VENDOR_PREFIX + "TransitionProperty"
}
});
}, '@VERSION@' ,{skinnable:true, requires:['widget', 'event-gestures', 'transition']});