Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Base3.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-Base'>/**
19 </span> * @author Jacky Nguyen &lt;jacky@sencha.com&gt;
20  * @docauthor Jacky Nguyen &lt;jacky@sencha.com&gt;
21  * @class Ext.Base
22  *
23  * The root of all classes created with {@link Ext#define}
24  * All prototype and static members of this class are inherited by any other class
25  *
26  */
27 (function(flexSetter) {
28
29 var Base = Ext.Base = function() {};
30     Base.prototype = {
31         $className: 'Ext.Base',
32
33         $class: Base,
34
35 <span id='Ext-Base-property-self'>        /**
36 </span>         * Get the reference to the current class from which this object was instantiated. Unlike {@link Ext.Base#statics},
37          * `this.self` is scope-dependent and it's meant to be used for dynamic inheritance. See {@link Ext.Base#statics}
38          * for a detailed comparison
39          *
40          *     Ext.define('My.Cat', {
41          *         statics: {
42          *             speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
43          *         },
44          *
45          *         constructor: function() {
46          *             alert(this.self.speciesName); / dependent on 'this'
47          *
48          *             return this;
49          *         },
50          *
51          *         clone: function() {
52          *             return new this.self();
53          *         }
54          *     });
55          *
56          *
57          *     Ext.define('My.SnowLeopard', {
58          *         extend: 'My.Cat',
59          *         statics: {
60          *             speciesName: 'Snow Leopard'         // My.SnowLeopard.speciesName = 'Snow Leopard'
61          *         }
62          *     });
63          *
64          *     var cat = new My.Cat();                     // alerts 'Cat'
65          *     var snowLeopard = new My.SnowLeopard();     // alerts 'Snow Leopard'
66          *
67          *     var clone = snowLeopard.clone();
68          *     alert(Ext.getClassName(clone));             // alerts 'My.SnowLeopard'
69          *
70          * @type Class
71          * @protected
72          */
73         self: Base,
74
75         // Default constructor, simply returns `this`
76         constructor: function() {
77             return this;
78         },
79
80 <span id='Ext-Base-method-initConfig'>        /**
81 </span>         * Initialize configuration for this class. a typical example:
82          *
83          *     Ext.define('My.awesome.Class', {
84          *         // The default config
85          *         config: {
86          *             name: 'Awesome',
87          *             isAwesome: true
88          *         },
89          *
90          *         constructor: function(config) {
91          *             this.initConfig(config);
92          *
93          *             return this;
94          *         }
95          *     });
96          *
97          *     var awesome = new My.awesome.Class({
98          *         name: 'Super Awesome'
99          *     });
100          *
101          *     alert(awesome.getName()); // 'Super Awesome'
102          *
103          * @protected
104          * @param {Object} config
105          * @return {Object} mixins The mixin prototypes as key - value pairs
106          */
107         initConfig: function(config) {
108             if (!this.$configInited) {
109                 this.config = Ext.Object.merge({}, this.config || {}, config || {});
110
111                 this.applyConfig(this.config);
112
113                 this.$configInited = true;
114             }
115
116             return this;
117         },
118
119 <span id='Ext-Base-method-setConfig'>        /**
120 </span>         * @private
121          */
122         setConfig: function(config) {
123             this.applyConfig(config || {});
124
125             return this;
126         },
127
128 <span id='Ext-Base-property-applyConfig'>        /**
129 </span>         * @private
130          */
131         applyConfig: flexSetter(function(name, value) {
132             var setter = 'set' + Ext.String.capitalize(name);
133
134             if (typeof this[setter] === 'function') {
135                 this[setter].call(this, value);
136             }
137
138             return this;
139         }),
140
141 <span id='Ext-Base-method-callParent'>        /**
142 </span>         * Call the parent's overridden method. For example:
143          *
144          *     Ext.define('My.own.A', {
145          *         constructor: function(test) {
146          *             alert(test);
147          *         }
148          *     });
149          *
150          *     Ext.define('My.own.B', {
151          *         extend: 'My.own.A',
152          *
153          *         constructor: function(test) {
154          *             alert(test);
155          *
156          *             this.callParent([test + 1]);
157          *         }
158          *     });
159          *
160          *     Ext.define('My.own.C', {
161          *         extend: 'My.own.B',
162          *
163          *         constructor: function() {
164          *             alert(&quot;Going to call parent's overriden constructor...&quot;);
165          *
166          *             this.callParent(arguments);
167          *         }
168          *     });
169          *
170          *     var a = new My.own.A(1); // alerts '1'
171          *     var b = new My.own.B(1); // alerts '1', then alerts '2'
172          *     var c = new My.own.C(2); // alerts &quot;Going to call parent's overriden constructor...&quot;
173          *                              // alerts '2', then alerts '3'
174          *
175          * @protected
176          * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
177          * from the current method, for example: `this.callParent(arguments)`
178          * @return {Mixed} Returns the result from the superclass' method
179          */
180         callParent: function(args) {
181             var method = this.callParent.caller,
182                 parentClass, methodName;
183
184             if (!method.$owner) {
185                 //&lt;debug error&gt;
186                 if (!method.caller) {
187                     Ext.Error.raise({
188                         sourceClass: Ext.getClassName(this),
189                         sourceMethod: &quot;callParent&quot;,
190                         msg: &quot;Attempting to call a protected method from the public scope, which is not allowed&quot;
191                     });
192                 }
193                 //&lt;/debug&gt;
194
195                 method = method.caller;
196             }
197
198             parentClass = method.$owner.superclass;
199             methodName = method.$name;
200
201             //&lt;debug error&gt;
202             if (!(methodName in parentClass)) {
203                 Ext.Error.raise({
204                     sourceClass: Ext.getClassName(this),
205                     sourceMethod: methodName,
206                     msg: &quot;this.callParent() was called but there's no such method (&quot; + methodName +
207                          &quot;) found in the parent class (&quot; + (Ext.getClassName(parentClass) || 'Object') + &quot;)&quot;
208                  });
209             }
210             //&lt;/debug&gt;
211
212             return parentClass[methodName].apply(this, args || []);
213         },
214
215
216 <span id='Ext-Base-method-statics'>        /**
217 </span>         * Get the reference to the class from which this object was instantiated. Note that unlike {@link Ext.Base#self},
218          * `this.statics()` is scope-independent and it always returns the class from which it was called, regardless of what
219          * `this` points to during run-time
220          *
221          *     Ext.define('My.Cat', {
222          *         statics: {
223          *             totalCreated: 0,
224          *             speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
225          *         },
226          *  
227          *         constructor: function() {
228          *             var statics = this.statics();
229          *  
230          *             alert(statics.speciesName);     // always equals to 'Cat' no matter what 'this' refers to
231          *                                             // equivalent to: My.Cat.speciesName
232          *  
233          *             alert(this.self.speciesName);   // dependent on 'this'
234          *  
235          *             statics.totalCreated++;
236          *  
237          *             return this;
238          *         },
239          *  
240          *         clone: function() {
241          *             var cloned = new this.self;                      // dependent on 'this'
242          *  
243          *             cloned.groupName = this.statics().speciesName;   // equivalent to: My.Cat.speciesName
244          *  
245          *             return cloned;
246          *         }
247          *     });
248          *
249          *
250          *     Ext.define('My.SnowLeopard', {
251          *         extend: 'My.Cat',
252          *  
253          *         statics: {
254          *             speciesName: 'Snow Leopard'     // My.SnowLeopard.speciesName = 'Snow Leopard'
255          *         },
256          *  
257          *         constructor: function() {
258          *             this.callParent();
259          *         }
260          *     });
261          *
262          *     var cat = new My.Cat();                 // alerts 'Cat', then alerts 'Cat'
263          *
264          *     var snowLeopard = new My.SnowLeopard(); // alerts 'Cat', then alerts 'Snow Leopard'
265          *
266          *     var clone = snowLeopard.clone();
267          *     alert(Ext.getClassName(clone));         // alerts 'My.SnowLeopard'
268          *     alert(clone.groupName);                 // alerts 'Cat'
269          *
270          *     alert(My.Cat.totalCreated);             // alerts 3
271          *
272          * @protected
273          * @return {Class}
274          */
275         statics: function() {
276             var method = this.statics.caller,
277                 self = this.self;
278
279             if (!method) {
280                 return self;
281             }
282
283             return method.$owner;
284         },
285
286 <span id='Ext-Base-method-callOverridden'>        /**
287 </span>         * Call the original method that was previously overridden with {@link Ext.Base#override}
288          *
289          *     Ext.define('My.Cat', {
290          *         constructor: function() {
291          *             alert(&quot;I'm a cat!&quot;);
292          *   
293          *             return this;
294          *         }
295          *     });
296          *
297          *     My.Cat.override({
298          *         constructor: function() {
299          *             alert(&quot;I'm going to be a cat!&quot;);
300          *   
301          *             var instance = this.callOverridden();
302          *   
303          *             alert(&quot;Meeeeoooowwww&quot;);
304          *   
305          *             return instance;
306          *         }
307          *     });
308          *
309          *     var kitty = new My.Cat(); // alerts &quot;I'm going to be a cat!&quot;
310          *                               // alerts &quot;I'm a cat!&quot;
311          *                               // alerts &quot;Meeeeoooowwww&quot;
312          *
313          * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
314          * @return {Mixed} Returns the result after calling the overridden method
315          */
316         callOverridden: function(args) {
317             var method = this.callOverridden.caller;
318
319             //&lt;debug error&gt;
320             if (!method.$owner) {
321                 Ext.Error.raise({
322                     sourceClass: Ext.getClassName(this),
323                     sourceMethod: &quot;callOverridden&quot;,
324                     msg: &quot;Attempting to call a protected method from the public scope, which is not allowed&quot;
325                 });
326             }
327
328             if (!method.$previous) {
329                 Ext.Error.raise({
330                     sourceClass: Ext.getClassName(this),
331                     sourceMethod: &quot;callOverridden&quot;,
332                     msg: &quot;this.callOverridden was called in '&quot; + method.$name +
333                          &quot;' but this method has never been overridden&quot;
334                  });
335             }
336             //&lt;/debug&gt;
337
338             return method.$previous.apply(this, args || []);
339         },
340
341         destroy: function() {}
342     };
343
344     // These static properties will be copied to every newly created class with {@link Ext#define}
345     Ext.apply(Ext.Base, {
346 <span id='Ext-Base-method-create'>        /**
347 </span>         * Create a new instance of this Class.
348          *
349          *     Ext.define('My.cool.Class', {
350          *         ...
351          *     });
352          *      
353          *     My.cool.Class.create({
354          *         someConfig: true
355          *     });
356          *
357          * All parameters are passed to the constructor of the class.
358          *
359          * @return {Object} the created instance.
360          * @static
361          */
362         create: function() {
363             return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
364         },
365
366 <span id='Ext-Base-property-own'>        /**
367 </span>         * @private
368          */
369         own: flexSetter(function(name, value) {
370             if (typeof value === 'function') {
371                 this.ownMethod(name, value);
372             }
373             else {
374                 this.prototype[name] = value;
375             }
376         }),
377
378 <span id='Ext-Base-method-ownMethod'>        /**
379 </span>         * @private
380          */
381         ownMethod: function(name, fn) {
382             var originalFn;
383
384             if (fn.$owner !== undefined &amp;&amp; fn !== Ext.emptyFn) {
385                 originalFn = fn;
386
387                 fn = function() {
388                     return originalFn.apply(this, arguments);
389                 };
390             }
391
392             //&lt;debug&gt;
393             var className;
394             className = Ext.getClassName(this);
395             if (className) {
396                 fn.displayName = className + '#' + name;
397             }
398             //&lt;/debug&gt;
399             fn.$owner = this;
400             fn.$name = name;
401
402             this.prototype[name] = fn;
403         },
404
405 <span id='Ext-Base-method-addStatics'>        /**
406 </span>         * Add / override static properties of this class.
407          *
408          *     Ext.define('My.cool.Class', {
409          *         ...
410          *     });
411          *
412          *     My.cool.Class.addStatics({
413          *         someProperty: 'someValue',      // My.cool.Class.someProperty = 'someValue'
414          *         method1: function() { ... },    // My.cool.Class.method1 = function() { ... };
415          *         method2: function() { ... }     // My.cool.Class.method2 = function() { ... };
416          *     });
417          *
418          * @param {Object} members
419          * @return {Ext.Base} this
420          * @static
421          */
422         addStatics: function(members) {
423             for (var name in members) {
424                 if (members.hasOwnProperty(name)) {
425                     this[name] = members[name];
426                 }
427             }
428
429             return this;
430         },
431
432 <span id='Ext-Base-method-implement'>        /**
433 </span>         * Add methods / properties to the prototype of this class.
434          *
435          *     Ext.define('My.awesome.Cat', {
436          *         constructor: function() {
437          *             ...
438          *         }
439          *     });
440          *
441          *      My.awesome.Cat.implement({
442          *          meow: function() {
443          *             alert('Meowww...');
444          *          }
445          *      });
446          *
447          *      var kitty = new My.awesome.Cat;
448          *      kitty.meow();
449          *
450          * @param {Object} members
451          * @static
452          */
453         implement: function(members) {
454             var prototype = this.prototype,
455                 name, i, member, previous;
456             //&lt;debug&gt;
457             var className = Ext.getClassName(this);
458             //&lt;/debug&gt;
459             for (name in members) {
460                 if (members.hasOwnProperty(name)) {
461                     member = members[name];
462
463                     if (typeof member === 'function') {
464                         member.$owner = this;
465                         member.$name = name;
466                         //&lt;debug&gt;
467                         if (className) {
468                             member.displayName = className + '#' + name;
469                         }
470                         //&lt;/debug&gt;
471                     }
472
473                     prototype[name] = member;
474                 }
475             }
476
477             if (Ext.enumerables) {
478                 var enumerables = Ext.enumerables;
479
480                 for (i = enumerables.length; i--;) {
481                     name = enumerables[i];
482
483                     if (members.hasOwnProperty(name)) {
484                         member = members[name];
485                         member.$owner = this;
486                         member.$name = name;
487                         prototype[name] = member;
488                     }
489                 }
490             }
491         },
492
493 <span id='Ext-Base-method-borrow'>        /**
494 </span>         * Borrow another class' members to the prototype of this class.
495          *
496          *     Ext.define('Bank', {
497          *         money: '$$$',
498          *         printMoney: function() {
499          *             alert('$$$$$$$');
500          *         }
501          *     });
502          *
503          *     Ext.define('Thief', {
504          *         ...
505          *     });
506          *
507          *     Thief.borrow(Bank, ['money', 'printMoney']);
508          *
509          *     var steve = new Thief();
510          *
511          *     alert(steve.money); // alerts '$$$'
512          *     steve.printMoney(); // alerts '$$$$$$$'
513          *
514          * @param {Ext.Base} fromClass The class to borrow members from
515          * @param {Array/String} members The names of the members to borrow
516          * @return {Ext.Base} this
517          * @static
518          * @private
519          */
520         borrow: function(fromClass, members) {
521             var fromPrototype = fromClass.prototype,
522                 i, ln, member;
523
524             members = Ext.Array.from(members);
525
526             for (i = 0, ln = members.length; i &lt; ln; i++) {
527                 member = members[i];
528
529                 this.own(member, fromPrototype[member]);
530             }
531
532             return this;
533         },
534
535 <span id='Ext-Base-method-override'>        /**
536 </span>         * Override prototype members of this class. Overridden methods can be invoked via
537          * {@link Ext.Base#callOverridden}
538          *
539          *     Ext.define('My.Cat', {
540          *         constructor: function() {
541          *             alert(&quot;I'm a cat!&quot;);
542          *
543          *             return this;
544          *         }
545          *     });
546          *
547          *     My.Cat.override({
548          *         constructor: function() {
549          *             alert(&quot;I'm going to be a cat!&quot;);
550          *
551          *             var instance = this.callOverridden();
552          *
553          *             alert(&quot;Meeeeoooowwww&quot;);
554          *
555          *             return instance;
556          *         }
557          *     });
558          *
559          *     var kitty = new My.Cat(); // alerts &quot;I'm going to be a cat!&quot;
560          *                               // alerts &quot;I'm a cat!&quot;
561          *                               // alerts &quot;Meeeeoooowwww&quot;
562          *
563          * @param {Object} members
564          * @return {Ext.Base} this
565          * @static
566          */
567         override: function(members) {
568             var prototype = this.prototype,
569                 name, i, member, previous;
570
571             for (name in members) {
572                 if (members.hasOwnProperty(name)) {
573                     member = members[name];
574
575                     if (typeof member === 'function') {
576                         if (typeof prototype[name] === 'function') {
577                             previous = prototype[name];
578                             member.$previous = previous;
579                         }
580
581                         this.ownMethod(name, member);
582                     }
583                     else {
584                         prototype[name] = member;
585                     }
586                 }
587             }
588
589             if (Ext.enumerables) {
590                 var enumerables = Ext.enumerables;
591
592                 for (i = enumerables.length; i--;) {
593                     name = enumerables[i];
594
595                     if (members.hasOwnProperty(name)) {
596                         if (prototype[name] !== undefined) {
597                             previous = prototype[name];
598                             members[name].$previous = previous;
599                         }
600
601                         this.ownMethod(name, members[name]);
602                     }
603                 }
604             }
605
606             return this;
607         },
608
609 <span id='Ext-Base-property-mixin'>        /**
610 </span>         * Used internally by the mixins pre-processor
611          * @private
612          */
613         mixin: flexSetter(function(name, cls) {
614             var mixin = cls.prototype,
615                 my = this.prototype,
616                 i, fn;
617
618             for (i in mixin) {
619                 if (mixin.hasOwnProperty(i)) {
620                     if (my[i] === undefined) {
621                         if (typeof mixin[i] === 'function') {
622                             fn = mixin[i];
623
624                             if (fn.$owner === undefined) {
625                                 this.ownMethod(i, fn);
626                             }
627                             else {
628                                 my[i] = fn;
629                             }
630                         }
631                         else {
632                             my[i] = mixin[i];
633                         }
634                     }
635                     else if (i === 'config' &amp;&amp; my.config &amp;&amp; mixin.config) {
636                         Ext.Object.merge(my.config, mixin.config);
637                     }
638                 }
639             }
640
641             if (my.mixins === undefined) {
642                 my.mixins = {};
643             }
644
645             my.mixins[name] = mixin;
646         }),
647
648 <span id='Ext-Base-method-getName'>        /**
649 </span>         * Get the current class' name in string format.
650          *
651          *     Ext.define('My.cool.Class', {
652          *         constructor: function() {
653          *             alert(this.self.getName()); // alerts 'My.cool.Class'
654          *         }
655          *     });
656          *
657          *     My.cool.Class.getName(); // 'My.cool.Class'
658          *
659          * @return {String} className
660          */
661         getName: function() {
662             return Ext.getClassName(this);
663         },
664
665 <span id='Ext-Base-method-createAlias'>        /**
666 </span>         * Create aliases for existing prototype methods. Example:
667          *
668          *     Ext.define('My.cool.Class', {
669          *         method1: function() { ... },
670          *         method2: function() { ... }
671          *     });
672          *
673          *     var test = new My.cool.Class();
674          *
675          *     My.cool.Class.createAlias({
676          *         method3: 'method1',
677          *         method4: 'method2'
678          *     });
679          *
680          *     test.method3(); // test.method1()
681          *
682          *     My.cool.Class.createAlias('method5', 'method3');
683          *
684          *     test.method5(); // test.method3() -&gt; test.method1()
685          *
686          * @param {String/Object} alias The new method name, or an object to set multiple aliases. See
687          * {@link Ext.Function#flexSetter flexSetter}
688          * @param {String/Object} origin The original method name
689          * @static
690          * @method
691          */
692         createAlias: flexSetter(function(alias, origin) {
693             this.prototype[alias] = this.prototype[origin];
694         })
695     });
696
697 })(Ext.Function.flexSetter);
698 </pre>
699 </body>
700 </html>