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