Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / pkgs / pkg-toolbars-debug.js
1 /*!
2  * Ext JS Library 3.1.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.layout.ToolbarLayout
9  * @extends Ext.layout.ContainerLayout
10  * Layout manager implicitly used by Ext.Toolbar.
11  */
12 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
13     monitorResize : true,
14     triggerWidth : 18,
15     lastOverflow : false,
16     forceLayout: true,
17
18     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
19     // private
20     onLayout : function(ct, target){
21         if(!this.leftTr){
22             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
23             target.addClass('x-toolbar-layout-ct');
24             target.insertHtml('beforeEnd',
25                  '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="' + align + '"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');
26             this.leftTr = target.child('tr.x-toolbar-left-row', true);
27             this.rightTr = target.child('tr.x-toolbar-right-row', true);
28             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
29         }
30         var side = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
31             pos = 0,
32             items = ct.items.items;
33
34         for(var i = 0, len = items.length, c; i < len; i++, pos++) {
35             c = items[i];
36             if(c.isFill){
37                 side = this.rightTr;
38                 pos = -1;
39             }else if(!c.rendered){
40                 c.render(this.insertCell(c, side, pos));
41             }else{
42                 if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){
43                     var td = this.insertCell(c, side, pos);
44                     td.appendChild(c.getPositionEl().dom);
45                     c.container = Ext.get(td);
46                 }
47             }
48         }
49         //strip extra empty cells
50         this.cleanup(this.leftTr);
51         this.cleanup(this.rightTr);
52         this.cleanup(this.extrasTr);
53         this.fitToSize(target);
54     },
55
56     cleanup : function(row){
57         var cn = row.childNodes;
58         for(var i = cn.length-1, c; i >= 0 && (c = cn[i]); i--){
59             if(!c.firstChild){
60                 row.removeChild(c);
61             }
62         }
63     },
64
65     insertCell : function(c, side, pos){
66         var td = document.createElement('td');
67         td.className='x-toolbar-cell';
68         side.insertBefore(td, side.childNodes[pos]||null);
69         return td;
70     },
71
72     hideItem : function(item){
73         var h = (this.hiddens = this.hiddens || []);
74         h.push(item);
75         item.xtbHidden = true;
76         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
77         item.hide();
78     },
79
80     unhideItem : function(item){
81         item.show();
82         item.xtbHidden = false;
83         this.hiddens.remove(item);
84         if(this.hiddens.length < 1){
85             delete this.hiddens;
86         }
87     },
88
89     getItemWidth : function(c){
90         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
91     },
92
93     fitToSize : function(t){
94         if(this.container.enableOverflow === false){
95             return;
96         }
97         var w = t.dom.clientWidth,
98             lw = this.lastWidth || 0,
99             iw = t.dom.firstChild.offsetWidth,
100             clipWidth = w - this.triggerWidth,
101             hideIndex = -1;
102
103         this.lastWidth = w;
104
105         if(iw > w || (this.hiddens && w >= lw)){
106             var i, items = this.container.items.items,
107                 len = items.length, c,
108                 loopWidth = 0;
109
110             for(i = 0; i < len; i++) {
111                 c = items[i];
112                 if(!c.isFill){
113                     loopWidth += this.getItemWidth(c);
114                     if(loopWidth > clipWidth){
115                         if(!(c.hidden || c.xtbHidden)){
116                             this.hideItem(c);
117                         }
118                     }else if(c.xtbHidden){
119                         this.unhideItem(c);
120                     }
121                 }
122             }
123         }
124         if(this.hiddens){
125             this.initMore();
126             if(!this.lastOverflow){
127                 this.container.fireEvent('overflowchange', this.container, true);
128                 this.lastOverflow = true;
129             }
130         }else if(this.more){
131             this.clearMenu();
132             this.more.destroy();
133             delete this.more;
134             if(this.lastOverflow){
135                 this.container.fireEvent('overflowchange', this.container, false);
136                 this.lastOverflow = false;
137             }
138         }
139     },
140
141     createMenuConfig : function(c, hideOnClick){
142         var cfg = Ext.apply({}, c.initialConfig),
143             group = c.toggleGroup;
144
145         Ext.apply(cfg, {
146             text: c.overflowText || c.text,
147             iconCls: c.iconCls,
148             icon: c.icon,
149             itemId: c.itemId,
150             disabled: c.disabled,
151             handler: c.handler,
152             scope: c.scope,
153             menu: c.menu,
154             hideOnClick: hideOnClick
155         });
156         if(group || c.enableToggle){
157             Ext.apply(cfg, {
158                 group: group,
159                 checked: c.pressed,
160                 listeners: {
161                     checkchange: function(item, checked){
162                         c.toggle(checked);
163                     }
164                 }
165             });
166         }
167         delete cfg.ownerCt;
168         delete cfg.xtype;
169         delete cfg.id;
170         return cfg;
171     },
172
173     // private
174     addComponentToMenu : function(m, c){
175         if(c instanceof Ext.Toolbar.Separator){
176             m.add('-');
177         }else if(Ext.isFunction(c.isXType)){
178             if(c.isXType('splitbutton')){
179                 m.add(this.createMenuConfig(c, true));
180             }else if(c.isXType('button')){
181                 m.add(this.createMenuConfig(c, !c.menu));
182             }else if(c.isXType('buttongroup')){
183                 c.items.each(function(item){
184                      this.addComponentToMenu(m, item);
185                 }, this);
186             }
187         }
188     },
189
190     clearMenu : function(){
191         var m = this.moreMenu;
192         if(m && m.items){
193             m.items.each(function(item){
194                 delete item.menu;
195             });
196         }
197     },
198
199     // private
200     beforeMoreShow : function(m){
201         var h = this.container.items.items,
202             len = h.length,
203             c,
204             prev,
205             needsSep = function(group, item){
206                 return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
207             };
208
209         this.clearMenu();
210         m.removeAll();
211         for(var i = 0; i < len; i++){
212             c = h[i];
213             if(c.xtbHidden){
214                 if(prev && (needsSep(c, prev) || needsSep(prev, c))){
215                     m.add('-');
216                 }
217                 this.addComponentToMenu(m, c);
218                 prev = c;
219             }
220         }
221         // put something so the menu isn't empty
222         // if no compatible items found
223         if(m.items.length < 1){
224             m.add(this.noItemsMenuText);
225         }
226     },
227
228     initMore : function(){
229         if(!this.more){
230             this.moreMenu = new Ext.menu.Menu({
231                 listeners: {
232                     beforeshow: this.beforeMoreShow,
233                     scope: this
234                 }
235             });
236             this.moreMenu.ownerCt = this.container;
237             this.more = new Ext.Button({
238                 iconCls: 'x-toolbar-more-icon',
239                 cls: 'x-toolbar-more',
240                 menu: this.moreMenu
241             });
242             var td = this.insertCell(this.more, this.extrasTr, 100);
243             this.more.render(td);
244         }
245     },
246
247     onRemove : function(c){
248         delete this.leftTr;
249         delete this.rightTr;
250         delete this.extrasTr;
251         Ext.layout.ToolbarLayout.superclass.onRemove.call(this, c);
252     },
253
254     destroy : function(){
255         Ext.destroy(this.more, this.moreMenu);
256         delete this.leftTr;
257         delete this.rightTr;
258         delete this.extrasTr;
259         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
260     }
261     /**
262      * @property activeItem
263      * @hide
264      */
265 });
266
267 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
268
269 /**
270  * @class Ext.Toolbar
271  * @extends Ext.Container
272  * <p>Basic Toolbar class. Although the <tt>{@link Ext.Container#defaultType defaultType}</tt> for Toolbar
273  * is <tt>{@link Ext.Button button}</tt>, Toolbar elements (child items for the Toolbar container) may
274  * be virtually any type of Component. Toolbar elements can be created explicitly via their constructors,
275  * or implicitly via their xtypes, and can be <tt>{@link #add}</tt>ed dynamically.</p>
276  * <p>Some items have shortcut strings for creation:</p>
277  * <pre>
278 <u>Shortcut</u>  <u>xtype</u>          <u>Class</u>                  <u>Description</u>
279 '->'      'tbfill'       {@link Ext.Toolbar.Fill}       begin using the right-justified button container
280 '-'       'tbseparator'  {@link Ext.Toolbar.Separator}  add a vertical separator bar between toolbar items
281 ' '       'tbspacer'     {@link Ext.Toolbar.Spacer}     add horiztonal space between elements
282  * </pre>
283  *
284  * Example usage of various elements:
285  * <pre><code>
286 var tb = new Ext.Toolbar({
287     renderTo: document.body,
288     width: 600,
289     height: 100,
290     items: [
291         {
292             // xtype: 'button', // default for Toolbars, same as 'tbbutton'
293             text: 'Button'
294         },
295         {
296             xtype: 'splitbutton', // same as 'tbsplitbutton'
297             text: 'Split Button'
298         },
299         // begin using the right-justified button container
300         '->', // same as {xtype: 'tbfill'}, // Ext.Toolbar.Fill
301         {
302             xtype: 'textfield',
303             name: 'field1',
304             emptyText: 'enter search term'
305         },
306         // add a vertical separator bar between toolbar items
307         '-', // same as {xtype: 'tbseparator'} to create Ext.Toolbar.Separator
308         'text 1', // same as {xtype: 'tbtext', text: 'text1'} to create Ext.Toolbar.TextItem
309         {xtype: 'tbspacer'},// same as ' ' to create Ext.Toolbar.Spacer
310         'text 2',
311         {xtype: 'tbspacer', width: 50}, // add a 50px space
312         'text 3'
313     ]
314 });
315  * </code></pre>
316  * Example adding a ComboBox within a menu of a button:
317  * <pre><code>
318 // ComboBox creation
319 var combo = new Ext.form.ComboBox({
320     store: new Ext.data.ArrayStore({
321         autoDestroy: true,
322         fields: ['initials', 'fullname'],
323         data : [
324             ['FF', 'Fred Flintstone'],
325             ['BR', 'Barney Rubble']
326         ]
327     }),
328     displayField: 'fullname',
329     typeAhead: true,
330     mode: 'local',
331     forceSelection: true,
332     triggerAction: 'all',
333     emptyText: 'Select a name...',
334     selectOnFocus: true,
335     width: 135,
336     getListParent: function() {
337         return this.el.up('.x-menu');
338     },
339     iconCls: 'no-icon' //use iconCls if placing within menu to shift to right side of menu
340 });
341
342 // put ComboBox in a Menu
343 var menu = new Ext.menu.Menu({
344     id: 'mainMenu',
345     items: [
346         combo // A Field in a Menu
347     ]
348 });
349
350 // add a Button with the menu
351 tb.add({
352         text:'Button w/ Menu',
353         menu: menu  // assign menu by instance
354     });
355 tb.doLayout();
356  * </code></pre>
357  * @constructor
358  * Creates a new Toolbar
359  * @param {Object/Array} config A config object or an array of buttons to <tt>{@link #add}</tt>
360  * @xtype toolbar
361  */
362 Ext.Toolbar = function(config){
363     if(Ext.isArray(config)){
364         config = {items: config, layout: 'toolbar'};
365     } else {
366         config = Ext.apply({
367             layout: 'toolbar'
368         }, config);
369         if(config.buttons) {
370             config.items = config.buttons;
371         }
372     }
373     Ext.Toolbar.superclass.constructor.call(this, config);
374 };
375
376 (function(){
377
378 var T = Ext.Toolbar;
379
380 Ext.extend(T, Ext.Container, {
381
382     defaultType: 'button',
383
384     /**
385      * @cfg {String/Object} layout
386      * This class assigns a default layout (<code>layout:'<b>toolbar</b>'</code>).
387      * Developers <i>may</i> override this configuration option if another layout
388      * is required (the constructor must be passed a configuration object in this
389      * case instead of an array).
390      * See {@link Ext.Container#layout} for additional information.
391      */
392     /**
393      * @cfg {Boolean} enableOverflow
394      * Defaults to false. Configure <code>true<code> to make the toolbar provide a button
395      * which activates a dropdown Menu to show items which overflow the Toolbar's width.
396      */
397
398     trackMenus : true,
399     internalDefaults: {removeMode: 'container', hideParent: true},
400     toolbarCls: 'x-toolbar',
401
402     initComponent : function(){
403         T.superclass.initComponent.call(this);
404
405         /**
406          * @event overflowchange
407          * Fires after the overflow state has changed.
408          * @param {Object} c The Container
409          * @param {Boolean} lastOverflow overflow state
410          */
411         this.addEvents('overflowchange');
412     },
413
414     // private
415     onRender : function(ct, position){
416         if(!this.el){
417             if(!this.autoCreate){
418                 this.autoCreate = {
419                     cls: this.toolbarCls + ' x-small-editor'
420                 };
421             }
422             this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
423             Ext.Toolbar.superclass.onRender.apply(this, arguments);
424         }
425     },
426
427     /**
428      * <p>Adds element(s) to the toolbar -- this function takes a variable number of
429      * arguments of mixed type and adds them to the toolbar.</p>
430      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
431      * @param {Mixed} arg1 The following types of arguments are all valid:<br />
432      * <ul>
433      * <li>{@link Ext.Button} config: A valid button config object (equivalent to {@link #addButton})</li>
434      * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>
435      * <li>Field: Any form field (equivalent to {@link #addField})</li>
436      * <li>Item: Any subclass of {@link Ext.Toolbar.Item} (equivalent to {@link #addItem})</li>
437      * <li>String: Any generic string (gets wrapped in a {@link Ext.Toolbar.TextItem}, equivalent to {@link #addText}).
438      * Note that there are a few special strings that are treated differently as explained next.</li>
439      * <li>'-': Creates a separator element (equivalent to {@link #addSeparator})</li>
440      * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>
441      * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>
442      * </ul>
443      * @param {Mixed} arg2
444      * @param {Mixed} etc.
445      * @method add
446      */
447
448     // private
449     lookupComponent : function(c){
450         if(Ext.isString(c)){
451             if(c == '-'){
452                 c = new T.Separator();
453             }else if(c == ' '){
454                 c = new T.Spacer();
455             }else if(c == '->'){
456                 c = new T.Fill();
457             }else{
458                 c = new T.TextItem(c);
459             }
460             this.applyDefaults(c);
461         }else{
462             if(c.isFormField || c.render){ // some kind of form field, some kind of Toolbar.Item
463                 c = this.createComponent(c);
464             }else if(c.tag){ // DomHelper spec
465                 c = new T.Item({autoEl: c});
466             }else if(c.tagName){ // element
467                 c = new T.Item({el:c});
468             }else if(Ext.isObject(c)){ // must be button config?
469                 c = c.xtype ? this.createComponent(c) : this.constructButton(c);
470             }
471         }
472         return c;
473     },
474
475     // private
476     applyDefaults : function(c){
477         if(!Ext.isString(c)){
478             c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
479             var d = this.internalDefaults;
480             if(c.events){
481                 Ext.applyIf(c.initialConfig, d);
482                 Ext.apply(c, d);
483             }else{
484                 Ext.applyIf(c, d);
485             }
486         }
487         return c;
488     },
489
490     /**
491      * Adds a separator
492      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
493      * @return {Ext.Toolbar.Item} The separator {@link Ext.Toolbar.Item item}
494      */
495     addSeparator : function(){
496         return this.add(new T.Separator());
497     },
498
499     /**
500      * Adds a spacer element
501      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
502      * @return {Ext.Toolbar.Spacer} The spacer item
503      */
504     addSpacer : function(){
505         return this.add(new T.Spacer());
506     },
507
508     /**
509      * Forces subsequent additions into the float:right toolbar
510      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
511      */
512     addFill : function(){
513         this.add(new T.Fill());
514     },
515
516     /**
517      * Adds any standard HTML element to the toolbar
518      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
519      * @param {Mixed} el The element or id of the element to add
520      * @return {Ext.Toolbar.Item} The element's item
521      */
522     addElement : function(el){
523         return this.addItem(new T.Item({el:el}));
524     },
525
526     /**
527      * Adds any Toolbar.Item or subclass
528      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
529      * @param {Ext.Toolbar.Item} item
530      * @return {Ext.Toolbar.Item} The item
531      */
532     addItem : function(item){
533         return this.add.apply(this, arguments);
534     },
535
536     /**
537      * Adds a button (or buttons). See {@link Ext.Button} for more info on the config.
538      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
539      * @param {Object/Array} config A button config or array of configs
540      * @return {Ext.Button/Array}
541      */
542     addButton : function(config){
543         if(Ext.isArray(config)){
544             var buttons = [];
545             for(var i = 0, len = config.length; i < len; i++) {
546                 buttons.push(this.addButton(config[i]));
547             }
548             return buttons;
549         }
550         return this.add(this.constructButton(config));
551     },
552
553     /**
554      * Adds text to the toolbar
555      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
556      * @param {String} text The text to add
557      * @return {Ext.Toolbar.Item} The element's item
558      */
559     addText : function(text){
560         return this.addItem(new T.TextItem(text));
561     },
562
563     /**
564      * Adds a new element to the toolbar from the passed {@link Ext.DomHelper} config
565      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
566      * @param {Object} config
567      * @return {Ext.Toolbar.Item} The element's item
568      */
569     addDom : function(config){
570         return this.add(new T.Item({autoEl: config}));
571     },
572
573     /**
574      * Adds a dynamically rendered Ext.form field (TextField, ComboBox, etc). Note: the field should not have
575      * been rendered yet. For a field that has already been rendered, use {@link #addElement}.
576      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
577      * @param {Ext.form.Field} field
578      * @return {Ext.Toolbar.Item}
579      */
580     addField : function(field){
581         return this.add(field);
582     },
583
584     /**
585      * Inserts any {@link Ext.Toolbar.Item}/{@link Ext.Button} at the specified index.
586      * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
587      * @param {Number} index The index where the item is to be inserted
588      * @param {Object/Ext.Toolbar.Item/Ext.Button/Array} item The button, or button config object to be
589      * inserted, or an array of buttons/configs.
590      * @return {Ext.Button/Item}
591      */
592     insertButton : function(index, item){
593         if(Ext.isArray(item)){
594             var buttons = [];
595             for(var i = 0, len = item.length; i < len; i++) {
596                buttons.push(this.insertButton(index + i, item[i]));
597             }
598             return buttons;
599         }
600         return Ext.Toolbar.superclass.insert.call(this, index, item);
601     },
602
603     // private
604     trackMenu : function(item, remove){
605         if(this.trackMenus && item.menu){
606             var method = remove ? 'mun' : 'mon';
607             this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
608             this[method](item, 'menushow', this.onButtonMenuShow, this);
609             this[method](item, 'menuhide', this.onButtonMenuHide, this);
610         }
611     },
612
613     // private
614     constructButton : function(item){
615         var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
616         return b;
617     },
618
619     // private
620     onAdd : function(c){
621         Ext.Toolbar.superclass.onAdd.call(this);
622         this.trackMenu(c);
623     },
624
625     // private
626     onRemove : function(c){
627         Ext.Toolbar.superclass.onRemove.call(this);
628         this.trackMenu(c, true);
629     },
630
631     // private
632     onDisable : function(){
633         this.items.each(function(item){
634              if(item.disable){
635                  item.disable();
636              }
637         });
638     },
639
640     // private
641     onEnable : function(){
642         this.items.each(function(item){
643              if(item.enable){
644                  item.enable();
645              }
646         });
647     },
648
649     // private
650     onButtonTriggerOver : function(btn){
651         if(this.activeMenuBtn && this.activeMenuBtn != btn){
652             this.activeMenuBtn.hideMenu();
653             btn.showMenu();
654             this.activeMenuBtn = btn;
655         }
656     },
657
658     // private
659     onButtonMenuShow : function(btn){
660         this.activeMenuBtn = btn;
661     },
662
663     // private
664     onButtonMenuHide : function(btn){
665         delete this.activeMenuBtn;
666     }
667 });
668 Ext.reg('toolbar', Ext.Toolbar);
669
670 /**
671  * @class Ext.Toolbar.Item
672  * @extends Ext.BoxComponent
673  * The base class that other non-interacting Toolbar Item classes should extend in order to
674  * get some basic common toolbar item functionality.
675  * @constructor
676  * Creates a new Item
677  * @param {HTMLElement} el
678  * @xtype tbitem
679  */
680 T.Item = Ext.extend(Ext.BoxComponent, {
681     hideParent: true, //  Hiding a Toolbar.Item hides its containing TD
682     enable:Ext.emptyFn,
683     disable:Ext.emptyFn,
684     focus:Ext.emptyFn
685     /**
686      * @cfg {String} overflowText Text to be used for the menu if the item is overflowed.
687      */
688 });
689 Ext.reg('tbitem', T.Item);
690
691 /**
692  * @class Ext.Toolbar.Separator
693  * @extends Ext.Toolbar.Item
694  * A simple class that adds a vertical separator bar between toolbar items
695  * (css class:<tt>'xtb-sep'</tt>). Example usage:
696  * <pre><code>
697 new Ext.Panel({
698     tbar : [
699         'Item 1',
700         {xtype: 'tbseparator'}, // or '-'
701         'Item 2'
702     ]
703 });
704 </code></pre>
705  * @constructor
706  * Creates a new Separator
707  * @xtype tbseparator
708  */
709 T.Separator = Ext.extend(T.Item, {
710     onRender : function(ct, position){
711         this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
712     }
713 });
714 Ext.reg('tbseparator', T.Separator);
715
716 /**
717  * @class Ext.Toolbar.Spacer
718  * @extends Ext.Toolbar.Item
719  * A simple element that adds extra horizontal space between items in a toolbar.
720  * By default a 2px wide space is added via css specification:<pre><code>
721 .x-toolbar .xtb-spacer {
722     width:2px;
723 }
724  * </code></pre>
725  * <p>Example usage:</p>
726  * <pre><code>
727 new Ext.Panel({
728     tbar : [
729         'Item 1',
730         {xtype: 'tbspacer'}, // or ' '
731         'Item 2',
732         // space width is also configurable via javascript
733         {xtype: 'tbspacer', width: 50}, // add a 50px space
734         'Item 3'
735     ]
736 });
737 </code></pre>
738  * @constructor
739  * Creates a new Spacer
740  * @xtype tbspacer
741  */
742 T.Spacer = Ext.extend(T.Item, {
743     /**
744      * @cfg {Number} width
745      * The width of the spacer in pixels (defaults to 2px via css style <tt>.x-toolbar .xtb-spacer</tt>).
746      */
747
748     onRender : function(ct, position){
749         this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
750     }
751 });
752 Ext.reg('tbspacer', T.Spacer);
753
754 /**
755  * @class Ext.Toolbar.Fill
756  * @extends Ext.Toolbar.Spacer
757  * A non-rendering placeholder item which instructs the Toolbar's Layout to begin using
758  * the right-justified button container.
759  * <pre><code>
760 new Ext.Panel({
761     tbar : [
762         'Item 1',
763         {xtype: 'tbfill'}, // or '->'
764         'Item 2'
765     ]
766 });
767 </code></pre>
768  * @constructor
769  * Creates a new Fill
770  * @xtype tbfill
771  */
772 T.Fill = Ext.extend(T.Item, {
773     // private
774     render : Ext.emptyFn,
775     isFill : true
776 });
777 Ext.reg('tbfill', T.Fill);
778
779 /**
780  * @class Ext.Toolbar.TextItem
781  * @extends Ext.Toolbar.Item
782  * A simple class that renders text directly into a toolbar
783  * (with css class:<tt>'xtb-text'</tt>). Example usage:
784  * <pre><code>
785 new Ext.Panel({
786     tbar : [
787         {xtype: 'tbtext', text: 'Item 1'} // or simply 'Item 1'
788     ]
789 });
790 </code></pre>
791  * @constructor
792  * Creates a new TextItem
793  * @param {String/Object} text A text string, or a config object containing a <tt>text</tt> property
794  * @xtype tbtext
795  */
796 T.TextItem = Ext.extend(T.Item, {
797     /**
798      * @cfg {String} text The text to be used as innerHTML (html tags are accepted)
799      */
800
801     constructor: function(config){
802         T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
803     },
804
805     // private
806     onRender : function(ct, position) {
807         this.autoEl = {cls: 'xtb-text', html: this.text || ''};
808         T.TextItem.superclass.onRender.call(this, ct, position);
809     },
810
811     /**
812      * Updates this item's text, setting the text to be used as innerHTML.
813      * @param {String} t The text to display (html accepted).
814      */
815     setText : function(t) {
816         if(this.rendered){
817             this.el.update(t);
818         }else{
819             this.text = t;
820         }
821     }
822 });
823 Ext.reg('tbtext', T.TextItem);
824
825 // backwards compat
826 T.Button = Ext.extend(Ext.Button, {});
827 T.SplitButton = Ext.extend(Ext.SplitButton, {});
828 Ext.reg('tbbutton', T.Button);
829 Ext.reg('tbsplit', T.SplitButton);
830
831 })();
832 /**\r
833  * @class Ext.ButtonGroup\r
834  * @extends Ext.Panel\r
835  * Container for a group of buttons. Example usage:\r
836  * <pre><code>\r
837 var p = new Ext.Panel({\r
838     title: 'Panel with Button Group',\r
839     width: 300,\r
840     height:200,\r
841     renderTo: document.body,\r
842     html: 'whatever',\r
843     tbar: [{\r
844         xtype: 'buttongroup',\r
845         {@link #columns}: 3,\r
846         title: 'Clipboard',\r
847         items: [{\r
848             text: 'Paste',\r
849             scale: 'large',\r
850             rowspan: 3, iconCls: 'add',\r
851             iconAlign: 'top',\r
852             cls: 'x-btn-as-arrow'\r
853         },{\r
854             xtype:'splitbutton',\r
855             text: 'Menu Button',\r
856             scale: 'large',\r
857             rowspan: 3,\r
858             iconCls: 'add',\r
859             iconAlign: 'top',\r
860             arrowAlign:'bottom',\r
861             menu: [{text: 'Menu Item 1'}]\r
862         },{\r
863             xtype:'splitbutton', text: 'Cut', iconCls: 'add16', menu: [{text: 'Cut Menu Item'}]\r
864         },{\r
865             text: 'Copy', iconCls: 'add16'\r
866         },{\r
867             text: 'Format', iconCls: 'add16'\r
868         }]\r
869     }]\r
870 });\r
871  * </code></pre>\r
872  * @constructor\r
873  * Create a new ButtonGroup.\r
874  * @param {Object} config The config object\r
875  * @xtype buttongroup\r
876  */\r
877 Ext.ButtonGroup = Ext.extend(Ext.Panel, {\r
878     /**\r
879      * @cfg {Number} columns The <tt>columns</tt> configuration property passed to the\r
880      * {@link #layout configured layout manager}. See {@link Ext.layout.TableLayout#columns}.\r
881      */\r
882     /**\r
883      * @cfg {String} baseCls  Defaults to <tt>'x-btn-group'</tt>.  See {@link Ext.Panel#baseCls}.\r
884      */\r
885     baseCls: 'x-btn-group',\r
886     /**\r
887      * @cfg {String} layout  Defaults to <tt>'table'</tt>.  See {@link Ext.Container#layout}.\r
888      */\r
889     layout:'table',\r
890     defaultType: 'button',\r
891     /**\r
892      * @cfg {Boolean} frame  Defaults to <tt>true</tt>.  See {@link Ext.Panel#frame}.\r
893      */\r
894     frame: true,\r
895     internalDefaults: {removeMode: 'container', hideParent: true},\r
896 \r
897     initComponent : function(){\r
898         this.layoutConfig = this.layoutConfig || {};\r
899         Ext.applyIf(this.layoutConfig, {\r
900             columns : this.columns\r
901         });\r
902         if(!this.title){\r
903             this.addClass('x-btn-group-notitle');\r
904         }\r
905         this.on('afterlayout', this.onAfterLayout, this);\r
906         Ext.ButtonGroup.superclass.initComponent.call(this);\r
907     },\r
908 \r
909     applyDefaults : function(c){\r
910         c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);\r
911         var d = this.internalDefaults;\r
912         if(c.events){\r
913             Ext.applyIf(c.initialConfig, d);\r
914             Ext.apply(c, d);\r
915         }else{\r
916             Ext.applyIf(c, d);\r
917         }\r
918         return c;\r
919     },\r
920 \r
921     onAfterLayout : function(){\r
922         var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;\r
923         this.body.setWidth(bodyWidth);\r
924         this.el.setWidth(bodyWidth + this.getFrameWidth());\r
925     }\r
926     /**\r
927      * @cfg {Array} tools  @hide\r
928      */\r
929 });\r
930 \r
931 Ext.reg('buttongroup', Ext.ButtonGroup);\r
932 /**
933  * @class Ext.PagingToolbar
934  * @extends Ext.Toolbar
935  * <p>As the amount of records increases, the time required for the browser to render
936  * them increases. Paging is used to reduce the amount of data exchanged with the client.
937  * Note: if there are more records/rows than can be viewed in the available screen area, vertical
938  * scrollbars will be added.</p>
939  * <p>Paging is typically handled on the server side (see exception below). The client sends
940  * parameters to the server side, which the server needs to interpret and then respond with the
941  * approprate data.</p>
942  * <p><b>Ext.PagingToolbar</b> is a specialized toolbar that is bound to a {@link Ext.data.Store}
943  * and provides automatic paging control. This Component {@link Ext.data.Store#load load}s blocks
944  * of data into the <tt>{@link #store}</tt> by passing {@link Ext.data.Store#paramNames paramNames} used for
945  * paging criteria.</p>
946  * <p>PagingToolbar is typically used as one of the Grid's toolbars:</p>
947  * <pre><code>
948 Ext.QuickTips.init(); // to display button quicktips
949
950 var myStore = new Ext.data.Store({
951     reader: new Ext.data.JsonReader({
952         {@link Ext.data.JsonReader#totalProperty totalProperty}: 'results', 
953         ...
954     }),
955     ...
956 });
957
958 var myPageSize = 25;  // server script should only send back 25 items at a time
959
960 var grid = new Ext.grid.GridPanel({
961     ...
962     store: myStore,
963     bbar: new Ext.PagingToolbar({
964         {@link #store}: myStore,       // grid and PagingToolbar using same store
965         {@link #displayInfo}: true,
966         {@link #pageSize}: myPageSize,
967         {@link #prependButtons}: true,
968         items: [
969             'text 1'
970         ]
971     })
972 });
973  * </code></pre>
974  *
975  * <p>To use paging, pass the paging requirements to the server when the store is first loaded.</p>
976  * <pre><code>
977 store.load({
978     params: {
979         // specify params for the first page load if using paging
980         start: 0,          
981         limit: myPageSize,
982         // other params
983         foo:   'bar'
984     }
985 });
986  * </code></pre>
987  * 
988  * <p>If using {@link Ext.data.Store#autoLoad store's autoLoad} configuration:</p>
989  * <pre><code>
990 var myStore = new Ext.data.Store({
991     {@link Ext.data.Store#autoLoad autoLoad}: {params:{start: 0, limit: 25}},
992     ...
993 });
994  * </code></pre>
995  * 
996  * <p>The packet sent back from the server would have this form:</p>
997  * <pre><code>
998 {
999     "success": true,
1000     "results": 2000, 
1001     "rows": [ // <b>*Note:</b> this must be an Array 
1002         { "id":  1, "name": "Bill", "occupation": "Gardener" },
1003         { "id":  2, "name":  "Ben", "occupation": "Horticulturalist" },
1004         ...
1005         { "id": 25, "name":  "Sue", "occupation": "Botanist" }
1006     ]
1007 }
1008  * </code></pre>
1009  * <p><u>Paging with Local Data</u></p>
1010  * <p>Paging can also be accomplished with local data using extensions:</p>
1011  * <div class="mdetail-params"><ul>
1012  * <li><a href="http://extjs.com/forum/showthread.php?t=71532">Ext.ux.data.PagingStore</a></li>
1013  * <li>Paging Memory Proxy (examples/ux/PagingMemoryProxy.js)</li>
1014  * </ul></div>
1015  * @constructor Create a new PagingToolbar
1016  * @param {Object} config The config object
1017  * @xtype paging
1018  */
1019 (function() {
1020
1021 var T = Ext.Toolbar;
1022
1023 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
1024     /**
1025      * @cfg {Ext.data.Store} store
1026      * The {@link Ext.data.Store} the paging toolbar should use as its data source (required).
1027      */
1028     /**
1029      * @cfg {Boolean} displayInfo
1030      * <tt>true</tt> to display the displayMsg (defaults to <tt>false</tt>)
1031      */
1032     /**
1033      * @cfg {Number} pageSize
1034      * The number of records to display per page (defaults to <tt>20</tt>)
1035      */
1036     pageSize : 20,
1037     /**
1038      * @cfg {Boolean} prependButtons
1039      * <tt>true</tt> to insert any configured <tt>items</tt> <i>before</i> the paging buttons.
1040      * Defaults to <tt>false</tt>.
1041      */
1042     /**
1043      * @cfg {String} displayMsg
1044      * The paging status message to display (defaults to <tt>'Displaying {0} - {1} of {2}'</tt>).
1045      * Note that this string is formatted using the braced numbers <tt>{0}-{2}</tt> as tokens
1046      * that are replaced by the values for start, end and total respectively. These tokens should
1047      * be preserved when overriding this string if showing those values is desired.
1048      */
1049     displayMsg : 'Displaying {0} - {1} of {2}',
1050     /**
1051      * @cfg {String} emptyMsg
1052      * The message to display when no records are found (defaults to 'No data to display')
1053      */
1054     emptyMsg : 'No data to display',
1055     /**
1056      * @cfg {String} beforePageText
1057      * The text displayed before the input item (defaults to <tt>'Page'</tt>).
1058      */
1059     beforePageText : 'Page',
1060     /**
1061      * @cfg {String} afterPageText
1062      * Customizable piece of the default paging text (defaults to <tt>'of {0}'</tt>). Note that
1063      * this string is formatted using <tt>{0}</tt> as a token that is replaced by the number of
1064      * total pages. This token should be preserved when overriding this string if showing the
1065      * total page count is desired.
1066      */
1067     afterPageText : 'of {0}',
1068     /**
1069      * @cfg {String} firstText
1070      * The quicktip text displayed for the first page button (defaults to <tt>'First Page'</tt>).
1071      * <b>Note</b>: quick tips must be initialized for the quicktip to show.
1072      */
1073     firstText : 'First Page',
1074     /**
1075      * @cfg {String} prevText
1076      * The quicktip text displayed for the previous page button (defaults to <tt>'Previous Page'</tt>).
1077      * <b>Note</b>: quick tips must be initialized for the quicktip to show.
1078      */
1079     prevText : 'Previous Page',
1080     /**
1081      * @cfg {String} nextText
1082      * The quicktip text displayed for the next page button (defaults to <tt>'Next Page'</tt>).
1083      * <b>Note</b>: quick tips must be initialized for the quicktip to show.
1084      */
1085     nextText : 'Next Page',
1086     /**
1087      * @cfg {String} lastText
1088      * The quicktip text displayed for the last page button (defaults to <tt>'Last Page'</tt>).
1089      * <b>Note</b>: quick tips must be initialized for the quicktip to show.
1090      */
1091     lastText : 'Last Page',
1092     /**
1093      * @cfg {String} refreshText
1094      * The quicktip text displayed for the Refresh button (defaults to <tt>'Refresh'</tt>).
1095      * <b>Note</b>: quick tips must be initialized for the quicktip to show.
1096      */
1097     refreshText : 'Refresh',
1098
1099     /**
1100      * <p><b>Deprecated</b>. <code>paramNames</code> should be set in the <b>data store</b>
1101      * (see {@link Ext.data.Store#paramNames}).</p>
1102      * <br><p>Object mapping of parameter names used for load calls, initially set to:</p>
1103      * <pre>{start: 'start', limit: 'limit'}</pre>
1104      * @type Object
1105      * @property paramNames
1106      * @deprecated
1107      */
1108
1109     /**
1110      * The number of records to display per page.  See also <tt>{@link #cursor}</tt>.
1111      * @type Number
1112      * @property pageSize
1113      */
1114
1115     /**
1116      * Indicator for the record position.  This property might be used to get the active page
1117      * number for example:<pre><code>
1118      * // t is reference to the paging toolbar instance
1119      * var activePage = Math.ceil((t.cursor + t.pageSize) / t.pageSize);
1120      * </code></pre>
1121      * @type Number
1122      * @property cursor
1123      */
1124
1125     initComponent : function(){
1126         var pagingItems = [this.first = new T.Button({
1127             tooltip: this.firstText,
1128             overflowText: this.firstText,
1129             iconCls: 'x-tbar-page-first',
1130             disabled: true,
1131             handler: this.moveFirst,
1132             scope: this
1133         }), this.prev = new T.Button({
1134             tooltip: this.prevText,
1135             overflowText: this.prevText,
1136             iconCls: 'x-tbar-page-prev',
1137             disabled: true,
1138             handler: this.movePrevious,
1139             scope: this
1140         }), '-', this.beforePageText,
1141         this.inputItem = new Ext.form.NumberField({
1142             cls: 'x-tbar-page-number',
1143             allowDecimals: false,
1144             allowNegative: false,
1145             enableKeyEvents: true,
1146             selectOnFocus: true,
1147             submitValue: false,
1148             listeners: {
1149                 scope: this,
1150                 keydown: this.onPagingKeyDown,
1151                 blur: this.onPagingBlur
1152             }
1153         }), this.afterTextItem = new T.TextItem({
1154             text: String.format(this.afterPageText, 1)
1155         }), '-', this.next = new T.Button({
1156             tooltip: this.nextText,
1157             overflowText: this.nextText,
1158             iconCls: 'x-tbar-page-next',
1159             disabled: true,
1160             handler: this.moveNext,
1161             scope: this
1162         }), this.last = new T.Button({
1163             tooltip: this.lastText,
1164             overflowText: this.lastText,
1165             iconCls: 'x-tbar-page-last',
1166             disabled: true,
1167             handler: this.moveLast,
1168             scope: this
1169         }), '-', this.refresh = new T.Button({
1170             tooltip: this.refreshText,
1171             overflowText: this.refreshText,
1172             iconCls: 'x-tbar-loading',
1173             handler: this.doRefresh,
1174             scope: this
1175         })];
1176
1177
1178         var userItems = this.items || this.buttons || [];
1179         if (this.prependButtons) {
1180             this.items = userItems.concat(pagingItems);
1181         }else{
1182             this.items = pagingItems.concat(userItems);
1183         }
1184         delete this.buttons;
1185         if(this.displayInfo){
1186             this.items.push('->');
1187             this.items.push(this.displayItem = new T.TextItem({}));
1188         }
1189         Ext.PagingToolbar.superclass.initComponent.call(this);
1190         this.addEvents(
1191             /**
1192              * @event change
1193              * Fires after the active page has been changed.
1194              * @param {Ext.PagingToolbar} this
1195              * @param {Object} pageData An object that has these properties:<ul>
1196              * <li><code>total</code> : Number <div class="sub-desc">The total number of records in the dataset as
1197              * returned by the server</div></li>
1198              * <li><code>activePage</code> : Number <div class="sub-desc">The current page number</div></li>
1199              * <li><code>pages</code> : Number <div class="sub-desc">The total number of pages (calculated from
1200              * the total number of records in the dataset as returned by the server and the current {@link #pageSize})</div></li>
1201              * </ul>
1202              */
1203             'change',
1204             /**
1205              * @event beforechange
1206              * Fires just before the active page is changed.
1207              * Return false to prevent the active page from being changed.
1208              * @param {Ext.PagingToolbar} this
1209              * @param {Object} params An object hash of the parameters which the PagingToolbar will send when
1210              * loading the required page. This will contain:<ul>
1211              * <li><code>start</code> : Number <div class="sub-desc">The starting row number for the next page of records to
1212              * be retrieved from the server</div></li>
1213              * <li><code>limit</code> : Number <div class="sub-desc">The number of records to be retrieved from the server</div></li>
1214              * </ul>
1215              * <p>(note: the names of the <b>start</b> and <b>limit</b> properties are determined
1216              * by the store's {@link Ext.data.Store#paramNames paramNames} property.)</p>
1217              * <p>Parameters may be added as required in the event handler.</p>
1218              */
1219             'beforechange'
1220         );
1221         this.on('afterlayout', this.onFirstLayout, this, {single: true});
1222         this.cursor = 0;
1223         this.bindStore(this.store, true);
1224     },
1225
1226     // private
1227     onFirstLayout : function(){
1228         if(this.dsLoaded){
1229             this.onLoad.apply(this, this.dsLoaded);
1230         }
1231     },
1232
1233     // private
1234     updateInfo : function(){
1235         if(this.displayItem){
1236             var count = this.store.getCount();
1237             var msg = count == 0 ?
1238                 this.emptyMsg :
1239                 String.format(
1240                     this.displayMsg,
1241                     this.cursor+1, this.cursor+count, this.store.getTotalCount()
1242                 );
1243             this.displayItem.setText(msg);
1244         }
1245     },
1246
1247     // private
1248     onLoad : function(store, r, o){
1249         if(!this.rendered){
1250             this.dsLoaded = [store, r, o];
1251             return;
1252         }
1253         var p = this.getParams();
1254         this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
1255         var d = this.getPageData(), ap = d.activePage, ps = d.pages;
1256
1257         this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
1258         this.inputItem.setValue(ap);
1259         this.first.setDisabled(ap == 1);
1260         this.prev.setDisabled(ap == 1);
1261         this.next.setDisabled(ap == ps);
1262         this.last.setDisabled(ap == ps);
1263         this.refresh.enable();
1264         this.updateInfo();
1265         this.fireEvent('change', this, d);
1266     },
1267
1268     // private
1269     getPageData : function(){
1270         var total = this.store.getTotalCount();
1271         return {
1272             total : total,
1273             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
1274             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
1275         };
1276     },
1277
1278     /**
1279      * Change the active page
1280      * @param {Integer} page The page to display
1281      */
1282     changePage : function(page){
1283         this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
1284     },
1285
1286     // private
1287     onLoadError : function(){
1288         if(!this.rendered){
1289             return;
1290         }
1291         this.refresh.enable();
1292     },
1293
1294     // private
1295     readPage : function(d){
1296         var v = this.inputItem.getValue(), pageNum;
1297         if (!v || isNaN(pageNum = parseInt(v, 10))) {
1298             this.inputItem.setValue(d.activePage);
1299             return false;
1300         }
1301         return pageNum;
1302     },
1303
1304     onPagingFocus : function(){
1305         this.inputItem.select();
1306     },
1307
1308     //private
1309     onPagingBlur : function(e){
1310         this.inputItem.setValue(this.getPageData().activePage);
1311     },
1312
1313     // private
1314     onPagingKeyDown : function(field, e){
1315         var k = e.getKey(), d = this.getPageData(), pageNum;
1316         if (k == e.RETURN) {
1317             e.stopEvent();
1318             pageNum = this.readPage(d);
1319             if(pageNum !== false){
1320                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
1321                 this.doLoad(pageNum * this.pageSize);
1322             }
1323         }else if (k == e.HOME || k == e.END){
1324             e.stopEvent();
1325             pageNum = k == e.HOME ? 1 : d.pages;
1326             field.setValue(pageNum);
1327         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
1328             e.stopEvent();
1329             if((pageNum = this.readPage(d))){
1330                 var increment = e.shiftKey ? 10 : 1;
1331                 if(k == e.DOWN || k == e.PAGEDOWN){
1332                     increment *= -1;
1333                 }
1334                 pageNum += increment;
1335                 if(pageNum >= 1 & pageNum <= d.pages){
1336                     field.setValue(pageNum);
1337                 }
1338             }
1339         }
1340     },
1341
1342     // private
1343     getParams : function(){
1344         //retain backwards compat, allow params on the toolbar itself, if they exist.
1345         return this.paramNames || this.store.paramNames;
1346     },
1347
1348     // private
1349     beforeLoad : function(){
1350         if(this.rendered && this.refresh){
1351             this.refresh.disable();
1352         }
1353     },
1354
1355     // private
1356     doLoad : function(start){
1357         var o = {}, pn = this.getParams();
1358         o[pn.start] = start;
1359         o[pn.limit] = this.pageSize;
1360         if(this.fireEvent('beforechange', this, o) !== false){
1361             this.store.load({params:o});
1362         }
1363     },
1364
1365     /**
1366      * Move to the first page, has the same effect as clicking the 'first' button.
1367      */
1368     moveFirst : function(){
1369         this.doLoad(0);
1370     },
1371
1372     /**
1373      * Move to the previous page, has the same effect as clicking the 'previous' button.
1374      */
1375     movePrevious : function(){
1376         this.doLoad(Math.max(0, this.cursor-this.pageSize));
1377     },
1378
1379     /**
1380      * Move to the next page, has the same effect as clicking the 'next' button.
1381      */
1382     moveNext : function(){
1383         this.doLoad(this.cursor+this.pageSize);
1384     },
1385
1386     /**
1387      * Move to the last page, has the same effect as clicking the 'last' button.
1388      */
1389     moveLast : function(){
1390         var total = this.store.getTotalCount(),
1391             extra = total % this.pageSize;
1392
1393         this.doLoad(extra ? (total - extra) : total - this.pageSize);
1394     },
1395
1396     /**
1397      * Refresh the current page, has the same effect as clicking the 'refresh' button.
1398      */
1399     doRefresh : function(){
1400         this.doLoad(this.cursor);
1401     },
1402
1403     /**
1404      * Binds the paging toolbar to the specified {@link Ext.data.Store}
1405      * @param {Store} store The store to bind to this toolbar
1406      * @param {Boolean} initial (Optional) true to not remove listeners
1407      */
1408     bindStore : function(store, initial){
1409         var doLoad;
1410         if(!initial && this.store){
1411             if(store !== this.store && this.store.autoDestroy){
1412                 this.store.destroy();
1413             }else{
1414                 this.store.un('beforeload', this.beforeLoad, this);
1415                 this.store.un('load', this.onLoad, this);
1416                 this.store.un('exception', this.onLoadError, this);
1417             }
1418             if(!store){
1419                 this.store = null;
1420             }
1421         }
1422         if(store){
1423             store = Ext.StoreMgr.lookup(store);
1424             store.on({
1425                 scope: this,
1426                 beforeload: this.beforeLoad,
1427                 load: this.onLoad,
1428                 exception: this.onLoadError
1429             });
1430             doLoad = true;
1431         }
1432         this.store = store;
1433         if(doLoad){
1434             this.onLoad(store, null, {});
1435         }
1436     },
1437
1438     /**
1439      * Unbinds the paging toolbar from the specified {@link Ext.data.Store} <b>(deprecated)</b>
1440      * @param {Ext.data.Store} store The data store to unbind
1441      */
1442     unbind : function(store){
1443         this.bindStore(null);
1444     },
1445
1446     /**
1447      * Binds the paging toolbar to the specified {@link Ext.data.Store} <b>(deprecated)</b>
1448      * @param {Ext.data.Store} store The data store to bind
1449      */
1450     bind : function(store){
1451         this.bindStore(store);
1452     },
1453
1454     // private
1455     onDestroy : function(){
1456         this.bindStore(null);
1457         Ext.PagingToolbar.superclass.onDestroy.call(this);
1458     }
1459 });
1460
1461 })();
1462 Ext.reg('paging', Ext.PagingToolbar);