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