Upgrade to ExtJS 4.0.1 - Released 05/18/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="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../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  * @singleton
34  * @markdown
35  */
36 (function(Class, alias) {
37
38     var slice = Array.prototype.slice;
39
40     var Manager = Ext.ClassManager = {
41
42 <span id='Ext-ClassManager-property-classes'>        /**
43 </span>         * @property classes
44          * @type Object
45          * All classes which were defined through the ClassManager. Keys are the
46          * name of the classes and the values are references to the classes.
47          * @private
48          */
49         classes: {},
50
51 <span id='Ext-ClassManager-property-existCache'>        /**
52 </span>         * @private
53          */
54         existCache: {},
55
56 <span id='Ext-ClassManager-property-namespaceRewrites'>        /**
57 </span>         * @private
58          */
59         namespaceRewrites: [{
60             from: 'Ext.',
61             to: Ext
62         }],
63
64 <span id='Ext-ClassManager-property-maps'>        /**
65 </span>         * @private
66          */
67         maps: {
68             alternateToName: {},
69             aliasToName: {},
70             nameToAliases: {}
71         },
72
73 <span id='Ext-ClassManager-property-enableNamespaceParseCache'>        /** @private */
74 </span>        enableNamespaceParseCache: true,
75
76 <span id='Ext-ClassManager-property-namespaceParseCache'>        /** @private */
77 </span>        namespaceParseCache: {},
78
79 <span id='Ext-ClassManager-property-instantiators'>        /** @private */
80 </span>        instantiators: [],
81
82         //&lt;debug&gt;
83 <span id='Ext-ClassManager-property-instantiationCounts'>        /** @private */
84 </span>        instantiationCounts: {},
85         //&lt;/debug&gt;
86
87 <span id='Ext-ClassManager-method-isCreated'>        /**
88 </span>         * Checks if a class has already been created.
89          *
90          * @param {String} className
91          * @return {Boolean} exist
92          */
93         isCreated: function(className) {
94             var i, ln, part, root, parts;
95
96             //&lt;debug error&gt;
97             if (typeof className !== 'string' || className.length &lt; 1) {
98                 Ext.Error.raise({
99                     sourceClass: &quot;Ext.ClassManager&quot;,
100                     sourceMethod: &quot;exist&quot;,
101                     msg: &quot;Invalid classname, must be a string and must not be empty&quot;
102                 });
103             }
104             //&lt;/debug&gt;
105
106             if (this.classes.hasOwnProperty(className) || this.existCache.hasOwnProperty(className)) {
107                 return true;
108             }
109
110             root = Ext.global;
111             parts = this.parseNamespace(className);
112
113             for (i = 0, ln = parts.length; i &lt; ln; i++) {
114                 part = parts[i];
115
116                 if (typeof part !== 'string') {
117                     root = part;
118                 } else {
119                     if (!root || !root[part]) {
120                         return false;
121                     }
122
123                     root = root[part];
124                 }
125             }
126
127             Ext.Loader.historyPush(className);
128
129             this.existCache[className] = true;
130
131             return true;
132         },
133
134 <span id='Ext-ClassManager-method-parseNamespace'>        /**
135 </span>         * Supports namespace rewriting
136          * @private
137          */
138         parseNamespace: function(namespace) {
139             //&lt;debug error&gt;
140             if (typeof namespace !== 'string') {
141                 Ext.Error.raise({
142                     sourceClass: &quot;Ext.ClassManager&quot;,
143                     sourceMethod: &quot;parseNamespace&quot;,
144                     msg: &quot;Invalid namespace, must be a string&quot;
145                 });
146             }
147             //&lt;/debug&gt;
148
149             var cache = this.namespaceParseCache;
150
151             if (this.enableNamespaceParseCache) {
152                 if (cache.hasOwnProperty(namespace)) {
153                     return cache[namespace];
154                 }
155             }
156
157             var parts = [],
158                 rewrites = this.namespaceRewrites,
159                 rewrite, from, to, i, ln, root = Ext.global;
160
161             for (i = 0, ln = rewrites.length; i &lt; ln; i++) {
162                 rewrite = rewrites[i];
163                 from = rewrite.from;
164                 to = rewrite.to;
165
166                 if (namespace === from || namespace.substring(0, from.length) === from) {
167                     namespace = namespace.substring(from.length);
168
169                     if (typeof to !== 'string') {
170                         root = to;
171                     } else {
172                         parts = parts.concat(to.split('.'));
173                     }
174
175                     break;
176                 }
177             }
178
179             parts.push(root);
180
181             parts = parts.concat(namespace.split('.'));
182
183             if (this.enableNamespaceParseCache) {
184                 cache[namespace] = parts;
185             }
186
187             return parts;
188         },
189
190 <span id='Ext-ClassManager-method-setNamespace'>        /**
191 </span>         * Creates a namespace and assign the `value` to the created object
192
193     Ext.ClassManager.setNamespace('MyCompany.pkg.Example', someObject);
194
195     alert(MyCompany.pkg.Example === someObject); // alerts true
196
197          * @param {String} name
198          * @param {Mixed} value
199          * @markdown
200          */
201         setNamespace: function(name, value) {
202             var root = Ext.global,
203                 parts = this.parseNamespace(name),
204                 leaf = parts.pop(),
205                 i, ln, part;
206
207             for (i = 0, ln = parts.length; i &lt; ln; i++) {
208                 part = parts[i];
209
210                 if (typeof part !== 'string') {
211                     root = part;
212                 } else {
213                     if (!root[part]) {
214                         root[part] = {};
215                     }
216
217                     root = root[part];
218                 }
219             }
220
221             root[leaf] = value;
222
223             return root[leaf];
224         },
225
226 <span id='Ext-ClassManager-method-createNamespaces'>        /**
227 </span>         * The new Ext.ns, supports namespace rewriting
228          * @private
229          */
230         createNamespaces: function() {
231             var root = Ext.global,
232                 parts, part, i, j, ln, subLn;
233
234             for (i = 0, ln = arguments.length; i &lt; ln; i++) {
235                 parts = this.parseNamespace(arguments[i]);
236
237                 for (j = 0, subLn = parts.length; j &lt; subLn; j++) {
238                     part = parts[j];
239
240                     if (typeof part !== 'string') {
241                         root = part;
242                     } else {
243                         if (!root[part]) {
244                             root[part] = {};
245                         }
246
247                         root = root[part];
248                     }
249                 }
250             }
251
252             return root;
253         },
254
255 <span id='Ext-ClassManager-method-set'>        /**
256 </span>         * Sets a name reference to a class.
257          *
258          * @param {String} name
259          * @param {Object} value
260          * @return {Ext.ClassManager} this
261          */
262         set: function(name, value) {
263             var targetName = this.getName(value);
264
265             this.classes[name] = this.setNamespace(name, value);
266
267             if (targetName &amp;&amp; targetName !== name) {
268                 this.maps.alternateToName[name] = targetName;
269             }
270
271             return this;
272         },
273
274 <span id='Ext-ClassManager-method-get'>        /**
275 </span>         * Retrieve a class by its name.
276          *
277          * @param {String} name
278          * @return {Class} class
279          */
280         get: function(name) {
281             if (this.classes.hasOwnProperty(name)) {
282                 return this.classes[name];
283             }
284
285             var root = Ext.global,
286                 parts = this.parseNamespace(name),
287                 part, i, ln;
288
289             for (i = 0, ln = parts.length; i &lt; ln; i++) {
290                 part = parts[i];
291
292                 if (typeof part !== 'string') {
293                     root = part;
294                 } else {
295                     if (!root || !root[part]) {
296                         return null;
297                     }
298
299                     root = root[part];
300                 }
301             }
302
303             return root;
304         },
305
306 <span id='Ext-ClassManager-method-setAlias'>        /**
307 </span>         * Register the alias for a class.
308          *
309          * @param {Class/String} cls a reference to a class or a className
310          * @param {String} alias Alias to use when referring to this class
311          */
312         setAlias: function(cls, alias) {
313             var aliasToNameMap = this.maps.aliasToName,
314                 nameToAliasesMap = this.maps.nameToAliases,
315                 className;
316
317             if (typeof cls === 'string') {
318                 className = cls;
319             } else {
320                 className = this.getName(cls);
321             }
322
323             if (alias &amp;&amp; aliasToNameMap[alias] !== className) {
324                 //&lt;debug info&gt;
325                 if (aliasToNameMap.hasOwnProperty(alias) &amp;&amp; Ext.isDefined(Ext.global.console)) {
326                     Ext.global.console.log(&quot;[Ext.ClassManager] Overriding existing alias: '&quot; + alias + &quot;' &quot; +
327                         &quot;of: '&quot; + aliasToNameMap[alias] + &quot;' with: '&quot; + className + &quot;'. Be sure it's intentional.&quot;);
328                 }
329                 //&lt;/debug&gt;
330
331                 aliasToNameMap[alias] = className;
332             }
333
334             if (!nameToAliasesMap[className]) {
335                 nameToAliasesMap[className] = [];
336             }
337
338             if (alias) {
339                 Ext.Array.include(nameToAliasesMap[className], alias);
340             }
341
342             return this;
343         },
344
345 <span id='Ext-ClassManager-method-getByAlias'>        /**
346 </span>         * Get a reference to the class by its alias.
347          *
348          * @param {String} alias
349          * @return {Class} class
350          */
351         getByAlias: function(alias) {
352             return this.get(this.getNameByAlias(alias));
353         },
354
355 <span id='Ext-ClassManager-method-getNameByAlias'>        /**
356 </span>         * Get the name of a class by its alias.
357          *
358          * @param {String} alias
359          * @return {String} className
360          */
361         getNameByAlias: function(alias) {
362             return this.maps.aliasToName[alias] || '';
363         },
364
365 <span id='Ext-ClassManager-method-getNameByAlternate'>        /**
366 </span>         * Get the name of a class by its alternate name.
367          *
368          * @param {String} alternate
369          * @return {String} className
370          */
371         getNameByAlternate: function(alternate) {
372             return this.maps.alternateToName[alternate] || '';
373         },
374
375 <span id='Ext-ClassManager-method-getAliasesByName'>        /**
376 </span>         * Get the aliases of a class by the class name
377          *
378          * @param {String} name
379          * @return {Array} aliases
380          */
381         getAliasesByName: function(name) {
382             return this.maps.nameToAliases[name] || [];
383         },
384
385 <span id='Ext-ClassManager-method-getName'>        /**
386 </span>         * Get the name of the class by its reference or its instance;
387          * usually invoked by the shorthand {@link Ext#getClassName Ext.getClassName}
388
389     Ext.ClassManager.getName(Ext.Action); // returns &quot;Ext.Action&quot;
390
391          * @param {Class/Object} object
392          * @return {String} className
393          * @markdown
394          */
395         getName: function(object) {
396             return object &amp;&amp; object.$className || '';
397         },
398
399 <span id='Ext-ClassManager-method-getClass'>        /**
400 </span>         * Get the class of the provided object; returns null if it's not an instance
401          * of any class created with Ext.define. This is usually invoked by the shorthand {@link Ext#getClass Ext.getClass}
402          *
403     var component = new Ext.Component();
404
405     Ext.ClassManager.getClass(component); // returns Ext.Component
406              *
407          * @param {Object} object
408          * @return {Class} class
409          * @markdown
410          */
411         getClass: function(object) {
412             return object &amp;&amp; object.self || null;
413         },
414
415 <span id='Ext-ClassManager-method-create'>        /**
416 </span>         * Defines a class. This is usually invoked via the alias {@link Ext#define Ext.define}
417
418     Ext.ClassManager.create('My.awesome.Class', {
419         someProperty: 'something',
420         someMethod: function() { ... }
421         ...
422
423     }, function() {
424         alert('Created!');
425         alert(this === My.awesome.Class); // alerts true
426
427         var myInstance = new this();
428     });
429
430          * @param {String} className The class name to create in string dot-namespaced format, for example:
431          * 'My.very.awesome.Class', 'FeedViewer.plugin.CoolPager'
432          * It is highly recommended to follow this simple convention:
433
434 - The root and the class name are 'CamelCased'
435 - Everything else is lower-cased
436
437          * @param {Object} data The key - value pairs of properties to apply to this class. Property names can be of any valid
438          * strings, except those in the reserved listed below:
439
440 - `mixins`
441 - `statics`
442 - `config`
443 - `alias`
444 - `self`
445 - `singleton`
446 - `alternateClassName`
447          *
448          * @param {Function} createdFn Optional callback to execute after the class is created, the execution scope of which
449          * (`this`) will be the newly created class itself.
450          * @return {Ext.Base}
451          * @markdown
452          */
453         create: function(className, data, createdFn) {
454             var manager = this;
455
456             //&lt;debug error&gt;
457             if (typeof className !== 'string') {
458                 Ext.Error.raise({
459                     sourceClass: &quot;Ext&quot;,
460                     sourceMethod: &quot;define&quot;,
461                     msg: &quot;Invalid class name '&quot; + className + &quot;' specified, must be a non-empty string&quot;
462                 });
463             }
464             //&lt;/debug&gt;
465
466             data.$className = className;
467
468             return new Class(data, function() {
469                 var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
470                     registeredPostprocessors = manager.postprocessors,
471                     index = 0,
472                     postprocessors = [],
473                     postprocessor, postprocessors, process, i, ln;
474
475                 delete data.postprocessors;
476
477                 for (i = 0, ln = postprocessorStack.length; i &lt; ln; i++) {
478                     postprocessor = postprocessorStack[i];
479
480                     if (typeof postprocessor === 'string') {
481                         postprocessor = registeredPostprocessors[postprocessor];
482
483                         if (!postprocessor.always) {
484                             if (data[postprocessor.name] !== undefined) {
485                                 postprocessors.push(postprocessor.fn);
486                             }
487                         }
488                         else {
489                             postprocessors.push(postprocessor.fn);
490                         }
491                     }
492                     else {
493                         postprocessors.push(postprocessor);
494                     }
495                 }
496
497                 process = function(clsName, cls, clsData) {
498                     postprocessor = postprocessors[index++];
499
500                     if (!postprocessor) {
501                         manager.set(className, cls);
502
503                         Ext.Loader.historyPush(className);
504
505                         if (createdFn) {
506                             createdFn.call(cls, cls);
507                         }
508
509                         return;
510                     }
511
512                     if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
513                         process.apply(this, arguments);
514                     }
515                 };
516
517                 process.call(manager, className, this, data);
518             });
519         },
520
521 <span id='Ext-ClassManager-method-instantiateByAlias'>        /**
522 </span>         * Instantiate a class by its alias; usually invoked by the convenient shorthand {@link Ext#createByAlias Ext.createByAlias}
523          * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has not been defined yet, it will
524          * attempt to load the class via synchronous loading.
525
526     var window = Ext.ClassManager.instantiateByAlias('widget.window', { width: 600, height: 800, ... });
527
528          * @param {String} alias
529          * @param {Mixed} args,... Additional arguments after the alias will be passed to the
530          * class constructor.
531          * @return {Object} instance
532          * @markdown
533          */
534         instantiateByAlias: function() {
535             var alias = arguments[0],
536                 args = slice.call(arguments),
537                 className = this.getNameByAlias(alias);
538
539             if (!className) {
540                 className = this.maps.aliasToName[alias];
541
542                 //&lt;debug error&gt;
543                 if (!className) {
544                     Ext.Error.raise({
545                         sourceClass: &quot;Ext&quot;,
546                         sourceMethod: &quot;createByAlias&quot;,
547                         msg: &quot;Cannot create an instance of unrecognized alias: &quot; + alias
548                     });
549                 }
550                 //&lt;/debug&gt;
551
552                 //&lt;debug warn&gt;
553                 if (Ext.global.console) {
554                     Ext.global.console.warn(&quot;[Ext.Loader] Synchronously loading '&quot; + className + &quot;'; consider adding &quot; +
555                          &quot;Ext.require('&quot; + alias + &quot;') above Ext.onReady&quot;);
556                 }
557                 //&lt;/debug&gt;
558
559                 Ext.syncRequire(className);
560             }
561
562             args[0] = className;
563
564             return this.instantiate.apply(this, args);
565         },
566
567 <span id='Ext-ClassManager-method-instantiate'>        /**
568 </span>         * Instantiate a class by either full name, alias or alternate name; usually invoked by the convenient
569          * shorthand {@link Ext#create Ext.create}
570          *
571          * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has not been defined yet, it will
572          * attempt to load the class via synchronous loading.
573          *
574          * For example, all these three lines return the same result:
575
576     // alias
577     var window = Ext.ClassManager.instantiate('widget.window', { width: 600, height: 800, ... });
578
579     // alternate name
580     var window = Ext.ClassManager.instantiate('Ext.Window', { width: 600, height: 800, ... });
581
582     // full class name
583     var window = Ext.ClassManager.instantiate('Ext.window.Window', { width: 600, height: 800, ... });
584
585          * @param {String} name
586          * @param {Mixed} args,... Additional arguments after the name will be passed to the class' constructor.
587          * @return {Object} instance
588          * @markdown
589          */
590         instantiate: function() {
591             var name = arguments[0],
592                 args = slice.call(arguments, 1),
593                 alias = name,
594                 possibleName, cls;
595
596             if (typeof name !== 'function') {
597                 //&lt;debug error&gt;
598                 if ((typeof name !== 'string' || name.length &lt; 1)) {
599                     Ext.Error.raise({
600                         sourceClass: &quot;Ext&quot;,
601                         sourceMethod: &quot;create&quot;,
602                         msg: &quot;Invalid class name or alias '&quot; + name + &quot;' specified, must be a non-empty string&quot;
603                     });
604                 }
605                 //&lt;/debug&gt;
606
607                 cls = this.get(name);
608             }
609             else {
610                 cls = name;
611             }
612
613             // No record of this class name, it's possibly an alias, so look it up
614             if (!cls) {
615                 possibleName = this.getNameByAlias(name);
616
617                 if (possibleName) {
618                     name = possibleName;
619
620                     cls = this.get(name);
621                 }
622             }
623
624             // Still no record of this class name, it's possibly an alternate name, so look it up
625             if (!cls) {
626                 possibleName = this.getNameByAlternate(name);
627
628                 if (possibleName) {
629                     name = possibleName;
630
631                     cls = this.get(name);
632                 }
633             }
634
635             // Still not existing at this point, try to load it via synchronous mode as the last resort
636             if (!cls) {
637                 //&lt;debug warn&gt;
638                 if (Ext.global.console) {
639                     Ext.global.console.warn(&quot;[Ext.Loader] Synchronously loading '&quot; + name + &quot;'; consider adding &quot; +
640                          &quot;Ext.require('&quot; + ((possibleName) ? alias : name) + &quot;') above Ext.onReady&quot;);
641                 }
642                 //&lt;/debug&gt;
643
644                 Ext.syncRequire(name);
645
646                 cls = this.get(name);
647             }
648
649             //&lt;debug error&gt;
650             if (!cls) {
651                 Ext.Error.raise({
652                     sourceClass: &quot;Ext&quot;,
653                     sourceMethod: &quot;create&quot;,
654                     msg: &quot;Cannot create an instance of unrecognized class name / alias: &quot; + alias
655                 });
656             }
657
658             if (typeof cls !== 'function') {
659                 Ext.Error.raise({
660                     sourceClass: &quot;Ext&quot;,
661                     sourceMethod: &quot;create&quot;,
662                     msg: &quot;'&quot; + name + &quot;' is a singleton and cannot be instantiated&quot;
663                 });
664             }
665             //&lt;/debug&gt;
666
667             //&lt;debug&gt;
668             if (!this.instantiationCounts[name]) {
669                 this.instantiationCounts[name] = 0;
670             }
671
672             this.instantiationCounts[name]++;
673             //&lt;/debug&gt;
674
675             return this.getInstantiator(args.length)(cls, args);
676         },
677
678 <span id='Ext-ClassManager-method-dynInstantiate'>        /**
679 </span>         * @private
680          * @param name
681          * @param args
682          */
683         dynInstantiate: function(name, args) {
684             args = Ext.Array.from(args, true);
685             args.unshift(name);
686
687             return this.instantiate.apply(this, args);
688         },
689
690 <span id='Ext-ClassManager-method-getInstantiator'>        /**
691 </span>         * @private
692          * @param length
693          */
694         getInstantiator: function(length) {
695             if (!this.instantiators[length]) {
696                 var i = length,
697                     args = [];
698
699                 for (i = 0; i &lt; length; i++) {
700                     args.push('a['+i+']');
701                 }
702
703                 this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
704             }
705
706             return this.instantiators[length];
707         },
708
709 <span id='Ext-ClassManager-property-postprocessors'>        /**
710 </span>         * @private
711          */
712         postprocessors: {},
713
714 <span id='Ext-ClassManager-property-defaultPostprocessors'>        /**
715 </span>         * @private
716          */
717         defaultPostprocessors: [],
718
719 <span id='Ext-ClassManager-method-registerPostprocessor'>        /**
720 </span>         * Register a post-processor function.
721          *
722          * @param {String} name
723          * @param {Function} postprocessor
724          */
725         registerPostprocessor: function(name, fn, always) {
726             this.postprocessors[name] = {
727                 name: name,
728                 always: always ||  false,
729                 fn: fn
730             };
731
732             return this;
733         },
734
735 <span id='Ext-ClassManager-method-setDefaultPostprocessors'>        /**
736 </span>         * Set the default post processors array stack which are applied to every class.
737          *
738          * @param {String/Array} The name of a registered post processor or an array of registered names.
739          * @return {Ext.ClassManager} this
740          */
741         setDefaultPostprocessors: function(postprocessors) {
742             this.defaultPostprocessors = Ext.Array.from(postprocessors);
743
744             return this;
745         },
746
747 <span id='Ext-ClassManager-method-setDefaultPostprocessorPosition'>        /**
748 </span>         * Insert this post-processor at a specific position in the stack, optionally relative to
749          * any existing post-processor
750          *
751          * @param {String} name The post-processor name. Note that it needs to be registered with
752          * {@link Ext.ClassManager#registerPostprocessor} before this
753          * @param {String} offset The insertion position. Four possible values are:
754          * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument)
755          * @param {String} relativeName
756          * @return {Ext.ClassManager} this
757          */
758         setDefaultPostprocessorPosition: function(name, offset, relativeName) {
759             var defaultPostprocessors = this.defaultPostprocessors,
760                 index;
761
762             if (typeof offset === 'string') {
763                 if (offset === 'first') {
764                     defaultPostprocessors.unshift(name);
765
766                     return this;
767                 }
768                 else if (offset === 'last') {
769                     defaultPostprocessors.push(name);
770
771                     return this;
772                 }
773
774                 offset = (offset === 'after') ? 1 : -1;
775             }
776
777             index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
778
779             if (index !== -1) {
780                 defaultPostprocessors.splice(Math.max(0, index + offset), 0, name);
781             }
782
783             return this;
784         },
785
786 <span id='Ext-ClassManager-method-getNamesByExpression'>        /**
787 </span>         * Converts a string expression to an array of matching class names. An expression can either refers to class aliases
788          * or class names. Expressions support wildcards:
789
790      // returns ['Ext.window.Window']
791     var window = Ext.ClassManager.getNamesByExpression('widget.window');
792
793     // returns ['widget.panel', 'widget.window', ...]
794     var allWidgets = Ext.ClassManager.getNamesByExpression('widget.*');
795
796     // returns ['Ext.data.Store', 'Ext.data.ArrayProxy', ...]
797     var allData = Ext.ClassManager.getNamesByExpression('Ext.data.*');
798
799          * @param {String} expression
800          * @return {Array} classNames
801          * @markdown
802          */
803         getNamesByExpression: function(expression) {
804             var nameToAliasesMap = this.maps.nameToAliases,
805                 names = [],
806                 name, alias, aliases, possibleName, regex, i, ln;
807
808             //&lt;debug error&gt;
809             if (typeof expression !== 'string' || expression.length &lt; 1) {
810                 Ext.Error.raise({
811                     sourceClass: &quot;Ext.ClassManager&quot;,
812                     sourceMethod: &quot;getNamesByExpression&quot;,
813                     msg: &quot;Expression &quot; + expression + &quot; is invalid, must be a non-empty string&quot;
814                 });
815             }
816             //&lt;/debug&gt;
817
818             if (expression.indexOf('*') !== -1) {
819                 expression = expression.replace(/\*/g, '(.*?)');
820                 regex = new RegExp('^' + expression + '$');
821
822                 for (name in nameToAliasesMap) {
823                     if (nameToAliasesMap.hasOwnProperty(name)) {
824                         aliases = nameToAliasesMap[name];
825
826                         if (name.search(regex) !== -1) {
827                             names.push(name);
828                         }
829                         else {
830                             for (i = 0, ln = aliases.length; i &lt; ln; i++) {
831                                 alias = aliases[i];
832
833                                 if (alias.search(regex) !== -1) {
834                                     names.push(name);
835                                     break;
836                                 }
837                             }
838                         }
839                     }
840                 }
841
842             } else {
843                 possibleName = this.getNameByAlias(expression);
844
845                 if (possibleName) {
846                     names.push(possibleName);
847                 } else {
848                     possibleName = this.getNameByAlternate(expression);
849
850                     if (possibleName) {
851                         names.push(possibleName);
852                     } else {
853                         names.push(expression);
854                     }
855                 }
856             }
857
858             return names;
859         }
860     };
861
862     Manager.registerPostprocessor('alias', function(name, cls, data) {
863         var aliases = data.alias,
864             widgetPrefix = 'widget.',
865             i, ln, alias;
866
867         if (!(aliases instanceof Array)) {
868             aliases = [aliases];
869         }
870
871         for (i = 0, ln = aliases.length; i &lt; ln; i++) {
872             alias = aliases[i];
873
874             //&lt;debug error&gt;
875             if (typeof alias !== 'string') {
876                 Ext.Error.raise({
877                     sourceClass: &quot;Ext&quot;,
878                     sourceMethod: &quot;define&quot;,
879                     msg: &quot;Invalid alias of: '&quot; + alias + &quot;' for class: '&quot; + name + &quot;'; must be a valid string&quot;
880                 });
881             }
882             //&lt;/debug&gt;
883
884             this.setAlias(cls, alias);
885         }
886
887         // This is ugly, will change to make use of parseNamespace for alias later on
888         for (i = 0, ln = aliases.length; i &lt; ln; i++) {
889             alias = aliases[i];
890
891             if (alias.substring(0, widgetPrefix.length) === widgetPrefix) {
892                 // Only the first alias with 'widget.' prefix will be used for xtype
893                 cls.xtype = cls.$xtype = alias.substring(widgetPrefix.length);
894                 break;
895             }
896         }
897     });
898
899     Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
900         fn.call(this, name, new cls(), data);
901         return false;
902     });
903
904     Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
905         var alternates = data.alternateClassName,
906             i, ln, alternate;
907
908         if (!(alternates instanceof Array)) {
909             alternates = [alternates];
910         }
911
912         for (i = 0, ln = alternates.length; i &lt; ln; i++) {
913             alternate = alternates[i];
914
915             //&lt;debug error&gt;
916             if (typeof alternate !== 'string') {
917                 Ext.Error.raise({
918                     sourceClass: &quot;Ext&quot;,
919                     sourceMethod: &quot;define&quot;,
920                     msg: &quot;Invalid alternate of: '&quot; + alternate + &quot;' for class: '&quot; + name + &quot;'; must be a valid string&quot;
921                 });
922             }
923             //&lt;/debug&gt;
924
925             this.set(alternate, cls);
926         }
927     });
928
929     Manager.setDefaultPostprocessors(['alias', 'singleton', 'alternateClassName']);
930
931     Ext.apply(Ext, {
932 <span id='Ext-method-create'>        /**
933 </span>         * Convenient shorthand, see {@link Ext.ClassManager#instantiate}
934          * @member Ext
935          * @method create
936          */
937         create: alias(Manager, 'instantiate'),
938
939 <span id='Ext-ClassManager-method-factory'>        /**
940 </span>         * @private
941          * API to be stablized
942          *
943          * @param {Mixed} item
944          * @param {String} namespace
945          */
946         factory: function(item, namespace) {
947             if (item instanceof Array) {
948                 var i, ln;
949
950                 for (i = 0, ln = item.length; i &lt; ln; i++) {
951                     item[i] = Ext.factory(item[i], namespace);
952                 }
953
954                 return item;
955             }
956
957             var isString = (typeof item === 'string');
958
959             if (isString || (item instanceof Object &amp;&amp; item.constructor === Object)) {
960                 var name, config = {};
961
962                 if (isString) {
963                     name = item;
964                 }
965                 else {
966                     name = item.className;
967                     config = item;
968                     delete config.className;
969                 }
970
971                 if (namespace !== undefined &amp;&amp; name.indexOf(namespace) === -1) {
972                     name = namespace + '.' + Ext.String.capitalize(name);
973                 }
974
975                 return Ext.create(name, config);
976             }
977
978             if (typeof item === 'function') {
979                 return Ext.create(item);
980             }
981
982             return item;
983         },
984
985 <span id='Ext-method-widget'>        /**
986 </span>         * Convenient shorthand to create a widget by its xtype, also see {@link Ext.ClassManager#instantiateByAlias}
987
988     var button = Ext.widget('button'); // Equivalent to Ext.create('widget.button')
989     var panel = Ext.widget('panel'); // Equivalent to Ext.create('widget.panel')
990
991          * @member Ext
992          * @method widget
993          * @markdown
994          */
995         widget: function(name) {
996             var args = slice.call(arguments);
997             args[0] = 'widget.' + name;
998
999             return Manager.instantiateByAlias.apply(Manager, args);
1000         },
1001
1002 <span id='Ext-method-createByAlias'>        /**
1003 </span>         * Convenient shorthand, see {@link Ext.ClassManager#instantiateByAlias}
1004          * @member Ext
1005          * @method createByAlias
1006          */
1007         createByAlias: alias(Manager, 'instantiateByAlias'),
1008
1009 <span id='Ext-method-define'>        /**
1010 </span>         * Convenient shorthand for {@link Ext.ClassManager#create}, see detailed {@link Ext.Class explanation}
1011          * @member Ext
1012          * @method define
1013          */
1014         define: alias(Manager, 'create'),
1015
1016 <span id='Ext-method-getClassName'>        /**
1017 </span>         * Convenient shorthand, see {@link Ext.ClassManager#getName}
1018          * @member Ext
1019          * @method getClassName
1020          */
1021         getClassName: alias(Manager, 'getName'),
1022
1023 <span id='Ext-ClassManager-method-getDisplayName'>        /**
1024 </span>         *
1025          * @param {Mixed} object
1026          */
1027         getDisplayName: function(object) {
1028             if (object.displayName) {
1029                 return object.displayName;
1030             }
1031
1032             if (object.$name &amp;&amp; object.$class) {
1033                 return Ext.getClassName(object.$class) + '#' + object.$name;
1034             }
1035
1036             if (object.$className) {
1037                 return object.$className;
1038             }
1039
1040             return 'Anonymous';
1041         },
1042
1043 <span id='Ext-method-getClassName'>        /**
1044 </span>         * Convenient shorthand, see {@link Ext.ClassManager#getClass}
1045          * @member Ext
1046          * @method getClassName
1047          */
1048         getClass: alias(Manager, 'getClass'),
1049
1050 <span id='Ext-method-namespace'>        /**
1051 </span>         * Creates namespaces to be used for scoping variables and classes so that they are not global.
1052          * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
1053
1054     Ext.namespace('Company', 'Company.data');
1055
1056      // equivalent and preferable to the above syntax
1057     Ext.namespace('Company.data');
1058
1059     Company.Widget = function() { ... };
1060
1061     Company.data.CustomStore = function(config) { ... };
1062
1063          * @param {String} namespace1
1064          * @param {String} namespace2
1065          * @param {String} etc
1066          * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
1067          * @function
1068          * @member Ext
1069          * @method namespace
1070          * @markdown
1071          */
1072         namespace: alias(Manager, 'createNamespaces')
1073     });
1074
1075     Ext.createWidget = Ext.widget;
1076
1077 <span id='Ext-method-ns'>    /**
1078 </span>     * Convenient alias for {@link Ext#namespace Ext.namespace}
1079      * @member Ext
1080      * @method ns
1081      */
1082     Ext.ns = Ext.namespace;
1083
1084     Class.registerPreprocessor('className', function(cls, data) {
1085         if (data.$className) {
1086             cls.$className = data.$className;
1087             //&lt;debug&gt;
1088             cls.displayName = cls.$className;
1089             //&lt;/debug&gt;
1090         }
1091     }, true);
1092
1093     Class.setDefaultPreprocessorPosition('className', 'first');
1094
1095 })(Ext.Class, Ext.Function.alias);
1096 </pre>
1097 </body>
1098 </html>