Roo/form/ComboBoxArray.js
[roojs1] / Roo / Toolbar.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  * @class Roo.Toolbar
14  * Basic Toolbar class.
15  * @constructor
16  * Creates a new Toolbar
17  * @param {Object} container The config object
18  */ 
19 Roo.Toolbar = function(container, buttons, config)
20 {
21     /// old consturctor format still supported..
22     if(container instanceof Array){ // omit the container for later rendering
23         buttons = container;
24         config = buttons;
25         container = null;
26     }
27     if (typeof(container) == 'object' && container.xtype) {
28         config = container;
29         container = config.container;
30         buttons = config.buttons || []; // not really - use items!!
31     }
32     var xitems = [];
33     if (config && config.items) {
34         xitems = config.items;
35         delete config.items;
36     }
37     Roo.apply(this, config);
38     this.buttons = buttons;
39     
40     if(container){
41         this.render(container);
42     }
43     this.xitems = xitems;
44     Roo.each(xitems, function(b) {
45         this.add(b);
46     }, this);
47     
48 };
49
50 Roo.Toolbar.prototype = {
51     /**
52      * @cfg {Array} items
53      * array of button configs or elements to add (will be converted to a MixedCollection)
54      */
55     
56     /**
57      * @cfg {String/HTMLElement/Element} container
58      * The id or element that will contain the toolbar
59      */
60     // private
61     render : function(ct){
62         this.el = Roo.get(ct);
63         if(this.cls){
64             this.el.addClass(this.cls);
65         }
66         // using a table allows for vertical alignment
67         // 100% width is needed by Safari...
68         this.el.update('<div class="x-toolbar x-small-editor"><table cellspacing="0"><tr></tr></table></div>');
69         this.tr = this.el.child("tr", true);
70         var autoId = 0;
71         this.items = new Roo.util.MixedCollection(false, function(o){
72             return o.id || ("item" + (++autoId));
73         });
74         if(this.buttons){
75             this.add.apply(this, this.buttons);
76             delete this.buttons;
77         }
78     },
79
80     /**
81      * Adds element(s) to the toolbar -- this function takes a variable number of 
82      * arguments of mixed type and adds them to the toolbar.
83      * @param {Mixed} arg1 The following types of arguments are all valid:<br />
84      * <ul>
85      * <li>{@link Roo.Toolbar.Button} config: A valid button config object (equivalent to {@link #addButton})</li>
86      * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>
87      * <li>Field: Any form field (equivalent to {@link #addField})</li>
88      * <li>Item: Any subclass of {@link Roo.Toolbar.Item} (equivalent to {@link #addItem})</li>
89      * <li>String: Any generic string (gets wrapped in a {@link Roo.Toolbar.TextItem}, equivalent to {@link #addText}).
90      * Note that there are a few special strings that are treated differently as explained nRoo.</li>
91      * <li>'separator' or '-': Creates a separator element (equivalent to {@link #addSeparator})</li>
92      * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>
93      * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>
94      * </ul>
95      * @param {Mixed} arg2
96      * @param {Mixed} etc.
97      */
98     add : function(){
99         var a = arguments, l = a.length;
100         for(var i = 0; i < l; i++){
101             this._add(a[i]);
102         }
103     },
104     // private..
105     _add : function(el) {
106         
107         if (el.xtype) {
108             el = Roo.factory(el, typeof(Roo.Toolbar[el.xtype]) == 'undefined' ? Roo.form : Roo.Toolbar);
109         }
110         
111         if (el.applyTo){ // some kind of form field
112             return this.addField(el);
113         } 
114         if (el.render){ // some kind of Toolbar.Item
115             return this.addItem(el);
116         }
117         if (typeof el == "string"){ // string
118             if(el == "separator" || el == "-"){
119                 return this.addSeparator();
120             }
121             if (el == " "){
122                 return this.addSpacer();
123             }
124             if(el == "->"){
125                 return this.addFill();
126             }
127             return this.addText(el);
128             
129         }
130         if(el.tagName){ // element
131             return this.addElement(el);
132         }
133         if(typeof el == "object"){ // must be button config?
134             return this.addButton(el);
135         }
136         // and now what?!?!
137         return false;
138         
139     },
140     
141     /**
142      * Add an Xtype element
143      * @param {Object} xtype Xtype Object
144      * @return {Object} created Object
145      */
146     addxtype : function(e){
147         return this.add(e);  
148     },
149     
150     /**
151      * Returns the Element for this toolbar.
152      * @return {Roo.Element}
153      */
154     getEl : function(){
155         return this.el;  
156     },
157     
158     /**
159      * Adds a separator
160      * @return {Roo.Toolbar.Item} The separator item
161      */
162     addSeparator : function(){
163         return this.addItem(new Roo.Toolbar.Separator());
164     },
165
166     /**
167      * Adds a spacer element
168      * @return {Roo.Toolbar.Spacer} The spacer item
169      */
170     addSpacer : function(){
171         return this.addItem(new Roo.Toolbar.Spacer());
172     },
173
174     /**
175      * Adds a fill element that forces subsequent additions to the right side of the toolbar
176      * @return {Roo.Toolbar.Fill} The fill item
177      */
178     addFill : function(){
179         return this.addItem(new Roo.Toolbar.Fill());
180     },
181
182     /**
183      * Adds any standard HTML element to the toolbar
184      * @param {String/HTMLElement/Element} el The element or id of the element to add
185      * @return {Roo.Toolbar.Item} The element's item
186      */
187     addElement : function(el){
188         return this.addItem(new Roo.Toolbar.Item(el));
189     },
190     /**
191      * Collection of items on the toolbar.. (only Toolbar Items, so use fields to retrieve fields)
192      * @type Roo.util.MixedCollection  
193      */
194     items : false,
195      
196     /**
197      * Adds any Toolbar.Item or subclass
198      * @param {Roo.Toolbar.Item} item
199      * @return {Roo.Toolbar.Item} The item
200      */
201     addItem : function(item){
202         var td = this.nextBlock();
203         item.render(td);
204         this.items.add(item);
205         return item;
206     },
207     
208     /**
209      * Adds a button (or buttons). See {@link Roo.Toolbar.Button} for more info on the config.
210      * @param {Object/Array} config A button config or array of configs
211      * @return {Roo.Toolbar.Button/Array}
212      */
213     addButton : function(config){
214         if(config instanceof Array){
215             var buttons = [];
216             for(var i = 0, len = config.length; i < len; i++) {
217                 buttons.push(this.addButton(config[i]));
218             }
219             return buttons;
220         }
221         var b = config;
222         if(!(config instanceof Roo.Toolbar.Button)){
223             b = config.split ?
224                 new Roo.Toolbar.SplitButton(config) :
225                 new Roo.Toolbar.Button(config);
226         }
227         var td = this.nextBlock();
228         b.render(td);
229         this.items.add(b);
230         return b;
231     },
232     
233     /**
234      * Adds text to the toolbar
235      * @param {String} text The text to add
236      * @return {Roo.Toolbar.Item} The element's item
237      */
238     addText : function(text){
239         return this.addItem(new Roo.Toolbar.TextItem(text));
240     },
241     
242     /**
243      * Inserts any {@link Roo.Toolbar.Item}/{@link Roo.Toolbar.Button} at the specified index.
244      * @param {Number} index The index where the item is to be inserted
245      * @param {Object/Roo.Toolbar.Item/Roo.Toolbar.Button (may be Array)} item The button, or button config object to be inserted.
246      * @return {Roo.Toolbar.Button/Item}
247      */
248     insertButton : function(index, item){
249         if(item instanceof Array){
250             var buttons = [];
251             for(var i = 0, len = item.length; i < len; i++) {
252                buttons.push(this.insertButton(index + i, item[i]));
253             }
254             return buttons;
255         }
256         if (!(item instanceof Roo.Toolbar.Button)){
257            item = new Roo.Toolbar.Button(item);
258         }
259         var td = document.createElement("td");
260         this.tr.insertBefore(td, this.tr.childNodes[index]);
261         item.render(td);
262         this.items.insert(index, item);
263         return item;
264     },
265     
266     /**
267      * Adds a new element to the toolbar from the passed {@link Roo.DomHelper} config.
268      * @param {Object} config
269      * @return {Roo.Toolbar.Item} The element's item
270      */
271     addDom : function(config, returnEl){
272         var td = this.nextBlock();
273         Roo.DomHelper.overwrite(td, config);
274         var ti = new Roo.Toolbar.Item(td.firstChild);
275         ti.render(td);
276         this.items.add(ti);
277         return ti;
278     },
279
280     /**
281      * Collection of fields on the toolbar.. usefull for quering (value is false if there are no fields)
282      * @type Roo.util.MixedCollection  
283      */
284     fields : false,
285     
286     /**
287      * Adds a dynamically rendered Roo.form field (TextField, ComboBox, etc).
288      * Note: the field should not have been rendered yet. For a field that has already been
289      * rendered, use {@link #addElement}.
290      * @param {Roo.form.Field} field
291      * @return {Roo.ToolbarItem}
292      */
293      
294       
295     addField : function(field) {
296         if (!this.fields) {
297             var autoId = 0;
298             this.fields = new Roo.util.MixedCollection(false, function(o){
299                 return o.id || ("item" + (++autoId));
300             });
301
302         }
303         
304         var td = this.nextBlock();
305         field.render(td);
306         var ti = new Roo.Toolbar.Item(td.firstChild);
307         ti.render(td);
308         this.items.add(ti);
309         this.fields.add(field);
310         return ti;
311     },
312     /**
313      * Hide the toolbar
314      * @method hide
315      */
316      
317       
318     hide : function()
319     {
320         this.el.child('div').setVisibilityMode(Roo.Element.DISPLAY);
321         this.el.child('div').hide();
322     },
323     /**
324      * Show the toolbar
325      * @method show
326      */
327     show : function()
328     {
329         this.el.child('div').show();
330     },
331       
332     // private
333     nextBlock : function(){
334         var td = document.createElement("td");
335         this.tr.appendChild(td);
336         return td;
337     },
338
339     // private
340     destroy : function(){
341         if(this.items){ // rendered?
342             Roo.destroy.apply(Roo, this.items.items);
343         }
344         if(this.fields){ // rendered?
345             Roo.destroy.apply(Roo, this.fields.items);
346         }
347         Roo.Element.uncache(this.el, this.tr);
348     }
349 };
350
351 /**
352  * @class Roo.Toolbar.Item
353  * The base class that other classes should extend in order to get some basic common toolbar item functionality.
354  * @constructor
355  * Creates a new Item
356  * @param {HTMLElement} el 
357  */
358 Roo.Toolbar.Item = function(el){
359     this.el = Roo.getDom(el);
360     this.id = Roo.id(this.el);
361     this.hidden = false;
362 };
363
364 Roo.Toolbar.Item.prototype = {
365     
366     /**
367      * Get this item's HTML Element
368      * @return {HTMLElement}
369      */
370     getEl : function(){
371        return this.el;  
372     },
373
374     // private
375     render : function(td){
376         this.td = td;
377         td.appendChild(this.el);
378     },
379     
380     /**
381      * Removes and destroys this item.
382      */
383     destroy : function(){
384         this.td.parentNode.removeChild(this.td);
385     },
386     
387     /**
388      * Shows this item.
389      */
390     show: function(){
391         this.hidden = false;
392         this.td.style.display = "";
393     },
394     
395     /**
396      * Hides this item.
397      */
398     hide: function(){
399         this.hidden = true;
400         this.td.style.display = "none";
401     },
402     
403     /**
404      * Convenience function for boolean show/hide.
405      * @param {Boolean} visible true to show/false to hide
406      */
407     setVisible: function(visible){
408         if(visible) {
409             this.show();
410         }else{
411             this.hide();
412         }
413     },
414     
415     /**
416      * Try to focus this item.
417      */
418     focus : function(){
419         Roo.fly(this.el).focus();
420     },
421     
422     /**
423      * Disables this item.
424      */
425     disable : function(){
426         Roo.fly(this.td).addClass("x-item-disabled");
427         this.disabled = true;
428         this.el.disabled = true;
429     },
430     
431     /**
432      * Enables this item.
433      */
434     enable : function(){
435         Roo.fly(this.td).removeClass("x-item-disabled");
436         this.disabled = false;
437         this.el.disabled = false;
438     }
439 };
440
441
442 /**
443  * @class Roo.Toolbar.Separator
444  * @extends Roo.Toolbar.Item
445  * A simple toolbar separator class
446  * @constructor
447  * Creates a new Separator
448  */
449 Roo.Toolbar.Separator = function(){
450     var s = document.createElement("span");
451     s.className = "ytb-sep";
452     Roo.Toolbar.Separator.superclass.constructor.call(this, s);
453 };
454 Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
455     enable:Roo.emptyFn,
456     disable:Roo.emptyFn,
457     focus:Roo.emptyFn
458 });
459
460 /**
461  * @class Roo.Toolbar.Spacer
462  * @extends Roo.Toolbar.Item
463  * A simple element that adds extra horizontal space to a toolbar.
464  * @constructor
465  * Creates a new Spacer
466  */
467 Roo.Toolbar.Spacer = function(){
468     var s = document.createElement("div");
469     s.className = "ytb-spacer";
470     Roo.Toolbar.Spacer.superclass.constructor.call(this, s);
471 };
472 Roo.extend(Roo.Toolbar.Spacer, Roo.Toolbar.Item, {
473     enable:Roo.emptyFn,
474     disable:Roo.emptyFn,
475     focus:Roo.emptyFn
476 });
477
478 /**
479  * @class Roo.Toolbar.Fill
480  * @extends Roo.Toolbar.Spacer
481  * A simple element that adds a greedy (100% width) horizontal space to a toolbar.
482  * @constructor
483  * Creates a new Spacer
484  */
485 Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
486     // private
487     render : function(td){
488         td.style.width = '100%';
489         Roo.Toolbar.Fill.superclass.render.call(this, td);
490     }
491 });
492
493 /**
494  * @class Roo.Toolbar.TextItem
495  * @extends Roo.Toolbar.Item
496  * A simple class that renders text directly into a toolbar.
497  * @constructor
498  * Creates a new TextItem
499  * @param {String} text
500  */
501 Roo.Toolbar.TextItem = function(text){
502     if (typeof(text) == 'object') {
503         text = text.text;
504     }
505     var s = document.createElement("span");
506     s.className = "ytb-text";
507     s.innerHTML = text;
508     Roo.Toolbar.TextItem.superclass.constructor.call(this, s);
509 };
510 Roo.extend(Roo.Toolbar.TextItem, Roo.Toolbar.Item, {
511     enable:Roo.emptyFn,
512     disable:Roo.emptyFn,
513     focus:Roo.emptyFn
514 });
515
516 /**
517  * @class Roo.Toolbar.Button
518  * @extends Roo.Button
519  * A button that renders into a toolbar.
520  * @constructor
521  * Creates a new Button
522  * @param {Object} config A standard {@link Roo.Button} config object
523  */
524 Roo.Toolbar.Button = function(config){
525     Roo.Toolbar.Button.superclass.constructor.call(this, null, config);
526 };
527 Roo.extend(Roo.Toolbar.Button, Roo.Button, {
528     render : function(td){
529         this.td = td;
530         Roo.Toolbar.Button.superclass.render.call(this, td);
531     },
532     
533     /**
534      * Removes and destroys this button
535      */
536     destroy : function(){
537         Roo.Toolbar.Button.superclass.destroy.call(this);
538         this.td.parentNode.removeChild(this.td);
539     },
540     
541     /**
542      * Shows this button
543      */
544     show: function(){
545         this.hidden = false;
546         this.td.style.display = "";
547     },
548     
549     /**
550      * Hides this button
551      */
552     hide: function(){
553         this.hidden = true;
554         this.td.style.display = "none";
555     },
556
557     /**
558      * Disables this item
559      */
560     disable : function(){
561         Roo.fly(this.td).addClass("x-item-disabled");
562         this.disabled = true;
563     },
564
565     /**
566      * Enables this item
567      */
568     enable : function(){
569         Roo.fly(this.td).removeClass("x-item-disabled");
570         this.disabled = false;
571     }
572 });
573 // backwards compat
574 Roo.ToolbarButton = Roo.Toolbar.Button;
575
576 /**
577  * @class Roo.Toolbar.SplitButton
578  * @extends Roo.SplitButton
579  * A menu button that renders into a toolbar.
580  * @constructor
581  * Creates a new SplitButton
582  * @param {Object} config A standard {@link Roo.SplitButton} config object
583  */
584 Roo.Toolbar.SplitButton = function(config){
585     Roo.Toolbar.SplitButton.superclass.constructor.call(this, null, config);
586 };
587 Roo.extend(Roo.Toolbar.SplitButton, Roo.SplitButton, {
588     render : function(td){
589         this.td = td;
590         Roo.Toolbar.SplitButton.superclass.render.call(this, td);
591     },
592     
593     /**
594      * Removes and destroys this button
595      */
596     destroy : function(){
597         Roo.Toolbar.SplitButton.superclass.destroy.call(this);
598         this.td.parentNode.removeChild(this.td);
599     },
600     
601     /**
602      * Shows this button
603      */
604     show: function(){
605         this.hidden = false;
606         this.td.style.display = "";
607     },
608     
609     /**
610      * Hides this button
611      */
612     hide: function(){
613         this.hidden = true;
614         this.td.style.display = "none";
615     }
616 });
617
618 // backwards compat
619 Roo.Toolbar.MenuButton = Roo.Toolbar.SplitButton;