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