]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/dd/dd-scroll.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / dd / dd-scroll.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('dd-scroll', function(Y) {
9
10
11     /**
12      * Base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
13      * This class should not be called on it's own, it's designed to be a plugin.
14      * @module dd
15      * @submodule dd-scroll
16      */
17     /**
18      * Base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
19      * This class should not be called on it's own, it's designed to be a plugin.
20      * @class Scroll
21      * @extends Base
22      * @namespace DD
23      * @constructor
24      */
25
26     var S = function() {
27         S.superclass.constructor.apply(this, arguments);
28
29     },
30     WS, NS,
31     HOST = 'host',
32     BUFFER = 'buffer',
33     PARENT_SCROLL = 'parentScroll',
34     WINDOW_SCROLL = 'windowScroll',
35     SCROLL_TOP = 'scrollTop',
36     SCROLL_LEFT = 'scrollLeft',
37     OFFSET_WIDTH = 'offsetWidth',
38     OFFSET_HEIGHT = 'offsetHeight';
39
40
41     S.ATTRS = {
42         /**
43         * @attribute parentScroll
44         * @description Internal config option to hold the node that we are scrolling. Should not be set by the developer.
45         * @type Node
46         */
47         parentScroll: {
48             value: false,
49             setter: function(node) {
50                 if (node) {
51                     return node;
52                 }
53                 return false;
54             }
55         },
56         /**
57         * @attribute buffer
58         * @description The number of pixels from the edge of the screen to turn on scrolling. Default: 30
59         * @type Number
60         */
61         buffer: {
62             value: 30,
63             validator: Y.Lang.isNumber
64         },
65         /**
66         * @attribute scrollDelay
67         * @description The number of milliseconds delay to pass to the auto scroller. Default: 235
68         * @type Number
69         */
70         scrollDelay: {
71             value: 235,
72             validator: Y.Lang.isNumber
73         },
74         /**
75         * @attribute host
76         * @description The host we are plugged into.
77         * @type Object
78         */
79         host: {
80             value: null
81         },
82         /**
83         * @attribute windowScroll
84         * @description Turn on window scroll support, default: false
85         * @type Boolean
86         */
87         windowScroll: {
88             value: false,
89             validator: Y.Lang.isBoolean
90         },
91         /**
92         * @attribute vertical
93         * @description Allow vertical scrolling, default: true.
94         * @type Boolean
95         */
96         vertical: {
97             value: true,
98             validator: Y.Lang.isBoolean
99         },
100         /**
101         * @attribute horizontal
102         * @description Allow horizontal scrolling, default: true.
103         * @type Boolean
104         */
105         horizontal: {
106             value: true,
107             validator: Y.Lang.isBoolean
108         }
109     };
110
111     Y.extend(S, Y.Base, {
112         /**
113         * @private
114         * @property _scrolling
115         * @description Tells if we are actively scrolling or not.
116         * @type Boolean
117         */
118         _scrolling: null,
119         /**
120         * @private
121         * @property _vpRegionCache
122         * @description Cache of the Viewport dims.
123         * @type Object
124         */
125         _vpRegionCache: null,
126         /**
127         * @private
128         * @property _dimCache
129         * @description Cache of the dragNode dims.
130         * @type Object
131         */
132         _dimCache: null,
133         /**
134         * @private
135         * @property _scrollTimer
136         * @description Holder for the Timer object returned from Y.later.
137         * @type {Y.later}
138         */
139         _scrollTimer: null,
140         /**
141         * @private
142         * @method _getVPRegion
143         * @description Sets the _vpRegionCache property with an Object containing the dims from the viewport.
144         */        
145         _getVPRegion: function() {
146             var r = {},
147                 n = this.get(PARENT_SCROLL),
148             b = this.get(BUFFER),
149             ws = this.get(WINDOW_SCROLL),
150             xy = ((ws) ? [] : n.getXY()),
151             w = ((ws) ? 'winWidth' : OFFSET_WIDTH),
152             h = ((ws) ? 'winHeight' : OFFSET_HEIGHT),
153             t = ((ws) ? n.get(SCROLL_TOP) : xy[1]),
154             l = ((ws) ? n.get(SCROLL_LEFT) : xy[0]);
155
156             r = {
157                 top: t + b,
158                 right: (n.get(w) + l) - b,
159                 bottom: (n.get(h) + t) - b,
160                 left: l + b
161             };
162             this._vpRegionCache = r;
163             return r;
164         },
165         initializer: function() {
166             var h = this.get(HOST);
167             h.after('drag:start', Y.bind(this.start, this));
168             h.after('drag:end', Y.bind(this.end, this));
169             h.on('drag:align', Y.bind(this.align, this));
170
171             //TODO - This doesn't work yet??
172             Y.one('win').on('scroll', Y.bind(function() {
173                 this._vpRegionCache = null;
174             }, this));
175         },
176         /**
177         * @private
178         * @method _checkWinScroll
179         * @description Check to see if we need to fire the scroll timer. If scroll timer is running this will scroll the window.
180         * @param {Boolean} move Should we move the window. From Y.later
181         */        
182         _checkWinScroll: function(move) {
183             var r = this._getVPRegion(),
184                 ho = this.get(HOST),
185                 ws = this.get(WINDOW_SCROLL),
186                 xy = ho.lastXY,
187                 scroll = false,
188                 b = this.get(BUFFER),
189                 win = this.get(PARENT_SCROLL),
190                 sTop = win.get(SCROLL_TOP),
191                 sLeft = win.get(SCROLL_LEFT),
192                 w = this._dimCache.w,
193                 h = this._dimCache.h,
194                 bottom = xy[1] + h,
195                 top = xy[1],
196                 right = xy[0] + w,
197                 left = xy[0],
198                 nt = top,
199                 nl = left,
200                 st = sTop,
201                 sl = sLeft;
202             
203             if (this.get('horizontal')) {
204                 if (left <= r.left) {
205                     scroll = true;
206                     nl = xy[0] - ((ws) ? b : 0);
207                     sl = sLeft - b;
208                 }
209                 if (right >= r.right) {
210                     scroll = true;
211                     nl = xy[0] + ((ws) ? b : 0);
212                     sl = sLeft + b;
213                 }
214             }
215             if (this.get('vertical')) {
216                 if (bottom >= r.bottom) {
217                     scroll = true;
218                     nt = xy[1] + ((ws) ? b : 0);
219                     st = sTop + b;
220
221                 }
222                 if (top <= r.top) {
223                     scroll = true;
224                     nt = xy[1] - ((ws) ? b : 0);
225                     st = sTop - b;
226                 }
227             }
228
229             if (st < 0) {
230                 st = 0;
231                 nt = xy[1];
232             }
233
234             if (sl < 0) {
235                 sl = 0;
236                 nl = xy[0];
237             }
238
239             if (nt < 0) {
240                 nt = xy[1];
241             }
242             if (nl < 0) {
243                 nl = xy[0];
244             }
245             if (move) {
246                 ho.actXY = [nl, nt];
247                 ho._moveNode({ node: win, top: st, left: sl});
248                 if (!st && !sl) {
249                     this._cancelScroll();
250                 }
251             } else {
252                 if (scroll) {
253                     this._initScroll();
254                 } else {
255                     this._cancelScroll();
256                 }
257             }
258         },
259         /**
260         * @private
261         * @method _initScroll
262         * @description Cancel a previous scroll timer and init a new one.
263         */        
264         _initScroll: function() {
265             this._cancelScroll();
266             this._scrollTimer = Y.Lang.later(this.get('scrollDelay'), this, this._checkWinScroll, [true], true);
267
268         },
269         /**
270         * @private
271         * @method _cancelScroll
272         * @description Cancel a currently running scroll timer.
273         */        
274         _cancelScroll: function() {
275             this._scrolling = false;
276             if (this._scrollTimer) {
277                 this._scrollTimer.cancel();
278                 delete this._scrollTimer;
279             }
280         },
281         /**
282         * @method align
283         * @description Called from the drag:align event to determine if we need to scroll.
284         */        
285         align: function(e) {
286             if (this._scrolling) {
287                 this._cancelScroll();
288                 e.preventDefault();
289             }
290             if (!this._scrolling) {
291                 this._checkWinScroll();
292             }
293         },
294         /**
295         * @private
296         * @method _setDimCache
297         * @description Set the cache of the dragNode dims.
298         */        
299         _setDimCache: function() {
300             var node = this.get(HOST).get('dragNode');
301             this._dimCache = {
302                 h: node.get(OFFSET_HEIGHT),
303                 w: node.get(OFFSET_WIDTH)
304             };
305         },
306         /**
307         * @method start
308         * @description Called from the drag:start event
309         */
310         start: function() {
311             this._setDimCache();
312         },
313         /**
314         * @method end
315         * @description Called from the drag:end event
316         */
317         end: function(xy) {
318             this._dimCache = null;
319             this._cancelScroll();
320         },
321         /**
322         * @method toString
323         * @description General toString method for logging
324         * @return String name for the object
325         */
326         toString: function() {
327             return S.NAME + ' #' + this.get('node').get('id');
328         }
329     });
330
331     Y.namespace('Plugin');
332
333     
334     /**
335      * Extends the Scroll class to make the window scroll while dragging.
336      * @class DDWindowScroll
337      * @extends DD.Scroll
338      * @namespace Plugin
339      * @constructor
340      */
341     WS = function() {
342         WS.superclass.constructor.apply(this, arguments);
343     };
344     WS.ATTRS = Y.merge(S.ATTRS, {
345         /**
346         * @attribute windowScroll
347         * @description Turn on window scroll support, default: true
348         * @type Boolean
349         */
350         windowScroll: {
351             value: true,
352             setter: function(scroll) {
353                 if (scroll) {
354                     this.set(PARENT_SCROLL, Y.one('win'));
355                 }
356                 return scroll;
357             }
358         }
359     });
360     Y.extend(WS, S, {
361         //Shouldn't have to do this..
362         initializer: function() {
363             this.set('windowScroll', this.get('windowScroll'));
364         }
365     });
366     /**
367     * @property NS
368     * @default winscroll
369     * @readonly
370     * @protected
371     * @static
372     * @description The Scroll instance will be placed on the Drag instance under the winscroll namespace.
373     * @type {String}
374     */
375     WS.NAME = WS.NS = 'winscroll';
376     Y.Plugin.DDWinScroll = WS;
377     
378
379     /**
380      * Extends the Scroll class to make a parent node scroll while dragging.
381      * @class DDNodeScroll
382      * @extends DD.Scroll
383      * @namespace Plugin
384      * @constructor
385      */
386     NS = function() {
387         NS.superclass.constructor.apply(this, arguments);
388
389     };
390     NS.ATTRS = Y.merge(S.ATTRS, {
391         /**
392         * @attribute node
393         * @description The node we want to scroll. Used to set the internal parentScroll attribute.
394         * @type Node
395         */
396         node: {
397             value: false,
398             setter: function(node) {
399                 var n = Y.one(node);
400                 if (!n) {
401                     if (node !== false) {
402                         Y.error('DDNodeScroll: Invalid Node Given: ' + node);
403                     }
404                 } else {
405                     this.set(PARENT_SCROLL, n);
406                 }
407                 return n;
408             }
409         }
410     });
411     Y.extend(NS, S, {
412         //Shouldn't have to do this..
413         initializer: function() {
414             this.set('node', this.get('node'));
415         }
416     });
417     /**
418     * @property NS
419     * @default nodescroll
420     * @readonly
421     * @protected
422     * @static
423     * @description The NodeScroll instance will be placed on the Drag instance under the nodescroll namespace.
424     * @type {String}
425     */
426     NS.NAME = NS.NS = 'nodescroll';
427     Y.Plugin.DDNodeScroll = NS;
428
429     Y.DD.Scroll = S;    
430
431
432
433 }, '3.3.0' ,{requires:['dd-drag'], skinnable:false, optional:['dd-proxy']});