X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/3789b528d8dd8aad4558e38e22d775bcab1cbd36..6746dc89c47ed01b165cc1152533605f97eb8e8d:/docs/source/Component2.html diff --git a/docs/source/Component2.html b/docs/source/Component2.html index 100a84a5..c1bb0df7 100644 --- a/docs/source/Component2.html +++ b/docs/source/Component2.html @@ -15,252 +15,1040 @@
-/** - * @class Ext.flash.Component - * @extends Ext.Component - * - * A simple Component for displaying an Adobe Flash SWF movie. The movie will be sized and can participate - * in layout like any other Component. - * - * This component requires the third-party SWFObject library version 2.2 or above. It is not included within - * the ExtJS distribution, so you will have to include it into your page manually in order to use this component. - * The SWFObject library can be downloaded from the [SWFObject project page](http://code.google.com/p/swfobject) - * and then simply import it into the head of your HTML document: - * - * <script type="text/javascript" src="path/to/local/swfobject.js"></script> - * - * ## Configuration - * - * This component allows several options for configuring how the target Flash movie is embedded. The most - * important is the required {@link #url} which points to the location of the Flash movie to load. Other - * configurations include: - * - * - {@link #backgroundColor} - * - {@link #wmode} - * - {@link #flashVars} - * - {@link #flashParams} - * - {@link #flashAttributes} - * - * ## Example usage: - * - * var win = Ext.widget('window', { - * title: "It's a tiger!", - * layout: 'fit', - * width: 300, - * height: 300, - * x: 20, - * y: 20, - * resizable: true, - * items: { - * xtype: 'flash', - * url: 'tiger.swf' - * } - * }); - * win.show(); - * - * ## Express Install - * - * Adobe provides a tool called [Express Install](http://www.adobe.com/devnet/flashplayer/articles/express_install.html) - * that offers users an easy way to upgrade their Flash player. If you wish to make use of this, you should set - * the static EXPRESS\_INSTALL\_URL property to the location of your Express Install SWF file: - * - * Ext.flash.Component.EXPRESS_INSTALL_URL = 'path/to/local/expressInstall.swf'; - * +/** + * @class Ext.Component + * @extends Ext.AbstractComponent + * <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 Container} class. + * Components may be added to a Container through the {@link Ext.container.Container#items items} config option at the time the Container is created, + * or they may be added dynamically via the {@link Ext.container.Container#add add} method.</p> + * <p>The Component base class has built-in support for basic hide/show and enable/disable and size control behavior.</p> + * <p>All Components are registered with the {@link Ext.ComponentManager} on construction so that they can be referenced at any time via + * {@link Ext#getCmp 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.</p> + * <p>See the <a href="http://sencha.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 +------------- ------------------ +button {@link Ext.button.Button} +buttongroup {@link Ext.container.ButtonGroup} +colorpalette {@link Ext.picker.Color} +component {@link Ext.Component} +container {@link Ext.container.Container} +cycle {@link Ext.button.Cycle} +dataview {@link Ext.view.View} +datepicker {@link Ext.picker.Date} +editor {@link Ext.Editor} +editorgrid {@link Ext.grid.plugin.Editing} +grid {@link Ext.grid.Panel} +multislider {@link Ext.slider.Multi} +panel {@link Ext.panel.Panel} +progress {@link Ext.ProgressBar} +slider {@link Ext.slider.Single} +spacer {@link Ext.toolbar.Spacer} +splitbutton {@link Ext.button.Split} +tabpanel {@link Ext.tab.Panel} +treepanel {@link Ext.tree.Panel} +viewport {@link Ext.container.Viewport} +window {@link Ext.window.Window} + +Toolbar components +--------------------------------------- +paging {@link Ext.toolbar.Paging} +toolbar {@link Ext.toolbar.Toolbar} +tbfill {@link Ext.toolbar.Fill} +tbitem {@link Ext.toolbar.Item} +tbseparator {@link Ext.toolbar.Separator} +tbspacer {@link Ext.toolbar.Spacer} +tbtext {@link Ext.toolbar.TextItem} + +Menu components +--------------------------------------- +menu {@link Ext.menu.Menu} +menucheckitem {@link Ext.menu.CheckItem} +menuitem {@link Ext.menu.Item} +menuseparator {@link Ext.menu.Separator} +menutextitem {@link Ext.menu.Item} + +Form components +--------------------------------------- +form {@link Ext.form.Panel} +checkbox {@link Ext.form.field.Checkbox} +combo {@link Ext.form.field.ComboBox} +datefield {@link Ext.form.field.Date} +displayfield {@link Ext.form.field.Display} +field {@link Ext.form.field.Base} +fieldset {@link Ext.form.FieldSet} +hidden {@link Ext.form.field.Hidden} +htmleditor {@link Ext.form.field.HtmlEditor} +label {@link Ext.form.Label} +numberfield {@link Ext.form.field.Number} +radio {@link Ext.form.field.Radio} +radiogroup {@link Ext.form.RadioGroup} +textarea {@link Ext.form.field.TextArea} +textfield {@link Ext.form.field.Text} +timefield {@link Ext.form.field.Time} +trigger {@link Ext.form.field.Trigger} + +Chart components +--------------------------------------- +chart {@link Ext.chart.Chart} +barchart {@link Ext.chart.series.Bar} +columnchart {@link Ext.chart.series.Column} +linechart {@link Ext.chart.series.Line} +piechart {@link Ext.chart.series.Pie} + +</pre><p> + * It should not usually be necessary to instantiate a Component because there are provided subclasses which implement specialized Component + * use cases which over most application needs. However it is possible to instantiate a base Component, and it will be renderable, + * or will particpate in layouts as the child item of a Container: +{@img Ext.Component/Ext.Component.png Ext.Component component} +<pre><code> + Ext.create('Ext.Component', { + html: 'Hello world!', + width: 300, + height: 200, + padding: 20, + style: { + color: '#FFFFFF', + backgroundColor:'#000000' + }, + renderTo: Ext.getBody() + }); +</code></pre> + *</p> + *<p>The Component above creates its encapsulating <code>div</code> upon render, and use the configured HTML as content. More complex + * internal structure may be created using the {@link #renderTpl} configuration, although to display database-derived mass + * data, it is recommended that an ExtJS data-backed Component such as a {@link Ext.view.View View}, or + * {@link Ext.grid.Panel GridPanel}, or {@link Ext.tree.Panel TreePanel} be used.</p> * @constructor - * Creates a new Ext.flash.Component instance. - * @param {Object} config The component configuration. - * - * @xtype flash - * @docauthor Jason Johnston <jason@sencha.com> + * Creates new Component. + * @param {Ext.core.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.define('Ext.flash.Component', { - extend: 'Ext.Component', - alternateClassName: 'Ext.FlashComponent', - alias: 'widget.flash', - - /** - * @cfg {String} flashVersion - * Indicates the version the flash content was published for. Defaults to <tt>'9.0.115'</tt>. + +Ext.define('Ext.Component', { + + /* Begin Definitions */ + + alias: ['widget.component', 'widget.box'], + + extend: 'Ext.AbstractComponent', + + requires: [ + 'Ext.util.DelayedTask' + ], + + uses: [ + 'Ext.Layer', + 'Ext.resizer.Resizer', + 'Ext.util.ComponentDragger' + ], + + mixins: { + floating: 'Ext.util.Floating' + }, + + statics: { + // Collapse/expand directions + DIRECTION_TOP: 'top', + DIRECTION_RIGHT: 'right', + DIRECTION_BOTTOM: 'bottom', + DIRECTION_LEFT: 'left', + + VERTICAL_DIRECTION: /^(?:top|bottom)$/ + }, + + /* End Definitions */ + + /** + * @cfg {Mixed} resizable + * <p>Specify as <code>true</code> to apply a {@link Ext.resizer.Resizer Resizer} to this Component + * after rendering.</p> + * <p>May also be specified as a config object to be passed to the constructor of {@link Ext.resizer.Resizer Resizer} + * to override any defaults. By default the Component passes its minimum and maximum size, and uses + * <code>{@link Ext.resizer.Resizer#dynamic}: false</code></p> + */ + + /** + * @cfg {String} resizeHandles + * A valid {@link Ext.resizer.Resizer} handles config string (defaults to 'all'). Only applies when resizable = true. */ - flashVersion : '9.0.115', + resizeHandles: 'all', - /** - * @cfg {String} backgroundColor - * The background color of the SWF movie. Defaults to <tt>'#ffffff'</tt>. + /** + * @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>). */ - backgroundColor: '#ffffff', - /** - * @cfg {String} wmode - * The wmode of the flash object. This can be used to control layering. Defaults to <tt>'opaque'</tt>. - * Set to 'transparent' to ignore the {@link #backgroundColor} and make the background of the Flash - * movie transparent. + /** + * @cfg {Boolean} floating + * <p>Specify as true to float the Component outside of the document flow using CSS absolute positioning.</p> + * <p>Components such as {@link Ext.window.Window Window}s and {@link Ext.menu.Menu Menu}s are floating + * by default.</p> + * <p>Floating Components that are programatically {@link Ext.Component#render rendered} will register themselves with the global + * {@link Ext.WindowManager ZIndexManager}</p> + * <h3 class="pa">Floating Components as child items of a Container</h3> + * <p>A floating Component may be used as a child item of a Container. This just allows the floating Component to seek a ZIndexManager by + * examining the ownerCt chain.</p> + * <p>When configured as floating, Components acquire, at render time, a {@link Ext.ZIndexManager ZIndexManager} which manages a stack + * of related floating Components. The ZIndexManager brings a single floating Component to the top of its stack when + * the Component's {@link #toFront} method is called.</p> + * <p>The ZIndexManager is found by traversing up the {@link #ownerCt} chain to find an ancestor which itself is floating. This is so that + * descendant floating Components of floating <i>Containers</i> (Such as a ComboBox dropdown within a Window) can have its zIndex managed relative + * to any siblings, but always <b>above</b> that floating ancestor Container.</p> + * <p>If no floating ancestor is found, a floating Component registers itself with the default {@link Ext.WindowManager ZIndexManager}.</p> + * <p>Floating components <i>do not participate in the Container's layout</i>. Because of this, they are not rendered until you explicitly + * {@link #show} them.</p> + * <p>After rendering, the ownerCt reference is deleted, and the {@link #floatParent} property is set to the found floating ancestor Container. + * If no floating ancestor Container was found the {@link #floatParent} property will not be set.</p> */ - wmode: 'opaque', + floating: false, - /** - * @cfg {Object} flashVars - * A set of key value pairs to be passed to the flash object as flash variables. Defaults to <tt>undefined</tt>. + /** + * @cfg {Boolean} toFrontOnShow + * <p>True to automatically call {@link #toFront} when the {@link #show} method is called + * on an already visible, floating component (default is <code>true</code>).</p> + */ + toFrontOnShow: true, + + /** + * <p>Optional. Only present for {@link #floating} Components after they have been rendered.</p> + * <p>A reference to the ZIndexManager which is managing this Component's z-index.</p> + * <p>The {@link Ext.ZIndexManager ZIndexManager} maintains a stack of floating Component z-indices, and also provides a single modal + * mask which is insert just beneath the topmost visible modal floating Component.</p> + * <p>Floating Components may be {@link #toFront brought to the front} or {@link #toBack sent to the back} of the z-index stack.</p> + * <p>This defaults to the global {@link Ext.WindowManager ZIndexManager} for floating Components that are programatically + * {@link Ext.Component#render rendered}.</p> + * <p>For {@link #floating} Components which are added to a Container, the ZIndexManager is acquired from the first ancestor Container found + * which is floating, or if not found the global {@link Ext.WindowManager ZIndexManager} is used.</p> + * <p>See {@link #floating} and {@link #floatParent}</p> + * @property zIndexManager + * @type Ext.ZIndexManager + */ + + /** + * <p>Optional. Only present for {@link #floating} Components which were inserted as descendant items of floating Containers.</p> + * <p>Floating Components that are programatically {@link Ext.Component#render rendered} will not have a <code>floatParent</code> property.</p> + * <p>For {@link #floating} Components which are child items of a Container, the floatParent will be the floating ancestor Container which is + * responsible for the base z-index value of all its floating descendants. It provides a {@link Ext.ZIndexManager ZIndexManager} which provides + * z-indexing services for all its descendant floating Components.</p> + * <p>For example, the dropdown {@link Ext.view.BoundList BoundList} of a ComboBox which is in a Window will have the Window as its + * <code>floatParent</code></p> + * <p>See {@link #floating} and {@link #zIndexManager}</p> + * @property floatParent + * @type Ext.Container + */ + + /** + * @cfg {Mixed} draggable + * <p>Specify as true to make a {@link #floating} Component draggable using the Component's encapsulating element as the drag handle.</p> + * <p>This may also be specified as a config object for the {@link Ext.util.ComponentDragger ComponentDragger} which is instantiated to perform dragging.</p> + * <p>For example to create a Component which may only be dragged around using a certain internal element as the drag handle, + * use the delegate option:</p> + * <code><pre> +new Ext.Component({ + constrain: true, + floating:true, + style: { + backgroundColor: '#fff', + border: '1px solid black' + }, + html: '<h1 style="cursor:move">The title</h1><p>The content</p>', + draggable: { + delegate: 'h1' + } +}).show(); +</pre></code> */ - /** - * @cfg {Object} flashParams - * A set of key value pairs to be passed to the flash object as parameters. Possible parameters can be found here: - * http://kb2.adobe.com/cps/127/tn_12701.html Defaults to <tt>undefined</tt>. + /** + * @cfg {Boolean} maintainFlex + * <p><b>Only valid when a sibling element of a {@link Ext.resizer.Splitter Splitter} within a {@link Ext.layout.container.VBox VBox} or + * {@link Ext.layout.container.HBox HBox} layout.</b></p> + * <p>Specifies that if an immediate sibling Splitter is moved, the Component on the <i>other</i> side is resized, and this + * Component maintains its configured {@link Ext.layout.container.Box#flex flex} value.</p> */ - /** - * @cfg {Object} flashAttributes - * A set of key value pairs to be passed to the flash object as attributes. Defaults to <tt>undefined</tt>. + hideMode: 'display', + // Deprecate 5.0 + hideParent: false, + + ariaRole: 'presentation', + + bubbleEvents: [], + + actionMode: 'el', + monPropRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/, + + //renderTpl: new Ext.XTemplate( + // '<div id="{id}" class="{baseCls} {cls} {cmpCls}<tpl if="typeof ui !== \'undefined\'"> {uiBase}-{ui}</tpl>"<tpl if="typeof style !== \'undefined\'"> style="{style}"</tpl>></div>', { + // compiled: true, + // disableFormats: true + // } + //), + constructor: function(config) { + config = config || {}; + if (config.initialConfig) { + + // Being initialized from an Ext.Action instance... + if (config.isAction) { + 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.callParent([config]); + + // If we were configured from an instance of Ext.Action, (or configured with a baseAction option), + // register this Component as one of its items + if (this.baseAction){ + this.baseAction.addComponent(this); + } + }, + + initComponent: function() { + var me = this; + + if (me.listeners) { + me.on(me.listeners); + delete me.listeners; + } + me.enableBubble(me.bubbleEvents); + me.mons = []; + }, + + // private + afterRender: function() { + var me = this, + resizable = me.resizable; + + if (me.floating) { + me.makeFloating(me.floating); + } else { + me.el.setVisibilityMode(Ext.core.Element[me.hideMode.toUpperCase()]); + } + + if (Ext.isDefined(me.autoScroll)) { + me.setAutoScroll(me.autoScroll); + } + me.callParent(); + + if (!(me.x && me.y) && (me.pageX || me.pageY)) { + me.setPagePosition(me.pageX, me.pageY); + } + + if (resizable) { + me.initResizable(resizable); + } + + if (me.draggable) { + me.initDraggable(); + } + + me.initAria(); + }, + + initAria: function() { + var actionEl = this.getActionEl(), + role = this.ariaRole; + if (role) { + actionEl.dom.setAttribute('role', role); + } + }, + + /** + * Sets the overflow on the content element of the component. + * @param {Boolean} scroll True to allow the Component to auto scroll. + * @return {Ext.Component} this */ + setAutoScroll : function(scroll){ + var me = this, + targetEl; + scroll = !!scroll; + if (me.rendered) { + targetEl = me.getTargetEl(); + targetEl.setStyle('overflow', scroll ? 'auto' : ''); + if (scroll && (Ext.isIE6 || Ext.isIE7)) { + // The scrollable container element must be non-statically positioned or IE6/7 will make + // positioned children stay in place rather than scrolling with the rest of the content + targetEl.position(); + } + } + me.autoScroll = scroll; + return me; + }, - /** - * @cfg {String} url - * The URL of the SWF file to include. Required. + // private + makeFloating : function(cfg){ + this.mixins.floating.constructor.call(this, cfg); + }, + + initResizable: function(resizable) { + resizable = Ext.apply({ + target: this, + dynamic: false, + constrainTo: this.constrainTo, + handles: this.resizeHandles + }, resizable); + resizable.target = this; + this.resizer = Ext.create('Ext.resizer.Resizer', resizable); + }, + + getDragEl: function() { + return this.el; + }, + + initDraggable: function() { + var me = this, + ddConfig = Ext.applyIf({ + el: this.getDragEl(), + constrainTo: me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.dom.parentNode) + }, this.draggable); + + // Add extra configs if Component is specified to be constrained + if (me.constrain || me.constrainDelegate) { + ddConfig.constrain = me.constrain; + ddConfig.constrainDelegate = me.constrainDelegate; + } + + this.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig); + }, + + /** + * 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 + * @param {Mixed} animate If true, the Component is <i>animated</i> into its new position. You may also pass an animation configuration. + * @return {Ext.Component} this */ + setPosition: function(x, y, animate) { + var me = this, + el = me.el, + to = {}, + adj, adjX, adjY, xIsNumber, yIsNumber; - /** - * @cfg {String/Number} swfWidth The width of the embedded SWF movie inside the component. Defaults to "100%" - * so that the movie matches the width of the component. + if (Ext.isArray(x)) { + animate = y; + y = x[1]; + x = x[0]; + } + me.x = x; + me.y = y; + + if (!me.rendered) { + return me; + } + + adj = me.adjustPosition(x, y); + adjX = adj.x; + adjY = adj.y; + xIsNumber = Ext.isNumber(adjX); + yIsNumber = Ext.isNumber(adjY); + + if (xIsNumber || yIsNumber) { + if (animate) { + if (xIsNumber) { + to.left = adjX; + } + if (yIsNumber) { + to.top = adjY; + } + + me.stopAnimation(); + me.animate(Ext.apply({ + duration: 1000, + listeners: { + afteranimate: Ext.Function.bind(me.afterSetPosition, me, [adjX, adjY]) + }, + to: to + }, animate)); + } + else { + if (!xIsNumber) { + el.setTop(adjY); + } + else if (!yIsNumber) { + el.setLeft(adjX); + } + else { + el.setLeftTop(adjX, adjY); + } + me.afterSetPosition(adjX, adjY); + } + } + return me; + }, + + /** + * @private Template method called after a Component has been positioned. */ - swfWidth: '100%', + afterSetPosition: function(ax, ay) { + this.onPosition(ax, ay); + this.fireEvent('move', this, ax, ay); + }, + + showAt: function(x, y, animate) { + // A floating Component is positioned relative to its ownerCt if any. + if (this.floating) { + this.setPosition(x, y, animate); + } else { + this.setPagePosition(x, y, animate); + } + this.show(); + }, - /** - * @cfg {String/Number} swfHeight The height of the embedded SWF movie inside the component. Defaults to "100%" - * so that the movie matches the height of the component. + /** + * 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 + * @param {Mixed} animate If passed, the Component is <i>animated</i> into its new position. If this parameter + * is a number, it is used as the animation duration in milliseconds. + * @return {Ext.Component} this */ - swfHeight: '100%', + setPagePosition: function(x, y, animate) { + var me = this, + p; - /** - * @cfg {Boolean} expressInstall - * True to prompt the user to install flash if not installed. Note that this uses - * Ext.FlashComponent.EXPRESS_INSTALL_URL, which should be set to the local resource. Defaults to <tt>false</tt>. + if (Ext.isArray(x)) { + y = x[1]; + x = x[0]; + } + me.pageX = x; + me.pageY = y; + if (me.floating && me.floatParent) { + // Floating Components being positioned in their ownerCt have to be made absolute + p = me.floatParent.getTargetEl().getViewRegion(); + if (Ext.isNumber(x) && Ext.isNumber(p.left)) { + x -= p.left; + } + if (Ext.isNumber(y) && Ext.isNumber(p.top)) { + y -= p.top; + } + me.setPosition(x, y, animate); + } + else { + p = me.el.translatePoints(x, y); + me.setPosition(p.left, p.top, animate); + } + return me; + }, + + /** + * 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} */ - expressInstall: false, + getBox : function(local){ + var pos = this.getPosition(local); + var s = this.getSize(); + s.x = pos[0]; + s.y = pos[1]; + return s; + }, - /** - * @property swf - * @type {Ext.core.Element} - * A reference to the object or embed element into which the SWF file is loaded. Only - * populated after the component is rendered and the SWF has been successfully embedded. + /** + * 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.Component} this */ + updateBox : function(box){ + this.setSize(box.width, box.height); + this.setPagePosition(box.x, box.y); + return this; + }, - // Have to create a placeholder div with the swfId, which SWFObject will replace with the object/embed element. - renderTpl: ['<div id="{swfId}"></div>'], + // Include margins + getOuterSize: function() { + var el = this.el; + return { + width: el.getWidth() + el.getMargin('lr'), + height: el.getHeight() + el.getMargin('tb') + }; + }, - initComponent: function() { - // <debug> - if (!('swfobject' in window)) { - Ext.Error.raise('The SWFObject library is not loaded. Ext.flash.Component requires SWFObject version 2.2 or later: http://code.google.com/p/swfobject/'); + // private + adjustSize: function(w, h) { + if (this.autoWidth) { + w = 'auto'; } - if (!this.url) { - Ext.Error.raise('The "url" config is required for Ext.flash.Component'); + + if (this.autoHeight) { + h = 'auto'; } - // </debug> + return { + width: w, + height: h + }; + }, + + // private + adjustPosition: function(x, y) { + + // Floating Components being positioned in their ownerCt have to be made absolute + if (this.floating && this.floatParent) { + var o = this.floatParent.getTargetEl().getViewRegion(); + x += o.left; + y += o.top; + } + + return { + x: x, + y: y + }; + }, + + /** + * 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.el, + xy; + + if (local === true) { + return [el.getLeft(true), el.getTop(true)]; + } + xy = this.xy || el.getXY(); + + // Floating Components in an ownerCt have to have their positions made relative + if (this.floating && this.floatParent) { + var o = this.floatParent.getTargetEl().getViewRegion(); + xy[0] -= o.left; + xy[1] -= o.top; + } + return xy; + }, + + // Todo: add in xtype prefix support + getId: function() { + return this.id || (this.id = (this.getXType() || 'ext-comp') + '-' + this.getAutoId()); + }, + + onEnable: function() { + var actionEl = this.getActionEl(); + actionEl.dom.removeAttribute('aria-disabled'); + actionEl.dom.disabled = false; this.callParent(); - this.addEvents( - /** - * @event success - * Fired when the Flash movie has been successfully embedded - * @param {Ext.flash.Component} this - */ - 'success', - - /** - * @event failure - * Fired when the Flash movie embedding fails - * @param {Ext.flash.Component} this - */ - 'failure' - ); - }, - - onRender: function() { - var me = this, - params, vars, undef, - swfId = me.getSwfId(); + }, + + onDisable: function() { + var actionEl = this.getActionEl(); + actionEl.dom.setAttribute('aria-disabled', true); + actionEl.dom.disabled = true; + this.callParent(); + }, + + /** + * <p>Shows this Component, rendering it first if {@link #autoRender} or {@link #floating} are <code>true</code>.</p> + * <p>After being shown, a {@link #floating} Component (such as a {@link Ext.window.Window}), is activated it and brought to the front of + * its {@link #zIndexManager z-index stack}.</p> + * @param {String/Element} animateTarget Optional, and <b>only valid for {@link #floating} Components such as + * {@link Ext.window.Window Window}s or {@link Ext.tip.ToolTip ToolTip}s, or regular Components which have been configured + * with <code>floating: true</code>.</b> The target from which the Component should + * animate from while opening (defaults to null with no animation) + * @param {Function} callback (optional) A callback function to call after the Component is displayed. Only necessary if animation was specified. + * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Component. + * @return {Component} this + */ + show: function(animateTarget, cb, scope) { + if (this.rendered && this.isVisible()) { + if (this.toFrontOnShow && this.floating) { + this.toFront(); + } + } else if (this.fireEvent('beforeshow', this) !== false) { + this.hidden = false; - me.renderData.swfId = swfId; + // Render on first show if there is an autoRender config, or if this is a floater (Window, Menu, BoundList etc). + if (!this.rendered && (this.autoRender || this.floating)) { + this.doAutoRender(); + } + if (this.rendered) { + this.beforeShow(); + this.onShow.apply(this, arguments); + + // Notify any owning Container unless it's suspended. + // Floating Components do not participate in layouts. + if (this.ownerCt && !this.floating && !(this.ownerCt.suspendLayout || this.ownerCt.layout.layoutBusy)) { + this.ownerCt.doLayout(); + } + this.afterShow.apply(this, arguments); + } + } + return this; + }, + + beforeShow: Ext.emptyFn, + + // Private. Override in subclasses where more complex behaviour is needed. + onShow: function() { + var me = this; + me.el.show(); + if (this.floating && this.constrain) { + this.doConstrain(); + } me.callParent(arguments); + }, + + afterShow: function(animateTarget, cb, scope) { + var me = this, + fromBox, + toBox, + ghostPanel; + + // Default to configured animate target if none passed + animateTarget = animateTarget || me.animateTarget; + + // Need to be able to ghost the Component + if (!me.ghost) { + animateTarget = null; + } + // If we're animating, kick of an animation of the ghost from the target to the *Element* current box + if (animateTarget) { + animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget); + toBox = me.el.getBox(); + fromBox = animateTarget.getBox(); + fromBox.width += 'px'; + fromBox.height += 'px'; + toBox.width += 'px'; + toBox.height += 'px'; + me.el.addCls(Ext.baseCSSPrefix + 'hide-offsets'); + ghostPanel = me.ghost(); + ghostPanel.el.stopAnimation(); + + ghostPanel.el.animate({ + from: fromBox, + to: toBox, + listeners: { + afteranimate: function() { + delete ghostPanel.componentLayout.lastComponentSize; + me.unghost(); + me.el.removeCls(Ext.baseCSSPrefix + 'hide-offsets'); + if (me.floating) { + me.toFront(); + } + Ext.callback(cb, scope || me); + } + } + }); + } + else { + if (me.floating) { + me.toFront(); + } + Ext.callback(cb, scope || me); + } + me.fireEvent('show', me); + }, + + /** + * Hides this Component, setting it to invisible using the configured {@link #hideMode}. + * @param {String/Element/Component} animateTarget Optional, and <b>only valid for {@link #floating} Components such as + * {@link Ext.window.Window Window}s or {@link Ext.tip.ToolTip ToolTip}s, or regular Components which have been configured + * with <code>floating: true</code>.</b>. + * The target to which the Component should animate while hiding (defaults to null with no animation) + * @param {Function} callback (optional) A callback function to call after the Component is hidden. + * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Component. + * @return {Ext.Component} this + */ + hide: function() { + + // Clear the flag which is set if a floatParent was hidden while this is visible. + // If a hide operation was subsequently called, that pending show must be hidden. + this.showOnParentShow = false; - params = Ext.apply({ - allowScriptAccess: 'always', - bgcolor: me.backgroundColor, - wmode: me.wmode - }, me.flashParams); - - vars = Ext.apply({ - allowedDomain: document.location.hostname - }, me.flashVars); - - new swfobject.embedSWF( - me.url, - swfId, - me.swfWidth, - me.swfHeight, - me.flashVersion, - me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undef, - vars, - params, - me.flashAttributes, - Ext.bind(me.swfCallback, me) - ); - }, - - /** + if (!(this.rendered && !this.isVisible()) && this.fireEvent('beforehide', this) !== false) { + this.hidden = true; + if (this.rendered) { + this.onHide.apply(this, arguments); + + // Notify any owning Container unless it's suspended. + // Floating Components do not participate in layouts. + if (this.ownerCt && !this.floating && !(this.ownerCt.suspendLayout || this.ownerCt.layout.layoutBusy)) { + this.ownerCt.doLayout(); + } + } + } + return this; + }, + + // Possibly animate down to a target element. + onHide: function(animateTarget, cb, scope) { + var me = this, + ghostPanel, + toBox; + + // Default to configured animate target if none passed + animateTarget = animateTarget || me.animateTarget; + + // Need to be able to ghost the Component + if (!me.ghost) { + animateTarget = null; + } + // If we're animating, kick off an animation of the ghost down to the target + if (animateTarget) { + animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget); + ghostPanel = me.ghost(); + ghostPanel.el.stopAnimation(); + toBox = animateTarget.getBox(); + toBox.width += 'px'; + toBox.height += 'px'; + ghostPanel.el.animate({ + to: toBox, + listeners: { + afteranimate: function() { + delete ghostPanel.componentLayout.lastComponentSize; + ghostPanel.el.hide(); + me.afterHide(cb, scope); + } + } + }); + } + me.el.hide(); + if (!animateTarget) { + me.afterHide(cb, scope); + } + }, + + afterHide: function(cb, scope) { + Ext.callback(cb, scope || this); + this.fireEvent('hide', this); + }, + + /** * @private - * The callback method for handling an embedding success or failure by SWFObject - * @param {Object} e The event object passed by SWFObject - see http://code.google.com/p/swfobject/wiki/api + * Template method to contribute functionality at destroy time. */ - swfCallback: function(e) { + onDestroy: function() { var me = this; - if (e.success) { - me.swf = Ext.get(e.ref); - me.onSuccess(); - me.fireEvent('success', me); - } else { - me.onFailure(); - me.fireEvent('failure', me); + + // Ensure that any ancillary components are destroyed. + if (me.rendered) { + Ext.destroy( + me.proxy, + me.resizer + ); + // Different from AbstractComponent + if (me.actionMode == 'container' || me.removeMode == 'container') { + me.container.remove(); + } + } + delete me.focusTask; + me.callParent(); + }, + + deleteMembers: function() { + var args = arguments, + len = args.length, + i = 0; + for (; i < len; ++i) { + delete this[args[i]]; } }, - /** - * Retrieve the id of the SWF object/embed element + /** + * 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 */ - getSwfId: function() { - return this.swfId || (this.swfId = "extswf" + this.getAutoId()); + focus: function(selectText, delay) { + var me = this, + focusEl; + + if (delay) { + if (!me.focusTask) { + me.focusTask = Ext.create('Ext.util.DelayedTask', me.focus); + } + me.focusTask.delay(Ext.isNumber(delay) ? delay : 10, null, me, [selectText, false]); + return me; + } + + if (me.rendered && !me.isDestroyed) { + // getFocusEl could return a Component. + focusEl = me.getFocusEl(); + focusEl.focus(); + if (focusEl.dom && selectText === true) { + focusEl.dom.select(); + } + + // Focusing a floating Component brings it to the front of its stack. + // this is performed by its zIndexManager. Pass preventFocus true to avoid recursion. + if (me.floating) { + me.toFront(true); + } + } + return me; }, - onSuccess: function() { - // swfobject forces visiblity:visible on the swf element, which prevents it - // from getting hidden when an ancestor is given visibility:hidden. - this.swf.setStyle('visibility', 'inherit'); + /** + * @private + * Returns the focus holder element associated with this Component. By default, this is the Component's encapsulating + * element. Subclasses which use embedded focusable elements (such as Window and Button) should override this for use + * by the {@link #focus} method. + * @returns {Ext.core.Element} the focus holing element. + */ + getFocusEl: function() { + return this.el; }, - onFailure: Ext.emptyFn, + // private + blur: function() { + if (this.rendered) { + this.getFocusEl().blur(); + } + return this; + }, - beforeDestroy: function() { - var me = this, - swf = me.swf; - if (swf) { - swfobject.removeSWF(me.getSwfId()); - Ext.destroy(swf); - delete me.swf; + getEl: function() { + return this.el; + }, + + // Deprecate 5.0 + getResizeEl: function() { + return this.el; + }, + + // Deprecate 5.0 + getPositionEl: function() { + return this.el; + }, + + // Deprecate 5.0 + getActionEl: function() { + return this.el; + }, + + // Deprecate 5.0 + getVisibilityEl: function() { + return this.el; + }, + + // Deprecate 5.0 + onResize: Ext.emptyFn, + + // private + getBubbleTarget: function() { + return this.ownerCt; + }, + + // private + getContentTarget: function() { + return this.el; + }, + + /** + * 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; + + var self = Ext.getClass(this); + + // prevent dup id + return new self(cfg); + }, + + /** + * Gets the xtype for this component as registered with {@link Ext.ComponentManager}. For a list of all + * available xtypes, see the {@link Ext.Component} header. Example usage: + * <pre><code> +var t = new Ext.form.field.Text(); +alert(t.getXType()); // alerts 'textfield' +</code></pre> + * @return {String} The xtype + */ + getXType: function() { + return this.self.xtype; + }, + + /** + * 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.Container} The first Container for which the custom function returns true + */ + findParentBy: function(fn) { + var p; + + // Iterate up the ownerCt chain until there's no ownerCt, or we find an ancestor which matches using the selector function. + for (p = this.ownerCt; p && !fn(p, this); p = p.ownerCt); + return p || null; + }, + + /** + * <p>Find a container above this component at any level by xtype or class</p> + * <p>See also the {@link Ext.Component#up up} method.</p> + * @param {String/Class} xtype The xtype string for a component, or the class of the component directly + * @return {Ext.container.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.up(xtype); + }, + + /** + * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of + * function call will be the scope provided or the current component. The arguments to the function + * will be the args provided or the current component. If the function returns false at any point, + * the bubble is stopped. + * @param {Function} fn The function to call + * @param {Object} scope (optional) The scope of the function (defaults to current node) + * @param {Array} args (optional) The args to call the function with (default to passing the current component) + * @return {Ext.Component} this + */ + bubble: function(fn, scope, args) { + var p = this; + while (p) { + if (fn.apply(scope || p, args || [p]) === false) { + break; + } + p = p.ownerCt; } - me.callParent(); + return this; }, - statics: { - /** - * Sets the url for installing flash if it doesn't exist. This should be set to a local resource. - * See http://www.adobe.com/devnet/flashplayer/articles/express_install.html for details. - * @static - * @type String - */ - EXPRESS_INSTALL_URL: 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf' + getProxy: function() { + if (!this.proxy) { + this.proxy = this.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', Ext.getBody(), true); + } + return this.proxy; } + });