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