Upgrade to ExtJS 3.2.2 - Released 06/02/2010
[extjs.git] / src / widgets / layout / CardLayout.js
1 /*!
2  * Ext JS Library 3.2.2
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.layout.CardLayout
9  * @extends Ext.layout.FitLayout
10  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
11  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
12  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
13  * and should generally not need to be created directly via the new keyword.</p>
14  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
15  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
16  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
17  * so that functionality must be provided by the developer.</p>
18  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added
19  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a
20  * common navigation routine -- for this example, the implementation of that routine has been ommitted since
21  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a
22  * completely different implementation.  For serious implementations, a better approach would be to extend
23  * CardLayout to provide the custom functionality needed.  Example usage:</p>
24  * <pre><code>
25 var navHandler = function(direction){
26     // This routine could contain business logic required to manage the navigation steps.
27     // It would call setActiveItem as needed, manage navigation button state, handle any
28     // branching logic that might be required, handle alternate actions like cancellation
29     // or finalization, etc.  A complete wizard implementation could get pretty
30     // sophisticated depending on the complexity required, and should probably be
31     // done as a subclass of CardLayout in a real-world implementation.
32 };
33
34 var card = new Ext.Panel({
35     title: 'Example Wizard',
36     layout:'card',
37     activeItem: 0, // make sure the active item is set on the container config!
38     bodyStyle: 'padding:15px',
39     defaults: {
40         // applied to each contained panel
41         border:false
42     },
43     // just an example of one possible navigation scheme, using buttons
44     bbar: [
45         {
46             id: 'move-prev',
47             text: 'Back',
48             handler: navHandler.createDelegate(this, [-1]),
49             disabled: true
50         },
51         '->', // greedy spacer so that the buttons are aligned to each side
52         {
53             id: 'move-next',
54             text: 'Next',
55             handler: navHandler.createDelegate(this, [1])
56         }
57     ],
58     // the panels (or "cards") within the layout
59     items: [{
60         id: 'card-0',
61         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'
62     },{
63         id: 'card-1',
64         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'
65     },{
66         id: 'card-2',
67         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'
68     }]
69 });
70 </code></pre>
71  */
72 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
73     /**
74      * @cfg {Boolean} deferredRender
75      * True to render each contained item at the time it becomes active, false to render all contained items
76      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
77      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
78      * true might improve performance.
79      */
80     deferredRender : false,
81
82     /**
83      * @cfg {Boolean} layoutOnCardChange
84      * True to force a layout of the active item when the active card is changed. Defaults to false.
85      */
86     layoutOnCardChange : false,
87
88     /**
89      * @cfg {Boolean} renderHidden @hide
90      */
91     // private
92     renderHidden : true,
93
94     type: 'card',
95
96     /**
97      * Sets the active (visible) item in the layout.
98      * @param {String/Number} item The string component id or numeric index of the item to activate
99      */
100     setActiveItem : function(item){
101         var ai = this.activeItem,
102             ct = this.container;
103         item = ct.getComponent(item);
104
105         // Is this a valid, different card?
106         if(item && ai != item){
107
108             // Changing cards, hide the current one
109             if(ai){
110                 ai.hide();
111                 if (ai.hidden !== true) {
112                     return false;
113                 }
114                 ai.fireEvent('deactivate', ai);
115             }
116
117             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
118
119             // Change activeItem reference
120             this.activeItem = item;
121
122             // The container is about to get a recursive layout, remove any deferLayout reference
123             // because it will trigger a redundant layout.
124             delete item.deferLayout;
125
126             // Show the new component
127             item.show();
128
129             this.layout();
130
131             if(layout){
132                 item.doLayout();
133             }
134             item.fireEvent('activate', item);
135         }
136     },
137
138     // private
139     renderAll : function(ct, target){
140         if(this.deferredRender){
141             this.renderItem(this.activeItem, undefined, target);
142         }else{
143             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
144         }
145     }
146 });
147 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;