AbstractComponent.js 121 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460
  1. /**
  2. * An abstract base class which provides shared methods for Components across the Sencha product line.
  3. *
  4. * Please refer to sub class's documentation
  5. * @private
  6. */
  7. Ext.define('Ext.AbstractComponent', {
  8. /* Begin Definitions */
  9. requires: [
  10. 'Ext.ComponentQuery',
  11. 'Ext.ComponentManager',
  12. 'Ext.util.ProtoElement'
  13. ],
  14. mixins: {
  15. observable: 'Ext.util.Observable',
  16. animate: 'Ext.util.Animate',
  17. elementCt: 'Ext.util.ElementContainer',
  18. renderable: 'Ext.util.Renderable',
  19. state: 'Ext.state.Stateful'
  20. },
  21. // The "uses" property specifies class which are used in an instantiated AbstractComponent.
  22. // They do *not* have to be loaded before this class may be defined - that is what "requires" is for.
  23. uses: [
  24. 'Ext.PluginManager',
  25. 'Ext.Element',
  26. 'Ext.DomHelper',
  27. 'Ext.XTemplate',
  28. 'Ext.ComponentQuery',
  29. 'Ext.ComponentLoader',
  30. 'Ext.EventManager',
  31. 'Ext.layout.Context',
  32. 'Ext.layout.Layout',
  33. 'Ext.layout.component.Auto',
  34. 'Ext.LoadMask',
  35. 'Ext.ZIndexManager'
  36. ],
  37. statics: {
  38. AUTO_ID: 1000,
  39. pendingLayouts: null,
  40. layoutSuspendCount: 0,
  41. /**
  42. * Cancels layout of a component.
  43. * @param {Ext.Component} comp
  44. */
  45. cancelLayout: function(comp, isDestroying) {
  46. var context = this.runningLayoutContext || this.pendingLayouts;
  47. if (context) {
  48. context.cancelComponent(comp, false, isDestroying);
  49. }
  50. },
  51. /**
  52. * Performs all pending layouts that were sceduled while
  53. * {@link Ext.AbstractComponent#suspendLayouts suspendLayouts} was in effect.
  54. * @static
  55. */
  56. flushLayouts: function () {
  57. var me = this,
  58. context = me.pendingLayouts;
  59. if (context && context.invalidQueue.length) {
  60. me.pendingLayouts = null;
  61. me.runningLayoutContext = context;
  62. Ext.override(context, {
  63. runComplete: function () {
  64. // we need to release the layout queue before running any of the
  65. // finishedLayout calls because they call afterComponentLayout
  66. // which can re-enter by calling doLayout/doComponentLayout.
  67. me.runningLayoutContext = null;
  68. return this.callParent(); // not "me" here!
  69. }
  70. });
  71. context.run();
  72. }
  73. },
  74. /**
  75. * Resumes layout activity in the whole framework.
  76. *
  77. * {@link Ext#suspendLayouts} is alias of {@link Ext.AbstractComponent#suspendLayouts}.
  78. *
  79. * @param {Boolean} [flush=false] True to perform all the pending layouts. This can also be
  80. * achieved by calling {@link Ext.AbstractComponent#flushLayouts flushLayouts} directly.
  81. * @static
  82. */
  83. resumeLayouts: function (flush) {
  84. if (this.layoutSuspendCount && ! --this.layoutSuspendCount) {
  85. if (flush) {
  86. this.flushLayouts();
  87. }
  88. }
  89. },
  90. /**
  91. * Stops layouts from happening in the whole framework.
  92. *
  93. * It's useful to suspend the layout activity while updating multiple components and
  94. * containers:
  95. *
  96. * Ext.suspendLayouts();
  97. * // batch of updates...
  98. * Ext.resumeLayouts(true);
  99. *
  100. * {@link Ext#suspendLayouts} is alias of {@link Ext.AbstractComponent#suspendLayouts}.
  101. *
  102. * See also {@link Ext#batchLayouts} for more abstract way of doing this.
  103. *
  104. * @static
  105. */
  106. suspendLayouts: function () {
  107. ++this.layoutSuspendCount;
  108. },
  109. /**
  110. * Updates layout of a component.
  111. *
  112. * @param {Ext.Component} comp The component to update.
  113. * @param {Boolean} [defer=false] True to just queue the layout if this component.
  114. * @static
  115. */
  116. updateLayout: function (comp, defer) {
  117. var me = this,
  118. running = me.runningLayoutContext,
  119. pending;
  120. if (running) {
  121. running.queueInvalidate(comp);
  122. } else {
  123. pending = me.pendingLayouts || (me.pendingLayouts = new Ext.layout.Context());
  124. pending.queueInvalidate(comp);
  125. if (!defer && !me.layoutSuspendCount && !comp.isLayoutSuspended()) {
  126. me.flushLayouts();
  127. }
  128. }
  129. }
  130. },
  131. /* End Definitions */
  132. /**
  133. * @property {Boolean} isComponent
  134. * `true` in this class to identify an object as an instantiated Component, or subclass thereof.
  135. */
  136. isComponent: true,
  137. /**
  138. * @private
  139. */
  140. getAutoId: function() {
  141. this.autoGenId = true;
  142. return ++Ext.AbstractComponent.AUTO_ID;
  143. },
  144. deferLayouts: false,
  145. /**
  146. * @cfg {String} id
  147. * The **unique id of this component instance.**
  148. *
  149. * It should not be necessary to use this configuration except for singleton objects in your application. Components
  150. * created with an id may be accessed globally using {@link Ext#getCmp Ext.getCmp}.
  151. *
  152. * Instead of using assigned ids, use the {@link #itemId} config, and {@link Ext.ComponentQuery ComponentQuery}
  153. * which provides selector-based searching for Sencha Components analogous to DOM querying. The {@link
  154. * Ext.container.Container Container} class contains {@link Ext.container.Container#down shortcut methods} to query
  155. * its descendant Components by selector.
  156. *
  157. * Note that this id will also be used as the element id for the containing HTML element that is rendered to the
  158. * page for this component. This allows you to write id-based CSS rules to style the specific instance of this
  159. * component uniquely, and also to select sub-elements using this component's id as the parent.
  160. *
  161. * **Note**: to avoid complications imposed by a unique id also see `{@link #itemId}`.
  162. *
  163. * **Note**: to access the container of a Component see `{@link #ownerCt}`.
  164. *
  165. * Defaults to an {@link #getId auto-assigned id}.
  166. */
  167. /**
  168. * @property {Boolean} autoGenId
  169. * `true` indicates an id was auto-generated rather than provided by configuration.
  170. * @private
  171. */
  172. autoGenId: false,
  173. /**
  174. * @cfg {String} itemId
  175. * An itemId can be used as an alternative way to get a reference to a component when no object reference is
  176. * available. Instead of using an `{@link #id}` with {@link Ext}.{@link Ext#getCmp getCmp}, use `itemId` with
  177. * {@link Ext.container.Container}.{@link Ext.container.Container#getComponent getComponent} which will retrieve
  178. * `itemId`'s or {@link #id}'s. Since `itemId`'s are an index to the container's internal MixedCollection, the
  179. * `itemId` is scoped locally to the container -- avoiding potential conflicts with {@link Ext.ComponentManager}
  180. * which requires a **unique** `{@link #id}`.
  181. *
  182. * var c = new Ext.panel.Panel({ //
  183. * {@link Ext.Component#height height}: 300,
  184. * {@link #renderTo}: document.body,
  185. * {@link Ext.container.Container#layout layout}: 'auto',
  186. * {@link Ext.container.Container#cfg-items items}: [
  187. * {
  188. * itemId: 'p1',
  189. * {@link Ext.panel.Panel#title title}: 'Panel 1',
  190. * {@link Ext.Component#height height}: 150
  191. * },
  192. * {
  193. * itemId: 'p2',
  194. * {@link Ext.panel.Panel#title title}: 'Panel 2',
  195. * {@link Ext.Component#height height}: 150
  196. * }
  197. * ]
  198. * })
  199. * p1 = c.{@link Ext.container.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
  200. * p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponent}('p2'); // reference via a sibling
  201. *
  202. * Also see {@link #id}, `{@link Ext.container.Container#query}`, `{@link Ext.container.Container#down}` and
  203. * `{@link Ext.container.Container#child}`.
  204. *
  205. * **Note**: to access the container of an item see {@link #ownerCt}.
  206. */
  207. /**
  208. * @property {Ext.Container} ownerCt
  209. * This Component's owner {@link Ext.container.Container Container} (is set automatically
  210. * when this Component is added to a Container).
  211. *
  212. * **Note**: to access items within the Container see {@link #itemId}.
  213. * @readonly
  214. */
  215. /**
  216. * @cfg {String/Object} autoEl
  217. * A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
  218. * encapsulate this Component.
  219. *
  220. * You do not normally need to specify this. For the base classes {@link Ext.Component} and
  221. * {@link Ext.container.Container}, this defaults to **'div'**. The more complex Sencha classes use a more
  222. * complex DOM structure specified by their own {@link #renderTpl}s.
  223. *
  224. * This is intended to allow the developer to create application-specific utility Components encapsulated by
  225. * different DOM elements. Example usage:
  226. *
  227. * {
  228. * xtype: 'component',
  229. * autoEl: {
  230. * tag: 'img',
  231. * src: 'http://www.example.com/example.jpg'
  232. * }
  233. * }, {
  234. * xtype: 'component',
  235. * autoEl: {
  236. * tag: 'blockquote',
  237. * html: 'autoEl is cool!'
  238. * }
  239. * }, {
  240. * xtype: 'container',
  241. * autoEl: 'ul',
  242. * cls: 'ux-unordered-list',
  243. * items: {
  244. * xtype: 'component',
  245. * autoEl: 'li',
  246. * html: 'First list item'
  247. * }
  248. * }
  249. */
  250. /**
  251. * @cfg {Ext.XTemplate/String/String[]} renderTpl
  252. * An {@link Ext.XTemplate XTemplate} used to create the internal structure inside this Component's encapsulating
  253. * {@link #getEl Element}.
  254. *
  255. * You do not normally need to specify this. For the base classes {@link Ext.Component} and
  256. * {@link Ext.container.Container}, this defaults to **`null`** which means that they will be initially rendered
  257. * with no internal structure; they render their {@link #getEl Element} empty. The more specialized ExtJS and Touch
  258. * classes which use a more complex DOM structure, provide their own template definitions.
  259. *
  260. * This is intended to allow the developer to create application-specific utility Components with customized
  261. * internal structure.
  262. *
  263. * Upon rendering, any created child elements may be automatically imported into object properties using the
  264. * {@link #renderSelectors} and {@link #cfg-childEls} options.
  265. * @protected
  266. */
  267. renderTpl: '{%this.renderContent(out,values)%}',
  268. /**
  269. * @cfg {Object} renderData
  270. *
  271. * The data used by {@link #renderTpl} in addition to the following property values of the component:
  272. *
  273. * - id
  274. * - ui
  275. * - uiCls
  276. * - baseCls
  277. * - componentCls
  278. * - frame
  279. *
  280. * See {@link #renderSelectors} and {@link #cfg-childEls} for usage examples.
  281. */
  282. /**
  283. * @cfg {Object} renderSelectors
  284. * An object containing properties specifying {@link Ext.DomQuery DomQuery} selectors which identify child elements
  285. * created by the render process.
  286. *
  287. * After the Component's internal structure is rendered according to the {@link #renderTpl}, this object is iterated through,
  288. * and the found Elements are added as properties to the Component using the `renderSelector` property name.
  289. *
  290. * For example, a Component which renderes a title and description into its element:
  291. *
  292. * Ext.create('Ext.Component', {
  293. * renderTo: Ext.getBody(),
  294. * renderTpl: [
  295. * '<h1 class="title">{title}</h1>',
  296. * '<p>{desc}</p>'
  297. * ],
  298. * renderData: {
  299. * title: "Error",
  300. * desc: "Something went wrong"
  301. * },
  302. * renderSelectors: {
  303. * titleEl: 'h1.title',
  304. * descEl: 'p'
  305. * },
  306. * listeners: {
  307. * afterrender: function(cmp){
  308. * // After rendering the component will have a titleEl and descEl properties
  309. * cmp.titleEl.setStyle({color: "red"});
  310. * }
  311. * }
  312. * });
  313. *
  314. * For a faster, but less flexible, alternative that achieves the same end result (properties for child elements on the
  315. * Component after render), see {@link #cfg-childEls} and {@link #addChildEls}.
  316. */
  317. /**
  318. * @cfg {Object[]} childEls
  319. * An array describing the child elements of the Component. Each member of the array
  320. * is an object with these properties:
  321. *
  322. * - `name` - The property name on the Component for the child element.
  323. * - `itemId` - The id to combine with the Component's id that is the id of the child element.
  324. * - `id` - The id of the child element.
  325. *
  326. * If the array member is a string, it is equivalent to `{ name: m, itemId: m }`.
  327. *
  328. * For example, a Component which renders a title and body text:
  329. *
  330. * Ext.create('Ext.Component', {
  331. * renderTo: Ext.getBody(),
  332. * renderTpl: [
  333. * '<h1 id="{id}-title">{title}</h1>',
  334. * '<p>{msg}</p>',
  335. * ],
  336. * renderData: {
  337. * title: "Error",
  338. * msg: "Something went wrong"
  339. * },
  340. * childEls: ["title"],
  341. * listeners: {
  342. * afterrender: function(cmp){
  343. * // After rendering the component will have a title property
  344. * cmp.title.setStyle({color: "red"});
  345. * }
  346. * }
  347. * });
  348. *
  349. * A more flexible, but somewhat slower, approach is {@link #renderSelectors}.
  350. */
  351. /**
  352. * @cfg {String/HTMLElement/Ext.Element} renderTo
  353. * Specify the id of the element, a DOM element or an existing Element that this component will be rendered into.
  354. *
  355. * **Notes:**
  356. *
  357. * Do *not* use this option if the Component is to be a child item of a {@link Ext.container.Container Container}.
  358. * It is the responsibility of the {@link Ext.container.Container Container}'s
  359. * {@link Ext.container.Container#layout layout manager} to render and manage its child items.
  360. *
  361. * When using this config, a call to render() is not required.
  362. *
  363. * See also: {@link #method-render}.
  364. */
  365. /**
  366. * @cfg {Boolean} frame
  367. * Specify as `true` to have the Component inject framing elements within the Component at render time to provide a
  368. * graphical rounded frame around the Component content.
  369. *
  370. * This is only necessary when running on outdated, or non standard-compliant browsers such as Microsoft's Internet
  371. * Explorer prior to version 9 which do not support rounded corners natively.
  372. *
  373. * The extra space taken up by this framing is available from the read only property {@link #frameSize}.
  374. */
  375. /**
  376. * @property {Object} frameSize
  377. * @readonly
  378. * Indicates the width of any framing elements which were added within the encapsulating element
  379. * to provide graphical, rounded borders. See the {@link #frame} config.
  380. *
  381. * This is an object containing the frame width in pixels for all four sides of the Component containing the
  382. * following properties:
  383. *
  384. * @property {Number} [frameSize.top=0] The width of the top framing element in pixels.
  385. * @property {Number} [frameSize.right=0] The width of the right framing element in pixels.
  386. * @property {Number} [frameSize.bottom=0] The width of the bottom framing element in pixels.
  387. * @property {Number} [frameSize.left=0] The width of the left framing element in pixels.
  388. * @property {Number} [frameSize.width=0] The total width of the left and right framing elements in pixels.
  389. * @property {Number} [frameSize.height=0] The total height of the top and right bottom elements in pixels.
  390. */
  391. frameSize: { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0 },
  392. /**
  393. * @cfg {String/Object} componentLayout
  394. * The sizing and positioning of a Component's internal Elements is the responsibility of the Component's layout
  395. * manager which sizes a Component's internal structure in response to the Component being sized.
  396. *
  397. * Generally, developers will not use this configuration as all provided Components which need their internal
  398. * elements sizing (Such as {@link Ext.form.field.Base input fields}) come with their own componentLayout managers.
  399. *
  400. * The {@link Ext.layout.container.Auto default layout manager} will be used on instances of the base Ext.Component
  401. * class which simply sizes the Component's encapsulating element to the height and width specified in the
  402. * {@link #setSize} method.
  403. */
  404. /**
  405. * @cfg {Ext.XTemplate/Ext.Template/String/String[]} tpl
  406. * An {@link Ext.Template}, {@link Ext.XTemplate} or an array of strings to form an Ext.XTemplate. Used in
  407. * conjunction with the `{@link #data}` and `{@link #tplWriteMode}` configurations.
  408. */
  409. /**
  410. * @cfg {Object} data
  411. * The initial set of data to apply to the `{@link #tpl}` to update the content area of the Component.
  412. */
  413. /**
  414. * @cfg {String} xtype
  415. * This property provides a shorter alternative to creating objects than using a full
  416. * class name. Using `xtype` is the most common way to define component instances,
  417. * especially in a container. For example, the items in a form containing text fields
  418. * could be created explicitly like so:
  419. *
  420. * items: [
  421. * Ext.create('Ext.form.field.Text', {
  422. * fieldLabel: 'Foo'
  423. * }),
  424. * Ext.create('Ext.form.field.Text', {
  425. * fieldLabel: 'Bar'
  426. * }),
  427. * Ext.create('Ext.form.field.Number', {
  428. * fieldLabel: 'Num'
  429. * })
  430. * ]
  431. *
  432. * But by using `xtype`, the above becomes:
  433. *
  434. * items: [
  435. * {
  436. * xtype: 'textfield',
  437. * fieldLabel: 'Foo'
  438. * },
  439. * {
  440. * xtype: 'textfield',
  441. * fieldLabel: 'Bar'
  442. * },
  443. * {
  444. * xtype: 'numberfield',
  445. * fieldLabel: 'Num'
  446. * }
  447. * ]
  448. *
  449. * When the `xtype` is common to many items, {@link Ext.container.AbstractContainer#defaultType}
  450. * is another way to specify the `xtype` for all items that don't have an explicit `xtype`:
  451. *
  452. * defaultType: 'textfield',
  453. * items: [
  454. * { fieldLabel: 'Foo' },
  455. * { fieldLabel: 'Bar' },
  456. * { fieldLabel: 'Num', xtype: 'numberfield' }
  457. * ]
  458. *
  459. * Each member of the `items` array is now just a "configuration object". These objects
  460. * are used to create and configure component instances. A configuration object can be
  461. * manually used to instantiate a component using {@link Ext#widget}:
  462. *
  463. * var text1 = Ext.create('Ext.form.field.Text', {
  464. * fieldLabel: 'Foo'
  465. * });
  466. *
  467. * // or alternatively:
  468. *
  469. * var text1 = Ext.widget({
  470. * xtype: 'textfield',
  471. * fieldLabel: 'Foo'
  472. * });
  473. *
  474. * This conversion of configuration objects into instantiated components is done when
  475. * a container is created as part of its {Ext.container.AbstractContainer#initComponent}
  476. * process. As part of the same process, the `items` array is converted from its raw
  477. * array form into a {@link Ext.util.MixedCollection} instance.
  478. *
  479. * You can define your own `xtype` on a custom {@link Ext.Component component} by specifying
  480. * the `xtype` property in {@link Ext#define}. For example:
  481. *
  482. * Ext.define('MyApp.PressMeButton', {
  483. * extend: 'Ext.button.Button',
  484. * xtype: 'pressmebutton',
  485. * text: 'Press Me'
  486. * });
  487. *
  488. * Care should be taken when naming an `xtype` in a custom component because there is
  489. * a single, shared scope for all xtypes. Third part components should consider using
  490. * a prefix to avoid collisions.
  491. *
  492. * Ext.define('Foo.form.CoolButton', {
  493. * extend: 'Ext.button.Button',
  494. * xtype: 'ux-coolbutton',
  495. * text: 'Cool!'
  496. * });
  497. */
  498. /**
  499. * @cfg {String} tplWriteMode
  500. * The Ext.(X)Template method to use when updating the content area of the Component.
  501. * See `{@link Ext.XTemplate#overwrite}` for information on default mode.
  502. */
  503. tplWriteMode: 'overwrite',
  504. /**
  505. * @cfg {String} [baseCls='x-component']
  506. * The base CSS class to apply to this components's element. This will also be prepended to elements within this
  507. * component like Panel's body will get a class x-panel-body. This means that if you create a subclass of Panel, and
  508. * you want it to get all the Panels styling for the element and the body, you leave the baseCls x-panel and use
  509. * componentCls to add specific styling for this component.
  510. */
  511. baseCls: Ext.baseCSSPrefix + 'component',
  512. /**
  513. * @cfg {String} componentCls
  514. * CSS Class to be added to a components root level element to give distinction to it via styling.
  515. */
  516. /**
  517. * @cfg {String} [cls='']
  518. * An optional extra CSS class that will be added to this component's Element. This can be useful
  519. * for adding customized styles to the component or any of its children using standard CSS rules.
  520. */
  521. /**
  522. * @cfg {String} [overCls='']
  523. * An optional extra CSS class that will be added to this component's Element when the mouse moves over the Element,
  524. * and removed when the mouse moves out. This can be useful for adding customized 'active' or 'hover' styles to the
  525. * component or any of its children using standard CSS rules.
  526. */
  527. /**
  528. * @cfg {String} [disabledCls='x-item-disabled']
  529. * CSS class to add when the Component is disabled. Defaults to 'x-item-disabled'.
  530. */
  531. disabledCls: Ext.baseCSSPrefix + 'item-disabled',
  532. /**
  533. * @cfg {String} ui
  534. * A UI style for a component.
  535. */
  536. ui: 'default',
  537. /**
  538. * @cfg {String[]} uiCls
  539. * An array of of classNames which are currently applied to this component
  540. * @private
  541. */
  542. uiCls: [],
  543. /**
  544. * @cfg {String/Object} style
  545. * A custom style specification to be applied to this component's Element. Should be a valid argument to
  546. * {@link Ext.Element#applyStyles}.
  547. *
  548. * new Ext.panel.Panel({
  549. * title: 'Some Title',
  550. * renderTo: Ext.getBody(),
  551. * width: 400, height: 300,
  552. * layout: 'form',
  553. * items: [{
  554. * xtype: 'textarea',
  555. * style: {
  556. * width: '95%',
  557. * marginBottom: '10px'
  558. * }
  559. * },
  560. * new Ext.button.Button({
  561. * text: 'Send',
  562. * minWidth: '100',
  563. * style: {
  564. * marginBottom: '10px'
  565. * }
  566. * })
  567. * ]
  568. * });
  569. */
  570. /**
  571. * @cfg {Number} width
  572. * The width of this component in pixels.
  573. */
  574. /**
  575. * @cfg {Number} height
  576. * The height of this component in pixels.
  577. */
  578. /**
  579. * @cfg {Number/String/Boolean} border
  580. * Specifies the border size for this component. The border can be a single numeric value to apply to all sides or it can
  581. * be a CSS style specification for each style, for example: '10 5 3 10'.
  582. *
  583. * For components that have no border by default, setting this won't make the border appear by itself.
  584. * You also need to specify border color and style:
  585. *
  586. * border: 5,
  587. * style: {
  588. * borderColor: 'red',
  589. * borderStyle: 'solid'
  590. * }
  591. *
  592. * To turn off the border, use `border: false`.
  593. */
  594. /**
  595. * @cfg {Number/String} padding
  596. * Specifies the padding for this component. The padding can be a single numeric value to apply to all sides or it
  597. * can be a CSS style specification for each style, for example: '10 5 3 10'.
  598. */
  599. /**
  600. * @cfg {Number/String} margin
  601. * Specifies the margin for this component. The margin can be a single numeric value to apply to all sides or it can
  602. * be a CSS style specification for each style, for example: '10 5 3 10'.
  603. */
  604. /**
  605. * @cfg {Boolean} hidden
  606. * True to hide the component.
  607. */
  608. hidden: false,
  609. /**
  610. * @cfg {Boolean} disabled
  611. * True to disable the component.
  612. */
  613. disabled: false,
  614. /**
  615. * @cfg {Boolean} [draggable=false]
  616. * Allows the component to be dragged.
  617. */
  618. /**
  619. * @property {Boolean} draggable
  620. * Indicates whether or not the component can be dragged.
  621. * @readonly
  622. */
  623. draggable: false,
  624. /**
  625. * @cfg {Boolean} floating
  626. * Create the Component as a floating and use absolute positioning.
  627. *
  628. * The z-index of floating Components is handled by a ZIndexManager. If you simply render a floating Component into the DOM, it will be managed
  629. * by the global {@link Ext.WindowManager WindowManager}.
  630. *
  631. * If you include a floating Component as a child item of a Container, then upon render, ExtJS will seek an ancestor floating Component to house a new
  632. * ZIndexManager instance to manage its descendant floaters. If no floating ancestor can be found, the global WindowManager will be used.
  633. *
  634. * When a floating Component which has a ZindexManager managing descendant floaters is destroyed, those descendant floaters will also be destroyed.
  635. */
  636. floating: false,
  637. /**
  638. * @cfg {String} hideMode
  639. * A String which specifies how this Component's encapsulating DOM element will be hidden. Values may be:
  640. *
  641. * - `'display'` : The Component will be hidden using the `display: none` style.
  642. * - `'visibility'` : The Component will be hidden using the `visibility: hidden` style.
  643. * - `'offsets'` : The Component will be hidden by absolutely positioning it out of the visible area of the document.
  644. * This is useful when a hidden Component must maintain measurable dimensions. Hiding using `display` results in a
  645. * Component having zero dimensions.
  646. */
  647. hideMode: 'display',
  648. /**
  649. * @cfg {String} contentEl
  650. * Specify an existing HTML element, or the `id` of an existing HTML element to use as the content for this component.
  651. *
  652. * This config option is used to take an existing HTML element and place it in the layout element of a new component
  653. * (it simply moves the specified DOM element _after the Component is rendered_ to use as the content.
  654. *
  655. * **Notes:**
  656. *
  657. * The specified HTML element is appended to the layout element of the component _after any configured
  658. * {@link #html HTML} has been inserted_, and so the document will not contain this element at the time
  659. * the {@link #event-render} event is fired.
  660. *
  661. * The specified HTML element used will not participate in any **`{@link Ext.container.Container#layout layout}`**
  662. * scheme that the Component may use. It is just HTML. Layouts operate on child
  663. * **`{@link Ext.container.Container#cfg-items items}`**.
  664. *
  665. * Add either the `x-hidden` or the `x-hide-display` CSS class to prevent a brief flicker of the content before it
  666. * is rendered to the panel.
  667. */
  668. /**
  669. * @cfg {String/Object} [html='']
  670. * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element content.
  671. * The HTML content is added after the component is rendered, so the document will not contain this HTML at the time
  672. * the {@link #event-render} event is fired. This content is inserted into the body _before_ any configured {@link #contentEl}
  673. * is appended.
  674. */
  675. /**
  676. * @cfg {Boolean} styleHtmlContent
  677. * True to automatically style the html inside the content target of this component (body for panels).
  678. */
  679. styleHtmlContent: false,
  680. /**
  681. * @cfg {String} [styleHtmlCls='x-html']
  682. * The class that is added to the content target when you set styleHtmlContent to true.
  683. */
  684. styleHtmlCls: Ext.baseCSSPrefix + 'html',
  685. /**
  686. * @cfg {Number} minHeight
  687. * The minimum value in pixels which this Component will set its height to.
  688. *
  689. * **Warning:** This will override any size management applied by layout managers.
  690. */
  691. /**
  692. * @cfg {Number} minWidth
  693. * The minimum value in pixels which this Component will set its width to.
  694. *
  695. * **Warning:** This will override any size management applied by layout managers.
  696. */
  697. /**
  698. * @cfg {Number} maxHeight
  699. * The maximum value in pixels which this Component will set its height to.
  700. *
  701. * **Warning:** This will override any size management applied by layout managers.
  702. */
  703. /**
  704. * @cfg {Number} maxWidth
  705. * The maximum value in pixels which this Component will set its width to.
  706. *
  707. * **Warning:** This will override any size management applied by layout managers.
  708. */
  709. /**
  710. * @cfg {Ext.ComponentLoader/Object} loader
  711. * A configuration object or an instance of a {@link Ext.ComponentLoader} to load remote content
  712. * for this Component.
  713. *
  714. * Ext.create('Ext.Component', {
  715. * loader: {
  716. * url: 'content.html',
  717. * autoLoad: true
  718. * },
  719. * renderTo: Ext.getBody()
  720. * });
  721. */
  722. /**
  723. * @cfg {Ext.ComponentLoader/Object/String/Boolean} autoLoad
  724. * An alias for {@link #loader} config which also allows to specify just a string which will be
  725. * used as the url that's automatically loaded:
  726. *
  727. * Ext.create('Ext.Component', {
  728. * autoLoad: 'content.html',
  729. * renderTo: Ext.getBody()
  730. * });
  731. *
  732. * The above is the same as:
  733. *
  734. * Ext.create('Ext.Component', {
  735. * loader: {
  736. * url: 'content.html',
  737. * autoLoad: true
  738. * },
  739. * renderTo: Ext.getBody()
  740. * });
  741. *
  742. * Don't use it together with {@link #loader} config.
  743. *
  744. * @deprecated 4.1.1 Use {@link #loader} config instead.
  745. */
  746. /**
  747. * @cfg {Boolean} autoShow
  748. * True to automatically show the component upon creation. This config option may only be used for
  749. * {@link #floating} components or components that use {@link #autoRender}. Defaults to false.
  750. */
  751. autoShow: false,
  752. /**
  753. * @cfg {Boolean/String/HTMLElement/Ext.Element} autoRender
  754. * This config is intended mainly for non-{@link #floating} Components which may or may not be shown. Instead of using
  755. * {@link #renderTo} in the configuration, and rendering upon construction, this allows a Component to render itself
  756. * upon first _{@link Ext.Component#method-show show}_. If {@link #floating} is true, the value of this config is omited as if it is `true`.
  757. *
  758. * Specify as `true` to have this Component render to the document body upon first show.
  759. *
  760. * Specify as an element, or the ID of an element to have this Component render to a specific element upon first
  761. * show.
  762. */
  763. autoRender: false,
  764. // @private
  765. allowDomMove: true,
  766. /**
  767. * @cfg {Object/Object[]} plugins
  768. * An object or array of objects that will provide custom functionality for this component. The only requirement for
  769. * a valid plugin is that it contain an init method that accepts a reference of type Ext.Component. When a component
  770. * is created, if any plugins are available, the component will call the init method on each plugin, passing a
  771. * reference to itself. Each plugin can then call methods or respond to events on the component as needed to provide
  772. * its functionality.
  773. */
  774. /**
  775. * @property {Boolean} rendered
  776. * Indicates whether or not the component has been rendered.
  777. * @readonly
  778. */
  779. rendered: false,
  780. /**
  781. * @property {Number} componentLayoutCounter
  782. * @private
  783. * The number of component layout calls made on this object.
  784. */
  785. componentLayoutCounter: 0,
  786. /**
  787. * @cfg {Boolean/Number} [shrinkWrap=2]
  788. *
  789. * If this property is a number, it is interpreted as follows:
  790. *
  791. * - 0: Neither width nor height depend on content. This is equivalent to `false`.
  792. * - 1: Width depends on content (shrink wraps), but height does not.
  793. * - 2: Height depends on content (shrink wraps), but width does not. The default.
  794. * - 3: Both width and height depend on content (shrink wrap). This is equivalent to `true`.
  795. *
  796. * In CSS terms, shrink-wrap width is analogous to an inline-block element as opposed
  797. * to a block-level element. Some container layouts always shrink-wrap their children,
  798. * effectively ignoring this property (e.g., {@link Ext.layout.container.HBox},
  799. * {@link Ext.layout.container.VBox}, {@link Ext.layout.component.Dock}).
  800. */
  801. shrinkWrap: 2,
  802. weight: 0,
  803. /**
  804. * @property {Boolean} maskOnDisable
  805. * This is an internal flag that you use when creating custom components. By default this is set to true which means
  806. * that every component gets a mask when it's disabled. Components like FieldContainer, FieldSet, Field, Button, Tab
  807. * override this property to false since they want to implement custom disable logic.
  808. */
  809. maskOnDisable: true,
  810. /**
  811. * @property {Boolean} [_isLayoutRoot=false]
  812. * Setting this property to `true` causes the {@link #isLayoutRoot} method to return
  813. * `true` and stop the search for the top-most component for a layout.
  814. * @protected
  815. */
  816. _isLayoutRoot: false,
  817. /**
  818. * Creates new Component.
  819. * @param {Object} config (optional) Config object.
  820. */
  821. constructor : function(config) {
  822. var me = this,
  823. i, len, xhooks;
  824. if (config) {
  825. Ext.apply(me, config);
  826. xhooks = me.xhooks;
  827. if (xhooks) {
  828. delete me.xhooks;
  829. Ext.override(me, xhooks);
  830. }
  831. } else {
  832. config = {};
  833. }
  834. me.initialConfig = config;
  835. me.mixins.elementCt.constructor.call(me);
  836. me.addEvents(
  837. /**
  838. * @event beforeactivate
  839. * Fires before a Component has been visually activated. Returning false from an event listener can prevent
  840. * the activate from occurring.
  841. * @param {Ext.Component} this
  842. */
  843. 'beforeactivate',
  844. /**
  845. * @event activate
  846. * Fires after a Component has been visually activated.
  847. * @param {Ext.Component} this
  848. */
  849. 'activate',
  850. /**
  851. * @event beforedeactivate
  852. * Fires before a Component has been visually deactivated. Returning false from an event listener can
  853. * prevent the deactivate from occurring.
  854. * @param {Ext.Component} this
  855. */
  856. 'beforedeactivate',
  857. /**
  858. * @event deactivate
  859. * Fires after a Component has been visually deactivated.
  860. * @param {Ext.Component} this
  861. */
  862. 'deactivate',
  863. /**
  864. * @event added
  865. * Fires after a Component had been added to a Container.
  866. * @param {Ext.Component} this
  867. * @param {Ext.container.Container} container Parent Container
  868. * @param {Number} pos position of Component
  869. */
  870. 'added',
  871. /**
  872. * @event disable
  873. * Fires after the component is disabled.
  874. * @param {Ext.Component} this
  875. */
  876. 'disable',
  877. /**
  878. * @event enable
  879. * Fires after the component is enabled.
  880. * @param {Ext.Component} this
  881. */
  882. 'enable',
  883. /**
  884. * @event beforeshow
  885. * Fires before the component is shown when calling the {@link Ext.Component#method-show show} method. Return false from an event
  886. * handler to stop the show.
  887. * @param {Ext.Component} this
  888. */
  889. 'beforeshow',
  890. /**
  891. * @event show
  892. * Fires after the component is shown when calling the {@link Ext.Component#method-show show} method.
  893. * @param {Ext.Component} this
  894. */
  895. 'show',
  896. /**
  897. * @event beforehide
  898. * Fires before the component is hidden when calling the {@link Ext.Component#method-hide hide} method. Return false from an event
  899. * handler to stop the hide.
  900. * @param {Ext.Component} this
  901. */
  902. 'beforehide',
  903. /**
  904. * @event hide
  905. * Fires after the component is hidden. Fires after the component is hidden when calling the {@link Ext.Component#method-hide hide}
  906. * method.
  907. * @param {Ext.Component} this
  908. */
  909. 'hide',
  910. /**
  911. * @event removed
  912. * Fires when a component is removed from an Ext.container.Container
  913. * @param {Ext.Component} this
  914. * @param {Ext.container.Container} ownerCt Container which holds the component
  915. */
  916. 'removed',
  917. /**
  918. * @event beforerender
  919. * Fires before the component is {@link #rendered}. Return false from an event handler to stop the
  920. * {@link #method-render}.
  921. * @param {Ext.Component} this
  922. */
  923. 'beforerender',
  924. /**
  925. * @event render
  926. * Fires after the component markup is {@link #rendered}.
  927. * @param {Ext.Component} this
  928. */
  929. 'render',
  930. /**
  931. * @event afterrender
  932. * Fires after the component rendering is finished.
  933. *
  934. * The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed by any
  935. * afterRender method defined for the Component.
  936. * @param {Ext.Component} this
  937. */
  938. 'afterrender',
  939. /**
  940. * @event boxready
  941. * Fires *one time* - after the component has been layed out for the first time at its initial size.
  942. * @param {Ext.Component} this
  943. * @param {Number} width The initial width
  944. * @param {Number} height The initial height
  945. */
  946. 'boxready',
  947. /**
  948. * @event beforedestroy
  949. * Fires before the component is {@link #method-destroy}ed. Return false from an event handler to stop the
  950. * {@link #method-destroy}.
  951. * @param {Ext.Component} this
  952. */
  953. 'beforedestroy',
  954. /**
  955. * @event destroy
  956. * Fires after the component is {@link #method-destroy}ed.
  957. * @param {Ext.Component} this
  958. */
  959. 'destroy',
  960. /**
  961. * @event resize
  962. * Fires after the component is resized. Note that this does *not* fire when the component is first layed out at its initial
  963. * size. To hook that point in the lifecycle, use the {@link #boxready} event.
  964. * @param {Ext.Component} this
  965. * @param {Number} width The new width that was set
  966. * @param {Number} height The new height that was set
  967. * @param {Number} oldWidth The previous width
  968. * @param {Number} oldHeight The previous height
  969. */
  970. 'resize',
  971. /**
  972. * @event move
  973. * Fires after the component is moved.
  974. * @param {Ext.Component} this
  975. * @param {Number} x The new x position
  976. * @param {Number} y The new y position
  977. */
  978. 'move',
  979. /**
  980. * @event focus
  981. * Fires when this Component receives focus.
  982. * @param {Ext.Component} this
  983. * @param {Ext.EventObject} The focus event.
  984. */
  985. 'focus',
  986. /**
  987. * @event blur
  988. * Fires when this Component loses focus.
  989. * @param {Ext.Component} this
  990. * @param {Ext.EventObject} The blur event.
  991. */
  992. 'blur'
  993. );
  994. me.getId();
  995. me.setupProtoEl();
  996. // initComponent, beforeRender, or event handlers may have set the style or cls property since the protoEl was set up
  997. // so we must apply styles and classes here too.
  998. if (me.cls) {
  999. me.initialCls = me.cls;
  1000. me.protoEl.addCls(me.cls);
  1001. }
  1002. if (me.style) {
  1003. me.initialStyle = me.style;
  1004. me.protoEl.setStyle(me.style);
  1005. }
  1006. me.mons = [];
  1007. me.renderData = me.renderData || {};
  1008. me.renderSelectors = me.renderSelectors || {};
  1009. if (me.plugins) {
  1010. me.plugins = me.constructPlugins();
  1011. }
  1012. // we need this before we call initComponent
  1013. if (!me.hasListeners) {
  1014. me.hasListeners = new me.HasListeners();
  1015. }
  1016. me.initComponent();
  1017. // ititComponent gets a chance to change the id property before registering
  1018. Ext.ComponentManager.register(me);
  1019. // Dont pass the config so that it is not applied to 'this' again
  1020. me.mixins.observable.constructor.call(me);
  1021. me.mixins.state.constructor.call(me, config);
  1022. // Save state on resize.
  1023. this.addStateEvents('resize');
  1024. // Move this into Observable?
  1025. if (me.plugins) {
  1026. for (i = 0, len = me.plugins.length; i < len; i++) {
  1027. me.plugins[i] = me.initPlugin(me.plugins[i]);
  1028. }
  1029. }
  1030. me.loader = me.getLoader();
  1031. if (me.renderTo) {
  1032. me.render(me.renderTo);
  1033. // EXTJSIV-1935 - should be a way to do afterShow or something, but that
  1034. // won't work. Likewise, rendering hidden and then showing (w/autoShow) has
  1035. // implications to afterRender so we cannot do that.
  1036. }
  1037. // Auto show only works unilaterally on *uncontained* Components.
  1038. // If contained, then it is the Container's responsibility to do the showing at next layout time.
  1039. if (me.autoShow && !me.isContained) {
  1040. me.show();
  1041. }
  1042. //<debug>
  1043. if (Ext.isDefined(me.disabledClass)) {
  1044. if (Ext.isDefined(Ext.global.console)) {
  1045. Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');
  1046. }
  1047. me.disabledCls = me.disabledClass;
  1048. delete me.disabledClass;
  1049. }
  1050. //</debug>
  1051. },
  1052. initComponent: function () {
  1053. // This is called again here to allow derived classes to add plugin configs to the
  1054. // plugins array before calling down to this, the base initComponent.
  1055. this.plugins = this.constructPlugins();
  1056. // this will properly (ignore or) constrain the configured width/height to their
  1057. // min/max values for consistency.
  1058. this.setSize(this.width, this.height);
  1059. },
  1060. /**
  1061. * The supplied default state gathering method for the AbstractComponent class.
  1062. *
  1063. * This method returns dimension settings such as `flex`, `anchor`, `width` and `height` along with `collapsed`
  1064. * state.
  1065. *
  1066. * Subclasses which implement more complex state should call the superclass's implementation, and apply their state
  1067. * to the result if this basic state is to be saved.
  1068. *
  1069. * Note that Component state will only be saved if the Component has a {@link #stateId} and there as a StateProvider
  1070. * configured for the document.
  1071. *
  1072. * @return {Object}
  1073. */
  1074. getState: function() {
  1075. var me = this,
  1076. state = null,
  1077. sizeModel = me.getSizeModel();
  1078. if (sizeModel.width.configured) {
  1079. state = me.addPropertyToState(state, 'width');
  1080. }
  1081. if (sizeModel.height.configured) {
  1082. state = me.addPropertyToState(state, 'height');
  1083. }
  1084. return state;
  1085. },
  1086. /**
  1087. * Save a property to the given state object if it is not its default or configured
  1088. * value.
  1089. *
  1090. * @param {Object} state The state object
  1091. * @param {String} propName The name of the property on this object to save.
  1092. * @param {String} [value] The value of the state property (defaults to `this[propName]`).
  1093. * @return {Boolean} The state object or a new object if state was null and the property
  1094. * was saved.
  1095. * @protected
  1096. */
  1097. addPropertyToState: function (state, propName, value) {
  1098. var me = this,
  1099. len = arguments.length;
  1100. // If the property is inherited, it is a default and we don't want to save it to
  1101. // the state, however if we explicitly specify a value, always save it
  1102. if (len == 3 || me.hasOwnProperty(propName)) {
  1103. if (len < 3) {
  1104. value = me[propName];
  1105. }
  1106. // If the property has the same value as was initially configured, again, we
  1107. // don't want to save it.
  1108. if (value !== me.initialConfig[propName]) {
  1109. (state || (state = {}))[propName] = value;
  1110. }
  1111. }
  1112. return state;
  1113. },
  1114. show: Ext.emptyFn,
  1115. animate: function(animObj) {
  1116. var me = this,
  1117. hasToWidth,
  1118. hasToHeight,
  1119. toHeight,
  1120. toWidth,
  1121. to,
  1122. clearWidth,
  1123. clearHeight,
  1124. curWidth, w, curHeight, h, needsResize;
  1125. animObj = animObj || {};
  1126. to = animObj.to || {};
  1127. if (Ext.fx.Manager.hasFxBlock(me.id)) {
  1128. return me;
  1129. }
  1130. hasToWidth = Ext.isDefined(to.width);
  1131. if (hasToWidth) {
  1132. toWidth = Ext.Number.constrain(to.width, me.minWidth, me.maxWidth);
  1133. }
  1134. hasToHeight = Ext.isDefined(to.height);
  1135. if (hasToHeight) {
  1136. toHeight = Ext.Number.constrain(to.height, me.minHeight, me.maxHeight);
  1137. }
  1138. // Special processing for animating Component dimensions.
  1139. if (!animObj.dynamic && (hasToWidth || hasToHeight)) {
  1140. curWidth = (animObj.from ? animObj.from.width : undefined) || me.getWidth();
  1141. w = curWidth;
  1142. curHeight = (animObj.from ? animObj.from.height : undefined) || me.getHeight();
  1143. h = curHeight;
  1144. needsResize = false;
  1145. if (hasToHeight && toHeight > curHeight) {
  1146. h = toHeight;
  1147. needsResize = true;
  1148. }
  1149. if (hasToWidth && toWidth > curWidth) {
  1150. w = toWidth;
  1151. needsResize = true;
  1152. }
  1153. // If any dimensions are being increased, we must resize the internal structure
  1154. // of the Component, but then clip it by sizing its encapsulating element back to original dimensions.
  1155. // The animation will then progressively reveal the larger content.
  1156. if (needsResize) {
  1157. clearWidth = !Ext.isNumber(me.width);
  1158. clearHeight = !Ext.isNumber(me.height);
  1159. me.setSize(w, h);
  1160. me.el.setSize(curWidth, curHeight);
  1161. if (clearWidth) {
  1162. delete me.width;
  1163. }
  1164. if (clearHeight) {
  1165. delete me.height;
  1166. }
  1167. }
  1168. if (hasToWidth) {
  1169. to.width = toWidth;
  1170. }
  1171. if (hasToHeight) {
  1172. to.height = toHeight;
  1173. }
  1174. }
  1175. return me.mixins.animate.animate.apply(me, arguments);
  1176. },
  1177. onHide: function() {
  1178. this.updateLayout({ isRoot: false });
  1179. },
  1180. onShow : function() {
  1181. this.updateLayout({ isRoot: false });
  1182. },
  1183. constructPlugin: function(plugin) {
  1184. // If a config object with a ptype
  1185. if (plugin.ptype && typeof plugin.init != 'function') {
  1186. plugin.cmp = this;
  1187. plugin = Ext.PluginManager.create(plugin);
  1188. }
  1189. // Just a ptype
  1190. else if (typeof plugin == 'string') {
  1191. plugin = Ext.PluginManager.create({
  1192. ptype: plugin,
  1193. cmp: this
  1194. });
  1195. }
  1196. return plugin;
  1197. },
  1198. /**
  1199. * @private
  1200. * Returns an array of fully constructed plugin instances. This converts any configs into their
  1201. * appropriate instances.
  1202. *
  1203. * It does not mutate the plugins array. It creates a new array.
  1204. *
  1205. * This is borrowed by {@link Ext.grid.Lockable Lockable} which clones and distributes Plugins
  1206. * to both child grids of a locking grid, so must keep to that contract.
  1207. */
  1208. constructPlugins: function() {
  1209. var me = this,
  1210. plugins,
  1211. result = [],
  1212. i, len;
  1213. if (me.plugins) {
  1214. plugins = Ext.isArray(me.plugins) ? me.plugins : [ me.plugins ];
  1215. for (i = 0, len = plugins.length; i < len; i++) {
  1216. // this just returns already-constructed plugin instances...
  1217. result[i] = me.constructPlugin(plugins[i]);
  1218. }
  1219. return result;
  1220. }
  1221. },
  1222. // @private
  1223. initPlugin : function(plugin) {
  1224. plugin.init(this);
  1225. return plugin;
  1226. },
  1227. /**
  1228. * @private
  1229. * Injected as an override by Ext.Aria.initialize
  1230. */
  1231. updateAria: Ext.emptyFn,
  1232. /**
  1233. * Called by Component#doAutoRender
  1234. *
  1235. * Register a Container configured `floating: true` with this Component's {@link Ext.ZIndexManager ZIndexManager}.
  1236. *
  1237. * Components added in ths way will not participate in any layout, but will be rendered
  1238. * upon first show in the way that {@link Ext.window.Window Window}s are.
  1239. */
  1240. registerFloatingItem: function(cmp) {
  1241. var me = this;
  1242. if (!me.floatingDescendants) {
  1243. me.floatingDescendants = new Ext.ZIndexManager(me);
  1244. }
  1245. me.floatingDescendants.register(cmp);
  1246. },
  1247. unregisterFloatingItem: function(cmp) {
  1248. var me = this;
  1249. if (me.floatingDescendants) {
  1250. me.floatingDescendants.unregister(cmp);
  1251. }
  1252. },
  1253. layoutSuspendCount: 0,
  1254. suspendLayouts: function () {
  1255. var me = this;
  1256. if (!me.rendered) {
  1257. return;
  1258. }
  1259. if (++me.layoutSuspendCount == 1) {
  1260. me.suspendLayout = true;
  1261. }
  1262. },
  1263. resumeLayouts: function (flushOptions) {
  1264. var me = this;
  1265. if (!me.rendered) {
  1266. return;
  1267. }
  1268. if (! --me.layoutSuspendCount) {
  1269. me.suspendLayout = false;
  1270. if (flushOptions && !me.isLayoutSuspended()) {
  1271. me.updateLayout(flushOptions);
  1272. }
  1273. }
  1274. },
  1275. setupProtoEl: function() {
  1276. var me = this,
  1277. cls = [ me.baseCls, me.getComponentLayout().targetCls ];
  1278. //<deprecated since=0.99>
  1279. if (Ext.isDefined(me.cmpCls)) {
  1280. if (Ext.isDefined(Ext.global.console)) {
  1281. Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
  1282. }
  1283. me.componentCls = me.cmpCls;
  1284. delete me.cmpCls;
  1285. }
  1286. //</deprecated>
  1287. if (me.componentCls) {
  1288. cls.push(me.componentCls);
  1289. } else {
  1290. me.componentCls = me.baseCls;
  1291. }
  1292. me.protoEl = new Ext.util.ProtoElement({
  1293. cls: cls.join(' ') // in case any of the parts have multiple classes
  1294. });
  1295. },
  1296. /**
  1297. * Sets the UI for the component. This will remove any existing UIs on the component. It will also loop through any
  1298. * uiCls set on the component and rename them so they include the new UI
  1299. * @param {String} ui The new UI for the component
  1300. */
  1301. setUI: function(ui) {
  1302. var me = this,
  1303. oldUICls = Ext.Array.clone(me.uiCls),
  1304. newUICls = [],
  1305. classes = [],
  1306. cls,
  1307. i;
  1308. //loop through all existing uiCls and update the ui in them
  1309. for (i = 0; i < oldUICls.length; i++) {
  1310. cls = oldUICls[i];
  1311. classes = classes.concat(me.removeClsWithUI(cls, true));
  1312. newUICls.push(cls);
  1313. }
  1314. if (classes.length) {
  1315. me.removeCls(classes);
  1316. }
  1317. //remove the UI from the element
  1318. me.removeUIFromElement();
  1319. //set the UI
  1320. me.ui = ui;
  1321. //add the new UI to the element
  1322. me.addUIToElement();
  1323. //loop through all existing uiCls and update the ui in them
  1324. classes = [];
  1325. for (i = 0; i < newUICls.length; i++) {
  1326. cls = newUICls[i];
  1327. classes = classes.concat(me.addClsWithUI(cls, true));
  1328. }
  1329. if (classes.length) {
  1330. me.addCls(classes);
  1331. }
  1332. // Changing the ui can lead to significant changes to a component's appearance, so the layout needs to be
  1333. // updated. Internally most calls to setUI are pre-render. Buttons are a notable exception as setScale changes
  1334. // the ui and often requires the layout to be updated.
  1335. if (me.rendered) {
  1336. me.updateLayout();
  1337. }
  1338. },
  1339. /**
  1340. * Adds a cls to the uiCls array, which will also call {@link #addUIClsToElement} and adds to all elements of this
  1341. * component.
  1342. * @param {String/String[]} classes A string or an array of strings to add to the uiCls
  1343. * @param {Object} skip (Boolean) skip True to skip adding it to the class and do it later (via the return)
  1344. */
  1345. addClsWithUI: function(classes, skip) {
  1346. var me = this,
  1347. clsArray = [],
  1348. length,
  1349. i = 0,
  1350. cls;
  1351. if (typeof classes === "string") {
  1352. classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes);
  1353. }
  1354. length = classes.length;
  1355. me.uiCls = Ext.Array.clone(me.uiCls);
  1356. for (; i < length; i++) {
  1357. cls = classes[i];
  1358. if (cls && !me.hasUICls(cls)) {
  1359. me.uiCls.push(cls);
  1360. clsArray = clsArray.concat(me.addUIClsToElement(cls));
  1361. }
  1362. }
  1363. if (skip !== true) {
  1364. me.addCls(clsArray);
  1365. }
  1366. return clsArray;
  1367. },
  1368. /**
  1369. * Removes a cls to the uiCls array, which will also call {@link #removeUIClsFromElement} and removes it from all
  1370. * elements of this component.
  1371. * @param {String/String[]} cls A string or an array of strings to remove to the uiCls
  1372. */
  1373. removeClsWithUI: function(classes, skip) {
  1374. var me = this,
  1375. clsArray = [],
  1376. i = 0,
  1377. length, cls;
  1378. if (typeof classes === "string") {
  1379. classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes);
  1380. }
  1381. length = classes.length;
  1382. for (i = 0; i < length; i++) {
  1383. cls = classes[i];
  1384. if (cls && me.hasUICls(cls)) {
  1385. me.uiCls = Ext.Array.remove(me.uiCls, cls);
  1386. clsArray = clsArray.concat(me.removeUIClsFromElement(cls));
  1387. }
  1388. }
  1389. if (skip !== true) {
  1390. me.removeCls(clsArray);
  1391. }
  1392. return clsArray;
  1393. },
  1394. /**
  1395. * Checks if there is currently a specified uiCls
  1396. * @param {String} cls The cls to check
  1397. */
  1398. hasUICls: function(cls) {
  1399. var me = this,
  1400. uiCls = me.uiCls || [];
  1401. return Ext.Array.contains(uiCls, cls);
  1402. },
  1403. frameElementsArray: ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
  1404. /**
  1405. * Method which adds a specified UI + uiCls to the components element. Can be overridden to remove the UI from more
  1406. * than just the components element.
  1407. * @param {String} ui The UI to remove from the element
  1408. */
  1409. addUIClsToElement: function(cls) {
  1410. var me = this,
  1411. baseClsUi = me.baseCls + '-' + me.ui + '-' + cls,
  1412. result = [Ext.baseCSSPrefix + cls, me.baseCls + '-' + cls, baseClsUi],
  1413. frameElementCls = me.frameElementCls,
  1414. frameElementsArray, frameElementsLength, i, el, frameElement, c;
  1415. if (me.frame && !Ext.supports.CSS3BorderRadius) {
  1416. // define each element of the frame
  1417. frameElementsArray = me.frameElementsArray;
  1418. frameElementsLength = frameElementsArray.length;
  1419. i = 0;
  1420. // loop through each of them, and if they are defined add the ui
  1421. for (; i < frameElementsLength; i++) {
  1422. frameElement = frameElementsArray[i];
  1423. el = me['frame' + frameElement.toUpperCase()];
  1424. c = baseClsUi + '-' + frameElement;
  1425. if (el && el.dom) {
  1426. el.addCls(c);
  1427. } else if (Ext.Array.indexOf(frameElementCls[frameElement], c) == -1) {
  1428. frameElementCls[frameElement].push(c);
  1429. }
  1430. }
  1431. }
  1432. me.frameElementCls = frameElementCls;
  1433. return result;
  1434. },
  1435. /**
  1436. * Method which removes a specified UI + uiCls from the components element. The cls which is added to the element
  1437. * will be: `this.baseCls + '-' + ui`
  1438. * @param {String} ui The UI to add to the element
  1439. */
  1440. removeUIClsFromElement: function(cls) {
  1441. var me = this,
  1442. baseClsUi = me.baseCls + '-' + me.ui + '-' + cls,
  1443. result = [Ext.baseCSSPrefix + cls, me.baseCls + '-' + cls, baseClsUi],
  1444. frameElementCls = me.frameElementCls,
  1445. frameElementsArray, frameElementsLength, i, el, frameElement, c;
  1446. if (me.frame && !Ext.supports.CSS3BorderRadius) {
  1447. // define each element of the frame
  1448. frameElementsArray = me.frameElementsArray;
  1449. frameElementsLength = frameElementsArray.length;
  1450. i = 0;
  1451. // loop through each of them, and if they are defined add the ui
  1452. for (; i < frameElementsLength; i++) {
  1453. frameElement = frameElementsArray[i];
  1454. el = me['frame' + frameElement.toUpperCase()];
  1455. c = baseClsUi + '-' + frameElement;
  1456. if (el && el.dom) {
  1457. el.addCls(c);
  1458. } else {
  1459. Ext.Array.remove(frameElementCls[frameElement], c);
  1460. }
  1461. }
  1462. }
  1463. me.frameElementCls = frameElementCls;
  1464. return result;
  1465. },
  1466. /**
  1467. * Method which adds a specified UI to the components element.
  1468. * @private
  1469. */
  1470. addUIToElement: function() {
  1471. var me = this,
  1472. baseClsUI = me.baseCls + '-' + me.ui,
  1473. frameElementCls = me.frameElementCls,
  1474. frameElementsArray, frameElementsLength, i, el, frameElement, c;
  1475. me.addCls(baseClsUI);
  1476. if (me.frame && !Ext.supports.CSS3BorderRadius) {
  1477. // define each element of the frame
  1478. frameElementsArray = me.frameElementsArray;
  1479. frameElementsLength = frameElementsArray.length;
  1480. i = 0;
  1481. // loop through each of them, and if they are defined add the ui
  1482. for (; i < frameElementsLength; i++) {
  1483. frameElement = frameElementsArray[i];
  1484. el = me['frame' + frameElement.toUpperCase()];
  1485. c = baseClsUI + '-' + frameElement;
  1486. if (el) {
  1487. el.addCls(c);
  1488. } else {
  1489. if (!Ext.Array.contains(frameElementCls[frameElement], c)) {
  1490. frameElementCls[frameElement].push(c);
  1491. }
  1492. }
  1493. }
  1494. }
  1495. },
  1496. /**
  1497. * Method which removes a specified UI from the components element.
  1498. * @private
  1499. */
  1500. removeUIFromElement: function() {
  1501. var me = this,
  1502. baseClsUI = me.baseCls + '-' + me.ui,
  1503. frameElementCls = me.frameElementCls,
  1504. frameElementsArray, frameElementsLength, i, el, frameElement, c;
  1505. me.removeCls(baseClsUI);
  1506. if (me.frame && !Ext.supports.CSS3BorderRadius) {
  1507. // define each element of the frame
  1508. frameElementsArray = me.frameElementsArray;
  1509. frameElementsLength = frameElementsArray.length;
  1510. i = 0;
  1511. for (; i < frameElementsLength; i++) {
  1512. frameElement = frameElementsArray[i];
  1513. el = me['frame' + frameElement.toUpperCase()];
  1514. c = baseClsUI + '-' + frameElement;
  1515. if (el) {
  1516. el.removeCls(c);
  1517. } else {
  1518. Ext.Array.remove(frameElementCls[frameElement], c);
  1519. }
  1520. }
  1521. }
  1522. },
  1523. /**
  1524. * @private
  1525. */
  1526. getTpl: function(name) {
  1527. return Ext.XTemplate.getTpl(this, name);
  1528. },
  1529. /**
  1530. * Converts style definitions to String.
  1531. * @return {String} A CSS style string with style, padding, margin and border.
  1532. * @private
  1533. */
  1534. initStyles: function(targetEl) {
  1535. var me = this,
  1536. Element = Ext.Element,
  1537. padding = me.padding,
  1538. margin = me.margin,
  1539. x = me.x,
  1540. y = me.y,
  1541. width, height;
  1542. // Convert the padding, margin and border properties from a space separated string
  1543. // into a proper style string
  1544. if (padding !== undefined) {
  1545. targetEl.setStyle('padding', Element.unitizeBox((padding === true) ? 5 : padding));
  1546. }
  1547. if (margin !== undefined) {
  1548. targetEl.setStyle('margin', Element.unitizeBox((margin === true) ? 5 : margin));
  1549. }
  1550. if (me.border !== undefined) {
  1551. me.setBorder(me.border, targetEl);
  1552. }
  1553. // initComponent, beforeRender, or event handlers may have set the style or cls property since the protoEl was set up
  1554. // so we must apply styles and classes here too.
  1555. if (me.cls && me.cls != me.initialCls) {
  1556. targetEl.addCls(me.cls);
  1557. delete me.cls;
  1558. delete me.initialCls;
  1559. }
  1560. if (me.style && me.style != me.initialStyle) {
  1561. targetEl.setStyle(me.style);
  1562. delete me.style;
  1563. delete me.initialStyle;
  1564. }
  1565. if (x !== undefined) {
  1566. targetEl.setStyle('left', (typeof x == 'number') ? (x + 'px') : x);
  1567. }
  1568. if (y !== undefined) {
  1569. targetEl.setStyle('top', (typeof y == 'number') ? (y + 'px') : y);
  1570. }
  1571. // Framed components need their width/height to apply to the frame, which is
  1572. // best handled in layout at present.
  1573. if (!me.getFrameInfo()) {
  1574. width = me.width;
  1575. height = me.height;
  1576. // If we're using the content box model, we also cannot assign numeric initial sizes since we do not know the border widths to subtract
  1577. if (width !== undefined) {
  1578. if (typeof width === 'number') {
  1579. if (Ext.isBorderBox) {
  1580. targetEl.setStyle('width', width + 'px');
  1581. }
  1582. } else {
  1583. targetEl.setStyle('width', width);
  1584. }
  1585. }
  1586. if (height !== undefined) {
  1587. if (typeof height === 'number') {
  1588. if (Ext.isBorderBox) {
  1589. targetEl.setStyle('height', height + 'px');
  1590. }
  1591. } else {
  1592. targetEl.setStyle('height', height);
  1593. }
  1594. }
  1595. }
  1596. },
  1597. // @private
  1598. initEvents : function() {
  1599. var me = this,
  1600. afterRenderEvents = me.afterRenderEvents,
  1601. el,
  1602. property,
  1603. fn = function(listeners){
  1604. me.mon(el, listeners);
  1605. };
  1606. if (afterRenderEvents) {
  1607. for (property in afterRenderEvents) {
  1608. if (afterRenderEvents.hasOwnProperty(property)) {
  1609. el = me[property];
  1610. if (el && el.on) {
  1611. Ext.each(afterRenderEvents[property], fn);
  1612. }
  1613. }
  1614. }
  1615. }
  1616. // This will add focus/blur listeners to the getFocusEl() element if that is naturally focusable.
  1617. // If *not* naturally focusable, then the FocusManager must be enabled to get it to listen for focus so that
  1618. // the FocusManager can track and highlight focus.
  1619. me.addFocusListener();
  1620. },
  1621. /**
  1622. * @private
  1623. * <p>Sets up the focus listener on this Component's {@link #getFocusEl focusEl} if it has one.</p>
  1624. * <p>Form Components which must implicitly participate in tabbing order usually have a naturally focusable
  1625. * element as their {@link #getFocusEl focusEl}, and it is the DOM event of that recieving focus which drives
  1626. * the Component's onFocus handling, and the DOM event of it being blurred which drives the onBlur handling.</p>
  1627. * <p>If the {@link #getFocusEl focusEl} is <b>not</b> naturally focusable, then the listeners are only added
  1628. * if the {@link Ext.FocusManager FocusManager} is enabled.</p>
  1629. */
  1630. addFocusListener: function() {
  1631. var me = this,
  1632. focusEl = me.getFocusEl(),
  1633. needsTabIndex;
  1634. // All Containers may be focusable, not only "form" type elements, but also
  1635. // Panels, Toolbars, Windows etc.
  1636. // Usually, the <DIV> element they will return as their focusEl will not be able to recieve focus
  1637. // However, if the FocusManager is invoked, its non-default navigation handlers (invoked when
  1638. // tabbing/arrowing off of certain Components) may explicitly focus a Panel or Container or FieldSet etc.
  1639. // Add listeners to the focus and blur events on the focus element
  1640. // If this Component returns a focusEl, we might need to add a focus listener to it.
  1641. if (focusEl) {
  1642. // getFocusEl might return a Component if a Container wishes to delegate focus to a descendant.
  1643. // Window can do this via its defaultFocus configuration which can reference a Button.
  1644. if (focusEl.isComponent) {
  1645. return focusEl.addFocusListener();
  1646. }
  1647. // If the focusEl is naturally focusable, then we always need a focus listener to drive the Component's
  1648. // onFocus handling.
  1649. // If *not* naturally focusable, then we only need the focus listener if the FocusManager is enabled.
  1650. needsTabIndex = focusEl.needsTabIndex();
  1651. if (!me.focusListenerAdded && (!needsTabIndex || Ext.FocusManager.enabled)) {
  1652. if (needsTabIndex) {
  1653. focusEl.dom.tabIndex = -1;
  1654. }
  1655. focusEl.on({
  1656. focus: me.onFocus,
  1657. blur: me.onBlur,
  1658. scope: me
  1659. });
  1660. me.focusListenerAdded = true;
  1661. }
  1662. }
  1663. },
  1664. /**
  1665. * @private
  1666. * <p>Returns the focus holder element associated with this Component. At the Component base class level, this function returns <code>undefined</code>.</p>
  1667. * <p>Subclasses which use embedded focusable elements (such as Window, Field and Button) should override this for use by the {@link #focus} method.</p>
  1668. * <p>Containers which need to participate in the {@link Ext.FocusManager FocusManager}'s navigation and Container focusing scheme also
  1669. * need to return a focusEl, although focus is only listened for in this case if the {@link Ext.FocusManager FocusManager} is {@link Ext.FocusManager#method-enable enable}d.</p>
  1670. * @returns {undefined} <code>undefined</code> because raw Components cannot by default hold focus.
  1671. */
  1672. getFocusEl: Ext.emptyFn,
  1673. isFocusable: function(c) {
  1674. var me = this,
  1675. focusEl;
  1676. if ((me.focusable !== false) && (focusEl = me.getFocusEl()) && me.rendered && !me.destroying && !me.isDestroyed && !me.disabled && me.isVisible(true)) {
  1677. // getFocusEl might return a Component if a Container wishes to delegate focus to a descendant.
  1678. // Window can do this via its defaultFocus configuration which can reference a Button.
  1679. if (focusEl.isComponent) {
  1680. return focusEl.isFocusable();
  1681. }
  1682. return focusEl && focusEl.dom && focusEl.isVisible();
  1683. }
  1684. },
  1685. // private
  1686. preFocus: Ext.emptyFn,
  1687. // private
  1688. onFocus: function(e) {
  1689. var me = this,
  1690. focusCls = me.focusCls,
  1691. focusEl = me.getFocusEl();
  1692. if (!me.disabled) {
  1693. me.preFocus(e);
  1694. if (focusCls && focusEl) {
  1695. focusEl.addCls(me.addClsWithUI(focusCls, true));
  1696. }
  1697. if (!me.hasFocus) {
  1698. me.hasFocus = true;
  1699. me.fireEvent('focus', me, e);
  1700. }
  1701. }
  1702. },
  1703. // private
  1704. beforeBlur : Ext.emptyFn,
  1705. // private
  1706. onBlur : function(e) {
  1707. var me = this,
  1708. focusCls = me.focusCls,
  1709. focusEl = me.getFocusEl();
  1710. if (me.destroying) {
  1711. return;
  1712. }
  1713. me.beforeBlur(e);
  1714. if (focusCls && focusEl) {
  1715. focusEl.removeCls(me.removeClsWithUI(focusCls, true));
  1716. }
  1717. if (me.validateOnBlur) {
  1718. me.validate();
  1719. }
  1720. me.hasFocus = false;
  1721. me.fireEvent('blur', me, e);
  1722. me.postBlur(e);
  1723. },
  1724. // private
  1725. postBlur : Ext.emptyFn,
  1726. /**
  1727. * Tests whether this Component matches the selector string.
  1728. * @param {String} selector The selector string to test against.
  1729. * @return {Boolean} True if this Component matches the selector.
  1730. */
  1731. is: function(selector) {
  1732. return Ext.ComponentQuery.is(this, selector);
  1733. },
  1734. /**
  1735. * Walks up the `ownerCt` axis looking for an ancestor Container which matches the passed simple selector.
  1736. *
  1737. * Example:
  1738. *
  1739. * var owningTabPanel = grid.up('tabpanel');
  1740. *
  1741. * @param {String} [selector] The simple selector to test.
  1742. * @return {Ext.container.Container} The matching ancestor Container (or `undefined` if no match was found).
  1743. */
  1744. up: function(selector) {
  1745. // Use bubble target to navigate upwards so that Components can implement their own hierarchy.
  1746. // For example Menus implement getBubbleTarget because they have a parentMenu or ownerButton as an
  1747. // upward link depending upon how they are owned and triggered.
  1748. var result = this.getBubbleTarget();
  1749. if (selector) {
  1750. for (; result; result = result.getBubbleTarget()) {
  1751. if (Ext.ComponentQuery.is(result, selector)) {
  1752. return result;
  1753. }
  1754. }
  1755. }
  1756. return result;
  1757. },
  1758. /**
  1759. * Returns the next sibling of this Component.
  1760. *
  1761. * Optionally selects the next sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.
  1762. *
  1763. * May also be refered to as **`next()`**
  1764. *
  1765. * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with
  1766. * {@link #nextNode}
  1767. * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following items.
  1768. * @return {Ext.Component} The next sibling (or the next sibling which matches the selector).
  1769. * Returns null if there is no matching sibling.
  1770. */
  1771. nextSibling: function(selector) {
  1772. var o = this.ownerCt, it, last, idx, c;
  1773. if (o) {
  1774. it = o.items;
  1775. idx = it.indexOf(this) + 1;
  1776. if (idx) {
  1777. if (selector) {
  1778. for (last = it.getCount(); idx < last; idx++) {
  1779. if ((c = it.getAt(idx)).is(selector)) {
  1780. return c;
  1781. }
  1782. }
  1783. } else {
  1784. if (idx < it.getCount()) {
  1785. return it.getAt(idx);
  1786. }
  1787. }
  1788. }
  1789. }
  1790. return null;
  1791. },
  1792. /**
  1793. * Returns the previous sibling of this Component.
  1794. *
  1795. * Optionally selects the previous sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery}
  1796. * selector.
  1797. *
  1798. * May also be refered to as **`prev()`**
  1799. *
  1800. * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with
  1801. * {@link #previousNode}
  1802. * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding items.
  1803. * @return {Ext.Component} The previous sibling (or the previous sibling which matches the selector).
  1804. * Returns null if there is no matching sibling.
  1805. */
  1806. previousSibling: function(selector) {
  1807. var o = this.ownerCt, it, idx, c;
  1808. if (o) {
  1809. it = o.items;
  1810. idx = it.indexOf(this);
  1811. if (idx != -1) {
  1812. if (selector) {
  1813. for (--idx; idx >= 0; idx--) {
  1814. if ((c = it.getAt(idx)).is(selector)) {
  1815. return c;
  1816. }
  1817. }
  1818. } else {
  1819. if (idx) {
  1820. return it.getAt(--idx);
  1821. }
  1822. }
  1823. }
  1824. }
  1825. return null;
  1826. },
  1827. /**
  1828. * Returns the previous node in the Component tree in tree traversal order.
  1829. *
  1830. * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the
  1831. * tree in reverse order to attempt to find a match. Contrast with {@link #previousSibling}.
  1832. * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding nodes.
  1833. * @return {Ext.Component} The previous node (or the previous node which matches the selector).
  1834. * Returns null if there is no matching node.
  1835. */
  1836. previousNode: function(selector, /* private */ includeSelf) {
  1837. var node = this,
  1838. ownerCt = node.ownerCt,
  1839. result,
  1840. it, i, sib;
  1841. // If asked to include self, test me
  1842. if (includeSelf && node.is(selector)) {
  1843. return node;
  1844. }
  1845. if (ownerCt) {
  1846. for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
  1847. sib = it[i];
  1848. if (sib.query) {
  1849. result = sib.query(selector);
  1850. result = result[result.length - 1];
  1851. if (result) {
  1852. return result;
  1853. }
  1854. }
  1855. if (sib.is(selector)) {
  1856. return sib;
  1857. }
  1858. }
  1859. return ownerCt.previousNode(selector, true);
  1860. }
  1861. return null;
  1862. },
  1863. /**
  1864. * Returns the next node in the Component tree in tree traversal order.
  1865. *
  1866. * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the
  1867. * tree to attempt to find a match. Contrast with {@link #nextSibling}.
  1868. * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes.
  1869. * @return {Ext.Component} The next node (or the next node which matches the selector).
  1870. * Returns null if there is no matching node.
  1871. */
  1872. nextNode: function(selector, /* private */ includeSelf) {
  1873. var node = this,
  1874. ownerCt = node.ownerCt,
  1875. result,
  1876. it, len, i, sib;
  1877. // If asked to include self, test me
  1878. if (includeSelf && node.is(selector)) {
  1879. return node;
  1880. }
  1881. if (ownerCt) {
  1882. for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) + 1, len = it.length; i < len; i++) {
  1883. sib = it[i];
  1884. if (sib.is(selector)) {
  1885. return sib;
  1886. }
  1887. if (sib.down) {
  1888. result = sib.down(selector);
  1889. if (result) {
  1890. return result;
  1891. }
  1892. }
  1893. }
  1894. return ownerCt.nextNode(selector);
  1895. }
  1896. return null;
  1897. },
  1898. /**
  1899. * Retrieves the id of this component. Will autogenerate an id if one has not already been set.
  1900. * @return {String}
  1901. */
  1902. getId : function() {
  1903. return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
  1904. },
  1905. /**
  1906. * Returns the value of {@link #itemId} assigned to this component, or when that
  1907. * is not set, returns the value of {@link #id}.
  1908. * @return {String}
  1909. */
  1910. getItemId : function() {
  1911. return this.itemId || this.id;
  1912. },
  1913. /**
  1914. * Retrieves the top level element representing this component.
  1915. * @return {Ext.dom.Element}
  1916. */
  1917. getEl : function() {
  1918. return this.el;
  1919. },
  1920. /**
  1921. * This is used to determine where to insert the 'html', 'contentEl' and 'items' in this component.
  1922. * @private
  1923. */
  1924. getTargetEl: function() {
  1925. return this.frameBody || this.el;
  1926. },
  1927. /**
  1928. * @private
  1929. * Returns the CSS style object which will set the Component's scroll styles. This must be applied
  1930. * to the {@link #getTargetEl target element}.
  1931. */
  1932. getOverflowStyle: function() {
  1933. var me = this,
  1934. result = null;
  1935. if (typeof me.autoScroll == 'boolean') {
  1936. result = {
  1937. overflow: me.autoScroll ? 'auto' : ''
  1938. };
  1939. } else if (me.overflowX !== undefined || me.overflowY !== undefined) {
  1940. result = {
  1941. 'overflow-x': (me.overflowX||''),
  1942. 'overflow-y': (me.overflowY||'')
  1943. };
  1944. }
  1945. // The scrollable container element must be non-statically positioned or IE6/7 will make
  1946. // positioned children stay in place rather than scrolling with the rest of the content
  1947. if (result && (Ext.isIE6 || Ext.isIE7)) {
  1948. result.position = 'relative';
  1949. }
  1950. return result;
  1951. },
  1952. /**
  1953. * Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
  1954. * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).
  1955. *
  1956. * **If using your own subclasses, be aware that a Component must register its own xtype to participate in
  1957. * determination of inherited xtypes.**
  1958. *
  1959. * For a list of all available xtypes, see the {@link Ext.Component} header.
  1960. *
  1961. * Example usage:
  1962. *
  1963. * var t = new Ext.form.field.Text();
  1964. * var isText = t.isXType('textfield'); // true
  1965. * var isBoxSubclass = t.isXType('field'); // true, descended from Ext.form.field.Base
  1966. * var isBoxInstance = t.isXType('field', true); // false, not a direct Ext.form.field.Base instance
  1967. *
  1968. * @param {String} xtype The xtype to check for this Component
  1969. * @param {Boolean} [shallow=false] True to check whether this Component is directly of the specified xtype, false to
  1970. * check whether this Component is descended from the xtype.
  1971. * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
  1972. */
  1973. isXType: function(xtype, shallow) {
  1974. if (shallow) {
  1975. return this.xtype === xtype;
  1976. }
  1977. else {
  1978. return this.xtypesMap[xtype];
  1979. }
  1980. },
  1981. /**
  1982. * Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all available xtypes, see the
  1983. * {@link Ext.Component} header.
  1984. *
  1985. * **If using your own subclasses, be aware that a Component must register its own xtype to participate in
  1986. * determination of inherited xtypes.**
  1987. *
  1988. * Example usage:
  1989. *
  1990. * var t = new Ext.form.field.Text();
  1991. * alert(t.getXTypes()); // alerts 'component/field/textfield'
  1992. *
  1993. * @return {String} The xtype hierarchy string
  1994. */
  1995. getXTypes: function() {
  1996. var self = this.self,
  1997. xtypes, parentPrototype, parentXtypes;
  1998. if (!self.xtypes) {
  1999. xtypes = [];
  2000. parentPrototype = this;
  2001. while (parentPrototype) {
  2002. parentXtypes = parentPrototype.xtypes;
  2003. if (parentXtypes !== undefined) {
  2004. xtypes.unshift.apply(xtypes, parentXtypes);
  2005. }
  2006. parentPrototype = parentPrototype.superclass;
  2007. }
  2008. self.xtypeChain = xtypes;
  2009. self.xtypes = xtypes.join('/');
  2010. }
  2011. return self.xtypes;
  2012. },
  2013. /**
  2014. * Update the content area of a component.
  2015. * @param {String/Object} htmlOrData If this component has been configured with a template via the tpl config then
  2016. * it will use this argument as data to populate the template. If this component was not configured with a template,
  2017. * the components content area will be updated via Ext.Element update
  2018. * @param {Boolean} [loadScripts=false] Only legitimate when using the html configuration.
  2019. * @param {Function} [callback] Only legitimate when using the html configuration. Callback to execute when
  2020. * scripts have finished loading
  2021. */
  2022. update : function(htmlOrData, loadScripts, cb) {
  2023. var me = this;
  2024. if (me.tpl && !Ext.isString(htmlOrData)) {
  2025. me.data = htmlOrData;
  2026. if (me.rendered) {
  2027. me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
  2028. }
  2029. } else {
  2030. me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
  2031. if (me.rendered) {
  2032. me.getTargetEl().update(me.html, loadScripts, cb);
  2033. }
  2034. }
  2035. if (me.rendered) {
  2036. me.updateLayout();
  2037. }
  2038. },
  2039. /**
  2040. * Convenience function to hide or show this component by boolean.
  2041. * @param {Boolean} visible True to show, false to hide
  2042. * @return {Ext.Component} this
  2043. */
  2044. setVisible : function(visible) {
  2045. return this[visible ? 'show': 'hide']();
  2046. },
  2047. /**
  2048. * Returns true if this component is visible.
  2049. *
  2050. * @param {Boolean} [deep=false] Pass `true` to interrogate the visibility status of all parent Containers to
  2051. * determine whether this Component is truly visible to the user.
  2052. *
  2053. * Generally, to determine whether a Component is hidden, the no argument form is needed. For example when creating
  2054. * dynamically laid out UIs in a hidden Container before showing them.
  2055. *
  2056. * @return {Boolean} True if this component is visible, false otherwise.
  2057. */
  2058. isVisible: function(deep) {
  2059. var me = this,
  2060. child = me,
  2061. visible = me.rendered && !me.hidden,
  2062. ancestor = me.ownerCt;
  2063. // Clear hiddenOwnerCt property
  2064. me.hiddenAncestor = false;
  2065. if (me.destroyed) {
  2066. return false;
  2067. }
  2068. if (deep && visible && ancestor) {
  2069. while (ancestor) {
  2070. // If any ancestor is hidden, then this is hidden.
  2071. // If an ancestor Panel (only Panels have a collapse method) is collapsed,
  2072. // then its layoutTarget (body) is hidden, so this is hidden unless its within a
  2073. // docked item; they are still visible when collapsed (Unless they themseves are hidden)
  2074. if (ancestor.hidden || (ancestor.collapsed &&
  2075. !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
  2076. // Store hiddenOwnerCt property if needed
  2077. me.hiddenAncestor = ancestor;
  2078. visible = false;
  2079. break;
  2080. }
  2081. child = ancestor;
  2082. ancestor = ancestor.ownerCt;
  2083. }
  2084. }
  2085. return visible;
  2086. },
  2087. onBoxReady: function(){
  2088. var me = this;
  2089. if (me.disableOnBoxReady) {
  2090. me.onDisable();
  2091. } else if (me.enableOnBoxReady) {
  2092. me.onEnable();
  2093. }
  2094. if (me.resizable) {
  2095. me.initResizable(me.resizable);
  2096. }
  2097. // Draggability must be initialized after resizability
  2098. // Because if we have to be wrapped, the resizer wrapper must be dragged as a pseudo-Component
  2099. if (me.draggable) {
  2100. me.initDraggable();
  2101. }
  2102. },
  2103. /**
  2104. * Enable the component
  2105. * @param {Boolean} [silent=false] Passing true will supress the 'enable' event from being fired.
  2106. */
  2107. enable: function(silent) {
  2108. var me = this;
  2109. delete me.disableOnBoxReady;
  2110. me.removeCls(me.disabledCls);
  2111. if (me.rendered) {
  2112. me.onEnable();
  2113. } else {
  2114. me.enableOnBoxReady = true;
  2115. }
  2116. me.disabled = false;
  2117. delete me.resetDisable;
  2118. if (silent !== true) {
  2119. me.fireEvent('enable', me);
  2120. }
  2121. return me;
  2122. },
  2123. /**
  2124. * Disable the component.
  2125. * @param {Boolean} [silent=false] Passing true will supress the 'disable' event from being fired.
  2126. */
  2127. disable: function(silent) {
  2128. var me = this;
  2129. delete me.enableOnBoxReady;
  2130. me.addCls(me.disabledCls);
  2131. if (me.rendered) {
  2132. me.onDisable();
  2133. } else {
  2134. me.disableOnBoxReady = true;
  2135. }
  2136. me.disabled = true;
  2137. if (silent !== true) {
  2138. delete me.resetDisable;
  2139. me.fireEvent('disable', me);
  2140. }
  2141. return me;
  2142. },
  2143. /**
  2144. * Allows addition of behavior to the enable operation.
  2145. * After calling the superclass’s onEnable, the Component will be enabled.
  2146. *
  2147. * @template
  2148. * @protected
  2149. */
  2150. onEnable: function() {
  2151. if (this.maskOnDisable) {
  2152. this.el.dom.disabled = false;
  2153. this.unmask();
  2154. }
  2155. },
  2156. /**
  2157. * Allows addition of behavior to the disable operation.
  2158. * After calling the superclass’s onDisable, the Component will be disabled.
  2159. *
  2160. * @template
  2161. * @protected
  2162. */
  2163. onDisable : function() {
  2164. var me = this,
  2165. focusCls = me.focusCls,
  2166. focusEl = me.getFocusEl();
  2167. if (focusCls && focusEl) {
  2168. focusEl.removeCls(me.removeClsWithUI(focusCls, true));
  2169. }
  2170. if (me.maskOnDisable) {
  2171. me.el.dom.disabled = true;
  2172. me.mask();
  2173. }
  2174. },
  2175. mask: function() {
  2176. var box = this.lastBox,
  2177. target = this.getMaskTarget(),
  2178. args = [];
  2179. // Pass it the height of our element if we know it.
  2180. if (box) {
  2181. args[2] = box.height;
  2182. }
  2183. target.mask.apply(target, args);
  2184. },
  2185. unmask: function() {
  2186. this.getMaskTarget().unmask();
  2187. },
  2188. getMaskTarget: function(){
  2189. return this.el;
  2190. },
  2191. /**
  2192. * Method to determine whether this Component is currently disabled.
  2193. * @return {Boolean} the disabled state of this Component.
  2194. */
  2195. isDisabled : function() {
  2196. return this.disabled;
  2197. },
  2198. /**
  2199. * Enable or disable the component.
  2200. * @param {Boolean} disabled True to disable.
  2201. */
  2202. setDisabled : function(disabled) {
  2203. return this[disabled ? 'disable': 'enable']();
  2204. },
  2205. /**
  2206. * Method to determine whether this Component is currently set to hidden.
  2207. * @return {Boolean} the hidden state of this Component.
  2208. */
  2209. isHidden : function() {
  2210. return this.hidden;
  2211. },
  2212. /**
  2213. * Adds a CSS class to the top level element representing this component.
  2214. * @param {String/String[]} cls The CSS class name to add
  2215. * @return {Ext.Component} Returns the Component to allow method chaining.
  2216. */
  2217. addCls : function(cls) {
  2218. var me = this,
  2219. el = me.rendered ? me.el : me.protoEl;
  2220. el.addCls.apply(el, arguments);
  2221. return me;
  2222. },
  2223. /**
  2224. * @inheritdoc Ext.AbstractComponent#addCls
  2225. * @deprecated 4.1 Use {@link #addCls} instead.
  2226. */
  2227. addClass : function() {
  2228. return this.addCls.apply(this, arguments);
  2229. },
  2230. /**
  2231. * Checks if the specified CSS class exists on this element's DOM node.
  2232. * @param {String} className The CSS class to check for
  2233. * @return {Boolean} True if the class exists, else false
  2234. * @method
  2235. */
  2236. hasCls: function (cls) {
  2237. var me = this,
  2238. el = me.rendered ? me.el : me.protoEl;
  2239. return el.hasCls.apply(el, arguments);
  2240. },
  2241. /**
  2242. * Removes a CSS class from the top level element representing this component.
  2243. * @param {String/String[]} cls The CSS class name to remove
  2244. * @returns {Ext.Component} Returns the Component to allow method chaining.
  2245. */
  2246. removeCls : function(cls) {
  2247. var me = this,
  2248. el = me.rendered ? me.el : me.protoEl;
  2249. el.removeCls.apply(el, arguments);
  2250. return me;
  2251. },
  2252. //<debug>
  2253. removeClass : function() {
  2254. if (Ext.isDefined(Ext.global.console)) {
  2255. Ext.global.console.warn('Ext.Component: removeClass has been deprecated. Please use removeCls.');
  2256. }
  2257. return this.removeCls.apply(this, arguments);
  2258. },
  2259. //</debug>
  2260. addOverCls: function() {
  2261. var me = this;
  2262. if (!me.disabled) {
  2263. me.el.addCls(me.overCls);
  2264. }
  2265. },
  2266. removeOverCls: function() {
  2267. this.el.removeCls(this.overCls);
  2268. },
  2269. addListener : function(element, listeners, scope, options) {
  2270. var me = this,
  2271. fn,
  2272. option;
  2273. if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
  2274. if (options.element) {
  2275. fn = listeners;
  2276. listeners = {};
  2277. listeners[element] = fn;
  2278. element = options.element;
  2279. if (scope) {
  2280. listeners.scope = scope;
  2281. }
  2282. for (option in options) {
  2283. if (options.hasOwnProperty(option)) {
  2284. if (me.eventOptionsRe.test(option)) {
  2285. listeners[option] = options[option];
  2286. }
  2287. }
  2288. }
  2289. }
  2290. // At this point we have a variable called element,
  2291. // and a listeners object that can be passed to on
  2292. if (me[element] && me[element].on) {
  2293. me.mon(me[element], listeners);
  2294. } else {
  2295. me.afterRenderEvents = me.afterRenderEvents || {};
  2296. if (!me.afterRenderEvents[element]) {
  2297. me.afterRenderEvents[element] = [];
  2298. }
  2299. me.afterRenderEvents[element].push(listeners);
  2300. }
  2301. }
  2302. return me.mixins.observable.addListener.apply(me, arguments);
  2303. },
  2304. // inherit docs
  2305. removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
  2306. var me = this,
  2307. element = managedListener.options ? managedListener.options.element : null;
  2308. if (element) {
  2309. element = me[element];
  2310. if (element && element.un) {
  2311. if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
  2312. element.un(managedListener.ename, managedListener.fn, managedListener.scope);
  2313. if (!isClear) {
  2314. Ext.Array.remove(me.managedListeners, managedListener);
  2315. }
  2316. }
  2317. }
  2318. } else {
  2319. return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
  2320. }
  2321. },
  2322. /**
  2323. * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
  2324. * @return {Ext.container.Container} the Container which owns this Component.
  2325. */
  2326. getBubbleTarget : function() {
  2327. return this.ownerCt;
  2328. },
  2329. /**
  2330. * Method to determine whether this Component is floating.
  2331. * @return {Boolean} the floating state of this component.
  2332. */
  2333. isFloating : function() {
  2334. return this.floating;
  2335. },
  2336. /**
  2337. * Method to determine whether this Component is draggable.
  2338. * @return {Boolean} the draggable state of this component.
  2339. */
  2340. isDraggable : function() {
  2341. return !!this.draggable;
  2342. },
  2343. /**
  2344. * Method to determine whether this Component is droppable.
  2345. * @return {Boolean} the droppable state of this component.
  2346. */
  2347. isDroppable : function() {
  2348. return !!this.droppable;
  2349. },
  2350. /**
  2351. * Method to manage awareness of when components are added to their
  2352. * respective Container, firing an #added event. References are
  2353. * established at add time rather than at render time.
  2354. *
  2355. * Allows addition of behavior when a Component is added to a
  2356. * Container. At this stage, the Component is in the parent
  2357. * Container's collection of child items. After calling the
  2358. * superclass's onAdded, the ownerCt reference will be present,
  2359. * and if configured with a ref, the refOwner will be set.
  2360. *
  2361. * @param {Ext.container.Container} container Container which holds the component
  2362. * @param {Number} pos Position at which the component was added
  2363. *
  2364. * @template
  2365. * @protected
  2366. */
  2367. onAdded : function(container, pos) {
  2368. var me = this;
  2369. me.ownerCt = container;
  2370. if (me.hasListeners.added) {
  2371. me.fireEvent('added', me, container, pos);
  2372. }
  2373. },
  2374. /**
  2375. * Method to manage awareness of when components are removed from their
  2376. * respective Container, firing a #removed event. References are properly
  2377. * cleaned up after removing a component from its owning container.
  2378. *
  2379. * Allows addition of behavior when a Component is removed from
  2380. * its parent Container. At this stage, the Component has been
  2381. * removed from its parent Container's collection of child items,
  2382. * but has not been destroyed (It will be destroyed if the parent
  2383. * Container's autoDestroy is true, or if the remove call was
  2384. * passed a truthy second parameter). After calling the
  2385. * superclass's onRemoved, the ownerCt and the refOwner will not
  2386. * be present.
  2387. * @param {Boolean} destroying Will be passed as true if the Container performing the remove operation will delete this
  2388. * Component upon remove.
  2389. *
  2390. * @template
  2391. * @protected
  2392. */
  2393. onRemoved : function(destroying) {
  2394. var me = this;
  2395. if (me.hasListeners.removed) {
  2396. me.fireEvent('removed', me, me.ownerCt);
  2397. }
  2398. delete me.ownerCt;
  2399. delete me.ownerLayout;
  2400. },
  2401. /**
  2402. * Invoked before the Component is destroyed.
  2403. *
  2404. * @method
  2405. * @template
  2406. * @protected
  2407. */
  2408. beforeDestroy : Ext.emptyFn,
  2409. /**
  2410. * Allows addition of behavior to the resize operation.
  2411. *
  2412. * Called when Ext.resizer.Resizer#drag event is fired.
  2413. *
  2414. * @method
  2415. * @template
  2416. * @protected
  2417. */
  2418. onResize : Ext.emptyFn,
  2419. /**
  2420. * Sets the width and height of this Component. This method fires the {@link #resize} event. This method can accept
  2421. * either width and height as separate arguments, or you can pass a size object like `{width:10, height:20}`.
  2422. *
  2423. * @param {Number/String/Object} width The new width to set. This may be one of:
  2424. *
  2425. * - A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
  2426. * - A String used to set the CSS width style.
  2427. * - A size object in the format `{width: widthValue, height: heightValue}`.
  2428. * - `undefined` to leave the width unchanged.
  2429. *
  2430. * @param {Number/String} height The new height to set (not required if a size object is passed as the first arg).
  2431. * This may be one of:
  2432. *
  2433. * - A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
  2434. * - A String used to set the CSS height style. Animation may **not** be used.
  2435. * - `undefined` to leave the height unchanged.
  2436. *
  2437. * @return {Ext.Component} this
  2438. */
  2439. setSize : function(width, height) {
  2440. var me = this;
  2441. // support for standard size objects
  2442. if (width && typeof width == 'object') {
  2443. height = width.height;
  2444. width = width.width;
  2445. }
  2446. // Constrain within configured maxima
  2447. if (typeof width == 'number') {
  2448. me.width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
  2449. } else if (width === null) {
  2450. delete me.width;
  2451. }
  2452. if (typeof height == 'number') {
  2453. me.height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
  2454. } else if (height === null) {
  2455. delete me.height;
  2456. }
  2457. // If not rendered, all we need to is set the properties.
  2458. // The initial layout will set the size
  2459. if (me.rendered && me.isVisible()) {
  2460. // If we are changing size, then we are not the root.
  2461. me.updateLayout({
  2462. isRoot: false
  2463. });
  2464. }
  2465. return me;
  2466. },
  2467. /**
  2468. * Determines whether this Component is the root of a layout. This returns `true` if
  2469. * this component can run its layout without assistance from or impact on its owner.
  2470. * If this component cannot run its layout given these restrictions, `false` is returned
  2471. * and its owner will be considered as the next candidate for the layout root.
  2472. *
  2473. * Setting the {@link #_isLayoutRoot} property to `true` causes this method to always
  2474. * return `true`. This may be useful when updating a layout of a Container which shrink
  2475. * wraps content, and you know that it will not change size, and so can safely be the
  2476. * topmost participant in the layout run.
  2477. * @protected
  2478. */
  2479. isLayoutRoot: function() {
  2480. var me = this,
  2481. ownerLayout = me.ownerLayout;
  2482. // Return true if we have been explicitly flagged as the layout root, or if we are floating.
  2483. // Sometimes floating Components get an ownerCt ref injected into them which is *not* a true ownerCt, merely
  2484. // an upward link for reference purposes. For example a grid column menu is linked to the
  2485. // owning header via an ownerCt reference.
  2486. if (!ownerLayout || me._isLayoutRoot || me.floating) {
  2487. return true;
  2488. }
  2489. return ownerLayout.isItemLayoutRoot(me);
  2490. },
  2491. /**
  2492. * Returns true if layout is suspended for this component. This can come from direct
  2493. * suspension of this component's layout activity ({@link Ext.Container#suspendLayout}) or if one
  2494. * of this component's containers is suspended.
  2495. *
  2496. * @return {Boolean} True layout of this component is suspended.
  2497. */
  2498. isLayoutSuspended: function () {
  2499. var comp = this,
  2500. ownerLayout;
  2501. while (comp) {
  2502. if (comp.layoutSuspendCount || comp.suspendLayout) {
  2503. return true;
  2504. }
  2505. ownerLayout = comp.ownerLayout;
  2506. if (!ownerLayout) {
  2507. break;
  2508. }
  2509. // TODO - what about suspending a Layout instance?
  2510. // this works better than ownerCt since ownerLayout means "is managed by" in
  2511. // the proper sense... some floating components have ownerCt but won't have an
  2512. // ownerLayout
  2513. comp = ownerLayout.owner;
  2514. }
  2515. return false;
  2516. },
  2517. /**
  2518. * Updates this component's layout. If this update effects this components {@link #ownerCt},
  2519. * that component's `updateLayout` method will be called to perform the layout instead.
  2520. * Otherwise, just this component (and its child items) will layout.
  2521. *
  2522. * @param {Object} options An object with layout options.
  2523. * @param {Boolean} options.defer True if this layout should be deferred.
  2524. * @param {Boolean} options.isRoot True if this layout should be the root of the layout.
  2525. */
  2526. updateLayout: function (options) {
  2527. var me = this,
  2528. defer,
  2529. isRoot = options && options.isRoot;
  2530. if (!me.rendered || me.layoutSuspendCount || me.suspendLayout) {
  2531. return;
  2532. }
  2533. if (me.hidden) {
  2534. Ext.AbstractComponent.cancelLayout(me);
  2535. } else if (typeof isRoot != 'boolean') {
  2536. isRoot = me.isLayoutRoot();
  2537. }
  2538. // if we aren't the root, see if our ownerLayout will handle it...
  2539. if (isRoot || !me.ownerLayout || !me.ownerLayout.onContentChange(me)) {
  2540. // either we are the root or our ownerLayout doesn't care
  2541. if (!me.isLayoutSuspended()) {
  2542. // we aren't suspended (knew that), but neither is any of our ownerCt's...
  2543. defer = (options && options.hasOwnProperty('defer')) ? options.defer : me.deferLayouts;
  2544. Ext.AbstractComponent.updateLayout(me, defer);
  2545. }
  2546. }
  2547. },
  2548. /**
  2549. * Returns an object that describes how this component's width and height are managed.
  2550. * All of these objects are shared and should not be modified.
  2551. *
  2552. * @return {Object} The size model for this component.
  2553. * @return {Ext.layout.SizeModel} return.width The {@link Ext.layout.SizeModel size model}
  2554. * for the width.
  2555. * @return {Ext.layout.SizeModel} return.height The {@link Ext.layout.SizeModel size model}
  2556. * for the height.
  2557. */
  2558. getSizeModel: function (ownerCtSizeModel) {
  2559. var me = this,
  2560. models = Ext.layout.SizeModel,
  2561. ownerContext = me.componentLayout.ownerContext,
  2562. width = me.width,
  2563. height = me.height,
  2564. typeofWidth, typeofHeight,
  2565. hasPixelWidth, hasPixelHeight,
  2566. heightModel, ownerLayout, policy, shrinkWrap, topLevel, widthModel;
  2567. if (ownerContext) {
  2568. // If we are in the middle of a running layout, always report the current,
  2569. // dynamic size model rather than recompute it. This is not (only) a time
  2570. // saving thing, but a correctness thing since we cannot get the right answer
  2571. // otherwise.
  2572. widthModel = ownerContext.widthModel;
  2573. heightModel = ownerContext.heightModel;
  2574. }
  2575. if (!widthModel || !heightModel) {
  2576. hasPixelWidth = ((typeofWidth = typeof width) == 'number');
  2577. hasPixelHeight = ((typeofHeight = typeof height) == 'number');
  2578. topLevel = me.floating || !(ownerLayout = me.ownerLayout);
  2579. // Floating or no owner layout, e.g. rendered using renderTo
  2580. if (topLevel) {
  2581. policy = Ext.layout.Layout.prototype.autoSizePolicy;
  2582. shrinkWrap = me.floating ? 3 : me.shrinkWrap;
  2583. if (hasPixelWidth) {
  2584. widthModel = models.configured;
  2585. }
  2586. if (hasPixelHeight) {
  2587. heightModel = models.configured;
  2588. }
  2589. } else {
  2590. policy = ownerLayout.getItemSizePolicy(me, ownerCtSizeModel);
  2591. shrinkWrap = ownerLayout.isItemShrinkWrap(me);
  2592. }
  2593. shrinkWrap = (shrinkWrap === true) ? 3 : (shrinkWrap || 0); // false->0, true->3
  2594. // Now that we have shrinkWrap as a 0-3 value, we need to turn off shrinkWrap
  2595. // bits for any dimension that has a configured size not in pixels. These must
  2596. // be read from the DOM.
  2597. //
  2598. if (topLevel && shrinkWrap) {
  2599. if (width && typeofWidth == 'string') {
  2600. shrinkWrap &= 2; // percentage, "30em" or whatever - not width shrinkWrap
  2601. }
  2602. if (height && typeofHeight == 'string') {
  2603. shrinkWrap &= 1; // percentage, "30em" or whatever - not height shrinkWrap
  2604. }
  2605. }
  2606. if (shrinkWrap !== 3) {
  2607. if (!ownerCtSizeModel) {
  2608. ownerCtSizeModel = me.ownerCt && me.ownerCt.getSizeModel();
  2609. }
  2610. if (ownerCtSizeModel) {
  2611. shrinkWrap |= (ownerCtSizeModel.width.shrinkWrap ? 1 : 0) | (ownerCtSizeModel.height.shrinkWrap ? 2 : 0);
  2612. }
  2613. }
  2614. if (!widthModel) {
  2615. if (!policy.setsWidth) {
  2616. if (hasPixelWidth) {
  2617. widthModel = models.configured;
  2618. } else {
  2619. widthModel = (shrinkWrap & 1) ? models.shrinkWrap : models.natural;
  2620. }
  2621. } else if (policy.readsWidth) {
  2622. if (hasPixelWidth) {
  2623. widthModel = models.calculatedFromConfigured;
  2624. } else {
  2625. widthModel = (shrinkWrap & 1) ? models.calculatedFromShrinkWrap :
  2626. models.calculatedFromNatural;
  2627. }
  2628. } else {
  2629. widthModel = models.calculated;
  2630. }
  2631. }
  2632. if (!heightModel) {
  2633. if (!policy.setsHeight) {
  2634. if (hasPixelHeight) {
  2635. heightModel = models.configured;
  2636. } else {
  2637. heightModel = (shrinkWrap & 2) ? models.shrinkWrap : models.natural;
  2638. }
  2639. } else if (policy.readsHeight) {
  2640. if (hasPixelHeight) {
  2641. heightModel = models.calculatedFromConfigured;
  2642. } else {
  2643. heightModel = (shrinkWrap & 2) ? models.calculatedFromShrinkWrap :
  2644. models.calculatedFromNatural;
  2645. }
  2646. } else {
  2647. heightModel = models.calculated;
  2648. }
  2649. }
  2650. }
  2651. // We return one of the cached objects with the proper "width" and "height" as the
  2652. // sizeModels we have determined.
  2653. return widthModel.pairsByHeightOrdinal[heightModel.ordinal];
  2654. },
  2655. isDescendant: function(ancestor) {
  2656. if (ancestor.isContainer) {
  2657. for (var c = this.ownerCt; c; c = c.ownerCt) {
  2658. if (c === ancestor) {
  2659. return true;
  2660. }
  2661. }
  2662. }
  2663. return false;
  2664. },
  2665. /**
  2666. * This method needs to be called whenever you change something on this component that requires the Component's
  2667. * layout to be recalculated.
  2668. * @return {Ext.container.Container} this
  2669. */
  2670. doComponentLayout : function() {
  2671. this.updateLayout();
  2672. return this;
  2673. },
  2674. /**
  2675. * Forces this component to redo its componentLayout.
  2676. * @deprecated 4.1.0 Use {@link #updateLayout} instead.
  2677. */
  2678. forceComponentLayout: function () {
  2679. this.updateLayout();
  2680. },
  2681. // @private
  2682. setComponentLayout : function(layout) {
  2683. var currentLayout = this.componentLayout;
  2684. if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
  2685. currentLayout.setOwner(null);
  2686. }
  2687. this.componentLayout = layout;
  2688. layout.setOwner(this);
  2689. },
  2690. getComponentLayout : function() {
  2691. var me = this;
  2692. if (!me.componentLayout || !me.componentLayout.isLayout) {
  2693. me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
  2694. }
  2695. return me.componentLayout;
  2696. },
  2697. /**
  2698. * Called by the layout system after the Component has been layed out.
  2699. *
  2700. * @param {Number} width The width that was set
  2701. * @param {Number} height The height that was set
  2702. * @param {Number} oldWidth The old width. <code>undefined</code> if this was the initial layout.
  2703. * @param {Number} oldHeight The old height. <code>undefined</code> if this was the initial layout.
  2704. *
  2705. * @template
  2706. * @protected
  2707. */
  2708. afterComponentLayout: function(width, height, oldWidth, oldHeight) {
  2709. var me = this,
  2710. floaters, len, i, floater;
  2711. if (++me.componentLayoutCounter === 1) {
  2712. me.afterFirstLayout(width, height);
  2713. }
  2714. // Contained autoShow items must be shown upon next layout of the Container
  2715. if (me.floatingItems) {
  2716. floaters = me.floatingItems.items;
  2717. len = floaters.length;
  2718. for (i = 0; i < len; i++) {
  2719. floater = floaters[i];
  2720. if (!floater.rendered && floater.autoShow) {
  2721. floater.show();
  2722. }
  2723. }
  2724. }
  2725. if (me.hasListeners.resize && (width !== oldWidth || height !== oldHeight)) {
  2726. me.fireEvent('resize', me, width, height, oldWidth, oldHeight);
  2727. }
  2728. },
  2729. /**
  2730. * Occurs before componentLayout is run. Returning false from this method will prevent the componentLayout from
  2731. * being executed.
  2732. *
  2733. * @param {Number} adjWidth The box-adjusted width that was set
  2734. * @param {Number} adjHeight The box-adjusted height that was set
  2735. *
  2736. * @template
  2737. * @protected
  2738. */
  2739. beforeComponentLayout: function(width, height) {
  2740. return true;
  2741. },
  2742. /**
  2743. * Sets the left and top of the component. To set the page XY position instead, use {@link Ext.Component#setPagePosition setPagePosition}. This
  2744. * method fires the {@link #move} event.
  2745. * @param {Number} left The new left
  2746. * @param {Number} top The new top
  2747. * @param {Boolean/Object} [animate] If true, the Component is _animated_ into its new position. You may also pass an
  2748. * animation configuration.
  2749. * @return {Ext.Component} this
  2750. */
  2751. setPosition : function(x, y, animate) {
  2752. var me = this,
  2753. pos = me.beforeSetPosition.apply(me, arguments);
  2754. if (pos && me.rendered) {
  2755. // Convert position WRT RTL
  2756. pos = me.convertPosition(pos);
  2757. // Proceed only if the new position is different from the current one.
  2758. if (pos.left !== me.el.getLeft() || pos.top !== me.el.getTop()) {
  2759. if (animate) {
  2760. me.stopAnimation();
  2761. me.animate(Ext.apply({
  2762. duration: 1000,
  2763. listeners: {
  2764. afteranimate: Ext.Function.bind(me.afterSetPosition, me, [pos.left, pos.top])
  2765. },
  2766. to: pos
  2767. }, animate));
  2768. } else {
  2769. // Must use Element's methods to set element position because, if it is a Layer (floater), it may need to sync a shadow
  2770. // We must also only set the properties which are defined because Element.setLeftTop autos any undefined coordinates
  2771. if (pos.left !== undefined && pos.top !== undefined) {
  2772. me.el.setLeftTop(pos.left, pos.top);
  2773. } else if (pos.left !== undefined) {
  2774. me.el.setLeft(pos.left);
  2775. } else if (pos.top !==undefined) {
  2776. me.el.setTop(pos.top);
  2777. }
  2778. me.afterSetPosition(pos.left, pos.top);
  2779. }
  2780. }
  2781. }
  2782. return me;
  2783. },
  2784. /**
  2785. * @private Template method called before a Component is positioned.
  2786. */
  2787. beforeSetPosition: function (x, y, animate) {
  2788. var pos, x0;
  2789. // decode the position arguments:
  2790. if (!x || Ext.isNumber(x)) {
  2791. pos = { x: x, y : y, anim: animate };
  2792. } else if (Ext.isNumber(x0 = x[0])) { // an array of [x, y]
  2793. pos = { x : x0, y : x[1], anim: y };
  2794. } else {
  2795. pos = { x: x.x, y: x.y, anim: y }; // already an object w/ x & y properties
  2796. }
  2797. pos.hasX = Ext.isNumber(pos.x);
  2798. pos.hasY = Ext.isNumber(pos.y);
  2799. // store the position as specified:
  2800. this.x = pos.x;
  2801. this.y = pos.y;
  2802. return (pos.hasX || pos.hasY) ? pos : null;
  2803. },
  2804. /**
  2805. * Template method called after a Component has been positioned.
  2806. *
  2807. * @param {Number} x
  2808. * @param {Number} y
  2809. *
  2810. * @template
  2811. * @protected
  2812. */
  2813. afterSetPosition: function(x, y) {
  2814. var me = this;
  2815. me.onPosition(x, y);
  2816. if (me.hasListeners.move) {
  2817. me.fireEvent('move', me, x, y);
  2818. }
  2819. },
  2820. /**
  2821. * This method converts an "{x: x, y: y}" object to a "{left: x+'px', top: y+'px'}" object.
  2822. * The returned object contains the styles to set to effect the position. This is
  2823. * overridden in RTL mode to be "{right: x, top: y}".
  2824. * @private
  2825. */
  2826. convertPosition: function (pos, withUnits) {
  2827. var ret = {},
  2828. El = Ext.Element;
  2829. if (pos.hasX) {
  2830. ret.left = withUnits ? El.addUnits(pos.x) : pos.x;
  2831. }
  2832. if (pos.hasY) {
  2833. ret.top = withUnits ? El.addUnits(pos.y) : pos.y;
  2834. }
  2835. return ret;
  2836. },
  2837. /**
  2838. * Called after the component is moved, this method is empty by default but can be implemented by any
  2839. * subclass that needs to perform custom logic after a move occurs.
  2840. *
  2841. * @param {Number} x The new x position
  2842. * @param {Number} y The new y position
  2843. *
  2844. * @template
  2845. * @protected
  2846. */
  2847. onPosition: Ext.emptyFn,
  2848. /**
  2849. * Sets the width of the component. This method fires the {@link #resize} event.
  2850. *
  2851. * @param {Number} width The new width to setThis may be one of:
  2852. *
  2853. * - A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
  2854. * - A String used to set the CSS width style.
  2855. *
  2856. * @return {Ext.Component} this
  2857. */
  2858. setWidth : function(width) {
  2859. return this.setSize(width);
  2860. },
  2861. /**
  2862. * Sets the height of the component. This method fires the {@link #resize} event.
  2863. *
  2864. * @param {Number} height The new height to set. This may be one of:
  2865. *
  2866. * - A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
  2867. * - A String used to set the CSS height style.
  2868. * - _undefined_ to leave the height unchanged.
  2869. *
  2870. * @return {Ext.Component} this
  2871. */
  2872. setHeight : function(height) {
  2873. return this.setSize(undefined, height);
  2874. },
  2875. /**
  2876. * Gets the current size of the component's underlying element.
  2877. * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
  2878. */
  2879. getSize : function() {
  2880. return this.el.getSize();
  2881. },
  2882. /**
  2883. * Gets the current width of the component's underlying element.
  2884. * @return {Number}
  2885. */
  2886. getWidth : function() {
  2887. return this.el.getWidth();
  2888. },
  2889. /**
  2890. * Gets the current height of the component's underlying element.
  2891. * @return {Number}
  2892. */
  2893. getHeight : function() {
  2894. return this.el.getHeight();
  2895. },
  2896. /**
  2897. * Gets the {@link Ext.ComponentLoader} for this Component.
  2898. * @return {Ext.ComponentLoader} The loader instance, null if it doesn't exist.
  2899. */
  2900. getLoader: function(){
  2901. var me = this,
  2902. autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
  2903. loader = me.loader || autoLoad;
  2904. if (loader) {
  2905. if (!loader.isLoader) {
  2906. me.loader = new Ext.ComponentLoader(Ext.apply({
  2907. target: me,
  2908. autoLoad: autoLoad
  2909. }, loader));
  2910. } else {
  2911. loader.setTarget(me);
  2912. }
  2913. return me.loader;
  2914. }
  2915. return null;
  2916. },
  2917. /**
  2918. * Sets the dock position of this component in its parent panel. Note that this only has effect if this item is part
  2919. * of the dockedItems collection of a parent that has a DockLayout (note that any Panel has a DockLayout by default)
  2920. * @param {Object} dock The dock position.
  2921. * @param {Boolean} [layoutParent=false] True to re-layout parent.
  2922. * @return {Ext.Component} this
  2923. */
  2924. setDocked : function(dock, layoutParent) {
  2925. var me = this;
  2926. me.dock = dock;
  2927. if (layoutParent && me.ownerCt && me.rendered) {
  2928. me.ownerCt.updateLayout();
  2929. }
  2930. return me;
  2931. },
  2932. /**
  2933. *
  2934. * @param {String/Number} border The border, see {@link #border}. If a falsey value is passed
  2935. * the border will be removed.
  2936. */
  2937. setBorder: function(border, /* private */ targetEl) {
  2938. var me = this,
  2939. initial = !!targetEl;
  2940. if (me.rendered || initial) {
  2941. if (!initial) {
  2942. targetEl = me.el;
  2943. }
  2944. if (!border) {
  2945. border = 0;
  2946. } else {
  2947. border = Ext.Element.unitizeBox((border === true) ? 1 : border);
  2948. }
  2949. targetEl.setStyle('border-width', border);
  2950. if (!initial) {
  2951. me.updateLayout();
  2952. }
  2953. }
  2954. me.border = border;
  2955. },
  2956. onDestroy : function() {
  2957. var me = this;
  2958. if (me.monitorResize && Ext.EventManager.resizeEvent) {
  2959. Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
  2960. }
  2961. // Destroying the floatingItems ZIndexManager will also destroy descendant floating Components
  2962. Ext.destroy(
  2963. me.componentLayout,
  2964. me.loadMask,
  2965. me.floatingDescendants
  2966. );
  2967. },
  2968. /**
  2969. * Destroys the Component.
  2970. */
  2971. destroy : function() {
  2972. var me = this,
  2973. selectors = me.renderSelectors,
  2974. selector,
  2975. el;
  2976. if (!me.isDestroyed) {
  2977. if (!me.hasListeners.beforedestroy || me.fireEvent('beforedestroy', me) !== false) {
  2978. me.destroying = true;
  2979. me.beforeDestroy();
  2980. if (me.floating) {
  2981. delete me.floatParent;
  2982. // A zIndexManager is stamped into a *floating* Component when it is added to a Container.
  2983. // If it has no zIndexManager at render time, it is assigned to the global Ext.WindowManager instance.
  2984. if (me.zIndexManager) {
  2985. me.zIndexManager.unregister(me);
  2986. }
  2987. } else if (me.ownerCt && me.ownerCt.remove) {
  2988. me.ownerCt.remove(me, false);
  2989. }
  2990. me.onDestroy();
  2991. // Attempt to destroy all plugins
  2992. Ext.destroy(me.plugins);
  2993. if (me.hasListeners.destroy) {
  2994. me.fireEvent('destroy', me);
  2995. }
  2996. Ext.ComponentManager.unregister(me);
  2997. me.mixins.state.destroy.call(me);
  2998. me.clearListeners();
  2999. // make sure we clean up the element references after removing all events
  3000. if (me.rendered) {
  3001. if (!me.preserveElOnDestroy) {
  3002. me.el.remove();
  3003. }
  3004. me.mixins.elementCt.destroy.call(me); // removes childEls
  3005. if (selectors) {
  3006. for (selector in selectors) {
  3007. if (selectors.hasOwnProperty(selector)) {
  3008. el = me[selector];
  3009. if (el) { // in case any other code may have already removed it
  3010. delete me[selector];
  3011. el.remove();
  3012. }
  3013. }
  3014. }
  3015. }
  3016. delete me.el;
  3017. delete me.frameBody;
  3018. delete me.rendered;
  3019. }
  3020. me.destroying = false;
  3021. me.isDestroyed = true;
  3022. }
  3023. }
  3024. },
  3025. /**
  3026. * Retrieves a plugin by its pluginId which has been bound to this component.
  3027. * @param {String} pluginId
  3028. * @return {Ext.AbstractPlugin} plugin instance.
  3029. */
  3030. getPlugin: function(pluginId) {
  3031. var i = 0,
  3032. plugins = this.plugins,
  3033. ln = plugins.length;
  3034. for (; i < ln; i++) {
  3035. if (plugins[i].pluginId === pluginId) {
  3036. return plugins[i];
  3037. }
  3038. }
  3039. },
  3040. /**
  3041. * Determines whether this component is the descendant of a particular container.
  3042. * @param {Ext.Container} container
  3043. * @return {Boolean} True if it is.
  3044. */
  3045. isDescendantOf: function(container) {
  3046. return !!this.findParentBy(function(p){
  3047. return p === container;
  3048. });
  3049. }
  3050. }, function() {
  3051. var AbstractComponent = this;
  3052. AbstractComponent.createAlias({
  3053. on: 'addListener',
  3054. prev: 'previousSibling',
  3055. next: 'nextSibling'
  3056. });
  3057. /**
  3058. * @inheritdoc Ext.AbstractComponent#resumeLayouts
  3059. * @member Ext
  3060. */
  3061. Ext.resumeLayouts = function (flush) {
  3062. AbstractComponent.resumeLayouts(flush);
  3063. };
  3064. /**
  3065. * @inheritdoc Ext.AbstractComponent#suspendLayouts
  3066. * @member Ext
  3067. */
  3068. Ext.suspendLayouts = function () {
  3069. AbstractComponent.suspendLayouts();
  3070. };
  3071. /**
  3072. * Utility wrapper that suspends layouts of all components for the duration of a given function.
  3073. * @param {Function} fn The function to execute.
  3074. * @param {Object} [scope] The scope (`this` reference) in which the specified function is executed.
  3075. * @member Ext
  3076. */
  3077. Ext.batchLayouts = function(fn, scope) {
  3078. AbstractComponent.suspendLayouts();
  3079. // Invoke the function
  3080. fn.call(scope);
  3081. AbstractComponent.resumeLayouts(true);
  3082. };
  3083. });