3 * Copyright(c) 2006-2010 Ext JS, LLC
5 * http://www.extjs.com/license
8 * @class Ext.SplitBar
\r
9 * @extends Ext.util.Observable
\r
10 * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
\r
14 var split = new Ext.SplitBar("elementToDrag", "elementToSize",
\r
15 Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
\r
16 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
\r
17 split.minSize = 100;
\r
18 split.maxSize = 600;
\r
19 split.animate = true;
\r
20 split.on('moved', splitterMoved);
\r
23 * Create a new SplitBar
\r
24 * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
\r
25 * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
\r
26 * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
\r
27 * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or
\r
28 Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
\r
29 position of the SplitBar).
\r
31 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
\r
34 this.el = Ext.get(dragElement, true);
\r
35 this.el.dom.unselectable = "on";
\r
37 this.resizingEl = Ext.get(resizingElement, true);
\r
41 * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
\r
42 * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
\r
45 this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
\r
48 * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
\r
50 * @property tickSize
\r
53 * The minimum size of the resizing element. (Defaults to 0)
\r
59 * The maximum size of the resizing element. (Defaults to 2000)
\r
62 this.maxSize = 2000;
\r
65 * Whether to animate the transition to the new size
\r
68 this.animate = false;
\r
71 * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
\r
74 this.useShim = false;
\r
81 this.proxy = Ext.SplitBar.createProxy(this.orientation);
\r
83 this.proxy = Ext.get(existingProxy).dom;
\r
86 this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
\r
89 this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
\r
92 this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
\r
95 this.dragSpecs = {};
\r
98 * @private The adapter to use to positon and resize elements
\r
100 this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
\r
101 this.adapter.init(this);
\r
103 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
105 this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
\r
106 this.el.addClass("x-splitbar-h");
\r
109 this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
\r
110 this.el.addClass("x-splitbar-v");
\r
116 * Fires when the splitter is moved (alias for {@link #moved})
\r
117 * @param {Ext.SplitBar} this
\r
118 * @param {Number} newSize the new width or height
\r
123 * Fires when the splitter is moved
\r
124 * @param {Ext.SplitBar} this
\r
125 * @param {Number} newSize the new width or height
\r
129 * @event beforeresize
\r
130 * Fires before the splitter is dragged
\r
131 * @param {Ext.SplitBar} this
\r
138 Ext.SplitBar.superclass.constructor.call(this);
\r
141 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
\r
142 onStartProxyDrag : function(x, y){
\r
143 this.fireEvent("beforeresize", this);
\r
144 this.overlay = Ext.DomHelper.append(document.body, {cls: "x-drag-overlay", html: " "}, true);
\r
145 this.overlay.unselectable();
\r
146 this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
\r
147 this.overlay.show();
\r
148 Ext.get(this.proxy).setDisplayed("block");
\r
149 var size = this.adapter.getElementSize(this);
\r
150 this.activeMinSize = this.getMinimumSize();
\r
151 this.activeMaxSize = this.getMaximumSize();
\r
152 var c1 = size - this.activeMinSize;
\r
153 var c2 = Math.max(this.activeMaxSize - size, 0);
\r
154 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
155 this.dd.resetConstraints();
\r
156 this.dd.setXConstraint(
\r
157 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
\r
158 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
\r
161 this.dd.setYConstraint(0, 0);
\r
163 this.dd.resetConstraints();
\r
164 this.dd.setXConstraint(0, 0);
\r
165 this.dd.setYConstraint(
\r
166 this.placement == Ext.SplitBar.TOP ? c1 : c2,
\r
167 this.placement == Ext.SplitBar.TOP ? c2 : c1,
\r
171 this.dragSpecs.startSize = size;
\r
172 this.dragSpecs.startPoint = [x, y];
\r
173 Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
\r
177 * @private Called after the drag operation by the DDProxy
\r
179 onEndProxyDrag : function(e){
\r
180 Ext.get(this.proxy).setDisplayed(false);
\r
181 var endPoint = Ext.lib.Event.getXY(e);
\r
183 Ext.destroy(this.overlay);
\r
184 delete this.overlay;
\r
187 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
188 newSize = this.dragSpecs.startSize +
\r
189 (this.placement == Ext.SplitBar.LEFT ?
\r
190 endPoint[0] - this.dragSpecs.startPoint[0] :
\r
191 this.dragSpecs.startPoint[0] - endPoint[0]
\r
194 newSize = this.dragSpecs.startSize +
\r
195 (this.placement == Ext.SplitBar.TOP ?
\r
196 endPoint[1] - this.dragSpecs.startPoint[1] :
\r
197 this.dragSpecs.startPoint[1] - endPoint[1]
\r
200 newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
\r
201 if(newSize != this.dragSpecs.startSize){
\r
202 if(this.fireEvent('beforeapply', this, newSize) !== false){
\r
203 this.adapter.setElementSize(this, newSize);
\r
204 this.fireEvent("moved", this, newSize);
\r
205 this.fireEvent("resize", this, newSize);
\r
211 * Get the adapter this SplitBar uses
\r
212 * @return The adapter object
\r
214 getAdapter : function(){
\r
215 return this.adapter;
\r
219 * Set the adapter this SplitBar uses
\r
220 * @param {Object} adapter A SplitBar adapter object
\r
222 setAdapter : function(adapter){
\r
223 this.adapter = adapter;
\r
224 this.adapter.init(this);
\r
228 * Gets the minimum size for the resizing element
\r
229 * @return {Number} The minimum size
\r
231 getMinimumSize : function(){
\r
232 return this.minSize;
\r
236 * Sets the minimum size for the resizing element
\r
237 * @param {Number} minSize The minimum size
\r
239 setMinimumSize : function(minSize){
\r
240 this.minSize = minSize;
\r
244 * Gets the maximum size for the resizing element
\r
245 * @return {Number} The maximum size
\r
247 getMaximumSize : function(){
\r
248 return this.maxSize;
\r
252 * Sets the maximum size for the resizing element
\r
253 * @param {Number} maxSize The maximum size
\r
255 setMaximumSize : function(maxSize){
\r
256 this.maxSize = maxSize;
\r
260 * Sets the initialize size for the resizing element
\r
261 * @param {Number} size The initial size
\r
263 setCurrentSize : function(size){
\r
264 var oldAnimate = this.animate;
\r
265 this.animate = false;
\r
266 this.adapter.setElementSize(this, size);
\r
267 this.animate = oldAnimate;
\r
271 * Destroy this splitbar.
\r
272 * @param {Boolean} removeEl True to remove the element
\r
274 destroy : function(removeEl){
\r
275 Ext.destroy(this.shim, Ext.get(this.proxy));
\r
280 this.purgeListeners();
\r
285 * @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
287 Ext.SplitBar.createProxy = function(dir){
\r
288 var proxy = new Ext.Element(document.createElement("div"));
\r
289 document.body.appendChild(proxy.dom);
\r
290 proxy.unselectable();
\r
291 var cls = 'x-splitbar-proxy';
\r
292 proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
\r
297 * @class Ext.SplitBar.BasicLayoutAdapter
\r
298 * Default Adapter. It assumes the splitter and resizing element are not positioned
\r
299 * elements and only gets/sets the width of the element. Generally used for table based layouts.
\r
301 Ext.SplitBar.BasicLayoutAdapter = function(){
\r
304 Ext.SplitBar.BasicLayoutAdapter.prototype = {
\r
305 // do nothing for now
\r
306 init : function(s){
\r
310 * Called before drag operations to get the current size of the resizing element.
\r
311 * @param {Ext.SplitBar} s The SplitBar using this adapter
\r
313 getElementSize : function(s){
\r
314 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
315 return s.resizingEl.getWidth();
\r
317 return s.resizingEl.getHeight();
\r
322 * Called after drag operations to set the size of the resizing element.
\r
323 * @param {Ext.SplitBar} s The SplitBar using this adapter
\r
324 * @param {Number} newSize The new size to set
\r
325 * @param {Function} onComplete A function to be invoked when resizing is complete
\r
327 setElementSize : function(s, newSize, onComplete){
\r
328 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
330 s.resizingEl.setWidth(newSize);
\r
332 onComplete(s, newSize);
\r
335 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
\r
340 s.resizingEl.setHeight(newSize);
\r
342 onComplete(s, newSize);
\r
345 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
\r
352 *@class Ext.SplitBar.AbsoluteLayoutAdapter
\r
353 * @extends Ext.SplitBar.BasicLayoutAdapter
\r
354 * Adapter that moves the splitter element to align with the resized sizing element.
\r
355 * Used with an absolute positioned SplitBar.
\r
356 * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
\r
357 * document.body, make sure you assign an id to the body element.
\r
359 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
\r
360 this.basic = new Ext.SplitBar.BasicLayoutAdapter();
\r
361 this.container = Ext.get(container);
\r
364 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
\r
365 init : function(s){
\r
366 this.basic.init(s);
\r
369 getElementSize : function(s){
\r
370 return this.basic.getElementSize(s);
\r
373 setElementSize : function(s, newSize, onComplete){
\r
374 this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
\r
377 moveSplitter : function(s){
\r
378 var yes = Ext.SplitBar;
\r
379 switch(s.placement){
\r
381 s.el.setX(s.resizingEl.getRight());
\r
384 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
\r
387 s.el.setY(s.resizingEl.getBottom());
\r
390 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
\r
397 * Orientation constant - Create a vertical SplitBar
\r
401 Ext.SplitBar.VERTICAL = 1;
\r
404 * Orientation constant - Create a horizontal SplitBar
\r
408 Ext.SplitBar.HORIZONTAL = 2;
\r
411 * Placement constant - The resizing element is to the left of the splitter element
\r
415 Ext.SplitBar.LEFT = 1;
\r
418 * Placement constant - The resizing element is to the right of the splitter element
\r
422 Ext.SplitBar.RIGHT = 2;
\r
425 * Placement constant - The resizing element is positioned above the splitter element
\r
429 Ext.SplitBar.TOP = 3;
\r
432 * Placement constant - The resizing element is positioned under splitter element
\r
436 Ext.SplitBar.BOTTOM = 4;
\r