123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- /*
- * Ext JS Library 2.0 Copyright(c) 2006-2007, Ext JS, LLC. licensing@extjs.com
- *
- * http://extjs.com/license
- */
- /**
- * @class Ext.Container
- * @extends Ext.BoxComponent Base class for any {@link Ext.BoxComponent} that
- * can contain other components. Containers handle the basic behavior
- * of containing items, namely adding, inserting and removing them. The
- * specific layout logic required to visually render contained items is
- * delegated to any one of the different {@link #layout} classes
- * available. This class is intended to be extended and should
- * generally not need to be created directly via the new keyword.
- */
- Ext.Container = Ext.extend(Ext.BoxComponent, {
- /**
- * @cfg {Boolean} monitorResize True to automatically monitor window
- * resize events to handle anything that is sensitive to the
- * current size of the viewport. This value is typically
- * managed by the chosen {@link #layout} and should not need to
- * be set manually.
- */
- /**
- * @cfg {String} layout The layout type to be used in this
- * container. If not specified, a default
- * {@link Ext.layout.ContainerLayout} will be created and used.
- * Valid values are: accordion, anchor, border, card, column,
- * fit, form and table. Specific config values for the chosen
- * layout type can be specified using {@link #layoutConfig}.
- */
- /**
- * @cfg {Object} layoutConfig This is a config object containing
- * properties specific to the chosen layout (to be used in
- * conjunction with the {@link #layout} config value). For
- * complete details regarding the valid config options for each
- * layout type, see the layout class corresponding to the type
- * specified:
- * <ul class="mdetail-params">
- * <li>{@link Ext.layout.Accordion}</li>
- * <li>{@link Ext.layout.AnchorLayout}</li>
- * <li>{@link Ext.layout.BorderLayout}</li>
- * <li>{@link Ext.layout.CardLayout}</li>
- * <li>{@link Ext.layout.ColumnLayout}</li>
- * <li>{@link Ext.layout.FitLayout}</li>
- * <li>{@link Ext.layout.FormLayout}</li>
- * <li>{@link Ext.layout.TableLayout}</li>
- * </ul>
- */
- /**
- * @cfg {Boolean/Number} bufferResize When set to true (100
- * milliseconds) or a number of milliseconds, the layout
- * assigned for this container will buffer the frequency it
- * calculates and does a re-layout of components. This is
- * useful for heavy containers or containers with a large
- * amount of sub components that frequent calls to layout are
- * expensive.
- */
- /**
- * @cfg {String/Number} activeItem A string component id or the
- * numeric index of the component that should be initially
- * activated within the container's layout on render. For
- * example, activeItem: 'item-1' or activeItem: 0 (index 0 =
- * the first item in the container's collection). activeItem
- * only applies to layout styles that can display items one at
- * a time (like {@link Ext.layout.Accordion},
- * {@link Ext.layout.CardLayout} and
- * {@link Ext.layout.FitLayout}). Related to
- * {@link Ext.layout.ContainerLayout#activeItem}.
- */
- /**
- * @cfg {Mixed} items A single item, or an array of child Components
- * to be added to this container. Each item can be any type of
- * object based on {@link Ext.Component}.<br>
- * <br>
- * Component config objects may also be specified in order to
- * avoid the overhead of constructing a real Component object
- * if lazy rendering might mean that the added Component will
- * not be rendered immediately. To take advantage of this "lazy
- * instantiation", set the {@link Ext.Component#xtype} config
- * property to the registered type of the Component wanted.<br>
- * <br>
- * For a list of all available xtypes, see
- * {@link Ext.Component}. If a single item is being passed, it
- * should be passed directly as an object reference (e.g.,
- * items: {...}). Multiple items should be passed as an array
- * of objects (e.g., items: [{...}, {...}]).
- */
- /**
- * @cfg {Object} defaults A config object that will be applied to
- * all components added to this container either via the
- * {@link #items} config or via the {@link #add} or
- * {@link #insert} methods. The defaults config can contain any
- * number of name/value property pairs to be added to each
- * item, and should be valid for the types of items being added
- * to the container. For example, to automatically apply
- * padding to the body of each of a set of contained
- * {@link Ext.Panel} items, you could pass: defaults:
- * {bodyStyle:'padding:15px'}.
- */
- /**
- * @cfg {Boolean} autoDestroy If true the container will
- * automatically destroy any contained component that is
- * removed from it, else destruction must be handled manually
- * (defaults to true).
- */
- autoDestroy : true,
- /**
- * @cfg {Boolean} hideBorders True to hide the borders of each
- * contained component, false to defer to the component's
- * existing border settings (defaults to false).
- */
- /**
- * @cfg {String} defaultType The default type of container
- * represented by this object as registered in
- * {@link Ext.ComponentMgr} (defaults to 'panel').
- */
- defaultType : 'panel',
- // private
- initComponent : function() {
- Ext.Container.superclass.initComponent.call(this);
- this.addEvents(
- /**
- * @event afterlayout Fires when the components in this
- * container are arranged by the associated
- * layout manager.
- * @param {Ext.Container}
- * this
- * @param {ContainerLayout}
- * layout The ContainerLayout implementation
- * for this container
- */
- 'afterlayout',
- /**
- * @event beforeadd Fires before any
- * {@link Ext.Component} is added or inserted
- * into the container. A handler can return false
- * to cancel the add.
- * @param {Ext.Container}
- * this
- * @param {Ext.Component}
- * component The component being added
- * @param {Number}
- * index The index at which the component
- * will be added to the container's items
- * collection
- */
- 'beforeadd',
- /**
- * @event beforeremove Fires before any
- * {@link Ext.Component} is removed from the
- * container. A handler can return false to
- * cancel the remove.
- * @param {Ext.Container}
- * this
- * @param {Ext.Component}
- * component The component being removed
- */
- 'beforeremove',
- /**
- * @event add Fires after any {@link Ext.Component} is
- * added or inserted into the container.
- * @param {Ext.Container}
- * this
- * @param {Ext.Component}
- * component The component that was added
- * @param {Number}
- * index The index at which the component was
- * added to the container's items collection
- */
- 'add',
- /**
- * @event remove Fires after any {@link Ext.Component}
- * is removed from the container.
- * @param {Ext.Container}
- * this
- * @param {Ext.Component}
- * component The component that was removed
- */
- 'remove');
- /**
- * The collection of components in this container as a
- * {@link Ext.util.MixedCollection}
- *
- * @type MixedCollection
- * @property items
- */
- var items = this.items;
- if (items) {
- delete this.items;
- if (items instanceof Array) {
- this.add.apply(this, items);
- } else {
- this.add(items);
- }
- }
- },
- // private
- initItems : function() {
- if (!this.items) {
- this.items = new Ext.util.MixedCollection(false,
- this.getComponentId);
- this.getLayout(); // initialize the layout
- }
- },
- // private
- setLayout : function(layout) {
- if (this.layout && this.layout != layout) {
- this.layout.setContainer(null);
- }
- this.initItems();
- this.layout = layout;
- layout.setContainer(this);
- },
- // private
- render : function() {
- Ext.Container.superclass.render.apply(this, arguments);
- if (this.layout) {
- if (typeof this.layout == 'string') {
- this.layout = new Ext.Container.LAYOUTS[this.layout
- .toLowerCase()](this.layoutConfig);
- }
- this.setLayout(this.layout);
- if (this.activeItem !== undefined) {
- var item = this.activeItem;
- delete this.activeItem;
- this.layout.setActiveItem(item);
- return;
- }
- }
- if (!this.ownerCt) {
- this.doLayout();
- }
- if (this.monitorResize === true) {
- Ext.EventManager.onWindowResize(this.doLayout, this);
- }
- },
- // protected - should only be called by layouts
- getLayoutTarget : function() {
- return this.el;
- },
- // private - used as the key lookup function for the items
- // collection
- getComponentId : function(comp) {
- return comp.itemId || comp.id;
- },
- /**
- * Adds a Component to this Container. Fires the beforeadd event
- * before adding, then fires the add event after the component has
- * been added.
- *
- * @param {Ext.Component/Object}
- * component The component to add.<br>
- * <br>
- * Ext uses lazy rendering, and will only render the
- * added Component should it become necessary.<br>
- * <br>
- * A Component config object may be passed in order to
- * avoid the overhead of constructing a real Component
- * object if lazy rendering might mean that the added
- * Component will not be rendered immediately. To take
- * advantage of this "lazy instantiation", set the
- * {@link Ext.Component#xtype} config property to the
- * registered type of the Component wanted.<br>
- * <br>
- * For a list of all available xtypes, see
- * {@link Ext.Component}.
- * @return {Ext.Component} component The Component (or config
- * object) that was added with the Container's default
- * config values applied.
- */
- add : function(comp) {
- if (!this.items) {
- this.initItems();
- }
- var a = arguments, len = a.length;
- if (len > 1) {
- for (var i = 0; i < len; i++) {
- this.add(a[i]);
- }
- return;
- }
- var c = this.lookupComponent(this.applyDefaults(comp));
- var pos = this.items.length;
- if (this.fireEvent('beforeadd', this, c, pos) !== false
- && this.onBeforeAdd(c) !== false) {
- this.items.add(c);
- c.ownerCt = this;
- this.fireEvent('add', this, c, pos);
- }
- return c;
- },
- /**
- * Inserts a Component into this Container at a specified index.
- * Fires the beforeadd event before inserting, then fires the add
- * event after the Component has been inserted.
- *
- * @param {Number}
- * index The index at which the Component will be
- * inserted into the Container's items collection
- * @param {Ext.Component}
- * component The child Component to insert.<br>
- * <br>
- * Ext uses lazy rendering, and will only render the
- * inserted Component should it become necessary.<br>
- * <br>
- * A Component config object may be passed in order to
- * avoid the overhead of constructing a real Component
- * object if lazy rendering might mean that the inserted
- * Component will not be rendered immediately. To take
- * advantage of this "lazy instantiation", set the
- * {@link Ext.Component#xtype} config property to the
- * registered type of the Component wanted.<br>
- * <br>
- * For a list of all available xtypes, see
- * {@link Ext.Component}.
- * @return {Ext.Component} component The Component (or config
- * object) that was inserted with the Container's default
- * config values applied.
- */
- insert : function(index, comp) {
- if (!this.items) {
- this.initItems();
- }
- var a = arguments, len = a.length;
- if (len > 2) {
- for (var i = len - 1; i >= 1; --i) {
- this.insert(index, a[i]);
- }
- return;
- }
- var c = this.lookupComponent(this.applyDefaults(comp));
- if (c.ownerCt == this && this.items.indexOf(c) < index) {
- --index;
- }
- if (this.fireEvent('beforeadd', this, c, index) !== false
- && this.onBeforeAdd(c) !== false) {
- this.items.insert(index, c);
- c.ownerCt = this;
- this.fireEvent('add', this, c, index);
- }
- return c;
- },
- // private
- applyDefaults : function(c) {
- if (this.defaults) {
- if (typeof c == 'string') {
- c = Ext.ComponentMgr.get(c);
- Ext.apply(c, this.defaults);
- } else if (!c.events) {
- Ext.applyIf(c, this.defaults);
- } else {
- Ext.apply(c, this.defaults);
- }
- }
- return c;
- },
- // private
- onBeforeAdd : function(item) {
- if (item.ownerCt) {
- item.ownerCt.remove(item, false);
- }
- if (this.hideBorders === true) {
- item.border = (item.border === true);
- }
- },
- /**
- * Removes a component from this container. Fires the beforeremove
- * event before removing, then fires the remove event after the
- * component has been removed.
- *
- * @param {Component/String}
- * component The component reference or id to remove
- * @param {Boolean}
- * autoDestroy (optional) True to automatically invoke
- * the component's {@link Ext.Component#destroy} function
- */
- remove : function(comp, autoDestroy) {
- var c = this.getComponent(comp);
- if (c && this.fireEvent('beforeremove', this, c) !== false) {
- this.items.remove(c);
- delete c.ownerCt;
- if (autoDestroy === true
- || (autoDestroy !== false && this.autoDestroy)) {
- c.destroy();
- }
- if (this.layout && this.layout.activeItem == c) {
- delete this.layout.activeItem;
- }
- this.fireEvent('remove', this, c);
- }
- return c;
- },
- /**
- * Gets a direct child Component by id, or by index.
- *
- * @param {String/Number}
- * id or index of child Component to return.
- * @return Ext.Component
- */
- getComponent : function(comp) {
- if (typeof comp == 'object') {
- return comp;
- }
- return this.items.get(comp);
- },
- // private
- lookupComponent : function(comp) {
- if (typeof comp == 'string') {
- return Ext.ComponentMgr.get(comp);
- } else if (!comp.events) {
- return this.createComponent(comp);
- }
- return comp;
- },
- // private
- createComponent : function(config) {
- return Ext.ComponentMgr.create(config, this.defaultType);
- },
- /**
- * Force this container's layout to be recalculated. A call to this
- * function is required after adding a new component to an already
- * rendered container. If you are not dynamically adding and
- * removing components after render, this function will generally
- * not need to be called.
- */
- doLayout : function() {
- if (this.rendered && this.layout) {
- this.layout.layout();
- }
- if (this.items) {
- var cs = this.items.items;
- for (var i = 0, len = cs.length; i < len; i++) {
- var c = cs[i];
- if (c.doLayout) {
- c.doLayout();
- }
- }
- }
- },
- /**
- * Returns the layout currently in use by the container. If the
- * container does not currently have a layout set, a default
- * {@link Ext.layout.ContainerLayout} will be created and set as the
- * container's layout.
- *
- * @return {ContainerLayout} layout The container's layout
- */
- getLayout : function() {
- if (!this.layout) {
- var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
- this.setLayout(layout);
- }
- return this.layout;
- },
- // private
- onDestroy : function() {
- if (this.items) {
- var cs = this.items.items;
- for (var i = 0, len = cs.length; i < len; i++) {
- Ext.destroy(cs[i]);
- }
- }
- if (this.monitorResize) {
- Ext.EventManager.removeResizeListener(this.doLayout, this);
- }
- Ext.Container.superclass.onDestroy.call(this);
- },
- /**
- * Bubbles up the component/container heirarchy, calling the
- * specified function with each component. The scope (<i>this</i>)
- * of function call will be the scope provided or the current
- * component. The arguments to the function will be the args
- * provided or the current component. If the function returns false
- * at any point, the bubble is stopped.
- *
- * @param {Function}
- * fn The function to call
- * @param {Object}
- * scope (optional) The scope of the function (defaults
- * to current node)
- * @param {Array}
- * args (optional) The args to call the function with
- * (default to passing the current component)
- */
- bubble : function(fn, scope, args) {
- var p = this;
- while (p) {
- if (fn.apply(scope || p, args || [p]) === false) {
- break;
- }
- p = p.ownerCt;
- }
- },
- /**
- * Cascades down the component/container heirarchy from this
- * component (called first), calling the specified function with
- * each component. The scope (<i>this</i>) of function call will
- * be the scope provided or the current component. The arguments to
- * the function will be the args provided or the current component.
- * If the function returns false at any point, the cascade is
- * stopped on that branch.
- *
- * @param {Function}
- * fn The function to call
- * @param {Object}
- * scope (optional) The scope of the function (defaults
- * to current component)
- * @param {Array}
- * args (optional) The args to call the function with
- * (defaults to passing the current component)
- */
- cascade : function(fn, scope, args) {
- if (fn.apply(scope || this, args || [this]) !== false) {
- if (this.items) {
- var cs = this.items.items;
- for (var i = 0, len = cs.length; i < len; i++) {
- if (cs[i].cascade) {
- cs[i].cascade(fn, scope, args);
- } else {
- fn.apply(scope || this, args || [cs[i]]);
- }
- }
- }
- }
- },
- /**
- * Find a component under this container at any level by id
- *
- * @param {String}
- * id
- * @return Ext.Component
- */
- findById : function(id) {
- var m, ct = this;
- this.cascade(function(c) {
- if (ct != c && c.id === id) {
- m = c;
- return false;
- }
- });
- return m || null;
- },
- /**
- * Find a component under this container at any level by xtype or
- * class
- *
- * @param {String/Class}
- * xtype The xtype string for a component, or the class
- * of the component directly
- * @return {Array} Array of Ext.Components
- */
- findByType : function(xtype) {
- return typeof xtype == 'function' ? this.findBy(function(c) {
- return c.constructor === xtype;
- }) : this.findBy(function(c) {
- return c.constructor.xtype === xtype;
- });
- },
- /**
- * Find a component under this container at any level by property
- *
- * @param {String}
- * prop
- * @param {String}
- * value
- * @return {Array} Array of Ext.Components
- */
- find : function(prop, value) {
- return this.findBy(function(c) {
- return c[prop] === value;
- });
- },
- /**
- * Find a component under this container at any level by a custom
- * function. If the passed function returns true, the component will
- * be included in the results. The passed function is called with
- * the arguments (component, this container).
- *
- * @param {Function}
- * fcn
- * @param {Object}
- * scope (optional)
- * @return {Array} Array of Ext.Components
- */
- findBy : function(fn, scope) {
- var m = [], ct = this;
- this.cascade(function(c) {
- if (ct != c && fn.call(scope || c, c, ct) === true) {
- m.push(c);
- }
- });
- return m;
- }
- });
- Ext.Container.LAYOUTS = {};
- Ext.reg('container', Ext.Container);
|