123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>The source code</title>
- <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
- <style type="text/css">
- .highlight { display: block; background-color: #ddd; }
- </style>
- <script type="text/javascript">
- function highlight() {
- document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
- }
- </script>
- </head>
- <body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-layout-container-Card'>/**
- </span> * This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
- * visible at any given time. This layout style is most commonly used for wizards, tab implementations, etc.
- * This class is intended to be extended or created via the layout:'card' {@link Ext.container.Container#layout} config,
- * and should generally not need to be created directly via the new keyword.
- *
- * The CardLayout's focal method is {@link #setActiveItem}. Since only one panel is displayed at a time,
- * the only way to move from one Component to the next is by calling setActiveItem, passing the next panel to display
- * (or its id or index). The layout itself does not provide a user interface for handling this navigation,
- * so that functionality must be provided by the developer.
- *
- * To change the active card of a container, call the setActiveItem method of its layout:
- *
- * @example
- * var p = Ext.create('Ext.panel.Panel', {
- * layout: 'card',
- * items: [
- * { html: 'Card 1' },
- * { html: 'Card 2' }
- * ],
- * renderTo: Ext.getBody()
- * });
- *
- * p.getLayout().setActiveItem(1);
- *
- * In the following example, a simplistic wizard setup is demonstrated. A button bar is added
- * to the footer of the containing panel to provide navigation buttons. The buttons will be handled by a
- * common navigation routine. Note that other uses of a CardLayout (like a tab control) would require a
- * completely different implementation. For serious implementations, a better approach would be to extend
- * CardLayout to provide the custom functionality needed.
- *
- * @example
- * var navigate = function(panel, direction){
- * // This routine could contain business logic required to manage the navigation steps.
- * // It would call setActiveItem as needed, manage navigation button state, handle any
- * // branching logic that might be required, handle alternate actions like cancellation
- * // or finalization, etc. A complete wizard implementation could get pretty
- * // sophisticated depending on the complexity required, and should probably be
- * // done as a subclass of CardLayout in a real-world implementation.
- * var layout = panel.getLayout();
- * layout[direction]();
- * Ext.getCmp('move-prev').setDisabled(!layout.getPrev());
- * Ext.getCmp('move-next').setDisabled(!layout.getNext());
- * };
- *
- * Ext.create('Ext.panel.Panel', {
- * title: 'Example Wizard',
- * width: 300,
- * height: 200,
- * layout: 'card',
- * bodyStyle: 'padding:15px',
- * defaults: {
- * // applied to each contained panel
- * border: false
- * },
- * // just an example of one possible navigation scheme, using buttons
- * bbar: [
- * {
- * id: 'move-prev',
- * text: 'Back',
- * handler: function(btn) {
- * navigate(btn.up("panel"), "prev");
- * },
- * disabled: true
- * },
- * '->', // greedy spacer so that the buttons are aligned to each side
- * {
- * id: 'move-next',
- * text: 'Next',
- * handler: function(btn) {
- * navigate(btn.up("panel"), "next");
- * }
- * }
- * ],
- * // the panels (or "cards") within the layout
- * items: [{
- * id: 'card-0',
- * html: '<h1>Welcome to the Wizard!</h1><p>Step 1 of 3</p>'
- * },{
- * id: 'card-1',
- * html: '<p>Step 2 of 3</p>'
- * },{
- * id: 'card-2',
- * html: '<h1>Congratulations!</h1><p>Step 3 of 3 - Complete</p>'
- * }],
- * renderTo: Ext.getBody()
- * });
- */
- Ext.define('Ext.layout.container.Card', {
- /* Begin Definitions */
- extend: 'Ext.layout.container.Fit',
- alternateClassName: 'Ext.layout.CardLayout',
- alias: 'layout.card',
- /* End Definitions */
- type: 'card',
- hideInactive: true,
- <span id='Ext-layout-container-Card-cfg-deferredRender'> /**
- </span> * @cfg {Boolean} deferredRender
- * True to render each contained item at the time it becomes active, false to render all contained items
- * as soon as the layout is rendered (defaults to false). If there is a significant amount of content or
- * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
- * true might improve performance.
- */
- deferredRender : false,
-
- getRenderTree: function () {
- var me = this,
- activeItem = me.getActiveItem();
- if (activeItem) {
- // If they veto the activate, we have no active item
- if (activeItem.hasListeners.beforeactivate && activeItem.fireEvent('beforeactivate', activeItem) === false) {
-
- // We must null our activeItem reference, AND the one in our owning Container.
- // Because upon layout invalidation, renderChildren will use this.getActiveItem which
- // uses this.activeItem || this.owner.activeItem
- activeItem = me.activeItem = me.owner.activeItem = null;
- }
-
- // Item is to be the active one. Fire event after it is first layed out
- else if (activeItem.hasListeners.activate) {
- activeItem.on({
- boxready: function() {
- activeItem.fireEvent('activate', activeItem);
- },
- single: true
- });
- }
- if (me.deferredRender) {
- if (activeItem) {
- return me.getItemsRenderTree([activeItem]);
- }
- } else {
- return me.callParent(arguments);
- }
- }
- },
- renderChildren: function () {
- var me = this,
- active = me.getActiveItem();
-
- if (!me.deferredRender) {
- me.callParent();
- } else if (active) {
- // ensure the active item is configured for the layout
- me.renderItems([active], me.getRenderTarget());
- }
- },
- isValidParent : function(item, target, position) {
- // Note: Card layout does not care about order within the target because only one is ever visible.
- // We only care whether the item is a direct child of the target.
- var itemEl = item.el ? item.el.dom : Ext.getDom(item);
- return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
- },
- <span id='Ext-layout-container-Card-method-getActiveItem'> /**
- </span> * Return the active (visible) component in the layout.
- * @returns {Ext.Component}
- */
- getActiveItem: function() {
- var me = this,
- // Ensure the calculated result references a Component
- result = me.parseActiveItem(me.activeItem || (me.owner && me.owner.activeItem));
- // Sanitize the result in case the active item is no longer there.
- if (result && me.owner.items.indexOf(result) != -1) {
- me.activeItem = result;
- } else {
- me.activeItem = null;
- }
- return me.activeItem;
- },
- // @private
- parseActiveItem: function(item) {
- if (item && item.isComponent) {
- return item;
- } else if (typeof item == 'number' || item === undefined) {
- return this.getLayoutItems()[item || 0];
- } else {
- return this.owner.getComponent(item);
- }
- },
- // @private. Called before both dynamic render, and bulk render.
- // Ensure that the active item starts visible, and inactive ones start invisible
- configureItem: function(item) {
- if (item === this.getActiveItem()) {
- item.hidden = false;
- } else {
- item.hidden = true;
- }
- this.callParent(arguments);
- },
- onRemove: function(component) {
- var me = this;
-
- if (component === me.activeItem) {
- me.activeItem = null;
- }
- },
- // @private
- getAnimation: function(newCard, owner) {
- var newAnim = (newCard || {}).cardSwitchAnimation;
- if (newAnim === false) {
- return false;
- }
- return newAnim || owner.cardSwitchAnimation;
- },
- <span id='Ext-layout-container-Card-method-getNext'> /**
- </span> * Return the active (visible) component in the layout to the next card
- * @returns {Ext.Component} The next component or false.
- */
- getNext: function() {
- //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
- //should come back in 4.1
- var wrap = arguments[0],
- items = this.getLayoutItems(),
- index = Ext.Array.indexOf(items, this.activeItem);
-
- return items[index + 1] || (wrap ? items[0] : false);
- },
- <span id='Ext-layout-container-Card-method-next'> /**
- </span> * Sets the active (visible) component in the layout to the next card
- * @return {Ext.Component} the activated component or false when nothing activated.
- */
- next: function() {
- //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
- //should come back in 4.1
- var anim = arguments[0],
- wrap = arguments[1];
- return this.setActiveItem(this.getNext(wrap), anim);
- },
- <span id='Ext-layout-container-Card-method-getPrev'> /**
- </span> * Return the active (visible) component in the layout to the previous card
- * @returns {Ext.Component} The previous component or false.
- */
- getPrev: function() {
- //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
- //should come back in 4.1
- var wrap = arguments[0],
- items = this.getLayoutItems(),
- index = Ext.Array.indexOf(items, this.activeItem);
-
- return items[index - 1] || (wrap ? items[items.length - 1] : false);
- },
- <span id='Ext-layout-container-Card-method-prev'> /**
- </span> * Sets the active (visible) component in the layout to the previous card
- * @return {Ext.Component} the activated component or false when nothing activated.
- */
- prev: function() {
- //NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
- //should come back in 4.1
- var anim = arguments[0],
- wrap = arguments[1];
- return this.setActiveItem(this.getPrev(wrap), anim);
- },
- <span id='Ext-layout-container-Card-method-setActiveItem'> /**
- </span> * Makes the given card active.
- *
- * var card1 = Ext.create('Ext.panel.Panel', {itemId: 'card-1'});
- * var card2 = Ext.create('Ext.panel.Panel', {itemId: 'card-2'});
- * var panel = Ext.create('Ext.panel.Panel', {
- * layout: 'card',
- * activeItem: 0,
- * items: [card1, card2]
- * });
- * // These are all equivalent
- * panel.getLayout().setActiveItem(card2);
- * panel.getLayout().setActiveItem('card-2');
- * panel.getLayout().setActiveItem(1);
- *
- * @param {Ext.Component/Number/String} newCard The component, component {@link Ext.Component#id id},
- * {@link Ext.Component#itemId itemId}, or index of component.
- * @return {Ext.Component} the activated component or false when nothing activated.
- * False is returned also when trying to activate an already active card.
- */
- setActiveItem: function(newCard) {
- var me = this,
- owner = me.owner,
- oldCard = me.activeItem,
- rendered = owner.rendered,
- newIndex;
- newCard = me.parseActiveItem(newCard);
- newIndex = owner.items.indexOf(newCard);
- // If the card is not a child of the owner, then add it.
- // Without doing a layout!
- if (newIndex == -1) {
- newIndex = owner.items.items.length;
- Ext.suspendLayouts();
- newCard = owner.add(newCard);
- Ext.resumeLayouts();
- }
- // Is this a valid, different card?
- if (newCard && oldCard != newCard) {
- // Fire the beforeactivate and beforedeactivate events on the cards
- if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
- return false;
- }
- if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
- return false;
- }
- if (rendered) {
- Ext.suspendLayouts();
- // If the card has not been rendered yet, now is the time to do so.
- if (!newCard.rendered) {
- me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
- }
- if (oldCard) {
- if (me.hideInactive) {
- oldCard.hide();
- oldCard.hiddenByLayout = true;
- }
- oldCard.fireEvent('deactivate', oldCard, newCard);
- }
- // Make sure the new card is shown
- if (newCard.hidden) {
- newCard.show();
- }
- // Layout needs activeItem to be correct, so set it if the show has not been vetoed
- if (!newCard.hidden) {
- me.activeItem = newCard;
- }
- Ext.resumeLayouts(true);
- } else {
- me.activeItem = newCard;
- }
- newCard.fireEvent('activate', newCard, oldCard);
- return me.activeItem;
- }
- return false;
- }
- });
- </pre>
- </body>
- </html>
|