Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / calendar / src / dd / CalendarScrollManager.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 /**
8  * @class Ext.dd.ScrollManager
9  * <p>Provides automatic scrolling of overflow regions in the page during drag operations.</p>
10  * <p>The ScrollManager configs will be used as the defaults for any scroll container registered with it,
11  * but you can also override most of the configs per scroll container by adding a 
12  * <tt>ddScrollConfig</tt> object to the target element that contains these properties: {@link #hthresh},
13  * {@link #vthresh}, {@link #increment} and {@link #frequency}.  Example usage:
14  * <pre><code>
15 var el = Ext.get('scroll-ct');
16 el.ddScrollConfig = {
17     vthresh: 50,
18     hthresh: -1,
19     frequency: 100,
20     increment: 200
21 };
22 Ext.dd.ScrollManager.register(el);
23 </code></pre>
24  * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
25  * @singleton
26  */
27 Ext.dd.ScrollManager = function() {
28     var ddm = Ext.dd.DragDropMgr,
29         els = {},
30         dragEl = null,
31         proc = {},
32         onStop = function(e) {
33             dragEl = null;
34             clearProc();
35         },
36         triggerRefresh = function() {
37             if (ddm.dragCurrent) {
38                 ddm.refreshCache(ddm.dragCurrent.groups);
39             }
40         },
41         doScroll = function() {
42             if (ddm.dragCurrent) {
43                 var dds = Ext.dd.ScrollManager,
44                     inc = proc.el.ddScrollConfig ? proc.el.ddScrollConfig.increment: dds.increment;
45                 if (!dds.animate) {
46                     if (proc.el.scroll(proc.dir, inc)) {
47                         triggerRefresh();
48                     }
49                 } else {
50                     proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
51                 }
52             }
53         },
54         clearProc = function() {
55             if (proc.id) {
56                 clearInterval(proc.id);
57             }
58             proc.id = 0;
59             proc.el = null;
60             proc.dir = "";
61         },
62         startProc = function(el, dir) {
63             clearProc();
64             proc.el = el;
65             proc.dir = dir;
66             var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ?
67                             el.ddScrollConfig.frequency: Ext.dd.ScrollManager.frequency,
68                 group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup: undefined;
69
70             if (group === undefined || ddm.dragCurrent.ddGroup == group) {
71                 proc.id = setInterval(doScroll, freq);
72             }
73         },
74         onFire = function(e, isDrop) {
75             if (isDrop || !ddm.dragCurrent) {
76                 return;
77             }
78             var dds = Ext.dd.ScrollManager;
79             if (!dragEl || dragEl != ddm.dragCurrent) {
80                 dragEl = ddm.dragCurrent;
81                 // refresh regions on drag start
82                 dds.refreshCache();
83             }
84
85             var xy = Ext.lib.Event.getXY(e),
86                 pt = new Ext.lib.Point(xy[0], xy[1]),
87                 id,
88                 el,
89                 r,
90                 c;
91             for (id in els) {
92                 if (els.hasOwnProperty(id)) {
93                     el = els[id];
94                     r = el._region;
95                     c = el.ddScrollConfig ? el.ddScrollConfig: dds;
96                     if (r && r.contains(pt) && el.isScrollable()) {
97                         if (r.bottom - pt.y <= c.vthresh) {
98                             if (proc.el != el) {
99                                 startProc(el, "down");
100                             }
101                             return;
102                         } else if (r.right - pt.x <= c.hthresh) {
103                             if (proc.el != el) {
104                                 startProc(el, "left");
105                             }
106                             return;
107                         } else if (pt.y - r.top <= c.vthresh) {
108                             if (proc.el != el) {
109                                 startProc(el, "up");
110                             }
111                             return;
112                         } else if (pt.x - r.left <= c.hthresh) {
113                             if (proc.el != el) {
114                                 startProc(el, "right");
115                             }
116                             return;
117                         }
118                     }
119                 }
120             }
121             clearProc();
122         };
123
124     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
125     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
126
127     return {
128         /**
129          * Registers new overflow element(s) to auto scroll
130          * @param {Mixed/Array} el The id of or the element to be scrolled or an array of either
131          */
132         register: function(el) {
133             if (Ext.isArray(el)) {
134                 var i = 0,
135                     len = el.length;
136                 for (; i < len; i++) {
137                     this.register(el[i]);
138                 }
139             } else {
140                 el = Ext.get(el);
141                 els[el.id] = el;
142             }
143         },
144
145         /**
146          * Unregisters overflow element(s) so they are no longer scrolled
147          * @param {Mixed/Array} el The id of or the element to be removed or an array of either
148          */
149         unregister: function(el) {
150             if (Ext.isArray(el)) {
151                 var i = 0,
152                     len = el.length;
153                 for (; i < len; i++) {
154                     this.unregister(el[i]);
155                 }
156             } else {
157                 el = Ext.get(el);
158                 delete els[el.id];
159             }
160         },
161
162         /**
163          * The number of pixels from the top or bottom edge of a container the pointer needs to be to
164          * trigger scrolling (defaults to 25)
165          * @type Number
166          */
167         vthresh: 25,
168         /**
169          * The number of pixels from the right or left edge of a container the pointer needs to be to
170          * trigger scrolling (defaults to 25)
171          * @type Number
172          */
173         hthresh: 25,
174
175         /**
176          * The number of pixels to scroll in each scroll increment (defaults to 50)
177          * @type Number
178          */
179         increment: 100,
180
181         /**
182          * The frequency of scrolls in milliseconds (defaults to 500)
183          * @type Number
184          */
185         frequency: 500,
186
187         /**
188          * True to animate the scroll (defaults to true)
189          * @type Boolean
190          */
191         animate: true,
192
193         /**
194          * The animation duration in seconds - 
195          * MUST BE less than Ext.dd.ScrollManager.frequency! (defaults to .4)
196          * @type Number
197          */
198         animDuration: 0.4,
199
200         /**
201          * Manually trigger a cache refresh.
202          */
203         refreshCache: function() {
204             var id;
205             for (id in els) {
206                 if (els.hasOwnProperty(id)) {
207                     if (typeof els[id] == 'object') {
208                         // for people extending the object prototype
209                         els[id]._region = els[id].getRegion();
210                     }
211                 }
212             }
213         }
214     };
215 }();