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