Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / docs / source / SplitBar.html
1 <html>\r
2 <head>\r
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    \r
4   <title>The source code</title>\r
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
7 </head>\r
8 <body  onload="prettyPrint();">\r
9     <pre class="prettyprint lang-js"><div id="cls-Ext.SplitBar"></div>/**\r
10  * @class Ext.SplitBar\r
11  * @extends Ext.util.Observable\r
12  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).\r
13  * <br><br>\r
14  * Usage:\r
15  * <pre><code>\r
16 var split = new Ext.SplitBar("elementToDrag", "elementToSize",\r
17                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);\r
18 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));\r
19 split.minSize = 100;\r
20 split.maxSize = 600;\r
21 split.animate = true;\r
22 split.on('moved', splitterMoved);\r
23 </code></pre>\r
24  * @constructor\r
25  * Create a new SplitBar\r
26  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
27  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
28  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
29  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or\r
30                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
31                         position of the SplitBar).\r
32  */\r
33 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
34 \r
35     /** @private */\r
36     this.el = Ext.get(dragElement, true);\r
37     this.el.dom.unselectable = "on";\r
38     /** @private */\r
39     this.resizingEl = Ext.get(resizingElement, true);\r
40 \r
41     /**\r
42      * @private\r
43      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
44      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated\r
45      * @type Number\r
46      */\r
47     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
48 \r
49     <div id="prop-Ext.SplitBar-tickSize"></div>/**\r
50      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
51      * @type Number\r
52      * @property tickSize\r
53      */\r
54     <div id="prop-Ext.SplitBar-minSize"></div>/**\r
55      * The minimum size of the resizing element. (Defaults to 0)\r
56      * @type Number\r
57      */\r
58     this.minSize = 0;\r
59 \r
60     <div id="prop-Ext.SplitBar-maxSize"></div>/**\r
61      * The maximum size of the resizing element. (Defaults to 2000)\r
62      * @type Number\r
63      */\r
64     this.maxSize = 2000;\r
65 \r
66     <div id="prop-Ext.SplitBar-animate"></div>/**\r
67      * Whether to animate the transition to the new size\r
68      * @type Boolean\r
69      */\r
70     this.animate = false;\r
71 \r
72     <div id="prop-Ext.SplitBar-useShim"></div>/**\r
73      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
74      * @type Boolean\r
75      */\r
76     this.useShim = false;\r
77 \r
78     /** @private */\r
79     this.shim = null;\r
80 \r
81     if(!existingProxy){\r
82         /** @private */\r
83         this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
84     }else{\r
85         this.proxy = Ext.get(existingProxy).dom;\r
86     }\r
87     /** @private */\r
88     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
89 \r
90     /** @private */\r
91     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
92 \r
93     /** @private */\r
94     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
95 \r
96     /** @private */\r
97     this.dragSpecs = {};\r
98 \r
99     /**\r
100      * @private The adapter to use to positon and resize elements\r
101      */\r
102     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
103     this.adapter.init(this);\r
104 \r
105     if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
106         /** @private */\r
107         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
108         this.el.addClass("x-splitbar-h");\r
109     }else{\r
110         /** @private */\r
111         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
112         this.el.addClass("x-splitbar-v");\r
113     }\r
114 \r
115     this.addEvents(\r
116         <div id="event-Ext.SplitBar-resize"></div>/**\r
117          * @event resize\r
118          * Fires when the splitter is moved (alias for {@link #moved})\r
119          * @param {Ext.SplitBar} this\r
120          * @param {Number} newSize the new width or height\r
121          */\r
122         "resize",\r
123         <div id="event-Ext.SplitBar-moved"></div>/**\r
124          * @event moved\r
125          * Fires when the splitter is moved\r
126          * @param {Ext.SplitBar} this\r
127          * @param {Number} newSize the new width or height\r
128          */\r
129         "moved",\r
130         <div id="event-Ext.SplitBar-beforeresize"></div>/**\r
131          * @event beforeresize\r
132          * Fires before the splitter is dragged\r
133          * @param {Ext.SplitBar} this\r
134          */\r
135         "beforeresize",\r
136 \r
137         "beforeapply"\r
138     );\r
139 \r
140     Ext.SplitBar.superclass.constructor.call(this);\r
141 };\r
142 \r
143 Ext.extend(Ext.SplitBar, Ext.util.Observable, {\r
144     onStartProxyDrag : function(x, y){\r
145         this.fireEvent("beforeresize", this);\r
146         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);\r
147         this.overlay.unselectable();\r
148         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
149         this.overlay.show();\r
150         Ext.get(this.proxy).setDisplayed("block");\r
151         var size = this.adapter.getElementSize(this);\r
152         this.activeMinSize = this.getMinimumSize();\r
153         this.activeMaxSize = this.getMaximumSize();\r
154         var c1 = size - this.activeMinSize;\r
155         var c2 = Math.max(this.activeMaxSize - size, 0);\r
156         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
157             this.dd.resetConstraints();\r
158             this.dd.setXConstraint(\r
159                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,\r
160                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
161                 this.tickSize\r
162             );\r
163             this.dd.setYConstraint(0, 0);\r
164         }else{\r
165             this.dd.resetConstraints();\r
166             this.dd.setXConstraint(0, 0);\r
167             this.dd.setYConstraint(\r
168                 this.placement == Ext.SplitBar.TOP ? c1 : c2,\r
169                 this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
170                 this.tickSize\r
171             );\r
172          }\r
173         this.dragSpecs.startSize = size;\r
174         this.dragSpecs.startPoint = [x, y];\r
175         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
176     },\r
177 \r
178     /**\r
179      * @private Called after the drag operation by the DDProxy\r
180      */\r
181     onEndProxyDrag : function(e){\r
182         Ext.get(this.proxy).setDisplayed(false);\r
183         var endPoint = Ext.lib.Event.getXY(e);\r
184         if(this.overlay){\r
185             Ext.destroy(this.overlay);\r
186             delete this.overlay;\r
187         }\r
188         var newSize;\r
189         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
190             newSize = this.dragSpecs.startSize +\r
191                 (this.placement == Ext.SplitBar.LEFT ?\r
192                     endPoint[0] - this.dragSpecs.startPoint[0] :\r
193                     this.dragSpecs.startPoint[0] - endPoint[0]\r
194                 );\r
195         }else{\r
196             newSize = this.dragSpecs.startSize +\r
197                 (this.placement == Ext.SplitBar.TOP ?\r
198                     endPoint[1] - this.dragSpecs.startPoint[1] :\r
199                     this.dragSpecs.startPoint[1] - endPoint[1]\r
200                 );\r
201         }\r
202         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);\r
203         if(newSize != this.dragSpecs.startSize){\r
204             if(this.fireEvent('beforeapply', this, newSize) !== false){\r
205                 this.adapter.setElementSize(this, newSize);\r
206                 this.fireEvent("moved", this, newSize);\r
207                 this.fireEvent("resize", this, newSize);\r
208             }\r
209         }\r
210     },\r
211 \r
212     <div id="method-Ext.SplitBar-getAdapter"></div>/**\r
213      * Get the adapter this SplitBar uses\r
214      * @return The adapter object\r
215      */\r
216     getAdapter : function(){\r
217         return this.adapter;\r
218     },\r
219 \r
220     <div id="method-Ext.SplitBar-setAdapter"></div>/**\r
221      * Set the adapter this SplitBar uses\r
222      * @param {Object} adapter A SplitBar adapter object\r
223      */\r
224     setAdapter : function(adapter){\r
225         this.adapter = adapter;\r
226         this.adapter.init(this);\r
227     },\r
228 \r
229     <div id="method-Ext.SplitBar-getMinimumSize"></div>/**\r
230      * Gets the minimum size for the resizing element\r
231      * @return {Number} The minimum size\r
232      */\r
233     getMinimumSize : function(){\r
234         return this.minSize;\r
235     },\r
236 \r
237     <div id="method-Ext.SplitBar-setMinimumSize"></div>/**\r
238      * Sets the minimum size for the resizing element\r
239      * @param {Number} minSize The minimum size\r
240      */\r
241     setMinimumSize : function(minSize){\r
242         this.minSize = minSize;\r
243     },\r
244 \r
245     <div id="method-Ext.SplitBar-getMaximumSize"></div>/**\r
246      * Gets the maximum size for the resizing element\r
247      * @return {Number} The maximum size\r
248      */\r
249     getMaximumSize : function(){\r
250         return this.maxSize;\r
251     },\r
252 \r
253     <div id="method-Ext.SplitBar-setMaximumSize"></div>/**\r
254      * Sets the maximum size for the resizing element\r
255      * @param {Number} maxSize The maximum size\r
256      */\r
257     setMaximumSize : function(maxSize){\r
258         this.maxSize = maxSize;\r
259     },\r
260 \r
261     <div id="method-Ext.SplitBar-setCurrentSize"></div>/**\r
262      * Sets the initialize size for the resizing element\r
263      * @param {Number} size The initial size\r
264      */\r
265     setCurrentSize : function(size){\r
266         var oldAnimate = this.animate;\r
267         this.animate = false;\r
268         this.adapter.setElementSize(this, size);\r
269         this.animate = oldAnimate;\r
270     },\r
271 \r
272     <div id="method-Ext.SplitBar-destroy"></div>/**\r
273      * Destroy this splitbar.\r
274      * @param {Boolean} removeEl True to remove the element\r
275      */\r
276     destroy : function(removeEl){\r
277         Ext.destroy(this.shim, Ext.get(this.proxy));\r
278         this.dd.unreg();\r
279         if(removeEl){\r
280             this.el.remove();\r
281         }\r
282         this.purgeListeners();\r
283     }\r
284 });\r
285 \r
286 /**\r
287  * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.\r
288  */\r
289 Ext.SplitBar.createProxy = function(dir){\r
290     var proxy = new Ext.Element(document.createElement("div"));\r
291     document.body.appendChild(proxy.dom);\r
292     proxy.unselectable();\r
293     var cls = 'x-splitbar-proxy';\r
294     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
295     return proxy.dom;\r
296 };\r
297 \r
298 <div id="cls-Ext.SplitBar.BasicLayoutAdapter"></div>/**\r
299  * @class Ext.SplitBar.BasicLayoutAdapter\r
300  * Default Adapter. It assumes the splitter and resizing element are not positioned\r
301  * elements and only gets/sets the width of the element. Generally used for table based layouts.\r
302  */\r
303 Ext.SplitBar.BasicLayoutAdapter = function(){\r
304 };\r
305 \r
306 Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
307     // do nothing for now\r
308     init : function(s){\r
309 \r
310     },\r
311     <div id="method-Ext.SplitBar.BasicLayoutAdapter-getElementSize"></div>/**\r
312      * Called before drag operations to get the current size of the resizing element.\r
313      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
314      */\r
315      getElementSize : function(s){\r
316         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
317             return s.resizingEl.getWidth();\r
318         }else{\r
319             return s.resizingEl.getHeight();\r
320         }\r
321     },\r
322 \r
323     <div id="method-Ext.SplitBar.BasicLayoutAdapter-setElementSize"></div>/**\r
324      * Called after drag operations to set the size of the resizing element.\r
325      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
326      * @param {Number} newSize The new size to set\r
327      * @param {Function} onComplete A function to be invoked when resizing is complete\r
328      */\r
329     setElementSize : function(s, newSize, onComplete){\r
330         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
331             if(!s.animate){\r
332                 s.resizingEl.setWidth(newSize);\r
333                 if(onComplete){\r
334                     onComplete(s, newSize);\r
335                 }\r
336             }else{\r
337                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
338             }\r
339         }else{\r
340 \r
341             if(!s.animate){\r
342                 s.resizingEl.setHeight(newSize);\r
343                 if(onComplete){\r
344                     onComplete(s, newSize);\r
345                 }\r
346             }else{\r
347                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');\r
348             }\r
349         }\r
350     }\r
351 };\r
352 \r
353 <div id="cls-Ext.SplitBar.AbsoluteLayoutAdapter"></div>/**\r
354  *@class Ext.SplitBar.AbsoluteLayoutAdapter\r
355  * @extends Ext.SplitBar.BasicLayoutAdapter\r
356  * Adapter that  moves the splitter element to align with the resized sizing element.\r
357  * Used with an absolute positioned SplitBar.\r
358  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
359  * document.body, make sure you assign an id to the body element.\r
360  */\r
361 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){\r
362     this.basic = new Ext.SplitBar.BasicLayoutAdapter();\r
363     this.container = Ext.get(container);\r
364 };\r
365 \r
366 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {\r
367     init : function(s){\r
368         this.basic.init(s);\r
369     },\r
370 \r
371     getElementSize : function(s){\r
372         return this.basic.getElementSize(s);\r
373     },\r
374 \r
375     setElementSize : function(s, newSize, onComplete){\r
376         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
377     },\r
378 \r
379     moveSplitter : function(s){\r
380         var yes = Ext.SplitBar;\r
381         switch(s.placement){\r
382             case yes.LEFT:\r
383                 s.el.setX(s.resizingEl.getRight());\r
384                 break;\r
385             case yes.RIGHT:\r
386                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");\r
387                 break;\r
388             case yes.TOP:\r
389                 s.el.setY(s.resizingEl.getBottom());\r
390                 break;\r
391             case yes.BOTTOM:\r
392                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());\r
393                 break;\r
394         }\r
395     }\r
396 };\r
397 \r
398 <div id="prop-Ext.SplitBar.AbsoluteLayoutAdapter-VERTICAL"></div>/**\r
399  * Orientation constant - Create a vertical SplitBar\r
400  * @static\r
401  * @type Number\r
402  */\r
403 Ext.SplitBar.VERTICAL = 1;\r
404 \r
405 <div id="prop-Ext.SplitBar.AbsoluteLayoutAdapter-HORIZONTAL"></div>/**\r
406  * Orientation constant - Create a horizontal SplitBar\r
407  * @static\r
408  * @type Number\r
409  */\r
410 Ext.SplitBar.HORIZONTAL = 2;\r
411 \r
412 <div id="prop-Ext.SplitBar.AbsoluteLayoutAdapter-LEFT"></div>/**\r
413  * Placement constant - The resizing element is to the left of the splitter element\r
414  * @static\r
415  * @type Number\r
416  */\r
417 Ext.SplitBar.LEFT = 1;\r
418 \r
419 <div id="prop-Ext.SplitBar.AbsoluteLayoutAdapter-RIGHT"></div>/**\r
420  * Placement constant - The resizing element is to the right of the splitter element\r
421  * @static\r
422  * @type Number\r
423  */\r
424 Ext.SplitBar.RIGHT = 2;\r
425 \r
426 <div id="prop-Ext.SplitBar.AbsoluteLayoutAdapter-TOP"></div>/**\r
427  * Placement constant - The resizing element is positioned above the splitter element\r
428  * @static\r
429  * @type Number\r
430  */\r
431 Ext.SplitBar.TOP = 3;\r
432 \r
433 <div id="prop-Ext.SplitBar.AbsoluteLayoutAdapter-BOTTOM"></div>/**\r
434  * Placement constant - The resizing element is positioned under splitter element\r
435  * @static\r
436  * @type Number\r
437  */\r
438 Ext.SplitBar.BOTTOM = 4;\r
439 </pre>    \r
440 </body>\r
441 </html>