123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>The source code</title>
- <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
- <style type="text/css">
- .highlight { display: block; background-color: #ddd; }
- </style>
- <script type="text/javascript">
- function highlight() {
- document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
- }
- </script>
- </head>
- <body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><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 framework. This is a low level factory that is used by Ext.ClassManager and generally
- * should not be used directly. If you choose to use Ext.Class you will lose out on the namespace, aliasing and depency loading
- * features made available by Ext.ClassManager. The only time you would use Ext.Class directly is to create an anonymous class.
- *
- * If you wish to create a class you should use {@link Ext#define Ext.define} which aliases
- * {@link Ext.ClassManager#create Ext.ClassManager.create} to enable namespacing and dynamic dependency resolution.
- *
- * Ext.Class is the factory and **not** the superclass of everything. For the base class that **all** Ext classes inherit
- * from, see {@link Ext.Base}.
- */
- (function() {
- var ExtClass,
- Base = Ext.Base,
- baseStaticMembers = [],
- baseStaticMember, baseStaticMemberLength;
- for (baseStaticMember in Base) {
- if (Base.hasOwnProperty(baseStaticMember)) {
- baseStaticMembers.push(baseStaticMember);
- }
- }
- baseStaticMemberLength = baseStaticMembers.length;
- // Creates a constructor that has nothing extra in its scope chain.
- function makeCtor (className) {
- function constructor () {
- // Opera has some problems returning from a constructor when Dragonfly isn't running. The || null seems to
- // be sufficient to stop it misbehaving. Known to be required against 10.53, 11.51 and 11.61.
- return this.constructor.apply(this, arguments) || null;
- }
- //<debug>
- if (className) {
- constructor.displayName = className;
- }
- //</debug>
- return constructor;
- }
- <span id='Ext-Class-method-constructor'> /**
- </span> * @method constructor
- * Create a new anonymous class.
- *
- * @param {Object} data An object represent the properties of this class
- * @param {Function} onCreated 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 = ExtClass = function(Class, data, onCreated) {
- if (typeof Class != 'function') {
- onCreated = data;
- data = Class;
- Class = null;
- }
- if (!data) {
- data = {};
- }
- Class = ExtClass.create(Class, data);
- ExtClass.process(Class, data, onCreated);
- return Class;
- };
- Ext.apply(ExtClass, {
- <span id='Ext-Class-method-onBeforeCreated'> /**
- </span> * @private
- * @param Class
- * @param data
- * @param hooks
- */
- onBeforeCreated: function(Class, data, hooks) {
- Class.addMembers(data);
- hooks.onCreated.call(Class, Class);
- },
- <span id='Ext-Class-method-create'> /**
- </span> * @private
- * @param Class
- * @param classData
- * @param onClassCreated
- */
- create: function(Class, data) {
- var name, i;
- if (!Class) {
- Class = makeCtor(
- //<debug>
- data.$className
- //</debug>
- );
- }
- for (i = 0; i < baseStaticMemberLength; i++) {
- name = baseStaticMembers[i];
- Class[name] = Base[name];
- }
- return Class;
- },
- <span id='Ext-Class-method-process'> /**
- </span> * @private
- * @param Class
- * @param data
- * @param onCreated
- */
- process: function(Class, data, onCreated) {
- var preprocessorStack = data.preprocessors || ExtClass.defaultPreprocessors,
- registeredPreprocessors = this.preprocessors,
- hooks = {
- onBeforeCreated: this.onBeforeCreated
- },
- preprocessors = [],
- preprocessor, preprocessorsProperties,
- i, ln, j, subLn, preprocessorProperty, process;
- delete data.preprocessors;
- for (i = 0,ln = preprocessorStack.length; i < ln; i++) {
- preprocessor = preprocessorStack[i];
- if (typeof preprocessor == 'string') {
- preprocessor = registeredPreprocessors[preprocessor];
- preprocessorsProperties = preprocessor.properties;
- if (preprocessorsProperties === true) {
- preprocessors.push(preprocessor.fn);
- }
- else if (preprocessorsProperties) {
- for (j = 0,subLn = preprocessorsProperties.length; j < subLn; j++) {
- preprocessorProperty = preprocessorsProperties[j];
- if (data.hasOwnProperty(preprocessorProperty)) {
- preprocessors.push(preprocessor.fn);
- break;
- }
- }
- }
- }
- else {
- preprocessors.push(preprocessor);
- }
- }
- hooks.onCreated = onCreated ? onCreated : Ext.emptyFn;
- hooks.preprocessors = preprocessors;
- this.doProcess(Class, data, hooks);
- },
-
- doProcess: function(Class, data, hooks){
- var me = this,
- preprocessor = hooks.preprocessors.shift();
- if (!preprocessor) {
- hooks.onBeforeCreated.apply(me, arguments);
- return;
- }
- if (preprocessor.call(me, Class, data, hooks, me.doProcess) !== false) {
- me.doProcess(Class, data, hooks);
- }
- },
- <span id='Ext-Class-property-preprocessors'> /** @private */
- </span> preprocessors: {},
- <span id='Ext-Class-static-method-registerPreprocessor'> /**
- </span> * Register a new pre-processor to be used during the class creation process
- *
- * @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);
- * }
- * });
- *
- * @param {Function} fn.cls The created class
- * @param {Object} fn.data The set of properties passed in {@link Ext.Class} constructor
- * @param {Function} fn.fn The callback function that **must** to be executed when this
- * pre-processor finishes, regardless of whether the processing is synchronous or aynchronous.
- * @return {Ext.Class} this
- * @private
- * @static
- */
- registerPreprocessor: function(name, fn, properties, position, relativeTo) {
- if (!position) {
- position = 'last';
- }
- if (!properties) {
- properties = [name];
- }
- this.preprocessors[name] = {
- name: name,
- properties: properties || false,
- fn: fn
- };
- this.setDefaultPreprocessorPosition(name, position, relativeTo);
- return this;
- },
- <span id='Ext-Class-static-method-getPreprocessor'> /**
- </span> * Retrieve a pre-processor callback function by its name, which has been registered before
- *
- * @param {String} name
- * @return {Function} preprocessor
- * @private
- * @static
- */
- getPreprocessor: function(name) {
- return this.preprocessors[name];
- },
- <span id='Ext-Class-method-getPreprocessors'> /**
- </span> * @private
- */
- getPreprocessors: function() {
- return this.preprocessors;
- },
- <span id='Ext-Class-property-defaultPreprocessors'> /**
- </span> * @private
- */
- defaultPreprocessors: [],
- <span id='Ext-Class-static-method-getDefaultPreprocessors'> /**
- </span> * Retrieve the array stack of default pre-processors
- * @return {Function[]} defaultPreprocessors
- * @private
- * @static
- */
- getDefaultPreprocessors: function() {
- return this.defaultPreprocessors;
- },
- <span id='Ext-Class-static-method-setDefaultPreprocessors'> /**
- </span> * Set the default array stack of default pre-processors
- *
- * @private
- * @param {Array} preprocessors
- * @return {Ext.Class} this
- * @static
- */
- setDefaultPreprocessors: function(preprocessors) {
- this.defaultPreprocessors = Ext.Array.from(preprocessors);
- return this;
- },
- <span id='Ext-Class-static-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);
- * }
- * }).setDefaultPreprocessorPosition('debug', 'last');
- *
- * @private
- * @param {String} name The pre-processor name. Note that it needs to be registered with
- * {@link Ext.Class#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
- * @static
- */
- 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) {
- Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);
- }
- return this;
- },
- configNameCache: {},
- getConfigNameMap: function(name) {
- var cache = this.configNameCache,
- map = cache[name],
- capitalizedName;
- if (!map) {
- capitalizedName = name.charAt(0).toUpperCase() + name.substr(1);
- map = cache[name] = {
- internal: name,
- initialized: '_is' + capitalizedName + 'Initialized',
- apply: 'apply' + capitalizedName,
- update: 'update' + capitalizedName,
- 'set': 'set' + capitalizedName,
- 'get': 'get' + capitalizedName,
- doSet : 'doSet' + capitalizedName,
- changeEvent: name.toLowerCase() + 'change'
- };
- }
- return map;
- }
- });
- <span id='Ext-Class-cfg-extend'> /**
- </span> * @cfg {String} extend
- * The parent class that this class extends. For example:
- *
- * Ext.define('Person', {
- * say: function(text) { alert(text); }
- * });
- *
- * Ext.define('Developer', {
- * extend: 'Person',
- * say: function(text) { this.callParent(["print "+text]); }
- * });
- */
- ExtClass.registerPreprocessor('extend', function(Class, data) {
- var Base = Ext.Base,
- basePrototype = Base.prototype,
- extend = data.extend,
- Parent, parentPrototype, i;
- delete data.extend;
- if (extend && extend !== Object) {
- Parent = extend;
- }
- else {
- Parent = Base;
- }
- parentPrototype = Parent.prototype;
- if (!Parent.$isClass) {
- for (i in basePrototype) {
- if (!parentPrototype[i]) {
- parentPrototype[i] = basePrototype[i];
- }
- }
- }
- Class.extend(Parent);
- Class.triggerExtended.apply(Class, arguments);
- if (data.onClassExtended) {
- Class.onExtended(data.onClassExtended, Class);
- delete data.onClassExtended;
- }
- }, true);
- //<feature classSystem.statics>
- <span id='Ext-Class-cfg-statics'> /**
- </span> * @cfg {Object} statics
- * List of static methods for this class. For example:
- *
- * 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');
- */
- ExtClass.registerPreprocessor('statics', function(Class, data) {
- Class.addStatics(data.statics);
- delete data.statics;
- });
- //</feature>
- //<feature classSystem.inheritableStatics>
- <span id='Ext-Class-cfg-inheritableStatics'> /**
- </span> * @cfg {Object} inheritableStatics
- * List of inheritable static methods for this class.
- * Otherwise just like {@link #statics} but subclasses inherit these methods.
- */
- ExtClass.registerPreprocessor('inheritableStatics', function(Class, data) {
- Class.addInheritableStatics(data.inheritableStatics);
- delete data.inheritableStatics;
- });
- //</feature>
- //<feature classSystem.config>
- <span id='Ext-Class-cfg-config'> /**
- </span> * @cfg {Object} config
- * List of configuration options with their default values, for which automatically
- * accessor methods are generated. For example:
- *
- * Ext.define('SmartPhone', {
- * config: {
- * hasTouchScreen: false,
- * operatingSystem: 'Other',
- * price: 500
- * },
- * constructor: function(cfg) {
- * this.initConfig(cfg);
- * }
- * });
- *
- * var iPhone = new SmartPhone({
- * hasTouchScreen: true,
- * operatingSystem: 'iOS'
- * });
- *
- * iPhone.getPrice(); // 500;
- * iPhone.getOperatingSystem(); // 'iOS'
- * iPhone.getHasTouchScreen(); // true;
- */
- ExtClass.registerPreprocessor('config', function(Class, data) {
- var config = data.config,
- prototype = Class.prototype;
- delete data.config;
- Ext.Object.each(config, function(name, value) {
- var nameMap = ExtClass.getConfigNameMap(name),
- internalName = nameMap.internal,
- initializedName = nameMap.initialized,
- applyName = nameMap.apply,
- updateName = nameMap.update,
- setName = nameMap.set,
- getName = nameMap.get,
- hasOwnSetter = (setName in prototype) || data.hasOwnProperty(setName),
- hasOwnApplier = (applyName in prototype) || data.hasOwnProperty(applyName),
- hasOwnUpdater = (updateName in prototype) || data.hasOwnProperty(updateName),
- optimizedGetter, customGetter;
- if (value === null || (!hasOwnSetter && !hasOwnApplier && !hasOwnUpdater)) {
- prototype[internalName] = value;
- prototype[initializedName] = true;
- }
- else {
- prototype[initializedName] = false;
- }
- if (!hasOwnSetter) {
- data[setName] = function(value) {
- var oldValue = this[internalName],
- applier = this[applyName],
- updater = this[updateName];
- if (!this[initializedName]) {
- this[initializedName] = true;
- }
- if (applier) {
- value = applier.call(this, value, oldValue);
- }
- if (typeof value != 'undefined') {
- this[internalName] = value;
- if (updater && value !== oldValue) {
- updater.call(this, value, oldValue);
- }
- }
- return this;
- };
- }
- if (!(getName in prototype) || data.hasOwnProperty(getName)) {
- customGetter = data[getName] || false;
- if (customGetter) {
- optimizedGetter = function() {
- return customGetter.apply(this, arguments);
- };
- }
- else {
- optimizedGetter = function() {
- return this[internalName];
- };
- }
- data[getName] = function() {
- var currentGetter;
- if (!this[initializedName]) {
- this[initializedName] = true;
- this[setName](this.config[name]);
- }
- currentGetter = this[getName];
- if ('$previous' in currentGetter) {
- currentGetter.$previous = optimizedGetter;
- }
- else {
- this[getName] = optimizedGetter;
- }
- return optimizedGetter.apply(this, arguments);
- };
- }
- });
- Class.addConfig(config, true);
- });
- //</feature>
- //<feature classSystem.mixins>
- <span id='Ext-Class-cfg-mixins'> /**
- </span> * @cfg {String[]/Object} mixins
- * List of classes to mix into this class. For example:
- *
- * Ext.define('CanSing', {
- * sing: function() {
- * alert("I'm on the highway to hell...")
- * }
- * });
- *
- * Ext.define('Musician', {
- * mixins: ['CanSing']
- * })
- *
- * In this case the Musician class will get a `sing` method from CanSing mixin.
- *
- * But what if the Musician already has a `sing` method? Or you want to mix
- * in two classes, both of which define `sing`? In such a cases it's good
- * to define mixins as an object, where you assign a name to each mixin:
- *
- * Ext.define('Musician', {
- * mixins: {
- * canSing: 'CanSing'
- * },
- *
- * sing: function() {
- * // delegate singing operation to mixin
- * this.mixins.canSing.sing.call(this);
- * }
- * })
- *
- * In this case the `sing` method of Musician will overwrite the
- * mixed in `sing` method. But you can access the original mixed in method
- * through special `mixins` property.
- */
- ExtClass.registerPreprocessor('mixins', function(Class, data, hooks) {
- var mixins = data.mixins,
- name, mixin, i, ln;
- delete data.mixins;
- Ext.Function.interceptBefore(hooks, 'onCreated', function() {
- if (mixins instanceof Array) {
- for (i = 0,ln = mixins.length; i < ln; i++) {
- mixin = mixins[i];
- name = mixin.prototype.mixinId || mixin.$className;
- Class.mixin(name, mixin);
- }
- }
- else {
- for (var mixinName in mixins) {
- if (mixins.hasOwnProperty(mixinName)) {
- Class.mixin(mixinName, mixins[mixinName]);
- }
- }
- }
- });
- });
- //</feature>
- //<feature classSystem.backwardsCompatible>
- // Backwards compatible
- Ext.extend = function(Class, Parent, members) {
- if (arguments.length === 2 && Ext.isObject(Parent)) {
- members = Parent;
- Parent = Class;
- Class = null;
- }
- var cls;
- if (!Parent) {
- throw new Error("[Ext.extend] Attempting to extend from a class which has not been loaded on the page.");
- }
- members.extend = Parent;
- members.preprocessors = [
- 'extend'
- //<feature classSystem.statics>
- ,'statics'
- //</feature>
- //<feature classSystem.inheritableStatics>
- ,'inheritableStatics'
- //</feature>
- //<feature classSystem.mixins>
- ,'mixins'
- //</feature>
- //<feature classSystem.config>
- ,'config'
- //</feature>
- ];
- if (Class) {
- cls = new ExtClass(Class, members);
- // The 'constructor' is given as 'Class' but also needs to be on prototype
- cls.prototype.constructor = Class;
- } else {
- cls = new ExtClass(members);
- }
- cls.prototype.override = function(o) {
- for (var m in o) {
- if (o.hasOwnProperty(m)) {
- this[m] = o[m];
- }
- }
- };
- return cls;
- };
- //</feature>
- }());
- </pre>
- </body>
- </html>
|