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         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). Note: the field should not have
288      * been rendered yet. For a field that has already been rendered, use {@link #addElement}.
289      * @param {Roo.form.Field} field
290      * @return {Roo.ToolbarItem}
291      */
292      
293       
294     addField : function(field) {
295         if (!this.fields) {
296             var autoId = 0;
297             this.fields = new Roo.util.MixedCollection(false, function(o){
298                 return o.id || ("item" + (++autoId));
299             });
300
301         }
302         
303         var td = this.nextBlock();
304         field.render(td);
305         var ti = new Roo.Toolbar.Item(td.firstChild);
306         ti.render(td);
307         this.items.add(ti);
308         this.fields.add(field);
309         return ti;
310     },
311     /**
312      * Hide the toolbar
313      * @method hide
314      */
315      
316       
317     hide : function()
318     {
319         this.el.child('div').setVisibilityMode(Roo.Element.DISPLAY);
320         this.el.child('div').hide();
321     },
322     /**
323      * Show the toolbar
324      * @method show
325      */
326     show : function()
327     {
328         this.el.child('div').show();
329     },
330       
331     // private
332     nextBlock : function(){
333         var td = document.createElement("td");
334         this.tr.appendChild(td);
335         return td;
336     },
337
338     // private
339     destroy : function(){
340         if(this.items){ // rendered?
341             Roo.destroy.apply(Roo, this.items.items);
342         }
343         if(this.fields){ // rendered?
344             Roo.destroy.apply(Roo, this.fields.items);
345         }
346         Roo.Element.uncache(this.el, this.tr);
347     }
348 };
349
350 /**
351  * @class Roo.Toolbar.Item
352  * The base class that other classes should extend in order to get some basic common toolbar item functionality.
353  * @constructor
354  * Creates a new Item
355  * @param {HTMLElement} el 
356  */
357 Roo.Toolbar.Item = function(el){
358     this.el = Roo.getDom(el);
359     this.id = Roo.id(this.el);
360     this.hidden = false;
361 };
362
363 Roo.Toolbar.Item.prototype = {
364     
365     /**
366      * Get this item's HTML Element
367      * @return {HTMLElement}
368      */
369     getEl : function(){
370        return this.el;  
371     },
372
373     // private
374     render : function(td){
375         this.td = td;
376         td.appendChild(this.el);
377     },
378     
379     /**
380      * Removes and destroys this item.
381      */
382     destroy : function(){
383         this.td.parentNode.removeChild(this.td);
384     },
385     
386     /**
387      * Shows this item.
388      */
389     show: function(){
390         this.hidden = false;
391         this.td.style.display = "";
392     },
393     
394     /**
395      * Hides this item.
396      */
397     hide: function(){
398         this.hidden = true;
399         this.td.style.display = "none";
400     },
401     
402     /**
403      * Convenience function for boolean show/hide.
404      * @param {Boolean} visible true to show/false to hide
405      */
406     setVisible: function(visible){
407         if(visible) {
408             this.show();
409         }else{
410             this.hide();
411         }
412     },
413     
414     /**
415      * Try to focus this item.
416      */
417     focus : function(){
418         Roo.fly(this.el).focus();
419     },
420     
421     /**
422      * Disables this item.
423      */
424     disable : function(){
425         Roo.fly(this.td).addClass("x-item-disabled");
426         this.disabled = true;
427         this.el.disabled = true;
428     },
429     
430     /**
431      * Enables this item.
432      */
433     enable : function(){
434         Roo.fly(this.td).removeClass("x-item-disabled");
435         this.disabled = false;
436         this.el.disabled = false;
437     }
438 };
439
440
441 /**
442  * @class Roo.Toolbar.Separator
443  * @extends Roo.Toolbar.Item
444  * A simple toolbar separator class
445  * @constructor
446  * Creates a new Separator
447  */
448 Roo.Toolbar.Separator = function(){
449     var s = document.createElement("span");
450     s.className = "ytb-sep";
451     Roo.Toolbar.Separator.superclass.constructor.call(this, s);
452 };
453 Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
454     enable:Roo.emptyFn,
455     disable:Roo.emptyFn,
456     focus:Roo.emptyFn
457 });
458
459 /**
460  * @class Roo.Toolbar.Spacer
461  * @extends Roo.Toolbar.Item
462  * A simple element that adds extra horizontal space to a toolbar.
463  * @constructor
464  * Creates a new Spacer
465  */
466 Roo.Toolbar.Spacer = function(){
467     var s = document.createElement("div");
468     s.className = "ytb-spacer";
469     Roo.Toolbar.Spacer.superclass.constructor.call(this, s);
470 };
471 Roo.extend(Roo.Toolbar.Spacer, Roo.Toolbar.Item, {
472     enable:Roo.emptyFn,
473     disable:Roo.emptyFn,
474     focus:Roo.emptyFn
475 });
476
477 /**
478  * @class Roo.Toolbar.Fill
479  * @extends Roo.Toolbar.Spacer
480  * A simple element that adds a greedy (100% width) horizontal space to a toolbar.
481  * @constructor
482  * Creates a new Spacer
483  */
484 Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
485     // private
486     render : function(td){
487         td.style.width = '100%';
488         Roo.Toolbar.Fill.superclass.render.call(this, td);
489     }
490 });
491
492 /**
493  * @class Roo.Toolbar.TextItem
494  * @extends Roo.Toolbar.Item
495  * A simple class that renders text directly into a toolbar.
496  * @constructor
497  * Creates a new TextItem
498  * @param {String} text
499  */
500 Roo.Toolbar.TextItem = function(text){
501     if (typeof(text) == 'object') {
502         text = text.text;
503     }
504     var s = document.createElement("span");
505     s.className = "ytb-text";
506     s.innerHTML = text;
507     Roo.Toolbar.TextItem.superclass.constructor.call(this, s);
508 };
509 Roo.extend(Roo.Toolbar.TextItem, Roo.Toolbar.Item, {
510     enable:Roo.emptyFn,
511     disable:Roo.emptyFn,
512     focus:Roo.emptyFn
513 });
514
515 /**
516  * @class Roo.Toolbar.Button
517  * @extends Roo.Button
518  * A button that renders into a toolbar.
519  * @constructor
520  * Creates a new Button
521  * @param {Object} config A standard {@link Roo.Button} config object
522  */
523 Roo.Toolbar.Button = function(config){
524     Roo.Toolbar.Button.superclass.constructor.call(this, null, config);
525 };
526 Roo.extend(Roo.Toolbar.Button, Roo.Button, {
527     render : function(td){
528         this.td = td;
529         Roo.Toolbar.Button.superclass.render.call(this, td);
530     },
531     
532     /**
533      * Removes and destroys this button
534      */
535     destroy : function(){
536         Roo.Toolbar.Button.superclass.destroy.call(this);
537         this.td.parentNode.removeChild(this.td);
538     },
539     
540     /**
541      * Shows this button
542      */
543     show: function(){
544         this.hidden = false;
545         this.td.style.display = "";
546     },
547     
548     /**
549      * Hides this button
550      */
551     hide: function(){
552         this.hidden = true;
553         this.td.style.display = "none";
554     },
555
556     /**
557      * Disables this item
558      */
559     disable : function(){
560         Roo.fly(this.td).addClass("x-item-disabled");
561         this.disabled = true;
562     },
563
564     /**
565      * Enables this item
566      */
567     enable : function(){
568         Roo.fly(this.td).removeClass("x-item-disabled");
569         this.disabled = false;
570     }
571 });
572 // backwards compat
573 Roo.ToolbarButton = Roo.Toolbar.Button;
574
575 /**
576  * @class Roo.Toolbar.SplitButton
577  * @extends Roo.SplitButton
578  * A menu button that renders into a toolbar.
579  * @constructor
580  * Creates a new SplitButton
581  * @param {Object} config A standard {@link Roo.SplitButton} config object
582  */
583 Roo.Toolbar.SplitButton = function(config){
584     Roo.Toolbar.SplitButton.superclass.constructor.call(this, null, config);
585 };
586 Roo.extend(Roo.Toolbar.SplitButton, Roo.SplitButton, {
587     render : function(td){
588         this.td = td;
589         Roo.Toolbar.SplitButton.superclass.render.call(this, td);
590     },
591     
592     /**
593      * Removes and destroys this button
594      */
595     destroy : function(){
596         Roo.Toolbar.SplitButton.superclass.destroy.call(this);
597         this.td.parentNode.removeChild(this.td);
598     },
599     
600     /**
601      * Shows this button
602      */
603     show: function(){
604         this.hidden = false;
605         this.td.style.display = "";
606     },
607     
608     /**
609      * Hides this button
610      */
611     hide: function(){
612         this.hidden = true;
613         this.td.style.display = "none";
614     }
615 });
616
617 // backwards compat
618 Roo.Toolbar.MenuButton = Roo.Toolbar.SplitButton;