| 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>
 |