Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / layout / container / AbstractCard.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * This layout manages multiple child Components, each is fit to the Container, where only a single child Component
17  * can be visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
18  * This class is intended to be extended or created via the layout:'card' {@link Ext.container.Container#layout} config,
19  * and should generally not need to be created directly via the new keyword.
20  *
21  * The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
22  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
23  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
24  * so that functionality must be provided by the developer.
25  *
26  * Containers that are configured with a card layout will have a method setActiveItem dynamically added to it.
27  *
28  *     var p = new Ext.panel.Panel({
29  *         fullscreen: true,
30  *         layout: 'card',
31  *         items: [{
32  *             html: 'Card 1'
33  *         },{
34  *             html: 'Card 2'
35  *         }]
36  *     });
37  *     p.setActiveItem(1);
38  *
39  */
40 Ext.define('Ext.layout.container.AbstractCard', {
41
42     /* Begin Definitions */
43
44     extend: 'Ext.layout.container.Fit',
45
46     /* End Definitions */
47
48     type: 'card',
49
50     sizeAllCards: false,
51
52     hideInactive: true,
53
54     /**
55      * @cfg {Boolean} deferredRender
56      * True to render each contained item at the time it becomes active, false to render all contained items
57      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
58      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
59      * true might improve performance.
60      */
61     deferredRender : false,
62
63     beforeLayout: function() {
64         var me = this;
65         me.activeItem = me.getActiveItem();
66         if (me.activeItem && me.deferredRender) {
67             me.renderItems([me.activeItem], me.getRenderTarget());
68             return true;
69         }
70         else {
71             return this.callParent(arguments);
72         }
73     },
74
75     onLayout: function() {
76         var me = this,
77             activeItem = me.activeItem,
78             items = me.getVisibleItems(),
79             ln = items.length,
80             targetBox = me.getTargetBox(),
81             i, item;
82
83         for (i = 0; i < ln; i++) {
84             item = items[i];
85             me.setItemBox(item, targetBox);
86         }
87
88         if (!me.firstActivated && activeItem) {
89             if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
90                 activeItem.fireEvent('activate', activeItem);
91             }
92             me.firstActivated = true;
93         }
94     },
95
96     isValidParent : function(item, target, position) {
97         // Note: Card layout does not care about order within the target because only one is ever visible.
98         // We only care whether the item is a direct child of the target.
99         var itemEl = item.el ? item.el.dom : Ext.getDom(item);
100         return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
101     },
102
103     /**
104      * Return the active (visible) component in the layout.
105      * @returns {Ext.Component}
106      */
107     getActiveItem: function() {
108         var me = this;
109         if (!me.activeItem && me.owner) {
110             me.activeItem = me.parseActiveItem(me.owner.activeItem);
111         }
112
113         if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
114             return me.activeItem;
115         }
116
117         return null;
118     },
119
120     // @private
121     parseActiveItem: function(item) {
122         if (item && item.isComponent) {
123             return item;
124         }
125         else if (typeof item == 'number' || item === undefined) {
126             return this.getLayoutItems()[item || 0];
127         }
128         else {
129             return this.owner.getComponent(item);
130         }
131     },
132
133     // @private
134     configureItem: function(item, position) {
135         this.callParent([item, position]);
136         if (this.hideInactive && this.activeItem !== item) {
137             item.hide();
138         }
139         else {
140             item.show();
141         }
142     },
143
144     onRemove: function(component) {
145         if (component === this.activeItem) {
146             this.activeItem = null;
147             if (this.owner.items.getCount() === 0) {
148                 this.firstActivated = false;
149             }
150         }
151     },
152
153     // @private
154     getAnimation: function(newCard, owner) {
155         var newAnim = (newCard || {}).cardSwitchAnimation;
156         if (newAnim === false) {
157             return false;
158         }
159         return newAnim || owner.cardSwitchAnimation;
160     },
161
162     /**
163      * Return the active (visible) component in the layout to the next card
164      * @returns {Ext.Component} The next component or false.
165      */
166     getNext: function() {
167         //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This 
168         //should come back in 4.1
169         var wrap = arguments[0];
170         var items = this.getLayoutItems(),
171             index = Ext.Array.indexOf(items, this.activeItem);
172         return items[index + 1] || (wrap ? items[0] : false);
173     },
174
175     /**
176      * Sets the active (visible) component in the layout to the next card
177      * @return {Ext.Component} the activated component or false when nothing activated.
178      */
179     next: function() {
180         //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This 
181         //should come back in 4.1
182         var anim = arguments[0], wrap = arguments[1];
183         return this.setActiveItem(this.getNext(wrap), anim);
184     },
185
186     /**
187      * Return the active (visible) component in the layout to the previous card
188      * @returns {Ext.Component} The previous component or false.
189      */
190     getPrev: function() {
191         //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This 
192         //should come back in 4.1
193         var wrap = arguments[0];
194         var items = this.getLayoutItems(),
195             index = Ext.Array.indexOf(items, this.activeItem);
196         return items[index - 1] || (wrap ? items[items.length - 1] : false);
197     },
198
199     /**
200      * Sets the active (visible) component in the layout to the previous card
201      * @return {Ext.Component} the activated component or false when nothing activated.
202      */
203     prev: function() {
204         //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This 
205         //should come back in 4.1
206         var anim = arguments[0], wrap = arguments[1];
207         return this.setActiveItem(this.getPrev(wrap), anim);
208     }
209 });
210