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