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