cmp-foundation-debug.js
资源名称:ext-3.1.0.zip [点击查看]
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:446k
源码类别:
JavaScript
开发平台:
JavaScript
- /*! * Ext JS Library 3.1.0 * Copyright(c) 2006-2009 Ext JS, LLC * licensing@extjs.com * http://www.extjs.com/license */ /** * @class Ext.ComponentMgr * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass * thereof) on a page so that they can be easily accessed by {@link Ext.Component component} * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p> * <p>This object also provides a registry of available Component <i>classes</i> * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}. * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components * when creating a full, nested config object for a complete Ext page.</p> * <p>A child Component may be specified simply as a <i>config object</i> * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component * needs rendering, the correct type can be looked up for lazy instantiation.</p> * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p> * @singleton */ Ext.ComponentMgr = function(){ var all = new Ext.util.MixedCollection(); var types = {}; var ptypes = {}; return { /** * Registers a component. * @param {Ext.Component} c The component */ register : function(c){ all.add(c); }, /** * Unregisters a component. * @param {Ext.Component} c The component */ unregister : function(c){ all.remove(c); }, /** * Returns a component by {@link Ext.Component#id id}. * For additional details see {@link Ext.util.MixedCollection#get}. * @param {String} id The component {@link Ext.Component#id id} * @return Ext.Component The Component, <code>undefined</code> if not found, or <code>null</code> if a * Class was found. */ get : function(id){ return all.get(id); }, /** * Registers a function that will be called when a Component with the specified id is added to ComponentMgr. This will happen on instantiation. * @param {String} id The component {@link Ext.Component#id id} * @param {Function} fn The callback function * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the Component. */ onAvailable : function(id, fn, scope){ all.on("add", function(index, o){ if(o.id == id){ fn.call(scope || o, o); all.un("add", fn, scope); } }); }, /** * The MixedCollection used internally for the component cache. An example usage may be subscribing to * events on the MixedCollection to monitor addition or removal. Read-only. * @type {MixedCollection} */ all : all, /** * Checks if a Component type is registered. * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up * @return {Boolean} Whether the type is registered. */ isRegistered : function(xtype){ return types[xtype] !== undefined; }, /** * <p>Registers a new Component constructor, keyed by a new * {@link Ext.Component#xtype}.</p> * <p>Use this method (or its alias {@link Ext#reg Ext.reg}) to register new * subclasses of {@link Ext.Component} so that lazy instantiation may be used when specifying * child Components. * see {@link Ext.Container#items}</p> * @param {String} xtype The mnemonic string by which the Component class may be looked up. * @param {Constructor} cls The new Component class. */ registerType : function(xtype, cls){ types[xtype] = cls; cls.xtype = xtype; }, /** * Creates a new Component from the specified config object using the * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate. * @param {Object} config A configuration object for the Component you wish to create. * @param {Constructor} defaultType The constructor to provide the default Component type if * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>). * @return {Ext.Component} The newly instantiated Component. */ create : function(config, defaultType){ return config.render ? config : new types[config.xtype || defaultType](config); }, /** * <p>Registers a new Plugin constructor, keyed by a new * {@link Ext.Component#ptype}.</p> * <p>Use this method (or its alias {@link Ext#preg Ext.preg}) to register new * plugins for {@link Ext.Component}s so that lazy instantiation may be used when specifying * Plugins.</p> * @param {String} ptype The mnemonic string by which the Plugin class may be looked up. * @param {Constructor} cls The new Plugin class. */ registerPlugin : function(ptype, cls){ ptypes[ptype] = cls; cls.ptype = ptype; }, /** * Creates a new Plugin from the specified config object using the * config object's {@link Ext.component#ptype ptype} to determine the class to instantiate. * @param {Object} config A configuration object for the Plugin you wish to create. * @param {Constructor} defaultType The constructor to provide the default Plugin type if * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>). * @return {Ext.Component} The newly instantiated Plugin. */ createPlugin : function(config, defaultType){ var PluginCls = ptypes[config.ptype || defaultType]; if (PluginCls.init) { return PluginCls; } else { return new PluginCls(config); } } }; }(); /** * Shorthand for {@link Ext.ComponentMgr#registerType} * @param {String} xtype The {@link Ext.component#xtype mnemonic string} by which the Component class * may be looked up. * @param {Constructor} cls The new Component class. * @member Ext * @method reg */ Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down /** * Shorthand for {@link Ext.ComponentMgr#registerPlugin} * @param {String} ptype The {@link Ext.component#ptype mnemonic string} by which the Plugin class * may be looked up. * @param {Constructor} cls The new Plugin class. * @member Ext * @method preg */ Ext.preg = Ext.ComponentMgr.registerPlugin; /** * Shorthand for {@link Ext.ComponentMgr#create} * Creates a new Component from the specified config object using the * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate. * @param {Object} config A configuration object for the Component you wish to create. * @param {Constructor} defaultType The constructor to provide the default Component type if * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>). * @return {Ext.Component} The newly instantiated Component. * @member Ext * @method create */ Ext.create = Ext.ComponentMgr.create;/** * @class Ext.Component * @extends Ext.util.Observable * <p>Base class for all Ext components. All subclasses of Component may participate in the automated * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class. * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created, * or they may be added dynamically via the {@link Ext.Container#add add} method.</p> * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p> * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via * {@link Ext#getCmp}, passing the {@link #id}.</p> * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p> * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how * and to either extend or augment ExtJs base classes to create custom Components.</p> * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p> * <pre> xtype Class ------------- ------------------ box {@link Ext.BoxComponent} button {@link Ext.Button} buttongroup {@link Ext.ButtonGroup} colorpalette {@link Ext.ColorPalette} component {@link Ext.Component} container {@link Ext.Container} cycle {@link Ext.CycleButton} dataview {@link Ext.DataView} datepicker {@link Ext.DatePicker} editor {@link Ext.Editor} editorgrid {@link Ext.grid.EditorGridPanel} flash {@link Ext.FlashComponent} grid {@link Ext.grid.GridPanel} listview {@link Ext.ListView} panel {@link Ext.Panel} progress {@link Ext.ProgressBar} propertygrid {@link Ext.grid.PropertyGrid} slider {@link Ext.Slider} spacer {@link Ext.Spacer} splitbutton {@link Ext.SplitButton} tabpanel {@link Ext.TabPanel} treepanel {@link Ext.tree.TreePanel} viewport {@link Ext.ViewPort} window {@link Ext.Window} Toolbar components --------------------------------------- paging {@link Ext.PagingToolbar} toolbar {@link Ext.Toolbar} tbbutton {@link Ext.Toolbar.Button} (deprecated; use button) tbfill {@link Ext.Toolbar.Fill} tbitem {@link Ext.Toolbar.Item} tbseparator {@link Ext.Toolbar.Separator} tbspacer {@link Ext.Toolbar.Spacer} tbsplit {@link Ext.Toolbar.SplitButton} (deprecated; use splitbutton) tbtext {@link Ext.Toolbar.TextItem} Menu components --------------------------------------- menu {@link Ext.menu.Menu} colormenu {@link Ext.menu.ColorMenu} datemenu {@link Ext.menu.DateMenu} menubaseitem {@link Ext.menu.BaseItem} menucheckitem {@link Ext.menu.CheckItem} menuitem {@link Ext.menu.Item} menuseparator {@link Ext.menu.Separator} menutextitem {@link Ext.menu.TextItem} Form components --------------------------------------- form {@link Ext.form.FormPanel} checkbox {@link Ext.form.Checkbox} checkboxgroup {@link Ext.form.CheckboxGroup} combo {@link Ext.form.ComboBox} datefield {@link Ext.form.DateField} displayfield {@link Ext.form.DisplayField} field {@link Ext.form.Field} fieldset {@link Ext.form.FieldSet} hidden {@link Ext.form.Hidden} htmleditor {@link Ext.form.HtmlEditor} label {@link Ext.form.Label} numberfield {@link Ext.form.NumberField} radio {@link Ext.form.Radio} radiogroup {@link Ext.form.RadioGroup} textarea {@link Ext.form.TextArea} textfield {@link Ext.form.TextField} timefield {@link Ext.form.TimeField} trigger {@link Ext.form.TriggerField} Chart components --------------------------------------- chart {@link Ext.chart.Chart} barchart {@link Ext.chart.BarChart} cartesianchart {@link Ext.chart.CartesianChart} columnchart {@link Ext.chart.ColumnChart} linechart {@link Ext.chart.LineChart} piechart {@link Ext.chart.PieChart} Store xtypes --------------------------------------- arraystore {@link Ext.data.ArrayStore} directstore {@link Ext.data.DirectStore} groupingstore {@link Ext.data.GroupingStore} jsonstore {@link Ext.data.JsonStore} simplestore {@link Ext.data.SimpleStore} (deprecated; use arraystore) store {@link Ext.data.Store} xmlstore {@link Ext.data.XmlStore} </pre> * @constructor * @param {Ext.Element/String/Object} config The configuration options may be specified as either: * <div class="mdetail-params"><ul> * <li><b>an element</b> : * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li> * <li><b>a string</b> : * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li> * <li><b>anything else</b> : * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li> * </ul></div> */ Ext.Component = function(config){ config = config || {}; if(config.initialConfig){ if(config.isAction){ // actions this.baseAction = config; } config = config.initialConfig; // component cloning / action set up }else if(config.tagName || config.dom || Ext.isString(config)){ // element object config = {applyTo: config, id: config.id || config}; } /** * This Component's initial configuration specification. Read-only. * @type Object * @property initialConfig */ this.initialConfig = config; Ext.apply(this, config); this.addEvents( /** * @event added * Fires when a component is added to an Ext.Container * @param {Ext.Component} this * @param {Ext.Container} ownerCt Container which holds the component * @param {number} index Position at which the component was added */ 'added', /** * @event disable * Fires after the component is disabled. * @param {Ext.Component} this */ 'disable', /** * @event enable * Fires after the component is enabled. * @param {Ext.Component} this */ 'enable', /** * @event beforeshow * Fires before the component is shown by calling the {@link #show} method. * Return false from an event handler to stop the show. * @param {Ext.Component} this */ 'beforeshow', /** * @event show * Fires after the component is shown when calling the {@link #show} method. * @param {Ext.Component} this */ 'show', /** * @event beforehide * Fires before the component is hidden by calling the {@link #hide} method. * Return false from an event handler to stop the hide. * @param {Ext.Component} this */ 'beforehide', /** * @event hide * Fires after the component is hidden. * Fires after the component is hidden when calling the {@link #hide} method. * @param {Ext.Component} this */ 'hide', /** * @event removed * Fires when a component is removed from an Ext.Container * @param {Ext.Component} this * @param {Ext.Container} ownerCt Container which holds the component */ 'removed', /** * @event beforerender * Fires before the component is {@link #rendered}. Return false from an * event handler to stop the {@link #render}. * @param {Ext.Component} this */ 'beforerender', /** * @event render * Fires after the component markup is {@link #rendered}. * @param {Ext.Component} this */ 'render', /** * @event afterrender * <p>Fires after the component rendering is finished.</p> * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed * by any afterRender method defined for the Component, and, if {@link #stateful}, after state * has been restored.</p> * @param {Ext.Component} this */ 'afterrender', /** * @event beforedestroy * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}. * @param {Ext.Component} this */ 'beforedestroy', /** * @event destroy * Fires after the component is {@link #destroy}ed. * @param {Ext.Component} this */ 'destroy', /** * @event beforestaterestore * Fires before the state of the component is restored. Return false from an event handler to stop the restore. * @param {Ext.Component} this * @param {Object} state The hash of state values returned from the StateProvider. If this * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default, * that simply copies property values into this Component. The method maybe overriden to * provide custom state restoration. */ 'beforestaterestore', /** * @event staterestore * Fires after the state of the component is restored. * @param {Ext.Component} this * @param {Object} state The hash of state values returned from the StateProvider. This is passed * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this * Component. The method maybe overriden to provide custom state restoration. */ 'staterestore', /** * @event beforestatesave * Fires before the state of the component is saved to the configured state provider. Return false to stop the save. * @param {Ext.Component} this * @param {Object} state The hash of state values. This is determined by calling * <b><tt>getState()</tt></b> on the Component. This method must be provided by the * developer to return whetever representation of state is required, by default, Ext.Component * has a null implementation. */ 'beforestatesave', /** * @event statesave * Fires after the state of the component is saved to the configured state provider. * @param {Ext.Component} this * @param {Object} state The hash of state values. This is determined by calling * <b><tt>getState()</tt></b> on the Component. This method must be provided by the * developer to return whetever representation of state is required, by default, Ext.Component * has a null implementation. */ 'statesave' ); this.getId(); Ext.ComponentMgr.register(this); Ext.Component.superclass.constructor.call(this); if(this.baseAction){ this.baseAction.addComponent(this); } this.initComponent(); if(this.plugins){ if(Ext.isArray(this.plugins)){ for(var i = 0, len = this.plugins.length; i < len; i++){ this.plugins[i] = this.initPlugin(this.plugins[i]); } }else{ this.plugins = this.initPlugin(this.plugins); } } if(this.stateful !== false){ this.initState(); } if(this.applyTo){ this.applyToMarkup(this.applyTo); delete this.applyTo; }else if(this.renderTo){ this.render(this.renderTo); delete this.renderTo; } }; // private Ext.Component.AUTO_ID = 1000; Ext.extend(Ext.Component, Ext.util.Observable, { // Configs below are used for all Components when rendered by FormLayout. /** * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p> * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g. * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br> * <p>Also see <tt>{@link #hideLabel}</tt> and * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p> * Example use:<pre><code> new Ext.FormPanel({ height: 100, renderTo: Ext.getBody(), items: [{ xtype: 'textfield', fieldLabel: 'Name' }] }); </code></pre> */ /** * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's * label. Defaults to the container's labelStyle value if set (e.g., * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p> * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br> * <p>Also see <code>{@link #hideLabel}</code> and * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p> * Example use:<pre><code> new Ext.FormPanel({ height: 100, renderTo: Ext.getBody(), items: [{ xtype: 'textfield', fieldLabel: 'Name', labelStyle: 'font-weight:bold;' }] }); </code></pre> */ /** * @cfg {String} labelSeparator <p>The separator to display after the text of each * <tt>{@link #fieldLabel}</tt>. This property may be configured at various levels. * The order of precedence is: * <div class="mdetail-params"><ul> * <li>field / component level</li> * <li>container level</li> * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li> * </ul></div> * To display no separator for this field's label specify empty string ''.</p> * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br> * <p>Also see <tt>{@link #hideLabel}</tt> and * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p> * Example use:<pre><code> new Ext.FormPanel({ height: 100, renderTo: Ext.getBody(), layoutConfig: { labelSeparator: '~' // layout config has lowest priority (defaults to ':') }, {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>', // config at container level items: [{ xtype: 'textfield', fieldLabel: 'Field 1', labelSeparator: '...' // field/component level config supersedes others },{ xtype: 'textfield', fieldLabel: 'Field 2' // labelSeparator will be '=' }] }); </code></pre> */ /** * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>. * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be * reserved so that the field will line up with other fields that do have labels. * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p> * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br> * Example use:<pre><code> new Ext.FormPanel({ height: 100, renderTo: Ext.getBody(), items: [{ xtype: 'textfield' hideLabel: true }] }); </code></pre> */ /** * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered * directly after each form field wrapper to provide field clearing (defaults to * <tt>'x-form-clear-left'</tt>).</p> * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br> * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p> */ /** * @cfg {String} itemCls * <p><b>Note</b>: this config is only used when this Component is rendered by a Container which * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g. * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br> * <p>An additional CSS class to apply to the div wrapping the form item * element of this field. If supplied, <tt>itemCls</tt> at the <b>field</b> level will override * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p> * <p>Since it is applied to the item wrapper (see * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows * you to write standard CSS rules that can apply to the field, the label (if specified), or * any other element within the markup for the field.</p> * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br> * Example use:<pre><code> // Apply a style to the field's label: <style> .required .x-form-item-label {font-weight:bold;color:red;} </style> new Ext.FormPanel({ height: 100, renderTo: Ext.getBody(), items: [{ xtype: 'textfield', fieldLabel: 'Name', itemCls: 'required' //this label will be styled },{ xtype: 'textfield', fieldLabel: 'Favorite Color' }] }); </code></pre> */ // Configs below are used for all Components when rendered by AnchorLayout. /** * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b> * based layout manager, for example:<div class="mdetail-params"><ul> * <li>{@link Ext.form.FormPanel}</li> * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li> * </ul></div></p> * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p> */ /** * @cfg {String} id * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}). * You should assign an id if you need to be able to access the component later and you do * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p> * <p>Note that this id will also be used as the element id for the containing HTML element * that is rendered to the page for this component. This allows you to write id-based CSS * rules to style the specific instance of this component uniquely, and also to select * sub-elements using this component's id as the parent.</p> * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p> * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p> */ /** * @cfg {String} itemId * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component * when no object reference is available. Instead of using an <code>{@link #id}</code> with * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container -- * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b> * <code>{@link #id}</code>.</p> * <pre><code> var c = new Ext.Panel({ // {@link Ext.BoxComponent#height height}: 300, {@link #renderTo}: document.body, {@link Ext.Container#layout layout}: 'auto', {@link Ext.Container#items items}: [ { itemId: 'p1', {@link Ext.Panel#title title}: 'Panel 1', {@link Ext.BoxComponent#height height}: 150 }, { itemId: 'p2', {@link Ext.Panel#title title}: 'Panel 2', {@link Ext.BoxComponent#height height}: 150 } ] }) p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()} p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling * </code></pre> * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p> * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p> */ /** * @cfg {String} xtype * The registered <tt>xtype</tt> to create. This config option is not used when passing * a config object into a constructor. This config option is used only when * lazy instantiation is being used, and a child item of a Container is being * specified not as a fully instantiated Component, but as a <i>Component config * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what * type of child Component to create.<br><br> * The predefined xtypes are listed {@link Ext.Component here}. * <br><br> * If you subclass Components to create your own Components, you may register * them using {@link Ext.ComponentMgr#registerType} in order to be able to * take advantage of lazy instantiation and rendering. */ /** * @cfg {String} ptype * The registered <tt>ptype</tt> to create. This config option is not used when passing * a config object into a constructor. This config option is used only when * lazy instantiation is being used, and a Plugin is being * specified not as a fully instantiated Component, but as a <i>Component config * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what * type of Plugin to create.<br><br> * If you create your own Plugins, you may register them using * {@link Ext.ComponentMgr#registerPlugin} in order to be able to * take advantage of lazy instantiation and rendering. */ /** * @cfg {String} cls * An optional extra CSS class that will be added to this component's Element (defaults to ''). This can be * useful for adding customized styles to the component or any of its children using standard CSS rules. */ /** * @cfg {String} overCls * An optional extra CSS class that will be added to this component's Element when the mouse moves * over the Element, and removed when the mouse moves out. (defaults to ''). This can be * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules. */ /** * @cfg {String} style * A custom style specification to be applied to this component's Element. Should be a valid argument to * {@link Ext.Element#applyStyles}. * <pre><code> new Ext.Panel({ title: 'Some Title', renderTo: Ext.getBody(), width: 400, height: 300, layout: 'form', items: [{ xtype: 'textarea', style: { width: '95%', marginBottom: '10px' } }, new Ext.Button({ text: 'Send', minWidth: '100', style: { marginBottom: '10px' } }) ] }); * </code></pre> */ /** * @cfg {String} ctCls * <p>An optional extra CSS class that will be added to this component's container. This can be useful for * adding customized styles to the container or any of its children using standard CSS rules. See * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p> * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class * which assigns a value by default: * <div class="mdetail-params"><ul> * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li> * </ul></div> * To configure the above Class with an extra CSS class append to the default. For example, * for BoxLayout (Hbox and Vbox):<pre><code> * ctCls: 'x-box-layout-ct custom-class' * </code></pre> * </p> */ /** * @cfg {Boolean} disabled * Render this component disabled (default is false). */ disabled : false, /** * @cfg {Boolean} hidden * Render this component hidden (default is false). If <tt>true</tt>, the * {@link #hide} method will be called internally. */ hidden : false, /** * @cfg {Object/Array} plugins * An object or array of objects that will provide custom functionality for this component. The only * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component. * When a component is created, if any plugins are available, the component will call the init method on each * plugin, passing a reference to itself. Each plugin can then call methods or respond to events on the * component as needed to provide its functionality. */ /** * @cfg {Mixed} applyTo * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV * that is already present in the document that specifies some structural markup for this * component.</p><div><ul> * <li><b>Description</b> : <ul> * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified * by id or CSS class name within the main element, and the component being created may attempt * to create its subcomponents from that markup if applicable.</div> * </ul></li> * <li><b>Notes</b> : <ul> * <div class="sub-desc">When using this config, a call to render() is not required.</div> * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target * element's parent node will automatically be used as the component's container.</div> * </ul></li> * </ul></div> */ /** * @cfg {Mixed} renderTo * <p>Specify the id of the element, a DOM element or an existing Element that this component * will be rendered into.</p><div><ul> * <li><b>Notes</b> : <ul> * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of * a {@link Ext.Container Container}. It is the responsibility of the * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager} * to render and manage its child items.</div> * <div class="sub-desc">When using this config, a call to render() is not required.</div> * </ul></li> * </ul></div> * <p>See <tt>{@link #render}</tt> also.</p> */ /** * @cfg {Boolean} stateful * <p>A flag which causes the Component to attempt to restore the state of * internal properties from a saved state on startup. The component must have * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned * for state to be managed. Auto-generated ids are not guaranteed to be stable * across page loads and cannot be relied upon to save and restore the same * state for a component.<p> * <p>For state saving to work, the state manager's provider must have been * set to an implementation of {@link Ext.state.Provider} which overrides the * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get} * methods to save and recall name/value pairs. A built-in implementation, * {@link Ext.state.CookieProvider} is available.</p> * <p>To set the state provider for the current page:</p> * <pre><code> Ext.state.Manager.setProvider(new Ext.state.CookieProvider({ expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now })); * </code></pre> * <p>A stateful Component attempts to save state when one of the events * listed in the <code>{@link #stateEvents}</code> configuration fires.</p> * <p>To save state, a stateful Component first serializes its state by * calling <b><code>getState</code></b>. By default, this function does * nothing. The developer must provide an implementation which returns an * object hash which represents the Component's restorable state.</p> * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set} * which uses the configured {@link Ext.state.Provider} to save the object * keyed by the Component's <code>{@link stateId}</code>, or, if that is not * specified, its <code>{@link #id}</code>.</p> * <p>During construction, a stateful Component attempts to <i>restore</i> * its state by calling {@link Ext.state.Manager#get} passing the * <code>{@link #stateId}</code>, or, if that is not specified, the * <code>{@link #id}</code>.</p> * <p>The resulting object is passed to <b><code>applyState</code></b>. * The default implementation of <code>applyState</code> simply copies * properties into the object, but a developer may override this to support * more behaviour.</p> * <p>You can perform extra processing on state save and restore by attaching * handlers to the {@link #beforestaterestore}, {@link #staterestore}, * {@link #beforestatesave} and {@link #statesave} events.</p> */ /** * @cfg {String} stateId * The unique id for this component to use for state management purposes * (defaults to the component id if one was set, otherwise null if the * component is using a generated id). * <p>See <code>{@link #stateful}</code> for an explanation of saving and * restoring Component state.</p> */ /** * @cfg {Array} stateEvents * <p>An array of events that, when fired, should trigger this component to * save its state (defaults to none). <code>stateEvents</code> may be any type * of event supported by this component, including browser or custom events * (e.g., <tt>['click', 'customerchange']</tt>).</p> * <p>See <code>{@link #stateful}</code> for an explanation of saving and * restoring Component state.</p> */ /** * @cfg {Mixed} autoEl * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will * encapsulate this Component.</p> * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent}, * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex * DOM structure created by their own onRender methods.</p> * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by * different DOM elements. Example usage:</p><pre><code> { xtype: 'box', autoEl: { tag: 'img', src: 'http://www.example.com/example.jpg' } }, { xtype: 'box', autoEl: { tag: 'blockquote', html: 'autoEl is cool!' } }, { xtype: 'container', autoEl: 'ul', cls: 'ux-unordered-list', items: { xtype: 'box', autoEl: 'li', html: 'First list item' } } </code></pre> */ autoEl : 'div', /** * @cfg {String} disabledClass * CSS class added to the component when it is disabled (defaults to 'x-item-disabled'). */ disabledClass : 'x-item-disabled', /** * @cfg {Boolean} allowDomMove * Whether the component can move the Dom node when rendering (defaults to true). */ allowDomMove : true, /** * @cfg {Boolean} autoShow * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove * them on render (defaults to false). */ autoShow : false, /** * @cfg {String} hideMode * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt> * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt> * (css display).</p> * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred * since items are automatically laid out when they are first shown (no sizing * is done while hidden).</p> */ hideMode : 'display', /** * @cfg {Boolean} hideParent * True to hide and show the component's container when hide/show is called on the component, false to hide * and show the component itself (defaults to false). For example, this can be used as a shortcut for a hide * button on a window by setting hide:true on the button when adding it to its parent container. */ hideParent : false, /** * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p> * <p>This will <i>usually</i> be a <DIV> element created by the class's onRender method, but * that may be overridden using the <code>{@link #autoEl}</code> config.</p> * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br> * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners} * config for a suggestion, or use a render listener directly:</p><pre><code> new Ext.Panel({ title: 'The Clickable Panel', listeners: { render: function(p) { // Append the Panel to the click handler's argument list. p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true)); }, single: true // Remove the listener after first invocation } }); </code></pre> * <p>See also <tt>{@link #getEl getEl}</p> * @type Ext.Element * @property el */ /** * This Component's owner {@link Ext.Container Container} (defaults to undefined, and is set automatically when * this Component is added to a Container). Read-only. * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p> * @type Ext.Container * @property ownerCt */ /** * True if this component is hidden. Read-only. * @type Boolean * @property hidden */ /** * True if this component is disabled. Read-only. * @type Boolean * @property disabled */ /** * True if this component has been rendered. Read-only. * @type Boolean * @property rendered */ rendered : false, /** * @cfg {String} contentEl * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content * for this component.</p> * <ul> * <li><b>Description</b> : * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element * of a new component (it simply moves the specified DOM element <i>after the Component is rendered</i> to use as the content.</div></li> * <li><b>Notes</b> : * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured * {@link #html HTML} has been inserted</i>, and so the document will not contain this element at the time the {@link #render} event is fired.</div> * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code> * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div> * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to * prevent a brief flicker of the content before it is rendered to the panel.</div></li> * </ul> */ /** * @cfg {String/Object} html * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element * content (defaults to ''). The HTML content is added after the component is rendered, * so the document will not contain this HTML at the time the {@link #render} event is fired. * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended. */ /** * @cfg {Mixed} tpl * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold> * or an array of strings to form an Ext.XTemplate. * Used in conjunction with the <code>{@link #data}</code> and * <code>{@link #tplWriteMode}</code> configurations. */ /** * @cfg {String} tplWriteMode The Ext.(X)Template method to use when * updating the content area of the Component. Defaults to <tt>'overwrite'</tt> * (see <code>{@link Ext.XTemplate#overwrite}</code>). */ tplWriteMode : 'overwrite', /** * @cfg {Mixed} data * The initial set of data to apply to the <code>{@link #tpl}</code> to * update the content area of the Component. */ // private ctype : 'Ext.Component', // private actionMode : 'el', // private getActionEl : function(){ return this[this.actionMode]; }, initPlugin : function(p){ if(p.ptype && !Ext.isFunction(p.init)){ p = Ext.ComponentMgr.createPlugin(p); }else if(Ext.isString(p)){ p = Ext.ComponentMgr.createPlugin({ ptype: p }); } p.init(this); return p; }, /* // protected * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default). * <pre><code> // Traditional constructor: Ext.Foo = function(config){ // call superclass constructor: Ext.Foo.superclass.constructor.call(this, config); this.addEvents({ // add events }); }; Ext.extend(Ext.Foo, Ext.Bar, { // class body } // initComponent replaces the constructor: Ext.Foo = Ext.extend(Ext.Bar, { initComponent : function(){ // call superclass initComponent Ext.Container.superclass.initComponent.call(this); this.addEvents({ // add events }); } } </code></pre> */ initComponent : Ext.emptyFn, /** * <p>Render this Component into the passed HTML element.</p> * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then * do not use the render method.</b></p> * <p>A Container's child Components are rendered by that Container's * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p> * <p>Certain layout managers allow dynamic addition of child components. Those that do * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout}, * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p> * <p>If the Container is already rendered when a new child Component is added, you may need to call * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any * unrendered child Components to be rendered. This is required so that you can add multiple * child components if needed while only refreshing the layout once.</p> * <p>When creating complex UIs, it is important to remember that sizing and positioning * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager. * If you expect child items to be sized in response to user interactions, you must * configure the Container with a layout manager which creates and manages the type of layout you * have in mind.</p> * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic * layout manager is used which does nothing but render child components sequentially into the * Container. No sizing or positioning will be performed in this situation.</b></p> * @param {Element/HTMLElement/String} container (optional) The element this Component should be * rendered into. If it is being created from existing markup, this should be omitted. * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b> * which this component will be inserted (defaults to appending to the end of the container) */ render : function(container, position){ if(!this.rendered && this.fireEvent('beforerender', this) !== false){ if(!container && this.el){ this.el = Ext.get(this.el); container = this.el.dom.parentNode; this.allowDomMove = false; } this.container = Ext.get(container); if(this.ctCls){ this.container.addClass(this.ctCls); } this.rendered = true; if(position !== undefined){ if(Ext.isNumber(position)){ position = this.container.dom.childNodes[position]; }else{ position = Ext.getDom(position); } } this.onRender(this.container, position || null); if(this.autoShow){ this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]); } if(this.cls){ this.el.addClass(this.cls); delete this.cls; } if(this.style){ this.el.applyStyles(this.style); delete this.style; } if(this.overCls){ this.el.addClassOnOver(this.overCls); } this.fireEvent('render', this); // Populate content of the component with html, contentEl or // a tpl. var contentTarget = this.getContentTarget(); if (this.html){ contentTarget.update(Ext.DomHelper.markup(this.html)); delete this.html; } if (this.contentEl){ var ce = Ext.getDom(this.contentEl); Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']); contentTarget.appendChild(ce); } if (this.tpl) { if (!this.tpl.compile) { this.tpl = new Ext.XTemplate(this.tpl); } if (this.data) { this.tpl[this.tplWriteMode](contentTarget, this.data); delete this.data; } } this.afterRender(this.container); if(this.hidden){ // call this so we don't fire initial hide events. this.doHide(); } if(this.disabled){ // pass silent so the event doesn't fire the first time. this.disable(true); } if(this.stateful !== false){ this.initStateEvents(); } this.fireEvent('afterrender', this); } return this; }, /** * Update the content area of a component. * @param {Mixed} htmlOrData * If this component has been configured with a template via the tpl config * then it will use this argument as data to populate the template. * If this component was not configured with a template, the components * content area will be updated via Ext.Element update * @param {Boolean} loadScripts * (optional) Only legitimate when using the html configuration. Defaults to false * @param {Function} callback * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading */ update: function(htmlOrData, loadScripts, cb) { var contentTarget = this.getContentTarget(); if (this.tpl && typeof htmlOrData !== "string") { this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {}); } else { var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData; contentTarget.update(html, loadScripts, cb); } }, /** * @private * Method to manage awareness of when components are added to their * respective Container, firing an added event. * References are established at add time rather than at render time. * @param {Ext.Container} container Container which holds the component * @param {number} pos Position at which the component was added */ onAdded : function(container, pos) { this.ownerCt = container; this.initRef(); this.fireEvent('added', this, container, pos); }, /** * @private * Method to manage awareness of when components are removed from their * respective Container, firing an removed event. References are properly * cleaned up after removing a component from its owning container. */ onRemoved : function() { this.removeRef(); this.fireEvent('removed', this, this.ownerCt); delete this.ownerCt; }, /** * @private * Method to establish a reference to a component. */ initRef : function() { /** * @cfg {String} ref * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code> * specifying into which ancestor Container to place a named reference to this Component.</p> * <p>The ancestor axis can be traversed by using '/' characters in the path. * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code> var myGrid = new Ext.grid.EditorGridPanel({ title: 'My EditorGridPanel', store: myStore, colModel: myColModel, tbar: [{ text: 'Save', handler: saveChanges, disabled: true, ref: '../saveButton' }], listeners: { afteredit: function() { // The button reference is in the GridPanel myGrid.saveButton.enable(); } } }); </code></pre> * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code> * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code> * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p> * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p> */ if(this.ref && !this.refOwner){ var levels = this.ref.split('/'), last = levels.length, i = 0, t = this; while(t && i < last){ t = t.ownerCt; ++i; } if(t){ t[this.refName = levels[--i]] = this; /** * @type Ext.Container * @property refOwner * The ancestor Container into which the {@link #ref} reference was inserted if this Component * is a child of a Container, and has been configured with a <code>ref</code>. */ this.refOwner = t; } } }, removeRef : function() { if (this.refOwner && this.refName) { delete this.refOwner[this.refName]; delete this.refOwner; } }, // private initState : function(){ if(Ext.state.Manager){ var id = this.getStateId(); if(id){ var state = Ext.state.Manager.get(id); if(state){ if(this.fireEvent('beforestaterestore', this, state) !== false){ this.applyState(Ext.apply({}, state)); this.fireEvent('staterestore', this, state); } } } } }, // private getStateId : function(){ return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id); }, // private initStateEvents : function(){ if(this.stateEvents){ for(var i = 0, e; e = this.stateEvents[i]; i++){ this.on(e, this.saveState, this, {delay:100}); } } }, // private applyState : function(state){ if(state){ Ext.apply(this, state); } }, // private getState : function(){ return null; }, // private saveState : function(){ if(Ext.state.Manager && this.stateful !== false){ var id = this.getStateId(); if(id){ var state = this.getState(); if(this.fireEvent('beforestatesave', this, state) !== false){ Ext.state.Manager.set(id, state); this.fireEvent('statesave', this, state); } } } }, /** * Apply this component to existing markup that is valid. With this function, no call to render() is required. * @param {String/HTMLElement} el */ applyToMarkup : function(el){ this.allowDomMove = false; this.el = Ext.get(el); this.render(this.el.dom.parentNode); }, /** * Adds a CSS class to the component's underlying element. * @param {string} cls The CSS class name to add * @return {Ext.Component} this */ addClass : function(cls){ if(this.el){ this.el.addClass(cls); }else{ this.cls = this.cls ? this.cls + ' ' + cls : cls; } return this; }, /** * Removes a CSS class from the component's underlying element. * @param {string} cls The CSS class name to remove * @return {Ext.Component} this */ removeClass : function(cls){ if(this.el){ this.el.removeClass(cls); }else if(this.cls){ this.cls = this.cls.split(' ').remove(cls).join(' '); } return this; }, // private // default function is not really useful onRender : function(ct, position){ if(!this.el && this.autoEl){ if(Ext.isString(this.autoEl)){ this.el = document.createElement(this.autoEl); }else{ var div = document.createElement('div'); Ext.DomHelper.overwrite(div, this.autoEl); this.el = div.firstChild; } if (!this.el.id) { this.el.id = this.getId(); } } if(this.el){ this.el = Ext.get(this.el); if(this.allowDomMove !== false){ ct.dom.insertBefore(this.el.dom, position); if (div) { Ext.removeNode(div); div = null; } } } }, // private getAutoCreate : function(){ var cfg = Ext.isObject(this.autoCreate) ? this.autoCreate : Ext.apply({}, this.defaultAutoCreate); if(this.id && !cfg.id){ cfg.id = this.id; } return cfg; }, // private afterRender : Ext.emptyFn, /** * Destroys this component by purging any event listeners, removing the component's element from the DOM, * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from * {@link Ext.ComponentMgr}. Destruction is generally handled automatically by the framework and this method * should usually not need to be called directly. * */ destroy : function(){ if(!this.isDestroyed){ if(this.fireEvent('beforedestroy', this) !== false){ this.destroying = true; this.beforeDestroy(); if(this.ownerCt && this.ownerCt.remove){ this.ownerCt.remove(this, false); } if(this.rendered){ this.el.remove(); if(this.actionMode == 'container' || this.removeMode == 'container'){ this.container.remove(); } } this.onDestroy(); Ext.ComponentMgr.unregister(this); this.fireEvent('destroy', this); this.purgeListeners(); this.destroying = false; this.isDestroyed = true; } } }, deleteMembers : function(){ var args = arguments; for(var i = 0, len = args.length; i < len; ++i){ delete this[args[i]]; } }, // private beforeDestroy : Ext.emptyFn, // private onDestroy : Ext.emptyFn, /** * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p> * <p>This will <i>usually</i> be a <DIV> element created by the class's onRender method, but * that may be overridden using the {@link #autoEl} config.</p> * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br> * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners * for this Component's own Observable events), see the {@link #listeners} config for a suggestion, * or use a render listener directly:</p><pre><code> new Ext.Panel({ title: 'The Clickable Panel', listeners: { render: function(p) { // Append the Panel to the click handler's argument list. p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true)); }, single: true // Remove the listener after first invocation } }); </code></pre> * @return {Ext.Element} The Element which encapsulates this Component. */ getEl : function(){ return this.el; }, // private getContentTarget : function(){ return this.el; }, /** * Returns the <code>id</code> of this component or automatically generates and * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code> * 'ext-comp-' + (++Ext.Component.AUTO_ID) * </code></pre> * @return {String} id */ getId : function(){ return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID)); }, /** * Returns the <code>{@link #itemId}</code> of this component. If an * <code>{@link #itemId}</code> was not assigned through configuration the * <code>id</code> is returned using <code>{@link #getId}</code>. * @return {String} */ getItemId : function(){ return this.itemId || this.getId(); }, /** * Try to focus this component. * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds) * @return {Ext.Component} this */ focus : function(selectText, delay){ if(delay){ this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]); return; } if(this.rendered){ this.el.focus(); if(selectText === true){ this.el.dom.select(); } } return this; }, // private blur : function(){ if(this.rendered){ this.el.blur(); } return this; }, /** * Disable this component and fire the 'disable' event. * @return {Ext.Component} this */ disable : function(/* private */ silent){ if(this.rendered){ this.onDisable(); } this.disabled = true; if(silent !== true){ this.fireEvent('disable', this); } return this; }, // private onDisable : function(){ this.getActionEl().addClass(this.disabledClass); this.el.dom.disabled = true; }, /** * Enable this component and fire the 'enable' event. * @return {Ext.Component} this */ enable : function(){ if(this.rendered){ this.onEnable(); } this.disabled = false; this.fireEvent('enable', this); return this; }, // private onEnable : function(){ this.getActionEl().removeClass(this.disabledClass); this.el.dom.disabled = false; }, /** * Convenience function for setting disabled/enabled by boolean. * @param {Boolean} disabled * @return {Ext.Component} this */ setDisabled : function(disabled){ return this[disabled ? 'disable' : 'enable'](); }, /** * Show this component. Listen to the '{@link #beforeshow}' event and return * <tt>false</tt> to cancel showing the component. Fires the '{@link #show}' * event after showing the component. * @return {Ext.Component} this */ show : function(){ if(this.fireEvent('beforeshow', this) !== false){ this.hidden = false; if(this.autoRender){ this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender); } if(this.rendered){ this.onShow(); } this.fireEvent('show', this); } return this; }, // private onShow : function(){ this.getVisibilityEl().removeClass('x-hide-' + this.hideMode); }, /** * Hide this component. Listen to the '{@link #beforehide}' event and return * <tt>false</tt> to cancel hiding the component. Fires the '{@link #hide}' * event after hiding the component. Note this method is called internally if * the component is configured to be <code>{@link #hidden}</code>. * @return {Ext.Component} this */ hide : function(){ if(this.fireEvent('beforehide', this) !== false){ this.doHide(); this.fireEvent('hide', this); } return this; }, // private doHide: function(){ this.hidden = true; if(this.rendered){ this.onHide(); } }, // private onHide : function(){ this.getVisibilityEl().addClass('x-hide-' + this.hideMode); }, // private getVisibilityEl : function(){ return this.hideParent ? this.container : this.getActionEl(); }, /** * Convenience function to hide or show this component by boolean. * @param {Boolean} visible True to show, false to hide * @return {Ext.Component} this */ setVisible : function(visible){ return this[visible ? 'show' : 'hide'](); }, /** * Returns true if this component is visible. * @return {Boolean} True if this component is visible, false otherwise. */ isVisible : function(){ return this.rendered && this.getVisibilityEl().isVisible(); }, /** * Clone the current component using the original config values passed into this instance by default. * @param {Object} overrides A new config containing any properties to override in the cloned version. * An id property can be passed on this object, otherwise one will be generated to avoid duplicates. * @return {Ext.Component} clone The cloned copy of this component */ cloneConfig : function(overrides){ overrides = overrides || {}; var id = overrides.id || Ext.id(); var cfg = Ext.applyIf(overrides, this.initialConfig); cfg.id = id; // prevent dup id return new this.constructor(cfg); }, /** * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all * available xtypes, see the {@link Ext.Component} header. Example usage: * <pre><code> var t = new Ext.form.TextField(); alert(t.getXType()); // alerts 'textfield' </code></pre> * @return {String} The xtype */ getXType : function(){ return this.constructor.xtype; }, /** * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p> * <p><b>If using your own subclasses, be aware that a Component must register its own xtype * to participate in determination of inherited xtypes.</b></p> * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p> * <p>Example usage:</p> * <pre><code> var t = new Ext.form.TextField(); var isText = t.isXType('textfield'); // true var isBoxSubclass = t.isXType('box'); // true, descended from BoxComponent var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance </code></pre> * @param {String} xtype The xtype to check for this Component * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is * the default), or true to check whether this Component is directly of the specified xtype. * @return {Boolean} True if this component descends from the specified xtype, false otherwise. */ isXType : function(xtype, shallow){ //assume a string by default if (Ext.isFunction(xtype)){ xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component }else if (Ext.isObject(xtype)){ xtype = xtype.constructor.xtype; //handle being passed an instance } return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype; }, /** * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all * available xtypes, see the {@link Ext.Component} header.</p> * <p><b>If using your own subclasses, be aware that a Component must register its own xtype * to participate in determination of inherited xtypes.</b></p> * <p>Example usage:</p> * <pre><code> var t = new Ext.form.TextField(); alert(t.getXTypes()); // alerts 'component/box/field/textfield' </code></pre> * @return {String} The xtype hierarchy string */ getXTypes : function(){ var tc = this.constructor; if(!tc.xtypes){ var c = [], sc = this; while(sc && sc.constructor.xtype){ c.unshift(sc.constructor.xtype); sc = sc.constructor.superclass; } tc.xtypeChain = c; tc.xtypes = c.join('/'); } return tc.xtypes; }, /** * Find a container above this component at any level by a custom function. If the passed function returns * true, the container will be returned. * @param {Function} fn The custom function to call with the arguments (container, this component). * @return {Ext.Container} The first Container for which the custom function returns true */ findParentBy : function(fn) { for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt); return p || null; }, /** * Find a container above this component 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 {Ext.Container} The first Container which matches the given xtype or class */ findParentByType : function(xtype) { return Ext.isFunction(xtype) ? this.findParentBy(function(p){ return p.constructor === xtype; }) : this.findParentBy(function(p){ return p.constructor.xtype === xtype; }); }, // protected getPositionEl : function(){ return this.positionEl || this.el; }, // private purgeListeners : function(){ Ext.Component.superclass.purgeListeners.call(this); if(this.mons){ this.on('beforedestroy', this.clearMons, this, {single: true}); } }, // private clearMons : function(){ Ext.each(this.mons, function(m){ m.item.un(m.ename, m.fn, m.scope); }, this); this.mons = []; }, // private createMons: function(){ if(!this.mons){ this.mons = []; this.on('beforedestroy', this.clearMons, this, {single: true}); } }, /** * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component * is destroyed. Usage:</p><code><pre> myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50}); </pre></code> * <p>or:</p><code><pre> myGridPanel.mon(myGridPanel.getSelectionModel(), { selectionchange: handleSelectionChange, buffer: 50 }); </pre></code> * @param {Observable|Element} item The item to which to add a listener/listeners. * @param {Object|String} ename The event name, or an object containing event name properties. * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this * is the handler function. * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this * is the scope (<code>this</code> reference) in which the handler function is executed. * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this * is the {@link Ext.util.Observable#addListener addListener} options. */ mon : function(item, ename, fn, scope, opt){ this.createMons(); if(Ext.isObject(ename)){ var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/; var o = ename; for(var e in o){ if(propRe.test(e)){ continue; } if(Ext.isFunction(o[e])){ // shared options this.mons.push({ item: item, ename: e, fn: o[e], scope: o.scope }); item.on(e, o[e], o.scope, o); }else{ // individual options this.mons.push({ item: item, ename: e, fn: o[e], scope: o.scope }); item.on(e, o[e]); } } return; } this.mons.push({ item: item, ename: ename, fn: fn, scope: scope }); item.on(ename, fn, scope, opt); }, /** * Removes listeners that were added by the {@link #mon} method. * @param {Observable|Element} item The item from which to remove a listener/listeners. * @param {Object|String} ename The event name, or an object containing event name properties. * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this * is the handler function. * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this * is the scope (<code>this</code> reference) in which the handler function is executed. */ mun : function(item, ename, fn, scope){ var found, mon; this.createMons(); for(var i = 0, len = this.mons.length; i < len; ++i){ mon = this.mons[i]; if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){ this.mons.splice(i, 1); item.un(ename, fn, scope); found = true; break; } } return found; }, /** * Returns the next component in the owning container * @return Ext.Component */ nextSibling : function(){ if(this.ownerCt){ var index = this.ownerCt.items.indexOf(this); if(index != -1 && index+1 < this.ownerCt.items.getCount()){ return this.ownerCt.items.itemAt(index+1); } } return null; }, /** * Returns the previous component in the owning container * @return Ext.Component */ previousSibling : function(){ if(this.ownerCt){ var index = this.ownerCt.items.indexOf(this); if(index > 0){ return this.ownerCt.items.itemAt(index-1); } } return null; }, /** * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy. * @return {Ext.Container} the Container which owns this Component. */ getBubbleTarget : function(){ return this.ownerCt; } }); Ext.reg('component', Ext.Component);/**
- * @class Ext.Action
- * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it
- * can be usefully shared among multiple components. Actions let you share handlers, configuration options and UI
- * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}
- * and {@link Ext.menu.Menu} components).</p>
- * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support
- * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),
- * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>
- * Example usage:<br>
- * <pre><code>
- // Define the shared action. Each component below will have the same
- // display text and icon, and will display the same message on click.
- var action = new Ext.Action({
- {@link #text}: 'Do something',
- {@link #handler}: function(){
- Ext.Msg.alert('Click', 'You did something.');
- },
- {@link #iconCls}: 'do-something',
- {@link #itemId}: 'myAction'
- });
- var panel = new Ext.Panel({
- title: 'Actions',
- width: 500,
- height: 300,
- tbar: [
- // Add the action directly to a toolbar as a menu button
- action,
- {
- text: 'Action Menu',
- // Add the action to a menu as a text item
- menu: [action]
- }
- ],
- items: [
- // Add the action to the panel body as a standard button
- new Ext.Button(action)
- ],
- renderTo: Ext.getBody()
- });
- // Change the text for all components using the action
- action.setText('Something else');
- // Reference an action through a container using the itemId
- var btn = panel.getComponent('myAction');
- var aRef = btn.baseAction;
- aRef.setText('New text');
- </code></pre>
- * @constructor
- * @param {Object} config The configuration options
- */
- Ext.Action = Ext.extend(Object, {
- /**
- * @cfg {String} text The text to set for all components using this action (defaults to '').
- */
- /**
- * @cfg {String} iconCls
- * The CSS class selector that specifies a background image to be used as the header icon for
- * all components using this action (defaults to '').
- * <p>An example of specifying a custom icon class would be something like:
- * </p><pre><code>
- // specify the property in the config for the class:
- ...
- iconCls: 'do-something'
- // css class that specifies background image to be used as the icon image:
- .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
- </code></pre>
- */
- /**
- * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).
- */
- /**
- * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).
- */
- /**
- * @cfg {Function} handler The function that will be invoked by each component tied to this action
- * when the component's primary event is triggered (defaults to undefined).
- */
- /**
- * @cfg {String} itemId
- * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
- */
- /**
- * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the
- * <code>{@link #handler}</code> is executed. Defaults to this Button.
- */
- constructor : function(config){
- this.initialConfig = config;
- this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
- this.items = [];
- },
- // private
- isAction : true,
- /**
- * Sets the text to be displayed by all components using this action.
- * @param {String} text The text to display
- */
- setText : function(text){
- this.initialConfig.text = text;
- this.callEach('setText', [text]);
- },
- /**
- * Gets the text currently displayed by all components using this action.
- */
- getText : function(){
- return this.initialConfig.text;
- },
- /**
- * Sets the icon CSS class for all components using this action. The class should supply
- * a background image that will be used as the icon image.
- * @param {String} cls The CSS class supplying the icon image
- */
- setIconClass : function(cls){
- this.initialConfig.iconCls = cls;
- this.callEach('setIconClass', [cls]);
- },
- /**
- * Gets the icon CSS class currently used by all components using this action.
- */
- getIconClass : function(){
- return this.initialConfig.iconCls;
- },
- /**
- * Sets the disabled state of all components using this action. Shortcut method
- * for {@link #enable} and {@link #disable}.
- * @param {Boolean} disabled True to disable the component, false to enable it
- */
- setDisabled : function(v){
- this.initialConfig.disabled = v;
- this.callEach('setDisabled', [v]);
- },
- /**
- * Enables all components using this action.
- */
- enable : function(){
- this.setDisabled(false);
- },
- /**
- * Disables all components using this action.
- */
- disable : function(){
- this.setDisabled(true);
- },
- /**
- * Returns true if the components using this action are currently disabled, else returns false.
- */
- isDisabled : function(){
- return this.initialConfig.disabled;
- },
- /**
- * Sets the hidden state of all components using this action. Shortcut method
- * for <code>{@link #hide}</code> and <code>{@link #show}</code>.
- * @param {Boolean} hidden True to hide the component, false to show it
- */
- setHidden : function(v){
- this.initialConfig.hidden = v;
- this.callEach('setVisible', [!v]);
- },
- /**
- * Shows all components using this action.
- */
- show : function(){
- this.setHidden(false);
- },
- /**
- * Hides all components using this action.
- */
- hide : function(){
- this.setHidden(true);
- },
- /**
- * Returns true if the components using this action are currently hidden, else returns false.
- */
- isHidden : function(){
- return this.initialConfig.hidden;
- },
- /**
- * Sets the function that will be called by each Component using this action when its primary event is triggered.
- * @param {Function} fn The function that will be invoked by the action's components. The function
- * will be called with no arguments.
- * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.
- */
- setHandler : function(fn, scope){
- this.initialConfig.handler = fn;
- this.initialConfig.scope = scope;
- this.callEach('setHandler', [fn, scope]);
- },
- /**
- * Executes the specified function once for each Component currently tied to this action. The function passed
- * in should accept a single argument that will be an object that supports the basic Action config/method interface.
- * @param {Function} fn The function to execute for each component
- * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component.
- */
- each : function(fn, scope){
- Ext.each(this.items, fn, scope);
- },
- // private
- callEach : function(fnName, args){
- var cs = this.items;
- for(var i = 0, len = cs.length; i < len; i++){
- cs[i][fnName].apply(cs[i], args);
- }
- },
- // private
- addComponent : function(comp){
- this.items.push(comp);
- comp.on('destroy', this.removeComponent, this);
- },
- // private
- removeComponent : function(comp){
- this.items.remove(comp);
- },
- /**
- * Executes this action manually using the handler function specified in the original config object
- * or the handler function set with <code>{@link #setHandler}</code>. Any arguments passed to this
- * function will be passed on to the handler function.
- * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function
- * @param {Mixed} arg2 (optional)
- * @param {Mixed} etc... (optional)
- */
- execute : function(){
- this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
- }
- });
- /** * @class Ext.Layer * @extends Ext.Element * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and * automatic maintaining of shadow/shim positions. * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true) * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false) * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}). * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true) * @cfg {String} cls CSS class to add to the element * @cfg {Number} zindex Starting z-index (defaults to 11000) * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4) * @cfg {Boolean} useDisplay * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt> * to use css style <tt>'display:none;'</tt> to hide the Layer. * @constructor * @param {Object} config An object with config options. * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it. */ (function(){ Ext.Layer = function(config, existingEl){ config = config || {}; var dh = Ext.DomHelper; var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body; if(existingEl){ this.dom = Ext.getDom(existingEl); } if(!this.dom){ var o = config.dh || {tag: 'div', cls: 'x-layer'}; this.dom = dh.append(pel, o); } if(config.cls){ this.addClass(config.cls); } this.constrain = config.constrain !== false; this.setVisibilityMode(Ext.Element.VISIBILITY); if(config.id){ this.id = this.dom.id = config.id; }else{ this.id = Ext.id(this.dom); } this.zindex = config.zindex || this.getZIndex(); this.position('absolute', this.zindex); if(config.shadow){ this.shadowOffset = config.shadowOffset || 4; this.shadow = new Ext.Shadow({ offset : this.shadowOffset, mode : config.shadow }); }else{ this.shadowOffset = 0; } this.useShim = config.shim !== false && Ext.useShims; this.useDisplay = config.useDisplay; this.hide(); }; var supr = Ext.Element.prototype; // shims are shared among layer to keep from having 100 iframes var shims = []; Ext.extend(Ext.Layer, Ext.Element, { getZIndex : function(){ return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000; }, getShim : function(){ if(!this.useShim){ return null; } if(this.shim){ return this.shim; } var shim = shims.shift(); if(!shim){ shim = this.createShim(); shim.enableDisplayMode('block'); shim.dom.style.display = 'none'; shim.dom.style.visibility = 'visible'; } var pn = this.dom.parentNode; if(shim.dom.parentNode != pn){ pn.insertBefore(shim.dom, this.dom); } shim.setStyle('z-index', this.getZIndex()-2); this.shim = shim; return shim; }, hideShim : function(){ if(this.shim){ this.shim.setDisplayed(false); shims.push(this.shim); delete this.shim; } }, disableShadow : function(){ if(this.shadow){ this.shadowDisabled = true; this.shadow.hide(); this.lastShadowOffset = this.shadowOffset; this.shadowOffset = 0; } }, enableShadow : function(show){ if(this.shadow){ this.shadowDisabled = false; this.shadowOffset = this.lastShadowOffset; delete this.lastShadowOffset; if(show){ this.sync(true); } } }, // private // this code can execute repeatedly in milliseconds (i.e. during a drag) so // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls) sync : function(doShow){ var sw = this.shadow; if(!this.updating && this.isVisible() && (sw || this.useShim)){ var sh = this.getShim(); var w = this.getWidth(), h = this.getHeight(); var l = this.getLeft(true), t = this.getTop(true); if(sw && !this.shadowDisabled){ if(doShow && !sw.isVisible()){ sw.show(this); }else{ sw.realign(l, t, w, h); } if(sh){ if(doShow){ sh.show(); } // fit the shim behind the shadow, so it is shimmed too var a = sw.adjusts, s = sh.dom.style; s.left = (Math.min(l, l+a.l))+'px'; s.top = (Math.min(t, t+a.t))+'px'; s.width = (w+a.w)+'px'; s.height = (h+a.h)+'px'; } }else if(sh){ if(doShow){ sh.show(); } sh.setSize(w, h); sh.setLeftTop(l, t); } } }, // private destroy : function(){ this.hideShim(); if(this.shadow){ this.shadow.hide(); } this.removeAllListeners(); Ext.removeNode(this.dom); delete this.dom; }, remove : function(){ this.destroy(); }, // private beginUpdate : function(){ this.updating = true; }, // private endUpdate : function(){ this.updating = false; this.sync(true); }, // private hideUnders : function(negOffset){ if(this.shadow){ this.shadow.hide(); } this.hideShim(); }, // private constrainXY : function(){ if(this.constrain){ var vw = Ext.lib.Dom.getViewWidth(), vh = Ext.lib.Dom.getViewHeight(); var s = Ext.getDoc().getScroll(); var xy = this.getXY(); var x = xy[0], y = xy[1]; var so = this.shadowOffset; var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so; // only move it if it needs it var moved = false; // first validate right/bottom if((x + w) > vw+s.left){ x = vw - w - so; moved = true; } if((y + h) > vh+s.top){ y = vh - h - so; moved = true; } // then make sure top/left isn't negative if(x < s.left){ x = s.left; moved = true; } if(y < s.top){ y = s.top; moved = true; } if(moved){ if(this.avoidY){ var ay = this.avoidY; if(y <= ay && (y+h) >= ay){ y = ay-h-5; } } xy = [x, y]; this.storeXY(xy); supr.setXY.call(this, xy); this.sync(); } } return this; }, isVisible : function(){ return this.visible; }, // private showAction : function(){ this.visible = true; // track visibility to prevent getStyle calls if(this.useDisplay === true){ this.setDisplayed(''); }else if(this.lastXY){ supr.setXY.call(this, this.lastXY); }else if(this.lastLT){ supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]); } }, // private hideAction : function(){ this.visible = false; if(this.useDisplay === true){ this.setDisplayed(false); }else{ this.setLeftTop(-10000,-10000); } }, // overridden Element method setVisible : function(v, a, d, c, e){ if(v){ this.showAction(); } if(a && v){ var cb = function(){ this.sync(true); if(c){ c(); } }.createDelegate(this); supr.setVisible.call(this, true, true, d, cb, e); }else{ if(!v){ this.hideUnders(true); } var cb = c; if(a){ cb = function(){ this.hideAction(); if(c){ c(); } }.createDelegate(this); } supr.setVisible.call(this, v, a, d, cb, e); if(v){ this.sync(true); }else if(!a){ this.hideAction(); } } return this; }, storeXY : function(xy){ delete this.lastLT; this.lastXY = xy; }, storeLeftTop : function(left, top){ delete this.lastXY; this.lastLT = [left, top]; }, // private beforeFx : function(){ this.beforeAction(); return Ext.Layer.superclass.beforeFx.apply(this, arguments); }, // private afterFx : function(){ Ext.Layer.superclass.afterFx.apply(this, arguments); this.sync(this.isVisible()); }, // private beforeAction : function(){ if(!this.updating && this.shadow){ this.shadow.hide(); } }, // overridden Element method setLeft : function(left){ this.storeLeftTop(left, this.getTop(true)); supr.setLeft.apply(this, arguments); this.sync(); return this; }, setTop : function(top){ this.storeLeftTop(this.getLeft(true), top); supr.setTop.apply(this, arguments); this.sync(); return this; }, setLeftTop : function(left, top){ this.storeLeftTop(left, top); supr.setLeftTop.apply(this, arguments); this.sync(); return this; }, setXY : function(xy, a, d, c, e){ this.fixDisplay(); this.beforeAction(); this.storeXY(xy); var cb = this.createCB(c); supr.setXY.call(this, xy, a, d, cb, e); if(!a){ cb(); } return this; }, // private createCB : function(c){ var el = this; return function(){ el.constrainXY(); el.sync(true); if(c){ c(); } }; }, // overridden Element method setX : function(x, a, d, c, e){ this.setXY([x, this.getY()], a, d, c, e); return this; }, // overridden Element method setY : function(y, a, d, c, e){ this.setXY([this.getX(), y], a, d, c, e); return this; }, // overridden Element method setSize : function(w, h, a, d, c, e){ this.beforeAction(); var cb = this.createCB(c); supr.setSize.call(this, w, h, a, d, cb, e); if(!a){ cb(); } return this; }, // overridden Element method setWidth : function(w, a, d, c, e){ this.beforeAction(); var cb = this.createCB(c); supr.setWidth.call(this, w, a, d, cb, e); if(!a){ cb(); } return this; }, // overridden Element method setHeight : function(h, a, d, c, e){ this.beforeAction(); var cb = this.createCB(c); supr.setHeight.call(this, h, a, d, cb, e); if(!a){ cb(); } return this; }, // overridden Element method setBounds : function(x, y, w, h, a, d, c, e){ this.beforeAction(); var cb = this.createCB(c); if(!a){ this.storeXY([x, y]); supr.setXY.call(this, [x, y]); supr.setSize.call(this, w, h, a, d, cb, e); cb(); }else{ supr.setBounds.call(this, x, y, w, h, a, d, cb, e); } return this; }, /** * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index). * @param {Number} zindex The new z-index to set * @return {this} The Layer */ setZIndex : function(zindex){ this.zindex = zindex; this.setStyle('z-index', zindex + 2); if(this.shadow){ this.shadow.setZIndex(zindex + 1); } if(this.shim){ this.shim.setStyle('z-index', zindex); } return this; } }); })(); /** * @class Ext.Shadow * Simple class that can provide a shadow effect for any element. Note that the element MUST be absolutely positioned, * and the shadow does not provide any shimming. This should be used only in simple cases -- for more advanced * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class. * @constructor * Create a new Shadow * @param {Object} config The config object */ Ext.Shadow = function(config){ Ext.apply(this, config); if(typeof this.mode != "string"){ this.mode = this.defaultMode; } var o = this.offset, a = {h: 0}; var rad = Math.floor(this.offset/2); switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows case "drop": a.w = 0; a.l = a.t = o; a.t -= 1; if(Ext.isIE){ a.l -= this.offset + rad; a.t -= this.offset + rad; a.w -= rad; a.h -= rad; a.t += 1; } break; case "sides": a.w = (o*2); a.l = -o; a.t = o-1; if(Ext.isIE){ a.l -= (this.offset - rad); a.t -= this.offset + rad; a.l += 1; a.w -= (this.offset - rad)*2; a.w -= rad + 1; a.h -= 1; } break; case "frame": a.w = a.h = (o*2); a.l = a.t = -o; a.t += 1; a.h -= 2; if(Ext.isIE){ a.l -= (this.offset - rad); a.t -= (this.offset - rad); a.l += 1; a.w -= (this.offset + rad + 1); a.h -= (this.offset + rad); a.h += 1; } break; }; this.adjusts = a; }; Ext.Shadow.prototype = { /** * @cfg {String} mode * The shadow display mode. Supports the following options:<div class="mdetail-params"><ul> * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li> * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li> * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li> * </ul></div> */ /** * @cfg {String} offset * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>) */ offset: 4, // private defaultMode: "drop", /** * Displays the shadow under the target element * @param {Mixed} targetEl The id or element under which the shadow should display */ show : function(target){ target = Ext.get(target); if(!this.el){ this.el = Ext.Shadow.Pool.pull(); if(this.el.dom.nextSibling != target.dom){ this.el.insertBefore(target); } } this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1); if(Ext.isIE){ this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")"; } this.realign( target.getLeft(true), target.getTop(true), target.getWidth(), target.getHeight() ); this.el.dom.style.display = "block"; }, /** * Returns true if the shadow is visible, else false */ isVisible : function(){ return this.el ? true : false; }, /** * Direct alignment when values are already available. Show must be called at least once before * calling this method to ensure it is initialized. * @param {Number} left The target element left position * @param {Number} top The target element top position * @param {Number} width The target element width * @param {Number} height The target element height */ realign : function(l, t, w, h){ if(!this.el){ return; } var a = this.adjusts, d = this.el.dom, s = d.style; var iea = 0; s.left = (l+a.l)+"px"; s.top = (t+a.t)+"px"; var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px"; if(s.width != sws || s.height != shs){ s.width = sws; s.height = shs; if(!Ext.isIE){ var cn = d.childNodes; var sww = Math.max(0, (sw-12))+"px"; cn[0].childNodes[1].style.width = sww; cn[1].childNodes[1].style.width = sww; cn[2].childNodes[1].style.width = sww; cn[1].style.height = Math.max(0, (sh-12))+"px"; } } }, /** * Hides this shadow */ hide : function(){ if(this.el){ this.el.dom.style.display = "none"; Ext.Shadow.Pool.push(this.el); delete this.el; } }, /** * Adjust the z-index of this shadow * @param {Number} zindex The new z-index */ setZIndex : function(z){ this.zIndex = z; if(this.el){ this.el.setStyle("z-index", z); } } }; // Private utility class that manages the internal Shadow cache Ext.Shadow.Pool = function(){ var p = []; var markup = Ext.isIE ? '<div class="x-ie-shadow"></div>' : '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>'; return { pull : function(){ var sh = p.shift(); if(!sh){ sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup)); sh.autoBoxAdjust = false; } return sh; }, push : function(sh){ p.push(sh); } }; }();/** * @class Ext.BoxComponent * @extends Ext.Component * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p> * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly * within the Component rendering model.</p> * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing * element, or one that is created to your specifications at render time. Usually, to participate in layouts, * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p> * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the * element to reference:<pre><code> var pageHeader = new Ext.BoxComponent({ el: 'my-header-div' });</code></pre> * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p> * <p>To create a BoxComponent based around a HTML element to be created at render time, use the * {@link Ext.Component#autoEl autoEl} config option which takes the form of a * {@link Ext.DomHelper DomHelper} specification:<pre><code> var myImage = new Ext.BoxComponent({ autoEl: { tag: 'img', src: '/images/my-image.jpg' } });</code></pre></p> * @constructor * @param {Ext.Element/String/Object} config The configuration options. * @xtype box */ Ext.BoxComponent = Ext.extend(Ext.Component, { // tabTip config is used when a BoxComponent is a child of a TabPanel /** * @cfg {String} tabTip * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p> * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over * the associated tab selector element. {@link Ext.QuickTips}.init() * must be called in order for the tips to render. */ // Configs below are used for all Components when rendered by BorderLayout. /** * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b> * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br> * <p>See {@link Ext.layout.BorderLayout} also.</p> */ // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout. /** * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b> * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p> * <p>An object containing margins to apply to this BoxComponent in the * format:</p><pre><code> { top: (top margin), right: (right margin), bottom: (bottom margin), left: (left margin) }</code></pre> * <p>May also be a string containing space-separated, numeric margin values. The order of the * sides associated with each value matches the way CSS processes margin values:</p> * <p><div class="mdetail-params"><ul> * <li>If there is only one value, it applies to all sides.</li> * <li>If there are two values, the top and bottom borders are set to the first value and the * right and left are set to the second.</li> * <li>If there are three values, the top is set to the first value, the left and right are set * to the second, and the bottom is set to the third.</li> * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li> * </ul></div></p> * <p>Defaults to:</p><pre><code> * {top:0, right:0, bottom:0, left:0} * </code></pre> */ /** * @cfg {Number} x * The local x (left) coordinate for this component if contained within a positioning container. */ /** * @cfg {Number} y * The local y (top) coordinate for this component if contained within a positioning container. */ /** * @cfg {Number} pageX * The page level x coordinate for this component if contained within a positioning container. */ /** * @cfg {Number} pageY * The page level y coordinate for this component if contained within a positioning container. */ /** * @cfg {Number} height * The height of this component in pixels (defaults to auto). * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}. */ /** * @cfg {Number} width * The width of this component in pixels (defaults to auto). * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}. */ /** * @cfg {Number} boxMinHeight * <p>The minimum value in pixels which this BoxComponent will set its height to.</p> * <p><b>Warning:</b> This will override any size management applied by layout managers.</p> */ /** * @cfg {Number} boxMinWidth * <p>The minimum value in pixels which this BoxComponent will set its width to.</p> * <p><b>Warning:</b> This will override any size management applied by layout managers.</p> */ /** * @cfg {Number} boxMaxHeight * <p>The maximum value in pixels which this BoxComponent will set its height to.</p> * <p><b>Warning:</b> This will override any size management applied by layout managers.</p> */ /** * @cfg {Number} boxMaxWidth * <p>The maximum value in pixels which this BoxComponent will set its width to.</p> * <p><b>Warning:</b> This will override any size management applied by layout managers.</p> */ /** * @cfg {Boolean} autoHeight * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p> * <p><b>Note</b>: Although many components inherit this config option, not all will * function as expected with a height of 'auto'. Setting autoHeight:true means that the * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p> * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response * to changes within the structure of the Component cannot be detected. Therefore changes to the height might * result in elements needing to be synchronized with the new height. Example:</p><pre><code> var w = new Ext.Window({ title: 'Window', width: 600, autoHeight: true, items: { title: 'Collapse Me', height: 400, collapsible: true, border: false, listeners: { beforecollapse: function() { w.el.shadow.hide(); }, beforeexpand: function() { w.el.shadow.hide(); }, collapse: function() { w.syncShadow(); }, expand: function() { w.syncShadow(); } } } }).show(); </code></pre> */ /** * @cfg {Boolean} autoWidth * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p> * <p><b>Note</b>: Although many components inherit this config option, not all will * function as expected with a width of 'auto'. Setting autoWidth:true means that the * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p> * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response * to changes within the structure of the Component cannot be detected. Therefore changes to the width might * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code> <div id='grid-container' style='margin-left:25%;width:50%'></div> </code></pre> * A Panel rendered into that target element must listen for browser window resize in order to relay its * child items when the browser changes its width:<pre><code> var myPanel = new Ext.Panel({ renderTo: 'grid-container', monitorResize: true, // relay on browser resize title: 'Panel', height: 400, autoWidth: true, layout: 'hbox', layoutConfig: { align: 'stretch' }, defaults: { flex: 1 }, items: [{ title: 'Box 1', }, { title: 'Box 2' }, { title: 'Box 3' }], }); </code></pre> */ /** * @cfg {Boolean} autoScroll * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>). */ /* // private internal config * {Boolean} deferHeight * True to defer height calculations to an external component, false to allow this component to set its own * height (defaults to false). */ // private initComponent : function(){ Ext.BoxComponent.superclass.initComponent.call(this); this.addEvents( /** * @event resize * Fires after the component is resized. * @param {Ext.Component} this * @param {Number} adjWidth The box-adjusted width that was set * @param {Number} adjHeight The box-adjusted height that was set * @param {Number} rawWidth The width that was originally specified * @param {Number} rawHeight The height that was originally specified */ 'resize', /** * @event move * Fires after the component is moved. * @param {Ext.Component} this * @param {Number} x The new x position * @param {Number} y The new y position */ 'move' ); }, // private, set in afterRender to signify that the component has been rendered boxReady : false, // private, used to defer height settings to subclasses deferHeight: false, /** * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>. * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul> * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li> * <li>A String used to set the CSS width style.</li> * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li> * <li><code>undefined</code> to leave the width unchanged.</li> * </ul></div> * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg). * This may be one of:<div class="mdetail-params"><ul> * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li> * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li> * <li><code>undefined</code> to leave the height unchanged.</li> * </ul></div> * @return {Ext.BoxComponent} this */ setSize : function(w, h){ // support for standard size objects if(typeof w == 'object'){ h = w.height, w = w.width; } if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) { w = this.boxMinWidth; } if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) { h = this.boxMinHeight; } if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) { w = this.boxMaxWidth; } if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) { h = this.boxMaxHeight; } // not rendered if(!this.boxReady){ this.width = w, this.height = h; return this; } // prevent recalcs when not needed if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){ return this; } this.lastSize = {width: w, height: h}; var adj = this.adjustSize(w, h), aw = adj.width, ah = adj.height, rz; if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters rz = this.getResizeEl(); if(!this.deferHeight && aw !== undefined && ah !== undefined){ rz.setSize(aw, ah); }else if(!this.deferHeight && ah !== undefined){ rz.setHeight(ah); }else if(aw !== undefined){ rz.setWidth(aw); } this.onResize(aw, ah, w, h); } return this; }, /** * Sets the width of the component. This method fires the {@link #resize} event. * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul> * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li> * <li>A String used to set the CSS width style.</li> * </ul></div> * @return {Ext.BoxComponent} this */ setWidth : function(width){ return this.setSize(width); }, /** * Sets the height of the component. This method fires the {@link #resize} event. * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul> * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li> * <li>A String used to set the CSS height style.</li> * <li><i>undefined</i> to leave the height unchanged.</li> * </ul></div> * @return {Ext.BoxComponent} this */ setHeight : function(height){ return this.setSize(undefined, height); }, /** * Gets the current size of the component's underlying element. * @return {Object} An object containing the element's size {width: (element width), height: (element height)} */ getSize : function(){ return this.getResizeEl().getSize(); }, /** * Gets the current width of the component's underlying element. * @return {Number} */ getWidth : function(){ return this.getResizeEl().getWidth(); }, /** * Gets the current height of the component's underlying element. * @return {Number} */ getHeight : function(){ return this.getResizeEl().getHeight(); }, /** * Gets the current size of the component's underlying element, including space taken by its margins. * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)} */ getOuterSize : function(){ var el = this.getResizeEl(); return {width: el.getWidth() + el.getMargins('lr'), height: el.getHeight() + el.getMargins('tb')}; }, /** * Gets the current XY position of the component's underlying element. * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false) * @return {Array} The XY position of the element (e.g., [100, 200]) */ getPosition : function(local){ var el = this.getPositionEl(); if(local === true){ return [el.getLeft(true), el.getTop(true)]; } return this.xy || el.getXY(); }, /** * Gets the current box measurements of the component's underlying element. * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false) * @return {Object} box An object in the format {x, y, width, height} */ getBox : function(local){ var pos = this.getPosition(local); var s = this.getSize(); s.x = pos[0]; s.y = pos[1]; return s; }, /** * Sets the current box measurements of the component's underlying element. * @param {Object} box An object in the format {x, y, width, height} * @return {Ext.BoxComponent} this */ updateBox : function(box){ this.setSize(box.width, box.height); this.setPagePosition(box.x, box.y); return this; }, /** * <p>Returns the outermost Element of this Component which defines the Components overall size.</p> * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>, * but in some cases, a Component may have some more wrapping Elements around its main * active Element.</p> * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which * contains both the <code><input></code> Element (which is what would be returned * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element. * This Element is returned as the <code>resizeEl</code>. * @return {Ext.Element} The Element which is to be resized by size managing layouts. */ getResizeEl : function(){ return this.resizeEl || this.el; }, /** * Sets the overflow on the content element of the component. * @param {Boolean} scroll True to allow the Component to auto scroll. * @return {Ext.BoxComponent} this */ setAutoScroll : function(scroll){ if(this.rendered){ this.getContentTarget().setOverflow(scroll ? 'auto' : ''); } this.autoScroll = scroll; return this; }, /** * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}. * This method fires the {@link #move} event. * @param {Number} left The new left * @param {Number} top The new top * @return {Ext.BoxComponent} this */ setPosition : function(x, y){ if(x && typeof x[1] == 'number'){ y = x[1]; x = x[0]; } this.x = x; this.y = y; if(!this.boxReady){ return this; } var adj = this.adjustPosition(x, y); var ax = adj.x, ay = adj.y; var el = this.getPositionEl(); if(ax !== undefined || ay !== undefined){ if(ax !== undefined && ay !== undefined){ el.setLeftTop(ax, ay); }else if(ax !== undefined){ el.setLeft(ax); }else if(ay !== undefined){ el.setTop(ay); } this.onPosition(ax, ay); this.fireEvent('move', this, ax, ay); } return this; }, /** * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}. * This method fires the {@link #move} event. * @param {Number} x The new x position * @param {Number} y The new y position * @return {Ext.BoxComponent} this */ setPagePosition : function(x, y){ if(x && typeof x[1] == 'number'){ y = x[1]; x = x[0]; } this.pageX = x; this.pageY = y; if(!this.boxReady){ return; } if(x === undefined || y === undefined){ // cannot translate undefined points return; } var p = this.getPositionEl().translatePoints(x, y); this.setPosition(p.left, p.top); return this; }, // private afterRender : function(){ Ext.BoxComponent.superclass.afterRender.call(this); if(this.resizeEl){ this.resizeEl = Ext.get(this.resizeEl); } if(this.positionEl){ this.positionEl = Ext.get(this.positionEl); } this.boxReady = true; this.setAutoScroll(this.autoScroll); this.setSize(this.width, this.height); if(this.x || this.y){ this.setPosition(this.x, this.y); }else if(this.pageX || this.pageY){ this.setPagePosition(this.pageX, this.pageY); } }, /** * Force the component's size to recalculate based on the underlying element's current height and width. * @return {Ext.BoxComponent} this */ syncSize : function(){ delete this.lastSize; this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight()); return this; }, /* // protected * Called after the component is resized, this method is empty by default but can be implemented by any * subclass that needs to perform custom logic after a resize occurs. * @param {Number} adjWidth The box-adjusted width that was set * @param {Number} adjHeight The box-adjusted height that was set * @param {Number} rawWidth The width that was originally specified * @param {Number} rawHeight The height that was originally specified */ onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){ this.fireEvent('resize', this, adjWidth, adjHeight, rawWidth, rawHeight); }, /* // protected * Called after the component is moved, this method is empty by default but can be implemented by any * subclass that needs to perform custom logic after a move occurs. * @param {Number} x The new x position * @param {Number} y The new y position */ onPosition : function(x, y){ }, // private adjustSize : function(w, h){ if(this.autoWidth){ w = 'auto'; } if(this.autoHeight){ h = 'auto'; } return {width : w, height: h}; }, // private adjustPosition : function(x, y){ return {x : x, y: y}; } }); Ext.reg('box', Ext.BoxComponent); /** * @class Ext.Spacer * @extends Ext.BoxComponent * <p>Used to provide a sizable space in a layout.</p> * @constructor * @param {Object} config */ Ext.Spacer = Ext.extend(Ext.BoxComponent, { autoEl:'div' }); Ext.reg('spacer', Ext.Spacer);/**
- * @class Ext.SplitBar
- * @extends Ext.util.Observable
- * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
- * <br><br>
- * Usage:
- * <pre><code>
- var split = new Ext.SplitBar("elementToDrag", "elementToSize",
- Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
- split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
- split.minSize = 100;
- split.maxSize = 600;
- split.animate = true;
- split.on('moved', splitterMoved);
- </code></pre>
- * @constructor
- * Create a new SplitBar
- * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
- * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
- * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
- * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or
- Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
- position of the SplitBar).
- */
- Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
- /** @private */
- this.el = Ext.get(dragElement, true);
- this.el.dom.unselectable = "on";
- /** @private */
- this.resizingEl = Ext.get(resizingElement, true);
- /**
- * @private
- * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
- * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
- * @type Number
- */
- this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
- /**
- * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
- * @type Number
- * @property tickSize
- */
- /**
- * The minimum size of the resizing element. (Defaults to 0)
- * @type Number
- */
- this.minSize = 0;
- /**
- * The maximum size of the resizing element. (Defaults to 2000)
- * @type Number
- */
- this.maxSize = 2000;
- /**
- * Whether to animate the transition to the new size
- * @type Boolean
- */
- this.animate = false;
- /**
- * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
- * @type Boolean
- */
- this.useShim = false;
- /** @private */
- this.shim = null;
- if(!existingProxy){
- /** @private */
- this.proxy = Ext.SplitBar.createProxy(this.orientation);
- }else{
- this.proxy = Ext.get(existingProxy).dom;
- }
- /** @private */
- this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
- /** @private */
- this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
- /** @private */
- this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
- /** @private */
- this.dragSpecs = {};
- /**
- * @private The adapter to use to positon and resize elements
- */
- this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
- this.adapter.init(this);
- if(this.orientation == Ext.SplitBar.HORIZONTAL){
- /** @private */
- this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
- this.el.addClass("x-splitbar-h");
- }else{
- /** @private */
- this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
- this.el.addClass("x-splitbar-v");
- }
- this.addEvents(
- /**
- * @event resize
- * Fires when the splitter is moved (alias for {@link #moved})
- * @param {Ext.SplitBar} this
- * @param {Number} newSize the new width or height
- */
- "resize",
- /**
- * @event moved
- * Fires when the splitter is moved
- * @param {Ext.SplitBar} this
- * @param {Number} newSize the new width or height
- */
- "moved",
- /**
- * @event beforeresize
- * Fires before the splitter is dragged
- * @param {Ext.SplitBar} this
- */
- "beforeresize",
- "beforeapply"
- );
- Ext.SplitBar.superclass.constructor.call(this);
- };
- Ext.extend(Ext.SplitBar, Ext.util.Observable, {
- onStartProxyDrag : function(x, y){
- this.fireEvent("beforeresize", this);
- this.overlay = Ext.DomHelper.append(document.body, {cls: "x-drag-overlay", html: " "}, true);
- this.overlay.unselectable();
- this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
- this.overlay.show();
- Ext.get(this.proxy).setDisplayed("block");
- var size = this.adapter.getElementSize(this);
- this.activeMinSize = this.getMinimumSize();
- this.activeMaxSize = this.getMaximumSize();
- var c1 = size - this.activeMinSize;
- var c2 = Math.max(this.activeMaxSize - size, 0);
- if(this.orientation == Ext.SplitBar.HORIZONTAL){
- this.dd.resetConstraints();
- this.dd.setXConstraint(
- this.placement == Ext.SplitBar.LEFT ? c1 : c2,
- this.placement == Ext.SplitBar.LEFT ? c2 : c1,
- this.tickSize
- );
- this.dd.setYConstraint(0, 0);
- }else{
- this.dd.resetConstraints();
- this.dd.setXConstraint(0, 0);
- this.dd.setYConstraint(
- this.placement == Ext.SplitBar.TOP ? c1 : c2,
- this.placement == Ext.SplitBar.TOP ? c2 : c1,
- this.tickSize
- );
- }
- this.dragSpecs.startSize = size;
- this.dragSpecs.startPoint = [x, y];
- Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
- },
- /**
- * @private Called after the drag operation by the DDProxy
- */
- onEndProxyDrag : function(e){
- Ext.get(this.proxy).setDisplayed(false);
- var endPoint = Ext.lib.Event.getXY(e);
- if(this.overlay){
- Ext.destroy(this.overlay);
- delete this.overlay;
- }
- var newSize;
- if(this.orientation == Ext.SplitBar.HORIZONTAL){
- newSize = this.dragSpecs.startSize +
- (this.placement == Ext.SplitBar.LEFT ?
- endPoint[0] - this.dragSpecs.startPoint[0] :
- this.dragSpecs.startPoint[0] - endPoint[0]
- );
- }else{
- newSize = this.dragSpecs.startSize +
- (this.placement == Ext.SplitBar.TOP ?
- endPoint[1] - this.dragSpecs.startPoint[1] :
- this.dragSpecs.startPoint[1] - endPoint[1]
- );
- }
- newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
- if(newSize != this.dragSpecs.startSize){
- if(this.fireEvent('beforeapply', this, newSize) !== false){
- this.adapter.setElementSize(this, newSize);
- this.fireEvent("moved", this, newSize);
- this.fireEvent("resize", this, newSize);
- }
- }
- },
- /**
- * Get the adapter this SplitBar uses
- * @return The adapter object
- */
- getAdapter : function(){
- return this.adapter;
- },
- /**
- * Set the adapter this SplitBar uses
- * @param {Object} adapter A SplitBar adapter object
- */
- setAdapter : function(adapter){
- this.adapter = adapter;
- this.adapter.init(this);
- },
- /**
- * Gets the minimum size for the resizing element
- * @return {Number} The minimum size
- */
- getMinimumSize : function(){
- return this.minSize;
- },
- /**
- * Sets the minimum size for the resizing element
- * @param {Number} minSize The minimum size
- */
- setMinimumSize : function(minSize){
- this.minSize = minSize;
- },
- /**
- * Gets the maximum size for the resizing element
- * @return {Number} The maximum size
- */
- getMaximumSize : function(){
- return this.maxSize;
- },
- /**
- * Sets the maximum size for the resizing element
- * @param {Number} maxSize The maximum size
- */
- setMaximumSize : function(maxSize){
- this.maxSize = maxSize;
- },
- /**
- * Sets the initialize size for the resizing element
- * @param {Number} size The initial size
- */
- setCurrentSize : function(size){
- var oldAnimate = this.animate;
- this.animate = false;
- this.adapter.setElementSize(this, size);
- this.animate = oldAnimate;
- },
- /**
- * Destroy this splitbar.
- * @param {Boolean} removeEl True to remove the element
- */
- destroy : function(removeEl){
- Ext.destroy(this.shim, Ext.get(this.proxy));
- this.dd.unreg();
- if(removeEl){
- this.el.remove();
- }
- this.purgeListeners();
- }
- });
- /**
- * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
- */
- Ext.SplitBar.createProxy = function(dir){
- var proxy = new Ext.Element(document.createElement("div"));
- document.body.appendChild(proxy.dom);
- proxy.unselectable();
- var cls = 'x-splitbar-proxy';
- proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
- return proxy.dom;
- };
- /**
- * @class Ext.SplitBar.BasicLayoutAdapter
- * Default Adapter. It assumes the splitter and resizing element are not positioned
- * elements and only gets/sets the width of the element. Generally used for table based layouts.
- */
- Ext.SplitBar.BasicLayoutAdapter = function(){
- };
- Ext.SplitBar.BasicLayoutAdapter.prototype = {
- // do nothing for now
- init : function(s){
- },
- /**
- * Called before drag operations to get the current size of the resizing element.
- * @param {Ext.SplitBar} s The SplitBar using this adapter
- */
- getElementSize : function(s){
- if(s.orientation == Ext.SplitBar.HORIZONTAL){
- return s.resizingEl.getWidth();
- }else{
- return s.resizingEl.getHeight();
- }
- },
- /**
- * Called after drag operations to set the size of the resizing element.
- * @param {Ext.SplitBar} s The SplitBar using this adapter
- * @param {Number} newSize The new size to set