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