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