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