source: trunk/web/addons/job_monarch/lib/extjs-30/pkgs/pkg-toolbars-debug.js @ 625

Last change on this file since 625 was 625, checked in by ramonb, 15 years ago

lib/extjs-30:

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