Show:
                            /**
                             * Provide a simple Flick plugin, which can be used along with the "flick" gesture event, to
                             * animate the motion of the host node in response to a (mouse or touch) flick gesture.
                             *
                             * <p>The current implementation is designed to move the node, relative to the bounds of a parent node and is suitable
                             * for scroll/carousel type implementations. Future versions will remove that constraint, to allow open ended movement within
                             * the document.</p>
                             *
                             * @module node-flick
                             */
                            
                                var HOST = "host",
                                    PARENT_NODE = "parentNode",
                                    BOUNDING_BOX = "boundingBox",
                                    OFFSET_HEIGHT = "offsetHeight",
                                    OFFSET_WIDTH = "offsetWidth",
                                    SCROLL_HEIGHT = "scrollHeight",
                                    SCROLL_WIDTH = "scrollWidth",
                                    BOUNCE = "bounce",
                                    MIN_DISTANCE = "minDistance",
                                    MIN_VELOCITY = "minVelocity",
                                    BOUNCE_DISTANCE = "bounceDistance",
                                    DECELERATION = "deceleration",
                                    STEP = "step",
                                    DURATION = "duration",
                                    EASING = "easing",
                                    FLICK = "flick",
                            
                                    getClassName = Y.ClassNameManager.getClassName;
                            
                                /**
                                 * A plugin class which can be used to animate the motion of a node, in response to a flick gesture.
                                 *
                                 * @class Flick
                                 * @namespace Plugin
                                 * @param {Object} config The initial attribute values for the plugin
                                 */
                                function Flick(config) {
                                    Flick.superclass.constructor.apply(this, arguments);
                                }
                            
                                Flick.ATTRS = {
                            
                                    /**
                                     * Drag coefficent for inertial scrolling. The closer to 1 this
                                     * value is, the less friction during scrolling.
                                     *
                                     * @attribute deceleration
                                     * @default 0.98
                                     */
                                    deceleration : {
                                        value: 0.98
                                    },
                            
                                    /**
                                     * 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.7
                                     */
                                    bounce : {
                                        value: 0.7
                                    },
                            
                                    /**
                                     * The bounce distance in pixels
                                     *
                                     * @attribute bounceDistance
                                     * @type Number
                                     * @default 150
                                     */
                                    bounceDistance : {
                                        value: 150
                                    },
                            
                                    /**
                                     * The minimum flick gesture velocity (px/ms) at which to trigger the flick response
                                     *
                                     * @attribute minVelocity
                                     * @type Number
                                     * @default 0
                                     */
                                    minVelocity : {
                                        value: 0
                                    },
                            
                                    /**
                                     * The minimum flick gesture distance (px) for which to trigger the flick response
                                     *
                                     * @attribute minVelocity
                                     * @type Number
                                     * @default 10
                                     */
                                    minDistance : {
                                        value: 10
                                    },
                            
                                    /**
                                     * The constraining box relative to which the flick animation and bounds should be calculated.
                                     *
                                     * @attribute boundingBox
                                     * @type Node
                                     * @default parentNode
                                     */
                                    boundingBox : {
                                        valueFn : function() {
                                            return this.get(HOST).get(PARENT_NODE);
                                        }
                                    },
                            
                                    /**
                                     * Time between flick animation frames.
                                     *
                                     * @attribute step
                                     * @type Number
                                     * @default 10
                                     */
                                    step : {
                                        value:10
                                    },
                            
                                    /**
                                     * The custom duration to apply to the flick animation. By default,
                                     * the animation duration is controlled by the deceleration factor.
                                     *
                                     * @attribute duration
                                     * @type Number
                                     * @default null
                                     */
                                    duration : {
                                        value:null
                                    },
                            
                                    /**
                                     * The custom transition easing to use for the flick animation. If not
                                     * provided defaults to internally to Flick.EASING, or Flick.SNAP_EASING based
                                     * on whether or not we're animating the flick or bounce step.
                                     *
                                     * @attribute easing
                                     * @type String
                                     * @default null
                                     */
                                    easing : {
                                        value:null
                                    }
                                };
                            
                                /**
                                 * The NAME of the Flick class. Used to prefix events generated
                                 * by the plugin.
                                 *
                                 * @property NAME
                                 * @static
                                 * @type String
                                 * @default "pluginFlick"
                                 */
                                Flick.NAME = "pluginFlick";
                            
                                /**
                                 * The namespace for the plugin. This will be the property on the node, which will
                                 * reference the plugin instance, when it's plugged in.
                                 *
                                 * @property NS
                                 * @static
                                 * @type String
                                 * @default "flick"
                                 */
                                Flick.NS = "flick";
                            
                                Y.extend(Flick, Y.Plugin.Base, {
                            
                                    /**
                                     * The initializer lifecycle implementation.
                                     *
                                     * @method initializer
                                     * @param {Object} config The user configuration for the plugin
                                     */
                                    initializer : function(config) {
                                        this._node = this.get(HOST);
                            
                                        this._renderClasses();
                                        this.setBounds();
                            
                                        this._node.on(FLICK, Y.bind(this._onFlick, this), {
                                            minDistance : this.get(MIN_DISTANCE),
                                            minVelocity : this.get(MIN_VELOCITY)
                                        });
                                    },
                            
                                    /**
                                     * Sets the min/max boundaries for the flick animation,
                                     * based on the boundingBox dimensions.
                                     *
                                     * @method setBounds
                                     */
                                    setBounds : function () {
                                        var box = this.get(BOUNDING_BOX),
                                            node = this._node,
                            
                                            boxHeight = box.get(OFFSET_HEIGHT),
                                            boxWidth = box.get(OFFSET_WIDTH),
                            
                                            contentHeight = node.get(SCROLL_HEIGHT),
                                            contentWidth = node.get(SCROLL_WIDTH);
                            
                                        if (contentHeight > boxHeight) {
                                            this._maxY = contentHeight - boxHeight;
                                            this._minY = 0;
                                            this._scrollY = true;
                                        }
                            
                                        if (contentWidth > boxWidth) {
                                            this._maxX = contentWidth - boxWidth;
                                            this._minX = 0;
                                            this._scrollX = true;
                                        }
                            
                                        this._x = this._y = 0;
                            
                                        node.set("top", this._y + "px");
                                        node.set("left", this._x + "px");
                                    },
                            
                                    /**
                                     * Adds the CSS classes, necessary to set up overflow/position properties on the
                                     * node and boundingBox.
                                     *
                                     * @method _renderClasses
                                     * @protected
                                     */
                                    _renderClasses : function() {
                                        this.get(BOUNDING_BOX).addClass(Flick.CLASS_NAMES.box);
                                        this._node.addClass(Flick.CLASS_NAMES.content);
                                    },
                            
                                    /**
                                     * The flick event listener. Kicks off the flick animation.
                                     *
                                     * @method _onFlick
                                     * @param e {EventFacade} The flick event facade, containing e.flick.distance, e.flick.velocity etc.
                                     * @protected
                                     */
                                    _onFlick: function(e) {
                                        this._v = e.flick.velocity;
                                        this._flick = true;
                                        this._flickAnim();
                                    },
                            
                                    /**
                                     * Executes a single frame in the flick animation
                                     *
                                     * @method _flickFrame
                                     * @protected
                                     */
                                    _flickAnim: function() {
                            
                                        var y = this._y,
                                            x = this._x,
                            
                                            maxY = this._maxY,
                                            minY = this._minY,
                                            maxX = this._maxX,
                                            minX = this._minX,
                                            velocity = this._v,
                            
                                            step = this.get(STEP),
                                            deceleration = this.get(DECELERATION),
                                            bounce = this.get(BOUNCE);
                            
                                        this._v = (velocity * deceleration);
                            
                                        this._snapToEdge = false;
                            
                                        if (this._scrollX) {
                                            x = x - (velocity * step);
                                        }
                            
                                        if (this._scrollY) {
                                            y = y - (velocity * step);
                                        }
                            
                                        if (Math.abs(velocity).toFixed(4) <= Flick.VELOCITY_THRESHOLD) {
                            
                                            this._flick = false;
                            
                                            this._killTimer(!(this._exceededYBoundary || this._exceededXBoundary));
                            
                                            if (this._scrollX) {
                                                if (x < minX) {
                                                    this._snapToEdge = true;
                                                    this._setX(minX);
                                                } else if (x > maxX) {
                                                    this._snapToEdge = true;
                                                    this._setX(maxX);
                                                }
                                            }
                            
                                            if (this._scrollY) {
                                                if (y < minY) {
                                                    this._snapToEdge = true;
                                                    this._setY(minY);
                                                } else if (y > maxY) {
                                                    this._snapToEdge = true;
                                                    this._setY(maxY);
                                                }
                                            }
                            
                                        } else {
                            
                                            if (this._scrollX && (x < minX || x > maxX)) {
                                                this._exceededXBoundary = true;
                                                this._v *= bounce;
                                            }
                            
                                            if (this._scrollY && (y < minY || y > maxY)) {
                                                this._exceededYBoundary = true;
                                                this._v *= bounce;
                                            }
                            
                                            if (this._scrollX) {
                                                this._setX(x);
                                            }
                            
                                            if (this._scrollY) {
                                                this._setY(y);
                                            }
                            
                                            this._flickTimer = Y.later(step, this, this._flickAnim);
                                        }
                                    },
                            
                                    /**
                                     * Internal utility method to set the X offset position
                                     *
                                     * @method _setX
                                     * @param {Number} val
                                     * @private
                                     */
                                    _setX : function(val) {
                                        this._move(val, null, this.get(DURATION), this.get(EASING));
                                    },
                            
                                    /**
                                     * Internal utility method to set the Y offset position
                                     *
                                     * @method _setY
                                     * @param {Number} val
                                     * @private
                                     */
                                    _setY : function(val) {
                                        this._move(null, val, this.get(DURATION), this.get(EASING));
                                    },
                            
                                    /**
                                     * Internal utility method to move the node to a given XY position,
                                     * using transitions, if specified.
                                     *
                                     * @method _move
                                     * @param {Number} x The X offset position
                                     * @param {Number} y The Y offset position
                                     * @param {Number} duration The duration to use for the transition animation
                                     * @param {String} easing The easing to use for the transition animation.
                                     *
                                     * @private
                                     */
                                    _move: function(x, y, duration, easing) {
                            
                                        if (x !== null) {
                                            x = this._bounce(x);
                                        } else {
                                            x = this._x;
                                        }
                            
                                        if (y !== null) {
                                            y = this._bounce(y);
                                        } else {
                                            y = this._y;
                                        }
                            
                                        duration = duration || this._snapToEdge ? Flick.SNAP_DURATION : 0;
                                        easing = easing || this._snapToEdge ? Flick.SNAP_EASING : Flick.EASING;
                            
                                        this._x = x;
                                        this._y = y;
                            
                                        this._anim(x, y, duration, easing);
                                    },
                            
                                    /**
                                     * Internal utility method to perform the transition step
                                     *
                                     * @method _anim
                                     * @param {Number} x The X offset position
                                     * @param {Number} y The Y offset position
                                     * @param {Number} duration The duration to use for the transition animation
                                     * @param {String} easing The easing to use for the transition animation.
                                     *
                                     * @private
                                     */
                                    _anim : function(x, y, duration, easing) {
                                        var xn = x * -1,
                                            yn = y * -1,
                            
                                            transition = {
                                                duration : duration / 1000,
                                                easing : easing
                                            };
                            
                                        Y.log("Transition: duration, easing:" + transition.duration, transition.easing, "node-flick");
                            
                                        if (Y.Transition.useNative) {
                                            transition.transform = 'translate('+ (xn) + 'px,' + (yn) +'px)';
                                        } else {
                                            transition.left = xn + 'px';
                                            transition.top = yn + 'px';
                                        }
                            
                                        this._node.transition(transition);
                                    },
                            
                                    /**
                                     * Internal utility method to constrain the offset value
                                     * based on the bounce criteria.
                                     *
                                     * @method _bounce
                                     * @param {Number} x The offset value to constrain.
                                     * @param {Number} max The max offset value.
                                     *
                                     * @private
                                     */
                                    _bounce : function(val, max) {
                                        var bounce = this.get(BOUNCE),
                                            dist = this.get(BOUNCE_DISTANCE),
                                            min = bounce ? -dist : 0;
                            
                                        max = bounce ? max + dist : max;
                            
                                        if(!bounce) {
                                            if(val < min) {
                                                val = min;
                                            } else if(val > max) {
                                                val = max;
                                            }
                                        }
                                        return val;
                                    },
                            
                                    /**
                                     * Stop the animation timer
                                     *
                                     * @method _killTimer
                                     * @private
                                     */
                                    _killTimer: function() {
                                        if(this._flickTimer) {
                                            this._flickTimer.cancel();
                                        }
                                    }
                            
                                }, {
                            
                                    /**
                                     * The threshold used to determine when the decelerated velocity of the node
                                     * is practically 0.
                                     *
                                     * @property VELOCITY_THRESHOLD
                                     * @static
                                     * @type Number
                                     * @default 0.015
                                     */
                                    VELOCITY_THRESHOLD : 0.015,
                            
                                    /**
                                     * The duration to use for the bounce snap-back transition
                                     *
                                     * @property SNAP_DURATION
                                     * @static
                                     * @type Number
                                     * @default 400
                                     */
                                     SNAP_DURATION : 400,
                            
                                    /**
                                     * The default easing to use for the main flick movement transition
                                     *
                                     * @property EASING
                                     * @static
                                     * @type String
                                     * @default 'cubic-bezier(0, 0.1, 0, 1.0)'
                                     */
                                    EASING : 'cubic-bezier(0, 0.1, 0, 1.0)',
                            
                                    /**
                                     * The default easing to use for the bounce snap-back transition
                                     *
                                     * @property SNAP_EASING
                                     * @static
                                     * @type String
                                     * @default 'ease-out'
                                     */
                                    SNAP_EASING : 'ease-out',
                            
                                    /**
                                     * The default CSS class names used by the plugin
                                     *
                                     * @property CLASS_NAMES
                                     * @static
                                     * @type Object
                                     */
                                    CLASS_NAMES : {
                                        box: getClassName(Flick.NS),
                                        content: getClassName(Flick.NS, "content")
                                    }
                                });
                            
                                Y.Plugin.Flick = Flick;