Upgrade to ExtJS 3.2.2 - Released 06/02/2010
[extjs.git] / src / dd / ScrollManager.js
1 /*!
2  * Ext JS Library 3.2.2
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.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     var els = {};
30     var dragEl = null;
31     var proc = {};
32     
33     var onStop = function(e){
34         dragEl = null;
35         clearProc();
36     };
37     
38     var triggerRefresh = function(){
39         if(ddm.dragCurrent){
40              ddm.refreshCache(ddm.dragCurrent.groups);
41         }
42     };
43     
44     var doScroll = function(){
45         if(ddm.dragCurrent){
46             var dds = Ext.dd.ScrollManager;
47             var inc = proc.el.ddScrollConfig ?
48                       proc.el.ddScrollConfig.increment : dds.increment;
49             if(!dds.animate){
50                 if(proc.el.scroll(proc.dir, inc)){
51                     triggerRefresh();
52                 }
53             }else{
54                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
55             }
56         }
57     };
58     
59     var clearProc = function(){
60         if(proc.id){
61             clearInterval(proc.id);
62         }
63         proc.id = 0;
64         proc.el = null;
65         proc.dir = "";
66     };
67     
68     var startProc = function(el, dir){
69         clearProc();
70         proc.el = el;
71         proc.dir = dir;
72         var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
73                 el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
74         proc.id = setInterval(doScroll, freq);
75     };
76     
77     var onFire = function(e, isDrop){
78         if(isDrop || !ddm.dragCurrent){ return; }
79         var dds = Ext.dd.ScrollManager;
80         if(!dragEl || dragEl != ddm.dragCurrent){
81             dragEl = ddm.dragCurrent;
82             // refresh regions on drag start
83             dds.refreshCache();
84         }
85         
86         var xy = Ext.lib.Event.getXY(e);
87         var pt = new Ext.lib.Point(xy[0], xy[1]);
88         for(var id in els){
89             var el = els[id], r = el._region;
90             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
91             if(r && r.contains(pt) && el.isScrollable()){
92                 if(r.bottom - pt.y <= c.vthresh){
93                     if(proc.el != el){
94                         startProc(el, "down");
95                     }
96                     return;
97                 }else if(r.right - pt.x <= c.hthresh){
98                     if(proc.el != el){
99                         startProc(el, "left");
100                     }
101                     return;
102                 }else if(pt.y - r.top <= c.vthresh){
103                     if(proc.el != el){
104                         startProc(el, "up");
105                     }
106                     return;
107                 }else if(pt.x - r.left <= c.hthresh){
108                     if(proc.el != el){
109                         startProc(el, "right");
110                     }
111                     return;
112                 }
113             }
114         }
115         clearProc();
116     };
117     
118     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
119     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
120     
121     return {
122         /**
123          * Registers new overflow element(s) to auto scroll
124          * @param {Mixed/Array} el The id of or the element to be scrolled or an array of either
125          */
126         register : function(el){
127             if(Ext.isArray(el)){
128                 for(var i = 0, len = el.length; i < len; i++) {
129                         this.register(el[i]);
130                 }
131             }else{
132                 el = Ext.get(el);
133                 els[el.id] = el;
134             }
135         },
136         
137         /**
138          * Unregisters overflow element(s) so they are no longer scrolled
139          * @param {Mixed/Array} el The id of or the element to be removed or an array of either
140          */
141         unregister : function(el){
142             if(Ext.isArray(el)){
143                 for(var i = 0, len = el.length; i < len; i++) {
144                         this.unregister(el[i]);
145                 }
146             }else{
147                 el = Ext.get(el);
148                 delete els[el.id];
149             }
150         },
151         
152         /**
153          * The number of pixels from the top or bottom edge of a container the pointer needs to be to
154          * trigger scrolling (defaults to 25)
155          * @type Number
156          */
157         vthresh : 25,
158         /**
159          * The number of pixels from the right or left edge of a container the pointer needs to be to
160          * trigger scrolling (defaults to 25)
161          * @type Number
162          */
163         hthresh : 25,
164
165         /**
166          * The number of pixels to scroll in each scroll increment (defaults to 50)
167          * @type Number
168          */
169         increment : 100,
170         
171         /**
172          * The frequency of scrolls in milliseconds (defaults to 500)
173          * @type Number
174          */
175         frequency : 500,
176         
177         /**
178          * True to animate the scroll (defaults to true)
179          * @type Boolean
180          */
181         animate: true,
182         
183         /**
184          * The animation duration in seconds - 
185          * MUST BE less than Ext.dd.ScrollManager.frequency! (defaults to .4)
186          * @type Number
187          */
188         animDuration: .4,
189         
190         /**
191          * Manually trigger a cache refresh.
192          */
193         refreshCache : function(){
194             for(var id in els){
195                 if(typeof els[id] == 'object'){ // for people extending the object prototype
196                     els[id]._region = els[id].getRegion();
197                 }
198             }
199         }
200     };
201 }();