2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
8 YUI.add('dd-scroll', function(Y) {
12 * The Drag & Drop Utility allows you to create a draggable interface efficiently, buffering you from browser-level abnormalities and enabling you to focus on the interesting logic surrounding your particular implementation. This component enables you to create a variety of standard draggable objects with just a few lines of code and then, using its extensive API, add your own specific implementation logic.
14 * @submodule dd-scroll
17 * This class is the base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
18 * This class should not be called on it's own, it's designed to be a plugin.
26 S.superclass.constructor.apply(this, arguments);
31 PARENT_SCROLL = 'parentScroll',
32 WINDOW_SCROLL = 'windowScroll',
33 SCROLL_TOP = 'scrollTop',
34 SCROLL_LEFT = 'scrollLeft',
35 OFFSET_WIDTH = 'offsetWidth',
36 OFFSET_HEIGHT = 'offsetHeight';
41 * @attribute parentScroll
42 * @description Internal config option to hold the node that we are scrolling. Should not be set by the developer.
47 setter: function(node) {
56 * @description The number of pixels from the edge of the screen to turn on scrolling. Default: 30
63 * @attribute scrollDelay
64 * @description The number of milliseconds delay to pass to the auto scroller. Default: 235
72 * @description The host we are plugged into.
79 * @attribute windowScroll
80 * @description Turn on window scroll support, default: false
88 * @description Allow vertical scrolling, default: true.
95 * @attribute horizontal
96 * @description Allow horizontal scrolling, default: true.
104 Y.extend(S, Y.Base, {
107 * @property _scrolling
108 * @description Tells if we are actively scrolling or not.
114 * @property _vpRegionCache
115 * @description Cache of the Viewport dims.
118 _vpRegionCache: null,
121 * @property _dimCache
122 * @description Cache of the dragNode dims.
128 * @property _scrollTimer
129 * @description Holder for the Timer object returned from Y.later.
135 * @method _getVPRegion
136 * @description Sets the _vpRegionCache property with an Object containing the dims from the viewport.
138 _getVPRegion: function() {
140 //if (!this._vpRegionCache) {
141 var n = this.get(PARENT_SCROLL),
142 b = this.get(BUFFER),
143 ws = this.get(WINDOW_SCROLL),
144 xy = ((ws) ? [] : n.getXY()),
145 w = ((ws) ? 'winWidth' : OFFSET_WIDTH),
146 h = ((ws) ? 'winHeight' : OFFSET_HEIGHT),
147 t = ((ws) ? n.get(SCROLL_TOP) : xy[1]),
148 l = ((ws) ? n.get(SCROLL_LEFT) : xy[0]);
152 right: (n.get(w) + l) - b,
153 bottom: (n.get(h) + t) - b,
156 this._vpRegionCache = r;
158 // r = this._vpRegionCache;
162 initializer: function() {
163 var h = this.get(HOST);
164 h.after('drag:start', Y.bind(this.start, this));
165 h.after('drag:end', Y.bind(this.end, this));
166 h.on('drag:align', Y.bind(this.align, this));
168 //TODO - This doesn't work yet??
169 Y.get(window).on('scroll', Y.bind(function() {
170 this._vpRegionCache = null;
175 * @method _checkWinScroll
176 * @description Check to see if we need to fire the scroll timer. If scroll timer is running this will scroll the window.
177 * @param {Boolean} move Should we move the window. From Y.later
179 _checkWinScroll: function(move) {
180 var r = this._getVPRegion(),
182 ws = this.get(WINDOW_SCROLL),
185 b = this.get(BUFFER),
186 win = this.get(PARENT_SCROLL),
187 sTop = win.get(SCROLL_TOP),
188 sLeft = win.get(SCROLL_LEFT),
189 w = this._dimCache.w,
190 h = this._dimCache.h,
200 if (this.get('horizontal')) {
201 if (left <= r.left) {
203 nl = xy[0] - ((ws) ? b : 0);
206 if (right >= r.right) {
208 nl = xy[0] + ((ws) ? b : 0);
212 if (this.get('vertical')) {
213 if (bottom >= r.bottom) {
215 nt = xy[1] + ((ws) ? b : 0);
221 nt = xy[1] - ((ws) ? b : 0);
244 ho._moveNode({ node: win, top: st, left: sl});
246 this._cancelScroll();
252 this._cancelScroll();
258 * @method _initScroll
259 * @description Cancel a previous scroll timer and init a new one.
261 _initScroll: function() {
262 this._cancelScroll();
263 this._scrollTimer = Y.Lang.later(this.get('scrollDelay'), this, this._checkWinScroll, [true], true);
268 * @method _cancelScroll
269 * @description Cancel a currently running scroll timer.
271 _cancelScroll: function() {
272 this._scrolling = false;
273 if (this._scrollTimer) {
274 this._scrollTimer.cancel();
275 delete this._scrollTimer;
280 * @description Called from the drag:align event to determine if we need to scroll.
283 if (this._scrolling) {
284 this._cancelScroll();
287 if (!this._scrolling) {
288 this._checkWinScroll();
293 * @method _setDimCache
294 * @description Set the cache of the dragNode dims.
296 _setDimCache: function() {
297 var node = this.get(HOST).get('dragNode');
299 h: node.get(OFFSET_HEIGHT),
300 w: node.get(OFFSET_WIDTH)
305 * @description Called from the drag:start event
312 * @description Called from the drag:end event
315 this._dimCache = null;
316 this._cancelScroll();
320 * @description General toString method for logging
321 * @return String name for the object
323 toString: function() {
324 return S.NAME + ' #' + this.get('node').get('id');
328 Y.namespace('Plugin');
332 * Extends the Scroll class to make the window scroll while dragging.
333 * @class DDWindowScroll
338 var WS = function() {
339 WS.superclass.constructor.apply(this, arguments);
341 WS.ATTRS = Y.merge(S.ATTRS, {
343 * @attribute windowScroll
344 * @description Turn on window scroll support, default: true
349 setter: function(scroll) {
351 this.set(PARENT_SCROLL, Y.get(window));
358 //Shouldn't have to do this..
359 initializer: function() {
360 this.set('windowScroll', this.get('windowScroll'));
363 WS.NAME = WS.NS = 'winscroll';
364 Y.Plugin.DDWinScroll = WS;
368 * Extends the Scroll class to make a parent node scroll while dragging.
369 * @class DDNodeScroll
374 var NS = function() {
375 NS.superclass.constructor.apply(this, arguments);
378 NS.ATTRS = Y.merge(S.ATTRS, {
381 * @description The node we want to scroll. Used to set the internal parentScroll attribute.
386 setter: function(node) {
389 if (node !== false) {
390 Y.error('DDNodeScroll: Invalid Node Given: ' + node);
394 this.set(PARENT_SCROLL, n);
401 //Shouldn't have to do this..
402 initializer: function() {
403 this.set('node', this.get('node'));
406 NS.NAME = NS.NS = 'nodescroll';
407 Y.Plugin.DDNodeScroll = NS;
413 }, '3.0.0' ,{skinnable:false, requires:['dd-drag'], optional:['dd-proxy']});