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; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-Class'>/**
19 </span> * @author Jacky Nguyen <jacky@sencha.com>
20 * @docauthor Jacky Nguyen <jacky@sencha.com>
23 * Handles class creation throughout the framework. This is a low level factory that is used by Ext.ClassManager and generally
24 * should not be used directly. If you choose to use Ext.Class you will lose out on the namespace, aliasing and depency loading
25 * features made available by Ext.ClassManager. The only time you would use Ext.Class directly is to create an anonymous class.
27 * If you wish to create a class you should use {@link Ext#define Ext.define} which aliases
28 * {@link Ext.ClassManager#create Ext.ClassManager.create} to enable namespacing and dynamic dependency resolution.
30 * Ext.Class is the factory and **not** the superclass of everything. For the base class that **all** Ext classes inherit
31 * from, see {@link Ext.Base}.
37 baseStaticProperties = [],
40 for (baseStaticProperty in Base) {
41 if (Base.hasOwnProperty(baseStaticProperty)) {
42 baseStaticProperties.push(baseStaticProperty);
46 <span id='Ext-Class-method-constructor'> /**
47 </span> * @method constructor
49 * @param {Object} classData An object represent the properties of this class
50 * @param {Function} createdFn (Optional) The callback function to be executed when this class is fully created.
51 * Note that the creation process can be asynchronous depending on the pre-processors used.
52 * @return {Ext.Base} The newly created class
54 Ext.Class = Class = function(newClass, classData, onClassCreated) {
55 if (typeof newClass != 'function') {
56 onClassCreated = classData;
58 newClass = function() {
59 return this.constructor.apply(this, arguments);
67 var preprocessorStack = classData.preprocessors || Class.getDefaultPreprocessors(),
68 registeredPreprocessors = Class.getPreprocessors(),
71 preprocessor, staticPropertyName, process, i, j, ln;
73 for (i = 0, ln = baseStaticProperties.length; i < ln; i++) {
74 staticPropertyName = baseStaticProperties[i];
75 newClass[staticPropertyName] = Base[staticPropertyName];
78 delete classData.preprocessors;
80 for (j = 0, ln = preprocessorStack.length; j < ln; j++) {
81 preprocessor = preprocessorStack[j];
83 if (typeof preprocessor == 'string') {
84 preprocessor = registeredPreprocessors[preprocessor];
86 if (!preprocessor.always) {
87 if (classData.hasOwnProperty(preprocessor.name)) {
88 preprocessors.push(preprocessor.fn);
92 preprocessors.push(preprocessor.fn);
96 preprocessors.push(preprocessor);
100 classData.onClassCreated = onClassCreated || Ext.emptyFn;
102 classData.onBeforeClassCreated = function(cls, data) {
103 onClassCreated = data.onClassCreated;
105 delete data.onBeforeClassCreated;
106 delete data.onClassCreated;
110 onClassCreated.call(cls, cls);
113 process = function(cls, data) {
114 preprocessor = preprocessors[index++];
117 data.onBeforeClassCreated.apply(this, arguments);
121 if (preprocessor.call(this, cls, data, process) !== false) {
122 process.apply(this, arguments);
126 process.call(Class, newClass, classData);
133 <span id='Ext-Class-property-preprocessors'> /** @private */
134 </span> preprocessors: {},
136 <span id='Ext-Class-static-method-registerPreprocessor'> /**
137 </span> * Register a new pre-processor to be used during the class creation process
140 * @param {String} name The pre-processor's name
141 * @param {Function} fn The callback function to be executed. Typical format:
143 * function(cls, data, fn) {
146 * // Execute this when the processing is finished.
147 * // Asynchronous processing is perfectly ok
149 * fn.call(this, cls, data);
153 * @param {Function} fn.cls The created class
154 * @param {Object} fn.data The set of properties passed in {@link Ext.Class} constructor
155 * @param {Function} fn.fn The callback function that **must** to be executed when this pre-processor finishes,
156 * regardless of whether the processing is synchronous or aynchronous
158 * @return {Ext.Class} this
161 registerPreprocessor: function(name, fn, always) {
162 this.preprocessors[name] = {
164 always: always || false,
171 <span id='Ext-Class-static-method-getPreprocessor'> /**
172 </span> * Retrieve a pre-processor callback function by its name, which has been registered before
174 * @param {String} name
175 * @return {Function} preprocessor
178 getPreprocessor: function(name) {
179 return this.preprocessors[name];
182 getPreprocessors: function() {
183 return this.preprocessors;
186 <span id='Ext-Class-static-method-getDefaultPreprocessors'> /**
187 </span> * Retrieve the array stack of default pre-processors
189 * @return {Function[]} defaultPreprocessors
192 getDefaultPreprocessors: function() {
193 return this.defaultPreprocessors || [];
196 <span id='Ext-Class-static-method-setDefaultPreprocessors'> /**
197 </span> * Set the default array stack of default pre-processors
199 * @param {Function/Function[]} preprocessors
200 * @return {Ext.Class} this
203 setDefaultPreprocessors: function(preprocessors) {
204 this.defaultPreprocessors = Ext.Array.from(preprocessors);
209 <span id='Ext-Class-static-method-setDefaultPreprocessorPosition'> /**
210 </span> * Inserts this pre-processor at a specific position in the stack, optionally relative to
211 * any existing pre-processor. For example:
213 * Ext.Class.registerPreprocessor('debug', function(cls, data, fn) {
217 * fn.call(this, cls, data);
219 * }).setDefaultPreprocessorPosition('debug', 'last');
221 * @param {String} name The pre-processor name. Note that it needs to be registered with
222 * {@link #registerPreprocessor registerPreprocessor} before this
223 * @param {String} offset The insertion position. Four possible values are:
224 * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument)
225 * @param {String} relativeName
226 * @return {Ext.Class} this
229 setDefaultPreprocessorPosition: function(name, offset, relativeName) {
230 var defaultPreprocessors = this.defaultPreprocessors,
233 if (typeof offset == 'string') {
234 if (offset === 'first') {
235 defaultPreprocessors.unshift(name);
239 else if (offset === 'last') {
240 defaultPreprocessors.push(name);
245 offset = (offset === 'after') ? 1 : -1;
248 index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
251 Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);
258 <span id='Ext-Class-cfg-extend'> /**
259 </span> * @cfg {String} extend
260 * The parent class that this class extends. For example:
262 * Ext.define('Person', {
263 * say: function(text) { alert(text); }
266 * Ext.define('Developer', {
268 * say: function(text) { this.callParent(["print "+text]); }
271 Class.registerPreprocessor('extend', function(cls, data) {
272 var extend = data.extend,
274 basePrototype = base.prototype,
275 prototype = function() {},
276 parent, i, k, ln, staticName, parentStatics,
277 parentPrototype, clsPrototype;
279 if (extend && extend !== Object) {
286 parentPrototype = parent.prototype;
288 prototype.prototype = parentPrototype;
289 clsPrototype = cls.prototype = new prototype();
291 if (!('$class' in parent)) {
292 for (i in basePrototype) {
293 if (!parentPrototype[i]) {
294 parentPrototype[i] = basePrototype[i];
299 clsPrototype.self = cls;
301 cls.superclass = clsPrototype.superclass = parentPrototype;
305 //<feature classSystem.inheritableStatics>
306 // Statics inheritance
307 parentStatics = parentPrototype.$inheritableStatics;
310 for (k = 0, ln = parentStatics.length; k < ln; k++) {
311 staticName = parentStatics[k];
313 if (!cls.hasOwnProperty(staticName)) {
314 cls[staticName] = parent[staticName];
320 //<feature classSystem.config>
321 // Merge the parent class' config object without referencing it
322 if (parentPrototype.config) {
323 clsPrototype.config = Ext.Object.merge({}, parentPrototype.config);
326 clsPrototype.config = {};
330 //<feature classSystem.onClassExtended>
331 if (clsPrototype.$onExtended) {
332 clsPrototype.$onExtended.call(cls, cls, data);
335 if (data.onClassExtended) {
336 clsPrototype.$onExtended = data.onClassExtended;
337 delete data.onClassExtended;
343 //<feature classSystem.statics>
344 <span id='Ext-Class-cfg-statics'> /**
345 </span> * @cfg {Object} statics
346 * List of static methods for this class. For example:
348 * Ext.define('Computer', {
350 * factory: function(brand) {
351 * // 'this' in static methods refer to the class itself
352 * return new this(brand);
356 * constructor: function() { ... }
359 * var dellComputer = Computer.factory('Dell');
361 Class.registerPreprocessor('statics', function(cls, data) {
362 cls.addStatics(data.statics);
368 //<feature classSystem.inheritableStatics>
369 <span id='Ext-Class-cfg-inheritableStatics'> /**
370 </span> * @cfg {Object} inheritableStatics
371 * List of inheritable static methods for this class.
372 * Otherwise just like {@link #statics} but subclasses inherit these methods.
374 Class.registerPreprocessor('inheritableStatics', function(cls, data) {
375 cls.addInheritableStatics(data.inheritableStatics);
377 delete data.inheritableStatics;
381 //<feature classSystem.config>
382 <span id='Ext-Class-cfg-config'> /**
383 </span> * @cfg {Object} config
384 * List of configuration options with their default values, for which automatically
385 * accessor methods are generated. For example:
387 * Ext.define('SmartPhone', {
389 * hasTouchScreen: false,
390 * operatingSystem: 'Other',
393 * constructor: function(cfg) {
394 * this.initConfig(cfg);
398 * var iPhone = new SmartPhone({
399 * hasTouchScreen: true,
400 * operatingSystem: 'iOS'
403 * iPhone.getPrice(); // 500;
404 * iPhone.getOperatingSystem(); // 'iOS'
405 * iPhone.getHasTouchScreen(); // true;
406 * iPhone.hasTouchScreen(); // true
408 Class.registerPreprocessor('config', function(cls, data) {
409 var prototype = cls.prototype;
411 Ext.Object.each(data.config, function(name) {
412 var cName = name.charAt(0).toUpperCase() + name.substr(1),
414 apply = 'apply' + cName,
415 setter = 'set' + cName,
416 getter = 'get' + cName;
418 if (!(apply in prototype) && !data.hasOwnProperty(apply)) {
419 data[apply] = function(val) {
424 if (!(setter in prototype) && !data.hasOwnProperty(setter)) {
425 data[setter] = function(val) {
426 var ret = this[apply].call(this, val, this[pName]);
428 if (typeof ret != 'undefined') {
436 if (!(getter in prototype) && !data.hasOwnProperty(getter)) {
437 data[getter] = function() {
443 Ext.Object.merge(prototype.config, data.config);
448 //<feature classSystem.mixins>
449 <span id='Ext-Class-cfg-mixins'> /**
450 </span> * @cfg {Object} mixins
451 * List of classes to mix into this class. For example:
453 * Ext.define('CanSing', {
455 * alert("I'm on the highway to hell...")
459 * Ext.define('Musician', {
467 Class.registerPreprocessor('mixins', function(cls, data) {
468 var mixins = data.mixins,
473 Ext.Function.interceptBefore(data, 'onClassCreated', function(cls) {
474 if (mixins instanceof Array) {
475 for (i = 0,ln = mixins.length; i < ln; i++) {
477 name = mixin.prototype.mixinId || mixin.$className;
479 cls.mixin(name, mixin);
483 for (name in mixins) {
484 if (mixins.hasOwnProperty(name)) {
485 cls.mixin(name, mixins[name]);
494 Class.setDefaultPreprocessors([
496 //<feature classSystem.statics>
499 //<feature classSystem.inheritableStatics>
500 ,'inheritableStatics'
502 //<feature classSystem.config>
505 //<feature classSystem.mixins>
510 //<feature classSystem.backwardsCompatible>
511 // Backwards compatible
512 Ext.extend = function(subclass, superclass, members) {
513 if (arguments.length === 2 && Ext.isObject(superclass)) {
514 members = superclass;
515 superclass = subclass;
522 Ext.Error.raise("Attempting to extend from a class which has not been loaded on the page.");
525 members.extend = superclass;
526 members.preprocessors = [
528 //<feature classSystem.statics>
531 //<feature classSystem.inheritableStatics>
532 ,'inheritableStatics'
534 //<feature classSystem.mixins>
537 //<feature classSystem.config>
543 cls = new Class(subclass, members);
546 cls = new Class(members);
549 cls.prototype.override = function(o) {
551 if (o.hasOwnProperty(m)) {