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