Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / ClassManager.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-ClassManager'>/**
19 </span> * @author Jacky Nguyen &lt;jacky@sencha.com&gt;
20  * @docauthor Jacky Nguyen &lt;jacky@sencha.com&gt;
21  * @class Ext.ClassManager
22  *
23  * Ext.ClassManager manages all classes and handles mapping from string class name to
24  * actual class objects throughout the whole framework. It is not generally accessed directly, rather through
25  * these convenient shorthands:
26  *
27  * - {@link Ext#define Ext.define}
28  * - {@link Ext#create Ext.create}
29  * - {@link Ext#widget Ext.widget}
30  * - {@link Ext#getClass Ext.getClass}
31  * - {@link Ext#getClassName Ext.getClassName}
32  *
33  * # Basic syntax:
34  *
35  *     Ext.define(className, properties);
36  *
37  * in which `properties` is an object represent a collection of properties that apply to the class. See
38  * {@link Ext.ClassManager#create} for more detailed instructions.
39  *
40  *     Ext.define('Person', {
41  *          name: 'Unknown',
42  *
43  *          constructor: function(name) {
44  *              if (name) {
45  *                  this.name = name;
46  *              }
47  *
48  *              return this;
49  *          },
50  *
51  *          eat: function(foodType) {
52  *              alert(&quot;I'm eating: &quot; + foodType);
53  *
54  *              return this;
55  *          }
56  *     });
57  *
58  *     var aaron = new Person(&quot;Aaron&quot;);
59  *     aaron.eat(&quot;Sandwich&quot;); // alert(&quot;I'm eating: Sandwich&quot;);
60  *
61  * Ext.Class has a powerful set of extensible {@link Ext.Class#registerPreprocessor pre-processors} which takes care of
62  * everything related to class creation, including but not limited to inheritance, mixins, configuration, statics, etc.
63  *
64  * # Inheritance:
65  *
66  *     Ext.define('Developer', {
67  *          extend: 'Person',
68  *
69  *          constructor: function(name, isGeek) {
70  *              this.isGeek = isGeek;
71  *
72  *              // Apply a method from the parent class' prototype
73  *              this.callParent([name]);
74  *
75  *              return this;
76  *
77  *          },
78  *
79  *          code: function(language) {
80  *              alert(&quot;I'm coding in: &quot; + language);
81  *
82  *              this.eat(&quot;Bugs&quot;);
83  *
84  *              return this;
85  *          }
86  *     });
87  *
88  *     var jacky = new Developer(&quot;Jacky&quot;, true);
89  *     jacky.code(&quot;JavaScript&quot;); // alert(&quot;I'm coding in: JavaScript&quot;);
90  *                               // alert(&quot;I'm eating: Bugs&quot;);
91  *
92  * See {@link Ext.Base#callParent} for more details on calling superclass' methods
93  *
94  * # Mixins:
95  *
96  *     Ext.define('CanPlayGuitar', {
97  *          playGuitar: function() {
98  *             alert(&quot;F#...G...D...A&quot;);
99  *          }
100  *     });
101  *
102  *     Ext.define('CanComposeSongs', {
103  *          composeSongs: function() { ... }
104  *     });
105  *
106  *     Ext.define('CanSing', {
107  *          sing: function() {
108  *              alert(&quot;I'm on the highway to hell...&quot;)
109  *          }
110  *     });
111  *
112  *     Ext.define('Musician', {
113  *          extend: 'Person',
114  *
115  *          mixins: {
116  *              canPlayGuitar: 'CanPlayGuitar',
117  *              canComposeSongs: 'CanComposeSongs',
118  *              canSing: 'CanSing'
119  *          }
120  *     })
121  *
122  *     Ext.define('CoolPerson', {
123  *          extend: 'Person',
124  *
125  *          mixins: {
126  *              canPlayGuitar: 'CanPlayGuitar',
127  *              canSing: 'CanSing'
128  *          },
129  *
130  *          sing: function() {
131  *              alert(&quot;Ahem....&quot;);
132  *
133  *              this.mixins.canSing.sing.call(this);
134  *
135  *              alert(&quot;[Playing guitar at the same time...]&quot;);
136  *
137  *              this.playGuitar();
138  *          }
139  *     });
140  *
141  *     var me = new CoolPerson(&quot;Jacky&quot;);
142  *
143  *     me.sing(); // alert(&quot;Ahem...&quot;);
144  *                // alert(&quot;I'm on the highway to hell...&quot;);
145  *                // alert(&quot;[Playing guitar at the same time...]&quot;);
146  *                // alert(&quot;F#...G...D...A&quot;);
147  *
148  * # Config:
149  *
150  *     Ext.define('SmartPhone', {
151  *          config: {
152  *              hasTouchScreen: false,
153  *              operatingSystem: 'Other',
154  *              price: 500
155  *          },
156  *
157  *          isExpensive: false,
158  *
159  *          constructor: function(config) {
160  *              this.initConfig(config);
161  *
162  *              return this;
163  *          },
164  *
165  *          applyPrice: function(price) {
166  *              this.isExpensive = (price &gt; 500);
167  *
168  *              return price;
169  *          },
170  *
171  *          applyOperatingSystem: function(operatingSystem) {
172  *              if (!(/^(iOS|Android|BlackBerry)$/i).test(operatingSystem)) {
173  *                  return 'Other';
174  *              }
175  *
176  *              return operatingSystem;
177  *          }
178  *     });
179  *
180  *     var iPhone = new SmartPhone({
181  *          hasTouchScreen: true,
182  *          operatingSystem: 'iOS'
183  *     });
184  *
185  *     iPhone.getPrice(); // 500;
186  *     iPhone.getOperatingSystem(); // 'iOS'
187  *     iPhone.getHasTouchScreen(); // true;
188  *     iPhone.hasTouchScreen(); // true
189  *
190  *     iPhone.isExpensive; // false;
191  *     iPhone.setPrice(600);
192  *     iPhone.getPrice(); // 600
193  *     iPhone.isExpensive; // true;
194  *
195  *     iPhone.setOperatingSystem('AlienOS');
196  *     iPhone.getOperatingSystem(); // 'Other'
197  *
198  * # Statics:
199  *
200  *     Ext.define('Computer', {
201  *          statics: {
202  *              factory: function(brand) {
203  *                 // 'this' in static methods refer to the class itself
204  *                  return new this(brand);
205  *              }
206  *          },
207  *
208  *          constructor: function() { ... }
209  *     });
210  *
211  *     var dellComputer = Computer.factory('Dell');
212  *
213  * Also see {@link Ext.Base#statics} and {@link Ext.Base#self} for more details on accessing
214  * static properties within class methods
215  *
216  * @singleton
217  */
218 (function(Class, alias) {
219
220     var slice = Array.prototype.slice;
221
222     var Manager = Ext.ClassManager = {
223
224 <span id='Ext-ClassManager-property-classes'>        /**
225 </span>         * @property {Object} classes
226          * All classes which were defined through the ClassManager. Keys are the
227          * name of the classes and the values are references to the classes.
228          * @private
229          */
230         classes: {},
231
232 <span id='Ext-ClassManager-property-existCache'>        /**
233 </span>         * @private
234          */
235         existCache: {},
236
237 <span id='Ext-ClassManager-property-namespaceRewrites'>        /**
238 </span>         * @private
239          */
240         namespaceRewrites: [{
241             from: 'Ext.',
242             to: Ext
243         }],
244
245 <span id='Ext-ClassManager-property-maps'>        /**
246 </span>         * @private
247          */
248         maps: {
249             alternateToName: {},
250             aliasToName: {},
251             nameToAliases: {}
252         },
253
254 <span id='Ext-ClassManager-property-enableNamespaceParseCache'>        /** @private */
255 </span>        enableNamespaceParseCache: true,
256
257 <span id='Ext-ClassManager-property-namespaceParseCache'>        /** @private */
258 </span>        namespaceParseCache: {},
259
260 <span id='Ext-ClassManager-property-instantiators'>        /** @private */
261 </span>        instantiators: [],
262
263         //&lt;debug&gt;
264 <span id='Ext-ClassManager-property-instantiationCounts'>        /** @private */
265 </span>        instantiationCounts: {},
266         //&lt;/debug&gt;
267
268 <span id='Ext-ClassManager-method-isCreated'>        /**
269 </span>         * Checks if a class has already been created.
270          *
271          * @param {String} className
272          * @return {Boolean} exist
273          */
274         isCreated: function(className) {
275             var i, ln, part, root, parts;
276
277             //&lt;debug error&gt;
278             if (typeof className !== 'string' || className.length &lt; 1) {
279                 Ext.Error.raise({
280                     sourceClass: &quot;Ext.ClassManager&quot;,
281                     sourceMethod: &quot;exist&quot;,
282                     msg: &quot;Invalid classname, must be a string and must not be empty&quot;
283                 });
284             }
285             //&lt;/debug&gt;
286
287             if (this.classes.hasOwnProperty(className) || this.existCache.hasOwnProperty(className)) {
288                 return true;
289             }
290
291             root = Ext.global;
292             parts = this.parseNamespace(className);
293
294             for (i = 0, ln = parts.length; i &lt; ln; i++) {
295                 part = parts[i];
296
297                 if (typeof part !== 'string') {
298                     root = part;
299                 } else {
300                     if (!root || !root[part]) {
301                         return false;
302                     }
303
304                     root = root[part];
305                 }
306             }
307
308             Ext.Loader.historyPush(className);
309
310             this.existCache[className] = true;
311
312             return true;
313         },
314
315 <span id='Ext-ClassManager-method-parseNamespace'>        /**
316 </span>         * Supports namespace rewriting
317          * @private
318          */
319         parseNamespace: function(namespace) {
320             //&lt;debug error&gt;
321             if (typeof namespace !== 'string') {
322                 Ext.Error.raise({
323                     sourceClass: &quot;Ext.ClassManager&quot;,
324                     sourceMethod: &quot;parseNamespace&quot;,
325                     msg: &quot;Invalid namespace, must be a string&quot;
326                 });
327             }
328             //&lt;/debug&gt;
329
330             var cache = this.namespaceParseCache;
331
332             if (this.enableNamespaceParseCache) {
333                 if (cache.hasOwnProperty(namespace)) {
334                     return cache[namespace];
335                 }
336             }
337
338             var parts = [],
339                 rewrites = this.namespaceRewrites,
340                 rewrite, from, to, i, ln, root = Ext.global;
341
342             for (i = 0, ln = rewrites.length; i &lt; ln; i++) {
343                 rewrite = rewrites[i];
344                 from = rewrite.from;
345                 to = rewrite.to;
346
347                 if (namespace === from || namespace.substring(0, from.length) === from) {
348                     namespace = namespace.substring(from.length);
349
350                     if (typeof to !== 'string') {
351                         root = to;
352                     } else {
353                         parts = parts.concat(to.split('.'));
354                     }
355
356                     break;
357                 }
358             }
359
360             parts.push(root);
361
362             parts = parts.concat(namespace.split('.'));
363
364             if (this.enableNamespaceParseCache) {
365                 cache[namespace] = parts;
366             }
367
368             return parts;
369         },
370
371 <span id='Ext-ClassManager-method-setNamespace'>        /**
372 </span>         * Creates a namespace and assign the `value` to the created object
373          *
374          *     Ext.ClassManager.setNamespace('MyCompany.pkg.Example', someObject);
375          *
376          *     alert(MyCompany.pkg.Example === someObject); // alerts true
377          *
378          * @param {String} name
379          * @param {Object} value
380          */
381         setNamespace: function(name, value) {
382             var root = Ext.global,
383                 parts = this.parseNamespace(name),
384                 ln = parts.length - 1,
385                 leaf = parts[ln],
386                 i, part;
387
388             for (i = 0; i &lt; ln; i++) {
389                 part = parts[i];
390
391                 if (typeof part !== 'string') {
392                     root = part;
393                 } else {
394                     if (!root[part]) {
395                         root[part] = {};
396                     }
397
398                     root = root[part];
399                 }
400             }
401
402             root[leaf] = value;
403
404             return root[leaf];
405         },
406
407 <span id='Ext-ClassManager-method-createNamespaces'>        /**
408 </span>         * The new Ext.ns, supports namespace rewriting
409          * @private
410          */
411         createNamespaces: function() {
412             var root = Ext.global,
413                 parts, part, i, j, ln, subLn;
414
415             for (i = 0, ln = arguments.length; i &lt; ln; i++) {
416                 parts = this.parseNamespace(arguments[i]);
417
418                 for (j = 0, subLn = parts.length; j &lt; subLn; j++) {
419                     part = parts[j];
420
421                     if (typeof part !== 'string') {
422                         root = part;
423                     } else {
424                         if (!root[part]) {
425                             root[part] = {};
426                         }
427
428                         root = root[part];
429                     }
430                 }
431             }
432
433             return root;
434         },
435
436 <span id='Ext-ClassManager-method-set'>        /**
437 </span>         * Sets a name reference to a class.
438          *
439          * @param {String} name
440          * @param {Object} value
441          * @return {Ext.ClassManager} this
442          */
443         set: function(name, value) {
444             var targetName = this.getName(value);
445
446             this.classes[name] = this.setNamespace(name, value);
447
448             if (targetName &amp;&amp; targetName !== name) {
449                 this.maps.alternateToName[name] = targetName;
450             }
451
452             return this;
453         },
454
455 <span id='Ext-ClassManager-method-get'>        /**
456 </span>         * Retrieve a class by its name.
457          *
458          * @param {String} name
459          * @return {Ext.Class} class
460          */
461         get: function(name) {
462             if (this.classes.hasOwnProperty(name)) {
463                 return this.classes[name];
464             }
465
466             var root = Ext.global,
467                 parts = this.parseNamespace(name),
468                 part, i, ln;
469
470             for (i = 0, ln = parts.length; i &lt; ln; i++) {
471                 part = parts[i];
472
473                 if (typeof part !== 'string') {
474                     root = part;
475                 } else {
476                     if (!root || !root[part]) {
477                         return null;
478                     }
479
480                     root = root[part];
481                 }
482             }
483
484             return root;
485         },
486
487 <span id='Ext-ClassManager-method-setAlias'>        /**
488 </span>         * Register the alias for a class.
489          *
490          * @param {Ext.Class/String} cls a reference to a class or a className
491          * @param {String} alias Alias to use when referring to this class
492          */
493         setAlias: function(cls, alias) {
494             var aliasToNameMap = this.maps.aliasToName,
495                 nameToAliasesMap = this.maps.nameToAliases,
496                 className;
497
498             if (typeof cls === 'string') {
499                 className = cls;
500             } else {
501                 className = this.getName(cls);
502             }
503
504             if (alias &amp;&amp; aliasToNameMap[alias] !== className) {
505                 //&lt;debug info&gt;
506                 if (aliasToNameMap.hasOwnProperty(alias) &amp;&amp; Ext.isDefined(Ext.global.console)) {
507                     Ext.global.console.log(&quot;[Ext.ClassManager] Overriding existing alias: '&quot; + alias + &quot;' &quot; +
508                         &quot;of: '&quot; + aliasToNameMap[alias] + &quot;' with: '&quot; + className + &quot;'. Be sure it's intentional.&quot;);
509                 }
510                 //&lt;/debug&gt;
511
512                 aliasToNameMap[alias] = className;
513             }
514
515             if (!nameToAliasesMap[className]) {
516                 nameToAliasesMap[className] = [];
517             }
518
519             if (alias) {
520                 Ext.Array.include(nameToAliasesMap[className], alias);
521             }
522
523             return this;
524         },
525
526 <span id='Ext-ClassManager-method-getByAlias'>        /**
527 </span>         * Get a reference to the class by its alias.
528          *
529          * @param {String} alias
530          * @return {Ext.Class} class
531          */
532         getByAlias: function(alias) {
533             return this.get(this.getNameByAlias(alias));
534         },
535
536 <span id='Ext-ClassManager-method-getNameByAlias'>        /**
537 </span>         * Get the name of a class by its alias.
538          *
539          * @param {String} alias
540          * @return {String} className
541          */
542         getNameByAlias: function(alias) {
543             return this.maps.aliasToName[alias] || '';
544         },
545
546 <span id='Ext-ClassManager-method-getNameByAlternate'>        /**
547 </span>         * Get the name of a class by its alternate name.
548          *
549          * @param {String} alternate
550          * @return {String} className
551          */
552         getNameByAlternate: function(alternate) {
553             return this.maps.alternateToName[alternate] || '';
554         },
555
556 <span id='Ext-ClassManager-method-getAliasesByName'>        /**
557 </span>         * Get the aliases of a class by the class name
558          *
559          * @param {String} name
560          * @return {String[]} aliases
561          */
562         getAliasesByName: function(name) {
563             return this.maps.nameToAliases[name] || [];
564         },
565
566 <span id='Ext-ClassManager-method-getName'>        /**
567 </span>         * Get the name of the class by its reference or its instance.
568          *
569          *     Ext.ClassManager.getName(Ext.Action); // returns &quot;Ext.Action&quot;
570          *
571          * {@link Ext#getClassName Ext.getClassName} is alias for {@link Ext.ClassManager#getName Ext.ClassManager.getName}.
572          *
573          * @param {Ext.Class/Object} object
574          * @return {String} className
575          */
576         getName: function(object) {
577             return object &amp;&amp; object.$className || '';
578         },
579
580 <span id='Ext-ClassManager-method-getClass'>        /**
581 </span>         * Get the class of the provided object; returns null if it's not an instance
582          * of any class created with Ext.define.
583          *
584          *     var component = new Ext.Component();
585          *
586          *     Ext.ClassManager.getClass(component); // returns Ext.Component
587          *
588          * {@link Ext#getClass Ext.getClass} is alias for {@link Ext.ClassManager#getClass Ext.ClassManager.getClass}.
589          *
590          * @param {Object} object
591          * @return {Ext.Class} class
592          */
593         getClass: function(object) {
594             return object &amp;&amp; object.self || null;
595         },
596
597 <span id='Ext-ClassManager-method-create'>        /**
598 </span>         * Defines a class.
599          *
600          * {@link Ext#define Ext.define} and {@link Ext.ClassManager#create Ext.ClassManager.create} are almost aliases
601          * of each other, with the only exception that Ext.define allows definition of {@link Ext.Class#override overrides}.
602          * To avoid trouble, always use Ext.define.
603          *
604          *     Ext.define('My.awesome.Class', {
605          *         someProperty: 'something',
606          *         someMethod: function() { ... }
607          *         ...
608          *
609          *     }, function() {
610          *         alert('Created!');
611          *         alert(this === My.awesome.Class); // alerts true
612          *
613          *         var myInstance = new this();
614          *     });
615          *
616          * @param {String} className The class name to create in string dot-namespaced format, for example:
617          * `My.very.awesome.Class`, `FeedViewer.plugin.CoolPager`. It is highly recommended to follow this simple convention:
618          *
619          * - The root and the class name are 'CamelCased'
620          * - Everything else is lower-cased
621          *
622          * @param {Object} data The key-value pairs of properties to apply to this class. Property names can be of any valid
623          * strings, except those in the reserved list below:
624          *
625          * - {@link Ext.Base#self self}
626          * - {@link Ext.Class#alias alias}
627          * - {@link Ext.Class#alternateClassName alternateClassName}
628          * - {@link Ext.Class#config config}
629          * - {@link Ext.Class#extend extend}
630          * - {@link Ext.Class#inheritableStatics inheritableStatics}
631          * - {@link Ext.Class#mixins mixins}
632          * - {@link Ext.Class#override override} (only when using {@link Ext#define Ext.define})
633          * - {@link Ext.Class#requires requires}
634          * - {@link Ext.Class#singleton singleton}
635          * - {@link Ext.Class#statics statics}
636          * - {@link Ext.Class#uses uses}
637          *
638          * @param {Function} [createdFn] callback to execute after the class is created, the execution scope of which
639          * (`this`) will be the newly created class itself.
640          *
641          * @return {Ext.Base}
642          */
643         create: function(className, data, createdFn) {
644             var manager = this;
645
646             //&lt;debug error&gt;
647             if (typeof className !== 'string') {
648                 Ext.Error.raise({
649                     sourceClass: &quot;Ext&quot;,
650                     sourceMethod: &quot;define&quot;,
651                     msg: &quot;Invalid class name '&quot; + className + &quot;' specified, must be a non-empty string&quot;
652                 });
653             }
654             //&lt;/debug&gt;
655
656             data.$className = className;
657
658             return new Class(data, function() {
659                 var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
660                     registeredPostprocessors = manager.postprocessors,
661                     index = 0,
662                     postprocessors = [],
663                     postprocessor, process, i, ln;
664
665                 delete data.postprocessors;
666
667                 for (i = 0, ln = postprocessorStack.length; i &lt; ln; i++) {
668                     postprocessor = postprocessorStack[i];
669
670                     if (typeof postprocessor === 'string') {
671                         postprocessor = registeredPostprocessors[postprocessor];
672
673                         if (!postprocessor.always) {
674                             if (data[postprocessor.name] !== undefined) {
675                                 postprocessors.push(postprocessor.fn);
676                             }
677                         }
678                         else {
679                             postprocessors.push(postprocessor.fn);
680                         }
681                     }
682                     else {
683                         postprocessors.push(postprocessor);
684                     }
685                 }
686
687                 process = function(clsName, cls, clsData) {
688                     postprocessor = postprocessors[index++];
689
690                     if (!postprocessor) {
691                         manager.set(className, cls);
692
693                         Ext.Loader.historyPush(className);
694
695                         if (createdFn) {
696                             createdFn.call(cls, cls);
697                         }
698
699                         return;
700                     }
701
702                     if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
703                         process.apply(this, arguments);
704                     }
705                 };
706
707                 process.call(manager, className, this, data);
708             });
709         },
710
711 <span id='Ext-ClassManager-method-instantiateByAlias'>        /**
712 </span>         * Instantiate a class by its alias.
713          *
714          * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has not been defined yet, it will
715          * attempt to load the class via synchronous loading.
716          *
717          *     var window = Ext.ClassManager.instantiateByAlias('widget.window', { width: 600, height: 800, ... });
718          *
719          * {@link Ext#createByAlias Ext.createByAlias} is alias for {@link Ext.ClassManager#instantiateByAlias Ext.ClassManager.instantiateByAlias}.
720          *
721          * @param {String} alias
722          * @param {Object...} args Additional arguments after the alias will be passed to the
723          * class constructor.
724          * @return {Object} instance
725          */
726         instantiateByAlias: function() {
727             var alias = arguments[0],
728                 args = slice.call(arguments),
729                 className = this.getNameByAlias(alias);
730
731             if (!className) {
732                 className = this.maps.aliasToName[alias];
733
734                 //&lt;debug error&gt;
735                 if (!className) {
736                     Ext.Error.raise({
737                         sourceClass: &quot;Ext&quot;,
738                         sourceMethod: &quot;createByAlias&quot;,
739                         msg: &quot;Cannot create an instance of unrecognized alias: &quot; + alias
740                     });
741                 }
742                 //&lt;/debug&gt;
743
744                 //&lt;debug warn&gt;
745                 if (Ext.global.console) {
746                     Ext.global.console.warn(&quot;[Ext.Loader] Synchronously loading '&quot; + className + &quot;'; consider adding &quot; +
747                          &quot;Ext.require('&quot; + alias + &quot;') above Ext.onReady&quot;);
748                 }
749                 //&lt;/debug&gt;
750
751                 Ext.syncRequire(className);
752             }
753
754             args[0] = className;
755
756             return this.instantiate.apply(this, args);
757         },
758
759 <span id='Ext-ClassManager-method-instantiate'>        /**
760 </span>         * Instantiate a class by either full name, alias or alternate name.
761          *
762          * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has not been defined yet, it will
763          * attempt to load the class via synchronous loading.
764          *
765          * For example, all these three lines return the same result:
766          *
767          *     // alias
768          *     var window = Ext.ClassManager.instantiate('widget.window', { width: 600, height: 800, ... });
769          *
770          *     // alternate name
771          *     var window = Ext.ClassManager.instantiate('Ext.Window', { width: 600, height: 800, ... });
772          *
773          *     // full class name
774          *     var window = Ext.ClassManager.instantiate('Ext.window.Window', { width: 600, height: 800, ... });
775          *
776          * {@link Ext#create Ext.create} is alias for {@link Ext.ClassManager#instantiate Ext.ClassManager.instantiate}.
777          *
778          * @param {String} name
779          * @param {Object...} args Additional arguments after the name will be passed to the class' constructor.
780          * @return {Object} instance
781          */
782         instantiate: function() {
783             var name = arguments[0],
784                 args = slice.call(arguments, 1),
785                 alias = name,
786                 possibleName, cls;
787
788             if (typeof name !== 'function') {
789                 //&lt;debug error&gt;
790                 if ((typeof name !== 'string' || name.length &lt; 1)) {
791                     Ext.Error.raise({
792                         sourceClass: &quot;Ext&quot;,
793                         sourceMethod: &quot;create&quot;,
794                         msg: &quot;Invalid class name or alias '&quot; + name + &quot;' specified, must be a non-empty string&quot;
795                     });
796                 }
797                 //&lt;/debug&gt;
798
799                 cls = this.get(name);
800             }
801             else {
802                 cls = name;
803             }
804
805             // No record of this class name, it's possibly an alias, so look it up
806             if (!cls) {
807                 possibleName = this.getNameByAlias(name);
808
809                 if (possibleName) {
810                     name = possibleName;
811
812                     cls = this.get(name);
813                 }
814             }
815
816             // Still no record of this class name, it's possibly an alternate name, so look it up
817             if (!cls) {
818                 possibleName = this.getNameByAlternate(name);
819
820                 if (possibleName) {
821                     name = possibleName;
822
823                     cls = this.get(name);
824                 }
825             }
826
827             // Still not existing at this point, try to load it via synchronous mode as the last resort
828             if (!cls) {
829                 //&lt;debug warn&gt;
830                 if (Ext.global.console) {
831                     Ext.global.console.warn(&quot;[Ext.Loader] Synchronously loading '&quot; + name + &quot;'; consider adding &quot; +
832                          &quot;Ext.require('&quot; + ((possibleName) ? alias : name) + &quot;') above Ext.onReady&quot;);
833                 }
834                 //&lt;/debug&gt;
835
836                 Ext.syncRequire(name);
837
838                 cls = this.get(name);
839             }
840
841             //&lt;debug error&gt;
842             if (!cls) {
843                 Ext.Error.raise({
844                     sourceClass: &quot;Ext&quot;,
845                     sourceMethod: &quot;create&quot;,
846                     msg: &quot;Cannot create an instance of unrecognized class name / alias: &quot; + alias
847                 });
848             }
849
850             if (typeof cls !== 'function') {
851                 Ext.Error.raise({
852                     sourceClass: &quot;Ext&quot;,
853                     sourceMethod: &quot;create&quot;,
854                     msg: &quot;'&quot; + name + &quot;' is a singleton and cannot be instantiated&quot;
855                 });
856             }
857             //&lt;/debug&gt;
858
859             //&lt;debug&gt;
860             if (!this.instantiationCounts[name]) {
861                 this.instantiationCounts[name] = 0;
862             }
863
864             this.instantiationCounts[name]++;
865             //&lt;/debug&gt;
866
867             return this.getInstantiator(args.length)(cls, args);
868         },
869
870 <span id='Ext-ClassManager-method-dynInstantiate'>        /**
871 </span>         * @private
872          * @param name
873          * @param args
874          */
875         dynInstantiate: function(name, args) {
876             args = Ext.Array.from(args, true);
877             args.unshift(name);
878
879             return this.instantiate.apply(this, args);
880         },
881
882 <span id='Ext-ClassManager-method-getInstantiator'>        /**
883 </span>         * @private
884          * @param length
885          */
886         getInstantiator: function(length) {
887             if (!this.instantiators[length]) {
888                 var i = length,
889                     args = [];
890
891                 for (i = 0; i &lt; length; i++) {
892                     args.push('a['+i+']');
893                 }
894
895                 this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
896             }
897
898             return this.instantiators[length];
899         },
900
901 <span id='Ext-ClassManager-property-postprocessors'>        /**
902 </span>         * @private
903          */
904         postprocessors: {},
905
906 <span id='Ext-ClassManager-property-defaultPostprocessors'>        /**
907 </span>         * @private
908          */
909         defaultPostprocessors: [],
910
911 <span id='Ext-ClassManager-method-registerPostprocessor'>        /**
912 </span>         * Register a post-processor function.
913          *
914          * @param {String} name
915          * @param {Function} postprocessor
916          */
917         registerPostprocessor: function(name, fn, always) {
918             this.postprocessors[name] = {
919                 name: name,
920                 always: always ||  false,
921                 fn: fn
922             };
923
924             return this;
925         },
926
927 <span id='Ext-ClassManager-method-setDefaultPostprocessors'>        /**
928 </span>         * Set the default post processors array stack which are applied to every class.
929          *
930          * @param {String/String[]} The name of a registered post processor or an array of registered names.
931          * @return {Ext.ClassManager} this
932          */
933         setDefaultPostprocessors: function(postprocessors) {
934             this.defaultPostprocessors = Ext.Array.from(postprocessors);
935
936             return this;
937         },
938
939 <span id='Ext-ClassManager-method-setDefaultPostprocessorPosition'>        /**
940 </span>         * Insert this post-processor at a specific position in the stack, optionally relative to
941          * any existing post-processor
942          *
943          * @param {String} name The post-processor name. Note that it needs to be registered with
944          * {@link Ext.ClassManager#registerPostprocessor} before this
945          * @param {String} offset The insertion position. Four possible values are:
946          * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument)
947          * @param {String} relativeName
948          * @return {Ext.ClassManager} this
949          */
950         setDefaultPostprocessorPosition: function(name, offset, relativeName) {
951             var defaultPostprocessors = this.defaultPostprocessors,
952                 index;
953
954             if (typeof offset === 'string') {
955                 if (offset === 'first') {
956                     defaultPostprocessors.unshift(name);
957
958                     return this;
959                 }
960                 else if (offset === 'last') {
961                     defaultPostprocessors.push(name);
962
963                     return this;
964                 }
965
966                 offset = (offset === 'after') ? 1 : -1;
967             }
968
969             index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
970
971             if (index !== -1) {
972                 Ext.Array.splice(defaultPostprocessors, Math.max(0, index + offset), 0, name);
973             }
974
975             return this;
976         },
977
978 <span id='Ext-ClassManager-method-getNamesByExpression'>        /**
979 </span>         * Converts a string expression to an array of matching class names. An expression can either refers to class aliases
980          * or class names. Expressions support wildcards:
981          *
982          *     // returns ['Ext.window.Window']
983          *     var window = Ext.ClassManager.getNamesByExpression('widget.window');
984          *
985          *     // returns ['widget.panel', 'widget.window', ...]
986          *     var allWidgets = Ext.ClassManager.getNamesByExpression('widget.*');
987          *
988          *     // returns ['Ext.data.Store', 'Ext.data.ArrayProxy', ...]
989          *     var allData = Ext.ClassManager.getNamesByExpression('Ext.data.*');
990          *
991          * @param {String} expression
992          * @return {String[]} classNames
993          */
994         getNamesByExpression: function(expression) {
995             var nameToAliasesMap = this.maps.nameToAliases,
996                 names = [],
997                 name, alias, aliases, possibleName, regex, i, ln;
998
999             //&lt;debug error&gt;
1000             if (typeof expression !== 'string' || expression.length &lt; 1) {
1001                 Ext.Error.raise({
1002                     sourceClass: &quot;Ext.ClassManager&quot;,
1003                     sourceMethod: &quot;getNamesByExpression&quot;,
1004                     msg: &quot;Expression &quot; + expression + &quot; is invalid, must be a non-empty string&quot;
1005                 });
1006             }
1007             //&lt;/debug&gt;
1008
1009             if (expression.indexOf('*') !== -1) {
1010                 expression = expression.replace(/\*/g, '(.*?)');
1011                 regex = new RegExp('^' + expression + '$');
1012
1013                 for (name in nameToAliasesMap) {
1014                     if (nameToAliasesMap.hasOwnProperty(name)) {
1015                         aliases = nameToAliasesMap[name];
1016
1017                         if (name.search(regex) !== -1) {
1018                             names.push(name);
1019                         }
1020                         else {
1021                             for (i = 0, ln = aliases.length; i &lt; ln; i++) {
1022                                 alias = aliases[i];
1023
1024                                 if (alias.search(regex) !== -1) {
1025                                     names.push(name);
1026                                     break;
1027                                 }
1028                             }
1029                         }
1030                     }
1031                 }
1032
1033             } else {
1034                 possibleName = this.getNameByAlias(expression);
1035
1036                 if (possibleName) {
1037                     names.push(possibleName);
1038                 } else {
1039                     possibleName = this.getNameByAlternate(expression);
1040
1041                     if (possibleName) {
1042                         names.push(possibleName);
1043                     } else {
1044                         names.push(expression);
1045                     }
1046                 }
1047             }
1048
1049             return names;
1050         }
1051     };
1052
1053     var defaultPostprocessors = Manager.defaultPostprocessors;
1054     //&lt;feature classSystem.alias&gt;
1055
1056 <span id='Ext-Class-cfg-alias'>    /**
1057 </span>     * @cfg {String[]} alias
1058      * @member Ext.Class
1059      * List of short aliases for class names.  Most useful for defining xtypes for widgets:
1060      *
1061      *     Ext.define('MyApp.CoolPanel', {
1062      *         extend: 'Ext.panel.Panel',
1063      *         alias: ['widget.coolpanel'],
1064      *         title: 'Yeah!'
1065      *     });
1066      *
1067      *     // Using Ext.create
1068      *     Ext.widget('widget.coolpanel');
1069      *     // Using the shorthand for widgets and in xtypes
1070      *     Ext.widget('panel', {
1071      *         items: [
1072      *             {xtype: 'coolpanel', html: 'Foo'},
1073      *             {xtype: 'coolpanel', html: 'Bar'}
1074      *         ]
1075      *     });
1076      */
1077     Manager.registerPostprocessor('alias', function(name, cls, data) {
1078         var aliases = data.alias,
1079             i, ln;
1080
1081         delete data.alias;
1082
1083         for (i = 0, ln = aliases.length; i &lt; ln; i++) {
1084             alias = aliases[i];
1085
1086             this.setAlias(cls, alias);
1087         }
1088     });
1089
1090 <span id='Ext-Class-cfg-singleton'>    /**
1091 </span>     * @cfg {Boolean} singleton
1092      * @member Ext.Class
1093      * When set to true, the class will be instantiated as singleton.  For example:
1094      *
1095      *     Ext.define('Logger', {
1096      *         singleton: true,
1097      *         log: function(msg) {
1098      *             console.log(msg);
1099      *         }
1100      *     });
1101      *
1102      *     Logger.log('Hello');
1103      */
1104     Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
1105         fn.call(this, name, new cls(), data);
1106         return false;
1107     });
1108
1109 <span id='Ext-Class-cfg-alternateClassName'>    /**
1110 </span>     * @cfg {String/String[]} alternateClassName
1111      * @member Ext.Class
1112      * Defines alternate names for this class.  For example:
1113      *
1114      *     Ext.define('Developer', {
1115      *         alternateClassName: ['Coder', 'Hacker'],
1116      *         code: function(msg) {
1117      *             alert('Typing... ' + msg);
1118      *         }
1119      *     });
1120      *
1121      *     var joe = Ext.create('Developer');
1122      *     joe.code('stackoverflow');
1123      *
1124      *     var rms = Ext.create('Hacker');
1125      *     rms.code('hack hack');
1126      */
1127     Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
1128         var alternates = data.alternateClassName,
1129             i, ln, alternate;
1130
1131         if (!(alternates instanceof Array)) {
1132             alternates = [alternates];
1133         }
1134
1135         for (i = 0, ln = alternates.length; i &lt; ln; i++) {
1136             alternate = alternates[i];
1137
1138             //&lt;debug error&gt;
1139             if (typeof alternate !== 'string') {
1140                 Ext.Error.raise({
1141                     sourceClass: &quot;Ext&quot;,
1142                     sourceMethod: &quot;define&quot;,
1143                     msg: &quot;Invalid alternate of: '&quot; + alternate + &quot;' for class: '&quot; + name + &quot;'; must be a valid string&quot;
1144                 });
1145             }
1146             //&lt;/debug&gt;
1147
1148             this.set(alternate, cls);
1149         }
1150     });
1151
1152     Manager.setDefaultPostprocessors(['alias', 'singleton', 'alternateClassName']);
1153
1154     Ext.apply(Ext, {
1155 <span id='Ext-method-create'>        /**
1156 </span>         * @method
1157          * @member Ext
1158          * @alias Ext.ClassManager#instantiate
1159          */
1160         create: alias(Manager, 'instantiate'),
1161
1162 <span id='Ext-ClassManager-method-factory'>        /**
1163 </span>         * @private
1164          * API to be stablized
1165          *
1166          * @param {Object} item
1167          * @param {String} namespace
1168          */
1169         factory: function(item, namespace) {
1170             if (item instanceof Array) {
1171                 var i, ln;
1172
1173                 for (i = 0, ln = item.length; i &lt; ln; i++) {
1174                     item[i] = Ext.factory(item[i], namespace);
1175                 }
1176
1177                 return item;
1178             }
1179
1180             var isString = (typeof item === 'string');
1181
1182             if (isString || (item instanceof Object &amp;&amp; item.constructor === Object)) {
1183                 var name, config = {};
1184
1185                 if (isString) {
1186                     name = item;
1187                 }
1188                 else {
1189                     name = item.className;
1190                     config = item;
1191                     delete config.className;
1192                 }
1193
1194                 if (namespace !== undefined &amp;&amp; name.indexOf(namespace) === -1) {
1195                     name = namespace + '.' + Ext.String.capitalize(name);
1196                 }
1197
1198                 return Ext.create(name, config);
1199             }
1200
1201             if (typeof item === 'function') {
1202                 return Ext.create(item);
1203             }
1204
1205             return item;
1206         },
1207
1208 <span id='Ext-method-widget'>        /**
1209 </span>         * Convenient shorthand to create a widget by its xtype, also see {@link Ext.ClassManager#instantiateByAlias}
1210          *
1211          *     var button = Ext.widget('button'); // Equivalent to Ext.create('widget.button')
1212          *     var panel = Ext.widget('panel'); // Equivalent to Ext.create('widget.panel')
1213          *
1214          * @method
1215          * @member Ext
1216          * @param {String} name  xtype of the widget to create.
1217          * @param {Object...} args  arguments for the widget constructor.
1218          * @return {Object} widget instance
1219          */
1220         widget: function(name) {
1221             var args = slice.call(arguments);
1222             args[0] = 'widget.' + name;
1223
1224             return Manager.instantiateByAlias.apply(Manager, args);
1225         },
1226
1227 <span id='Ext-method-createByAlias'>        /**
1228 </span>         * @method
1229          * @member Ext
1230          * @alias Ext.ClassManager#instantiateByAlias
1231          */
1232         createByAlias: alias(Manager, 'instantiateByAlias'),
1233
1234 <span id='Ext-Class-cfg-override'>        /**
1235 </span>         * @cfg {String} override
1236          * @member Ext.Class
1237          * 
1238          * Defines an override applied to a class. Note that **overrides can only be created using
1239          * {@link Ext#define}.** {@link Ext.ClassManager#create} only creates classes.
1240          * 
1241          * To define an override, include the override property. The content of an override is
1242          * aggregated with the specified class in order to extend or modify that class. This can be
1243          * as simple as setting default property values or it can extend and/or replace methods.
1244          * This can also extend the statics of the class.
1245          *
1246          * One use for an override is to break a large class into manageable pieces.
1247          *
1248          *      // File: /src/app/Panel.js
1249          *
1250          *      Ext.define('My.app.Panel', {
1251          *          extend: 'Ext.panel.Panel',
1252          *          requires: [
1253          *              'My.app.PanelPart2',
1254          *              'My.app.PanelPart3'
1255          *          ]
1256          *
1257          *          constructor: function (config) {
1258          *              this.callSuper(arguments); // calls Ext.panel.Panel's constructor
1259          *              //...
1260          *          },
1261          *
1262          *          statics: {
1263          *              method: function () {
1264          *                  return 'abc';
1265          *              }
1266          *          }
1267          *      });
1268          *
1269          *      // File: /src/app/PanelPart2.js
1270          *      Ext.define('My.app.PanelPart2', {
1271          *          override: 'My.app.Panel',
1272          *
1273          *          constructor: function (config) {
1274          *              this.callSuper(arguments); // calls My.app.Panel's constructor
1275          *              //...
1276          *          }
1277          *      });
1278          *
1279          * Another use of overrides is to provide optional parts of classes that can be
1280          * independently required. In this case, the class may even be unaware of the
1281          * override altogether.
1282          *
1283          *      Ext.define('My.ux.CoolTip', {
1284          *          override: 'Ext.tip.ToolTip',
1285          *
1286          *          constructor: function (config) {
1287          *              this.callSuper(arguments); // calls Ext.tip.ToolTip's constructor
1288          *              //...
1289          *          }
1290          *      });
1291          *
1292          * The above override can now be required as normal.
1293          *
1294          *      Ext.define('My.app.App', {
1295          *          requires: [
1296          *              'My.ux.CoolTip'
1297          *          ]
1298          *      });
1299          *
1300          * Overrides can also contain statics:
1301          *
1302          *      Ext.define('My.app.BarMod', {
1303          *          override: 'Ext.foo.Bar',
1304          *
1305          *          statics: {
1306          *              method: function (x) {
1307          *                  return this.callSuper([x * 2]); // call Ext.foo.Bar.method
1308          *              }
1309          *          }
1310          *      });
1311          *
1312          * IMPORTANT: An override is only included in a build if the class it overrides is
1313          * required. Otherwise, the override, like the target class, is not included.
1314          */
1315         
1316 <span id='Ext-method-define'>        /**
1317 </span>         * @method
1318          *
1319          * @member Ext
1320          * @alias Ext.ClassManager#create
1321          */
1322         define: function (className, data, createdFn) {
1323             if (!data.override) {
1324                 return Manager.create.apply(Manager, arguments);
1325             }
1326
1327             var requires = data.requires,
1328                 uses = data.uses,
1329                 overrideName = className;
1330
1331             className = data.override;
1332
1333             // hoist any 'requires' or 'uses' from the body onto the faux class:
1334             data = Ext.apply({}, data);
1335             delete data.requires;
1336             delete data.uses;
1337             delete data.override;
1338
1339             // make sure className is in the requires list:
1340             if (typeof requires == 'string') {
1341                 requires = [ className, requires ];
1342             } else if (requires) {
1343                 requires = requires.slice(0);
1344                 requires.unshift(className);
1345             } else {
1346                 requires = [ className ];
1347             }
1348
1349 // TODO - we need to rework this to allow the override to not require the target class
1350 //  and rather 'wait' for it in such a way that if the target class is not in the build,
1351 //  neither are any of its overrides.
1352 //
1353 //  Also, this should process the overrides for a class ASAP (ideally before any derived
1354 //  classes) if the target class 'requires' the overrides. Without some special handling, the
1355 //  overrides so required will be processed before the class and have to be bufferred even
1356 //  in a build.
1357 //
1358 // TODO - we should probably support the &quot;config&quot; processor on an override (to config new
1359 //  functionaliy like Aria) and maybe inheritableStatics (although static is now supported
1360 //  by callSuper). If inheritableStatics causes those statics to be included on derived class
1361 //  constructors, that probably means &quot;no&quot; to this since an override can come after other
1362 //  classes extend the target.
1363             return Manager.create(overrideName, {
1364                     requires: requires,
1365                     uses: uses,
1366                     isPartial: true,
1367                     constructor: function () {
1368                         //&lt;debug error&gt;
1369                         throw new Error(&quot;Cannot create override '&quot; + overrideName + &quot;'&quot;);
1370                         //&lt;/debug&gt;
1371                     }
1372                 }, function () {
1373                     var cls = Manager.get(className);
1374                     if (cls.override) { // if (normal class)
1375                         cls.override(data);
1376                     } else { // else (singleton)
1377                         cls.self.override(data);
1378                     }
1379
1380                     if (createdFn) {
1381                         // called once the override is applied and with the context of the
1382                         // overridden class (the override itself is a meaningless, name-only
1383                         // thing).
1384                         createdFn.call(cls);
1385                     }
1386                 });
1387         },
1388
1389 <span id='Ext-method-getClassName'>        /**
1390 </span>         * @method
1391          * @member Ext
1392          * @alias Ext.ClassManager#getName
1393          */
1394         getClassName: alias(Manager, 'getName'),
1395
1396 <span id='Ext-ClassManager-method-getDisplayName'>        /**
1397 </span>         * Returns the displayName property or className or object.
1398          * When all else fails, returns &quot;Anonymous&quot;.
1399          * @param {Object} object
1400          * @return {String}
1401          */
1402         getDisplayName: function(object) {
1403             if (object.displayName) {
1404                 return object.displayName;
1405             }
1406
1407             if (object.$name &amp;&amp; object.$class) {
1408                 return Ext.getClassName(object.$class) + '#' + object.$name;
1409             }
1410
1411             if (object.$className) {
1412                 return object.$className;
1413             }
1414
1415             return 'Anonymous';
1416         },
1417
1418 <span id='Ext-method-getClass'>        /**
1419 </span>         * @method
1420          * @member Ext
1421          * @alias Ext.ClassManager#getClass
1422          */
1423         getClass: alias(Manager, 'getClass'),
1424
1425 <span id='Ext-method-namespace'>        /**
1426 </span>         * Creates namespaces to be used for scoping variables and classes so that they are not global.
1427          * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
1428          *
1429          *     Ext.namespace('Company', 'Company.data');
1430          *
1431          *     // equivalent and preferable to the above syntax
1432          *     Ext.namespace('Company.data');
1433          *
1434          *     Company.Widget = function() { ... };
1435          *
1436          *     Company.data.CustomStore = function(config) { ... };
1437          *
1438          * @method
1439          * @member Ext
1440          * @param {String} namespace1
1441          * @param {String} namespace2
1442          * @param {String} etc
1443          * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
1444          */
1445         namespace: alias(Manager, 'createNamespaces')
1446     });
1447
1448 <span id='Ext-method-createWidget'>    /**
1449 </span>     * Old name for {@link Ext#widget}.
1450      * @deprecated 4.0.0 Use {@link Ext#widget} instead.
1451      * @method
1452      * @member Ext
1453      * @alias Ext#widget
1454      */
1455     Ext.createWidget = Ext.widget;
1456
1457 <span id='Ext-method-ns'>    /**
1458 </span>     * Convenient alias for {@link Ext#namespace Ext.namespace}
1459      * @method
1460      * @member Ext
1461      * @alias Ext#namespace
1462      */
1463     Ext.ns = Ext.namespace;
1464
1465     Class.registerPreprocessor('className', function(cls, data) {
1466         if (data.$className) {
1467             cls.$className = data.$className;
1468             //&lt;debug&gt;
1469             cls.displayName = cls.$className;
1470             //&lt;/debug&gt;
1471         }
1472     }, true);
1473
1474     Class.setDefaultPreprocessorPosition('className', 'first');
1475
1476     Class.registerPreprocessor('xtype', function(cls, data) {
1477         var xtypes = Ext.Array.from(data.xtype),
1478             widgetPrefix = 'widget.',
1479             aliases = Ext.Array.from(data.alias),
1480             i, ln, xtype;
1481
1482         data.xtype = xtypes[0];
1483         data.xtypes = xtypes;
1484
1485         aliases = data.alias = Ext.Array.from(data.alias);
1486
1487         for (i = 0,ln = xtypes.length; i &lt; ln; i++) {
1488             xtype = xtypes[i];
1489
1490             //&lt;debug error&gt;
1491             if (typeof xtype != 'string' || xtype.length &lt; 1) {
1492                 throw new Error(&quot;[Ext.define] Invalid xtype of: '&quot; + xtype + &quot;' for class: '&quot; + name + &quot;'; must be a valid non-empty string&quot;);
1493             }
1494             //&lt;/debug&gt;
1495
1496             aliases.push(widgetPrefix + xtype);
1497         }
1498
1499         data.alias = aliases;
1500     });
1501
1502     Class.setDefaultPreprocessorPosition('xtype', 'last');
1503
1504     Class.registerPreprocessor('alias', function(cls, data) {
1505         var aliases = Ext.Array.from(data.alias),
1506             xtypes = Ext.Array.from(data.xtypes),
1507             widgetPrefix = 'widget.',
1508             widgetPrefixLength = widgetPrefix.length,
1509             i, ln, alias, xtype;
1510
1511         for (i = 0, ln = aliases.length; i &lt; ln; i++) {
1512             alias = aliases[i];
1513
1514             //&lt;debug error&gt;
1515             if (typeof alias != 'string') {
1516                 throw new Error(&quot;[Ext.define] Invalid alias of: '&quot; + alias + &quot;' for class: '&quot; + name + &quot;'; must be a valid string&quot;);
1517             }
1518             //&lt;/debug&gt;
1519
1520             if (alias.substring(0, widgetPrefixLength) === widgetPrefix) {
1521                 xtype = alias.substring(widgetPrefixLength);
1522                 Ext.Array.include(xtypes, xtype);
1523
1524                 if (!cls.xtype) {
1525                     cls.xtype = data.xtype = xtype;
1526                 }
1527             }
1528         }
1529
1530         data.alias = aliases;
1531         data.xtypes = xtypes;
1532     });
1533
1534     Class.setDefaultPreprocessorPosition('alias', 'last');
1535
1536 })(Ext.Class, Ext.Function.alias);
1537 </pre>
1538 </body>
1539 </html>