Show:
                            
                                /**
                                 * Base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
                                 * This class should not be called on it's own, it's designed to be a plugin.
                                 * @module dd
                                 * @submodule dd-scroll
                                 */
                                /**
                                 * Base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
                                 * This class should not be called on it's own, it's designed to be a plugin.
                                 * @class Scroll
                                 * @extends Base
                                 * @namespace DD
                                 * @constructor
                                 */
                            
                                var S = function() {
                                    S.superclass.constructor.apply(this, arguments);
                            
                                },
                                WS, NS,
                                HOST = 'host',
                                BUFFER = 'buffer',
                                PARENT_SCROLL = 'parentScroll',
                                WINDOW_SCROLL = 'windowScroll',
                                SCROLL_TOP = 'scrollTop',
                                SCROLL_LEFT = 'scrollLeft',
                                OFFSET_WIDTH = 'offsetWidth',
                                OFFSET_HEIGHT = 'offsetHeight';
                            
                            
                                S.ATTRS = {
                                    /**
                                    * Internal config option to hold the node that we are scrolling. Should not be set by the developer.
                                    * @attribute parentScroll
                                    * @protected
                                    * @type Node
                                    */
                                    parentScroll: {
                                        value: false,
                                        setter: function(node) {
                                            if (node) {
                                                return node;
                                            }
                                            return false;
                                        }
                                    },
                                    /**
                                    * The number of pixels from the edge of the screen to turn on scrolling. Default: 30
                                    * @attribute buffer
                                    * @type Number
                                    */
                                    buffer: {
                                        value: 30,
                                        validator: Y.Lang.isNumber
                                    },
                                    /**
                                    * The number of milliseconds delay to pass to the auto scroller. Default: 235
                                    * @attribute scrollDelay
                                    * @type Number
                                    */
                                    scrollDelay: {
                                        value: 235,
                                        validator: Y.Lang.isNumber
                                    },
                                    /**
                                    * The host we are plugged into.
                                    * @attribute host
                                    * @type Object
                                    */
                                    host: {
                                        value: null
                                    },
                                    /**
                                    * Turn on window scroll support, default: false
                                    * @attribute windowScroll
                                    * @type Boolean
                                    */
                                    windowScroll: {
                                        value: false,
                                        validator: Y.Lang.isBoolean
                                    },
                                    /**
                                    * Allow vertical scrolling, default: true.
                                    * @attribute vertical
                                    * @type Boolean
                                    */
                                    vertical: {
                                        value: true,
                                        validator: Y.Lang.isBoolean
                                    },
                                    /**
                                    * Allow horizontal scrolling, default: true.
                                    * @attribute horizontal
                                    * @type Boolean
                                    */
                                    horizontal: {
                                        value: true,
                                        validator: Y.Lang.isBoolean
                                    }
                                };
                            
                                Y.extend(S, Y.Base, {
                                    /**
                                    * Tells if we are actively scrolling or not.
                                    * @private
                                    * @property _scrolling
                                    * @type Boolean
                                    */
                                    _scrolling: null,
                                    /**
                                    * Cache of the Viewport dims.
                                    * @private
                                    * @property _vpRegionCache
                                    * @type Object
                                    */
                                    _vpRegionCache: null,
                                    /**
                                    * Cache of the dragNode dims.
                                    * @private
                                    * @property _dimCache
                                    * @type Object
                                    */
                                    _dimCache: null,
                                    /**
                                    * Holder for the Timer object returned from Y.later.
                                    * @private
                                    * @property _scrollTimer
                                    * @type {Y.later}
                                    */
                                    _scrollTimer: null,
                                    /**
                                    * Sets the _vpRegionCache property with an Object containing the dims from the viewport.
                                    * @private
                                    * @method _getVPRegion
                                    */
                                    _getVPRegion: function() {
                                        var r = {},
                                            n = this.get(PARENT_SCROLL),
                                        b = this.get(BUFFER),
                                        ws = this.get(WINDOW_SCROLL),
                                        xy = ((ws) ? [] : n.getXY()),
                                        w = ((ws) ? 'winWidth' : OFFSET_WIDTH),
                                        h = ((ws) ? 'winHeight' : OFFSET_HEIGHT),
                                        t = ((ws) ? n.get(SCROLL_TOP) : xy[1]),
                                        l = ((ws) ? n.get(SCROLL_LEFT) : xy[0]);
                            
                                        r = {
                                            top: t + b,
                                            right: (n.get(w) + l) - b,
                                            bottom: (n.get(h) + t) - b,
                                            left: l + b
                                        };
                                        this._vpRegionCache = r;
                                        return r;
                                    },
                                    initializer: function() {
                                        var h = this.get(HOST);
                                        h.after('drag:start', Y.bind(this.start, this));
                                        h.after('drag:end', Y.bind(this.end, this));
                                        h.on('drag:align', Y.bind(this.align, this));
                            
                                        //TODO - This doesn't work yet??
                                        Y.one('win').on('scroll', Y.bind(function() {
                                            this._vpRegionCache = null;
                                        }, this));
                                    },
                                    /**
                                    * Check to see if we need to fire the scroll timer. If scroll timer is running this will scroll the window.
                                    * @private
                                    * @method _checkWinScroll
                                    * @param {Boolean} move Should we move the window. From Y.later
                                    */
                                    _checkWinScroll: function(move) {
                                        var r = this._getVPRegion(),
                                            ho = this.get(HOST),
                                            ws = this.get(WINDOW_SCROLL),
                                            xy = ho.lastXY,
                                            scroll = false,
                                            b = this.get(BUFFER),
                                            win = this.get(PARENT_SCROLL),
                                            sTop = win.get(SCROLL_TOP),
                                            sLeft = win.get(SCROLL_LEFT),
                                            w = this._dimCache.w,
                                            h = this._dimCache.h,
                                            bottom = xy[1] + h,
                                            top = xy[1],
                                            right = xy[0] + w,
                                            left = xy[0],
                                            nt = top,
                                            nl = left,
                                            st = sTop,
                                            sl = sLeft;
                            
                                        if (this.get('horizontal')) {
                                            if (left <= r.left) {
                                                scroll = true;
                                                nl = xy[0] - ((ws) ? b : 0);
                                                sl = sLeft - b;
                                            }
                                            if (right >= r.right) {
                                                scroll = true;
                                                nl = xy[0] + ((ws) ? b : 0);
                                                sl = sLeft + b;
                                            }
                                        }
                                        if (this.get('vertical')) {
                                            if (bottom >= r.bottom) {
                                                scroll = true;
                                                nt = xy[1] + ((ws) ? b : 0);
                                                st = sTop + b;
                            
                                            }
                                            if (top <= r.top) {
                                                scroll = true;
                                                nt = xy[1] - ((ws) ? b : 0);
                                                st = sTop - b;
                                            }
                                        }
                            
                                        if (st < 0) {
                                            st = 0;
                                            nt = xy[1];
                                        }
                            
                                        if (sl < 0) {
                                            sl = 0;
                                            nl = xy[0];
                                        }
                            
                                        if (nt < 0) {
                                            nt = xy[1];
                                        }
                                        if (nl < 0) {
                                            nl = xy[0];
                                        }
                                        if (move) {
                                            ho.actXY = [nl, nt];
                                            ho._alignNode([nl, nt], true); //We are srolling..
                                            xy = ho.actXY;
                                            ho.actXY = [nl, nt];
                                            ho._moveNode({ node: win, top: st, left: sl});
                                            if (!st && !sl) {
                                                this._cancelScroll();
                                            }
                                        } else {
                                            if (scroll) {
                                                this._initScroll();
                                            } else {
                                                this._cancelScroll();
                                            }
                                        }
                                    },
                                    /**
                                    * Cancel a previous scroll timer and init a new one.
                                    * @private
                                    * @method _initScroll
                                    */
                                    _initScroll: function() {
                                        this._cancelScroll();
                                        this._scrollTimer = Y.Lang.later(this.get('scrollDelay'), this, this._checkWinScroll, [true], true);
                            
                                    },
                                    /**
                                    * Cancel a currently running scroll timer.
                                    * @private
                                    * @method _cancelScroll
                                    */
                                    _cancelScroll: function() {
                                        this._scrolling = false;
                                        if (this._scrollTimer) {
                                            this._scrollTimer.cancel();
                                            delete this._scrollTimer;
                                        }
                                    },
                                    /**
                                    * Called from the drag:align event to determine if we need to scroll.
                                    * @method align
                                    */
                                    align: function(e) {
                                        if (this._scrolling) {
                                            this._cancelScroll();
                                            e.preventDefault();
                                        }
                                        if (!this._scrolling) {
                                            this._checkWinScroll();
                                        }
                                    },
                                    /**
                                    * Set the cache of the dragNode dims.
                                    * @private
                                    * @method _setDimCache
                                    */
                                    _setDimCache: function() {
                                        var node = this.get(HOST).get('dragNode');
                                        this._dimCache = {
                                            h: node.get(OFFSET_HEIGHT),
                                            w: node.get(OFFSET_WIDTH)
                                        };
                                    },
                                    /**
                                    * Called from the drag:start event
                                    * @method start
                                    */
                                    start: function() {
                                        this._setDimCache();
                                    },
                                    /**
                                    * Called from the drag:end event
                                    * @method end
                                    */
                                    end: function() {
                                        this._dimCache = null;
                                        this._cancelScroll();
                                    }
                                });
                            
                                Y.namespace('Plugin');
                            
                            
                                /**
                                 * Extends the Scroll class to make the window scroll while dragging.
                                 * @class DDWindowScroll
                                 * @extends Scroll
                                 * @namespace Plugin
                                 * @constructor
                                 */
                                WS = function() {
                                    WS.superclass.constructor.apply(this, arguments);
                                };
                                WS.ATTRS = Y.merge(S.ATTRS, {
                                    /**
                                    * Turn on window scroll support, default: true
                                    * @attribute windowScroll
                                    * @type Boolean
                                    */
                                    windowScroll: {
                                        value: true,
                                        setter: function(scroll) {
                                            if (scroll) {
                                                this.set(PARENT_SCROLL, Y.one('win'));
                                            }
                                            return scroll;
                                        }
                                    }
                                });
                                Y.extend(WS, S, {
                                    //Shouldn't have to do this..
                                    initializer: function() {
                                        this.set('windowScroll', this.get('windowScroll'));
                                    }
                                });
                                /**
                                * The Scroll instance will be placed on the Drag instance under the winscroll namespace.
                                * @property NS
                                * @default winscroll
                                * @readonly
                                * @protected
                                * @static
                                * @type {String}
                                */
                                WS.NAME = WS.NS = 'winscroll';
                                Y.Plugin.DDWinScroll = WS;
                            
                            
                                /**
                                 * Extends the Scroll class to make a parent node scroll while dragging.
                                 * @class DDNodeScroll
                                 * @extends Scroll
                                 * @namespace Plugin
                                 * @constructor
                                 */
                                NS = function() {
                                    NS.superclass.constructor.apply(this, arguments);
                            
                                };
                                NS.ATTRS = Y.merge(S.ATTRS, {
                                    /**
                                    * The node we want to scroll. Used to set the internal parentScroll attribute.
                                    * @attribute node
                                    * @type Node
                                    */
                                    node: {
                                        value: false,
                                        setter: function(node) {
                                            var n = Y.one(node);
                                            if (!n) {
                                                if (node !== false) {
                                                    Y.error('DDNodeScroll: Invalid Node Given: ' + node);
                                                }
                                            } else {
                                                this.set(PARENT_SCROLL, n);
                                            }
                                            return n;
                                        }
                                    }
                                });
                                Y.extend(NS, S, {
                                    //Shouldn't have to do this..
                                    initializer: function() {
                                        this.set('node', this.get('node'));
                                    }
                                });
                                /**
                                * The NodeScroll instance will be placed on the Drag instance under the nodescroll namespace.
                                * @property NS
                                * @default nodescroll
                                * @readonly
                                * @protected
                                * @static
                                * @type {String}
                                */
                                NS.NAME = NS.NS = 'nodescroll';
                                Y.Plugin.DDNodeScroll = NS;
                            
                                Y.DD.Scroll = S;