--- /dev/null
+<!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-Class'>/**
+</span> * @author Jacky Nguyen <jacky@sencha.com>
+ * @docauthor Jacky Nguyen <jacky@sencha.com>
+ * @class Ext.Class
+ *
+ * Handles class creation throughout the whole framework. Note that most of the time {@link Ext#define Ext.define} should
+ * be used instead, since it's a higher level wrapper that aliases to {@link Ext.ClassManager#create}
+ * to enable namespacing and dynamic dependency resolution.
+ *
+ * # Basic syntax: #
+ *
+ * Ext.define(className, properties);
+ *
+ * in which `properties` is an object represent a collection of properties that apply to the class. See
+ * {@link Ext.ClassManager#create} for more detailed instructions.
+ *
+ * Ext.define('Person', {
+ * name: 'Unknown',
+ *
+ * constructor: function(name) {
+ * if (name) {
+ * this.name = name;
+ * }
+ *
+ * return this;
+ * },
+ *
+ * eat: function(foodType) {
+ * alert("I'm eating: " + foodType);
+ *
+ * return this;
+ * }
+ * });
+ *
+ * var aaron = new Person("Aaron");
+ * aaron.eat("Sandwich"); // alert("I'm eating: Sandwich");
+ *
+ * Ext.Class has a powerful set of extensible {@link Ext.Class#registerPreprocessor pre-processors} which takes care of
+ * everything related to class creation, including but not limited to inheritance, mixins, configuration, statics, etc.
+ *
+ * # Inheritance: #
+ *
+ * Ext.define('Developer', {
+ * extend: 'Person',
+ *
+ * constructor: function(name, isGeek) {
+ * this.isGeek = isGeek;
+ *
+ * // Apply a method from the parent class' prototype
+ * this.callParent([name]);
+ *
+ * return this;
+ *
+ * },
+ *
+ * code: function(language) {
+ * alert("I'm coding in: " + language);
+ *
+ * this.eat("Bugs");
+ *
+ * return this;
+ * }
+ * });
+ *
+ * var jacky = new Developer("Jacky", true);
+ * jacky.code("JavaScript"); // alert("I'm coding in: JavaScript");
+ * // alert("I'm eating: Bugs");
+ *
+ * See {@link Ext.Base#callParent} for more details on calling superclass' methods
+ *
+ * # Mixins: #
+ *
+ * Ext.define('CanPlayGuitar', {
+ * playGuitar: function() {
+ * alert("F#...G...D...A");
+ * }
+ * });
+ *
+ * Ext.define('CanComposeSongs', {
+ * composeSongs: function() { ... }
+ * });
+ *
+ * Ext.define('CanSing', {
+ * sing: function() {
+ * alert("I'm on the highway to hell...")
+ * }
+ * });
+ *
+ * Ext.define('Musician', {
+ * extend: 'Person',
+ *
+ * mixins: {
+ * canPlayGuitar: 'CanPlayGuitar',
+ * canComposeSongs: 'CanComposeSongs',
+ * canSing: 'CanSing'
+ * }
+ * })
+ *
+ * Ext.define('CoolPerson', {
+ * extend: 'Person',
+ *
+ * mixins: {
+ * canPlayGuitar: 'CanPlayGuitar',
+ * canSing: 'CanSing'
+ * },
+ *
+ * sing: function() {
+ * alert("Ahem....");
+ *
+ * this.mixins.canSing.sing.call(this);
+ *
+ * alert("[Playing guitar at the same time...]");
+ *
+ * this.playGuitar();
+ * }
+ * });
+ *
+ * var me = new CoolPerson("Jacky");
+ *
+ * me.sing(); // alert("Ahem...");
+ * // alert("I'm on the highway to hell...");
+ * // alert("[Playing guitar at the same time...]");
+ * // alert("F#...G...D...A");
+ *
+ * # Config: #
+ *
+ * Ext.define('SmartPhone', {
+ * config: {
+ * hasTouchScreen: false,
+ * operatingSystem: 'Other',
+ * price: 500
+ * },
+ *
+ * isExpensive: false,
+ *
+ * constructor: function(config) {
+ * this.initConfig(config);
+ *
+ * return this;
+ * },
+ *
+ * applyPrice: function(price) {
+ * this.isExpensive = (price > 500);
+ *
+ * return price;
+ * },
+ *
+ * applyOperatingSystem: function(operatingSystem) {
+ * if (!(/^(iOS|Android|BlackBerry)$/i).test(operatingSystem)) {
+ * return 'Other';
+ * }
+ *
+ * return operatingSystem;
+ * }
+ * });
+ *
+ * var iPhone = new SmartPhone({
+ * hasTouchScreen: true,
+ * operatingSystem: 'iOS'
+ * });
+ *
+ * iPhone.getPrice(); // 500;
+ * iPhone.getOperatingSystem(); // 'iOS'
+ * iPhone.getHasTouchScreen(); // true;
+ * iPhone.hasTouchScreen(); // true
+ *
+ * iPhone.isExpensive; // false;
+ * iPhone.setPrice(600);
+ * iPhone.getPrice(); // 600
+ * iPhone.isExpensive; // true;
+ *
+ * iPhone.setOperatingSystem('AlienOS');
+ * iPhone.getOperatingSystem(); // 'Other'
+ *
+ * # Statics: #
+ *
+ * Ext.define('Computer', {
+ * statics: {
+ * factory: function(brand) {
+ * // 'this' in static methods refer to the class itself
+ * return new this(brand);
+ * }
+ * },
+ *
+ * constructor: function() { ... }
+ * });
+ *
+ * var dellComputer = Computer.factory('Dell');
+ *
+ * Also see {@link Ext.Base#statics} and {@link Ext.Base#self} for more details on accessing
+ * static properties within class methods
+ *
+ */
+(function() {
+
+ var Class,
+ Base = Ext.Base,
+ baseStaticProperties = [],
+ baseStaticProperty;
+
+ for (baseStaticProperty in Base) {
+ if (Base.hasOwnProperty(baseStaticProperty)) {
+ baseStaticProperties.push(baseStaticProperty);
+ }
+ }
+
+<span id='Ext-Class-method-constructor'><span id='Ext-Class'> /**
+</span></span> * @constructor
+ * @param {Object} classData An object represent the properties of this class
+ * @param {Function} createdFn Optional, the callback function to be executed when this class is fully created.
+ * Note that the creation process can be asynchronous depending on the pre-processors used.
+ * @return {Ext.Base} The newly created class
+ */
+ Ext.Class = Class = function(newClass, classData, onClassCreated) {
+ if (typeof newClass !== 'function') {
+ onClassCreated = classData;
+ classData = newClass;
+ newClass = function() {
+ return this.constructor.apply(this, arguments);
+ };
+ }
+
+ if (!classData) {
+ classData = {};
+ }
+
+ var preprocessorStack = classData.preprocessors || Class.getDefaultPreprocessors(),
+ registeredPreprocessors = Class.getPreprocessors(),
+ index = 0,
+ preprocessors = [],
+ preprocessor, preprocessors, staticPropertyName, process, i, j, ln;
+
+ for (i = 0, ln = baseStaticProperties.length; i < ln; i++) {
+ staticPropertyName = baseStaticProperties[i];
+ newClass[staticPropertyName] = Base[staticPropertyName];
+ }
+
+ delete classData.preprocessors;
+
+ for (j = 0, ln = preprocessorStack.length; j < ln; j++) {
+ preprocessor = preprocessorStack[j];
+
+ if (typeof preprocessor === 'string') {
+ preprocessor = registeredPreprocessors[preprocessor];
+
+ if (!preprocessor.always) {
+ if (classData.hasOwnProperty(preprocessor.name)) {
+ preprocessors.push(preprocessor.fn);
+ }
+ }
+ else {
+ preprocessors.push(preprocessor.fn);
+ }
+ }
+ else {
+ preprocessors.push(preprocessor);
+ }
+ }
+
+ classData.onClassCreated = onClassCreated;
+
+ classData.onBeforeClassCreated = function(cls, data) {
+ onClassCreated = data.onClassCreated;
+
+ delete data.onBeforeClassCreated;
+ delete data.onClassCreated;
+
+ cls.implement(data);
+
+ if (onClassCreated) {
+ onClassCreated.call(cls, cls);
+ }
+ };
+
+ process = function(cls, data) {
+ preprocessor = preprocessors[index++];
+
+ if (!preprocessor) {
+ data.onBeforeClassCreated.apply(this, arguments);
+ return;
+ }
+
+ if (preprocessor.call(this, cls, data, process) !== false) {
+ process.apply(this, arguments);
+ }
+ };
+
+ process.call(Class, newClass, classData);
+
+ return newClass;
+ };
+
+ Ext.apply(Class, {
+
+<span id='Ext-Class-property-preprocessors'> /** @private */
+</span> preprocessors: {},
+
+<span id='Ext-Class-method-registerPreprocessor'> /**
+</span> * Register a new pre-processor to be used during the class creation process
+ *
+ * @member Ext.Class registerPreprocessor
+ * @param {String} name The pre-processor's name
+ * @param {Function} fn The callback function to be executed. Typical format:
+
+ function(cls, data, fn) {
+ // Your code here
+
+ // Execute this when the processing is finished.
+ // Asynchronous processing is perfectly ok
+ if (fn) {
+ fn.call(this, cls, data);
+ }
+ });
+
+ * Passed arguments for this function are:
+ *
+ * - `{Function} cls`: The created class
+ * - `{Object} data`: The set of properties passed in {@link Ext.Class} constructor
+ * - `{Function} fn`: The callback function that <b>must</b> to be executed when this pre-processor finishes,
+ * regardless of whether the processing is synchronous or aynchronous
+ *
+ * @return {Ext.Class} this
+ * @markdown
+ */
+ registerPreprocessor: function(name, fn, always) {
+ this.preprocessors[name] = {
+ name: name,
+ always: always || false,
+ fn: fn
+ };
+
+ return this;
+ },
+
+<span id='Ext-Class-method-getPreprocessor'> /**
+</span> * Retrieve a pre-processor callback function by its name, which has been registered before
+ *
+ * @param {String} name
+ * @return {Function} preprocessor
+ */
+ getPreprocessor: function(name) {
+ return this.preprocessors[name];
+ },
+
+ getPreprocessors: function() {
+ return this.preprocessors;
+ },
+
+<span id='Ext-Class-method-getDefaultPreprocessors'> /**
+</span> * Retrieve the array stack of default pre-processors
+ *
+ * @return {Function} defaultPreprocessors
+ */
+ getDefaultPreprocessors: function() {
+ return this.defaultPreprocessors || [];
+ },
+
+<span id='Ext-Class-method-setDefaultPreprocessors'> /**
+</span> * Set the default array stack of default pre-processors
+ *
+ * @param {Array} preprocessors
+ * @return {Ext.Class} this
+ */
+ setDefaultPreprocessors: function(preprocessors) {
+ this.defaultPreprocessors = Ext.Array.from(preprocessors);
+
+ return this;
+ },
+
+<span id='Ext-Class-method-setDefaultPreprocessorPosition'> /**
+</span> * Insert this pre-processor at a specific position in the stack, optionally relative to
+ * any existing pre-processor. For example:
+
+ Ext.Class.registerPreprocessor('debug', function(cls, data, fn) {
+ // Your code here
+
+ if (fn) {
+ fn.call(this, cls, data);
+ }
+ }).insertDefaultPreprocessor('debug', 'last');
+
+ * @param {String} name The pre-processor name. Note that it needs to be registered with
+ * {@link Ext#registerPreprocessor registerPreprocessor} before this
+ * @param {String} offset The insertion position. Four possible values are:
+ * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument)
+ * @param {String} relativeName
+ * @return {Ext.Class} this
+ * @markdown
+ */
+ setDefaultPreprocessorPosition: function(name, offset, relativeName) {
+ var defaultPreprocessors = this.defaultPreprocessors,
+ index;
+
+ if (typeof offset === 'string') {
+ if (offset === 'first') {
+ defaultPreprocessors.unshift(name);
+
+ return this;
+ }
+ else if (offset === 'last') {
+ defaultPreprocessors.push(name);
+
+ return this;
+ }
+
+ offset = (offset === 'after') ? 1 : -1;
+ }
+
+ index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
+
+ if (index !== -1) {
+ defaultPreprocessors.splice(Math.max(0, index + offset), 0, name);
+ }
+
+ return this;
+ }
+ });
+
+ Class.registerPreprocessor('extend', function(cls, data) {
+ var extend = data.extend,
+ base = Ext.Base,
+ basePrototype = base.prototype,
+ prototype = function() {},
+ parent, i, k, ln, staticName, parentStatics,
+ parentPrototype, clsPrototype;
+
+ if (extend && extend !== Object) {
+ parent = extend;
+ }
+ else {
+ parent = base;
+ }
+
+ parentPrototype = parent.prototype;
+
+ prototype.prototype = parentPrototype;
+ clsPrototype = cls.prototype = new prototype();
+
+ if (!('$class' in parent)) {
+ for (i in basePrototype) {
+ if (!parentPrototype[i]) {
+ parentPrototype[i] = basePrototype[i];
+ }
+ }
+ }
+
+ clsPrototype.self = cls;
+
+ cls.superclass = clsPrototype.superclass = parentPrototype;
+
+ delete data.extend;
+
+ // Statics inheritance
+ parentStatics = parentPrototype.$inheritableStatics;
+
+ if (parentStatics) {
+ for (k = 0, ln = parentStatics.length; k < ln; k++) {
+ staticName = parentStatics[k];
+
+ if (!cls.hasOwnProperty(staticName)) {
+ cls[staticName] = parent[staticName];
+ }
+ }
+ }
+
+ // Merge the parent class' config object without referencing it
+ if (parentPrototype.config) {
+ clsPrototype.config = Ext.Object.merge({}, parentPrototype.config);
+ }
+ else {
+ clsPrototype.config = {};
+ }
+
+ if (clsPrototype.$onExtended) {
+ clsPrototype.$onExtended.call(cls, cls, data);
+ }
+
+ if (data.onClassExtended) {
+ clsPrototype.$onExtended = data.onClassExtended;
+ delete data.onClassExtended;
+ }
+
+ }, true);
+
+ Class.registerPreprocessor('statics', function(cls, data) {
+ var statics = data.statics,
+ name;
+
+ for (name in statics) {
+ if (statics.hasOwnProperty(name)) {
+ cls[name] = statics[name];
+ }
+ }
+
+ delete data.statics;
+ });
+
+ Class.registerPreprocessor('inheritableStatics', function(cls, data) {
+ var statics = data.inheritableStatics,
+ inheritableStatics,
+ prototype = cls.prototype,
+ name;
+
+ inheritableStatics = prototype.$inheritableStatics;
+
+ if (!inheritableStatics) {
+ inheritableStatics = prototype.$inheritableStatics = [];
+ }
+
+ for (name in statics) {
+ if (statics.hasOwnProperty(name)) {
+ cls[name] = statics[name];
+ inheritableStatics.push(name);
+ }
+ }
+
+ delete data.inheritableStatics;
+ });
+
+ Class.registerPreprocessor('mixins', function(cls, data) {
+ cls.mixin(data.mixins);
+
+ delete data.mixins;
+ });
+
+ Class.registerPreprocessor('config', function(cls, data) {
+ var prototype = cls.prototype;
+
+ Ext.Object.each(data.config, function(name) {
+ var cName = name.charAt(0).toUpperCase() + name.substr(1),
+ pName = name,
+ apply = 'apply' + cName,
+ setter = 'set' + cName,
+ getter = 'get' + cName;
+
+ if (!(apply in prototype) && !data.hasOwnProperty(apply)) {
+ data[apply] = function(val) {
+ return val;
+ };
+ }
+
+ if (!(setter in prototype) && !data.hasOwnProperty(setter)) {
+ data[setter] = function(val) {
+ var ret = this[apply].call(this, val, this[pName]);
+
+ if (ret !== undefined) {
+ this[pName] = ret;
+ }
+
+ return this;
+ };
+ }
+
+ if (!(getter in prototype) && !data.hasOwnProperty(getter)) {
+ data[getter] = function() {
+ return this[pName];
+ };
+ }
+ });
+
+ Ext.Object.merge(prototype.config, data.config);
+ delete data.config;
+ });
+
+ Class.setDefaultPreprocessors(['extend', 'statics', 'inheritableStatics', 'mixins', 'config']);
+
+ // Backwards compatible
+ Ext.extend = function(subclass, superclass, members) {
+ if (arguments.length === 2 && Ext.isObject(superclass)) {
+ members = superclass;
+ superclass = subclass;
+ subclass = null;
+ }
+
+ var cls;
+
+ if (!superclass) {
+ Ext.Error.raise("Attempting to extend from a class which has not been loaded on the page.");
+ }
+
+ members.extend = superclass;
+ members.preprocessors = ['extend', 'mixins', 'config', 'statics'];
+
+ if (subclass) {
+ cls = new Class(subclass, members);
+ }
+ else {
+ cls = new Class(members);
+ }
+
+ cls.prototype.override = function(o) {
+ for (var m in o) {
+ if (o.hasOwnProperty(m)) {
+ this[m] = o[m];
+ }
+ }
+ };
+
+ return cls;
+ };
+
+})();
+</pre></pre></body></html>
\ No newline at end of file