remove debugging code
[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     var cfg = {};
360     if (typeof (el.xtype) != 'undefined') {
361         cfg = el;
362         el = cfg.el;
363     }
364     
365     this.el = Roo.getDom(el);
366     this.id = Roo.id(this.el);
367     this.hidden = false;
368     
369     this.addEvents({
370          /**
371              * @event render
372              * Fires when the button is rendered
373              * @param {Button} this
374              */
375         'render': true
376     });
377     Roo.Toolbar.Item.superclass.constructor.call(this,cfg);
378 };
379 Roo.extend(Roo.Toolbar.Item, Roo.util.Observable, {
380 //Roo.Toolbar.Item.prototype = {
381     
382     /**
383      * Get this item's HTML Element
384      * @return {HTMLElement}
385      */
386     getEl : function(){
387        return this.el;  
388     },
389
390     // private
391     render : function(td){
392         
393          this.td = td;
394         td.appendChild(this.el);
395         
396         this.fireEvent('render', this);
397     },
398     
399     /**
400      * Removes and destroys this item.
401      */
402     destroy : function(){
403         this.td.parentNode.removeChild(this.td);
404     },
405     
406     /**
407      * Shows this item.
408      */
409     show: function(){
410         this.hidden = false;
411         this.td.style.display = "";
412     },
413     
414     /**
415      * Hides this item.
416      */
417     hide: function(){
418         this.hidden = true;
419         this.td.style.display = "none";
420     },
421     
422     /**
423      * Convenience function for boolean show/hide.
424      * @param {Boolean} visible true to show/false to hide
425      */
426     setVisible: function(visible){
427         if(visible) {
428             this.show();
429         }else{
430             this.hide();
431         }
432     },
433     
434     /**
435      * Try to focus this item.
436      */
437     focus : function(){
438         Roo.fly(this.el).focus();
439     },
440     
441     /**
442      * Disables this item.
443      */
444     disable : function(){
445         Roo.fly(this.td).addClass("x-item-disabled");
446         this.disabled = true;
447         this.el.disabled = true;
448     },
449     
450     /**
451      * Enables this item.
452      */
453     enable : function(){
454         Roo.fly(this.td).removeClass("x-item-disabled");
455         this.disabled = false;
456         this.el.disabled = false;
457     }
458 });
459
460
461 /**
462  * @class Roo.Toolbar.Separator
463  * @extends Roo.Toolbar.Item
464  * A simple toolbar separator class
465  * @constructor
466  * Creates a new Separator
467  */
468 Roo.Toolbar.Separator = function(cfg){
469     
470     var s = document.createElement("span");
471     s.className = "ytb-sep";
472     if (cfg) {
473         cfg.el = s;
474     }
475     
476     Roo.Toolbar.Separator.superclass.constructor.call(this, cfg || s);
477 };
478 Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
479     enable:Roo.emptyFn,
480     disable:Roo.emptyFn,
481     focus:Roo.emptyFn
482 });
483
484 /**
485  * @class Roo.Toolbar.Spacer
486  * @extends Roo.Toolbar.Item
487  * A simple element that adds extra horizontal space to a toolbar.
488  * @constructor
489  * Creates a new Spacer
490  */
491 Roo.Toolbar.Spacer = function(cfg){
492     var s = document.createElement("div");
493     s.className = "ytb-spacer";
494     if (cfg) {
495         cfg.el = s;
496     }
497     Roo.Toolbar.Spacer.superclass.constructor.call(this, cfg || s);
498 };
499 Roo.extend(Roo.Toolbar.Spacer, Roo.Toolbar.Item, {
500     enable:Roo.emptyFn,
501     disable:Roo.emptyFn,
502     focus:Roo.emptyFn
503 });
504
505 /**
506  * @class Roo.Toolbar.Fill
507  * @extends Roo.Toolbar.Spacer
508  * A simple element that adds a greedy (100% width) horizontal space to a toolbar.
509  * @constructor
510  * Creates a new Spacer
511  */
512 Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
513     // private
514     render : function(td){
515         td.style.width = '100%';
516         Roo.Toolbar.Fill.superclass.render.call(this, td);
517     }
518 });
519
520 /**
521  * @class Roo.Toolbar.TextItem
522  * @extends Roo.Toolbar.Item
523  * A simple class that renders text directly into a toolbar.
524  * @constructor
525  * Creates a new TextItem
526  * @param {String} text
527  */
528 Roo.Toolbar.TextItem = function(cfg){
529     var  text = cfg || "";
530     if (typeof(cfg) == 'object') {
531         text = cfg.text || "";
532     }  else {
533         cfg = null;
534     }
535     var s = document.createElement("span");
536     s.className = "ytb-text";
537     s.innerHTML = text;
538     if (cfg) {
539         cfg.el  = s;
540     }
541     
542     Roo.Toolbar.TextItem.superclass.constructor.call(this, cfg ||  s);
543 };
544 Roo.extend(Roo.Toolbar.TextItem, Roo.Toolbar.Item, {
545     
546      
547     enable:Roo.emptyFn,
548     disable:Roo.emptyFn,
549     focus:Roo.emptyFn
550 });
551
552 /**
553  * @class Roo.Toolbar.Button
554  * @extends Roo.Button
555  * A button that renders into a toolbar.
556  * @constructor
557  * Creates a new Button
558  * @param {Object} config A standard {@link Roo.Button} config object
559  */
560 Roo.Toolbar.Button = function(config){
561     Roo.Toolbar.Button.superclass.constructor.call(this, null, config);
562 };
563 Roo.extend(Roo.Toolbar.Button, Roo.Button, {
564     render : function(td){
565         this.td = td;
566         Roo.Toolbar.Button.superclass.render.call(this, td);
567     },
568     
569     /**
570      * Removes and destroys this button
571      */
572     destroy : function(){
573         Roo.Toolbar.Button.superclass.destroy.call(this);
574         this.td.parentNode.removeChild(this.td);
575     },
576     
577     /**
578      * Shows this button
579      */
580     show: function(){
581         this.hidden = false;
582         this.td.style.display = "";
583     },
584     
585     /**
586      * Hides this button
587      */
588     hide: function(){
589         this.hidden = true;
590         this.td.style.display = "none";
591     },
592
593     /**
594      * Disables this item
595      */
596     disable : function(){
597         Roo.fly(this.td).addClass("x-item-disabled");
598         this.disabled = true;
599     },
600
601     /**
602      * Enables this item
603      */
604     enable : function(){
605         Roo.fly(this.td).removeClass("x-item-disabled");
606         this.disabled = false;
607     }
608 });
609 // backwards compat
610 Roo.ToolbarButton = Roo.Toolbar.Button;
611
612 /**
613  * @class Roo.Toolbar.SplitButton
614  * @extends Roo.SplitButton
615  * A menu button that renders into a toolbar.
616  * @constructor
617  * Creates a new SplitButton
618  * @param {Object} config A standard {@link Roo.SplitButton} config object
619  */
620 Roo.Toolbar.SplitButton = function(config){
621     Roo.Toolbar.SplitButton.superclass.constructor.call(this, null, config);
622 };
623 Roo.extend(Roo.Toolbar.SplitButton, Roo.SplitButton, {
624     render : function(td){
625         this.td = td;
626         Roo.Toolbar.SplitButton.superclass.render.call(this, td);
627     },
628     
629     /**
630      * Removes and destroys this button
631      */
632     destroy : function(){
633         Roo.Toolbar.SplitButton.superclass.destroy.call(this);
634         this.td.parentNode.removeChild(this.td);
635     },
636     
637     /**
638      * Shows this button
639      */
640     show: function(){
641         this.hidden = false;
642         this.td.style.display = "";
643     },
644     
645     /**
646      * Hides this button
647      */
648     hide: function(){
649         this.hidden = true;
650         this.td.style.display = "none";
651     }
652 });
653
654 // backwards compat
655 Roo.Toolbar.MenuButton = Roo.Toolbar.SplitButton;